def aggregate(self, cell): centerpoint = QgsPointXY( (cell.rect.xMinimum() + cell.rect.xMaximum()) / 2, (cell.rect.yMinimum() + cell.rect.yMaximum()) / 2) total_pt_distance = sum( [centerpoint.distance(point) for point in cell.points_within()]) data = cell.attrs_as_array() if data.shape[1] < 2: return data aggregates = np.zeros(data.shape[0], np.float32) for point in cell.points_within(): aggregates = aggregates + (np.array(cell[point]) * ( (total_pt_distance - centerpoint.distance(point)) / total_pt_distance)) return [float(d) for d in aggregates]
def postionupdated(self, position: QgsPointXY, info): # Check layer for logging capability and if in logging mode if not self.logging or not self.layer or not self.layerprovider or not self.tracking_settings: return # Check tracking setting type if hasattr(self.tracking_settings, 'distance'): # Get tracking interval tracking_interval = self.tracking_settings['distance'] # Compare distance if position.distance(self.tracking_settings['last']) >= tracking_interval: # Log track element self.log_track(position, info) # Update last position self.tracking_settings['last'] = position else: # Get tracking interval (default to time 1 sec) tracking_interval = self.tracking_settings['time'] # Get current timestamp now = datetime.timestamp(datetime.now()) # Compare timestamp if (now - self.tracking_settings['last']) >= tracking_interval: # Log track element self.log_track(position, info) # Update last position self.tracking_settings['last'] = now
def canvasPressEvent(self, event): """ If pressEvent point is near the layer point, enable dragging. Else show msg box """ if event.button() == Qt.LeftButton: click_point = self.toLayerCoordinates(self.lm_layer, event.pos()) if self.lm_layer.featureCount() == 1: feature_list = self.lm_layer.dataProvider().getFeatures( ) #Returns iterator to a list of one feature self.lm_feature = next( feature_list) #get first and only element in the list self.lm_point = self.lm_feature.geometry().asPoint() dist = QgsPointXY.distance(click_point, self.lm_point) tolerance = (QgsTolerance.toleranceInMapUnits( 15, self.lm_layer, self.canvas().mapSettings(), QgsTolerance.Pixels)) if dist < tolerance: #Clicked on a landmark self.clicked_on_landmark = True self.create_ghost_point() else: #Not clicked on a landmark confirmation_msg = "Do you want to move {} here? \n\n".format( self.lm_layer.name()) reply = QMessageBox.question(self.parent(), 'Movement Confirmation', confirmation_msg, QMessageBox.Yes, QMessageBox.No) if reply == QMessageBox.Yes: self.move_position(click_point)
def processAlgorithm(self, parameters, context, feedback): raster = self.parameterAsRasterLayer(parameters, self.PrmInput, context) out_path = self.parameterAsOutputLayer(parameters, self.PrmOutputRaster, context) north = self.parameterAsDouble(parameters, self.PrmNorthLatitude, context) south = self.parameterAsDouble(parameters, self.PrmSouthLatitude, context) east = self.parameterAsDouble(parameters, self.PrmEastLongitude, context) west = self.parameterAsDouble(parameters, self.PrmWestLongitude, context) rotation = self.parameterAsDouble(parameters, self.PrmRotation, context) if rotation == 0: status = processing.run("gdal:translate", {'INPUT': raster, 'EXTRA': '-a_srs EPSG:4326 -a_ullr {} {} {} {}'.format(west, north, east, south), 'DATA_TYPE': 0, 'OUTPUT': out_path}) else: rwidth = raster.width() rheight = raster.height() center_x = (east + west) / 2.0 center_y = (north + south)/ 2.0 center_pt = QgsPointXY(center_x, center_y) ul_pt = QgsPointXY(west, north) ur_pt = QgsPointXY(east, north) lr_pt = QgsPointXY(east, south) ll_pt = QgsPointXY(west, south) distance = center_pt.distance(ul_pt) az = center_pt.azimuth(ul_pt) - rotation pt1 = center_pt.project(distance, az) az = center_pt.azimuth(ur_pt) - rotation pt2 = center_pt.project(distance, az) az = center_pt.azimuth(lr_pt) - rotation pt3 = center_pt.project(distance, az) az = center_pt.azimuth(ll_pt) - rotation pt4 = center_pt.project(distance, az) gcp1= '-gcp {} {} {} {}'.format(0,0, pt1.x(), pt1.y()) gcp2= '-gcp {} {} {} {}'.format(rwidth,0, pt2.x(), pt2.y()) gcp3= '-gcp {} {} {} {}'.format(rwidth, rheight, pt3.x(), pt3.y()) gcp4= '-gcp {} {} {} {}'.format(0, rheight, pt4.x(), pt4.y()) status = processing.run("gdal:translate", {'INPUT': raster, 'EXTRA': '-a_srs EPSG:4326 -a_nodata 0,0,0 {} {} {} {}'.format(gcp1, gcp2, gcp3, gcp4), 'DATA_TYPE': 0, 'OUTPUT': out_path}) feedback.pushInfo('{}'.format(status)) results = {} results[self.PrmOutputRaster] = out_path return (results)
def testMeasureLineProjected(self): # +-+ # | | # +-+ + # test setting/getting the source CRS da_3068 = QgsDistanceArea() da_wsg84 = QgsDistanceArea() da_3068.setSourceCrs(QgsCoordinateReferenceSystem.fromOgcWmsCrs('EPSG:3068'), QgsProject.instance().transformContext()) if (da_3068.sourceCrs().isGeographic()): da_3068.setEllipsoid(da_3068.sourceCrs().ellipsoidAcronym()) print(("setting [{}] srid [{}] description [{}]".format(u'Soldner Berlin', da_3068.sourceCrs().authid(), da_3068.sourceCrs().description()))) self.assertEqual(da_3068.sourceCrs().authid(), 'EPSG:3068') da_wsg84.setSourceCrs(QgsCoordinateReferenceSystem.fromOgcWmsCrs('EPSG:4326'), QgsProject.instance().transformContext()) if (da_wsg84.sourceCrs().isGeographic()): da_wsg84.setEllipsoid(da_wsg84.sourceCrs().ellipsoidAcronym()) self.assertEqual(da_wsg84.sourceCrs().authid(), 'EPSG:4326') print(("setting [{}] srid [{}] description [{}] isGeographic[{}]".format(u'Wsg84', da_wsg84.sourceCrs().authid(), da_wsg84.sourceCrs().description(), da_wsg84.sourceCrs().isGeographic()))) # print(("-- projectionAcronym[{}] ellipsoidAcronym[{}] toWkt[{}] mapUnits[{}] toProj4[{}]".format(da_wsg84.sourceCrs().projectionAcronym(),da_wsg84.sourceCrs().ellipsoidAcronym(), da_wsg84.sourceCrs().toWkt(),da_wsg84.sourceCrs().mapUnits(),da_wsg84.sourceCrs().toProj4()))) print(("Testing Position change for[{}] years[{}]".format(u'Ampelanlage - Potsdamer Platz, Verkehrsinsel', u'1924 and 1998'))) # 1924-10-24 SRID=3068;POINT(23099.49 20296.69) # 1924-10-24 SRID=4326;POINT(13.37650707988041 52.50952361017194) # 1998-10-02 SRID=3068;POINT(23082.30 20267.80) # 1998-10-02 SRID=4326;POINT(13.37625537334001 52.50926345498337) # values returned by SpatiaLite point_soldner_1924 = QgsPointXY(23099.49, 20296.69) point_soldner_1998 = QgsPointXY(23082.30, 20267.80) distance_soldner_meters = 33.617379 azimuth_soldner_1924 = 3.678339 # ST_Transform(point_soldner_1924,point_soldner_1998,4326) point_wsg84_1924 = QgsPointXY(13.37650707988041, 52.50952361017194) point_wsg84_1998 = QgsPointXY(13.37625537334001, 52.50926345498337) # ST_Distance(point_wsg84_1924,point_wsg84_1998,1) distance_wsg84_meters = 33.617302 # ST_Distance(point_wsg84_1924,point_wsg84_1998) # distance_wsg84_mapunits=0.000362 distance_wsg84_mapunits_format = QgsDistanceArea.formatDistance(0.000362, 7, QgsUnitTypes.DistanceDegrees, True) # ST_Azimuth(point_wsg84_1924,point_wsg84_1998) azimuth_wsg84_1924 = 3.674878 # ST_Azimuth(point_wsg84_1998,point_wsg84_1998) azimuth_wsg84_1998 = 0.533282 # ST_Project(point_wsg84_1924,33.617302,3.674878) # SRID=4326;POINT(13.37625537318728 52.50926345503591) point_soldner_1998_project = QgsPointXY(13.37625537318728, 52.50926345503591) # ST_Project(point_wsg84_1998,33.617302,0.533282) # SRID=4326;POINT(13.37650708009255 52.50952361009799) point_soldner_1924_project = QgsPointXY(13.37650708009255, 52.50952361009799) distance_qpoint = point_soldner_1924.distance(point_soldner_1998) azimuth_qpoint = point_soldner_1924.azimuth(point_soldner_1998) point_soldner_1998_result = point_soldner_1924.project(distance_qpoint, azimuth_qpoint) point_soldner_1924_result = QgsPointXY(0, 0) point_soldner_1998_result = QgsPointXY(0, 0) # Test meter based projected point from point_1924 to point_1998 length_1998_mapunits, point_soldner_1998_result = da_3068.measureLineProjected(point_soldner_1924, distance_soldner_meters, azimuth_qpoint) self.assertEqual(point_soldner_1998_result.toString(6), point_soldner_1998.toString(6)) # Test degree based projected point from point_1924 1 meter due East point_wsg84_meter_result = QgsPointXY(0, 0) point_wsg84_1927_meter = QgsPointXY(13.37652180838435, 52.50952361017102) length_meter_mapunits, point_wsg84_meter_result = da_wsg84.measureLineProjected(point_wsg84_1924, 1.0, (math.pi / 2)) self.assertEqual(QgsDistanceArea.formatDistance(length_meter_mapunits, 7, QgsUnitTypes.DistanceDegrees, True), '0.0000147 deg') self.assertEqual(point_wsg84_meter_result.toString(7), point_wsg84_1927_meter.toString(7)) point_wsg84_1998_result = QgsPointXY(0, 0) length_1928_mapunits, point_wsg84_1998_result = da_wsg84.measureLineProjected(point_wsg84_1924, distance_wsg84_meters, azimuth_wsg84_1924) self.assertEqual(QgsDistanceArea.formatDistance(length_1928_mapunits, 7, QgsUnitTypes.DistanceDegrees, True), distance_wsg84_mapunits_format) self.assertEqual(point_wsg84_1998_result.toString(7), point_wsg84_1998.toString(7))
class MapTool(QgsMapTool): MODE_NONE = 0 MODE_PAN = 1 MODE_ROTATE = 2 MODE_SCALE = 3 MODE_SCALE_X = 4 MODE_SCALE_Y = 5 MODE_PAN_RESULT = 6 MODE_NODE = 7 NODE_NAMES = ['A', 'B', 'C', 'D'] def __init__(self, widget): QgsMapTool.__init__(self, widget.canvas) self.widget = widget self.canvas = widget.canvas self.mode = self.MODE_NONE self.selected_node = None # clicked point self.p0 = None # centre rectangle self.pX = None # rectangle vertices (handles) self.pA = None # hg self.pB = None # hd self.pC = None # bd self.pD = None # bg self.zoneWidth = None self.zoneDepth = None # eye (rotation) self.pY = None # rectangle self.rb = QgsRubberBand(self.canvas, QgsWkbTypes.PolygonGeometry) self.rb.setStrokeColor(Qt.blue) self.rb.setWidth(3) self.rbFoc = QgsRubberBand(self.canvas, QgsWkbTypes.LineGeometry) self.rbFoc.setStrokeColor(Qt.blue) self.rbFoc.setWidth(1) # SCALE nodes self.rbPA = QgsRubberBand(self.canvas, QgsWkbTypes.PointGeometry) self.rbPA.setColor(Qt.red) self.rbPA.setWidth(8) self.rbPB = QgsRubberBand(self.canvas, QgsWkbTypes.PointGeometry) self.rbPB.setColor(Qt.red) self.rbPB.setWidth(8) self.rbPC = QgsRubberBand(self.canvas, QgsWkbTypes.PointGeometry) self.rbPC.setColor(Qt.red) self.rbPC.setWidth(8) self.rbPD = QgsRubberBand(self.canvas, QgsWkbTypes.PointGeometry) self.rbPD.setColor(QColor(255, 50, 150, 255)) self.rbPD.setWidth(8) # scale Y node self.rbPH = QgsRubberBand(self.canvas, QgsWkbTypes.PointGeometry) self.rbPH.setColor(Qt.red) self.rbPH.setWidth(8) # scale X node self.rbPL = QgsRubberBand(self.canvas, QgsWkbTypes.PointGeometry) self.rbPL.setColor(Qt.red) self.rbPL.setWidth(8) # final pan self.rbPan = QgsRubberBand(self.canvas, QgsWkbTypes.PointGeometry) self.rbPan.setColor(QColor(0, 200, 50, 255)) self.rbPan.setWidth(8) # ROTATE node self.rbPY = QgsRubberBand(self.canvas, QgsWkbTypes.PointGeometry) self.rbPY.setColor(Qt.blue) self.rbPY.setWidth(6) self.rotation = 0.0 # cutting lines self.rbLines = QgsRubberBand(self.canvas, QgsWkbTypes.LineGeometry) self.rbLines.setColor(QColor(40, 180, 30, 255)) self.rbLines.setWidth(1.5) # plots self.rbPlots = QgsRubberBand(self.canvas, QgsWkbTypes.PolygonGeometry) self.rbPlots.setStrokeColor(QColor(200, 120, 70, 150)) self.rbPlots.setWidth(0.8) self.rubbers = [ self.rb, self.rbPA, self.rbPB, self.rbPC, self.rbPD, self.rbPY, self.rbPH, self.rbPL, self.rbPan, self.rbLines, self.rbPlots, self.rbFoc, ] self.rowLines = None self.columnLines = None self.allLines = None def hide(self): for rb in self.rubbers: rb.reset() def updateRubberGeom(self): if self.pA is None: return self.zoneWidth = self.pA.distance(self.pB) self.zoneDepth = self.pA.distance(self.pD) self.pM = QgsPointXY((self.pC.x() + self.pD.x()) / 2, (self.pC.y() + self.pD.y()) / 2) self.d0 = self.pM.distance(self.pY) # self.widget.updateZ(self.pY) self.rb.setToGeometry( QgsGeometry.fromPolygonXY( [[self.pD, self.pA, self.pB, self.pC, self.pD]])) self.rbFoc.setToGeometry( QgsGeometry.fromPolylineXY([self.pD, self.pY, self.pC])) for p, rb in [ [self.pA, self.rbPA], [self.pB, self.rbPB], [self.pC, self.rbPC], [self.pD, self.rbPD], [self.pY, self.rbPY], [self.pH, self.rbPH], [self.pL, self.rbPL], ]: rb.setToGeometry(QgsGeometry.fromPointXY(p)) leftEdge = (QgsGeometry.fromPolylineXY([ self.pA, self.pD ]).densifyByCount(self.widget.rowCount.value() - 1).asPolyline()) rightEdge = (QgsGeometry.fromPolylineXY([ self.pB, self.pC ]).densifyByCount(self.widget.rowCount.value() - 1).asPolyline()) # Plot edges lines polyline = list(zip(leftEdge, rightEdge)) backSide = (QgsGeometry.fromPolylineXY([ self.pA, self.pB ]).densifyByCount(self.widget.columnCount.value() - 1).asPolyline()) frontSide = (QgsGeometry.fromPolylineXY([ self.pD, self.pC ]).densifyByCount(self.widget.columnCount.value() - 1).asPolyline()) polylineX = list(zip(frontSide[:], backSide[:])) self.finalWidth = self.zoneWidth self.rowLines = polyline self.columnLines = polylineX self.allLines = polyline + polylineX self.rbLines.setToGeometry( QgsGeometry.fromMultiPolylineXY( polylineX + polyline + polyline[::max(1, 1 + len(polyline))])) if self.widget.cbReverseRows.isChecked(): if self.widget.cbReverseColumns.isChecked(): self.rbPC.setColor(Qt.red) self.rbPD.setColor(Qt.red) self.rbPA.setColor(Qt.red) self.rbPB.setColor(QColor(0, 200, 150, 255)) else: self.rbPC.setColor(Qt.red) self.rbPD.setColor(Qt.red) self.rbPB.setColor(Qt.red) self.rbPA.setColor(QColor(0, 200, 150, 255)) else: if self.widget.cbReverseColumns.isChecked(): self.rbPA.setColor(Qt.red) self.rbPB.setColor(Qt.red) self.rbPD.setColor(Qt.red) self.rbPC.setColor(QColor(0, 200, 150, 255)) else: self.rbPA.setColor(Qt.red) self.rbPB.setColor(Qt.red) self.rbPC.setColor(Qt.red) self.rbPD.setColor(QColor(0, 200, 150, 255)) self.widget.alert.setText("Total plots: {}".format( self.widget.columnCount.value() * self.widget.rowCount.value())) def getLines(self): return QgsGeometry.fromMultiPolylineXY(self.rowLines) def getSampleLines(self): return ( [self.rowLines[0], self.rowLines[1]] + self.rowLines[2:-1][::max(1, 1 + int((len(self.rowLines) - 3) / 9))] + [self.rowLines[-1]]) def newRubber(self): if self.pX is not None: self.updateRubberGeom() return # default parameters h = 2 * self.widget.canvas.extent().height() / 3 / 20 # first bbox, according to current view h = self.canvas.extent().height() / 6 c = self.canvas.extent().center() rubberExtent = QgsRectangle(QgsPointXY(c.x() - h, c.y() - h), QgsPointXY(c.x() + h, c.y() + h)) self.rotation = 0.0 width = rubberExtent.xMaximum() - rubberExtent.xMinimum() height = rubberExtent.yMaximum() - rubberExtent.yMinimum() # centre rectangle self.pX = QgsPointXY(rubberExtent.xMinimum() + width / 2, rubberExtent.yMinimum() + height / 2) self.pA = QgsPointXY(rubberExtent.xMinimum(), rubberExtent.yMaximum()) self.pB = QgsPointXY(rubberExtent.xMaximum(), rubberExtent.yMaximum()) self.pC = QgsPointXY(rubberExtent.xMaximum(), rubberExtent.yMinimum()) self.pD = QgsPointXY(rubberExtent.xMinimum(), rubberExtent.yMinimum()) # handles H / L self.pH = QgsPointXY((self.pA.x() + self.pB.x()) / 2, (self.pA.y() + self.pB.y()) / 2) self.pL = QgsPointXY((self.pB.x() + self.pC.x()) / 2, (self.pB.y() + self.pC.y()) / 2) # eye (rotation) self.pY = QgsPointXY(self.pX.x(), self.pX.y() - 2 * height / 3) self.pM = QgsPointXY((self.pC.x() + self.pD.x()) / 2, (self.pC.y() + self.pD.y()) / 2) self.rotation_init = self.rotation self.pA_init = QgsPointXY(self.pA) self.pB_init = QgsPointXY(self.pB) self.pC_init = QgsPointXY(self.pC) self.pD_init = QgsPointXY(self.pD) self.pX_init = QgsPointXY(self.pX) self.pY_init = QgsPointXY(self.pY) self.pH_init = QgsPointXY(self.pH) self.pL_init = QgsPointXY(self.pL) self.updateRubberGeom() def canvasPressEvent(self, event): x = event.pos().x() y = event.pos().y() self.p0 = self.canvas.getCoordinateTransform().toMapCoordinates(x, y) distPA = self.p0.distance(self.pA) / self.canvas.mapUnitsPerPixel() distPB = self.p0.distance(self.pB) / self.canvas.mapUnitsPerPixel() distPC = self.p0.distance(self.pC) / self.canvas.mapUnitsPerPixel() distPD = self.p0.distance(self.pD) / self.canvas.mapUnitsPerPixel() distPY = self.p0.distance(self.pY) / self.canvas.mapUnitsPerPixel() distPH = self.p0.distance(self.pH) / self.canvas.mapUnitsPerPixel() distPL = self.p0.distance(self.pL) / self.canvas.mapUnitsPerPixel() edit_individual_node = self.widget.cbIndividualNode.isChecked() if distPA < 6 or distPB < 6 or distPC < 6 or distPD < 6: if edit_individual_node: self.mode = self.MODE_NODE val, idx = min( (val, idx) for (idx, val) in enumerate([distPA, distPB, distPC, distPD])) self.selected_node = self.NODE_NAMES[idx] else: self.mode = self.MODE_SCALE return if distPH < 6: self.mode = self.MODE_SCALE_Y return if distPL < 6: self.mode = self.MODE_SCALE_X return if distPY < 6: self.mode = self.MODE_ROTATE return if self.rb.asGeometry().contains(self.p0): self.mode = self.MODE_PAN return def canvasMoveEvent(self, event): if self.mode == self.MODE_NONE: return x = event.pos().x() y = event.pos().y() pt = self.canvas.getCoordinateTransform().toMapCoordinates(x, y) dx = pt.x() - self.p0.x() dy = pt.y() - self.p0.y() # node name if self.mode == self.MODE_NODE: if self.selected_node == 'A': self.pA.setX(self.pA_init.x() + dx) self.pA.setY(self.pA_init.y() + dy) elif self.selected_node == 'B': self.pB.setX(self.pB_init.x() + dx) self.pB.setY(self.pB_init.y() + dy) elif self.selected_node == 'C': self.pC.setX(self.pC_init.x() + dx) self.pC.setY(self.pC_init.y() + dy) elif self.selected_node == 'D': self.pD.setX(self.pD_init.x() + dx) self.pD.setY(self.pD_init.y() + dy) # pan mode if self.mode == self.MODE_PAN: for p, p_ini in [ [self.pA, self.pA_init], [self.pB, self.pB_init], [self.pC, self.pC_init], [self.pD, self.pD_init], [self.pX, self.pX_init], [self.pY, self.pY_init], [self.pH, self.pH_init], [self.pL, self.pL_init], ]: p.setX(p_ini.x() + dx) p.setY(p_ini.y() + dy) # horizontal + vertical sizing if self.mode == self.MODE_SCALE: d_old = self.pA_init.distance(self.pX_init) d_new = pt.distance(self.pX_init) dd = d_new / d_old for p, p_ini in [ [self.pA, self.pA_init], [self.pB, self.pB_init], [self.pC, self.pC_init], [self.pD, self.pD_init], [self.pY, self.pY_init], [self.pH, self.pH_init], [self.pL, self.pL_init], ]: dx = dd * (p_ini.x() - self.pX.x()) dy = dd * (p_ini.y() - self.pX.y()) p.setX(self.pX.x() + dx) p.setY(self.pX.y() + dy) # horizontal sizing if self.mode == self.MODE_SCALE_X: d_old = self.pL_init.distance(self.pX_init) d_new = pt.distance(self.pX_init) dd = d_new / d_old if dd < 0.001: dd = 0.001 dx = dd * (self.pL_init.x() - self.pX.x()) dy = dd * (self.pL_init.y() - self.pX.y()) self.pL.setX(self.pX.x() + dx) self.pL.setY(self.pX.y() + dy) centre = self.pH for p, p_ini in [[self.pA, self.pA_init], [self.pB, self.pB_init]]: dx = dd * (p_ini.x() - centre.x()) dy = dd * (p_ini.y() - centre.y()) p.setX(centre.x() + dx) p.setY(centre.y() + dy) centre = self.pM for p, p_ini in [[self.pC, self.pC_init], [self.pD, self.pD_init]]: dx = dd * (p_ini.x() - centre.x()) dy = dd * (p_ini.y() - centre.y()) p.setX(centre.x() + dx) p.setY(centre.y() + dy) # vertical sizing if self.mode == self.MODE_SCALE_Y: d_old = self.pH_init.distance(self.pX_init) d_new = pt.distance(self.pX_init) dd = d_new / d_old if dd < 0.001: dd = 0.001 dx = dd * (self.pH_init.x() - self.pX.x()) dy = dd * (self.pH_init.y() - self.pX.y()) self.pH.setX(self.pX.x() + dx) self.pH.setY(self.pX.y() + dy) centre = self.pL for p, p_ini in [[self.pB, self.pB_init], [self.pC, self.pC_init]]: dx = dd * (p_ini.x() - centre.x()) dy = dd * (p_ini.y() - centre.y()) p.setX(centre.x() + dx) p.setY(centre.y() + dy) centre = QgsPointXY((self.pA.x() + self.pD.x()) / 2, (self.pA.y() + self.pD.y()) / 2) for p, p_ini in [[self.pA, self.pA_init], [self.pD, self.pD_init]]: dx = dd * (p_ini.x() - centre.x()) dy = dd * (p_ini.y() - centre.y()) p.setX(centre.x() + dx) p.setY(centre.y() + dy) if self.mode == self.MODE_ROTATE: self.pY.setX(self.pY_init.x() + dx) self.pY.setY(self.pY_init.y() + dy) azimuth = self.pX.azimuth(pt) theta = azimuth - self.rotation_init + 180 self.rotation = self.rotation_init + theta for a, i in [ [self.pA, self.pA_init], [self.pB, self.pB_init], [self.pC, self.pC_init], [self.pD, self.pD_init], [self.pH, self.pH_init], [self.pL, self.pL_init], ]: A = QgsGeometry.fromPointXY(i) A.rotate(theta, self.pX) a.setX(A.asPoint().x()) a.setY(A.asPoint().y()) self.updateRubberGeom() def canvasReleaseEvent(self, event): self.pA_init = QgsPointXY(self.pA) self.pB_init = QgsPointXY(self.pB) self.pC_init = QgsPointXY(self.pC) self.pD_init = QgsPointXY(self.pD) self.pX_init = QgsPointXY(self.pX) self.pY_init = QgsPointXY(self.pY) self.pH_init = QgsPointXY(self.pH) self.pL_init = QgsPointXY(self.pL) self.rotation_init = self.rotation self.mode = self.MODE_NONE def activate(self): pass def deactivate(self): self.hide() def isZoomTool(self): return False def isTransient(self): return False def isEditTool(self): return True
class captureGPSFeatures(FieldRestrictionTypeUtilsMixin): def __init__(self, iface, featuresWithGPSToolbar): TOMsMessageLog.logMessage("In captureGPSFeatures::init", level=Qgis.Info) FieldRestrictionTypeUtilsMixin.__init__(self, iface) # Save reference to the QGIS interface self.iface = iface self.canvas = self.iface.mapCanvas() self.featuresWithGPSToolbar = featuresWithGPSToolbar self.gpsMapTool = False self.marker = None # This will set up the items on the toolbar # Create actions self.gnssToolGroup = QActionGroup(featuresWithGPSToolbar) self.actionCreateRestriction = QAction(QIcon(":/plugins/featureswithgps/resources/mActionAddTrack.svg"), QCoreApplication.translate("MyPlugin", "Create Restriction"), self.iface.mainWindow()) self.actionCreateRestriction.setCheckable(True) self.actionAddGPSLocation = QAction(QIcon(":/plugins/featureswithgps/resources/greendot3.png"), QCoreApplication.translate("MyPlugin", "Add vertex from gnss"), self.iface.mainWindow()) #self.actionAddGPSLocation.setCheckable(True) self.actionRemoveRestriction = QAction(QIcon(":plugins/featureswithgps/resources/mActionDeleteTrack.svg"), QCoreApplication.translate("MyPlugin", "Remove Restriction"), self.iface.mainWindow()) self.actionRemoveRestriction.setCheckable(True) self.actionRestrictionDetails = QAction(QIcon(":/plugins/featureswithgps/resources/mActionGetInfo.svg"), QCoreApplication.translate("MyPlugin", "Get Restriction Details"), self.iface.mainWindow()) self.actionRestrictionDetails.setCheckable(True) self.gnssToolGroup.addAction(self.actionRestrictionDetails) self.actionCreateSign = QAction(QIcon(":/plugins/featureswithgps/resources/mActionSetEndPoint.svg"), QCoreApplication.translate("MyPlugin", "Create sign from gnss"), self.iface.mainWindow()) self.actionCreateSign.setCheckable(True) self.actionCreateMTR = QAction(QIcon(":/plugins/featureswithgps/resources/UK_traffic_sign_606F.svg"), QCoreApplication.translate("MyPlugin", "Create moving traffic restriction"), self.iface.mainWindow()) self.actionCreateMTR.setCheckable(True) self.actionMoveFeatureToDifferentLayer = QAction(QIcon(""), QCoreApplication.translate("MyPlugin", "Move feature to different layer"), self.iface.mainWindow()) self.actionMoveFeatureToDifferentLayer.setCheckable(True) self.gnssToolGroup.addAction(self.actionMoveFeatureToDifferentLayer) # Add actions to the toolbar self.featuresWithGPSToolbar.addAction(self.actionCreateRestriction) self.featuresWithGPSToolbar.addAction(self.actionAddGPSLocation) self.featuresWithGPSToolbar.addAction(self.actionRestrictionDetails) #self.featuresWithGPSToolbar.addAction(self.actionRemoveRestriction) self.featuresWithGPSToolbar.addAction(self.actionCreateSign) #self.featuresWithGPSToolbar.addAction(self.actionCreateMTR) self.featuresWithGPSToolbar.addAction(self.actionMoveFeatureToDifferentLayer) self.gnssToolGroup.addAction(self.actionCreateRestriction) #self.gnssToolGroup.addAction(self.actionAddGPSLocation) #self.gnssToolGroup.addAction(self.actionRemoveRestriction) self.gnssToolGroup.addAction(self.actionRestrictionDetails) #self.gnssToolGroup.addAction(self.actionCreateSign) #self.gnssToolGroup.addAction(self.actionCreateMTR) self.gnssToolGroup.addAction(self.actionMoveFeatureToDifferentLayer) self.gnssToolGroup.setExclusive(True) self.gnssToolGroup.triggered.connect(self.onGroupTriggered) # Connect action signals to slots self.actionCreateRestriction.triggered.connect(self.doCreateRestriction) self.actionAddGPSLocation.triggered.connect(self.doAddGPSLocation) self.actionRestrictionDetails.triggered.connect(self.doRestrictionDetails) #self.actionRemoveRestriction.triggered.connect(self.doRemoveRestriction) self.actionCreateSign.triggered.connect(self.doCreateSign) #self.actionCreateMTR.triggered.connect(self.doCreateMTR) self.actionMoveFeatureToDifferentLayer.triggered.connect(self.doMoveFeatureToDifferentLayer) self.actionCreateRestriction.setEnabled(False) self.actionAddGPSLocation.setEnabled(False) self.actionRestrictionDetails.setEnabled(False) #self.actionRemoveRestriction.setEnabled(False) self.actionCreateSign.setEnabled(False) #self.actionCreateMTR.setEnabled(False) self.actionMoveFeatureToDifferentLayer.setEnabled(False) self.searchBar = searchBar(self.iface, self.featuresWithGPSToolbar) self.searchBar.disableSearchBar() self.mapTool = None self.currGnssAction = None self.gpsConnection = None self.createMapToolDict = {} def enableFeaturesWithGPSToolbarItems(self): TOMsMessageLog.logMessage("In enablefeaturesWithGPSToolbarItems", level=Qgis.Warning) self.gpsAvailable = False self.closeTOMs = False self.tableNames = TOMsLayers(self.iface) self.params = gpsParams() self.tableNames.TOMsLayersNotFound.connect(self.setCloseTOMsFlag) #self.tableNames.gpsLayersNotFound.connect(self.setCloseCaptureGPSFeaturesFlag) self.params.TOMsParamsNotFound.connect(self.setCloseCaptureGPSFeaturesFlag) self.TOMsConfigFileObject = TOMsConfigFile() self.TOMsConfigFileObject.TOMsConfigFileNotFound.connect(self.setCloseTOMsFlag) self.TOMsConfigFileObject.initialiseTOMsConfigFile() self.tableNames.getLayers(self.TOMsConfigFileObject) self.prj = QgsProject().instance() self.dest_crs = self.prj.crs() TOMsMessageLog.logMessage("In captureGPSFeatures::init project CRS is " + self.dest_crs.description(), level=Qgis.Warning) self.transformation = QgsCoordinateTransform(QgsCoordinateReferenceSystem("EPSG:4326"), self.dest_crs, self.prj) self.params.getParams() if self.closeTOMs: QMessageBox.information(self.iface.mainWindow(), "ERROR", ("Unable to start editing tool ...")) #self.actionProposalsPanel.setChecked(False) return # TODO: allow function to continue without GPS enabled ... # Now check to see if the port is set. If not assume that just normal tools gpsPort = self.params.setParam("gpsPort") TOMsMessageLog.logMessage("In enableFeaturesWithGPSToolbarItems: GPS port is: {}".format(gpsPort), level=Qgis.Warning) self.gpsConnection = None if gpsPort: self.gpsAvailable = True if self.gpsAvailable == True: self.curr_gps_location = None self.curr_gps_info = None TOMsMessageLog.logMessage("In enableFeaturesWithGPSToolbarItems - GPS port is specified ", level=Qgis.Info) self.gps_thread = GPS_Thread(self.dest_crs, gpsPort) thread = QThread() self.gps_thread.moveToThread(thread) self.gps_thread.gpsActivated.connect(self.gpsStarted) self.gps_thread.gpsPosition.connect(self.gpsPositionProvided) self.gps_thread.gpsDeactivated.connect(functools.partial(self.gpsStopped)) self.gps_thread.gpsError.connect(self.gpsErrorEncountered) #self.gps_thread.progress.connect(progressBar.setValue) thread.started.connect(self.gps_thread.startGPS) #thread.finished.connect(functools.partial(self.gpsStopped, thread)) thread.start() self.thread = thread TOMsMessageLog.logMessage("In enableFeaturesWithGPSToolbarItems - attempting connection ", level=Qgis.Info) time.sleep(1.0) try: self.roamDistance = float(self.params.setParam("roamDistance")) except Exception as e: TOMsMessageLog.logMessage("In enableFeaturesWithGPSToolbarItems:init: roamDistance issue: {}".format(e), level=Qgis.Warning) self.roamDistance = 5.0 self.enableToolbarItems() self.createMapToolDict = {} def enableToolbarItems(self): TOMsMessageLog.logMessage("In enableToolbarItems", level=Qgis.Warning) self.actionCreateRestriction.setEnabled(True) self.actionRestrictionDetails.setEnabled(True) #self.actionRemoveRestriction.setEnabled(True) #self.actionCreateSign.setEnabled(True) #self.actionCreateMTR.setEnabled(True) self.actionMoveFeatureToDifferentLayer.setEnabled(True) self.searchBar.enableSearchBar() self.currMapTool = None self.theCurrentMapTool = None self.iface.currentLayerChanged.connect(self.changeCurrLayer2) self.canvas.mapToolSet.connect(self.changeMapTool2) self.canvas.extentsChanged.connect(self.changeExtents) # transaction for move ... self.localTransaction = MoveLayerTransaction(self.iface) def enableGnssToolbarItem(self): if self.gpsConnection: self.actionAddGPSLocation.setEnabled(True) self.actionCreateSign.setEnabled(True) self.lastCentre = QgsPointXY(0,0) def disableGnssToolbarItem(self): self.actionAddGPSLocation.setEnabled(False) self.actionCreateSign.setEnabled(False) def disableToolbarItems(self): self.actionCreateRestriction.setEnabled(False) self.actionRestrictionDetails.setEnabled(False) self.actionRemoveRestriction.setEnabled(False) self.actionCreateSign.setEnabled(False) #self.actionCreateMTR.setEnabled(False) self.actionMoveFeatureToDifferentLayer.setEnabled(False) self.searchBar.disableSearchBar() """if self.gpsConnection: self.actionAddGPSLocation.setEnabled(False)""" def setCloseTOMsFlag(self): self.closeTOMs = True QMessageBox.information(self.iface.mainWindow(), "ERROR", ("Now closing TOMs ...")) def disableFeaturesWithGPSToolbarItems(self): TOMsMessageLog.logMessage("In disablefeaturesWithGPSToolbarItems", level=Qgis.Warning) if self.gpsConnection and not self.closeTOMs: self.gps_thread.endGPS() self.disableToolbarItems() # TODO: Need to delete any tools ... for layer, mapTool in self.createMapToolDict.items (): try: status = layer.rollBack() except Exception as e: None """reply = QMessageBox.information(None, "Information", "Problem rolling back changes" + str(self.currLayer.commitErrors()), QMessageBox.Ok)""" del mapTool self.createMapToolDict = {} try: self.iface.currentLayerChanged.disconnect(self.changeCurrLayer2) except Exception as e: TOMsMessageLog.logMessage( "In disableFeaturesWithGPSToolbarItems. Issue with disconnects for currentLayerChanged {}".format(e), level=Qgis.Warning) try: self.canvas.mapToolSet.disconnect(self.changeMapTool2) except Exception as e: TOMsMessageLog.logMessage( "In disableFeaturesWithGPSToolbarItems. Issue with disconnects for mapToolSet {}".format( e), level=Qgis.Warning) try: self.canvas.extentsChanged.disconnect(self.changeExtents) except Exception as e: TOMsMessageLog.logMessage( "In disableFeaturesWithGPSToolbarItems. Issue with disconnects for extentsChanged {}".format( e), level=Qgis.Warning) self.tableNames.removePathFromLayerForms() def setCloseCaptureGPSFeaturesFlag(self): self.closeCaptureGPSFeatures = True self.gpsAvailable = True def onGroupTriggered(self, action): # hold the current action self.currGnssAction = action TOMsMessageLog.logMessage("In onGroupTriggered: curr action is {}".format(action.text()), level=Qgis.Info) """ Using signals for ChangeTool and ChangeLayer to manage the tools - with the following functions """ def isGnssTool(self, mapTool): if (isinstance(mapTool, CreateRestrictionTool) or isinstance(mapTool, GeometryInfoMapTool) or isinstance(mapTool, RemoveRestrictionTool)): return True return False def changeMapTool2(self): TOMsMessageLog.logMessage( "In changeMapTool2 ...", level=Qgis.Info) currMapTool = self.iface.mapCanvas().mapTool() if not self.isGnssTool(currMapTool): TOMsMessageLog.logMessage( "In changeMapTool2. Unchecking action ...", level=Qgis.Info) if self.currGnssAction: self.currGnssAction.setChecked(False) else: TOMsMessageLog.logMessage( "In changeMapTool2. No action for gnssTools.", level=Qgis.Info) TOMsMessageLog.logMessage( "In changeMapTool2. finished.", level=Qgis.Info) #print('tool unset') def changeCurrLayer2(self): TOMsMessageLog.logMessage("In changeLayer2 ... ", level=Qgis.Info) try: currMapTool = self.iface.mapCanvas().mapTool() self.currGnssAction.setChecked(False) except Exception as e: None """if self.isGnssTool(currMapTool): TOMsMessageLog.logMessage("In changeLayer2. Action triggered ... ", level=Qgis.Info) self.currGnssAction.trigger() # assumption is that there is an action associated with the tool else: TOMsMessageLog.logMessage( "In changeLayer2. No action for currentMapTool.", level=Qgis.Info)""" TOMsMessageLog.logMessage( "In changeLayer2. finished.", level=Qgis.Info) print('layer changed') def doCreateRestriction(self): TOMsMessageLog.logMessage("In doCreateRestriction", level=Qgis.Info) self.currLayer = self.iface.activeLayer() if not self.currLayer: reply = QMessageBox.information(self.iface.mainWindow(), "Information", "Please choose a layer ...", QMessageBox.Ok) return # TODO: Check that this is a restriction layer if self.actionCreateRestriction.isChecked(): TOMsMessageLog.logMessage("In doCreateRestriction - tool activated", level=Qgis.Info) TOMsMessageLog.logMessage( "In doCreateRestriction: current map tool {}".format(type(self.iface.mapCanvas().mapTool()).__name__), level=Qgis.Info) self.createRestrictionMapTool = self.createMapToolDict.get(self.currLayer) if not self.createRestrictionMapTool: TOMsMessageLog.logMessage("In doCreateRestriction. creating new map tool", level=Qgis.Info) self.createRestrictionMapTool = CreateRestrictionTool(self.iface, self.currLayer) self.createMapToolDict[self.currLayer] = self.createRestrictionMapTool TOMsMessageLog.logMessage("In doCreateRestriction. Here 1", level=Qgis.Info) self.iface.mapCanvas().setMapTool(self.createRestrictionMapTool) TOMsMessageLog.logMessage("In doCreateRestriction. Here 2", level=Qgis.Info) if not self.createRestrictionMapTool.isCapturing(): if self.currLayer.isEditable() == True: if self.currLayer.commitChanges() == False: reply = QMessageBox.information(None, "Information", "Problem committing changes" + str(self.currLayer.commitErrors()), QMessageBox.Ok) else: TOMsMessageLog.logMessage("In doCreateRestriction: changes committed", level=Qgis.Info) if self.currLayer.readOnly() == True: TOMsMessageLog.logMessage("In doCreateRestriction - Not able to start transaction ...", level=Qgis.Info) else: if self.currLayer.startEditing() == False: reply = QMessageBox.information(None, "Information", "Could not start transaction on " + self.currLayer.name(), QMessageBox.Ok) return TOMsMessageLog.logMessage("In doCreateRestriction. Here 3", level=Qgis.Info) else: TOMsMessageLog.logMessage("In doCreateRestriction - tool deactivated", level=Qgis.Info) if self.createRestrictionMapTool: self.iface.mapCanvas().unsetMapTool(self.createRestrictionMapTool) self.currMapTool = None self.currentlySelectedLayer = None self.actionCreateRestriction.setChecked(False) # TODO: stop editting on layers?? TOMsMessageLog.logMessage("In doCreateRestriction. Here 4", level=Qgis.Info) # -- end of tools for signals def changeExtents(self): TOMsMessageLog.logMessage("In changeExtents ... ", level=Qgis.Info) def doAddGPSLocation(self): # need to have a addPointFromGPS function within each tool TOMsMessageLog.logMessage("In doAddGPSLocation", level=Qgis.Info) if self.gpsConnection: if self.curr_gps_location: try: status = self.createRestrictionMapTool.addPointFromGPS(self.curr_gps_location, self.curr_gps_info) except Exception as e: TOMsMessageLog.logMessage("In doAddGPSLocation: Problem adding gnss location: {}".format(e), level=Qgis.Warning) reply = QMessageBox.information(self.iface.mainWindow(), "Error", "Problem adding gnss location ... ", QMessageBox.Ok) else: reply = QMessageBox.information(self.iface.mainWindow(), "Information", "No position found ...", QMessageBox.Ok) else: reply = QMessageBox.information(self.iface.mainWindow(), "Information", "You need to activate the tool first ...", QMessageBox.Ok) def doRestrictionDetails(self): """ Select point and then display details. Assume that there is only one of these map tools in existence at any one time ?? """ TOMsMessageLog.logMessage("In doRestrictionDetails", level=Qgis.Info) # TODO: Check whether or not there is a create maptool available. If so, stop this and finish using that/those tools if not self.iface.activeLayer(): reply = QMessageBox.information(self.iface.mainWindow(), "Information", "Please choose a layer ...", QMessageBox.Ok) return if self.actionRestrictionDetails.isChecked(): TOMsMessageLog.logMessage("In doRestrictionDetails - tool activated", level=Qgis.Warning) self.showRestrictionMapTool = GeometryInfoMapTool(self.iface) self.iface.mapCanvas().setMapTool(self.showRestrictionMapTool) self.showRestrictionMapTool.notifyFeatureFound.connect(self.showRestrictionDetails) else: TOMsMessageLog.logMessage("In doRestrictionDetails - tool deactivated", level=Qgis.Warning) if self.showRestrictionMapTool: self.iface.mapCanvas().unsetMapTool(self.showRestrictionMapTool) self.actionRestrictionDetails.setChecked(False) #@pyqtSlot(str) def showRestrictionDetails(self, closestLayer, closestFeature): TOMsMessageLog.logMessage( "In showRestrictionDetails ... Layer: " + str(closestLayer.name()), level=Qgis.Info) self.showRestrictionMapTool.notifyFeatureFound.disconnect(self.showRestrictionDetails) # TODO: could improve ... basically check to see if transaction in progress ... if closestLayer.isEditable() == True: reply = QMessageBox.question(None, "Information", "There is a transaction in progress on this layer. This action will rollback back any changes. Do you want to continue?", QMessageBox.Yes, QMessageBox.No) if reply == QMessageBox.No: return if closestLayer.commitChanges() == False: reply = QMessageBox.information(None, "Information", "Problem committing changes" + str(closestLayer.commitErrors()), QMessageBox.Ok) else: TOMsMessageLog.logMessage("In showRestrictionDetails: changes committed", level=Qgis.Info) """if self.iface.activeLayer().readOnly() == True: TOMsMessageLog.logMessage("In showSignDetails - Not able to start transaction ...", level=Qgis.Info) else: if self.iface.activeLayer().startEditing() == False: reply = QMessageBox.information(None, "Information", "Could not start transaction on " + self.currLayer.name(), QMessageBox.Ok) return""" self.dialog = self.iface.getFeatureForm(closestLayer, closestFeature) #self.TOMsUtils.setupRestrictionDialog(self.dialog, closestLayer, closestFeature) self.setupFieldRestrictionDialog(self.dialog, closestLayer, closestFeature) self.dialog.show() """ Decided that it is best to use the QGIS select/delete tools to manage removals. So these functions are not used """ def doRemoveRestriction(self): TOMsMessageLog.logMessage("In doRemoveRestriction", level=Qgis.Info) self.currLayer = self.iface.activeLayer() if not self.currLayer: reply = QMessageBox.information(self.iface.mainWindow(), "Information", "Please choose a layer ...", QMessageBox.Ok) return if self.currLayer.readOnly() == True: """reply = QMessageBox.information(None, "Information", "Could not start transaction on " + self.currLayer.name(), QMessageBox.Ok)""" TOMsMessageLog.logMessage("In doRemoveRestriction - Not able to start transaction ...", level=Qgis.Info) self.actionRemoveRestriction.setChecked(False) return if self.actionRemoveRestriction.isChecked(): TOMsMessageLog.logMessage("In doRemoveRestriction - tool activated", level=Qgis.Warning) """self.mapTool = self.deleteMapToolDict.get(self.currLayer) if not self.mapTool: self.mapTool = RemoveRestrictionTool(self.iface) self.deleteMapToolDict[self.currLayer] = self.mapTool""" self.mapTool = RemoveRestrictionTool(self.iface) #self.removeRestrictionMapTool.setAction(self.actionRemoveRestriction) self.iface.mapCanvas().setMapTool(self.removeRestrictionMapTool) #self.gpsMapTool = True #self.removeRestrictionMapTool.deactivated.connect(functools.partial(self.deactivateAction, self.actionRemoveRestriction)) #self.iface.currentLayerChanged.connect(self.changeCurrLayer) #self.canvas.mapToolSet.connect(self.changeMapTool) self.removeRestrictionMapTool.notifyFeatureFound.connect(self.removeRestriction) else: TOMsMessageLog.logMessage("In doRemoveRestriction - tool deactivated", level=Qgis.Warning) self.removeRestrictionMapTool.notifyFeatureFound.disconnect(self.removeRestriction) #self.canvas.mapToolSet.disconnect(self.changeMapTool) #self.iface.currentLayerChanged.disconnect(self.changeCurrLayer) self.iface.mapCanvas().unsetMapTool(self.removeRestrictionMapTool) #self.removeRestrictionMapTool.deactivate() #self.mapTool = None self.actionRemoveRestriction.setChecked(False) #@pyqtSlot(str) def removeRestriction(self, closestLayer, closestFeature): TOMsMessageLog.logMessage( "In removeRestriction ... Layer: " + str(closestLayer.name()), level=Qgis.Info) if closestLayer.isEditable() == True: if closestLayer.commitChanges() == False: reply = QMessageBox.information(None, "Information", "Problem committing changes" + str(closestLayer.commitErrors()), QMessageBox.Ok) else: TOMsMessageLog.logMessage("In removeRestriction: changes committed", level=Qgis.Info) if self.currLayer.startEditing() == False: reply = QMessageBox.information(None, "Information", "Could not start transaction on " + self.currLayer.name(), QMessageBox.Ok) return # TODO: Sort out this for UPDATE # self.setDefaultRestrictionDetails(closestFeature, closestLayer) closestLayer.deleteFeature(closestFeature.id()) if closestLayer.commitChanges() == False: reply = QMessageBox.information(None, "Information", "Problem committing changes" + str(closestLayer.commitErrors()), QMessageBox.Ok) else: TOMsMessageLog.logMessage("In removeRestriction: changes committed", level=Qgis.Info) """ This is a tool for adding a point feature. currently only used for signs, but could be used for any point """ def doCreateSign(self): TOMsMessageLog.logMessage("In doCreateSign", level=Qgis.Info) if self.actionCreateSign.isChecked(): self.currMapTool = self.canvas.mapTool() self.currentlySelectedLayer = self.iface.activeLayer() self.signsLayer = self.tableNames.setLayer("Signs") self.iface.setActiveLayer(self.signsLayer) self.createPointMapTool = CreatePointTool(self.iface, self.signsLayer) TOMsMessageLog.logMessage("In doCreateSign - tool activated", level=Qgis.Info) self.signsLayer.editingStopped.connect(self.reinstateMapTool) self.actionCreateSign.setChecked(False) self.iface.mapCanvas().setMapTool(self.createPointMapTool) """ add the point from the gnss """ try: status = self.canvas.mapTool().addPointFromGPS(self.curr_gps_location, self.curr_gps_info) except Exception as e: TOMsMessageLog.logMessage("In doCreateSign: Problem adding gnss location: {}".format(e), level=Qgis.Warning) reply = QMessageBox.information(self.iface.mainWindow(), "Error", "Problem adding gnss location ... ", QMessageBox.Ok) """ Not currently used, but want to develop ... """ def doCreateMTR(self): TOMsMessageLog.logMessage("In doCreateMTR", level=Qgis.Info) if self.actionCreateMTR.isChecked(): TOMsMessageLog.logMessage("In doCreateMTR - tool activated", level=Qgis.Info) # Open MTR form ... try: self.thisMtrForm except AttributeError: self.thisMtrForm = mtrForm(self.iface) #res = mtrFormFactory.prepareForm(self.iface, self.dbConn, self.dialog) #self.mtrTypeCB = self.dialog.findChild(QComboBox, "cmb_MTR_list") #self.mtrTypeCB.activated[str].connect(self.onLocalChanged) #self.currDialog.findChild(QComboBox, "cmb_MTR_list").activated[str].connect(self.onChanged) """ Need to setup dialog: a. create drop down b. link structure of form to different options from drop down, e.g., Access Restriction needs ?? attributes and one point, Turn Restriction needs ?? attributes and two points c. link getPoint actions to buttons """ status = self.thisMtrForm.show() # Run the dialog event loop result = self.thisMtrForm.exec_() # else: TOMsMessageLog.logMessage("In doCreateMTR - tool deactivated", level=Qgis.Info) #self.iface.mapCanvas().unsetMapTool(self.mapTool) #self.mapTool = None self.actionCreateMTR.setChecked(False) self.gpsMapTool = False def onLocalChanged(self, text): TOMsMessageLog.logMessage( "In generateFirstStageForm::selectionchange. " + text, level=Qgis.Info) res = mtrFormFactory.prepareForm(self.iface, self.dbConn, self.dialog, text) """ Used with the createSign tool to reinstate the last used maptool, i.e., to allow the interupt of feature creation """ def reinstateMapTool(self): TOMsMessageLog.logMessage("In reinstateMapTool ... ", level=Qgis.Info) self.iface.activeLayer().editingStopped.disconnect(self.reinstateMapTool) if self.currMapTool: TOMsMessageLog.logMessage( "In reinstateMapTool. layer to be reinstated {} using tool {}".format(self.currentlySelectedLayer.name(), self.currMapTool.toolName()), level=Qgis.Warning) # now reinstate if self.currentlySelectedLayer: self.iface.setActiveLayer(self.currentlySelectedLayer) self.iface.mapCanvas().setMapTool(self.currMapTool) def doMoveFeatureToDifferentLayer(self): """ Select point and then display details. Assume that there is only one of these map tools in existence at any one time ?? """ TOMsMessageLog.logMessage("In doMoveFeatureToDifferentLayer", level=Qgis.Info) # TODO: Check whether or not there is a create maptool available. If so, stop this and finish using that/those tools if not self.iface.activeLayer(): reply = QMessageBox.information(self.iface.mainWindow(), "Information", "Please choose a layer ...", QMessageBox.Ok) return if self.actionMoveFeatureToDifferentLayer.isChecked(): TOMsMessageLog.logMessage("In doMoveFeatureToDifferentLayer - tool activated", level=Qgis.Warning) self.moveFeatureToDifferentLayerMapTool = ChangeLayerMapTool(self.iface, self.localTransaction) self.iface.mapCanvas().setMapTool(self.moveFeatureToDifferentLayerMapTool) #self.showRestrictionMapTool.notifyFeatureFound.connect(self.showRestrictionDetails) else: TOMsMessageLog.logMessage("In doMoveFeatureToDifferentLayer - tool deactivated", level=Qgis.Warning) if self.moveFeatureToDifferentLayerMapTool: self.iface.mapCanvas().unsetMapTool(self.moveFeatureToDifferentLayerMapTool) self.actionMoveFeatureToDifferentLayer.setChecked(False) #@pyqtSlot(QgsGpsConnection) def gpsStarted(self, connection): TOMsMessageLog.logMessage("In enableTools - GPS connection found ", level=Qgis.Info) self.gpsConnection = connection # marker self.marker = QgsVertexMarker(self.canvas) self.marker.setColor(QColor(255, 0, 0)) # (R,G,B) self.marker.setIconSize(10) self.marker.setIconType(QgsVertexMarker.ICON_CIRCLE) self.marker.setPenWidth(3) self.enableGnssToolbarItem() reply = QMessageBox.information(None, "Information", "Connection found", QMessageBox.Ok) #@pyqtSlot() def gpsStopped(self): TOMsMessageLog.logMessage("In enableTools - GPS connection stopped ", level=Qgis.Warning) self.gps_thread.deleteLater() self.thread.quit() self.thread.wait() self.thread.deleteLater() if self.gpsConnection: if self.canvas is not None: self.marker.hide() self.canvas.scene().removeItem(self.marker) self.gpsConnection = None self.disableGnssToolbarItem() #@pyqtSlot() def gpsPositionProvided(self, mapPointXY, gpsInfo): """reply = QMessageBox.information(None, "Information", "Position provided", QMessageBox.Ok)""" TOMsMessageLog.logMessage("In enableTools - ******** initial GPS location provided " + mapPointXY.asWkt(), level=Qgis.Info) self.curr_gps_location = mapPointXY self.curr_gps_info = gpsInfo wgs84_pointXY = QgsPointXY(gpsInfo.longitude, gpsInfo.latitude) wgs84_point = QgsPoint(wgs84_pointXY) wgs84_point.transform(self.transformation) x = wgs84_point.x() y = wgs84_point.y() new_mapPointXY = QgsPointXY(x, y) TOMsMessageLog.logMessage("In enableTools - ******** transformed GPS location provided " + str(gpsInfo.longitude) + ":" + str(gpsInfo.latitude) + "; " + new_mapPointXY.asWkt(), level=Qgis.Info) if gpsInfo.pdop >= 1: # gps ok self.marker.setColor(QColor(0, 200, 0)) else: self.marker.setColor(QColor(255, 0, 0)) self.marker.setCenter(mapPointXY) self.marker.show() #self.canvas.setCenter(mapPointXY) """TOMsMessageLog.logMessage("In enableTools: distance from last fix: {}".format(self.lastCentre.distance(mapPointXY)), level=Qgis.Info)""" if self.lastCentre.distance(mapPointXY) > self.roamDistance: self.lastCentre = mapPointXY self.canvas.setCenter(mapPointXY) TOMsMessageLog.logMessage( "In enableTools: distance from last fix: {}".format(self.lastCentre.distance(mapPointXY)), level=Qgis.Warning) self.canvas.refresh() # TODO: populate message bar with details about satellites, etc #@pyqtSlot(Exception, str) def gpsErrorEncountered(self, e): TOMsMessageLog.logMessage("In enableTools - GPS connection has error {}".format(e), level=Qgis.Warning) """self.actionCreateRestriction.setEnabled(False) self.actionAddGPSLocation.setEnabled(False)""" self.disableGnssToolbarItem()
def processAlgorithm(self, parameters, context, feedback): self.parameters = parameters self.context = context self.feedback = feedback load_geotiffs = self.parameterAsInt(parameters, self.PrmLoadGeoTiffs, context) out_folder = self.parameterAsFile(parameters, self.PrmGroundOverlayFolder, context) input_file = self.parameterAsFile(parameters, self.PrmInput, context) f, extension = os.path.splitext(input_file) dirname = os.path.dirname(input_file) extension = extension.lower() try: if extension == '.kmz': kmz = ZipFile(input_file, 'r') kml = kmz.open('doc.kml', 'r') elif extension == '.kml': kml = open(input_file, encoding="utf-8", errors="backslashreplace") else: msg = "Invalid extension: Should be kml or kmz" raise QgsProcessingException(msg) except Exception: msg = "Failed to open file" raise QgsProcessingException(msg) parser = xml.sax.make_parser() self.overlays = [] # Set up the handler for doing the main processing handler = GroundOverlayHandler(feedback) handler.groundoverlay.connect(self.groundoverlay) parser.setContentHandler(handler) try: input_source = xml.sax.xmlreader.InputSource() input_source.setByteStream(kml) input_source.setEncoding('utf-8') parser.parse(input_source) except Exception: '''s = traceback.format_exc() feedback.pushInfo(s)''' feedback.reportError( tr('Failure in kml extraction - May return partial results.')) handler.endDocument() # Iterate through each found overlay images for overlay in self.overlays: north = overlay[0] south = overlay[1] east = overlay[2] west = overlay[3] rotation = overlay[4] href = overlay[5] if href.startswith('http:') or href.startswith('https:'): feedback.reportError( 'Cannot process network images: {}'.format(href)) continue if extension == '.kmz': try: image = kmz.read(href) output_file = os.path.basename(href) file_name, ext = os.path.splitext(output_file) # Write out a temporary image temp_file_name = os.path.join( out_folder, '{}_temp{}'.format(file_name, ext)) fp = open(temp_file_name, "wb") fp.write(image) fp.close() raster = QgsRasterLayer(temp_file_name, "temp") except Exception: feedback.reportError( 'Image does not exist: {}'.format(href)) continue else: # Check to see if it is a valid file name in_path = os.path.join(dirname, href) if not os.path.isfile(in_path): # The path was not valid feedback.reportError( 'Image file does not exist: {}'.format(in_path)) continue raster = QgsRasterLayer(in_path, "temp") output_file = os.path.basename(in_path) file_name, ext = os.path.splitext(output_file) if not raster.isValid(): feedback.reportError('Invalid raster image: {}'.format(href)) continue out_path = os.path.join(out_folder, file_name + ".tif") if rotation == 0: status = processing.run( "gdal:translate", { 'INPUT': raster, 'EXTRA': '-a_srs EPSG:4326 -a_ullr {} {} {} {}'.format( west, north, east, south), 'DATA_TYPE': 0, 'OUTPUT': out_path }) else: rwidth = raster.width() rheight = raster.height() center_x = (east + west) / 2.0 center_y = (north + south) / 2.0 center_pt = QgsPointXY(center_x, center_y) ul_pt = QgsPointXY(west, north) ur_pt = QgsPointXY(east, north) lr_pt = QgsPointXY(east, south) ll_pt = QgsPointXY(west, south) distance = center_pt.distance(ul_pt) az = center_pt.azimuth(ul_pt) - rotation pt1 = center_pt.project(distance, az) az = center_pt.azimuth(ur_pt) - rotation pt2 = center_pt.project(distance, az) az = center_pt.azimuth(lr_pt) - rotation pt3 = center_pt.project(distance, az) az = center_pt.azimuth(ll_pt) - rotation pt4 = center_pt.project(distance, az) gcp1 = '-gcp {} {} {} {}'.format(0, 0, pt1.x(), pt1.y()) gcp2 = '-gcp {} {} {} {}'.format(rwidth, 0, pt2.x(), pt2.y()) gcp3 = '-gcp {} {} {} {}'.format(rwidth, rheight, pt3.x(), pt3.y()) gcp4 = '-gcp {} {} {} {}'.format(0, rheight, pt4.x(), pt4.y()) status = processing.run( "gdal:translate", { 'INPUT': raster, 'EXTRA': '-a_srs EPSG:4326 -a_nodata 0,0,0 {} {} {} {}'.format( gcp1, gcp2, gcp3, gcp4), 'DATA_TYPE': 0, 'OUTPUT': out_path }) if load_geotiffs: context.addLayerToLoadOnCompletion( out_path, context.LayerDetails(file_name, project=context.project())) del raster if extension == '.kmz': try: os.remove(temp_file_name) os.remove(temp_file_name + '.aux.xml') except Exception: pass if extension == '.kmz': kmz.close() else: kml.close() # self.feedback.pushInfo('Number of overlays: {}'.format(len(self.overlays))) return ({})
class gnss_tool(QObject): gnssStarted = pyqtSignal() gnssStopped = pyqtSignal() def __init__(self, iface, params): super().__init__() TOMsMessageLog.logMessage("In gnss_tool::init", level=Qgis.Info) # Save reference to the QGIS interface self.iface = iface self.params = params self.canvas = self.iface.mapCanvas() self.prj = QgsProject().instance() self.dest_crs = self.prj.crs() TOMsMessageLog.logMessage("In gnss_tool::init project CRS is " + self.dest_crs.description(), level=Qgis.Warning) self.transformation = QgsCoordinateTransform(QgsCoordinateReferenceSystem("EPSG:4326"), self.dest_crs, self.prj) self.lastCentre = QgsPointXY(0, 0) self.setRoamDistance() self.setPort() def setPort(self): # Now check to see if the port is set. If not assume that just normal tools try: self.gpsPort = self.params.setParam("gpsPort") except Exception as e: TOMsMessageLog.logMessage("In enableFeaturesWithGPSToolbarItems:init: gpsPort issue: {}".format(e), level=Qgis.Warning) self.gpsPort = None TOMsMessageLog.logMessage("In gnss_tool: GPS port is: {}".format(self.gpsPort), level=Qgis.Info) def setRoamDistance(self): try: self.roamDistance = float(self.params.setParam("roamDistance")) except Exception as e: TOMsMessageLog.logMessage("In enableFeaturesWithGPSToolbarItems:init: roamDistance issue: {}".format(e), level=Qgis.Warning) self.roamDistance = 5.0 TOMsMessageLog.logMessage("In gnss_tool: roamDistance is: {}".format(self.roamDistance), level=Qgis.Info) def start_gnss(self): TOMsMessageLog.logMessage("In gnss_tool:start_gnss - GPS port is specified ", level=Qgis.Info) if self.gpsPort: self.gpsAvailable = True self.gpsConnection = None self.curr_gps_location = None self.curr_gps_info = None self.gps_thread = GPS_Thread(self.dest_crs, self.gpsPort) thread = QThread() self.gps_thread.moveToThread(thread) self.gps_thread.gpsActivated.connect(self.gpsStarted) self.gps_thread.gpsPosition.connect(self.gpsPositionProvided) self.gps_thread.gpsDeactivated.connect(self.gpsStopped) #self.gps_thread.gpsError.connect(self.gpsErrorEncountered) #objThread = QThread() #obj = SomeObject() #obj.moveToThread(objThread) #self.gps_thread.gpsDeactivated.connect(thread.quit) #obj.finished.connect(objThread.quit) #self.gps_thread.started.connect(self.startGPS) #objThread.started.connect(obj.long_running) #thread.finished.connect(self.gpsStopped) #objThread.finished.connect(app.exit) #thread.start() #objThread.start() # self.gps_thread.progress.connect(progressBar.setValue) thread.started.connect(self.gps_thread.startGPS) # thread.finished.connect(functools.partial(self.gpsStopped, thread)) thread.start() self.thread = thread TOMsMessageLog.logMessage("In enableFeaturesWithGPSToolbarItems - attempting connection ", level=Qgis.Info) #time.sleep(1.0) def stop_gnss(self): #self.gps_thread.endGPS() self.gpsStopped() # @pyqtSlot(QgsGpsConnection) def gpsStarted(self, connection): TOMsMessageLog.logMessage("In enableTools - GPS connection found ", level=Qgis.Info) self.gpsConnection = connection # marker self.marker = QgsVertexMarker(self.canvas) self.marker.setColor(QColor(255, 0, 0)) # (R,G,B) self.marker.setIconSize(10) self.marker.setIconType(QgsVertexMarker.ICON_CIRCLE) self.marker.setPenWidth(3) #self.enableGnssToolbarItem() reply = QMessageBox.information(None, "Information", "Connection found", QMessageBox.Ok) self.gnssStarted.emit() # @pyqtSlot() def gpsStopped(self): TOMsMessageLog.logMessage("In enableTools - GPS connection stopped ", level=Qgis.Warning) self.gps_thread.deleteLater() self.thread.quit() self.thread.wait() self.thread.deleteLater() if self.gpsConnection: if self.canvas is not None: self.marker.hide() self.canvas.scene().removeItem(self.marker) self.gpsConnection = None self.gnssStopped.emit() #QApplication.processEvents() # @pyqtSlot() def gpsPositionProvided(self, mapPointXY, gpsInfo): """reply = QMessageBox.information(None, "Information", "Position provided", QMessageBox.Ok)""" TOMsMessageLog.logMessage("In enableTools - ******** initial GPS location provided " + mapPointXY.asWkt(), level=Qgis.Info) self.curr_gps_location = mapPointXY self.curr_gps_info = gpsInfo wgs84_pointXY = QgsPointXY(gpsInfo.longitude, gpsInfo.latitude) wgs84_point = QgsPoint(wgs84_pointXY) wgs84_point.transform(self.transformation) x = wgs84_point.x() y = wgs84_point.y() new_mapPointXY = QgsPointXY(x, y) TOMsMessageLog.logMessage( "In enableTools - ******** transformed GPS location provided " + str(gpsInfo.longitude) + ":" + str( gpsInfo.latitude) + "; " + new_mapPointXY.asWkt(), level=Qgis.Info) if gpsInfo.pdop >= 1: # gps ok self.marker.setColor(QColor(0, 200, 0)) else: self.marker.setColor(QColor(255, 0, 0)) self.marker.setCenter(mapPointXY) self.marker.show() # self.canvas.setCenter(mapPointXY) """TOMsMessageLog.logMessage("In enableTools: distance from last fix: {}".format(self.lastCentre.distance(mapPointXY)), level=Qgis.Info)""" if self.lastCentre.distance(mapPointXY) > self.roamDistance: self.lastCentre = mapPointXY self.canvas.setCenter(mapPointXY) TOMsMessageLog.logMessage( "In enableTools: distance from last fix: {}".format(self.lastCentre.distance(mapPointXY)), level=Qgis.Warning) self.canvas.refresh() # TODO: populate message bar with details about satellites, etc def curr_gnss_position(self): if self.gpsConnection: return self.curr_gps_location, self.curr_gps_info else: return None, None # @pyqtSlot(Exception, str) def gpsErrorEncountered(self, e): TOMsMessageLog.logMessage("In enableTools - GPS connection has error ", level=Qgis.Info) QMessageBox.information(self.iface.mainWindow(), "ERROR", ("Error encountered with GNSS. Closing tools ...")) self.gnssStopped.emit()