예제 #1
0
        public void ClockwiseTangentMove(ref ConvexHull hull, ref TangentLine TLine, ref double slope, ref int slopeChangedCount, string TangentType)
        {
            bool   slopeChanged  = false;
            string LOWER_TANGENT = "LOWER_TANGENT";

            do
            {
                int    index;
                PointF pendingTanPoint;
                double pendingSlope;
                if (TangentType == LOWER_TANGENT)
                {
                    //TangentLeftPoint will move to the next point in a CLOCKWISE direction
                    float leftPointX = TLine.GetLeftPoint().X;
                    index = hull.GetConvexHullPoints().FindIndex(p => p.X == leftPointX);

                    //Start at the index, so to go CLOCKWISE we need to move next through the list
                    int i = Next(hull.GetConvexHullPoints(), index);

                    pendingTanPoint = hull.GetConvexHullPoints()[i];
                    pendingSlope    = CalculateSlope(pendingTanPoint, TLine.GetRightPoint());
                }
                else
                {
                    //TangentRightPoint will move to the next point in a CLOCKWISE direction
                    float rightPointX = TLine.GetRightPoint().X;
                    index = hull.GetConvexHullPoints().FindIndex(p => p.X == rightPointX);

                    //Start at the index, so to go CLOCKWISE we need to move next through the list
                    int i = Next(hull.GetConvexHullPoints(), index);

                    pendingTanPoint = hull.GetConvexHullPoints()[i];
                    pendingSlope    = CalculateSlope(TLine.GetLeftPoint(), pendingTanPoint);
                }


                if (pendingSlope > slope)
                {
                    //That's good, so now we can change the tangent line
                    if (TangentType == LOWER_TANGENT)
                    {
                        TLine.SetLeftPoint(pendingTanPoint);
                    }
                    else
                    {
                        TLine.SetRightPoint(pendingTanPoint);
                    }
                    //And also update the slope
                    slope = pendingSlope;
                    //And the slope changed
                    slopeChanged = true;
                    slopeChangedCount++;
                }
                else
                {
                    slopeChanged = false;
                }
            } while (slopeChanged);
        }
예제 #2
0
        public ConvexHull FindConvexHull(List <PointF> points)
        {
            //Base Case
            int n = points.Count;

            if (n == 1)
            {
                return(new ConvexHull(points));
            }

            //Recursion
            ConvexHull chLeft  = null;
            ConvexHull chRight = null;

            if (n > 1)
            {
                int mid = (int)Math.Ceiling((double)points.Count / 2);

                List <PointF> lowerHalf = GetPointsWithinRange(0, mid, points);
                List <PointF> upperHalf = GetPointsWithinRange(mid, n, points);

                chLeft  = FindConvexHull(lowerHalf);
                chRight = FindConvexHull(upperHalf);
            }

            //Make Tangent Lines

            //Rightmost X value of the Left Hull
            PointF tanPointLeft = GetPointFromHull("RIGHTMOST", chLeft);
            //Leftmost X value of the Right Hull
            PointF tanPointRight = GetPointFromHull("LEFTMOST", chRight);

            TangentLine upperTangent = new TangentLine(tanPointLeft, tanPointRight);
            TangentLine lowerTangent = new TangentLine(tanPointLeft, tanPointRight);


            //Record the slope of the tangent lines
            double slope = CalculateSlope(upperTangent.GetLeftPoint(), upperTangent.GetRightPoint());
            bool   thereCouldBeMoreChanges = false;

            //bool slopeChanged = false;

            //Major Loop (CONDITION) for UPPER TANGENT LINE
            do
            {
                int slopeChangedCount = 0;

                //UpperTanLeft Loop
                CounterClockwiseTangentMove(ref chLeft, ref upperTangent, ref slope, ref slopeChangedCount, "UPPER_TANGENT");

                //UpperTanRight Loop
                ClockwiseTangentMove(ref chRight, ref upperTangent, ref slope, ref slopeChangedCount, "UPPER_TANGENT");

                thereCouldBeMoreChanges = (slopeChangedCount > 0) ? true : false;
            } while (thereCouldBeMoreChanges);

            //Major Loop (CONDITION) for LOWER TANGENT LINE
            slope = CalculateSlope(lowerTangent.GetLeftPoint(), lowerTangent.GetRightPoint());
            do
            {
                int slopeChangedCount = 0;

                //LowerTanLeft Loop
                ClockwiseTangentMove(ref chLeft, ref lowerTangent, ref slope, ref slopeChangedCount, "LOWER_TANGENT");

                //LowerTanRight Loop
                CounterClockwiseTangentMove(ref chRight, ref lowerTangent, ref slope, ref slopeChangedCount, "LOWER_TANGENT");

                thereCouldBeMoreChanges = (slopeChangedCount > 0) ? true : false;
            } while (thereCouldBeMoreChanges);


            return(MergeConvexHulls(chLeft, chRight, upperTangent, lowerTangent));
        }
예제 #3
0
        public ConvexHull MergeConvexHulls(ConvexHull hullLeft, ConvexHull hullRight, TangentLine upTan, TangentLine lowTan)
        {
            //Start at the upTan right point using the hullRight first because the upTan Right Point will be in the hullRight
            float upTanRightPointX = upTan.GetRightPoint().X;
            int   index            = hullRight.GetConvexHullPoints().FindIndex(p => p.X == upTanRightPointX);

            //Make a new convexHull that will contain the merged hulls
            ConvexHull mergedHull = new ConvexHull(upTan.GetRightPoint());

            //Move clockwise until we get to lowTan right point
            PointF nextPoint;
            bool   sameIndexWasReturned = false;

            //If the starting point isn't already the lowertangent right point, then do the loop
            if (upTan.GetRightPoint().X != lowTan.GetRightPoint().X)
            {
                do
                {
                    int i = Next(hullRight.GetConvexHullPoints(), index, ref sameIndexWasReturned);
                    nextPoint = hullRight.GetConvexHullPoints()[i];

                    //Add the nextPoint into the mergedHull
                    if (!sameIndexWasReturned)
                    {
                        mergedHull.AddPoint(nextPoint);
                    }

                    //Update index
                    index = i;
                } while (nextPoint.X != lowTan.GetRightPoint().X);
            }

            //If we are right here, that means that the last point just added, was the Lower Tangent Right Point.
            //Now we want to add the Lower Tangent Left Point, and start iterating up CLOCKWISE the leftHull until we reach the point that is equal to the Upper Tangent Left Point.

            nextPoint = lowTan.GetLeftPoint();
            mergedHull.AddPoint(nextPoint);

            float lowTanLeftPointX = lowTan.GetLeftPoint().X;

            index = hullLeft.GetConvexHullPoints().FindIndex(p => p.X == lowTanLeftPointX);

            //If the lowertanget left point isn't already the upper tangent left point, then do the loop.
            if (lowTan.GetLeftPoint().X != upTan.GetLeftPoint().X)
            {
                sameIndexWasReturned = false;
                do
                {
                    int i = Next(hullLeft.GetConvexHullPoints(), index, ref sameIndexWasReturned);
                    nextPoint = hullLeft.GetConvexHullPoints()[i];

                    //Add the nextPoint into the mergedHull
                    if (!sameIndexWasReturned)
                    {
                        mergedHull.AddPoint(nextPoint);
                    }

                    //Update index
                    index = i;
                } while (nextPoint.X != upTan.GetLeftPoint().X);
            }

            //Once we reach here that means that last point added was the Upper Left Tangent Point, which is the last one we need to add for a complete hull.
            return(mergedHull);
        }