1 //----------------------------------------------------------------------------
2 // Anti-Grain Geometry - Version 2.4
3 // Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com)
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.
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
18 #include "agg_trans_perspective.h"
19 #include "agg_dda_line.h"
26 //===========================================span_interpolator_persp_exact
27 template<unsigned SubpixelShift
= 8>
28 class span_interpolator_persp_exact
31 typedef trans_perspective trans_type
;
32 typedef trans_perspective::iterator_x iterator_type
;
35 subpixel_shift
= SubpixelShift
,
36 subpixel_scale
= 1 << subpixel_shift
39 //--------------------------------------------------------------------
40 span_interpolator_persp_exact() {}
42 //--------------------------------------------------------------------
43 // Arbitrary quadrangle transformations
44 span_interpolator_persp_exact(const double* src
, const double* dst
)
46 quad_to_quad(src
, dst
);
49 //--------------------------------------------------------------------
50 // Direct transformations
51 span_interpolator_persp_exact(double x1
, double y1
,
55 rect_to_quad(x1
, y1
, x2
, y2
, quad
);
58 //--------------------------------------------------------------------
59 // Reverse transformations
60 span_interpolator_persp_exact(const double* quad
,
64 quad_to_rect(quad
, x1
, y1
, x2
, y2
);
67 //--------------------------------------------------------------------
68 // Set the transformations using two arbitrary quadrangles.
69 void quad_to_quad(const double* src
, const double* dst
)
71 m_trans_dir
.quad_to_quad(src
, dst
);
72 m_trans_inv
.quad_to_quad(dst
, src
);
75 //--------------------------------------------------------------------
76 // Set the direct transformations, i.e., rectangle -> quadrangle
77 void rect_to_quad(double x1
, double y1
, double x2
, double y2
,
85 quad_to_quad(src
, quad
);
89 //--------------------------------------------------------------------
90 // Set the reverse transformations, i.e., quadrangle -> rectangle
91 void quad_to_rect(const double* quad
,
92 double x1
, double y1
, double x2
, double y2
)
99 quad_to_quad(quad
, dst
);
102 //--------------------------------------------------------------------
103 // Check if the equations were solved successfully
104 bool is_valid() const { return m_trans_dir
.is_valid(); }
106 //----------------------------------------------------------------
107 void begin(double x
, double y
, unsigned len
)
109 m_iterator
= m_trans_dir
.begin(x
, y
, 1.0);
110 double xt
= m_iterator
.x
;
111 double yt
= m_iterator
.y
;
115 const double delta
= 1/double(subpixel_scale
);
118 m_trans_inv
.transform(&dx
, &dy
);
121 int sx1
= uround(subpixel_scale
/sqrt(dx
*dx
+ dy
*dy
)) >> subpixel_shift
;
124 m_trans_inv
.transform(&dx
, &dy
);
127 int sy1
= uround(subpixel_scale
/sqrt(dx
*dx
+ dy
*dy
)) >> subpixel_shift
;
132 m_trans_dir
.transform(&xt
, &yt
);
136 m_trans_inv
.transform(&dx
, &dy
);
139 int sx2
= uround(subpixel_scale
/sqrt(dx
*dx
+ dy
*dy
)) >> subpixel_shift
;
142 m_trans_inv
.transform(&dx
, &dy
);
145 int sy2
= uround(subpixel_scale
/sqrt(dx
*dx
+ dy
*dy
)) >> subpixel_shift
;
147 m_scale_x
= dda2_line_interpolator(sx1
, sx2
, len
);
148 m_scale_y
= dda2_line_interpolator(sy1
, sy2
, len
);
152 //----------------------------------------------------------------
153 void resynchronize(double xe
, double ye
, unsigned len
)
155 // Assume x1,y1 are equal to the ones at the previous end point
156 int sx1
= m_scale_x
.y();
157 int sy1
= m_scale_y
.y();
159 // Calculate transformed coordinates at x2,y2
162 m_trans_dir
.transform(&xt
, &yt
);
164 const double delta
= 1/double(subpixel_scale
);
168 // Calculate scale by X at x2,y2
171 m_trans_inv
.transform(&dx
, &dy
);
174 int sx2
= uround(subpixel_scale
/sqrt(dx
*dx
+ dy
*dy
)) >> subpixel_shift
;
176 // Calculate scale by Y at x2,y2
179 m_trans_inv
.transform(&dx
, &dy
);
182 int sy2
= uround(subpixel_scale
/sqrt(dx
*dx
+ dy
*dy
)) >> subpixel_shift
;
184 // Initialize the interpolators
185 m_scale_x
= dda2_line_interpolator(sx1
, sx2
, len
);
186 m_scale_y
= dda2_line_interpolator(sy1
, sy2
, len
);
191 //----------------------------------------------------------------
199 //----------------------------------------------------------------
200 void coordinates(int* x
, int* y
) const
202 *x
= iround(m_iterator
.x
* subpixel_scale
);
203 *y
= iround(m_iterator
.y
* subpixel_scale
);
206 //----------------------------------------------------------------
207 void local_scale(int* x
, int* y
)
213 //----------------------------------------------------------------
214 void transform(double* x
, double* y
) const
216 m_trans_dir
.transform(x
, y
);
220 trans_type m_trans_dir
;
221 trans_type m_trans_inv
;
222 iterator_type m_iterator
;
223 dda2_line_interpolator m_scale_x
;
224 dda2_line_interpolator m_scale_y
;
237 //============================================span_interpolator_persp_lerp
238 template<unsigned SubpixelShift
= 8>
239 class span_interpolator_persp_lerp
242 typedef trans_perspective trans_type
;
243 enum subpixel_scale_e
245 subpixel_shift
= SubpixelShift
,
246 subpixel_scale
= 1 << subpixel_shift
249 //--------------------------------------------------------------------
250 span_interpolator_persp_lerp() {}
252 //--------------------------------------------------------------------
253 // Arbitrary quadrangle transformations
254 span_interpolator_persp_lerp(const double* src
, const double* dst
)
256 quad_to_quad(src
, dst
);
259 //--------------------------------------------------------------------
260 // Direct transformations
261 span_interpolator_persp_lerp(double x1
, double y1
,
262 double x2
, double y2
,
265 rect_to_quad(x1
, y1
, x2
, y2
, quad
);
268 //--------------------------------------------------------------------
269 // Reverse transformations
270 span_interpolator_persp_lerp(const double* quad
,
271 double x1
, double y1
,
272 double x2
, double y2
)
274 quad_to_rect(quad
, x1
, y1
, x2
, y2
);
277 //--------------------------------------------------------------------
278 // Set the transformations using two arbitrary quadrangles.
279 void quad_to_quad(const double* src
, const double* dst
)
281 m_trans_dir
.quad_to_quad(src
, dst
);
282 m_trans_inv
.quad_to_quad(dst
, src
);
285 //--------------------------------------------------------------------
286 // Set the direct transformations, i.e., rectangle -> quadrangle
287 void rect_to_quad(double x1
, double y1
, double x2
, double y2
,
291 src
[0] = src
[6] = x1
;
292 src
[2] = src
[4] = x2
;
293 src
[1] = src
[3] = y1
;
294 src
[5] = src
[7] = y2
;
295 quad_to_quad(src
, quad
);
299 //--------------------------------------------------------------------
300 // Set the reverse transformations, i.e., quadrangle -> rectangle
301 void quad_to_rect(const double* quad
,
302 double x1
, double y1
, double x2
, double y2
)
305 dst
[0] = dst
[6] = x1
;
306 dst
[2] = dst
[4] = x2
;
307 dst
[1] = dst
[3] = y1
;
308 dst
[5] = dst
[7] = y2
;
309 quad_to_quad(quad
, dst
);
312 //--------------------------------------------------------------------
313 // Check if the equations were solved successfully
314 bool is_valid() const { return m_trans_dir
.is_valid(); }
316 //----------------------------------------------------------------
317 void begin(double x
, double y
, unsigned len
)
319 // Calculate transformed coordinates at x1,y1
322 m_trans_dir
.transform(&xt
, &yt
);
323 int x1
= iround(xt
* subpixel_scale
);
324 int y1
= iround(yt
* subpixel_scale
);
328 const double delta
= 1/double(subpixel_scale
);
330 // Calculate scale by X at x1,y1
333 m_trans_inv
.transform(&dx
, &dy
);
336 int sx1
= uround(subpixel_scale
/sqrt(dx
*dx
+ dy
*dy
)) >> subpixel_shift
;
338 // Calculate scale by Y at x1,y1
341 m_trans_inv
.transform(&dx
, &dy
);
344 int sy1
= uround(subpixel_scale
/sqrt(dx
*dx
+ dy
*dy
)) >> subpixel_shift
;
346 // Calculate transformed coordinates at x2,y2
350 m_trans_dir
.transform(&xt
, &yt
);
351 int x2
= iround(xt
* subpixel_scale
);
352 int y2
= iround(yt
* subpixel_scale
);
354 // Calculate scale by X at x2,y2
357 m_trans_inv
.transform(&dx
, &dy
);
360 int sx2
= uround(subpixel_scale
/sqrt(dx
*dx
+ dy
*dy
)) >> subpixel_shift
;
362 // Calculate scale by Y at x2,y2
365 m_trans_inv
.transform(&dx
, &dy
);
368 int sy2
= uround(subpixel_scale
/sqrt(dx
*dx
+ dy
*dy
)) >> subpixel_shift
;
370 // Initialize the interpolators
371 m_coord_x
= dda2_line_interpolator(x1
, x2
, len
);
372 m_coord_y
= dda2_line_interpolator(y1
, y2
, len
);
373 m_scale_x
= dda2_line_interpolator(sx1
, sx2
, len
);
374 m_scale_y
= dda2_line_interpolator(sy1
, sy2
, len
);
378 //----------------------------------------------------------------
379 void resynchronize(double xe
, double ye
, unsigned len
)
381 // Assume x1,y1 are equal to the ones at the previous end point
382 int x1
= m_coord_x
.y();
383 int y1
= m_coord_y
.y();
384 int sx1
= m_scale_x
.y();
385 int sy1
= m_scale_y
.y();
387 // Calculate transformed coordinates at x2,y2
390 m_trans_dir
.transform(&xt
, &yt
);
391 int x2
= iround(xt
* subpixel_scale
);
392 int y2
= iround(yt
* subpixel_scale
);
394 const double delta
= 1/double(subpixel_scale
);
398 // Calculate scale by X at x2,y2
401 m_trans_inv
.transform(&dx
, &dy
);
404 int sx2
= uround(subpixel_scale
/sqrt(dx
*dx
+ dy
*dy
)) >> subpixel_shift
;
406 // Calculate scale by Y at x2,y2
409 m_trans_inv
.transform(&dx
, &dy
);
412 int sy2
= uround(subpixel_scale
/sqrt(dx
*dx
+ dy
*dy
)) >> subpixel_shift
;
414 // Initialize the interpolators
415 m_coord_x
= dda2_line_interpolator(x1
, x2
, len
);
416 m_coord_y
= dda2_line_interpolator(y1
, y2
, len
);
417 m_scale_x
= dda2_line_interpolator(sx1
, sx2
, len
);
418 m_scale_y
= dda2_line_interpolator(sy1
, sy2
, len
);
422 //----------------------------------------------------------------
431 //----------------------------------------------------------------
432 void coordinates(int* x
, int* y
) const
438 //----------------------------------------------------------------
439 void local_scale(int* x
, int* y
)
445 //----------------------------------------------------------------
446 void transform(double* x
, double* y
) const
448 m_trans_dir
.transform(x
, y
);
452 trans_type m_trans_dir
;
453 trans_type m_trans_inv
;
454 dda2_line_interpolator m_coord_x
;
455 dda2_line_interpolator m_coord_y
;
456 dda2_line_interpolator m_scale_x
;
457 dda2_line_interpolator m_scale_y
;