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 ¢er, 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 ¢er, 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 ¢er, 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