-
Notifications
You must be signed in to change notification settings - Fork 187
Fix Loop contains which contained a missing negation and add test cases. #156
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: master
Are you sure you want to change the base?
Changes from all commits
a87035b
ed507ae
39caea7
69704c9
12554af
55902bd
4f7483f
e141dbf
c597829
5836f6f
7c7e52c
6df2625
0f45e9d
6937d18
aeac25e
6570bb0
46b2465
c8d0c06
a09abef
cc51d8b
61272a9
f996d29
63e5133
9a1faa3
05836a2
86e764d
a1c1dd6
e2d2c5f
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -1612,12 +1612,12 @@ func (l *loopCrosser) hasCrossing(ai, bi *rangeIterator) bool { | |
return false | ||
} | ||
|
||
// containsCenterMatches reports if the clippedShapes containsCenter boolean corresponds | ||
// to the crossing target type given. (This is to work around C++ allowing false == 0, | ||
// true == 1 type implicit conversions and comparisons) | ||
func containsCenterMatches(a *clippedShape, target crossingTarget) bool { | ||
return (!a.containsCenter && target == crossingTargetDontCross) || | ||
(a.containsCenter && target == crossingTargetCross) | ||
// containsCenterMatches reports if the clippedShapes containsCenter boolean | ||
// corresponds to the crossing target type given. (This is to work around C++ | ||
// allowing false == 0, true == 1 type implicit conversions and comparisons) | ||
func containsCenterMatches(a bool, target crossingTarget) bool { | ||
return (!a && target == crossingTargetDontCross) || | ||
(a && target == crossingTargetCross) | ||
} | ||
|
||
// hasCrossingRelation reports whether given two iterators positioned such that | ||
|
@@ -1626,7 +1626,8 @@ func containsCenterMatches(a *clippedShape, target crossingTarget) bool { | |
// is an edge crossing, a wedge crossing, or a point P that matches both relations | ||
// crossing targets. This function advances both iterators past ai.cellID. | ||
func (l *loopCrosser) hasCrossingRelation(ai, bi *rangeIterator) bool { | ||
aClipped := ai.it.IndexCell().shapes[0] | ||
// ABSL_DCHECK(ai->id().contains(bi->id())); | ||
aClipped := ai.clipped() | ||
if aClipped.numEdges() != 0 { | ||
// The current cell of A has at least one edge, so check for crossings. | ||
if l.hasCrossing(ai, bi) { | ||
|
@@ -1636,8 +1637,9 @@ func (l *loopCrosser) hasCrossingRelation(ai, bi *rangeIterator) bool { | |
return false | ||
} | ||
|
||
if containsCenterMatches(aClipped, l.aCrossingTarget) { | ||
// The crossing target for A is not satisfied, so we skip over these cells of B. | ||
if !containsCenterMatches(ai.containsCenter(), l.aCrossingTarget) { | ||
// The crossing target for A is not satisfied, so we skip over | ||
// these cells of B. | ||
bi.seekBeyond(ai) | ||
ai.next() | ||
return false | ||
|
@@ -1647,8 +1649,7 @@ func (l *loopCrosser) hasCrossingRelation(ai, bi *rangeIterator) bool { | |
// worth iterating through the cells of B to see whether any cell | ||
// centers also satisfy the crossing target for B. | ||
for bi.cellID() <= ai.rangeMax { | ||
bClipped := bi.it.IndexCell().shapes[0] | ||
if containsCenterMatches(bClipped, l.bCrossingTarget) { | ||
if containsCenterMatches(bi.containsCenter(), l.bCrossingTarget) { | ||
return true | ||
} | ||
bi.next() | ||
|
@@ -1701,16 +1702,16 @@ func hasCrossingRelation(a, b *Loop, relation loopRelation) bool { | |
return true | ||
} | ||
} else { | ||
// The A and B cells are the same. Since the two cells | ||
// have the same center point P, check whether P satisfies | ||
// the crossing targets. | ||
aClipped := ai.it.IndexCell().shapes[0] | ||
bClipped := bi.it.IndexCell().shapes[0] | ||
if containsCenterMatches(aClipped, ab.aCrossingTarget) && | ||
containsCenterMatches(bClipped, ab.bCrossingTarget) { | ||
// The A and B cells are the same. Since the two | ||
// cells have the same center point P, check | ||
// whether P satisfies the crossing targets. | ||
if containsCenterMatches(ai.containsCenter(), ab.aCrossingTarget) && | ||
containsCenterMatches(bi.containsCenter(), ab.bCrossingTarget) { | ||
return true | ||
} | ||
// Otherwise test all the edge crossings directly. | ||
aClipped := ai.it.IndexCell().shapes[0] | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Why not use your new ai/bi.clipped() function? |
||
bClipped := bi.it.IndexCell().shapes[0] | ||
if aClipped.numEdges() > 0 && bClipped.numEdges() > 0 && ab.cellCrossesCell(aClipped, bClipped) { | ||
return true | ||
} | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -805,6 +805,31 @@ func TestLoopContainsMatchesCrossingSign(t *testing.T) { | |
} | ||
|
||
func TestLoopRelations(t *testing.T) { | ||
|
||
// Test cases from https://github.com/golang/geo/issues/77 and 78 | ||
// relating to loop relations contains giving wrong result some cases. | ||
containingLoop := LoopFromPoints([]Point{ | ||
PointFromLatLng(LatLngFromDegrees(-38.0, -135.0)), | ||
PointFromLatLng(LatLngFromDegrees(-38.0, 149.0)), | ||
PointFromLatLng(LatLngFromDegrees(77.0, 149.0)), | ||
PointFromLatLng(LatLngFromDegrees(77.0, -135.0)), | ||
}) | ||
|
||
innerTile := LoopFromPoints([]Point{ | ||
PointFromLatLng(LatLngFromDegrees(37.99616267972809, 13.007812500000002)), | ||
PointFromLatLng(LatLngFromDegrees(37.99616267972809, 13.359375000000002)), | ||
PointFromLatLng(LatLngFromDegrees(38.272819658516866, 13.359375000000002)), | ||
PointFromLatLng(LatLngFromDegrees(38.272819658516866, 13.007812500000002)), | ||
}) | ||
|
||
// +0.2 lat +0.2 lon from innerTile | ||
extendedTile := LoopFromPoints([]Point{ | ||
PointFromLatLng(LatLngFromDegrees(37.99616267972809, 13.007812500000002)), | ||
PointFromLatLng(LatLngFromDegrees(37.99616267972809, 13.559375000000002)), | ||
PointFromLatLng(LatLngFromDegrees(38.472819658516866, 13.559375000000002)), | ||
PointFromLatLng(LatLngFromDegrees(38.472819658516866, 13.007812500000002)), | ||
}) | ||
|
||
tests := []struct { | ||
a, b *Loop | ||
contains bool // A contains B | ||
|
@@ -1332,6 +1357,18 @@ func TestLoopRelations(t *testing.T) { | |
contains: true, | ||
sharedEdge: true, | ||
}, | ||
// https://github.com/golang/geo/issues/77 and 78 | ||
// These cases failed prior to this fix. | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Remove this comment ("this fix" means the pull request, not the file). I'd suggest a different comment. Something like: |
||
{ | ||
a: containingLoop, | ||
b: innerTile, | ||
contains: true, | ||
}, | ||
{ | ||
a: containingLoop, | ||
b: extendedTile, | ||
contains: true, | ||
}, | ||
} | ||
|
||
for _, test := range tests { | ||
|
@@ -1817,3 +1854,17 @@ func BenchmarkLoopContainsPoint(b *testing.B) { | |
vertices *= 2 | ||
} | ||
} | ||
|
||
// TODO(rsned): Differences from C++ | ||
// TEST_F(S2LoopTestBase, CompressedEncodedLoopDecodesApproxEqual) { | ||
// TEST_F(S2LoopTestBase, DistanceMethods) { | ||
// TEST_F(S2LoopTestBase, GetAreaAccuracy) { | ||
// TEST_F(S2LoopTestBase, GetAreaConsistentWithSign) { | ||
// TEST_F(S2LoopTestBase, MakeRegularLoop) { | ||
// TEST(S2Loop, BoundaryNear) { | ||
// TEST(S2Loop, BoundsForLoopContainment) { | ||
// TEST(S2LoopDeathTest, IsValidDetectsInvalidLoops) { | ||
// TEST(S2Loop, DefaultLoopIsInvalid) { | ||
// TEST(S2Loop, EmptyFullLossyConversions) { | ||
// TEST(S2Loop, EncodeDecode) { | ||
// TEST(S2Loop, LoopRelations2) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why not make
a
type*rangeIterator
? That way you can ensure that the boolean means what you intend it to mean. Alternatively, consider renaminga
tocontainsCenter
.