Skip to content

Commit b5f5675

Browse files
committed
Expanded test coverage more.
1 parent a22db09 commit b5f5675

File tree

6 files changed

+153
-30
lines changed

6 files changed

+153
-30
lines changed

docs/src/guides/defaults.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ Of note here are the `ngeom` and `getgeom` for each geometry type, which transla
1313
| [`AbstractPolygonTrait`](@ref) | [`nring(geom)`](@ref) | [`getring(geom)`](@ref) |
1414
| [`AbstractMultiLineStringTrait`](@ref) | [`nlinestring(geom)`](@ref) | [`getlinestring(geom)`](@ref) |
1515
| [`AbstractMultiPolygonTrait`](@ref) | [`npolygon(geom)`](@ref) | [`getpolygon(geom)`](@ref) |
16-
| [`AbstractPolyHedralSurfaceTrait`](@ref) | [`npatch(geom)`](@ref) | [`getpatch(geom)`](@ref) |
16+
| [`AbstractPolyhedralSurfaceTrait`](@ref) | [`npatch(geom)`](@ref) | [`getpatch(geom)`](@ref) |
1717
| [`AbstractGeometryCollectionTrait`](@ref) | [`ngeom(geom)`](@ref) | [`getgeom(geom)`](@ref) |
1818

1919
## Polygons

src/GeoInterface.jl

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -27,8 +27,8 @@ export AbstractGeometryTrait,
2727
QuadTrait,
2828
PentagonTrait,
2929
HexagonTrait,
30-
AbstractPolyHedralSurfaceTrait,
31-
PolyHedralSurfaceTrait,
30+
AbstractPolyhedralSurfaceTrait,
31+
PolyhedralSurfaceTrait,
3232
TINTrait,
3333
AbstractMultiPointTrait,
3434
MultiPointTrait,

src/fallbacks.jl

Lines changed: 11 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -28,14 +28,15 @@ npoint(t::AbstractCurveTrait, geom) = ngeom(t, geom)
2828
getpoint(t::AbstractCurveTrait, geom) = getgeom(t, geom)
2929
getpoint(t::AbstractCurveTrait, geom, i) = getgeom(t, geom, i)
3030
startpoint(t::AbstractCurveTrait, geom) = getpoint(t, geom, 1)
31-
endpoint(t::AbstractCurveTrait, geom) = getpoint(t, geom, length(geom))
31+
endpoint(t::AbstractCurveTrait, geom) = getpoint(t, geom, npoint(geom))
3232

3333
## Polygons
3434
nring(t::AbstractPolygonTrait, geom) = ngeom(t, geom)
3535
getring(t::AbstractPolygonTrait, geom) = getgeom(t, geom)
3636
getring(t::AbstractPolygonTrait, geom, i) = getgeom(t, geom, i)
3737
getexterior(t::AbstractPolygonTrait, geom) = getring(t, geom, 1)
3838
nhole(t::AbstractPolygonTrait, geom) = nring(t, geom) - 1
39+
gethole(t::AbstractPolygonTrait, geom) = (getgeom(t, geom, i) for i in 2:ngeom(t, geom))
3940
gethole(t::AbstractPolygonTrait, geom, i) = getring(t, geom, i + 1)
4041
npoint(t::AbstractPolygonTrait, geom) = sum(npoint(p) for p in getring(t, geom))
4142
getpoint(t::AbstractPolygonTrait, geom) = flatten((p for p in getpoint(r)) for r in getring(t, geom))
@@ -62,9 +63,9 @@ npoint(t::AbstractMultiPolygonTrait, geom) = sum(npoint(r) for r in getring(t, g
6263
getpoint(t::AbstractMultiPolygonTrait, geom) = flatten((p for p in getpoint(r)) for r in getring(t, geom))
6364

6465
## Surface
65-
npatch(t::AbstractPolyHedralSurfaceTrait, geom)::Integer = ngeom(t, geom)
66-
getpatch(t::AbstractPolyHedralSurfaceTrait, geom) = getgeom(t, geom)
67-
getpatch(t::AbstractPolyHedralSurfaceTrait, geom, i::Integer) = getgeom(t, geom, i)
66+
npatch(t::AbstractPolyhedralSurfaceTrait, geom)::Integer = ngeom(t, geom)
67+
getpatch(t::AbstractPolyhedralSurfaceTrait, geom) = getgeom(t, geom)
68+
getpatch(t::AbstractPolyhedralSurfaceTrait, geom, i::Integer) = getgeom(t, geom, i)
6869

6970
## Default iterator
7071
getgeom(t::AbstractGeometryTrait, geom) = (getgeom(t, geom, i) for i in 1:ngeom(t, geom))
@@ -83,18 +84,15 @@ nring(::PentagonTrait, geom) = 1
8384
npoint(::HexagonTrait, geom) = 6
8485
nring(::HexagonTrait, geom) = 1
8586

86-
issimple(::AbstractCurveTrait, geom) =
87-
allunique([getpoint(t, geom, i) for i in 1:npoint(geom)-1]) && allunique([getpoint(t, geom, i) for i in 2:npoint(t, geom)])
87+
# TODO Only simple if it's also not intersecting itself, except for its endpoints
88+
issimple(t::AbstractCurveTrait, geom) = allunique((getpoint(t, geom, i) for i in 1:npoint(geom)-1)) && allunique((getpoint(t, geom, i) for i in 2:npoint(t, geom)))
8889
isclosed(t::AbstractCurveTrait, geom) = getpoint(t, geom, 1) == getpoint(t, geom, npoint(t, geom))
8990
isring(t::AbstractCurveTrait, geom) = issimple(t, geom) && isclosed(t, geom)
9091

91-
# TODO Only simple if it's also not intersecting itself, except for its endpoints
92-
issimple(t::AbstractMultiCurveTrait, geom) = all(i -> issimple(getgeom(t, geom, i)), 1:ngeom(t, geom))
93-
isclosed(t::AbstractMultiCurveTrait, geom) = all(i -> isclosed(getgeom(t, geom, i)), 1:ngeom(t, geom))
92+
issimple(t::AbstractMultiPointTrait, geom) = allunique((getgeom(t, geom)))
9493

95-
issimple(t::AbstractMultiPointTrait, geom) = allunique((getgeom(t, geom, i) for i in 1:ngeom(t, geom)))
96-
getpoint(t::AbstractMultiPointTrait, geom) = getgeom(t, geom)
97-
getpoint(t::AbstractMultiPointTrait, geom, i) = getgeom(t, geom, i)
94+
issimple(t::AbstractMultiCurveTrait, geom) = all(issimple.(getgeom(t, geom)))
95+
isclosed(t::AbstractMultiCurveTrait, geom) = all(isclosed.(getgeom(t, geom)))
9896

9997
crs(::AbstractGeometryTrait, geom) = nothing
10098
extent(::AbstractGeometryTrait, geom) = nothing
@@ -136,7 +134,7 @@ subtrait(::AbstractPointTrait) = nothing
136134
subtrait(::AbstractCurveTrait) = AbstractPointTrait
137135
subtrait(::AbstractCurvePolygonTrait) = AbstractCurveTrait
138136
subtrait(::AbstractPolygonTrait) = AbstractLineStringTrait
139-
subtrait(::AbstractPolyHedralSurfaceTrait) = AbstractPolygonTrait
137+
subtrait(::AbstractPolyhedralSurfaceTrait) = AbstractPolygonTrait
140138
subtrait(::TINTrait) = TriangleTrait
141139
subtrait(::AbstractMultiPointTrait) = AbstractPointTrait
142140
subtrait(::AbstractMultiLineStringTrait) = AbstractLineStringTrait

src/interface.jl

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -250,28 +250,28 @@ Note that this is only valid for [`AbstractPolygonTrait`](@ref)s.
250250
"""
251251
gethole(geom) = gethole(geomtype(geom), geom)
252252

253-
# PolyHedralSurface
253+
# PolyhedralSurface
254254
"""
255255
npatch(geom)
256256
257257
Returns the number of patches for the given `geom`.
258-
Note that this is only valid for [`AbstractPolyHedralSurfaceTrait`](@ref)s.
258+
Note that this is only valid for [`AbstractPolyhedralSurfaceTrait`](@ref)s.
259259
"""
260260
npatch(geom)::Integer = npatch(geomtype(geom), geom)
261261

262262
"""
263263
getpatch(geom, i::Integer) -> AbstractPolygon
264264
265265
Returns the `i`th patch for the given `geom`.
266-
Note that this is only valid for [`AbstractPolyHedralSurfaceTrait`](@ref)s.
266+
Note that this is only valid for [`AbstractPolyhedralSurfaceTrait`](@ref)s.
267267
"""
268268
getpatch(geom, i::Integer) = getpatch(geomtype(geom), geom, i)
269269

270270
"""
271271
getpatch(geom) -> iterator
272272
273273
Returns an iterator over all patches in `geom`.
274-
Note that this is only valid for [`AbstractPolyHedralSurfaceTrait`](@ref)s.
274+
Note that this is only valid for [`AbstractPolyhedralSurfaceTrait`](@ref)s.
275275
"""
276276
getpatch(geom) = getpatch(geomtype(geom), geom)
277277

src/types.jl

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -50,12 +50,12 @@ struct PentagonTrait <: AbstractPolygonTrait end
5050
"A [`PolygonTrait`](@ref) with six vertices."
5151
struct HexagonTrait <: AbstractPolygonTrait end
5252

53-
"An AbstractPolyHedralSurfaceTrait type for all polyhedralsurfaces."
54-
abstract type AbstractPolyHedralSurfaceTrait <: AbstractSurfaceTrait end
55-
"A PolyHedralSurfaceTrait is a connected surface consisting of [`PolygonTrait`](@ref)s."
56-
struct PolyHedralSurfaceTrait <: AbstractPolyHedralSurfaceTrait end
57-
"A TINTrait is a [`PolyHedralSurfaceTrait`](@ref) consisting of [`TriangleTrait`](@ref)s."
58-
struct TINTrait <: AbstractPolyHedralSurfaceTrait end # Surface consisting of Triangles
53+
"An AbstractPolyhedralSurfaceTrait type for all polyhedralsurfaces."
54+
abstract type AbstractPolyhedralSurfaceTrait <: AbstractSurfaceTrait end
55+
"A PolyhedralSurfaceTrait is a connected surface consisting of [`PolygonTrait`](@ref)s."
56+
struct PolyhedralSurfaceTrait <: AbstractPolyhedralSurfaceTrait end
57+
"A TINTrait is a [`PolyhedralSurfaceTrait`](@ref) consisting of [`TriangleTrait`](@ref)s."
58+
struct TINTrait <: AbstractPolyhedralSurfaceTrait end # Surface consisting of Triangles
5959

6060
"An AbstractMultiPointTrait type for all multipoints."
6161
abstract type AbstractMultiPointTrait <: AbstractGeometryCollectionTrait end

test/test_primitives.jl

Lines changed: 129 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -4,18 +4,26 @@ using Test
44
@testset "Developer" begin
55
# Implement interface
66
struct MyPoint end
7+
struct MyEmptyPoint end
78
struct MyCurve end
89
struct MyPolygon end
10+
struct MyTriangle end
911
struct MyMultiPoint end
1012
struct MyMultiCurve end
1113
struct MyMultiPolygon end
14+
struct MyTIN end
1215
struct MyCollection end
1316

1417
GeoInterface.isgeometry(::MyPoint) = true
1518
GeoInterface.geomtype(::MyPoint) = PointTrait()
1619
GeoInterface.ncoord(::PointTrait, geom::MyPoint) = 2
1720
GeoInterface.getcoord(::PointTrait, geom::MyPoint, i) = [1, 2][i]
1821

22+
GeoInterface.isgeometry(::MyEmptyPoint) = true
23+
GeoInterface.geomtype(::MyEmptyPoint) = PointTrait()
24+
GeoInterface.ncoord(::PointTrait, geom::MyEmptyPoint) = 0
25+
GeoInterface.isempty(::PointTrait, geom::MyEmptyPoint) = true
26+
1927
GeoInterface.isgeometry(::MyCurve) = true
2028
GeoInterface.geomtype(::MyCurve) = LineStringTrait()
2129
GeoInterface.ngeom(::LineStringTrait, geom::MyCurve) = 2
@@ -28,6 +36,11 @@ using Test
2836
GeoInterface.ngeom(::PolygonTrait, geom::MyPolygon) = 2
2937
GeoInterface.getgeom(::PolygonTrait, geom::MyPolygon, i) = MyCurve()
3038

39+
GeoInterface.isgeometry(::MyTriangle) = true
40+
GeoInterface.geomtype(::MyTriangle) = TriangleTrait()
41+
GeoInterface.ngeom(::TriangleTrait, geom::MyTriangle) = 3
42+
GeoInterface.getgeom(::TriangleTrait, geom::MyTriangle, i) = MyCurve()
43+
3144
GeoInterface.isgeometry(::MyMultiPoint) = true
3245
GeoInterface.geomtype(::MyMultiPoint) = MultiPointTrait()
3346
GeoInterface.ngeom(::MultiPointTrait, geom::MyMultiPoint) = 2
@@ -43,18 +56,38 @@ using Test
4356
GeoInterface.ngeom(::MultiPolygonTrait, geom::MyMultiPolygon) = 2
4457
GeoInterface.getgeom(::MultiPolygonTrait, geom::MyMultiPolygon, i) = MyPolygon()
4558

59+
GeoInterface.isgeometry(::MyTIN) = true
60+
GeoInterface.geomtype(::MyTIN) = PolyhedralSurfaceTrait()
61+
GeoInterface.ngeom(::PolyhedralSurfaceTrait, geom::MyTIN) = 2
62+
GeoInterface.getgeom(::PolyhedralSurfaceTrait, geom::MyTIN, i) = MyTriangle()
63+
4664
GeoInterface.isgeometry(::MyCollection) = true
4765
GeoInterface.geomtype(::MyCollection) = GeometryCollectionTrait()
4866
GeoInterface.ngeom(::GeometryCollectionTrait, geom::MyCollection) = 2
4967
GeoInterface.getgeom(::GeometryCollectionTrait, geom::MyCollection, i) = MyCurve()
5068

51-
5269
@testset "Point" begin
5370
geom = MyPoint()
5471
@test testgeometry(geom)
5572
@test GeoInterface.x(geom) === 1
5673
@test GeoInterface.y(geom) === 2
74+
@test_throws ArgumentError GeoInterface.z(geom)
75+
@test_throws ArgumentError GeoInterface.m(geom)
5776
@test ncoord(geom) === 2
77+
@test collect(getcoord(geom)) == [1, 2]
78+
@test getcoord(geom, 1) === 1
79+
@test GeoInterface.coordnames(geom) == (:X, :Y)
80+
@test !GeoInterface.isempty(geom)
81+
@test !GeoInterface.is3d(geom)
82+
@test !GeoInterface.ismeasured(geom)
83+
84+
geom = MyEmptyPoint()
85+
@test GeoInterface.coordnames(geom) == ()
86+
@test GeoInterface.isempty(geom)
87+
88+
@test isnothing(GeoInterface.crs(geom))
89+
@test isnothing(GeoInterface.extent(geom))
90+
@test isnothing(GeoInterface.bbox(geom))
5891
end
5992

6093
@testset "LineString" begin
@@ -63,9 +96,18 @@ using Test
6396

6497
@test GeoInterface.npoint(geom) == 2 # defaults to ngeom
6598
@test GeoInterface.coordinates(geom) == [[1, 2], [1, 2]]
66-
@test_throws MethodError GeoInterface.area(geom)
99+
points = GeoInterface.getpoint(geom)
67100
point = GeoInterface.getpoint(geom, 1)
101+
pointa = GeoInterface.startpoint(geom)
102+
pointb = GeoInterface.endpoint(geom)
68103
@test GeoInterface.y(point) == 2
104+
105+
@test_throws MethodError GeoInterface.length(geom)
106+
107+
@test GeoInterface.issimple(geom)
108+
@test GeoInterface.isclosed(geom)
109+
@test GeoInterface.isring(geom)
110+
69111
end
70112

71113
@testset "Polygon" begin
@@ -77,10 +119,20 @@ using Test
77119
@test GeoInterface.nhole(geom) == 1
78120
@test GeoInterface.coordinates(geom) == [[[1, 2], [1, 2]], [[1, 2], [1, 2]]]
79121
lines = GeoInterface.getring(geom)
122+
line = GeoInterface.getring(geom, 1)
123+
lines = GeoInterface.gethole(geom)
80124
line = GeoInterface.gethole(geom, 1)
81125
line = GeoInterface.getexterior(geom)
82126
@test GeoInterface.npoint(geom) == 4
83127
@test collect(GeoInterface.getpoint(geom)) == [MyPoint(), MyPoint(), MyPoint(), MyPoint()]
128+
129+
@test_throws MethodError GeoInterface.area(geom)
130+
131+
geom = MyTriangle()
132+
@test testgeometry(geom)
133+
@test GeoInterface.nring(geom) == 1
134+
@test GeoInterface.nhole(geom) == 0
135+
@test GeoInterface.npoint(geom) == 3
84136
end
85137

86138
@testset "MultiPoint" begin
@@ -92,6 +144,8 @@ using Test
92144
point = GeoInterface.getpoint(geom, 1)
93145
@test GeoInterface.coordinates(geom) == [[1, 2], [1, 2]]
94146
@test collect(points) == [MyPoint(), MyPoint()]
147+
148+
@test !GeoInterface.issimple(geom)
95149
end
96150

97151
@testset "MultiLineString" begin
@@ -116,6 +170,17 @@ using Test
116170
@test collect(polygons) == [MyPolygon(), MyPolygon()]
117171
end
118172

173+
@testset "Surface" begin
174+
geom = MyTIN()
175+
@test testgeometry(geom)
176+
177+
@test GeoInterface.npatch(geom) == 2
178+
polygons = GeoInterface.getpatch(geom)
179+
polygon = GeoInterface.getpatch(geom, 1)
180+
@test GeoInterface.coordinates(geom) == [[[[1, 2], [1, 2]], [[1, 2], [1, 2]], [[1, 2], [1, 2]]], [[[1, 2], [1, 2]], [[1, 2], [1, 2]], [[1, 2], [1, 2]]]]
181+
@test collect(polygons) == [MyTriangle(), MyTriangle()]
182+
end
183+
119184
@testset "GeometryCollection" begin
120185
geom = MyCollection()
121186
@test testgeometry(geom)
@@ -131,6 +196,8 @@ end
131196

132197
@testset "Defaults" begin
133198
@test GeoInterface.subtrait(TINTrait()) == TriangleTrait
199+
@test GeoInterface.nring(QuadTrait(), ()) == 1
200+
@test GeoInterface.npoint(QuadTrait(), ()) == 4
134201
end
135202

136203
@testset "Feature" begin
@@ -158,10 +225,68 @@ end
158225
Base.convert(::Type{XCurve}, ::LineStringTrait, geom::XCurve) = geom # fast fallthrough
159226
Base.convert(::Type{XCurve}, ::LineStringTrait, geom) = geom
160227

161-
Base.convert(T::Type{XPolygon}, geom::X) where {X} = Base.convert(T, geomtype(geom), geom)
162-
163228
geom = MyCurve()
164229
@test !isnothing(convert(MyCurve, geom))
165230

231+
Base.convert(T::Type{XPolygon}, geom::X) where {X} = Base.convert(T, geomtype(geom), geom)
166232
@test_throws Exception convert(MyPolygon, geom)
167233
end
234+
235+
@testset "Operations" begin
236+
struct XGeom end
237+
238+
GeoInterface.isgeometry(::XGeom) = true
239+
GeoInterface.geomtype(::XGeom) = PointTrait()
240+
GeoInterface.ncoord(::PointTrait, geom::XGeom) = 2
241+
GeoInterface.getcoord(::PointTrait, geom::XGeom, i) = [1, 2][i]
242+
243+
GeoInterface.equals(::PointTrait, ::PointTrait, ::XGeom, ::XGeom) = true
244+
GeoInterface.disjoint(::PointTrait, ::PointTrait, ::XGeom, ::XGeom) = true
245+
GeoInterface.intersects(::PointTrait, ::PointTrait, ::XGeom, ::XGeom) = true
246+
GeoInterface.touches(::PointTrait, ::PointTrait, ::XGeom, ::XGeom) = true
247+
GeoInterface.within(::PointTrait, ::PointTrait, ::XGeom, ::XGeom) = true
248+
GeoInterface.contains(::PointTrait, ::PointTrait, ::XGeom, ::XGeom) = true
249+
GeoInterface.overlaps(::PointTrait, ::PointTrait, ::XGeom, ::XGeom) = true
250+
GeoInterface.crosses(::PointTrait, ::PointTrait, ::XGeom, ::XGeom) = true
251+
252+
GeoInterface.relate(::PointTrait, ::PointTrait, ::XGeom, ::XGeom, matrix) = true
253+
254+
GeoInterface.symdifference(::PointTrait, ::PointTrait, a::XGeom, ::XGeom) = a
255+
GeoInterface.difference(::PointTrait, ::PointTrait, a::XGeom, ::XGeom) = a
256+
GeoInterface.intersection(::PointTrait, ::PointTrait, a::XGeom, ::XGeom) = a
257+
GeoInterface.union(::PointTrait, ::PointTrait, ::XGeom, a::XGeom) = a
258+
259+
GeoInterface.distance(::PointTrait, ::PointTrait, ::XGeom, ::XGeom) = rand()
260+
261+
GeoInterface.buffer(::PointTrait, a::XGeom, distance) = a
262+
GeoInterface.convexhull(::PointTrait, a::XGeom) = a
263+
264+
GeoInterface.astext(::PointTrait, ::XGeom) = "POINT (1 2)"
265+
GeoInterface.asbinary(::PointTrait, ::XGeom) = [0x0, 0x0]
266+
267+
geom = XGeom()
268+
269+
@test GeoInterface.equals(geom, geom)
270+
@test GeoInterface.disjoint(geom, geom)
271+
@test GeoInterface.intersects(geom, geom)
272+
@test GeoInterface.touches(geom, geom)
273+
@test GeoInterface.within(geom, geom)
274+
@test GeoInterface.contains(geom, geom)
275+
@test GeoInterface.overlaps(geom, geom)
276+
@test GeoInterface.crosses(geom, geom)
277+
278+
@test GeoInterface.relate(geom, geom, ["a"])
279+
280+
@test GeoInterface.isgeometry(GeoInterface.symdifference(geom, geom))
281+
@test GeoInterface.isgeometry(GeoInterface.difference(geom, geom))
282+
@test GeoInterface.isgeometry(GeoInterface.intersection(geom, geom))
283+
@test GeoInterface.isgeometry(GeoInterface.union(geom, geom))
284+
285+
@test GeoInterface.distance(geom, geom) isa Number
286+
287+
@test GeoInterface.isgeometry(GeoInterface.buffer(geom, 1.0))
288+
@test GeoInterface.isgeometry(GeoInterface.convexhull(geom))
289+
290+
@test GeoInterface.astext(geom) isa String
291+
@test GeoInterface.asbinary(geom) isa Vector{UInt8}
292+
end

0 commit comments

Comments
 (0)