On 24 January 2018 at 20:11, Daan Goedkoop <dgoedk...@gmx.net> wrote:
> It sometimes needs to reverse line directions. I used to do it like this: > > return QgsGeometry.fromPolyline(geom.asPolyline().reverse()) > > Q1. Do I understand it correctly, that fromPolyline returns a > QgsPointXY list, thus destroying any M/Z values? Yes. Avoid these as much as possible. asPolyline() is also quite slow, so that's another good reason to avoid it. > > What I do now, and what seems to work, is this: > > return QgsGeometry(geom.constGet().reversed()) > > Q2. Is this the preferred way? Yes. It's very fast, will work for Circular Strings and Compound Curves, and will maintain Z/M values. > Q3. Is it better to use constGet() or normal get()? Use constGet() wherever possible (i.e. you're not modifying the returned value). The rationale here is: - QgsGeometry objects are implicitly shared, so copying them is very fast and performs only a shallow copy. - Calling constGet() on a QgsGeometry returns the underlying geometry primitive without forcing a slow "detach" (deep copy) of the geometry. So use that if you can. - Call get() only when you need to modify the geometry primitive, e.g. geometry.get().transform( my_coord_transform ). It'll force the deep copy, but you'll need to do this anyway since you're modifying the copy. > The second issue are multi-part geometries. I have tried something > like this, after selecting a simple line in a .shp layer: > >>> qgis.utils.iface.activeLayer().selectedFeatures()[0].geometry().constGet().wkbType() > 5 (note: multipart line. I don't understand why, but ok) It's probably a MultiLineString layer type. >>> qgis.utils.iface.activeLayer().selectedFeatures()[0].geometry().constGet().numGeometries() > 0 >>> qgis.utils.iface.activeLayer().selectedFeatures()[0].geometry().constGet().geometryN(0) > <crashes QGIS entirely> I *think* you're unlucky here and that the feature's geometry is a multi line string consisting of 0 parts. That's why numGeometries() returns 0, and geometryN( 0 ) tries to access an out-of-range object and crashes (which we should fix and throw a Python exception instead). Try calling .asWkt() on your geometry to see what it actually is. > So apparently this doesn't work. So now I use an approach like this: > > list = > qgis.utils.iface.activeLayer().selectedFeatures()[0].geometry().asGeometryCollection() > mls = QgsMultiLineString() > for line in list: > mls.addGeometry(line.constGet().reversed()) > newgeom = QgsGeometry(mls) > > Q4. Is this the recommended way of doing things? Yes - looks good to me. asGeometryCollection() is nice and efficient, and won't lose curves or Z/M types. I'm not sure if it's any quicker or any more readable, but a slightly different approach would be: list = qgis.utils.iface.activeLayer().selectedFeatures()[0].geometry().asGeometryCollection() reversed_lines = [] for line in list: reversed_lines .append(QgsGeometry(line.constGet().reversed()) newgeom = QgsGeometry.collectGeometry(reversed_lines ) (QgsGeometry.collectGeometry() is nice and fast too) > Can someone shed a light on this? Hopefully that does! Nyall _______________________________________________ QGIS-Developer mailing list QGIS-Developer@lists.osgeo.org List info: https://lists.osgeo.org/mailman/listinfo/qgis-developer Unsubscribe: https://lists.osgeo.org/mailman/listinfo/qgis-developer