Anti-Grain Geometry Tutorial
agg_span_interpolator_persp.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 #ifndef AGG_SPAN_INTERPOLATOR_PERSP_INCLUDED
16 #define AGG_SPAN_INTERPOLATOR_PERSP_INCLUDED
17 
18 #include <cmath>
19 #include "agg_trans_perspective.h"
20 #include "agg_dda_line.h"
21 
22 namespace agg
23 {
24 
25 
26 
27  //===========================================span_interpolator_persp_exact
28  template<unsigned SubpixelShift = 8>
30  {
31  public:
34  enum subpixel_scale_e
35  {
36  subpixel_shift = SubpixelShift,
37  subpixel_scale = 1 << subpixel_shift
38  };
39 
40  //--------------------------------------------------------------------
42 
43  //--------------------------------------------------------------------
44  // Arbitrary quadrangle transformations
45  span_interpolator_persp_exact(const double* src, const double* dst)
46  {
47  quad_to_quad(src, dst);
48  }
49 
50  //--------------------------------------------------------------------
51  // Direct transformations
52  span_interpolator_persp_exact(double x1, double y1,
53  double x2, double y2,
54  const double* quad)
55  {
56  rect_to_quad(x1, y1, x2, y2, quad);
57  }
58 
59  //--------------------------------------------------------------------
60  // Reverse transformations
61  span_interpolator_persp_exact(const double* quad,
62  double x1, double y1,
63  double x2, double y2)
64  {
65  quad_to_rect(quad, x1, y1, x2, y2);
66  }
67 
68  //--------------------------------------------------------------------
69  // Set the transformations using two arbitrary quadrangles.
70  void quad_to_quad(const double* src, const double* dst)
71  {
72  m_trans_dir.quad_to_quad(src, dst);
73  m_trans_inv.quad_to_quad(dst, src);
74  }
75 
76  //--------------------------------------------------------------------
77  // Set the direct transformations, i.e., rectangle -> quadrangle
78  void rect_to_quad(double x1, double y1, double x2, double y2,
79  const double* quad)
80  {
81  double src[8];
82  src[0] = src[6] = x1;
83  src[2] = src[4] = x2;
84  src[1] = src[3] = y1;
85  src[5] = src[7] = y2;
86  quad_to_quad(src, quad);
87  }
88 
89 
90  //--------------------------------------------------------------------
91  // Set the reverse transformations, i.e., quadrangle -> rectangle
92  void quad_to_rect(const double* quad,
93  double x1, double y1, double x2, double y2)
94  {
95  double dst[8];
96  dst[0] = dst[6] = x1;
97  dst[2] = dst[4] = x2;
98  dst[1] = dst[3] = y1;
99  dst[5] = dst[7] = y2;
100  quad_to_quad(quad, dst);
101  }
102 
103  //--------------------------------------------------------------------
104  // Check if the equations were solved successfully
105  bool is_valid() const { return m_trans_dir.is_valid(); }
106 
107  //----------------------------------------------------------------
108  void begin(double x, double y, unsigned len)
109  {
110  m_iterator = m_trans_dir.begin(x, y, 1.0);
111  double xt = m_iterator.x;
112  double yt = m_iterator.y;
113 
114  double dx;
115  double dy;
116  const double delta = 1/double(subpixel_scale);
117  dx = xt + delta;
118  dy = yt;
119  m_trans_inv.transform(&dx, &dy);
120  dx -= x;
121  dy -= y;
122  int sx1 = uround(subpixel_scale/std::sqrt(dx*dx + dy*dy)) >> subpixel_shift;
123  dx = xt;
124  dy = yt + delta;
125  m_trans_inv.transform(&dx, &dy);
126  dx -= x;
127  dy -= y;
128  int sy1 = uround(subpixel_scale/std::sqrt(dx*dx + dy*dy)) >> subpixel_shift;
129 
130  x += len;
131  xt = x;
132  yt = y;
133  m_trans_dir.transform(&xt, &yt);
134 
135  dx = xt + delta;
136  dy = yt;
137  m_trans_inv.transform(&dx, &dy);
138  dx -= x;
139  dy -= y;
140  int sx2 = uround(subpixel_scale/std::sqrt(dx*dx + dy*dy)) >> subpixel_shift;
141  dx = xt;
142  dy = yt + delta;
143  m_trans_inv.transform(&dx, &dy);
144  dx -= x;
145  dy -= y;
146  int sy2 = uround(subpixel_scale/std::sqrt(dx*dx + dy*dy)) >> subpixel_shift;
147 
148  m_scale_x = dda2_line_interpolator(sx1, sx2, len);
149  m_scale_y = dda2_line_interpolator(sy1, sy2, len);
150  }
151 
152 
153  //----------------------------------------------------------------
154  void resynchronize(double xe, double ye, unsigned len)
155  {
156  // Assume x1,y1 are equal to the ones at the previous end point
157  int sx1 = m_scale_x.y();
158  int sy1 = m_scale_y.y();
159 
160  // Calculate transformed coordinates at x2,y2
161  double xt = xe;
162  double yt = ye;
163  m_trans_dir.transform(&xt, &yt);
164 
165  const double delta = 1/double(subpixel_scale);
166  double dx;
167  double dy;
168 
169  // Calculate scale by X at x2,y2
170  dx = xt + delta;
171  dy = yt;
172  m_trans_inv.transform(&dx, &dy);
173  dx -= xe;
174  dy -= ye;
175  int sx2 = uround(subpixel_scale/std::sqrt(dx*dx + dy*dy)) >> subpixel_shift;
176 
177  // Calculate scale by Y at x2,y2
178  dx = xt;
179  dy = yt + delta;
180  m_trans_inv.transform(&dx, &dy);
181  dx -= xe;
182  dy -= ye;
183  int sy2 = uround(subpixel_scale/std::sqrt(dx*dx + dy*dy)) >> subpixel_shift;
184 
185  // Initialize the interpolators
186  m_scale_x = dda2_line_interpolator(sx1, sx2, len);
187  m_scale_y = dda2_line_interpolator(sy1, sy2, len);
188  }
189 
190 
191 
192  //----------------------------------------------------------------
193  void operator++()
194  {
195  ++m_iterator;
196  ++m_scale_x;
197  ++m_scale_y;
198  }
199 
200  //----------------------------------------------------------------
201  void coordinates(int* x, int* y) const
202  {
203  *x = iround(m_iterator.x * subpixel_scale);
204  *y = iround(m_iterator.y * subpixel_scale);
205  }
206 
207  //----------------------------------------------------------------
208  void local_scale(int* x, int* y)
209  {
210  *x = m_scale_x.y();
211  *y = m_scale_y.y();
212  }
213 
214  //----------------------------------------------------------------
215  void transform(double* x, double* y) const
216  {
217  m_trans_dir.transform(x, y);
218  }
219 
220  private:
221  trans_type m_trans_dir;
222  trans_type m_trans_inv;
223  iterator_type m_iterator;
224  dda2_line_interpolator m_scale_x;
225  dda2_line_interpolator m_scale_y;
226  };
227 
228 
229 
230 
231 
232 
233 
234 
235 
236 
237 
238  //============================================span_interpolator_persp_lerp
239  template<unsigned SubpixelShift = 8>
241  {
242  public:
244  enum subpixel_scale_e
245  {
246  subpixel_shift = SubpixelShift,
247  subpixel_scale = 1 << subpixel_shift
248  };
249 
250  //--------------------------------------------------------------------
252 
253  //--------------------------------------------------------------------
254  // Arbitrary quadrangle transformations
255  span_interpolator_persp_lerp(const double* src, const double* dst)
256  {
257  quad_to_quad(src, dst);
258  }
259 
260  //--------------------------------------------------------------------
261  // Direct transformations
262  span_interpolator_persp_lerp(double x1, double y1,
263  double x2, double y2,
264  const double* quad)
265  {
266  rect_to_quad(x1, y1, x2, y2, quad);
267  }
268 
269  //--------------------------------------------------------------------
270  // Reverse transformations
271  span_interpolator_persp_lerp(const double* quad,
272  double x1, double y1,
273  double x2, double y2)
274  {
275  quad_to_rect(quad, x1, y1, x2, y2);
276  }
277 
278  //--------------------------------------------------------------------
279  // Set the transformations using two arbitrary quadrangles.
280  void quad_to_quad(const double* src, const double* dst)
281  {
282  m_trans_dir.quad_to_quad(src, dst);
283  m_trans_inv.quad_to_quad(dst, src);
284  }
285 
286  //--------------------------------------------------------------------
287  // Set the direct transformations, i.e., rectangle -> quadrangle
288  void rect_to_quad(double x1, double y1, double x2, double y2,
289  const double* quad)
290  {
291  double src[8];
292  src[0] = src[6] = x1;
293  src[2] = src[4] = x2;
294  src[1] = src[3] = y1;
295  src[5] = src[7] = y2;
296  quad_to_quad(src, quad);
297  }
298 
299 
300  //--------------------------------------------------------------------
301  // Set the reverse transformations, i.e., quadrangle -> rectangle
302  void quad_to_rect(const double* quad,
303  double x1, double y1, double x2, double y2)
304  {
305  double dst[8];
306  dst[0] = dst[6] = x1;
307  dst[2] = dst[4] = x2;
308  dst[1] = dst[3] = y1;
309  dst[5] = dst[7] = y2;
310  quad_to_quad(quad, dst);
311  }
312 
313  //--------------------------------------------------------------------
314  // Check if the equations were solved successfully
315  bool is_valid() const { return m_trans_dir.is_valid(); }
316 
317  //----------------------------------------------------------------
318  void begin(double x, double y, unsigned len)
319  {
320  // Calculate transformed coordinates at x1,y1
321  double xt = x;
322  double yt = y;
323  m_trans_dir.transform(&xt, &yt);
324  int x1 = iround(xt * subpixel_scale);
325  int y1 = iround(yt * subpixel_scale);
326 
327  double dx;
328  double dy;
329  const double delta = 1/double(subpixel_scale);
330 
331  // Calculate scale by X at x1,y1
332  dx = xt + delta;
333  dy = yt;
334  m_trans_inv.transform(&dx, &dy);
335  dx -= x;
336  dy -= y;
337  int sx1 = uround(subpixel_scale/std::sqrt(dx*dx + dy*dy)) >> subpixel_shift;
338 
339  // Calculate scale by Y at x1,y1
340  dx = xt;
341  dy = yt + delta;
342  m_trans_inv.transform(&dx, &dy);
343  dx -= x;
344  dy -= y;
345  int sy1 = uround(subpixel_scale/std::sqrt(dx*dx + dy*dy)) >> subpixel_shift;
346 
347  // Calculate transformed coordinates at x2,y2
348  x += len;
349  xt = x;
350  yt = y;
351  m_trans_dir.transform(&xt, &yt);
352  int x2 = iround(xt * subpixel_scale);
353  int y2 = iround(yt * subpixel_scale);
354 
355  // Calculate scale by X at x2,y2
356  dx = xt + delta;
357  dy = yt;
358  m_trans_inv.transform(&dx, &dy);
359  dx -= x;
360  dy -= y;
361  int sx2 = uround(subpixel_scale/std::sqrt(dx*dx + dy*dy)) >> subpixel_shift;
362 
363  // Calculate scale by Y at x2,y2
364  dx = xt;
365  dy = yt + delta;
366  m_trans_inv.transform(&dx, &dy);
367  dx -= x;
368  dy -= y;
369  int sy2 = uround(subpixel_scale/std::sqrt(dx*dx + dy*dy)) >> subpixel_shift;
370 
371  // Initialize the interpolators
372  m_coord_x = dda2_line_interpolator(x1, x2, len);
373  m_coord_y = dda2_line_interpolator(y1, y2, len);
374  m_scale_x = dda2_line_interpolator(sx1, sx2, len);
375  m_scale_y = dda2_line_interpolator(sy1, sy2, len);
376  }
377 
378 
379  //----------------------------------------------------------------
380  void resynchronize(double xe, double ye, unsigned len)
381  {
382  // Assume x1,y1 are equal to the ones at the previous end point
383  int x1 = m_coord_x.y();
384  int y1 = m_coord_y.y();
385  int sx1 = m_scale_x.y();
386  int sy1 = m_scale_y.y();
387 
388  // Calculate transformed coordinates at x2,y2
389  double xt = xe;
390  double yt = ye;
391  m_trans_dir.transform(&xt, &yt);
392  int x2 = iround(xt * subpixel_scale);
393  int y2 = iround(yt * subpixel_scale);
394 
395  const double delta = 1/double(subpixel_scale);
396  double dx;
397  double dy;
398 
399  // Calculate scale by X at x2,y2
400  dx = xt + delta;
401  dy = yt;
402  m_trans_inv.transform(&dx, &dy);
403  dx -= xe;
404  dy -= ye;
405  int sx2 = uround(subpixel_scale/std::sqrt(dx*dx + dy*dy)) >> subpixel_shift;
406 
407  // Calculate scale by Y at x2,y2
408  dx = xt;
409  dy = yt + delta;
410  m_trans_inv.transform(&dx, &dy);
411  dx -= xe;
412  dy -= ye;
413  int sy2 = uround(subpixel_scale/std::sqrt(dx*dx + dy*dy)) >> subpixel_shift;
414 
415  // Initialize the interpolators
416  m_coord_x = dda2_line_interpolator(x1, x2, len);
417  m_coord_y = dda2_line_interpolator(y1, y2, len);
418  m_scale_x = dda2_line_interpolator(sx1, sx2, len);
419  m_scale_y = dda2_line_interpolator(sy1, sy2, len);
420  }
421 
422 
423  //----------------------------------------------------------------
424  void operator++()
425  {
426  ++m_coord_x;
427  ++m_coord_y;
428  ++m_scale_x;
429  ++m_scale_y;
430  }
431 
432  //----------------------------------------------------------------
433  void coordinates(int* x, int* y) const
434  {
435  *x = m_coord_x.y();
436  *y = m_coord_y.y();
437  }
438 
439  //----------------------------------------------------------------
440  void local_scale(int* x, int* y)
441  {
442  *x = m_scale_x.y();
443  *y = m_scale_y.y();
444  }
445 
446  //----------------------------------------------------------------
447  void transform(double* x, double* y) const
448  {
449  m_trans_dir.transform(x, y);
450  }
451 
452  private:
453  trans_type m_trans_dir;
454  trans_type m_trans_inv;
455  dda2_line_interpolator m_coord_x;
456  dda2_line_interpolator m_coord_y;
457  dda2_line_interpolator m_scale_x;
458  dda2_line_interpolator m_scale_y;
459  };
460 
461 }
462 
463 #endif
Definition: agg_arc.cpp:24