Anti-Grain Geometry - AGG (libagg)
2.5
|
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