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