agg_math.h
上传用户:hymbga
上传日期:2009-05-24
资源大小:6364k
文件大小:13k
源码类别:

Windows编程

开发平台:

C/C++

  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. // Bessel function (besj) was adapted for use in AGG library by Andy Wilk 
  16. // Contact: castor.vulgaris@gmail.com
  17. //----------------------------------------------------------------------------
  18. #ifndef AGG_MATH_INCLUDED
  19. #define AGG_MATH_INCLUDED
  20. #include <math.h>
  21. #include "agg_basics.h"
  22. namespace agg
  23. {
  24.     //------------------------------------------------------vertex_dist_epsilon
  25.     // Coinciding points maximal distance (Epsilon)
  26.     const double vertex_dist_epsilon = 1e-14;
  27.     //-----------------------------------------------------intersection_epsilon
  28.     // See calc_intersection
  29.     const double intersection_epsilon = 1.0e-30;
  30.     //------------------------------------------------------------cross_product
  31.     AGG_INLINE double cross_product(double x1, double y1, 
  32.                                     double x2, double y2, 
  33.                                     double x,  double y)
  34.     {
  35.         return (x - x2) * (y2 - y1) - (y - y2) * (x2 - x1);
  36.     }
  37.     //--------------------------------------------------------point_in_triangle
  38.     AGG_INLINE bool point_in_triangle(double x1, double y1, 
  39.                                       double x2, double y2, 
  40.                                       double x3, double y3, 
  41.                                       double x,  double y)
  42.     {
  43.         bool cp1 = cross_product(x1, y1, x2, y2, x, y) < 0.0;
  44.         bool cp2 = cross_product(x2, y2, x3, y3, x, y) < 0.0;
  45.         bool cp3 = cross_product(x3, y3, x1, y1, x, y) < 0.0;
  46.         return cp1 == cp2 && cp2 == cp3 && cp3 == cp1;
  47.     }
  48.     //-----------------------------------------------------------calc_distance
  49.     AGG_INLINE double calc_distance(double x1, double y1, double x2, double y2)
  50.     {
  51.         double dx = x2-x1;
  52.         double dy = y2-y1;
  53.         return sqrt(dx * dx + dy * dy);
  54.     }
  55.     //------------------------------------------------calc_line_point_distance
  56.     AGG_INLINE double calc_line_point_distance(double x1, double y1, 
  57.                                                double x2, double y2, 
  58.                                                double x,  double y)
  59.     {
  60.         double dx = x2-x1;
  61.         double dy = y2-y1;
  62.         double d = sqrt(dx * dx + dy * dy);
  63.         if(d < vertex_dist_epsilon)
  64.         {
  65.             return calc_distance(x1, y1, x, y);
  66.         }
  67.         return ((x - x2) * dy - (y - y2) * dx) / d;
  68.     }
  69.     //-------------------------------------------------------calc_intersection
  70.     AGG_INLINE bool calc_intersection(double ax, double ay, double bx, double by,
  71.                                       double cx, double cy, double dx, double dy,
  72.                                       double* x, double* y)
  73.     {
  74.         double num = (ay-cy) * (dx-cx) - (ax-cx) * (dy-cy);
  75.         double den = (bx-ax) * (dy-cy) - (by-ay) * (dx-cx);
  76.         if(fabs(den) < intersection_epsilon) return false;
  77.         double r = num / den;
  78.         *x = ax + r * (bx-ax);
  79.         *y = ay + r * (by-ay);
  80.         return true;
  81.     }
  82.     //-----------------------------------------------------intersection_exists
  83.     AGG_INLINE bool intersection_exists(double x1, double y1, double x2, double y2,
  84.                                         double x3, double y3, double x4, double y4)
  85.     {
  86.         // It's less expensive but you can't control the 
  87.         // boundary conditions: Less or LessEqual
  88.         double dx1 = x2 - x1;
  89.         double dy1 = y2 - y1;
  90.         double dx2 = x4 - x3;
  91.         double dy2 = y4 - y3;
  92.         return ((x3 - x2) * dy1 - (y3 - y2) * dx1 < 0.0) != 
  93.                ((x4 - x2) * dy1 - (y4 - y2) * dx1 < 0.0) &&
  94.                ((x1 - x4) * dy2 - (y1 - y4) * dx2 < 0.0) !=
  95.                ((x2 - x4) * dy2 - (y2 - y4) * dx2 < 0.0);
  96.         // It's is more expensive but more flexible 
  97.         // in terms of boundary conditions.
  98.         //--------------------
  99.         //double den  = (x2-x1) * (y4-y3) - (y2-y1) * (x4-x3);
  100.         //if(fabs(den) < intersection_epsilon) return false;
  101.         //double nom1 = (x4-x3) * (y1-y3) - (y4-y3) * (x1-x3);
  102.         //double nom2 = (x2-x1) * (y1-y3) - (y2-y1) * (x1-x3);
  103.         //double ua = nom1 / den;
  104.         //double ub = nom2 / den;
  105.         //return ua >= 0.0 && ua <= 1.0 && ub >= 0.0 && ub <= 1.0;
  106.     }
  107.     //--------------------------------------------------------calc_orthogonal
  108.     AGG_INLINE void calc_orthogonal(double thickness,
  109.                                     double x1, double y1,
  110.                                     double x2, double y2,
  111.                                     double* x, double* y)
  112.     {
  113.         double dx = x2 - x1;
  114.         double dy = y2 - y1;
  115.         double d = sqrt(dx*dx + dy*dy); 
  116.         *x = thickness * dy / d;
  117.         *y = thickness * dx / d;
  118.     }
  119.     //--------------------------------------------------------dilate_triangle
  120.     AGG_INLINE void dilate_triangle(double x1, double y1,
  121.                                     double x2, double y2,
  122.                                     double x3, double y3,
  123.                                     double *x, double* y,
  124.                                     double d)
  125.     {
  126.         double dx1=0.0;
  127.         double dy1=0.0; 
  128.         double dx2=0.0;
  129.         double dy2=0.0; 
  130.         double dx3=0.0;
  131.         double dy3=0.0; 
  132.         double loc = cross_product(x1, y1, x2, y2, x3, y3);
  133.         if(fabs(loc) > intersection_epsilon)
  134.         {
  135.             if(cross_product(x1, y1, x2, y2, x3, y3) > 0.0) 
  136.             {
  137.                 d = -d;
  138.             }
  139.             calc_orthogonal(d, x1, y1, x2, y2, &dx1, &dy1);
  140.             calc_orthogonal(d, x2, y2, x3, y3, &dx2, &dy2);
  141.             calc_orthogonal(d, x3, y3, x1, y1, &dx3, &dy3);
  142.         }
  143.         *x++ = x1 + dx1;  *y++ = y1 - dy1;
  144.         *x++ = x2 + dx1;  *y++ = y2 - dy1;
  145.         *x++ = x2 + dx2;  *y++ = y2 - dy2;
  146.         *x++ = x3 + dx2;  *y++ = y3 - dy2;
  147.         *x++ = x3 + dx3;  *y++ = y3 - dy3;
  148.         *x++ = x1 + dx3;  *y++ = y1 - dy3;
  149.     }
  150.     //------------------------------------------------------calc_triangle_area
  151.     AGG_INLINE double calc_triangle_area(double x1, double y1,
  152.                                          double x2, double y2,
  153.                                          double x3, double y3)
  154.     {
  155.         return (x1*y2 - x2*y1 + x2*y3 - x3*y2 + x3*y1 - x1*y3) * 0.5;
  156.     }
  157.     //-------------------------------------------------------calc_polygon_area
  158.     template<class Storage> double calc_polygon_area(const Storage& st)
  159.     {
  160.         unsigned i;
  161.         double sum = 0.0;
  162.         double x  = st[0].x;
  163.         double y  = st[0].y;
  164.         double xs = x;
  165.         double ys = y;
  166.         for(i = 1; i < st.size(); i++)
  167.         {
  168.             const typename Storage::value_type& v = st[i];
  169.             sum += x * v.y - y * v.x;
  170.             x = v.x;
  171.             y = v.y;
  172.         }
  173.         return (sum + x * ys - y * xs) * 0.5;
  174.     }
  175.     //------------------------------------------------------------------------
  176.     // Tables for fast sqrt
  177.     extern int16u g_sqrt_table[1024];
  178.     extern int8   g_elder_bit_table[256];
  179.     //---------------------------------------------------------------fast_sqrt
  180.     //Fast integer Sqrt - really fast: no cycles, divisions or multiplications
  181.     #if defined(_MSC_VER)
  182.     #pragma warning(push)
  183.     #pragma warning(disable : 4035) //Disable warning "no return value"
  184.     #endif
  185.     AGG_INLINE unsigned fast_sqrt(unsigned val)
  186.     {
  187.     #if defined(_M_IX86) && defined(_MSC_VER) && !defined(AGG_NO_ASM)
  188.         //For Ix86 family processors this assembler code is used. 
  189.         //The key command here is bsr - determination the number of the most 
  190.         //significant bit of the value. For other processors
  191.         //(and maybe compilers) the pure C "#else" section is used.
  192.         __asm
  193.         {
  194.             mov ebx, val
  195.             mov edx, 11
  196.             bsr ecx, ebx
  197.             sub ecx, 9
  198.             jle less_than_9_bits
  199.             shr ecx, 1
  200.             adc ecx, 0
  201.             sub edx, ecx
  202.             shl ecx, 1
  203.             shr ebx, cl
  204.     less_than_9_bits:
  205.             xor eax, eax
  206.             mov  ax, g_sqrt_table[ebx*2]
  207.             mov ecx, edx
  208.             shr eax, cl
  209.         }
  210.     #else
  211.         //This code is actually pure C and portable to most 
  212.         //arcitectures including 64bit ones. 
  213.         unsigned t = val;
  214.         int bit=0;
  215.         unsigned shift = 11;
  216.         //The following piece of code is just an emulation of the
  217.         //Ix86 assembler command "bsr" (see above). However on old
  218.         //Intels (like Intel MMX 233MHz) this code is about twice 
  219.         //faster (sic!) then just one "bsr". On PIII and PIV the
  220.         //bsr is optimized quite well.
  221.         bit = t >> 24;
  222.         if(bit)
  223.         {
  224.             bit = g_elder_bit_table[bit] + 24;
  225.         }
  226.         else
  227.         {
  228.             bit = (t >> 16) & 0xFF;
  229.             if(bit)
  230.             {
  231.                 bit = g_elder_bit_table[bit] + 16;
  232.             }
  233.             else
  234.             {
  235.                 bit = (t >> 8) & 0xFF;
  236.                 if(bit)
  237.                 {
  238.                     bit = g_elder_bit_table[bit] + 8;
  239.                 }
  240.                 else
  241.                 {
  242.                     bit = g_elder_bit_table[t];
  243.                 }
  244.             }
  245.         }
  246.         //This is calculation sqrt itself.
  247.         bit -= 9;
  248.         if(bit > 0)
  249.         {
  250.             bit = (bit >> 1) + (bit & 1);
  251.             shift -= bit;
  252.             val >>= (bit << 1);
  253.         }
  254.         return g_sqrt_table[val] >> shift;
  255.     #endif
  256.     }
  257.     #if defined(_MSC_VER)
  258.     #pragma warning(pop)
  259.     #endif
  260.     //--------------------------------------------------------------------besj
  261.     // Function BESJ calculates Bessel function of first kind of order n
  262.     // Arguments:
  263.     //     n - an integer (>=0), the order
  264.     //     x - value at which the Bessel function is required
  265.     //--------------------
  266.     // C++ Mathematical Library
  267.     // Convereted from equivalent FORTRAN library
  268.     // Converetd by Gareth Walker for use by course 392 computational project
  269.     // All functions tested and yield the same results as the corresponding
  270.     // FORTRAN versions.
  271.     //
  272.     // If you have any problems using these functions please report them to
  273.     // M.Muldoon@UMIST.ac.uk
  274.     //
  275.     // Documentation available on the web
  276.     // http://www.ma.umist.ac.uk/mrm/Teaching/392/libs/392.html
  277.     // Version 1.0   8/98
  278.     // 29 October, 1999
  279.     //--------------------
  280.     // Adapted for use in AGG library by Andy Wilk (castor.vulgaris@gmail.com)
  281.     //------------------------------------------------------------------------
  282.     inline double besj(double x, int n)
  283.     {
  284.         if(n < 0)
  285.         {
  286.             return 0;
  287.         }
  288.         double d = 1E-6;
  289.         double b = 0;
  290.         if(fabs(x) <= d) 
  291.         {
  292.             if(n != 0) return 0;
  293.             return 1;
  294.         }
  295.         double b1 = 0; // b1 is the value from the previous iteration
  296.         // Set up a starting order for recurrence
  297.         int m1 = (int)fabs(x) + 6;
  298.         if(fabs(x) > 5) 
  299.         {
  300.             m1 = (int)(fabs(1.4 * x + 60 / x));
  301.         }
  302.         int m2 = (int)(n + 2 + fabs(x) / 4);
  303.         if (m1 > m2) 
  304.         {
  305.             m2 = m1;
  306.         }
  307.     
  308.         // Apply recurrence down from curent max order
  309.         for(;;) 
  310.         {
  311.             double c3 = 0;
  312.             double c2 = 1E-30;
  313.             double c4 = 0;
  314.             int m8 = 1;
  315.             if (m2 / 2 * 2 == m2) 
  316.             {
  317.                 m8 = -1;
  318.             }
  319.             int imax = m2 - 2;
  320.             for (int i = 1; i <= imax; i++) 
  321.             {
  322.                 double c6 = 2 * (m2 - i) * c2 / x - c3;
  323.                 c3 = c2;
  324.                 c2 = c6;
  325.                 if(m2 - i - 1 == n)
  326.                 {
  327.                     b = c6;
  328.                 }
  329.                 m8 = -1 * m8;
  330.                 if (m8 > 0)
  331.                 {
  332.                     c4 = c4 + 2 * c6;
  333.                 }
  334.             }
  335.             double c6 = 2 * c2 / x - c3;
  336.             if(n == 0)
  337.             {
  338.                 b = c6;
  339.             }
  340.             c4 += c6;
  341.             b /= c4;
  342.             if(fabs(b - b1) < d)
  343.             {
  344.                 return b;
  345.             }
  346.             b1 = b;
  347.             m2 += 3;
  348.         }
  349.     }
  350. }
  351. #endif