VAT  3.0
Video Analysis Tool
geometric.h
1 #ifndef _GEOMETRIC_H_
2 #define _GEOMETRIC_H_
3 
4 #include <vector>
5 #include <deque>
6 #include <cmath>
7 #include <cfloat>
8 #include <cstring>
9 #include <iostream>
10 #include "common.h"
11 #include "calibration.h"
12 
13 //#define M_PI 3.14159265358979323846 // why would you redefine M_PI? WTF!
14 //Intersection error defined as sqrt(2)/2, as used in function pointxy_in_segment_strict
15 #define MAX_ERROR_TO_INTERSECTION 0.707106781186547524381894
16 #define MAX_FLOAT_ERROR 0.01
17 #define MAX_FLOAT_ERROR_LITTLE_NUMBERS 0.000001
18 
19 template <typename T>
20 class Rectangle;
21 
22 template <typename T>
23 class line2D {
24  public:
25  line2D();
26  line2D(T i_x1, T i_y1, T i_x2, T i_y2);
27  ~line2D();
28 
29  T x1;
30  T y1;
31  T x2;
32  T y2;
33 };
34 
35 template <typename T>
36 class Intersection {
37  public:
38  Intersection();
39  Intersection(T i_x1, T i_y1, T i_x2, T i_y2);
40  ~Intersection();
41 
42  T x1, y1;
43  T x2, y2;
44  T distance;
45  int type; // 1: One point intersection (Stored in (x1,y1) )
46  // 0: Segment intersection (Limits stored in {(x1,y1);(x2,y2)} )
47 };
48 
49 template <typename T>
50 class point2D {
51  public:
52  point2D();
53  point2D(T i_x, T i_y);
54  ~point2D();
55  static double distance(point2D *p1, point2D *p2);
56  static bool isCCWPts(point2D *pPt0, point2D *pPt1, point2D *pPt2);
57  static bool isCCW(double x0, double y0, double x1, double y1, double x2, double y2);
58  static bool processIntersectionLines(double x1, double y1, double x2, double y2,
59  double x3, double y3, double x4, double y4,
60  point2D *pIntersection);
61  static bool isLinesIntersection(double x1, double y1, double x2, double y2,
62  double x3, double y3, double x4, double y4,
63  point2D *pIntersection);
64  static bool pointInSegment(double x, double y, point2D *begin, point2D *end);
65  double pointLineDistance(point2D *lpt1, point2D *lpt2);
66  static bool pointInSegmentStrict(T x, T y, point2D *begin, point2D *end);
67  double pointSegmentDistance(point2D *begin, point2D *end);
68  static Intersection<T> *getSegmentsIntersection(point2D *p1L1, point2D *p2L1, point2D *p1L2, point2D *p2L2);
69  static Intersection<T> *getPreciseSegmentsIntersection(point2D *p1L1, point2D *p2L1, point2D *p1L2, point2D *p2L2);
70  static bool pointPreciselyInSegmentStrict(double x, double y, point2D *begin, point2D *end);
71 
72  T x;
73  T y;
74 };
75 
76 template <typename T>
77 class point3D {
78  public:
79  point3D();
80  point3D(T i_x, T i_y, T i_z);
81  ~point3D();
82  double distance(point3D *p1, point3D *p2);
83 
84  T x;
85  T y;
86  T z;
87  bool equalPoints3D(point3D *p1, point3D *p2);
88 };
89 
90 /*class h_segment {
91  public:
92  h_segment();
93  h_segment(int i_line, int i_left, int i_right);
94  ~h_segment();
95 
96  int line;
97  int left;
98  int right;
99 };*/
100 
101 
102 template <typename T>
103 class segment2D {
104  public:
105  segment2D();
106  segment2D(point2D<T>& i_first, point2D<T>& i_last);
107  ~segment2D();
108 
109  point2D<T> first;
110  point2D<T> last;
111 };
112 
113 template <typename T>
114 class segment3D {
115  public:
116  segment3D();
117  segment3D(point3D<T>& i_first, point3D<T>& i_last);
118  ~segment3D();
119 
120  point3D<T> first;
121  point3D<T> last;
122 };
123 
124 
125 template <typename T>
126 class Rectangle {
127  public:
128  Rectangle();
129  Rectangle(T x, T y, T w, T h);
130  ~Rectangle();
131  void initRectangle(T x, T y, T w, T h);
132  void initRectangleReliability(T r);
133 
134  Rectangle *copyRectangle();
135 
136  Rectangle *mergeRectangle(Rectangle *rect);
137  void mergeRectangle(Rectangle &r);
138 
139  static Rectangle *mergeRectangles(Rectangle *r1, Rectangle *r2);
140  static void mergeRectangles(Rectangle &r1, Rectangle &r2, Rectangle &res);
141 
142  void absorbRectangle(Rectangle *r);
143  void absorbRectangle(Rectangle &r);
144 
145  static double rectangleDistance(Rectangle *r1, Rectangle *r2);
146  double rectangleDistance(Rectangle *r);
147 
148  static double rectangleGravityDistance(Rectangle *r1, Rectangle *r2);
149  double rectangleGravityDistance(Rectangle *r);
150 
151  static T horizontalDistance(Rectangle *r1, Rectangle *r2);
152  static T verticalDistance(Rectangle *r1, Rectangle *r2);
153 
154 
155  static Rectangle *rectanglesIntersection(Rectangle *r1, Rectangle *r2);
156  static bool rectanglesIntersection(Rectangle &r1, Rectangle &r2, Rectangle &inter);
157  static bool rectanglesIntersection(Rectangle *r1, Rectangle *r2, Rectangle *inter);
158  Rectangle *rectangleIntersection(Rectangle *r);
159 
160  static Rectangle *rectanglesUnion(Rectangle *r1, Rectangle *r2);
161  Rectangle *rectangleUnion(Rectangle *r);
162 
163  static double rectangleIntersectRatio(Rectangle *r1, Rectangle *r2);
164  double rectangleIntersectRatio(Rectangle *r);
165 
166  static double rectangleIntersectRatioStrict(Rectangle *r1, Rectangle *r2);
167  double rectangleIntersectRatioStrict(Rectangle *r);
168 
169  static bool rectangleInRectangle(Rectangle *r1, Rectangle *r2);
170  bool rectangleInRectangle(Rectangle *r);
171 
172  static double rectangleIntersectionArea(Rectangle *r1, Rectangle *r2);
173  double rectangleIntersectionArea(Rectangle *r);
174 
175  static double rectangleNIntersectionArea(const std::vector<Rectangle *>& rectangles);
176 
177  double rectangleArea();
178 
179  int getPositionRelativeToCamera(SceneModel *smodel);
180 
181  int getPositionRelativeToCameraOld(SceneModel *smodel);
182 
183  void setEstimated3DPosition(SceneModel *smodel, point3D<double>& p, int position);
184 
185  void setPositionAtCenterBottom(SceneModel *smodel, point3D<double>& p);
186 
187  static bool isRect1InsideRect2(Rectangle *r1, Rectangle *r2);
188 
189  bool rectangleInside(Rectangle &r);
190 
191  static bool thereIsIntersection(Rectangle *r1, Rectangle *r2);
192 
193  bool thereIsIntersection(Rectangle &r);
194 
195  //Subtracts rectangles to this rectangle and stores resulting rectangles in results vector
196  void substractRectangles(std::vector<Rectangle> &toSubstract, std::deque<Rectangle> &results);
197 
198  static T overlappingArea(Rectangle<T> *r1, Rectangle<T> *r2);
199  static T overlappingArea(Rectangle<T> &r1, Rectangle<T> &r2);
200 
201  bool pointInRectangle(T p_x, T p_y);
202 
203  bool operator==(Rectangle &r);
204 
205 
206  T xleft;
207  T ytop;
208  T xright;
209  T ybottom;
210  T width;
211  T height;
212 };
213 
214 typedef Rectangle<int> rectangle;
215 typedef rectangle *rectangle_t;
217 typedef frectangle *frectangle_t;
220 
221 
222 
223 template <typename T>
224 class polygon2D {
225  public:
226  polygon2D();
227  polygon2D(int reserve);
228  polygon2D& operator=(polygon2D& p);
229  polygon2D *copy();
230  ~polygon2D();
231  void computeBoundingRectangle(Rectangle<T>& b);
232  void computeBoundingRectangle();
233  static polygon2D *intersectionPolygon(polygon2D *p1, polygon2D *p2);
234  bool getIntersectionsWithConvexPolygon(double val, bool vertical, double& v1, double& v2);
235  bool counterclockwisePolygon();
236  polygon2D *getInversedPolygon();
237  bool pointInPolygon(T x, T y, bool strict);
238  static bool pointPreciselyInConvexPolygon(double x, double y, polygon2D *poly, bool strict);
239  static bool equalPolygons(polygon2D *p1, polygon2D *p2, double allowed_point_error);
240  double polygonArea();
241  bool pointInConvexPolygon(T x, T y, bool strict);
242 
243  static polygon2D *rectanglesIntersection(polygon2D *rectangle1, polygon2D *rectangle2);
244  bool memmove(int to, int from, int number);
245  QSharedPointer<polygon2D<int> > projectImagePolygon2D(homography_matrix H);
246 
247  bool bb_done;
248 
250  std::vector< point2D<T> > points;
251 };
252 
254 
255 template <typename T>
256 class polygon3D {
257  public:
258  polygon3D();
259  polygon3D(int reserve);
260  polygon3D& operator=(polygon3D& p);
261  ~polygon3D();
262 
263  QSharedPointer<polygon2D<T> > makePolygon2D();
264  QSharedPointer<polygon2D<int> > projectPolygon2D(perspective_matrix M);
265 
267  std::vector< point3D<T> > points;
268 };
269 
270 // for points 2D
271 #define POINT_2D_X(p) ((p)->x)
272 #define POINT_2D_Y(p) ((p)->y)
273 
274 // for points 3D
275 #define POINT_3D_X(p) ((p)->x)
276 #define POINT_3D_Y(p) ((p)->y)
277 #define POINT_3D_Z(p) ((p)->z)
278 
279 
280 // for 2d and 3d polygon...
281 #define POLYGON_N_POINTS(pl) ((pl)->points.size())
282 #define POLYGON_NTH_POINT(pl, n) (&(pl)->points[n])
283 
284 // only for 2d-polygon
285 #define POLYGON_2D_BB_DONE(pl) ((pl)->bb_done)
286 #define POLYGON_2D_BB(pl) ((pl)->boundingBox)
287 #define POLYGON_2D_BB_X(pl) RECT_X(&((pl)->boundingBox))
288 #define POLYGON_2D_BB_Y(pl) RECT_Y(&((pl)->boundingBox))
289 #define POLYGON_2D_BB_WIDTH(pl) RECT_WIDTH(&((pl)->boundingBox))
290 #define POLYGON_2D_BB_HEIGHT(pl) RECT_HEIGHT(&((pl)->boundingBox))
291 #define POLYGON_2D_BB_XLEFT(pl) RECT_XLEFT(&((pl)->boundingBox))
292 #define POLYGON_2D_BB_XRIGHT(pl) RECT_XRIGHT(&((pl)->boundingBox))
293 #define POLYGON_2D_BB_YBOTTOM(pl) RECT_YBOTTOM(&((pl)->boundingBox))
294 #define POLYGON_2D_BB_YTOP(pl) RECT_YTOP(&((pl)->boundingBox))
295 #define POLYGON_2D_BB_XCENTER(pl) (POLYGON_2D_BB_XLEFT(pl) + POLYGON_2D_BB_WIDTH(pl) / 2.0)
296 #define POLYGON_2D_BB_YCENTER(pl) (POLYGON_2D_BB_YTOP(pl) + POLYGON_2D_BB_HEIGHT(pl) / 2.0)
297 #define RECT_XLEFT(_rect) ((_rect)->xleft)
298 #define RECT_X(_rect) RECT_XLEFT(_rect)
299 #define RECT_XRIGHT(_rect) ((_rect)->xright)
300 #define RECT_YTOP(_rect) ((_rect)->ytop)
301 #define RECT_Y(_rect) RECT_YTOP(_rect)
302 #define RECT_YBOTTOM(_rect) ((_rect)->ybottom)
303 #define RECT_WIDTH(_rect) ((_rect)->width)
304 #define RECT_HEIGHT(_rect) ((_rect)->height)
305 #define RECT_XCENTER(_rect) (RECT_XLEFT(_rect) + RECT_WIDTH(_rect)/2)
306 #define RECT_YCENTER(_rect) (RECT_YTOP(_rect) + RECT_HEIGHT(_rect)/2)
307 
308 //IMPLEMENTATIONS
309 
310 template <typename T>
311 line2D<T>::line2D() : x1(0), y1(0), x2(0), y2(0) {}
312 
313 template <typename T>
314 line2D<T>::line2D(T i_x1, T i_y1, T i_x2, T i_y2) : x1(i_x1), y1(i_y1),
315  x2(i_x2), y2(i_y2) {}
316 template <typename T>
318 
319 template <typename T>
320 point2D<T>::point2D() : x(0), y(0) {}
321 
322 template <typename T>
323 point2D<T>::point2D(T i_x, T i_y) : x(i_x), y(i_y) {}
324 
325 template <typename T>
326 double point2D<T>::distance(point2D<T> *p1, point2D<T> *p2) {
327  double
328  dx = POINT_2D_X(p1) - POINT_2D_X(p2),
329  dy = POINT_2D_Y(p1) - POINT_2D_Y(p2);
330  return sqrt(dx*dx + dy*dy);
331 }
332 
333 template <typename T>
335 
336 template <typename T>
337 point3D<T>::point3D() : x(0), y(0), z(0) {}
338 
339 template <typename T>
340 point3D<T>::point3D(T i_x, T i_y, T i_z) : x(i_x), y(i_y), z(i_z) {}
341 
342 template <typename T>
343 double point3D<T>::distance(point3D<T> *p1, point3D<T> *p2) {
344  double
345  dx = POINT_3D_X(p1) - POINT_3D_X(p2),
346  dy = POINT_3D_Y(p1) - POINT_3D_Y(p2),
347  dz = POINT_3D_Z(p1) - POINT_3D_Z(p2);
348  return sqrt(dx*dx + dy*dy + dz*dz);
349 }
350 
351 template <typename T>
353 /*
354 h_segment::h_segment() : line(0), left(0), right(0) {}
355 
356 h_segment::h_segment(int i_line, int i_left, int i_right) : line(i_line),
357  left(i_left),
358  right(i_right) {}
359 
360 h_segment::~h_segment() {}
361 */
362 template <typename T>
363 Intersection<T>::Intersection(): x1(0), y1(0), x2(0), y2(0),
364  distance(0), type(1) {}
365 
366 template <typename T>
367 Intersection<T>::Intersection(T i_x1, T i_y1,
368  T i_x2, T i_y2): x1(i_x1), y1(i_y1),
369  x2(i_x2), y2(i_y2) {
370  T dx = x1 - x2, dy = y1 - y2;
371  distance = sqrt(dx + dy);
372 }
373 
374 template <typename T>
376 
377 template <typename T>
379 
380 template <typename T>
381 segment2D<T>::segment2D(point2D<T>& i_first, point2D<T>& i_last) : first(i_first), last(i_last) {}
382 
383 template <typename T>
385 
386 template <typename T>
388 
389 template <typename T>
390 segment3D<T>::segment3D(point3D<T>& i_first, point3D<T>& i_last) : first(i_first), last(i_last) {}
391 
392 template <typename T>
394 
395 
396 template <typename T>
397 polygon2D<T>::polygon2D() : bb_done(false) {}
398 
399 template <typename T>
401  memcpy(this, &p, sizeof(polygon2D<T>));
402  points = p.points;
403  return *this;
404 }
405 
406 template <typename T>
408  polygon2D<T> *p = new polygon2D<T>(points.size());
409  memcpy(p, this, sizeof(polygon2D<T>));
410  p->points = points;
411  return p;
412 }
413 
414 template <typename T>
415 polygon2D<T>::polygon2D(int reserve): bb_done(false) {
416  points.resize(reserve);
417 }
418 
419 
420 template <typename T>
422 
423 //Compute the bounding rectangle of a polygon
424 template <typename T>
426  if (bb_done)
427  memcpy(&b, &boundingBox, sizeof(Rectangle<int>));
428  else {
429  int n = points.size();
430 
431  if(n == 0) {
432  memset(&b, 0, sizeof(Rectangle<int>));
433  memset(&boundingBox, 0, sizeof(Rectangle<int>));
434  bb_done = false;
435  return;
436  }
437 
438  double xmin, xmax, ymin, ymax;
439  point2D<T> *current;
440  typename std::vector< point2D<T> >::iterator it, it_end = points.end();
441 
442  xmin = DBL_MAX / 2.0;
443  xmax = - xmin;
444  ymin = xmin;
445  ymax = xmax;
446 
447  for (it = points.begin(); it != it_end; it++) {
448  current = &(*it);
449  xmin = POINT_2D_X(current) < xmin ? POINT_2D_X(current) : xmin;
450  xmax = POINT_2D_X(current) > xmax ? POINT_2D_X(current) : xmax;
451  ymin = POINT_2D_Y(current) < ymin ? POINT_2D_Y(current) : ymin;
452  ymax = POINT_2D_Y(current) > ymax ? POINT_2D_Y(current) : ymax;
453  }
454 
455  RECT_X(&b) = RECT_X(&boundingBox) = xmin;
456  RECT_Y(&b) = RECT_Y(&boundingBox) = ymin;
457  RECT_WIDTH(&b) = RECT_WIDTH(&boundingBox) = xmax - xmin + 1;
458  RECT_HEIGHT(&b) = RECT_HEIGHT(&boundingBox) = ymax - ymin + 1;
459  RECT_XRIGHT(&b) = RECT_XRIGHT(&boundingBox) = xmax;
460  RECT_YBOTTOM(&b) = RECT_YBOTTOM(&boundingBox) = ymax;
461  bb_done = true;
462  }
463 }
464 
465 //Compute the bounding rectangle of a polygon (internal data)
466 template <typename T>
468 
469  int n = points.size();
470 
471  if(n == 0) {
472  memset(&boundingBox, 0, sizeof(Rectangle<int>));
473  bb_done = false;
474  return;
475  }
476 
477  double xmin, xmax, ymin, ymax;
478  point2D<T> *current;
479  typename std::vector< point2D<T> >::iterator it, it_end = points.end();
480 
481  xmin = DBL_MAX / 2.0;
482  xmax = - xmin;
483  ymin = xmin;
484  ymax = xmax;
485 
486  for (it = points.begin(); it != it_end; it++) {
487  current = &(*it);
488  xmin = POINT_2D_X(current) < xmin ? POINT_2D_X(current) : xmin;
489  xmax = POINT_2D_X(current) > xmax ? POINT_2D_X(current) : xmax;
490  ymin = POINT_2D_Y(current) < ymin ? POINT_2D_Y(current) : ymin;
491  ymax = POINT_2D_Y(current) > ymax ? POINT_2D_Y(current) : ymax;
492  }
493 
494  RECT_X(&boundingBox) = xmin;
495  RECT_Y(&boundingBox) = ymin;
496  RECT_WIDTH(&boundingBox) = xmax - xmin + 1;
497  RECT_HEIGHT(&boundingBox) = ymax - ymin + 1;
498  RECT_XRIGHT(&boundingBox) = xmax;
499  RECT_YBOTTOM(&boundingBox) = ymax;
500  bb_done = true;
501 }
502 
503 // Optimized functions for convex polygon (requires ordered points of a convex polygon)
504 template <typename T>
505 double polygon2D<T>::polygonArea() {
506  int i, j, n = points.size();
507  double area = 0.0;
508 
509  for (i = 0; i < n; i++) {
510  j = (i == n - 1 ? 0 : i + 1);
511  area += points[i].x * points[j].y - points[i].y * points[j].x;
512  }
513 
514  return fabs(area) / 2.0;
515 }
516 
517 //Checks if a point (x,y) is inside a polygon
518 template <typename T>
519 bool polygon2D<T>::pointInConvexPolygon(T x, T y, bool strict) {
520 
521  int i, pos = 0, neg = 0;
522  int num_points = points.size();
523  double xp1, xp2, yp1, yp2;
524  point2D<T> *p1, *p2;
525 
526  if(!this->boundingBox.pointInRectangle(x, y))
527  return 0;
528 
529  p2 = &points[0];
530 
531  for(i=0;i<num_points;i++) {
532  p1 = p2;
533  p2 = &points[num_points - 1 ? i + 1 : 0];
534 
535  if (point2D<T>::pointInSegmentStrict(x, y, p1, p2))
536  return (strict ? 0 : 1);
537 
538  xp1 = POINT_2D_X(p1); yp1 = POINT_2D_Y(p1);
539  xp2 = POINT_2D_X(p2); yp2 = POINT_2D_Y(p2);
540 
541  if (((yp1<=y) && (y<yp2)) || ((yp2<=y) && (y<yp1))) {
542  if ( x*(yp2 - yp1) + xp2*yp1 - xp1*yp2 < y*(xp2 - xp1) )
543  pos++;
544  else
545  neg++;
546  }
547 
548  if(neg && pos)
549  return false;
550  }
551 
552  return true;
553 }
554 
555 //Checks a point in a polygon
556 template <typename T>
557 bool polygon2D<T>::pointPreciselyInConvexPolygon(double x, double y, polygon2D<T> *poly, bool strict) {
558  int i, pos = 0, neg = 0;
559  int num_points = POLYGON_N_POINTS(poly);
560  double xp1, xp2, yp1, yp2;
561  point2D<T> *p1, *p2;
562 
563  if(!POLYGON_2D_BB(poly).pointInRectangle(x, y))
564  return false;
565 
566  p2 = POLYGON_NTH_POINT(poly, 0);
567 
568  for(i=0;i<num_points;i++) {
569  p1 = p2;
570  p2 = POLYGON_NTH_POINT(poly, i<num_points - 1 ? i + 1 : 0);
571 
573  return (strict ? 0 : 1);
574 
575  xp1 = POINT_2D_X(p1); yp1 = POINT_2D_Y(p1);
576  xp2 = POINT_2D_X(p2); yp2 = POINT_2D_Y(p2);
577 
578  if ( (yp1 <= y && y < yp2) || (yp2 <= y && y < yp1) ) {
579  if ( x*(yp2 - yp1) + xp2*yp1 - xp1*yp2 < y*(xp2 - xp1) )
580  pos++;
581  else
582  neg++;
583  }
584 
585  if(neg && pos)
586  return false;
587  }
588 
589  return true;
590 }
591 
592 
593 // Get the intersection points with a polygon
594 template <typename T>
595 bool polygon2D<T>::getIntersectionsWithConvexPolygon(double val, bool vertical, double& v1, double& v2) {
596 
597  //First check if it is in the zone of the roof
598  if(vertical) {
599  if( val < RECT_XLEFT(&boundingBox) || val > RECT_XRIGHT(&boundingBox))
600  return false;
601  } else {
602  if( val < RECT_YTOP(&boundingBox) || val > RECT_YBOTTOM(&boundingBox))
603  return false;
604  }
605 
606  int i, obtained_points = 0;
607  int num_points = points.size();
608  double xp1, xp2, yp1, yp2;
609  point2D<T> *p1, *p2;
610  double min, max;
611 
612  p2 = &points[0];
613 
614  for(i=0;i<num_points;i++) {
615  p1 = p2;
616  p2 = &points[i < num_points - 1 ? i + 1 : 0];
617 
618  xp1 = POINT_2D_X(p1); yp1 = POINT_2D_Y(p1);
619  xp2 = POINT_2D_X(p2); yp2 = POINT_2D_Y(p2);
620 
621  if(vertical) {
622  if(xp2 > xp1) {
623  min = xp1; max = xp2;
624  } else {
625  min = xp2; max = xp1;
626  }
627  if(xp2 - xp1 == 0.0) //Ignore if segment is vertical (there must be two other intersecting it)
628  continue;
629  else {
630  if ((val >= min) && (val <= max)) {
631  if(!obtained_points) {
632  v1 = (val*(yp2 - yp1) + xp2*yp1 - xp1*yp2)/(xp2 - xp1);
633  obtained_points++;
634  } else {
635  v2 = (val*(yp2 - yp1) + xp2*yp1 - xp1*yp2)/(xp2 - xp1);
636  obtained_points++;
637  }
638  }
639  }
640  } else { //Horizontal
641  if(yp2 > yp1) {
642  min = yp1; max = yp2;
643  } else {
644  min = yp2; max = yp1;
645  }
646  if(yp2 - yp1 == 0.0) //Ignore if segment is horizontal (there must be two other intersecting it)
647  continue;
648  else {
649  if ((val >= min) && (val <= max)) {
650  if(!obtained_points) {
651  v1 = ( val*(xp2 - xp1) - xp2*yp1 + xp1*yp2 ) / (yp2 - yp1);
652  obtained_points++;
653  } else {
654  v2 = ( val*(xp2 - xp1) - xp2*yp1 + xp1*yp2 ) / (yp2 - yp1);
655  obtained_points++;
656  }
657  }
658  }
659  }
660 
661  if(obtained_points == 2)
662  return true;
663  }
664 
665  return false;
666 }
667 
668 
669 //This function allows a maximum error of allowed_point_error of distance
670 //error between equal points. This is done for robustness with respect to floating point errors in despite
671 //of a little loss of precision.
672 template <typename T>
673 bool polygon2D<T>::equalPolygons(polygon2D<T> *p1, polygon2D<T> *p2, double allowed_point_error) {
674  int i, j;
675  int found = 0;
676  int n_points = p1->points.size(), n_points2 = p2->points.size();
677 
678  if(n_points != n_points2)
679  return false;
680 
681  for(i=0; i<n_points; i++)
682  if( fabs(p1->points[0].x - p2->points[i].x) < allowed_point_error
683  && fabs(p1->points[0].y - p2->points[i].y) < allowed_point_error) {
684  found = 1;
685  j = i;
686  break;
687  }
688  if(found == 0)
689  return false;
690 
691  for(i=1,j=(j+1)%n_points; i<n_points; i++, j=(j+1)%n_points)
692  if( fabs(p1->points[i].x - p2->points[j].x) >= allowed_point_error
693  || fabs(p1->points[i].y - p2->points[j].y) >= allowed_point_error)
694  return false;
695 
696  return true;
697 }
698 
699 //Function which returns a polygon representing the area of intersection of two convex polygons (with any orientation).
700 //Both polygons must be clockwise or counter-clockwise at the same time.
701 //TO-DO!!!! pass doubles to int, specifying the precision required. e.g. 150.4562, 132.5,
702 // with precision 2, works with numbers, 15045.62, 13250, and will transform
703 //to double by dividing by 100.0 all numbers :D
704 template <typename T>
706 
707  //First check polygons bounding boxes, if there is no bounding boxes intersection, there is no polygon intersection
708  if(!Rectangle<T>::thereIsIntersection(&POLYGON_2D_BB(p1), &POLYGON_2D_BB(p2)))
709  return NULL;
710 
711  if(polygon2D<T>::equalPolygons(p1, p2, 0.001))
712  return p1->copy();
713 
714  int i;
715  int num_inner_pol1 = 0, num_inner_pol2 = 0;
716  int p1_points = p1->points.size(), p2_points = p2->points.size();
717  int inner_points_p1[p1_points], inner_points_p2[p2_points];
718  point2D<T> *p1pol1, *p1pol2;
719 
720  memset(inner_points_p1, 0, p1_points*sizeof(int));
721  memset(inner_points_p2, 0, p2_points*sizeof(int));
722 
723  //Set inner point flags for both rectangles. An inner point can not be an intersecting point
724  for(i=0; i<p1_points; i++) {
725  p1pol1 = POLYGON_NTH_POINT(p1, i);
726  if(polygon2D<T>::pointPreciselyInConvexPolygon(p1pol1->x, p1pol1->y, p2, 1)) {
727  num_inner_pol1++;
728  inner_points_p1[i] = 1;
729  }
730  }
731 
732  for(i=0; i<p2_points; i++) {
733  p1pol2 = POLYGON_NTH_POINT(p2, i);
734  if(polygon2D<T>::pointPreciselyInConvexPolygon(p1pol2->x, p1pol2->y, p1, 1)) {
735  num_inner_pol2++;
736  inner_points_p2[i] = 1;
737  }
738  }
739 
740  if(num_inner_pol1 == p1_points)
741  return p1->copy();
742 
743  if(num_inner_pol2 == p2_points)
744  return p2->copy();
745 
746  int max_points = 2*(p1_points + p2_points);
747  polygon2D<T> *intersection_polygon = new polygon2D(max_points);
748  int j, numIntersections = 0, num_current_intersections, num_allocated = 0, add;
749  Intersection<T> *icurrent, *allocatedResults[max_points];
750  double xnear, ynear, xfar, yfar;
751  double dx, dy, d1, d2;
752  point2D<T> *p2pol1, *p2pol2;
753 
754  //If no inner points for both rectangles, search for intersections
755  if( num_inner_pol1 == 0 && num_inner_pol2 == 0 ) {
756 
757  point2D<T> current_intersections[2];
758 
759  p2pol1 = POLYGON_NTH_POINT(p1, 0);
760 
761  for(i=0; i<p1_points; i++) {
762  p1pol1 = p2pol1;
763  p2pol1 = POLYGON_NTH_POINT(p1, (i + 1)%p1_points);
764 
765  num_current_intersections = 0;
766 
767  p2pol2 = POLYGON_NTH_POINT(p2, 0);
768  for(j=0; j<p2_points; j++) {
769  p1pol2 = p2pol2;
770  p2pol2 = POLYGON_NTH_POINT(p2, (j + 1)%p2_points);
771 
772  //If no intersection found, pass to the next pair
773  if( (icurrent = point2D<T>::getPreciseSegmentsIntersection(p1pol1, p2pol1, p1pol2, p2pol2)) == NULL )
774  continue;
775 
776  allocatedResults[num_allocated++] = icurrent;
777 
778  if(icurrent->type == 1) {
779  current_intersections[num_current_intersections ].x = icurrent->x1;
780  current_intersections[num_current_intersections++].y = icurrent->y1;
781  } else { //If there is line intersection, we have all the possible intersection points for two segments
782  num_current_intersections = 0;
783  current_intersections[num_current_intersections ].x = icurrent->x1;
784  current_intersections[num_current_intersections++].y = icurrent->y1;
785  current_intersections[num_current_intersections ].x = icurrent->x2;
786  current_intersections[num_current_intersections++].y = icurrent->y2;
787  break;
788  }
789 
790  if(num_current_intersections > 2)
791  std::cout << "ERROR!!!: Exceded intersections capacity." << std::endl;
792  }
793 
794  if(num_current_intersections == 0)
795  continue;
796 
797  if( num_current_intersections == 2
798  && current_intersections[0].x == current_intersections[1].x
799  && current_intersections[0].y == current_intersections[1].y )
800  num_current_intersections = 1;
801 
802  if(num_current_intersections == 1) {
803  xnear = current_intersections[0].x;
804  ynear = current_intersections[0].y;
805 
806  add = 1;
807 
808  if( numIntersections > 0 //Check if previous intersection is the same point
809  && intersection_polygon->points[numIntersections - 1].x == xnear
810  && intersection_polygon->points[numIntersections - 1].y == ynear )
811  add = 0;
812  //In case that the point is the last intersection, check against the first point
813  else if( numIntersections > 1
814  && intersection_polygon->points[0].x == xnear
815  && intersection_polygon->points[0].y == ynear )
816  add = 0;
817 
818  if(add) {
819  intersection_polygon->points[numIntersections].x = xnear;
820  intersection_polygon->points[numIntersections++].y = ynear;
821  }
822  } else {
823  dx = current_intersections[0].x - p1pol1->x;
824  dy = current_intersections[0].y - p1pol1->y;
825  d1 = dx*dx + dy*dy;
826  dx = current_intersections[1].x - p1pol1->x;
827  dy = current_intersections[1].y - p1pol1->y;
828  d2 = dx*dx + dy*dy;
829  if(d1 < d2) {
830  xnear = current_intersections[0].x;
831  ynear = current_intersections[0].y;
832  xfar = current_intersections[1].x;
833  yfar = current_intersections[1].y;
834  } else {
835  xnear = current_intersections[1].x;
836  ynear = current_intersections[1].y;
837  xfar = current_intersections[0].x;
838  yfar = current_intersections[0].y;
839  }
840 
841  if( numIntersections > 0 //Check if previous intersection is the same point
842  && ( intersection_polygon->points[numIntersections - 1].x != xnear
843  || intersection_polygon->points[numIntersections - 1].y != ynear ) ) {
844  intersection_polygon->points[numIntersections].x = xnear;
845  intersection_polygon->points[numIntersections++].y = ynear;
846  } else if(numIntersections == 0) {
847  intersection_polygon->points[numIntersections].x = xnear;
848  intersection_polygon->points[numIntersections++].y = ynear;
849  }
850 
851  //In case that the point is the last intersection, check against the first point
852  if( numIntersections > 1
853  && ( intersection_polygon->points[0].x != xfar
854  || intersection_polygon->points[0].y != yfar ) ) {
855  intersection_polygon->points[numIntersections].x = xfar;
856  intersection_polygon->points[numIntersections++].y = yfar;
857  } else if(numIntersections <= 1) {
858  intersection_polygon->points[numIntersections].x = xfar;
859  intersection_polygon->points[numIntersections++].y = yfar;
860  }
861  }
862  }
863 
864  for(i=0; i<num_allocated; i++)
865  delete allocatedResults[i];
866 
867  if(numIntersections < 3) { //If the intersection can not form an area, the area is NULL
868  delete intersection_polygon;
869  return NULL;
870  }
871 
872  return intersection_polygon;
873  }
874 
875 
876  /* std::cout.precision(10);
877  std::cout << "Inner points: \tp1(";
878  for(i=0; i<p1_points; i++)
879  std::cout << inner_points_p1[i] << " ";
880  std::cout << ") \tp2(";
881  for(i=0; i<p2_points; i++)
882  std::cout << inner_points_p2[i] << " ";
883  std::cout << ")" << std::endl;
884  */
885 
886  int from_p1, inner_index;
887  double p1_inner_min_distance[p1_points], p2_inner_min_distance[p2_points];
888  double min, max = 0.0, dist;
889 
890  memset(p1_inner_min_distance, 0, p1_points*sizeof(double));
891  memset(p2_inner_min_distance, 0, p2_points*sizeof(double));
892  //Get the more distant inner point from the other rectangle segments, to avoid floating point precision problems
893 
894  //Check inner points of p2
895  for(i=0; i<p2_points; i++) {
896  if(inner_points_p2[i]) {
897  min = DBL_MAX;
898  p2pol1 = POLYGON_NTH_POINT(p1, 0);
899  for(j=0; j<p1_points; j++) {
900  p1pol1 = p2pol1;
901  p2pol1 = POLYGON_NTH_POINT(p1, (j + 1)%p1_points);
902  dist = POLYGON_NTH_POINT(p2, i)->pointSegmentDistance(p1pol1, p2pol1);
903  if(dist < min)
904  min = dist;
905  }
906  p2_inner_min_distance[i] = min;
907  if(min > max) {
908  max = min;
909  from_p1 = 0;
910  inner_index = i;
911  }
912  }
913  }
914 
915  //Check inner points of p1
916  for(i=0; i<p1_points; i++) {
917  if(inner_points_p1[i]) {
918  min = DBL_MAX;
919  p2pol2 = POLYGON_NTH_POINT(p2, 0);
920  for(j=0; j<p2_points; j++) {
921  p1pol2 = p2pol2;
922  p2pol2 = POLYGON_NTH_POINT(p2, (j + 1)%p2_points);
923  dist = POLYGON_NTH_POINT(p1, i)->pointSegmentDistance(p1pol2, p2pol2);
924  if(dist < min)
925  min = dist;
926  }
927  p1_inner_min_distance[i] = min;
928  if(min > max) {
929  max = min;
930  from_p1 = 1;
931  inner_index = i;
932  }
933  }
934  }
935 
936  point2D<T> *current_point;
937  polygon2D<T> *p_inner, *p_other;
938  int n_pinner, n_pother, i_inner, i_other, in_inner = 1, first_other = 1;
939  int *inner_points_p_inner, *inner_points_p_other, differentLastToAdd = 1;
940  int inner_in_limit, other_in_limit;
941  //TO-DO!!! FIX WHEN icurrent == NULL
942  //Example from frame 254969 of GERHOME beard man video.
943  //BLOB 3, PERSON, CROUCHING, alpha = 0.1596865465, h = 41,25812530
944  //inner_pol = base_pol, other_pol = object_pol,
945  //Most inner point comes from rectangle 1 (point 3)
946  //Good Sequence: inner_3 -> A -> other_0 -> B -> inner_2
947  //B is not detected, the intersection between segs. other_{0,1} and inner_{1,2}
948  //is not detected.
949  //Recovery method must be implemented if there is no way to detect the intersection.
950 
951  if(from_p1) {
952  p_inner = p1;
953  p_other = p2;
954  n_pinner = p1_points;
955  n_pother = p2_points;
956  current_point = POLYGON_NTH_POINT(p1, inner_index);
957  inner_points_p_inner = inner_points_p1;
958  inner_points_p_other = inner_points_p2;
959  } else {
960  p_inner = p2;
961  p_other = p1;
962  n_pinner = p2_points;
963  n_pother = p1_points;
964  current_point = POLYGON_NTH_POINT(p2, inner_index);
965  inner_points_p_inner = inner_points_p2;
966  inner_points_p_other = inner_points_p1;
967  }
968 
969  //Insert inner point as the first point of the final solution
970  intersection_polygon->points[numIntersections ].x = current_point->x;
971  intersection_polygon->points[numIntersections++].y = current_point->y;
972  i_inner = inner_index;
973 
974  do {
975  if(in_inner == 1) {
976  p1pol1 = POLYGON_NTH_POINT(p_inner, i_inner);
977  p2pol1 = POLYGON_NTH_POINT(p_inner, (i_inner + 1)%n_pinner);
978 
979  //If next point to check is inner point, add it immediately and pass to next segment
980  if(inner_points_p_inner[(i_inner + 1)%n_pinner]) {
981  i_inner = (i_inner + 1)%n_pinner;
982  //If the next possible point to add is inner point and the same one added first,
983  //the work is finished. :D
984  if(i_inner == inner_index) {
985  differentLastToAdd = 0;
986  icurrent = NULL;
987  } else { //Add the inner point because it is sure that it is part of the intersection solution
988  current_point = POLYGON_NTH_POINT(p_inner, i_inner);
989  intersection_polygon->points[numIntersections ].x = current_point->x;
990  intersection_polygon->points[numIntersections++].y = current_point->y;
991  continue;
992  }
993  } else if(first_other) { //If next point is not inner point, check the intersections
994  //Search for first intersection
995  p2pol2 = POLYGON_NTH_POINT(p_other, 0);
996  for(j=0; j<n_pother; j++) {
997  p1pol2 = p2pol2;
998  p2pol2 = POLYGON_NTH_POINT(p_other, (j + 1)%n_pother);
999  //If no intersection found, pass to the next segment
1000  if( (icurrent = point2D<T>::getPreciseSegmentsIntersection(p1pol1, p2pol1, p1pol2, p2pol2)) == NULL )
1001  continue;
1002  //Set the index for the first segment to analyse for the other rectangle
1003  i_other = j;
1004  first_other = 0;
1005  allocatedResults[num_allocated++] = icurrent;
1006  break;
1007  }
1008  } else {
1009  //Start intersection search from next point to not repeat the same intersection
1010  int aux_other;
1011  p2pol2 = POLYGON_NTH_POINT(p_other, i_other);
1012  for(j=0, aux_other = i_other; j < n_pother - 1; j++, aux_other = (aux_other + 1)%n_pother) {
1013  p1pol2 = p2pol2;
1014  p2pol2 = POLYGON_NTH_POINT(p_other, (aux_other + 1)%n_pother);
1015  //If no intersection found, pass to the next segment
1016  if( (icurrent = point2D<T>::getPreciseSegmentsIntersection(p1pol1, p2pol1, p1pol2, p2pol2)) == NULL )
1017  continue;
1018  //Set the index for the first segment to analyse for the other rectangle
1019  i_other = aux_other;
1020  allocatedResults[num_allocated++] = icurrent;
1021  break;
1022  }
1023  }
1024 
1025  if(icurrent == NULL) { //An error???? It should not happen because if next point is out an intersection should exist.
1026  //If an error of this type occurs we stop the computation.
1027  // std::cout << "intersection_polygon: Error of intersection not found!!" << std::endl;
1028  break;
1029  } else if(icurrent->type == 1) { //A point intersection
1030  intersection_polygon->points[numIntersections ].x = icurrent->x1;
1031  intersection_polygon->points[numIntersections++].y = icurrent->y1;
1032  //Decision for next segment and rectangle
1033  inner_in_limit = icurrent->x1 == p2pol1->x && icurrent->y1 == p2pol1->y ? 1 : 0;
1034  other_in_limit = 0;
1035  p1pol2 = POLYGON_NTH_POINT(p_other, i_other );
1036  p2pol2 = POLYGON_NTH_POINT(p_other, (i_other + 1)%n_pother);
1037  if(icurrent->x1 == p1pol2->x && icurrent->y1 == p1pol2->y)
1038  other_in_limit = 1;
1039  else if(icurrent->x1 == p2pol2->x && icurrent->y1 == p2pol2->y) {
1040  other_in_limit = 1;
1041  i_other = (i_other + 1)%n_pother;
1042  }
1043 
1044  if(inner_in_limit) {
1045  if(other_in_limit) //If intersection corresponds to a vertex in both rectangles, treat the special case
1046  in_inner = -1;
1047  else //If intersection point is not in limit of the other rectangle segment, no need to change of rectangle
1048  in_inner = 1;
1049  } else //If the intersection is not in limit, we have to change from inner to the other rectangle
1050  in_inner = 0;
1051  } else { //If there is line intersection, we add the second point and treat the next point decision as a special case
1052  //Add the not added point, and based on this decide the next starting segment for both rectangles
1053  intersection_polygon->points[numIntersections ].x = icurrent->x2;
1054  intersection_polygon->points[numIntersections++].y = icurrent->y2;
1055 
1056  i_other = (i_other + 1)%n_pother;
1057 
1058  p2pol2 = POLYGON_NTH_POINT(p_other, i_other);
1059 
1060  //If both ending points correspond to a vertex, treat special case
1061  if(p2pol1->x == p2pol2->x && p2pol1->y == p2pol2->y)
1062  in_inner = -1;
1063  else { //Nearest second to last added point will remain
1064  double
1065  dx_inner = p2pol1->x - intersection_polygon->points[numIntersections - 1].x,
1066  dx_other = p2pol2->x - intersection_polygon->points[numIntersections - 1].x,
1067  dy_inner = p2pol1->y - intersection_polygon->points[numIntersections - 1].y,
1068  dy_other = p2pol2->y - intersection_polygon->points[numIntersections - 1].y;
1069 
1070  if(dx_inner*dx_inner + dy_inner*dy_inner < dx_other*dx_other + dy_other*dy_other)
1071  in_inner = 1;
1072  else
1073  in_inner = 0;
1074  }
1075  }
1076 
1077  i_inner = (i_inner + 1)%n_pinner;
1078 
1079  } else if (in_inner == 0) { //In the other rectangle
1080 
1081  p1pol2 = POLYGON_NTH_POINT(p_other, i_other);
1082  p2pol2 = POLYGON_NTH_POINT(p_other, (i_other + 1)%n_pother);
1083 
1084  //If next point to check is inner point, add it immediately and pass to next segment
1085  if(inner_points_p_other[(i_other + 1)%n_pother]) {
1086  i_other = (i_other + 1)%n_pother;
1087  current_point = POLYGON_NTH_POINT(p_other, i_other);
1088  intersection_polygon->points[numIntersections ].x = current_point->x;
1089  intersection_polygon->points[numIntersections++].y = current_point->y;
1090  continue;
1091  } else {
1092  //Start intersection search from next point to not repeat the same intersection
1093  int aux_inner;
1094  p2pol1 = POLYGON_NTH_POINT(p_inner, i_inner);
1095  for(j=0, aux_inner = i_inner; j<(n_pinner - 1); j++, aux_inner = (aux_inner + 1)%n_pinner) {
1096  p1pol1 = p2pol1;
1097  p2pol1 = POLYGON_NTH_POINT(p_inner, (aux_inner + 1)%n_pinner);
1098  //If no intersection found, pass to the next segment
1099  if( (icurrent = point2D<T>::getPreciseSegmentsIntersection(p1pol2, p2pol2, p1pol1, p2pol1)) == NULL )
1100  continue;
1101  //Set the index for the first segment to analyse for the other rectangle
1102  i_inner = aux_inner;
1103  allocatedResults[num_allocated++] = icurrent;
1104  break;
1105  }
1106  }
1107 
1108  if(icurrent == NULL) { //An error???? It should not happen because if next point is out an intersection should exist.
1109  //If an error of this type occurs, finish computation and give the partial intersection found.
1110  std::cout << "Error of intersection not found!!" << std::endl;
1111  break;
1112  } else if(icurrent->type == 1) { //A point intersection
1113  intersection_polygon->points[numIntersections ].x = icurrent->x1;
1114  intersection_polygon->points[numIntersections++].y = icurrent->y1;
1115  //Decision for next segment and rectangle
1116  other_in_limit = icurrent->x1 == p2pol2->x && icurrent->y1 == p2pol2->y ? 1 : 0;
1117  inner_in_limit = 0;
1118  p1pol1 = POLYGON_NTH_POINT(p_inner, i_inner );
1119  p2pol1 = POLYGON_NTH_POINT(p_inner, (i_inner + 1)%n_pinner);
1120  if(icurrent->x1 == p1pol1->x && icurrent->y1 == p1pol1->y)
1121  inner_in_limit = 1;
1122  else if(icurrent->x1 == p2pol1->x && icurrent->y1 == p2pol1->y) {
1123  inner_in_limit = 1;
1124  i_inner = (i_inner + 1)%n_pinner;
1125  }
1126 
1127  if(other_in_limit) {
1128  if(inner_in_limit) //If intersection corresponds to a vertex in both rectangles, treat the special case
1129  in_inner = -1;
1130  else //If intersection point is not in limit of the inner rectangle segment, no need to change of rectangle
1131  in_inner = 0;
1132  } else //If the intersection is not in limit, we have to change from other to the inner rectangle
1133  in_inner = 1;
1134  } else { //If there is line intersection, we add the second point and treat the next point decision as a special case
1135  //Add the not added point, and based on this decide the next starting segment for both rectangles
1136  intersection_polygon->points[numIntersections ].x = icurrent->x2;
1137  intersection_polygon->points[numIntersections++].y = icurrent->y2;
1138 
1139  i_inner = (i_inner + 1)%n_pinner;
1140 
1141  p2pol1 = POLYGON_NTH_POINT(p_inner, i_inner);
1142 
1143  //If both ending points correspond to a vertex, treat special case
1144  if(p2pol1->x == p2pol2->x && p2pol1->y == p2pol2->y)
1145  in_inner = -1;
1146  else { //Nearest second to last added point will remain
1147  double
1148  dx_inner = p2pol1->x - intersection_polygon->points[numIntersections - 1].x,
1149  dx_other = p2pol2->x - intersection_polygon->points[numIntersections - 1].x,
1150  dy_inner = p2pol1->y - intersection_polygon->points[numIntersections - 1].y,
1151  dy_other = p2pol2->y - intersection_polygon->points[numIntersections - 1].y;
1152 
1153  if(dx_inner*dx_inner + dy_inner*dy_inner < dx_other*dx_other + dy_other*dy_other)
1154  in_inner = 1;
1155  else
1156  in_inner = 0;
1157  }
1158  }
1159 
1160  i_other = (i_other + 1)%n_pother;
1161 
1162  } else { //Last added point correspond to a vertex in both rectangles
1163 
1164  //If next point to check is inner point, add it immediately and pass to next segment
1165  if(inner_points_p_inner[(i_inner + 1)%n_pinner]) {
1166  i_inner = (i_inner + 1)%n_pinner;
1167  i_other = (i_other + 1)%n_pother;
1168  //If the next possible point to add is inner point and the same one added first,
1169  //the work is finished. :D
1170  if(i_inner == inner_index) {
1171  differentLastToAdd = 0;
1172  icurrent = NULL;
1173  } else { //Add the inner point because it is sure that it is part of the intersection solution
1174  current_point = POLYGON_NTH_POINT(p_inner, i_inner);
1175  intersection_polygon->points[numIntersections ].x = current_point->x;
1176  intersection_polygon->points[numIntersections++].y = current_point->y;
1177  in_inner = 1;
1178  continue;
1179  }
1180  } else if(inner_points_p_other[(i_other + 1)%n_pother]) {
1181  i_inner = (i_inner + 1)%n_pinner;
1182  i_other = (i_other + 1)%n_pother;
1183  current_point = POLYGON_NTH_POINT(p_other, i_other);
1184  intersection_polygon->points[numIntersections ].x = current_point->x;
1185  intersection_polygon->points[numIntersections++].y = current_point->y;
1186  in_inner = 0;
1187  continue;
1188  } else {
1189 
1190  //Check if current segments perform a line intersection (A point intersection is warrantied because the first
1191  //point corresponds to a common vertex)
1192 
1193  //Start intersection search from next point to not repeat the same intersection
1194  p1pol1 = POLYGON_NTH_POINT(p_inner, i_inner);
1195  p2pol1 = POLYGON_NTH_POINT(p_inner, (i_inner + 1)%n_pinner);
1196  p1pol2 = POLYGON_NTH_POINT(p_other, i_other);
1197  p2pol2 = POLYGON_NTH_POINT(p_other, (i_other + 1)%n_pother);
1198 
1199  icurrent = point2D<T>::getPreciseSegmentsIntersection(p1pol2, p2pol2, p1pol1, p2pol1);
1200 
1201  if(icurrent != NULL && icurrent->type == 0) { //New line case to treat
1202  //Add the not added point, and based on this decide the next starting segment for both rectangles
1203  intersection_polygon->points[numIntersections ].x = icurrent->x2;
1204  intersection_polygon->points[numIntersections++].y = icurrent->y2;
1205  i_inner = (i_inner + 1)%n_pinner;
1206  i_other = (i_other + 1)%n_pother;
1207  //If both ending points correspond to a vertex, treat special case
1208  if(p2pol1->x == p2pol2->x && p2pol1->y == p2pol2->y)
1209  in_inner = -1;
1210  else { //Nearest second to last added point will remain
1211  double
1212  dx_inner = p2pol1->x - intersection_polygon->points[numIntersections - 1].x,
1213  dx_other = p2pol2->x - intersection_polygon->points[numIntersections - 1].x,
1214  dy_inner = p2pol1->y - intersection_polygon->points[numIntersections - 1].y,
1215  dy_other = p2pol2->y - intersection_polygon->points[numIntersections - 1].y;
1216 
1217  if(dx_inner*dx_inner + dy_inner*dy_inner < dx_other*dx_other + dy_other*dy_other)
1218  in_inner = 1;
1219  else
1220  in_inner = 0;
1221  }
1222  } else { //If it is not a segment intersection, the last possibility corresponds to
1223  //one of both current segments, intersecting a different segment of the other rectangle
1224 
1225  point2D<T> *p1aux, *p2aux;
1226  int aux_index;
1227 
1228  //Check for intersection with inner rectangle first
1229  aux_index = (i_inner + 1)%n_pinner;
1230  p2aux = POLYGON_NTH_POINT(p_inner, aux_index);
1231  for(j=0; j < n_pinner - 1; j++, aux_index = (aux_index + 1)%n_pinner) {
1232  p1aux = p2aux;
1233  p2aux = POLYGON_NTH_POINT(p_inner, (aux_index + 1)%n_pinner);
1234  //If no intersection found, pass to the next segment
1235  if( (icurrent = point2D<T>::getPreciseSegmentsIntersection(p1pol2, p2pol2, p1aux, p2aux)) == NULL )
1236  continue;
1237  //Set the index for the first segment to analyse for the other rectangle
1238  i_inner = aux_index;
1239  allocatedResults[num_allocated++] = icurrent;
1240  break;
1241  }
1242 
1243  if(icurrent == NULL) { //If no intersection found for other rectangle segment, intersection must be
1244  //between the current segment from inner rectangle and one of the other rectangle
1245 
1246  //Check for intersection with other rectangle
1247  aux_index = (i_other + 1)%n_pother;
1248  p2aux = POLYGON_NTH_POINT(p_other, aux_index);
1249  for(j=0; j < n_pother - 1; j++, aux_index = (aux_index + 1)%n_pother) {
1250  p1aux = p2aux;
1251  p2aux = POLYGON_NTH_POINT(p_other, (aux_index + 1)%n_pother);
1252  //If no intersection found, pass to the next segment
1253  if( (icurrent = point2D<T>::getPreciseSegmentsIntersection(p1pol1, p2pol1, p1aux, p2aux)) == NULL )
1254  continue;
1255  //Set the index for the first segment to analyse for the other rectangle
1256  i_other = aux_index;
1257  allocatedResults[num_allocated++] = icurrent;
1258  break;
1259  }
1260 
1261  if(icurrent == NULL) { //If no intersection found for other rectangle segment, intersection must be
1262  //between the current segment from inner rectangle and one of the other rectangle
1263  //An error???? It should not happen because if next point is out an intersection should exist.
1264  //If an error of this type occurs, finish computation and give the partial intersection found.
1265  std::cout << "Error of intersection not found!!" << std::endl;
1266  break;
1267  } else { //A point intersection for inner rectangle segment, so go to other rectangle
1268  intersection_polygon->points[numIntersections ].x = icurrent->x1;
1269  intersection_polygon->points[numIntersections++].y = icurrent->y1;
1270  i_inner = (i_inner + 1)%n_pinner;
1271  in_inner = 0;
1272  }
1273  } else { //A point intersection for other rectangle segment, so go to inner rectangle
1274  intersection_polygon->points[numIntersections ].x = icurrent->x1;
1275  intersection_polygon->points[numIntersections++].y = icurrent->y1;
1276  i_other = (i_other + 1)%n_pother;
1277  in_inner = 1;
1278  }
1279  }
1280  }
1281  }
1282  } while (differentLastToAdd);
1283 
1284  for(i=0; i<num_allocated; i++)
1285  delete allocatedResults[i];
1286 
1287  if(numIntersections < 3) { //If the intersection can not form an area, the area is NULL
1288  delete intersection_polygon;
1289  return NULL;
1290  }
1291 
1292  return intersection_polygon;
1293 }
1294 
1295 template <typename T>
1296 bool polygon2D<T>::memmove(int to, int from, int number) {
1297  if(to < 0 || from < 0) {
1298  std::cout << "polygon2D: memmove error: to or from lower than 0." << std::endl;
1299  return false;
1300  }
1301 
1302  if(to == from)
1303  return true;
1304 
1305  if(to < from) {
1306  if(number > points.size() - from) {
1307  std::cout << "polygon2D: memmove error: according to 'from' and 'number', elements to move exceding existing elements." << std::endl;
1308  return false;
1309  }
1310  for(int i = 0; i < number; i++)
1311  points[to + i] = points[from + i];
1312  }
1313 
1314  //from > to
1315  if(to + number > points.capacity())
1316  points.reserve(to + number);
1317  for(int i = number - 1; i >= 0; i--)
1318  points[to + i] = points[from + i];
1319 
1320  return true;
1321 }
1322 
1323 
1324 //Function which returns a polygon representing the area of intersection of two rectangles (with any orientation)
1325 //TO DO: Generalize for any polygon
1326 //This function presents problems with certain rectangle configurations due to floating point precision
1327 //with segment intersections. When this occurs, memory leaks can happen.
1328 template <typename T>
1330 
1331  //First check polygons bounding boxes, if there is no bounding boxes intersection, there is no polygon intersection
1332  if(!Rectangle<T>::thereIsIntersection(&POLYGON_2D_BB(rectangle1), &POLYGON_2D_BB(rectangle2)))
1333  return NULL;
1334 
1335  if(polygon2D<T>::equalPolygons(rectangle1, rectangle2, 0.001))
1336  return rectangle1->copy();
1337 
1338  int i;
1339  int num_inner_pol1 = 0, first_inner_pol1 = -1, num_inner_pol2 = 0, first_inner_pol2 = -1;
1340  point2D<T> *p1pol1, p1pol2;
1341 
1342  //Set inner point flags for both rectangles. An inner point can not be an intersecting point
1343  for(i=0; i<4; i++) {
1344  p1pol1 = POLYGON_NTH_POINT(rectangle1, i);
1345  if(rectangle2->pointInConvexPolygon(p1pol1->x, p1pol1->y, true)) {
1346  num_inner_pol1++;
1347  if(first_inner_pol1 < 0)
1348  first_inner_pol1 = i;
1349  }
1350 
1351  p1pol2 = POLYGON_NTH_POINT(rectangle2, i);
1352  if(rectangle1->pointInConvexPolygon(p1pol2->x, p1pol2->y, true)) {
1353  num_inner_pol2++;
1354  if(first_inner_pol2 < 0)
1355  first_inner_pol2 = i;
1356  }
1357  }
1358 
1359  // std::cout << "First Inn Pol 1: " << first_inner_pol1 << "\tFirst Inn Pol 2: " << first_inner_pol2 << std::endl;
1360  if( fabs(rectangle1->points[0].x + 284.314450444592) < MAX_FLOAT_ERROR
1361  && fabs(rectangle2->points[0].x + 239.497076034818) < MAX_FLOAT_ERROR)
1362  std::cout << "Point found: x[0] = " << rectangle1->points[0].x << std::endl;
1363  if(num_inner_pol1 == 4)
1364  return rectangle1->copy();
1365 
1366  if(num_inner_pol2 == 4)
1367  return rectangle2->copy();
1368 
1369  Intersection<T> *intersectionsRectangle2[4][4], currentIntersections[4], allocatedResults[12], current;
1370  int j, k, l, with_segment_intersection, numIntersections, numTotalDoubles = 0, num_allocated = 0;
1371  int sequenceMap[12], //values: 0 (polygon point), 1 (intersection point), -1 (both)
1372  originalSegmentMap[12], //values: 0 (polygon point), 1 (intersection point), -1 (both)
1373  num_intersectionsRectangle2[4], segmentIntersectionRectangle1[4], segmentIntersectionRectangle2[4];
1374  point2D<T> *p2pol1, p2pol2;
1375  double dpol, dx, dy, dcur1, dcur2;
1376  bool move_inner_undone = true;
1377  polygon2D<T> *rectangle1_ext = copy_fpolygon2d_extended_size(rectangle1, 12);
1378 
1379  memset(sequenceMap, 0, 12*sizeof(int));
1380  memset(originalSegmentMap, 0, 12*sizeof(int));
1381  memset(num_intersectionsRectangle2, 0, 4*sizeof(int));
1382  memset(segmentIntersectionRectangle1, 0, 4*sizeof(int));
1383  memset(segmentIntersectionRectangle2, 0, 4*sizeof(int));
1384 
1385  p2pol1 = POLYGON_NTH_POINT(rectangle1, 0);
1386 
1387  for(i=0, j=1; i<4; i++) {
1388  p1pol1 = p2pol1;
1389  p2pol1 = POLYGON_NTH_POINT(rectangle1, (i + 1)%4);
1390 
1391  numIntersections = 0;
1392  with_segment_intersection = 0;
1393 
1394  p2pol2 = POLYGON_NTH_POINT(rectangle2, 0);
1395  for(k=0; k<4; k++) {
1396  p1pol2 = p2pol2;
1397  p2pol2 = POLYGON_NTH_POINT(rectangle2, (k + 1)%4);
1398 
1399  //If no intersection found, pass to the next pair
1400  if( (current = get_segments_intersection(p1pol1, p2pol1, p1pol2, p2pol2)) == NULL )
1401  continue;
1402 
1403  allocatedResults[num_allocated++] = current;
1404 
1405  if(current->type == 0) { //If the intersection corresponds to a segment, for two rectangles
1406  //the other intersections MUST correspond to the same limit points of the
1407  //resulting segments
1408  if(++numTotalDoubles == 4) { //If this counter arrives to 4, it means that there is a perfect match between rectangles
1409  for(l=0; l<num_allocated; l++)
1410  delete allocatedResults[l];
1411  delete rectangle1_ext;
1412  return copy_fpolygon2d(rectangle1);
1413  }
1414  currentIntersections[0] = intersectionsRectangle2[k][0] = current;
1415  segmentIntersectionRectangle1[i] = 1;
1416  with_segment_intersection = segmentIntersectionRectangle2[k] = num_intersectionsRectangle2[k] = numIntersections = 1;
1417  break;
1418  }
1419 
1420  if(!segmentIntersectionRectangle2[k])
1421  intersectionsRectangle2[k][num_intersectionsRectangle2[k]++] = current;
1422  currentIntersections[numIntersections++] = current;
1423  }
1424 
1425  if(numIntersections > 0) { //Process currently found intersections
1426 
1427  dx = p1pol1->x - p2pol1->x;
1428  dy = p1pol1->y - p2pol1->y;
1429  dpol = dx*dx + dy*dy;
1430 
1431  if(with_segment_intersection) { //Treat special case of a segment intersection result
1432 
1433  dx = currentIntersections[0]->x1 - p1pol1->x;
1434  dy = currentIntersections[0]->y1 - p1pol1->y;
1435  dcur1 = dx*dx + dy*dy;
1436  dx = currentIntersections[0]->x2 - p1pol1->x;
1437  dy = currentIntersections[0]->y2 - p1pol1->y;
1438  dcur2 = dx*dx + dy*dy;
1439 
1440  if(dcur1 < dcur2) {
1441  if(dcur1 > MAX_FLOAT_ERROR) { //If the nearest segment point is not the rectangle point itself, the point is added
1442  rectangle1_ext->n_points++;
1443  if(i < 3)
1444  memmove(rectangle1_ext->points + j + 1, rectangle1_ext->points + j, sizeof(struct fpoint_2d)*(3-i) );
1445  rectangle1_ext->points[j].x = currentIntersections[0]->x1;
1446  rectangle1_ext->points[j].y = currentIntersections[0]->y1;
1447  originalSegmentMap[j] = i;
1448  sequenceMap[j++] = 1;
1449  } else {
1450  originalSegmentMap[j-1] = i;
1451  sequenceMap[j-1] = -1;
1452  }
1453  if( fabs(dpol - dcur2) > MAX_FLOAT_ERROR ) { //If the farest segment point is not the other rectangle point, the point is added
1454  rectangle1_ext->n_points++;
1455  if(i < 3)
1456  memmove(rectangle1_ext->points + j + 1, rectangle1_ext->points + j, sizeof(struct fpoint_2d)*(3-i) );
1457  rectangle1_ext->points[j].x = currentIntersections[0]->x2;
1458  rectangle1_ext->points[j].y = currentIntersections[0]->y2;
1459  originalSegmentMap[j] = i;
1460  sequenceMap[j++] = 1;
1461  } else {
1462  originalSegmentMap[j] = i;
1463  sequenceMap[j] = -1;
1464  }
1465  } else { //Same idea but with inverse order
1466  if(dcur2 > MAX_FLOAT_ERROR) { //If the nearest segment point is not the rectangle point itself, the point is added
1467  rectangle1_ext->n_points++;
1468  if(i < 3)
1469  memmove(rectangle1_ext->points + j + 1, rectangle1_ext->points + j, sizeof(struct fpoint_2d)*(3-i) );
1470  rectangle1_ext->points[j].x = currentIntersections[0]->x2;
1471  rectangle1_ext->points[j].y = currentIntersections[0]->y2;
1472  originalSegmentMap[j] = i;
1473  sequenceMap[j++] = 1;
1474  } else {
1475  originalSegmentMap[j-1] = i;
1476  sequenceMap[j-1] = -1;
1477  }
1478 
1479  if( fabs(dpol - dcur1) > MAX_FLOAT_ERROR ) { //If the farest segment point is not the other rectangle point, the point is added
1480  rectangle1_ext->n_points++;
1481  if(i < 3)
1482  memmove(rectangle1_ext->points + j + 1, rectangle1_ext->points + j, sizeof(struct fpoint_2d)*(3-i) );
1483  rectangle1_ext->points[j].x = currentIntersections[0]->x1;
1484  rectangle1_ext->points[j].y = currentIntersections[0]->y1;
1485  originalSegmentMap[j] = i;
1486  sequenceMap[j++] = 1;
1487  } else {
1488  originalSegmentMap[j] = i;
1489  sequenceMap[j] = -1;
1490  }
1491  }
1492  } else { //Point intersections: For two rectangles, only a maximum of two intersections can happen in a rectangle segment
1493  //TO DO: For generalizing to polygons, intersection points must be ordered according to distance
1494  //As for rectangles (and for convex polygons) the maximum number of intersections is 2, the ordering
1495  //is made by cases
1496 
1497  //If there is two intersections or more, verify repeated points (case where a corner point intersects one of the other rectangle )
1498  if(numIntersections >= 2) {
1499  for(k=0; k<numIntersections-1; k++)
1500  for(l=k+1; l<numIntersections; l++) {
1501  if( fabs(currentIntersections[k]->x1 - currentIntersections[l]->x1) < MAX_FLOAT_ERROR
1502  && fabs(currentIntersections[k]->y1 - currentIntersections[l]->y1) < MAX_FLOAT_ERROR ) {
1503  if(l + 1 < numIntersections)
1504  memmove(currentIntersections + l, currentIntersections + l + 1, sizeof(Intersection<T> *)*(numIntersections-l-1) );
1505  numIntersections--;
1506  break;
1507  }
1508  }
1509  }
1510 
1511  if(numIntersections == 2) {
1512  dx = currentIntersections[0]->x1 - p1pol1->x;
1513  dy = currentIntersections[0]->y1 - p1pol1->y;
1514  dcur1 = dx*dx + dy*dy;
1515  dx = currentIntersections[1]->x1 - p1pol1->x;
1516  dy = currentIntersections[1]->y1 - p1pol1->y;
1517  dcur2 = dx*dx + dy*dy;
1518 
1519  if(dcur1 < dcur2) {
1520  if(dcur1 > MAX_FLOAT_ERROR) { //If the nearest segment point is not the rectangle point itself, the point is added
1521  rectangle1_ext->n_points++;
1522  if(i < 3)
1523  memmove(rectangle1_ext->points + j + 1, rectangle1_ext->points + j, sizeof(struct fpoint_2d)*(3-i) );
1524 
1525  rectangle1_ext->points[j].x = currentIntersections[0]->x1;
1526  rectangle1_ext->points[j].y = currentIntersections[0]->y1;
1527 
1528  originalSegmentMap[j] = i;
1529  sequenceMap[j++] = 1;
1530 
1531  } else {
1532  originalSegmentMap[j-1] = i;
1533  sequenceMap[j-1] = -1;
1534  }
1535  if( fabs(dpol - dcur2) > MAX_FLOAT_ERROR ) { //If the farest segment point is not the other rectangle point, the point is added
1536  rectangle1_ext->n_points++;
1537  if(i<3)
1538  memmove(rectangle1_ext->points + j + 1, rectangle1_ext->points + j, sizeof(struct fpoint_2d)*(3-i) );
1539  rectangle1_ext->points[j].x = currentIntersections[1]->x1;
1540  rectangle1_ext->points[j].y = currentIntersections[1]->y1;
1541  originalSegmentMap[j] = i;
1542  sequenceMap[j++] = 1;
1543  } else {
1544  originalSegmentMap[j] = i;
1545  sequenceMap[j] = -1;
1546  }
1547  } else { //Same idea but with inverse order
1548  if(dcur2 > MAX_FLOAT_ERROR) { //If the nearest segment point is not the rectangle point itself, the point is added
1549  rectangle1_ext->n_points++;
1550  if(i<3)
1551  memmove(rectangle1_ext->points + j + 1, rectangle1_ext->points + j, sizeof(struct fpoint_2d)*(3-i) );
1552  rectangle1_ext->points[j].x = currentIntersections[1]->x1;
1553  rectangle1_ext->points[j].y = currentIntersections[1]->y1;
1554  originalSegmentMap[j] = i;
1555  sequenceMap[j++] = 1;
1556  } else {
1557  originalSegmentMap[j-1] = i;
1558  sequenceMap[j-1] = -1;
1559  }
1560  if( fabs(dpol - dcur1) > MAX_FLOAT_ERROR ) { //If the farest segment point is not the other rectangle point, the point is added
1561  rectangle1_ext->n_points++;
1562  if(i<3)
1563  memmove(rectangle1_ext->points + j + 1, rectangle1_ext->points + j, sizeof(struct fpoint_2d)*(3-i) );
1564  rectangle1_ext->points[j].x = currentIntersections[0]->x1;
1565  rectangle1_ext->points[j].y = currentIntersections[0]->y1;
1566  originalSegmentMap[j] = i;
1567  sequenceMap[j++] = 1;
1568  } else {
1569  originalSegmentMap[j] = i;
1570  sequenceMap[j] = -1;
1571  }
1572  }
1573  } else { //Just one intersection
1574  dx = currentIntersections[0]->x1 - p1pol1->x;
1575  dy = currentIntersections[0]->y1 - p1pol1->y;
1576  dcur1 = dx*dx + dy*dy;
1577 
1578  if(dcur1 > MAX_FLOAT_ERROR && fabs(dpol - dcur1) > MAX_FLOAT_ERROR) { //If the nearest segment point is not the rectangle point itself, the point is added
1579  rectangle1_ext->n_points++;
1580  if(i<3)
1581  memmove(rectangle1_ext->points + j + 1, rectangle1_ext->points + j, sizeof(struct fpoint_2d)*(3-i) );
1582  rectangle1_ext->points[j].x = currentIntersections[0]->x1;
1583  rectangle1_ext->points[j].y = currentIntersections[0]->y1;
1584  originalSegmentMap[j] = i;
1585  sequenceMap[j++] = 1;
1586  } else if( fabs(dpol - dcur1) < MAX_FLOAT_ERROR ) {
1587  originalSegmentMap[j] = i;
1588  sequenceMap[j] = -1;
1589  } else {
1590  originalSegmentMap[j-1] = i;
1591  sequenceMap[j-1] = -1;
1592  }
1593  }
1594  }
1595  }
1596 
1597  if(i < 3) {
1598  if(move_inner_undone && first_inner_pol1 > 0 && first_inner_pol1 == i + 1) {
1599  first_inner_pol1 = j;
1600  move_inner_undone = false;
1601  }
1602  j++;
1603  }
1604  }
1605 
1606  int numTotalIntersections = 0;
1607  for(i=0; i<rectangle1_ext->n_points; i++)
1608  if(sequenceMap[i] != 0)
1609  numTotalIntersections++;
1610 
1611  //If no inner points for both rectangles, there is two possibilities
1612  if( num_inner_pol1 == 0 && num_inner_pol2 == 0 ) {
1613  if(numTotalIntersections < 3) { //If the intersection can not form an area, the area is NULL
1614  for(l=0; l<num_allocated; l++)
1615  delete allocatedResults[l];
1616  delete rectangle1_ext;
1617  return NULL;
1618  }
1619 
1620  for(i=0; i<num_allocated; i++)
1621  delete allocatedResults[i];
1622 
1623  //Else, the intersection is just formed by the intersection points
1624  for(i=0, j=0; i<rectangle1_ext->n_points; i++)
1625  if(sequenceMap[i] != 0) {
1626  rectangle1_ext->points[j].x = rectangle1_ext->points[i].x;
1627  rectangle1_ext->points[j].y = rectangle1_ext->points[i].y;
1628  j++;
1629  }
1630  rectangle1_ext->n_points = numTotalIntersections;
1631  return rectangle1_ext;
1632 
1633  }
1634 
1635  // std::cout << "Extended Rectangle 1:" << std::endl;
1636  //for(i=0; i < rectangle1_ext->n_points; i++)
1637  // std::cout << "(" << rectangle1_ext->points[i].x << ", " << rectangle1_ext->points[i].y << ") ";
1638  //std::cout << std::endl;
1639 
1640  //If the execution arrives here, then is necessary to also generate the extended polygon for second rectangle
1641 
1642  int sequenceMap2[12], originalSegmentMap2[12];
1643  polygon2D<T> *rectangle2_ext = copy_fpolygon2d_extended_size(rectangle2, 12);
1644 
1645  memset(sequenceMap2, 0, 12*sizeof(int));
1646  memset(originalSegmentMap2, 0, 12*sizeof(int));
1647 
1648  move_inner_undone = true;
1649  p2pol2 = POLYGON_NTH_POINT(rectangle2, 0);
1650 
1651  for(i=0, j=1; i<4; i++) {
1652 
1653  p1pol2 = p2pol2;
1654  p2pol2 = POLYGON_NTH_POINT(rectangle2, (i + 1)%4);
1655 
1656  if(num_intersectionsRectangle2[i] > 0) { //Process currently found intersections
1657 
1658  dx = p1pol2->x - p2pol2->x;
1659  dy = p1pol2->y - p2pol2->y;
1660  dpol = dx*dx + dy*dy;
1661 
1662  if(segmentIntersectionRectangle2[i]) { //Treat special case of a segment intersection result
1663 
1664  dx = intersectionsRectangle2[i][0]->x1 - p1pol2->x;
1665  dy = intersectionsRectangle2[i][0]->y1 - p1pol2->y;
1666  dcur1 = dx*dx + dy*dy;
1667  dx = intersectionsRectangle2[i][0]->x2 - p1pol2->x;
1668  dy = intersectionsRectangle2[i][0]->y2 - p1pol2->y;
1669  dcur2 = dx*dx + dy*dy;
1670 
1671  if(dcur1 < dcur2) {
1672  if(dcur1 > MAX_FLOAT_ERROR) { //If the nearest segment point is not the rectangle point itself, the point is added
1673  rectangle2_ext->n_points++;
1674  if(i<3)
1675  memmove(rectangle2_ext->points + j + 1, rectangle2_ext->points + j, sizeof(struct fpoint_2d)*(3-i) );
1676  rectangle2_ext->points[j].x = intersectionsRectangle2[i][0]->x1;
1677  rectangle2_ext->points[j].y = intersectionsRectangle2[i][0]->y1;
1678  originalSegmentMap2[j] = i;
1679  sequenceMap2[j++] = 1;
1680  } else {
1681  originalSegmentMap2[j-1] = i;
1682  sequenceMap2[j-1] = -1;
1683  }
1684  if( fabs(dpol - dcur2) >= MAX_FLOAT_ERROR ) { //If the farest segment point is not the other rectangle point, the point is added
1685  rectangle2_ext->n_points++;
1686  if(i<3)
1687  memmove(rectangle2_ext->points + j + 1, rectangle2_ext->points + j, sizeof(struct fpoint_2d)*(3-i) );
1688  rectangle2_ext->points[j].x = intersectionsRectangle2[i][0]->x2;
1689  rectangle2_ext->points[j].y = intersectionsRectangle2[i][0]->y2;
1690  originalSegmentMap2[j] = i;
1691  sequenceMap2[j++] = 1;
1692  } else {
1693  originalSegmentMap2[j] = i;
1694  sequenceMap2[j] = -1;
1695  }
1696  } else { //Same idea but with inverse order
1697  if(dcur2 > MAX_FLOAT_ERROR) { //If the nearest segment point is not the rectangle point itself, the point is added
1698  rectangle2_ext->n_points++;
1699  if(i<3)
1700  memmove(rectangle2_ext->points + j + 1, rectangle2_ext->points + j, sizeof(struct fpoint_2d)*(3-i) );
1701  rectangle2_ext->points[j].x = intersectionsRectangle2[i][0]->x2;
1702  rectangle2_ext->points[j].y = intersectionsRectangle2[i][0]->y2;
1703  originalSegmentMap2[j] = i;
1704  sequenceMap2[j++] = 1;
1705  } else {
1706  originalSegmentMap2[j-1] = i;
1707  sequenceMap2[j-1] = -1;
1708  }
1709  if( fabs(dpol - dcur1) > MAX_FLOAT_ERROR ) { //If the farest segment point is not the other rectangle point, the point is added
1710  rectangle2_ext->n_points++;
1711  if(i<3)
1712  memmove(rectangle2_ext->points + j + 1, rectangle2_ext->points + j, sizeof(struct fpoint_2d)*(3-i) );
1713  rectangle2_ext->points[j].x = intersectionsRectangle2[i][0]->x1;
1714  rectangle2_ext->points[j].y = intersectionsRectangle2[i][0]->y1;
1715  originalSegmentMap2[j] = i;
1716  sequenceMap2[j++] = 1;
1717  } else {
1718  originalSegmentMap2[j] = i;
1719  sequenceMap2[j] = -1;
1720  }
1721  }
1722  } else { //Point intersections: For two rectangles, only a maximum of two intersections can happen in a rectangle segment
1723  //TO DO: For generalizing to polygons, intersection points must be ordered according to distance
1724  //As for rectangles (and for convex polygons) the maximum number of intersections is 2, the ordering
1725  //is made by cases
1726  if(num_intersectionsRectangle2[i] >= 2) {
1727  for(k=0; k<num_intersectionsRectangle2[i]-1; k++)
1728  for(l=k+1; l<num_intersectionsRectangle2[i]; l++) {
1729  if( fabs(intersectionsRectangle2[i][k]->x1 - intersectionsRectangle2[i][l]->x1) < MAX_FLOAT_ERROR
1730  && fabs(intersectionsRectangle2[i][k]->y1 - intersectionsRectangle2[i][l]->y1) < MAX_FLOAT_ERROR ) {
1731  if(l+1 < num_intersectionsRectangle2[i])
1732  memmove(intersectionsRectangle2[i] + l, intersectionsRectangle2[i] + l + 1, sizeof(Intersection<T> *)*(num_intersectionsRectangle2[i]-l-1) );
1733  num_intersectionsRectangle2[i]--;
1734  break;
1735  }
1736  }
1737  }
1738 
1739  if(num_intersectionsRectangle2[i] == 2) { //se
1740  dx = intersectionsRectangle2[i][0]->x1 - p1pol2->x;
1741  dy = intersectionsRectangle2[i][0]->y1 - p1pol2->y;
1742  dcur1 = dx*dx + dy*dy;
1743  dx = intersectionsRectangle2[i][1]->x1 - p1pol2->x;
1744  dy = intersectionsRectangle2[i][1]->y1 - p1pol2->y;
1745  dcur2 = dx*dx + dy*dy;
1746 
1747  if(dcur1 < dcur2) {
1748  if(dcur1 > MAX_FLOAT_ERROR) { //If the nearest segment point is not the rectangle point itself, the point is added
1749  rectangle2_ext->n_points++;
1750  if(i<3)
1751  memmove(rectangle2_ext->points + j + 1, rectangle2_ext->points + j, sizeof(struct fpoint_2d)*(3-i) );
1752  rectangle2_ext->points[j].x = intersectionsRectangle2[i][0]->x1;
1753  rectangle2_ext->points[j].y = intersectionsRectangle2[i][0]->y1;
1754  originalSegmentMap2[j] = i;
1755  sequenceMap2[j++] = 1;
1756  } else {
1757  originalSegmentMap2[j-1] = i;
1758  sequenceMap2[j-1] = -1;
1759  }
1760  if( fabs(dpol - dcur2) > MAX_FLOAT_ERROR ) { //If the farest segment point is not the other rectangle point, the point is added
1761  rectangle2_ext->n_points++;
1762  if(i<3)
1763  memmove(rectangle2_ext->points + j + 1, rectangle2_ext->points + j, sizeof(struct fpoint_2d)*(3-i) );
1764  rectangle2_ext->points[j].x = intersectionsRectangle2[i][1]->x1;
1765  rectangle2_ext->points[j].y = intersectionsRectangle2[i][1]->y1;
1766  originalSegmentMap2[j] = i;
1767  sequenceMap2[j++] = 1;
1768  } else {
1769  originalSegmentMap2[j] = i;
1770  sequenceMap2[j] = -1;
1771  }
1772  } else { //Same idea but with inverse order
1773  if(dcur2 > MAX_FLOAT_ERROR) { //If the nearest segment point is not the rectangle point itself, the point is added
1774  rectangle2_ext->n_points++;
1775  if(i<3)
1776  memmove(rectangle2_ext->points + j + 1, rectangle2_ext->points + j, sizeof(struct fpoint_2d)*(3-i) );
1777  rectangle2_ext->points[j].x = intersectionsRectangle2[i][1]->x1;
1778  rectangle2_ext->points[j].y = intersectionsRectangle2[i][1]->y1;
1779  originalSegmentMap2[j] = i;
1780  sequenceMap2[j++] = 1;
1781  } else {
1782  originalSegmentMap2[j-1] = i;
1783  sequenceMap2[j-1] = -1;
1784  }
1785 
1786  if( fabs(dpol - dcur1) > MAX_FLOAT_ERROR ) { //If the farest segment point is not the other rectangle point, the point is added
1787  rectangle2_ext->n_points++;
1788  if(i<3)
1789  memmove(rectangle2_ext->points + j + 1, rectangle2_ext->points + j, sizeof(struct fpoint_2d)*(3-i) );
1790  rectangle2_ext->points[j].x = intersectionsRectangle2[i][0]->x1;
1791  rectangle2_ext->points[j].y = intersectionsRectangle2[i][0]->y1;
1792  originalSegmentMap2[j] = i;
1793  sequenceMap2[j++] = 1;
1794  } else {
1795  originalSegmentMap2[j] = i;
1796  sequenceMap2[j] = -1;
1797  }
1798  }
1799  } else { //Just one intersection
1800  dx = intersectionsRectangle2[i][0]->x1 - p1pol2->x;
1801  dy = intersectionsRectangle2[i][0]->y1 - p1pol2->y;
1802  dcur1 = dx*dx + dy*dy;
1803 
1804  if(dcur1 > MAX_FLOAT_ERROR && fabs(dpol - dcur1) > MAX_FLOAT_ERROR) { //If the nearest segment point is not the rectangle point itself, the point is added
1805  rectangle2_ext->n_points++;
1806  if(i<3)
1807  memmove(rectangle2_ext->points + j + 1, rectangle2_ext->points + j, sizeof(struct fpoint_2d)*(3-i) );
1808  rectangle2_ext->points[j].x = intersectionsRectangle2[i][0]->x1;
1809  rectangle2_ext->points[j].y = intersectionsRectangle2[i][0]->y1;
1810  originalSegmentMap2[j] = i;
1811  sequenceMap2[j++] = 1;
1812  } else if( fabs(dcur1 - dpol) < MAX_FLOAT_ERROR ) {
1813  originalSegmentMap2[j] = i;
1814  sequenceMap2[j] = -1;
1815  } else {
1816  originalSegmentMap2[j] = i;
1817  sequenceMap2[j-1] = -1;
1818  }
1819  }
1820  }
1821  }
1822 
1823  if(i < 3) {
1824  if(move_inner_undone && first_inner_pol2 > 0 && first_inner_pol2 == i + 1) {
1825  first_inner_pol2 = j;
1826  move_inner_undone = false;
1827  }
1828  j++;
1829  }
1830 
1831  }
1832 
1833  // std::cout << "Extended Rectangle 2:\t" << std::endl;
1834  //for(i=0; i < rectangle2_ext->n_points; i++)
1835  // std::cout << "(" << rectangle2_ext->points[i].x << ", " << rectangle2_ext->points[i].y << ") ";
1836  //std::cout << std::endl;
1837 
1838  //std::cout << "First Inn Pol 1: " << first_inner_pol1 << "\tFirst Inn Pol 2: " << first_inner_pol2 << std::endl;
1839 
1840  //Now get the intersection polygon
1841  polygon2D<T> *inner_point_rectangle, the_other_rectangle, intersection_polygon;
1842  int *innerSequenceMap, *otherSequenceMap, *innerOriginalSegmentMap, *otherOriginalSegmentMap, *innerSegmentIntersection, *otherSegmentIntersection;
1843  int first_inner_index, first_other_index, inner_index, other_index, nother, ninner, search_first_other = 1, current_inner = 1;
1844 
1845  //Because of previous validation it MUST exist an inner point
1846  if(num_inner_pol1 > 0) {
1847  inner_point_rectangle = rectangle1_ext;
1848  the_other_rectangle = rectangle2_ext;
1849  first_inner_index = inner_index = first_inner_pol1;
1850  innerSequenceMap = sequenceMap;
1851  otherSequenceMap = sequenceMap2;
1852  innerOriginalSegmentMap = originalSegmentMap;
1853  otherOriginalSegmentMap = originalSegmentMap2;
1854  innerSegmentIntersection = segmentIntersectionRectangle1;
1855  otherSegmentIntersection = segmentIntersectionRectangle2;
1856  } else {
1857  inner_point_rectangle = rectangle2_ext;
1858  the_other_rectangle = rectangle1_ext;
1859  first_inner_index = inner_index = first_inner_pol2;
1860  innerSequenceMap = sequenceMap2;
1861  otherSequenceMap = sequenceMap;
1862  innerOriginalSegmentMap = originalSegmentMap2;
1863  otherOriginalSegmentMap = originalSegmentMap;
1864  innerSegmentIntersection = segmentIntersectionRectangle2;
1865  otherSegmentIntersection = segmentIntersectionRectangle1;
1866  }
1867 
1868  ninner = inner_point_rectangle->n_points;
1869  nother = the_other_rectangle->n_points;
1870 
1871  //Construct the intersection polygon
1872  intersection_polygon = copy_fpolygon2d(inner_point_rectangle);
1873 
1874  for(i=0, j=0, k=0; i<ninner || j<nother; ) {
1875  if(k>ninner) {
1876  int l;
1877  std::cout.precision(15);
1878  std::cout << "Rectangle 1:\t" << std::endl;
1879  for(l=0; l < rectangle1->n_points; l++)
1880  std::cout << "(" << rectangle1->points[l].x << ", " << rectangle1->points[l].y << ") ";
1881  std::cout << std::endl;
1882  std::cout << "Rectangle 2:\t" << std::endl;
1883  for(l=0; l < rectangle2->n_points; l++)
1884  std::cout << "(" << rectangle2->points[l].x << ", " << rectangle2->points[l].y << ") ";
1885  std::cout << std::endl;
1886  std::cout << "Extended Rectangle 1:\t" << std::endl;
1887  for(l=0; l < rectangle1_ext->n_points; l++)
1888  std::cout << "(" << rectangle1_ext->points[l].x << ", " << rectangle1_ext->points[l].y << ") ";
1889  std::cout << std::endl;
1890  std::cout << "Extended Rectangle 2:\t" << std::endl;
1891  for(l=0; l < rectangle2_ext->n_points; l++)
1892  std::cout << "(" << rectangle2_ext->points[l].x << ", " << rectangle2_ext->points[l].y << ") ";
1893  std::cout << std::endl;
1894  }
1895 
1896  if(current_inner) { //If currently processing inner rectangle points
1897  //if point is intersection and it does not belong to a segment intersection, swap from inner to the other sequence
1898  if( innerSequenceMap[inner_index] != 0 //Check if point corresponds to an intersection
1899  && innerSegmentIntersection[innerOriginalSegmentMap[inner_index]] == 0 //Check if point is not the first of a segment intersection
1900  && innerSegmentIntersection[innerOriginalSegmentMap[(inner_index + 3)%4]] == 0 ) //Check if point was not the second of a segment intersection
1901  current_inner = 0;
1902 
1903  //If the first swap between polygons does not happen yet, nothing more has to be done as the intersection
1904  //polygon was initialized with the inner point rectangle. Just increment the index of point added.
1905  if(search_first_other) {
1906  intersection_polygon->points[k ].x = inner_point_rectangle->points[inner_index].x;
1907  intersection_polygon->points[k++].y = inner_point_rectangle->points[inner_index].y;
1908 
1909  if(current_inner == 0) { //If the first swap will happen, search for the first index of the other sequence
1910  search_first_other = 0;
1911  for(l=0; l<nother; l++)
1912  if( fabs(inner_point_rectangle->points[inner_index].x - the_other_rectangle->points[l].x) < MAX_FLOAT_ERROR
1913  && fabs(inner_point_rectangle->points[inner_index].y - the_other_rectangle->points[l].y) < MAX_FLOAT_ERROR ) {
1914  first_other_index = other_index = l;
1915  break;
1916  }
1917  other_index = (other_index + 1) % nother;
1918  j++;
1919  }
1920  } else { //If the first swap has been already made, the point has to be added, because information from the
1921  //other rectangle have been added, altering maybe the order of the inner point rectangle
1922  intersection_polygon->points[k ].x = inner_point_rectangle->points[inner_index].x;
1923  intersection_polygon->points[k++].y = inner_point_rectangle->points[inner_index].y;
1924 
1925  if(current_inner == 0) { //Search for the next index of the other sequence
1926  //Search for next intersection point until find it or until the sequence is finished
1927  while( j < nother
1928  && ( fabs(inner_point_rectangle->points[inner_index].x - the_other_rectangle->points[other_index].x) >= MAX_FLOAT_ERROR
1929  || fabs(inner_point_rectangle->points[inner_index].y - the_other_rectangle->points[other_index].y) >= MAX_FLOAT_ERROR ) ) {
1930  other_index = (other_index + 1) % nother;
1931  j++;
1932  }
1933 
1934  if(j < nother) { //If index is still valid, advance to the next position, because the intersection point has been
1935  j++; //already added
1936  other_index = (other_index + 1) % nother;
1937  }
1938  }
1939  }
1940 
1941  inner_index = (inner_index + 1) % ninner;
1942  i++;
1943 
1944  //If we have made the loop with this rectangle and there is no swap, we have finished
1945  if(current_inner == 1 && inner_index == first_inner_index)
1946  break;
1947 
1948  } else { //If now the other sequence is active
1949 
1950  //if point is intersection and it does not belong to a segment intersection, swap from inner to the other sequence
1951  if( otherSequenceMap[other_index] != 0 //Check if point corresponds to an intersection
1952  && otherSegmentIntersection[otherOriginalSegmentMap[other_index]] == 0 //Check if point is not the first of a segment intersection
1953  && otherSegmentIntersection[otherOriginalSegmentMap[(other_index + 3) % nother]] == 0 ) //Check if point was not the second of a segment intersection
1954  current_inner = 1;
1955 
1956  intersection_polygon->points[k ].x = the_other_rectangle->points[other_index].x;
1957  intersection_polygon->points[k++].y = the_other_rectangle->points[other_index].y;
1958 
1959  if(current_inner == 1) { //Search for the next index of the inner sequence
1960  //Search for next intersection point until find it or until the sequence is finished
1961  while( i < ninner
1962  && ( fabs(inner_point_rectangle->points[inner_index].x - the_other_rectangle->points[other_index].x) >= MAX_FLOAT_ERROR
1963  || fabs(inner_point_rectangle->points[inner_index].y - the_other_rectangle->points[other_index].y) >= MAX_FLOAT_ERROR ) ) {
1964  inner_index = (inner_index + 1) % ninner;
1965  i++;
1966  }
1967 
1968  i++;
1969  if(i < ninner) { //If index is still valid, advance to the next position, because the intersection point has been
1970  //already added
1971  inner_index = (inner_index + 1) % ninner;
1972  } else //We have arrived to the same initial point
1973  break;
1974  }
1975 
1976  other_index = (other_index + 1) % nother;
1977  j++;
1978 
1979  //If we have made the loop with this rectangle and there is no swap, we have finished
1980  if(current_inner == 0 && other_index == first_other_index)
1981  break;
1982  }
1983  }
1984 
1985  intersection_polygon->n_points = k;
1986 
1987  for(l=0; l<num_allocated; l++)
1988  delete allocatedResults[l];
1989 
1990  delete rectangle1_ext;
1991  delete rectangle2_ext;
1992 
1993  return intersection_polygon;
1994 
1995  }
1996 
1997 //Calculate de intersection between to line segments. The function returns a structure which represent the two
1998 //result possibilities: 1 point, 1 segment represented by its two limiting points
1999 template <typename T>
2001  double
2002  xp1L1 = POINT_2D_X(p1L1), yp1L1 = POINT_2D_Y(p1L1),
2003  xp2L1 = POINT_2D_X(p2L1), yp2L1 = POINT_2D_Y(p2L1),
2004  xp1L2 = POINT_2D_X(p1L2), yp1L2 = POINT_2D_Y(p1L2),
2005  xp2L2 = POINT_2D_X(p2L2), yp2L2 = POINT_2D_Y(p2L2),
2006  minxL1, minxL2, minyL1, minyL2, maxxL1, maxxL2, maxyL1, maxyL2;
2007 
2008  if(xp1L1 < xp2L1) { minxL1 = xp1L1; maxxL1 = xp2L1; }
2009  else { minxL1 = xp2L1; maxxL1 = xp1L1; }
2010 
2011  if(yp1L1 < yp2L1) { minyL1 = yp1L1; maxyL1 = yp2L1; }
2012  else { minyL1 = yp2L1; maxyL1 = yp1L1; }
2013 
2014  if(xp1L2 < xp2L2) { minxL2 = xp1L2; maxxL2 = xp2L2; }
2015  else { minxL2 = xp2L2; maxxL2 = xp1L2; }
2016 
2017  if(yp1L2 < yp2L2) { minyL2 = yp1L2; maxyL2 = yp2L2; }
2018  else { minyL2 = yp2L2; maxyL2 = yp1L2; }
2019 
2020  //X coordinate criteria
2021  if( minxL1 > maxxL2 || maxxL1 < minxL2)
2022  return NULL;
2023 
2024  //Y coordinate criteria
2025  if( minyL1 > maxyL2 || maxyL1 < minyL2)
2026  return NULL;
2027 
2028 
2029  if( fabs(xp1L1 - xp2L1) < MAX_FLOAT_ERROR ) { //Infinite slope for L1
2030  if( fabs(xp1L2 - xp2L2) < MAX_FLOAT_ERROR ) { //Infinite slope for L2 also
2031  if( fabs(xp1L1 - xp1L2) < MAX_FLOAT_ERROR ) { //Intersection of parallel lines
2032  Intersection<T> *result = new Intersection<T>();
2033  double
2034  min = minyL1 > minyL2 ? minyL1 : minyL2,
2035  max = maxyL1 < maxyL2 ? maxyL1 : maxyL2;
2036  if ( fabs(min - max) < MAX_FLOAT_ERROR ) { //If intersection occurs just in a limit point
2037  result->x1 = xp1L1; result->y1 = min; result->type = 1;
2038  } else { //If intersection result in a segment, extreme values are given and intersection type is 0
2039  result->x1 = xp1L1; result->y1 = min;
2040  result->x2 = xp1L1; result->y2 = max;
2041  result->type = 0;
2042  }
2043  return result;
2044  }
2045  return NULL;
2046  }
2047 
2048  //If L2 has a non infinite slope:
2049  double //the valid interval for y is between the maximal minimum, and the minimal maximum
2050  min = minyL1 > minyL2 ? minyL1 : minyL2,
2051  max = maxyL1 < maxyL2 ? maxyL1 : maxyL2,
2052  x = xp1L1,
2053  y = ((xp1L1 - xp2L2)*yp1L2 - (xp1L1 - xp1L2)*yp2L2)/(xp1L2 - xp2L2);
2054 
2055  if( y >= min && max >= y ) {
2056  Intersection<T> *result = new Intersection<T>();
2057  result->x1 = x;
2058  result->y1 = y;
2059  result->type = 1;
2060  return result;
2061  } else
2062  return NULL;
2063  } else if( fabs(xp1L2 - xp2L2) < MAX_FLOAT_ERROR ) { //Infinite slope for L2, and finite slope for L1
2064 
2065  double //the valid interval for y is between the maximal minimum, and the minimal maximum
2066  min = minyL1 > minyL2 ? minyL1 : minyL2,
2067  max = maxyL1 < maxyL2 ? maxyL1 : maxyL2,
2068  x = xp1L2,
2069  y = ((xp1L2 - xp2L1)*yp1L1 - (xp1L2 - xp1L1)*yp2L1)/(xp1L1 - xp2L1);
2070 
2071  if( y >= min && max >= y ) {
2072  Intersection<T> *result = new Intersection<T>();
2073  result->x1 = x;
2074  result->y1 = y;
2075  result->type = 1;
2076  return result;
2077  } else
2078  return NULL;
2079 
2080  }
2081 
2082  //If both slopes are finite
2083  double
2084  a1 = (yp2L1 - yp1L1)/(xp2L1 - xp1L1),
2085  a2 = (yp2L2 - yp1L2)/(xp2L2 - xp1L2),
2086  b1 = yp2L1 - a1*xp2L1,
2087  b2 = yp2L2 - a2*xp2L2;
2088 
2089  //Parallel lines
2090  if( fabs(a1 - a2) < MAX_FLOAT_ERROR_LITTLE_NUMBERS ) {
2091 
2092  //If intercepts are different, there is no intersection between the parallel lines
2093  if ( fabs(b1 - b2) >= MAX_FLOAT_ERROR )
2094  return NULL;
2095 
2096  //If there is intersection, calculate
2097  Intersection<T> *result = new Intersection<T>();
2098  double
2099  min = minxL1 > minxL2 ? minxL1 : minxL2,
2100  max = maxxL1 < maxxL2 ? maxxL1 : maxxL2;
2101  if ( fabs(min - max) < MAX_FLOAT_ERROR ) { //If intersection occurs just in a limit point
2102  result->x1 = min; result->y1 = min*a1 + b1; result->type = 1;
2103  } else { //If intersection result in a segment, extreme values are given and intersection type is 0
2104  result->x1 = min; result->y1 = min * a1 + b1;
2105  result->x2 = max; result->y2 = max * a1 + b1;
2106  result->type = 0;
2107  }
2108  return result;
2109  }
2110 
2111 
2112  double
2113  min = minxL1 > minxL2 ? minxL1 : minxL2,
2114  max = maxxL1 < maxxL2 ? maxxL1 : maxxL2,
2115  den = a1 - a2,
2116  x = (b2 - b1) / den,
2117  y = (b2*a1 - b1*a2) / den;
2118  if( x >= min && max >= x ) {
2119  Intersection<T> *result = new Intersection<T>();
2120  result->x1 = x;
2121  result->y1 = y;
2122  result->type = 1;
2123  return result;
2124  }
2125 
2126  return NULL;
2127 }
2128 
2129 //Calculate de intersection between to line segments. The function returns a structure which represent the two
2130 //result possibilities: 1 point, 1 segment represented by its two limiting points
2131 //This variant of get_segments_intersection does not consider floating point errors, giving the precise intersections.
2132 //If floating point error is present it will be handled as the real point, avoiding suppositions about the real value
2133 template <typename T>
2135  double
2136  xp1L1 = POINT_2D_X(p1L1), yp1L1 = POINT_2D_Y(p1L1),
2137  xp2L1 = POINT_2D_X(p2L1), yp2L1 = POINT_2D_Y(p2L1),
2138  xp1L2 = POINT_2D_X(p1L2), yp1L2 = POINT_2D_Y(p1L2),
2139  xp2L2 = POINT_2D_X(p2L2), yp2L2 = POINT_2D_Y(p2L2),
2140  minxL1, minxL2, minyL1, minyL2, maxxL1, maxxL2, maxyL1, maxyL2;
2141 
2142  if(xp1L1 < xp2L1) { minxL1 = xp1L1; maxxL1 = xp2L1; }
2143  else { minxL1 = xp2L1; maxxL1 = xp1L1; }
2144 
2145  if(yp1L1 < yp2L1) { minyL1 = yp1L1; maxyL1 = yp2L1; }
2146  else { minyL1 = yp2L1; maxyL1 = yp1L1; }
2147 
2148  if(xp1L2 < xp2L2) { minxL2 = xp1L2; maxxL2 = xp2L2; }
2149  else { minxL2 = xp2L2; maxxL2 = xp1L2; }
2150 
2151  if(yp1L2 < yp2L2) { minyL2 = yp1L2; maxyL2 = yp2L2; }
2152  else { minyL2 = yp2L2; maxyL2 = yp1L2; }
2153 
2154  //X coordinate criteria
2155  if( minxL1 > maxxL2 || maxxL1 < minxL2)
2156  return NULL;
2157 
2158  //Y coordinate criteria
2159  if( minyL1 > maxyL2 || maxyL1 < minyL2)
2160  return NULL;
2161 
2162 
2163  if( xp1L1 == xp2L1 ) { //Infinite slope for L1
2164  if( xp1L2 == xp2L2 ) { //Infinite slope for L2 also
2165  if( xp1L1 == xp1L2 ) { //Intersection of parallel lines
2166  Intersection<T> *result = new Intersection<T>();
2167  double
2168  min = minyL1 > minyL2 ? minyL1 : minyL2,
2169  max = maxyL1 < maxyL2 ? maxyL1 : maxyL2;
2170  if ( min == max ) { //If intersection occurs just in a limit point
2171  result->x1 = xp1L1; result->y1 = min; result->type = 1;
2172  } else { //If intersection result in a segment, extreme values are given and intersection type is 0
2173  result->x1 = xp1L1; result->y1 = min;
2174  result->x2 = xp1L1; result->y2 = max;
2175  result->type = 0;
2176  }
2177  return result;
2178  }
2179  return NULL;
2180  }
2181 
2182  //If L2 has a non infinite slope:
2183  double //the valid interval for y is between the maximal minimum, and the minimal maximum
2184  min = minyL1 > minyL2 ? minyL1 : minyL2,
2185  max = maxyL1 < maxyL2 ? maxyL1 : maxyL2,
2186  x = xp1L1,
2187  y = ((xp1L1 - xp2L2)*yp1L2 - (xp1L1 - xp1L2)*yp2L2)/(xp1L2 - xp2L2);
2188 
2189  if( y >= min && max >= y ) {
2190  Intersection<T> *result = new Intersection<T>();
2191  result->x1 = x;
2192  result->y1 = y;
2193  result->type = 1;
2194  return result;
2195  } else
2196  return NULL;
2197  } else if( xp1L2 == xp2L2 ) { //Infinite slope for L2, and finite slope for L1
2198 
2199  double //the valid interval for y is between the maximal minimum, and the minimal maximum
2200  min = minyL1 > minyL2 ? minyL1 : minyL2,
2201  max = maxyL1 < maxyL2 ? maxyL1 : maxyL2,
2202  x = xp1L2,
2203  y = ((xp1L2 - xp2L1)*yp1L1 - (xp1L2 - xp1L1)*yp2L1)/(xp1L1 - xp2L1);
2204 
2205  if( y >= min && max >= y ) {
2206  Intersection<T> *result = new Intersection<T>();
2207  result->x1 = x;
2208  result->y1 = y;
2209  result->type = 1;
2210  return result;
2211  } else
2212  return NULL;
2213  }
2214 
2215  //If both slopes are finite
2216  double
2217  a1 = (yp2L1 - yp1L1)/(xp2L1 - xp1L1),
2218  a2 = (yp2L2 - yp1L2)/(xp2L2 - xp1L2),
2219  b1 = yp2L1 - a1*xp2L1,
2220  b2 = yp2L2 - a2*xp2L2;
2221 
2222  //Parallel lines
2223  if(a1 == a2) {
2224 
2225  //If intercepts are different, there is no intersection between the parallel lines
2226  if ( b1 != b2)
2227  return NULL;
2228 
2229  //If there is intersection, calculate
2230  Intersection<T> *result = new Intersection<T>();
2231  double
2232  min = minxL1 > minxL2 ? minxL1 : minxL2,
2233  max = maxxL1 < maxxL2 ? maxxL1 : maxxL2;
2234  if ( min == max ) { //If intersection occurs just in a limit point
2235  result->x1 = min; result->y1 = min*a1 + b1; result->type = 1;
2236  } else { //If intersection result in a segment, extreme values are given and intersection type is 0
2237  result->x1 = min; result->y1 = min * a1 + b1;
2238  result->x2 = max; result->y2 = max * a1 + b1;
2239  result->type = 0;
2240  }
2241  return result;
2242  }
2243 
2244  double
2245  min = minxL1 > minxL2 ? minxL1 : minxL2,
2246  max = maxxL1 < maxxL2 ? maxxL1 : maxxL2,
2247  den = a1 - a2,
2248  x = (b2 - b1) / den,
2249  y = (b2*a1 - b1*a2) / den;
2250  if( x >= min && max >= x ) {
2251  Intersection<T> *result = new Intersection<T>();
2252  result->x1 = x;
2253  result->y1 = y;
2254  result->type = 1;
2255  return result;
2256  }
2257 
2258  return NULL;
2259 }
2260 
2261 
2262 template <typename T>
2263 bool point2D<T>::pointPreciselyInSegmentStrict(double x, double y, point2D<T> *begin, point2D<T> *end) {
2264 
2265  double
2266  x1 = POINT_2D_X(begin),
2267  y1 = POINT_2D_Y(begin),
2268  x2 = POINT_2D_X(end),
2269  y2 = POINT_2D_Y(end),
2270  min, max;
2271 
2272  //Infinite slope
2273  if(x1 == x2) {
2274  if(y1 == y2) //A point
2275  return x == x1 && y == y1 ? 1 : 0;
2276  if(x != x1) //The only possible x = x1
2277  return 0;
2278  //Test y allowed interval
2279  if(y1 > y2) { min = y2; max = y1; }
2280  else { min = y1; max = y2; }
2281  return y >= min && y <= max ? 1 : 0;
2282  }
2283 
2284  //Test x allowed interval
2285  if(x1 > x2) { min = x2; max = x1; }
2286  else { min = x1; max = x2; }
2287  if( x < min || x > max )
2288  return 0;
2289 
2290  //Test y allowed interval
2291  if(y1 > y2) { min = y2; max = y1; }
2292  else { min = y1; max = y2; }
2293  if( y < min || y > max )
2294  return 0;
2295 
2296  //Test if point belongs to the line (no devisions to avoid loss of float precision)
2297  return y*(x2 - x1) == x*(y2 - y1) + x2*y1 - x1*y2 ? 1 : 0;
2298  }
2299 
2300 /*
2301 int there_is_rect_intersection(frect_t rect1, frect_t rect2) {
2302 
2303  //X coordinate criteria
2304  if( RECT_XLEFT(rect1) >= RECT_XRIGHT(rect2) || RECT_XRIGHT(rect1) <= RECT_XLEFT(rect2) )
2305  return 0;
2306 
2307  //Y coordinate criteria
2308  if( RECT_YBOTTOM(rect1) <= RECT_YTOP(rect2) || RECT_YTOP(rect1) >= RECT_YBOTTOM(rect2) )
2309  return 0;
2310 
2311  return 1;
2312 }
2313 
2314  int there_is_rect_intersection(rect_t rect1, rect_t rect2) {
2315 
2316  //X coordinate criteria
2317  if( RECT_XLEFT(rect1) >= RECT_XRIGHT(rect2) || RECT_XRIGHT(rect1) <= RECT_XLEFT(rect2) )
2318  return 0;
2319 
2320  //Y coordinate criteria
2321  if( RECT_YBOTTOM(rect1) <= RECT_YTOP(rect2) || RECT_YTOP(rect1) >= RECT_YBOTTOM(rect2) )
2322  return 0;
2323 
2324  return 1;
2325  }
2326  */
2327 
2328 template <typename T>
2330  double
2331  x0 = points[0].x,
2332  y0 = points[0].y,
2333  x1 = points[1].x,
2334  y1 = points[1].y,
2335  x2 = points[2].x,
2336  y2 = points[2].y,
2337  cross_product = (x1 - x0) * (y2 - y1) - (y1 - y0) * (x2 - x1);
2338 
2339  return (cross_product > 0) ? true : false;
2340 }
2341 
2342 template <typename T>
2344  int n_points = points.size();
2345  polygon2D<T> *inverse = new polygon2D(n_points);
2346  *inverse = *this;
2347  int i, j;
2348  for(i = 0; i < n_points; i++) {
2349  j = n_points - i - 1;
2350  inverse->points[j].x = points[i].x;
2351  inverse->points[j].y = points[i].y;
2352  }
2353  return inverse;
2354 }
2355 
2356 template <typename T>
2357 QSharedPointer<polygon2D<T> > polygon3D<T>::makePolygon2D() {
2358  int i = 0, n = points.size();
2359  QSharedPointer<polygon2D<T> > res(new polygon2D<T>(n));
2360 
2361  for(i=0; i<n; i++) {
2362  res->points[i].x = points[i].x;
2363  res->points[i].y = points[i].y;
2364  }
2365 
2366  res->computeBoundingRectangle();
2367 
2368  return res;
2369 }
2370 
2371 template <typename T>
2372 QSharedPointer< polygon2D<int> > polygon3D<T>::projectPolygon2D(perspective_matrix M) {
2373  int i = 0, n = points.size();
2374  QSharedPointer< polygon2D<int> > res(new polygon2D<int>(n));
2375  double X, Y;
2376 
2377  for(i=0; i<n; i++) {
2378  SceneModel::worldToImgCoords(M, points[i].x, points[i].y, points[i].z, &X, &Y);
2379  res->points[i].x = (int)X;
2380  res->points[i].y = (int)Y;
2381  }
2382 
2383  res->computeBoundingRectangle();
2384 
2385  return res;
2386 }
2387 
2388 template <typename T>
2389 bool polygon2D<T>::pointInPolygon(T x, T y, bool strict) {
2390  double length;
2391  double x2, y2;
2392  double angle;
2393  int i, check, test_ok, nbi, n = points.size();
2394  point2D<T> inter, *begin, *end;
2395 
2396  // First case: is the point outside the bounding box ?
2397  Rectangle<T> bounding_rect;
2398  computeBoundingRectangle(bounding_rect);
2399  if (!bounding_rect.pointInRectangle(x, y))
2400  return false;
2401 
2402  // Or it is on the frontier of the polygon
2403  for (i = 0; i < n; i++) {
2404  begin = &points[i];
2405  end = &points[i < n - 1 ? i + 1 : 0];
2406  if (point2D<T>::pointInSegmentStrict(x, y, begin, end))
2407  return (strict ? 0 : 1);
2408  }
2409 
2410  // compute an acceptable size for the test segment
2411  length = (RECT_WIDTH(&bounding_rect) < RECT_HEIGHT(&bounding_rect) ?
2412  RECT_HEIGHT(&bounding_rect) : RECT_WIDTH(&bounding_rect));
2413 
2414  // And compute the test segment
2415  angle = 0.0;
2416  do {
2417  nbi = 0;
2418  test_ok = 1;
2419  x2 = x + length * cos(angle);
2420  y2 = y + length * sin(angle);
2421  for (i = 0; i < n; i++) {
2422  begin = &points[i];
2423  end = &points[i < n - 1 ? i + 1 : 0];
2424 
2425  if( (check = point2D<T>::isLinesIntersection(x, y, x2, y2,
2426  POINT_2D_X(begin),POINT_2D_Y(begin),
2427  POINT_2D_X(end), POINT_2D_Y(end), &inter)) )
2428  nbi++;
2429 
2430  // If the intersection point is too close from one of the endings
2431  // of the current segment, then slightly change the angle, and do
2432  // it again
2433  if (check > 0) {
2434  if (point2D<T>::distance(begin, &inter) < 0.01 || point2D<T>::distance(end, &inter) < 0.01) {
2435  test_ok = 0;
2436  angle += 0.2;
2437  }
2438  }
2439  }
2440  } while(!test_ok);
2441 
2442  // If the test is ok, then the point is inside the polygon
2443  // if we have an odd number of intersection
2444  if (nbi % 2 == 1)
2445  return true;
2446  else
2447  return false;
2448 }
2449 
2450 template <typename T>
2451 QSharedPointer<polygon2D<int> > polygon2D<T>::projectImagePolygon2D(homography_matrix H) {
2452  int i = 0, n = points.size();
2453  polygon2D<int> *r = new polygon2D<int>(n);
2454  QSharedPointer< polygon2D<int> > res(r);
2455  double X, Y;
2456  for(i=0; i<n; i++) {
2457  SceneModel::homographyToImgCoords(H, points[i].x, points[i].y, &X, &Y);
2458  res->points[i].x = (int)X;
2459  res->points[i].y = (int)Y;
2460  }
2461 
2462  res->computeBoundingRectangle();
2463 
2464  return res;
2465 
2466 }
2467 
2468 template <typename T>
2469 bool point2D<T>::pointInSegmentStrict(T x, T y, point2D<T> *begin, point2D<T> *end) {
2470  point2D<T> point;
2471  if(pointInSegment(x, y, begin, end))
2472  if( ( ( x >= POINT_2D_X(begin) && x <= POINT_2D_X(end) )
2473  || ( x >= POINT_2D_X(end) && x <= POINT_2D_X(begin) ) )
2474  && ( ( y >= POINT_2D_Y(end) && y <= POINT_2D_Y(begin) )
2475  || (y >= POINT_2D_Y(end) && y <= POINT_2D_Y(begin) ) ) )
2476  return true;
2477 
2478  point.x = x;
2479  point.y = y;
2480  // if the distance between (x,y) and segment is very short. We consider that the point
2481  // belonsg to the segment.
2482  //Distance will be just taken to avoid float error
2483  //if(point_segment_distance(&point, begin_p, end_p)< (sqrt(2.0)/2.0))
2484  if(point.pointSegmentDistance(begin, end) < MAX_FLOAT_ERROR)
2485  return true;
2486  return false;
2487 }
2488 
2489 template <typename T>
2491  double res = 0;
2492  double pscal = 0;
2493 
2494  pscal = (POINT_2D_X(end) - POINT_2D_X(begin)) * (x - POINT_2D_X(begin))
2495  + (POINT_2D_Y(end) - POINT_2D_Y(begin)) * (y - POINT_2D_Y(begin));
2496 
2497  if (pscal <= 0)
2498  res = distance(this, begin);
2499  else {
2500  pscal = (POINT_2D_X(begin) - POINT_2D_X(end)) * (x - POINT_2D_X(end))
2501  + (POINT_2D_Y(begin) - POINT_2D_Y(end)) * (y - POINT_2D_Y(end));
2502  if (pscal <= 0)
2503  res = distance(this, end);
2504  else
2505  res = pointLineDistance(begin, end);
2506  }
2507 
2508  return res;
2509 }
2510 
2511 /*template <typename T>
2512 double point2D<T>::distance2D(point2D<T> *pt1, point2D<T> *pt2) {
2513  double dx = POINT_2D_X(pt1) - POINT_2D_X(pt2);
2514  double dy = POINT_2D_Y(pt1) - POINT_2D_Y(pt2);
2515  double squared_dist = dx * dx + dy * dy;
2516 
2517  return sqrt(fabs(squared_dist));
2518 }*/
2519 
2520 template <typename T>
2522  double a = POINT_2D_Y(lpt1) - POINT_2D_Y(lpt2);
2523  double b = POINT_2D_X(lpt2) - POINT_2D_X(lpt1);
2524  double c = - (a * POINT_2D_X(lpt1) + b * POINT_2D_Y(lpt1));
2525  double s = sqrt(a * a + b * b);
2526 
2527  return fabs((a * x + b * y + c) / s);
2528 }
2529 
2530 template <typename T>
2531 bool point2D<T>::pointInSegment(double x, double y, point2D<T> *begin, point2D<T> *end) {
2532  double seg_vect[2], vect[2];
2533  double norm, cp;
2534 
2535  // first tests: is the point equal to one of the endings ?
2536  if (((x == POINT_2D_X(begin)) && (y == POINT_2D_Y(begin))) ||
2537  ((x == POINT_2D_X(end)) && (y == POINT_2D_Y(end))))
2538  return 1;
2539 
2540  seg_vect[0] = POINT_2D_X(end) - POINT_2D_X(begin);
2541  seg_vect[1] = POINT_2D_Y(end) - POINT_2D_Y(begin);
2542  norm = sqrt((seg_vect[0] * seg_vect[0]) + (seg_vect[1] * seg_vect[1]));
2543  seg_vect[0] = seg_vect[0] / norm;
2544  seg_vect[1] = seg_vect[1] / norm;
2545 
2546  vect[0] = x - POINT_2D_X(begin);
2547  vect[1] = y - POINT_2D_Y(begin);
2548  norm = sqrt((vect[0] * vect[0]) + (vect[1] * vect[1]));
2549  vect[0] = vect[0] / norm;
2550  vect[1] = vect[1] / norm;
2551 
2552  cp = (vect[0] * seg_vect[1]) - (vect[1] * seg_vect[0]);
2553  if (fabs(cp) > 0.01)
2554  return false;
2555 
2556  norm = 100.0;
2557  if (fabs(seg_vect[0]) >= fabs(seg_vect[1]) && fabs(seg_vect[0]) > 0.01)
2558  norm = vect[0] / seg_vect[0];
2559  if (fabs(seg_vect[1]) >= fabs(seg_vect[0]) && fabs(seg_vect[1]) > 0.01)
2560  norm = vect[1] / seg_vect[1];
2561  if ((norm >= 0.0) && (norm <= 1.0))
2562  return true;
2563  return false;
2564 }
2565 
2566 // The algorithm is described on Robert Sedgewick book, it's
2567 // Algorithms in C++. Chap 24, Elementary Geometric Methods
2568 // pp346--357
2569 // If both endpoints of each line are on different "sides"
2570 // (have different counterclockwise values) of the other,
2571 // then the lines must intersect
2572 template <typename T>
2573 bool point2D<T>::isLinesIntersection(double x1, double y1, double x2, double y2,
2574  double x3, double y3, double x4, double y4,
2575  point2D<T> *pIntersection) {
2576  // Intersection
2577  if ( isCCW(x1,y1,x2,y2,x3,y3) * isCCW(x1,y1,x2,y2,x4,y4) <= 0
2578  && isCCW(x3,y3,x4,y4,x1,y1) * isCCW(x3,y3,x4,y4,x2,y2) <= 0 ) {
2579  // Process intersection point, if exists
2580  if (processIntersectionLines(x1, y1, x2, y2, x3, y3, x4, y4, pIntersection))
2581  return true;
2582  else
2583  return false;
2584  }
2585  return false;
2586 }
2587 
2588 
2589 template <typename T>
2590 bool point2D<T>::processIntersectionLines(double x1, double y1, double x2, double y2,
2591  double x3, double y3, double x4, double y4,
2592  point2D<T> *pIntersection) {
2593  if(pIntersection == NULL) {
2594  std::cout << "point2D: Error: processIntersectionLines - intersection is NULL." << std::endl;
2595  return false;
2596  }
2597 
2598  // Same points
2599  if(x1==x3 && y1==y3) {
2600  POINT_2D_X(pIntersection) = x1;
2601  POINT_2D_Y(pIntersection) = y1;
2602  return true;
2603  }
2604 
2605  if(x1==x4 && y1==y4) {
2606  POINT_2D_X(pIntersection) = x1;
2607  POINT_2D_Y(pIntersection) = y1;
2608  return true;
2609  }
2610 
2611  if(x2==x3 && y2==y3) {
2612  POINT_2D_X(pIntersection) = x2;
2613  POINT_2D_Y(pIntersection) = y2;
2614  return true;
2615  }
2616 
2617  if(x2==x4 && y2==y4) {
2618  POINT_2D_X(pIntersection) = x2;
2619  POINT_2D_Y(pIntersection) = y2;
2620  return true;
2621  }
2622 
2623  // All the points have the same y
2624  if(y1==y2 && y2==y3 && y3==y4) {
2625  double max1 = std::max(x1,x2);
2626  double min1 = std::min(x1,x2);
2627  double max2 = std::max(x3,x4);
2628  double min2 = std::min(x3,x4);
2629 
2630  // no intersection
2631  if(max1 < min2 || max2 < min1)
2632  return false;
2633 
2634  // partial or total overlapping
2635  if(max1 > min2 || max2 > min1) {
2636  // Partial overlapping
2637  if(max2 > max1 && min2 > min1) {
2638  // The segment [min2;max1] is the overlapped part
2639  POINT_2D_X(pIntersection) = (min2 + max1)/2.0;
2640  POINT_2D_Y(pIntersection) = y3;
2641  return true;
2642  }
2643 
2644  if(max1 > max2 && min1 > min2) {
2645  // The segment [min1;max2] is the overlapped part
2646  POINT_2D_X(pIntersection) = (min1 + max2)/2.0;
2647  POINT_2D_Y(pIntersection) = y3;
2648  return true;
2649  }
2650 
2651  // Total overlapping
2652  if (min2 > min1 && max2 < max1) {
2653  // The segment [min2;max2] is the overlapped part
2654  POINT_2D_X(pIntersection) = (min2 + max2)/2.0;
2655  POINT_2D_Y(pIntersection) = y3;
2656  return true;
2657  }
2658 
2659  if (min2 < min1 && max2 > max1) {
2660  // The segment [min1;max1] is the overlapped part
2661  POINT_2D_X(pIntersection) = (min1 + max1)/2.0;
2662  POINT_2D_Y(pIntersection) = y3;
2663  return true;
2664  }
2665  }
2666  }
2667 
2668  // All the points have the same x
2669  if(x1==x2 && x2==x3 && x3==x4) {
2670  double max1 = std::max(y1,y2);
2671  double min1 = std::min(y1,y2);
2672  double max2 = std::max(y3,y4);
2673  double min2 = std::min(y3,y4);
2674 
2675  // no intersection
2676  if (max1 < min2 || max2 < min1)
2677  return false;
2678 
2679  // partial or total overlapping
2680  if(max1 > min2 || max2 > min1) {
2681  // Partial overlapping
2682  if(max2 > max1 && min2 > min1) {
2683  // The segment [min2;max1] is the overlapped part
2684  POINT_2D_Y(pIntersection) = (min2 + max1)/2.0;
2685  POINT_2D_X(pIntersection) = x3;
2686  return true;
2687  }
2688 
2689  if(max1 > max2 && min1 > min2) {
2690  // The segment [min1;max2] is the overlapped part
2691  POINT_2D_Y(pIntersection) = (min1 + max2)/2.0;
2692  POINT_2D_X(pIntersection) = x3;
2693  return true;
2694  }
2695 
2696  // Total overlapping
2697  if(min2 > min1 && max2 < max1) {
2698  // The segment [min2;max2] is the overlapped part
2699  POINT_2D_Y(pIntersection) = (min2 + max2)/2.0;
2700  POINT_2D_X(pIntersection) = x3;
2701  return true;
2702  }
2703 
2704  if(min2 < min1 && max2 > max1) {
2705  // The segment [min1;max1] is the overlapped part
2706  POINT_2D_Y(pIntersection) = (min1 + max1)/2.0;
2707  POINT_2D_X(pIntersection) = x3;
2708  return true;
2709  }
2710  }
2711  }
2712 
2713  // General case
2714  // Init
2715  POINT_2D_X(pIntersection) = 0;
2716  POINT_2D_Y(pIntersection) = 0;
2717 
2718  // Coordinates of the first segment
2719  double x12 = x2 - x1;
2720  double y12 = y2 - y1;
2721 
2722  // Coordinates of the second segment
2723  double x34 = x4 - x3;
2724  double y34 = y4 - y3;
2725 
2726  double x31 = x1 - x3;
2727  double y31 = y1 - y3;
2728 
2729  // Process cross-product
2730  double alpha = x31 * y34 - y31 * x34;
2731  double delta = y12 * x34 - x12 * y34;
2732 
2733  // Test
2734  if (fabs(delta) < 1e-6) {
2735  std::cout << "Error: point2D: processIntersectionsLines - delta is NULL" << std::endl;
2736  return false;
2737  }
2738 
2739  if(delta != 0) {
2740  alpha /= delta;
2741  POINT_2D_X(pIntersection) = x1 + alpha*x12;
2742  POINT_2D_Y(pIntersection) = y1 + alpha*y12;
2743  }
2744 
2745  return true;
2746 }
2747 
2748 // The algorithm is described on Robert Sedgewick book, it's
2749 // Algorithms in C++. Chap 24, Elementary Geometric Methods
2750 // pp346--357
2751 // This function determine if we turn counterclockwise in
2752 // travelling from the first to the second to the third point
2753 // It's based on the slope comparisons
2754 template <typename T>
2755 bool point2D<T>::isCCWPts(point2D<T> *pPt0, point2D<T> *pPt1, point2D<T> *pPt2) {
2756  return isCCW( POINT_2D_X(pPt0), POINT_2D_Y(pPt0),
2757  POINT_2D_X(pPt1), POINT_2D_Y(pPt1),
2758  POINT_2D_X(pPt2), POINT_2D_Y(pPt2) );
2759 }
2760 
2761 template <typename T>
2762 bool point2D<T>::isCCW(double x0, double y0, double x1, double y1, double x2, double y2) {
2763  double dx1 = x1 - x0;
2764  double dy1 = y1 - y0;
2765  double dx2 = x2 - x0;
2766  double dy2 = y2 - y0;
2767 
2768  if ((dx1*dy2) > (dy1*dx2))
2769  return 1;
2770  if ((dx1*dy2) < (dy1*dx2))
2771  return -1;
2772  if ((dx1*dx2) < 0 || (dy1*dy2) < 0)
2773  return -1;
2774  if ( (dx1*dx1+dy1*dy1) < (dx2*dx2+dy2*dy2))
2775  return 1;
2776 
2777  return 0;
2778 }
2779 
2780 template <typename T>
2782 
2783 template <typename T>
2785  memcpy(this, &p, sizeof(polygon3D<T>));
2786  points = p.points;
2787  return *this;
2788 }
2789 
2790 template <typename T>
2791 polygon3D<T>::polygon3D(int reserve) {
2792  points.reserve(reserve);
2793 }
2794 
2795 template <typename T>
2797 
2798 template <typename T>
2800  initRectangle(1,1,1,1);
2801 }
2802 
2803 template <typename T>
2804 Rectangle<T>::Rectangle(T x, T y, T w, T h) {
2805  initRectangle(x, y, w, h);
2806 }
2807 
2808 template <typename T>
2810 
2811 template <typename T>
2812 void Rectangle<T>::initRectangle(T x, T y, T w, T h) {
2813  xleft = x;
2814  xright = (w > 0 ? x + w - 1 : x);
2815  ytop = y;
2816  ybottom = (h > 0 ? y + h - 1 : y);
2817  width = w;
2818  height = h;
2819 }
2820 
2821 template <typename T>
2823  xleft = xright = ytop = ybottom = width = height = r;
2824 }
2825 
2826 template <typename T>
2828  Rectangle<T> *copy = new Rectangle<T>();
2829  memcpy(copy, this, sizeof(Rectangle<T>));
2830  return copy;
2831 }
2832 
2833 template <typename T>
2835 
2836  if(r1 == NULL && r2 == NULL)
2837  return NULL;
2838  if(r1 == NULL)
2839  return r2->copyRectangle();
2840  if(r2 == NULL)
2841  return r1->copyRectangle();
2842 
2843  Rectangle<T> *merge = new Rectangle<T>();
2844 
2845  merge->xleft = std::min(r1->xleft, r2->xleft);
2846  merge->xright = std::max(r2->xright, r2->xright);
2847  merge->ytop = std::min(r1->ytop, r2->ytop);
2848  merge->ybottom = std::max(r1->ybottom, r2->ybottom);
2849  merge->width = merge->xright - merge->xleft + 1;
2850  merge->height = merge->ybottom - merge->ytop + 1;
2851 
2852  return merge;
2853 }
2854 
2855 
2856 template <typename T>
2858 
2859  res.xleft = std::min(r1.xleft, r2.xleft);
2860  res.xright = std::max(r2.xright, r2.xright);
2861  res.ytop = std::min(r1.ytop, r2.ytop);
2862  res.ybottom = std::max(r1.ybottom, r2.ybottom);
2863  res.width = res.xright - res.xleft + 1;
2864  res.height = res.ybottom - res.ytop + 1;
2865 
2866 }
2867 
2868 
2869 template <typename T>
2871  return mergeRectangles(this, r);
2872 }
2873 
2874 template <typename T>
2876  this->xleft = std::min(this->xleft, r.xleft);
2877  this->xright = std::max(this->xright, r.xright);
2878  this->ytop = std::min(this->ytop, r.ytop);
2879  this->ybottom = std::max(this->ybottom, r.ybottom);
2880  this->width = this->xright - this->xleft + 1;
2881  this->height = this->ybottom - this->ytop + 1;
2882 }
2883 
2884 
2885 template <typename T>
2887  if(r == NULL)
2888  return;
2889 
2890  xleft = std::min(xleft, r->xleft);
2891  xright = std::max(xright, r->xright);
2892  ytop = std::min(ytop, r->ytop);
2893  ybottom = std::max(ybottom, r->ybottom);
2894  width = xright - xleft + 1;
2895  height = ybottom - ytop + 1;
2896 }
2897 
2898 template <typename T>
2900  xleft = std::min(xleft, r.xleft);
2901  xright = std::max(xright, r.xright);
2902  ytop = std::min(ytop, r.ytop);
2903  ybottom = std::max(ybottom, r.ybottom);
2904  width = xright - xleft + 1;
2905  height = ybottom - ytop + 1;
2906 }
2907 
2908 
2909 
2910 template <typename T>
2912  if(r1->xright < r2->xleft)
2913  return r2->xleft - r1->xright;
2914  else if(r2->xright < r1->xleft)
2915  return r1->xleft - r2->xright;
2916  else
2917  return 0;
2918 }
2919 
2920 template <typename T>
2922  if(r1->ybottom < r2->ytop)
2923  return r2->ytop - r1->ybottom;
2924  else if(r2->ybottom < r1->ytop)
2925  return r1->ytop - r2->ybottom;
2926  else
2927  return 0;
2928 }
2929 
2930 template <typename T>
2932  Rectangle<T> *inter;
2933 
2934  if((inter = rectanglesIntersection(r1, r2)) != NULL) {
2935  delete inter;
2936  return 0.0;
2937  }
2938 
2939  double dy = 0.0, dx = 0.0;
2940 
2941 
2942  if(r1->xright <= r2->xleft) {
2943  dx = r2->xleft - r1->xright;
2944  } else if(r2->xright <= r1->xleft) {
2945  dx = r1->xleft - r2->xright;
2946  }
2947 
2948  if(r1->ybottom <= r2->ytop) {
2949  dy = r2->ytop - r1->ybottom;
2950  } else if(r2->ybottom <= r1->ytop) {
2951  dy = r1->ytop - r2->ybottom;
2952  }
2953 
2954  if(dy == 0.0)
2955  return dx;
2956  else if(dx == 0.0)
2957  return dy;
2958 
2959  return sqrt(dx*dx + dy*dy);
2960 
2961 }
2962 
2963 template <typename T>
2965  return rectangleDistance(this, r);
2966 }
2967 
2968 template <typename T>
2970  if( r1 == NULL || r2 == NULL )
2971  return 0.0;
2972 
2973  double
2974  X1 = r1->xleft + r1->width / 2.0,
2975  X2 = r2->xleft + r2->width / 2.0,
2976  Y1 = r1->ytop + r1->height / 2.0,
2977  Y2 = r2->ytop + r2->height / 2.0;
2978 
2979  if(X1 == X2)
2980  return fabs(Y1 - Y2);
2981  if(Y1 == Y2)
2982  return fabs(X1 - X2);
2983 
2984  double dX = X1 - X2, dY = Y1 - Y2;
2985 
2986  return sqrt(dX*dX + dY*dY);
2987 }
2988 
2989 template <typename T>
2991  return rectangleGravityDistance(this, r);
2992 }
2993 
2994 template <typename T>
2996  if(r1 == NULL || r2 == NULL)
2997  return NULL;
2998 
2999  int
3000  x_left = std::max(r1->xleft, r2->xleft),
3001  x_right = std::min(r1->xright, r2->xright),
3002  y_top = std::max(r1->ytop, r2->ytop),
3003  y_bottom = std::min(r1->ybottom, r2->ybottom);
3004 
3005  if(x_left < x_right && y_top < y_bottom)
3006  return new Rectangle<T>(x_left, y_top, x_right - x_left + 1, y_bottom - y_top + 1);
3007  else
3008  return NULL;
3009 }
3010 
3011 template <typename T>
3013  if(r1 == NULL || r2 == NULL || inter == NULL)
3014  return false;
3015 
3016  int
3017  x_left = std::max(r1->xleft, r2->xleft),
3018  x_right = std::min(r1->xright, r2->xright),
3019  y_top = std::max(r1->ytop, r2->ytop),
3020  y_bottom = std::min(r1->ybottom, r2->ybottom);
3021 
3022  if(x_left < x_right && y_top < y_bottom) {
3023  inter->initRectangle(x_left, y_top, x_right - x_left + 1, y_bottom - y_top + 1);
3024  return true;
3025  }
3026 
3027  return false;
3028 }
3029 
3030 template <typename T>
3032  int
3033  x_left = std::max(r1.xleft, r2.xleft),
3034  x_right = std::min(r1.xright, r2.xright),
3035  y_top = std::max(r1.ytop, r2.ytop),
3036  y_bottom = std::min(r1.ybottom, r2.ybottom);
3037 
3038  if(x_left < x_right && y_top < y_bottom) {
3039  inter.initRectangle(x_left, y_top, x_right - x_left + 1, y_bottom - y_top + 1);
3040  return true;
3041  }
3042 
3043  return false;
3044 }
3045 
3046 
3047 template <typename T>
3049  return rectanglesIntersection(this, r);
3050 }
3051 
3052 template <typename T>
3054  if(r1 == NULL && r2 == NULL)
3055  return NULL;
3056  if(r1 == NULL)
3057  return r2->copyRectangle();
3058  if(r2 == NULL)
3059  return r1->copyRectangle();
3060  int
3061  x_left = std::min(r1->xleft, r2->xleft),
3062  x_right = std::max(r1->xright, r2->xright),
3063  y_top = std::min(r1->ytop, r2->ytop),
3064  y_bottom = std::max(r1->ybottom, r2->ybottom);
3065 
3066  return new Rectangle<T>(x_left, y_top, x_right - x_left + 1, y_bottom - y_top + 1);
3067 
3068 }
3069 
3070 
3071 template <typename T>
3073  return rectanglesUnion(this, r);
3074 }
3075 
3076 template <typename T>
3078 
3079  if(r1 == NULL || r2 == NULL)
3080  return 0.0;
3081 
3082  Rectangle<T> *inter = rectanglesIntersection(r1, r2);
3083  if(inter == NULL)
3084  return 0.0;
3085 
3086  double
3087  a1 = r1->width*r1->height,
3088  a2 = r2->width*r2->height,
3089  ai = inter->width*inter->height, ratio;
3090 
3091  if(a2 > a1)
3092  ratio = (a2 - ai)/a2;
3093  else
3094  ratio = (a1 - ai)/a1;
3095 
3096  delete inter;
3097 
3098  return ratio;
3099 }
3100 
3101 
3102 template <typename T>
3104  return rectangleIntersectRatioStrict(this, r);
3105 }
3106 
3107 template <typename T>
3109  if(r1 == NULL || r2 == NULL)
3110  return 0.0;
3111 
3112  Rectangle<T> *inter = rectanglesIntersection(r1, r2);
3113  if(inter == NULL)
3114  return 0.0;
3115 
3116  double a1 = r1->width*r1->height, r;
3117  r = inter->width * inter->height / a1;
3118 
3119  delete inter;
3120 
3121  return r;
3122 }
3123 
3124 template <typename T>
3126  return rectangleIntersectRatio(this, r);
3127 }
3128 
3129 
3130 template <typename T>
3132  return r1->xleft >= r2->xleft && r1->xright >= r2->xright
3133  && r1->ytop >= r2->ytop && r1->ybottom <= r2->ybottom;
3134 }
3135 
3136 template <typename T>
3138  return rectangleInRectangle(this, r);
3139 }
3140 
3141 template <typename T>
3143  if(r1 == NULL || r2 == NULL)
3144  return 0.0;
3145 
3146  Rectangle<T> *inter = rectanglesIntersection(r1, r2);
3147  if(inter == NULL)
3148  return 0.0;
3149 
3150  double a = inter->width*inter->height;
3151 
3152  delete inter;
3153 
3154  return a;
3155 }
3156 
3157 template <typename T>
3159  return rectangleIntersectionArea(this, r);
3160 }
3161 
3162 template <typename T>
3163 double Rectangle<T>::rectangleNIntersectionArea(const std::vector<Rectangle<T> *>& rectangles) {
3164 
3165  if(rectangles.empty())
3166  return 0.0;
3167 
3168  typename std::vector<Rectangle<T> *>::iterator r_iter = rectangles.begin(),
3169  r_end = rectangles.end();
3170  double
3171  xLeft = (*r_iter)->xleft,
3172  xRight = (*r_iter)->xright,
3173  yTop = (*r_iter)->ytop,
3174  yBottom = (*r_iter)->ybottom;
3175  r_iter++;
3176 
3177  for (; r_iter != r_end; r_iter++) {
3178  xLeft = std::max(xLeft, (*r_iter)->xleft);
3179  xRight = std::min(xRight, (*r_iter)->xright);
3180  yTop = std::max(yTop, (*r_iter)->ytop);
3181  yBottom = std::min(yBottom, (*r_iter)->ybottom);
3182  }
3183 
3184  if( xLeft <= xRight && yTop <= yBottom )
3185  return (xRight - xLeft + 1)*(yBottom - yTop + 1);
3186 
3187  return 0.0;
3188 
3189 }
3190 
3191 
3192 template <typename T>
3193 double Rectangle<T>::rectangleArea() {
3194  return width*height;
3195 }
3196 
3197 template <typename T>
3199 
3200  double x, y, X1, Y1, X2, Y2;
3201 
3202  //BOTTOM LEFT TEST
3203  X1 = xleft; Y1 = ybottom;
3204  SceneModel::imgToWorldCoordsGivenHeight(SM_CALIB_MATRIX(smodel), X1, Y1, 0.0, &x, &y);
3205  SceneModel::worldToImgCoords(SM_CALIB_MATRIX(smodel), x, y, smodel->m_OneMeterRepresentation, &X2, &Y2);
3206  if(Y2 <= Y1) { //Cases 0-1-2
3207  if(X2 >= X1) //If left point goes to right, everyone goes --> CASE 2: TOP-RIGHT
3208  return 2;
3209  //Cases 0-1
3210  //BOTTOM RIGHT TEST
3211  X1 = xright;
3212  SceneModel::imgToWorldCoordsGivenHeight(SM_CALIB_MATRIX(smodel), X1, Y1, 0.0, &x, &y);
3213  SceneModel::worldToImgCoords(SM_CALIB_MATRIX(smodel), x, y, smodel->m_OneMeterRepresentation, &X2, &Y2);
3214  if(X2 <= X1) //If right point also goes to left, everyone goes --> CASE 0: TOP-LEFT
3215  return 0;
3216  //CASE 1: TOP-CENTER
3217  return 1;
3218  }
3219 
3220  //TOP LEFT TEST
3221  Y1 = ytop;
3222  SceneModel::imgToWorldCoordsGivenHeight(SM_CALIB_MATRIX(smodel), X1, Y1, 0.0, &x, &y);
3223  SceneModel::worldToImgCoords(SM_CALIB_MATRIX(smodel), x, y, smodel->m_OneMeterRepresentation, &X2, &Y2);
3224  if(Y2 <= Y1) { //Cases 3-4-5
3225  if(X2 >= X1) //If left point goes to right, everyone goes --> CASE 5: MIDDLE-RIGHT
3226  return 5;
3227  //Cases 3-4
3228  //TOP RIGHT TEST
3229  X1 = xright;
3230  SceneModel::imgToWorldCoordsGivenHeight(SM_CALIB_MATRIX(smodel), X1, Y1, 0.0, &x, &y);
3231  SceneModel::worldToImgCoords(SM_CALIB_MATRIX(smodel), x, y, smodel->m_OneMeterRepresentation, &X2, &Y2);
3232  if(X2 <= X1) //If right point also goes to left, everyone goes --> CASE 3: MIDDLE-LEFT
3233  return 3;
3234  //CASE 4: MIDDLE-CENTER
3235  return 4;
3236  }
3237 
3238  //Cases 6-7-8
3239  if(X2 >= X1) //If left point goes to right, everyone goes --> CASE 8: BOTTOM-RIGHT
3240  return 8;
3241  //Cases 7-8
3242  //TOP RIGHT TEST
3243  X1 = xright;
3244  SceneModel::imgToWorldCoordsGivenHeight(SM_CALIB_MATRIX(smodel), X1, Y1, 0.0, &x, &y);
3245  SceneModel::worldToImgCoords(SM_CALIB_MATRIX(smodel), x, y, smodel->m_OneMeterRepresentation, &X2, &Y2);
3246  if(X2 <= X1) //If right point also goes to left, everyone goes --> CASE 6: BOTTOM-LEFT
3247  return 6;
3248  //CASE 7: BOTTOM-CENTER
3249  return 7;
3250 }
3251 
3252 template <typename T>
3254  double x2d = 0.0; //TODO: SM_CAMERA_X2D_FOC_POINT(smodel);
3255  double y2d = 0.0; //TODO: SM_CAMERA_Y2D_FOC_POINT(smodel);
3256  int LeftToRight/*0:Left, 1:Middle, 2:Right*/, FrontToBack/*0:Front, 1:Center, 2:Back*/;
3257 
3258  if(xright < x2d)
3259  LeftToRight = 0;
3260  else if(xleft > x2d)
3261  LeftToRight = 2;
3262  else
3263  LeftToRight = 1;
3264 
3265  if(ybottom < y2d)
3266  FrontToBack = 0;
3267  else if(ytop > y2d)
3268  FrontToBack = 2;
3269  else
3270  FrontToBack = 1;
3271 
3272  return LeftToRight + 3*FrontToBack;
3273 }
3274 
3275 template <typename T>
3276 void Rectangle<T>::setEstimated3DPosition(SceneModel *smodel, point3D<double>& p, int position) {
3277  double x, y;
3278  if(position < 3) //from a blob in the upper positions
3279  SceneModel::imgToWorldCoordsGivenHeight(SM_CALIB_MATRIX(smodel), (xleft + xright) / 2.0, ybottom, 0, &x, &y);
3280  else if(position < 6) //from a blob in the center positions
3281  SceneModel::imgToWorldCoordsGivenHeight(SM_CALIB_MATRIX(smodel), (xleft + xright) / 2.0, (ybottom + ytop) / 2.0, 0, &x, &y);
3282  else //from a blob in the bottom positions
3283  SceneModel::imgToWorldCoordsGivenHeight(SM_CALIB_MATRIX(smodel), (xleft + xright) / 2.0, ytop / 2.0, 0, &x, &y);
3284 
3285  p.x = x;
3286  p.y = y;
3287  p.z = 0.0;
3288 }
3289 
3290 
3291 
3292 template <typename T>
3294  double x, y;
3295  SceneModel::imgToWorldCoordsGivenHeight(SM_CALIB_MATRIX(smodel), (xleft + xright) / 2.0, ybottom, 0.0, &x, &y);
3296 
3297  p.x = x;
3298  p.y = y;
3299  p.z = 0.0;
3300 }
3301 
3302 template <typename T>
3304  if( RECT_YBOTTOM(r1) <= RECT_YBOTTOM(r2) && RECT_YTOP(r1) >= RECT_YTOP(r2)
3305  && RECT_XRIGHT(r1) <= RECT_XRIGHT(r2) && RECT_XLEFT(r1) >= RECT_XLEFT(r2) )
3306  return true;
3307  return false;
3308 }
3309 
3310 template <typename T>
3312  if( RECT_YBOTTOM(&r) <= RECT_YBOTTOM(this) && RECT_YTOP(&r) >= RECT_YTOP(this)
3313  && RECT_XRIGHT(&r) <= RECT_XRIGHT(this) && RECT_XLEFT(&r) >= RECT_XLEFT(this) )
3314  return true;
3315  return false;
3316 }
3317 
3318 
3319 template <typename T>
3321  Rectangle<T> intersection;
3322 
3323  if(!rectanglesIntersection(r1, r2, &intersection))
3324  return 0;
3325  return intersection.rectangleArea();
3326 }
3327 
3328 template <typename T>
3330  Rectangle<T> intersection;
3331 
3332  if(!rectanglesIntersection(r1, r2, intersection))
3333  return 0;
3334  return intersection.rectangleArea();
3335 }
3336 
3337 
3338 template <typename T>
3339 bool Rectangle<T>::pointInRectangle(T p_x, T p_y) {
3340  return xleft <= p_x && p_x <= xright && ytop <= p_y && p_y <= ybottom;
3341 }
3342 
3343 
3344 template <typename T>
3346 
3347  //X coordinate criteria
3348  if( RECT_XLEFT(r1) >= RECT_XRIGHT(r2) || RECT_XRIGHT(r1) <= RECT_XLEFT(r2) )
3349  return false;
3350 
3351  //Y coordinate criteria
3352  if( RECT_YBOTTOM(r1) <= RECT_YTOP(r2) || RECT_YTOP(r1) >= RECT_YBOTTOM(r2) )
3353  return false;
3354 
3355  return true;
3356 }
3357 
3358 template <typename T>
3360 
3361  //X coordinate criteria
3362  if( RECT_XLEFT(this) >= RECT_XRIGHT(&r) || RECT_XRIGHT(this) <= RECT_XLEFT(&r) )
3363  return false;
3364 
3365  //Y coordinate criteria
3366  if( RECT_YBOTTOM(this) <= RECT_YTOP(&r) || RECT_YTOP(this) >= RECT_YBOTTOM(&r) )
3367  return false;
3368 
3369  return true;
3370 }
3371 
3372 //Subtracts rectangles to this rectangle and adds resulting rectangles in results deque.
3373 // Generalization reduces to try to generate a maximum of four rectangles if bounds correspond to each case.
3374 //r:
3375 // -----------------------------
3376 // | A |
3377 // | |
3378 // | - - - - ----------- - - - |
3379 // | | | |
3380 // | B | s | C |
3381 // | | | |
3382 // | - - - ----------- - - - |
3383 // | |
3384 // | D |
3385 // -----------------------------
3386 
3387 
3388 template <typename T>
3389 void Rectangle<T>::substractRectangles(std::vector< Rectangle<T> > &toSubstract, std::deque< Rectangle<T> > &results) {
3390 
3391  typedef typename std::deque< Rectangle<T> >::iterator rec_deq_iter_type;
3392 
3393  std::deque< Rectangle<T> > local_results;
3394 
3395  local_results.push_back(*this);
3396 
3397  int size = toSubstract.size();
3398  if(size == 0)
3399  return;
3400 
3401  rec_deq_iter_type it;
3402  Rectangle<T> r;
3403  int i, j, yt, yb;
3404 
3405  //Substract each rectangle to the set of remaining rectangles
3406  for(i=0; i<size; i++) {
3407  Rectangle<T> &s = toSubstract[i];
3408  for(it = local_results.begin(); it != local_results.end(); ) {
3409  r = *it;
3410  //If it doesn't intersect, the rectangle remains on the solution
3411  if(!r.thereIsIntersection(s)) {
3412  it++;
3413  continue;
3414  }
3415 
3416  //Rectagle A
3417  if(r.ytop < s.ytop)
3418  local_results.push_back(Rectangle<T>(r.xleft, r.ytop, r.width, s.ytop - r.ytop + 1));
3419 
3420  yt = std::max(r.ytop, s.ytop);
3421  yb = std::min(r.ybottom, s.ybottom);
3422  //Rectangle B
3423  if(r.xleft < s.xleft)
3424  local_results.push_back(Rectangle<T>(r.xleft, yt, s.xleft - r.xleft + 1, yb - yt + 1));
3425 
3426  //Rectangle C
3427  if(s.xright < r.xright)
3428  local_results.push_back(Rectangle<T>(s.xright, yt, r.xright - s.xright + 1, yb - yt + 1));
3429 
3430  //Rectagle D
3431  if(s.ybottom < r.ybottom)
3432  local_results.push_back(Rectangle<T>(r.xleft, s.ybottom, r.width, r.ybottom - s.ybottom + 1));
3433 
3434  //If there was an intersection, the original changes for sure.
3435  it = local_results.erase(it);
3436  }
3437 
3438  //If it is already empty, nothing more to reduce
3439  if(local_results.empty())
3440  return;
3441  }
3442 
3443  if(local_results.empty())
3444  return;
3445 
3446  rec_deq_iter_type lit, lend = local_results.end();
3447  for(lit = local_results.begin(); lit != lend; lit++)
3448  results.push_back(*lit);
3449 
3450 }
3451 
3452 template <typename T>
3454  if(r.xleft != this->xleft)
3455  return false;
3456  if(r.xright != this->xright)
3457  return false;
3458  if(r.ytop != this->ytop)
3459  return false;
3460  if(r.ybottom != this->ybottom)
3461  return false;
3462  return true;
3463 }
3464 
3465 
3466 
3467 #endif /* _GEOMETRIC_H_*/
Definition: geometric.h:103
Definition: geometric.h:114
Definition: geometric.h:20
Definition: geometric.h:36
Definition: calibration.h:51
Definition: calibration.h:26
Definition: calibration.h:23
Definition: gtstructures.h:32
Definition: geometric.h:23
Definition: geometric.h:256
Definition: geometric.h:224