1 #pragma once
2 
3 #ifndef T_GEOMETRY_INCLUDED
4 #define T_GEOMETRY_INCLUDED
5 
6 #include "tutil.h"
7 #include <cmath>
8 
9 #undef DVAPI
10 #undef DVVAR
11 #ifdef TGEOMETRY_EXPORTS
12 #define DVAPI DV_EXPORT_API
13 #define DVVAR DV_EXPORT_VAR
14 #else
15 #define DVAPI DV_IMPORT_API
16 #define DVVAR DV_IMPORT_VAR
17 #endif
18 
19 //=============================================================================
20 /*
21 * This is an example of how to use the TPointT, the TRectT and the TAffine
22 * classes.
23 */
24 /*!  The template class TPointT defines the x- and y-coordinates of a point.
25 */
26 template <class T>
27 class TPointT {
28 public:
29   T x, y;
30 
TPointT()31   TPointT() : x(0), y(0){};
TPointT(T _x,T _y)32   TPointT(T _x, T _y) : x(_x), y(_y){};
TPointT(const TPointT & point)33   TPointT(const TPointT &point) : x(point.x), y(point.y){};
34   inline TPointT &operator=(const TPointT &a) {
35     x = a.x;
36     y = a.y;
37     return *this;
38   };
39 
40   inline TPointT &operator+=(const TPointT &a) {
41     x += a.x;
42     y += a.y;
43     return *this;
44   };
45   inline TPointT &operator-=(const TPointT &a) {
46     x -= a.x;
47     y -= a.y;
48     return *this;
49   };
50   inline TPointT operator+(const TPointT &a) const {
51     return TPointT(x + a.x, y + a.y);
52   };
53   inline TPointT operator-(const TPointT &a) const {
54     return TPointT(x - a.x, y - a.y);
55   };
56   inline TPointT operator-() const { return TPointT(-x, -y); };
57 
58   bool operator!=(const TPointT &p) const { return x != p.x || y != p.y; }
59 };
60 
61 /*! \relates TPointT
62 * Rotate a point 90 degrees (counterclockwise).
63 \param p a point.
64 \return the rotated point
65 \sa rotate270
66 */
67 template <class T>
rotate90(const TPointT<T> & p)68 inline TPointT<T> rotate90(const TPointT<T> &p)  // 90 counterclockwise
69 {
70   return TPointT<T>(-p.y, p.x);
71 }
72 /*! \relates TPointT
73 * Rotate a point 270 degrees (clockwise).
74 \param p a point.
75 \return the rotated point
76 \sa rotate90
77 */
78 template <class T>
rotate270(const TPointT<T> & p)79 inline TPointT<T> rotate270(const TPointT<T> &p)  // 90 clockwise
80 {
81   return TPointT<T>(p.y, -p.x);
82 }
83 
84 /*!
85 \relates TPointT
86 */
87 template <class T>  // Scalar(dot) Product
88 inline T operator*(const TPointT<T> &a, const TPointT<T> &b) {
89   return a.x * b.x + a.y * b.y;
90 }
91 
92 //-----------------------------------------------------------------------------
93 
94 template <class T>
95 inline std::ostream &operator<<(std::ostream &out, const TPointT<T> &p) {
96   return out << "(" << p.x << ", " << p.y << ")";
97 }
98 
99 //-----------------------------------------------------------------------------
100 
101 typedef TPointT<int> TPoint, TPointI;
102 typedef TPointT<double> TPointD;
103 
104 #ifdef _WIN32
105 template class DVAPI TPointT<int>;
106 template class DVAPI TPointT<double>;
107 #endif
108 
109 template <class T>
110 inline bool operator==(const TPointT<T> &p0, const TPointT<T> &p1) {
111   return p0.x == p1.x && p0.y == p1.y;
112 }
113 
114 //-----------------------------------------------------------------------------
115 
116 //!\relates TPointT
117 inline TPoint operator*(int a, const TPoint &p) {
118   return TPoint(a * p.x, a * p.y);
119 }
120 
121 //!\relates TPointT
122 inline TPoint operator*(const TPoint &p, int a) {
123   return TPoint(a * p.x, a * p.y);
124 }
125 
126 //!\relates TPointT
127 inline TPointD operator*(double a, const TPointD &p) {
128   return TPointD(a * p.x, a * p.y);
129 }
130 
131 //!\relates TPointT
132 inline TPointD operator*(const TPointD &p, double a) {
133   return TPointD(a * p.x, a * p.y);
134 }
135 
136 //-----------------------------------------------------------------------------
137 /*!
138 \relates TPointT
139 This helper function returns the square of the absolute value of the specified
140 point (a TPointI)
141 */
norm2(const TPointI & p)142 inline int norm2(const TPointI &p) { return p.x * p.x + p.y * p.y; }
143 
144 //-----------------------------------------------------------------------------
145 /*!
146 \relates TPointT
147 This helper function returns the square of the absolute value of the specified
148 point (a TPointD)
149 */
norm2(const TPointD & p)150 inline double norm2(const TPointD &p) { return p.x * p.x + p.y * p.y; }
151 
152 /*!
153 \relates TPointT
154 This helper function returns the absolute value of the specified point
155 */
norm(const TPointD & p)156 inline double norm(const TPointD &p) { return std::sqrt(norm2(p)); }
157 
158 /*!
159 \relates TPointT
160 This helper function returns the normalized version of the specified point
161 */
normalize(const TPointD & p)162 inline TPointD normalize(const TPointD &p) {
163   double n = norm(p);
164   assert(n != 0.0);
165   return (1.0 / n) * p;
166 }
167 
168 /*!
169 \relates TPointT
170 This helper function converts a TPoint (TPointT<int>) into a TPointD
171 */
convert(const TPoint & p)172 inline TPointD convert(const TPoint &p) { return TPointD(p.x, p.y); }
173 
174 /*!
175 \relates TPointT
176 This helper function converts a TPointD (TPointT<double>) into a TPoint
177 */
convert(const TPointD & p)178 inline TPoint convert(const TPointD &p) {
179   return TPoint(tround(p.x), tround(p.y));
180 }
181 
182 /*!
183 \relates TPointT
184 This helper function returns the square of the distance between two points
185 */
tdistance2(const TPointD & p1,const TPointD & p2)186 inline double tdistance2(const TPointD &p1, const TPointD &p2) {
187   return norm2(p2 - p1);
188 }
189 
190 inline bool operator==(const TPointD &p0, const TPointD &p1) {
191   return tdistance2(p0, p1) < TConsts::epsilon * TConsts::epsilon;
192 }
193 
194 /*!
195 \relates TPointT
196 This helper function returns the distance between two points
197 */
tdistance(const TPointD & p1,const TPointD & p2)198 inline double tdistance(const TPointD &p1, const TPointD &p2) {
199   return norm(p2 - p1);
200 }
201 
202 /*!
203 the cross product
204 \relates TPointT
205 */
cross(const TPointD & a,const TPointD & b)206 inline double cross(const TPointD &a, const TPointD &b) {
207   return a.x * b.y - a.y * b.x;
208 }
209 
210 /*!
211 the cross product
212 \relates TPoint
213 */
cross(const TPoint & a,const TPoint & b)214 inline int cross(const TPoint &a, const TPoint &b) {
215   return a.x * b.y - a.y * b.x;
216 }
217 
218 /*!
219 returns the angle of the point p in polar coordinates
220 n.b atan(-y) = -pi/2, atan(x) = 0, atan(y) = pi/2, atan(-x) = pi
221 */
atan(const TPointD & p)222 inline double atan(const TPointD &p) { return atan2(p.y, p.x); }
223 
224 //=============================================================================
225 
226 template <class T>
227 class DVAPI T3DPointT {
228 public:
229   T x, y, z;
230 
T3DPointT()231   T3DPointT() : x(0), y(0), z(0) {}
232 
T3DPointT(T _x,T _y,T _z)233   T3DPointT(T _x, T _y, T _z) : x(_x), y(_y), z(_z) {}
T3DPointT(const TPointT<T> & _p,T _z)234   T3DPointT(const TPointT<T> &_p, T _z) : x(_p.x), y(_p.y), z(_z) {}
235 
T3DPointT(const T3DPointT & _p)236   T3DPointT(const T3DPointT &_p) : x(_p.x), y(_p.y), z(_p.z) {}
237 
238   inline T3DPointT &operator=(const T3DPointT &a) {
239     x = a.x;
240     y = a.y;
241     z = a.z;
242     return *this;
243   }
244 
245   inline T3DPointT &operator+=(const T3DPointT &a) {
246     x += a.x;
247     y += a.y;
248     z += a.z;
249     return *this;
250   }
251 
252   inline T3DPointT &operator-=(const T3DPointT &a) {
253     x -= a.x;
254     y -= a.y;
255     z -= a.z;
256     return *this;
257   }
258 
259   inline T3DPointT operator+(const T3DPointT &a) const {
260     return T3DPointT(x + a.x, y + a.y, z + a.z);
261   }
262 
263   inline T3DPointT operator-(const T3DPointT &a) const {
264     return T3DPointT(x - a.x, y - a.y, z - a.z);
265   }
266 
267   inline T3DPointT operator-() const { return T3DPointT(-x, -y, -z); }
268 
269   bool operator==(const T3DPointT &p) const {
270     return x == p.x && y == p.y && z == p.z;
271   }
272 
273   bool operator!=(const T3DPointT &p) const {
274     return x != p.x || y != p.y || z != p.z;
275   }
276 };
277 
278 //=============================================================================
279 
280 template <class T>
281 inline std::ostream &operator<<(std::ostream &out, const T3DPointT<T> &p) {
282   return out << "(" << p.x << ", " << p.y << ", " << p.z << ")";
283 }
284 
285 typedef T3DPointT<int> T3DPoint, T3DPointI;
286 typedef T3DPointT<double> T3DPointD;
287 
288 #ifdef _WIN32
289 template class DVAPI T3DPointT<int>;
290 template class DVAPI T3DPointT<double>;
291 #endif
292 
293 //-----------------------------------------------------------------------------
294 
295 //!\relates T3DPointT
296 template <class T>
297 inline T3DPointT<T> operator*(T a, const T3DPointT<T> &p) {
298   return T3DPointT<T>(a * p.x, a * p.y, a * p.z);
299 }
300 
301 //!\relates TPointT
302 template <class T>
303 inline T3DPointT<T> operator*(const T3DPointT<T> &p, T a) {
304   return T3DPointT<T>(a * p.x, a * p.y, a * p.z);
305 }
306 
307 //-----------------------------------------------------------------------------
308 /*!
309 \relates TPointT
310 This helper function returns the square of the absolute value of the specified
311 point (a TPointI)
312 */
313 template <class T>
norm2(const T3DPointT<T> & p)314 inline T norm2(const T3DPointT<T> &p) {
315   return p.x * p.x + p.y * p.y + p.z * p.z;
316 }
317 
318 /*!
319 */
320 template <class T>
norm(const T3DPointT<T> & p)321 inline T norm(const T3DPointT<T> &p) {
322   return std::sqrt(norm2(p));
323 }
324 
325 /*!
326 */
normalize(const T3DPointD & p)327 inline T3DPointD normalize(const T3DPointD &p) {
328   double n = norm(p);
329   assert(n != 0.0);
330   return (1.0 / n) * p;
331 }
332 
333 /*!
334 */
convert(const T3DPoint & p)335 inline T3DPointD convert(const T3DPoint &p) { return T3DPointD(p.x, p.y, p.z); }
336 
337 /*!
338 */
convert(const T3DPointD & p)339 inline T3DPoint convert(const T3DPointD &p) {
340   return T3DPoint(tround(p.x), tround(p.y), tround(p.z));
341 }
342 
343 //!
344 template <class T>
tdistance(const T3DPointT<T> & p1,const T3DPointT<T> & p2)345 inline T tdistance(const T3DPointT<T> &p1, const T3DPointT<T> &p2) {
346   return norm<T>(p2 - p1);
347 }
348 
349 //!
350 template <class T>
tdistance2(const T3DPointT<T> & p1,const T3DPointT<T> & p2)351 inline T tdistance2(const T3DPointT<T> &p1, const T3DPointT<T> &p2) {
352   return norm2<T>(p2 - p1);
353 }
354 
355 //!
356 template <class T>
cross(const T3DPointT<T> & a,const T3DPointT<T> & b)357 inline T3DPointT<T> cross(const T3DPointT<T> &a, const T3DPointT<T> &b) {
358   return T3DPointT<T>(a.y * b.z - b.y * a.z, a.z * b.x - b.z * a.x,
359                       a.x * b.y - b.x * a.y);
360 }
361 //=============================================================================
362 /*!
363 TThickPoint describe a thick point.
364 \relates TThickQuadratic, TThickCubic
365 */
366 class DVAPI TThickPoint final : public TPointD {
367 public:
368   double thick;
369 
TThickPoint()370   TThickPoint() : TPointD(), thick(0) {}
371 
372   TThickPoint(double _x, double _y, double _thick = 0)
TPointD(_x,_y)373       : TPointD(_x, _y), thick(_thick) {}
374 
375   TThickPoint(const TPointD &_p, double _thick = 0)
376       : TPointD(_p.x, _p.y), thick(_thick) {}
377 
TThickPoint(const T3DPointD & _p)378   TThickPoint(const T3DPointD &_p) : TPointD(_p.x, _p.y), thick(_p.z) {}
379 
TThickPoint(const TThickPoint & _p)380   TThickPoint(const TThickPoint &_p) : TPointD(_p.x, _p.y), thick(_p.thick) {}
381 
382   inline TThickPoint &operator=(const TThickPoint &a) {
383     x     = a.x;
384     y     = a.y;
385     thick = a.thick;
386     return *this;
387   }
388 
389   inline TThickPoint &operator+=(const TThickPoint &a) {
390     x += a.x;
391     y += a.y;
392     thick += a.thick;
393     return *this;
394   }
395 
396   inline TThickPoint &operator-=(const TThickPoint &a) {
397     x -= a.x;
398     y -= a.y;
399     thick -= a.thick;
400     return *this;
401   }
402 
403   inline TThickPoint operator+(const TThickPoint &a) const {
404     return TThickPoint(x + a.x, y + a.y, thick + a.thick);
405   }
406 
407   inline TThickPoint operator-(const TThickPoint &a) const {
408     return TThickPoint(x - a.x, y - a.y, thick - a.thick);
409   }
410 
411   inline TThickPoint operator-() const { return TThickPoint(-x, -y, -thick); }
412 
413   bool operator==(const TThickPoint &p) const {
414     return x == p.x && y == p.y && thick == p.thick;
415   }
416 
417   bool operator!=(const TThickPoint &p) const {
418     return x != p.x || y != p.y || thick != p.thick;
419   }
420 };
421 
422 inline double operator*(const TThickPoint &a, const TThickPoint &b) {
423   return a.x * b.x + a.y * b.y + a.thick * b.thick;
424 }
425 
426 inline TThickPoint operator*(double a, const TThickPoint &p) {
427   return TThickPoint(a * p.x, a * p.y, a * p.thick);
428 }
429 
430 inline TThickPoint operator*(const TThickPoint &p, double a) {
431   return TThickPoint(a * p.x, a * p.y, a * p.thick);
432 }
433 
434 /*!
435 \relates TPointD
436 This helper function converts a TThickPoint into a TPointD
437 */
convert(const TThickPoint & p)438 inline TPointD convert(const TThickPoint &p) { return TPointD(p.x, p.y); }
439 
440 /*!
441 \relates TThickPoint
442 This helper function returns the square of the distance between two thick points
443 (only x and y are used)
444 */
tdistance2(const TThickPoint & p1,const TThickPoint & p2)445 inline double tdistance2(const TThickPoint &p1, const TThickPoint &p2) {
446   return norm2(convert(p2 - p1));
447 }
448 /*!
449 \relates TThickPoint
450 This helper function returns the distance between two thick  points
451 (only x and y are used)
452 */
tdistance(const TThickPoint & p1,const TThickPoint & p2)453 inline double tdistance(const TThickPoint &p1, const TThickPoint &p2) {
454   return norm(convert(p2 - p1));
455 }
456 
457 inline std::ostream &operator<<(std::ostream &out, const TThickPoint &p) {
458   return out << "(" << p.x << ", " << p.y << ", " << p.thick << ")";
459 }
460 
461 //=============================================================================
462 //!	This is a template class representing a generic vector in a plane, i.e.
463 //! a point.
464 /*!
465                 It is a data structure with two objects in it representing
466    coordinate of the point and
467                 the basic operations on it.
468         */
469 template <class T>
470 class DVAPI TDimensionT {
471 public:
472   T lx, ly;
473   /*!
474           Constructs a vector of two elements, i.e. a point in a plane.
475   */
TDimensionT()476   TDimensionT() : lx(), ly() {}
TDimensionT(T _lx,T _ly)477   TDimensionT(T _lx, T _ly) : lx(_lx), ly(_ly) {}
478   /*!
479           Copy constructor.
480   */
TDimensionT(const TDimensionT & d)481   TDimensionT(const TDimensionT &d) : lx(d.lx), ly(d.ly) {}
482   /*!
483           Vector addition.
484   */
485   TDimensionT &operator+=(TDimensionT a) {
486     lx += a.lx;
487     ly += a.ly;
488     return *this;
489   }
490   /*!
491           Difference of two vectors.
492   */
493   TDimensionT &operator-=(TDimensionT a) {
494     lx -= a.lx;
495     ly -= a.ly;
496     return *this;
497   }
498   /*!
499           Addition of two vectors.
500   */
501   TDimensionT operator+(TDimensionT a) const {
502     TDimensionT ris(*this);
503     return ris += a;
504   }
505   /*!
506           Vector difference.
507   */
508   TDimensionT operator-(TDimensionT a) const {
509     TDimensionT ris(*this);
510     return ris -= a;
511   }
512   /*!
513           Compare vectors and returns \e true if are equals element by element.
514   */
515   bool operator==(const TDimensionT &d) const {
516     return lx == d.lx && ly == d.ly;
517   }
518   /*!
519           Compare vectors and returns \e true if are not equals element by
520      element.
521   */
522   bool operator!=(const TDimensionT &d) const { return !operator==(d); }
523 };
524 
525 //=============================================================================
526 
527 typedef TDimensionT<int> TDimension, TDimensionI;
528 typedef TDimensionT<double> TDimensionD;
529 
530 //=============================================================================
531 
532 template <class T>
533 inline std::ostream &operator<<(std::ostream &out, const TDimensionT<T> &p) {
534   return out << "(" << p.lx << ", " << p.ly << ")";
535 }
536 
537 #ifdef _WIN32
538 template class DVAPI TDimensionT<int>;
539 template class DVAPI TDimensionT<double>;
540 #endif
541 
542 //=============================================================================
543 
544 //! Specifies the corners of a rectangle.
545 /*!
546 x0 specifies the x-coordinate of the bottom-left corner of a rectangle.
547 y0 specifies the y-coordinate of the bottom-left corner of a rectangle.
548 x1 specifies the x-coordinate of the upper-right corner of a rectangle.
549 y1 specifies the y-coordinate of the upper-right corner of a rectangle.
550 */
551 template <class T>
552 class DVAPI TRectT {
553 public:
554   /*! if x0>x1 || y0>y1 then rect is empty
555 if x0==y1 && y0==y1 and rect is a  TRectD then rect is empty */
556 
557   T x0, y0;
558   T x1, y1;
559 
560   /*! makes an empty rect */
561   TRectT();
562 
TRectT(T _x0,T _y0,T _x1,T _y1)563   TRectT(T _x0, T _y0, T _x1, T _y1) : x0(_x0), y0(_y0), x1(_x1), y1(_y1){};
564 
TRectT(const TRectT & rect)565   TRectT(const TRectT &rect)
566       : x0(rect.x0), y0(rect.y0), x1(rect.x1), y1(rect.y1){};
567 
TRectT(const TPointT<T> & p0,const TPointT<T> & p1)568   TRectT(const TPointT<T> &p0, const TPointT<T> &p1)  // non importa l'ordine
569       : x0(std::min((T)p0.x, (T)p1.x)),
570         y0(std::min((T)p0.y, (T)p1.y)),
571         x1(std::max((T)p0.x, (T)p1.x)),
572         y1(std::max((T)p0.y, (T)p1.y)){};
573 
574   TRectT(const TPointT<T> &bottomLeft, const TDimensionT<T> &d);
575 
576   TRectT(const TDimensionT<T> &d);
577 
578   void empty();
579 
580   /*! TRectD is empty if and only if (x0>x1 || y0>y1) || (x0==y1 && y0==y1);
581 TRectI  is empty if x0>x1 || y0>y1 */
582   bool isEmpty() const;
583 
584   T getLx() const;
585   T getLy() const;
586 
getSize()587   TDimensionT<T> getSize() const { return TDimensionT<T>(getLx(), getLy()); };
588 
getP00()589   TPointT<T> getP00() const { return TPointT<T>(x0, y0); };
getP10()590   TPointT<T> getP10() const { return TPointT<T>(x1, y0); };
getP01()591   TPointT<T> getP01() const { return TPointT<T>(x0, y1); };
getP11()592   TPointT<T> getP11() const { return TPointT<T>(x1, y1); };
593 
594   //! Returns the union of two source rectangles.
595   //!The union is the smallest rectangle that contains both source rectangles.
596   TRectT<T> operator+(const TRectT<T> &rect) const {  // unione
597     if (isEmpty())
598       return rect;
599     else if (rect.isEmpty())
600       return *this;
601     else
602       return TRectT<T>(std::min((T)x0, (T)rect.x0),
603                        std::min((T)y0, (T)rect.y0),
604                        std::max((T)x1, (T)rect.x1),
605                        std::max((T)y1, (T)rect.y1));
606   };
607   TRectT<T> &operator+=(const TRectT<T> &rect) {  // unione
608     return *this = *this + rect;
609   };
610   TRectT<T> &operator*=(const TRectT<T> &rect) {  // intersezione
611     return *this = *this * rect;
612   };
613 
614   //!Returns the intersection of two existing rectangles.
615   //The intersection is the largest rectangle contained in both existing rectangles.
616   TRectT<T> operator*(const TRectT<T> &rect) const {  // intersezione
617     if (isEmpty() || rect.isEmpty())
618       return TRectT<T>();
619     else if (rect.x1 < x0 || x1 < rect.x0 || rect.y1 < y0 || y1 < rect.y0)
620       return TRectT<T>();
621     else
622       return TRectT<T>(std::max((T)x0, (T)rect.x0), std::max((T)y0, (T)rect.y0),
623                        std::min((T)x1, (T)rect.x1),
624                        std::min((T)y1, (T)rect.y1));
625   };
626 
627   TRectT<T> &operator+=(const TPointT<T> &p) {  // shift
628     x0 += p.x;
629     y0 += p.y;
630     x1 += p.x;
631     y1 += p.y;
632     return *this;
633   };
634   TRectT<T> &operator-=(const TPointT<T> &p) {
635     x0 -= p.x;
636     y0 -= p.y;
637     x1 -= p.x;
638     y1 -= p.y;
639     return *this;
640   };
641   TRectT<T> operator+(const TPointT<T> &p) const {
642     TRectT<T> ris(*this);
643     return ris += p;
644   };
645   TRectT<T> operator-(const TPointT<T> &p) const {
646     TRectT<T> ris(*this);
647     return ris -= p;
648   };
649 
650   bool operator==(const TRectT<T> &r) const {
651     return x0 == r.x0 && y0 == r.y0 && x1 == r.x1 && y1 == r.y1;
652   };
653 
654   bool operator!=(const TRectT<T> &r) const {
655     return x0 != r.x0 || y0 != r.y0 || x1 != r.x1 || y1 != r.y1;
656   };
657 
contains(const TPointT<T> & p)658   bool contains(const TPointT<T> &p) const {
659     return x0 <= p.x && p.x <= x1 && y0 <= p.y && p.y <= y1;
660   };
661 
contains(const TRectT<T> & b)662   bool contains(const TRectT<T> &b) const {
663     return x0 <= b.x0 && x1 >= b.x1 && y0 <= b.y0 && y1 >= b.y1;
664   };
665 
overlaps(const TRectT<T> & b)666   bool overlaps(const TRectT<T> &b) const {
667     return x0 <= b.x1 && x1 >= b.x0 && y0 <= b.y1 && y1 >= b.y0;
668   };
669 
enlarge(T dx,T dy)670   TRectT<T> enlarge(T dx, T dy) const {
671     if (isEmpty()) return *this;
672     return TRectT<T>(x0 - dx, y0 - dy, x1 + dx, y1 + dy);
673   };
674 
enlarge(T d)675   TRectT<T> enlarge(T d) const { return enlarge(d, d); };
enlarge(TDimensionT<T> d)676   TRectT<T> enlarge(TDimensionT<T> d) const { return enlarge(d.lx, d.ly); };
677 };
678 
679 //-----------------------------------------------------------------------------
680 
681 typedef TRectT<int> TRect, TRectI;
682 typedef TRectT<double> TRectD;
683 
684 #ifdef _WIN32
685 template class DVAPI TRectT<int>;
686 template class DVAPI TRectT<double>;
687 #endif
688 
689 //=============================================================================
690 
691 // check this, not final version
692 /*!
693 \relates TRectT
694 Convert a TRectD into a TRect
695 */
696 
convert(const TRectD & r)697 inline TRect convert(const TRectD &r) {
698   return TRect((int)(r.x0 + 0.5), (int)(r.y0 + 0.5), (int)(r.x1 + 0.5),
699                (int)(r.y1 + 0.5));
700 }
701 /*!
702 \relates TRectT
703 Convert a TRect into a TRectD
704 */
convert(const TRect & r)705 inline TRectD convert(const TRect &r) { return TRectD(r.x0, r.y0, r.x1, r.y1); }
706 
707 // template?
708 /*!
709 \relates TRectT
710 \relates TPointT
711 */
boundingBox(const TPointD & p0,const TPointD & p1)712 inline TRectD boundingBox(const TPointD &p0, const TPointD &p1) {
713   return TRectD(std::min(p0.x, p1.x), std::min(p0.y, p1.y),  // bottom left
714                 std::max(p0.x, p1.x), std::max(p0.y, p1.y));  // top right
715 }
716 /*!
717 \relates TRectT
718 \relates TPointT
719 */
boundingBox(const TPointD & p0,const TPointD & p1,const TPointD & p2)720 inline TRectD boundingBox(const TPointD &p0, const TPointD &p1,
721                           const TPointD &p2) {
722   return TRectD(std::min({p0.x, p1.x, p2.x}), std::min({p0.y, p1.y, p2.y}),
723                 std::max({p0.x, p1.x, p2.x}), std::max({p0.y, p1.y, p2.y}));
724 }
725 
726 /*!
727 \relates TRectT
728 \relates TPointT
729 */
boundingBox(const TPointD & p0,const TPointD & p1,const TPointD & p2,const TPointD & p3)730 inline TRectD boundingBox(const TPointD &p0, const TPointD &p1,
731                           const TPointD &p2, const TPointD &p3) {
732   return TRectD(
733       std::min({p0.x, p1.x, p2.x, p3.x}), std::min({p0.y, p1.y, p2.y, p3.y}),
734       std::max({p0.x, p1.x, p2.x, p3.x}), std::max({p0.y, p1.y, p2.y, p3.y}));
735 }
736 
737 //-----------------------------------------------------------------------------
738 
739 // TRectT is a rectangle that uses thick points
740 template <>
TRectT()741 inline TRectT<int>::TRectT() : x0(0), y0(0), x1(-1), y1(-1) {}
742 template <>
TRectT(const TPointT<int> & bottomLeft,const TDimensionT<int> & d)743 inline TRectT<int>::TRectT(const TPointT<int> &bottomLeft,
744                            const TDimensionT<int> &d)
745     : x0(bottomLeft.x)
746     , y0(bottomLeft.y)
747     , x1(bottomLeft.x + d.lx - 1)
748     , y1(bottomLeft.y + d.ly - 1){};
749 template <>
TRectT(const TDimensionT<int> & d)750 inline TRectT<int>::TRectT(const TDimensionT<int> &d)
751     : x0(0), y0(0), x1(d.lx - 1), y1(d.ly - 1){};
752 template <>
isEmpty()753 inline bool TRectT<int>::isEmpty() const {
754   return x0 > x1 || y0 > y1;
755 }
756 template <>
empty()757 inline void TRectT<int>::empty() {
758   x0 = y0 = 0;
759   x1 = y1 = -1;
760 }
761 
762 // Is the adding of one here to account for the thickness?
763 template <>
getLx()764 inline int TRectT<int>::getLx() const {
765   return x1 >= x0 ? x1 - x0 + 1 : 0;
766 }
767 template <>
getLy()768 inline int TRectT<int>::getLy() const {
769   return y1 >= y0 ? y1 - y0 + 1 : 0;
770 }
771 
772 template <>
TRectT()773 inline TRectT<double>::TRectT() : x0(0), y0(0), x1(0), y1(0) {}
774 template <>
TRectT(const TPointT<double> & bottomLeft,const TDimensionT<double> & d)775 inline TRectT<double>::TRectT(const TPointT<double> &bottomLeft,
776                               const TDimensionT<double> &d)
777     : x0(bottomLeft.x)
778     , y0(bottomLeft.y)
779     , x1(bottomLeft.x + d.lx)
780     , y1(bottomLeft.y + d.ly){};
781 template <>
TRectT(const TDimensionT<double> & d)782 inline TRectT<double>::TRectT(const TDimensionT<double> &d)
783     : x0(0.0), y0(0.0), x1(d.lx), y1(d.ly){};
784 template <>
isEmpty()785 inline bool TRectT<double>::isEmpty() const {
786   return (x0 == x1 && y0 == y1) || x0 > x1 || y0 > y1;
787 }
788 template <>
empty()789 inline void TRectT<double>::empty() {
790   x0 = y0 = x1 = y1 = 0;
791 }
792 template <>
getLx()793 inline double TRectT<double>::getLx() const {
794   return x1 >= x0 ? x1 - x0 : 0;
795 }
796 template <>
getLy()797 inline double TRectT<double>::getLy() const {
798   return y1 >= y0 ? y1 - y0 : 0;
799 }
800 
801 //-----------------------------------------------------------------------------
802 
803 inline TRectD &operator*=(TRectD &rect, double factor) {
804   rect.x0 *= factor;
805   rect.y0 *= factor;
806   rect.x1 *= factor;
807   rect.y1 *= factor;
808   return rect;
809 }
810 
811 //-----------------------------------------------------------------------------
812 
813 inline TRectD operator*(const TRectD &rect, double factor) {
814   TRectD result(rect);
815   return result *= factor;
816 }
817 
818 //-----------------------------------------------------------------------------
819 
820 inline TRectD &operator/=(TRectD &rect, double factor) {
821   assert(factor != 0.0);
822   return rect *= (1.0 / factor);
823 }
824 
825 //-----------------------------------------------------------------------------
826 
827 inline TRectD operator/(const TRectD &rect, double factor) {
828   assert(factor != 0.0);
829   TRectD result(rect);
830   return result *= 1.0 / factor;
831 }
832 
833 //-----------------------------------------------------------------------------
834 
835 template <class T>
836 inline std::ostream &operator<<(std::ostream &out, const TRectT<T> &r) {
837   return out << "(" << r.x0 << "," << r.y0 << ";" << r.x1 << "," << r.y1 << ")";
838 }
839 
840 //=============================================================================
841 
842 namespace TConsts {
843 
844 extern DVVAR const TPointD napd;
845 extern DVVAR const TPoint nap;
846 extern DVVAR const T3DPointD nap3d;
847 extern DVVAR const TThickPoint natp;
848 extern DVVAR const TRectD infiniteRectD;
849 extern DVVAR const TRectI infiniteRectI;
850 }
851 
852 //=============================================================================
853 //! This is the base class for the affine transformations.
854 /*!
855  This class performs basic manipulations of affine transformations.
856  An affine transformation is a linear transformation followed by a translation.
857 
858   [a11, a12, a13]
859   [a21, a22, a23]
860 
861   a13 and a23 represent translation (moving sideways or up and down)
862   the other 4 handle rotation, scale and shear
863 */
864 class DVAPI TAffine {
865 public:
866   double a11, a12, a13;
867   double a21, a22, a23;
868   /*!
869           By default the object is initialized with a null matrix and a null
870      translation vector.
871   */
TAffine()872   TAffine() : a11(1.0), a12(0.0), a13(0.0), a21(0.0), a22(1.0), a23(0.0){};
873   /*!
874           Initializes the internal matrix and vector of translation with the
875      user values.
876   */
TAffine(double p11,double p12,double p13,double p21,double p22,double p23)877   TAffine(double p11, double p12, double p13, double p21, double p22,
878           double p23)
879       : a11(p11), a12(p12), a13(p13), a21(p21), a22(p22), a23(p23){};
880   /*!
881           Copy constructor.
882   */
TAffine(const TAffine & a)883   TAffine(const TAffine &a)
884       : a11(a.a11)
885       , a12(a.a12)
886       , a13(a.a13)
887       , a21(a.a21)
888       , a22(a.a22)
889       , a23(a.a23){};
890   /*!
891           Assignment operator.
892 */
893   TAffine &operator=(const TAffine &a);
894   /*Moved to tgeometry.cpp
895 {
896 a11 = a.a11; a12 = a.a12; a13 = a.a13;
897 a21 = a.a21; a22 = a.a22; a23 = a.a23;
898 return *this;
899 };
900 */
901   /*!
902           Matrix multiplication.
903           <p>\f$\left(\begin{array}{cc}\bf{A}&\vec{a}\\\vec{0}&1\end{array}\right)
904           \left(\begin{array}{cc}\bf{B}&\vec{b}\\\vec{0}&1\end{array}\right)\f$</p>
905 
906 */
907   TAffine operator*(const TAffine &b) const;
908   /*Moved to in tgeometry.cpp
909 {
910 return TAffine (
911 a11 * b.a11 + a12 * b.a21,
912 a11 * b.a12 + a12 * b.a22,
913 a11 * b.a13 + a12 * b.a23 + a13,
914 
915 a21 * b.a11 + a22 * b.a21,
916 a21 * b.a12 + a22 * b.a22,
917 a21 * b.a13 + a22 * b.a23 + a23);
918 };
919 */
920 
921   TAffine operator*=(const TAffine &b);
922   /*Moved to tgeometry.cpp
923 {
924 return *this = *this * b;
925 };
926 */
927   /*!
928           Retruns the inverse tansformation as:
929           <p>\f$\left(\begin{array}{ccc}\bf{A}^{-1}&-\bf{A}^{-1}&\vec{b}\\\vec{0}&\vec{0}&1\end{array}\right)\f$</p>
930   */
931 
932   TAffine inv() const;
933   /*Moved to tgeometry.cpp
934 {
935 if(a12 == 0.0 && a21 == 0.0)
936 {
937 assert(a11 != 0.0);
938 assert(a22 != 0.0);
939 double inv_a11 = 1.0/a11;
940 double inv_a22 = 1.0/a22;
941 return TAffine(inv_a11,0, -a13 * inv_a11,
942   0,inv_a22, -a23 * inv_a22);
943 }
944 else if(a11 == 0.0 && a22 == 0.0)
945 {
946 assert(a12 != 0.0);
947 assert(a21 != 0.0);
948 double inv_a21 = 1.0/a21;
949 double inv_a12 = 1.0/a12;
950 return TAffine(0, inv_a21, -a23 * inv_a21,
951   inv_a12, 0, -a13 * inv_a12);
952 }
953 else
954 {
955 double d = 1./det();
956 return TAffine(a22*d,-a12*d, (a12*a23-a22*a13)*d,
957   -a21*d, a11*d, (a21*a13-a11*a23)*d);
958 }
959 };
960 */
961 
962   double det() const;
963   /*Sposto in tgeometry.cpp{
964 return a11*a22-a12*a21;
965 };
966 */
967 
968   /*!
969           Returns \e true if all elements are equals.
970   */
971   bool operator==(const TAffine &a) const;
972   /*Sposto in tgeometry.cpp
973 {
974 return a11==a.a11 && a12==a.a12 && a13==a.a13 &&
975 a21==a.a21 && a22==a.a22 && a23==a.a23;
976 };
977 */
978   /*!
979           Returns \e true if at least one element is different.
980   */
981 
982   bool operator!=(const TAffine &a) const;
983   /*Sposto in tgeometry.cpp
984 {
985 return a11!=a.a11 || a12!=a.a12 || a13!=a.a13 ||
986 a21!=a.a21 || a22!=a.a22 || a23!=a.a23;
987 };
988 */
989   /*!
990           Returns \e true if the transformation is an identity,
991           i.e in the error limit \e err leaves the vectors unchanged.
992   */
993 
994   bool isIdentity(double err = 1.e-8) const;
995   /*Sposto in tgeometry.cpp
996 {
997 return ((a11-1.0)*(a11-1.0)+(a22-1.0)*(a22-1.0)+
998 a12*a12+a13*a13+a21*a21+a23*a23) < err;
999 };
1000 */
1001   /*!
1002           Returns \e true if in the error limits \e err \f$\bf{A}\f$ is the
1003      identity matrix.
1004   */
1005 
1006   bool isTranslation(double err = 1.e-8) const;
1007   /*Sposto in tgeometry.cpp
1008 {
1009 return ((a11-1.0)*(a11-1.0)+(a22-1.0)*(a22-1.0)+
1010 a12*a12+a21*a21) < err;
1011 };
1012 */
1013   /*!
1014           Returns \e true if in the error limits the matrix \f$\bf{A}\f$ is of
1015      the form:
1016           <p>\f$\left(\begin{array}{cc}a&b\\-b&a\end{array}\right)\f$</p>.
1017   */
1018 
1019   bool isIsotropic(double err = 1.e-8) const;
1020   /*Sposto in tgeometry.cpp
1021   {
1022     return areAlmostEqual(a11, a22, err) && areAlmostEqual(a12, -a21, err);
1023   };
1024   */
1025 
1026   /*!
1027           Retruns the transfomed point.
1028   */
1029   TPointD operator*(const TPointD &p) const;
1030   /*Sposto in tgeometry.cpp
1031 {
1032 return TPointD(p.x*a11+p.y*a12+a13, p.x*a21+p.y*a22+a23);
1033 };
1034 */
1035 
1036   /*!
1037           Retruns the transformed box of the bounding box.
1038   */
1039   TRectD operator*(const TRectD &rect) const;
1040 
1041   /*!
1042           Returns a translated matrix that change the vector (u,v) in (x,y).
1043   \n	It returns a matrix of the form:
1044           <p>\f$\left(\begin{array}{ccc}\bf{A}&\vec{x}-\bf{A} \vec{u}\\
1045           \vec{0}&1\end{array}\right)\f$</p>
1046   */
1047   TAffine place(double u, double v, double x, double y) const;
1048 
1049   /*!
1050           See above.
1051   */
1052   TAffine place(const TPointD &pIn, const TPointD &pOut) const;
1053 };
1054 
1055 //-----------------------------------------------------------------------------
1056 
1057 // template <>
1058 inline bool areAlmostEqual(const TPointD &a, const TPointD &b,
1059                            double err = TConsts::epsilon) {
1060   return tdistance2(a, b) < err * err;
1061 }
1062 
1063 // template <>
1064 inline bool areAlmostEqual(const TRectD &a, const TRectD &b,
1065                            double err = TConsts::epsilon) {
1066   return areAlmostEqual(a.getP00(), b.getP00(), err) &&
1067          areAlmostEqual(a.getP11(), b.getP11(), err);
1068 }
1069 
1070 const TAffine AffI = TAffine();
1071 
1072 //-----------------------------------------------------------------------------
1073 
1074 class DVAPI TTranslation final : public TAffine {
1075 public:
TTranslation()1076   TTranslation(){};
TTranslation(double x,double y)1077   TTranslation(double x, double y) : TAffine(1, 0, x, 0, 1, y){};
TTranslation(const TPointD & p)1078   TTranslation(const TPointD &p) : TAffine(1, 0, p.x, 0, 1, p.y){};
1079 };
1080 
1081 //-----------------------------------------------------------------------------
1082 
1083 class DVAPI TRotation final : public TAffine {
1084 public:
TRotation()1085   TRotation(){};
1086 
1087   /*! makes a rotation matrix of  "degrees" degrees counterclockwise
1088 on the origin */
1089   TRotation(double degrees);
1090   /*Sposto in tgeometry.cpp
1091 {
1092 double rad, sn, cs;
1093 int idegrees = (int)degrees;
1094 if ((double)idegrees == degrees && idegrees % 90 == 0)
1095 {
1096 switch ((idegrees / 90) & 3)
1097 {
1098 case 0:  sn =  0; cs =  1; break;
1099 case 1:  sn =  1; cs =  0; break;
1100 case 2:  sn =  0; cs = -1; break;
1101 case 3:  sn = -1; cs =  0; break;
1102 default: sn =  0; cs =  0; break;
1103 }
1104 }
1105 else
1106 {
1107 rad = degrees * (TConsts::pi_180);
1108 sn = sin (rad);
1109 cs = cos (rad);
1110 if (sn == 1 || sn == -1)
1111   cs = 0;
1112 if (cs == 1 || cs == -1)
1113   sn = 0;
1114 }
1115 a11=cs;a12= -sn;a21= -a12;a22=a11;
1116 };
1117 */
1118 
1119   /*! makes a rotation matrix of  "degrees" degrees counterclockwise
1120 on the given center */
1121   TRotation(const TPointD &center, double degrees);
1122   /*Sposto in tgeometry.cpp
1123 {
1124 TAffine a = TTranslation(center) * TRotation(degrees) * TTranslation(-center);
1125 a11 = a.a11; a12 = a.a12; a13 = a.a13;
1126 a21 = a.a21; a22 = a.a22; a23 = a.a23;
1127 };
1128 */
1129 };
1130 
1131 //-----------------------------------------------------------------------------
1132 
1133 class DVAPI TScale final : public TAffine {
1134 public:
TScale()1135   TScale(){};
TScale(double sx,double sy)1136   TScale(double sx, double sy) : TAffine(sx, 0, 0, 0, sy, 0){};
TScale(double s)1137   TScale(double s) : TAffine(s, 0, 0, 0, s, 0) {}
1138 
1139   TScale(const TPointD &center, double sx, double sy);
1140   /*Sposto in tgeometry.cpp
1141 {
1142 TAffine a = TTranslation(center) * TScale(sx,sy) * TTranslation(-center);
1143 a11 = a.a11; a12 = a.a12; a13 = a.a13;
1144 a21 = a.a21; a22 = a.a22; a23 = a.a23;
1145 }
1146 */
1147 
1148   TScale(const TPointD &center, double s);
1149   /*Sposto in tgeometry.cpp
1150 {
1151 TAffine a = TTranslation(center) * TScale(s) * TTranslation(-center);
1152 a11 = a.a11; a12 = a.a12; a13 = a.a13;
1153 a21 = a.a21; a22 = a.a22; a23 = a.a23;
1154 }
1155 */
1156 };
1157 
1158 //-----------------------------------------------------------------------------
1159 
1160 class DVAPI TShear final : public TAffine {
1161 public:
TShear()1162   TShear(){};
TShear(double sx,double sy)1163   TShear(double sx, double sy) : TAffine(1, sx, 0, sy, 1, 0){};
1164 };
1165 
1166 //-----------------------------------------------------------------------------
1167 
1168 inline bool areEquals(const TAffine &a, const TAffine &b, double err = 1e-8) {
1169   return fabs(a.a11 - b.a11) < err && fabs(a.a12 - b.a12) < err &&
1170          fabs(a.a13 - b.a13) < err && fabs(a.a21 - b.a21) < err &&
1171          fabs(a.a22 - b.a22) < err && fabs(a.a23 - b.a23) < err;
1172 }
1173 
1174 //-----------------------------------------------------------------------------
1175 
inv(const TAffine & a)1176 inline TAffine inv(const TAffine &a) { return a.inv(); }
1177 
1178 //-----------------------------------------------------------------------------
1179 
1180 inline std::ostream &operator<<(std::ostream &out, const TAffine &a) {
1181   return out << "(" << a.a11 << ", " << a.a12 << ", " << a.a13 << ";" << a.a21
1182              << ", " << a.a22 << ", " << a.a23 << ")";
1183 }
1184 
1185 #endif  //  __T_GEOMETRY_INCLUDED__
1186