1
+ #include " main.h"
2
+
3
+ struct ConvexHullPoint
4
+ {
5
+ cv::Point point;
6
+ bool toProcess;
7
+ };
8
+
9
+ void drawPoints (cv::Mat &pane, std::vector<ConvexHullPoint> &points, cv::Point *activePoint = NULL ) {
10
+ for (int i = 0 ; i < points.size (); i++)
11
+ {
12
+ cv::circle (pane, points[i].point , points[i].toProcess ? 2 : 5 , points[i].toProcess ? CL_BLUE : CL_RED , -1 );
13
+ if (activePoint != NULL && points[i].point == *activePoint)
14
+ {
15
+ cv::circle (pane, points[i].point , 8 , CL_RED, 1 );
16
+ }
17
+ /* std::stringstream ss;
18
+ ss << i;
19
+ cv::putText(pane, ss.str(), cv::Point(polygon[i].x - 10, polygon[i].y - 10), CV_FONT_HERSHEY_SIMPLEX, 0.4f, CL_WHITE, 1);*/
20
+ }
21
+ }
22
+ void drawLineToFindSmallestAngle (cv::Mat &pane, cv::Point sourcePoint, cv::Point destPoint, bool textBeforeEndpoint = false ) {
23
+
24
+ Line line = getInfiniteLinePoints (pane.cols , pane.rows , sourcePoint, destPoint, true );
25
+ cv::line (pane, line.first , line.second , CL_RED_DARK);
26
+
27
+ Vec2f lineVector = getNormalizedVector (destPoint - sourcePoint);
28
+ cv::Point2f perpVector = getPerpendicularVector (lineVector);
29
+
30
+ // cv::line(pane, textPosition, cv::Point(textPosition.x + perpVector.x * 10, textPosition.y + perpVector.y * 10), CL_WHITE);
31
+
32
+ cv::putText (pane, " p" , cv::Point (
33
+ destPoint.x + (lineVector.x * 40 * (textBeforeEndpoint ? -1 : 1 )) + perpVector.x * 15 ,
34
+ destPoint.y + (lineVector.y * 40 * (textBeforeEndpoint ? -1 : 1 )) + perpVector.y * 15
35
+ ), CV_FONT_HERSHEY_SIMPLEX, 0 .6f , CL_GREEN, 1 );
36
+
37
+ }
38
+ void drawHullPolygon (cv::Mat &pane, std::vector<cv::Point > &polygon, bool close = false ) {
39
+ if (polygon.size () < 2 ) { return ; }
40
+ int i = 0 ;
41
+ for (; i < polygon.size () - 1 ; i++)
42
+ {
43
+ cv::line (pane, polygon[i], polygon[i + 1 ], CL_YELLOW_DARK, 3 );
44
+ }
45
+ if (close ) {
46
+ cv::line (pane, polygon[i], polygon[0 ], CL_YELLOW_DARK, 3 );
47
+ }
48
+ }
49
+
50
+ int getMostLeftPointIndex (std::vector<ConvexHullPoint> &points) {
51
+ int minX = INT_MAX;
52
+ int index = 0 ;
53
+ for (int i = 0 ; i < points.size (); i++) {
54
+ if (points[i].point .x < minX)
55
+ {
56
+ minX = points[i].point .x ;
57
+ index = i;
58
+ }
59
+ }
60
+ return index ;
61
+ }
62
+ int getPointIndexWithMinimumAngle (std::vector<ConvexHullPoint> &points, cv::Point startLine, cv::Point endLine, cv::Point countInPoint, cv::Mat &pane, std::vector<cv::Point > &polygon) {
63
+ Vec2f lineVector = getNormalizedVector (startLine, endLine);
64
+ float angleCos = -10 ;
65
+ int index = 0 ;
66
+ int wait = polygon.size () < 3 ? 100 : 20 ;
67
+ for (int i = 0 ; i < points.size (); i++)
68
+ {
69
+ if (points[i].point == startLine || points[i].point == endLine) {
70
+ continue ;
71
+ }
72
+ Vec2f pointVector = getNormalizedVector (points[i].point - countInPoint);
73
+ float angle = lineVector.dot (pointVector);
74
+
75
+ pane = pane = CL_BACKGROUND;
76
+ drawHullPolygon (pane, polygon);
77
+ // cv::line(pane, startLine, cv::Point(startLine.x + lineVector.x * 45, startLine.y + lineVector.y * 45), CL_WHITE);
78
+ // cv::line(pane, countInPoint, cv::Point(countInPoint.x + pointVector.x * 45, countInPoint.y + pointVector.y * 45), CL_WHITE);
79
+ drawLineToFindSmallestAngle (pane, startLine, endLine, polygon.size () == 1 );
80
+ cv::line (pane, countInPoint, points[i].point , CL_GRAY);
81
+
82
+ std::cout << " Points: start/doIn/end " << startLine << " /" << countInPoint << " /" << points[i].point << " \n\t lineVec/pointVec " << lineVector << " /" << pointVector << " - angle" << angle;
83
+ if (angle > angleCos)
84
+ {
85
+ angleCos = angle;
86
+ index = i;
87
+ std::cout << " Change to " << i;
88
+ }
89
+
90
+ cv::line (pane, countInPoint, points[index ].point , CL_YELLOW, 2 );
91
+ drawPoints (pane, points, &countInPoint);
92
+ cv::circle (pane, points[i].point , 5 , CL_WHITE, 1 );
93
+
94
+ cv::imshow (" Convex hull" , pane);
95
+ cv::waitKey (wait );
96
+
97
+ std::cout << " \n " ;
98
+
99
+ }
100
+
101
+ std::cout << " Final angle" << angleCos << " Point index " << index << " \n\n " ;
102
+
103
+ cv::waitKey (wait );
104
+
105
+ return index ;
106
+ }
107
+
108
+ void runConvexHull () {
109
+
110
+ cv::Mat pane (500 , 700 , CV_8UC3);
111
+ int padding = 50 ;
112
+ int maxWidth = pane.cols - 2 * padding;
113
+ int maxHeight = pane.rows - 2 * padding;
114
+
115
+ std::vector<ConvexHullPoint> points (50 );
116
+ std::vector<cv::Point > polygon;
117
+ for (int i = 0 ; i < points.size (); i++)
118
+ {
119
+ points[i] = ConvexHullPoint{ cv::Point (
120
+ (int )(maxWidth * getRandom ()) + padding,
121
+ (int )(maxHeight * getRandom ()) + padding
122
+ ), true };
123
+ }
124
+ pane = pane = CL_BACKGROUND;
125
+ drawPoints (pane, points);
126
+ cv::imshow (" Convex hull" , pane);
127
+ cv::waitKey (0 );
128
+ // Get start point
129
+ int startIndex = getMostLeftPointIndex (points);
130
+ points[startIndex].toProcess = false ;
131
+ cv::Point prevPoint = points[startIndex].point ;
132
+ pane = pane = CL_BACKGROUND;
133
+ drawPoints (pane, points);
134
+ cv::imshow (" Convex hull" , pane);
135
+ cv::waitKey (1000 );
136
+ polygon.push_back (points[startIndex].point );
137
+
138
+ // Get next point
139
+ int nextIndex = getPointIndexWithMinimumAngle (points, prevPoint, cv::Point (points[startIndex].point .x , pane.rows ), prevPoint, pane, polygon);
140
+ cv::Point nextPoint = points[nextIndex].point ;
141
+ points[nextIndex].toProcess = false ;
142
+ polygon.push_back (points[nextIndex].point );
143
+ pane = pane = CL_BACKGROUND;
144
+ drawHullPolygon (pane, polygon);
145
+ drawPoints (pane, points);
146
+ cv::imshow (" Convex hull" , pane);
147
+ // cv::waitKey(0);
148
+
149
+ for (int i = 0 ; nextIndex != startIndex ; i++)
150
+ {
151
+ // drawLineToFindSmallestAngle(pane, prevPoint, nextPoint);
152
+ cv::imshow (" Convex hull" , pane);
153
+ nextIndex = getPointIndexWithMinimumAngle (points, prevPoint, nextPoint, nextPoint, pane, polygon);
154
+ prevPoint = nextPoint;
155
+ nextPoint = points[nextIndex].point ;
156
+ points[nextIndex].toProcess = false ;
157
+ polygon.push_back (points[nextIndex].point );
158
+
159
+ /* drawPoints(pane, points);
160
+ cv::imshow("Convex hull", pane);
161
+ cv::waitKey(5);*/
162
+ }
163
+
164
+ pane = pane = CL_BACKGROUND;
165
+ drawHullPolygon (pane, polygon, true );
166
+ drawPoints (pane, points);
167
+ cv::imshow (" Convex hull" , pane);
168
+ cv::waitKey (0 );
169
+
170
+ }
0 commit comments