def canvasMoveEvent(self, event): # pylint: disable=missing-docstring if not self.is_active: # snapping tool - show indicator matches = self.get_district_boundary_matches(event.mapPoint()) if self.matches_are_valid_for_boundary(matches): # we require exactly 2 matches from different districts -- cursor must be over a border # of two features self.snap_indicator.setMatch(matches[0]) else: self.snap_indicator.setMatch(QgsPointLocator.Match()) elif self.districts: dist = self.click_point.distance(event.mapPoint()) if dist < QgsTolerance.vertexSearchRadius(self.canvas().mapSettings()): return match = self.get_district_area_match(event.mapPoint()) p = QgsGeometry.fromPointXY(event.mapPoint()) targets = [m for m in self.get_target_features_from_matches([match]) if m.id() not in self.modified and m.geometry().intersects(p)] if len(targets) == 1: target = targets[0] old_district = target[self.handler.target_field] if not self.current_district: candidates = [d for d in self.districts if d != old_district] if candidates: self.current_district = candidates[0] if self.current_district and old_district and self.current_district != old_district: if not self.modified: # first modified district - push edit command self.handler.begin_edit_group( QCoreApplication.translate('LinzRedistrict', 'Redistrict to {}').format( self.district_registry.get_district_title(self.current_district))) self.modified.add(target.id()) self.handler.assign_district([target.id()], self.current_district) AudioUtils.play_redistrict_sound()
def snap_to_intersection(self, pos): """ Temporarily override snapping config and snap to vertices and edges of any editable vector layer, to allow selection of node for editing (if snapped to edge, it would offer creation of a new vertex there). """ map_point = self.toMapCoordinates(pos) tol = QgsTolerance.vertexSearchRadius(self.canvas().mapSettings()) snap_type = QgsPointLocator.Type(QgsPointLocator.Edge) snap_layers = [] for layer in self.canvas().layers(): if not isinstance(layer, QgsVectorLayer): continue snap_layers.append(QgsSnappingUtils.LayerConfig( layer, snap_type, tol, QgsTolerance.ProjectUnits)) snap_util = self.canvas().snappingUtils() old_layers = snap_util.layers() old_mode = snap_util.snapToMapMode() old_inter = snap_util.snapOnIntersections() snap_util.setLayers(snap_layers) snap_util.setSnapToMapMode(QgsSnappingUtils.SnapAdvanced) snap_util.setSnapOnIntersections(True) m = snap_util.snapToMap(map_point) snap_util.setLayers(old_layers) snap_util.setSnapToMapMode(old_mode) snap_util.setSnapOnIntersections(old_inter) return m
def snap_to_segment(self, pos): """ Temporarily override snapping config and snap to vertices and edges of any editable vector layer, to allow selection of node for editing (if snapped to edge, it would offer creation of a new vertex there). """ map_point = self.toMapCoordinates(pos) tol = QgsTolerance.vertexSearchRadius(self.canvas.mapSettings()) snap_type = QgsPointLocator.Type(QgsPointLocator.Edge) snap_layers = [] for layer in self.canvas.layers(): if not isinstance(layer, QgsVectorLayer): continue snap_layers.append( QgsSnappingUtils.LayerConfig(layer, snap_type, tol, QgsTolerance.ProjectUnits)) snap_util = self.canvas.snappingUtils() old_layers = snap_util.layers() old_mode = snap_util.snapToMapMode() old_inter = snap_util.snapOnIntersections() snap_util.setLayers(snap_layers) snap_util.setSnapToMapMode(QgsSnappingUtils.SnapAdvanced) snap_util.setSnapOnIntersections(False) m = snap_util.snapToMap(map_point) snap_util.setLayers(old_layers) snap_util.setSnapToMapMode(old_mode) snap_util.setSnapOnIntersections(old_inter) return m
def snap_to_dimension_layer(self, pos): """ Temporarily override snapping config and snap to vertices and edges of any editable vector layer, to allow selection of node for editing (if snapped to edge, it would offer creation of a new vertex there). """ map_point = self.toMapCoordinates(pos) tol = QgsTolerance.vertexSearchRadius(self.canvas().mapSettings()) snap_type = QgsPointLocator.Type(QgsPointLocator.Edge) snap_layers = [ QgsSnappingUtils.LayerConfig(self.layer, snap_type, tol, QgsTolerance.ProjectUnits) ] snap_util = self.canvas().snappingUtils() old_layers = snap_util.layers() old_mode = snap_util.snapToMapMode() old_inter = snap_util.snapOnIntersections() snap_util.setLayers(snap_layers) snap_util.setSnapToMapMode(QgsSnappingUtils.SnapAdvanced) snap_util.setSnapOnIntersections(False) m = snap_util.snapToMap(map_point) snap_util.setLayers(old_layers) snap_util.setSnapToMapMode(old_mode) snap_util.setSnapOnIntersections(old_inter) f = QgsFeature() if m.featureId() is not None: self.layer.getFeatures(QgsFeatureRequest().setFilterFid( m.featureId())).nextFeature(f) return f
def snap_to_dimension_layer(self, pos): """ Temporarily override snapping config and snap to vertices and edges of any editable vector layer, to allow selection of node for editing (if snapped to edge, it would offer creation of a new vertex there). """ map_point = self.toMapCoordinates(pos) tol = QgsTolerance.vertexSearchRadius(self.canvas().mapSettings()) snap_type = QgsPointLocator.Type(QgsPointLocator.Edge) snap_layers = [QgsSnappingUtils.LayerConfig(self.layer, snap_type, tol, QgsTolerance.ProjectUnits)] snap_util = self.canvas().snappingUtils() old_layers = snap_util.layers() old_mode = snap_util.snapToMapMode() old_inter = snap_util.snapOnIntersections() snap_util.setLayers(snap_layers) snap_util.setSnapToMapMode(QgsSnappingUtils.SnapAdvanced) snap_util.setSnapOnIntersections(False) m = snap_util.snapToMap(map_point) snap_util.setLayers(old_layers) snap_util.setSnapToMapMode(old_mode) snap_util.setSnapOnIntersections(old_inter) f = QgsFeature() if m.featureId() is not None: self.layer.getFeatures(QgsFeatureRequest().setFilterFid(m.featureId())).nextFeature(f) return f
def get_district_area_match(self, point): """ Returns a possible snapping match corresponding to the area under the cursor :param point: map point to snap from """ locator = self.canvas().snappingUtils().locatorForLayer(self.handler.target_layer) tolerance = QgsTolerance.vertexSearchRadius(self.canvas().mapSettings()) match = locator.nearestArea(point, tolerance) return match
def get_district_boundary_matches(self, point): """ Returns a list of snapping matches corresponding to boundaries between existing districts :param point: map point to snap from """ # use QGIS cursor tolerance setting tolerance = QgsTolerance.vertexSearchRadius(self.canvas().mapSettings()) # collect matching edges locator = self.canvas().snappingUtils().locatorForLayer(self.handler.target_layer) match_filter = UniqueFeatureEdgeMatchCollectingFilter(tolerance) locator.nearestEdge(point, tolerance, match_filter) return match_filter.get_matches()
def canvasPressEvent(self, event): if self.rubberBand is not None: self.rubberBand.reset() del self.rubberBand self.rubberBand = None self.canvas.refresh() layerCoords = self.toLayerCoordinates(self.layer, event.pos()) searchRadius = QgsTolerance.vertexSearchRadius(self.canvas.currentLayer(), self.canvas.mapSettings()) selectRect = QgsRectangle(layerCoords.x() - searchRadius, layerCoords.y() - searchRadius, layerCoords.x() + searchRadius, layerCoords.y() + searchRadius) pointGeometry = QgsGeometry.fromPoint(layerCoords) if not pointGeometry: return minDistance = sys.float_info.max cf = None for f in self.layer.getFeatures(QgsFeatureRequest().setFilterRect(selectRect).setSubsetOfAttributes([])): if f.geometry(): currentDistance = pointGeometry.distance(f.geometry()) if currentDistance < minDistance: minDistance = currentDistance cf = f if minDistance == sys.float_info.max: return self.movedFeatures[:] = [] self.movedFeatures.append(QgsFeature(cf)) self.rubberBand = self.createRubberBand(self.layer.geometryType()) self.rubberBand.setToGeometry(cf.geometry(), self.layer) self.startPointMapCoords = self.toMapCoordinates(event.pos()) self.rubberBand.setColor(QColor(255, 0, 0, 65)) self.rubberBand.setWidth(2) self.rubberBand.show()
def snap_to_editable_layer(self, e): """ Temporarily override snapping config and snap to vertices and edges of any editable vector layer, to allow selection of node for editing (if snapped to edge, it would offer creation of a new vertex there). """ QgsMessageLog.logMessage("In TOMsNodeTool:snap_to_editable_layer", tag="TOMs panel") map_point = self.toMapCoordinates(e.pos()) tol = QgsTolerance.vertexSearchRadius(self.canvas().mapSettings()) snap_type = QgsPointLocator.Type(QgsPointLocator.Vertex|QgsPointLocator.Edge) #snap_layers = [] ### TH: Amend to choose only from selected feature (and layer) """snap_layers.append(QgsSnappingUtils.LayerConfig( self.origLayer, snap_type, tol, QgsTolerance.ProjectUnits))""" """for layer in self.canvas().layers(): if not isinstance(layer, QgsVectorLayer) or not layer.isEditable(): continue snap_layers.append(QgsSnappingUtils.LayerConfig( layer, snap_type, tol, QgsTolerance.ProjectUnits))""" snap_util = self.canvas().snappingUtils() old_snap_util = snap_util snap_config = snap_util.config() #snap_util = QgsSnappingUtils() #snap_config = snap_util.config() # old_layers = snap_util.layers() # old_mode = snap_util.mode() # old_intersections = old_snap_config.intersectionSnapping() """ for layer in snap_config.individualLayerSettings().keys(): snap_config.removeLayers([layer]) """ snap_util.setCurrentLayer(self.origLayer) snap_config.setMode(QgsSnappingConfig.ActiveLayer) snap_config.setIntersectionSnapping(False) # only snap to layers #m = snap_util.snapToMap(map_point) snap_config.setTolerance(tol) snap_config.setUnits(QgsTolerance.ProjectUnits) snap_config.setType(QgsSnappingConfig.VertexAndSegment) snap_config.setEnabled(True) """snap_config.setMode(QgsSnappingConfig.AdvancedConfiguration) currLayerSnapSettings = snap_config.individualLayerSettings(self.origLayer) currLayerSnapSettings.setTolerance(tol) currLayerSnapSettings.setUnits(QgsTolerance.ProjectUnits) currLayerSnapSettings.setType(QgsSnappingConfig.VertexAndSegment) currLayerSnapSettings.setEnabled(True) snap_config.setIndividualLayerSettings(self.origLayer, currLayerSnapSettings)""" # try to stay snapped to previously used feature # so the highlight does not jump around at nodes where features are joined ### TH: Amend to choose only from selected feature (and layer) filter_last = OneFeatureFilter(self.origLayer, self.origFeature.getFeature().id()) # m = snap_util.snapToMap(map_point, filter_last) """if m_last.isValid() and m_last.distance() <= m.distance(): m = m_last""" self.origFeature.printFeature() QgsMessageLog.logMessage("In TOMsNodeTool:snap_to_editable_layer: origLayer " + self.origLayer.name(), tag="TOMs panel") """ v3 try to use some other elements of snap_config - snapToCurrentLayer - setCurrentLayer """ QgsMessageLog.logMessage("In TOMsNodeTool:snap_to_editable_layer: pos " + str(e.pos().x()) + "|" + str(e.pos().y()), tag="TOMs panel") m = snap_util.snapToCurrentLayer(e.pos(), snap_type, filter_last) """self.canvas().setSnappingUtils(snap_util) m = snap_util.snapToMap(e.pos(), filter_last)""" #snap_util.setLayers(old_layers) #snap_config.setMode(old_mode) #snap_config.setIntersectionSnapping(old_intersections) self.canvas().setSnappingUtils(old_snap_util) #self.last_snap = m # TODO: Tidy up ... QgsMessageLog.logMessage("In TOMsNodeTool:snap_to_editable_layer: snap point " + str(m.type()) +";" + str(m.isValid()) + "; ", tag="TOMs panel") return m