1 //----------------------------------------------------------------------------
2 // Anti-Grain Geometry (AGG) - Version 2.5
3 // A high quality rendering engine for C++
4 // Copyright (C) 2002-2006 Maxim Shemanarev
5 // Contact: mcseem@antigrain.com
6 //          mcseemagg@yahoo.com
7 //          http://antigrain.com
8 //
9 // AGG is free software; you can redistribute it and/or
10 // modify it under the terms of the GNU General Public License
11 // as published by the Free Software Foundation; either version 2
12 // of the License, or (at your option) any later version.
13 //
14 // AGG is distributed in the hope that it will be useful,
15 // but WITHOUT ANY WARRANTY; without even the implied warranty of
16 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17 // GNU General Public License for more details.
18 //
19 // You should have received a copy of the GNU General Public License
20 // along with AGG; if not, write to the Free Software
21 // Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
22 // MA 02110-1301, USA.
23 //----------------------------------------------------------------------------
24 
25 #ifndef AGG_ELLIPSE_INCLUDED
26 #define AGG_ELLIPSE_INCLUDED
27 
28 #include "agg_basics.h"
29 #include <math.h>
30 
31 namespace agg
32 {
33 
34     //----------------------------------------------------------------ellipse
35     class ellipse
36     {
37     public:
ellipse()38         ellipse() :
39             m_x(0.0), m_y(0.0), m_rx(1.0), m_ry(1.0), m_scale(1.0),
40             m_num(4), m_step(0), m_cw(false) {}
41 
42         ellipse(double x, double y, double rx, double ry,
43                 unsigned num_steps=0, bool cw=false) :
m_x(x)44             m_x(x), m_y(y), m_rx(rx), m_ry(ry), m_scale(1.0),
45             m_num(num_steps), m_step(0), m_cw(cw)
46         {
47             if(m_num == 0) calc_num_steps();
48         }
49 
50         void init(double x, double y, double rx, double ry,
51                   unsigned num_steps=0, bool cw=false);
52 
53         void approximation_scale(double scale);
54         void rewind(unsigned path_id);
55         unsigned vertex(double* x, double* y);
56 
57     private:
58         void calc_num_steps();
59 
60         double m_x;
61         double m_y;
62         double m_rx;
63         double m_ry;
64         double m_scale;
65         unsigned m_num;
66         unsigned m_step;
67         bool m_cw;
68     };
69 
70     //------------------------------------------------------------------------
init(double x,double y,double rx,double ry,unsigned num_steps,bool cw)71     inline void ellipse::init(double x, double y, double rx, double ry,
72                               unsigned num_steps, bool cw)
73     {
74         m_x = x;
75         m_y = y;
76         m_rx = rx;
77         m_ry = ry;
78         m_num = num_steps;
79         m_step = 0;
80         m_cw = cw;
81         if(m_num == 0) calc_num_steps();
82     }
83 
84     //------------------------------------------------------------------------
approximation_scale(double scale)85     inline void ellipse::approximation_scale(double scale)
86     {
87         m_scale = scale;
88         calc_num_steps();
89     }
90 
91     //------------------------------------------------------------------------
calc_num_steps()92     inline void ellipse::calc_num_steps()
93     {
94         double ra = (fabs(m_rx) + fabs(m_ry)) / 2;
95         double da = acos(ra / (ra + 0.125 / m_scale)) * 2;
96         m_num = uround(2*pi / da);
97     }
98 
99     //------------------------------------------------------------------------
rewind(unsigned)100     inline void ellipse::rewind(unsigned)
101     {
102         m_step = 0;
103     }
104 
105     //------------------------------------------------------------------------
vertex(double * x,double * y)106     inline unsigned ellipse::vertex(double* x, double* y)
107     {
108         if(m_step == m_num)
109         {
110             ++m_step;
111             return path_cmd_end_poly | path_flags_close | path_flags_ccw;
112         }
113         if(m_step > m_num) return path_cmd_stop;
114         double angle = double(m_step) / double(m_num) * 2.0 * pi;
115         if(m_cw) angle = 2.0 * pi - angle;
116         *x = m_x + cos(angle) * m_rx;
117         *y = m_y + sin(angle) * m_ry;
118         m_step++;
119         return ((m_step == 1) ? path_cmd_move_to : path_cmd_line_to);
120     }
121 
122 }
123 
124 
125 
126 #endif
127 
128 
129