コード例 #1
0
        public void Insert(TPoint2D point)
        {
            var count = Points.Size;

            //always insert first two points
            if (count != 1)
            {
                var farRight     = point.X > RightMost.X;
                var farLeft      = point.X < LeftMost.X;
                var withinBounds = !farRight && !farLeft;

                //don't insert when point lies inside the range of the convex hull but on the wrong side
                if (withinBounds)
                {
                    var orientation    = Geometry2D.Orient(LeftMost.AsVector(), RightMost.AsVector(), point.AsVector());
                    var pointLiesAbove = orientation == 1;
                    if (pointLiesAbove != IsUpper)
                    {
                        return;
                    }
                }

                TPoint2D startPoint, endPoint;
                Points.TryFind(p => UpdatePredicate(point, p, true), out startPoint);
                Points.TryFind(p => UpdatePredicate(point, p, false), out endPoint);

                //point outside of hull
                if (startPoint != null || endPoint != null)
                {
                    if (startPoint != RightMost && endPoint != LeftMost)
                    {
                        SearchPredicate <TPoint2D> inRangePredicate = p =>
                        {
                            if (startPoint != null && p.X <= startPoint.X)
                            {
                                return(1);
                            }

                            if (endPoint != null && p.X >= endPoint.X)
                            {
                                return(-1);
                            }

                            return(0);
                        };

                        //delete everything after start up to end
                        TPoint2D element;
                        Points.TryFind(inRangePredicate, out element);
                        while (element != null)
                        {
                            Points.Delete(element);
                            Points.TryFind(inRangePredicate, out element);
                        }
                    }
                }
                //point inside of hull
                else
                {
                    return;
                }
            }

            Points.Insert(point, pointWithSameX =>
            {
                if (IsUpper)
                {
                    return(point.Y > pointWithSameX.Y);
                }

                return(point.Y < pointWithSameX.Y);
            });
        }