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