Anti-Grain Geometry Tutorial
agg_trans_viewport.h
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 // Viewport transformer - simple orthogonal conversions from world coordinates
17 // to screen (device) ones.
18 //
19 //----------------------------------------------------------------------------
20 
21 #ifndef AGG_TRANS_VIEWPORT_INCLUDED
22 #define AGG_TRANS_VIEWPORT_INCLUDED
23 
24 #include <cstring>
25 #include <cmath>
26 #include "agg_trans_affine.h"
27 
28 
29 namespace agg
30 {
31 
32  enum aspect_ratio_e
33  {
34  aspect_ratio_stretch,
35  aspect_ratio_meet,
36  aspect_ratio_slice
37  };
38 
39 
40  //----------------------------------------------------------trans_viewport
42  {
43  public:
44  //-------------------------------------------------------------------
45  trans_viewport() :
46  m_world_x1(0.0),
47  m_world_y1(0.0),
48  m_world_x2(1.0),
49  m_world_y2(1.0),
50  m_device_x1(0.0),
51  m_device_y1(0.0),
52  m_device_x2(1.0),
53  m_device_y2(1.0),
54  m_aspect(aspect_ratio_stretch),
55  m_is_valid(true),
56  m_align_x(0.5),
57  m_align_y(0.5),
58  m_wx1(0.0),
59  m_wy1(0.0),
60  m_wx2(1.0),
61  m_wy2(1.0),
62  m_dx1(0.0),
63  m_dy1(0.0),
64  m_kx(1.0),
65  m_ky(1.0)
66  {}
67 
68  //-------------------------------------------------------------------
69  void preserve_aspect_ratio(double alignx,
70  double aligny,
71  aspect_ratio_e aspect)
72  {
73  m_align_x = alignx;
74  m_align_y = aligny;
75  m_aspect = aspect;
76  update();
77  }
78 
79  //-------------------------------------------------------------------
80  void device_viewport(double x1, double y1, double x2, double y2)
81  {
82  m_device_x1 = x1;
83  m_device_y1 = y1;
84  m_device_x2 = x2;
85  m_device_y2 = y2;
86  update();
87  }
88 
89  //-------------------------------------------------------------------
90  void world_viewport(double x1, double y1, double x2, double y2)
91  {
92  m_world_x1 = x1;
93  m_world_y1 = y1;
94  m_world_x2 = x2;
95  m_world_y2 = y2;
96  update();
97  }
98 
99  //-------------------------------------------------------------------
100  void device_viewport(double* x1, double* y1, double* x2, double* y2) const
101  {
102  *x1 = m_device_x1;
103  *y1 = m_device_y1;
104  *x2 = m_device_x2;
105  *y2 = m_device_y2;
106  }
107 
108  //-------------------------------------------------------------------
109  void world_viewport(double* x1, double* y1, double* x2, double* y2) const
110  {
111  *x1 = m_world_x1;
112  *y1 = m_world_y1;
113  *x2 = m_world_x2;
114  *y2 = m_world_y2;
115  }
116 
117  //-------------------------------------------------------------------
118  void world_viewport_actual(double* x1, double* y1,
119  double* x2, double* y2) const
120  {
121  *x1 = m_wx1;
122  *y1 = m_wy1;
123  *x2 = m_wx2;
124  *y2 = m_wy2;
125  }
126 
127  //-------------------------------------------------------------------
128  bool is_valid() const { return m_is_valid; }
129  double align_x() const { return m_align_x; }
130  double align_y() const { return m_align_y; }
131  aspect_ratio_e aspect_ratio() const { return m_aspect; }
132 
133  //-------------------------------------------------------------------
134  void transform(double* x, double* y) const
135  {
136  *x = (*x - m_wx1) * m_kx + m_dx1;
137  *y = (*y - m_wy1) * m_ky + m_dy1;
138  }
139 
140  //-------------------------------------------------------------------
141  void transform_scale_only(double* x, double* y) const
142  {
143  *x *= m_kx;
144  *y *= m_ky;
145  }
146 
147  //-------------------------------------------------------------------
148  void inverse_transform(double* x, double* y) const
149  {
150  *x = (*x - m_dx1) / m_kx + m_wx1;
151  *y = (*y - m_dy1) / m_ky + m_wy1;
152  }
153 
154  //-------------------------------------------------------------------
155  void inverse_transform_scale_only(double* x, double* y) const
156  {
157  *x /= m_kx;
158  *y /= m_ky;
159  }
160 
161  //-------------------------------------------------------------------
162  double device_dx() const { return m_dx1 - m_wx1 * m_kx; }
163  double device_dy() const { return m_dy1 - m_wy1 * m_ky; }
164 
165  //-------------------------------------------------------------------
166  double scale_x() const
167  {
168  return m_kx;
169  }
170 
171  //-------------------------------------------------------------------
172  double scale_y() const
173  {
174  return m_ky;
175  }
176 
177  //-------------------------------------------------------------------
178  double scale() const
179  {
180  return (m_kx + m_ky) * 0.5;
181  }
182 
183  //-------------------------------------------------------------------
184  trans_affine to_affine() const
185  {
186  trans_affine mtx = trans_affine_translation(-m_wx1, -m_wy1);
187  mtx *= trans_affine_scaling(m_kx, m_ky);
188  mtx *= trans_affine_translation(m_dx1, m_dy1);
189  return mtx;
190  }
191 
192  //-------------------------------------------------------------------
193  trans_affine to_affine_scale_only() const
194  {
195  return trans_affine_scaling(m_kx, m_ky);
196  }
197 
198  //-------------------------------------------------------------------
199  unsigned byte_size() const
200  {
201  return sizeof(*this);
202  }
203 
204  void serialize(int8u* ptr) const
205  {
206  std::memcpy(ptr, this, sizeof(*this));
207  }
208 
209  void deserialize(const int8u* ptr)
210  {
211  std::memcpy(this, ptr, sizeof(*this));
212  }
213 
214  private:
215  void update();
216 
217  double m_world_x1;
218  double m_world_y1;
219  double m_world_x2;
220  double m_world_y2;
221  double m_device_x1;
222  double m_device_y1;
223  double m_device_x2;
224  double m_device_y2;
225  aspect_ratio_e m_aspect;
226  bool m_is_valid;
227  double m_align_x;
228  double m_align_y;
229  double m_wx1;
230  double m_wy1;
231  double m_wx2;
232  double m_wy2;
233  double m_dx1;
234  double m_dy1;
235  double m_kx;
236  double m_ky;
237  };
238 
239 
240 
241  //-----------------------------------------------------------------------
242  inline void trans_viewport::update()
243  {
244  const double epsilon = 1e-30;
245  if(std::fabs(m_world_x1 - m_world_x2) < epsilon ||
246  std::fabs(m_world_y1 - m_world_y2) < epsilon ||
247  std::fabs(m_device_x1 - m_device_x2) < epsilon ||
248  std::fabs(m_device_y1 - m_device_y2) < epsilon)
249  {
250  m_wx1 = m_world_x1;
251  m_wy1 = m_world_y1;
252  m_wx2 = m_world_x1 + 1.0;
253  m_wy2 = m_world_y2 + 1.0;
254  m_dx1 = m_device_x1;
255  m_dy1 = m_device_y1;
256  m_kx = 1.0;
257  m_ky = 1.0;
258  m_is_valid = false;
259  return;
260  }
261 
262  double world_x1 = m_world_x1;
263  double world_y1 = m_world_y1;
264  double world_x2 = m_world_x2;
265  double world_y2 = m_world_y2;
266  double device_x1 = m_device_x1;
267  double device_y1 = m_device_y1;
268  double device_x2 = m_device_x2;
269  double device_y2 = m_device_y2;
270  if(m_aspect != aspect_ratio_stretch)
271  {
272  double d;
273  m_kx = (device_x2 - device_x1) / (world_x2 - world_x1);
274  m_ky = (device_y2 - device_y1) / (world_y2 - world_y1);
275 
276  if((m_aspect == aspect_ratio_meet) == (m_kx < m_ky))
277  {
278  d = (world_y2 - world_y1) * m_ky / m_kx;
279  world_y1 += (world_y2 - world_y1 - d) * m_align_y;
280  world_y2 = world_y1 + d;
281  }
282  else
283  {
284  d = (world_x2 - world_x1) * m_kx / m_ky;
285  world_x1 += (world_x2 - world_x1 - d) * m_align_x;
286  world_x2 = world_x1 + d;
287  }
288  }
289  m_wx1 = world_x1;
290  m_wy1 = world_y1;
291  m_wx2 = world_x2;
292  m_wy2 = world_y2;
293  m_dx1 = device_x1;
294  m_dy1 = device_y1;
295  m_kx = (device_x2 - device_x1) / (world_x2 - world_x1);
296  m_ky = (device_y2 - device_y1) / (world_y2 - world_y1);
297  m_is_valid = true;
298  }
299 
300 
301 }
302 
303 
304 #endif
Definition: agg_arc.cpp:24