polygonal

This commit is contained in:
Josh Deprez 2021-09-10 12:27:10 +10:00
parent 86bfef30d5
commit 550cb5ef73

View file

@ -1,13 +1,40 @@
package geom package geom
import "image" import (
"image"
"math"
)
// PolygonContains reports if a polygon contains a point. The polygon must be in // PolygonExtrema returns the most northerly, easterly, southerly, and westerly
// clockwise order if +Y is pointing upwards, or anticlockwise if +Y is pointing // points (north is in the -Y direction, east is in the +X direction).
// downwards. func PolygonExtrema(polygon []image.Point) (e, n, w, s image.Point) {
func PolygonContains(polygon []image.Point, p image.Point) bool { e.X = math.MinInt
for i, q := range polygon { n.Y = math.MaxInt
r := polygon[(i+1)%len(polygon)] w.X = math.MaxInt
s.Y = math.MinInt
for _, p := range polygon {
if p.X > e.X {
e = p
}
if p.X < w.X {
w = p
}
if p.Y > s.Y {
s = p
}
if p.Y < n.Y {
n = p
}
}
return e, n, w, s
}
// PolygonContains reports if a convex polygon contains a point. The polygon
// must be in clockwise order if +Y is pointing upwards, or anticlockwise if +Y
// is pointing downwards.
func PolygonContains(convex []image.Point, p image.Point) bool {
for i, q := range convex {
r := convex[(i+1)%len(convex)]
// ∆(p q r) should have positive signed area // ∆(p q r) should have positive signed area
q, r = q.Sub(p), r.Sub(p) q, r = q.Sub(p), r.Sub(p)
if q.X*r.Y > r.X*q.Y { if q.X*r.Y > r.X*q.Y {
@ -17,14 +44,14 @@ func PolygonContains(polygon []image.Point, p image.Point) bool {
return true return true
} }
// PolygonRectOverlap reports if a polygon overlaps a rectangle. // PolygonRectOverlap reports if a convex polygon overlaps a rectangle.
func PolygonRectOverlap(polygon []image.Point, rect image.Rectangle) bool { func PolygonRectOverlap(convex []image.Point, rect image.Rectangle) bool {
if polygon[0].In(rect) { if convex[0].In(rect) {
return true return true
} }
// Check if any vertex of the rect is inside the polygon. // Check if any vertex of the rect is inside the polygon.
if PolygonContains(polygon, rect.Min) { if PolygonContains(convex, rect.Min) {
return true return true
} }
@ -37,8 +64,8 @@ func PolygonRectOverlap(polygon []image.Point, rect image.Rectangle) bool {
// Since rect is an axis-aligned rectangle, we only need vertical and // Since rect is an axis-aligned rectangle, we only need vertical and
// horizontal line intersection tests. // horizontal line intersection tests.
// Walk each edge of polygon. // Walk each edge of polygon.
for i, p := range polygon { for i, p := range convex {
q := polygon[(i+1)%len(polygon)] q := convex[(i+1)%len(convex)]
// Pretend the edge is a rectangle. Exclude those that don't overlap. // Pretend the edge is a rectangle. Exclude those that don't overlap.
if !rect.Overlaps(image.Rectangle{p, q}.Canon()) { if !rect.Overlaps(image.Rectangle{p, q}.Canon()) {
continue continue