Skip to content

Commit 2d428c1

Browse files
authored
rect.CapBound: Fix for tall and wide rects (#233)
For tall (>90 degrees) and wide (>180 degrees) lat/lng rects, rect.CapBound returned an incorrect cap that didn't contain the full rect. The function intends to return a polar cap in this case, but due to an apparent typo (2 * Pi instead of Pi), returned a cap centered at the center of the rect instead. This fix has recently been applied to C++ and Java in google3, but has not been exported to those github repos yet.
1 parent 5906ab3 commit 2d428c1

File tree

2 files changed

+11
-1
lines changed

2 files changed

+11
-1
lines changed

s2/rect.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -247,7 +247,7 @@ func (r Rect) CapBound() Cap {
247247
// maximum cap size is achieved at one of the rectangle vertices. For
248248
// rectangles that are larger than 180 degrees, we punt and always return a
249249
// bounding cap centered at one of the two poles.
250-
if math.Remainder(r.Lng.Hi-r.Lng.Lo, 2*math.Pi) >= 0 && r.Lng.Hi-r.Lng.Lo < 2*math.Pi {
250+
if math.Remainder(r.Lng.Hi-r.Lng.Lo, 2*math.Pi) >= 0 && r.Lng.Hi-r.Lng.Lo <= math.Pi {
251251
midCap := CapFromPoint(PointFromLatLng(r.Center())).AddPoint(PointFromLatLng(r.Lo())).AddPoint(PointFromLatLng(r.Hi()))
252252
if midCap.Height() < poleCap.Height() {
253253
return midCap

s2/rect_test.go

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -395,6 +395,16 @@ func TestRectCapBound(t *testing.T) {
395395
rectFromDegrees(-30, -150, -10, 50),
396396
CapFromCenterAngle(Point{r3.Vector{X: 0, Y: 0, Z: -1}}, s1.Angle(80)*s1.Degree),
397397
},
398+
{
399+
// Longitude span > 180 degrees and latitude span > 90 degrees. This results
400+
// in a polar cap that is larger than the "midpoint cap" (centered at the
401+
// center of the rect and containing the vertices), but is nonetheless the
402+
// correct result. The "midpoint cap" must not be returned since it doesn't
403+
// contain the entire rect due the rect being wider than 180 degrees.
404+
// In this example, (-34, 49) is in the rect but not the midpoint cap.
405+
rectFromDegrees(-60, -150, 70, 50),
406+
CapFromCenterAngle(Point{r3.Vector{X: 0, Y: 0, Z: 1}}, s1.Angle(150)*s1.Degree),
407+
},
398408
}
399409
for _, test := range tests {
400410
if got := test.r.CapBound(); !test.want.ApproxEqual(got) {

0 commit comments

Comments
 (0)