[QGIS-Developer] Digitizing with Edit Menu

Catania, Luke A ERDC-RDE-GRL-VA CIV Luke.A.Catania at erdc.dren.mil
Mon May 1 09:00:39 PDT 2023


Thanks for taking the time to code that.  I originally coded with the featureAdded method.  When I first found it I was pretty happy with the solution, but then since the user does not get informed until after they draw the shape and it is already added to the layer and so the feature then needs to be deleted so they can try again.  This can go a few iterations.

The previous version of the software I am working on which did not use QGIS but custom developed using R and Leaflet had this dynamic cursor that indicated the size and users miss that, so then I came across the eventFilter and applied that to the map canvas  and while still using the shapes from the edit menu basically used the mouse location to handle dynamically updating the cursor the a QLabel calculating the area bases on the shape being drawn.  It added more code, but out trainers are excited about this new feature..

[cid:image002.png at 01D97C23.A1C08A70]

[cid:image003.png at 01D97C24.87ED6810]

From: Yoann Quenach de Quivillic <yoann.quenach at gmail.com>
Sent: Sunday, April 30, 2023 5:48 PM
To: Catania, Luke A ERDC-RDE-GRL-VA CIV <Luke.A.Catania at erdc.dren.mil>
Cc: qgis-developer at lists.osgeo.org
Subject: Re: [QGIS-Developer] Digitizing with Edit Menu

Have you considered listening to the featureAdded signal instead?
The digitizing shape (aka rubberband) you see while digitizing is not really accessible. In fact, it isn't guaranteed to be the geometry of the feature being created. It could even not exist at all ; this is all dependent on the current QgsMapTool used.

Rather than monitoring clicks, or accessing the rubberband, you could listen to the featureAdded signal. This signal is emitted when a new feature is added to the layer. You can then perform your check (e;g area validation), and delete the feature if the check fails. It won't even appear on screen.

Here is a possible implementation. Note that I split the AreaValidator into three classes for genericity, but you could merge these three classes in a single one.

LayerConnector : this is used to automatically connect all map layers to a function
FeatureValidator: Specialization, connects all QgsVectorLayer featureAdded signal to a function that takes the layer and the feature being added as parameters
AreaValidator: Contains the actual area computation, and possible deletion of the feature


class LayerConnector(QObject):
    """Generic class to connect to all QgsMapLayer"""

    def __init__(self):
        super().__init__()
        QgsProject.instance().layerWasAdded.connect(self.connect_layer)
        self.connect_layers()

    def __del__(self):
        QgsProject.instance().layerWasAdded.disconnect(self.connect_layer)
        self.disconnect_layers()

    def connect_layers(self):
        print("Connecting")
        for layer in QgsProject.instance().mapLayers().values():
            self.connect_layer(layer)

    def disconnect_layers(self):
        print("DisConnecting")
        for layer in QgsProject.instance().mapLayers().values():
            self.disconnect_layer(layer)

    def connect_layer(self, layer):
        pass

    def disconnect_layer(self, layer):
        pass

class FeatureValidator(LayerConnector):
    """Connect all QgsVectorLayer to a process_feature method when a feature is added"""

    def connect_layer(self, layer):
        if not isinstance(layer, QgsVectorLayer):
            return
        layer.featureAdded.connect(self.on_feature_added)

    def disconnect_layer(self, layer):
        if not isinstance(layer, QgsVectorLayer):
            return
        layer.featureAdded.disconnect(self.on_feature_added)

    def on_feature_added(self, id):
        layer = self.sender()
        feat = layer.getFeature(id)
        self.process_feature(layer, feat)

    def process_feature(self, layer, feature):
        print(f"Feature {feature.id()} added to layer {layer.name()}")

class AreaValidator(FeatureValidator):
    def __init__(self, max_area):
        super().__init__()
        self.max_area = max_area

    def process_feature(self, layer, feature):
        geom = feature.geometry()
        if not geom:
            return

        # Here you should handle CRS transformation
        # before computing the feature area
        area = geom.area()

        if area > self.max_area:
            iface.messageBar().pushWarning("Cannot add feature", f"Area too big : {round(area, 2)}")
            layer.deleteFeature(feature.id())

validator = AreaValidator(500)

Le dim. 30 avr. 2023 à 18:42, Catania, Luke A ERDC-RDE-GRL-VA CIV via QGIS-Developer <qgis-developer at lists.osgeo.org<mailto:qgis-developer at lists.osgeo.org>> a écrit :
When you digitize a shape using the Edit menu in QGIS is the shape accessible?  I am looking to get he area of the shape as it is drawn.  I have added an event filter to my code to capture the coordinates and calculate it by creating a QgsGeometry, but my code is getting complicated as there are many shapes that a user can draw from this menu so if I can get access to this shape if it is temporary in memory, then I can just calculate the area on the shape and not have to capture all the positions of the mouse when clicked and moved.

[cid:image001.png at 01D97C20.131018C0]
_______________________________________________
QGIS-Developer mailing list
QGIS-Developer at lists.osgeo.org<mailto:QGIS-Developer at lists.osgeo.org>
List info: Blockedhttps://lists.osgeo.org/mailman/listinfo/qgis-developerBlocked
Unsubscribe: Blockedhttps://lists.osgeo.org/mailman/listinfo/qgis-developerBlocked
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.osgeo.org/pipermail/qgis-developer/attachments/20230501/760b71cf/attachment-0001.htm>
-------------- next part --------------
A non-text attachment was scrubbed...
Name: image001.png
Type: image/png
Size: 82922 bytes
Desc: image001.png
URL: <http://lists.osgeo.org/pipermail/qgis-developer/attachments/20230501/760b71cf/attachment-0003.png>
-------------- next part --------------
A non-text attachment was scrubbed...
Name: image002.png
Type: image/png
Size: 728686 bytes
Desc: image002.png
URL: <http://lists.osgeo.org/pipermail/qgis-developer/attachments/20230501/760b71cf/attachment-0004.png>
-------------- next part --------------
A non-text attachment was scrubbed...
Name: image003.png
Type: image/png
Size: 855843 bytes
Desc: image003.png
URL: <http://lists.osgeo.org/pipermail/qgis-developer/attachments/20230501/760b71cf/attachment-0005.png>


More information about the QGIS-Developer mailing list