コード例 #1
0
        private static void InWhichOrderAreVerticesAdded(List <ClipVertex> polyList)
        {
            ClipVertex thisVertex = polyList[0];

            float size = 0.01f;

            int safety = 0;

            while (true)
            {
                Gizmos.color = Color.red;

                //Gizmos.DrawWireSphere(new Vector3(thisVertex.coordinate.x, 0f, thisVertex.coordinate.y), size);

                size += 0.01f;

                thisVertex = thisVertex.next;

                //We are back at the first vertex
                if (thisVertex.Equals(polyList[0]))
                {
                    break;
                }

                safety += 1;

                if (safety > 100000)
                {
                    Debug.Log("Endless loop in debug in which orders are vertices added");

                    break;
                }
            }
        }
コード例 #2
0
        //
        // Debug
        //
        private static void DebugEntryExit(List <ClipVertex> polyList)
        {
            ClipVertex thisVertex = polyList[0];

            Gizmos.color = Color.green;

            //Gizmos.DrawWireSphere(new Vector3(thisVertex.coordinate.x, 0f, thisVertex.coordinate.y), 0.1f);

            float size = 0.02f;

            int safety = 0;

            while (true)
            {
                if (thisVertex.isIntersection)
                {
                    //Gizmos.color = Color.white;

                    //Debug.Log(thisVertex.neighbor);

                    //Gizmos.DrawWireSphere(new Vector3(thisVertex.neighbor.coordinate.x, 0f, thisVertex.neighbor.coordinate.y), 0.05f);


                    Gizmos.color = Color.yellow;

                    if (thisVertex.isEntry)
                    {
                        //Gizmos.color = Color.white;

                        //Gizmos.DrawWireSphere(new Vector3(thisVertex.next.coordinate.x, 0f, thisVertex.next.coordinate.y), 0.04f);

                        Gizmos.color = Color.red;
                    }

                    //Gizmos.DrawWireSphere(new Vector3(thisVertex.coordinate.x, 0f, thisVertex.coordinate.y), size);

                    size += 0.005f;
                }

                thisVertex = thisVertex.next;

                //We are back at the first vertex
                if (thisVertex.Equals(polyList[0]))
                {
                    break;
                }


                safety += 1;

                if (safety > 100000)
                {
                    Debug.Log("Endless loop in debug entry exit");

                    break;
                }
            }
        }
コード例 #3
0
        //Insert intersection vertex
        private static ClipVertex InsertIntersectionVertex(MyVector2 a, MyVector2 b, MyVector2 intersectionPoint, ClipVertex currentVertex)
        {
            //Calculate alpha which is how far the intersection coordinate is between a and b
            //so we can insert this vertex at the correct position
            //pos = start + dir * alpha
            float alpha = MyVector2.SqrMagnitude(a - intersectionPoint) / MyVector2.SqrMagnitude(a - b);

            //Debug.Log(alpha);

            //Create a new vertex
            ClipVertex intersectionVertex = new ClipVertex(intersectionPoint);

            intersectionVertex.isIntersection = true;
            intersectionVertex.alpha          = alpha;

            //Now we need to insert this intersection point somewhere after currentVertex
            ClipVertex insertAfterThisVertex = currentVertex;

            int safety = 0;

            while (true)
            {
                //If the next vertex is an intersectionvertex with a higher alpha
                //or if the next vertex is not an intersectionvertex, we cant improve, so break
                if (insertAfterThisVertex.next.alpha > alpha || !insertAfterThisVertex.next.isIntersection)
                {
                    break;
                }

                insertAfterThisVertex = insertAfterThisVertex.next;

                safety += 1;

                if (safety > 100000)
                {
                    Debug.Log("Stuck in loop in insert intersection vertices");

                    break;
                }
            }

            //Connect the vertex to the surrounding vertices
            intersectionVertex.next = insertAfterThisVertex.next;

            intersectionVertex.prev = insertAfterThisVertex;

            insertAfterThisVertex.next.prev = intersectionVertex;

            insertAfterThisVertex.next = intersectionVertex;

            return(intersectionVertex);
        }
コード例 #4
0
        //Mark entry exit points
        private static void MarkEntryExit(List <ClipVertex> poly, List <MyVector2> clipPolyVector)
        {
            //First see if the first vertex starts inside or outside (we can use the original list)
            bool isInside = _Intersections.PointPolygon(clipPolyVector, poly[0].coordinate);

            //Debug.Log(isInside);

            ClipVertex currentVertex = poly[0];

            ClipVertex firstVertex = currentVertex;

            int safety = 0;

            while (true)
            {
                if (currentVertex.isIntersection)
                {
                    //If we were outside, this is an entry
                    currentVertex.isEntry = isInside ? false : true;

                    //Now we know we are either inside or outside
                    isInside = !isInside;
                }

                currentVertex = currentVertex.next;

                //We have travelled around the entire polygon
                if (currentVertex.Equals(firstVertex))
                {
                    break;
                }

                safety += 1;

                if (safety > 100000)
                {
                    Debug.Log("Endless loop in mark entry exit");

                    break;
                }
            }
        }
コード例 #5
0
        //Find the the first entry vertex in a polygon
        private static ClipVertex FindFirstEntryVertex(List <ClipVertex> poly)
        {
            ClipVertex thisVertex = poly[0];

            ClipVertex firstVertex = thisVertex;

            int safety = 0;

            while (true)
            {
                //Is this an available entry vertex?
                if (thisVertex.isIntersection && thisVertex.isEntry && !thisVertex.isTakenByFinalPolygon)
                {
                    //We have found the first vertex
                    break;
                }

                thisVertex = thisVertex.next;

                //We have travelled the entire polygon without finding an available entry vertex
                if (thisVertex.Equals(firstVertex))
                {
                    thisVertex = null;

                    break;
                }

                safety += 1;

                if (safety > 100000)
                {
                    Debug.Log("Endless loop in find first entry vertex");

                    break;
                }
            }

            return(thisVertex);
        }
コード例 #6
0
        //We may end up with several polygons, so this will split the connected list into one list per polygon
        private static void AddPolygonToList(List <ClipVertex> verticesToAdd, List <List <MyVector2> > finalPoly, bool shouldReverse)
        {
            List <MyVector2> thisPolyList = new List <MyVector2>();

            finalPoly.Add(thisPolyList);

            for (int i = 0; i < verticesToAdd.Count; i++)
            {
                ClipVertex v = verticesToAdd[i];

                thisPolyList.Add(v.coordinate);

                //Have we found a new polygon?
                if (v.nextPoly != null)
                {
                    //If we are finding the !intersection, the vertices will be clockwise
                    //so we should reverse the list to make it easier to triangulate
                    if (shouldReverse)
                    {
                        thisPolyList.Reverse();
                    }

                    thisPolyList = new List <MyVector2>();

                    finalPoly.Add(thisPolyList);

                    //Debug.Log("test");
                }

                //Debug.Log(v.nextPoly);
            }

            //Reverse the last list added
            if (shouldReverse)
            {
                finalPoly[finalPoly.Count - 1].Reverse();
            }
        }
コード例 #7
0
        //Reset vertices before we find the final polygon(s)
        private static void ResetVertices(List <ClipVertex> poly)
        {
            ClipVertex resetVertex = poly[0];

            int safety = 0;

            while (true)
            {
                //Reset
                resetVertex.isTakenByFinalPolygon = false;
                resetVertex.nextPoly = null;

                //Dont forget to reset the neighbor
                if (resetVertex.isIntersection)
                {
                    resetVertex.neighbor.isTakenByFinalPolygon = false;
                }

                resetVertex = resetVertex.next;

                //All vertices are reset
                if (resetVertex.Equals(poly[0]))
                {
                    break;
                }

                safety += 1;

                if (safety > 100000)
                {
                    Debug.Log("Endless loop in reset vertices");

                    break;
                }
            }
        }
コード例 #8
0
        //Get the clipped polygons: either the intersection or the !intersection
        //We might end up with more than one polygon and they are connected via clipvertex nextpoly
        //To get the intersection, we should
        //Traverese the polygon until an intersection is encountered. Add this intersection to the clipped polygon.
        //Traversal direction is determined by the entry/exit bool.
        // - If the intersection is an entry, move forward along the current polygon
        // - If the intersection is an exit, then change polygon, proceed in the backward direction of the other polygon
        // - Change polygon if a new intersection is found
        //If we want to the !intersection, we just travel in the reverse direction from the first intersection vertex
        private static List <ClipVertex> GetClippedPolygon(List <ClipVertex> poly, bool getIntersectionPolygon)
        {
            List <ClipVertex> finalPolygon = new List <ClipVertex>();


            //First we have to reset in case we are repeating this method several times depending on the type of boolean operation
            ResetVertices(poly);


            //Find the first intersection point which is always where we start
            ClipVertex thisVertex = FindFirstEntryVertex(poly);

            //Save this so we know when to stop the algortihm
            ClipVertex firstVertex = thisVertex;

            finalPolygon.Add(thisVertex);

            thisVertex.isTakenByFinalPolygon          = true;
            thisVertex.neighbor.isTakenByFinalPolygon = true;

            //These rows is the only part thats different if we want to get the intersection or the !intersection
            //Are needed once again if there are more than one polygon
            bool isMovingForward = getIntersectionPolygon ? true : false;

            thisVertex = getIntersectionPolygon ? thisVertex.next : thisVertex.prev;

            int safety = 0;

            while (true)
            {
                if (thisVertex.Equals(firstVertex) || (thisVertex.neighbor != null && thisVertex.neighbor.Equals(firstVertex)))
                {
                    //Debug.Log("Found a polygon with: " + finalPolygon.Count + " vertices");

                    //Debug.Log("Intersection vertices: " + intersectionVertices.Count);

                    //Try to find the next intersection point in case we end up with more than one polygon
                    ClipVertex nextVertex = FindFirstEntryVertex(poly);

                    //Stop if we are out of intersection vertices
                    if (nextVertex == null)
                    {
                        //Debug.Log("No more polygons can be found");

                        break;
                    }
                    //Find an entry vertex and start over with another polygon
                    else
                    {
                        //Debug.Log("Find another polygon");

                        //Debug.Log(thisVertex.nextPoly);

                        //Need to connect the polygons
                        finalPolygon[finalPolygon.Count - 1].nextPoly = nextVertex;


                        //Change to a new polygon
                        thisVertex = nextVertex;

                        firstVertex = nextVertex;

                        finalPolygon.Add(thisVertex);

                        thisVertex.isTakenByFinalPolygon          = true;
                        thisVertex.neighbor.isTakenByFinalPolygon = true;

                        //Do we want to get the intersection or the !intersection
                        isMovingForward = getIntersectionPolygon ? true : false;

                        thisVertex = getIntersectionPolygon ? thisVertex.next : thisVertex.prev;
                    }
                }


                //If this is not an intersection, then just add it
                if (!thisVertex.isIntersection)
                {
                    finalPolygon.Add(thisVertex);

                    //And move in the direction we are moving
                    thisVertex = isMovingForward ? thisVertex.next : thisVertex.prev;
                }
                else
                {
                    thisVertex.isTakenByFinalPolygon          = true;
                    thisVertex.neighbor.isTakenByFinalPolygon = true;

                    //Jump to the other polygon
                    thisVertex = thisVertex.neighbor;

                    finalPolygon.Add(thisVertex);

                    //Move forward/ back depending on if this is an entry / exit vertex and if we want to find the intersection or not
                    if (getIntersectionPolygon)
                    {
                        isMovingForward = thisVertex.isEntry ? true : false;

                        thisVertex = thisVertex.isEntry ? thisVertex.next : thisVertex.prev;
                    }
                    else
                    {
                        isMovingForward = !isMovingForward;

                        thisVertex = isMovingForward ? thisVertex.next : thisVertex.prev;
                    }
                }

                safety += 1;

                if (safety > 100000)
                {
                    Debug.Log("Endless loop when creating clipped polygon");

                    //Debug.Log(isMovingForward);

                    break;
                }
            }


            //Debug
            //float size = 0.02f;

            //for (int i = 0; i < finalPolygon.Count; i++)
            //{
            //    int iMinusOne = MathUtility.ClampListIndex(i - 1, finalPolygon.Count);

            //    Vector3 v1 = new Vector3(finalPolygon[i].coordinate.x, 0f, finalPolygon[i].coordinate.y);

            //    Vector3 v2 = new Vector3(finalPolygon[iMinusOne].coordinate.x, 0f, finalPolygon[iMinusOne].coordinate.y);

            //    Gizmos.color = Color.white;

            //    Gizmos.DrawWireSphere(v1, size);

            //    Gizmos.DrawLine(v1, v2);

            //    size += 0.005f;
            //}

            //Debug.Log(finalPolygon.Count);

            return(finalPolygon);
        }
コード例 #9
0
        public static List <List <MyVector2> > ClipPolygons(List <MyVector2> polyVector2, List <MyVector2> clipPolyVector2, BooleanOperation booleanOperation)
        {
            List <List <MyVector2> > finalPoly = new List <List <MyVector2> >();



            //Step 0. Create the data structure needed
            List <ClipVertex> poly = InitDataStructure(polyVector2);

            List <ClipVertex> clipPoly = InitDataStructure(clipPolyVector2);



            //Step 1. Find intersection points
            //Need to test if we have found an intersection point,
            //if none is found, the polygons dont intersect, or one polygon is inside the other
            bool hasFoundIntersection = false;

            for (int i = 0; i < poly.Count; i++)
            {
                ClipVertex currentVertex = poly[i];

                //Important to use iPlusOne because poly.next may change
                int iPlusOne = MathUtility.ClampListIndex(i + 1, poly.Count);

                MyVector2 a = poly[i].coordinate;

                MyVector2 b = poly[iPlusOne].coordinate;

                //Gizmos.DrawWireSphere(poly[i].coordinate, 0.02f);
                //Gizmos.DrawWireSphere(poly[i].next.coordinate, 0.02f);

                for (int j = 0; j < clipPoly.Count; j++)
                {
                    int jPlusOne = MathUtility.ClampListIndex(j + 1, clipPoly.Count);

                    MyVector2 c = clipPoly[j].coordinate;

                    MyVector2 d = clipPoly[jPlusOne].coordinate;

                    //Are these lines intersecting?
                    if (_Intersections.LineLine(a, b, c, d, true))
                    {
                        hasFoundIntersection = true;

                        MyVector2 intersectionPoint2D = _Intersections.GetLineLineIntersectionPoint(a, b, c, d);

                        //Vector3 intersectionPoint = new Vector3(intersectionPoint2D.x, 0f, intersectionPoint2D.y);

                        //Gizmos.color = Color.red;

                        //Gizmos.DrawWireSphere(intersectionPoint, 0.04f);

                        //We need to insert this intersection vertex into both polygons
                        //Insert into the polygon
                        ClipVertex vertexOnPolygon = InsertIntersectionVertex(a, b, intersectionPoint2D, currentVertex);

                        //Insert into the clip polygon
                        ClipVertex vertexOnClipPolygon = InsertIntersectionVertex(c, d, intersectionPoint2D, clipPoly[j]);

                        //Also connect the intersection vertices with each other
                        vertexOnPolygon.neighbor = vertexOnClipPolygon;

                        vertexOnClipPolygon.neighbor = vertexOnPolygon;
                    }
                }
            }


            //Debug in which order the vertices are in the linked list
            //InWhichOrderAreVerticesAdded(poly);

            //InWhichOrderAreVerticesAdded(clipPoly);



            //If the polygons are intersecting
            if (hasFoundIntersection)
            {
                //Step 2. Trace each polygon and mark entry and exit points to the other polygon's interior
                MarkEntryExit(poly, clipPolyVector2);

                MarkEntryExit(clipPoly, polyVector2);

                //Debug entry exit points
                DebugEntryExit(poly);
                //DebugEntryExit(clipPoly);



                //Step 3. Create the desired clipped polygon
                if (booleanOperation == BooleanOperation.Intersection)
                {
                    //Where the two polygons intersect
                    List <ClipVertex> intersectionVertices = GetClippedPolygon(poly, true);

                    //Debug.Log(intersectionVertices.Count);

                    AddPolygonToList(intersectionVertices, finalPoly, false);

                    //Debug.Log();
                }
                else if (booleanOperation == BooleanOperation.Difference)
                {
                    //Whats outside of the polygon that doesnt intersect
                    List <ClipVertex> outsidePolyVertices = GetClippedPolygon(poly, false);

                    AddPolygonToList(outsidePolyVertices, finalPoly, true);
                }
                else if (booleanOperation == BooleanOperation.ExclusiveOr)
                {
                    //Whats outside of the polygon that doesnt intersect
                    List <ClipVertex> outsidePolyVertices = GetClippedPolygon(poly, false);

                    AddPolygonToList(outsidePolyVertices, finalPoly, true);

                    //Whats outside of the polygon that doesnt intersect
                    List <ClipVertex> outsideClipPolyVertices = GetClippedPolygon(clipPoly, false);

                    AddPolygonToList(outsideClipPolyVertices, finalPoly, true);
                }
                else if (booleanOperation == BooleanOperation.Union)
                {
                    //Where the two polygons intersect
                    List <ClipVertex> intersectionVertices = GetClippedPolygon(poly, true);

                    AddPolygonToList(intersectionVertices, finalPoly, false);

                    //Whats outside of the polygon that doesnt intersect
                    List <ClipVertex> outsidePolyVertices = GetClippedPolygon(poly, false);

                    AddPolygonToList(outsidePolyVertices, finalPoly, true);

                    //Whats outside of the polygon that doesnt intersect
                    List <ClipVertex> outsideClipPolyVertices = GetClippedPolygon(clipPoly, false);

                    AddPolygonToList(outsideClipPolyVertices, finalPoly, true);
                }

                //Where the two polygons intersect
                //List<ClipVertex> intersectionVertices = GetClippedPolygon(poly, true);
                //Whats outside of the polygon that doesnt intersect
                //These will be in clockwise order so remember to change to counter clockwise
                //List<ClipVertex> outsidePolyVertices = GetClippedPolygon(poly, false);
                //List<ClipVertex> outsideClipPolyVertices = GetClippedPolygon(clipPoly, false);
            }
            //Check if one polygon is inside the other
            else
            {
                //Is the polygon inside the clip polygon?
                //Depending on the type of boolean operation, we might get a hole
                if (IsPolygonInsidePolygon(polyVector2, clipPolyVector2))
                {
                    Debug.Log("Poly is inside clip poly");
                }
                else if (IsPolygonInsidePolygon(clipPolyVector2, polyVector2))
                {
                    Debug.Log("Clip poly is inside poly");
                }
                else
                {
                    Debug.Log("Polygons are not intersecting");
                }
            }

            return(finalPoly);
        }