Skip to content

Commit

Permalink
Fix area calculation for polygons with holes
Browse files Browse the repository at this point in the history
  • Loading branch information
twpayne committed Aug 18, 2024
1 parent 8e46749 commit 3ad9aea
Show file tree
Hide file tree
Showing 3 changed files with 45 additions and 12 deletions.
9 changes: 2 additions & 7 deletions flat.go
Original file line number Diff line number Diff line change
Expand Up @@ -265,13 +265,8 @@ func doubleArea1(flatCoords []float64, offset, end, stride int) float64 {

func doubleArea2(flatCoords []float64, offset int, ends []int, stride int) float64 {
var doubleArea float64
for i, end := range ends {
da := doubleArea1(flatCoords, offset, end, stride)
if i == 0 {
doubleArea = da
} else {
doubleArea -= da
}
for _, end := range ends {
doubleArea += doubleArea1(flatCoords, offset, end, stride)
offset = end
}
return doubleArea
Expand Down
25 changes: 20 additions & 5 deletions geom_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ func aliases(x, y []float64) bool {
}

func TestArea(t *testing.T) {
for _, tc := range []struct {
for i, tc := range []struct {
g interface {
Area() float64
}
Expand Down Expand Up @@ -115,7 +115,7 @@ func TestArea(t *testing.T) {
{
g: NewPolygon(XY).MustSetCoords([][]Coord{
{{-3, -2}, {-1, 4}, {6, 1}, {3, 10}, {-4, 9}, {-3, -2}},
{{0, 6}, {2, 6}, {2, 8}, {0, 8}, {0, 6}},
{{0, 6}, {0, 8}, {2, 8}, {2, 6}, {0, 6}},
}),
want: 56,
},
Expand Down Expand Up @@ -151,7 +151,7 @@ func TestArea(t *testing.T) {
g: NewMultiPolygon(XY).MustSetCoords([][][]Coord{
{
{{-3, -2}, {-1, 4}, {6, 1}, {3, 10}, {-4, 9}, {-3, -2}},
{{0, 6}, {2, 6}, {2, 8}, {0, 8}, {0, 6}},
{{0, 6}, {0, 8}, {2, 8}, {2, 6}, {0, 6}},
},
}),
want: 56,
Expand All @@ -163,13 +163,28 @@ func TestArea(t *testing.T) {
},
{
{{-3, -2}, {-1, 4}, {6, 1}, {3, 10}, {-4, 9}, {-3, -2}},
{{0, 6}, {2, 6}, {2, 8}, {0, 8}, {0, 6}},
{{0, 6}, {0, 8}, {2, 8}, {2, 6}, {0, 6}},
},
}),
want: 57,
},
{
g: NewPolygon(XY).MustSetCoords([][]Coord{
{{0, 0}, {1, 0}, {1, 1}, {0, 1}, {0, 0}},
}),
want: 1,
},
{
g: NewPolygon(XY).MustSetCoords([][]Coord{
{{0, 0}, {3, 0}, {3, 3}, {0, 3}, {0, 0}},
{{1, 1}, {1, 2}, {2, 2}, {2, 1}, {1, 1}},
}),
want: 8,
},
} {
assert.Equal(t, tc.want, tc.g.Area())
t.Run(strconv.Itoa(i), func(t *testing.T) {
assert.Equal(t, tc.want, tc.g.Area())
})
}
}

Expand Down
23 changes: 23 additions & 0 deletions polygon_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -116,3 +116,26 @@ func TestPolygonSetSRID(t *testing.T) {
assert.Equal(t, 4326, NewPolygon(NoLayout).SetSRID(4326).SRID())
assert.Equal(t, 4326, Must(SetSRID(NewPolygon(NoLayout), 4326)).SRID())
}

func TestPolygonArea(t *testing.T) {
for i, tc := range []struct {
polygon *Polygon
expected float64
}{
{
polygon: NewPolygon(XY).MustSetCoords([][]Coord{{{0, 0}, {1, 0}, {1, 1}, {0, 1}, {0, 0}}}),
expected: 1,
},
{
polygon: NewPolygon(XY).MustSetCoords([][]Coord{
{{0, 0}, {3, 0}, {3, 3}, {0, 3}, {0, 0}},
{{1, 1}, {1, 2}, {2, 2}, {2, 1}, {1, 1}},
}),
expected: 8,
},
} {
t.Run(strconv.Itoa(i), func(t *testing.T) {
assert.Equal(t, tc.expected, tc.polygon.Area())
})
}
}

0 comments on commit 3ad9aea

Please sign in to comment.