/// <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); }
public bool Init(PolygonUtil.PolyOperation operations, Point2DList polygon1, Point2DList polygon2) { Clear(); mOperations = operations; mOriginalPolygon1 = polygon1; mOriginalPolygon2 = polygon2; // Make a copy of the polygons so that we dont modify the originals, and // force vertices to integer (pixel) values. mPoly1 = new Point2DList(polygon1); mPoly1.WindingOrder = Point2DList.WindingOrderType.Default; mPoly2 = new Point2DList(polygon2); mPoly2.WindingOrder = Point2DList.WindingOrderType.Default; // Find intersection points if (!VerticesIntersect(mPoly1, mPoly2, out mIntersections)) { // No intersections found - polygons do not overlap. mError = PolygonUtil.PolyUnionError.NoIntersections; return false; } // make sure edges that intersect more than once are updated to have correct start points int numIntersections = mIntersections.Count; for (int i = 0; i < numIntersections; ++i) { for (int j = i + 1; j < numIntersections; ++j) { if (mIntersections[i].EdgeOne.EdgeStart.Equals(mIntersections[j].EdgeOne.EdgeStart) && mIntersections[i].EdgeOne.EdgeEnd.Equals(mIntersections[j].EdgeOne.EdgeEnd)) { mIntersections[j].EdgeOne.EdgeStart = mIntersections[i].IntersectionPoint; } if (mIntersections[i].EdgeTwo.EdgeStart.Equals(mIntersections[j].EdgeTwo.EdgeStart) && mIntersections[i].EdgeTwo.EdgeEnd.Equals(mIntersections[j].EdgeTwo.EdgeEnd)) { mIntersections[j].EdgeTwo.EdgeStart = mIntersections[i].IntersectionPoint; } } } // Add intersection points to original polygons, ignoring existing points. foreach (EdgeIntersectInfo intersect in mIntersections) { if (!mPoly1.Contains(intersect.IntersectionPoint)) { mPoly1.Insert(mPoly1.IndexOf(intersect.EdgeOne.EdgeStart) + 1, intersect.IntersectionPoint); } if (!mPoly2.Contains(intersect.IntersectionPoint)) { mPoly2.Insert(mPoly2.IndexOf(intersect.EdgeTwo.EdgeStart) + 1, intersect.IntersectionPoint); } } mPoly1VectorAngles = new List<int>(); for (int i = 0; i < mPoly2.Count; ++i) { mPoly1VectorAngles.Add(-1); } mPoly2VectorAngles = new List<int>(); for (int i = 0; i < mPoly1.Count; ++i) { mPoly2VectorAngles.Add(-1); } // Find starting point on the edge of polygon1 that is outside of // the intersected area to begin polygon trace. int currentIndex = 0; do { bool bPointInPolygonAngle = PointInPolygonAngle(mPoly1[currentIndex], mPoly2); mPoly2VectorAngles[currentIndex] = bPointInPolygonAngle ? 1 : 0; if (bPointInPolygonAngle) { mStartingIndex = currentIndex; break; } currentIndex = mPoly1.NextIndex(currentIndex); } while (currentIndex != 0); // If we don't find a point on polygon1 thats outside of the // intersect area, the polygon1 must be inside of polygon2, // in which case, polygon2 IS the union of the two. if (mStartingIndex == -1) { mError = PolygonUtil.PolyUnionError.Poly1InsidePoly2; return false; } return true; }