Mako 8.2.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{
112public:
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{
449public:
454 typedef enum {
460
465 {
466 set();
467 }
468
479 CTransformMatrix(TItem _xx, TItem _xy, TItem _yx, TItem _yy, TItem _dx, TItem _dy) {
480 set(_xx, _xy, _yx, _yy, _dx, _dy);/*type = BMAT_NONE*/;
481 }
482
488 {
489 *this = m;
490 }
491
498 {
499 if (this != &m)
500 {
501 m_xx = m.m_xx;
502 m_xy = m.m_xy;
503 m_yx = m.m_yx;
504 m_yy = m.m_yy;
505 m_dx = m.m_dx;
506 m_dy = m.m_dy;
507 }
508 return *this;
509 }
510
517 CTransformMatrix(const RectTmpl<TItem>& sourceRect, const RectTmpl<TItem>& destRect)
518 {
519 set();
520 if (sourceRect.dX > 0 && destRect.dX > 0 && sourceRect.dY > 0 && destRect.dY > 0)
521 {
522 m_xx = destRect.dX / sourceRect.dX;
523 m_yy = destRect.dY / sourceRect.dY;
524 m_dx = destRect.x - sourceRect.x * m_xx;
525 m_dy = destRect.y - sourceRect.y * m_yy;
526 }
527 }
528
539 void set(TItem _xx = 1, TItem _xy = 0, TItem _yx = 0, TItem _yy = 1, TItem _dx = 0, TItem _dy = 0)
540 {
541 m_xx = _xx; m_xy = _xy; m_yx = _yx; m_yy = _yy; m_dx = _dx; m_dy = _dy;
542 }
543
548 TItem xx()const { return m_xx; }
549
554 TItem xy()const { return m_xy; }
555
560 TItem yx()const { return m_yx; }
561
566 TItem yy()const { return m_yy; }
567
572 TItem dx()const { return m_dx; }
573
578 TItem dy()const { return m_dy; }
579
584 void setXX(TItem x) { m_xx = x; }
585
590 void setXY(TItem x) { m_xy = x; }
591
596 void setYX(TItem x) { m_yx = x; }
597
602 void setYY(TItem x) { m_yy = x; }
603
608 void setDX(TItem x) { m_dx = x; }
609
614 void setDY(TItem x) { m_dy = x; }
615
622 bool equal(const CTransformMatrix<TItem>& matrix, bool ignoreDXDY = false) const
623 {
624 return (m_xx == matrix.xx()) &&
625 (m_xy == matrix.xy()) &&
626 (m_yx == matrix.yx()) &&
627 (m_yy == matrix.yy()) &&
628 (ignoreDXDY || (
629 (m_dx == matrix.dx()) &&
630 (m_dy == matrix.dy())));
631 }
632
638 bool identity(bool ignoreDXDY = false) const
639 {
640 return (m_xx == 1.0) &&
641 (m_xy == 0.0) &&
642 (m_yx == 0.0) &&
643 (m_yy == 1.0) &&
644 (ignoreDXDY || (
645 (m_dx == 0.0) &&
646 (m_dy == 0.0)));
647 }
648
655 TItem a = matrix.xx() * m_xx + matrix.xy() * m_yx;
656 TItem b = matrix.xx() * m_xy + matrix.xy() * m_yy;
657 TItem c = matrix.yx() * m_xx + matrix.yy() * m_yx;
658 TItem d = matrix.yx() * m_xy + matrix.yy() * m_yy;
659 TItem e = matrix.dx() * m_xx + matrix.dy() * m_yx + m_dx;
660 TItem f = matrix.dx() * m_xy + matrix.dy() * m_yy + m_dy;
661 m_xx = a; m_xy = b; m_yx = c; m_yy = d; m_dx = e; m_dy = f;
662 return *this;
663 }
664
671 TItem a = m_xx * matrix.xx() + m_xy * matrix.yx();
672 TItem b = m_xx * matrix.xy() + m_xy * matrix.yy();
673 TItem c = m_yx * matrix.xx() + m_yy * matrix.yx();
674 TItem d = m_yx * matrix.xy() + m_yy * matrix.yy();
675 TItem e = m_dx * matrix.xx() + m_dy * matrix.yx() + matrix.dx();
676 TItem f = m_dx * matrix.xy() + m_dy * matrix.yy() + matrix.dy();
677 m_xx = a; m_xy = b; m_yx = c; m_yy = d; m_dx = e; m_dy = f;
678 return *this;
679 }
680
685 bool degenerate() {
686 // Find the determinant
687 TItem det = m_xx * m_yy - m_yx * m_xy;
688
689 // A zero determinant indicates a degenerate matrix.
690 return (det == 0.0);
691 }
692
697 bool invert() {
698 TItem det;
699
700 // Find the determinant
701 det = m_xx * m_yy - m_yx * m_xy;
702 if (det == 0.0)
703 {
704 // This matrix cannot be inverted
705 return false;
706 }
707
708 TItem a = m_yy / det;
709 TItem b = -m_xy / det;
710 TItem c = -m_yx / det;
711 TItem d = m_xx / det;
712 TItem e = -(m_dx * m_yy - m_dy * m_yx) / det;
713 TItem f = (m_dx * m_xy - m_dy * m_xx) / det;
714 m_xx = a; m_xy = b; m_yx = c; m_yy = d; m_dx = e; m_dy = f;
715 return true;
716 }
717
719
725 void transform(PointTmpl<TItem>& result, const PointTmpl<TItem>& point, bool ignoreDXDY = false) const
726 {
727 TItem x = point.x * m_xx + point.y * m_yx;
728 TItem y = point.x * m_xy + point.y * m_yy;
729 if (!ignoreDXDY)
730 {
731 x += m_dx;
732 y += m_dy;
733 }
734 result.x = x;
735 result.y = y;
736 }
737
744 PointTmpl<TItem> transform(const PointTmpl<TItem>& point, bool ignoreDXDY = false) const
745 {
746 PointTmpl<TItem> result;
747
748 TItem x = point.x * m_xx + point.y * m_yx;
749 TItem y = point.x * m_xy + point.y * m_yy;
750 if (!ignoreDXDY)
751 {
752 x += m_dx;
753 y += m_dy;
754 }
755 result.x = x;
756 result.y = y;
757
758 return result;
759 }
760
768 bool iTransform(PointTmpl<TItem>& result, const PointTmpl<TItem>& point, bool ignoreDXDY = false) const
769 {
770 TItem det = m_xx * m_yy - m_yx * m_xy;
771 if (det == 0.0)
772 {
773 // This matrix cannot be inverted
774 return false;
775 }
776 TItem iDet = 1 / det;
777
778 TItem x = point.x;
779 TItem y = point.y;
780 if (!ignoreDXDY)
781 {
782 x -= m_dx;
783 y -= m_dy;
784 }
785
786 result.x = ((x * m_yy - y * m_yx) * iDet);
787 result.y = ((-x * m_xy + y * m_xx) * iDet);
788
789 return true;
790 }
791
798 std::pair<bool, PointTmpl<TItem> > iTransform(const PointTmpl<TItem>& point, bool ignoreDXDY = false) const
799 {
800 PointTmpl<TItem> result;
801
802 TItem det = m_xx * m_yy - m_yx * m_xy;
803 if (det == 0.0)
804 {
805 // This matrix cannot be inverted
806 return std::pair<bool, PointTmpl<TItem> >(false, result);
807 }
808 TItem iDet = 1 / det;
809
810 TItem x = point.x;
811 TItem y = point.y;
812 if (!ignoreDXDY)
813 {
814 x -= m_dx;
815 y -= m_dy;
816 }
817
818 result.x = ((x * m_yy - y * m_yx) * iDet);
819 result.y = ((-x * m_xy + y * m_xx) * iDet);
820
821 return std::pair<bool, PointTmpl<TItem> >(true, result);
822 }
823
828 void rotate(double radians)
829 {
830 constexpr double rad_90 = PI / 2.0;
831 constexpr double rad_180 = PI;
832 constexpr double rad_270 = 3.0 * PI / 2.0;
833 constexpr double rad_360 = 2.0 * PI;
834 constexpr double eps = 1.0e-6;
835
836 // Clamp to between 0 and 2*PI
837 while (radians >= rad_360)
838 radians -= rad_360;
839 while (radians < 0.0)
840 radians += rad_360;
841
843
844 if (fabs(radians) < 1.0e-6); // 0 degrees
845 else if (fabs(radians - rad_90) < eps) // 90 degrees
846 rotate = CTransformMatrix(0.0, 1.0, -1.0, 0.0, 0.0, 0.0);
847 else if (fabs(radians - rad_180) < eps) // 180 degrees
848 rotate = CTransformMatrix(-1.0, 0.0, 0.0, -1.0, 0.0, 0.0);
849 else if (fabs(radians - rad_270) < eps) // 270 degrees
850 rotate = CTransformMatrix(0.0, -1.0, 1.0, 0.0, 0.0, 0.0);
851 else
852 rotate = CTransformMatrix(cos(radians), sin(radians), -sin(radians), cos(radians), 0.0, 0.0);
853
854 preMul(rotate);
855 }
856
862 void scale(TItem xscale, TItem yscale)
863 {
864 CTransformMatrix mat(xscale, 0.0, 0.0, yscale, 0.0, 0.0);
865 preMul(mat);
866 }
867
873 void translate(TItem dx, TItem dy)
874 {
875 CTransformMatrix mat(1.0, 0.0, 0.0, 1.0, dx, dy);
876 preMul(mat);
877 }
878
883 TItem determinant() const
884 {
885 return m_xx * m_yy - m_yx * m_xy;
886 }
887
889
894 void transformRect(RectTmpl<TItem>& rect, bool ignoreDXDY = false) const
895 {
896 TItem llX, llY, urX, urY;
897 PointTmpl<TItem> point, transformedPoint;
898
899 if (rect.isEmpty())
900 return;
901#define EDLTMIN(a, b) (a) < (b) ? (a) : (b)
902#define EDLTMAX(a, b) (a) < (b) ? (b) : (a)
903 // Transform each of the points that make up the corners,
904 // and find the extremes.
905 point.x = rect.x;
906 point.y = rect.y;
907 transform(transformedPoint, point, ignoreDXDY);
908 llX = urX = transformedPoint.x;
909 llY = urY = transformedPoint.y;
910 point.x = rect.x + rect.dX;
911 transform(transformedPoint, point, ignoreDXDY);
912 llX = EDLTMIN(llX, transformedPoint.x);
913 llY = EDLTMIN(llY, transformedPoint.y);
914 urX = EDLTMAX(urX, transformedPoint.x);
915 urY = EDLTMAX(urY, transformedPoint.y);
916 point.y = rect.y + rect.dY;
917 transform(transformedPoint, point, ignoreDXDY);
918 llX = EDLTMIN(llX, transformedPoint.x);
919 llY = EDLTMIN(llY, transformedPoint.y);
920 urX = EDLTMAX(urX, transformedPoint.x);
921 urY = EDLTMAX(urY, transformedPoint.y);
922 point.x = rect.x;
923 transform(transformedPoint, point, ignoreDXDY);
924 llX = EDLTMIN(llX, transformedPoint.x);
925 llY = EDLTMIN(llY, transformedPoint.y);
926 urX = EDLTMAX(urX, transformedPoint.x);
927 urY = EDLTMAX(urY, transformedPoint.y);
928#undef EDLTMIN
929#undef EDLTMAX
930 rect.x = llX; rect.y = llY; rect.dX = urX - llX; rect.dY = urY - llY;
931 }
932
938 {
939 uint32 operationFlags = 0;
940
941 if ((m_dx != 0.0) || (m_dy != 0))
942 operationFlags |= eDoesTranslate;
943
944 if ((m_xy == 0) && (m_yx == 0))
945 operationFlags |= eDoesScale;
946
947 if ((m_xx == m_yy) && (m_xy == -m_yx)) {
948 operationFlags |= eDoesRotate;
949
950 double det = m_xx * m_yy - m_yx * m_xy;
951 double eps = 1.0e-06;
952
953 if (fabs(det - 1.0) > eps)
954 operationFlags |= eDoesScale;
955
956 }
957 else {
958
959 operationFlags |= eIsComplex;
960
961 }
962
963 return operationFlags;
964 }
965
966
967 // Decompose the transform into an equivalent set of translate + scale + shear + rotate
968 void decompose(PointTmpl<TItem>& translate, FPoint& scale, FPoint& shear, double& rotationAngle, double eps = 1.0e-06) const
969 {
970 // unit square decomposition of matrix ...
971 // A={a,c}, B={b,d}, Q=angle between vectors (ie PI/2-shear angle)!
972 // |A|=sqrt(aa+cc)
973 // |B|=sqrt(bb+dd)
974 // AxB=|A||B|sinQ=ad-bc=(new area of unit square)
975 // A.B=|A||B|cosQ=ab+cd
976
977 // ScaleX = |A|
978 // ScaleY = |B|
979 // Scale = ScaleY*cos(PI/2-Q) = ScaleY*sinQ = AxB/|A|
980 // AbsScale = abs(Scale) // effectively remove any mirror
981 // Aspect = ScaleX/abs(Scale)
982 // Shear = PI/2-Q = PI/2-acos((A.B)/(|A||B|))
983 // Rotate = atan2(c,a)
984
985 double a = m_xx;
986 double b = m_xy;
987 double c = m_yx;
988 double d = m_yy;
989
990 // get cross product (determinant), modulus (length) of A and scale
991// double AxB = a*d-b*c;
992 double AdotB = a * b + c * d;
993 double ModA = ::sqrt(a * a + c * c);
994 double ModB = ::sqrt(b * b + d * d);
995 double pi = PI;
996 double Shear = (pi / 2 - ::acos(AdotB / (ModB * ModA)));
997
998 // Set the translate
999 translate.x = m_dx;
1000 translate.y = m_dy;
1001
1002 // Set the rotation angle
1003 if ((b == 0) || (c == 0))
1004 rotationAngle = 0;
1005 else {
1006 rotationAngle = ::atan2(c, a);
1007 if (fabs(rotationAngle) < eps)
1008 rotationAngle = 0.0;
1009 }
1010
1011 //Set the scale
1012 scale.x = ((a != 0) && (a > 0)) || ((a == 0) && (c * b <= 0)) ? ModA : -ModA;
1013 scale.y = ((d != 0) && (d > 0)) || ((d == 0) && (c * b <= 0)) ? ModB : -ModB;
1014
1015 // Set shear
1016 if (fabs(Shear) < eps) {
1017
1018 // Case: no shear
1019 shear.x = 0;
1020 shear.y = 0;
1021
1022 }
1023 else {
1024
1025 // Case: shear present.
1026 shear.x = -tan(Shear);
1027 shear.y = 0;
1028
1029 if (a == d) {
1030
1031 // Shear will handle differential x and y scaling
1032 scale.x = a;
1033 scale.y = d;
1034
1035 }
1036 }
1037
1038 }
1039
1047
1048 DecomposeInfo decompose(double eps = 1.0e-06) const
1049 {
1050 DecomposeInfo info;
1051
1052 decompose(info.translate, info.scale, info.shear, info.rotationAngle, eps);
1053
1054 return info;
1055 }
1056
1057 double getScale() const
1058 {
1059 double a = m_xx;
1060 double b = m_xy;
1061 double c = m_yx;
1062 double d = m_yy;
1063
1064 double AxB = a * d - b * c;
1065 double ModA = ::sqrt(a * a + c * c);
1066
1067 return ::fabs(AxB / ModA);
1068 }
1069
1070 bool isSimpleScaled(TItem& scale) const
1071 {
1072 bool isSimple = ((m_xx == m_yy) && (m_xy == 0) && (m_yx == 0));
1073
1074 if (isSimple)
1075 scale = m_xx;
1076
1077 return isSimple;
1078 }
1079
1080
1081 std::pair<bool, TItem> isSimpleScaled() const
1082 {
1083 TItem scale;
1084 bool val = isSimpleScaled(scale);
1085
1086 return std::pair<bool, TItem>(val, scale);
1087 }
1088
1113 void decompose(PointTmpl<TItem>& translate, double& rotationAngle, double& shearAngle, FPoint& scale) const
1114 {
1115 CTransformMatrix<TItem> r = *this;
1116 translate = PointTmpl<TItem>(r.dx(), r.dy());
1117 r.setDX(0);
1118 r.setDY(0);
1119 {
1120 PointTmpl<TItem> point(1, 0);
1121 r.transform(point, point);
1122 rotationAngle = atan2(point.y, point.x);
1123 {
1125 rotate.rotate(-rotationAngle);
1126 r.postMul(rotate);
1127 }
1128 r.setXY(0);
1129 }
1130 {
1131 PointTmpl<TItem> point(0, 1);
1132 r.transform(point, point);
1133 shearAngle = (PI / 2.0) - atan2(point.y, point.x);
1134 if (shearAngle < -(PI / 2.0))
1135 {
1136 shearAngle += PI;
1137 }
1138 else if (shearAngle > (PI / 2.0))
1139 {
1140 shearAngle -= PI;
1141 }
1142 r.setYX(0);
1143 }
1144 scale = FPoint(r.xx(), r.yy());
1145 }
1146
1161 void compose(const PointTmpl<TItem>& translateAmount, double rotationAngle, double shearAngle, const FPoint& scaleAmount)
1162 {
1163 // Reset
1164 set();
1165
1166 // First translate
1167 translate(translateAmount.x, translateAmount.y);
1168
1169 // Then rotate
1170 rotate(rotationAngle);
1171
1172 // Then the shear. Must be less than +/- PI/2.
1173 if (shearAngle < -(PI / 2.0) || shearAngle >(PI / 2.0))
1174 {
1176 }
1177 double shearAmount = tan(shearAngle);
1178 CTransformMatrix<TItem> shearMat(1, 0, (TItem)shearAmount, 1, 0, 0);
1179 preMul(shearMat);
1180
1181 // Finally scale
1182 scale((TItem)scaleAmount.x, (TItem)scaleAmount.y);
1183 }
1184
1189 template <typename AType>
1190 void asArray(AType* array) const
1191 {
1192 if (!array)
1193 {
1195 }
1196 array[0] = (AType)m_xx;
1197 array[1] = (AType)m_xy;
1198 array[2] = (AType)m_yx;
1199 array[3] = (AType)m_yy;
1200 array[4] = (AType)m_dx;
1201 array[5] = (AType)m_dy;
1202 }
1203
1204private:
1205 TItem m_xx, m_xy, m_yx, m_yy, m_dx, m_dy;
1206};
1207
1209
1211
1212#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()
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 given matrix.
Definition edlgeom.h:654
CTransformMatrix< TItem > & postMul(const CTransformMatrix< TItem > &matrix)
Postmultiply by given matrix.
Definition edlgeom.h:670
TItem xy() const
Returns xy component.
Definition edlgeom.h:554
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:1113
void transform(PointTmpl< TItem > &result, const PointTmpl< TItem > &point, bool ignoreDXDY=false) const
Transform a point.
Definition edlgeom.h:725
bool equal(const CTransformMatrix< TItem > &matrix, bool ignoreDXDY=false) const
Compare to another matrix.
Definition edlgeom.h:622
void decompose(PointTmpl< TItem > &translate, FPoint &scale, FPoint &shear, double &rotationAngle, double eps=1.0e-06) const
Definition edlgeom.h:968
bool degenerate()
Check to see if the matrix is degenerate (0 scale)
Definition edlgeom.h:685
CTransformMatrix(const CTransformMatrix< TItem > &m)
Copy constructor.
Definition edlgeom.h:487
bool invert()
Invert the matrix.
Definition edlgeom.h:697
TItem yy() const
Returns yy component.
Definition edlgeom.h:566
bool identity(bool ignoreDXDY=false) const
Determine if identity matrix.
Definition edlgeom.h:638
CTransformMatrix()
Creates zero matrix.
Definition edlgeom.h:464
CTransformMatrix(TItem _xx, TItem _xy, TItem _yx, TItem _yy, TItem _dx, TItem _dy)
Creates the matrix elementary.
Definition edlgeom.h:479
double getScale() const
Definition edlgeom.h:1057
TItem dy() const
Returns dy component.
Definition edlgeom.h:578
void translate(TItem dx, TItem dy)
Translate.
Definition edlgeom.h:873
TItem xx() const
Returns xx component.
Definition edlgeom.h:548
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:1161
void set(TItem _xx=1, TItem _xy=0, TItem _yx=0, TItem _yy=1, TItem _dx=0, TItem _dy=0)
Create blank matrix.
Definition edlgeom.h:539
bool isSimpleScaled(TItem &scale) const
Definition edlgeom.h:1070
TItem dx() const
Returns dx component.
Definition edlgeom.h:572
PointTmpl< TItem > transform(const PointTmpl< TItem > &point, bool ignoreDXDY=false) const
Transform a point.
Definition edlgeom.h:744
void setDX(TItem x)
Sets dx component.
Definition edlgeom.h:608
DecomposeInfo decompose(double eps=1.0e-06) const
Definition edlgeom.h:1048
void transformRect(RectTmpl< TItem > &rect, bool ignoreDXDY=false) const
Transform a rectangle.
Definition edlgeom.h:894
CTransformMatrix & operator=(const CTransformMatrix< TItem > &m)
Assignment operator.
Definition edlgeom.h:497
void setYY(TItem x)
Sets yy component.
Definition edlgeom.h:602
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:798
TItem determinant() const
Find the determinant of the matrix.
Definition edlgeom.h:883
void setXX(TItem x)
Sets xx component.
Definition edlgeom.h:584
void scale(TItem xscale, TItem yscale)
Scale.
Definition edlgeom.h:862
void setXY(TItem x)
Sets xy component.
Definition edlgeom.h:590
std::pair< bool, TItem > isSimpleScaled() const
Definition edlgeom.h:1081
void rotate(double radians)
Add a rotation, clockwise, in radians.
Definition edlgeom.h:828
void setDY(TItem x)
Sets dy component.
Definition edlgeom.h:614
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:768
uint32 classify() const
Classify the transform.
Definition edlgeom.h:937
void asArray(AType *array) const
Retrieve the matrix as an array of the given type.
Definition edlgeom.h:1190
CTransformMatrix(const RectTmpl< TItem > &sourceRect, const RectTmpl< TItem > &destRect)
Creates a matrix that transforms from one rectangle to another.
Definition edlgeom.h:517
TItem yx() const
Returns yx component.
Definition edlgeom.h:560
void setYX(TItem x)
Sets yx component.
Definition edlgeom.h:596
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:1208
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:1041
double rotationAngle
Definition edlgeom.h:1045
FPoint scale
Definition edlgeom.h:1043
PointTmpl< TItem > translate
Definition edlgeom.h:1042
FPoint shear
Definition edlgeom.h:1044