using OpenNest.Geometry; using OpenNest.Math; using System.Collections.Generic; namespace OpenNest; /// /// Static helpers for testing entity-splitline intersections. /// public static class SplitLineIntersect { /// /// Finds the intersection point between an entity and a split line. /// Returns null if no intersection or the entity doesn't straddle the split line. /// public static Vector? FindIntersection(Entity entity, SplitLine sl) { if (!CrossesSplitLine(entity, sl)) return null; var bbox = entity.BoundingBox; var margin = 1.0; // Create a line at the split position spanning the entity's bbox extent (with margin) Line splitLine; if (sl.Axis == CutOffAxis.Vertical) splitLine = sl.ToLine(bbox.Bottom - margin, bbox.Top + margin); else splitLine = sl.ToLine(bbox.Left - margin, bbox.Right + margin); switch (entity.Type) { case EntityType.Line: var line = (Line)entity; if (Intersect.Intersects(line, splitLine, out var pt)) return pt; return null; case EntityType.Arc: var arc = (Arc)entity; if (Intersect.Intersects(arc, splitLine, out var pts)) return pts.Count > 0 ? pts[0] : null; return null; default: return null; } } /// /// Returns true if the entity's bounding box straddles the split line, /// meaning it extends to both sides of the split position (not just touching). /// public static bool CrossesSplitLine(Entity entity, SplitLine sl) { var bbox = entity.BoundingBox; if (sl.Axis == CutOffAxis.Vertical) return bbox.Left < sl.Position - Tolerance.Epsilon && bbox.Right > sl.Position + Tolerance.Epsilon; else return bbox.Bottom < sl.Position - Tolerance.Epsilon && bbox.Top > sl.Position + Tolerance.Epsilon; } /// /// Returns -1 if the point is below/left of the split line, /// +1 if above/right, or 0 if on the line (within tolerance). /// public static int SideOf(Vector pt, SplitLine sl) { var value = sl.Axis == CutOffAxis.Vertical ? pt.X : pt.Y; var diff = value - sl.Position; if (System.Math.Abs(diff) <= Tolerance.Epsilon) return 0; return diff < 0 ? -1 : 1; } }