Anti-Grain Geometry - AGG (libagg)
2.5
|
00001 //---------------------------------------------------------------------------- 00002 // Anti-Grain Geometry (AGG) - Version 2.5 00003 // A high quality rendering engine for C++ 00004 // Copyright (C) 2002-2006 Maxim Shemanarev 00005 // Contact: mcseem@antigrain.com 00006 // mcseemagg@yahoo.com 00007 // http://antigrain.com 00008 // 00009 // AGG is free software; you can redistribute it and/or 00010 // modify it under the terms of the GNU General Public License 00011 // as published by the Free Software Foundation; either version 2 00012 // of the License, or (at your option) any later version. 00013 // 00014 // AGG is distributed in the hope that it will be useful, 00015 // but WITHOUT ANY WARRANTY; without even the implied warranty of 00016 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00017 // GNU General Public License for more details. 00018 // 00019 // You should have received a copy of the GNU General Public License 00020 // along with AGG; if not, write to the Free Software 00021 // Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, 00022 // MA 02110-1301, USA. 00023 //---------------------------------------------------------------------------- 00024 00025 #ifndef AGG_ELLIPSE_INCLUDED 00026 #define AGG_ELLIPSE_INCLUDED 00027 00028 #include "agg_basics.h" 00029 #include <math.h> 00030 00031 namespace agg 00032 { 00033 00034 //----------------------------------------------------------------ellipse 00035 class ellipse 00036 { 00037 public: 00038 ellipse() : 00039 m_x(0.0), m_y(0.0), m_rx(1.0), m_ry(1.0), m_scale(1.0), 00040 m_num(4), m_step(0), m_cw(false) {} 00041 00042 ellipse(double x, double y, double rx, double ry, 00043 unsigned num_steps=0, bool cw=false) : 00044 m_x(x), m_y(y), m_rx(rx), m_ry(ry), m_scale(1.0), 00045 m_num(num_steps), m_step(0), m_cw(cw) 00046 { 00047 if(m_num == 0) calc_num_steps(); 00048 } 00049 00050 void init(double x, double y, double rx, double ry, 00051 unsigned num_steps=0, bool cw=false); 00052 00053 void approximation_scale(double scale); 00054 void rewind(unsigned path_id); 00055 unsigned vertex(double* x, double* y); 00056 00057 private: 00058 void calc_num_steps(); 00059 00060 double m_x; 00061 double m_y; 00062 double m_rx; 00063 double m_ry; 00064 double m_scale; 00065 unsigned m_num; 00066 unsigned m_step; 00067 bool m_cw; 00068 }; 00069 00070 //------------------------------------------------------------------------ 00071 inline void ellipse::init(double x, double y, double rx, double ry, 00072 unsigned num_steps, bool cw) 00073 { 00074 m_x = x; 00075 m_y = y; 00076 m_rx = rx; 00077 m_ry = ry; 00078 m_num = num_steps; 00079 m_step = 0; 00080 m_cw = cw; 00081 if(m_num == 0) calc_num_steps(); 00082 } 00083 00084 //------------------------------------------------------------------------ 00085 inline void ellipse::approximation_scale(double scale) 00086 { 00087 m_scale = scale; 00088 calc_num_steps(); 00089 } 00090 00091 //------------------------------------------------------------------------ 00092 inline void ellipse::calc_num_steps() 00093 { 00094 double ra = (fabs(m_rx) + fabs(m_ry)) / 2; 00095 double da = acos(ra / (ra + 0.125 / m_scale)) * 2; 00096 m_num = uround(2*pi / da); 00097 } 00098 00099 //------------------------------------------------------------------------ 00100 inline void ellipse::rewind(unsigned) 00101 { 00102 m_step = 0; 00103 } 00104 00105 //------------------------------------------------------------------------ 00106 inline unsigned ellipse::vertex(double* x, double* y) 00107 { 00108 if(m_step == m_num) 00109 { 00110 ++m_step; 00111 return path_cmd_end_poly | path_flags_close | path_flags_ccw; 00112 } 00113 if(m_step > m_num) return path_cmd_stop; 00114 double angle = double(m_step) / double(m_num) * 2.0 * pi; 00115 if(m_cw) angle = 2.0 * pi - angle; 00116 *x = m_x + cos(angle) * m_rx; 00117 *y = m_y + sin(angle) * m_ry; 00118 m_step++; 00119 return ((m_step == 1) ? path_cmd_move_to : path_cmd_line_to); 00120 } 00121 00122 } 00123 00124 00125 00126 #endif 00127 00128