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// class ellipse
17//
18//----------------------------------------------------------------------------
19
20#ifndef AGG_ELLIPSE_INCLUDED
21#define AGG_ELLIPSE_INCLUDED
22
23#include "agg_basics.h"
24#include <math.h>
25
26namespace agg
27{
28
29    //----------------------------------------------------------------ellipse
30    class ellipse
31    {
32    public:
33        ellipse() :
34            m_x(0.0), m_y(0.0), m_rx(1.0), m_ry(1.0), m_scale(1.0),
35            m_num(4), m_step(0), m_cw(false) {}
36
37        ellipse(double x, double y, double rx, double ry,
38                unsigned num_steps=0, bool cw=false) :
39            m_x(x), m_y(y), m_rx(rx), m_ry(ry), m_scale(1.0),
40            m_num(num_steps), m_step(0), m_cw(cw)
41        {
42            if(m_num == 0) calc_num_steps();
43        }
44
45        void init(double x, double y, double rx, double ry,
46                  unsigned num_steps=0, bool cw=false);
47
48        void approximation_scale(double scale);
49        void rewind(unsigned path_id);
50        unsigned vertex(double* x, double* y);
51
52    private:
53        void calc_num_steps();
54
55        double m_x;
56        double m_y;
57        double m_rx;
58        double m_ry;
59        double m_scale;
60        unsigned m_num;
61        unsigned m_step;
62        bool m_cw;
63    };
64
65    //------------------------------------------------------------------------
66    inline void ellipse::init(double x, double y, double rx, double ry,
67                              unsigned num_steps, bool cw)
68    {
69        m_x = x;
70        m_y = y;
71        m_rx = rx;
72        m_ry = ry;
73        m_num = num_steps;
74        m_step = 0;
75        m_cw = cw;
76        if(m_num == 0) calc_num_steps();
77    }
78
79    //------------------------------------------------------------------------
80    inline void ellipse::approximation_scale(double scale)
81    {
82        m_scale = scale;
83        calc_num_steps();
84    }
85
86    //------------------------------------------------------------------------
87    inline void ellipse::calc_num_steps()
88    {
89        double ra = (fabs(m_rx) + fabs(m_ry)) / 2;
90        double da = acos(ra / (ra + 0.125 / m_scale)) * 2;
91        m_num = uround(2*pi / da);
92    }
93
94    //------------------------------------------------------------------------
95    inline void ellipse::rewind(unsigned)
96    {
97        m_step = 0;
98    }
99
100    //------------------------------------------------------------------------
101    inline unsigned ellipse::vertex(double* x, double* y)
102    {
103        if(m_step == m_num)
104        {
105            ++m_step;
106            return path_cmd_end_poly | path_flags_close | path_flags_ccw;
107        }
108        if(m_step > m_num) return path_cmd_stop;
109        double angle = double(m_step) / double(m_num) * 2.0 * pi;
110        if(m_cw) angle = 2.0 * pi - angle;
111        *x = m_x + cos(angle) * m_rx;
112        *y = m_y + sin(angle) * m_ry;
113        m_step++;
114        return ((m_step == 1) ? path_cmd_move_to : path_cmd_line_to);
115    }
116
117}
118
119
120
121#endif
122
123
124