/// <inheritdoc />
        //// [MethodImpl(MethodImplOptions.AggressiveInlining)]
        protected override bool IsGoodQuadrantForPoint(MutablePoint pt)
        {
            if (pt.X < this.RootPoint.X && pt.Y > this.RootPoint.Y)
            {
                return(true);
            }

            return(false);
        }
        /// <inheritdoc />
        protected override void SetQuadrantLimits()
        {
            MutablePoint firstPoint = this.ListOfPoint.First();

            double leftX = firstPoint.X;
            double leftY = firstPoint.Y;

            double topX = leftX;
            double topY = leftY;

            foreach (var point in this.ListOfPoint)
            {
                if (point.X <= leftX)
                {
                    if (point.X == leftX)
                    {
                        if (point.Y > leftY)
                        {
                            leftY = point.Y;
                        }
                    }
                    else
                    {
                        leftX = point.X;
                        leftY = point.Y;
                    }
                }

                if (point.Y >= topY)
                {
                    if (point.Y == topY)
                    {
                        if (point.X < topX)
                        {
                            topX = point.X;
                        }
                    }
                    else
                    {
                        topX = point.X;
                        topY = point.Y;
                    }
                }
            }

            this.FirstPoint = new MutablePoint(topX, topY);
            this.LastPoint  = new MutablePoint(leftX, leftY);
            this.RootPoint  = new MutablePoint(topX, leftY);
        }
Beispiel #3
0
        /// <inheritdoc />
        protected override void SetQuadrantLimits()
        {
            MutablePoint firstPoint = this.ListOfPoint.First();

            double rightX = firstPoint.X;
            double rightY = firstPoint.Y;

            double bottomX = rightX;
            double bottomY = rightY;

            foreach (var point in this.ListOfPoint)
            {
                if (point.X >= rightX)
                {
                    if (point.X == rightX)
                    {
                        if (point.Y < rightY)
                        {
                            rightY = point.Y;
                        }
                    }
                    else
                    {
                        rightX = point.X;
                        rightY = point.Y;
                    }
                }

                if (point.Y <= bottomY)
                {
                    if (point.Y == bottomY)
                    {
                        if (point.X > bottomX)
                        {
                            bottomX = point.X;
                        }
                    }
                    else
                    {
                        bottomX = point.X;
                        bottomY = point.Y;
                    }
                }
            }

            this.FirstPoint = new MutablePoint(bottomX, bottomY);
            this.LastPoint  = new MutablePoint(rightX, rightY);
            this.RootPoint  = new MutablePoint(bottomX, rightY);
        }
        /// <inheritdoc />
        protected override void SetQuadrantLimits()
        {
            MutablePoint firstPoint = this.ListOfPoint.First();

            double rightX = firstPoint.X;
            double rightY = firstPoint.Y;

            double topX = rightX;
            double topY = rightY;

            foreach (var point in this.ListOfPoint)
            {
                if (point.X >= rightX)
                {
                    if (point.X == rightX)
                    {
                        if (point.Y > rightY)
                        {
                            rightY = point.Y;
                        }
                    }
                    else
                    {
                        rightX = point.X;
                        rightY = point.Y;
                    }
                }

                if (point.Y >= topY)
                {
                    if (point.Y == topY)
                    {
                        if (point.X > topX)
                        {
                            topX = point.X;
                        }
                    }
                    else
                    {
                        topX = point.X;
                        topY = point.Y;
                    }
                }
            }

            this.FirstPoint = new MutablePoint(rightX, rightY);
            this.LastPoint  = new MutablePoint(topX, topY);
            this.RootPoint  = new MutablePoint(topX, rightY);
        }
Beispiel #5
0
        /// <inheritdoc />
        protected override void SetQuadrantLimits()
        {
            MutablePoint firstPoint = this.ListOfPoint.First();

            double leftX = firstPoint.X;
            double leftY = firstPoint.Y;

            double bottomX = leftX;
            double bottomY = leftY;

            foreach (var point in this.ListOfPoint)
            {
                if (point.X <= leftX)
                {
                    if (point.X == leftX)
                    {
                        if (point.Y < leftY)
                        {
                            leftY = point.Y;
                        }
                    }
                    else
                    {
                        leftX = point.X;
                        leftY = point.Y;
                    }
                }

                if (point.Y <= bottomY)
                {
                    if (point.Y == bottomY)
                    {
                        if (point.X < bottomX)
                        {
                            bottomX = point.X;
                        }
                    }
                    else
                    {
                        bottomX = point.X;
                        bottomY = point.Y;
                    }
                }
            }

            this.FirstPoint = new MutablePoint(leftX, leftY);
            this.LastPoint  = new MutablePoint(bottomX, bottomY);
            this.RootPoint  = new MutablePoint(bottomX, leftY);
        }
        /// <summary>
        /// Iterate over each points to see if we can add it has a ConvexHull point.
        /// It is specific by Quadrant to improve efficiency.
        /// </summary>
        /// <param name="point">a point</param>
        //// [MethodImpl(MethodImplOptions.AggressiveInlining)]
        internal override void ProcessPoint(ref MutablePoint point)
        {
            this.CurrentNode = this.Root;
            AvlNode <MutablePoint> currentPrevious = null;
            AvlNode <MutablePoint> currentNext     = null;

            while (this.CurrentNode != null)
            {
                var insertionSide = Side.Unknown;
                if (point.X > this.CurrentNode.Item.X)
                {
                    if (this.CurrentNode.Left != null)
                    {
                        this.CurrentNode = this.CurrentNode.Left;
                        continue;
                    }

                    currentPrevious = this.CurrentNode.GetPreviousNode();
                    if (CanQuickReject(ref point, ref currentPrevious.Item))
                    {
                        return;
                    }

                    if (!this.IsPointToTheRightOfOthers(currentPrevious.Item, this.CurrentNode.Item, point))
                    {
                        return;
                    }

                    // Ensure to have no duplicate
                    if (this.CurrentNode.Item == point)
                    {
                        return;
                    }

                    insertionSide = Side.Left;
                }
                else if (point.X < this.CurrentNode.Item.X)
                {
                    if (this.CurrentNode.Right != null)
                    {
                        this.CurrentNode = this.CurrentNode.Right;
                        continue;
                    }

                    currentNext = this.CurrentNode.GetNextNode();
                    if (CanQuickReject(ref point, ref currentNext.Item))
                    {
                        return;
                    }

                    if (!this.IsPointToTheRightOfOthers(this.CurrentNode.Item, currentNext.Item, point))
                    {
                        return;
                    }

                    // Ensure to have no duplicate
                    if (this.CurrentNode.Item == point)
                    {
                        continue;
                    }

                    insertionSide = Side.Right;
                }
                else
                {
                    if (point.Y <= this.CurrentNode.Item.Y)
                    {
                        return; // invalid point
                    }

                    // Replace CurrentNode point with point
                    this.CurrentNode.Item = point;
                    this.InvalidateNeighbors(this.CurrentNode.GetPreviousNode(), this.CurrentNode, this.CurrentNode.GetNextNode());
                    return;
                }

                // We should insert the point
                // Try to optimize and verify if can replace a node instead insertion to minimize tree balancing
                if (insertionSide == Side.Right)
                {
                    currentPrevious = this.CurrentNode.GetPreviousNode();
                    if (currentPrevious != null && !this.IsPointToTheRightOfOthers(currentPrevious.Item, point, this.CurrentNode.Item))
                    {
                        this.CurrentNode.Item = point;
                        this.InvalidateNeighbors(currentPrevious, this.CurrentNode, currentNext);
                        return;
                    }

                    var nextNext = currentNext.GetNextNode();
                    if (nextNext != null && !this.IsPointToTheRightOfOthers(point, nextNext.Item, currentNext.Item))
                    {
                        currentNext.Item = point;
                        this.InvalidateNeighbors(null, currentNext, nextNext);
                        return;
                    }
                }
                else
                {
                    // Left
                    currentNext = this.CurrentNode.GetNextNode();
                    if (currentNext != null && !this.IsPointToTheRightOfOthers(point, currentNext.Item, this.CurrentNode.Item))
                    {
                        this.CurrentNode.Item = point;
                        this.InvalidateNeighbors(currentPrevious, this.CurrentNode, currentNext);
                        return;
                    }

                    var previousPrevious = currentPrevious.GetPreviousNode();
                    if (previousPrevious != null && !this.IsPointToTheRightOfOthers(previousPrevious.Item, point, currentPrevious.Item))
                    {
                        currentPrevious.Item = point;
                        this.InvalidateNeighbors(previousPrevious, currentPrevious, null);
                        return;
                    }
                }

                // Should insert but no invalidation is required. (That's why we need to insert... can't replace an adjacent neighbor)
                AvlNode <MutablePoint> newNode = new AvlNode <MutablePoint>();
                if (insertionSide == Side.Right)
                {
                    newNode.Parent         = this.CurrentNode;
                    newNode.Item           = point;
                    this.CurrentNode.Right = newNode;
                    this.AddBalance(newNode.Parent, -1);
                }
                else
                {
                    // Left
                    newNode.Parent        = this.CurrentNode;
                    newNode.Item          = point;
                    this.CurrentNode.Left = newNode;
                    this.AddBalance(newNode.Parent, 1);
                }

                return;
            }
        }
 /// <summary>
 /// Check if we can quickly reject a point
 /// </summary>
 /// <param name="point">a point</param>
 /// <param name="pointHull">a point on the hull</param>
 /// <returns>True if can quickly reject; otherwise false</returns>
 //// [MethodImpl(MethodImplOptions.AggressiveInlining)]
 internal static bool CanQuickReject(ref MutablePoint point, ref MutablePoint pointHull)
 {
     return(point.X >= pointHull.X && point.Y <= pointHull.Y);
 }