public void RemoveLastAndEmptyList() { CircularLinkedList <int> cll = new CircularLinkedList <int>(); cll.Add((10)); cll.Add((20)); cll.Add((30)); cll.Add((40)); /* 40 -> 30 -> 20 - > 10 * ^ | * |__________________| Head = 40, Tail = 10 */ cll.RemoveLast(); cll.RemoveLast(); cll.RemoveLast(); cll.RemoveLast(); /* * NULL, Count should be 0 */ Assert.AreEqual(cll.Head, null); Assert.AreEqual(cll.Count, 0); }
/// <summary> /// Given a circular list of half edges which completely surround a proposed face, create the new face. /// The supplied half-edges need not be in an order compatible with the existing mesh, but the order of /// the supplied faces or other connections in the mesh may be modified to accommodate the new face. /// </summary> /// <exception cref="ArgumentException"></exception> /// <param name="halfLoop">The supplied halfLoop parameter did not propose a face which could be /// legally inserted into the mesh</param> /// <returns>The new face</returns> private TFace FaceFromHalfEdgeLoop(CircularLinkedList <Half> halfLoop) { if (!EdgesAreFree(halfLoop)) { halfLoop = new CircularLinkedList <Half>(halfLoop.Select(h => h.pair).Reverse()); if (!EdgesAreFree(halfLoop)) { throw new ArgumentException("The polygon would introduce a non-manifold condition"); } } // Try to re-order the links to get a proper orientation halfLoop.ForEachPair(delegate(Half current, Half next) { if (!MakeAdjacent(current, next)) { throw new ArgumentException("The polygon would introduce a non-manifold condition"); } }); TFace face = new TFace { half = halfLoop.First.Value }; faces.Add(face); foreach (Half half in halfLoop) { half.Face = face; } return(face); }
public Form1() { finished = false; snake = new CircularLinkedList <Snake>(); InitializeComponent(); canvas = new Bitmap(pictureBox1.Width, pictureBox1.Height); g = Graphics.FromImage(canvas); Snake snakehead; snakehead = new Snake(0, 0, 30, 30, 30, 4); snake.AddNodeToFront(snakehead); x = rand.Next(0, canvas.Width - 30); y = rand.Next(0, canvas.Height - 30); if (x % 30 > 0) { while (x % 30 > 0) { x = rand.Next(30, canvas.Width - 30); } } if (y % 30 > 0) { while (y % 30 > 0) { y = rand.Next(30, canvas.Height - 30); } } food = new Food(x, y, 30, 30); score = 0; }
public static void Main(string[] args) { CircularLinkedList <string> circularList = new CircularLinkedList <string>(); circularList.Added += (object sender, AddToCollection <string> argument) => { Console.WriteLine(argument.Message); }; circularList.Removed += (object sender, RemFromCollection <string> argument) => { Console.WriteLine(argument.Message); }; circularList.Add("1"); circularList.Add("2"); circularList.Add("3"); circularList.Add("4"); foreach (var item in circularList) { Console.WriteLine(item); } circularList.Remove("2"); Console.WriteLine("\n После удаления: \n"); foreach (var item in circularList) { Console.WriteLine(item); } Console.WriteLine("\n Содержит 3: \n"); bool b = circularList.Contains("3"); Console.WriteLine(b); }
public override object Task1() { CircularLinkedList <byte> circle = new CircularLinkedList <byte>(); for (int i = 0; i <= byte.MaxValue; i++) { circle.AddLast((byte)i); } string[] parts = rawInput.Split(','); byte[] lengths = new byte[parts.Length]; for (int i = 0; i < parts.Length; i++) { lengths[i] = byte.Parse(parts[i]); } int totalSkips = 0; int skipSize = 0; foreach (int l in lengths) { ReverseSegment(circle, l); circle.MoveHeadRight(skipSize + l); totalSkips += skipSize + l; skipSize++; } circle.MoveHeadLeft(totalSkips); return(circle.First.Value * circle.First.Next.Value); }
public void CircularLinkedListConstructorTest() { string n = "Arthur"; CircularLinkedList target = new CircularLinkedList(n); Assert.Inconclusive("TODO: Implement code to verify target"); }
public void RemoveFirst() { CircularLinkedList <int> cll = new CircularLinkedList <int>(); cll.Add((10)); cll.Add((20)); cll.Add((30)); cll.Add((40)); /* 40 -> 30 -> 20 - > 10 * ^ | * |__________________| Head = 40, Tail = 10 */ cll.RemoveFirst(); /* 30 -> 20 - > 10 * ^ | * |____________| Head = 40, Tail = 10 */ Assert.AreEqual(cll.Head.Value, 30); Assert.AreEqual(cll.Tail.Value, 10); Assert.AreEqual(cll.Tail.Next.Value, 30); }
public void CircularLinkedList() { // Arrange var circularLinkedList = new CircularLinkedList <int>(); // Act circularLinkedList.Add(1); circularLinkedList.Add(2); circularLinkedList.Add(3); circularLinkedList.Add(4); var count1 = circularLinkedList.Count; circularLinkedList.Delete(3); var count2 = circularLinkedList.Count; var count = 0; for (var i = 0; i < circularLinkedList.Count * 2; i++) { count++; } // Assert Assert.Equal(4, count1); Assert.Equal(3, count2); Assert.Equal(circularLinkedList.Count * 2, count); }
public void MoveNextTest() { int[] arr = new int[] { 0, 1, 2, 3, 4, 5, 6, 7, 8 }; CircularLinkedList <int> list = new CircularLinkedList <int>(); foreach (int a in arr) { list.Add(a); } IEnumerator enumerator = list.GetEnumerator(); for (int i = 0; i < arr.Length * 2; i++) { enumerator.MoveNext(); if (i >= arr.Length) { Assert.AreEqual(arr[i - arr.Length], (int)enumerator.Current); } else { Assert.AreEqual(arr[i], (int)enumerator.Current); } } }
/// <summary> /// Determines whether the edges around the supplied vertex are ordered /// geometrically in the plane. /// </summary> /// <param name="vertex"></param> /// <returns></returns> private static bool IsOrdered(TVertex vertex) { if (vertex.Degree <= 2) { return(true); } CircularLinkedList <double> angles = new CircularLinkedList <double>(); foreach (Half h in vertex.HalfEdges) { double bearing = Bearing(h); angles.AddLast(bearing); } double min = angles.Min(); CircularLinkedListNode <double> node = angles.Find(min); CircularLinkedListNode <double> end = node; // Check that advancing from this minima they are sorted do { if (node.Value >= node.Next.Value) { return(false); } node = node.Next; }while (node != end.Previous); return(true); }
static void TestCircularList() { string[] items = { "a", "b", "c", "d" }; Console.Out.WriteLine("CIRCULAR LINKED LIST TESTS"); Console.Out.WriteLine(); Console.Out.WriteLine("> Create new list"); CircularLinkedList <string> list = new CircularLinkedList <string>(); list.Print(); Console.Out.WriteLine(); foreach (string item in items) { Console.Out.WriteLine("> Append '" + item + "'"); list.Append(item); list.Print(); Console.Out.WriteLine(); } Random rand = new Random(); while (0 < list.Count) { int index = rand.Next(0, list.Count); Console.Out.WriteLine("> Remove at " + index); list.RemoveAt(index); list.Print(); Console.Out.WriteLine(); } Console.Out.WriteLine(); }
public static void Main(string[] args) { SingleLinkedList <int> SingleLinkedList = new SingleLinkedList <int>(); DoubleLinkedList <int> doubleLinkedList = new DoubleLinkedList <int>(); CircularLinkedList <int> circularLinkedlist = new CircularLinkedList <int>(); // Single linked list //SingleLinkedList.AddLast(10); //SingleLinkedList.AddFirst(5); //SingleLinkedList.InsertAfter(5, 8); //SingleLinkedList.InsertBefore(8, 6); //SingleLinkedList.Display(); // Double linked list //doubleLinkedList.AddLast(10); //doubleLinkedList.AddFirst(5); //doubleLinkedList.InsertAfter(5, 8); //doubleLinkedList.InsertBefore(8, 6); //doubleLinkedList.Display(); // Circular linkedlist circularLinkedlist.AddLast(10); circularLinkedlist.AddFirst(5); circularLinkedlist.InsertAfter(5, 8); circularLinkedlist.InsertBefore(8, 6); circularLinkedlist.Delete(6); circularLinkedlist.Display(); Console.Read(); }
public void Reset_SetsCurrentToTheHead() { var sut = new CircularLinkedList <Reviewer> { new Reviewer("R1"), new Reviewer("R2"), new Reviewer("R3"), }; int counter = 0; Node <Reviewer> currentNode = null; foreach (Node <Reviewer> node in sut) { if (counter == 2) { break; } currentNode = node; counter++; } currentNode.Should().NotBe(sut.Head); sut.Reset(); sut.Head.Should().Be(sut.Current); }
public void Activate(ICycleObserver <PossessorSearcher.ItemPossessor> observer) { this.observer = observer; charList = new CircularLinkedList <PossessorSearcher.ItemPossessor>(); PossessorSearcher.FillPossessorList(charList); currPoss = charList.current.value; }
static void CircularLinkedListTest() { CircularLinkedList <int> list = new CircularLinkedList <int>(); Console.WriteLine("Starting"); list.addBack(43); list.addBack(83); list.addBack(98); list.addBack(65); list.addBack(4983); list.addBack(9898); list.addFront(5555555); Console.WriteLine("Size: " + list.size()); list.print(); list.popBack(); Console.WriteLine("Size: " + list.size()); list.print(); list.popFront(); Console.WriteLine("Size: " + list.size()); list.print(); Console.WriteLine("Finished"); }
public void Insert() { var students = new Student[] { new Student { No = 1, Name = "李1", Score = 22.1 }, new Student { No = 2, Name = "李2", Score = 32.3 }, new Student { No = 3, Name = "李3", Score = 42.5 } }; var circularLinkedList = new CircularLinkedList <Student>(); foreach (var student in students) { circularLinkedList.TailInsert(new Node <Student>(student)); } var insertStudent = new Student { No = 4, Name = "李4", Score = 44.4 }; circularLinkedList.Insert(new Node <Student>(insertStudent), 1); }
public override object Task2() { CircularLinkedList <char> programs = new CircularLinkedList <char>(); for (char i = 'a'; i <= 'p'; i++) { programs.AddLast(i); } HashSet <string> history = new HashSet <string>(); int patternLen = 0; // this is only 24 with my input. Didn't expect it to be so low for (; ; patternLen++) { ApplyDance(programs); string id = string.Join("", programs); if (history.Contains(id)) { break; } history.Add(string.Join("", programs)); } List <string> h = new List <string>(history); return(h[(1_000_000_000 - 1) % patternLen]);
//拉丁方阵问题 void LatinSquare(int count) { CircularLinkedList <int> numbers = new CircularLinkedList <int>(); for (int i = 0; i < count; i++) { numbers.Add(i + 1); } string log = ""; for (int i = 0; i < count; i++) { int row = 0; while (row < count) { log += numbers.Move() + " ,"; row++; } //新的一行从下一个位置开始 numbers.Move(); log += "\n"; } Debug.LogError(log); }
/// <summary> /// Re-order the half-edges around vertex such that they /// are spatially sorted /// </summary> /// <param name="vertex"></param> private static void Order(TVertex vertex) { // Put the half-edges into order according to bearing SortedDictionary <double, Half> outEdges = new SortedDictionary <double, Half>(); foreach (Half h in vertex.HalfEdges) { double bearing = Bearing(h); outEdges.Add(bearing, h); } // Copy into a circular linked-list for convenience CircularLinkedList <Half> outEdgesCycle = new CircularLinkedList <Half>(outEdges.Values); // Iterate around the list, correcting pointers as we go CircularLinkedListNode <Half> node = outEdgesCycle.First; do { Half previousInEdge = node.Previous.Value.pair; Half currentOutEdge = node.Value; Half currentInEdge = currentOutEdge.pair; Half nextOutEdge = node.Next.Value; previousInEdge.next = currentOutEdge; currentOutEdge.previous = previousInEdge; currentInEdge.next = nextOutEdge; nextOutEdge.previous = currentInEdge; node = node.Next; }while (node != outEdgesCycle.Last.Next); Debug.Assert(IsOrdered(vertex)); }
public static long Puzzle2() { var cups = 1000000; var moves = 10000000; var nodes = new Node[cups]; for (long i = 0; i < cups; ++i) { nodes[i] = new Node(i + 1); } var list = new CircularLinkedList(nodes); foreach (var i in PuzzleInput()) { list.Add(nodes[i - 1]); } for (long i = 10; i <= cups; ++i) { list.Add(nodes[i - 1]); } list.RunMoves(moves, cups); list.Start = list[1]; return(list .Skip(1) .Take(2) .Select(i => i.Value) .Aggregate((a, b) => a * b)); }
public void PrintNodesTest() { CircularLinkedList target = new CircularLinkedList(); target.PrintNodes(); Assert.Inconclusive("A method that does not return a value cannot be verified."); }
private static void RunMoves(this CircularLinkedList list, long count, long max) { var current = default(Node); var pick = new Node[3]; var next = default(Node); for (long i = 0; i < count; ++i) { current = list.Start; pick[0] = current.Next; pick[1] = pick[0].Next; pick[2] = pick[1].Next; next = pick[2].Next; var destination = current.Value.Dec(max); while (pick.Contains(list[destination])) { destination = destination.Dec(max); } list.Move(current, pick, list[destination]); list.Start = next; } }
// Testing the Add method. private void AddNumbers(CircularLinkedList <int> list) { for (int i = 1; i < 10; i++) { list.Add(i); } }
public void Current() { var cllString = new CircularLinkedList <string>(); var ci = cllString.GetCircularIterator(); Assert.Null(ci); }
// Reflect about any axis. // Work the same as the ReflectAboutAxis method in the NCPrimaryMovingStrategy. // Delegate to the moving strategy helper class. public R1CMovingStrategy ReflectAboutAxis(int axisIndex) { if (axisIndex != 1) { return(this); } R1CMovingStrategy newMovingStrategy = (R1CMovingStrategy)Clone(); MyLinkedList <R1CDirection> newLinkedList; if (linkedList is DoubleLinkedList <R1CDirection> ) { newLinkedList = new DoubleLinkedList <R1CDirection>(); } else { newLinkedList = new CircularLinkedList <R1CDirection>(); } CreateLinkedList(newLinkedList); newMovingStrategy.LinkedList = newLinkedList; newMovingStrategy.Direction = newLinkedList.GetLast().GetOppositeDirection().Direction; return(newMovingStrategy); }
private static void InitializeEdges(CircularLinkedList <Vertex> lav) { // Create a dummy incident edge into the first node from a dummy vertex collinear with // the first line segment. This removes special casing for the first bisector computation. CircularLinkedListNode <Vertex> firstNode = lav.First; Debug.Assert(firstNode != null); Debug.Assert(firstNode.Next != null); Vector2D firstEdgeDirection = firstNode.Next.Value.Position - firstNode.Value.Position; Vertex prefixVertex = new Vertex(firstNode.Value.Position - firstEdgeDirection); firstNode.Value.inEdge = new Edge(prefixVertex, firstNode.Value); // Create a dummy indicent edge from the last node to a dummy vertex collinear with the last // line segment. This removes special casing for the last bisector computation. CircularLinkedListNode <Vertex> lastNode = lav.Last; Debug.Assert(lastNode != null); Debug.Assert(lastNode.Previous != null); Vector2D lastEdgeDirection = lastNode.Value.Position - lastNode.Previous.Value.Position; Vertex suffixVertex = new Vertex(lastNode.Value.Position + lastEdgeDirection); lastNode.Value.outEdge = new Edge(lastNode.Value, suffixVertex); // Create edges between successive pairs of the list lav.ForEachPair(delegate(Vertex va, Vertex vb) { va.outEdge = new Edge(va, vb); vb.inEdge = va.outEdge; }); }
private void AddWords(CircularLinkedList <string> list) { list.Add("Ndumiso Chamane"); list.Add("Mfundo Mkhize"); list.Add("Ntuthuko Cele"); list.Add("Njabulo Khuzwayo"); }
private void ApplyDance(CircularLinkedList <char> programs) { foreach (string instruction in rawInput.Split(',')) { switch (instruction[0]) { case 's': programs.MoveHeadLeft(int.Parse(instruction.Substring(1))); break; case 'x': int[] indexes = Array.ConvertAll(instruction.Substring(1).Split('/'), int.Parse); var Ax = programs.ElementAt(indexes[0]); var Bx = programs.ElementAt(indexes[1]); var tmp = Ax.Value; Ax.Value = Bx.Value; Bx.Value = tmp; break; case 'p': var Ap = programs.FindElementByValue(instruction[1]); var Bp = programs.FindElementByValue(instruction[3]); Ap.Value = instruction[3]; Bp.Value = instruction[1]; break; } } }
static void Main(string[] args) { try { List <int> lst = new List <int>(new int[] { 1, 2, 3, 4, 5 }); CircularLinkedList <int> circular = new CircularLinkedList <int>(lst); do { circular.Shift(); Console.WriteLine(circular.Current.Value); } while (Console.ReadKey().Key != ConsoleKey.Escape); Console.WriteLine("Удаления"); do { Console.WriteLine("удалил: " + circular.Remove()); } while (Console.ReadKey().Key != ConsoleKey.Escape); circular.Shift(); var a = circular.Current; } catch (Exception e) { Console.WriteLine(e); throw; } }
string Vigenere(string input) { int[] secret = new int[] { 1, 27, 2, 2 }; CircularLinkedList <char> letters = new CircularLinkedList <char>(); char a = 'a'; //赋值26个字母 for (int i = 0; i < 26; i++) { letters.Add(a++); } string result = ""; //开始解密 for (int i = 0; i < input.Length; i++) { char decode = letters.MoveAt(letters.IndexOf(input[i])); for (int j = 0; j < secret[i]; j++) { decode = letters.Move(); } result += decode; } Debug.LogError(result); return(result); }
// The last node is always the circular reference, but it'll suffice for the problem at hand. public static CircularLinkedList<int> GenerateCircularLinkedList(int size, int max) { Random rand = new Random(); var newList = new CircularLinkedList<int>(); for (int i = 0; i < size; i++) { newList.AddLast(rand.Next(0, max)); } return newList; }
public static Node<int> FindCircularNode(CircularLinkedList<int> circularList) { var node = circularList[0]; var seen = new List<Node<int>>(); while (!seen.Contains(node.Next)) { seen.Add(node); node = node.Next; } return node; }
private static PointF[] GetTrianglePointArray(CircularLinkedList<Vector2> list) { LinkedListNode<Vector2> currentNode = list.First; PointF[] result = new PointF[3]; for (int i = 0; i < 3; i++) { result[i] = new PointF(currentNode.Value.X, currentNode.Value.Y); currentNode = list.NextOrFirst(currentNode); } return result; }
public static void Execute(CircularLinkedList<int> circularList) { Console.WriteLine("Chapter 02 Question 06: Circular linked list"); Console.WriteLine("Initial list"); Console.Write("["); foreach (var item in circularList) { Console.Write("{0} ->", item); } Console.Write("]"); var circularNode = FindCircularNode(circularList); Console.WriteLine(""); Console.WriteLine("The circular node's value is: "); Console.Write("[ {0} ]", circularNode.Value); Console.WriteLine(" "); }
private static void MakeEnterExitList(CircularLinkedList<Vector2> subject, CircularLinkedList<Vector2> clip, Dictionary<Vector2, Pair<Vector2>> intersections, CircularLinkedList<Vector2> entering, CircularLinkedList<Vector2> exiting) { LinkedListNode<Vector2> curr = subject.First; while (curr != subject.Last) { if (intersections.ContainsKey(curr.Value)) { bool isEntering = Vector2Cross(curr.Next.Value.X - curr.Previous.Value.X, curr.Next.Value.Y - curr.Previous.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 = curr.Next; } }
private static LinkedListNode<Vector2> TraverseList(CircularLinkedList<Vector2> contour, CircularLinkedList<Vector2> entering, CircularLinkedList<Vector2> exiting, ICollection<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.Add(contourNode.Value); contourNode = contour.NextOrFirst(contourNode); if (contourNode.Value == startNode) return null; } entering.Remove(contourNode.Value); polygon.Add(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<ICollection<Vector2>> Process(CircularLinkedList<Vector2> subject, CircularLinkedList<Vector2> clip, Operation operation) { LinkedListNode<Vector2> curSubject = subject.First; Dictionary<Vector2, Pair<Vector2>> intersections = new Dictionary<Vector2, Pair<Vector2>>(); List<ICollection<Vector2>> polygons = new List<ICollection<Vector2>>(); if (Misc.AreEqual<Vector2>(subject, clip)) { switch (operation) { case Operation.Union: polygons.Add(subject); return polygons; break; case Operation.Intersect: polygons.Add(subject); return polygons; break; case Operation.Difference: return polygons; break; default: break; } } while (curSubject != subject.Last) { LinkedListNode<Vector2> curClip = clip.First; while (curClip != clip.Last) { Vector2 intersectionPoint; if (IntersectSegment(curSubject.Value, curSubject.Next.Value, curClip.Value, curClip.Next.Value, out intersectionPoint)) { subject.AddAfter(curSubject, intersectionPoint); clip.AddAfter(curClip, intersectionPoint); intersections.Add(intersectionPoint, new Pair<Vector2>(curClip.Value, curClip.Next.Value)); } curClip = curClip.Next; } curSubject = curSubject.Next; } CircularLinkedList<Vector2> entering = new CircularLinkedList<Vector2>(); CircularLinkedList<Vector2> exiting = new CircularLinkedList<Vector2>(); MakeEnterExitList(subject, clip, intersections, entering, exiting); subject.RemoveLast(); clip.RemoveLast(); Traverse(subject, clip, entering, exiting, polygons, operation); if (polygons.Count == 0) { switch (operation) { case Operation.Union: polygons.Add(subject); polygons.Add(clip); break; case Operation.Intersect: break; case Operation.Difference: polygons.Add(subject); break; default: break; } } return polygons; }
static void Main(string[] args) { //Vector3 a = new Vector3(0, 1, 0); //Vector3 b = new Vector3(1, 0, 0); //Console.WriteLine(Vector3.Cross(a, b)); CircularLinkedList<Vector2> subject = new CircularLinkedList<Vector2>(); CircularLinkedList<Vector2> clip = new CircularLinkedList<Vector2>(); //#region Big and small square //subject.AddLast(new Vector2(0, 0)); //subject.AddLast(new Vector2(0, 4)); //subject.AddLast(new Vector2(4, 4)); //subject.AddLast(new Vector2(4, 0)); //subject.AddLast(new Vector2(0, 0)); //clip.AddLast(new Vector2(4, 1)); //clip.AddLast(new Vector2(4, 3)); //clip.AddLast(new Vector2(6, 3)); //clip.AddLast(new Vector2(6, 1)); //clip.AddLast(new Vector2(4, 1)); //#endregion //#region Shared edge //subject.AddLast(new Vector2(0, 0)); //subject.AddLast(new Vector2(0, 1)); //subject.AddLast(new Vector2(1, 0)); //subject.AddLast(new Vector2(0, 0)); //clip.AddLast(new Vector2(0, 1)); //clip.AddLast(new Vector2(1, 1)); //clip.AddLast(new Vector2(1, 0)); //clip.AddLast(new Vector2(0, 1)); //#endregion //#region Triangle and polygon //subject.AddLast(new Vector2(-3, 1)); //subject.AddLast(new Vector2(2, 2)); //subject.AddLast(new Vector2(2, -3)); //subject.AddLast(new Vector2(-3, 1)); //clip.AddLast(new Vector2(1, -1)); //clip.AddLast(new Vector2(5, -1)); //clip.AddLast(new Vector2(2, -5)); //clip.AddLast(new Vector2(-6, 3)); //clip.AddLast(new Vector2(1, 1)); //clip.AddLast(new Vector2(3, 0)); //clip.AddLast(new Vector2(1, -1)); //#endregion //#region Simple triangles //subject.AddLast(new Vector2(-2, 0)); //subject.AddLast(new Vector2(1, 1)); //subject.AddLast(new Vector2(-1, -2)); //subject.AddLast(new Vector2(-2, 0)); //clip.AddLast(new Vector2(-1, -1)); //clip.AddLast(new Vector2(1, 0)); //clip.AddLast(new Vector2(1, -2)); //clip.AddLast(new Vector2(-1, -1)); //#endregion //#region Two equal //subject.AddLast(new Vector2(0, 0)); //subject.AddLast(new Vector2(0, 1)); //subject.AddLast(new Vector2(1, 0)); //subject.AddLast(new Vector2(0, 0)); //clip.AddLast(new Vector2(0, 0)); //clip.AddLast(new Vector2(0, 1)); //clip.AddLast(new Vector2(1, 0)); //clip.AddLast(new Vector2(0, 0)); //#endregion //#region Two triangles 1 //subject.AddLast(new Vector2(-3, 0)); //subject.AddLast(new Vector2(0, 3)); //subject.AddLast(new Vector2(3, 0)); //subject.AddLast(new Vector2(-3, 0)); //clip.AddLast(new Vector2(-2, 1)); //clip.AddLast(new Vector2(2, 1)); //clip.AddLast(new Vector2(0, -1)); //clip.AddLast(new Vector2(-2, 1)); //#endregion //#region Two triangles 2 //subject.AddLast(new Vector2(-3, 0)); //subject.AddLast(new Vector2(0, 3)); //subject.AddLast(new Vector2(3, 0)); //subject.AddLast(new Vector2(-3, 0)); //clip.AddLast(new Vector2(-2, 2)); //clip.AddLast(new Vector2(2, 2)); //clip.AddLast(new Vector2(0, 0)); //clip.AddLast(new Vector2(-2, 2)); //#endregion #region Second touches 2 sides from inside and exit through third side subject.Clear(); clip.Clear(); subject.AddLast(new Vector2(-3, 0)); subject.AddLast(new Vector2(0, 3)); subject.AddLast(new Vector2(3, 0)); subject.AddLast(new Vector2(-3, 0)); clip.AddLast(new Vector2(-2, 1)); clip.AddLast(new Vector2(2, 1)); clip.AddLast(new Vector2(0, -1)); clip.AddLast(new Vector2(-2, 1)); Draw(subject, clip, "Second touches 2 sides from inside and exit through third side"); #endregion #region Second touches 1 side from inside and exit through other sides subject.Clear(); clip.Clear(); subject.AddLast(new Vector2(-3, 0)); subject.AddLast(new Vector2(0, 3)); subject.AddLast(new Vector2(3, 0)); subject.AddLast(new Vector2(-3, 0)); clip.AddLast(new Vector2(-2, 2)); clip.AddLast(new Vector2(2, 2)); clip.AddLast(new Vector2(0, 0)); clip.AddLast(new Vector2(-2, 2)); Draw(subject, clip, "Second touches 1 side from inside and exit through other sides"); #endregion #region Second touches 1 side from inside subject.Clear(); clip.Clear(); subject.AddLast(new Vector2(-3, 0)); subject.AddLast(new Vector2(0, 3)); subject.AddLast(new Vector2(3, 0)); subject.AddLast(new Vector2(-3, 0)); clip.AddLast(new Vector2(-1, 1)); clip.AddLast(new Vector2(1, 1)); clip.AddLast(new Vector2(0, 0)); clip.AddLast(new Vector2(-1, 1)); Draw(subject, clip, "Second touches 1 side from inside"); #endregion #region Second partially overlays 2 sides from same vertex subject.Clear(); clip.Clear(); subject.AddLast(new Vector2(-3, 0)); subject.AddLast(new Vector2(0, 3)); subject.AddLast(new Vector2(3, 0)); subject.AddLast(new Vector2(-3, 0)); clip.AddLast(new Vector2(-3, 0)); clip.AddLast(new Vector2(-1, 2)); clip.AddLast(new Vector2(0, 0)); clip.AddLast(new Vector2(-3, 0)); Draw(subject, clip, "Second partially overlays 2 sides from same vertex"); #endregion #region Second partially overlays 1 side from vertex and totally overlays other side subject.Clear(); clip.Clear(); subject.AddLast(new Vector2(-3, 0)); subject.AddLast(new Vector2(0, 3)); subject.AddLast(new Vector2(3, 0)); subject.AddLast(new Vector2(-3, 0)); clip.AddLast(new Vector2(-3, 0)); clip.AddLast(new Vector2(0, 3)); clip.AddLast(new Vector2(1, 0)); clip.AddLast(new Vector2(-3, 0)); Draw(subject, clip, "Second partially overlays 1 side from vertex and totally overlays other side"); #endregion #region Second partially overlays 1 side and touches other side subject.Clear(); clip.Clear(); subject.AddLast(new Vector2(-3, 0)); subject.AddLast(new Vector2(0, 3)); subject.AddLast(new Vector2(3, 0)); subject.AddLast(new Vector2(-3, 0)); clip.AddLast(new Vector2(-2, 1)); clip.AddLast(new Vector2(-1, 2)); clip.AddLast(new Vector2(-1, 0)); clip.AddLast(new Vector2(-2, 1)); Draw(subject, clip, "Second partially overlays 1 side and touches other side"); #endregion #region Second partially overlays 1 side and touches other vertex subject.Clear(); clip.Clear(); subject.AddLast(new Vector2(-3, 0)); subject.AddLast(new Vector2(0, 3)); subject.AddLast(new Vector2(3, 0)); subject.AddLast(new Vector2(-3, 0)); clip.AddLast(new Vector2(-1, 0)); clip.AddLast(new Vector2(0, 3)); clip.AddLast(new Vector2(1, 0)); clip.AddLast(new Vector2(-1, 0)); Draw(subject, clip, "Second partially overlays 1 side and touches other vertex"); #endregion #region Second partially overlays 1 side from inside subject.Clear(); clip.Clear(); subject.AddLast(new Vector2(-3, 0)); subject.AddLast(new Vector2(0, 3)); subject.AddLast(new Vector2(3, 0)); subject.AddLast(new Vector2(-3, 0)); clip.AddLast(new Vector2(-2, 1)); clip.AddLast(new Vector2(-1, 2)); clip.AddLast(new Vector2(-1, 1)); clip.AddLast(new Vector2(-2, 1)); Draw(subject, clip, "Second partially overlays 1 side from inside"); #endregion #region Second touches every side subject.Clear(); clip.Clear(); subject.AddLast(new Vector2(-3, 0)); subject.AddLast(new Vector2(0, 3)); subject.AddLast(new Vector2(3, 0)); subject.AddLast(new Vector2(-3, 0)); clip.AddLast(new Vector2(-1, 2)); clip.AddLast(new Vector2(1, 2)); clip.AddLast(new Vector2(0, 0)); clip.AddLast(new Vector2(-1, 2)); Draw(subject, clip, "Second touches every side"); #endregion #region Second totally overlays 1 side from inside subject.Clear(); clip.Clear(); subject.AddLast(new Vector2(-3, 0)); subject.AddLast(new Vector2(0, 3)); subject.AddLast(new Vector2(3, 0)); subject.AddLast(new Vector2(-3, 0)); clip.AddLast(new Vector2(-3, 0)); clip.AddLast(new Vector2(0, 2)); clip.AddLast(new Vector2(3, 0)); clip.AddLast(new Vector2(-3, 0)); Draw(subject, clip, "Second totally overlays 1 side from inside"); #endregion #region Second touches 2 sides from inside subject.Clear(); clip.Clear(); subject.AddLast(new Vector2(-3, 0)); subject.AddLast(new Vector2(0, 3)); subject.AddLast(new Vector2(3, 0)); subject.AddLast(new Vector2(-3, 0)); clip.AddLast(new Vector2(-1, 2)); clip.AddLast(new Vector2(1, 1)); clip.AddLast(new Vector2(-1, 0)); clip.AddLast(new Vector2(-1, 2)); Draw(subject, clip, "Second touches 2 sides from inside"); #endregion #region Second totally overlays 1 side from outside subject.Clear(); clip.Clear(); subject.AddLast(new Vector2(-3, 0)); subject.AddLast(new Vector2(0, 3)); subject.AddLast(new Vector2(3, 0)); subject.AddLast(new Vector2(-3, 0)); clip.AddLast(new Vector2(-3, 0)); clip.AddLast(new Vector2(3, 0)); clip.AddLast(new Vector2(0, -3)); clip.AddLast(new Vector2(-3, 0)); Draw(subject, clip, "Second totally overlays 1 side from outside"); #endregion #region Second partially overlays 1 side from vertex from outside subject.Clear(); clip.Clear(); subject.AddLast(new Vector2(-3, 0)); subject.AddLast(new Vector2(0, 3)); subject.AddLast(new Vector2(3, 0)); subject.AddLast(new Vector2(-3, 0)); clip.AddLast(new Vector2(-3, 0)); clip.AddLast(new Vector2(0, 0)); clip.AddLast(new Vector2(-1, -2)); clip.AddLast(new Vector2(-3, 0)); Draw(subject, clip, "Second partially overlays 1 side from vertex from outside"); #endregion #region Second partially overlays 1 side from outside subject.Clear(); clip.Clear(); subject.AddLast(new Vector2(-3, 0)); subject.AddLast(new Vector2(0, 3)); subject.AddLast(new Vector2(3, 0)); subject.AddLast(new Vector2(-3, 0)); clip.AddLast(new Vector2(-2, 0)); clip.AddLast(new Vector2(2, 0)); clip.AddLast(new Vector2(0, -2)); clip.AddLast(new Vector2(-2, 0)); Draw(subject, clip, "Second partially overlays 1 side from outside"); #endregion #region Second touches 1 side from outside subject.Clear(); clip.Clear(); subject.AddLast(new Vector2(-3, 0)); subject.AddLast(new Vector2(0, 3)); subject.AddLast(new Vector2(3, 0)); subject.AddLast(new Vector2(-3, 0)); clip.AddLast(new Vector2(-1, -2)); clip.AddLast(new Vector2(0, 0)); clip.AddLast(new Vector2(1, -2)); clip.AddLast(new Vector2(-1, -2)); Draw(subject, clip, "Second touches 1 side from outside"); #endregion #region Second completely inside subject.Clear(); clip.Clear(); subject.AddLast(new Vector2(-4, 0)); subject.AddLast(new Vector2(0, 4)); subject.AddLast(new Vector2(4, 0)); subject.AddLast(new Vector2(-4, 0)); clip.AddLast(new Vector2(-1, 2)); clip.AddLast(new Vector2(1, 2)); clip.AddLast(new Vector2(0, 1)); clip.AddLast(new Vector2(-1, 2)); Draw(subject, clip, "Second completely inside"); #endregion #region Second touches 1 side and exits from another side subject.Clear(); clip.Clear(); subject.AddLast(new Vector2(-3, 0)); subject.AddLast(new Vector2(0, 3)); subject.AddLast(new Vector2(3, 0)); subject.AddLast(new Vector2(-3, 0)); clip.AddLast(new Vector2(-3, 1)); clip.AddLast(new Vector2(-1, 3)); clip.AddLast(new Vector2(-1, 0)); clip.AddLast(new Vector2(-3, 1)); Draw(subject, clip, "Second touches 1 side and exits from another side"); #endregion #region Second touches 2 sides and exits from another side subject.Clear(); clip.Clear(); subject.AddLast(new Vector2(-3, 0)); subject.AddLast(new Vector2(0, 3)); subject.AddLast(new Vector2(3, 0)); subject.AddLast(new Vector2(-3, 0)); clip.AddLast(new Vector2(-3, 2)); clip.AddLast(new Vector2(-1, 2)); clip.AddLast(new Vector2(-1, 0)); clip.AddLast(new Vector2(-3, 2)); Draw(subject, clip, "Second touches 2 sides and exits from another side"); #endregion #region Second touches 1 side and intersects same side subject.Clear(); clip.Clear(); subject.AddLast(new Vector2(-3, 0)); subject.AddLast(new Vector2(0, 3)); subject.AddLast(new Vector2(3, 0)); subject.AddLast(new Vector2(-3, 0)); clip.AddLast(new Vector2(-2, 2)); clip.AddLast(new Vector2(-1, 2)); clip.AddLast(new Vector2(-1, 1)); clip.AddLast(new Vector2(-2, 2)); Draw(subject, clip, "Second touches 1 side and intersects same side"); #endregion #region Second touches 1 vertex from outside subject.Clear(); clip.Clear(); subject.AddLast(new Vector2(-3, 0)); subject.AddLast(new Vector2(0, 3)); subject.AddLast(new Vector2(3, 0)); subject.AddLast(new Vector2(-3, 0)); clip.AddLast(new Vector2(3, 0)); clip.AddLast(new Vector2(4, 1)); clip.AddLast(new Vector2(4, -1)); clip.AddLast(new Vector2(3, 0)); Draw(subject, clip, "Second touches 1 vertex from outside"); #endregion #region Second touches 1 vertex from inside subject.Clear(); clip.Clear(); subject.AddLast(new Vector2(-3, 0)); subject.AddLast(new Vector2(0, 3)); subject.AddLast(new Vector2(3, 0)); subject.AddLast(new Vector2(-3, 0)); clip.AddLast(new Vector2(-1, 1)); clip.AddLast(new Vector2(0, 3)); clip.AddLast(new Vector2(1, 1)); clip.AddLast(new Vector2(-1, 1)); Draw(subject, clip, "Second touches 1 vertex from inside"); #endregion #region Second partially overlays 1 side from vertex and exits from another vertex subject.Clear(); clip.Clear(); subject.AddLast(new Vector2(-3, 0)); subject.AddLast(new Vector2(0, 3)); subject.AddLast(new Vector2(3, 0)); subject.AddLast(new Vector2(-3, 0)); clip.AddLast(new Vector2(-3, 0)); clip.AddLast(new Vector2(0, 4)); clip.AddLast(new Vector2(0, 0)); clip.AddLast(new Vector2(-3, 0)); Draw(subject, clip, "Second partially overlays 1 side from vertex and exits from another vertex"); #endregion #region Second touches 1 vertex from inside and intersects other vertex of the same side subject.Clear(); clip.Clear(); subject.AddLast(new Vector2(-3, 0)); subject.AddLast(new Vector2(0, 3)); subject.AddLast(new Vector2(3, 0)); subject.AddLast(new Vector2(-3, 0)); clip.AddLast(new Vector2(-3, 0)); clip.AddLast(new Vector2(0, 4)); clip.AddLast(new Vector2(0, 2)); clip.AddLast(new Vector2(-3, 0)); Draw(subject, clip, "Second touches 1 vertex from inside and intersects other vertex of the same side"); #endregion #region Second touches 1 vertex from inside and intersects other vertex of the same side and intersects adjacent side subject.Clear(); clip.Clear(); subject.AddLast(new Vector2(-3, 0)); subject.AddLast(new Vector2(0, 3)); subject.AddLast(new Vector2(3, 0)); subject.AddLast(new Vector2(-3, 0)); clip.AddLast(new Vector2(-3, 0)); clip.AddLast(new Vector2(0, 4)); clip.AddLast(new Vector2(0, -1)); clip.AddLast(new Vector2(-3, 0)); Draw(subject, clip, "Second touches 1 vertex from inside and intersects other vertex of the same side and intersects adjacent side"); #endregion #region Second touches 1 vertex from outside and shares 1 vertex subject.Clear(); clip.Clear(); subject.AddLast(new Vector2(-3, 0)); subject.AddLast(new Vector2(0, 1)); subject.AddLast(new Vector2(3, 0)); subject.AddLast(new Vector2(-3, 0)); clip.AddLast(new Vector2(-3, 0)); clip.AddLast(new Vector2(3, 3)); clip.AddLast(new Vector2(3, -1)); clip.AddLast(new Vector2(-3, 0)); Draw(subject, clip, "Second touches 1 vertex from outside and shares 1 vertex"); #endregion #region Second touches 1 vertex from inside and shares 1 vertex subject.Clear(); clip.Clear(); subject.AddLast(new Vector2(-3, 0)); subject.AddLast(new Vector2(0, 3)); subject.AddLast(new Vector2(3, 0)); subject.AddLast(new Vector2(-3, 0)); clip.AddLast(new Vector2(-1, 1)); clip.AddLast(new Vector2(0, 3)); clip.AddLast(new Vector2(0, 0)); clip.AddLast(new Vector2(-1, 1)); Draw(subject, clip, "Second touches 1 vertex from inside and shares 1 vertex"); #endregion #region Triangles are equal subject.Clear(); clip.Clear(); subject.AddLast(new Vector2(-3, 0)); subject.AddLast(new Vector2(0, 3)); subject.AddLast(new Vector2(3, 0)); subject.AddLast(new Vector2(-3, 0)); clip.AddLast(new Vector2(-3, 0)); clip.AddLast(new Vector2(0, 3)); clip.AddLast(new Vector2(3, 0)); clip.AddLast(new Vector2(-3, 0)); Draw(subject, clip, "Triangles are equal"); #endregion #region Second has 2 shared vertices and intersects 1 side subject.Clear(); clip.Clear(); subject.AddLast(new Vector2(-3, 0)); subject.AddLast(new Vector2(0, 3)); subject.AddLast(new Vector2(3, 0)); subject.AddLast(new Vector2(-3, 0)); clip.AddLast(new Vector2(-3, 0)); clip.AddLast(new Vector2(-2, 2)); clip.AddLast(new Vector2(3, 0)); clip.AddLast(new Vector2(-3, 0)); Draw(subject, clip, "Second has 2 shared vertices and intersects 1 side"); #endregion #region Second touches 2 sides and last vertex outside subject.Clear(); clip.Clear(); subject.AddLast(new Vector2(-3, 0)); subject.AddLast(new Vector2(0, 3)); subject.AddLast(new Vector2(3, 0)); subject.AddLast(new Vector2(-3, 0)); clip.AddLast(new Vector2(-2, 1)); clip.AddLast(new Vector2(0, 4)); clip.AddLast(new Vector2(2, 1)); clip.AddLast(new Vector2(-2, 1)); Draw(subject, clip, "Second touches 2 sides and last vertex outside"); #endregion #region Second has 2 shared vertices and last vertex outside subject.Clear(); clip.Clear(); subject.AddLast(new Vector2(-3, 0)); subject.AddLast(new Vector2(0, 2)); subject.AddLast(new Vector2(3, 0)); subject.AddLast(new Vector2(-3, 0)); clip.AddLast(new Vector2(-3, 0)); clip.AddLast(new Vector2(0, 3)); clip.AddLast(new Vector2(3, 0)); clip.AddLast(new Vector2(-3, 0)); Draw(subject, clip, "Second has 2 shared vertices and last vertex outside"); #endregion #region Second has 2 shared vertices and 1 side of first partially overlays second side from vertex subject.Clear(); clip.Clear(); subject.AddLast(new Vector2(-3, 0)); subject.AddLast(new Vector2(0, 3)); subject.AddLast(new Vector2(1, 0)); subject.AddLast(new Vector2(-3, 0)); clip.AddLast(new Vector2(-3, 0)); clip.AddLast(new Vector2(0, 3)); clip.AddLast(new Vector2(3, 0)); clip.AddLast(new Vector2(-3, 0)); Draw(subject, clip, "Second has 2 shared vertices and 1 side of first partially overlays second side from vertex"); #endregion #region Second partially overlays one side with shared vertex and stays inside forever subject.Clear(); clip.Clear(); subject.AddLast(new Vector2(-3, 0)); subject.AddLast(new Vector2(0, 3)); subject.AddLast(new Vector2(3, 0)); subject.AddLast(new Vector2(-3, 0)); clip.AddLast(new Vector2(-3, 0)); clip.AddLast(new Vector2(0, 2)); clip.AddLast(new Vector2(0, 0)); clip.AddLast(new Vector2(-3, 0)); Draw(subject, clip, "Second partially overlays one side with shared vertex and stays inside forever"); #endregion #region Second partially overlays one side with shared vertex and exits through side with shared vertex subject.Clear(); clip.Clear(); subject.AddLast(new Vector2(-3, 0)); subject.AddLast(new Vector2(0, 3)); subject.AddLast(new Vector2(3, 0)); subject.AddLast(new Vector2(-3, 0)); clip.AddLast(new Vector2(-3, 0)); clip.AddLast(new Vector2(-2, 2)); clip.AddLast(new Vector2(0, 0)); clip.AddLast(new Vector2(-3, 0)); Draw(subject, clip, "Second partially overlays one side with shared vertex and exits through side with shared vertex"); #endregion #region Second partially overlays one side with shared vertex and exits through side without shared vertex subject.Clear(); clip.Clear(); subject.AddLast(new Vector2(-3, 0)); subject.AddLast(new Vector2(0, 3)); subject.AddLast(new Vector2(3, 0)); subject.AddLast(new Vector2(-3, 0)); clip.AddLast(new Vector2(-3, 0)); clip.AddLast(new Vector2(0, 4)); clip.AddLast(new Vector2(2, 0)); clip.AddLast(new Vector2(-3, 0)); Draw(subject, clip, "Second partially overlays one side with shared vertex and exits through side without shared vertex"); #endregion #region Second partially overlays one side with shared vertex and touches opposite side subject.Clear(); clip.Clear(); subject.AddLast(new Vector2(-3, 0)); subject.AddLast(new Vector2(0, 3)); subject.AddLast(new Vector2(3, 0)); subject.AddLast(new Vector2(-3, 0)); clip.AddLast(new Vector2(-3, 0)); clip.AddLast(new Vector2(1, 2)); clip.AddLast(new Vector2(0, 0)); clip.AddLast(new Vector2(-3, 0)); Draw(subject, clip, "Second partially overlays one side with shared vertex and touches opposite side"); #endregion #region Second has 1 shared vertex, second vertex touches opposite side and sides intersect subject.Clear(); clip.Clear(); subject.AddLast(new Vector2(-3, 0)); subject.AddLast(new Vector2(0, 3)); subject.AddLast(new Vector2(3, 0)); subject.AddLast(new Vector2(-3, 0)); clip.AddLast(new Vector2(-2, 3)); clip.AddLast(new Vector2(0, 3)); clip.AddLast(new Vector2(0, 0)); clip.AddLast(new Vector2(-2, 3)); Draw(subject, clip, "Second has 1 shared vertex, second vertex touches opposite side and sides intersect"); #endregion #region Second has 1 shared vertex, second vertex touches opposite side, third vertex outside subject.Clear(); clip.Clear(); subject.AddLast(new Vector2(-3, 0)); subject.AddLast(new Vector2(0, 1)); subject.AddLast(new Vector2(2, 0)); subject.AddLast(new Vector2(-3, 0)); clip.AddLast(new Vector2(-3, 0)); clip.AddLast(new Vector2(0, 2)); clip.AddLast(new Vector2(1, 0.5f)); clip.AddLast(new Vector2(-3, 0)); Draw(subject, clip, "Second has 1 shared vertex, second vertex touches opposite side, third vertex outside"); #endregion #region Second has 1 shared vertex and opposite side intersects adjacent side subject.Clear(); clip.Clear(); subject.AddLast(new Vector2(-3, 0)); subject.AddLast(new Vector2(0, 3)); subject.AddLast(new Vector2(3, 0)); subject.AddLast(new Vector2(-3, 0)); clip.AddLast(new Vector2(-2, 2)); clip.AddLast(new Vector2(0, 3)); clip.AddLast(new Vector2(-1, 1)); clip.AddLast(new Vector2(-2, 2)); Draw(subject, clip, "Second has 1 shared vertex and opposite side intersects adjacent side"); #endregion #region Second has 1 shared vertex, opposite side intersects 2 sides, adjacent side intersects 1 side subject.Clear(); clip.Clear(); subject.AddLast(new Vector2(-3, 0)); subject.AddLast(new Vector2(0, 3)); subject.AddLast(new Vector2(3, 0)); subject.AddLast(new Vector2(-3, 0)); clip.AddLast(new Vector2(-3, 0)); clip.AddLast(new Vector2(-2, 2)); clip.AddLast(new Vector2(2, 2)); clip.AddLast(new Vector2(-3, 0)); Draw(subject, clip, "Second has 1 shared vertex, opposite side intersects 2 sides, adjacent side intersects 1 side"); #endregion #region Second has 1 shared vertex and intersects both adjacent sides subject.Clear(); clip.Clear(); subject.AddLast(new Vector2(-3, 0)); subject.AddLast(new Vector2(0, 3)); subject.AddLast(new Vector2(3, 0)); subject.AddLast(new Vector2(-3, 0)); clip.AddLast(new Vector2(-2, 2)); clip.AddLast(new Vector2(0, 3)); clip.AddLast(new Vector2(2, 2)); clip.AddLast(new Vector2(-2, 2)); Draw(subject, clip, "Second has 1 shared vertex and intersects both adjacent sides"); #endregion #region Second has 1 shared vertex and intersects adjacent side and opposite side subject.Clear(); clip.Clear(); subject.AddLast(new Vector2(-3, 0)); subject.AddLast(new Vector2(0, 2)); subject.AddLast(new Vector2(3, 0)); subject.AddLast(new Vector2(-3, 0)); clip.AddLast(new Vector2(-3, 0)); clip.AddLast(new Vector2(0, 3)); clip.AddLast(new Vector2(2, -1)); clip.AddLast(new Vector2(-3, 0)); Draw(subject, clip, "Second has 1 shared vertex and intersects adjacent side and opposite side"); #endregion #region Second has 1 shared vertex and lays completely inside subject.Clear(); clip.Clear(); clip.AddLast(new Vector2(-3, 0)); clip.AddLast(new Vector2(0, 3)); clip.AddLast(new Vector2(3, 0)); clip.AddLast(new Vector2(-3, 0)); subject.AddLast(new Vector2(-1, 1)); subject.AddLast(new Vector2(0, 3)); subject.AddLast(new Vector2(1, 1)); subject.AddLast(new Vector2(-1, 1)); Draw(subject, clip, "Second has 1 shared vertex and lays completely inside"); #endregion #region Second has 1 shared vertex and intersects opposite side subject.Clear(); clip.Clear(); subject.AddLast(new Vector2(-3, 0)); subject.AddLast(new Vector2(0, 1)); subject.AddLast(new Vector2(3, 0)); subject.AddLast(new Vector2(-3, 0)); clip.AddLast(new Vector2(-3, 0)); clip.AddLast(new Vector2(-1, 3)); clip.AddLast(new Vector2(2, 1)); clip.AddLast(new Vector2(-3, 0)); Draw(subject, clip, "Second has 1 shared vertex and intersects opposite side"); #endregion #region Second has 1 shared vertex, second vertex lays on opposite side and adjacent side intersects opposite subject.Clear(); clip.Clear(); subject.AddLast(new Vector2(-3, 0)); subject.AddLast(new Vector2(0, 2)); subject.AddLast(new Vector2(3, 0)); subject.AddLast(new Vector2(-3, 0)); clip.AddLast(new Vector2(-1, 0)); clip.AddLast(new Vector2(0, 2)); clip.AddLast(new Vector2(0, -1)); clip.AddLast(new Vector2(-1, 0)); Draw(subject, clip, "Second has 1 shared vertex, second vertex lays on opposite side and adjacent side intersects opposite"); #endregion #region First partially overlays one side from inside subject.Clear(); clip.Clear(); clip.AddLast(new Vector2(-3, 0)); clip.AddLast(new Vector2(0, 3)); clip.AddLast(new Vector2(3, 0)); clip.AddLast(new Vector2(-3, 0)); subject.AddLast(new Vector2(-2, 0)); subject.AddLast(new Vector2(0, 2)); subject.AddLast(new Vector2(2, 0)); subject.AddLast(new Vector2(-2, 0)); Draw(subject, clip, "First partially overlays one side from inside"); #endregion #region First touches second from inside subject.Clear(); clip.Clear(); subject.AddLast(new Vector2(-1, 1)); subject.AddLast(new Vector2(1, 1)); subject.AddLast(new Vector2(0, 0)); subject.AddLast(new Vector2(-1, 1)); clip.AddLast(new Vector2(-3, 0)); clip.AddLast(new Vector2(0, 3)); clip.AddLast(new Vector2(3, 0)); clip.AddLast(new Vector2(-3, 0)); Draw(subject, clip, "First touches second from inside"); #endregion #region Second has 1 shared vertex, opposite side touches one vertex and adjacent side intesects opposite side of the first subject.Clear(); clip.Clear(); subject.AddLast(new Vector2(-3, 0)); subject.AddLast(new Vector2(0, 3)); subject.AddLast(new Vector2(3, 0)); subject.AddLast(new Vector2(-3, 0)); clip.AddLast(new Vector2(-3, 0)); clip.AddLast(new Vector2(-2, 3)); clip.AddLast(new Vector2(1, 3)); clip.AddLast(new Vector2(-3, 0)); Draw(subject, clip, "Second has 1 shared vertex, opposite side touches one vertex and adjacent side intesects opposite side of the first"); #endregion #region Second partially overlays one side and intersects adjacent side subject.Clear(); clip.Clear(); subject.AddLast(new Vector2(-3, 0)); subject.AddLast(new Vector2(0, 3)); subject.AddLast(new Vector2(3, 0)); subject.AddLast(new Vector2(-3, 0)); clip.AddLast(new Vector2(-2, 1)); clip.AddLast(new Vector2(-1, 2)); clip.AddLast(new Vector2(0, -1)); clip.AddLast(new Vector2(-2, 1)); Draw(subject, clip, "Second partially overlays one side and intersects adjacent side"); #endregion #region Second partially overlays one side and intersects other sides subject.Clear(); clip.Clear(); subject.AddLast(new Vector2(-3, 0)); subject.AddLast(new Vector2(0, 2)); subject.AddLast(new Vector2(3, 0)); subject.AddLast(new Vector2(-3, 0)); clip.AddLast(new Vector2(-1, 0)); clip.AddLast(new Vector2(0, 3)); clip.AddLast(new Vector2(1, 0)); clip.AddLast(new Vector2(-1, 0)); Draw(subject, clip, "Second partially overlays one side and intersects other sides"); #endregion #region Second has 1 vertex on side and intersects adjacent side subject.Clear(); clip.Clear(); subject.AddLast(new Vector2(-2, 0)); subject.AddLast(new Vector2(0, 2)); subject.AddLast(new Vector2(2, 0)); subject.AddLast(new Vector2(-2, 0)); clip.AddLast(new Vector2(-1, 1)); clip.AddLast(new Vector2(-1, 3)); clip.AddLast(new Vector2(1, 2)); clip.AddLast(new Vector2(-1, 1)); Draw(subject, clip, "Second has 1 vertex on side and intersects adjacent side"); #endregion #region Second has 1 vertex on side and intersects adjacent side containing 2 vertices inside subject.Clear(); clip.Clear(); subject.AddLast(new Vector2(-2, 0)); subject.AddLast(new Vector2(2, 1)); subject.AddLast(new Vector2(2, 0)); subject.AddLast(new Vector2(-2, 0)); clip.AddLast(new Vector2(0, 0.5f)); clip.AddLast(new Vector2(3, 2)); clip.AddLast(new Vector2(3, -1)); clip.AddLast(new Vector2(0, 0.5f)); Draw(subject, clip, "Second has 1 vertex on side and intersects adjacent side containing 2 vertices inside"); #endregion #region Second has 1 vertex on side and touches opposite vertex subject.Clear(); clip.Clear(); subject.AddLast(new Vector2(-3, 0)); subject.AddLast(new Vector2(0, 3)); subject.AddLast(new Vector2(3, 0)); subject.AddLast(new Vector2(-3, 0)); clip.AddLast(new Vector2(-3, 3)); clip.AddLast(new Vector2(3, 3)); clip.AddLast(new Vector2(0, 0)); clip.AddLast(new Vector2(-3, 3)); Draw(subject, clip, "Second has 1 vertex on side and touches opposite vertex"); #endregion //ICollection<CircularLinkedList<Vector2>> polys = WeilerAtherton.Process(subject, clip, Operation.Difference); #region Triangulaion //int c = 1; //foreach (CircularLinkedList<Vector2> poly in polys) //{ // #region Old non-hole triangulate // // Small test application demonstrating the usage of the triangulate // // class. // Console.WriteLine("Poly {0}", c++); // // Create a pretty complicated little contour by pushing them onto // // an stl vector. // // allocate an STL vector to hold the answer. // List<Vector2> result = new List<Vector2>(); // // Invoke the triangulator to triangulate this polygon. // if (!Triangulate.Process(new List<Vector2>(poly), result)) // Console.WriteLine("Triangulate failed!"); // // print out the results. // int tcount = result.Count / 3; // for (int i = 0; i < tcount; i++) // { // Vector2 p1 = result[i * 3 + 0]; // Vector2 p2 = result[i * 3 + 1]; // Vector2 p3 = result[i * 3 + 2]; // Console.WriteLine("Triangle {0} => ({1};{2}) ({3};{4}) ({5};{6})\n", i + 1, p1.X, p1.Y, p2.X, p2.Y, p3.X, p3.Y); // } // #endregion //} #endregion Console.WriteLine("Done"); Console.ReadKey(); }
// Builds a circular linked list with a_iIndexesCount index, from 0 to a_iIndexesCount - 1 private static CircularLinkedList<int> BuildContourVertexIndexesList( int a_iIndexesCount, int a_iIndexOffset ) { CircularLinkedList<int> oVertexIndexesList = new CircularLinkedList<int>( ); for( int iIndex = 0; iIndex < a_iIndexesCount; ++iIndex ) { oVertexIndexesList.AddLast( iIndex + a_iIndexesCount ); } return oVertexIndexesList; }
/// <summary> /// Performs algorithm and returns skeleton /// </summary> public List<Point2D> Skeleton() { List<Point2D> ret = new List<Point2D>(); int i = 0; while (Q.Count != 0) { Event currentEvent = Q.Dequeue(); CircularLinkedList<Vertex> currentLAV = SLAV[currentEvent.getLAVID()]; Console.WriteLine("------ Iteration " + i + " LAV ID " + currentEvent.getLAVID() + " ------"); if (currentLAV.Count > 0) { foreach (Vertex vertex in currentLAV) { if (vertex != null) { Console.WriteLine("Vertex with ID= " + vertex.getID() + (vertex.isActive() ? " is active " : " is not active")); } } Console.WriteLine("---------------------------------"); } i++; if (currentEvent.getType() == EventType.Edge) { Console.WriteLine("Edge event between " + currentEvent.getFirstPoint().getID() + " and " + currentEvent.getSecondPoint().getID()); Node<Vertex> prevNode = currentLAV.Find(currentEvent.getFirstPoint()); Node<Vertex> nextNode = currentLAV.Find(currentEvent.getSecondPoint()); //check if event is outdated if (prevNode == null || nextNode == null || (!prevNode.Value.isActive() && !nextNode.Value.isActive())) { Console.WriteLine("Skipped edge event"); continue; } Vertex prevV = prevNode.Value; Vertex nextV = nextNode.Value; //check if we remain to the last 3 points if (prevNode.PrevActive().PrevActive().Value.Equals(nextV)) { Point2D intersect = new Point2D(LineTools.LineIntersect(prevV.getPoint(), prevV.getRayStepPoint(), nextV.getPoint(), nextV.getRayStepPoint())); ret.Add(prevV.getPoint()); ret.Add(intersect); ret.Add(nextV.getPoint()); ret.Add(intersect); ret.Add(prevNode.PrevActive().Value.getPoint()); ret.Add(intersect); currentLAV.Find(prevV).Value.setActive(false); currentLAV.Find(nextV).Value.setActive(false); currentLAV.Find(prevV).PrevActive().Value.setActive(false); continue; } //output two arcs ret.Add(currentEvent.getFirstPoint().getPoint()); ret.Add(currentEvent.getIntersection()); ret.Add(currentEvent.getSecondPoint().getPoint()); ret.Add(currentEvent.getIntersection()); //modify list currentLAV.Find(currentEvent.getFirstPoint()).Value.setActive(false); currentLAV.Find(currentEvent.getSecondPoint()).Value.setActive(false); Point2D intersection = currentEvent.getIntersection(); if (!intersection.Equals(Point2D.Zero)) { Vertex newV = new Vertex(intersection, id++); newV.prevEdge = prevV.prevEdge; newV.nextEdge = nextV.nextEdge; newV.update(); Node<Vertex> newNode = new Node<Vertex>(newV); currentLAV.AddAfter(prevV, newV); //currentLAV.Remove(prevV); //currentLAV.Remove(nextV); findClosestIntersectionAndStore(currentLAV, currentLAV.Find(newV).PrevActive().Value, currentLAV.Find(newV).Value, currentLAV.Find(newV).NextActive().Value); } } else { Console.WriteLine("Split event " + currentEvent.getFirstPoint().getID()); Node<Vertex> prevNode = currentLAV.Find(currentEvent.getFirstPoint()); //check if event is outdated if (prevNode == null || !prevNode.Value.isActive()) { Console.WriteLine("Skipped split event"); continue; } Vertex prevV = prevNode.Value; prevV.setActive(false); //check if we remain to the last 3 points if (prevNode.PrevActive().PrevActive().Value.Equals(prevNode.NextActive().Value)) { Point2D intersect = new Point2D(LineTools.LineIntersect(prevV.getPoint(), prevV.getRayStepPoint(), prevNode.Next.Value.getPoint(), prevNode.Next.Value.getRayStepPoint())); ret.Add(prevNode.Value.getPoint()); ret.Add(intersect); ret.Add(prevNode.NextActive().Value.getPoint()); ret.Add(intersect); ret.Add(prevNode.PrevActive().Value.getPoint()); ret.Add(intersect); continue; } //output only VI ret.Add(prevV.getPoint()); ret.Add(currentEvent.getIntersection()); //split LAV reset que etc Vertex newNodeV1 = new Vertex(currentEvent.getIntersection(), id++); newNodeV1.prevEdge = currentEvent.getFirstPoint().prevEdge; newNodeV1.nextEdge = currentEvent.getFirstEdgePoint().nextEdge; newNodeV1.update(); Vertex newNodeV2 = new Vertex(currentEvent.getIntersection(), id++); newNodeV2.prevEdge = currentEvent.getFirstPoint().nextEdge; newNodeV2.nextEdge = currentEvent.getFirstEdgePoint().nextEdge; newNodeV2.update(); CircularLinkedList<Vertex> newLAV = new CircularLinkedList<Vertex>(); newLAV.AddFirst(newNodeV2); Node<Vertex> current = SLAV[currentEvent.getLAVID()].Find(currentEvent.getFirstPoint()); while(!current.Next.Value.Equals(currentEvent.getSecondEdgePoint())) { if (current.Next.Equals(current)) { break; } current = current.Next; newLAV.AddLast(current.Value); //current.Value.setActive(false); SLAV[currentEvent.getLAVID()].Remove(current.Value); } SLAV.Add(newLAV); SLAV[currentEvent.getLAVID()].AddAfter(currentEvent.getFirstPoint(),newNodeV1); //SLAV[currentEvent.getLAVID()].Find(currentEvent.getFirstPoint()).Value.setActive(false); //SLAV[currentEvent.getLAVID()].Remove(currentEvent.getFirstPoint()); //test for (int x = 0; x < newLAV.Count; x++) { Vertex prev = newLAV[x].PrevActive().Value; Vertex curr = newLAV[x].Value; Vertex next = newLAV[x].NextActive().Value; findClosestIntersectionAndStore(newLAV, prev, curr, next); } //findClosestIntersectionAndStore(newLAV, newLAV.Find(newNodeV2).PrevActive().Value, newLAV.Find(newNodeV2).Value, newLAV.Find(newNodeV2).NextActive().Value); findClosestIntersectionAndStore(SLAV[currentEvent.getLAVID()], SLAV[currentEvent.getLAVID()].Find(newNodeV1).PrevActive().Value, SLAV[currentEvent.getLAVID()].Find(newNodeV1).Value, SLAV[currentEvent.getLAVID()].Find(newNodeV1).NextActive().Value); } } return ret; }
// Returns true if the specified convex vertex is an ear tip private static bool IsEarTip( Vector3[ ] a_rMeshVertices, int a_iEarTipConvexVertexIndex, CircularLinkedList<int> a_rContourVertexIndexesList, LinkedList<int> a_rReflexVertexIndexesList ) { CircularLinkedListNode<int> rContourVertexNode = a_rContourVertexIndexesList.Find( a_iEarTipConvexVertexIndex ); int iPreviousContourVertexIndex = rContourVertexNode.Previous.Value; int iNextContourVertexIndex = rContourVertexNode.Next.Value; // Retrieve previous (i-1) / current (i) / next (i+1) vertices to form the triangle < Vi-1, Vi, Vi+1 > Vector3 f3ConvexContourVertex = a_rMeshVertices[ a_iEarTipConvexVertexIndex ]; Vector3 f3PreviousContourVertex = a_rMeshVertices[ iPreviousContourVertexIndex ]; Vector3 f3NextContourVertex = a_rMeshVertices[ iNextContourVertexIndex ]; // Look for an inner point into the triangle formed by the 3 vertices // Only need to look over the reflex vertices. for( LinkedListNode<int> rReflexIndexNode = a_rReflexVertexIndexesList.First; rReflexIndexNode != null; rReflexIndexNode = rReflexIndexNode.Next ) { // Retrieve the reflex vertex int iReflexContourVertexIndex = rReflexIndexNode.Value; // Is the point inside the triangle? // (Exclude the triangle points themselves) Vector3 f3ReflexContourVertex = a_rMeshVertices[ iReflexContourVertexIndex ]; if( f3ReflexContourVertex != f3PreviousContourVertex && f3ReflexContourVertex != f3ConvexContourVertex && f3ReflexContourVertex != f3NextContourVertex ) { if( Uni2DMathUtils.IsPointInsideTriangle( f3PreviousContourVertex, f3ConvexContourVertex, f3NextContourVertex, f3ReflexContourVertex ) == true ) { // Point is inside triangle: not an ear tip return false; } } } // No point inside the triangle: ear tip found! return true; }
// Builds and return a list of vertex indexes that are ear tips. private static CircularLinkedList<int> BuildEarTipVerticesList( Vector3[ ] a_rMeshVertices, CircularLinkedList<int> a_rOuterContourVertexIndexesList, LinkedList<int> a_rReflexVertexIndexesList, LinkedList<int> a_rConvexVertexIndexesList ) { CircularLinkedList<int> oEarTipVertexIndexesList = new CircularLinkedList<int>( ); // Iterate convex vertices for( LinkedListNode<int> rConvexIndexNode = a_rConvexVertexIndexesList.First; rConvexIndexNode != null; rConvexIndexNode = rConvexIndexNode.Next ) { // The convex vertex index int iConvexContourVertexIndex = rConvexIndexNode.Value; // Is the convex vertex is an ear tip? if( IsEarTip( a_rMeshVertices, iConvexContourVertexIndex, a_rOuterContourVertexIndexesList, a_rReflexVertexIndexesList ) == true ) { // Yes: adds it to the list oEarTipVertexIndexesList.AddLast( iConvexContourVertexIndex ); } } // Return the ear tip list return oEarTipVertexIndexesList; }
// Builds indexes lists of reflex and convex vertex private static void BuildReflexConvexVertexIndexesLists( Vector3[ ] a_rContourVerticesArray, CircularLinkedList<int> a_rContourVertexIndexesList, out LinkedList<int> a_rReflexVertexIndexesList, out LinkedList<int> a_rConvexVertexIndexesList ) { LinkedList<int> oReflexVertexIndexesList = new LinkedList<int>( ); LinkedList<int> oConvexVertexIndexesList = new LinkedList<int>( ); // Iterate contour vertices CircularLinkedListNode<int> rContourNode = a_rContourVertexIndexesList.First; do { int iContourVertexIndex = rContourNode.Value; Vector3 f3ContourVertex = a_rContourVerticesArray[ iContourVertexIndex ]; Vector3 f3PreviousContourVertex = a_rContourVerticesArray[ rContourNode.Previous.Value ]; Vector3 f3NextContourVertex = a_rContourVerticesArray[ rContourNode.Next.Value ]; // Sorting reflex / convex vertices // Reflex vertex forms a triangle with an angle >= 180° if( IsReflexVertex( f3ContourVertex, f3PreviousContourVertex, f3NextContourVertex ) == true ) { oReflexVertexIndexesList.AddLast( iContourVertexIndex ); } else // angle < 180° => Convex vertex { oConvexVertexIndexesList.AddLast( iContourVertexIndex ); } rContourNode = rContourNode.Next; } while( rContourNode != a_rContourVertexIndexesList.First ); // Transmit results a_rReflexVertexIndexesList = oReflexVertexIndexesList; a_rConvexVertexIndexesList = oConvexVertexIndexesList; }
// Returns a polygonized mesh from a 2D outer contour private static void EarClipping( Contour a_rDominantOuterContour, float a_fScale, Vector3 a_f3PivotPoint, float a_fWidth, float a_fHeight, out Vector3[ ] a_rVerticesArray, out int[ ] a_rTrianglesArray, out Vector2[ ] a_rUVs ) { // Sum of all contours count int iVerticesCount = a_rDominantOuterContour.Count; // Mesh vertices array a_rVerticesArray = new Vector3[ iVerticesCount ]; // Mesh UVs array a_rUVs = new Vector2[ iVerticesCount ]; // Vertex indexes lists array (used by ear clipping algorithm) CircularLinkedList<int> oVertexIndexesList = new CircularLinkedList<int>( ); // Build contour vertex index circular list // Store every Vector3 into mesh vertices array // Store corresponding index into the circular list int iVertexIndex = 0; foreach( Vector2 f2OuterContourVertex in a_rDominantOuterContour.Vertices ) { a_rVerticesArray[ iVertexIndex ] = f2OuterContourVertex; oVertexIndexesList.AddLast( iVertexIndex ); ++iVertexIndex; } // Build reflex/convex vertices lists LinkedList<int> rReflexVertexIndexesList; LinkedList<int> rConvexVertexIndexesList; BuildReflexConvexVertexIndexesLists( a_rVerticesArray, oVertexIndexesList, out rReflexVertexIndexesList, out rConvexVertexIndexesList ); // Triangles for this contour List<int> oTrianglesList = new List<int>( 3 * iVerticesCount ); // Build ear tips list CircularLinkedList<int> rEarTipVertexIndexesList = BuildEarTipVerticesList( a_rVerticesArray, oVertexIndexesList, rReflexVertexIndexesList, rConvexVertexIndexesList ); // Remove the ear tips one by one! while( rEarTipVertexIndexesList.Count > 0 && oVertexIndexesList.Count > 2 ) { CircularLinkedListNode<int> rEarTipNode = rEarTipVertexIndexesList.First; // Ear tip index int iEarTipVertexIndex = rEarTipNode.Value; // Ear vertex indexes CircularLinkedListNode<int> rContourVertexNode = oVertexIndexesList.Find( iEarTipVertexIndex ); CircularLinkedListNode<int> rPreviousAdjacentContourVertexNode = rContourVertexNode.Previous; CircularLinkedListNode<int> rNextAdjacentContourVertexNode = rContourVertexNode.Next; int iPreviousAjdacentContourVertexIndex = rPreviousAdjacentContourVertexNode.Value; int iNextAdjacentContourVertexIndex = rNextAdjacentContourVertexNode.Value; // Add the ear triangle to our triangles list oTrianglesList.Add( iPreviousAjdacentContourVertexIndex ); oTrianglesList.Add( iEarTipVertexIndex ); oTrianglesList.Add( iNextAdjacentContourVertexIndex ); // Remove the ear tip from vertices / convex / ear lists oVertexIndexesList.Remove( iEarTipVertexIndex ); rConvexVertexIndexesList.Remove( iEarTipVertexIndex ); // Adjacent n-1 vertex // if was convex => remain convex, can possibly an ear // if was an ear => can possibly not remain an ear // if was reflex => can possibly convex and possibly an ear if( rReflexVertexIndexesList.Contains( iPreviousAjdacentContourVertexIndex ) ) { CircularLinkedListNode<int> rPreviousPreviousAdjacentContourVertexNode = rPreviousAdjacentContourVertexNode.Previous; Vector3 f3AdjacentContourVertex = a_rVerticesArray[ rPreviousAdjacentContourVertexNode.Value ]; Vector3 f3PreviousAdjacentContourVertex = a_rVerticesArray[ rPreviousPreviousAdjacentContourVertexNode.Value ]; Vector3 f3NextAdjacentContourVertex = a_rVerticesArray[ rPreviousAdjacentContourVertexNode.Next.Value ]; if( IsReflexVertex( f3AdjacentContourVertex, f3PreviousAdjacentContourVertex, f3NextAdjacentContourVertex ) == false ) { rReflexVertexIndexesList.Remove( iPreviousAjdacentContourVertexIndex ); rConvexVertexIndexesList.AddFirst( iPreviousAjdacentContourVertexIndex ); } } // Adjacent n+1 vertex // if was convex => remain convex, can possibly an ear // if was an ear => can possibly not remain an ear // if was reflex => can possibly convex and possibly an ear if( rReflexVertexIndexesList.Contains( iNextAdjacentContourVertexIndex ) ) { CircularLinkedListNode<int> rNextNextAdjacentContourVertexNode = rNextAdjacentContourVertexNode.Next; Vector3 f3AdjacentContourVertex = a_rVerticesArray[ rNextAdjacentContourVertexNode.Value ]; Vector3 f3PreviousAdjacentContourVertex = a_rVerticesArray[ rNextAdjacentContourVertexNode.Previous.Value ]; Vector3 f3NextAdjacentContourVertex = a_rVerticesArray[ rNextNextAdjacentContourVertexNode.Value ]; if( IsReflexVertex( f3AdjacentContourVertex, f3PreviousAdjacentContourVertex, f3NextAdjacentContourVertex ) == false ) { rReflexVertexIndexesList.Remove( iNextAdjacentContourVertexIndex ); rConvexVertexIndexesList.AddFirst( iNextAdjacentContourVertexIndex ); } } if( rConvexVertexIndexesList.Contains( iPreviousAjdacentContourVertexIndex ) ) { if( IsEarTip( a_rVerticesArray, iPreviousAjdacentContourVertexIndex, oVertexIndexesList, rReflexVertexIndexesList ) ) { if( rEarTipVertexIndexesList.Contains( iPreviousAjdacentContourVertexIndex ) == false ) { rEarTipVertexIndexesList.AddLast( iPreviousAjdacentContourVertexIndex ); } } else { rEarTipVertexIndexesList.Remove( iPreviousAjdacentContourVertexIndex ); } } if( rConvexVertexIndexesList.Contains( iNextAdjacentContourVertexIndex ) ) { if( IsEarTip( a_rVerticesArray, iNextAdjacentContourVertexIndex, oVertexIndexesList, rReflexVertexIndexesList ) ) { if( rEarTipVertexIndexesList.Contains( iNextAdjacentContourVertexIndex ) == false ) { rEarTipVertexIndexesList.AddFirst( iNextAdjacentContourVertexIndex ); } } else { rEarTipVertexIndexesList.Remove( iNextAdjacentContourVertexIndex ); } } rEarTipVertexIndexesList.Remove( iEarTipVertexIndex ); } // Create UVs, rescale vertices, apply pivot Vector2 f2Dimensions = new Vector2( 1.0f / a_fWidth, 1.0f / a_fHeight ); for( iVertexIndex = 0; iVertexIndex < iVerticesCount; ++iVertexIndex ) { Vector3 f3VertexPos = a_rVerticesArray[ iVertexIndex ]; //a_rUVs[ iVertexIndex ] = Vector2.Scale( f3VertexPos, f2Dimensions ); a_rUVs[ iVertexIndex ] = new Vector2( f3VertexPos.x * f2Dimensions.x, f3VertexPos.y * f2Dimensions.y ); a_rVerticesArray[ iVertexIndex ] = ( f3VertexPos - a_f3PivotPoint ) * a_fScale; } a_rTrianglesArray = oTrianglesList.ToArray( ); }
private static void Traverse(CircularLinkedList<Vector2> subject, CircularLinkedList<Vector2> clip, CircularLinkedList<Vector2> entering, CircularLinkedList<Vector2> exiting, List<ICollection<Vector2>> polygons, Operation operation) { if (operation == Operation.Intersect) Misc.Swap<CircularLinkedList<Vector2>>(ref entering, ref exiting); if (operation == Operation.Difference) clip = clip.Reverse(); CircularLinkedList<Vector2> currentList = subject; CircularLinkedList<Vector2> otherList = clip; while (entering.Count > 0) { CircularLinkedList<Vector2> polygon = new CircularLinkedList<Vector2>(); Vector2 start = entering.First.Value; int count = 0; LinkedListNode<Vector2> transitionNode = entering.First; bool enteringCheck = true; while (transitionNode != null && (count == 0 || (count > 0 && start != transitionNode.Value))) { transitionNode = TraverseList(currentList, entering, exiting, polygon, transitionNode, start, otherList); enteringCheck = !enteringCheck; if (currentList == subject) { currentList = clip; otherList = subject; } else { currentList = subject; otherList = clip; } count++; } polygons.Add(polygon); } }
private OwnVector2 findNearestOppositeEdge(CircularLinkedList<Vertex> LAV, Vertex current, out Vertex firstEdgePoint, out Vertex secondEdgePoint) { firstEdgePoint = null; secondEdgePoint = null; Node<Vertex> temp = LAV.Find(current).Next; Point2D intersectionPoint = new Point2D(0,0); Point2D currentClosest = new Point2D(0, 0); Vertices testPoly = new Vertices(); foreach(Vertex v in LAV) { testPoly.Add(v.getPoint()); } while (!temp.Next.Value.Equals(current)) { //check if the edge is not behind the vertex if(LineTools.LineIntersect( current.getRayStart(), new Point2D(current.getRayStart().X + (-current.getRayDirection().X * int.MaxValue), -current.getRayStart().Y + (-current.getRayDirection().Y * int.MaxValue)), temp.Value.getPoint(), temp.Next.Value.getPoint(), true,false, out intersectionPoint)) { //Calc Bi (intersection ray current + bisector of triangle) Point2D intersect1 = new Point2D(LineTools.LineIntersect( current.prevEdge.getFirstPoint(), current.prevEdge.getSecondPoint(), temp.Value.getPoint(), temp.Next.Value.getPoint())); Point2D intersect2 = new Point2D(LineTools.LineIntersect( current.nextEdge.getFirstPoint(), current.nextEdge.getSecondPoint(), temp.Value.getPoint(), temp.Next.Value.getPoint())); Vertices tempVer = new Vertices(); tempVer.Add(current.getPoint()); tempVer.Add(intersect1); tempVer.Add(intersect2); Vertex edgeBisector1 = new Vertex(intersect1, -1); edgeBisector1.prevEdge = new Edge(current.getPoint(), intersect1); edgeBisector1.nextEdge = new Edge(intersect1, intersect2); edgeBisector1.update(); Point2D Bi = new Point2D(LineTools.LineIntersect( current.getRayStart(), current.getRayStepPoint(), edgeBisector1.getRayStart(), edgeBisector1.getRayStepPoint())); if (tempVer.PointInPolygon(ref Bi) == -1) { edgeBisector1 = new Vertex(intersect2, -1); edgeBisector1.prevEdge = new Edge(current.getPoint(), intersect2); edgeBisector1.nextEdge = new Edge(intersect2, intersect1); edgeBisector1.update(); Bi = new Point2D(LineTools.LineIntersect( current.getRayStart(), current.getRayStepPoint(), edgeBisector1.getRayStart(), edgeBisector1.getRayStepPoint())); if (tempVer.PointInPolygon(ref Bi) == -1) { temp = temp.Next; continue; } } //check if Bi inside polygon to begin with if (testPoly.PointInPolygon(ref Bi) == -1) { temp = temp.Next; continue; } //check if Bi is in area defined by opposing edge and it's bisectors //first check if both bisectors of edge are convex so we can see if Bi is inside the defined triangle if(temp.Value.isConvex() && temp.Next.Value.isConvex()) { OwnVector2 trianglePoint = LineTools.LineIntersect( temp.Value.getRayStart(), temp.Value.getRayStepPoint(), temp.Next.Value.getRayStart(), temp.Next.Value.getRayStepPoint()); if (!MathHelper.PointInTriangle(trianglePoint, temp.Value.getPoint(), temp.Next.Value.getPoint(), Bi)) { temp = temp.Next; continue; } } else{ Vertices test = new Vertices(); int sign1 = temp.Value.isConvex() ? 1 : -1; int sign2 = temp.Next.Value.isConvex() ? 1 : -1; test.Add(temp.Value.getPoint()); test.Add(temp.Next.Value.getPoint()); test.Add(new Point2D( temp.Next.Value.getPoint().X + (sign2 * temp.Next.Value.getRayDirection().X * int.MaxValue), temp.Next.Value.getPoint().Y + (sign2 * temp.Next.Value.getRayDirection().Y * int.MaxValue))); test.Add(new Point2D( temp.Value.getPoint().X + (sign1 * temp.Value.getRayDirection().X * int.MaxValue), temp.Value.getPoint().Y + (sign1 * temp.Value.getRayDirection().Y * int.MaxValue))); if (test.PointInPolygon(ref Bi) == -1) { temp = temp.Next; continue; } } if (currentClosest.Equals(Point2D.Zero) || Point2D.Distance(current.getPoint(), currentClosest) > Point2D.Distance(current.getPoint(), Bi)) { currentClosest = Bi; firstEdgePoint = temp.Value; secondEdgePoint = temp.Next.Value; } } temp = temp.Next; } testDots.Add(currentClosest); return currentClosest; }
/// <summary> /// Setup all the necessary lists for the algorithm to work /// </summary> private void setup() { //initialize SLAV SLAV = new List<CircularLinkedList<Vertex>>(); //initialize priority queue Q Q = new HeapPriorityQueue<Event>(500); //initialize first LAV CircularLinkedList<Vertex> LAV = new CircularLinkedList<Vertex>(); for (int i = 0; i < polygon.ControlVertices.Count; i++) { //Create vertex for each controlpoint and store edges + calc bisector ray Vertex vertex = new Vertex(polygon.ControlVertices[i], id++); vertex.prevEdge = new Edge(polygon.ControlVertices.PreviousVertex(i), vertex.getPoint()); vertex.nextEdge = new Edge(vertex.getPoint(), polygon.ControlVertices.NextVertex(i)); vertex.update(); //Add them to initial LAV LAV.AddLast(vertex); } SLAV.Add(LAV); //initial event creation testDots = new List<OwnVector2>(); for(int i = 0; i < LAV.Count; i++) { Vertex prev = LAV[i].Previous.Value; Vertex current = LAV[i].Value; Vertex next = LAV[i].Next.Value; findClosestIntersectionAndStore(LAV, prev, current, next); } }
private static void Draw(CircularLinkedList<Vector2> subject, CircularLinkedList<Vector2> clip, string imageName) { firstTriangle = GetTrianglePointArray(subject); secondTriangle = GetTrianglePointArray(clip); Plotter.Draw(firstTriangle, secondTriangle, imageName, true); }
private void findClosestIntersectionAndStore(CircularLinkedList<Vertex> LAV, Vertex prev, Vertex current, Vertex next) { Vertices testPoly = new Vertices(); foreach (Vertex v in LAV) { testPoly.Add(v.getPoint()); } OwnVector2 prevIntersection = LineTools.LineIntersect( prev.getRayStart(), prev.getRayStepPoint(), current.getRayStart(), current.getRayStepPoint()); OwnVector2 nextIntersection = LineTools.LineIntersect( current.getRayStart(), current.getRayStepPoint(), next.getRayStart(), next.getRayStepPoint()); OwnVector2 nearestOppositeIntersection = OwnVector2.Zero; Point2D testPrev = new Point2D(prevIntersection); if (testPoly.PointInPolygon(ref testPrev) == -1) { prevIntersection = Point2D.Zero; } Point2D testNext = new Point2D(nextIntersection); if (testPoly.PointInPolygon(ref testNext) == -1) { nextIntersection = Point2D.Zero; } Vertex firstEdgePoint = null; Vertex secondEdgePoint = null; if(current.isConcave()) { nearestOppositeIntersection = findNearestOppositeEdge(LAV, current, out firstEdgePoint, out secondEdgePoint); } float distPrev = prevIntersection.Equals(Point2D.Zero) ? float.MaxValue : OwnVector2.Distance(current.getPoint(), prevIntersection); float distNext = nextIntersection.Equals(Point2D.Zero) ? float.MaxValue : OwnVector2.Distance(current.getPoint(), nextIntersection); float distOpposite = float.MaxValue; if (distPrev == 0) { prevIntersection = Point2D.Zero; } if (distNext == 0) { nextIntersection = Point2D.Zero; } if (current.isConcave()) { distOpposite = OwnVector2.Distance(current.getPoint(), nearestOppositeIntersection); } if (prevIntersection.Equals(OwnVector2.Zero) && nextIntersection.Equals(OwnVector2.Zero) && nearestOppositeIntersection.Equals(OwnVector2.Zero)) { return; } if ((nextIntersection.Equals(OwnVector2.Zero) && nearestOppositeIntersection.Equals(OwnVector2.Zero)) || distPrev < distNext && distPrev < distOpposite) { Event e = new Event(new Point2D(prevIntersection), SLAV.IndexOf(LAV), EventType.Edge); e.storeFirstPoint(prev); e.storeSecondPoint(current); Q.Enqueue(e, distPrev); } else if ((nearestOppositeIntersection.Equals(OwnVector2.Zero) && prevIntersection.Equals(OwnVector2.Zero)) || distNext <= distPrev && distNext <= distOpposite) { Event e = new Event(new Point2D(nextIntersection), SLAV.IndexOf(LAV), EventType.Edge); e.storeFirstPoint(current); e.storeSecondPoint(next); Q.Enqueue(e, distNext); } else { Event e = new Event(new Point2D(nearestOppositeIntersection), SLAV.IndexOf(LAV), EventType.Split); e.storeFirstPoint(current); e.storeFirstEdgePoint(firstEdgePoint); e.storeSecondEdgePoint(secondEdgePoint); Q.Enqueue(e, distOpposite); } }