Accord.Math.Geometry.GrahamConvexHull.FindHull C# (CSharp) Method

FindHull() public method

Find convex hull for the given set of points.
public FindHull ( List points ) : List
points List Set of points to search convex hull for.
return List
        public List<IntPoint> FindHull( List<IntPoint> points )
        {
            // do nothing if there 3 points or less
            if ( points.Count <= 3 )
            {
                return new List<IntPoint>( points );
            }

            List<PointToProcess> pointsToProcess = new List<PointToProcess>( );

            // convert input points to points we can process
            foreach ( IntPoint point in points )
            {
                pointsToProcess.Add( new PointToProcess( point ) );
            }

            // find a point, with lowest X and lowest Y
            int firstCornerIndex = 0;
            PointToProcess firstCorner = pointsToProcess[0];

            for ( int i = 1, n = pointsToProcess.Count; i < n; i++ )
            {
                if ( ( pointsToProcess[i].X < firstCorner.X ) ||
                     ( ( pointsToProcess[i].X == firstCorner.X ) && ( pointsToProcess[i].Y < firstCorner.Y ) ) )
                {
                    firstCorner = pointsToProcess[i];
                    firstCornerIndex = i;
                }
            }

            // remove the just found point
            pointsToProcess.RemoveAt( firstCornerIndex );

            // find K (tangent of line's angle) and distance to the first corner
            for ( int i = 0, n = pointsToProcess.Count; i < n; i++ )
            {
                int dx = pointsToProcess[i].X - firstCorner.X;
                int dy = pointsToProcess[i].Y - firstCorner.Y;

                // don't need square root, since it is not important in our case
                pointsToProcess[i].Distance = dx * dx + dy * dy;
                // tangent of lines angle
                pointsToProcess[i].K = ( dx == 0 ) ? float.PositiveInfinity : (float) dy / dx;
            }

            // sort points by angle and distance
            pointsToProcess.Sort( );

            List<PointToProcess> convexHullTemp = new List<PointToProcess>( );

            // add first corner, which is always on the hull
            convexHullTemp.Add( firstCorner );
            // add another point, which forms a line with lowest slope
            convexHullTemp.Add( pointsToProcess[0] );
            pointsToProcess.RemoveAt( 0 );

            PointToProcess lastPoint = convexHullTemp[1];
            PointToProcess prevPoint = convexHullTemp[0];

            while ( pointsToProcess.Count != 0 )
            {
                PointToProcess newPoint = pointsToProcess[0];

                // skip any point, which has the same slope as the last one or
                // has 0 distance to the first point
                if ( ( newPoint.K == lastPoint.K ) || ( newPoint.Distance == 0 ) )
                {
                    pointsToProcess.RemoveAt( 0 );
                    continue;
                }

                // check if current point is on the left side from two last points
                if ( ( newPoint.X - prevPoint.X ) * ( lastPoint.Y - newPoint.Y ) - ( lastPoint.X - newPoint.X ) * ( newPoint.Y - prevPoint.Y ) < 0 )
                {
                    // add the point to the hull
                    convexHullTemp.Add( newPoint );
                    // and remove it from the list of points to process
                    pointsToProcess.RemoveAt( 0 );

                    prevPoint = lastPoint;
                    lastPoint = newPoint;
                }
                else
                {
                    // remove the last point from the hull
                    convexHullTemp.RemoveAt( convexHullTemp.Count - 1 );

                    lastPoint = prevPoint;
                    prevPoint = convexHullTemp[convexHullTemp.Count - 2];
                }
            }

            // convert points back
            List<IntPoint> convexHull = new List<IntPoint>( );

            foreach ( PointToProcess pt in convexHullTemp )
            {
                convexHull.Add( pt.ToPoint( ) );
            }

            return convexHull;
        }

Usage Example

        public void FindTest()
        {
            List<IntPoint> contour = new List<IntPoint>();

            int max = 100;

            for (int i = 0; i < max; i++)
                add(contour, i, max);

            for (int i = 0; i < max; i++)
                add(contour, max, i);

            for (int i = 0; i < max; i++)
                add(contour, 0, i);

            for (int i = 0; i < max / 2; i++)
                add(contour, i, i);

            for (int i = 0; i < max / 2; i++)
                add(contour, i + max / 2, max / 2 - i);

            PointsMarker marker = new PointsMarker(contour);
            var bitmap = Accord.Imaging.Image.CreateGrayscaleImage(max + 1, max + 1);
            bitmap = marker.Apply(bitmap);
            // Accord.Controls.ImageBox.Show(bitmap);

            GrahamConvexHull graham = new GrahamConvexHull();
            List<IntPoint> hull = graham.FindHull(contour);
            ConvexHullDefects hullDefects = new ConvexHullDefects(10);
            List<ConvexityDefect> defects = hullDefects.FindDefects(contour, hull);

            Assert.AreEqual(1, defects.Count);
            Assert.AreEqual(99, defects[0].Depth);
        }
All Usage Examples Of Accord.Math.Geometry.GrahamConvexHull::FindHull
GrahamConvexHull