// assumes p is ccw ordered, edge is counted as interior (neither case) public static bool SegmentIntersectsNonDegenerateConvexPolygonInterior(IntLineSegment2 s, IntVector2[] p) { #if DEBUG if (Clockness(p[0], p[1], p[2]) == Clk.Clockwise) { throw new BadInputException("p not ccw"); } if (p.Length < 3) { throw new BadInputException("len(p) < 3"); } #endif var(x, y) = s; bool xInterior = true, yInterior = true; IntVector2 a = p[p.Length - 1], b; int i = 0; for (; i < p.Length && (xInterior || yInterior); i++, a = b) { b = p[i]; var abx = Clockness(a, b, x); var aby = Clockness(a, b, y); if (abx == Clk.Clockwise && aby == Clk.Clockwise) { return(false); } xInterior &= abx != Clk.Clockwise; yInterior &= aby != Clk.Clockwise; if (abx == (Clk)(-(int)aby) || abx == Clk.Neither || aby == Clk.Neither) { // The below is equivalent to: // // (a, b) places x, y onto opposite half-planes. // // Intersect if (x, y) places a, b onto opposite half-planes. // var xya = Clockness(x, y, a); // var xyb = Clockness(x, y, b); // if (xya != xyb || xya == Clk.Neither || xyb == Clk.Neither) return true; if (IntLineSegment2.Intersects(a.X, a.Y, b.X, b.Y, x.X, x.Y, y.X, y.Y)) { return(true); } } } for (; i < p.Length; i++, a = b) { b = p[i]; if (IntLineSegment2.Intersects(a.X, a.Y, b.X, b.Y, x.X, x.Y, y.X, y.Y)) { return(true); } } return(xInterior && yInterior); }
public static bool SegmentIntersectsConvexPolygonInterior(IntLineSegment2 s, IntVector2[] p) { if (p.Length == 1) { return(false); } else if (p.Length == 2) { return(s.Intersects(new IntLineSegment2(p[0], p[1]))); } else { return(SegmentIntersectsNonDegenerateConvexPolygonInterior(s, p)); } }
public static PolygonContainmentResult SegmentInPolygon(this PolyNode node, IntLineSegment2 query) { var bvh = node.visibilityGraphNodeData.ContourBvh; if (bvh != null) { if (bvh.Intersects(ref query)) { return(PolygonContainmentResult.IntersectsPolygon); } } else { var last = node.Contour[node.Contour.Count - 1]; var q1 = query.First; var q2 = query.Second; for (var i = 0; i < node.Contour.Count; i++) { var current = node.Contour[i]; if ((current == q1 && last == q2) || (current == q2 && last == q1)) { return(PolygonContainmentResult.OnPolygon); } if (IntLineSegment2.Intersects(current.X, current.Y, last.X, last.Y, q1.X, q1.Y, q2.X, q2.Y)) { return(PolygonContainmentResult.IntersectsPolygon); } last = current; } } // Query segment isn't on-contour or intersecting the contour, so it's either fully in or out. var endpointContainment = Clipper.PointInPolygon(query.First, node.Contour); if (endpointContainment == PolygonContainmentResult.OnPolygon) { return(PolygonContainmentResult.IntersectsPolygon); } return(endpointContainment); }