Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Incorrect winding/orientation/order of polygon's vertices in Memory layers #58333

Closed
2 tasks done
agiudiceandrea opened this issue Aug 7, 2024 · 1 comment · Fixed by #59167
Closed
2 tasks done

Incorrect winding/orientation/order of polygon's vertices in Memory layers #58333

agiudiceandrea opened this issue Aug 7, 2024 · 1 comment · Fixed by #59167
Assignees
Labels
Bug Either a bug report, or a bug fix. Let's hope for the latter! Data Provider Related to specific vector, raster or mesh data providers Digitizing Related to feature digitizing map tools or functionality Regression Something which used to work, but doesn't anymore

Comments

@agiudiceandrea
Copy link
Contributor

agiudiceandrea commented Aug 7, 2024

What is the bug or the crash?

Using QGIS 3.38.1 on Windows 10 (OSGeo4W), when digitizing a polygon geometry with a hole in a Memory layer, the resulting order of the vertices in the WKT representation of the polygon is different in some circumstances and the outputs of the exteriorRing(), interiorRing(), orientation(), forcePolygonClockwise(), forcePolygonCounterClockwise() functions are weird and not consistent.

The issue doesn't occur using QGIS 3.34.9 on the same system.

Steps to reproduce the issue

Using QGIS 3.38.1:

  1. create a new blank project with CRS EPSG:4326
  2. create a new Polygon scratch (Memory) layer with same CRS as the project and start the edit mode
  3. add a polygon feature digitizing the polygon vertices in the following clockwise (CW) order: 0 0, 0 3, 3 3, 3 0
  4. add an interior ring to the polygon digitizing the ring vertices in the following clockwise (CW) order: 1 1, 1 2, 2 2, 2 1
  5. stop the edit mode

The following Python code executed in the Python console, shows the issues:

geom = iface.activeLayer().getFeature(1).geometry()

# the geometry representation IS NOT THE SAME as the actual digitized geometry
geom # outputs <QgsGeometry: Polygon ((0 0, 0 3, 3 3, 3 0, 0 0),(1 1, 2 1, 2 2, 1 2, 1 1))> in which, first ring looks clockwise (CW) as digitized and second ring looks counterclockwise (CCW) not as digitized

# the output of exteriorRing(0) and exteriorRing(0).orientation() are correct
geom.get().exteriorRing() # outputs <QgsLineString: LineString (0 0, 0 3, 3 3, 3 0, 0 0)> which looks CW
geom.get().exteriorRing().orientation() # outputs <AngularDirection.Clockwise: 0> i.e. CW

# either the output of interiorRing(0) or interiorRing(0).orientation() is WRONG
geom.get().interiorRing(0) # outputs <QgsLineString: LineString (1 1, 2 1, 2 2, 1 2, 1 1)> which looks CCW
geom.get().interiorRing(0).orientation() # outputs <AngularDirection.Clockwise: 0> i.e. CW

# forcePolygonClockwise() gives WRONG CW polygon
geomCW = geom.forcePolygonClockwise()
geomCW # outputs <QgsGeometry: Polygon ((0 0, 0 3, 3 3, 3 0, 0 0),(1 1, 1 2, 2 2, 2 1, 1 1))> in which, incorrectly both first and second rings are CW

# forcePolygonCounterClockwise() gives WRONG CCW polygon
geomCCW = geom.forcePolygonCounterClockwise()
geomCCW # outputs <QgsGeometry: Polygon ((0 0, 3 0, 3 3, 0 3, 0 0),(1 1, 2 1, 2 2, 1 2, 1 1))> in which, incorrectly both first and second rings are CCW

The same incorrect behaviour occurs using the corresponding functions (geom_to_wkt, force_polygon_cw, force_polygon_ccw) in the field calculator.

The issue doesn't occur using QGIS 3.34.9 on the same system, following the same steps:

geom = iface.activeLayer().getFeature(1).geometry()

# the geometry representation is the same as the actual digitized geometry
geom # outputs <QgsGeometry: Polygon ((0 0, 0 3, 3 3, 3 0, 0 0),(1 1, 1 2, 2 2, 2 1, 1 1))> in which, both first and second rings are clockwise (CW) as digitized

# the output of exteriorRing(0) and interiorRing(0).orientation() are correct
geom.get().exteriorRing() # outputs <QgsLineString: LineString (0 0, 0 3, 3 3, 3 0, 0 0)> which is CW
geom.get().exteriorRing().orientation() # outputs <AngularDirection.Clockwise: 0> i.e. CW

# the output of interiorRing(0) and interiorRing(0).orientation() are correct
geom.get().interiorRing(0) # outputs <QgsLineString: LineString (1 1, 1 2, 2 2, 2 1, 1 1)> which is CW
geom.get().interiorRing(0).orientation() # outputs <AngularDirection.Clockwise: 0> i.e. CW

# forcePolygonClockwise() gives correct CW polygon
geomCW = geom.forcePolygonClockwise()
geomCW # outputs <QgsGeometry: Polygon ((0 0, 0 3, 3 3, 3 0, 0 0),(1 1, 2 1, 2 2, 1 2, 1 1))> in which, correctly first ring is CW and second ring is CCW

# forcePolygonCounterClockwise() gives correct CCW polygon
geomCCW = geom.forcePolygonCounterClockwise()
geomCCW # outputs <QgsGeometry: Polygon ((0 0, 3 0, 3 3, 0 3, 0 0),(1 1, 1 2, 2 2, 2 1, 1 1))> in which, correctly first ring is CCW and second ring is CW

Versions

QGIS version
3.38.1-Grenoble
QGIS code revision
3d4177a
Qt version
5.15.13
Python version
3.12.4
GDAL/OGR version
3.9.1
PROJ version
9.4.0
EPSG Registry database version
v11.004 (2024-02-24)
GEOS version
3.12.2-CAPI-1.18.2
SQLite version
3.45.1
PDAL version
2.6.3
PostgreSQL client version
16.2
SpatiaLite version
5.1.0
QWT version
6.2.0
QScintilla2 version
2.14.1
OS version
Windows 10 Version 1903

Active Python plugins
db_manager
0.1.20
grassprovider
2.12.99
MetaSearch
0.3.6
processing
2.12.99

Supported QGIS version

  • I'm running a supported QGIS version according to the roadmap.

New profile

Additional context

The issue occurs on Windows since QGIS 3.36.0.

May be related to #55306.

@agiudiceandrea agiudiceandrea added Bug Either a bug report, or a bug fix. Let's hope for the latter! Data Provider Related to specific vector, raster or mesh data providers Regression Something which used to work, but doesn't anymore labels Aug 7, 2024
@agiudiceandrea agiudiceandrea changed the title Incorrect winding/orientation of polygon's vertices in Memory layers Incorrect winding/orientation/order of polygon's vertices in Memory layers Aug 7, 2024
@agiudiceandrea agiudiceandrea added the Digitizing Related to feature digitizing map tools or functionality label Aug 7, 2024
@lbartoletti lbartoletti self-assigned this Aug 19, 2024
@lbartoletti
Copy link
Member

@agiudiceandrea

# the geometry representation IS NOT THE SAME as the actual digitized geometry
geom # outputs <QgsGeometry: Polygon ((0 0, 0 3, 3 3, 3 0, 0 0),(1 1, 2 1, 2 2, 1 2, 1 1))> in which, first ring looks clockwise (CW) as digitized and second ring looks counterclockwise (CCW) not as digitized

OK It's the fix from #55306

# the output of exteriorRing(0) and exteriorRing(0).orientation() are correct
geom.get().exteriorRing() # outputs <QgsLineString: LineString (0 0, 0 3, 3 3, 3 0, 0 0)> which looks CW
geom.get().exteriorRing().orientation() # outputs <AngularDirection.Clockwise: 0> i.e. CW

OK

# either the output of interiorRing(0) or interiorRing(0).orientation() is WRONG
geom.get().interiorRing(0) # outputs <QgsLineString: LineString (1 1, 2 1, 2 2, 1 2, 1 1)> which looks CCW
geom.get().interiorRing(0).orientation() # outputs <AngularDirection.Clockwise: 0> i.e. CW

OUCH, the WKT is right. But the orientation is wrong.

Let's take a look, with the linestrings:

>>> g
<QgsLineString: LineString (1 1, 1 2, 2 2, 2 1, 1 1)>
>>> l
<QgsLineString: LineString (1 1, 2 1, 2 2, 1 2, 1 1)>

Orientation use Area (QgsCurve::sumUpArea). But :

>>> g.sumUpArea()
-1.0
>>> l.sumUpArea()
-1.0

So, sumUpArea is wrong 😱
I have a fix. With this fix, your code looks like:

geom 
# <QgsGeometry: Polygon ((0 0, 0 3, 3 3, 3 0, 0 0),(1 1, 2 1, 2 2, 1 2, 1 1))>
geom.get().exteriorRing()
# <QgsLineString: LineString (0 0, 0 3, 3 3, 3 0, 0 0)>
geom.get().exteriorRing().orientation()
# <AngularDirection.Clockwise: 0>
geom.get().interiorRing(0)
# <QgsLineString: LineString (1 1, 2 1, 2 2, 1 2, 1 1)>
geom.get().interiorRing(0).orientation()
# <AngularDirection.CounterClockwise: 1>
geomCW = geom.forcePolygonClockwise()
geomCW
# <QgsGeometry: Polygon ((0 0, 0 3, 3 3, 3 0, 0 0),(1 1, 2 1, 2 2, 1 2, 1 1))>
geomCCW = geom.forcePolygonCounterClockwise()
geomCCW
# <QgsGeometry: Polygon ((0 0, 3 0, 3 3, 0 3, 0 0),(1 1, 1 2, 2 2, 2 1, 1 1))>

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Bug Either a bug report, or a bug fix. Let's hope for the latter! Data Provider Related to specific vector, raster or mesh data providers Digitizing Related to feature digitizing map tools or functionality Regression Something which used to work, but doesn't anymore
Projects
None yet
2 participants