Ejemplo n.º 1
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;
            }
        }
        public CircularLinkedList <T> Reverse()
        {
            CircularLinkedList <T> temp = new CircularLinkedList <T>();

            foreach (var current in this)
            {
                temp.AddFirst(current);
            }

            return(temp);
        }
Ejemplo n.º 3
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);
        }
Ejemplo n.º 4
0
        private static void Traverse(CircularLinkedList <Vector2> subject,
                                     CircularLinkedList <Vector2> clip,
                                     CircularLinkedList <Vector2> entering,
                                     CircularLinkedList <Vector2> exiting,
                                     List <CircularLinkedList <Vector2> > polygons,
                                     Operation operation)
        {
            if (operation == Operation.Intersect)
            {
                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);
            }
        }
Ejemplo n.º 5
0
        private static LinkedListNode <Vector2> TraverseList(CircularLinkedList <Vector2> contour,
                                                             CircularLinkedList <Vector2> entering,
                                                             CircularLinkedList <Vector2> exiting,
                                                             CircularLinkedList <Vector2> polygon,
                                                             LinkedListNode <Vector2> currentNode,
                                                             Vector2 startNode,
                                                             CircularLinkedList <Vector2> contour2)
        {
            LinkedListNode <Vector2> contourNode = contour.Find(currentNode.Value);

            if (contourNode == null)
            {
                return(null);
            }

            entering.Remove(currentNode.Value);

            while (contourNode != null
                   &&
                   !entering.Contains(contourNode.Value)
                   &&
                   !exiting.Contains(contourNode.Value)
                   )
            {
                polygon.AddLast(contourNode.Value);
                contourNode = contour.NextOrFirst(contourNode);

                if (contourNode.Value == startNode)
                {
                    return(null);
                }
            }

            entering.Remove(contourNode.Value);
            polygon.AddLast(contourNode.Value);

            return(contour2.NextOrFirst(contour2.Find(contourNode.Value)));
        }
Ejemplo n.º 6
0
        /// <summary>
        ///
        /// </summary>
        /// <param name="subject">Первый контур.</param>
        /// <param name="clip">Второй контур.</param>
        /// <param name="operation">Операция, проводимая над контурами.</param>
        /// <returns></returns>
        public static ICollection <CircularLinkedList <Vector2> > Process(CircularLinkedList <Vector2> subject,
                                                                          CircularLinkedList <Vector2> clip,
                                                                          Operation operation)
        {
            LinkedListNode <Vector2> curSubject = subject.First;
            Dictionary <Vector2, Pair <Vector2> > intersections = new Dictionary <Vector2, Pair <Vector2> >();
            List <CircularLinkedList <Vector2> >  polygons      = new List <CircularLinkedList <Vector2> >();

            if (AreEqual <Vector2>(subject, clip))
            {
                switch (operation)
                {
                case Operation.Union:
                    polygons.Add(subject);
                    return(polygons);

                    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);
        }
Ejemplo n.º 7
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();
        }
Ejemplo n.º 8
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);
 }