Polygon.cpp
Go to the documentation of this file.
1/*
2 * This file is part of ArmarX.
3 *
4 * Copyright (C) 2011-2016, High Performance Humanoid Technologies (H2T), Karlsruhe Institute of Technology (KIT), all rights reserved.
5 *
6 * ArmarX is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License version 2 as
8 * published by the Free Software Foundation.
9 *
10 * ArmarX is distributed in the hope that it will be useful, but
11 * WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program. If not, see <http://www.gnu.org/licenses/>.
17 *
18 * @package
19 * @author
20 * @date
21 * @copyright http://www.gnu.org/licenses/gpl-2.0.txt
22 * GNU General Public License
23 */
24#include "Polygon.h"
25
27
29{
30
31 //******************************************************************************************************************
32 // Basic tools
33 //******************************************************************************************************************
34
35 // Sorts the points in the array inout by their X-coordinate (descending)
36 void
37 SortByX(Vec3d* inout, int arraylength)
38 {
39 Vec3d temp;
40 //bool newmax;
41 int i, j;
42
43 for (i = 0; i < arraylength; i++)
44 {
45 for (j = i + 1; j < arraylength;
46 j++) // evtl schneller: erst max-index suchen, nur am ende tauschen
47 {
48 // oder: j von oben nach unten laufen lassen
49 if (inout[j].x > inout[i].x)
50 {
51 temp = inout[j];
52 inout[j] = inout[i];
53 inout[i] = temp;
54 }
55 }
56 }
57 }
58
59 // Sorts the points in the array inout by their Y-coordinate (descending)
60 void
61 SortByY(Vec3d* inout, int arraylength)
62 {
63 Vec3d temp;
64 //bool newmax;
65 int i, j;
66
67 for (i = 0; i < arraylength; i++)
68 {
69 for (j = i + 1; j < arraylength; j++)
70 {
71 if (inout[j].y > inout[i].y)
72 {
73 temp = inout[j];
74 inout[j] = inout[i];
75 inout[i] = temp;
76 }
77 }
78 }
79 }
80
81 // returns true if line sequence definded by three points makes a turn to the left
82 bool
83 LeftTurn(Vec3d p1, Vec3d p2, Vec3d p3)
84 {
85 return (p2.x - p1.x) * (p3.y - p2.y) - (p3.x - p2.x) * (p2.y - p1.y) >= 0;
86 }
87
88 // returns true if line sequence definded by three points makes a turn to the right
89 bool
90 RightTurn(Vec3d p1, Vec3d p2, Vec3d p3)
91 {
92 return (p2.x - p1.x) * (p3.y - p2.y) - (p3.x - p2.x) * (p2.y - p1.y) <= 0;
93 }
94
95 // returns true if Point lies on the right side of the line defined by linePoint1 and linePoint2 (2D)
96 bool
97 PointIsOnTheRightSideOfTheLine(Vec3d Point, Vec3d linePoint1, Vec3d linePoint2)
98 {
99 return (Point.y - linePoint1.y) * (linePoint2.x - linePoint1.x) -
100 (Point.x - linePoint1.x) * (linePoint2.y - linePoint1.y) <
101 0;
102 }
103
104 // Returns true if it is possible that the two polygons intersect
105 bool
107 {
108 return ((pol1->maxX > pol2->minX) && (pol2->maxX > pol1->minX) &&
109 (pol1->maxY > pol2->minY) && (pol2->maxY > pol1->minY));
110 }
111
112 //******************************************************************************************************************
113 // Calculate the convex hull of polygons
114 //******************************************************************************************************************
115
116 // Analog zu Sanders-VL Algorithmentechnik, Folien 16 vom 12.02.2008, S.28-32.
117 // Calculates the convex hull of the points in "in", the left part of the hull is stored in hull_left,
118 // the right part in hull_right. Both start with the lowest point, then the highest point, then the
119 // points of the respective hull descending by y until the lowest point (again).
120 // hull_left, hull_right, temp1 and temp2 have to be of size (max number of corners of a polygon) + 1
121 void
122 CalcConvexHull(Vec3d* in,
123 int num_all_points,
124 Vec3d* hull_left,
125 int* num_hull_points_left,
126 Vec3d* hull_right,
127 int* num_hull_points_right,
128 Vec3d* temp1,
129 Vec3d* temp2)
130 {
131 int left_points_counter, right_points_counter;
132
133 for (int i = 0; i < num_all_points; i++)
134 {
135 temp1[i] = in[i];
136 }
137
138 SortByY(temp1, num_all_points);
139
140 hull_left[0] = temp1[num_all_points - 1];
141 hull_left[1] = temp1[0];
142 hull_right[0] = temp1[num_all_points - 1];
143 hull_right[1] = temp1[0];
144 float divided_x_dif =
145 (temp1[0].x - temp1[num_all_points - 1].x) / (temp1[0].y - temp1[num_all_points - 1].y);
146
147
148 // Divide into points on the left and on the right of the line from highest to lowest point.
149 // Left part is in the first part of the array, in descending order of y-values, right part
150 // is in the upper part of the array in (from the end) descending order of y-values
151 left_points_counter = 0;
152 right_points_counter = 0;
153 for (int i = 1; i < num_all_points - 1; i++)
154 {
155 if (temp1[i].x < temp1[0].x + (temp1[i].y - temp1[0].y) * divided_x_dif)
156 {
157 temp2[left_points_counter] = temp1[i];
158 left_points_counter++;
159 }
160 else
161 {
162 temp2[num_all_points - 1 - right_points_counter] = temp1[i];
163 right_points_counter++;
164 }
165 }
166 // add lowest point
167 temp2[left_points_counter] = temp1[num_all_points - 1];
168 left_points_counter++;
169 temp2[num_all_points - 1 - right_points_counter] = temp1[num_all_points - 1];
170 right_points_counter++;
171
172
173 // left part
174 int hull_ind_l = 2;
175 hull_left[2] = temp2[0];
176 for (int i = 1; i < left_points_counter; i++)
177 {
178 while (RightTurn(hull_left[hull_ind_l - 1], hull_left[hull_ind_l], temp2[i]))
179 {
180 hull_ind_l--;
181 }
182 hull_ind_l++;
183 hull_left[hull_ind_l] = temp2[i];
184 }
185 *num_hull_points_left = hull_ind_l + 1;
186
187
188 //right part
189 int hull_ind_r = 2;
190 hull_right[2] = temp2[num_all_points - 1];
191 for (int i = 2; i <= right_points_counter; i++)
192 {
193 while (LeftTurn(
194 hull_right[hull_ind_r - 1], hull_right[hull_ind_r], temp2[num_all_points - i]))
195 {
196 hull_ind_r--;
197 }
198 hull_ind_r++;
199 hull_right[hull_ind_r] = temp2[num_all_points - i];
200 }
201 *num_hull_points_right = hull_ind_r + 1;
202 }
203
204 void
205 CalcConvexHull(Vec3d* in,
206 int num_all_points,
207 Vec3d* hull_left,
208 int* num_hull_points_left,
209 Vec3d* hull_right,
210 int* num_hull_points_right)
211 {
212 Vec3d* temp1 = new Vec3d[num_all_points + 1];
213 Vec3d* temp2 = new Vec3d[num_all_points + 1];
215 num_all_points,
216 hull_left,
217 num_hull_points_left,
218 hull_right,
219 num_hull_points_right,
220 temp1,
221 temp2);
222 }
223
224 // interface to create the convex polygon pol from the points in the array in
225 void
226 CalcConvexHull(Vec3d* in, int num_all_points, Polygon* pol, Vec3d* temp1, Vec3d* temp2)
227 {
228 int i, j;
229
231 num_all_points,
232 (Vec3d*)&pol->hullLeft,
233 &pol->nCornersLeft,
234 (Vec3d*)&pol->hullRight,
235 &pol->nCornersRight,
236 temp1,
237 temp2);
238
239 // merge left and right part of the hull with corners ordered by y descending
240 pol->hull[0] = pol->hullLeft[1]; // first elem = highest point
241 pol->hull[0].z = 3;
242 int ind_l = 2;
243 int ind_r = 2;
244 int ind_h = 1;
245 while (ind_l < pol->nCornersLeft - 1 && ind_r < pol->nCornersRight - 1)
246 {
247 if (pol->hullLeft[ind_l].y > pol->hullRight[ind_r].y)
248 {
249 pol->hull[ind_h] = pol->hullLeft[ind_l];
250 pol->hull[ind_h].z = 1;
251 ind_l++;
252 }
253 else
254 {
255 pol->hull[ind_h] = pol->hullRight[ind_r];
256 pol->hull[ind_h].z = 2;
257 ind_r++;
258 }
259 ind_h++;
260 }
261 // now get the elements which rest in the left or the right part
262 while (ind_l < pol->nCornersLeft - 1)
263 {
264 pol->hull[ind_h] = pol->hullLeft[ind_l];
265 pol->hull[ind_h].z = 1;
266 ind_l++;
267 ind_h++;
268 }
269 while (ind_r < pol->nCornersRight - 1)
270 {
271 pol->hull[ind_h] = pol->hullRight[ind_r];
272 pol->hull[ind_h].z = 2;
273 ind_r++;
274 ind_h++;
275 }
276
277 pol->nCorners = pol->nCornersRight + pol->nCornersLeft - 4;
278 pol->hull[pol->nCorners - 1] = pol->hullLeft[0]; // last elem = lowest point
279 pol->hull[pol->nCorners - 1].z = 3;
280
281
282 // calculate the hull with the corners ordered in clockwise sense
283 i = 0;
284 for (j = 1; j < pol->nCornersRight - 1; j++, i++)
285 {
286 pol->hullCircle[i] = pol->hullRight[j];
287 }
288 pol->hullCircle[i] = pol->hullRight[0];
289 i++;
290 for (j = pol->nCornersLeft - 2; j > 1; j--, i++)
291 {
292 pol->hullCircle[i] = pol->hullLeft[j];
293 }
294 pol->hullCircle[i] = pol->hullRight[1];
295
296
297 // calculate the coordinates for the enveloping rectangle
298 pol->minY = pol->hull[pol->nCorners - 1].y;
299 pol->maxY = pol->hull[0].y;
300 pol->minX = pol->hull[0].x;
301 for (i = 2; i <= pol->nCornersLeft; i++)
302 if (pol->hullLeft[i].x < pol->minX)
303 {
304 pol->minX = pol->hullLeft[i].x;
305 }
306 pol->maxX = pol->hull[0].x;
307 for (i = 2; i <= pol->nCornersRight; i++)
308 if (pol->hullRight[i].x > pol->maxX)
309 {
310 pol->maxX = pol->hullRight[i].x;
311 }
312 }
313
314 void
315 CalcConvexHull(Vec3d* in, int num_all_points, Polygon* pol)
316 {
317 Vec3d* temp1 = new Vec3d[num_all_points + 1];
318 Vec3d* temp2 = new Vec3d[num_all_points + 1];
319 CalcConvexHull(in, num_all_points, pol, temp1, temp2);
320 }
321
322 // interface to create the convex polygon pol from the points already in pol->hull
323 void
324 CalcConvexHull(Polygon* pol, Vec3d* temp1, Vec3d* temp2)
325 {
326 CalcConvexHull((Vec3d*)&pol->hull, pol->nCorners, pol, temp1, temp2);
327 }
328
329 void
331 {
332 Vec3d* temp1 = new Vec3d[pol->nCorners + 1];
333 Vec3d* temp2 = new Vec3d[pol->nCorners + 1];
334 CalcConvexHull(pol, temp1, temp2);
335 }
336
337 // creates a convex polygon from the points in hullpoints, assuming that they all belong to the
338 // convex hull
339 void
340 CreateConvexPolygonFromHullPoints(Vec3d* hullpoints, int nPoints, Polygon* pol)
341 {
342 int left_points_counter, right_points_counter;
343
344 SortByY(hullpoints, nPoints);
345
346 pol->hullLeft[0] = hullpoints[nPoints - 1];
347 pol->hullLeft[1] = hullpoints[0];
348 pol->hullRight[0] = hullpoints[nPoints - 1];
349 pol->hullRight[1] = hullpoints[0];
350 float divided_x_dif = (hullpoints[0].x - hullpoints[nPoints - 1].x) /
351 (hullpoints[0].y - hullpoints[nPoints - 1].y);
352
353 pol->hull[0].x = hullpoints[0].x;
354 pol->hull[0].y = hullpoints[0].y;
355 pol->hull[0].z = 3;
356 pol->hull[nPoints - 1].x = hullpoints[nPoints - 1].x;
357 pol->hull[nPoints - 1].y = hullpoints[nPoints - 1].y;
358 pol->hull[nPoints - 1].z = 3;
359
360 left_points_counter = 2;
361 right_points_counter = 2;
362 for (int i = 1; i < nPoints - 1; i++)
363 {
364 pol->hull[i].x = hullpoints[i].x;
365 pol->hull[i].y = hullpoints[i].y;
366 if (hullpoints[i].x <
367 hullpoints[0].x + (hullpoints[i].y - hullpoints[0].y) * divided_x_dif)
368 {
369 pol->hullLeft[left_points_counter] = hullpoints[i];
370 pol->hull[i].z = 1;
371 left_points_counter++;
372 }
373 else
374 {
375 pol->hullRight[right_points_counter] = hullpoints[i];
376 pol->hull[i].z = 2;
377 right_points_counter++;
378 }
379 }
380
381 pol->hullLeft[left_points_counter] = hullpoints[nPoints - 1];
382 pol->hullRight[right_points_counter] = hullpoints[nPoints - 1];
383
384 pol->nCorners = nPoints;
385 pol->nCornersLeft = left_points_counter + 1;
386 pol->nCornersRight = right_points_counter + 1;
387
388 // calculate the hull with the corners ordered in clockwise sense
389 int i = 0;
390 for (int j = 1; j < pol->nCornersRight - 1; j++, i++)
391 {
392 pol->hullCircle[i] = pol->hullRight[j];
393 }
394 pol->hullCircle[i] = pol->hullRight[0];
395 i++;
396 for (int j = pol->nCornersLeft - 2; j > 1; j--, i++)
397 {
398 pol->hullCircle[i] = pol->hullLeft[j];
399 }
400 pol->hullCircle[i] = pol->hullRight[1];
401
402
403 // calculate the coordinates for the enveloping rectangle
404 pol->minY = pol->hull[pol->nCorners - 1].y;
405 pol->maxY = pol->hull[0].y;
406 pol->minX = pol->hull[0].x;
407 for (int i = 2; i <= pol->nCornersLeft; i++)
408 if (pol->hullLeft[i].x < pol->minX)
409 {
410 pol->minX = pol->hullLeft[i].x;
411 }
412 pol->maxX = pol->hull[0].x;
413 for (int i = 2; i <= pol->nCornersRight; i++)
414 if (pol->hullRight[i].x > pol->maxX)
415 {
416 pol->maxX = pol->hullRight[i].x;
417 }
418 }
419
420 //******************************************************************************************************************
421 // Calculate the intersection polygon of two convex polygons
422 //******************************************************************************************************************
423
424 // returns the convex polygon that is the intersection polygon of p1 and p2. pointAccu and boolTable have to
425 // be of size 2*(maximal number of points in a normal polygon), clockwiseHullPoly1/2 of size (maximal number
426 // of points in a normal polygon)+1
427 void
429 Polygon* p2,
430 Polygon* pInter,
431 Vec3d* pointAccu,
432 bool* boolTable,
433 Vec3d* clockwiseHullPoly1,
434 Vec3d* clockwiseHullPoly2)
435 {
436 int pointcount = 0;
437 int i, j;
438
439 //*******************************************************************
440 // Get corners of polygon 1 that lie inside polygon 2
441 //
442 // The line segments are traversed in clockwise order. A point lies
443 // inside the convex polygon iff it is on the right side of every
444 // line segment.
445 //*******************************************************************
446
447 // boolTable contains booleans which indicate if point i is inside the polygon
448 for (j = 0; j < p1->nCorners; j++)
449 {
450 boolTable[j] = true;
451 }
452
453 for (i = 0; i < p2->nCorners; i++)
454 for (j = 0; j < p1->nCorners; j++)
455 {
456 boolTable[j] &= PointIsOnTheRightSideOfTheLine(
457 p1->hull[j], p2->hullCircle[i], p2->hullCircle[i + 1]);
458 }
459
460
461 for (j = 0; j < p1->nCorners; j++)
462 if (boolTable[j] == true)
463 {
464 pointAccu[pointcount] = p1->hull[j];
465 pointcount++;
466 }
467
468
469 //*******************************************************************
470 // Get corners of polygon 2 that lie inside polygon 1
471 //*******************************************************************
472
473 for (j = 0; j < p2->nCorners; j++)
474 {
475 boolTable[j] = true;
476 }
477
478 for (i = 0; i < p1->nCorners; i++)
479 for (j = 0; j < p2->nCorners; j++)
480 {
481 boolTable[j] &= PointIsOnTheRightSideOfTheLine(
482 p2->hull[j], p1->hullCircle[i], p1->hullCircle[i + 1]);
483 }
484
485
486 for (j = 0; j < p2->nCorners; j++)
487 if (boolTable[j] == true)
488 {
489 pointAccu[pointcount] = p2->hull[j];
490 pointcount++;
491 }
492
493
494 // optim: hier abbruchkriterium, wenn pointcount=0 und zentren nicht sehr nah beieinander
495
496
497 //*******************************************************************
498 // Calculate intersections
499 //
500 // A line is defined as p1 + c*(p2-p1). Solving the two equations
501 // resulting from setting line1 = line2 gives the value of c for
502 // which the above term gives the intersection point. If c is
503 // in [0,1], the intersection lies on the line segment (p1,p2).
504 // An analogue criterion exists for the other line segment.
505 //*******************************************************************
506
507 float x1, y1, x2, y2, x3, y3, x4, y4, c1, c2, denominator;
508
509
510 for (i = 0; i < p1->nCorners; i++)
511 {
512 x1 = p1->hullCircle[i].x;
513 y1 = p1->hullCircle[i].y;
514 x2 = p1->hullCircle[i + 1].x;
515 y2 = p1->hullCircle[i + 1].y;
516 for (j = 0; j < p2->nCorners; j++)
517 {
518 x3 = p2->hullCircle[j].x;
519 y3 = p2->hullCircle[j].y;
520 x4 = p2->hullCircle[j + 1].x;
521 y4 = p2->hullCircle[j + 1].y;
522 denominator = (y4 - y3) * (x2 - x1) - (x4 - x3) * (y2 - y1);
523 c1 = ((x4 - x3) * (y1 - y3) - (y4 - y3) * (x1 - x3)) / denominator;
524 c2 = ((x2 - x1) * (y1 - y3) - (y2 - y1) * (x1 - x3)) / denominator;
525 if (0 <= c1 && 1 >= c1 && 0 <= c2 && 1 >= c2)
526 {
527 pointAccu[pointcount].x = x1 + c1 * (x2 - x1);
528 pointAccu[pointcount].y = y1 + c1 * (y2 - y1);
529 pointcount++;
530 }
531 }
532 }
533
534 if (pointcount >= 3)
535 {
536 CreateConvexPolygonFromHullPoints(pointAccu, pointcount, pInter);
537 }
538 else
539 {
540 pInter->nCorners = 0;
541 }
542 }
543
544 void
546 {
547 Vec3d pointAccu[2 * DSHT_MAX_POLYGON_CORNERS];
548 bool boolTable[2 * DSHT_MAX_POLYGON_CORNERS];
549 Vec3d clockwiseHullPoly1[DSHT_MAX_POLYGON_CORNERS + 1];
550 Vec3d clockwiseHullPoly2[DSHT_MAX_POLYGON_CORNERS + 1];
552 p1, p2, pInter, pointAccu, boolTable, clockwiseHullPoly1, clockwiseHullPoly2);
553 }
554
555} // namespace visionx::ConvexPolygonCalculations
#define DSHT_MAX_POLYGON_CORNERS
This file offers overloads of toIce() and fromIce() functions for STL container types.
void SortByY(Vec3d *inout, int arraylength)
Definition Polygon.cpp:61
bool LeftTurn(Vec3d p1, Vec3d p2, Vec3d p3)
Definition Polygon.cpp:83
bool PointIsOnTheRightSideOfTheLine(Vec3d Point, Vec3d linePoint1, Vec3d linePoint2)
Definition Polygon.cpp:97
bool RightTurn(Vec3d p1, Vec3d p2, Vec3d p3)
Definition Polygon.cpp:90
void CreateConvexPolygonFromHullPoints(Vec3d *hullpoints, int nPoints, Polygon *pol)
Definition Polygon.cpp:340
void SortByX(Vec3d *inout, int arraylength)
Definition Polygon.cpp:37
bool PolygonsMightIntersect(Polygon *pol1, Polygon *pol2)
Definition Polygon.cpp:106
void CalcConvexHull(Vec3d *in, int num_all_points, Vec3d *hull_left, int *num_hull_points_left, Vec3d *hull_right, int *num_hull_points_right, Vec3d *temp1, Vec3d *temp2)
Definition Polygon.cpp:122
void GetPolygonIntersection(Polygon *p1, Polygon *p2, Polygon *pInter, Vec3d *pointAccu, bool *boolTable, Vec3d *clockwiseHullPoly1, Vec3d *clockwiseHullPoly2)
Definition Polygon.cpp:428
Eigen::Vector3f Point
Vec3d hullCircle[2 *DSHT_MAX_POLYGON_CORNERS+1]
Definition Polygon.h:41
Vec3d hull[2 *DSHT_MAX_POLYGON_CORNERS]
Definition Polygon.h:37
Vec3d hullLeft[2 *DSHT_MAX_POLYGON_CORNERS+1]
Definition Polygon.h:49
Vec3d hullRight[2 *DSHT_MAX_POLYGON_CORNERS+1]
Definition Polygon.h:52