internal static PolyRelInternal SwitchAAndBPolygonRelationship(this PolyRelInternal relationship) { if ((relationship & PolyRelInternal.Intersection) == PolyRelInternal.AInsideB) { relationship |= PolyRelInternal.BInsideA; relationship &= ~PolyRelInternal.AInsideB; } else if ((relationship & PolyRelInternal.Intersection) == PolyRelInternal.BInsideA) { relationship |= PolyRelInternal.AInsideB; relationship &= ~PolyRelInternal.BInsideA; } return(relationship); }
internal PolygonInteractionRecord InvertPolygonInRecord(Polygon polygon, out Polygon invertedPolygon) { var tolerance = polygon.GetToleranceForPolygon(); bool polygonAIsInverted = subPolygonToInt[polygon] < numPolygonsInA; var visitedIntersectionPairs = new HashSet <(PolygonEdge, PolygonEdge)>(); var delimiters = PolygonBooleanBase.NumberVerticesAndGetPolygonVertexDelimiter(polygon); invertedPolygon = polygon.Copy(true, true); var allLines = invertedPolygon.AllPolygons.SelectMany(p => p.Edges).ToList(); var newIntersections = new List <SegmentIntersection>(); var possibleDuplicates = new List <(int, PolygonEdge, PolygonEdge)>(); for (int i = 0; i < IntersectionData.Count; i++) { var oldIntersection = IntersectionData[i]; var edgeA = oldIntersection.EdgeA; var edgeB = oldIntersection.EdgeB; var indexOfEdge = polygonAIsInverted ? edgeA.IndexInList : edgeB.IndexInList; var k = 0; while (delimiters[k] <= indexOfEdge) { k++; } indexOfEdge = delimiters[k - 1] + (delimiters[k] - indexOfEdge) - 1; var newFlippedEdge = allLines[indexOfEdge]; if (oldIntersection.WhereIntersection == WhereIsIntersection.BothStarts || (polygonAIsInverted && oldIntersection.WhereIntersection == WhereIsIntersection.AtStartOfA) || (!polygonAIsInverted && oldIntersection.WhereIntersection == WhereIsIntersection.AtStartOfB)) { newFlippedEdge = newFlippedEdge.ToPoint.StartLine; } if (polygonAIsInverted) { if (visitedIntersectionPairs.Contains((newFlippedEdge, edgeB))) { continue; } visitedIntersectionPairs.Add((newFlippedEdge, edgeB)); PolygonOperations.AddIntersectionBetweenLines(newFlippedEdge, edgeB, newIntersections, possibleDuplicates, tolerance); } else { if (visitedIntersectionPairs.Contains((edgeA, newFlippedEdge))) { continue; } visitedIntersectionPairs.Add((edgeA, newFlippedEdge)); PolygonOperations.AddIntersectionBetweenLines(edgeA, newFlippedEdge, newIntersections, possibleDuplicates, tolerance); } } var newSubPolygonToInt = new Dictionary <Polygon, int>(); var isAPositive = invertedPolygon.IsPositive; var isBPositive = invertedPolygon.IsPositive; if (!polygonAIsInverted) { using var newPolyEnumerator = invertedPolygon.AllPolygons.GetEnumerator(); foreach (var keyValuePair in subPolygonToInt) { if (keyValuePair.Value == 0) { isAPositive = keyValuePair.Key.IsPositive; } if (keyValuePair.Value < numPolygonsInA) { newSubPolygonToInt.Add(keyValuePair.Key, keyValuePair.Value); } else { newPolyEnumerator.MoveNext(); newSubPolygonToInt.Add(newPolyEnumerator.Current, keyValuePair.Value); } } return(new PolygonInteractionRecord(Relationship, newIntersections, (PolyRelInternal[])polygonRelations.Clone(), newSubPolygonToInt, numPolygonsInA, numPolygonsInB, isAPositive, isBPositive) { CoincidentEdges = this.CoincidentEdges, CoincidentVertices = this.CoincidentVertices, EdgesCross = this.EdgesCross }); } var index = 0; foreach (var keyValuePair in subPolygonToInt) { if (keyValuePair.Value == numPolygonsInA) { isBPositive = keyValuePair.Key.IsPositive; } if (keyValuePair.Value >= numPolygonsInA) { newSubPolygonToInt.Add(keyValuePair.Key, index++); } } foreach (var newpoly in invertedPolygon.AllPolygons) { newSubPolygonToInt.Add(newpoly, index++); } var newPolygonRelations = new PolyRelInternal[numPolygonsInA * numPolygonsInB]; for (int i = 0; i < numPolygonsInA; i++) { for (int j = 0; j < numPolygonsInB; j++) { newPolygonRelations[numPolygonsInB * i + j] = Constants.SwitchAAndBPolygonRelationship(polygonRelations[numPolygonsInA * j + i]); } } return(new PolygonInteractionRecord((PolygonRelationship)Constants.SwitchAAndBPolygonRelationship((PolyRelInternal)Relationship), newIntersections, newPolygonRelations, newSubPolygonToInt, numPolygonsInB, numPolygonsInA, isBPositive, isAPositive) { CoincidentEdges = this.CoincidentEdges, CoincidentVertices = this.CoincidentVertices, EdgesCross = this.EdgesCross }); }
internal void SetRelationshipBetween(int index, PolyRelInternal newRel) { polygonRelations[index] = newRel; //Separated //AInsideB //AIsInsideHoleOfB //BInsideA //BIsInsideHoleOfA //Intersection //Equal //EqualButOpposite // okay need to compare all possibilities of the PolygonRelationship enum to itself // there are 8 values so that 8 x 8 = 64 possibilities. // let's see how this breaks down if (this.Relationship == PolygonRelationship.Intersection) { return; } // if already Intersection, then nothing to do (that's 8) if (newRel == PolyRelInternal.Separated) { return; } // if the newRel is Separated then no update as well (7 more) var newRelationship = (PolygonRelationship)(((int)newRel) & 248); if (newRelationship == Relationship) { return; } // if they're the same then nothing to do (that's 6 more since previous conditions would have caught 2 of these // down to 43 if (newRelationship == PolygonRelationship.Intersection || ((newRelationship == PolygonRelationship.AInsideB || newRelationship == PolygonRelationship.AIsInsideHoleOfB) && (Relationship == PolygonRelationship.BInsideA || Relationship == PolygonRelationship.BIsInsideHoleOfA)) || ((newRelationship == PolygonRelationship.BInsideA || newRelationship == PolygonRelationship.BIsInsideHoleOfA) && (Relationship == PolygonRelationship.AInsideB || Relationship == PolygonRelationship.AIsInsideHoleOfB))) { this.Relationship = PolygonRelationship.Intersection; } // how many more pairs are these: 7 + 8....down to 28 else if (Relationship == PolygonRelationship.Separated) { Relationship = newRelationship; //6 more here (i think...not included newRel is Separated or Intersection } else if (newRelationship == PolygonRelationship.Equal) { return; // current Relationship would be more descriptive } // so finding out that a subpolygon in Equal doesn't change anything (that 5 more cases) else if (newRelationship == PolygonRelationship.EqualButOpposite) { if (Relationship == PolygonRelationship.BInsideA) { Relationship = PolygonRelationship.BIsInsideHoleOfA; } if (Relationship == PolygonRelationship.AInsideB) { Relationship = PolygonRelationship.AIsInsideHoleOfB; } // really need to check the new EqualButOpposite with AInsideB, AIsInsideHoleOfB, BInsideA, // BIsInsideHoleOfA, & Equal (so that's 5 additional cases) but the above two subcases are the // only ways this can ever happen, right? } // there are 12 left, all of which are either impossible or have no effect (I think). These are listed below. // The first 4 are possible and we need to be careful if the outer positive polygons match, then when we compare // the inner hole of A to the outer of B, we will get the first condition below, but we don't want to change the // full Relationship unless we are sure it's not identical. This requires us to have one more function at the end // which is DefineOverallInteractionFromFinalListOfSubInteractions //R = Equal , Nrel = AInsideB //R = Equal , Nrel = AIsInsideHoleOfB //R = Equal , Nrel = BInsideA //R = Equal , Nrel = BIsInsideHoleOfA //R = AIsInsideHoleOfB , Nrel = AInsideB //R = AInsideB , Nrel = AIsInsideHoleOfB //R = BIsInsideHoleOfA , Nrel = BInsideA //R = BInsideA , Nrel = BIsInsideHoleOfA //R = EqualButOpposite , Nrel = AInsideB //R = EqualButOpposite , Nrel = AIsInsideHoleOfB //R = EqualButOpposite , Nrel = BInsideA //R = EqualButOpposite , Nrel = BIsInsideHoleOfA return; }