4

I tried to get the intersect line feature if user placed point on that line.

I tried below:

class AddPoint(QgsMapToolEdit):
    def __init__(self, canvas, iface, Layer):
        self.canvas = canvas
        self.iface = iface
        self.layer=layer
        QgsMapToolEdit.__init__(self, self.canvas)
    def canvasReleaseEvent(self, event):
        click_point = event.snapPoint()
        geom = QgsGeometry().fromPointXY(click_point)
        feat=self.getLine(geom,self.layer)
        print(feat)
    def getLine(self,point,layer):
        bbx=point.boundingBox()
        for i in layer.getFeatures(QgsFeatureRequest().setFilterRect(bbx)):
            if i.geometry().intersects(point):
                return i
        return None
 

But above code not returning any feature, why?

1
  • IMHO, without using snapping, it is almost not possible to get a point intersecting the line. One solution would be get the nearest line to the clicked point, but it may give the wrong line in areas with many lines. Nov 22, 2021 at 10:00

1 Answer 1

4

You don't need to define a new method to get the intersected line. QgsSnappingUtils class has snapToMap() method which returns a QgsPointLocator::Match struct and it has featureid() method which returns the snapped feature id. Then, you can get the feature by id.

Use like this:

class AddPoint(QgsMapToolEdit):
    def __init__(self, canvas, iface, layer):
        self.canvas = canvas
        self.iface = iface
        self.layer = layer
        QgsMapToolEdit.__init__(self, self.canvas)
        
        self.snapper = canvas.snappingUtils()
        config = QgsSnappingConfig()
        config.setEnabled(True)
        config.setType(QgsSnappingConfig.VertexAndSegment)
        config.setUnits(QgsTolerance.Pixels)
        config.setTolerance(12)
        config.setMode(2)
        self.snapper.setConfig(config)
        self.snapindicator = QgsSnapIndicator(canvas)
        
    def canvasReleaseEvent(self, event):
        feat_id = self.snapper.snapToMap(event.pos()).featureId()
        print(f"Snapped feature id: {feat_id}")
        
        ### then you can get the feature ###
        feat = self.layer.getFeature(feat_id)
        
    def canvasMoveEvent(self, event):
        snapMatch = self.snapper.snapToMap(event.pos())
        self.snapindicator.setMatch(snapMatch)
        
        
canvas = iface.mapCanvas()
t = AddPoint(canvas, iface, iface.activeLayer())
canvas.setMapTool(t)

enter image description here

3
  • It return the top feature id, if Multiple Features avail in same Location is it return all ids? Nov 22, 2021 at 10:00
  • I don't know, it returns snapped feature id in the active layer when I run it. Nov 22, 2021 at 10:06
  • Could you share a sample data which produces the result you mentioned? Nov 22, 2021 at 19:31

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.