Skip to content

Commit feb0055

Browse files
evetionrafaqz
andauthored
Implement GeoInterface isempty, x, and y. (#191)
* Implement GeoInterface isempty. * Implement GI X and Y. * Ignore GeoInterfaceRecipes ambiguity. * Add tests. Speed up some Point methods. * Fix test. --------- Co-authored-by: Rafael Schouten <[email protected]>
1 parent 1c12df5 commit feb0055

File tree

5 files changed

+43
-13
lines changed

5 files changed

+43
-13
lines changed

src/geo_interface.jl

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,8 @@ GeoInterface.geomtrait(::MultiPolygon) = MultiPolygonTrait()
1919
GeoInterface.geomtrait(::GeometryCollection) = GeometryCollectionTrait()
2020
GeoInterface.geomtrait(geom::PreparedGeometry) = GeoInterface.geomtrait(geom.ownedby)
2121

22+
GeoInterface.isempty(::AbstractGeometryTrait, geom::AbstractGeometry) = isEmpty(geom)
23+
2224
GeoInterface.ngeom(::AbstractGeometryCollectionTrait, geom::AbstractMultiGeometry) =
2325
isEmpty(geom) ? 0 : Int(numGeometries(geom))
2426
GeoInterface.ngeom(::LineStringTrait, geom::LineString) = Int(numPoints(geom))
@@ -45,7 +47,7 @@ GeoInterface.getgeom(
4547
::Union{LineStringTrait,LinearRingTrait},
4648
geom::Union{LineString,LinearRing},
4749
i,
48-
) = Point(getPoint(geom, i))
50+
) = getPoint(geom, i)
4951
GeoInterface.getgeom(t::AbstractPointTrait, geom::PreparedGeometry) = nothing
5052
function GeoInterface.getgeom(::PolygonTrait, geom::Polygon, i::Int)
5153
if i == 1
@@ -70,11 +72,15 @@ GeoInterface.ncoord(::AbstractGeometryTrait, geom::AbstractGeometry) =
7072
GeoInterface.ncoord(t::AbstractGeometryTrait, geom::PreparedGeometry) =
7173
GeoInterface.ncoord(t, geom.ownedby)
7274

73-
GeoInterface.getcoord(::AbstractGeometryTrait, geom::AbstractGeometry, i) =
75+
GeoInterface.getcoord(::AbstractPointTrait, geom::Point, i) =
7476
getCoordinates(getCoordSeq(geom), 1)[i]
75-
GeoInterface.getcoord(t::AbstractGeometryTrait, geom::PreparedGeometry, i) =
77+
GeoInterface.getcoord(t::AbstractPointTrait, geom::PreparedGeometry, i) =
7678
GeoInterface.getcoord(t, geom.ownedby, i)
7779

80+
GeoInterface.x(::AbstractPointTrait, point::AbstractGeometry) = getGeomX(point)
81+
GeoInterface.y(::AbstractPointTrait, point::AbstractGeometry) = getGeomY(point)
82+
GeoInterface.z(::AbstractPointTrait, point::AbstractGeometry) = getGeomZ(point)
83+
7884
# FIXME this doesn't work for 3d geoms, Z is missing
7985
function GeoInterface.extent(::AbstractGeometryTrait, geom::AbstractGeometry)
8086
# minx, miny, maxx, maxy = getExtent(geom)

src/geos_functions.jl

Lines changed: 23 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -347,14 +347,19 @@ function getCoordinates!(out::Vector{Float64}, ptr::GEOSCoordSeq, i::Integer, co
347347
end
348348
ndim = getDimensions(ptr, context)
349349
@assert length(out) == ndim
350-
GC.@preserve out begin
351-
start = pointer(out)
352-
floatsize = sizeof(Float64)
353-
GEOSCoordSeq_getX_r(context, ptr, i - 1, start)
354-
GEOSCoordSeq_getY_r(context, ptr, i - 1, start + floatsize)
355-
if ndim == 3
356-
GEOSCoordSeq_getZ_r(context, ptr, i - 1, start + 2 * floatsize)
357-
end
350+
start = pointer(out)
351+
floatsize = sizeof(Float64)
352+
if ndim == 3
353+
GEOSCoordSeq_getXYZ_r(
354+
context,
355+
ptr,
356+
i - 1,
357+
start,
358+
start + floatsize,
359+
start + 2 * floatsize,
360+
)
361+
else
362+
GEOSCoordSeq_getXY_r(context, ptr, i - 1, start, start + floatsize)
358363
end
359364
out
360365
end
@@ -365,13 +370,12 @@ function getCoordinates(
365370
context::GEOSContext = get_global_context(),
366371
)
367372
ndim = getDimensions(ptr, context)
368-
out = Array{Float64}(undef, ndim)
373+
out = Vector{Float64}(undef, ndim)
369374
getCoordinates!(out, ptr, i, context)
370375
out
371376
end
372377

373378
function getCoordinates(ptr::GEOSCoordSeq, context::GEOSContext = get_global_context())
374-
ndim = getDimensions(ptr, context)
375379
ncoords = getSize(ptr, context)
376380
coordseq = Vector{Float64}[]
377381
sizehint!(coordseq, ncoords)
@@ -1369,6 +1373,15 @@ function getGeomY(obj::Point, context::GEOSContext = get_context(obj))
13691373
out[]
13701374
end
13711375

1376+
function getGeomZ(obj::Point, context::GEOSContext = get_context(obj))
1377+
out = Ref{Float64}()
1378+
result = GEOSGeomGetZ_r(context, obj, out)
1379+
if result == -1
1380+
error("LibGEOS: Error in GEOSGeomGetY")
1381+
end
1382+
out[]
1383+
end
1384+
13721385
# Return NULL on exception, Geometry must be a Polygon.
13731386
# Returned object is a pointer to internal storage: it must NOT be destroyed directly.
13741387
function interiorRing(obj::Polygon, n::Integer, context::GEOSContext = get_context(obj))

test/runtests.jl

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
2+
using GeoInterface, GeoInterfaceRecipes, Extents
13
using GeoInterface, Extents
24
using Test, LibGEOS, RecipesBase
35
import Aqua
@@ -25,4 +27,5 @@ end
2527
include("test_invalid_geometry.jl")
2628
include("test_strtree.jl")
2729
include("test_misc.jl")
30+
2831
end

test/test_geo_interface.jl

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,11 +31,17 @@ const LG = LibGEOS
3131
@test GeoInterface.coordinates(pt) [1, 2] atol = 1e-5
3232
@test GeoInterface.geomtrait(pt) == PointTrait()
3333
@test GeoInterface.testgeometry(pt)
34+
@test GeoInterface.x(pt) == 1
35+
@test GeoInterface.y(pt) == 2
36+
@test isnan(GeoInterface.z(pt))
3437

3538
@inferred GeoInterface.ncoord(pt)
3639
@inferred GeoInterface.ngeom(pt)
3740
@inferred GeoInterface.getgeom(pt)
3841
@inferred GeoInterface.coordinates(pt)
42+
@inferred GeoInterface.x(pt)
43+
@inferred GeoInterface.y(pt)
44+
@inferred GeoInterface.z(pt)
3945

4046
pt = LibGEOS.readgeom("POINT EMPTY")
4147
@test GeoInterface.coordinates(pt) Float64[] atol = 1e-5

test/test_geos_operations.jl

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,12 +45,14 @@ end
4545
expected = readgeom("LINESTRING (130 240, 650 240)")
4646
output = convexhull(input)
4747
@test !isEmpty(output)
48+
@test !GeoInterface.isempty(output)
4849
@test writegeom(output) == writegeom(expected)
4950

5051
# LibGEOS.delaunayTriangulationTest
5152
g1 = readgeom("POLYGON EMPTY")
5253
g2 = delaunayTriangulationEdges(g1)
5354
@test isEmpty(g1)
55+
@test GeoInterface.isempty(g1)
5456
@test isEmpty(g2)
5557
@test GeoInterface.geomtrait(g2) == MultiLineStringTrait()
5658

0 commit comments

Comments
 (0)