private static void MakeEnterExitList(CircularLinkedList <Vector2> subject, CircularLinkedList <Vector2> clip, Dictionary <Vector2, Pair <Vector2> > intersections, CircularLinkedList <Vector2> entering, CircularLinkedList <Vector2> exiting, Polygon ClipP, Polygon SbujectP) { LinkedListNode <Vector2> curr = subject.First; do { if (intersections.ContainsKey(curr.Value)) { bool isEntering = Vector2Cross(subject.NextOrFirst(curr).Value.X - subject.PreviousOrLast(curr).Value.X, subject.NextOrFirst(curr).Value.Y - subject.PreviousOrLast(curr).Value.Y, intersections[curr.Value].Second.X - intersections[curr.Value].First.X, intersections[curr.Value].Second.Y - intersections[curr.Value].First.Y) < 0; if (isEntering) { entering.AddLast(curr.Value); } else { exiting.AddLast(curr.Value); } } curr = subject.NextOrFirst(curr); } while (curr != subject.First); }
public CircularLinkedList <T> Reverse() { CircularLinkedList <T> temp = new CircularLinkedList <T>(); foreach (var current in this) { temp.AddFirst(current); } return(temp); }
public static List <Polygon> GetClippedPolygons(Polygon Clip, Polygon Subject) { List <Polygon> output = new List <Polygon>(); CircularLinkedList <Vector2> SubjectL = new CircularLinkedList <Vector2>(); CircularLinkedList <Vector2> ClipL = new CircularLinkedList <Vector2>(); //todo check if subject inside clip bool AllPointsInside = true; for (int i = 0; i < Subject.points.Count; i++) { if (!Clip.IsInside(Subject.points[i])) { AllPointsInside = false; break; } } if (AllPointsInside) { output.Add(Subject); return(output); } for (int i = 0; i < Clip.points.Count; i++) { ClipL.AddLast(new Vector2(Clip.points[i].X, Clip.points[i].Y)); } for (int i = 0; i < Subject.points.Count; i++) { SubjectL.AddLast(new Vector2(Subject.points[i].X, Subject.points[i].Y)); } List <CircularLinkedList <Vector2> > result = (List <CircularLinkedList <Vector2> >)WeilerAtherton.Process(SubjectL, ClipL, Operation.Intersect, Clip, Subject); for (int i = 0; i < result.Count; i++) { output.Add(new Polygon() { Completed = true }); List <Vector2> temp = result[i].ToList <Vector2>(); for (int j = 0; j < temp.Count; j++) { output[output.Count - 1].Add(new Point((int)temp[j].X, (int)temp[j].Y)); } } return(output); }
private static void Traverse(CircularLinkedList <Vector2> subject, CircularLinkedList <Vector2> clip, CircularLinkedList <Vector2> entering, CircularLinkedList <Vector2> exiting, List <CircularLinkedList <Vector2> > polygons, Operation operation) { while (entering.Count > 0) { CircularLinkedList <Vector2> polygon = new CircularLinkedList <Vector2>(); Vector2 start = entering.First.Value; LinkedListNode <Vector2> curNode = subject.Find(start); polygon.AddLast(curNode.Value); curNode = subject.NextOrFirst(curNode); bool IsSubjectNode = true; while (curNode.Value != start) { polygon.AddLast(curNode.Value); if (entering.Contains(curNode.Value)) { entering.Remove(curNode.Value); IsSubjectNode = true; curNode = subject.Find(curNode.Value); } if (exiting.Contains(curNode.Value)) { exiting.Remove(curNode.Value); IsSubjectNode = false; curNode = clip.Find(curNode.Value); } if (IsSubjectNode) { curNode = subject.NextOrFirst(curNode); } else { curNode = clip.NextOrFirst(curNode); } } entering.Remove(curNode.Value); polygons.Add(polygon); } }
private static LinkedListNode <Vector2> TraverseList(CircularLinkedList <Vector2> contour, CircularLinkedList <Vector2> entering, CircularLinkedList <Vector2> exiting, CircularLinkedList <Vector2> polygon, LinkedListNode <Vector2> currentNode, Vector2 startNode, CircularLinkedList <Vector2> contour2) { LinkedListNode <Vector2> contourNode = contour.Find(currentNode.Value); if (contourNode == null) { return(null); } entering.Remove(currentNode.Value); while (contourNode != null && !entering.Contains(contourNode.Value) && !exiting.Contains(contourNode.Value) ) { polygon.AddLast(contourNode.Value); contourNode = contour.NextOrFirst(contourNode); if (contourNode.Value == startNode) { return(null); } } entering.Remove(contourNode.Value); polygon.AddLast(contourNode.Value); return(contour2.NextOrFirst(contour2.Find(contourNode.Value))); }
/// <summary> /// /// </summary> /// <param name="subject">Первый контур.</param> /// <param name="clip">Второй контур.</param> /// <param name="operation">Операция, проводимая над контурами.</param> /// <returns></returns> public static ICollection <CircularLinkedList <Vector2> > Process(CircularLinkedList <Vector2> subject, CircularLinkedList <Vector2> clip, Operation operation, Polygon ClipP, Polygon SubjectP) { LinkedListNode <Vector2> curSubject = subject.First; Dictionary <Vector2, Pair <Vector2> > intersections = new Dictionary <Vector2, Pair <Vector2> >(); List <CircularLinkedList <Vector2> > polygons = new List <CircularLinkedList <Vector2> >(); if (AreEqual <Vector2>(subject, clip)) { switch (operation) { case Operation.Union: polygons.Add(subject); return(polygons); case Operation.Intersect: polygons.Add(subject); return(polygons); case Operation.Difference: // нужно как-то разграничивать внешние и внутренние полигоны return(polygons); default: break; } } do { LinkedListNode <Vector2> curClip = clip.First; do { Vector2 intersectionPoint; if (IntersectSegment(curSubject.Value, subject.NextOrFirst(curSubject).Value, curClip.Value, clip.NextOrFirst(curClip).Value, out intersectionPoint)) { if (!intersections.ContainsKey(intersectionPoint)) { subject.AddAfter(curSubject, intersectionPoint); clip.AddAfter(curClip, intersectionPoint); intersections.Add(intersectionPoint, new Pair <Vector2>(curClip.Value, clip.NextOrFirst(curClip).Value)); } } curClip = clip.NextOrFirst(curClip); }while (curClip != clip.First); curSubject = subject.NextOrFirst(curSubject); }while (curSubject != subject.First); CircularLinkedList <Vector2> entering = new CircularLinkedList <Vector2>(); CircularLinkedList <Vector2> exiting = new CircularLinkedList <Vector2>(); MakeEnterExitList(subject, clip, intersections, entering, exiting, ClipP, SubjectP); Traverse(subject, clip, entering, exiting, polygons, operation); return(polygons); }