1 //----------------------------------------------------------------------------
2 // Anti-Grain Geometry - Version 2.4
3 // Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com)
4 // Copyright (C) 2005 Tony Juricic (tonygeek@yahoo.com)
6 // Permission to copy, use, modify, sell and distribute this software
7 // is granted provided this copyright notice appears in all copies.
8 // This software is provided "as is" without express or implied
9 // warranty, and with no claim as to its suitability for any purpose.
11 //----------------------------------------------------------------------------
12 // Contact: mcseem@antigrain.com
13 // mcseemagg@yahoo.com
14 // http://www.antigrain.com
15 //----------------------------------------------------------------------------
17 #ifndef AGG_CURVES_INCLUDED
18 #define AGG_CURVES_INCLUDED
20 #include "agg_array.h"
25 // See Implementation agg_curves.cpp
27 //--------------------------------------------curve_approximation_method_e
28 enum curve_approximation_method_e
34 //--------------------------------------------------------------curve3_inc
39 m_num_steps(0), m_step(0), m_scale(1.0) { }
41 curve3_inc(double x1
, double y1
,
43 double x3
, double y3
) :
44 m_num_steps(0), m_step(0), m_scale(1.0)
46 init(x1
, y1
, x2
, y2
, x3
, y3
);
49 void reset() { m_num_steps
= 0; m_step
= -1; }
50 void init(double x1
, double y1
,
52 double x3
, double y3
);
54 void approximation_method(curve_approximation_method_e
) {}
55 curve_approximation_method_e
approximation_method() const { return curve_inc
; }
57 void approximation_scale(double s
);
58 double approximation_scale() const;
60 void angle_tolerance(double) {}
61 double angle_tolerance() const { return 0.0; }
63 void cusp_limit(double) {}
64 double cusp_limit() const { return 0.0; }
66 void rewind(unsigned path_id
);
67 unsigned vertex(double* x
, double* y
);
93 //-------------------------------------------------------------curve3_div
98 m_approximation_scale(1.0),
99 m_angle_tolerance(0.0),
103 curve3_div(double x1
, double y1
,
104 double x2
, double y2
,
105 double x3
, double y3
) :
106 m_approximation_scale(1.0),
107 m_angle_tolerance(0.0),
110 init(x1
, y1
, x2
, y2
, x3
, y3
);
113 void reset() { m_points
.remove_all(); m_count
= 0; }
114 void init(double x1
, double y1
,
115 double x2
, double y2
,
116 double x3
, double y3
);
118 void approximation_method(curve_approximation_method_e
) {}
119 curve_approximation_method_e
approximation_method() const { return curve_div
; }
121 void approximation_scale(double s
) { m_approximation_scale
= s
; }
122 double approximation_scale() const { return m_approximation_scale
; }
124 void angle_tolerance(double a
) { m_angle_tolerance
= a
; }
125 double angle_tolerance() const { return m_angle_tolerance
; }
127 void cusp_limit(double) {}
128 double cusp_limit() const { return 0.0; }
130 void rewind(unsigned)
135 unsigned vertex(double* x
, double* y
)
137 if(m_count
>= m_points
.size()) return path_cmd_stop
;
138 const point_d
& p
= m_points
[m_count
++];
141 return (m_count
== 1) ? path_cmd_move_to
: path_cmd_line_to
;
145 void bezier(double x1
, double y1
,
146 double x2
, double y2
,
147 double x3
, double y3
);
148 void recursive_bezier(double x1
, double y1
,
149 double x2
, double y2
,
150 double x3
, double y3
,
153 double m_approximation_scale
;
154 double m_distance_tolerance_square
;
155 double m_angle_tolerance
;
157 pod_bvector
<point_d
> m_points
;
166 //-------------------------------------------------------------curve4_points
171 curve4_points(double x1
, double y1
,
172 double x2
, double y2
,
173 double x3
, double y3
,
174 double x4
, double y4
)
176 cp
[0] = x1
; cp
[1] = y1
; cp
[2] = x2
; cp
[3] = y2
;
177 cp
[4] = x3
; cp
[5] = y3
; cp
[6] = x4
; cp
[7] = y4
;
179 void init(double x1
, double y1
,
180 double x2
, double y2
,
181 double x3
, double y3
,
182 double x4
, double y4
)
184 cp
[0] = x1
; cp
[1] = y1
; cp
[2] = x2
; cp
[3] = y2
;
185 cp
[4] = x3
; cp
[5] = y3
; cp
[6] = x4
; cp
[7] = y4
;
187 double operator [] (unsigned i
) const { return cp
[i
]; }
188 double& operator [] (unsigned i
) { return cp
[i
]; }
193 //-------------------------------------------------------------curve4_inc
198 m_num_steps(0), m_step(0), m_scale(1.0) { }
200 curve4_inc(double x1
, double y1
,
201 double x2
, double y2
,
202 double x3
, double y3
,
203 double x4
, double y4
) :
204 m_num_steps(0), m_step(0), m_scale(1.0)
206 init(x1
, y1
, x2
, y2
, x3
, y3
, x4
, y4
);
209 curve4_inc(const curve4_points
& cp
) :
210 m_num_steps(0), m_step(0), m_scale(1.0)
212 init(cp
[0], cp
[1], cp
[2], cp
[3], cp
[4], cp
[5], cp
[6], cp
[7]);
215 void reset() { m_num_steps
= 0; m_step
= -1; }
216 void init(double x1
, double y1
,
217 double x2
, double y2
,
218 double x3
, double y3
,
219 double x4
, double y4
);
221 void init(const curve4_points
& cp
)
223 init(cp
[0], cp
[1], cp
[2], cp
[3], cp
[4], cp
[5], cp
[6], cp
[7]);
226 void approximation_method(curve_approximation_method_e
) {}
227 curve_approximation_method_e
approximation_method() const { return curve_inc
; }
229 void approximation_scale(double s
);
230 double approximation_scale() const;
232 void angle_tolerance(double) {}
233 double angle_tolerance() const { return 0.0; }
235 void cusp_limit(double) {}
236 double cusp_limit() const { return 0.0; }
238 void rewind(unsigned path_id
);
239 unsigned vertex(double* x
, double* y
);
267 //-------------------------------------------------------catrom_to_bezier
268 inline curve4_points
catrom_to_bezier(double x1
, double y1
,
269 double x2
, double y2
,
270 double x3
, double y3
,
271 double x4
, double y4
)
273 // Trans. matrix Catmull-Rom to Bezier
280 return curve4_points(
283 (-x1
+ 6*x2
+ x3
) / 6,
284 (-y1
+ 6*y2
+ y3
) / 6,
285 ( x2
+ 6*x3
- x4
) / 6,
286 ( y2
+ 6*y3
- y4
) / 6,
292 //-----------------------------------------------------------------------
294 catrom_to_bezier(const curve4_points
& cp
)
296 return catrom_to_bezier(cp
[0], cp
[1], cp
[2], cp
[3],
297 cp
[4], cp
[5], cp
[6], cp
[7]);
302 //-----------------------------------------------------ubspline_to_bezier
303 inline curve4_points
ubspline_to_bezier(double x1
, double y1
,
304 double x2
, double y2
,
305 double x3
, double y3
,
306 double x4
, double y4
)
308 // Trans. matrix Uniform BSpline to Bezier
315 return curve4_points(
316 (x1
+ 4*x2
+ x3
) / 6,
317 (y1
+ 4*y2
+ y3
) / 6,
322 (x2
+ 4*x3
+ x4
) / 6,
323 (y2
+ 4*y3
+ y4
) / 6);
327 //-----------------------------------------------------------------------
329 ubspline_to_bezier(const curve4_points
& cp
)
331 return ubspline_to_bezier(cp
[0], cp
[1], cp
[2], cp
[3],
332 cp
[4], cp
[5], cp
[6], cp
[7]);
338 //------------------------------------------------------hermite_to_bezier
339 inline curve4_points
hermite_to_bezier(double x1
, double y1
,
340 double x2
, double y2
,
341 double x3
, double y3
,
342 double x4
, double y4
)
344 // Trans. matrix Hermite to Bezier
351 return curve4_points(
364 //-----------------------------------------------------------------------
366 hermite_to_bezier(const curve4_points
& cp
)
368 return hermite_to_bezier(cp
[0], cp
[1], cp
[2], cp
[3],
369 cp
[4], cp
[5], cp
[6], cp
[7]);
373 //-------------------------------------------------------------curve4_div
378 m_approximation_scale(1.0),
379 m_angle_tolerance(0.0),
384 curve4_div(double x1
, double y1
,
385 double x2
, double y2
,
386 double x3
, double y3
,
387 double x4
, double y4
) :
388 m_approximation_scale(1.0),
389 m_angle_tolerance(0.0),
393 init(x1
, y1
, x2
, y2
, x3
, y3
, x4
, y4
);
396 curve4_div(const curve4_points
& cp
) :
397 m_approximation_scale(1.0),
398 m_angle_tolerance(0.0),
401 init(cp
[0], cp
[1], cp
[2], cp
[3], cp
[4], cp
[5], cp
[6], cp
[7]);
404 void reset() { m_points
.remove_all(); m_count
= 0; }
405 void init(double x1
, double y1
,
406 double x2
, double y2
,
407 double x3
, double y3
,
408 double x4
, double y4
);
410 void init(const curve4_points
& cp
)
412 init(cp
[0], cp
[1], cp
[2], cp
[3], cp
[4], cp
[5], cp
[6], cp
[7]);
415 void approximation_method(curve_approximation_method_e
) {}
417 curve_approximation_method_e
approximation_method() const
422 void approximation_scale(double s
) { m_approximation_scale
= s
; }
423 double approximation_scale() const { return m_approximation_scale
; }
425 void angle_tolerance(double a
) { m_angle_tolerance
= a
; }
426 double angle_tolerance() const { return m_angle_tolerance
; }
428 void cusp_limit(double v
)
430 m_cusp_limit
= (v
== 0.0) ? 0.0 : pi
- v
;
433 double cusp_limit() const
435 return (m_cusp_limit
== 0.0) ? 0.0 : pi
- m_cusp_limit
;
438 void rewind(unsigned)
443 unsigned vertex(double* x
, double* y
)
445 if(m_count
>= m_points
.size()) return path_cmd_stop
;
446 const point_d
& p
= m_points
[m_count
++];
449 return (m_count
== 1) ? path_cmd_move_to
: path_cmd_line_to
;
453 void bezier(double x1
, double y1
,
454 double x2
, double y2
,
455 double x3
, double y3
,
456 double x4
, double y4
);
458 void recursive_bezier(double x1
, double y1
,
459 double x2
, double y2
,
460 double x3
, double y3
,
461 double x4
, double y4
,
464 double m_approximation_scale
;
465 double m_distance_tolerance_square
;
466 double m_angle_tolerance
;
469 pod_bvector
<point_d
> m_points
;
473 //-----------------------------------------------------------------curve3
477 curve3() : m_approximation_method(curve_div
) {}
478 curve3(double x1
, double y1
,
479 double x2
, double y2
,
480 double x3
, double y3
) :
481 m_approximation_method(curve_div
)
483 init(x1
, y1
, x2
, y2
, x3
, y3
);
492 void init(double x1
, double y1
,
493 double x2
, double y2
,
494 double x3
, double y3
)
496 if(m_approximation_method
== curve_inc
)
498 m_curve_inc
.init(x1
, y1
, x2
, y2
, x3
, y3
);
502 m_curve_div
.init(x1
, y1
, x2
, y2
, x3
, y3
);
506 void approximation_method(curve_approximation_method_e v
)
508 m_approximation_method
= v
;
511 curve_approximation_method_e
approximation_method() const
513 return m_approximation_method
;
516 void approximation_scale(double s
)
518 m_curve_inc
.approximation_scale(s
);
519 m_curve_div
.approximation_scale(s
);
522 double approximation_scale() const
524 return m_curve_inc
.approximation_scale();
527 void angle_tolerance(double a
)
529 m_curve_div
.angle_tolerance(a
);
532 double angle_tolerance() const
534 return m_curve_div
.angle_tolerance();
537 void cusp_limit(double v
)
539 m_curve_div
.cusp_limit(v
);
542 double cusp_limit() const
544 return m_curve_div
.cusp_limit();
547 void rewind(unsigned path_id
)
549 if(m_approximation_method
== curve_inc
)
551 m_curve_inc
.rewind(path_id
);
555 m_curve_div
.rewind(path_id
);
559 unsigned vertex(double* x
, double* y
)
561 if(m_approximation_method
== curve_inc
)
563 return m_curve_inc
.vertex(x
, y
);
565 return m_curve_div
.vertex(x
, y
);
569 curve3_inc m_curve_inc
;
570 curve3_div m_curve_div
;
571 curve_approximation_method_e m_approximation_method
;
578 //-----------------------------------------------------------------curve4
582 curve4() : m_approximation_method(curve_div
) {}
583 curve4(double x1
, double y1
,
584 double x2
, double y2
,
585 double x3
, double y3
,
586 double x4
, double y4
) :
587 m_approximation_method(curve_div
)
589 init(x1
, y1
, x2
, y2
, x3
, y3
, x4
, y4
);
592 curve4(const curve4_points
& cp
) :
593 m_approximation_method(curve_div
)
595 init(cp
[0], cp
[1], cp
[2], cp
[3], cp
[4], cp
[5], cp
[6], cp
[7]);
604 void init(double x1
, double y1
,
605 double x2
, double y2
,
606 double x3
, double y3
,
607 double x4
, double y4
)
609 if(m_approximation_method
== curve_inc
)
611 m_curve_inc
.init(x1
, y1
, x2
, y2
, x3
, y3
, x4
, y4
);
615 m_curve_div
.init(x1
, y1
, x2
, y2
, x3
, y3
, x4
, y4
);
619 void init(const curve4_points
& cp
)
621 init(cp
[0], cp
[1], cp
[2], cp
[3], cp
[4], cp
[5], cp
[6], cp
[7]);
624 void approximation_method(curve_approximation_method_e v
)
626 m_approximation_method
= v
;
629 curve_approximation_method_e
approximation_method() const
631 return m_approximation_method
;
634 void approximation_scale(double s
)
636 m_curve_inc
.approximation_scale(s
);
637 m_curve_div
.approximation_scale(s
);
639 double approximation_scale() const { return m_curve_inc
.approximation_scale(); }
641 void angle_tolerance(double v
)
643 m_curve_div
.angle_tolerance(v
);
646 double angle_tolerance() const
648 return m_curve_div
.angle_tolerance();
651 void cusp_limit(double v
)
653 m_curve_div
.cusp_limit(v
);
656 double cusp_limit() const
658 return m_curve_div
.cusp_limit();
661 void rewind(unsigned path_id
)
663 if(m_approximation_method
== curve_inc
)
665 m_curve_inc
.rewind(path_id
);
669 m_curve_div
.rewind(path_id
);
673 unsigned vertex(double* x
, double* y
)
675 if(m_approximation_method
== curve_inc
)
677 return m_curve_inc
.vertex(x
, y
);
679 return m_curve_div
.vertex(x
, y
);
683 curve4_inc m_curve_inc
;
684 curve4_div m_curve_div
;
685 curve_approximation_method_e m_approximation_method
;