private static IEnumerable <Vector3> ArcVertices(IArc arc, IArc nextArc, Sweepline sweepline) { if (arc.LeftNeighbour == arc.Site) { var azimuths = DrawingUtilities.AnglesInRange(0, 2 * Mathf.PI, NumberOfVerticesPerArc); var vertices = azimuths.Select(azimuth => PointOnEllipse(arc, azimuth, sweepline)).ToList(); return(vertices); } else if (Mathf.Approximately((float)arc.Site.Priority, (float)sweepline.Priority)) { var intersection = arc.PointOfIntersection(sweepline).ToUnityVector3(); var site = arc.Site.Position.ToUnityVector3(); var downArc = DrawingUtilities.VerticesOnGeodesic(intersection, site, NumberOfVerticesPerArc); var upArc = DrawingUtilities.VerticesOnGeodesic(site, intersection, NumberOfVerticesPerArc); var vertices = downArc.Concat(upArc); return(vertices); } else { var leftLimit = DrawingUtilities.AzimuthOf(arc.LeftIntersection(sweepline).ToUnityVector3()); var rightLimit = DrawingUtilities.AzimuthOf(nextArc.LeftIntersection(sweepline).ToUnityVector3()); var azimuths = DrawingUtilities.AnglesInRange(leftLimit, rightLimit, NumberOfVerticesPerArc); var vertices = azimuths.Select(azimuth => PointOnEllipse(arc, azimuth, sweepline)).ToList(); return(vertices); } }
public void LeftIntersection_WhenSweeplinePassesThroughLowerOfTheTwoFocii_ShouldReturnDirectionOfThatFocus (Arc arc, Sweepline sweepline) { arc.LeftNeighbour.Position = Utilities.VectorAt(114, 94); arc.Site.Position = Utilities.VectorAt(96, 77); sweepline = Utilities.SweeplineAt(121); // Fixture setup var focus = arc.Site.Position; var leftFocus = arc.LeftNeighbour.Position; var lowerFocus = focus.Z < leftFocus.Z ? focus : leftFocus; var directionOfLowerFocus = AngleUtilities.EquatorialDirection(lowerFocus); sweepline.Z = lowerFocus.Z; // Exercise system var directionOfLeftIntersection = arc.LeftIntersection(sweepline); // Verify outcome var failureString = String.Format("Direction of left intersection: {0},\n", directionOfLeftIntersection); Assert.True(Vector.AlmostEqual(directionOfLowerFocus, directionOfLeftIntersection, Tolerance), failureString); // Teardown }
public void LeftIntersection_WhenFociiAreAboveSweepline_ShouldReturnAVectorWhichWhenMappedToAPointOnTheArcIsEquidistantFromBothSites (Arc arc, Sweepline sweepline) { // Fixture setup var focus = arc.Site.Position; var leftFocus = arc.LeftNeighbour.Position; // Exercise system var directionOfIntersection = arc.LeftIntersection(sweepline); var intersection = arc.PointAt(directionOfIntersection, sweepline); // Verify outcome var distanceFromSite = Trig.InverseCosine(focus.ScalarMultiply(intersection)); var distanceFromLeftSite = Trig.InverseCosine(leftFocus.ScalarMultiply(intersection)); var failureString = String.Format("Direction of intersection: {0},\n" + "Intersection: {1},\n" + "Distance from site: {2},\n" + "Distance from left site: {3}", directionOfIntersection, intersection, distanceFromSite, distanceFromLeftSite); Assert.True(Number.AlmostEqual(distanceFromSite, distanceFromLeftSite, Tolerance), failureString); // Teardown }
public void LeftIntersection_OfLowerFocusWhenSweeplineIsBelowIt_ShouldBeInOrderLeftIntersectionThenSiteThenRightIntersection (Arc arc, Sweepline sweepline) { // Fixture setup var dualArc = new Arc { LeftNeighbour = arc.Site, Site = arc.LeftNeighbour }; var lowerArc = arc.Site.Position.Z < dualArc.Site.Position.Z ? arc : dualArc; var higherArc = arc.Site.Position.Z >= dualArc.Site.Position.Z ? arc : dualArc; var directionOfLowerFocus = AngleUtilities.EquatorialDirection(lowerArc.Site.Position); // Exercise system var directionOfLeftIntersection = lowerArc.LeftIntersection(sweepline); var directionOfRightIntersection = higherArc.LeftIntersection(sweepline); // Verify outcome var areInOrder = ArcOrderer.AreInOrder(directionOfLeftIntersection, directionOfLowerFocus, directionOfRightIntersection); var failureString = String.Format("Direction of left intersection: {0},\n" + "Direction of right intersection: {1},\n", directionOfLeftIntersection, directionOfRightIntersection); Assert.True(areInOrder, failureString); // Teardown }
private static GameObject InitializeSweeplineObject(Sweepline sweepline) { var vertices = SweeplineVertices(sweepline); var gameObject = DrawingUtilities.CreateLineObject("Sweepline", vertices, "SweeplineMaterial"); return(gameObject); }
private static Vector3 VertexOnSweepline(Sweepline sweepline, float azimuth) { var z = (float)sweepline.Z; var x = (float)Math.Sqrt(1 - z * z) * Mathf.Cos(azimuth); var y = (float)-Math.Sqrt(1 - z * z) * Mathf.Sin(azimuth); return(new Vector3(x, y, z)); }
public void Customize(IFixture fixture) { var randomZ = (-1.0 + 2.0 * new Random().NextDouble()); var randomColatitude = Trig.InverseCosine(randomZ); var sweepline = new Sweepline { Colatitude = randomColatitude }; fixture.Inject(sweepline); }
private static Vector3[] SweeplineVertices(Sweepline sweepline) { if (Math.Abs(sweepline.Z) >= 1) { return(new Vector3[0]); } var azimuths = DrawingUtilities.AnglesInRange(0, 2 * Mathf.PI, NumberOfVertices); var vertices = azimuths.Select(azimuth => VertexOnSweepline(sweepline, azimuth)).ToArray(); return(vertices); }
public static LinkedList <LineSegmentIntersection> FindIntersections(IEnumerable <DCEL_HalfEdge> lineSegments) { LinkedList <LineSegmentIntersection> result = new LinkedList <LineSegmentIntersection>(); Sweepline sweepline = new Sweepline(); RBTreeMap <EventPoint, LinkedList <Segment> > eventQueue = new RBTreeMap <EventPoint, LinkedList <Segment> >((x, y) => x.CompareTo(y)); var segments = lineSegments.Where(lineSegment => lineSegment.Origin.Position != lineSegment.Destination.Position) .Select(lineSegment => new Segment(lineSegment, sweepline)); //segments = FixOverlappingSegments(segments); foreach (var segment in segments) { var node = eventQueue.Find(segment.Upper); LinkedList <Segment> upperList = (node != null ? node.Value : null); if (upperList == null) { upperList = new LinkedList <Segment>(); eventQueue.Add(new RBTreeMapNode <EventPoint, LinkedList <Segment> >(new EventPoint(segment.Upper), upperList)); } upperList.AddLast(segment); if (!eventQueue.ContainsKey(segment.Lower)) { eventQueue.Add(new RBTreeMapNode <EventPoint, LinkedList <Segment> >(new EventPoint(segment.Lower), new LinkedList <Segment>())); } } RBTreeSet <Segment> status = new RBTreeSet <Segment>((x, y) => x.CompareTo(y)); while (eventQueue.Count > 0) { var pair = eventQueue.MinNode; eventQueue.RemoveMin(); EventPoint nextEventPoint = pair.Key; LinkedList <Segment> upperList = pair.Value; LineSegmentIntersection reportedIntersection; HandleEventPoint(nextEventPoint, upperList, sweepline, eventQueue, status, out reportedIntersection); if (reportedIntersection != null) { result.AddLast(reportedIntersection); } } return(result); }
public void LeftIntersection_WhenLeftNeigbourIsSameAsArcSite_ShouldReturnDirectionOfFocus (Arc arc, Sweepline sweepline) { // Fixture setup arc.LeftNeighbour = arc.Site; var directionOfFocus = AngleUtilities.EquatorialDirection(arc.Site.Position); // Exercise system var directionOfLeftIntersection = arc.LeftIntersection(sweepline); // Verify outcome var failureString = String.Format("Direction of left intersection: {0},\n", directionOfLeftIntersection); Assert.True(Vector.AlmostEqual(directionOfFocus, directionOfLeftIntersection, Tolerance), failureString); // Teardown }
public void PointAt_ShouldReturnAPointWithTheSameAzimuthAsTheArgument (Arc arc, Vector3 vector, Sweepline sweepline) { // Fixture setup // Exercise system var point = arc.PointAt(vector, sweepline); // Verify outcome var argumentAzimuth = Trig.InverseTangentFromRational(vector.Y, vector.X); var resultAzimuth = Trig.InverseTangentFromRational(point.Y, point.X); var failureString = String.Format("Argument azimuth was {0} \nResult azimuth was {1}", argumentAzimuth, resultAzimuth); Assert.True(Number.AlmostEqual(argumentAzimuth, resultAzimuth, Tolerance), failureString); // Teardown }
public void Vectors_ShouldAllBeAboveSweepline(List <Vector3> vectors, Sweepline anonymousSweepline) { // Fixture setup // Exercise system // Verify outcome var expectedResult = Trig.Cosine(anonymousSweepline.Colatitude); foreach (var vector in vectors) { var result = vector[2]; var failureString = String.Format("Had Z {0}, expected Z was {1}", result, expectedResult); Assert.True(result >= expectedResult, failureString); } // Teardown }
public void PointAt_ShouldReturnAPointEquidistantFromTheSweeplineAndTheFocus (Arc arc, Vector3 vector, Sweepline sweepline) { // Fixture setup var focus = arc.Site.Position; // Exercise system var point = arc.PointAt(vector, sweepline); // Verify outcome var distanceToFocus = Trig.InverseCosine(point.ScalarMultiply(focus)); var distanceToSweepline = Math.Abs(sweepline.Colatitude - Trig.InverseCosine(point.Z)); var failureString = String.Format("Distance to focus was {0}\nDistance to sweepline was {1}", distanceToFocus, distanceToSweepline); Assert.True(Number.AlmostEqual(distanceToFocus, distanceToSweepline, Tolerance), failureString); // Teardown }
public void PointAt_IfSweeplinePassesThroughFocusAndVectorIsNotAtSameAzimuthAsFocus_ShouldReturnNorthPole (Arc arc, Vector3 vector) { // Fixture setup var sweepline = new Sweepline { Z = arc.Site.Position.Z }; var northPole = new Vector3(0, 0, 1); // Exercise system var point = arc.PointAt(vector, sweepline); // Verify outcome var failureString = String.Format("Point was {0}", point); Assert.True(Vector.AlmostEqual(northPole, point, Tolerance), failureString); // Teardown }
public Segment(DCEL_HalfEdge source, Sweepline sweepline) { Source = source; EventPoint origin = new EventPoint(source.Origin); EventPoint destination = new EventPoint(source.Destination); int comp = origin.CompareTo(destination); if (comp < 0) { Upper = origin; Lower = destination; } else if (comp > 0) { Upper = destination; Lower = origin; } else { throw new InvalidOperationException("Trivial line segment."); } Sweepline = sweepline; }
public void LeftIntersection_WhenSweeplinePassesThroughBothFocuses_ShouldReturnEquatorialMidpointOfFocii (Arc arc, Sweepline sweepline) { // Fixture setup var colatitudeOfFocus = arc.Site.Position.SphericalCoordinates().Colatitude; var azimuthOfFocus = arc.Site.Position.SphericalCoordinates().Azimuth; var azimuthOfLeftFocus = arc.LeftNeighbour.Position.SphericalCoordinates().Azimuth; arc.Site.Position = new SphericalCoords(colatitudeOfFocus, azimuthOfFocus).CartesianCoordinates(); arc.LeftNeighbour.Position = new SphericalCoords(colatitudeOfFocus, azimuthOfLeftFocus).CartesianCoordinates(); // Exercise system var directionOfLeftIntersection = arc.LeftIntersection(sweepline); // Verify outcome var equatorialMidpoint = AngleUtilities.EquatorialMidpoint(arc.LeftNeighbour.Position, arc.Site.Position); var failureString = String.Format("Direction of left intersection: {0},\n", directionOfLeftIntersection); Assert.True(Vector.AlmostEqual(equatorialMidpoint, directionOfLeftIntersection, Tolerance), failureString); // Teardown }
private static void HandleEventPoint(EventPoint eventPoint, LinkedList <Segment> upperList, Sweepline sweepline, RBTreeMap <EventPoint, LinkedList <Segment> > eventQueue, RBTreeSet <Segment> status, out LineSegmentIntersection reportedIntersection) { reportedIntersection = null; sweepline.IncidentEventPoint = eventPoint; sweepline.BeforeEventPoint = true; //1. //upperList brought in as part of the input. None of its elements currently intersect the sweepline! //2. IEnumerable <Segment> middleList, lowerList; status.FindRange(Segment.CompareSweeplineIntersectionToCurrentEventPoint).Select(node => node.Key) .Partition(Segment.LowerIsCurrentEventPoint, out lowerList, out middleList); //3. if (upperList.Count + middleList.Count() + lowerList.Count() > 1) { //4. reportedIntersection = new LineSegmentIntersection( eventPoint.Position, upperList.Concat(middleList).Concat(lowerList).Select(segment => segment.Source)); } //5. foreach (var lower in lowerList) { status.Remove(lower); } foreach (var middle in middleList) { status.Remove(middle); } sweepline.BeforeEventPoint = false; //6. foreach (var middle in middleList) { status.Add(new RBTreeSetNode <Segment>(middle)); } foreach (var upper in upperList) { status.Add(new RBTreeSetNode <Segment>(upper)); } //7. //Just a comment in the book //8. if (upperList.IsEmpty() && middleList.IsEmpty()) { //9. var predecessorNode = status.FindMax(Segment.IntersectsSweeplineLeftOfEventPoint); var successorNode = status.FindMin(Segment.IntersectsSweeplineRightOfEventPoint); //10. if (predecessorNode != null && successorNode != null) { FindNewEvent(predecessorNode.Key, successorNode.Key, eventPoint, eventQueue); } } else { //11. var leftmostIntersectingNode = status.FindMin(Segment.IntersectsSweeplineRightOfEventPoint); //14. var rightmostIntersectingNode = status.FindMax(Segment.IntersectsSweeplineLeftOfEventPoint); //12. var leftmostPredecessorNode = leftmostIntersectingNode.Predecessor; //15. var rightmostSuccessorNode = rightmostIntersectingNode.Successor; //13. if (leftmostPredecessorNode != null) { //RemoveFutureEvent(leftmostPredecessor, rightmostIntersecting, eventPoint, eventQueue); FindNewEvent(leftmostPredecessorNode.Key, leftmostIntersectingNode.Key, eventPoint, eventQueue); } //16. if (rightmostSuccessorNode != null) { //RemoveFutureEvent(leftmostIntersecting, rightmostSuccessor, eventPoint, eventQueue); FindNewEvent(rightmostIntersectingNode.Key, rightmostSuccessorNode.Key, eventPoint, eventQueue); } } }
public SweeplineDrawer(Sweepline sweepline) { _sweepline = sweepline; _gameObject = InitializeSweeplineObject(sweepline); }
public static Vector3 PointOnEllipse(IArc arc, float azimuth, Sweepline sweepline) { var direction = new Generator.Vector3(Trig.Cosine(azimuth), Trig.Sine(azimuth), 0); return(arc.PointAt(direction, sweepline).ToUnityVector3()); }