xref: /haiku/headers/libs/agg/agg_trans_perspective.h (revision e39da397f5ff79f2db9f9a3ddf1852b6710578af)
139241fe2SDarkWyrm //----------------------------------------------------------------------------
2*e39da397SStephan Aßmus // Anti-Grain Geometry - Version 2.4
3*e39da397SStephan Aßmus // Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com)
439241fe2SDarkWyrm //
539241fe2SDarkWyrm // Permission to copy, use, modify, sell and distribute this software
639241fe2SDarkWyrm // is granted provided this copyright notice appears in all copies.
739241fe2SDarkWyrm // This software is provided "as is" without express or implied
839241fe2SDarkWyrm // warranty, and with no claim as to its suitability for any purpose.
939241fe2SDarkWyrm //
1039241fe2SDarkWyrm //----------------------------------------------------------------------------
1139241fe2SDarkWyrm // Contact: mcseem@antigrain.com
1239241fe2SDarkWyrm //          mcseemagg@yahoo.com
1339241fe2SDarkWyrm //          http://www.antigrain.com
1439241fe2SDarkWyrm //----------------------------------------------------------------------------
1539241fe2SDarkWyrm //
1639241fe2SDarkWyrm // Perspective 2D transformations
1739241fe2SDarkWyrm //
1839241fe2SDarkWyrm //----------------------------------------------------------------------------
1939241fe2SDarkWyrm #ifndef AGG_TRANS_PERSPECTIVE_INCLUDED
2039241fe2SDarkWyrm #define AGG_TRANS_PERSPECTIVE_INCLUDED
2139241fe2SDarkWyrm 
2239241fe2SDarkWyrm #include "agg_basics.h"
2339241fe2SDarkWyrm #include "agg_simul_eq.h"
2439241fe2SDarkWyrm 
2539241fe2SDarkWyrm namespace agg
2639241fe2SDarkWyrm {
2739241fe2SDarkWyrm     //=======================================================trans_perspective
2839241fe2SDarkWyrm     class trans_perspective
2939241fe2SDarkWyrm     {
3039241fe2SDarkWyrm     public:
3139241fe2SDarkWyrm         //--------------------------------------------------------------------
3239241fe2SDarkWyrm         trans_perspective() : m_valid(false) {}
3339241fe2SDarkWyrm 
3439241fe2SDarkWyrm 
3539241fe2SDarkWyrm         //--------------------------------------------------------------------
3639241fe2SDarkWyrm         // Arbitrary quadrangle transformations
3739241fe2SDarkWyrm         trans_perspective(const double* src, const double* dst)
3839241fe2SDarkWyrm         {
3939241fe2SDarkWyrm             quad_to_quad(src, dst);
4039241fe2SDarkWyrm         }
4139241fe2SDarkWyrm 
4239241fe2SDarkWyrm 
4339241fe2SDarkWyrm         //--------------------------------------------------------------------
4439241fe2SDarkWyrm         // Direct transformations
4539241fe2SDarkWyrm         trans_perspective(double x1, double y1, double x2, double y2,
4639241fe2SDarkWyrm                           const double* quad)
4739241fe2SDarkWyrm         {
4839241fe2SDarkWyrm             rect_to_quad(x1, y1, x2, y2, quad);
4939241fe2SDarkWyrm         }
5039241fe2SDarkWyrm 
5139241fe2SDarkWyrm 
5239241fe2SDarkWyrm         //--------------------------------------------------------------------
5339241fe2SDarkWyrm         // Reverse transformations
5439241fe2SDarkWyrm         trans_perspective(const double* quad,
5539241fe2SDarkWyrm                           double x1, double y1, double x2, double y2)
5639241fe2SDarkWyrm         {
5739241fe2SDarkWyrm             quad_to_rect(quad, x1, y1, x2, y2);
5839241fe2SDarkWyrm         }
5939241fe2SDarkWyrm 
6039241fe2SDarkWyrm 
6139241fe2SDarkWyrm         //--------------------------------------------------------------------
6239241fe2SDarkWyrm         // Set the transformations using two arbitrary quadrangles.
6339241fe2SDarkWyrm         void quad_to_quad(const double* src, const double* dst)
6439241fe2SDarkWyrm         {
6539241fe2SDarkWyrm 
6639241fe2SDarkWyrm             double left[8][8];
6739241fe2SDarkWyrm             double right[8][1];
6839241fe2SDarkWyrm 
6939241fe2SDarkWyrm             unsigned i;
7039241fe2SDarkWyrm             for (i = 0; i < 4; i++)
7139241fe2SDarkWyrm             {
7239241fe2SDarkWyrm                 unsigned ix = i * 2;
7339241fe2SDarkWyrm                 unsigned iy = ix + 1;
7439241fe2SDarkWyrm 
7539241fe2SDarkWyrm                 left[ix][0]  =  1.0;
7639241fe2SDarkWyrm                 left[ix][1]  =  src[ix];
7739241fe2SDarkWyrm                 left[ix][2]  =  src[iy];
7839241fe2SDarkWyrm                 left[ix][3]  =  0.0;
7939241fe2SDarkWyrm                 left[ix][4]  =  0.0;
8039241fe2SDarkWyrm                 left[ix][5]  =  0.0;
8139241fe2SDarkWyrm                 left[ix][6]  = -src[ix] * dst[ix];
8239241fe2SDarkWyrm                 left[ix][7]  = -src[iy] * dst[ix];
8339241fe2SDarkWyrm                 right[ix][0] =  dst[ix];
8439241fe2SDarkWyrm 
8539241fe2SDarkWyrm                 left[iy][0]  =  0.0;
8639241fe2SDarkWyrm                 left[iy][1]  =  0.0;
8739241fe2SDarkWyrm                 left[iy][2]  =  0.0;
8839241fe2SDarkWyrm                 left[iy][3]  =  1.0;
8939241fe2SDarkWyrm                 left[iy][4]  =  src[ix];
9039241fe2SDarkWyrm                 left[iy][5]  =  src[iy];
9139241fe2SDarkWyrm                 left[iy][6]  = -src[ix] * dst[iy];
9239241fe2SDarkWyrm                 left[iy][7]  = -src[iy] * dst[iy];
9339241fe2SDarkWyrm                 right[iy][0] =  dst[iy];
9439241fe2SDarkWyrm             }
9539241fe2SDarkWyrm             m_valid = simul_eq<8, 1>::solve(left, right, m_mtx);
9639241fe2SDarkWyrm         }
9739241fe2SDarkWyrm 
9839241fe2SDarkWyrm 
9939241fe2SDarkWyrm         //--------------------------------------------------------------------
10039241fe2SDarkWyrm         // Set the direct transformations, i.e., rectangle -> quadrangle
10139241fe2SDarkWyrm         void rect_to_quad(double x1, double y1, double x2, double y2,
10239241fe2SDarkWyrm                           const double* quad)
10339241fe2SDarkWyrm         {
10439241fe2SDarkWyrm             double src[8];
10539241fe2SDarkWyrm             src[0] = src[6] = x1;
10639241fe2SDarkWyrm             src[2] = src[4] = x2;
10739241fe2SDarkWyrm             src[1] = src[3] = y1;
10839241fe2SDarkWyrm             src[5] = src[7] = y2;
10939241fe2SDarkWyrm             quad_to_quad(src, quad);
11039241fe2SDarkWyrm         }
11139241fe2SDarkWyrm 
11239241fe2SDarkWyrm 
11339241fe2SDarkWyrm         //--------------------------------------------------------------------
11439241fe2SDarkWyrm         // Set the reverse transformations, i.e., quadrangle -> rectangle
11539241fe2SDarkWyrm         void quad_to_rect(const double* quad,
11639241fe2SDarkWyrm                           double x1, double y1, double x2, double y2)
11739241fe2SDarkWyrm         {
11839241fe2SDarkWyrm             double dst[8];
11939241fe2SDarkWyrm             dst[0] = dst[6] = x1;
12039241fe2SDarkWyrm             dst[2] = dst[4] = x2;
12139241fe2SDarkWyrm             dst[1] = dst[3] = y1;
12239241fe2SDarkWyrm             dst[5] = dst[7] = y2;
12339241fe2SDarkWyrm             quad_to_quad(quad, dst);
12439241fe2SDarkWyrm         }
12539241fe2SDarkWyrm 
12639241fe2SDarkWyrm         //--------------------------------------------------------------------
12739241fe2SDarkWyrm         // Check if the equations were solved successfully
12839241fe2SDarkWyrm         bool is_valid() const { return m_valid; }
12939241fe2SDarkWyrm 
13039241fe2SDarkWyrm         //--------------------------------------------------------------------
13139241fe2SDarkWyrm         // Transform a point (x, y)
13239241fe2SDarkWyrm         void transform(double* x, double* y) const
13339241fe2SDarkWyrm         {
13439241fe2SDarkWyrm             double tx = *x;
13539241fe2SDarkWyrm             double ty = *y;
13639241fe2SDarkWyrm             double d = 1.0 / (m_mtx[6][0] * tx + m_mtx[7][0] * ty + 1.0);
13739241fe2SDarkWyrm             *x = (m_mtx[0][0] + m_mtx[1][0] * tx + m_mtx[2][0] * ty) * d;
13839241fe2SDarkWyrm             *y = (m_mtx[3][0] + m_mtx[4][0] * tx + m_mtx[5][0] * ty) * d;
13939241fe2SDarkWyrm         }
14039241fe2SDarkWyrm 
141*e39da397SStephan Aßmus         //--------------------------------------------------------------------
142*e39da397SStephan Aßmus         class iterator_x
143*e39da397SStephan Aßmus         {
144*e39da397SStephan Aßmus             double den;
145*e39da397SStephan Aßmus             double den_step;
146*e39da397SStephan Aßmus             double nom_x;
147*e39da397SStephan Aßmus             double nom_x_step;
148*e39da397SStephan Aßmus             double nom_y;
149*e39da397SStephan Aßmus             double nom_y_step;
150*e39da397SStephan Aßmus 
151*e39da397SStephan Aßmus         public:
152*e39da397SStephan Aßmus             double x;
153*e39da397SStephan Aßmus             double y;
154*e39da397SStephan Aßmus 
155*e39da397SStephan Aßmus             iterator_x() {}
156*e39da397SStephan Aßmus             iterator_x(double tx, double ty, double step, const double m[8][1]) :
157*e39da397SStephan Aßmus                 den(m[6][0] * tx + m[7][0] * ty + 1.0),
158*e39da397SStephan Aßmus                 den_step(m[6][0] * step),
159*e39da397SStephan Aßmus                 nom_x(m[0][0] + m[1][0] * tx + m[2][0] * ty),
160*e39da397SStephan Aßmus                 nom_x_step(m[1][0] * step),
161*e39da397SStephan Aßmus                 nom_y(m[3][0] + m[4][0] * tx + m[5][0] * ty),
162*e39da397SStephan Aßmus                 nom_y_step(m[4][0] * step),
163*e39da397SStephan Aßmus                 x(nom_x / den),
164*e39da397SStephan Aßmus                 y(nom_y / den)
165*e39da397SStephan Aßmus             {
166*e39da397SStephan Aßmus             }
167*e39da397SStephan Aßmus 
168*e39da397SStephan Aßmus             void operator ++ ()
169*e39da397SStephan Aßmus             {
170*e39da397SStephan Aßmus                 den   += den_step;
171*e39da397SStephan Aßmus                 nom_x += nom_x_step;
172*e39da397SStephan Aßmus                 nom_y += nom_y_step;
173*e39da397SStephan Aßmus                 double d = 1.0 / den;
174*e39da397SStephan Aßmus                 x = nom_x * d;
175*e39da397SStephan Aßmus                 y = nom_y * d;
176*e39da397SStephan Aßmus             }
177*e39da397SStephan Aßmus         };
178*e39da397SStephan Aßmus 
179*e39da397SStephan Aßmus         //--------------------------------------------------------------------
180*e39da397SStephan Aßmus         iterator_x begin(double x, double y, double step) const
181*e39da397SStephan Aßmus         {
182*e39da397SStephan Aßmus             return iterator_x(x, y, step, m_mtx);
183*e39da397SStephan Aßmus         }
184*e39da397SStephan Aßmus 
18539241fe2SDarkWyrm     private:
18639241fe2SDarkWyrm         double m_mtx[8][1];
18739241fe2SDarkWyrm         bool   m_valid;
18839241fe2SDarkWyrm     };
18939241fe2SDarkWyrm 
19039241fe2SDarkWyrm }
19139241fe2SDarkWyrm 
19239241fe2SDarkWyrm #endif
193