public static List <SegmentIntersection> GetClosestPointsBetweenPolygons(Vector3[] polygonVerticesA, Vector3[] polygonVerticesB) { // Returns a list of intersections as Vector2s. Or, in the case of no intersection the vertex in polygonVerticesA closest to polygonB List <SegmentIntersection> intersections = new List <SegmentIntersection>(); float minDist = Mathf.Infinity; SegmentIntersection closestIntersection = new SegmentIntersection(false, polygonVerticesA[0], Mathf.Infinity, polygonVerticesA[0]); for (int i = 0; i < polygonVerticesA.Length - 1; i++) { for (int j = 0; j < polygonVerticesB.Length - 1; j++) { SegmentIntersection intersection = GetLineIntersection(polygonVerticesA[i], polygonVerticesA[i + 1], polygonVerticesB[j], polygonVerticesB[j + 1]); if (!intersection.OnSegment) { // Not on segment // Consider possibility that this is the closest segment interaction // if (intersection.MinDist < minDist) { minDist = intersection.MinDist; closestIntersection = intersection; } continue; } intersections.Add(intersection); } } if (intersections.Count == 0) { intersections.Add(closestIntersection); // No intersections. Take vertex in A closest to B } return(intersections); }
public void CanDetermineOppositeDirection() { Line3D line1 = new Line3D(new Pnt3D(0, 0, 0), new Pnt3D(5, 0, 0)); Line3D line2 = new Line3D(new Pnt3D(2, 0, 0), new Pnt3D(0, 0, 0)); const double tolerance = 0.01; var intersection = SegmentIntersection.CalculateIntersectionXY(1, 2, line1, line2, tolerance); Assert.True(intersection.HasLinearIntersection); Assert.True(intersection.LinearIntersectionInOppositeDirection); intersection = SegmentIntersection.CalculateIntersectionXY(2, 1, line2, line1, tolerance); Assert.True(intersection.HasLinearIntersection); Assert.True(intersection.LinearIntersectionInOppositeDirection); // Special case: The source end is very far away and deviates more than the tolerance from the target straigh: line1.SetEndPoint(new Pnt3D(100, 0.02, 0)); intersection = SegmentIntersection.CalculateIntersectionXY(1, 2, line1, line2, tolerance); Assert.True(intersection.HasLinearIntersection); Assert.True(intersection.LinearIntersectionInOppositeDirection); }
public void CanGetSegmentIntersectionsXY() { var line1 = new Line3D(new Pnt3D(0, 5, 0), new Pnt3D(10, 5, 0)); var line2 = new Line3D(new Pnt3D(6, 0, 0), new Pnt3D(6, 10, 0)); SegmentIntersection intersection = SegmentIntersection.CalculateIntersectionXY( 0, 0, line1, line2, 0.01); Assert.IsTrue(intersection.HasIntersection); Assert.AreEqual(0.6, intersection.SingleInteriorIntersectionFactor); line2 = new Line3D(new Pnt3D(10, 0, 0), new Pnt3D(10, 10, 0)); intersection = SegmentIntersection.CalculateIntersectionXY(0, 0, line1, line2, 0.01); Assert.IsTrue(intersection.HasIntersection); Assert.IsNull(intersection.SingleInteriorIntersectionFactor); Assert.IsTrue(intersection.SourceEndIntersects); line2 = new Line3D(new Pnt3D(10, 0, 0), new Pnt3D(10, 5, 0)); intersection = SegmentIntersection.CalculateIntersectionXY(0, 0, line1, line2, 0.01); Assert.IsTrue(intersection.HasIntersection); Assert.IsNull(intersection.SingleInteriorIntersectionFactor); Assert.IsTrue(intersection.SourceEndIntersects); }
private static SegmentIntersection AssertLinearIntersection( Line3D line1, Line3D line2, double tolerance, bool?oppositeDirection = null) { var intersection = SegmentIntersection.CalculateIntersectionXY(0, 0, line1, line2, tolerance); var intersectionTargetIsSource = SegmentIntersection.CalculateIntersectionXY(0, 0, line2, line1, tolerance); Assert.True(intersection.HasLinearIntersection); Assert.True(intersectionTargetIsSource.HasLinearIntersection); Assert.True(intersection.IsPotentialPseudoLinearIntersection( line1, line2, tolerance)); Assert.True( intersectionTargetIsSource.IsPotentialPseudoLinearIntersection( line2, line1, tolerance)); if (oppositeDirection != null) { if (oppositeDirection.Value) { Assert.True(intersection.LinearIntersectionInOppositeDirection); Assert.True(intersectionTargetIsSource.LinearIntersectionInOppositeDirection); } else { Assert.False(intersection.LinearIntersectionInOppositeDirection); Assert.False(intersectionTargetIsSource.LinearIntersectionInOppositeDirection); } } return(intersection); }
public static List <SegmentIntersection> GetPolygonIntersections(Vector3[] polygonVerticesA, Vector3[] polygonVerticesB) { // Should add some validation here List <SegmentIntersection> intersections = new List <SegmentIntersection>(); for (int i = 0; i < polygonVerticesA.Length - 1; i++) { for (int j = 0; j < polygonVerticesB.Length - 1; j++) { SegmentIntersection intersection = GetLineIntersection(polygonVerticesA[i], polygonVerticesA[i + 1], polygonVerticesB[j], polygonVerticesB[j + 1]); if (!intersection.OnSegment) { continue; } intersections.Add(intersection); } } return(intersections); }
public static float GetDistance(Segment seg, List <Segment> segments) { var minDist = seg.From.DistanceTo(seg.To); for (int i = 0; i < segments.Count; i++) { var s = segments[i]; var p = SegmentIntersection.FindIntersection(seg.From, seg.To, s.From, s.To); if (p != null) { var dist = p.Value.DistanceTo(seg.From); if (dist < minDist) { minDist = dist; } return(minDist); } } return(minDist); }
public void CanDetermineCorrectOrientationForPseudoLinearIntersecion() { // The linear intersection can be somewhat un-intuitive if the end points are witin the tolerance to the // other line but just outside the tolerance to the other end point. Line3D line1 = new Line3D(new Pnt3D(0, 0, 0), new Pnt3D(5, 0, 0)); Line3D line2 = new Line3D(new Pnt3D(0.011, 0, 0), new Pnt3D(-10, 10, 0)); const double tolerance = 0.01; SegmentIntersection intersection = AssertLinearIntersection(line1, line2, tolerance, true); double startAlongSource; Pnt3D sourceStart = intersection.GetLinearIntersectionStart(line1, out startAlongSource); double endAlongSource; Pnt3D sourceEnd = intersection.GetLinearIntersectionEnd(line1, out endAlongSource); line2.ReverseOrientation(); AssertLinearIntersection(line1, line2, tolerance, false); line2 = new Line3D(new Pnt3D(0.009, -0.008, 0), new Pnt3D(-10, 10, 0)); AssertLinearIntersection(line1, line2, tolerance, true); line2.ReverseOrientation(); AssertLinearIntersection(line1, line2, tolerance, false); // Really acute: line2 = new Line3D(new Pnt3D(0.03, 0.0, 0), new Pnt3D(-10, 1, 0)); AssertLinearIntersection(line1, line2, tolerance, true); line2.ReverseOrientation(); AssertLinearIntersection(line1, line2, tolerance, false); }
private List <Vector2> GetInnerStageVertex() { int numPoints = shapeCreator.shapes[stageShape].points.Count; List <Vector2> intersectionsList = new List <Vector2>(); intersection = gameObject.GetComponent <SegmentIntersection>(); Vector3[] stageMeshVertices = new Vector3[numPoints]; Vector2 intersectionVector = new Vector2(); for (int i = 0; i < numPoints; i++) { stageMeshVertices[i] = shapeCreator.shapes[stageShape].points[i]; } //foreach shadowMeshes pair of vertices we check each stageMeshVertices for (int i = 0; i < shadowCaster.shadowMeshes.Count; i++) { for (int k = 0; k < stageMeshVertices.Length; k++) { int k2 = 0; if (!(k == stageMeshVertices.Length - 1)) { k2 = k + 1; } Vector2 stageVert1 = new Vector2(stageMeshVertices[k].x, stageMeshVertices[k].z); Vector2 stageVert2 = new Vector2(stageMeshVertices[k2].x, stageMeshVertices[k2].z); Vector2 vec2Player = new Vector2(player.position.x, player.position.z); //Vector2 rayFromPlayer = (stageVert1 - vec2Player)*0.99f; for (int shape = stageShape + 1; shape < shapeCreator.shapes.Count; shape++) { for (int p = 0; p < shapeCreator.shapes[shape].points.Count; p++) { Vector3 point1 = shapeCreator.shapes[shape].points[p]; Vector3 point2 = new Vector3(); if (!(p == shapeCreator.shapes[shape].points.Count - 1)) { point2 = shapeCreator.shapes[shape].points[p + 1]; } else { point2 = shapeCreator.shapes[shape].points[0]; } Vector2 pointVert1 = new Vector2(point1.x, point1.z); Vector2 pointVert2 = new Vector2(point2.x, point2.z); Vector2 tempIntersectionVector = new Vector2(); if (intersection.LineIntersection(vec2Player, stageVert1, pointVert1, pointVert2, ref tempIntersectionVector)) { p = shapeCreator.shapes[shape].points.Count; allShadowVertices.Add(new ShadowVertex(stageShape, k, stageVert1, 0)); } } } ShadowRange shadowRange = new ShadowRange(); shadowRange.meshIndex = i; shadowRange.wallSegmentIndex = k; for (int j = 0; j < shadowCaster.shadowMeshes[i].vertices.Length; j++) { int j2 = 0; if (!(j == shadowCaster.shadowMeshes[i].vertices.Length - 1)) { j2 = j + 1; } Vector2 shadowVert1 = new Vector2(shadowCaster.shadowMeshes[i].vertices[j].x, shadowCaster.shadowMeshes[i].vertices[j].z); Vector2 shadowVert2 = new Vector2(shadowCaster.shadowMeshes[i].vertices[j2].x, shadowCaster.shadowMeshes[i].vertices[j2].z); if (intersection.LineIntersection(stageVert1, stageVert2, shadowVert1, shadowVert2, ref intersectionVector)) { intersectionsList.Add(intersectionVector); float distanceAlongStageEdge = (intersectionVector - stageVert1).magnitude / (stageVert2 - stageVert1).magnitude; shadowRange.rangePointPairs.Add(new RangePointPair(distanceAlongStageEdge, intersectionVector)); //Debug.Log(intersectionVector); /* * GameObject sphere = GameObject.CreatePrimitive(PrimitiveType.Sphere); * Destroy(sphere, 0.01f); * sphere.transform.position = new Vector3(intersectionVector.x, 0, intersectionVector.y); * sphere.transform.localScale = Vector3.one * (intersectionEdgeCount*0.01f + 0.05f); */ } } shadowRanges.Add(shadowRange); } } return(intersectionsList); }
public void CanGetLinearIntersectionInteriorXY() { var line1 = new Line3D(new Pnt3D(0, 0, 0), new Pnt3D(10, 10, 0)); var line2 = new Line3D(new Pnt3D(6, 6, 3), new Pnt3D(8, 8, 3)); SegmentIntersection intersection = SegmentIntersection.CalculateIntersectionXY( 0, 7, line1, line2, 0.01); Assert.IsTrue(intersection.HasIntersection); Assert.IsNull(intersection.SingleInteriorIntersectionFactor); Assert.IsTrue(intersection.HasLinearIntersection); Assert.IsFalse(intersection.SegmentsAreEqualInXy); Assert.IsFalse(intersection.SourceStartIntersects); Assert.IsFalse(intersection.SourceEndIntersects); Assert.IsTrue(intersection.TargetStartIntersects); Assert.IsTrue(intersection.TargetEndIntersects); Assert.IsFalse(intersection.LinearIntersectionInOppositeDirection); Assert.IsTrue(intersection.HasSourceInteriorIntersection); Assert.AreEqual(0.6, intersection.GetFirstIntersectionAlongSource()); double startFactorAlongSource; Assert.IsTrue(new Pnt3D(6, 6, 0).Equals( intersection.GetLinearIntersectionStart( line1, out startFactorAlongSource))); Assert.AreEqual(0.6, startFactorAlongSource); double endFactorAlongSource; Assert.IsTrue(new Pnt3D(8, 8, 0).Equals( intersection.GetLinearIntersectionEnd( line1, out endFactorAlongSource))); Assert.AreEqual(0.8, endFactorAlongSource); Assert.AreEqual(0.6, intersection.GetLinearIntersectionStartFactor(true)); Assert.AreEqual(0.8, intersection.GetLinearIntersectionEndFactor(true)); Assert.IsTrue(new Pnt3D(6, 6, 3).Equals( intersection.GetLinearIntersectionStartOnTarget(line2))); Assert.IsTrue(new Pnt3D(8, 8, 3).Equals( intersection.GetLinearIntersectionEndOnTarget(line2))); Assert.IsTrue(new Line3D( new Pnt3D(6, 6, 0), new Pnt3D(8, 8, 0) ).Equals(intersection.TryGetIntersectionLine(line1))); Assert.AreEqual(0, intersection.GetRatioAlongTargetLinearStart()); Assert.AreEqual(1.0, intersection.GetRatioAlongTargetLinearEnd()); // Now the source is inside the target and reversed: line1.ReverseOrientation(); intersection = SegmentIntersection.CalculateIntersectionXY( 0, 7, line2, line1, 0.01); Assert.IsTrue(intersection.HasIntersection); Assert.IsNull(intersection.SingleInteriorIntersectionFactor); Assert.IsTrue(intersection.HasLinearIntersection); Assert.IsFalse(intersection.SegmentsAreEqualInXy); Assert.IsTrue(intersection.SourceStartIntersects); Assert.IsTrue(intersection.SourceEndIntersects); Assert.IsFalse(intersection.TargetStartIntersects); Assert.IsFalse(intersection.TargetEndIntersects); Assert.IsTrue(intersection.LinearIntersectionInOppositeDirection); Assert.IsTrue(intersection.HasSourceInteriorIntersection); Assert.AreEqual(0, intersection.GetFirstIntersectionAlongSource()); Assert.IsTrue(new Pnt3D(6, 6, 3).Equals( intersection.GetLinearIntersectionStart( line2, out startFactorAlongSource))); Assert.AreEqual(0, startFactorAlongSource); Assert.IsTrue(new Pnt3D(8, 8, 3).Equals( intersection.GetLinearIntersectionEnd( line2, out endFactorAlongSource))); Assert.AreEqual(1, endFactorAlongSource); Assert.AreEqual(0, intersection.GetLinearIntersectionStartFactor(true)); Assert.AreEqual(1, intersection.GetLinearIntersectionEndFactor(true)); Assert.IsTrue(new Pnt3D(6, 6, 0).Equals( intersection.GetLinearIntersectionStartOnTarget(line1))); Assert.IsTrue(new Pnt3D(8, 8, 0).Equals( intersection.GetLinearIntersectionEndOnTarget(line1))); Assert.IsTrue(new Line3D( new Pnt3D(6, 6, 3), new Pnt3D(8, 8, 3) ).Equals(intersection.TryGetIntersectionLine(line2))); Assert.AreEqual(0.4, intersection.GetRatioAlongTargetLinearStart()); Assert.AreEqual(0.2, intersection.GetRatioAlongTargetLinearEnd()); }