Skip to content

Commit e78da94

Browse files
committed
msiner's golang#76 proposed to official package
1 parent fcc0957 commit e78da94

File tree

2 files changed

+34
-3
lines changed

2 files changed

+34
-3
lines changed

s2/polygon.go

+25-3
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,15 @@ type Polygon struct {
5757
// hasHoles tracks if this polygon has at least one hole.
5858
hasHoles bool
5959

60+
// hasInconsistentLoopOrientation is true if PolygonFromOrientedLoops() was
61+
// called and the given loops had inconsistent orientations (i.e., it is not
62+
// possible to construct a polygon such that the interior is on the left-hand
63+
// side of all loops). We need to remember this error so that it can be
64+
// returned later by Validate(), since it is not possible to detect this error
65+
// once the polygon has been initialized. This field is not preserved by
66+
// Encode/Decode.
67+
hasInconsistentLoopOrientations bool
68+
6069
// numVertices keeps the running total of all of the vertices of the contained loops.
6170
numVertices int
6271

@@ -180,6 +189,19 @@ func PolygonFromOrientedLoops(loops []*Loop) *Polygon {
180189
}
181190
}
182191

192+
// Verify that the original loops had consistent shell/hole orientations.
193+
// Each original loop L should have been inverted if and only if it now
194+
// represents a hole.
195+
for _, l := range p.Loops() {
196+
if (containedOrigin[l] != l.ContainsOrigin()) != l.IsHole() {
197+
// There is no point in saving the loop index because the error is a
198+
// property of the entire set of loops. In general, there is no way to
199+
// determine which ones are incorrect.
200+
p.hasInconsistentLoopOrientations = true
201+
break
202+
}
203+
}
204+
183205
return p
184206
}
185207

@@ -468,9 +490,9 @@ func (p *Polygon) Validate() error {
468490
// }
469491

470492
// Check whether initOriented detected inconsistent loop orientations.
471-
// if p.hasInconsistentLoopOrientations {
472-
// return fmt.Errorf("inconsistent loop orientations detected")
473-
// }
493+
if p.hasInconsistentLoopOrientations {
494+
return fmt.Errorf("inconsistent loop orientations detected")
495+
}
474496

475497
// Finally, verify the loop nesting hierarchy.
476498
return p.findLoopNestingError()

s2/polygon_test.go

+9
Original file line numberDiff line numberDiff line change
@@ -386,6 +386,15 @@ func TestPolygonIsValidLoopNestingInvalid(t *testing.T) {
386386
}
387387
}
388388

389+
func TestPolygonIsValidInconsistentOrientations(t *testing.T) {
390+
const iters = 1000
391+
392+
for iter := 0; iter < iters; iter++ {
393+
loops := generatePolygonConcentricTestLoops(2+randomUniformInt(5), 3)
394+
checkPolygonInvalid(t, "inconsistent loop orientations", loops, true, nil)
395+
}
396+
}
397+
389398
// TODO(roberts): Implement remaining validity tests.
390399
// IsValidTests
391400
// TestUnitLength

0 commit comments

Comments
 (0)