def doIntersection(self, initPoint, observations): nObs = len(observations) if nObs < 2: return self.rubber.reset() self.dlg = IntersectionDialog(self.iface, observations, initPoint) if not self.dlg.exec_() or self.dlg.solution is None: return intersectedPoint = self.dlg.solution self.saveIntersectionResult(self.dlg.report, intersectedPoint) self.saveDimension(intersectedPoint, self.dlg.observations)
class AdvancedIntersectionMapTool(QgsMapTool): def __init__(self, iface): self.iface = iface self.mapCanvas = iface.mapCanvas() QgsMapTool.__init__(self, self.mapCanvas) self.settings = MySettings() self.rubber = QgsRubberBand(self.mapCanvas) self.tolerance = self.settings.value("selectTolerance") units = self.settings.value("selectUnits") if units == "pixels": self.tolerance *= self.mapCanvas.mapUnitsPerPixel() def activate(self): QgsMapTool.activate(self) self.rubber.setWidth(self.settings.value("rubberWidth")) self.rubber.setColor(self.settings.value("rubberColor")) line_layer = MemoryLayers(self.iface).line_layer() # unset this tool if the layer is removed line_layer.layerDeleted.connect(self.unsetMapTool) self.layerId = line_layer.id() # create snapper for this layer self.snapLayer = QgsSnapper.SnapLayer() self.snapLayer.mLayer = line_layer self.snapLayer.mSnapTo = QgsSnapper.SnapToVertexAndSegment self.snapLayer.mTolerance = self.settings.value("selectTolerance") if self.settings.value("selectUnits") == "map": self.snapLayer.mUnitType = QgsTolerance.MapUnits else: self.snapLayer.mUnitType = QgsTolerance.Pixels def unsetMapTool(self): self.mapCanvas.unsetMapTool(self) def deactivate(self): self.rubber.reset() line_layer = QgsMapLayerRegistry.instance().mapLayer(self.layerId) if line_layer is not None: line_layer.layerDeleted.disconnect(self.unsetMapTool) QgsMapTool.deactivate(self) def canvasMoveEvent(self, mouseEvent): # put the observations within tolerance in the rubber band self.rubber.reset() for f in self.getFeatures(mouseEvent.pos()): self.rubber.addGeometry(f.geometry(), None) def canvasPressEvent(self, mouseEvent): pos = mouseEvent.pos() observations = self.getFeatures(pos) point = self.toMapCoordinates(pos) self.doIntersection(point, observations) def getFeatures(self, pixPoint): snapper = QgsSnapper(self.mapCanvas.mapRenderer()) snapper.setSnapLayers([self.snapLayer]) snapper.setSnapMode(QgsSnapper.SnapWithResultsWithinTolerances) ok, snappingResults = snapper.snapPoint(pixPoint, []) # output snapped features features = [] alreadyGot = [] for result in snappingResults: featureId = result.snappedAtGeometry f = QgsFeature() if featureId not in alreadyGot: if result.layer.getFeatures(QgsFeatureRequest().setFilterFid(featureId)).nextFeature(f) is not False: features.append(QgsFeature(f)) alreadyGot.append(featureId) return features def doIntersection(self, initPoint, observations): nObs = len(observations) if nObs < 2: return self.rubber.reset() self.dlg = IntersectionDialog(self.iface, observations, initPoint) if not self.dlg.exec_() or self.dlg.solution is None: return intersectedPoint = self.dlg.solution self.saveIntersectionResult(self.dlg.report, intersectedPoint) self.saveDimension(intersectedPoint, self.dlg.observations) def saveIntersectionResult(self, report, intersectedPoint): # save the intersection result (point) and its report # check first while True: if not self.settings.value("advancedIntersectionWritePoint"): break # if we do not place any point, skip layerid = self.settings.value("advancedIntersectionLayer") message = QCoreApplication.translate("IntersectIt", "To place the intersection solution," " you must select a layer in the settings.") status, intLayer = self.checkLayerExists(layerid, message) if status == 2: continue if status == 3: return if self.settings.value("advancedIntersectionWriteReport"): reportField = self.settings.value("reportField") message = QCoreApplication.translate("IntersectIt", "To save the intersection report, please select a field for it.") status = self.checkFieldExists(intLayer, reportField, message) if status == 2: continue if status == 3: return break # save the intersection results if self.settings.value("advancedIntersectionWritePoint"): f = QgsFeature() f.setGeometry(QgsGeometry().fromPoint(intersectedPoint)) if self.settings.value("advancedIntersectionWriteReport"): irep = intLayer.dataProvider().fieldNameIndex(reportField) f.addAttribute(irep, report) intLayer.dataProvider().addFeatures([f]) intLayer.updateExtents() self.mapCanvas.refresh() def saveDimension(self, intersectedPoint, observations): # check that dimension layer and fields have been set correctly if not self.settings.value("dimensionDistanceWrite") and not self.settings.value("dimensionOrientationWrite"): return # if we do not place any dimension, skip obsTypes = ("Distance", "Orientation") recheck = True while recheck: # settings might change during checking, # so recheck both observation types whenever the settings dialog is shown recheck = False for obsType in obsTypes: while True: if not self.settings.value("dimension"+obsType+"Write"): break # check layer layerId = self.settings.value("dimension"+obsType+"Layer") message = QCoreApplication.translate("IntersectIt", "To place dimensions, " "you must define a layer in the settings.") status, dimLayer = self.checkLayerExists(layerId, message) if status == 2: recheck = True continue if status == 3: return # check fields if self.settings.value("dimension"+obsType+"ObservationWrite"): obsField = self.settings.value("dimension"+obsType+"ObservationField") message = QCoreApplication.translate("IntersectIt", "To save the observation in the layer," " please select a field for it.") status = self.checkFieldExists(dimLayer, obsField, message) if status == 2: recheck = True continue if status == 3: return if self.settings.value("dimension"+obsType+"PrecisionWrite"): precisionField = self.settings.value("dimension"+obsType+"PrecisionField") message = QCoreApplication.translate("IntersectIt", "To save the precision of observation," " please select a field for it.") status = self.checkFieldExists(dimLayer, precisionField, message) if status == 2: recheck = True continue if status == 3: return break # save the intersection results for obsType in obsTypes: if self.settings.value("dimension"+obsType+"Write"): layerid = self.settings.value("dimension"+obsType+"Layer") layer = QgsMapLayerRegistry.instance().mapLayer(layerid) if layer is None: continue initFields = layer.dataProvider().fields() features = [] for obs in observations: if obs["type"] != obsType.lower(): continue f = QgsFeature() f.setFields(initFields) f.initAttributes(initFields.size()) if self.settings.value("dimension"+obsType+"ObservationWrite"): f[self.settings.value("dimension"+obsType+"ObservationField")] = obs["observation"] if self.settings.value("dimension"+obsType+"PrecisionWrite"): f[self.settings.value("dimension"+obsType+"PrecisionField")] = obs["precision"] p0 = QgsPoint(obs["x"], obs["y"]) p1 = intersectedPoint if obs["type"] == "distance": geom = Arc(p0, p1).geometry() elif obs["type"] == "orientation": geom = QgsGeometry().fromPolyline([p0, p1]) else: raise NameError("Invalid observation %s" % obs["type"]) f.setGeometry(geom) features.append(QgsFeature(f)) if not layer.dataProvider().addFeatures(features): self.iface.messageBar().pushMessage("Could not commit %s observations" % obsType, QgsMessageBar.CRITICAL) layer.updateExtents() self.mapCanvas.refresh() def checkLayerExists(self, layerid, message): # returns: # 1: layer exists # 2: does not exist, settings has been open, so loop once more (i.e. continue) # 3: does not exist, settings not edited, so cancel layer = QgsMapLayerRegistry.instance().mapLayer(layerid) if layer is not None: return 1, layer reply = QMessageBox.question(self.iface.mainWindow(), "Intersect It", message + " Would you like to open settings?", QMessageBox.Yes, QMessageBox.No) if reply == QMessageBox.Yes: if MySettingsDialog().exec_(): return 2 return 3 def checkFieldExists(self, layer, field, message): # returns: # 1: field exists # 2: does not exist, settings has been open, so loop once more (i.e. continue) # 3: does not exist, settings not edited, so cancel if layer.dataProvider().fieldNameIndex(field) != -1: return 1 reply = QMessageBox.question(self.iface.mainWindow(), "Intersect It", message + " Would you like to open settings?", QMessageBox.Yes, QMessageBox.No) if reply == QMessageBox.Yes: if MySettingsDialog().exec_(): return 2 return 3
class AdvancedIntersectionMapTool(QgsMapTool): def __init__(self, iface): self.iface = iface self.mapCanvas = iface.mapCanvas() QgsMapTool.__init__(self, self.mapCanvas) self.settings = MySettings() self.rubber = QgsRubberBand(self.mapCanvas) self.tolerance = self.settings.value("selectTolerance") units = self.settings.value("selectUnits") if units == "pixels": self.tolerance *= self.mapCanvas.mapUnitsPerPixel() def activate(self): QgsMapTool.activate(self) self.rubber.setWidth(self.settings.value("rubberWidth")) self.rubber.setColor(self.settings.value("rubberColor")) line_layer = MemoryLayers(self.iface).line_layer() # unset this tool if the layer is removed line_layer.layerDeleted.connect(self.unsetMapTool) self.layerId = line_layer.id() # create snapper for this layer self.snapLayer = QgsSnapper.SnapLayer() self.snapLayer.mLayer = line_layer self.snapLayer.mSnapTo = QgsSnapper.SnapToVertexAndSegment self.snapLayer.mTolerance = self.settings.value("selectTolerance") if self.settings.value("selectUnits") == "map": self.snapLayer.mUnitType = QgsTolerance.MapUnits else: self.snapLayer.mUnitType = QgsTolerance.Pixels def unsetMapTool(self): self.mapCanvas.unsetMapTool(self) def deactivate(self): self.rubber.reset() line_layer = QgsMapLayerRegistry.instance().mapLayer(self.layerId) if line_layer is not None: line_layer.layerDeleted.disconnect(self.unsetMapTool) QgsMapTool.deactivate(self) def canvasMoveEvent(self, mouseEvent): # put the observations within tolerance in the rubber band self.rubber.reset() for f in self.getFeatures(mouseEvent.pos()): self.rubber.addGeometry(f.geometry(), None) def canvasPressEvent(self, mouseEvent): pos = mouseEvent.pos() observations = self.getFeatures(pos) point = self.toMapCoordinates(pos) self.doIntersection(point, observations) def getFeatures(self, pixPoint): snapper = QgsSnapper(self.mapCanvas.mapRenderer()) snapper.setSnapLayers([self.snapLayer]) snapper.setSnapMode(QgsSnapper.SnapWithResultsWithinTolerances) ok, snappingResults = snapper.snapPoint(pixPoint, []) # output snapped features features = [] alreadyGot = [] for result in snappingResults: featureId = result.snappedAtGeometry f = QgsFeature() if featureId not in alreadyGot: if result.layer.getFeatures(QgsFeatureRequest().setFilterFid( featureId)).nextFeature(f) is not False: features.append(QgsFeature(f)) alreadyGot.append(featureId) return features def doIntersection(self, initPoint, observations): nObs = len(observations) if nObs < 2: return self.rubber.reset() self.dlg = IntersectionDialog(self.iface, observations, initPoint) if not self.dlg.exec_() or self.dlg.solution is None: return intersectedPoint = self.dlg.solution self.saveIntersectionResult(self.dlg.report, intersectedPoint) self.saveDimension(intersectedPoint, self.dlg.observations) def saveIntersectionResult(self, report, intersectedPoint): # save the intersection result (point) and its report # check first while True: if not self.settings.value("advancedIntersectionWritePoint"): break # if we do not place any point, skip layerid = self.settings.value("advancedIntersectionLayer") message = QCoreApplication.translate( "IntersectIt", "To place the intersection solution," " you must select a layer in the settings.") status, intLayer = self.checkLayerExists(layerid, message) if status == 2: continue if status == 3: return if self.settings.value("advancedIntersectionWriteReport"): reportField = self.settings.value("reportField") message = QCoreApplication.translate( "IntersectIt", "To save the intersection report, please select a field for it." ) status = self.checkFieldExists(intLayer, reportField, message) if status == 2: continue if status == 3: return break # save the intersection results if self.settings.value("advancedIntersectionWritePoint"): f = QgsFeature() f.setGeometry(QgsGeometry().fromPoint(intersectedPoint)) if self.settings.value("advancedIntersectionWriteReport"): irep = intLayer.dataProvider().fieldNameIndex(reportField) f.addAttribute(irep, report) intLayer.dataProvider().addFeatures([f]) intLayer.updateExtents() self.mapCanvas.refresh() def saveDimension(self, intersectedPoint, observations): # check that dimension layer and fields have been set correctly if not self.settings.value( "dimensionDistanceWrite") and not self.settings.value( "dimensionOrientationWrite"): return # if we do not place any dimension, skip obsTypes = ("Distance", "Orientation") recheck = True while recheck: # settings might change during checking, # so recheck both observation types whenever the settings dialog is shown recheck = False for obsType in obsTypes: while True: if not self.settings.value("dimension" + obsType + "Write"): break # check layer layerId = self.settings.value("dimension" + obsType + "Layer") message = QCoreApplication.translate( "IntersectIt", "To place dimensions, " "you must define a layer in the settings.") status, dimLayer = self.checkLayerExists(layerId, message) if status == 2: recheck = True continue if status == 3: return # check fields if self.settings.value("dimension" + obsType + "ObservationWrite"): obsField = self.settings.value("dimension" + obsType + "ObservationField") message = QCoreApplication.translate( "IntersectIt", "To save the observation in the layer," " please select a field for it.") status = self.checkFieldExists(dimLayer, obsField, message) if status == 2: recheck = True continue if status == 3: return if self.settings.value("dimension" + obsType + "PrecisionWrite"): precisionField = self.settings.value("dimension" + obsType + "PrecisionField") message = QCoreApplication.translate( "IntersectIt", "To save the precision of observation," " please select a field for it.") status = self.checkFieldExists(dimLayer, precisionField, message) if status == 2: recheck = True continue if status == 3: return break # save the intersection results for obsType in obsTypes: if self.settings.value("dimension" + obsType + "Write"): layerid = self.settings.value("dimension" + obsType + "Layer") layer = QgsMapLayerRegistry.instance().mapLayer(layerid) if layer is None: continue initFields = layer.dataProvider().fields() features = [] for obs in observations: if obs["type"] != obsType.lower(): continue f = QgsFeature() f.setFields(initFields) f.initAttributes(initFields.size()) if self.settings.value("dimension" + obsType + "ObservationWrite"): f[self.settings.value( "dimension" + obsType + "ObservationField")] = obs["observation"] if self.settings.value("dimension" + obsType + "PrecisionWrite"): f[self.settings.value( "dimension" + obsType + "PrecisionField")] = obs["precision"] p0 = QgsPoint(obs["x"], obs["y"]) p1 = intersectedPoint if obs["type"] == "distance": geom = Arc(p0, p1).geometry() elif obs["type"] == "orientation": geom = QgsGeometry().fromPolyline([p0, p1]) else: raise NameError("Invalid observation %s" % obs["type"]) f.setGeometry(geom) features.append(QgsFeature(f)) if not layer.dataProvider().addFeatures(features): self.iface.messageBar().pushMessage( "Could not commit %s observations" % obsType, QgsMessageBar.CRITICAL) layer.updateExtents() self.mapCanvas.refresh() def checkLayerExists(self, layerid, message): # returns: # 1: layer exists # 2: does not exist, settings has been open, so loop once more (i.e. continue) # 3: does not exist, settings not edited, so cancel layer = QgsMapLayerRegistry.instance().mapLayer(layerid) if layer is not None: return 1, layer reply = QMessageBox.question( self.iface.mainWindow(), "Intersect It", message + " Would you like to open settings?", QMessageBox.Yes, QMessageBox.No) if reply == QMessageBox.Yes: if MySettingsDialog().exec_(): return 2 return 3 def checkFieldExists(self, layer, field, message): # returns: # 1: field exists # 2: does not exist, settings has been open, so loop once more (i.e. continue) # 3: does not exist, settings not edited, so cancel if layer.dataProvider().fieldNameIndex(field) != -1: return 1 reply = QMessageBox.question( self.iface.mainWindow(), "Intersect It", message + " Would you like to open settings?", QMessageBox.Yes, QMessageBox.No) if reply == QMessageBox.Yes: if MySettingsDialog().exec_(): return 2 return 3