diff --git a/geom/attr_test.go b/geom/attr_test.go index 04a59fa0..51ad2c52 100644 --- a/geom/attr_test.go +++ b/geom/attr_test.go @@ -1586,3 +1586,51 @@ func TestSummary(t *testing.T) { }) } } + +func TestPolygonDumpRings(t *testing.T) { + for i, tc := range []struct { + inputWKT string + wantRingWKTs []string + }{ + { + "POLYGON EMPTY", + nil, + }, + { + "POLYGON ((0 0,0 1,1 0,0 0))", + []string{"LINESTRING(0 0,0 1,1 0,0 0)"}, + }, + { + "POLYGON ((0 0,0 4,4 0,0 0),(1 1,1 2,2 1,1 1))", + []string{ + "LINESTRING(0 0,0 4,4 0,0 0)", + "LINESTRING(1 1,1 2,2 1,1 1)", + }, + }, + } { + t.Run(strconv.Itoa(i), func(t *testing.T) { + input := geomFromWKT(t, tc.inputWKT).MustAsPolygon() + wantRings := make([]LineString, len(tc.wantRingWKTs)) + for j, wantRingWKT := range tc.wantRingWKTs { + wantRings[j] = geomFromWKT(t, wantRingWKT).MustAsLineString() + } + + gotRings := input.DumpRings() + + expectIntEq(t, len(gotRings), len(wantRings)) + for j := range wantRings { + expectGeomEq(t, + gotRings[j].AsGeometry(), + wantRings[j].AsGeometry(), + ) + } + + // Ensure that we actually got copy of the slice's backing array + // rather than just a copy of its header: + otherRings := input.DumpRings() + if len(otherRings) > 0 { + expectTrue(t, &gotRings[0] != &otherRings[0]) + } + }) + } +} diff --git a/geom/type_polygon.go b/geom/type_polygon.go index cfe1f2f9..ad34c835 100644 --- a/geom/type_polygon.go +++ b/geom/type_polygon.go @@ -620,6 +620,15 @@ func (p Polygon) DumpCoordinates() Sequence { return seq } +// DumpRings returns a copy of the Polygon's rings as a slice of LineStrings. +// If the Polygon is empty, then the slice will have length zero. Otherwise, +// the slice will consist of the exterior ring, followed by any interior rings. +func (p Polygon) DumpRings() []LineString { + tmp := make([]LineString, len(p.rings)) + copy(tmp, p.rings) + return tmp +} + // Summary returns a text summary of the Polygon following a similar format to https://postgis.net/docs/ST_Summary.html. func (p Polygon) Summary() string { numPoints := p.DumpCoordinates().Length()