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// Arc generator. Produces at most 4 consecutive cubic bezier curves, i.e.,
17// 4, 7, 10, or 13 vertices.
18//
19//----------------------------------------------------------------------------
20
21#ifndef AGG_BEZIER_ARC_INCLUDED
22#define AGG_BEZIER_ARC_INCLUDED
23
24#include "agg_conv_transform.h"
25
26namespace agg
27{
28
29    //-----------------------------------------------------------------------
30    void arc_to_bezier(double cx, double cy, double rx, double ry,
31                       double start_angle, double sweep_angle,
32                       double* curve);
33
34
35    //==============================================================bezier_arc
36    //
37    // See implemantaion agg_bezier_arc.cpp
38    //
39    class bezier_arc
40    {
41    public:
42        //--------------------------------------------------------------------
43        bezier_arc() : m_vertex(26), m_num_vertices(0), m_cmd(path_cmd_line_to) {}
44        bezier_arc(double x,  double y,
45                   double rx, double ry,
46                   double start_angle,
47                   double sweep_angle)
48        {
49            init(x, y, rx, ry, start_angle, sweep_angle);
50        }
51
52        //--------------------------------------------------------------------
53        void init(double x,  double y,
54                  double rx, double ry,
55                  double start_angle,
56                  double sweep_angle);
57
58        //--------------------------------------------------------------------
59        void rewind(unsigned)
60        {
61            m_vertex = 0;
62        }
63
64        //--------------------------------------------------------------------
65        unsigned vertex(double* x, double* y)
66        {
67            if(m_vertex >= m_num_vertices) return path_cmd_stop;
68            *x = m_vertices[m_vertex];
69            *y = m_vertices[m_vertex + 1];
70            m_vertex += 2;
71            return (m_vertex == 2) ? path_cmd_move_to : m_cmd;
72        }
73
74        // Supplemantary functions. num_vertices() actually returns doubled
75        // number of vertices. That is, for 1 vertex it returns 2.
76        //--------------------------------------------------------------------
77        unsigned  num_vertices() const { return m_num_vertices; }
78        const double* vertices() const { return m_vertices;     }
79        double*       vertices()       { return m_vertices;     }
80
81    private:
82        unsigned m_vertex;
83        unsigned m_num_vertices;
84        double   m_vertices[26];
85        unsigned m_cmd;
86    };
87
88
89
90    //==========================================================bezier_arc_svg
91    // Compute an SVG-style bezier arc.
92    //
93    // Computes an elliptical arc from (x1, y1) to (x2, y2). The size and
94    // orientation of the ellipse are defined by two radii (rx, ry)
95    // and an x-axis-rotation, which indicates how the ellipse as a whole
96    // is rotated relative to the current coordinate system. The center
97    // (cx, cy) of the ellipse is calculated automatically to satisfy the
98    // constraints imposed by the other parameters.
99    // large-arc-flag and sweep-flag contribute to the automatic calculations
100    // and help determine how the arc is drawn.
101    class bezier_arc_svg
102    {
103    public:
104        //--------------------------------------------------------------------
105        bezier_arc_svg() : m_arc(), m_radii_ok(false) {}
106
107        bezier_arc_svg(double x1, double y1,
108                       double rx, double ry,
109                       double angle,
110                       bool large_arc_flag,
111                       bool sweep_flag,
112                       double x2, double y2) :
113            m_arc(), m_radii_ok(false)
114        {
115            init(x1, y1, rx, ry, angle, large_arc_flag, sweep_flag, x2, y2);
116        }
117
118        //--------------------------------------------------------------------
119        void init(double x1, double y1,
120                  double rx, double ry,
121                  double angle,
122                  bool large_arc_flag,
123                  bool sweep_flag,
124                  double x2, double y2);
125
126        //--------------------------------------------------------------------
127        bool radii_ok() const { return m_radii_ok; }
128
129        //--------------------------------------------------------------------
130        void rewind(unsigned)
131        {
132            m_arc.rewind(0);
133        }
134
135        //--------------------------------------------------------------------
136        unsigned vertex(double* x, double* y)
137        {
138            return m_arc.vertex(x, y);
139        }
140
141        // Supplemantary functions. num_vertices() actually returns doubled
142        // number of vertices. That is, for 1 vertex it returns 2.
143        //--------------------------------------------------------------------
144        unsigned  num_vertices() const { return m_arc.num_vertices(); }
145        const double* vertices() const { return m_arc.vertices();     }
146        double*       vertices()       { return m_arc.vertices();     }
147
148    private:
149        bezier_arc m_arc;
150        bool       m_radii_ok;
151    };
152
153
154
155
156}
157
158
159#endif
160