Anti-Grain Geometry - AGG (libagg)  2.5
agg-2.5/include/agg_trans_viewport.h
Go to the documentation of this file.
00001 //----------------------------------------------------------------------------
00002 // Anti-Grain Geometry (AGG) - Version 2.5
00003 // A high quality rendering engine for C++
00004 // Copyright (C) 2002-2006 Maxim Shemanarev
00005 // Contact: mcseem@antigrain.com
00006 //          mcseemagg@yahoo.com
00007 //          http://antigrain.com
00008 // 
00009 // AGG is free software; you can redistribute it and/or
00010 // modify it under the terms of the GNU General Public License
00011 // as published by the Free Software Foundation; either version 2
00012 // of the License, or (at your option) any later version.
00013 // 
00014 // AGG is distributed in the hope that it will be useful,
00015 // but WITHOUT ANY WARRANTY; without even the implied warranty of
00016 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00017 // GNU General Public License for more details.
00018 // 
00019 // You should have received a copy of the GNU General Public License
00020 // along with AGG; if not, write to the Free Software
00021 // Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, 
00022 // MA 02110-1301, USA.
00023 //----------------------------------------------------------------------------
00024 //
00025 // Viewport transformer - simple orthogonal conversions from world coordinates
00026 //                        to screen (device) ones.
00027 //
00028 //----------------------------------------------------------------------------
00029 
00030 #ifndef AGG_TRANS_VIEWPORT_INCLUDED
00031 #define AGG_TRANS_VIEWPORT_INCLUDED
00032 
00033 #include <string.h>
00034 #include "agg_trans_affine.h"
00035 
00036 
00037 namespace agg
00038 {
00039 
00040     enum aspect_ratio_e
00041     {
00042         aspect_ratio_stretch,
00043         aspect_ratio_meet,
00044         aspect_ratio_slice
00045     };
00046 
00047 
00048     //----------------------------------------------------------trans_viewport
00049     class trans_viewport
00050     {
00051     public:
00052         //-------------------------------------------------------------------
00053         trans_viewport() : 
00054             m_world_x1(0.0),
00055             m_world_y1(0.0),
00056             m_world_x2(1.0),
00057             m_world_y2(1.0),
00058             m_device_x1(0.0),
00059             m_device_y1(0.0),
00060             m_device_x2(1.0),
00061             m_device_y2(1.0),
00062             m_aspect(aspect_ratio_stretch),
00063             m_is_valid(true),
00064             m_align_x(0.5),
00065             m_align_y(0.5),
00066             m_wx1(0.0),
00067             m_wy1(0.0),
00068             m_wx2(1.0),
00069             m_wy2(1.0),
00070             m_dx1(0.0),
00071             m_dy1(0.0),
00072             m_kx(1.0),
00073             m_ky(1.0)
00074         {}
00075 
00076         //-------------------------------------------------------------------
00077         void preserve_aspect_ratio(double alignx, 
00078                                    double aligny, 
00079                                    aspect_ratio_e aspect)
00080         {
00081             m_align_x = alignx;
00082             m_align_y = aligny;
00083             m_aspect  = aspect;
00084             update();
00085         }
00086 
00087         //-------------------------------------------------------------------
00088         void device_viewport(double x1, double y1, double x2, double y2)
00089         {
00090             m_device_x1 = x1;
00091             m_device_y1 = y1;
00092             m_device_x2 = x2;
00093             m_device_y2 = y2;
00094             update();
00095         }
00096 
00097         //-------------------------------------------------------------------
00098         void world_viewport(double x1, double y1, double x2, double y2)
00099         {
00100             m_world_x1 = x1;
00101             m_world_y1 = y1;
00102             m_world_x2 = x2;
00103             m_world_y2 = y2;
00104             update();
00105         }
00106 
00107         //-------------------------------------------------------------------
00108         void device_viewport(double* x1, double* y1, double* x2, double* y2) const
00109         {
00110             *x1 = m_device_x1;
00111             *y1 = m_device_y1;
00112             *x2 = m_device_x2;
00113             *y2 = m_device_y2;
00114         }
00115 
00116         //-------------------------------------------------------------------
00117         void world_viewport(double* x1, double* y1, double* x2, double* y2) const
00118         {
00119             *x1 = m_world_x1;
00120             *y1 = m_world_y1;
00121             *x2 = m_world_x2;
00122             *y2 = m_world_y2;
00123         }
00124 
00125         //-------------------------------------------------------------------
00126         void world_viewport_actual(double* x1, double* y1, 
00127                                    double* x2, double* y2) const
00128         {
00129             *x1 = m_wx1;
00130             *y1 = m_wy1;
00131             *x2 = m_wx2;
00132             *y2 = m_wy2;
00133         }
00134 
00135         //-------------------------------------------------------------------
00136         bool   is_valid()             const { return m_is_valid; }
00137         double align_x()              const { return m_align_x; }
00138         double align_y()              const { return m_align_y; }
00139         aspect_ratio_e aspect_ratio() const { return m_aspect; }
00140 
00141         //-------------------------------------------------------------------
00142         void transform(double* x, double* y) const
00143         {
00144             *x = (*x - m_wx1) * m_kx + m_dx1;
00145             *y = (*y - m_wy1) * m_ky + m_dy1;
00146         }
00147 
00148         //-------------------------------------------------------------------
00149         void transform_scale_only(double* x, double* y) const
00150         {
00151             *x *= m_kx;
00152             *y *= m_ky;
00153         }
00154 
00155         //-------------------------------------------------------------------
00156         void inverse_transform(double* x, double* y) const
00157         {
00158             *x = (*x - m_dx1) / m_kx + m_wx1;
00159             *y = (*y - m_dy1) / m_ky + m_wy1;
00160         }
00161 
00162         //-------------------------------------------------------------------
00163         void inverse_transform_scale_only(double* x, double* y) const
00164         {
00165             *x /= m_kx;
00166             *y /= m_ky;
00167         }
00168 
00169         //-------------------------------------------------------------------
00170         double device_dx() const { return m_dx1 - m_wx1 * m_kx; }
00171         double device_dy() const { return m_dy1 - m_wy1 * m_ky; }
00172 
00173         //-------------------------------------------------------------------
00174         double scale_x() const
00175         {
00176             return m_kx;
00177         }
00178 
00179         //-------------------------------------------------------------------
00180         double scale_y() const
00181         {
00182             return m_ky;
00183         }
00184 
00185         //-------------------------------------------------------------------
00186         double scale() const
00187         {
00188             return (m_kx + m_ky) * 0.5;
00189         }
00190 
00191         //-------------------------------------------------------------------
00192         trans_affine to_affine() const
00193         {
00194             trans_affine mtx = trans_affine_translation(-m_wx1, -m_wy1);
00195             mtx *= trans_affine_scaling(m_kx, m_ky);
00196             mtx *= trans_affine_translation(m_dx1, m_dy1);
00197             return mtx;
00198         }
00199 
00200         //-------------------------------------------------------------------
00201         trans_affine to_affine_scale_only() const
00202         {
00203             return trans_affine_scaling(m_kx, m_ky);
00204         }
00205 
00206         //-------------------------------------------------------------------
00207         unsigned byte_size() const
00208         {
00209             return sizeof(*this);
00210         }
00211 
00212         void serialize(int8u* ptr) const
00213         {
00214             memcpy(ptr, this, sizeof(*this)); 
00215         }
00216 
00217         void deserialize(const int8u* ptr)
00218         {
00219             memcpy(this,  ptr, sizeof(*this));
00220         }
00221 
00222     private:
00223         void update();
00224 
00225         double         m_world_x1;
00226         double         m_world_y1;
00227         double         m_world_x2;
00228         double         m_world_y2;
00229         double         m_device_x1;
00230         double         m_device_y1;
00231         double         m_device_x2;
00232         double         m_device_y2;
00233         aspect_ratio_e m_aspect;
00234         bool           m_is_valid;
00235         double         m_align_x;
00236         double         m_align_y;
00237         double         m_wx1;
00238         double         m_wy1;
00239         double         m_wx2;
00240         double         m_wy2;
00241         double         m_dx1;
00242         double         m_dy1;
00243         double         m_kx;
00244         double         m_ky;
00245     };
00246 
00247 
00248 
00249     //-----------------------------------------------------------------------
00250     inline void trans_viewport::update()
00251     {
00252         const double epsilon = 1e-30;
00253         if(fabs(m_world_x1  - m_world_x2)  < epsilon ||
00254            fabs(m_world_y1  - m_world_y2)  < epsilon ||
00255            fabs(m_device_x1 - m_device_x2) < epsilon ||
00256            fabs(m_device_y1 - m_device_y2) < epsilon)
00257         {
00258             m_wx1 = m_world_x1;
00259             m_wy1 = m_world_y1;
00260             m_wx2 = m_world_x1 + 1.0;
00261             m_wy2 = m_world_y2 + 1.0;
00262             m_dx1 = m_device_x1;
00263             m_dy1 = m_device_y1;
00264             m_kx  = 1.0;
00265             m_ky  = 1.0;
00266             m_is_valid = false;
00267             return;
00268         }
00269 
00270         double world_x1  = m_world_x1;
00271         double world_y1  = m_world_y1;
00272         double world_x2  = m_world_x2;
00273         double world_y2  = m_world_y2;
00274         double device_x1 = m_device_x1;
00275         double device_y1 = m_device_y1;
00276         double device_x2 = m_device_x2;
00277         double device_y2 = m_device_y2;
00278         if(m_aspect != aspect_ratio_stretch)
00279         {
00280             double d;
00281             m_kx = (device_x2 - device_x1) / (world_x2 - world_x1);
00282             m_ky = (device_y2 - device_y1) / (world_y2 - world_y1);
00283 
00284             if((m_aspect == aspect_ratio_meet) == (m_kx < m_ky))
00285             {
00286                 d         = (world_y2 - world_y1) * m_ky / m_kx;
00287                 world_y1 += (world_y2 - world_y1 - d) * m_align_y;
00288                 world_y2  =  world_y1 + d;
00289             }
00290             else
00291             {
00292                 d         = (world_x2 - world_x1) * m_kx / m_ky;
00293                 world_x1 += (world_x2 - world_x1 - d) * m_align_x;
00294                 world_x2  =  world_x1 + d;
00295             }
00296         }
00297         m_wx1 = world_x1;
00298         m_wy1 = world_y1;
00299         m_wx2 = world_x2;
00300         m_wy2 = world_y2;
00301         m_dx1 = device_x1;
00302         m_dy1 = device_y1;
00303         m_kx  = (device_x2 - device_x1) / (world_x2 - world_x1);
00304         m_ky  = (device_y2 - device_y1) / (world_y2 - world_y1);
00305         m_is_valid = true;
00306     }
00307 
00308 
00309 }
00310 
00311 
00312 #endif
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines