agg_ellipse.h 3.6 KB

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