@@ -60,87 +60,86 @@ public List<IntPoint> FindHull(List<IntPoint> points)
6060 return new List < IntPoint > ( points ) ;
6161 }
6262
63- List < PointToProcess > pointsToProcess = new List < PointToProcess > ( ) ;
64-
65- // convert input points to points we can process
66- foreach ( IntPoint point in points )
67- {
68- pointsToProcess . Add ( new PointToProcess ( point ) ) ;
69- }
70-
7163 // find a point, with lowest X and lowest Y
7264 int firstCornerIndex = 0 ;
73- PointToProcess firstCorner = pointsToProcess [ 0 ] ;
65+ IntPoint pointFirstCorner = points [ 0 ] ;
7466
75- for ( int i = 1 , n = pointsToProcess . Count ; i < n ; i ++ )
67+ for ( int i = 1 , n = points . Count ; i < n ; i ++ )
7668 {
77- if ( ( pointsToProcess [ i ] . X < firstCorner . X ) ||
78- ( ( pointsToProcess [ i ] . X == firstCorner . X ) && ( pointsToProcess [ i ] . Y < firstCorner . Y ) ) )
69+ if ( ( points [ i ] . X < pointFirstCorner . X ) ||
70+ ( ( points [ i ] . X == pointFirstCorner . X ) && ( points [ i ] . Y < pointFirstCorner . Y ) ) )
7971 {
80- firstCorner = pointsToProcess [ i ] ;
72+ pointFirstCorner = points [ i ] ;
8173 firstCornerIndex = i ;
8274 }
8375 }
8476
85- // remove the just found point
86- pointsToProcess . RemoveAt ( firstCornerIndex ) ;
77+ // convert input points to points we can process
78+ PointToProcess firstCorner = new PointToProcess ( pointFirstCorner ) ;
79+ // Points to process must exclude the first corner that we've already found
80+ PointToProcess [ ] arrPointsToProcess = new PointToProcess [ points . Count - 1 ] ;
81+ for ( int i = 0 ; i < points . Count - 1 ; i ++ )
82+ {
83+ IntPoint point = points [ i >= firstCornerIndex ? i + 1 : i ] ;
84+ arrPointsToProcess [ i ] = new PointToProcess ( point ) ;
85+ }
8786
8887 // find K (tangent of line's angle) and distance to the first corner
89- for ( int i = 0 , n = pointsToProcess . Count ; i < n ; i ++ )
88+ for ( int i = 0 , n = arrPointsToProcess . Length ; i < n ; i ++ )
9089 {
91- int dx = pointsToProcess [ i ] . X - firstCorner . X ;
92- int dy = pointsToProcess [ i ] . Y - firstCorner . Y ;
90+ int dx = arrPointsToProcess [ i ] . X - firstCorner . X ;
91+ int dy = arrPointsToProcess [ i ] . Y - firstCorner . Y ;
9392
9493 // don't need square root, since it is not important in our case
95- pointsToProcess [ i ] . Distance = dx * dx + dy * dy ;
94+ arrPointsToProcess [ i ] . Distance = dx * dx + dy * dy ;
9695 // tangent of lines angle
97- pointsToProcess [ i ] . K = ( dx == 0 ) ? float . PositiveInfinity : ( float ) dy / dx ;
96+ arrPointsToProcess [ i ] . K = ( dx == 0 ) ? float . PositiveInfinity : ( float ) dy / dx ;
9897 }
9998
10099 // sort points by angle and distance
101- pointsToProcess . Sort ( ) ;
100+ Array . Sort ( arrPointsToProcess ) ;
102101
103- List < PointToProcess > convexHullTemp = new List < PointToProcess > ( ) ;
102+ // Convert points to process to a queue. Continually removing the first item of an array list
103+ // is highly inefficient
104+ Queue < PointToProcess > queuePointsToProcess = new Queue < PointToProcess > ( arrPointsToProcess ) ;
105+
106+ LinkedList < PointToProcess > convexHullTemp = new LinkedList < PointToProcess > ( ) ;
104107
105108 // add first corner, which is always on the hull
106- convexHullTemp . Add ( firstCorner ) ;
109+ PointToProcess prevPoint = convexHullTemp . AddLast ( firstCorner ) . Value ;
107110 // add another point, which forms a line with lowest slope
108- convexHullTemp . Add ( pointsToProcess [ 0 ] ) ;
109- pointsToProcess . RemoveAt ( 0 ) ;
110-
111- PointToProcess lastPoint = convexHullTemp [ 1 ] ;
112- PointToProcess prevPoint = convexHullTemp [ 0 ] ;
111+ PointToProcess lastPoint = convexHullTemp . AddLast ( queuePointsToProcess . Dequeue ( ) ) . Value ;
113112
114- while ( pointsToProcess . Count != 0 )
113+ while ( queuePointsToProcess . Count != 0 )
115114 {
116- PointToProcess newPoint = pointsToProcess [ 0 ] ;
115+ PointToProcess newPoint = queuePointsToProcess . Peek ( ) ;
117116
118117 // skip any point, which has the same slope as the last one or
119118 // has 0 distance to the first point
120119 if ( ( newPoint . K == lastPoint . K ) || ( newPoint . Distance == 0 ) )
121120 {
122- pointsToProcess . RemoveAt ( 0 ) ;
121+ queuePointsToProcess . Dequeue ( ) ;
123122 continue ;
124123 }
125124
126125 // check if current point is on the left side from two last points
127126 if ( ( newPoint . X - prevPoint . X ) * ( lastPoint . Y - newPoint . Y ) - ( lastPoint . X - newPoint . X ) * ( newPoint . Y - prevPoint . Y ) < 0 )
128127 {
129128 // add the point to the hull
130- convexHullTemp . Add ( newPoint ) ;
129+ convexHullTemp . AddLast ( newPoint ) ;
131130 // and remove it from the list of points to process
132- pointsToProcess . RemoveAt ( 0 ) ;
131+ queuePointsToProcess . Dequeue ( ) ;
133132
134133 prevPoint = lastPoint ;
135134 lastPoint = newPoint ;
136135 }
137136 else
138137 {
139138 // remove the last point from the hull
140- convexHullTemp . RemoveAt ( convexHullTemp . Count - 1 ) ;
139+ convexHullTemp . RemoveLast ( ) ;
141140
142141 lastPoint = prevPoint ;
143- prevPoint = convexHullTemp [ convexHullTemp . Count - 2 ] ;
142+ prevPoint = convexHullTemp . Last . Previous . Value ;
144143 }
145144 }
146145
0 commit comments