Beispiel #1
0
        public List <Point> GetHull()
        {
            if (hullRoot != null)
            {
                List <Point> leftHullList  = hullRoot.GetConvexHull(true).GetArray();
                List <Point> rightHullList = hullRoot.GetConvexHull(false).GetArray();
                rightHullList.Reverse();

                int beginRight = 0;
                int endRight   = rightHullList.Count;

                while (beginRight < leftHullList.Count &&
                       beginRight < rightHullList.Count &&
                       leftHullList[leftHullList.Count - beginRight - 1].CompareTo(rightHullList[beginRight]) == 0)
                {
                    ++beginRight;
                }
                while (rightHullList.Count - endRight < leftHullList.Count &&
                       endRight >= 0 &&
                       leftHullList[rightHullList.Count - endRight].CompareTo(rightHullList[endRight - 1]) == 0)
                {
                    --endRight;
                }
                if (endRight > beginRight)
                {
                    leftHullList.AddRange(rightHullList.GetRange(beginRight, endRight - beginRight));
                }
                return(leftHullList);
            }
            return(new List <Point>());
        }
Beispiel #2
0
        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);
            }
        }
Beispiel #3
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);
            }
        }