private static void pushSubHullDown(RedBlackNode current, bool isLeftHalf) { if (current != null && !current.IsLeaf && current.GetConvexHull(isLeftHalf) != null) { Treap <Point> leftHalf; Treap <Point> rightHalf; Treap <Point> .SplitBySize(current.GetConvexHull(isLeftHalf), current.GeLowerSubHullSize(isLeftHalf), out leftHalf, out rightHalf); current.Left.SetConvexHull(isLeftHalf, Treap <Point> .Merge(leftHalf, current.Left.GetConvexHull(isLeftHalf))); current.Right.SetConvexHull(isLeftHalf, Treap <Point> .Merge(current.Right.GetConvexHull(isLeftHalf), rightHalf)); current.SetConvexHull(isLeftHalf, null); } }
private static void recount(RedBlackNode current, bool isLeftHalf) { if (current != null && current.Left != null && current.Right != null && current.GetConvexHull(isLeftHalf) == null) { current.MaxPoint = Utils.Max(current.Left.MaxPoint, current.Right.MaxPoint); Treap <Point> lowerCurrent = current.Left.GetConvexHull(isLeftHalf); Treap <Point> upperCurrent = current.Right.GetConvexHull(isLeftHalf); Point loweCurrentPoint = lowerCurrent.Key; Point upperCurrentPoint = upperCurrent.Key; double mediumY = (lowerCurrent.MaxElement.Y + upperCurrent.MinElement.Y) / 2; int toCutFromLowerHull = Treap <Point> .GetSize(lowerCurrent?.Left) + 1; int toLeaveInUpperHull = Treap <Point> .GetSize(upperCurrent?.Left) + 1; bool bridgeFound = false; while (!bridgeFound) { Point lowerPrevPoint = lowerCurrent?.Left != null ? lowerCurrent.Left.MaxElement : null; Point lowerNextPoint = lowerCurrent?.Right != null ? lowerCurrent.Right.MinElement : null; Point upperPrevPoint = upperCurrent?.Left != null ? upperCurrent.Left.MaxElement : null; Point upperNextPoint = upperCurrent?.Right != null ? upperCurrent.Right.MinElement : null; bridgeFound = makeDecisionAboutRotation(ref lowerCurrent, ref loweCurrentPoint, lowerPrevPoint, lowerNextPoint, ref toCutFromLowerHull, ref upperCurrent, ref upperCurrentPoint, upperPrevPoint, upperNextPoint, ref toLeaveInUpperHull, mediumY, isLeftHalf); } // we want to have top point in right treap after split --toLeaveInUpperHull; Treap <Point> leftPartOfLowerHull; Treap <Point> rightPartOfLowerHull; Treap <Point> leftPartOfUpperHull; Treap <Point> rightPartOfUpperHull; if (loweCurrentPoint.Y == upperCurrentPoint.Y) { if ((loweCurrentPoint.X < upperCurrentPoint.X && isLeftHalf) || (loweCurrentPoint.X > upperCurrentPoint.X && !isLeftHalf)) { ++toLeaveInUpperHull; } else if ((loweCurrentPoint.X > upperCurrentPoint.X && isLeftHalf) || (loweCurrentPoint.X < upperCurrentPoint.X && !isLeftHalf)) { --toCutFromLowerHull; } else { toLeaveInUpperHull++; } } current.SetLowerSubHullSize(isLeftHalf, toCutFromLowerHull); Treap <Point> .SplitBySize(current.Left.GetConvexHull(isLeftHalf), toCutFromLowerHull, out leftPartOfLowerHull, out rightPartOfLowerHull); Treap <Point> .SplitBySize(current.Right.GetConvexHull(isLeftHalf), toLeaveInUpperHull, out leftPartOfUpperHull, out rightPartOfUpperHull); current.SetConvexHull(isLeftHalf, Treap <Point> .Merge(leftPartOfLowerHull, rightPartOfUpperHull)); current.Left.SetConvexHull(isLeftHalf, rightPartOfLowerHull); current.Right.SetConvexHull(isLeftHalf, leftPartOfUpperHull); } }