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