Coverage Report

Created: 2026-02-14 06:52

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/MapServer/src/renderers/agg/include/agg_math.h
Line
Count
Source
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 mapserver
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
0
    {
41
0
        return (x - x2) * (y2 - y1) - (y - y2) * (x2 - x1);
42
0
    }
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
0
    {
50
0
        bool cp1 = cross_product(x1, y1, x2, y2, x, y) < 0.0;
51
0
        bool cp2 = cross_product(x2, y2, x3, y3, x, y) < 0.0;
52
0
        bool cp3 = cross_product(x3, y3, x1, y1, x, y) < 0.0;
53
0
        return cp1 == cp2 && cp2 == cp3 && cp3 == cp1;
54
0
    }
55
56
    //-----------------------------------------------------------calc_distance
57
    AGG_INLINE double calc_distance(double x1, double y1, double x2, double y2)
58
0
    {
59
0
        double dx = x2-x1;
60
0
        double dy = y2-y1;
61
0
        return sqrt(dx * dx + dy * dy);
62
0
    }
63
64
    //--------------------------------------------------------calc_sq_distance
65
    AGG_INLINE double calc_sq_distance(double x1, double y1, double x2, double y2)
66
0
    {
67
0
        double dx = x2-x1;
68
0
        double dy = y2-y1;
69
0
        return dx * dx + dy * dy;
70
0
    }
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
0
    {
77
0
        double dx = x2-x1;
78
0
        double dy = y2-y1;
79
0
        double d = sqrt(dx * dx + dy * dy);
80
0
        if(d < vertex_dist_epsilon)
81
0
        {
82
0
            return calc_distance(x1, y1, x, y);
83
0
        }
84
0
        return ((x - x2) * dy - (y - y2) * dx) / d;
85
0
    }
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
0
    {
92
0
        double dx = x2 - x1;
93
0
        double dy = y2 - y1;
94
0
95
0
        if(dx == 0 && dy == 0)
96
0
        {
97
0
          return 0;
98
0
        }
99
0
100
0
        double pdx = x - x1;
101
0
        double pdy = y - y1;
102
0
103
0
        return (pdx * dx + pdy * dy) / (dx * dx + dy * dy);
104
0
    }
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
0
    {
112
0
        if(u <= 0)
113
0
        {
114
0
          return calc_sq_distance(x, y, x1, y1);
115
0
        }
116
0
        else 
117
0
        if(u >= 1)
118
0
        {
119
0
          return calc_sq_distance(x, y, x2, y2);
120
0
        }
121
0
        return calc_sq_distance(x, y, x1 + u * (x2 - x1), y1 + u * (y2 - y1));
122
0
    }
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
0
    {
129
0
        return 
130
0
            calc_segment_point_sq_distance(
131
0
                x1, y1, x2, y2, x, y,
132
0
                calc_segment_point_u(x1, y1, x2, y2, x, y));
133
0
    }
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
0
    {
140
0
        double num = (ay-cy) * (dx-cx) - (ax-cx) * (dy-cy);
141
0
        double den = (bx-ax) * (dy-cy) - (by-ay) * (dx-cx);
142
0
        if(fabs(den) < intersection_epsilon) return false;
143
0
        double r = num / den;
144
0
        *x = ax + r * (bx-ax);
145
0
        *y = ay + r * (by-ay);
146
0
        return true;
147
0
    }
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
0
    {
153
0
        // It's less expensive but you can't control the 
154
0
        // boundary conditions: Less or LessEqual
155
0
        double dx1 = x2 - x1;
156
0
        double dy1 = y2 - y1;
157
0
        double dx2 = x4 - x3;
158
0
        double dy2 = y4 - y3;
159
0
        return ((x3 - x2) * dy1 - (y3 - y2) * dx1 < 0.0) != 
160
0
               ((x4 - x2) * dy1 - (y4 - y2) * dx1 < 0.0) &&
161
0
               ((x1 - x4) * dy2 - (y1 - y4) * dx2 < 0.0) !=
162
0
               ((x2 - x4) * dy2 - (y2 - y4) * dx2 < 0.0);
163
0
164
0
        // It's is more expensive but more flexible 
165
0
        // in terms of boundary conditions.
166
0
        //--------------------
167
0
        //double den  = (x2-x1) * (y4-y3) - (y2-y1) * (x4-x3);
168
0
        //if(fabs(den) < intersection_epsilon) return false;
169
0
        //double nom1 = (x4-x3) * (y1-y3) - (y4-y3) * (x1-x3);
170
0
        //double nom2 = (x2-x1) * (y1-y3) - (y2-y1) * (x1-x3);
171
0
        //double ua = nom1 / den;
172
0
        //double ub = nom2 / den;
173
0
        //return ua >= 0.0 && ua <= 1.0 && ub >= 0.0 && ub <= 1.0;
174
0
    }
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
0
    {
182
0
        double dx = x2 - x1;
183
0
        double dy = y2 - y1;
184
0
        double d = sqrt(dx*dx + dy*dy); 
185
0
        *x =  thickness * dy / d;
186
0
        *y = -thickness * dx / d;
187
0
    }
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
0
    {
196
0
        double dx1=0.0;
197
0
        double dy1=0.0; 
198
0
        double dx2=0.0;
199
0
        double dy2=0.0; 
200
0
        double dx3=0.0;
201
0
        double dy3=0.0; 
202
0
        double loc = cross_product(x1, y1, x2, y2, x3, y3);
203
0
        if(fabs(loc) > intersection_epsilon)
204
0
        {
205
0
            if(cross_product(x1, y1, x2, y2, x3, y3) > 0.0) 
206
0
            {
207
0
                d = -d;
208
0
            }
209
0
            calc_orthogonal(d, x1, y1, x2, y2, &dx1, &dy1);
210
0
            calc_orthogonal(d, x2, y2, x3, y3, &dx2, &dy2);
211
0
            calc_orthogonal(d, x3, y3, x1, y1, &dx3, &dy3);
212
0
        }
213
0
        *x++ = x1 + dx1;  *y++ = y1 + dy1;
214
0
        *x++ = x2 + dx1;  *y++ = y2 + dy1;
215
0
        *x++ = x2 + dx2;  *y++ = y2 + dy2;
216
0
        *x++ = x3 + dx2;  *y++ = y3 + dy2;
217
0
        *x++ = x3 + dx3;  *y++ = y3 + dy3;
218
0
        *x++ = x1 + dx3;  *y++ = y1 + dy3;
219
0
    }
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
0
    {
226
0
        return (x1*y2 - x2*y1 + x2*y3 - x3*y2 + x3*y1 - x1*y3) * 0.5;
227
0
    }
228
229
    //-------------------------------------------------------calc_polygon_area
230
    template<class Storage> double calc_polygon_area(const Storage& st)
231
0
    {
232
0
        unsigned i;
233
0
        double sum = 0.0;
234
0
        double x  = st[0].x;
235
0
        double y  = st[0].y;
236
0
        double xs = x;
237
0
        double ys = y;
238
239
0
        for(i = 1; i < st.size(); i++)
240
0
        {
241
0
            const typename Storage::value_type& v = st[i];
242
0
            sum += x * v.y - y * v.x;
243
0
            x = v.x;
244
0
            y = v.y;
245
0
        }
246
0
        return (sum + x * ys - y * xs) * 0.5;
247
0
    }
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
0
    {
263
0
    #if defined(_M_IX86) && defined(_MSC_VER) && !defined(AGG_NO_ASM)
264
0
        //For Ix86 family processors this assembler code is used. 
265
0
        //The key command here is bsr - determination the number of the most 
266
0
        //significant bit of the value. For other processors
267
0
        //(and maybe compilers) the pure C "#else" section is used.
268
0
        __asm
269
0
        {
270
0
            mov ebx, val
271
0
            mov edx, 11
272
0
            bsr ecx, ebx
273
0
            sub ecx, 9
274
0
            jle less_than_9_bits
275
0
            shr ecx, 1
276
0
            adc ecx, 0
277
0
            sub edx, ecx
278
0
            shl ecx, 1
279
0
            shr ebx, cl
280
0
    less_than_9_bits:
281
0
            xor eax, eax
282
0
            mov  ax, g_sqrt_table[ebx*2]
283
0
            mov ecx, edx
284
0
            shr eax, cl
285
0
        }
286
0
    #else
287
0
288
0
        //This code is actually pure C and portable to most 
289
0
        //architectures including 64bit ones. 
290
0
        unsigned t = val;
291
0
        int bit=0;
292
0
        unsigned shift = 11;
293
0
294
0
        //The following piece of code is just an emulation of the
295
0
        //Ix86 assembler command "bsr" (see above). However on old
296
0
        //Intels (like Intel MMX 233MHz) this code is about twice 
297
0
        //faster (sic!) then just one "bsr". On PIII and PIV the
298
0
        //bsr is optimized quite well.
299
0
        bit = t >> 24;
300
0
        if(bit)
301
0
        {
302
0
            bit = g_elder_bit_table[bit] + 24;
303
0
        }
304
0
        else
305
0
        {
306
0
            bit = (t >> 16) & 0xFF;
307
0
            if(bit)
308
0
            {
309
0
                bit = g_elder_bit_table[bit] + 16;
310
0
            }
311
0
            else
312
0
            {
313
0
                bit = (t >> 8) & 0xFF;
314
0
                if(bit)
315
0
                {
316
0
                    bit = g_elder_bit_table[bit] + 8;
317
0
                }
318
0
                else
319
0
                {
320
0
                    bit = g_elder_bit_table[t];
321
0
                }
322
0
            }
323
0
        }
324
0
325
0
        //This code calculates the sqrt.
326
0
        bit -= 9;
327
0
        if(bit > 0)
328
0
        {
329
0
            bit = (bit >> 1) + (bit & 1);
330
0
            shift -= bit;
331
0
            val >>= (bit << 1);
332
0
        }
333
0
        return g_sqrt_table[val] >> shift;
334
0
    #endif
335
0
    }
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
    // Converted 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
0
    {
367
0
        if(n < 0)
368
0
        {
369
0
            return 0;
370
0
        }
371
0
        double d = 1E-6;
372
0
        double b = 0;
373
0
        if(fabs(x) <= d) 
374
0
        {
375
0
            if(n != 0) return 0;
376
0
            return 1;
377
0
        }
378
0
        double b1 = 0; // b1 is the value from the previous iteration
379
0
        // Set up a starting order for recurrence
380
0
        int m1 = (int)fabs(x) + 6;
381
0
        if(fabs(x) > 5) 
382
0
        {
383
0
            m1 = (int)(fabs(1.4 * x + 60 / x));
384
0
        }
385
0
        int m2 = (int)(n + 2 + fabs(x) / 4);
386
0
        if (m1 > m2) 
387
0
        {
388
0
            m2 = m1;
389
0
        }
390
0
    
391
0
        // Apply recurrence down from current max order
392
0
        for(;;) 
393
0
        {
394
0
            double c3 = 0;
395
0
            double c2 = 1E-30;
396
0
            double c4 = 0;
397
0
            int m8 = 1;
398
0
            if (m2 / 2 * 2 == m2) 
399
0
            {
400
0
                m8 = -1;
401
0
            }
402
0
            int imax = m2 - 2;
403
0
            for (int i = 1; i <= imax; i++) 
404
0
            {
405
0
                double c6 = 2 * (m2 - i) * c2 / x - c3;
406
0
                c3 = c2;
407
0
                c2 = c6;
408
0
                if(m2 - i - 1 == n)
409
0
                {
410
0
                    b = c6;
411
0
                }
412
0
                m8 = -1 * m8;
413
0
                if (m8 > 0)
414
0
                {
415
0
                    c4 = c4 + 2 * c6;
416
0
                }
417
0
            }
418
0
            double c6 = 2 * c2 / x - c3;
419
0
            if(n == 0)
420
0
            {
421
0
                b = c6;
422
0
            }
423
0
            c4 += c6;
424
0
            b /= c4;
425
0
            if(fabs(b - b1) < d)
426
0
            {
427
0
                return b;
428
0
            }
429
0
            b1 = b;
430
0
            m2 += 3;
431
0
        }
432
0
    }
433
434
}
435
436
437
#endif