/// <summary> /// Calculates the intersection of a ray with a segment. Returns the result as the lambdas of the intersection /// point along the ray and the segment. If there is no intersection returns double.NaN in both lambdas.</summary> public static void RayWithSegment(ref EdgeD ray, ref EdgeD segment, out double rayL, out double segmentL) { Intersect.LineWithLine(ref ray, ref segment, out rayL, out segmentL); if (!double.IsNaN(rayL) && ((rayL < 0) || (segmentL < 0) || (segmentL > 1))) { rayL = segmentL = double.NaN; } }
private void AssertRayWithCircle(double frX, double frY, double toX, double toY, double cX, double cY, double cR, double expL1, double expL2) { EdgeD ray = new EdgeD(frX, frY, toX, toY); CircleD cir = new CircleD(cX, cY, cR); double l1, l2; Intersect.RayWithCircle(ref ray, ref cir, out l1, out l2); Assert.AreEqual(expL1, l1, 0.001); Assert.AreEqual(expL2, l2, 0.001); }
private void AssertLineWithCircle(double frX, double frY, double toX, double toY, double cX, double cY, double cR, double expL1, double expL2) { EdgeD lin = new EdgeD(frX, frY, toX, toY); CircleD cir = new CircleD(cX, cY, cR); double l1, l2; Intersect.LineWithCircle(ref lin, ref cir, out l1, out l2); Assert.AreEqual(MinTO(expL1, expL2), MinTO(l1, l2), 0.001); Assert.AreEqual(MaxTO(expL1, expL2), MaxTO(l1, l2), 0.001); }
/// <summary> /// Finds intersections between a ray and a rectangle. Returns the lambdas of intersections, if any, or NaN /// otherwise. Guarantees that lambda1 < lambda2, and if only one of them is NaN then it's lambda2. Lambda is /// such that ray.Start + lambda * (ray.End - ray.Start) gives the point of intersection.</summary> public static void RayWithRectangle(ref EdgeD ray, ref RectangleD rect, out double lambda1, out double lambda2) { double lambda, dummy; bool done1 = false; lambda1 = lambda2 = double.NaN; for (int i = 0; i < 4; i++) { EdgeD segment; switch (i) { case 0: segment = new EdgeD(rect.Left, rect.Top, rect.Right, rect.Top); break; case 1: segment = new EdgeD(rect.Right, rect.Top, rect.Right, rect.Bottom); break; case 2: segment = new EdgeD(rect.Right, rect.Bottom, rect.Left, rect.Bottom); break; case 3: segment = new EdgeD(rect.Left, rect.Bottom, rect.Left, rect.Top); break; default: throw new InternalErrorException("fsvxhfhj"); // unreachable } Intersect.RayWithSegment(ref ray, ref segment, out lambda, out dummy); if (!double.IsNaN(lambda)) { if (!done1) { lambda1 = lambda; done1 = true; } else if (lambda != lambda1) { if (lambda > lambda1) { lambda2 = lambda; } else { lambda2 = lambda1; lambda1 = lambda; } return; } } } }
/// <summary>Returns a polygon formed by intersecting an arbitrary polygon with a convex polygon.</summary> public static PolygonD PolygonWithConvexPolygon(PolygonD mainPoly, PolygonD clipPoly) { if (mainPoly.Vertices.Count <= 2 || clipPoly.Vertices.Count <= 2) { throw new InvalidOperationException("One of the polygons has 2 vertices or fewer."); } var result = new List <PointD>(); var resultVertices = mainPoly.Vertices.ToList(); foreach (var clipEdge in clipPoly.ToEdges()) { var newVertices = new List <PointD>(); var vertexStart = resultVertices[resultVertices.Count - 1]; foreach (var vertexEnd in resultVertices) { if (clipEdge.CrossZ(vertexStart) > 0) { if (clipEdge.CrossZ(vertexEnd) > 0) { newVertices.Add(vertexEnd); } else { newVertices.Add(Intersect.LineWithLine(clipEdge, new EdgeD(vertexStart, vertexEnd))); } } else { if (clipEdge.CrossZ(vertexEnd) > 0) { newVertices.Add(Intersect.LineWithLine(clipEdge, new EdgeD(vertexStart, vertexEnd))); newVertices.Add(vertexEnd); } } vertexStart = vertexEnd; } resultVertices = newVertices; } return(new PolygonD(resultVertices)); }
/// <summary>Returns true if this bounding box intersects with the specified bounding box.</summary> public bool IntersectsWithBoundingBox(BoundingBoxD box) { return(Intersect.BoundingBoxWithBoundingBox(ref this, ref box)); }
/// <summary>Returns true if this bounding box intersects with the specified ray.</summary> public bool IntersectsWithRay(EdgeD ray) { return(Intersect.RayWithBoundingBox(ref ray, ref this)); }