Skip to content

Commit

Permalink
add trait promotion without array (#159)
Browse files Browse the repository at this point in the history
* add trait promotion without array

* support FeatureCollection + tests

* Apply suggestion from code review

* Get tests working, propagate crs and extent up

* Update src/wrappers.jl

---------

Co-authored-by: Anshul Singhvi <anshulsinghvi@gmail.com>
Co-authored-by: Rafael Schouten <rafaelschouten@gmail.com>
  • Loading branch information
3 people authored Sep 23, 2024
1 parent b0156d3 commit 5c885b2
Show file tree
Hide file tree
Showing 2 changed files with 30 additions and 6 deletions.
24 changes: 19 additions & 5 deletions src/wrappers.jl
Original file line number Diff line number Diff line change
Expand Up @@ -172,16 +172,23 @@ for (geomtype, trait, childtype, child_trait, length_check, nesting) in (
# But not if geom is already a WrapperGeometry
convert(::Type{$geomtype}, ::$trait, geom::$geomtype) = geom
end

@eval function $geomtype{Z,M}(geom::T; extent::E=nothing, crs::C=nothing) where {Z,M,T,E,C}
Z isa Union{Bool,Nothing} || throw(ArgumentError("Z Parameter must be `true`, `false` or `nothing`"))
M isa Union{Bool,Nothing} || throw(ArgumentError("M Parameter must be `true`, `false` or `nothing`"))

# Wrap some geometry at the same level
# Is geom a single geometry ?
if isgeometry(geom)
geomtrait(geom) isa $trait || _argument_error(T, $trait)
Z1 = isnothing(Z) ? is3d(geom) : Z
M1 = isnothing(M) ? ismeasured(geom) : M
return $geomtype{Z1,M1,T,E,C}(geom, extent, crs)
if geomtrait(geom) isa $child_trait
# If geom is a child_trait, then make geom a vector and call again
return $geomtype([geom]; extent, crs)
else
# Wrap some geometry at the same level
geomtrait(geom) isa $trait || _argument_error(T, $trait)
Z1 = isnothing(Z) ? is3d(geom) : Z
M1 = isnothing(M) ? ismeasured(geom) : M
return $geomtype{Z1,M1,T,E,C}(geom, extent, crs)
end

# Otherwise wrap an array of child geometries
elseif geom isa AbstractArray
Expand Down Expand Up @@ -428,6 +435,13 @@ end
function FeatureCollection(parent; crs=nothing, extent=nothing)
if isfeaturecollection(parent)
FeatureCollection(parent, crs, extent)
elseif isfeature(parent)
# If `parent` is a single feature, wrap it in a featurecollection
FeatureCollection(
[parent],
isnothing(crs) ? Wrappers.crs(parent) : crs,
isnothing(extent) ? Wrappers.extent(parent) : extent
)
else
features = (parent isa AbstractArray) ? parent : collect(parent)
all(f -> isfeature(f), features) || _child_feature_error()
Expand Down
12 changes: 11 additions & 1 deletion test/test_wrappers.jl
Original file line number Diff line number Diff line change
Expand Up @@ -152,6 +152,7 @@ linearring_crs = GI.LinearRing(linearring; crs=EPSG(4326))

# Polygon
polygon = GI.Polygon([linearring, linearring])
@test GI.Polygon([linearring]) == GI.Polygon(linearring)
@test polygon == GI.Polygon(polygon)
@test GI.getgeom(polygon, 1) === linearring
@test collect(GI.getgeom(polygon)) == [linearring, linearring]
Expand Down Expand Up @@ -179,6 +180,7 @@ polygon3d = GI.Polygon([linearring3d, linearring3d])
# MultiPoint
multipoint = GI.MultiPoint([(1, 2), (3, 4), (3, 2), (1, 4), (7, 8), (9, 10)])
@test multipoint == GI.MultiPoint(multipoint)
@test GI.MultiPoint([(1, 2)]) == GI.MultiPoint((1, 2))
@test GI.getgeom(multipoint, 1) === (1, 2)
@test !GI.is3d(multipoint)
@test GI.ncoord(multipoint) == 2
Expand All @@ -192,6 +194,7 @@ multipoint_crs = GI.MultiPoint(multipoint; crs=EPSG(4326))
# GeometryCollection
geoms = [line, linestring, linearring, multipoint, (1, 2)]
collection = GI.GeometryCollection(geoms)
@test GI.GeometryCollection([line]) == GI.GeometryCollection(line)
@test collection == GI.GeometryCollection(collection)
@test GI.getgeom(collection) == geoms
@test GI.testgeometry(collection)
Expand All @@ -205,6 +208,7 @@ collection_crs = GI.GeometryCollection(collection; crs=EPSG(4326))
# MultiCurve
multicurve = GI.MultiCurve([linestring, linearring])
@test collect(GI.getpoint(multicurve)) == vcat(collect(GI.getpoint(linestring)), collect(GI.getpoint(linearring)))
@test GI.MultiCurve([linestring]) == GI.MultiCurve(linestring)
@test multicurve == GI.MultiCurve(multicurve)
@test GI.getgeom(multicurve, 1) === linestring
@test !GI.is3d(multicurve)
Expand All @@ -221,6 +225,7 @@ multicurve_crs = GI.MultiCurve(multicurve; crs=EPSG(4326))
polygon = GI.Polygon([linearring, linearring])
multipolygon = GI.MultiPolygon([polygon])
@test multipolygon == GI.MultiPolygon(multipolygon)
@test multipolygon == GI.MultiPolygon(polygon)
@test GI.getgeom(multipolygon, 1) === polygon
@test !GI.is3d(multipolygon)
@test GI.ncoord(multipolygon) == 2
Expand All @@ -238,6 +243,7 @@ multipolygon_crs = GI.MultiPolygon(multipolygon; crs=EPSG(4326))
# PolyhedralSurface
polyhedralsurface = GI.PolyhedralSurface([polygon, polygon])
@test polyhedralsurface == GI.PolyhedralSurface(polyhedralsurface)
@test GI.PolyhedralSurface(polygon) == GI.PolyhedralSurface(polygon)
@test !GI.is3d(polyhedralsurface)
@test GI.ncoord(polyhedralsurface) == 2
@test @inferred(GI.extent(polyhedralsurface)) == Extent(X=(1, 5), Y=(2, 6))
Expand Down Expand Up @@ -281,7 +287,11 @@ feature = GI.Feature(multipolygon;
@test_throws ArgumentError GI.Feature(:not_a_feature; properties=(x=1, y=2, z=3))

# Feature Collection
fc = GI.FeatureCollection([feature]; crs=EPSG(4326), extent=GI.extent(feature))
fc_unwrapped = GI.FeatureCollection(feature; crs=EPSG(4326), extent=GI.extent(feature))
fc = GI.FeatureCollection(fc_unwrapped.parent; crs=EPSG(4326), extent=GI.extent(feature)) # so that `==` works since the underlying array is the same
@test fc_unwrapped == fc
@test GI.crs(fc) == GI.crs(GI.FeatureCollection(feature; crs=EPSG(4326), extent=GI.extent(feature)))
@test GI.extent(fc) == GI.extent(GI.FeatureCollection(feature; crs=EPSG(4326), extent=GI.extent(feature)))
@test fc === GI.FeatureCollection(fc)
@test GI.crs(fc) == EPSG(4326)
@test GI.extent(fc) == fc.extent
Expand Down

0 comments on commit 5c885b2

Please sign in to comment.