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