Example #1
0
        public static PolygonUtil.PolyUnionError PolygonOperation(PolygonOperationContext ctx)
        {
            if ((ctx.mOperations & PolygonUtil.PolyOperation.Union) == PolygonUtil.PolyOperation.Union)
            {
                PolygonUtil.PolygonUnionInternal(ctx);
            }
            if ((ctx.mOperations & PolygonUtil.PolyOperation.Intersect) == PolygonUtil.PolyOperation.Intersect)
            {
                PolygonUtil.PolygonIntersectInternal(ctx);
            }
            if ((ctx.mOperations & PolygonUtil.PolyOperation.Subtract) == PolygonUtil.PolyOperation.Subtract)
            {
                PolygonUtil.PolygonSubtractInternal(ctx);
            }

            return ctx.mError;
        }
Example #2
0
 /// <summary>
 /// Performs one or more polygon operations on the 2 provided polygons
 /// </summary>
 /// <param name="polygon1">The first polygon.</param>
 /// <param name="polygon2">The second polygon</param>
 /// <param name="subtract">The result of the polygon subtraction</param>
 /// <returns>error code</returns>
 public static PolygonUtil.PolyUnionError PolygonOperation(PolygonUtil.PolyOperation operations, Point2DList polygon1, Point2DList polygon2, out Dictionary<uint, Point2DList> results)
 {
     PolygonOperationContext ctx = new PolygonOperationContext();
     ctx.Init(operations, polygon1, polygon2);
     results = ctx.mOutput;
     return PolygonUtil.PolygonOperation(ctx);
 }
Example #3
0
        public static void PolygonSubtractInternal(PolygonOperationContext ctx)
        {
            Point2DList subtract = ctx.Subtract;
            if (ctx.mStartingIndex == -1)
            {
                switch (ctx.mError)
                {
                    case PolygonUtil.PolyUnionError.NoIntersections:
                    case PolygonUtil.PolyUnionError.InfiniteLoop:
                    case PolygonUtil.PolyUnionError.Poly1InsidePoly2:
                        return;
                }
            }

            Point2DList currentPoly = ctx.mPoly1;
            Point2DList otherPoly = ctx.mPoly2;
            List<int> currentPolyVectorAngles = ctx.mPoly1VectorAngles;

            // Store the starting vertex so we can refer to it later.
            Point2D startingVertex = ctx.mPoly1[ctx.mStartingIndex];
            int currentIndex = ctx.mStartingIndex;
            subtract.Clear();

            // Trace direction
            bool forward = true;

            do
            {
                // Add the current vertex to the final union
                subtract.Add(currentPoly[currentIndex]);

                foreach (EdgeIntersectInfo intersect in ctx.mIntersections)
                {
                    // If the current point is an intersection point
                    if (currentPoly[currentIndex].Equals(intersect.IntersectionPoint, currentPoly.Epsilon))
                    {
                        // Make sure we want to swap polygons here.
                        int otherIndex = otherPoly.IndexOf(intersect.IntersectionPoint);

                        //Point2D otherVertex;
                        if (forward)
                        {
                            // If the next vertex, if we do swap, is inside the current polygon,
                            // then its safe to swap, otherwise, just carry on with the current poly.
                            int compareIndex = otherPoly.PreviousIndex(otherIndex);
                            Point2D compareVertex = otherPoly[compareIndex];
                            bool bPointInPolygonAngle = false;
                            if (currentPolyVectorAngles[compareIndex] == -1)
                            {
                                bPointInPolygonAngle = ctx.PointInPolygonAngle(compareVertex, currentPoly);
                                currentPolyVectorAngles[compareIndex] = bPointInPolygonAngle ? 1 : 0;
                            }
                            else
                            {
                                bPointInPolygonAngle = (currentPolyVectorAngles[compareIndex] == 1) ? true : false;
                            }

                            if (bPointInPolygonAngle)
                            {
                                // switch polygons
                                if (currentPoly == ctx.mPoly1)
                                {
                                    currentPoly = ctx.mPoly2;
                                    currentPolyVectorAngles = ctx.mPoly2VectorAngles;
                                    otherPoly = ctx.mPoly1;
                                }
                                else
                                {
                                    currentPoly = ctx.mPoly1;
                                    currentPolyVectorAngles = ctx.mPoly1VectorAngles;
                                    otherPoly = ctx.mPoly2;
                                }

                                // set currentIndex
                                currentIndex = otherIndex;

                                // Reverse direction
                                forward = !forward;

                                // Stop checking ctx.mIntersections for this point.
                                break;
                            }
                        }
                        else
                        {
                            // If the next vertex, if we do swap, is outside the current polygon,
                            // then its safe to swap, otherwise, just carry on with the current poly.
                            int compareIndex = otherPoly.NextIndex(otherIndex);
                            Point2D compareVertex = otherPoly[compareIndex];
                            bool bPointInPolygonAngle = false;
                            if (currentPolyVectorAngles[compareIndex] == -1)
                            {
                                bPointInPolygonAngle = ctx.PointInPolygonAngle(compareVertex, currentPoly);
                                currentPolyVectorAngles[compareIndex] = bPointInPolygonAngle ? 1 : 0;
                            }
                            else
                            {
                                bPointInPolygonAngle = (currentPolyVectorAngles[compareIndex] == 1) ? true : false;
                            }

                            if (!bPointInPolygonAngle)
                            {
                                // switch polygons
                                if (currentPoly == ctx.mPoly1)
                                {
                                    currentPoly = ctx.mPoly2;
                                    currentPolyVectorAngles = ctx.mPoly2VectorAngles;
                                    otherPoly = ctx.mPoly1;
                                }
                                else
                                {
                                    currentPoly = ctx.mPoly1;
                                    currentPolyVectorAngles = ctx.mPoly1VectorAngles;
                                    otherPoly = ctx.mPoly2;
                                }

                                // set currentIndex
                                currentIndex = otherIndex;

                                // Reverse direction
                                forward = !forward;

                                // Stop checking intersections for this point.
                                break;
                            }
                        }
                    }
                }

                if (forward)
                {
                    // Move to next index
                    currentIndex = currentPoly.NextIndex(currentIndex);
                }
                else
                {
                    currentIndex = currentPoly.PreviousIndex(currentIndex);
                }
            } while ((currentPoly[currentIndex] != startingVertex) && (subtract.Count <= (ctx.mPoly1.Count + ctx.mPoly2.Count)));


            // If the number of vertices in the union is more than the combined vertices
            // of the input polygons, then something is wrong and the algorithm will
            // loop forever. Luckily, we check for that.
            if (subtract.Count > (ctx.mPoly1.Count + ctx.mPoly2.Count))
            {
                ctx.mError = PolygonUtil.PolyUnionError.InfiniteLoop;
            }

            return;
        }
Example #4
0
 /// <summary>
 /// Subtracts one polygon from another.
 /// </summary>
 /// <param name="polygon1">The base polygon.</param>
 /// <param name="polygon2">The polygon to subtract from the base.</param>
 /// <param name="subtract">The result of the polygon subtraction</param>
 /// <returns>error code</returns>
 public static PolygonUtil.PolyUnionError PolygonSubtract(Point2DList polygon1, Point2DList polygon2, out Point2DList subtract)
 {
     PolygonOperationContext ctx = new PolygonOperationContext();
     ctx.Init(PolygonUtil.PolyOperation.Subtract, polygon1, polygon2);
     PolygonSubtractInternal(ctx);
     subtract = ctx.Subtract;
     return ctx.mError;
 }
Example #5
0
        protected static void PolygonIntersectInternal(PolygonOperationContext ctx)
        {
            Point2DList intersectOut = ctx.Intersect;
            if (ctx.mStartingIndex == -1)
            {
                switch (ctx.mError)
                {
                    case PolygonUtil.PolyUnionError.NoIntersections:
                    case PolygonUtil.PolyUnionError.InfiniteLoop:
                        return;
                    case PolygonUtil.PolyUnionError.Poly1InsidePoly2:
                        intersectOut.AddRange(ctx.mOriginalPolygon2);
                        return;
                }
            }

            Point2DList currentPoly = ctx.mPoly1;
            Point2DList otherPoly = ctx.mPoly2;
            List<int> currentPolyVectorAngles = ctx.mPoly1VectorAngles;

            // Store the starting vertex so we can refer to it later.            
            int currentIndex = ctx.mPoly1.IndexOf(ctx.mIntersections[0].IntersectionPoint);
            Point2D startingVertex = ctx.mPoly1[currentIndex];
            int firstPoly1Index = currentIndex;
            int firstPoly2Index = -1;
            intersectOut.Clear();

            do
            {
                // Add the current vertex to the final intersection
                if (intersectOut.Contains(currentPoly[currentIndex]))
                {
                    // This can happen when the two polygons only share a single edge, and neither is inside the other
                    break;
                }
                intersectOut.Add(currentPoly[currentIndex]);

                foreach (EdgeIntersectInfo intersect in ctx.mIntersections)
                {
                    // If the current point is an intersection point
                    if (currentPoly[currentIndex].Equals(intersect.IntersectionPoint, currentPoly.Epsilon))
                    {
                        // Make sure we want to swap polygons here.
                        int otherIndex = otherPoly.IndexOf(intersect.IntersectionPoint);

                        // If the next vertex, if we do swap, is inside the current polygon,
                        // then its safe to swap, otherwise, just carry on with the current poly.
                        int comparePointIndex = otherPoly.NextIndex(otherIndex);
                        Point2D comparePoint = otherPoly[comparePointIndex];
                        bool bPointInPolygonAngle = false;
                        if (currentPolyVectorAngles[comparePointIndex] == -1)
                        {
                            bPointInPolygonAngle = ctx.PointInPolygonAngle(comparePoint, currentPoly);
                            currentPolyVectorAngles[comparePointIndex] = bPointInPolygonAngle ? 1 : 0;
                        }
                        else
                        {
                            bPointInPolygonAngle = (currentPolyVectorAngles[comparePointIndex] == 1) ? true : false;
                        }

                        if (bPointInPolygonAngle)
                        {
                            // switch polygons
                            if (currentPoly == ctx.mPoly1)
                            {
                                currentPoly = ctx.mPoly2;
                                currentPolyVectorAngles = ctx.mPoly2VectorAngles;
                                otherPoly = ctx.mPoly1;
                                if (firstPoly2Index < 0)
                                {
                                    firstPoly2Index = otherIndex;
                                }
                            }
                            else
                            {
                                currentPoly = ctx.mPoly1;
                                currentPolyVectorAngles = ctx.mPoly1VectorAngles;
                                otherPoly = ctx.mPoly2;
                            }

                            // set currentIndex
                            currentIndex = otherIndex;

                            // Stop checking intersections for this point.
                            break;
                        }
                    }
                }

                // Move to next index
                currentIndex = currentPoly.NextIndex(currentIndex);

                if (currentPoly == ctx.mPoly1)
                {
                    if (currentIndex == firstPoly1Index)
                    {
                        break;
                    }
                }
                else
                {
                    if (firstPoly2Index >= 0 && currentIndex == firstPoly2Index)
                    {
                        break;
                    }
                }
            } while ((currentPoly[currentIndex] != startingVertex) && (intersectOut.Count <= (ctx.mPoly1.Count + ctx.mPoly2.Count)));

            // If the number of vertices in the union is more than the combined vertices
            // of the input polygons, then something is wrong and the algorithm will
            // loop forever. Luckily, we check for that.
            if (intersectOut.Count > (ctx.mPoly1.Count + ctx.mPoly2.Count))
            {
                ctx.mError = PolygonUtil.PolyUnionError.InfiniteLoop;
            }

            return;
        }
Example #6
0
 /// Merges two polygons, given that they intersect.
 /// </summary>
 /// <param name="polygon1">The first polygon.</param>
 /// <param name="polygon2">The second polygon.</param>
 /// <param name="union">The union of the two polygons</param>
 /// <returns>The error returned from union</returns>
 public static PolygonUtil.PolyUnionError PolygonUnion(Point2DList polygon1, Point2DList polygon2, out Point2DList union)
 {
     PolygonOperationContext ctx = new PolygonOperationContext();
     ctx.Init(PolygonUtil.PolyOperation.Union, polygon1, polygon2);
     PolygonUnionInternal(ctx);
     union = ctx.Union;
     return ctx.mError;
 }