Opened 8 years ago

Last modified 3 years ago

#755 new defect

Overlay ops accept GeometryCollections when headers indicate that they don't

Reported by: dbaston Owned by: geos-devel@…
Priority: major Milestone: 3.11.0
Component: Default Version: 3.5.0
Severity: Unassigned Keywords:
Cc:

Description

Example from Geometry.h:

	/**
	 * \brief
	 * Returns a Geometry representing the points making up this
	 * Geometry that do not make up other.
	 *
	 * @throws util::TopologyException if a robustness error occurs
	 * @throws util::IllegalArgumentException if either input is a
	 *         non-empty GeometryCollection
	 *
	 */

Actual behavior (through CAPI):

    GEOSGeometry* g1 = GEOSGeomFromWKT("GEOMETRYCOLLECTION (POINT (1 1), LINESTRING (2 2, 3 3)) ");
    GEOSGeometry* g2 = GEOSGeomFromWKT("GEOMETRYCOLLECTION (POINT (3 3), LINESTRING (1 1, 2 2)) ");

    GEOSGeometry* g3 = GEOSDifference(g2, g1);
    /* No error passed to user, g3 != NULL */

    printf("%s\n", GEOSGeomToWKT(g3));
    /* prints LINESTRING (1.0000000000000000 1.0000000000000000, 2.0000000000000000 2.0000000000000000) */

Related to https://trac.osgeo.org/postgis/ticket/3341 and possibly https://trac.osgeo.org/geos/ticket/725

Change History (13)

comment:1 by dbaston, 8 years ago

The excerpt from Geometry.h was intended to be:

	/**
	 * \brief
	 * Returns a Geometry representing the points making up this
	 * Geometry that do not make up other.
	 *
	 * @throws util::TopologyException if a robustness error occurs
	 * @throws util::IllegalArgumentException if either input is a
	 *         non-empty GeometryCollection
	 *
	 */
	virtual Geometry* difference(const Geometry *other) const;

comment:2 by strk, 8 years ago

See also #752

comment:3 by strk, 8 years ago

Milestone: 3.5.13.5.2

Ticket retargeted after milestone closed

comment:4 by robe, 6 years ago

Milestone: 3.5.23.8.0

comment:5 by pramsey, 5 years ago

Is the remediation to change the headers?

comment:6 by dbaston, 5 years ago

Call it a wontfix, if the overlay ops are going to be replaced anyway?

comment:7 by pramsey, 5 years ago

Well, changed under the covers, maybe not at an interface level. If it's a doco fix, no reason not to do it, I'm just not sure what ops to change :)

comment:8 by dbaston, 5 years ago

Depends if the new overlay impl is going to handle geometry collections, though?

Note that JTS errors out on collections (https://github.com/locationtech/jts/blob/master/modules/core/src/main/java/org/locationtech/jts/geom/Geometry.java#L1384). Has GEOS really been extended to properly handle these cases that JTS avoids?

comment:9 by pramsey, 5 years ago

Milestone: 3.8.03.9.0

comment:10 by pramsey, 3 years ago

Milestone: 3.9.03.10.0

comment:11 by Mike Taves, 3 years ago

I don't think these operations are working as expected. Here is an odd example with shapely with GEOS 3.9.1:

from shapely.geometry import Point, GeometryCollection

poly_list = [Point(i, 0).buffer(0.7, resolution=10) for i in range(2)]
A = GeometryCollection(poly_list)
res = A.difference(Point(1, 0).buffer(0.2))
print(res)

the result is "POLYGON EMPTY". If the first geometry were replaced with a unary-unioned polygon, the result would be a normal looking polygon with a hole punched thru.

The odd thing is when the number of coordinates used in the GeometryCollection is reduced, an exception is raised:

poly_list = [Point(i, 0).buffer(0.7, resolution=9) for i in range(2)]
A = GeometryCollection(poly_list)
res = A.difference(Point(1, 0).buffer(0.2))
# TopologyException: side location conflict at 0.5 -0.4861824369638621

A PostGIS 2.5.2 / GEOS 3.6.2 equivalent of the example is:

-- runs, but returns GEOMETRYCOLLECTION EMPTY
SELECT ST_AsText(ST_Difference(a, b))
FROM (
  SELECT '01070000000200000001030000000100000029000000666666666666E63F0000000000000000408621CECC1FE63F01A8EB5D7608BCBFE6A17C0DBD4DE53FCE79A9B31BB0CBBF4DD2AA4763F5E33F609B16EBB956D4BFAB911D203A1FE23FE3E43D063155DABF59ED7E8FAAADDF3F49ED7E8FAAADDFBFF5E43D063155DA3FA4911D203A1FE2BF769B16EBB956D43F48D2AA4763F5E3BFFC79A9B31BB0CB3FE3A17C0DBD4DE5BF65A8EB5D7608BC3F3E8621CECC1FE6BFA07DA278DEF8D93C666666666666E6BF98A7EB5D7608BCBF428621CECC1FE6BF9879A9B31BB0CBBFEAA17C0DBD4DE5BF489B16EBB956D4BF54D2AA4763F5E3BFCEE43D063155DABFB2911D203A1FE2BF38ED7E8FAAADDFBF69ED7E8FAAADDFBF9E911D203A1FE2BF06E53D063155DABF44D2AA4763F5E3BF869B16EBB956D4BFE0A17C0DBD4DE5BF187AA9B31BB0CBBF3D8621CECC1FE6BF94A8EB5D7608BCBF666666666666E6BF39173C127892E1BC438621CECC1FE6BF7FA7EB5D7608BC3FEBA17C0DBD4DE5BF9379A9B31BB0CB3F54D2AA4763F5E3BF479B16EBB956D43FB3911D203A1FE2BFCCE43D063155DA3F6BED7E8FAAADDFBF38ED7E8FAAADDF3F07E53D063155DABF9E911D203A1FE23F869B16EBB956D4BF44D2AA4763F5E33F197AA9B31BB0CBBFE0A17C0DBD4DE53F97A8EB5D7608BCBF3D8621CECC1FE63F70BCF3B44DF5E1BC666666666666E63F7BA7EB5D7608BC3F438621CECC1FE63F9179A9B31BB0CB3FEBA17C0DBD4DE53F479B16EBB956D43F54D2AA4763F5E33FCCE43D063155DA3FB3911D203A1FE23F37ED7E8FAAADDF3F6BED7E8FAAADDF3F9D911D203A1FE23F07E53D063155DA3F44D2AA4763F5E33F879B16EBB956D43FE0A17C0DBD4DE53F1B7AA9B31BB0CB3F3D8621CECC1FE63F9AA8EB5D7608BC3F666666666666E63F000000000000000001030000000100000029000000333333333333FB3F000000000000000020C31067E60FFB3F01A8EB5D7608BCBFF350BE86DEA6FA3FCE79A9B31BB0CBBF2669D5A3B1FAF93F609B16EBB956D4BFD6C80E109D0FF93FE3E43D063155DABF56BBDFA36AEBF73F49ED7E8FAAADDFBF3D798F414C95F63FA4911D203A1FE2BFDEA6C57AAE15F53F48D2AA4763F5E3BF402F75760376F33FE3A17C0DBD4DE5BF86BADE6587C0F13F3E8621CECC1FE6BF060000000000F03F666666666666E6BF0D8B4234F17EEC3F428621CECC1FE6BF9AA11513F913E93FEAA17C0DBD4DE5BF5CB2740AA3D4E53F54D2AA4763F5E3BF990DE17C67D5E23FB2911D203A1FE2BF648940B82A29E03F69ED7E8FAAADDFBFC4DCC4BF8BC1DB3F06E53D063155DABF785BAA703915D83F869B16EBB956D4BF40BC06E58564D53F187AA9B31BB0CBBF86F3BC6366C0D33F94A8EB5D7608BCBF343333333333D33F39173C127892E1BC7AF3BC6366C0D33F7FA7EB5D7608BC3F2ABC06E58564D53F9379A9B31BB0CB3F585BAA703915D83F479B16EBB956D43F9ADCC4BF8BC1DB3FCCE43D063155DA3F4A8940B82A29E03F38ED7E8FAAADDF3F7C0DE17C67D5E23F9E911D203A1FE23F3DB2740AA3D4E53F44D2AA4763F5E33F7AA11513F913E93FE0A17C0DBD4DE53FED8A4234F17EEC3F3D8621CECC1FE63FEEFFFFFFFFFFEF3F666666666666E63F78BADE6587C0F13F438621CECC1FE63F322F75760376F33FEBA17C0DBD4DE53FD2A6C57AAE15F53F54D2AA4763F5E33F33798F414C95F63FB3911D203A1FE23F4EBBDFA36AEBF73F6BED7E8FAAADDF3FCEC80E109D0FF93F07E53D063155DA3F2269D5A3B1FAF93F879B16EBB956D43FF050BE86DEA6FA3F1B7AA9B31BB0CB3F1EC31067E60FFB3F9AA8EB5D7608BC3F333333333333FB3F0000000000000000'::geometry as a,
  '01030000000100000029000000666666666666E63F0000000000000000408621CECC1FE63F01A8EB5D7608BCBFE6A17C0DBD4DE53FCE79A9B31BB0CBBF4DD2AA4763F5E33F609B16EBB956D4BFAB911D203A1FE23FE3E43D063155DABF59ED7E8FAAADDF3F49ED7E8FAAADDFBFF5E43D063155DA3FA4911D203A1FE2BF769B16EBB956D43F48D2AA4763F5E3BFFC79A9B31BB0CB3FE3A17C0DBD4DE5BF65A8EB5D7608BC3F3E8621CECC1FE6BFA07DA278DEF8D93C666666666666E6BF98A7EB5D7608BCBF428621CECC1FE6BF9879A9B31BB0CBBFEAA17C0DBD4DE5BF489B16EBB956D4BF54D2AA4763F5E3BFCEE43D063155DABFB2911D203A1FE2BF38ED7E8FAAADDFBF69ED7E8FAAADDFBF9E911D203A1FE2BF06E53D063155DABF44D2AA4763F5E3BF869B16EBB956D4BFE0A17C0DBD4DE5BF187AA9B31BB0CBBF3D8621CECC1FE6BF94A8EB5D7608BCBF666666666666E6BF39173C127892E1BC438621CECC1FE6BF7FA7EB5D7608BC3FEBA17C0DBD4DE5BF9379A9B31BB0CB3F54D2AA4763F5E3BF479B16EBB956D43FB3911D203A1FE2BFCCE43D063155DA3F6BED7E8FAAADDFBF38ED7E8FAAADDF3F07E53D063155DABF9E911D203A1FE23F869B16EBB956D4BF44D2AA4763F5E33F197AA9B31BB0CBBFE0A17C0DBD4DE53F97A8EB5D7608BCBF3D8621CECC1FE63F70BCF3B44DF5E1BC666666666666E63F7BA7EB5D7608BC3F438621CECC1FE63F9179A9B31BB0CB3FEBA17C0DBD4DE53F479B16EBB956D43F54D2AA4763F5E33FCCE43D063155DA3FB3911D203A1FE23F37ED7E8FAAADDF3F6BED7E8FAAADDF3F9D911D203A1FE23F07E53D063155DA3F44D2AA4763F5E33F879B16EBB956D43FE0A17C0DBD4DE53F1B7AA9B31BB0CB3F3D8621CECC1FE63F9AA8EB5D7608BC3F666666666666E63F0000000000000000'::geometry as b
) f;

-- ERROR:  lwgeom_difference: GEOS Error: TopologyException: side location conflict at 0.5 -0.4861824369638621
SELECT ST_AsText(ST_Difference(a, b))
FROM (
  SELECT '01070000000200000001030000000100000025000000666666666666E63F0000000000000000AA938D15480FE63FEAD4DC16251EBFBFC75206C8920CE53FB4108E091FA5CEBFDF68D7D52266E33F606666666666D6BF2AB82A25CE28E13FEE1E54A600CCDCBFFD1E54A600CCDC3F24B82A25CE28E1BF716666666666D63FDA68D7D52266E3BFDA108E091FA5CE3FC45206C8920CE5BF3AD5DC16251EBF3FA8938D15480FE6BF06E408DF445FD43C666666666666E6BF99D4DC16251EBFBFAB938D15480FE6BF8D108E091FA5CEBFCB5206C8920CE5BF506666666666D6BFE368D7D52266E3BFDE1E54A600CCDCBF31B82A25CE28E1BF1EB82A25CE28E1BF0B1F54A600CCDCBFD568D7D52266E3BF826666666666D6BFC05206C8920CE5BF00118E091FA5CEBFA7938D15480FE6BF8AD5DC16251EBFBF666666666666E6BF06E408DF445FE4BCAE938D15480FE6BF49D4DC16251EBF3FCE5206C8920CE5BF67108E091FA5CE3FEA68D7D52266E3BF3C6666666666D63F38B82A25CE28E1BFCE1E54A600CCDC3F191F54A600CCDCBF18B82A25CE28E13F916666666666D6BFD068D7D52266E33F22118E091FA5CEBFBD5206C8920CE53FCED5DC16251EBFBFA4938D15480FE63FA3EF26E88028EDBC666666666666E63F03D4DC16251EBF3FAF938D15480FE63F46108E091FA5CE3FD15206C8920CE53F2D6666666666D63FEE68D7D52266E33FC01E54A600CCDC3F3EB82A25CE28E13F11B82A25CE28E13F2B1F54A600CCDC3FCB68D7D52266E33FA66666666666D63FB95206C8920CE53F4D118E091FA5CE3FA3938D15480FE63F2BD6DC16251EBF3F666666666666E63F000000000000000001030000000100000025000000333333333333FB3F0000000000000000D5C9C60AA407FB3FEAD4DC16251EBFBF642903644986FA3FB4108E091FA5CEBF70B4EB6A11B3F93F606666666666D6BF155C95126794F83FEE1E54A600CCDCBFBF0795290033F73F24B82A25CE28E1BF9C9999999999F53FDA68D7D52266E3BF1BC231E1A3D4F33FC45206C8920CE5BF54CD6D51E2F1F13FA8938D15480FE6BF050000000000F03F666666666666E6BF6D65245D3B1CEC3FAB938D15480FE6BFDD7B9C3DB856E83FCB5206C8920CE5BFD8CCCCCCCCCCE43FE368D7D52266E3BF91F0D5ACFF99E13F31B82A25CE28E1BFC48FAAB563AEDD3F0B1F54A600CCDCBF562E5154BA33D93F826666666666D6BF805AF36FDAE6D53F00118E091FA5CEBFB2D8E4D46FE1D33F8AD5DC16251EBFBF343333333333D33F06E408DF445FE4BCA4D8E4D46FE1D33F49D4DC16251EBF3F645AF36FDAE6D53F67108E091FA5CE3F2C2E5154BA33D93F3C6666666666D63F908FAAB563AEDD3FCE1E54A600CCDC3F74F0D5ACFF99E13F18B82A25CE28E13FB8CCCCCCCCCCE43FD068D7D52266E33FB87B9C3DB856E83FBD5206C8920CE53F4665245D3B1CEC3FA4938D15480FE63FE3FFFFFFFFFFEF3F666666666666E63F40CD6D51E2F1F13FAF938D15480FE63F09C231E1A3D4F33FD15206C8920CE53F8B9999999999F53FEE68D7D52266E33FB00795290033F73F3EB82A25CE28E13F085C95126794F83F2B1F54A600CCDC3F66B4EB6A11B3F93FA66666666666D63F5C2903644986FA3F4D118E091FA5CE3FD2C9C60AA407FB3F2BD6DC16251EBF3F333333333333FB3F0000000000000000'::geometry as a,
  '01030000000100000025000000666666666666E63F0000000000000000AA938D15480FE63FEAD4DC16251EBFBFC75206C8920CE53FB4108E091FA5CEBFDF68D7D52266E33F606666666666D6BF2AB82A25CE28E13FEE1E54A600CCDCBFFD1E54A600CCDC3F24B82A25CE28E1BF716666666666D63FDA68D7D52266E3BFDA108E091FA5CE3FC45206C8920CE5BF3AD5DC16251EBF3FA8938D15480FE6BF06E408DF445FD43C666666666666E6BF99D4DC16251EBFBFAB938D15480FE6BF8D108E091FA5CEBFCB5206C8920CE5BF506666666666D6BFE368D7D52266E3BFDE1E54A600CCDCBF31B82A25CE28E1BF1EB82A25CE28E1BF0B1F54A600CCDCBFD568D7D52266E3BF826666666666D6BFC05206C8920CE5BF00118E091FA5CEBFA7938D15480FE6BF8AD5DC16251EBFBF666666666666E6BF06E408DF445FE4BCAE938D15480FE6BF49D4DC16251EBF3FCE5206C8920CE5BF67108E091FA5CE3FEA68D7D52266E3BF3C6666666666D63F38B82A25CE28E1BFCE1E54A600CCDC3F191F54A600CCDCBF18B82A25CE28E13F916666666666D6BFD068D7D52266E33F22118E091FA5CEBFBD5206C8920CE53FCED5DC16251EBFBFA4938D15480FE63FA3EF26E88028EDBC666666666666E63F03D4DC16251EBF3FAF938D15480FE63F46108E091FA5CE3FD15206C8920CE53F2D6666666666D63FEE68D7D52266E33FC01E54A600CCDC3F3EB82A25CE28E13F11B82A25CE28E13F2B1F54A600CCDC3FCB68D7D52266E33FA66666666666D63FB95206C8920CE53F4D118E091FA5CE3FA3938D15480FE63F2BD6DC16251EBF3F666666666666E63F0000000000000000'::geometry as b
) f;

Unless there is a robust solution to get expected behaviour with consistent results, GEOS should do what JTS does and raise an error if one of the inputs is a GeometryCollection.

On a related note, I see the PostGIS 2.2 manual for ST_Difference note "Do not call with a GeometryCollection as an argument", but this appears to be removed from the current release. Was this intentional?

comment:12 by pramsey, 3 years ago

mdavis is going to add geometry collection support into JTS OverylayNG, and then we can sync up and maybe clean out wrappers in downstream projects. The semantics seem not-impossible to suss out.

comment:13 by robe, 3 years ago

Milestone: 3.10.03.11.0

Retargeting in prep for GEOS 3.10.0 release

Note: See TracTickets for help on using tickets.