From 82a289369feb2e8571e9bcbc81ca3763ccc9a6e4 Mon Sep 17 00:00:00 2001 From: Maarten Pronk Date: Thu, 4 Jul 2024 23:55:04 +0200 Subject: [PATCH 1/4] Implement . --- src/fallbacks.jl | 10 +++++----- src/interface.jl | 35 ++++++++++++++++++++++++++--------- src/types.jl | 18 ++++++++++++++++++ 3 files changed, 49 insertions(+), 14 deletions(-) diff --git a/src/fallbacks.jl b/src/fallbacks.jl index 9c501ad1..00e1e22c 100644 --- a/src/fallbacks.jl +++ b/src/fallbacks.jl @@ -111,7 +111,7 @@ end coordinates(t::AbstractFeatureCollectionTrait, fc) = map(f -> coordinates(f), getfeature(t, fc)) extent(::Any, x) = Extents.extent(x) -function calc_extent(t::AbstractPointTrait, geom) +function calc_extent(::AbstractProjectedTrait, t::AbstractPointTrait, geom) x = GeoInterface.x(t, geom) y = GeoInterface.y(t, geom) if is3d(geom) @@ -121,7 +121,7 @@ function calc_extent(t::AbstractPointTrait, geom) return Extent(; X=(x, x), Y=(y, y)) end end -function calc_extent(t::AbstractGeometryTrait, geom) +function calc_extent(::AbstractProjectedTrait, t::AbstractGeometryTrait, geom) points = getpoint(t, geom) X = extrema(p -> x(p), points) Y = extrema(p -> y(p), points) @@ -132,12 +132,12 @@ function calc_extent(t::AbstractGeometryTrait, geom) Extent(; X, Y) end end -calc_extent(t::GeometryCollectionTrait, geom) = reduce(Extents.union, (extent(f) for f in getgeom(t, geom))) -function calc_extent(::AbstractFeatureTrait, feature) +calc_extent(::AbstractProjectedTrait, t::GeometryCollectionTrait, geom) = reduce(Extents.union, (extent(f) for f in getgeom(t, geom))) +function calc_extent(::AbstractProjectedTrait, ::AbstractFeatureTrait, feature) geom = geometry(feature) isnothing(geom) ? nothing : extent(geom) end -calc_extent(t::AbstractFeatureCollectionTrait, fc) = reduce(Extents.union, filter(!isnothing, collect(extent(f) for f in getfeature(t, fc)))) +calc_extent(::AbstractProjectedTrait, t::AbstractFeatureCollectionTrait, fc) = reduce(Extents.union, filter(!isnothing, collect(extent(f) for f in getfeature(t, fc)))) # Package level `GeoInterface.convert` method # Packages must implement their own `traittype` method diff --git a/src/interface.jl b/src/interface.jl index 5f1fb79e..5516e997 100644 --- a/src/interface.jl +++ b/src/interface.jl @@ -201,16 +201,19 @@ isring(geom) = isclosed(geom) && issimple(geom) Return the length of `geom` in its 2d coordinate system. Note that this is only valid for [`AbstractCurveTrait`](@ref)s. """ -length(geom) = length(geomtrait(geom), geom) +length(geom) = length(crstrait(geom), geomtrait(geom), geom) +length(::UnknownTrait, trait, geom) = length(trait, geom) # fallback # Surface + """ area(geom) -> Number Return the area of `geom` in its 2d coordinate system. Note that this is only valid for [`AbstractSurfaceTrait`](@ref)s. """ -area(geom) = area(geomtrait(geom), geom) +area(geom) = area(crstrait(geom), geomtrait(geom), geom) +area(::UnknownTrait, trait, geom) = area(trait, geom) # fallback """ centroid(geom) -> Point @@ -219,7 +222,8 @@ The mathematical centroid for this Surface as a Point. The result is not guaranteed to be on this Surface. Note that this is only valid for [`AbstractSurfaceTrait`](@ref)s. """ -centroid(geom) = centroid(geomtrait(geom), geom) +centroid(geom) = centroid(crstrait(geom), geomtrait(geom), geom) +centroid(::UnknownTrait, trait, geom) = centroid(trait, geom) # fallback """ pointonsurface(geom) -> Point @@ -227,7 +231,8 @@ centroid(geom) = centroid(geomtrait(geom), geom) A Point guaranteed to be on this geometry (as opposed to [`centroid`](@ref)). Note that this is only valid for [`AbstractSurfaceTrait`](@ref)s. """ -pointonsurface(geom) = pointonsurface(geomtrait(geom), geom) +pointonsurface(geom) = pointonsurface(crstrait(geom), geomtrait(geom), geom) +pointonsurface(::UnknownTrait, trait, geom) = pointonsurface(trait, geom) # fallback """ boundary(geom) -> Curve @@ -235,9 +240,11 @@ pointonsurface(geom) = pointonsurface(geomtrait(geom), geom) Return the boundary of `geom`. Note that this is only valid for [`AbstractSurfaceTrait`](@ref)s. """ -boundary(geom) = boundary(geomtrait(geom), geom) +boundary(geom) = boundary(crstrait(geom), geomtrait(geom), geom) +boundary(::UnknownTrait, trait, geom) = boundary(trait, geom) # fallback # Polygon/Triangle + """ nring(geom) -> Integer @@ -424,11 +431,12 @@ an extent is calculated from the coordinates of all geometries in `obj`. """ function extent(obj; fallback=true) t = trait(obj) - isnothing(t) && return Extents.extent(obj) - ex = extent(t, obj) - isnothing(ex) && fallback && return calc_extent(t, obj) - return ex + ct = crstrait(obj) + ex = extent(ct, t, obj) + isnothing(ex) && !isnothing(t) && fallback ? calc_extent(ct, t, obj) : ex end +extent(::UnknownTrait, trait, geom) = extent(trait, geom) # fallback +extent(::UnknownTrait, ::Nothing, geom) = Extents.extent(geom) """ bbox(geom) -> T <: Extents.Extent @@ -656,3 +664,12 @@ astext(geom) = astext(geomtrait(geom), geom) Convert `geom` into Well Known Binary (WKB) representation, such as `000000000140000000000000004010000000000000`. """ asbinary(geom) = asbinary(geomtrait(geom), geom) + +""" + crstrait(geom) -> AbstractCRSTrait + +Retrieves the type of the Coordinate Reference System for the given `geom`. +Defaults to retrieving from `crs(geom)` and to `UnknownTrait` if not implemented. + +""" +crstrait(geom) = UnknownTrait() diff --git a/src/types.jl b/src/types.jl index 1a81cf87..5fafb696 100644 --- a/src/types.jl +++ b/src/types.jl @@ -92,3 +92,21 @@ struct FeatureTrait <: AbstractFeatureTrait end abstract type AbstractFeatureCollectionTrait <: AbstractTrait end "A FeatureCollectionTrait holds objects of `FeatureTrait` and an `extent`" struct FeatureCollectionTrait <: AbstractFeatureCollectionTrait end + +"An AbstractCRSTrait for all coordinate reference systems" +abstract type AbstractCRSTrait end +"An AbstractProjectedTrait for all projected coordinate reference systems" +abstract type AbstractProjectedTrait <: AbstractCRSTrait end +"An AbstractGeographicTrait for all geographic coordinate reference systems" +abstract type AbstractGeographicTrait <: AbstractCRSTrait end +"An ProjectedTrait for all projected coordinate reference systems" +struct ProjectedTrait <: AbstractProjectedTrait end +"An UnknownTrait for all unknown (assumed projected) coordinate reference systems" +struct UnknownTrait <: AbstractProjectedTrait + function UnknownTrait() + Base.depwarn("It is unknown whether your geometry is projected or geographic. Please implement `crstrait` for your geometry.", :UnknownTrait) + new() + end +end +"An GeographicTrait for all geographic coordinate reference systems" +struct GeographicTrait <: AbstractGeographicTrait end From 39b05cfdad61a4cda21e0faf49536912a349f606 Mon Sep 17 00:00:00 2001 From: Maarten Pronk Date: Fri, 12 Jul 2024 16:20:35 +0200 Subject: [PATCH 2/4] Revert crstrait prefix on operations except for extent. --- src/interface.jl | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/src/interface.jl b/src/interface.jl index 5516e997..897c5dbc 100644 --- a/src/interface.jl +++ b/src/interface.jl @@ -201,8 +201,8 @@ isring(geom) = isclosed(geom) && issimple(geom) Return the length of `geom` in its 2d coordinate system. Note that this is only valid for [`AbstractCurveTrait`](@ref)s. """ -length(geom) = length(crstrait(geom), geomtrait(geom), geom) -length(::UnknownTrait, trait, geom) = length(trait, geom) # fallback +length(geom) = length(geomtrait(geom), geom) + # Surface @@ -212,8 +212,8 @@ length(::UnknownTrait, trait, geom) = length(trait, geom) # fallback Return the area of `geom` in its 2d coordinate system. Note that this is only valid for [`AbstractSurfaceTrait`](@ref)s. """ -area(geom) = area(crstrait(geom), geomtrait(geom), geom) -area(::UnknownTrait, trait, geom) = area(trait, geom) # fallback +area(geom) = area(geomtrait(geom), geom) + """ centroid(geom) -> Point @@ -222,8 +222,8 @@ The mathematical centroid for this Surface as a Point. The result is not guaranteed to be on this Surface. Note that this is only valid for [`AbstractSurfaceTrait`](@ref)s. """ -centroid(geom) = centroid(crstrait(geom), geomtrait(geom), geom) -centroid(::UnknownTrait, trait, geom) = centroid(trait, geom) # fallback +centroid(geom) = centroid(geomtrait(geom), geom) + """ pointonsurface(geom) -> Point @@ -231,8 +231,8 @@ centroid(::UnknownTrait, trait, geom) = centroid(trait, geom) # fallback A Point guaranteed to be on this geometry (as opposed to [`centroid`](@ref)). Note that this is only valid for [`AbstractSurfaceTrait`](@ref)s. """ -pointonsurface(geom) = pointonsurface(crstrait(geom), geomtrait(geom), geom) -pointonsurface(::UnknownTrait, trait, geom) = pointonsurface(trait, geom) # fallback +pointonsurface(geom) = pointonsurface(geomtrait(geom), geom) + """ boundary(geom) -> Curve @@ -240,8 +240,8 @@ pointonsurface(::UnknownTrait, trait, geom) = pointonsurface(trait, geom) # fal Return the boundary of `geom`. Note that this is only valid for [`AbstractSurfaceTrait`](@ref)s. """ -boundary(geom) = boundary(crstrait(geom), geomtrait(geom), geom) -boundary(::UnknownTrait, trait, geom) = boundary(trait, geom) # fallback +boundary(geom) = boundary(geomtrait(geom), geom) + # Polygon/Triangle From bd91c16406ebeaea3fe82f50b800ac4d9abb1e77 Mon Sep 17 00:00:00 2001 From: Maarten Pronk Date: Fri, 12 Jul 2024 23:49:40 +0200 Subject: [PATCH 3/4] Resolve docstring comment. --- src/types.jl | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/src/types.jl b/src/types.jl index 5fafb696..bd7b605a 100644 --- a/src/types.jl +++ b/src/types.jl @@ -93,14 +93,18 @@ abstract type AbstractFeatureCollectionTrait <: AbstractTrait end "A FeatureCollectionTrait holds objects of `FeatureTrait` and an `extent`" struct FeatureCollectionTrait <: AbstractFeatureCollectionTrait end -"An AbstractCRSTrait for all coordinate reference systems" +"Supertype for all coordinate reference system traits" abstract type AbstractCRSTrait end + "An AbstractProjectedTrait for all projected coordinate reference systems" abstract type AbstractProjectedTrait <: AbstractCRSTrait end "An AbstractGeographicTrait for all geographic coordinate reference systems" abstract type AbstractGeographicTrait <: AbstractCRSTrait end + "An ProjectedTrait for all projected coordinate reference systems" struct ProjectedTrait <: AbstractProjectedTrait end +"An GeographicTrait for all geographic coordinate reference systems" +struct GeographicTrait <: AbstractGeographicTrait end "An UnknownTrait for all unknown (assumed projected) coordinate reference systems" struct UnknownTrait <: AbstractProjectedTrait function UnknownTrait() @@ -108,5 +112,3 @@ struct UnknownTrait <: AbstractProjectedTrait new() end end -"An GeographicTrait for all geographic coordinate reference systems" -struct GeographicTrait <: AbstractGeographicTrait end From 1daaffde53fc38458596a136f3f13287a9880b13 Mon Sep 17 00:00:00 2001 From: Maarten Pronk Date: Sat, 13 Jul 2024 11:33:07 +0200 Subject: [PATCH 4/4] Don't implement crstrait for Extent just yet. --- src/fallbacks.jl | 10 +++++----- src/interface.jl | 9 ++++----- 2 files changed, 9 insertions(+), 10 deletions(-) diff --git a/src/fallbacks.jl b/src/fallbacks.jl index 00e1e22c..9c501ad1 100644 --- a/src/fallbacks.jl +++ b/src/fallbacks.jl @@ -111,7 +111,7 @@ end coordinates(t::AbstractFeatureCollectionTrait, fc) = map(f -> coordinates(f), getfeature(t, fc)) extent(::Any, x) = Extents.extent(x) -function calc_extent(::AbstractProjectedTrait, t::AbstractPointTrait, geom) +function calc_extent(t::AbstractPointTrait, geom) x = GeoInterface.x(t, geom) y = GeoInterface.y(t, geom) if is3d(geom) @@ -121,7 +121,7 @@ function calc_extent(::AbstractProjectedTrait, t::AbstractPointTrait, geom) return Extent(; X=(x, x), Y=(y, y)) end end -function calc_extent(::AbstractProjectedTrait, t::AbstractGeometryTrait, geom) +function calc_extent(t::AbstractGeometryTrait, geom) points = getpoint(t, geom) X = extrema(p -> x(p), points) Y = extrema(p -> y(p), points) @@ -132,12 +132,12 @@ function calc_extent(::AbstractProjectedTrait, t::AbstractGeometryTrait, geom) Extent(; X, Y) end end -calc_extent(::AbstractProjectedTrait, t::GeometryCollectionTrait, geom) = reduce(Extents.union, (extent(f) for f in getgeom(t, geom))) -function calc_extent(::AbstractProjectedTrait, ::AbstractFeatureTrait, feature) +calc_extent(t::GeometryCollectionTrait, geom) = reduce(Extents.union, (extent(f) for f in getgeom(t, geom))) +function calc_extent(::AbstractFeatureTrait, feature) geom = geometry(feature) isnothing(geom) ? nothing : extent(geom) end -calc_extent(::AbstractProjectedTrait, t::AbstractFeatureCollectionTrait, fc) = reduce(Extents.union, filter(!isnothing, collect(extent(f) for f in getfeature(t, fc)))) +calc_extent(t::AbstractFeatureCollectionTrait, fc) = reduce(Extents.union, filter(!isnothing, collect(extent(f) for f in getfeature(t, fc)))) # Package level `GeoInterface.convert` method # Packages must implement their own `traittype` method diff --git a/src/interface.jl b/src/interface.jl index 897c5dbc..61b6e71e 100644 --- a/src/interface.jl +++ b/src/interface.jl @@ -431,12 +431,11 @@ an extent is calculated from the coordinates of all geometries in `obj`. """ function extent(obj; fallback=true) t = trait(obj) - ct = crstrait(obj) - ex = extent(ct, t, obj) - isnothing(ex) && !isnothing(t) && fallback ? calc_extent(ct, t, obj) : ex + isnothing(t) && return Extents.extent(obj) + ex = extent(t, obj) + isnothing(ex) && fallback && return calc_extent(t, obj) + return ex end -extent(::UnknownTrait, trait, geom) = extent(trait, geom) # fallback -extent(::UnknownTrait, ::Nothing, geom) = Extents.extent(geom) """ bbox(geom) -> T <: Extents.Extent