Skip to content

Commit d08a211

Browse files
committed
Add curved geometry definitions to geo_interface.jl
1 parent 72f751b commit d08a211

File tree

3 files changed

+77
-6
lines changed

3 files changed

+77
-6
lines changed

src/geo_interface.jl

Lines changed: 24 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,11 @@ geointerface_geomtype(::LinearRingTrait) = LinearRing
88
geointerface_geomtype(::PolygonTrait) = Polygon
99
geointerface_geomtype(::MultiPolygonTrait) = MultiPolygon
1010
geointerface_geomtype(::GeometryCollectionTrait) = GeometryCollection
11+
geointerface_geomtype(::CircularStringTrait) = CircularString
12+
geointerface_geomtype(::CompoundCurveTrait) = CompoundCurve
13+
geointerface_geomtype(::CurvePolygonTrait) = CurvePolygon
14+
geointerface_geomtype(::MultiSurfaceTrait) = MultiSurface
15+
geointerface_geomtype(::MultiCurveTrait) = MultiCurve
1116

1217
GeoInterface.geomtrait(::Point) = PointTrait()
1318
GeoInterface.geomtrait(::MultiPoint) = MultiPointTrait()
@@ -17,23 +22,33 @@ GeoInterface.geomtrait(::LinearRing) = LinearRingTrait()
1722
GeoInterface.geomtrait(::Polygon) = PolygonTrait()
1823
GeoInterface.geomtrait(::MultiPolygon) = MultiPolygonTrait()
1924
GeoInterface.geomtrait(::GeometryCollection) = GeometryCollectionTrait()
25+
GeoInterface.geomtrait(::CircularString) = CircularStringTrait()
26+
GeoInterface.geomtrait(::CompoundCurve) = CompoundCurveTrait()
27+
GeoInterface.geomtrait(::CurvePolygon) = CurvePolygonTrait()
28+
GeoInterface.geomtrait(::MultiSurface) = MultiSurfaceTrait()
29+
GeoInterface.geomtrait(::MultiCurve) = MultiCurveTrait()
2030
GeoInterface.geomtrait(geom::PreparedGeometry) = GeoInterface.geomtrait(geom.ownedby)
2131

2232
GeoInterface.isempty(::AbstractGeometryTrait, geom::AbstractGeometry) = isEmpty(geom)
2333

2434
GeoInterface.ngeom(::AbstractGeometryCollectionTrait, geom::AbstractMultiGeometry) =
2535
isEmpty(geom) ? 0 : Int(numGeometries(geom))
2636
GeoInterface.ngeom(::LineStringTrait, geom::LineString) = Int(numPoints(geom))
37+
GeoInterface.ngeom(::CircularStringTrait, geom::CircularString) = Int(numPoints(geom))
2738
GeoInterface.ngeom(::LinearRingTrait, geom::LinearRing) = Int(numPoints(geom))
2839
GeoInterface.ngeom(::PolygonTrait, geom::Polygon) = Int(numInteriorRings(geom)) + 1
40+
GeoInterface.ngeom(::CurvePolygonTrait, geom::CurvePolygon) =
41+
Int(numInteriorRings(geom)) + 1
2942
GeoInterface.ngeom(t::AbstractGeometryTrait, geom::PreparedGeometry) =
3043
GeoInterface.ngeom(t, geom.ownedby)
3144
GeoInterface.ngeom(::AbstractPointTrait, geom::Point) = 0
3245
GeoInterface.ngeom(::AbstractPointTrait, geom::PreparedGeometry) = 0
3346

3447
GI.is3d(::AbstractGeometryTrait, geom::AbstractGeometry) = hasZ(geom)
35-
GI.getexterior(::AbstractPolygonTrait, geom::Polygon) = exteriorRing(geom)
36-
GI.gethole(::AbstractPolygonTrait, geom::Polygon, n) = interiorRing(geom, n)
48+
GI.getexterior(::AbstractPolygonTrait, geom::Union{Polygon,CurvePolygon}) =
49+
exteriorRing(geom)
50+
GI.gethole(::AbstractPolygonTrait, geom::Union{Polygon,CurvePolygon}, n) =
51+
interiorRing(geom, n)
3752

3853
function GeoInterface.getgeom(
3954
::AbstractGeometryCollectionTrait,
@@ -60,6 +75,13 @@ function GeoInterface.getgeom(::PolygonTrait, geom::Polygon, i::Int)
6075
interiorRing(geom, i - 1)
6176
end
6277
end
78+
function GeoInterface.getgeom(::CurvePolygonTrait, geom::CurvePolygon, i::Int)
79+
if i == 1
80+
exteriorRing(geom)
81+
else
82+
interiorRing(geom, i - 1)
83+
end
84+
end
6385
GeoInterface.getgeom(t::AbstractGeometryTrait, geom::PreparedGeometry, i) =
6486
GeoInterface.getgeom(t, geom.ownedby, i)
6587
GeoInterface.getgeom(t::AbstractPointTrait, geom::PreparedGeometry, i) = 0

src/geos_functions.jl

Lines changed: 39 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1336,7 +1336,10 @@ function normalize!(obj::Geometry, context::GEOSContext = get_context(obj))
13361336
end
13371337

13381338
# Return -1 on exception
1339-
function numInteriorRings(obj::Polygon, context::GEOSContext = get_context(obj))
1339+
function numInteriorRings(
1340+
obj::Union{Polygon,CurvePolygon},
1341+
context::GEOSContext = get_context(obj),
1342+
)
13401343
result = GEOSGetNumInteriorRings_r(context, obj)
13411344
if result == -1
13421345
error("LibGEOS: Error in GEOSGetNumInteriorRings")
@@ -1346,7 +1349,7 @@ end
13461349

13471350
# Call only on LINESTRING (returns -1 on exception)
13481351
function numPoints(
1349-
obj::Union{LineString,LinearRing},
1352+
obj::Union{LineString,LinearRing,CircularString},
13501353
context::GEOSContext = get_context(obj),
13511354
)
13521355
result = GEOSGeomGetNumPoints_r(context, obj)
@@ -1408,14 +1411,46 @@ function interiorRings(obj::Polygon, context::GEOSContext = get_context(obj))
14081411
end
14091412
end
14101413

1414+
# Polygon rings are of type LinearRingcan, and can be inferred, but CurvePolygon rings can be Union{LinearRing, CompoundCurve}
1415+
function interiorRing(
1416+
obj::CurvePolygon,
1417+
n::Integer,
1418+
context::GEOSContext = get_context(obj),
1419+
)
1420+
if !(0 < n <= numInteriorRings(obj, context))
1421+
error(
1422+
"LibGEOS: n=$n is out of bounds for CurvePolygon with $(numInteriorRings(obj, context)) interior ring(s)",
1423+
)
1424+
end
1425+
result = GEOSGetInteriorRingN_r(context, obj, n - 1)
1426+
if result == C_NULL
1427+
error("LibGEOS: Error in GEOSGetInteriorRingN")
1428+
end
1429+
geomFromGEOS(cloneGeom(result, context), context)
1430+
end
1431+
1432+
function interiorRings(obj::CurvePolygon, context::GEOSContext = get_context(obj))
1433+
n = numInteriorRings(obj, context)
1434+
if n == 0
1435+
return LinearRing[]
1436+
else
1437+
return [interiorRing(obj, i, context) for i = 1:n]
1438+
end
1439+
end
1440+
1441+
14111442
# Return NULL on exception, Geometry must be a Polygon.
14121443
# Returned object is a pointer to internal storage: it must NOT be destroyed directly.
1413-
function exteriorRing(obj::Polygon, context::GEOSContext = get_context(obj))
1444+
function exteriorRing(
1445+
obj::Union{Polygon,CurvePolygon},
1446+
context::GEOSContext = get_context(obj),
1447+
)::Union{LinearRing,CompoundCurve}
14141448
result = GEOSGetExteriorRing_r(context, obj)
14151449
if result == C_NULL
14161450
error("LibGEOS: Error in GEOSGetExteriorRing")
14171451
end
1418-
LinearRing(cloneGeom(result, context), context)
1452+
geomFromGEOS(cloneGeom(result, context), context)
1453+
# LinearRing(cloneGeom(result, context), context)
14191454
end
14201455

14211456
# Return -1 on exception

test/test_geos_types.jl

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -461,4 +461,18 @@ end
461461

462462
@test all(geomLength.(geos) .≈ [pi, 4pi, 4 + 2 * sqrt(2), 4pi, pi + 4, pi + 4, 4pi, 1])
463463
@test all(area.(geos) .≈ [0, 0, 2, 2pi, 0, pi / 2 + 2, 2pi, 0])
464+
465+
cp = readgeom(
466+
"CURVEPOLYGON (COMPOUNDCURVE (CIRCULARSTRING (0 0, 1 1, 2 0), (2 0, 2 -1, 0 -1, 0 0)))",
467+
)
468+
@test_broken isequal(cp, CurvePolygon(cp))
469+
470+
cp = readgeom(
471+
"CURVEPOLYGON (COMPOUNDCURVE (CIRCULARSTRING (0 0, 2 2, 4 0), (4 0, 4 -1, 0 -1, 0 0)), LINEARRING (1 0, 3 0, 3 1, 1 1, 1 0))",
472+
)
473+
@test area(cp) 2pi + 2
474+
@test geomLength(cp) 2pi + 12
475+
@test length(interiorRings(cp)) == 1
476+
@test typeof(exteriorRing(cp)) == CompoundCurve
477+
@test typeof(interiorRings(cp)[1]) == LinearRing
464478
end

0 commit comments

Comments
 (0)