xref: /haiku/headers/libs/agg/agg_ellipse.h (revision e39da397f5ff79f2db9f9a3ddf1852b6710578af)
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 
26 namespace agg
27 {
28 
29     //----------------------------------------------------------------ellipse
30     class ellipse
31     {
32     public:
ellipse()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) :
m_x(x)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     //------------------------------------------------------------------------
init(double x,double y,double rx,double ry,unsigned num_steps,bool cw)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     //------------------------------------------------------------------------
approximation_scale(double scale)80     inline void ellipse::approximation_scale(double scale)
81     {
82         m_scale = scale;
83         calc_num_steps();
84     }
85 
86     //------------------------------------------------------------------------
calc_num_steps()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     //------------------------------------------------------------------------
rewind(unsigned)95     inline void ellipse::rewind(unsigned)
96     {
97         m_step = 0;
98     }
99 
100     //------------------------------------------------------------------------
vertex(double * x,double * y)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