From fe1d6da8af788c6da16aad21f36ef00d3b475639 Mon Sep 17 00:00:00 2001 From: Skylar A Gering Date: Mon, 2 Oct 2023 11:58:16 -0700 Subject: [PATCH] Switch return type to be tuple --- src/methods/centroid.jl | 50 ++++++++++++++++++---------------------- test/methods/centroid.jl | 38 +++++++++++++++--------------- 2 files changed, 40 insertions(+), 48 deletions(-) diff --git a/src/methods/centroid.jl b/src/methods/centroid.jl index 99bf6490b..759c7fcfd 100644 --- a/src/methods/centroid.jl +++ b/src/methods/centroid.jl @@ -109,7 +109,7 @@ function centroid_and_length( ::Union{GI.LineStringTrait, GI.LinearRingTrait}, geom, ) - T = Float64 + T = typeof(GI.x(GI.getpoint(geom, 1))) # Initialize starting values xcentroid = T(0) ycentroid = T(0) @@ -133,7 +133,7 @@ function centroid_and_length( end xcentroid /= length ycentroid /= length - return GI.Point(xcentroid, ycentroid), length + return (xcentroid, ycentroid), length end """ @@ -149,7 +149,7 @@ function centroid_and_area( ::Union{GI.LineStringTrait, GI.LinearRingTrait}, geom, ) - T = Float64 + T = typeof(GI.x(GI.getpoint(geom, 1))) # Check that the geometry is closed @assert( GI.getpoint(geom, 1) == GI.getpoint(geom, GI.ngeom(geom)), @@ -175,7 +175,7 @@ function centroid_and_area( area /= 2 xcentroid /= 6area ycentroid /= 6area - return GI.Point(xcentroid, ycentroid), abs(area) + return (xcentroid, ycentroid), abs(area) end """ @@ -184,30 +184,24 @@ end Returns the centroid and area of a given polygon. """ function centroid_and_area(::GI.PolygonTrait, geom) - T = Float64 - # Initialize starting values - xcentroid = T(0) - ycentroid = T(0) - area = T(0) - # Exterior polygon centroid and area - ext_centroid, ext_area = centroid_and_area(GI.getexterior(geom)) - area += ext_area + # Exterior ring's centroid and area + (xcentroid, ycentroid), area = centroid_and_area(GI.getexterior(geom)) # Weight exterior centroid by area - xcentroid += GI.x(ext_centroid) * ext_area - ycentroid += GI.y(ext_centroid) * ext_area + xcentroid *= area + ycentroid *= area # Loop over any holes within the polygon for hole in GI.gethole(geom) # Hole polygon's centroid and area - interior_centroid, interior_area = centroid_and_area(hole) + (xinterior, yinterior), interior_area = centroid_and_area(hole) # Accumulate the area component into `area` area -= interior_area # Weighted average of centroid components - xcentroid -= GI.x(interior_centroid) * interior_area - ycentroid -= GI.y(interior_centroid) * interior_area + xcentroid -= xinterior * interior_area + ycentroid -= yinterior * interior_area end xcentroid /= area ycentroid /= area - return GI.Point(xcentroid, ycentroid), area + return (xcentroid, ycentroid), area end """ @@ -216,22 +210,22 @@ end Returns the centroid and area of a given multipolygon. """ function centroid_and_area(::GI.MultiPolygonTrait, geom) - T = Float64 - # Initialize starting values - xcentroid = T(0) - ycentroid = T(0) - area = T(0) + # First polygon's centroid and area + (xcentroid, ycentroid), area = centroid_and_area(GI.getpolygon(geom, 1)) + # Weight first polygon's centroid by area + xcentroid *= area + ycentroid *= area # Loop over any polygons within the multipolygon - for poly in GI.getpolygon(geom) + for i in 2:GI.ngeom(geom) #poly in GI.getpolygon(geom) # Polygon centroid and area - poly_centroid, poly_area = centroid_and_area(poly) + (xpoly, ypoly), poly_area = centroid_and_area(GI.getpolygon(geom, i)) # Accumulate the area component into `area` area += poly_area # Weighted average of centroid components - xcentroid += GI.x(poly_centroid) * poly_area - ycentroid += GI.y(poly_centroid) * poly_area + xcentroid += xpoly * poly_area + ycentroid += ypoly * poly_area end xcentroid /= area ycentroid /= area - return GI.Point(xcentroid, ycentroid), area + return (xcentroid, ycentroid), area end \ No newline at end of file diff --git a/test/methods/centroid.jl b/test/methods/centroid.jl index fb95b9b45..9aad3d861 100644 --- a/test/methods/centroid.jl +++ b/test/methods/centroid.jl @@ -3,16 +3,16 @@ l1 = LG.LineString([[0.0, 0.0], [10.0, 0.0], [10.0, 10.0]]) c1, len1 = GO.centroid_and_length(l1) c1_from_LG = LG.centroid(l1) - @test GI.x(c1) ≈ GI.x(c1_from_LG) - @test GI.y(c1) ≈ GI.y(c1_from_LG) + @test c1[1] ≈ GI.x(c1_from_LG) + @test c1[2] ≈ GI.y(c1_from_LG) @test len1 ≈ 20.0 # Spiral line string l2 = LG.LineString([[0.0, 0.0], [2.5, -2.5], [-5.0, -3.0], [-4.0, 6.0], [10.0, 10.0], [12.0, -14.56]]) c2, len2 = GO.centroid_and_length(l2) c2_from_LG = LG.centroid(l2) - @test GI.x(c2) ≈ GI.x(c2_from_LG) - @test GI.y(c2) ≈ GI.y(c2_from_LG) + @test c2[1] ≈ GI.x(c2_from_LG) + @test c2[2] ≈ GI.y(c2_from_LG) @test len2 ≈ 59.3090856788928 # Test that non-closed line strings throw an error for centroid_and_area @@ -22,15 +22,15 @@ r1 = LG.LinearRing([[0.0, 0.0], [3456.0, 7894.0], [6291.0, 1954.0], [0.0, 0.0]]) c3 = GO.centroid(r1) c3_from_LG = LG.centroid(r1) - @test GI.x(c3) ≈ GI.x(c3_from_LG) - @test GI.y(c3) ≈ GI.y(c3_from_LG) - + @test c3[1] ≈ GI.x(c3_from_LG) + @test c3[2] ≈ GI.y(c3_from_LG) end @testset "Polygons" begin # Basic rectangle p1 = AG.fromWKT("POLYGON((0 0, 10 0, 10 10, 0 10, 0 0))") c1 = GO.centroid(p1) + c1 .≈ (5, 5) @test GI.x(c1) ≈ 5 @test GI.y(c1) ≈ 5 @@ -41,8 +41,8 @@ end ]]) c2, area2 = GO.centroid_and_area(p2) c2_from_LG = LG.centroid(p2) - @test GI.x(c2) ≈ GI.x(c2_from_LG) - @test GI.y(c2) ≈ GI.y(c2_from_LG) + @test c2[1] ≈ GI.x(c2_from_LG) + @test c2[2] ≈ GI.y(c2_from_LG) @test area2 ≈ LG.area(p2) # Randomly generated polygon with lots of sides @@ -55,8 +55,8 @@ end ]]) c3, area3 = GO.centroid_and_area(p3) c3_from_LG = LG.centroid(p3) - @test GI.x(c3) ≈ GI.x(c3_from_LG) - @test GI.y(c3) ≈ GI.y(c3_from_LG) + @test c3[1] ≈ GI.x(c3_from_LG) + @test c3[2] ≈ GI.y(c3_from_LG) @test area3 ≈ LG.area(p3) # Polygon with one hole @@ -66,8 +66,8 @@ end ]) c4, area4 = GO.centroid_and_area(p4) c4_from_LG = LG.centroid(p4) - @test GI.x(c4) ≈ GI.x(c4_from_LG) - @test GI.y(c4) ≈ GI.y(c4_from_LG) + @test c4[1] ≈ GI.x(c4_from_LG) + @test c4[2] ≈ GI.y(c4_from_LG) @test area4 ≈ LG.area(p4) # Polygon with two holes @@ -78,8 +78,8 @@ end ]) c5 = GO.centroid(p5) c5_from_LG = LG.centroid(p5) - @test GI.x(c5) ≈ GI.x(c5_from_LG) - @test GI.y(c5) ≈ GI.y(c5_from_LG) + @test c5[1] ≈ GI.x(c5_from_LG) + @test c5[2] ≈ GI.y(c5_from_LG) # Same polygon as P5 but using a GeoInterface polygon p6 = GI.Polygon([ @@ -88,9 +88,7 @@ end [(-3.0, -9.0), (3.0, -9.0), (3.0, -8.5), (-3.0, -8.5), (-3.0, -9.0)], ]) c6 = GO.centroid(p6) - @test GI.x(c6) ≈ GI.x(c5) - @test GI.y(c6) ≈ GI.y(c5) - + @test all(c5 .≈ c6) end @testset "MultiPolygons" begin # Combine poylgons made above @@ -106,7 +104,7 @@ end ]) c1, area1 = GO.centroid_and_area(m1) c1_from_LG = LG.centroid(m1) - @test GI.x(c1) ≈ GI.x(c1_from_LG) - @test GI.y(c1) ≈ GI.y(c1_from_LG) + @test c1[1] ≈ GI.x(c1_from_LG) + @test c1[2] ≈ GI.y(c1_from_LG) @test area1 ≈ LG.area(m1) end \ No newline at end of file