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
            });
        }