xref: /haiku/headers/libs/agg/agg_trans_perspective.h (revision 820dca4df6c7bf955c46e8f6521b9408f50b2900)
1 //----------------------------------------------------------------------------
2 // Anti-Grain Geometry - Version 2.4
3 // Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com)
4 //
5 // Permission to copy, use, modify, sell and distribute this software
6 // is granted provided this copyright notice appears in all copies.
7 // This software is provided "as is" without express or implied
8 // warranty, and with no claim as to its suitability for any purpose.
9 //
10 //----------------------------------------------------------------------------
11 // Contact: mcseem@antigrain.com
12 //          mcseemagg@yahoo.com
13 //          http://www.antigrain.com
14 //----------------------------------------------------------------------------
15 //
16 // Perspective 2D transformations
17 //
18 //----------------------------------------------------------------------------
19 #ifndef AGG_TRANS_PERSPECTIVE_INCLUDED
20 #define AGG_TRANS_PERSPECTIVE_INCLUDED
21 
22 #include "agg_basics.h"
23 #include "agg_simul_eq.h"
24 
25 namespace agg
26 {
27     //=======================================================trans_perspective
28     class trans_perspective
29     {
30     public:
31         //--------------------------------------------------------------------
32         trans_perspective() : m_valid(false) {}
33 
34 
35         //--------------------------------------------------------------------
36         // Arbitrary quadrangle transformations
37         trans_perspective(const double* src, const double* dst)
38         {
39             quad_to_quad(src, dst);
40         }
41 
42 
43         //--------------------------------------------------------------------
44         // Direct transformations
45         trans_perspective(double x1, double y1, double x2, double y2,
46                           const double* quad)
47         {
48             rect_to_quad(x1, y1, x2, y2, quad);
49         }
50 
51 
52         //--------------------------------------------------------------------
53         // Reverse transformations
54         trans_perspective(const double* quad,
55                           double x1, double y1, double x2, double y2)
56         {
57             quad_to_rect(quad, x1, y1, x2, y2);
58         }
59 
60 
61         //--------------------------------------------------------------------
62         // Set the transformations using two arbitrary quadrangles.
63         void quad_to_quad(const double* src, const double* dst)
64         {
65 
66             double left[8][8];
67             double right[8][1];
68 
69             unsigned i;
70             for (i = 0; i < 4; i++)
71             {
72                 unsigned ix = i * 2;
73                 unsigned iy = ix + 1;
74 
75                 left[ix][0]  =  1.0;
76                 left[ix][1]  =  src[ix];
77                 left[ix][2]  =  src[iy];
78                 left[ix][3]  =  0.0;
79                 left[ix][4]  =  0.0;
80                 left[ix][5]  =  0.0;
81                 left[ix][6]  = -src[ix] * dst[ix];
82                 left[ix][7]  = -src[iy] * dst[ix];
83                 right[ix][0] =  dst[ix];
84 
85                 left[iy][0]  =  0.0;
86                 left[iy][1]  =  0.0;
87                 left[iy][2]  =  0.0;
88                 left[iy][3]  =  1.0;
89                 left[iy][4]  =  src[ix];
90                 left[iy][5]  =  src[iy];
91                 left[iy][6]  = -src[ix] * dst[iy];
92                 left[iy][7]  = -src[iy] * dst[iy];
93                 right[iy][0] =  dst[iy];
94             }
95             m_valid = simul_eq<8, 1>::solve(left, right, m_mtx);
96         }
97 
98 
99         //--------------------------------------------------------------------
100         // Set the direct transformations, i.e., rectangle -> quadrangle
101         void rect_to_quad(double x1, double y1, double x2, double y2,
102                           const double* quad)
103         {
104             double src[8];
105             src[0] = src[6] = x1;
106             src[2] = src[4] = x2;
107             src[1] = src[3] = y1;
108             src[5] = src[7] = y2;
109             quad_to_quad(src, quad);
110         }
111 
112 
113         //--------------------------------------------------------------------
114         // Set the reverse transformations, i.e., quadrangle -> rectangle
115         void quad_to_rect(const double* quad,
116                           double x1, double y1, double x2, double y2)
117         {
118             double dst[8];
119             dst[0] = dst[6] = x1;
120             dst[2] = dst[4] = x2;
121             dst[1] = dst[3] = y1;
122             dst[5] = dst[7] = y2;
123             quad_to_quad(quad, dst);
124         }
125 
126         //--------------------------------------------------------------------
127         // Check if the equations were solved successfully
128         bool is_valid() const { return m_valid; }
129 
130         //--------------------------------------------------------------------
131         // Transform a point (x, y)
132         void transform(double* x, double* y) const
133         {
134             double tx = *x;
135             double ty = *y;
136             double d = 1.0 / (m_mtx[6][0] * tx + m_mtx[7][0] * ty + 1.0);
137             *x = (m_mtx[0][0] + m_mtx[1][0] * tx + m_mtx[2][0] * ty) * d;
138             *y = (m_mtx[3][0] + m_mtx[4][0] * tx + m_mtx[5][0] * ty) * d;
139         }
140 
141         //--------------------------------------------------------------------
142         class iterator_x
143         {
144             double den;
145             double den_step;
146             double nom_x;
147             double nom_x_step;
148             double nom_y;
149             double nom_y_step;
150 
151         public:
152             double x;
153             double y;
154 
155             iterator_x() {}
156             iterator_x(double tx, double ty, double step, const double m[8][1]) :
157                 den(m[6][0] * tx + m[7][0] * ty + 1.0),
158                 den_step(m[6][0] * step),
159                 nom_x(m[0][0] + m[1][0] * tx + m[2][0] * ty),
160                 nom_x_step(m[1][0] * step),
161                 nom_y(m[3][0] + m[4][0] * tx + m[5][0] * ty),
162                 nom_y_step(m[4][0] * step),
163                 x(nom_x / den),
164                 y(nom_y / den)
165             {
166             }
167 
168             void operator ++ ()
169             {
170                 den   += den_step;
171                 nom_x += nom_x_step;
172                 nom_y += nom_y_step;
173                 double d = 1.0 / den;
174                 x = nom_x * d;
175                 y = nom_y * d;
176             }
177         };
178 
179         //--------------------------------------------------------------------
180         iterator_x begin(double x, double y, double step) const
181         {
182             return iterator_x(x, y, step, m_mtx);
183         }
184 
185     private:
186         double m_mtx[8][1];
187         bool   m_valid;
188     };
189 
190 }
191 
192 #endif
193