polygonal
This commit is contained in:
parent
86bfef30d5
commit
550cb5ef73
1 changed files with 40 additions and 13 deletions
|
@ -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
|
||||||
|
|
Loading…
Reference in a new issue