Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Make Test Geometry re-usable in other packages. #75

Closed
wants to merge 2 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions docs/src/guides/developer.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,8 @@ also implement those interfaces where applicable.

Last but not least, we also provide an interface for features--geometries with properties--if applicable.

If you only consume geometries, we provide simple geometries that implement GeoInterface for testing in the GeoInterface.TestGeometry module. These geometries are simple called `Point`, `LineString`, etc. after their traits.

## Required for Geometry

```julia
Expand Down
1 change: 1 addition & 0 deletions src/GeoInterface.jl
Original file line number Diff line number Diff line change
Expand Up @@ -52,5 +52,6 @@ include("interface.jl")
include("fallbacks.jl")
include("utils.jl")
include("base.jl")
include("test_geometry.jl")

end # module
90 changes: 90 additions & 0 deletions src/test_geometry.jl
Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@
module TestGeometry

using ..GeoInterface

# Implement interface
struct Point end
struct EmptyPoint end
struct Curve end
struct Polygon end
struct Triangle end
struct MultiPoint end
struct MultiCurve end
struct MultiPolygon end
struct TIN end
struct Collection end
struct Feature{G,P}
geometry::G
properties::P
end
struct FeatureCollection{G}
geoms::G
end

GeoInterface.isgeometry(::Point) = true
GeoInterface.geomtrait(::Point) = PointTrait()
GeoInterface.ncoord(::PointTrait, geom::Point) = 2
GeoInterface.getcoord(::PointTrait, geom::Point, i) = [1, 2][i]

GeoInterface.isgeometry(::EmptyPoint) = true
GeoInterface.geomtrait(::EmptyPoint) = PointTrait()
GeoInterface.ncoord(::PointTrait, geom::EmptyPoint) = 0
GeoInterface.isempty(::PointTrait, geom::EmptyPoint) = true

GeoInterface.isgeometry(::Curve) = true
GeoInterface.geomtrait(::Curve) = LineStringTrait()
GeoInterface.ngeom(::LineStringTrait, geom::Curve) = 2
GeoInterface.getgeom(::LineStringTrait, geom::Curve, i) = Point()
Base.convert(T::Type{Curve}, geom::X) where {X} = Base.convert(T, geomtrait(geom), geom)
Base.convert(::Type{Curve}, ::LineStringTrait, geom::Curve) = geom

GeoInterface.isgeometry(::Polygon) = true
GeoInterface.geomtrait(::Polygon) = PolygonTrait()
GeoInterface.ngeom(::PolygonTrait, geom::Polygon) = 2
GeoInterface.getgeom(::PolygonTrait, geom::Polygon, i) = Curve()

GeoInterface.isgeometry(::Triangle) = true
GeoInterface.geomtrait(::Triangle) = TriangleTrait()
GeoInterface.ngeom(::TriangleTrait, geom::Triangle) = 3
GeoInterface.getgeom(::TriangleTrait, geom::Triangle, i) = Curve()

GeoInterface.isgeometry(::MultiPoint) = true
GeoInterface.geomtrait(::MultiPoint) = MultiPointTrait()
GeoInterface.ngeom(::MultiPointTrait, geom::MultiPoint) = 2
GeoInterface.getgeom(::MultiPointTrait, geom::MultiPoint, i) = Point()

GeoInterface.isgeometry(::MultiCurve) = true
GeoInterface.geomtrait(::MultiCurve) = MultiCurveTrait()
GeoInterface.ngeom(::MultiCurveTrait, geom::MultiCurve) = 2
GeoInterface.getgeom(::MultiCurveTrait, geom::MultiCurve, i) = Curve()

GeoInterface.isgeometry(::MultiPolygon) = true
GeoInterface.geomtrait(::MultiPolygon) = MultiPolygonTrait()
GeoInterface.ngeom(::MultiPolygonTrait, geom::MultiPolygon) = 2
GeoInterface.getgeom(::MultiPolygonTrait, geom::MultiPolygon, i) = Polygon()

GeoInterface.isgeometry(::TIN) = true
GeoInterface.geomtrait(::TIN) = PolyhedralSurfaceTrait()
GeoInterface.ngeom(::PolyhedralSurfaceTrait, geom::TIN) = 2
GeoInterface.getgeom(::PolyhedralSurfaceTrait, geom::TIN, i) = Triangle()

GeoInterface.isgeometry(::Collection) = true
GeoInterface.geomtrait(::Collection) = GeometryCollectionTrait()
GeoInterface.ngeom(::GeometryCollectionTrait, geom::Collection) = 2
GeoInterface.getgeom(::GeometryCollectionTrait, geom::Collection, i) = Curve()

GeoInterface.isfeature(::Type{<:Feature}) = true
GeoInterface.trait(feature::Feature) = FeatureTrait()
GeoInterface.geometry(f::Feature) = f.geometry
GeoInterface.properties(f::Feature) = f.properties
GeoInterface.extent(f::Feature) = nothing

GeoInterface.isfeaturecollection(fc::Type{<:FeatureCollection}) = true
GeoInterface.trait(fc::FeatureCollection) = FeatureCollectionTrait()
GeoInterface.nfeature(::FeatureCollectionTrait, fc::FeatureCollection) = length(fc.geoms)
GeoInterface.getfeature(::FeatureCollectionTrait, fc::FeatureCollection) = fc.geoms
GeoInterface.getfeature(::FeatureCollectionTrait, fc::FeatureCollection, i::Integer) = fc.geoms[i]

export Point, EmptyPoint, Curve, Polygon, Triangle, MultiPoint, MultiCurve, MultiPolygon, TIN, Collection, Feature, FeatureCollection

end # module
129 changes: 24 additions & 105 deletions test/test_primitives.jl
Original file line number Diff line number Diff line change
@@ -1,92 +1,11 @@
using GeoInterface
using GeoInterface.TestGeometry
using Test

@testset "Developer" begin
# Implement interface
struct MyPoint end
struct MyEmptyPoint end
struct MyCurve end
struct MyPolygon end
struct MyTriangle end
struct MyMultiPoint end
struct MyMultiCurve end
struct MyMultiPolygon end
struct MyTIN end
struct MyCollection end
struct MyFeature{G,P}
geometry::G
properties::P
end
struct MyFeatureCollection{G}
geoms::G
end

GeoInterface.isgeometry(::MyPoint) = true
GeoInterface.geomtrait(::MyPoint) = PointTrait()
GeoInterface.ncoord(::PointTrait, geom::MyPoint) = 2
GeoInterface.getcoord(::PointTrait, geom::MyPoint, i) = [1, 2][i]

GeoInterface.isgeometry(::MyEmptyPoint) = true
GeoInterface.geomtrait(::MyEmptyPoint) = PointTrait()
GeoInterface.ncoord(::PointTrait, geom::MyEmptyPoint) = 0
GeoInterface.isempty(::PointTrait, geom::MyEmptyPoint) = true

GeoInterface.isgeometry(::MyCurve) = true
GeoInterface.geomtrait(::MyCurve) = LineStringTrait()
GeoInterface.ngeom(::LineStringTrait, geom::MyCurve) = 2
GeoInterface.getgeom(::LineStringTrait, geom::MyCurve, i) = MyPoint()
Base.convert(T::Type{MyCurve}, geom::X) where {X} = Base.convert(T, geomtrait(geom), geom)
Base.convert(::Type{MyCurve}, ::LineStringTrait, geom::MyCurve) = geom

GeoInterface.isgeometry(::MyPolygon) = true
GeoInterface.geomtrait(::MyPolygon) = PolygonTrait()
GeoInterface.ngeom(::PolygonTrait, geom::MyPolygon) = 2
GeoInterface.getgeom(::PolygonTrait, geom::MyPolygon, i) = MyCurve()

GeoInterface.isgeometry(::MyTriangle) = true
GeoInterface.geomtrait(::MyTriangle) = TriangleTrait()
GeoInterface.ngeom(::TriangleTrait, geom::MyTriangle) = 3
GeoInterface.getgeom(::TriangleTrait, geom::MyTriangle, i) = MyCurve()

GeoInterface.isgeometry(::MyMultiPoint) = true
GeoInterface.geomtrait(::MyMultiPoint) = MultiPointTrait()
GeoInterface.ngeom(::MultiPointTrait, geom::MyMultiPoint) = 2
GeoInterface.getgeom(::MultiPointTrait, geom::MyMultiPoint, i) = MyPoint()

GeoInterface.isgeometry(::MyMultiCurve) = true
GeoInterface.geomtrait(::MyMultiCurve) = MultiCurveTrait()
GeoInterface.ngeom(::MultiCurveTrait, geom::MyMultiCurve) = 2
GeoInterface.getgeom(::MultiCurveTrait, geom::MyMultiCurve, i) = MyCurve()

GeoInterface.isgeometry(::MyMultiPolygon) = true
GeoInterface.geomtrait(::MyMultiPolygon) = MultiPolygonTrait()
GeoInterface.ngeom(::MultiPolygonTrait, geom::MyMultiPolygon) = 2
GeoInterface.getgeom(::MultiPolygonTrait, geom::MyMultiPolygon, i) = MyPolygon()

GeoInterface.isgeometry(::MyTIN) = true
GeoInterface.geomtrait(::MyTIN) = PolyhedralSurfaceTrait()
GeoInterface.ngeom(::PolyhedralSurfaceTrait, geom::MyTIN) = 2
GeoInterface.getgeom(::PolyhedralSurfaceTrait, geom::MyTIN, i) = MyTriangle()

GeoInterface.isgeometry(::MyCollection) = true
GeoInterface.geomtrait(::MyCollection) = GeometryCollectionTrait()
GeoInterface.ngeom(::GeometryCollectionTrait, geom::MyCollection) = 2
GeoInterface.getgeom(::GeometryCollectionTrait, geom::MyCollection, i) = MyCurve()

GeoInterface.isfeature(::Type{<:MyFeature}) = true
GeoInterface.trait(feature::MyFeature) = FeatureTrait()
GeoInterface.geometry(f::MyFeature) = f.geometry
GeoInterface.properties(f::MyFeature) = f.properties
GeoInterface.extent(f::MyFeature) = nothing

GeoInterface.isfeaturecollection(fc::Type{<:MyFeatureCollection}) = true
GeoInterface.trait(fc::MyFeatureCollection) = FeatureCollectionTrait()
GeoInterface.nfeature(::FeatureCollectionTrait, fc::MyFeatureCollection) = length(fc.geoms)
GeoInterface.getfeature(::FeatureCollectionTrait, fc::MyFeatureCollection) = fc.geoms
GeoInterface.getfeature(::FeatureCollectionTrait, fc::MyFeatureCollection, i::Integer) = fc.geoms[i]

@testset "Point" begin
geom = MyPoint()
geom = Point()
@test testgeometry(geom)
@test GeoInterface.x(geom) === 1
@test GeoInterface.y(geom) === 2
Expand All @@ -100,7 +19,7 @@ using Test
@test !GeoInterface.is3d(geom)
@test !GeoInterface.ismeasured(geom)

geom = MyEmptyPoint()
geom = EmptyPoint()
@test GeoInterface.coordnames(geom) == ()
@test GeoInterface.isempty(geom)

Expand All @@ -110,7 +29,7 @@ using Test
end

@testset "LineString" begin
geom = MyCurve()
geom = Curve()
@test testgeometry(geom)

@test GeoInterface.npoint(geom) == 2 # defaults to ngeom
Expand All @@ -130,7 +49,7 @@ using Test
end

@testset "Polygon" begin
geom = MyPolygon()
geom = Polygon()
@test testgeometry(geom)
# Test that half a implementation yields an error

Expand All @@ -143,72 +62,72 @@ using Test
line = GeoInterface.gethole(geom, 1)
line = GeoInterface.getexterior(geom)
@test GeoInterface.npoint(geom) == 4
@test collect(GeoInterface.getpoint(geom)) == [MyPoint(), MyPoint(), MyPoint(), MyPoint()]
@test collect(GeoInterface.getpoint(geom)) == [Point(), Point(), Point(), Point()]

@test_throws MethodError GeoInterface.area(geom)

geom = MyTriangle()
geom = Triangle()
@test testgeometry(geom)
@test GeoInterface.nring(geom) == 1
@test GeoInterface.nhole(geom) == 0
@test GeoInterface.npoint(geom) == 3
end

@testset "MultiPoint" begin
geom = MyMultiPoint()
geom = MultiPoint()
@test testgeometry(geom)

@test GeoInterface.npoint(geom) == 2
points = GeoInterface.getpoint(geom)
point = GeoInterface.getpoint(geom, 1)
@test GeoInterface.coordinates(geom) == [[1, 2], [1, 2]]
@test collect(points) == [MyPoint(), MyPoint()]
@test collect(points) == [Point(), Point()]

@test !GeoInterface.issimple(geom)
end

@testset "MultiLineString" begin
geom = MyMultiCurve()
geom = MultiCurve()
@test testgeometry(geom)

@test GeoInterface.nlinestring(geom) == 2
lines = GeoInterface.getlinestring(geom)
line = GeoInterface.getlinestring(geom, 1)
@test GeoInterface.coordinates(geom) == [[[1, 2], [1, 2]], [[1, 2], [1, 2]]]
@test collect(lines) == [MyCurve(), MyCurve()]
@test collect(lines) == [Curve(), Curve()]
end

@testset "MultiPolygon" begin
geom = MyMultiPolygon()
geom = MultiPolygon()
@test testgeometry(geom)

@test GeoInterface.npolygon(geom) == 2
polygons = GeoInterface.getpolygon(geom)
polygon = GeoInterface.getpolygon(geom, 1)
@test GeoInterface.coordinates(geom) == [[[[1, 2], [1, 2]], [[1, 2], [1, 2]]], [[[1, 2], [1, 2]], [[1, 2], [1, 2]]]]
@test collect(polygons) == [MyPolygon(), MyPolygon()]
@test collect(polygons) == [Polygon(), Polygon()]
end

@testset "Surface" begin
geom = MyTIN()
geom = TIN()
@test testgeometry(geom)

@test GeoInterface.npatch(geom) == 2
polygons = GeoInterface.getpatch(geom)
polygon = GeoInterface.getpatch(geom, 1)
@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]]]]
@test collect(polygons) == [MyTriangle(), MyTriangle()]
@test collect(polygons) == [Triangle(), Triangle()]
end

@testset "GeometryCollection" begin
geom = MyCollection()
geom = Collection()
@test testgeometry(geom)

@test GeoInterface.ngeom(geom) == 2
geoms = GeoInterface.getgeom(geom)
thing = GeoInterface.getgeom(geom, 1)
@test GeoInterface.coordinates(geom) == [[[1, 2], [1, 2]], [[1, 2], [1, 2]]]
@test collect(geoms) == [MyCurve(), MyCurve()]
@test collect(geoms) == [Curve(), Curve()]
end

end
Expand All @@ -220,13 +139,13 @@ end
end

@testset "Feature" begin
feature = MyFeature((1, 2), (a=10, b=20))
feature = Feature((1, 2), (a=10, b=20))
@test GeoInterface.testfeature(feature)
end

@testset "FeatureCollection" begin
features = MyFeatureCollection(
[MyFeature(MyPoint(), (a="1", b="2")), MyFeature(MyPolygon(), (a="3", b="4"))]
features = FeatureCollection(
[Feature(Point(), (a="1", b="2")), Feature(Polygon(), (a="3", b="4"))]
)
@test GeoInterface.testfeaturecollection(features)
end
Expand All @@ -239,11 +158,11 @@ end
Base.convert(::Type{XCurve}, ::LineStringTrait, geom::XCurve) = geom # fast fallthrough
Base.convert(::Type{XCurve}, ::LineStringTrait, geom) = geom

geom = MyCurve()
@test !isnothing(convert(MyCurve, geom))
geom = Curve()
@test !isnothing(convert(Curve, geom))

Base.convert(T::Type{XPolygon}, geom::X) where {X} = Base.convert(T, geomtrait(geom), geom)
@test_throws Exception convert(MyPolygon, geom)
Base.convert(T::Type{XPolygon}, geom::X) where {X} = Base.convert(T, geomtype(geom), geom)
@test_throws Exception convert(Polygon, geom)
end

@testset "Operations" begin
Expand Down