[geos-devel] 3.9.0beta1 + GEOSwift

Andrew Hershberger andrew.d.hershberger at gmail.com
Sat Nov 28 18:33:46 PST 2020


Hi all, I help maintain https://github.com/GEOSwift/GEOSwift

I'm testing out 3.9.0beta1 and have run into a couple things to share.

If you want to try any of these out directly with GEOSwift, I recommend
using the Swift Package Manager. You can clone
https://github.com/GEOSwift/GEOSwift.git and check out
branch geos-3.9.0-testing. Then run `$ swift test` to build and run the
tests. I'm using Swift 5.3.1. One way to get Swift is to use the Docker
image: https://hub.docker.com/_/swift

1) GeometryConvertible_GEOSTests.testMakeValidWhenItIsAPolygon()

This test is checking that makeValid() (a wrapper around the CAPI's
GEOSMakeValid_r) produces an expected result given some pre-defined
geometry. Here's what happened:

Input:

Polygon(
  exterior: LinearRing(
    points: [
      Point(x: 0, y: 0),
      Point(x: 2, y: 0),
      Point(x: 1, y: 1),
      Point(x: 0, y: 2),
      Point(x: 2, y: 2),
      Point(x: 1, y: 1),
      Point(x: 0, y: 0)
    ]
  )
)

Actual (wrapped in a multipolygon)

Polygon(
  exterior: LinearRing(
    points: [
      Point(x: 0, y: 2),
      Point(x: 2, y: 2),
      Point(x: 1, y: 1),
      Point(x: 0, y: 2)
    ]
  )
)

Polygon(
  exterior: LinearRing(
    points: [
      Point(x: 2, y: 0),
      Point(x: 0, y: 0),
      Point(x: 1, y: 1),
      Point(x: 2, y: 0)
    ]
  )
)

Expected (wrapped in any order in a multipolygon)

Polygon(
  exterior: LinearRing(
    points: [
      Point(x: 1, y: 1),
      Point(x: 2, y: 0),
      Point(x: 0, y: 0),
      Point(x: 1, y: 1)
    ]
  )
)

Polygon(
  exterior: LinearRing(
    points: [
      Point(x: 1, y: 1),
      Point(x: 0, y: 2),
      Point(x: 2, y: 2),
      Point(x: 1, y: 1)
    ]
  )
)

Since these are topologically equivalent, I've just updated the test to
check for that instead of exact equality (see GEOSwift
commit 6c4b191646623159528433fbd112c11ddce7c5ea on the aforementioned
branch), but I thought I'd share here just in case this behavior is
unexpected.

2) GeometryConvertible_GEOSTests.testBufferAllTypes()

This test is intended to be a sort of stress-test to make sure that all the
types of geometry on which GEOSwift allows you to invoke buffer(by:)
(wrapper around the CAPI's GEOSBuffer_r) can actually be buffered. In geos
3.8.1, all the sample geometries were able to be buffered without any
issues.

Here's what we get for one of the test cases with 3.9.0beta1:

Input:

GeometryCollection(
  geometries: [
    GeometryCollection(
      geometries: [
        Point(x: 1.0, y: 2.0),
        MultiPoint(
          points: [
            Point(x: 1.0, y: 2.0),
            Point(x: 3.0, y: 4.0)
          ]
        ),
        LineString(
          points: [
            Point(x: 1.0, y: 2.0),
            Point(x: 3.0, y: 4.0)
          ]
        ),
        MultiLineString(
          lineStrings: [
            LineString(
              points: [
                Point(x: 1.0, y: 2.0),
                Point(x: 3.0, y: 4.0)
              ]
            ),
            LineString(
              points: [
                Point(x: 5.0, y: 6.0),
                Point(x: 7.0, y: 8.0)
              ]
            )
          ]
        ),
        Polygon(
          exterior: LinearRing(
            points: [
              Point(x: 2.0, y: 2.0),
              Point(x: -2.0, y: 2.0),
              Point(x: -2.0, y: -2.0),
              Point(x: 2.0, y: -2.0),
              Point(x: 2.0, y: 2.0)
            ]
          ),
          holes: [
            LinearRing(
              points: [
                Point(x: 1.0, y: 1.0),
                Point(x: 1.0, y: -1.0),
                Point(x: -1.0, y: -1.0),
                Point(x: -1.0, y: 1.0),
                Point(x: 1.0, y: 1.0)
              ]
            )
          ]
        ),
        MultiPolygon(
          polygons: [
            Polygon(
              exterior: LinearRing(
                points: [
                  Point(x: 2.0, y: 2.0),
                  Point(x: -2.0, y: 2.0),
                  Point(x: -2.0, y: -2.0),
                  Point(x: 2.0, y: -2.0),
                  Point(x: 2.0, y: 2.0)
                ]
              ),
              holes: [
                LinearRing(
                  points: [
                    Point(x: 1.0, y: 1.0),
                    Point(x: 1.0, y: -1.0),
                    Point(x: -1.0, y: -1.0),
                    Point(x: -1.0, y: 1.0),
                    Point(x: 1.0, y: 1.0)
                  ]
                )
              ]
            ),
            Polygon(
              exterior: LinearRing(
                points: [
                  Point(x: 7.0, y: 2.0),
                  Point(x: 3.0, y: 2.0),
                  Point(x: 3.0, y: -2.0),
                  Point(x: 7.0, y: -2.0),
                  Point(x: 7.0, y: 2.0)
                ]
              ),
              holes: []
            )
          ]
        )
      ]
    )
  ]
)

buffer(by: 0.5)

errorMessage: "IllegalArgumentException: Overlay input is mixed-dimension"

The exception is being thrown from EdgeNodingBuilder.cpp:195.

In frame #2, i = 0

In frame #0, i = 0

This suggests to me that it's checking the dimension of the Point inside of
the child GeometryCollection inside of the parent GeometryCollection.

g->getDimension() is returning 0 (geos::geom::Dimension::DimensionType P)
and expectedDim is 2.

Here's a relevant stack trace:

#0
geos::operation::overlayng::EdgeNodingBuilder::addGeometryCollection(geos::geom::GeometryCollection
const*, int, int) at geos/src/operation/overlayng/EdgeNodingBuilder.cpp:195
#1 geos::operation::overlayng::EdgeNodingBuilder::add(geos::geom::Geometry
const*, int) at geos/src/operation/overlayng/EdgeNodingBuilder.cpp:169
#2
geos::operation::overlayng::EdgeNodingBuilder::addGeometryCollection(geos::geom::GeometryCollection
const*, int, int) at geos/src/operation/overlayng/EdgeNodingBuilder.cpp:197
#3 geos::operation::overlayng::EdgeNodingBuilder::add(geos::geom::Geometry
const*, int) at geos/src/operation/overlayng/EdgeNodingBuilder.cpp:169
#4
geos::operation::overlayng::EdgeNodingBuilder::build(geos::geom::Geometry
const*, geos::geom::Geometry const*) at
geos/src/operation/overlayng/EdgeNodingBuilder.cpp:82
#5 geos::operation::overlayng::OverlayNG::computeEdgeOverlay() at
geos/src/operation/overlayng/OverlayNG.cpp:222
#6 geos::operation::overlayng::OverlayNG::getResult() at
geos/src/operation/overlayng/OverlayNG.cpp:179
#7
geos::operation::overlayng::PrecisionReducer::reducePrecision(geos::geom::Geometry
const*, geos::geom::PrecisionModel const*, bool) at
geos/src/operation/overlayng/PrecisionReducer.cpp:46
#8 geos::precision::GeometryPrecisionReducer::reduce(geos::geom::Geometry
const&) at geos/src/precision/GeometryPrecisionReducer.cpp:60
#9 geos::precision::GeometryPrecisionReducer::reduce(geos::geom::Geometry
const&, geos::geom::PrecisionModel const&) at
geos/include/geos/precision/GeometryPrecisionReducer.h:102
#10
geos::operation::buffer::BufferOp::bufferFixedPrecision(geos::geom::PrecisionModel
const&) at geos/src/operation/buffer/BufferOp.cpp:263
#11 geos::operation::buffer::BufferOp::bufferReducedPrecision(int) at
geos/src/operation/buffer/BufferOp.cpp:218
#12 geos::operation::buffer::BufferOp::bufferReducedPrecision() at
geos/src/operation/buffer/BufferOp.cpp:168
#13 geos::operation::buffer::BufferOp::computeGeometry() at
geos/src/operation/buffer/BufferOp.cpp:150
#14 geos::operation::buffer::BufferOp::getResultGeometry(double) at
geos/src/operation/buffer/BufferOp.cpp:122
#15 geos::operation::buffer::BufferOp::bufferOp(geos::geom::Geometry
const*, double, int, int) at geos/src/operation/buffer/BufferOp.cpp:114
#16 geos::geom::Geometry::buffer(double, int) const at
geos/src/geom/Geometry.cpp:509
#17 GEOSBuffer_r::$_41::operator()() const at geos/capi/geos_ts_c.cpp:1078
#18
_Z7executeIZ12GEOSBuffer_rE4$_41LDn0EEDTclfp0_EEP20GEOSContextHandle_HSOT_
at geos/capi/geos_ts_c.cpp:388
#19 ::GEOSBuffer_r(GEOSContextHandle_t, const geos::geom::Geometry *,
double, int) at geos/capi/geos_ts_c.cpp:1077
#20 GeometryConvertible.buffer(by:) at
GEOSwift/GEOSwift/GEOS/GeometryConvertible+GEOS.swift:348
#21 GeometryConvertible_GEOSTests.testBufferAllTypes() at
GEOSwift/GEOSwiftTests/GEOS/GeometryConvertible+GEOSTests.swift:856

Let me know what other info I can provide.

--
Andrew
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.osgeo.org/pipermail/geos-devel/attachments/20201128/914dbacf/attachment.html>


More information about the geos-devel mailing list