package poly // This implementation of the raycast algorithm test if a point is // to the left of a line, or on the segment line. Otherwise it is // assumed that the point is outside of the segment line. type rayres int func (r rayres) String() string { switch r { default: return "unknown" case out: return "out" case left: return "left" case on: return "on" } } const ( out = rayres(0) // outside of the segment. left = rayres(1) // to the left of the segment on = rayres(2) // on segment or vertex, special condition ) func raycast(p, a, b Point) rayres { if a.Y == b.Y { // A and B share the same Y plane. if a.X == b.X { // AB is just a point. if p.X == a.X && p.Y == a.Y { return on } return out } // AB is a horizontal line. if p.Y != a.Y { // P is not on same Y plane as A and B. return out } // P is on same Y plane as A and B if a.X < b.X { if p.X >= a.X && p.X <= b.X { return on } if p.X < a.X { return left } } else { if p.X >= b.X && p.X <= a.X { return on } if p.X < b.X { return left } } return out } if a.X == b.X { // AB is a vertical line. if a.Y > b.Y { // A is above B if p.Y > a.Y || p.Y < b.Y { return out } } else { // B is above A if p.Y > b.Y || p.Y < a.Y { return out } } if p.X == a.X { return on } if p.X < a.X { return left } return out } // AB is an angled line if a.Y > b.Y { // swap A and B so that A is below B. a.X, a.Y, b.X, b.Y = b.X, b.Y, a.X, a.Y } if p.Y < a.Y || p.Y > b.Y { return out } if a.X < b.X { if p.X < a.X { return left } if p.X > b.X { return out } } else { if p.X < b.X { return left } if p.X > a.X { return out } } if (p.X == a.X && p.Y == a.Y) || (p.X == b.X && p.Y == b.Y) { // P is on a vertex. return on } v1 := (p.Y - a.Y) / (p.X - a.X) v2 := (b.Y - a.Y) / (b.X - a.X) if v1-v2 == 0 { // P is on a segment return on } if v1 >= v2 { return left } return out }