From f705f5821774e8e85868d117715d249becc924c7 Mon Sep 17 00:00:00 2001 From: Rafael Schouten Date: Thu, 28 Dec 2023 23:56:38 +0100 Subject: [PATCH 1/6] add transform method for coordinate transformations --- src/GeometryOps.jl | 2 ++ src/transformations/transform.jl | 52 +++++++++++++++++++++++++++++++ test/transformations/transform.jl | 19 +++++++++++ 3 files changed, 73 insertions(+) create mode 100644 src/transformations/transform.jl create mode 100644 test/transformations/transform.jl diff --git a/src/GeometryOps.jl b/src/GeometryOps.jl index c86ac5fef..d1d230e08 100644 --- a/src/GeometryOps.jl +++ b/src/GeometryOps.jl @@ -7,6 +7,7 @@ using GeometryBasics import Proj using LinearAlgebra import ExactPredicates +import Proj.CoordinateTransformations.StaticArrays using GeoInterface.Extents: Extents @@ -38,5 +39,6 @@ include("transformations/flip.jl") include("transformations/simplify.jl") include("transformations/reproject.jl") include("transformations/tuples.jl") +include("transformations/transform.jl") end diff --git a/src/transformations/transform.jl b/src/transformations/transform.jl new file mode 100644 index 000000000..47076a4e3 --- /dev/null +++ b/src/transformations/transform.jl @@ -0,0 +1,52 @@ + +""" + transform(f, obj) + +Apply a function `f` to all the points in `obj`. + +Points will be passed to `f` as an `SVector` to allow +using CoordinateTransformations.jl and Rotations.jl +without hassle. + +`SVector` is also a valid GeoInterface.jl point, so will +work in all GeoInterface.jl methods. + +## Example + +```julia +julia> geom = GI.Polygon([GI.LinearRing([(1, 2), (3, 4), (5, 6), (1, 2)]), GI.LinearRing([(3, 4), (5, 6), (6, 7), (3, 4)])]); + +julia> f = CoordinateTransformations.Translation(3.5, 1.5) +Translation(3.5, 1.5) + +julia> GO.transform(f, geom) +GeoInterface.Wrappers.Polygon{false, false, Vector{GeoInterface.Wrappers.LinearRing{false, false, Vector{StaticArraysCore.SVector{2, Float64}}, Nothing, Nothing}}, Nothing, Nothing}(GeoInterface.Wrappers.Linea +rRing{false, false, Vector{StaticArraysCore.SVector{2, Float64}}, Nothing, Nothing}[GeoInterface.Wrappers.LinearRing{false, false, Vector{StaticArraysCore.SVector{2, Float64}}, Nothing, Nothing}(StaticArraysCo +re.SVector{2, Float64}[[5.5, 2.5], [7.5, 4.5], [9.5, 6.5], [5.5, 2.5]], nothing, nothing), GeoInterface.Wrappers.LinearRing{false, false, Vector{StaticArraysCore.SVector{2, Float64}}, Nothing, Nothing}(StaticA +rraysCore.SVector{2, Float64}[[7.5, 4.5], [9.5, 6.5], [10.5, 7.5], [7.5, 4.5]], nothing, nothing)], nothing, nothing) +``` + +With Rotations.jl you need to actuall multiply the Rotation +by the `SVector` point, which is easy using an anonymous function. + +```julia +julia> using Rotations + +julia> GO.transform(p -> one(RotMatrix{2}) * p, geom) +GeoInterface.Wrappers.Polygon{false, false, Vector{GeoInterface.Wrappers.LinearRing{false, false, Vector{StaticArraysCore.SVector{2, Int64}}, Nothing, Nothing}}, Nothing, Nothing}(GeoInterface.Wrappers.LinearR +ing{false, false, Vector{StaticArraysCore.SVector{2, Int64}}, Nothing, Nothing}[GeoInterface.Wrappers.LinearRing{false, false, Vector{StaticArraysCore.SVector{2, Int64}}, Nothing, Nothing}(StaticArraysCore.SVe +ctor{2, Int64}[[2, 1], [4, 3], [6, 5], [2, 1]], nothing, nothing), GeoInterface.Wrappers.LinearRing{false, false, Vector{StaticArraysCore.SVector{2, Int64}}, Nothing, Nothing}(StaticArraysCore.SVector{2, Int64 +}[[4, 3], [6, 5], [7, 6], [4, 3]], nothing, nothing)], nothing, nothing) +``` +""" +function transform(f, geom; kw...) + if _is3d(geom) + return apply(PointTrait, geom; kw...) do p + f(StaticArrays.SVector{3}((GI.y(p), GI.x(p), GI.z(p)))) + end + else + return apply(PointTrait, geom; kw...) do p + f(StaticArrays.SVector{2}((GI.y(p), GI.x(p)))) + end + end +end diff --git a/test/transformations/transform.jl b/test/transformations/transform.jl new file mode 100644 index 000000000..63dfa1843 --- /dev/null +++ b/test/transformations/transform.jl @@ -0,0 +1,19 @@ +using Test + +import GeoInterface as GI +import GeometryOps as GO +using GeometryOps.Proj.CoordinateTransformations +using Rotations + +@testset "transform" begin + geom = GI.Polygon([GI.LinearRing([(1, 2), (3, 4), (5, 6), (1, 2)]), + GI.LinearRing([(3, 4), (5, 6), (6, 7), (3, 4)])]) + translated = GI.Polygon([GI.LinearRing([[5.5, 2.5], [7.5, 4.5], [9.5, 6.5], [5.5, 2.5]]), GI.LinearRing([[7.5, 4.5], [9.5, 6.5], [10.5, 7.5], [7.5, 4.5]])]) + f = CoordinateTransformations.Translation(3.5, 1.5) + @test GO.transform(f, geom) == translated + GO.transform(p -> one(RotMatrix{2}) * p, geom) + == translated + + +end + From 0e276e44c853772e766a3c898a641bce2d73a635 Mon Sep 17 00:00:00 2001 From: Rafael Schouten Date: Thu, 28 Dec 2023 23:59:24 +0100 Subject: [PATCH 2/6] clean up tests --- test/transformations/transform.jl | 6 ------ 1 file changed, 6 deletions(-) diff --git a/test/transformations/transform.jl b/test/transformations/transform.jl index 63dfa1843..508935e1d 100644 --- a/test/transformations/transform.jl +++ b/test/transformations/transform.jl @@ -3,7 +3,6 @@ using Test import GeoInterface as GI import GeometryOps as GO using GeometryOps.Proj.CoordinateTransformations -using Rotations @testset "transform" begin geom = GI.Polygon([GI.LinearRing([(1, 2), (3, 4), (5, 6), (1, 2)]), @@ -11,9 +10,4 @@ using Rotations translated = GI.Polygon([GI.LinearRing([[5.5, 2.5], [7.5, 4.5], [9.5, 6.5], [5.5, 2.5]]), GI.LinearRing([[7.5, 4.5], [9.5, 6.5], [10.5, 7.5], [7.5, 4.5]])]) f = CoordinateTransformations.Translation(3.5, 1.5) @test GO.transform(f, geom) == translated - GO.transform(p -> one(RotMatrix{2}) * p, geom) - == translated - - end - From e7a0ec38df0eb0a22d660a861321114cdcb7762e Mon Sep 17 00:00:00 2001 From: Rafael Schouten Date: Thu, 28 Dec 2023 23:59:55 +0100 Subject: [PATCH 3/6] actually run the test --- test/runtests.jl | 1 + 1 file changed, 1 insertion(+) diff --git a/test/runtests.jl b/test/runtests.jl index 779cfa15e..bf68b6bfc 100644 --- a/test/runtests.jl +++ b/test/runtests.jl @@ -28,4 +28,5 @@ const GO = GeometryOps @testset "Reproject" begin include("transformations/reproject.jl") end @testset "Flip" begin include("transformations/flip.jl") end @testset "Simplify" begin include("transformations/simplify.jl") end + @testset "Transform" begin include("transformations/transform.jl") end end From 909bf9531558432ff54c20d1308c6f80bc3153b7 Mon Sep 17 00:00:00 2001 From: Rafael Schouten Date: Sat, 30 Dec 2023 02:55:18 +0100 Subject: [PATCH 4/6] dont flip! --- src/transformations/transform.jl | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/transformations/transform.jl b/src/transformations/transform.jl index 47076a4e3..70c24029e 100644 --- a/src/transformations/transform.jl +++ b/src/transformations/transform.jl @@ -42,11 +42,11 @@ ctor{2, Int64}[[2, 1], [4, 3], [6, 5], [2, 1]], nothing, nothing), GeoInterface. function transform(f, geom; kw...) if _is3d(geom) return apply(PointTrait, geom; kw...) do p - f(StaticArrays.SVector{3}((GI.y(p), GI.x(p), GI.z(p)))) + f(StaticArrays.SVector{3}((GI.x(p), GI.y(p), GI.z(p)))) end else return apply(PointTrait, geom; kw...) do p - f(StaticArrays.SVector{2}((GI.y(p), GI.x(p)))) + f(StaticArrays.SVector{2}((GI.x(p), GI.y(p)))) end end end From 599093112a08eec10c85cd85a91239e458c21b18 Mon Sep 17 00:00:00 2001 From: Rafael Schouten Date: Sat, 30 Dec 2023 02:57:46 +0100 Subject: [PATCH 5/6] no flip --- test/transformations/transform.jl | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/test/transformations/transform.jl b/test/transformations/transform.jl index 508935e1d..597c9a64a 100644 --- a/test/transformations/transform.jl +++ b/test/transformations/transform.jl @@ -7,7 +7,8 @@ using GeometryOps.Proj.CoordinateTransformations @testset "transform" begin geom = GI.Polygon([GI.LinearRing([(1, 2), (3, 4), (5, 6), (1, 2)]), GI.LinearRing([(3, 4), (5, 6), (6, 7), (3, 4)])]) - translated = GI.Polygon([GI.LinearRing([[5.5, 2.5], [7.5, 4.5], [9.5, 6.5], [5.5, 2.5]]), GI.LinearRing([[7.5, 4.5], [9.5, 6.5], [10.5, 7.5], [7.5, 4.5]])]) + translated = GI.Polygon([GI.LinearRing([[4.5, 3.5], [6.5, 5.5], [8.5, 7.5], [4.5, 3.5]]), + GI.LinearRing([[6.5, 5.5], [8.5, 7.5], [9.5, 8.5], [6.5, 5.5]])]) f = CoordinateTransformations.Translation(3.5, 1.5) @test GO.transform(f, geom) == translated end From be8bb83e5ca79d8bf3b51decc3f9b822702df61e Mon Sep 17 00:00:00 2001 From: Rafael Schouten Date: Tue, 2 Jan 2024 13:21:20 +0100 Subject: [PATCH 6/6] fix the doc --- src/transformations/transform.jl | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/src/transformations/transform.jl b/src/transformations/transform.jl index 70c24029e..ee1c3f671 100644 --- a/src/transformations/transform.jl +++ b/src/transformations/transform.jl @@ -14,6 +14,10 @@ work in all GeoInterface.jl methods. ## Example ```julia +julia> import GeoInterface as GI + +julia> import GeometryOps as GO + julia> geom = GI.Polygon([GI.LinearRing([(1, 2), (3, 4), (5, 6), (1, 2)]), GI.LinearRing([(3, 4), (5, 6), (6, 7), (3, 4)])]); julia> f = CoordinateTransformations.Translation(3.5, 1.5) @@ -22,8 +26,8 @@ Translation(3.5, 1.5) julia> GO.transform(f, geom) GeoInterface.Wrappers.Polygon{false, false, Vector{GeoInterface.Wrappers.LinearRing{false, false, Vector{StaticArraysCore.SVector{2, Float64}}, Nothing, Nothing}}, Nothing, Nothing}(GeoInterface.Wrappers.Linea rRing{false, false, Vector{StaticArraysCore.SVector{2, Float64}}, Nothing, Nothing}[GeoInterface.Wrappers.LinearRing{false, false, Vector{StaticArraysCore.SVector{2, Float64}}, Nothing, Nothing}(StaticArraysCo -re.SVector{2, Float64}[[5.5, 2.5], [7.5, 4.5], [9.5, 6.5], [5.5, 2.5]], nothing, nothing), GeoInterface.Wrappers.LinearRing{false, false, Vector{StaticArraysCore.SVector{2, Float64}}, Nothing, Nothing}(StaticA -rraysCore.SVector{2, Float64}[[7.5, 4.5], [9.5, 6.5], [10.5, 7.5], [7.5, 4.5]], nothing, nothing)], nothing, nothing) +re.SVector{2, Float64}[[4.5, 3.5], [6.5, 5.5], [8.5, 7.5], [4.5, 3.5]], nothing, nothing), GeoInterface.Wrappers.LinearRing{false, false, Vector{StaticArraysCore.SVector{2, Float64}}, Nothing, Nothing}(StaticA +rraysCore.SVector{2, Float64}[[6.5, 5.5], [8.5, 7.5], [9.5, 8.5], [6.5, 5.5]], nothing, nothing)], nothing, nothing) ``` With Rotations.jl you need to actuall multiply the Rotation