Skip to content

Commit

Permalink
Merge pull request #440 from peterstace/eliminate-copy-in-force-cw-ccw
Browse files Browse the repository at this point in the history
Eliminate copy in ForceCW and ForceCCW
  • Loading branch information
peterstace committed Feb 4, 2022
2 parents 04f7c21 + c4429b7 commit 84871fd
Show file tree
Hide file tree
Showing 5 changed files with 60 additions and 0 deletions.
36 changes: 36 additions & 0 deletions geom/perf_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import (
"fmt"
"math"
"math/rand"
"strconv"
"testing"

"github.com/peterstace/simplefeatures/geom"
Expand Down Expand Up @@ -421,3 +422,38 @@ func BenchmarkMultiLineStringIsSimpleManyLineStrings(b *testing.B) {
})
}
}

func BenchmarkForceCWandForceCCW(b *testing.B) {
for i, tc := range []struct {
wkt string
geoType GeometryType
isCW bool
isCCW bool
note string
}{
{"POLYGON((0 0,0 5,5 5,5 0,0 0))", TypePolygon, true, false, "CW"},
{"POLYGON((1 1,3 1,2 2,2 4,1 1))", TypePolygon, false, true, "CCW"},
{"POLYGON((0 0,0 5,5 5,5 0,0 0), (1 1,3 1,2 2,2 4,1 1))", TypePolygon, true, false, "outer CW inner CCW"},
{"POLYGON((0 0,5 0,5 5,0 5,0 0), (1 1,1 2,2 2,2 1,1 1))", TypePolygon, false, true, "outer CCW inner CW"},
{"MULTIPOLYGON(((40 40, 45 30, 20 45, 40 40)),((20 35, 45 20, 30 5, 10 10, 10 30, 20 35),(30 20, 20 25, 20 15, 30 20)))", TypeMultiPolygon, true, false, "all CW"},
{"MULTIPOLYGON(((40 40, 20 45, 45 30, 40 40)),((20 35, 10 30, 10 10, 30 5, 45 20, 20 35),(30 20, 20 15, 20 25, 30 20)))", TypeMultiPolygon, false, true, "all CCW"},
{"GEOMETRYCOLLECTION(POLYGON((0 0,0 5,5 5,5 0,0 0)), MULTIPOLYGON(((40 40, 45 30, 20 45, 40 40)),((20 35, 45 20, 30 5, 10 10, 10 30, 20 35),(30 20, 20 25, 20 15, 30 20))))", TypeGeometryCollection, true, false, "all CW"},
} {
g := geomFromWKT(b, tc.wkt)
for _, correct := range map[string]bool{
"correct": true,
"incorrect": false,
} {
b.Run(strconv.Itoa(i), func(b *testing.B) {
b.ResetTimer()
for i := 0; i < b.N; i++ {
if tc.isCW && correct || tc.isCCW && !correct {
g.ForceCW()
} else if tc.isCCW && correct || tc.isCW && !correct {
g.ForceCCW()
}
}
})
}
}
}
6 changes: 6 additions & 0 deletions geom/type_geometry.go
Original file line number Diff line number Diff line change
Expand Up @@ -765,13 +765,19 @@ func (g Geometry) PointOnSurface() Point {
// clockwise orientation and any inner rings in a counter-clockwise
// orientation. Non-areal geometrys are returned as is.
func (g Geometry) ForceCW() Geometry {
if g.IsCW() {
return g
}
return g.forceOrientation(true)
}

// ForceCCW returns the equivalent Geometry that has its exterior rings in a
// counter-clockwise orientation and any inner rings in a clockwise
// orientation. Non-areal geometrys are returned as is.
func (g Geometry) ForceCCW() Geometry {
if g.IsCCW() {
return g
}
return g.forceOrientation(false)
}

Expand Down
6 changes: 6 additions & 0 deletions geom/type_geometry_collection.go
Original file line number Diff line number Diff line change
Expand Up @@ -433,6 +433,9 @@ func (c GeometryCollection) PointOnSurface() Point {
// exterior rings clockwise and interior rings counter-clockwise). Geometries
// other that Polygons and MultiPolygons are unchanged.
func (c GeometryCollection) ForceCW() GeometryCollection {
if c.IsCW() {
return c
}
return c.forceOrientation(true)
}

Expand All @@ -441,6 +444,9 @@ func (c GeometryCollection) ForceCW() GeometryCollection {
// exterior rings counter-clockwise and interior rings clockwise). Geometries
// other that Polygons and MultiPolygons are unchanged.
func (c GeometryCollection) ForceCCW() GeometryCollection {
if c.IsCCW() {
return c
}
return c.forceOrientation(false)
}

Expand Down
6 changes: 6 additions & 0 deletions geom/type_multi_polygon.go
Original file line number Diff line number Diff line change
Expand Up @@ -436,13 +436,19 @@ func (m MultiPolygon) PointOnSurface() Point {
// clockwise orientation and any inner rings in a counter-clockwise
// orientation.
func (m MultiPolygon) ForceCW() MultiPolygon {
if m.IsCW() {
return m
}
return m.forceOrientation(true)
}

// ForceCCW returns the equivalent MultiPolygon that has its exterior rings in
// a counter-clockwise orientation and any inner rings in a clockwise
// orientation.
func (m MultiPolygon) ForceCCW() MultiPolygon {
if m.IsCCW() {
return m
}
return m.forceOrientation(false)
}

Expand Down
6 changes: 6 additions & 0 deletions geom/type_polygon.go
Original file line number Diff line number Diff line change
Expand Up @@ -536,13 +536,19 @@ func (p Polygon) PointOnSurface() Point {
// clockwise orientation and any inner rings in a counter-clockwise
// orientation.
func (p Polygon) ForceCW() Polygon {
if p.IsCW() {
return p
}
return p.forceOrientation(true)
}

// ForceCCW returns the equivalent Polygon that has its exterior ring in a
// counter-clockwise orientation and any inner rings in a clockwise
// orientation.
func (p Polygon) ForceCCW() Polygon {
if p.IsCCW() {
return p
}
return p.forceOrientation(false)
}

Expand Down

0 comments on commit 84871fd

Please sign in to comment.