From deafc8ce5e80fd247f70f493eae5101b4e4edd9c Mon Sep 17 00:00:00 2001 From: Anshul Singhvi Date: Mon, 25 Nov 2024 16:11:33 -0500 Subject: [PATCH 1/2] add `get_geometries` a generic utility inspired by similar functions in Rasters.jl and elsewhere - returns a vector of the geometries in a given object, be it a feature collection, table, iterable of geometries, or whatever. Potential next steps: - `get_geometries(x) do geom` that rebuilds the given structure as far as possible - this is the same as `apply(::AbstractGeometryTrait)` though.... - treatment of dataframes with multiple columns --- GeometryOpsCore/src/geometry_utils.jl | 32 +++++++++++++++++++++++++++ 1 file changed, 32 insertions(+) diff --git a/GeometryOpsCore/src/geometry_utils.jl b/GeometryOpsCore/src/geometry_utils.jl index c941273b2..a1e0b2165 100644 --- a/GeometryOpsCore/src/geometry_utils.jl +++ b/GeometryOpsCore/src/geometry_utils.jl @@ -1,3 +1,35 @@ _linearring(geom::GI.LineString) = GI.LinearRing(parent(geom); extent=geom.extent, crs=geom.crs) _linearring(geom::GI.LinearRing) = geom + + +function get_geometries(x) + if GI.isgeometry(x) + return x + # elseif GI.isgeometrycollection(x) + # return GI.getgeom(x) + elseif GI.isfeature(x) + return GI.geometry(x) + elseif GI.isfeaturecollection(x) + return [GI.geometry(f) for f in GI.getfeature(x)] + elseif Tables.istable(x) && Tables.hascolumn(x, first(GI.geometrycolumns(x))) + return Tables.getcolumn(x, first(GI.geometrycolumns(x))) + else + c = collect(x) + if c isa AbstractArray && GI.trait(first(c)) isa GI.AbstractGeometryTrait + return c + else + throw(ArgumentError(""" + Expected a geometry, feature, feature collection, table with geometry column, or iterable of geometries. + Got $(typeof(x)). + + The input must be one of: + - A GeoInterface geometry (has trait <: AbstractGeometryTrait) + - A GeoInterface feature (has trait FeatureTrait) + - A GeoInterface feature collection (has trait FeatureCollectionTrait) + - A Tables.jl table with a geometry column + - An iterable containing geometries + """)) + end + end +end From 2fcc1d0b3afea84921c4094bd0d07a6465731828 Mon Sep 17 00:00:00 2001 From: Anshul Singhvi Date: Wed, 10 Sep 2025 22:47:37 +0200 Subject: [PATCH 2/2] Implement PR #240 review comments for get_geometries function MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Add check if x is already an AbstractArray to avoid unnecessary collection - Handle GeometryCollection case properly with collect() - Handle offset axes using Base.has_offset_axes and vec() - Add geometrycolumn kwarg for tables with multiple geometry columns 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude --- GeometryOpsCore/src/geometry_utils.jl | 33 ++++++++++++++++++++++----- 1 file changed, 27 insertions(+), 6 deletions(-) diff --git a/GeometryOpsCore/src/geometry_utils.jl b/GeometryOpsCore/src/geometry_utils.jl index a1e0b2165..96373b462 100644 --- a/GeometryOpsCore/src/geometry_utils.jl +++ b/GeometryOpsCore/src/geometry_utils.jl @@ -3,17 +3,38 @@ _linearring(geom::GI.LineString) = GI.LinearRing(parent(geom); extent=geom.exten _linearring(geom::GI.LinearRing) = geom -function get_geometries(x) - if GI.isgeometry(x) +function get_geometries(x; geometrycolumn=nothing) + # Check if already an AbstractArray to avoid unnecessary collection + if x isa AbstractArray + # Handle offset axes if needed + if Base.has_offset_axes(x) + return vec(x) + else + return x + end + elseif GI.isgeometry(x) return x - # elseif GI.isgeometrycollection(x) - # return GI.getgeom(x) + elseif GI.isgeometrycollection(x) + # Handle GeometryCollection properly with collect + return collect(GI.getgeom(x)) elseif GI.isfeature(x) return GI.geometry(x) elseif GI.isfeaturecollection(x) return [GI.geometry(f) for f in GI.getfeature(x)] - elseif Tables.istable(x) && Tables.hascolumn(x, first(GI.geometrycolumns(x))) - return Tables.getcolumn(x, first(GI.geometrycolumns(x))) + elseif Tables.istable(x) + # Handle multiple geometry columns with kwarg + geom_col = if geometrycolumn !== nothing + geometrycolumn + else + geom_cols = GI.geometrycolumns(x) + isempty(geom_cols) ? nothing : first(geom_cols) + end + + if geom_col !== nothing && Tables.hascolumn(x, geom_col) + return Tables.getcolumn(x, geom_col) + else + error("No valid geometry column found in table") + end else c = collect(x) if c isa AbstractArray && GI.trait(first(c)) isa GI.AbstractGeometryTrait