agg_math.h 14 KB

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