Mako 8.3.0 API
MakoCore SDK API Documentation
Loading...
Searching...
No Matches
edlgeom.h
Go to the documentation of this file.
1/*
2 * Copyright (C) 2007-2025 Global Graphics Software Ltd. All rights reserved.
3 */
4
10
11#ifndef EDLGEOM_H
12#define EDLGEOM_H
13
14#include <algorithm>
15#include <edl/edltypes.h>
16#include <edl/edlmath.h>
17#include <edl/edlvector.h>
18#include <edl/edlerrors.h>
19
21
27template <typename PointType>
29{
30 public:
31 PointTmpl() : x(0), y(0)
32 {
33 }
34
35 PointTmpl(PointType ax, PointType ay) : x(ax), y(ay)
36 {
37 }
38
39 PointTmpl(const PointTmpl<PointType>& p) = default;
40
42
44
46 {
47 x += pt.x;
48 y += pt.y;
49 return *this;
50 }
51
52 bool equal(const PointTmpl& point) const
53 {
54 return ((x == point.x) && (y == point.y));
55 }
56
57 bool operator == (const PointTmpl& point) const
58 {
59 return ((x == point.x) && (y == point.y));
60 }
61
62 bool operator!= (const PointTmpl& point) const
63 {
64 return !(*this == point);
65 }
66
73 {
74 return PointTmpl<PointType>((PointType)(x + (pt.x - x) / 2.0), (PointType)(y + (pt.y - y) / 2.0));
75 }
76
82 double getDistance(const PointTmpl<PointType>& pt) const
83 {
84 return hypot(pt.x - x, pt.y - y);
85 }
86
87 PointType x;
88 PointType y;
89};
90
91template <typename PointType>
93{
94 return PointTmpl<PointType>(lhp.x + rhp.x, lhp.y + rhp.y);
95}
96template <typename PointType>
98{
99 return PointTmpl<PointType>(lhp.x - rhp.x, lhp.y - rhp.y);
100}
101
107
108// Point type may not be an unsigned type
109template <typename PointType>
111{
112 public:
114 x(0), y(0), dX(-1), dY(-1)
115 {}
116
117 RectTmpl(PointType ax, PointType ay, PointType adX, PointType adY) :
118 x(ax), y(ay), dX(adX), dY(adY)
119 {}
120
121 RectTmpl(const RectTmpl<PointType>& r) = default;
122
124
126
127 PointType x;
128 PointType y;
129 PointType dX;
130 PointType dY;
131
132 void setEmpty()
133 {
134 dX = (PointType)-1;
135 dY = (PointType)-1;
136 }
137
138 bool isEmpty() const
139 {
140 return (dX < (PointType)0 || dY < (PointType)0);
141 }
142
143 bool equal(const RectTmpl& rect) const
144 {
145 return ((x == rect.x) && (y == rect.y) &&
146 (dX == rect.dX) && (dY == rect.dY));
147 }
148
149 bool operator== (const RectTmpl& rect) const
150 {
151 return ((x == rect.x) && (y == rect.y) &&
152 (dX == rect.dX) && (dY == rect.dY));
153 }
154
155 bool operator!= (const RectTmpl& rect) const
156 {
157 return !(*this == rect);
158 }
159
160 bool similar(const RectTmpl& rect, float epsilon) const
161 {
162 return (fabs(x - rect.x) < epsilon &&
163 fabs(y - rect.y) < epsilon &&
164 fabs(dX - rect.dX) < epsilon &&
165 fabs(dY - rect.dY) < epsilon);
166 }
167
168 RectTmpl& offset(PointType offX, PointType offY)
169 {
170 if (!isEmpty())
171 {
172 x += offX;
173 y += offY;
174 }
175 return *this;
176 }
177
182 RectTmpl& inset(PointType insetX, PointType insetY)
183 {
184 if (!isEmpty())
185 {
186 if (dX < insetX * 2)
187 {
188 x += dX / 2;
189 dX = 0;
190 }
191 else
192 {
193 dX -= insetX * 2;
194 x += insetX;
195 }
196 if (dY < insetY * 2)
197 {
198 y += dY / 2;
199 dY = 0;
200 }
201 else
202 {
203 dY -= insetY * 2;
204 y += insetY;
205 }
206 }
207 return *this;
208 }
209
215 {
216 bool result = false;
217 if (isEmpty())
218 {
219 x = point.x; y = point.y;
220 dX = 0; dY = 0;
221 result = true;
222 }
223 else
224 {
225 if (point.x < x)
226 {
227 dX += (x - point.x);
228 x = point.x;
229 result = true;
230 }
231 if (point.y < y)
232 {
233 dY += (y - point.y);
234 y = point.y;
235 result = true;
236 }
237 if (point.x > x + dX)
238 {
239 dX = point.x - x;
240 result = true;
241 }
242 if (point.y > y + dY)
243 {
244 dY = point.y - y;
245 result = true;
246 }
247 }
248 return result;
249 }
250
255 {
256 if (!isEmpty() && !rect.isEmpty())
257 {
258 PointType llX = std::max<PointType>(x, rect.x);
259 PointType urX = std::min<PointType>(x + dX, rect.x + rect.dX);
260 PointType llY = std::max<PointType>(y, rect.y);
261 PointType urY = std::min<PointType>(y + dY, rect.y + rect.dY);
262 x = llX; y = llY; dX = urX - x; dY = urY - y;
263 }
264 else
265 {
266 setEmpty(); // Empty result
267 }
268 }
269
272 {
273 if (!isEmpty())
274 {
275 if (containsRect(rect))
276 {
277 // We completely contain the input rect; no need to grow
278 }
279 else if (!rect.isEmpty())
280 {
281 PointType llX = std::min<PointType>(x, rect.x);
282 PointType urX = std::max<PointType>(x + dX, rect.x + rect.dX);
283 PointType llY = std::min<PointType>(y, rect.y);
284 PointType urY = std::max<PointType>(y + dY, rect.y + rect.dY);
285 x = llX; y = llY; dX = urX - x; dY = urY - y;
286 }
287 }
288 else
289 {
290 x = rect.x; y = rect.y; dX = rect.dX; dY = rect.dY;
291 }
292 }
293
296 {
297 RectTmpl<PointType> copy = rect;
298 copy.intersectRect(*this);
299 return !copy.isEmpty();
300 }
301
303 bool containsRect(const RectTmpl<PointType>& rect) const
304 {
305 if (rect.isEmpty() || isEmpty())
306 {
307 return false;
308 }
309 if (x <= rect.x && // We start at or to the left of the input rect
310 y <= rect.y && // We start at or above the top of the input rect
311 (x + dX) >= (rect.x + rect.dX) && // We extend to or beyond the rect to the right
312 (y + dY) >= (rect.y + rect.dY)) // We extend to or beyond the rect to the bottom
313 {
314 return true;
315 }
316 else
317 {
318 return false;
319 }
320 }
321
322 bool containsPoint(PointType px, PointType py) const
323 {
324 return x <= px && px <= getRight() && y <= py && py <= getBottom();
325 }
326
327 PointType getRight() const
328 {
329 return x + dX;
330 }
331
332 PointType getBottom() const
333 {
334 return y + dY;
335 }
336};
337
341
348template <typename PointType>
350{
351 public:
352 BoxTmpl() : left(0), bottom(0), right(0), top(0)
353 {}
354
355 BoxTmpl(PointType _left, PointType _bottom, PointType _right, PointType _top) :
356 left(_left), bottom(_bottom), right(_right), top(_top)
357 {}
358
360 left(b.left), bottom(b.bottom), right(b.right), top(b.top)
361 {}
362
364 {
365 if (rect.isEmpty())
366 {
367 left = rect.x;
368 bottom = rect.y;
369 right = rect.x;
370 top = rect.y;
371 }
372 else
373 {
374 left = rect.x;
375 bottom = rect.y;
376 right = rect.x + rect.dX;
377 top = rect.y + rect.dY;
378 }
379 }
380
382
384
386 {
387 RectTmpl<PointType> result;
388 result.x = left < right ? left : right;
389 result.y = top < bottom ? top : bottom;
390 result.dX = left < right ? (right - left) : (left - right);
391 result.dY = top < bottom ? (bottom - top) : (top - bottom);
392 return result;
393 }
394
396 {
397 if (left > right)
398 {
399 PointType tmp = left;
400 left = right;
401 right = tmp;
402 }
403 if (bottom > top)
404 {
405 PointType tmp = bottom;
406 bottom = top;
407 top = tmp;
408 }
409 }
410
411 void offset(PointType x, PointType y)
412 {
413 left += x;
414 right += x;
415 top += y;
416 bottom += y;
417 }
418
419 void scale(PointType s)
420 {
421 left *= s;
422 right *= s;
423 top *= s;
424 bottom *= s;
425 }
426
427 bool equal(const BoxTmpl<PointType>& other) const
428 {
429 return (left == other.left)
430 && (bottom == other.bottom)
431 && (top == other.top)
432 && (right == other.right);
433 }
434
435 PointType left;
436 PointType bottom;
437 PointType top;
438 PointType right;
439};
440
444
446template <typename TItem>
448{
449 public:
454 typedef enum {
460
465 {
466 set();
467 }
468
479 CTransformMatrix(TItem _xx, TItem _xy, TItem _yx, TItem _yy, TItem _dx, TItem _dy)
480 {
481 set(_xx, _xy, _yx, _yy, _dx, _dy);
482 }
483
489 {
490 *this = m;
491 }
492
499 {
500 if (this != &m)
501 {
502 m_xx = m.m_xx;
503 m_xy = m.m_xy;
504 m_yx = m.m_yx;
505 m_yy = m.m_yy;
506 m_dx = m.m_dx;
507 m_dy = m.m_dy;
508 }
509 return *this;
510 }
511
518 CTransformMatrix(const RectTmpl<TItem>& sourceRect, const RectTmpl<TItem>& destRect)
519 {
520 set();
521 if (sourceRect.dX > 0 && destRect.dX > 0 && sourceRect.dY > 0 && destRect.dY > 0)
522 {
523 m_xx = destRect.dX / sourceRect.dX;
524 m_yy = destRect.dY / sourceRect.dY;
525 m_dx = destRect.x - sourceRect.x * m_xx;
526 m_dy = destRect.y - sourceRect.y * m_yy;
527 }
528 }
529
540 void set(TItem _xx = 1, TItem _xy = 0, TItem _yx = 0, TItem _yy = 1, TItem _dx = 0, TItem _dy = 0)
541 {
542 m_xx = _xx; m_xy = _xy; m_yx = _yx; m_yy = _yy; m_dx = _dx; m_dy = _dy;
543 }
544
549 TItem xx()const { return m_xx; }
550
555 TItem xy()const { return m_xy; }
556
561 TItem yx()const { return m_yx; }
562
567 TItem yy()const { return m_yy; }
568
573 TItem dx()const { return m_dx; }
574
579 TItem dy()const { return m_dy; }
580
585 void setXX(TItem x) { m_xx = x; }
586
591 void setXY(TItem x) { m_xy = x; }
592
597 void setYX(TItem x) { m_yx = x; }
598
603 void setYY(TItem x) { m_yy = x; }
604
609 void setDX(TItem x) { m_dx = x; }
610
615 void setDY(TItem x) { m_dy = x; }
616
623 bool equal(const CTransformMatrix<TItem>& matrix, bool ignoreDXDY = false) const
624 {
625 return (m_xx == matrix.xx()) &&
626 (m_xy == matrix.xy()) &&
627 (m_yx == matrix.yx()) &&
628 (m_yy == matrix.yy()) &&
629 (ignoreDXDY || (
630 (m_dx == matrix.dx()) &&
631 (m_dy == matrix.dy())));
632 }
633
639 bool identity(bool ignoreDXDY = false) const
640 {
641 return (m_xx == 1.0) &&
642 (m_xy == 0.0) &&
643 (m_yx == 0.0) &&
644 (m_yy == 1.0) &&
645 (ignoreDXDY || (
646 (m_dx == 0.0) &&
647 (m_dy == 0.0)));
648 }
649
659 bool ortho(bool &rotated) const
660 {
661 rotated = false; // Until proven otherwise
662 if (m_xy == 0 && m_yx == 0)
663 {
664 return true;
665 }
666 else if (m_xx == 0 && m_yy == 0)
667 {
668 rotated = true;
669 return true;
670 }
671 else
672 {
673 return false;
674 }
675 }
676
683 {
684 TItem a = matrix.xx() * m_xx + matrix.xy() * m_yx;
685 TItem b = matrix.xx() * m_xy + matrix.xy() * m_yy;
686 TItem c = matrix.yx() * m_xx + matrix.yy() * m_yx;
687 TItem d = matrix.yx() * m_xy + matrix.yy() * m_yy;
688 TItem e = matrix.dx() * m_xx + matrix.dy() * m_yx + m_dx;
689 TItem f = matrix.dx() * m_xy + matrix.dy() * m_yy + m_dy;
690 m_xx = a; m_xy = b; m_yx = c; m_yy = d; m_dx = e; m_dy = f;
691 return *this;
692 }
693
700 TItem a = m_xx * matrix.xx() + m_xy * matrix.yx();
701 TItem b = m_xx * matrix.xy() + m_xy * matrix.yy();
702 TItem c = m_yx * matrix.xx() + m_yy * matrix.yx();
703 TItem d = m_yx * matrix.xy() + m_yy * matrix.yy();
704 TItem e = m_dx * matrix.xx() + m_dy * matrix.yx() + matrix.dx();
705 TItem f = m_dx * matrix.xy() + m_dy * matrix.yy() + matrix.dy();
706 m_xx = a; m_xy = b; m_yx = c; m_yy = d; m_dx = e; m_dy = f;
707 return *this;
708 }
709
715 {
716 // Find the determinant
717 TItem det = m_xx * m_yy - m_yx * m_xy;
718
719 // A zero determinant indicates a degenerate matrix.
720 return (det == 0.0);
721 }
722
727 bool invert()
728 {
729 TItem det;
730
731 // Find the determinant
732 det = m_xx * m_yy - m_yx * m_xy;
733 if (det == 0.0)
734 {
735 // This matrix cannot be inverted
736 return false;
737 }
738
739 TItem a = m_yy / det;
740 TItem b = -m_xy / det;
741 TItem c = -m_yx / det;
742 TItem d = m_xx / det;
743 TItem e = -(m_dx * m_yy - m_dy * m_yx) / det;
744 TItem f = (m_dx * m_xy - m_dy * m_xx) / det;
745 m_xx = a; m_xy = b; m_yx = c; m_yy = d; m_dx = e; m_dy = f;
746 return true;
747 }
748
750
756 void transform(PointTmpl<TItem>& result, const PointTmpl<TItem>& point, bool ignoreDXDY = false) const
757 {
758 TItem x = point.x * m_xx + point.y * m_yx;
759 TItem y = point.x * m_xy + point.y * m_yy;
760 if (!ignoreDXDY)
761 {
762 x += m_dx;
763 y += m_dy;
764 }
765 result.x = x;
766 result.y = y;
767 }
768
775 PointTmpl<TItem> transform(const PointTmpl<TItem>& point, bool ignoreDXDY = false) const
776 {
777 PointTmpl<TItem> result;
778
779 TItem x = point.x * m_xx + point.y * m_yx;
780 TItem y = point.x * m_xy + point.y * m_yy;
781 if (!ignoreDXDY)
782 {
783 x += m_dx;
784 y += m_dy;
785 }
786 result.x = x;
787 result.y = y;
788
789 return result;
790 }
791
799 bool iTransform(PointTmpl<TItem>& result, const PointTmpl<TItem>& point, bool ignoreDXDY = false) const
800 {
801 TItem det = m_xx * m_yy - m_yx * m_xy;
802 if (det == 0.0)
803 {
804 // This matrix cannot be inverted
805 return false;
806 }
807 TItem iDet = 1 / det;
808
809 TItem x = point.x;
810 TItem y = point.y;
811 if (!ignoreDXDY)
812 {
813 x -= m_dx;
814 y -= m_dy;
815 }
816
817 result.x = ((x * m_yy - y * m_yx) * iDet);
818 result.y = ((-x * m_xy + y * m_xx) * iDet);
819
820 return true;
821 }
822
830 std::pair<bool, PointTmpl<TItem> > iTransform(const PointTmpl<TItem>& point, bool ignoreDXDY = false) const
831 {
832 PointTmpl<TItem> result;
833
834 TItem det = m_xx * m_yy - m_yx * m_xy;
835 if (det == 0.0)
836 {
837 // This matrix cannot be inverted
838 return std::pair<bool, PointTmpl<TItem> >(false, result);
839 }
840 TItem iDet = 1 / det;
841
842 TItem x = point.x;
843 TItem y = point.y;
844 if (!ignoreDXDY)
845 {
846 x -= m_dx;
847 y -= m_dy;
848 }
849
850 result.x = ((x * m_yy - y * m_yx) * iDet);
851 result.y = ((-x * m_xy + y * m_xx) * iDet);
852
853 return std::pair<bool, PointTmpl<TItem> >(true, result);
854 }
855
860 void rotate(double radians)
861 {
862 constexpr double rad_90 = PI / 2.0;
863 constexpr double rad_180 = PI;
864 constexpr double rad_270 = 3.0 * PI / 2.0;
865 constexpr double rad_360 = 2.0 * PI;
866 constexpr double eps = 1.0e-6;
867
868 // Clamp to between 0 and 2*PI
869 while (radians >= rad_360)
870 radians -= rad_360;
871 while (radians < 0.0)
872 radians += rad_360;
873
875
876 if (fabs(radians) < 1.0e-6); // 0 degrees
877 else if (fabs(radians - rad_90) < eps) // 90 degrees
878 rotate = CTransformMatrix(0.0, 1.0, -1.0, 0.0, 0.0, 0.0);
879 else if (fabs(radians - rad_180) < eps) // 180 degrees
880 rotate = CTransformMatrix(-1.0, 0.0, 0.0, -1.0, 0.0, 0.0);
881 else if (fabs(radians - rad_270) < eps) // 270 degrees
882 rotate = CTransformMatrix(0.0, -1.0, 1.0, 0.0, 0.0, 0.0);
883 else
884 rotate = CTransformMatrix(cos(radians), sin(radians), -sin(radians), cos(radians), 0.0, 0.0);
885
886 preMul(rotate);
887 }
888
894 void scale(TItem xscale, TItem yscale)
895 {
896 CTransformMatrix mat(xscale, 0.0, 0.0, yscale, 0.0, 0.0);
897 preMul(mat);
898 }
899
905 void translate(TItem dx, TItem dy)
906 {
907 CTransformMatrix mat(1.0, 0.0, 0.0, 1.0, dx, dy);
908 preMul(mat);
909 }
910
915 TItem determinant() const
916 {
917 return m_xx * m_yy - m_yx * m_xy;
918 }
919
925 void transformRect(RectTmpl<TItem>& rect, bool ignoreDXDY = false) const
926 {
927 TItem llX, llY, urX, urY;
928 PointTmpl<TItem> point, transformedPoint;
929
930 if (rect.isEmpty())
931 return;
932#define EDLTMIN(a, b) (a) < (b) ? (a) : (b)
933#define EDLTMAX(a, b) (a) < (b) ? (b) : (a)
934 // Transform each of the points that make up the corners,
935 // and find the extremes.
936 point.x = rect.x;
937 point.y = rect.y;
938 transform(transformedPoint, point, ignoreDXDY);
939 llX = urX = transformedPoint.x;
940 llY = urY = transformedPoint.y;
941 point.x = rect.x + rect.dX;
942 transform(transformedPoint, point, ignoreDXDY);
943 llX = EDLTMIN(llX, transformedPoint.x);
944 llY = EDLTMIN(llY, transformedPoint.y);
945 urX = EDLTMAX(urX, transformedPoint.x);
946 urY = EDLTMAX(urY, transformedPoint.y);
947 point.y = rect.y + rect.dY;
948 transform(transformedPoint, point, ignoreDXDY);
949 llX = EDLTMIN(llX, transformedPoint.x);
950 llY = EDLTMIN(llY, transformedPoint.y);
951 urX = EDLTMAX(urX, transformedPoint.x);
952 urY = EDLTMAX(urY, transformedPoint.y);
953 point.x = rect.x;
954 transform(transformedPoint, point, ignoreDXDY);
955 llX = EDLTMIN(llX, transformedPoint.x);
956 llY = EDLTMIN(llY, transformedPoint.y);
957 urX = EDLTMAX(urX, transformedPoint.x);
958 urY = EDLTMAX(urY, transformedPoint.y);
959#undef EDLTMIN
960#undef EDLTMAX
961 rect.x = llX; rect.y = llY; rect.dX = urX - llX; rect.dY = urY - llY;
962 }
963
969 {
970 uint32 operationFlags = 0;
971
972 if ((m_dx != 0.0) || (m_dy != 0))
973 operationFlags |= eDoesTranslate;
974
975 if ((m_xy == 0) && (m_yx == 0))
976 operationFlags |= eDoesScale;
977
978 if ((m_xx == m_yy) && (m_xy == -m_yx)) {
979 operationFlags |= eDoesRotate;
980
981 double det = m_xx * m_yy - m_yx * m_xy;
982 double eps = 1.0e-06;
983
984 if (fabs(det - 1.0) > eps)
985 operationFlags |= eDoesScale;
986
987 }
988 else {
989
990 operationFlags |= eIsComplex;
991
992 }
993
994 return operationFlags;
995 }
996
997
1007 void decompose(PointTmpl<TItem>& translate, FPoint& scale, FPoint& shear, double& rotationAngle, double eps = 1.0e-06) const
1008 {
1009 // unit square decomposition of matrix ...
1010 // A={a,c}, B={b,d}, Q=angle between vectors (ie PI/2-shear angle)!
1011 // |A|=sqrt(aa+cc)
1012 // |B|=sqrt(bb+dd)
1013 // AxB=|A||B|sinQ=ad-bc=(new area of unit square)
1014 // A.B=|A||B|cosQ=ab+cd
1015
1016 // ScaleX = |A|
1017 // ScaleY = |B|
1018 // Scale = ScaleY*cos(PI/2-Q) = ScaleY*sinQ = AxB/|A|
1019 // AbsScale = abs(Scale) // effectively remove any mirror
1020 // Aspect = ScaleX/abs(Scale)
1021 // Shear = PI/2-Q = PI/2-acos((A.B)/(|A||B|))
1022 // Rotate = atan2(c,a)
1023
1024 double a = m_xx;
1025 double b = m_xy;
1026 double c = m_yx;
1027 double d = m_yy;
1028
1029 // Determine the cross product (determinant), modulus (length) of A and scale
1030 double AdotB = a * b + c * d;
1031 double ModA = ::sqrt(a * a + c * c);
1032 double ModB = ::sqrt(b * b + d * d);
1033 double pi = PI;
1034 double Shear = (pi / 2 - ::acos(AdotB / (ModB * ModA)));
1035
1036 // Set the translate
1037 translate.x = m_dx;
1038 translate.y = m_dy;
1039
1040 // Set the rotation angle
1041 if ((b == 0) || (c == 0))
1042 rotationAngle = 0;
1043 else {
1044 rotationAngle = ::atan2(c, a);
1045 if (fabs(rotationAngle) < eps)
1046 rotationAngle = 0.0;
1047 }
1048
1049 //Set the scale
1050 scale.x = ((a != 0) && (a > 0)) || ((a == 0) && (c * b <= 0)) ? ModA : -ModA;
1051 scale.y = ((d != 0) && (d > 0)) || ((d == 0) && (c * b <= 0)) ? ModB : -ModB;
1052
1053 // Set shear
1054 if (fabs(Shear) < eps) {
1055
1056 // Case: no shear
1057 shear.x = 0;
1058 shear.y = 0;
1059
1060 }
1061 else {
1062
1063 // Case: shear present.
1064 shear.x = -tan(Shear);
1065 shear.y = 0;
1066
1067 if (a == d) {
1068
1069 // Shear will handle differential x and y scaling
1070 scale.x = a;
1071 scale.y = d;
1072
1073 }
1074 }
1075
1076 }
1077
1085
1093 DecomposeInfo decompose(double eps = 1.0e-06) const
1094 {
1095 DecomposeInfo info;
1096
1097 decompose(info.translate, info.scale, info.shear, info.rotationAngle, eps);
1098
1099 return info;
1100 }
1101
1106 double getScale() const
1107 {
1108 double a = m_xx;
1109 double b = m_xy;
1110 double c = m_yx;
1111 double d = m_yy;
1112
1113 double AxB = a * d - b * c;
1114 double ModA = ::sqrt(a * a + c * c);
1115
1116 return ::fabs(AxB / ModA);
1117 }
1118
1124 bool isSimpleScaled(TItem& scale) const
1125 {
1126 bool isSimple = ((m_xx == m_yy) && (m_xy == 0) && (m_yx == 0));
1127
1128 if (isSimple)
1129 scale = m_xx;
1130
1131 return isSimple;
1132 }
1133
1139 std::pair<bool, TItem> isSimpleScaled() const
1140 {
1141 TItem scale;
1142 bool val = isSimpleScaled(scale);
1143
1144 return std::pair<bool, TItem>(val, scale);
1145 }
1146
1171 void decompose(PointTmpl<TItem>& translate, double& rotationAngle, double& shearAngle, FPoint& scale) const
1172 {
1173 CTransformMatrix<TItem> r = *this;
1174 translate = PointTmpl<TItem>(r.dx(), r.dy());
1175 r.setDX(0);
1176 r.setDY(0);
1177 {
1178 PointTmpl<TItem> point(1, 0);
1179 r.transform(point, point);
1180 rotationAngle = atan2(point.y, point.x);
1181 {
1183 rotate.rotate(-rotationAngle);
1184 r.postMul(rotate);
1185 }
1186 r.setXY(0);
1187 }
1188 {
1189 PointTmpl<TItem> point(0, 1);
1190 r.transform(point, point);
1191 shearAngle = (PI / 2.0) - atan2(point.y, point.x);
1192 if (shearAngle < -(PI / 2.0))
1193 {
1194 shearAngle += PI;
1195 }
1196 else if (shearAngle > (PI / 2.0))
1197 {
1198 shearAngle -= PI;
1199 }
1200 r.setYX(0);
1201 }
1202 scale = FPoint(r.xx(), r.yy());
1203 }
1204
1219 void compose(const PointTmpl<TItem>& translateAmount, double rotationAngle, double shearAngle, const FPoint& scaleAmount)
1220 {
1221 // Reset
1222 set();
1223
1224 // First translate
1225 translate(translateAmount.x, translateAmount.y);
1226
1227 // Then rotate
1228 rotate(rotationAngle);
1229
1230 // Then the shear. Must be less than +/- PI/2.
1231 if (shearAngle < -(PI / 2.0) || shearAngle >(PI / 2.0))
1232 {
1234 }
1235 double shearAmount = tan(shearAngle);
1236 CTransformMatrix<TItem> shearMat(1, 0, (TItem)shearAmount, 1, 0, 0);
1237 preMul(shearMat);
1238
1239 // Finally scale
1240 scale((TItem)scaleAmount.x, (TItem)scaleAmount.y);
1241 }
1242
1247 template <typename AType>
1248 void asArray(AType* array) const
1249 {
1250 if (!array)
1251 {
1253 }
1254 array[0] = (AType)m_xx;
1255 array[1] = (AType)m_xy;
1256 array[2] = (AType)m_yx;
1257 array[3] = (AType)m_yy;
1258 array[4] = (AType)m_dx;
1259 array[5] = (AType)m_dy;
1260 }
1261
1262 private:
1263 TItem m_xx, m_xy, m_yx, m_yy, m_dx, m_dy;
1264};
1265
1267
1269
1270#endif /* EDLGEOM_H */
Template for a PDF-style box. Similar to a rectangle but specified using a left, bottom,...
Definition edlgeom.h:350
void scale(PointType s)
Definition edlgeom.h:419
void normalize()
Definition edlgeom.h:395
void offset(PointType x, PointType y)
Definition edlgeom.h:411
bool equal(const BoxTmpl< PointType > &other) const
Definition edlgeom.h:427
double top
Definition edlgeom.h:437
BoxTmpl(const RectTmpl< PointType > &rect)
Definition edlgeom.h:363
BoxTmpl(BoxTmpl< PointType > &&p)=default
RectTmpl< PointType > asRect() const
Definition edlgeom.h:385
BoxTmpl()
Definition edlgeom.h:352
double bottom
Definition edlgeom.h:436
BoxTmpl(PointType _left, PointType _bottom, PointType _right, PointType _top)
Definition edlgeom.h:355
BoxTmpl(const BoxTmpl< PointType > &b)
Definition edlgeom.h:359
double right
Definition edlgeom.h:438
BoxTmpl< PointType > & operator=(const BoxTmpl< PointType > &other)=default
double left
Definition edlgeom.h:435
Definition edlvector.h:30
Matrix class - special 3x2 matrix.
Definition edlgeom.h:448
CTransformMatrix< TItem > & preMul(const CTransformMatrix< TItem > &matrix)
Premultiply by the given matrix.
Definition edlgeom.h:682
CTransformMatrix< TItem > & postMul(const CTransformMatrix< TItem > &matrix)
Postmultiply by the given matrix.
Definition edlgeom.h:699
TItem xy() const
Fetch the xy component.
Definition edlgeom.h:555
void decompose(PointTmpl< TItem > &translate, double &rotationAngle, double &shearAngle, FPoint &scale) const
Similar to the other form of decompose, but does the decomposition in a different,...
Definition edlgeom.h:1171
void transform(PointTmpl< TItem > &result, const PointTmpl< TItem > &point, bool ignoreDXDY=false) const
Transform a point.
Definition edlgeom.h:756
bool equal(const CTransformMatrix< TItem > &matrix, bool ignoreDXDY=false) const
Compare to another matrix.
Definition edlgeom.h:623
void decompose(PointTmpl< TItem > &translate, FPoint &scale, FPoint &shear, double &rotationAngle, double eps=1.0e-06) const
Decompose the transform into an equivalent set of translate + scale + shear + rotate.
Definition edlgeom.h:1007
bool degenerate()
Check to see if the matrix is degenerate (0 scale).
Definition edlgeom.h:714
CTransformMatrix(const CTransformMatrix< TItem > &m)
Copy constructor.
Definition edlgeom.h:488
bool invert()
Invert the matrix.
Definition edlgeom.h:727
TItem yy() const
Fetch the yy component.
Definition edlgeom.h:567
bool identity(bool ignoreDXDY=false) const
Determine if identity matrix.
Definition edlgeom.h:639
CTransformMatrix()
Initializes the matrix to identity.
Definition edlgeom.h:464
CTransformMatrix(TItem _xx, TItem _xy, TItem _yx, TItem _yy, TItem _dx, TItem _dy)
Initializes the matrix.
Definition edlgeom.h:479
double getScale() const
Determine the average scale of the transform.
Definition edlgeom.h:1106
TItem dy() const
Fetch the dy component.
Definition edlgeom.h:579
void translate(TItem dx, TItem dy)
Translate.
Definition edlgeom.h:905
TItem xx() const
Fetch the xx component.
Definition edlgeom.h:549
void compose(const PointTmpl< TItem > &translateAmount, double rotationAngle, double shearAngle, const FPoint &scaleAmount)
Undo the second form of decompose above. It starts with an identity matrix and applies the transforms...
Definition edlgeom.h:1219
void set(TItem _xx=1, TItem _xy=0, TItem _yx=0, TItem _yy=1, TItem _dx=0, TItem _dy=0)
Set the matrix parameters.
Definition edlgeom.h:540
bool isSimpleScaled(TItem &scale) const
Determine if the transform is merely a scale, and if so, populate the scale.
Definition edlgeom.h:1124
TItem dx() const
Fetch the dx component.
Definition edlgeom.h:573
PointTmpl< TItem > transform(const PointTmpl< TItem > &point, bool ignoreDXDY=false) const
Transform a point.
Definition edlgeom.h:775
void setDX(TItem x)
Sets the dx component.
Definition edlgeom.h:609
DecomposeInfo decompose(double eps=1.0e-06) const
Decompose the transform into an equivalent set of translate + scale + shear + rotate but return the r...
Definition edlgeom.h:1093
void transformRect(RectTmpl< TItem > &rect, bool ignoreDXDY=false) const
Transform a rectangle.
Definition edlgeom.h:925
CTransformMatrix & operator=(const CTransformMatrix< TItem > &m)
Assignment operator.
Definition edlgeom.h:498
bool ortho(bool &rotated) const
Determine if the matrix is orthogonal. That is, if the matrix is aligned to the x and y axes....
Definition edlgeom.h:659
void setYY(TItem x)
Sets the yy component.
Definition edlgeom.h:603
std::pair< bool, PointTmpl< TItem > > iTransform(const PointTmpl< TItem > &point, bool ignoreDXDY=false) const
Transform a point by the inverse of the matrix.
Definition edlgeom.h:830
TItem determinant() const
Find the determinant of the matrix.
Definition edlgeom.h:915
void setXX(TItem x)
Sets the xx component.
Definition edlgeom.h:585
void scale(TItem xscale, TItem yscale)
Scale.
Definition edlgeom.h:894
void setXY(TItem x)
Sets the xy component.
Definition edlgeom.h:591
std::pair< bool, TItem > isSimpleScaled() const
Determine if the transform is merely a scale, and if so, return that scale.
Definition edlgeom.h:1139
void rotate(double radians)
Add a rotation, clockwise, in radians.
Definition edlgeom.h:860
void setDY(TItem x)
Sets the dy component.
Definition edlgeom.h:615
bool iTransform(PointTmpl< TItem > &result, const PointTmpl< TItem > &point, bool ignoreDXDY=false) const
Transform a point by the inverse of the matrix.
Definition edlgeom.h:799
uint32 classify() const
Classify the transform.
Definition edlgeom.h:968
void asArray(AType *array) const
Retrieve the matrix as an array of the given type.
Definition edlgeom.h:1248
CTransformMatrix(const RectTmpl< TItem > &sourceRect, const RectTmpl< TItem > &destRect)
Creates a matrix that transforms from one rectangle to another.
Definition edlgeom.h:518
TItem yx() const
Fetch the yx component.
Definition edlgeom.h:561
void setYX(TItem x)
Sets the yx component.
Definition edlgeom.h:597
Geometry primitives including: point, rectangle and matrix types supporting both integer and floating...
Definition edlgeom.h:29
double y
Definition edlgeom.h:88
PointTmpl< PointType > & operator+=(const PointTmpl< PointType > &pt)
Definition edlgeom.h:45
PointTmpl(PointType ax, PointType ay)
Definition edlgeom.h:35
PointTmpl()
Definition edlgeom.h:31
bool operator!=(const PointTmpl &point) const
Definition edlgeom.h:62
double x
Definition edlgeom.h:87
bool operator==(const PointTmpl &point) const
Definition edlgeom.h:57
PointTmpl< PointType > & operator=(const PointTmpl< PointType > &other)=default
bool equal(const PointTmpl &point) const
Definition edlgeom.h:52
PointTmpl< PointType > getMidPoint(const PointTmpl< PointType > &pt) const
Find the mid-point between this and another point.
Definition edlgeom.h:72
PointTmpl(const PointTmpl< PointType > &p)=default
double getDistance(const PointTmpl< PointType > &pt) const
Find the distance to another point.
Definition edlgeom.h:82
PointTmpl(PointTmpl< PointType > &&p)=default
Definition edlgeom.h:111
void setEmpty()
Definition edlgeom.h:132
RectTmpl(RectTmpl< PointType > &&p)=default
double dX
Definition edlgeom.h:129
void intersectRect(const RectTmpl< PointType > &rect)
Intersect this rect with another rect. If the rects do not intersect, the result is an empty rect.
Definition edlgeom.h:254
double y
Definition edlgeom.h:128
RectTmpl(const RectTmpl< PointType > &r)=default
RectTmpl & offset(PointType offX, PointType offY)
Definition edlgeom.h:168
void unionRect(const RectTmpl< PointType > &rect)
Unite this rect with another rect.
Definition edlgeom.h:271
bool similar(const RectTmpl &rect, float epsilon) const
Definition edlgeom.h:160
RectTmpl< PointType > & operator=(const RectTmpl< PointType > &other)=default
bool isEmpty() const
Definition edlgeom.h:138
bool containsPoint(PointType px, PointType py) const
Definition edlgeom.h:322
PointType getBottom() const
Definition edlgeom.h:332
RectTmpl & inset(PointType insetX, PointType insetY)
Inset a rectangle by the given values. Will collapse to a point if the rectangle is not enough to ser...
Definition edlgeom.h:182
double dY
Definition edlgeom.h:130
PointType getRight() const
Definition edlgeom.h:327
bool operator==(const RectTmpl &rect) const
Definition edlgeom.h:149
bool equal(const RectTmpl &rect) const
Definition edlgeom.h:143
RectTmpl()
Definition edlgeom.h:113
RectTmpl(PointType ax, PointType ay, PointType adX, PointType adY)
Definition edlgeom.h:117
bool operator!=(const RectTmpl &rect) const
Definition edlgeom.h:155
bool expandToPoint(const PointTmpl< PointType > &point)
Expand this rect if necessary to include point.
Definition edlgeom.h:214
bool intersectsWithRect(const RectTmpl< PointType > &rect) const
Does this rect intersect with another rect?
Definition edlgeom.h:295
double x
Definition edlgeom.h:127
bool containsRect(const RectTmpl< PointType > &rect) const
Does this rectangle completely contain the given rect?
Definition edlgeom.h:303
EDL_API void throwEDLError(uint32 errorcode)
Utility - Throw an IEDLError exception with the given error code.
const PointTmpl< PointType > operator-(const PointTmpl< PointType > &lhp, const PointTmpl< PointType > &rhp)
Definition edlgeom.h:97
#define EDLTMIN(a, b)
PointTmpl< double > FPoint
Definition edlgeom.h:102
#define EDLTMAX(a, b)
CTransformMatrix< double > FMatrix
Definition edlgeom.h:1266
BoxTmpl< double > FBox
Definition edlgeom.h:441
RectTmpl< double > FRect
Definition edlgeom.h:338
RectTmpl< int64 > Int64Rect
Definition edlgeom.h:340
RectTmpl< int32 > IntRect
Definition edlgeom.h:339
const PointTmpl< PointType > operator+(const PointTmpl< PointType > &lhp, const PointTmpl< PointType > &rhp)
Definition edlgeom.h:92
BoxTmpl< int32 > IntBox
Definition edlgeom.h:442
CEDLVector< FPoint > CFPointVect
Definition edlgeom.h:106
PointTmpl< int32 > IntPoint
Definition edlgeom.h:103
PointTmpl< uint32 > UIntPoint
Definition edlgeom.h:104
PointTmpl< int64 > Int64Point
Definition edlgeom.h:105
BoxTmpl< int64 > Int64Box
Definition edlgeom.h:443
(very thin) portability layer around operating system provided math functionality but also includes a...
#define PI
Local definition of PI to 20 decimal places.
Definition edlmath.h:25
#define _BEGIN_EDL_NAMESPACE
Definition edlnamespaces.h:75
#define _END_EDL_NAMESPACE
Definition edlnamespaces.h:76
EDL "standard" types including known bit-length signed and unsigned integer type[def]s and definition...
unsigned int uint32
Definition edltypes.h:34
Simple template vector class for general use.
@ EDL_ERR_BAD_ARGUMENTS
General error for bad arguments passed to an API function.
Definition edlerrors.h:42
eOperationTypes
Classification of operation type flags of the transform.
Definition edlgeom.h:454
@ eIsComplex
Definition edlgeom.h:458
@ eDoesScale
Definition edlgeom.h:456
@ eDoesTranslate
Definition edlgeom.h:455
@ eDoesRotate
Definition edlgeom.h:457
Definition edlgeom.h:1079
double rotationAngle
Definition edlgeom.h:1083
FPoint scale
Definition edlgeom.h:1081
PointTmpl< TItem > translate
Definition edlgeom.h:1080
FPoint shear
Definition edlgeom.h:1082