private static Partition Merge(Partition leftPartition, Partition rightPartition) { QuadEdge left = leftPartition.Left; //ldo QuadEdge right = rightPartition.Right; //rdo LowestCommonTangent(leftPartition, rightPartition, out QuadEdge lowLeft, out QuadEdge lowRight); //ldi, rdi QuadEdge edgeBase = QuadEdge.ConnectLeft(lowRight.Inverse, lowLeft); QuadEdge lcand = edgeBase.RightPrevious; QuadEdge rcand = edgeBase.OriginPrevious; if (edgeBase.Origin == right.Origin) { right = edgeBase; } if (edgeBase.Destination == left.Origin) { left = edgeBase.Inverse; } while (true) { QuadEdge temp = lcand.OriginNext; if (Point.IsCounterClockWise(edgeBase.Origin, temp.Destination, edgeBase.Destination)) { while (edgeBase.Origin.InCircle(lcand.Destination, temp.Destination, lcand.Origin)) { lcand.Delete(); lcand = temp; temp = lcand.OriginNext; } } temp = rcand.OriginPrevious; if (Point.IsCounterClockWise(edgeBase.Origin, temp.Destination, edgeBase.Destination)) { while (edgeBase.Destination.InCircle(temp.Destination, rcand.Destination, rcand.Origin)) { rcand.Delete(); rcand = temp; temp = rcand.OriginPrevious; } } bool leftValid = Point.IsCounterClockWise(edgeBase.Origin, lcand.Destination, edgeBase.Destination); bool rightValid = Point.IsCounterClockWise(edgeBase.Origin, rcand.Destination, edgeBase.Destination); if (!leftValid && !rightValid) { break; } if (!leftValid || rightValid && rcand.Destination.InCircle(lcand.Destination, lcand.Origin, rcand.Origin)) { edgeBase = QuadEdge.ConnectLeft(rcand, edgeBase.Inverse); rcand = edgeBase.Inverse.LeftNext; } else { edgeBase = QuadEdge.ConnectRight(lcand, edgeBase).Inverse; lcand = edgeBase.RightPrevious; } } return(new Partition { Left = left, Right = right }); }