[QGIS-Developer] Geometry data model logic?
Raymond Nijssen
r.nijssen at terglobo.nl
Wed Aug 22 07:47:19 PDT 2018
On 22-08-18 14:51, Denis Rouzaud wrote:
> Hi Raymond,
>
> Le mer. 22 août 2018 à 15:30, Raymond Nijssen <r.nijssen at terglobo.nl
> <mailto: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 ;) )
True, but the docs say these should be QgsPointXY's, not QgsPoint's. So
maybe the docs are wrong here, but still this is annoying because
asPolyLine() returns a list of QgsPointXY's. Only writing your own loop
can convert those.
>
>
> - QgsGeometry(QgsPoint) does work, but destroys my QgsPoint (and makes
> qgis instable)
>
>
> look at QgsGeometry::set method
Thanks, I got this working:
pg1 = QgsGeometry().fromWkt('polygon((0 0, 0 1, 1 1, 1 0, 0 0))')
print(pg1) # <QgsGeometry: Polygon ((0 0, 0 1, 1 1, 1 0, 0 0))>
pg2 = pg1.get()
print(pg2) # <QgsPolygon: Polygon ((0 0, 0 1, 1 1, 1 0, 0 0))>
g = QgsGeometry()
g.set(pg2)
print(g) # <QgsGeometry: Polygon ((0 0, 0 1, 1 1, 1 0, 0 0))>
So, now I can convert both ways between QgsGeometry and
QgsPoint/QgsLineString/QgsPolygon. But this script makes qgis crash
after running it 2 times. It has to do with the set() method. This could
also be a bug of course. Should I file it?
>
>
>
>
> 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!
Still waiting for the guru's! :)
>
> Best wishes,
> Denis
> --
>
> Denis Rouzaud
> denis at opengis.ch <mailto:denis at opengis.ch>
> +41 76 370 21 22
>
>
More information about the QGIS-Developer
mailing list