Ejemplo n.º 1
0
        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);
            }
        }