Example #1
0
        /// <summary>
        /// Runs the specified polygon.
        /// </summary>
        /// <param name="polygon">The polygon.</param>
        /// <param name="intersections">The intersections.</param>
        /// <param name="makeHolesPositive">if set to <c>true</c> [make holes positive].</param>
        /// <param name="tolerance">The tolerance.</param>
        /// <param name="strayHoles">The stray holes.</param>
        /// <returns>List&lt;Polygon&gt;.</returns>
        internal List <Polygon> Run(Polygon polygon, List <SegmentIntersection> intersections, ResultType resultType, double tolerance,
                                    List <bool> knownWrongPoints, int maxNumberOfPolygons)
        {
            var minAllowableArea = tolerance * tolerance / Constants.BaseTolerance;
            var interaction      = new PolygonInteractionRecord(polygon, null);

            interaction.IntersectionData.AddRange(intersections);
            var delimiters             = NumberVerticesAndGetPolygonVertexDelimiter(polygon);
            var intersectionLookup     = interaction.MakeIntersectionLookupList(delimiters[^ 1]);
        /// <summary>
        /// All of the previous boolean operations are accomplished by this function. Note that the function RemoveSelfIntersections is also
        /// very simliar to this function.
        /// </summary>
        /// <param name="polygonA">The polygon a.</param>
        /// <param name="polygonB">The polygon b.</param>
        /// <param name="intersections">The intersections.</param>
        /// <param name="isSubtract">The switch direction.</param>
        /// <param name="crossProductSign">The cross product sign.</param>
        /// <param name="tolerance">The minimum allowable area.</param>
        /// <returns>System.Collections.Generic.List&lt;TVGL.TwoDimensional.Polygon&gt;.</returns>
        internal List <Polygon> Run(Polygon polygonA, Polygon polygonB, PolygonInteractionRecord interaction, PolygonCollection polygonCollection,
                                    double tolerance = double.NaN)
        {
            double areaTolerance;

            if (double.IsNaN(tolerance))
            {
                var minDimension = Math.Min(polygonA.MaxX - polygonA.MinX, Math.Min(polygonA.MaxY - polygonA.MinY,
                                                                                    Math.Min(polygonB.MaxX - polygonB.MinX, polygonB.MaxY - polygonB.MinY)));
                tolerance     = Constants.BaseTolerance * minDimension;
                areaTolerance = tolerance * minDimension;
            }
            else
            {
                areaTolerance = tolerance * tolerance / Constants.BaseTolerance;    // why change the input tolerance? here, we are using it as a
            }
            // limit on the minimum allowable area only (about 12 lines down), so in order to change it from units of length to length-squared
            // we need to find the characteristic length that was multiplied by the base tolerance to obtain the linear tolerance.
            var delimiters = NumberVerticesAndGetPolygonVertexDelimiter(polygonA);

            delimiters = NumberVerticesAndGetPolygonVertexDelimiter(polygonB, delimiters[^ 1]);
 /// <summary>
 /// Returns the list of polygons that exist in either A OR B.By providing the intersections
 /// between the two polygons, the operation will be performed with less time and memory.
 /// </summary>
 /// <param name="polygonA">The polygon a.</param>
 /// <param name="polygonB">The polygon b.</param>
 /// <param name="polygonInteraction">The polygon relationship.</param>
 /// <param name="outputAsCollectionType">Type of the output as collection.</param>
 /// <param name="tolerance">The minimum allowable area.</param>
 /// <returns>System.Collections.Generic.List&lt;TVGL.TwoDimensional.Polygon&gt;.</returns>
 /// <exception cref="ArgumentException">A negative polygon (i.e. hole) is provided to Union which results in infinite shape. - polygonA</exception>
 /// <exception cref="ArgumentException">A negative polygon (i.e. hole) is provided to Union which results in infinite shape. - polygonB</exception>
 public static List <Polygon> Union(this Polygon polygonA, Polygon polygonB, PolygonInteractionRecord polygonInteraction,
                                    PolygonCollection outputAsCollectionType = PolygonCollection.PolygonWithHoles, double tolerance = double.NaN)
 {
     if (!polygonA.IsPositive)
     {
         throw new ArgumentException("A negative polygon (i.e. hole) is provided to Union which results in infinite shape.", nameof(polygonA));
     }
     if (!polygonB.IsPositive)
     {
         throw new ArgumentException("A negative polygon (i.e. hole) is provided to Union which results in infinite shape.", nameof(polygonB));
     }
     if (!polygonInteraction.CoincidentEdges && (polygonInteraction.Relationship == PolygonRelationship.Separated ||
                                                 polygonInteraction.Relationship == PolygonRelationship.AIsInsideHoleOfB ||
                                                 polygonInteraction.Relationship == PolygonRelationship.BIsInsideHoleOfA))
     {
         return new List <Polygon> {
                    polygonA.Copy(true, false), polygonB.Copy(true, false)
         }
     }
     ;
     if (polygonInteraction.Relationship == PolygonRelationship.BInsideA ||
         polygonInteraction.Relationship == PolygonRelationship.Equal)
     {
         return new List <Polygon> {
                    polygonA.Copy(true, false)
         }
     }
     ;
     if (polygonInteraction.Relationship == PolygonRelationship.AInsideB)
     {
         return new List <Polygon> {
                    polygonB.Copy(true, false)
         }
     }
     ;
     polygonUnion ??= new PolygonUnion();
     return(polygonUnion.Run(polygonA, polygonB, polygonInteraction, outputAsCollectionType, tolerance));
 }
        /// <summary>
        /// Returns the list of polygons that are the Exclusive-OR of the two input polygons. Exclusive-OR are the regions where one polgyon
        /// resides but not both. By providing the intersections between the two polygons, the operation will be performed with less time and memory.
        /// </summary>
        /// <param name="polygonA">The polygon a.</param>
        /// <param name="polygonB">The polygon b.</param>
        /// <param name="interactionRecord">The interaction record.</param>
        /// <param name="outputAsCollectionType">Type of the output as collection.</param>
        /// <param name="tolerance">The tolerance.</param>
        /// <returns>System.Collections.Generic.List&lt;TVGL.TwoDimensional.Polygon&gt;.</returns>
        public static List <Polygon> ExclusiveOr(this Polygon polygonA, Polygon polygonB, PolygonInteractionRecord interactionRecord,
                                                 PolygonCollection outputAsCollectionType = PolygonCollection.PolygonWithHoles, double tolerance = double.NaN)
        {
            if (interactionRecord.IntersectionWillBeEmpty())
            {
                return new List <Polygon> {
                           polygonA.Copy(true, false), polygonB.Copy(true, false)
                }
            }
            ;
            else if (interactionRecord.Relationship == PolygonRelationship.BInsideA &&
                     !interactionRecord.CoincidentEdges && !interactionRecord.CoincidentVertices)
            {
                var polygonACopy1 = polygonA.Copy(true, false);

                polygonACopy1.AddInnerPolygon(polygonB.Copy(true, true));
                return(new List <Polygon> {
                    polygonACopy1
                });
            }
            else if (interactionRecord.Relationship == PolygonRelationship.AInsideB &&
                     !interactionRecord.CoincidentEdges && !interactionRecord.CoincidentVertices)
            {
                var polygonBCopy2 = polygonB.Copy(true, false);
                polygonBCopy2.AddInnerPolygon(polygonA.Copy(true, true));
                return(new List <Polygon> {
                    polygonBCopy2
                });
            }
            else
            {
                var result = polygonA.Subtract(polygonB, interactionRecord, outputAsCollectionType, tolerance);
                result.AddRange(polygonB.Subtract(polygonA, interactionRecord, outputAsCollectionType, tolerance));
                return(result);
            }
        }
 /// <summary>
 /// Returns the list of polygons that result from A-B (subtracting polygon B from polygon A). By providing the intersections
 /// between the two polygons, the operation will be performed with less time and memory.
 /// </summary>
 /// <param name="minuend">The polygon a.</param>
 /// <param name="subtrahend">The polygon b.</param>
 /// <param name="interaction">The polygon relationship.</param>
 /// <param name="outputAsCollectionType">Type of the output as collection.</param>
 /// <param name="tolerance">The tolerance.</param>
 /// <returns>System.Collections.Generic.List&lt;TVGL.TwoDimensional.Polygon&gt;.</returns>
 /// <exception cref="ArgumentException">The minuend is already a negative polygon (i.e. hole). Consider another operation"
 /// +" to accomplish this function, like Intersect. - polygonA</exception>
 public static List <Polygon> Subtract(this Polygon minuend, Polygon subtrahend, PolygonInteractionRecord interaction,
                                       PolygonCollection outputAsCollectionType = PolygonCollection.PolygonWithHoles, double tolerance = double.NaN)
 {
     interaction = interaction.InvertPolygonInRecord(subtrahend, out var invertedPolygonB);
     return(Intersect(minuend, invertedPolygonB, interaction, outputAsCollectionType, tolerance));
 }
 /// <summary>
 /// Returns the list of polygons that result from the subshapes common to both A and B. By providing the intersections
 /// between the two polygons, the operation will be performed with less time and memory.
 /// </summary>
 /// <param name="polygonA">The polygon a.</param>
 /// <param name="polygonB">The polygon b.</param>
 /// <param name="interaction">The interaction.</param>
 /// <param name="outputAsCollectionType">Type of the output as collection.</param>
 /// <param name="tolerance">The minimum allowable area.</param>
 /// <returns>System.Collections.Generic.List&lt;TVGL.TwoDimensional.Polygon&gt;.</returns>
 public static List <Polygon> Intersect(this Polygon polygonA, Polygon polygonB, PolygonInteractionRecord interaction,
                                        PolygonCollection outputAsCollectionType = PolygonCollection.PolygonWithHoles, double tolerance = double.NaN)
 {
     if (interaction.IntersectionWillBeEmpty())
     {
         if (polygonB.IsPositive)
         {
             return(new List <Polygon>());
         }
         else
         {
             return new List <Polygon> {
                        polygonA.Copy(true, false)
             }
         };
     }
     else
     {
         polygonIntersection ??= new PolygonIntersection();
         return(polygonIntersection.Run(polygonA, polygonB, interaction, outputAsCollectionType, tolerance));
     }
 }