[QGIS-Developer] Geometry data model logic?

Denis Rouzaud denis.rouzaud at gmail.com
Wed Aug 22 05:51:36 PDT 2018


Hi Raymond,

Le mer. 22 août 2018 à 15:30, Raymond Nijssen <r.nijssen at terglobo.nl> a
écrit :

> Hopefully it is just a misconception on my side, but I really don't get
> the logic in the qgis geometry data model.
>
> I tried the following script (sorry, some lines are wrapped by my email
> client):
>
> ---
>
> #points
>
> p1 = QgsGeometry().fromWkt('point(0 0)')
> print(p1) # <QgsGeometry: Point (0 0)>
> print(p1.asPoint()) # <QgsPointXY: POINT(0 0)>
> print(p1.centroid()) # <QgsGeometry: Point (0 0)>
> print(p1.buffer(1, 1)) # <QgsGeometry: Polygon ((1 0, 0 -1, -1 0, 0 1, 1
> 0))>
>
> p2 = QgsPoint(1,2)
> print(p2) # <QgsPoint: Point (1 2)>
> p2g = QgsGeometry(p2)
> print(p2g) # <QgsGeometry: Point (1 2)>
> print(p2) # <QgsPoint: Point (1 2)>
> print(p2.centroid()) # <QgsPoint: Point (1 2)>
> print(QgsPointXY(p2.x(), p2.y())) # <QgsPointXY: POINT(1 2)>
> # The next line makes qgis crash after running it 2x !!
> #print(QgsGeometry(p2)) # <QgsGeometry: Point (1 2)>
>
> p3 = QgsPointXY(2, 0)
> print(p3) # <QgsPointXY: POINT(2 0)>
> print(QgsGeometry.fromPointXY(p3)) # <QgsGeometry: Point (2 0)>
> print(QgsPoint(p3.x(), p3.y())) # <QgsPoint: Point (2 0)>
>
> # lines
>
> l1 = QgsGeometry().fromWkt('linestring((0 0, 1 1, 1 2))')
> print(l1) # <QgsGeometry: LineString (0 0, 1 1, 1 2)>
> print(l1.buffer(1, 1).asPolygon())
> print(l1.asPolyline()) # [<QgsPointXY: POINT(0 0)>, <QgsPointXY: POINT(1
> 1)>, <QgsPointXY: POINT(1 0)>]
> print(QgsLineString(l1.asPolyline())) # TypeError: index 0 has type
> 'QgsPointXY' but 'QgsPoint' is expected
>
>
> ---
>
> My questions are:
>
> - How is the relation between QgsGeometry, QgsPoint, QgsPoitXY, etc
> meant to be? Is there documentation? Maybe even a schema?
>

QgsGeometry contains a QgsAbstractGeometry which is the base class of all
geometry classes.
You can get the abstract geometry using get and constGet methods.

The documentation partially mentions this
https://qgis.org/pyqgis/master/core/Geometry/QgsGeometry.html

>
> - Having QgsPoint and QgsPointXY etc is not handy, but I understand they
> are necessary for efficiency reasons. However, shouldn't they all have
> easy typecasting functions? For example:
> QgsGeometry.asPoint()
> QgsGeometry.asPointXY()
> QgsGeometry.asLineString()
> QgsGeometry.asLineStringXY()
> QgsGeometry.asPolygon()
> QgsGeometry.asPolygonXY()
> QgsGeometry.asMultiLineString()
> QgsGeometry.asMultiLineStringXY()
> etc..
>
> QgsPoint.asGeometry()
> QgsPoint.asPointXY()
>
> QgsLineString.asGeometry()
> QgsLineString.asPointXY()
>
> etc..
>

I was also asking my self the same thing.
I am not really sure if there is a reason or not that they were not
implemented.
The main issue to me is the difficulty to get the geometries as points with
their Z/M values.
The workaround I am using is looping along vertices using

geometry.get()->nextVertex( vertexId, pt );

You will the list of QgsPoint with Z/M values.


> - Why don't all geometry types inherit from QgsGeometry, making all the
> geometry operators work? For example:
> QgsPoint(1,2).buffer(3,5)
>

as said before, all geometry classes inherit from QgsAbstractGeometry. You
can use set method (setGeometry in 2.x) on QgsGeometry to create the
geometry from the any subclass of abstract geometry.

>
>
>
>
> Some, IMHO, really odd things are:
>
> - QgsGeometry.asPoint() returns a QgsPointXY
>

I guess that's historical (QgsPoint in 2.x became QgsPointXY in 3, while
QgsPointZ became QgsPoint).

>
> - QgsGeometry.asLineString() does not exist
>
> - QgsGeometry.asPolyLine() returns an array of QgsPointXY's (besides,
> polyline is a strange geometry type in this model)
>
> - QgsLineString([qgsPointXY, qgsPointXY, qgsPointXY, ...]) results in an
> error, while the documentation states:
>     QgsLineString(points: Iterable[QgsPointXY]) Construct a linestring
>     from list of points. This constructor is more efficient then calling
>     setPoints() or repeatedly calling addVertex()
>

ls = QgsLineString([QgsPoint(10, 2), QgsPoint(10, 1), QgsPoint(5, 1)])

this does work for me (and for Travis ;) )

>
> - QgsGeometry(QgsPoint) does work, but destroys my QgsPoint (and makes
> qgis instable)


look at QgsGeometry::set method

>


>
>
> Hopefully somebody can explain, making this more sense to me. And I'd
> like to contribute to improving this, though I'm not a cpp programmer.
>

This is indeed a bit obscure at first and it took me a bit of time to see
the logic here.

The gurus might arrive with a more precise explanation but I hope it's a
good start!

Best wishes,
Denis
-- 

Denis Rouzaud
denis at opengis.ch  <denis at opengis.ch>
+41 76 370 21 22
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.osgeo.org/pipermail/qgis-developer/attachments/20180822/0c79ec2c/attachment-0001.html>


More information about the QGIS-Developer mailing list