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);
        }
Exemplo n.º 2
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);
        }
Exemplo n.º 3
0
        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;
        }
Exemplo n.º 4
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);
        }
Exemplo n.º 5
0
        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);
        }
Exemplo n.º 8
0
        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);
        }
Exemplo n.º 9
0
        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);
                }
            }
        }
Exemplo n.º 10
0
        /// <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);
        }
Exemplo n.º 11
0
    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();
    }
Exemplo n.º 12
0
        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);
        }
Exemplo n.º 14
0
 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");
        }
Exemplo n.º 16
0
        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);
        }
Exemplo n.º 17
0
        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]);
Exemplo n.º 18
0
    //拉丁方阵问题
    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);
    }
Exemplo n.º 19
0
        /// <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));
        }
Exemplo n.º 20
0
        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.");
        }
Exemplo n.º 22
0
        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);
        }
Exemplo n.º 26
0
        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");
 }
Exemplo n.º 28
0
        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;
                }
            }
        }
Exemplo n.º 29
0
 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;
     }
 }
Exemplo n.º 30
0
    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);
    }
Exemplo n.º 31
0
 // 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;
 }
Exemplo n.º 32
0
 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;
 }
Exemplo n.º 33
0
        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;
        }
Exemplo n.º 34
0
 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(" ");
 }
Exemplo n.º 35
0
        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;
            }
        }
Exemplo n.º 36
0
        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));
        }
Exemplo n.º 37
0
        /// <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;
        }
Exemplo n.º 38
0
        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( );
	}
Exemplo n.º 45
0
        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);
            }
        }
Exemplo n.º 48
0
 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);
            }
        }