Request for comment 2: : Geometry Handling

Date 14 September 2007
Martin Dobias
Contact at gmail dot com




Currently, geometry handling in QGIS is a bit untidy. Implementation of QgsGeometry class has about 4.000 lines of code, geometries can be stored in WKB format, in GEOS class or in both. Some functions do operations directly with WKB, others operate with GEOS library. There's no easy access to retreive coordinates of the geometries or to do some operations with them. This RFC tries to improve this situation with several essential changes.


  • there should be only one representation of geometry - converting between different format costs some processing time that could be used more wisely. Moreover it costs also additional memory since the results are cached.
  • WKB is not suited well for manipulation with geometries - it's great as a common format for interchange of geometries between applications or libraries, but doing any changes to geometries represented in it results in quite low-level code operating with pointers and pointer arithmetics
  • one class (QgsGeometry) is too general to support different types of geometries effectively - different types of geometry need different access methods and support different operations, making the geometry class harder to understand


  • represent geometries in a format that would be either as native for QGIS as possible and wouldn't need conversions when using GEOS methods, only support WKB/WKT import/export
  • create a hierarchy of geometry classes, each for one type of geometry (point, polygon etc.), these classes will implement their own specific retreival methods and operations


GEOS uses these basic classes when working with coordinates:
  • Coordinate - class representing one 3D coordinate - with values x,y,z (although Z value is not being used by GEOS)
  • CoordinateSequence - interface that represents a vector of coordinates
  • CoordinateSequenceFactory - interface for a factory that creates CoordinateSequence instances

GEOS supports some level of customization of these data structures. It's possible to use custom implementation of CoordinateSequence - by default GEOS uses CoordinateArraySequence (resp. DefaultCoordinateSequence in GEOS < 3.0).
I suggest to use QVector to implement our own CoordinateSequence class. This would allow more native interface for coordinates access. Finally, in my test it seems that creation of vectors is much faster with QVector than with std::vector.

We can use a derived class from Coordinate, let's call it QgsCoord (for short, should be clear what it is about). We could add there some QGIS-specific functions if needed.
There's also possibility to use a custom class not related to GEOS Coordinate class, however this involves some overhead needed for conversion between them.


Hierarchy of geometry classes should follow the hierarchy used by GEOS - which follows OpenGIS Simple Features Specification:

- QgsPoint
- QgsLineString
  - QgsLinearRing
- QgsPolygon
- QgsGeometryCollection
  - QgsMultiPoint
  - QgsMultiLineString
  - QgsMultiPolygon

I'm not going to explain here purpose of each class as the hierarchy is pretty common and self-explaining. (Just note that linear ring has two special properties in comparison with line string: first and last point must be the same and it doesn't
intersect itself.)

QgsGeometry contains pointer to instance of a GEOS Geometry class. Derived classes from QgsGeometry have all their own equivalent in GEOS, so when working with the particular type of geometry, they can cast the GEOS geometry class to a more specific type. GEOS supports read-only access to the geometries once they've been created, however there's a support for custom filters which can access the geometry also in read-write manner and can be used for geometry modifications.

As you can see from the hierarchy, QgsPoint class which is currently used to store X,Y coordinates in QGIS is meant to be replaced by a similar class QgsCoord. QgsPoint will get a new meaning - it will be a geometry subclass instead of being just a simple wrapper for coordinates. This is rather a big change as QgsPoint is being used widely in whole QGIS code.


All geometry related classes should be moved to src/core/geometry directory.

QgsGeometryVertexIndex class should be redesigned too. Currently it's design is a bit obscure as it works in a manner of a stack, but in fact it's not necessary. It would completely suffice when it would contain three values: index of vertex in linestring, index of ring in geometry, index of geometry in collection. These three values define well what vertex we're talking about for all supported geometry types.


Here I'll try to summarize what benefits will this pack of changes bring:

  • better maintainibility of geometry handling classes - the code will be split in several classes, manipulations with WKB will be changed to higher-level routines ensuring better readibility and lower possibility of bugs
  • simpler geometry interfaces - geometry classes won't contain an overhaul of methods, will be better organized
  • easier access for geometries - currently some QGIS routines use directly WKB to read the geometry contents. By providing interfaces for access, working with geometries will be much easier
  • simpler implementation of providers - currently provider has to provide geometry in WKB or GEOS format. After the change, provider will be able to use native interface for construction of geometries


First, advanced editing branch should be merged back to trunk and then a new branch should be created for these changes.



I fully agree with the changes proposed by Martin. Btw: about editing of geos geometries: I asked on the geos mailing list. There are the interfaces GeometryEditor and GeometryEditorOperation which can be subclassed to implement edit operations. Even if those subclasses need to reconstruct geometries, the code for editing is properly wrapped inside them, so I like this solution.
About QgsGeometryVertexIndex: It is removed in the advanced editing branch. But if it is needed in future, no problem to implement it with the three indices as members.


Comment consideration by author

Voting History

Your Name
* + 1*
colspan="3" align="center" comments