bool AlreadyFinished(ref Polygon polygon, OperationType ot, SweepEvent currentEvent) { if ((ot == OperationType.INTERSECTION && currentEvent.Point.x > minMaxX) || (ot == OperationType.DIFFERENCE && currentEvent.Point.x > bbSubject.max.x)) { polygon = connector.CreatePolygon(); return(true); } if (ot == OperationType.UNION && currentEvent.Point.x > minMaxX) { // add all the non-processed line segments to the result if (!currentEvent.Left) { connector.Add(currentEvent.CreateEdge()); } while (!futureSweepLineEvents.IsEmpty()) { currentEvent = futureSweepLineEvents.ExtractFirst(); if (!currentEvent.Left) { connector.Add(currentEvent.CreateEdge()); } } polygon = connector.CreatePolygon(); return(true); } return(false); }
void HandleRightEvent(OperationType ot, SweepEvent currentEvent) { // the left end/part of the current SweepEvent must be removed from sweepLineEvents left = currentEvent.Other.positionInS; next = left.GetSuccessor(); prev = left.GetPredecessor(); // Check if the line segment belongs to the Boolean operation switch (currentEvent.Type) { case EdgeType.NORMAL: switch (ot) { case OperationType.INTERSECTION: if (currentEvent.Other.Inside) { connector.Add(currentEvent.CreateEdge()); } break; case OperationType.UNION: if (!currentEvent.Other.Inside) { connector.Add(currentEvent.CreateEdge()); } break; case OperationType.DIFFERENCE: if ((currentEvent.OwningPolygon == (int)Operand.SUBJECT && !currentEvent.Other.Inside) || (currentEvent.OwningPolygon == (int)Operand.CLIPPER && currentEvent.Other.Inside)) { connector.Add(currentEvent.CreateEdge()); } break; case OperationType.XOR: connector.Add(currentEvent.CreateEdge()); break; } break; case EdgeType.SAME_TRANSITION: if (ot == OperationType.INTERSECTION || ot == OperationType.UNION) { connector.Add(currentEvent.CreateEdge()); } break; case EdgeType.DIFFERENT_TRANSITION: if (ot == OperationType.DIFFERENCE) { connector.Add(currentEvent.CreateEdge()); } break; } AddDebugEdge(currentEvent); sweepLineEvents.RemoveAt(left); if (next != null && prev != null) { PossibleIntersection(prev.Value, next.Value); } }
/// <summary> /// Process a possible intersection between the segment associated to the left events e1 and e2 /// </summary> void PossibleIntersection(SweepEvent e1, SweepEvent e2) { Edge edge1 = e1.CreateEdge(); Edge edge2 = e2.CreateEdge(); List <Vector2> intersections = edge1.GetIntersectionsWith(edge2); if (intersections.Count == 0) { return; } if (intersections.Count == 1 && e1.HasEqualEndpoint(e2)) { return; } if (intersections.Count == 2 && e1.BelongsToSamePolygonAs(e2)) { return; } if (intersections.Count == 1) { Vector2 ip = intersections[0]; if (!e1.IsAnEndpoint(ip)) { DivideEdge(e1, ip); } if (!e2.IsAnEndpoint(ip)) { DivideEdge(e2, ip); } return; } List <SweepEvent> sortedEvents = new List <SweepEvent>(); // the line segments overlap if (e1.Point == e2.Point) { sortedEvents.Add(null); } else if (comparer.Compare(e1, e2) > 0) { sortedEvents.Add(e2); sortedEvents.Add(e1); } else { sortedEvents.Add(e1); sortedEvents.Add(e2); } if (e1.Other.Point == e2.Other.Point) { sortedEvents.Add(null); } else if (comparer.Compare(e1.Other, e2.Other) > 0) { sortedEvents.Add(e2.Other); sortedEvents.Add(e1.Other); } else { sortedEvents.Add(e1.Other); sortedEvents.Add(e2.Other); } ////////////////////////////////////// // Degeneracies : Overlapping Edges // ////////////////////////////////////// // 1. Case: overlapping edges that are equal if (sortedEvents.Count == 2) { e1.SetEdgeType(EdgeType.NON_CONTRIBUTING); if (e1.InOut == e2.InOut) { e2.SetEdgeType(EdgeType.SAME_TRANSITION); } else { e2.SetEdgeType(EdgeType.DIFFERENT_TRANSITION); } return; } // 2. Case: overlapping edges that share an endpoint if (sortedEvents.Count == 3) { sortedEvents[1].SetEdgeType(EdgeType.NON_CONTRIBUTING); int sharedIndex = (sortedEvents[0] != null) ? 0 : 2; // is left endpoint or right endpoint shared if (e1.InOut == e2.InOut) { sortedEvents[sharedIndex].Other.Type = EdgeType.SAME_TRANSITION; } else { sortedEvents[sharedIndex].Other.Type = EdgeType.DIFFERENT_TRANSITION; } if (sortedEvents[0] != null) { DivideEdge(sortedEvents[0], sortedEvents[1].Point); } else { DivideEdge(sortedEvents[2].Other, sortedEvents[1].Point); } return; } // 3. Case: overlapping edges where noone totally includes the other if (sortedEvents[0] != sortedEvents[3].Other) { sortedEvents[1].Type = EdgeType.NON_CONTRIBUTING; sortedEvents[2].Type = (e1.InOut == e2.InOut) ? EdgeType.SAME_TRANSITION : EdgeType.DIFFERENT_TRANSITION; DivideEdge(sortedEvents[0], sortedEvents[1].Point); DivideEdge(sortedEvents[1], sortedEvents[2].Point); return; } // one line segment includes the other one sortedEvents[1].Type = sortedEvents[1].Other.Type = EdgeType.NON_CONTRIBUTING; DivideEdge(sortedEvents[0], sortedEvents[1].Point); sortedEvents[3].Other.Type = (e1.InOut == e2.InOut) ? EdgeType.SAME_TRANSITION : EdgeType.DIFFERENT_TRANSITION; DivideEdge(sortedEvents[3].Other, sortedEvents[2].Point); }
void AddDebugEdge(SweepEvent currentEvent) { debugEdges.Add(new DebugEdge { Edge = currentEvent.CreateEdge(), InOut = currentEvent.InOut, Left = currentEvent.Left, Type = currentEvent.Type }); }