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