• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

NREL / SolTrace / 14628243107

23 Apr 2025 09:13PM UTC coverage: 44.154% (+0.5%) from 43.617%
14628243107

Pull #65

github

web-flow
Merge e65736e0a into 96166e291
Pull Request #65: Refactor the Trace function (and related functions)

363 of 670 new or added lines in 6 files covered. (54.18%)

135 existing lines in 4 files now uncovered.

1941 of 4396 relevant lines covered (44.15%)

10000057.29 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

26.01
/coretrace/intersect.cpp
1

2
/*******************************************************************************************************
3
*  Copyright 2018 Alliance for Sustainable Energy, LLC
4
*
5
*  NOTICE: This software was developed at least in part by Alliance for Sustainable Energy, LLC
6
*  ("Alliance") under Contract No. DE-AC36-08GO28308 with the U.S. Department of Energy and the U.S.
7
*  The Government retains for itself and others acting on its behalf a nonexclusive, paid-up,
8
*  irrevocable worldwide license in the software to reproduce, prepare derivative works, distribute
9
*  copies to the public, perform publicly and display publicly, and to permit others to do so.
10
*
11
*  Redistribution and use in source and binary forms, with or without modification, are permitted
12
*  provided that the following conditions are met:
13
*
14
*  1. Redistributions of source code must retain the above copyright notice, the above government
15
*  rights notice, this list of conditions and the following disclaimer.
16
*
17
*  2. Redistributions in binary form must reproduce the above copyright notice, the above government
18
*  rights notice, this list of conditions and the following disclaimer in the documentation and/or
19
*  other materials provided with the distribution.
20
*
21
*  3. The entire corresponding source code of any redistribution, with or without modification, by a
22
*  research entity, including but not limited to any contracting manager/operator of a United States
23
*  National Laboratory, any institution of higher learning, and any non-profit organization, must be
24
*  made publicly available under this license for as long as the redistribution is made available by
25
*  the research entity.
26
*
27
*  4. Redistribution of this software, without modification, must refer to the software by the same
28
*  designation. Redistribution of a modified version of this software (i) may not refer to the modified
29
*  version by the same designation, or by any confusingly similar designation, and (ii) must refer to
30
*  the underlying software originally provided by Alliance as "SolTrace". Except to comply with the 
31
*  foregoing, the term "SolTrace", or any confusingly similar designation may not be used to refer to 
32
*  any modified version of this software or any modified version of the underlying software originally 
33
*  provided by Alliance without the prior written consent of Alliance.
34
*
35
*  5. The name of the copyright holder, contributors, the United States Government, the United States
36
*  Department of Energy, or any of their employees may not be used to endorse or promote products
37
*  derived from this software without specific prior written permission.
38
*
39
*  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR
40
*  IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
41
*  FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER,
42
*  CONTRIBUTORS, UNITED STATES GOVERNMENT OR UNITED STATES DEPARTMENT OF ENERGY, NOR ANY OF THEIR
43
*  EMPLOYEES, BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
44
*  DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
45
*  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
46
*  IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
47
*  THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
48
*******************************************************************************************************/
49

50

51
#include <stdlib.h>
52
#include <math.h>
53

54
#include "types.h"
55
#include "procs.h"
56

57
#define   Order 3
58
#define   NumIterations 20
59
#define   Epsilon 0.000001
60

61
#define sign(x) (x>=0)
62

63

64
// barycentric technique for triangles (7 jul 2010)
65
// http://www.blackpawn.com/texts/pointinpoly/default.html
66
/*
67
        // Compute vectors        
68
        v0 = C - A
69
        v1 = B - A
70
        v2 = P - A
71

72
        // Compute dot products
73
        dot00 = dot(v0, v0)
74
        dot01 = dot(v0, v1)
75
        dot02 = dot(v0, v2)
76
        dot11 = dot(v1, v1)
77
        dot12 = dot(v1, v2)
78

79
        // Compute barycentric coordinates
80
        invDenom = 1 / (dot00 * dot11 - dot01 * dot01)
81
        u = (dot11 * dot02 - dot01 * dot12) * invDenom
82
        v = (dot00 * dot12 - dot01 * dot02) * invDenom
83

84
        // Check if point is in triangle
85
        return (u > 0) && (v > 0) && (u + v < 1)
86
*/
87

88
/*
89
int intri_bary(double x1, double y1,
90
                                 double x2, double y2,
91
                                 double x3, double y3,
92
                                 double xt, double yt)
93
{
94
        // Compute vectors
95
        double v00 = x3-x1;
96
        double v01 = y3-y1;
97
        double v10 = x2-x1;
98
        double v11 = y2-y1;
99
        double v20 = xt-x1;
100
        double v21 = yt-y1;
101

102

103
        // Compute dot products
104
        double dot00 = v00*v00+v01*v01;
105
        double dot01 = v00*v10+v01*v11;
106
        double dot02 = v00*v20+v01*v21;
107
        double dot11 = v10*v10+v11*v11;
108
        double dot12 = v10*v20+v11*v21;
109
        
110
        // Compute barycentric coordinates
111
        double invDenom = 1 / (dot00 * dot11 - dot01 * dot01);
112
        double u = (dot11 * dot02 - dot01 * dot12) * invDenom;
113
        double v = (dot00 * dot12 - dot01 * dot02) * invDenom;
114

115
        // Check if point is in triangle
116
        return (u > 0) && (v > 0) && (u + v < 1);
117
}*/
118

119
int intri(double x1, double y1,
×
120
                                 double x2, double y2,
121
                                 double x3, double y3,
122
                                 double xt, double yt)
123
{
124
        double a = (x1 - xt)*(y2 - yt) - (x2 - xt)*(y1 - yt);
×
125
    double b = (x2 - xt)*(y3 - yt) - (x3 - xt)*(y2 - yt);
×
126
    double c = (x3 - xt)*(y1 - yt) - (x1 - xt)*(y3 - yt);
×
127
    return (sign(a) == sign(b) && sign(b) == sign( c));
×
128
}
129

130
int inquad(double x1, double y1,
×
131
                                 double x2, double y2,
132
                                 double x3, double y3,
133
                                 double x4, double y4,
134
                                 double xt, double yt)
135
{
136
        return intri(x1,y1,x2,y2,x3,y3,xt,yt)
×
137
                || intri(x1,y1,x3,y3,x4,y4,xt,yt);
×
138
}
139

140
void Intersect( double PosLoc[3], 
280,729,521✔
141
                        double CosLoc[3],
142
                        TElement *Element,
143
                        double PosXYZ[3], 
144
                        double CosKLM[3],
145
                        double DFXYZ[3],
146
                        double *PathLength,
147
                        int *ErrorFlag )
148
{
149
/*{Purpose: To compute intersection point and direction numbers for surface normal
150
at intersection point of ray and surface. Path length is also computed.  From Spencer & Murty paper pg. 674
151
   Input - PosLoc[3] = Initial position of ray in local coordinate system.
152
           CosLoc[3] = Initial direction cosines of ray in local system.
153
           Element.SurfaceType = Surface type flag
154
                         = 1 for rotationally symmetric surfaces
155
                         = 2 for torics and cylinders
156
                         = 3 for plane surfaces
157
                         = 4 for finite element data surface
158
                         = 5 for VSHOT data surface
159
                         = 6 for Zernike Monomial description
160
                         = 7 for single axis curvature surfaces
161
                         = 8 for rotationally symmetric polynomial description
162
                         = 9 for      "          "         cubic spline interpolation
163
                         =10 for torus
164
           Element.Alpha = Sensitivity coefficients which specify deviation from conic
165
                   of revolution. For plane p = kx+ly+mz, Alpha[1] = p, Alpha{2..4] = k,l,m
166
           Element.VertexCurvX = Vertex Curvature of surface
167
           Element.Kappa = Surface specifier
168
                 < 0         ==> Hyperboloid
169
                 = 0         ==> Paraboloid
170
                 > 0 and < 1 ==> Hemelipsoid of revolution about major axis
171
                 = 1         ==> Hemisphere
172
                 > 1         ==> Hemielipsoid of revolution about minor axis
173
           Element.ConeHalfAngle = Half-angle of cone for cones or revolution or axicons
174
           Element.CurvOfRev = Curvature of revolution
175

176
   Output - PosXYZ[3] = X, Y, Z coordinate of ray/surface intersection
177
            CosKLM[3] = direction cosines of ray
178
            DFXYZ[3]  = direction numbers for the surface normal at the
179
                        intersection point (partial derivatives with respect to
180
                        X, Y, Z of surface equation).
181
            PathLength = Path length
182
            ErrorFlag  = Error flag
183
                         = 0 for no errors
184
                         = 1 for Newton-Raphson iteration failed to converge
185
                         = 2 for interpolation error in SURFACE procedure} */
186
        int i = 0;
280,729,521✔
187
        double S0 = 0.0, S00 = 0.0, S0A = 0.0;
280,729,521✔
188
        double X1 = 0.0,x = 0.0,y = 0.0,r = 0.0,Y10 = 0.0,Y1A = 0.0,X10 = 0.0,X1A = 0.0;
280,729,521✔
189
        double Y1 = 0.0;
280,729,521✔
190
        double SJ = 0.0;
280,729,521✔
191
        double SJ1 = 0.0;
280,729,521✔
192
        double DFDXYZ = 0.0;
280,729,521✔
193
        double FXYZ = 0.0;
280,729,521✔
194
        double ZStart = 0.0, ZA = 0.0;
280,729,521✔
195
        double ZStartcs = 0.0, PLengthcs = 0.0;
280,729,521✔
196
        int EFlagcs=0;
280,729,521✔
197
        double OuterRadius = 0.0, InnerRadius = 0.0, R1 = 0.0, R1A = 0.0, R10 = 0.0, Z1 = 0.0, dzdR1 = 0.0;
280,729,521✔
198
        double S0Aperture = 0.0;
280,729,521✔
199
        double Ro = 0.0, Ri = 0.0, XL = 0.0;
280,729,521✔
200
        bool ZAInterceptInsideAperture = false;
280,729,521✔
201
        double Y2 = 0.0,Y3 = 0.0,Y4 = 0.0;
280,729,521✔
202
        double SLOP60 = 0.0, FXY = 0.0;
280,729,521✔
203
        double PosDum[3] = { 0.0, 0.0, 0.0 };
280,729,521✔
204
        double PosAtZA[3] = { 0.0, 0.0, 0.0 };
280,729,521✔
205
        double PosAtZ0[3] = { 0.0, 0.0, 0.0 };
280,729,521✔
206
        double P1x = 0.0,P1y = 0.0,P2x = 0.0,P2y = 0.0,P3x = 0.0,P3y = 0.0,P4x = 0.0,P4y = 0.0;
280,729,521✔
207
        char ApertureShapeIndex = ' ';
280,729,521✔
208
        double PosInputToCS = 0.0;
280,729,521✔
209
        int in_quad = 0;
280,729,521✔
210

211
        *ErrorFlag = 0;
280,729,521✔
212
        for (i=0;i<3;i++)
1,122,918,084✔
213
        {
214
                PosXYZ[i] = PosLoc[i];
842,188,563✔
215
                CosKLM[i] = CosLoc[i];
842,188,563✔
216
        }
217

218
        //Closed form solutions used for closed surfaces (could use Newton-Raphson also,but would have to
219
        //pick the correct starting point (i.e. the initial point itself) to converge on first intersection
220
        //chose closed for cylinder
221
        if (Element->SurfaceType == 2) // cylinder
280,729,521✔
222
        {
223
                QuadricSurfaceClosedForm(Element, PosLoc, CosLoc, PosXYZ, DFXYZ, PathLength, ErrorFlag);
91,789✔
224
                return;
280,620,704✔
225
        }
226
        
227

228
        // wendelin 5-26-11 chose not use closed form solution for sphere.
229
        // this solves for a full spheroid, but can build a full spheroid from two hemispheres with iterative solution
230
        // JM 6/2023: Using closed form solution for sphere with single axis curvature aperture to avoid numerical problems caused by a bad starting point for Newton-Raphson (algorithm needs to start at a location with a defined z-location on the surface)
231
        if ((Element->SurfaceType == 1 || Element->SurfaceType == 7) && (Element->SurfaceIndex == 's' || Element->SurfaceIndex == 'S')) //sphere or partial cylinder
280,637,732✔
232
        {
233
                QuadricSurfaceClosedForm(Element, PosLoc, CosLoc, PosXYZ, DFXYZ, PathLength, ErrorFlag);
237,831✔
234
                return;
237,831✔
235
        }
236

237
        // JM 6/2023: Adding closed form solution for hyperboloids and hemi-ellipsoids
238
        if ((Element->SurfaceType == 1) && (Element->SurfaceIndex == 'o' || Element->SurfaceIndex == 'O')) //hyperboloid or hemiellipsoid
280,399,901✔
239
        {
240
                QuadricSurfaceClosedForm(Element, PosLoc, CosLoc, PosXYZ, DFXYZ, PathLength, ErrorFlag);
×
241
                return;
×
242
        }
243

244
        // JM 6/2023: Adding closed form solution for parabolas
245
        if ((Element->SurfaceIndex == 'p' || Element->SurfaceIndex == 'P'))
280,399,901✔
246
        {
247
                QuadricSurfaceClosedForm(Element, PosLoc, CosLoc, PosXYZ, DFXYZ, PathLength, ErrorFlag);
280,291,084✔
248
                return;
280,291,084✔
249
        }
250

251
        
252
        if (Element->SurfaceType == 10) // torus
108,817✔
253
        {
254
                TorusClosedForm(Element, PosLoc, CosLoc, PosXYZ, DFXYZ, PathLength, ErrorFlag);
×
255
                return;
×
256
        }
257
        
258
        //--------end of closed form solutions-------------
259
        //  {If not doing closed form solution, proceed to iterative solution}
260

261

262
        //start of new block for determining starting plane for Newton-Raphson   03-11-03
263
        
264
        /*{First, find starting plane.  The correct choice depends on the z-direction of the ray and the original
265
        position of the ray relative to the element surface.  First step is to find the intersection point
266
        of ray with  the element aperture plane and determine if it is inside or outside the aperture.
267
        Next, find z value of surface at x,y coords of original position.
268
        This determines which side of the surface equation the original position is. Then proceed through conditionals
269
        to determine the correct starting plane for Newton-Raphson.} */
270

271
        if (Element->ZAperture - PosXYZ[2] == 0.0) //numerical fix? 11-16-06 Tim Wendelin
108,817✔
272
                S0Aperture = 0.0;
×
273
        else
274
                S0Aperture = (Element->ZAperture - PosXYZ[2])/(CosKLM[2] + 0.00000000001); //numerical fix? tim wendelin 11-20-06
108,817✔
275
      
276
        x = PosXYZ[0]+CosKLM[0]*S0Aperture;               //x,y and radial position in aperture plane
108,817✔
277
        y = PosXYZ[1]+CosKLM[1]*S0Aperture;
108,817✔
278
        r = sqrt(x*x + y*y);
108,817✔
279
        
280
        //Determine if intersection point of ray with aperture plane falls inside element aperture
281
        SLOP60 = 1.7320508075688767; // tan(60.0*(ACOSM1O180));
108,817✔
282

283
        ZAInterceptInsideAperture=false;
108,817✔
284

285
        switch (Element->ShapeIndex)
108,817✔
286
        {
287
        case 'c':
22,726✔
288
        case 'C': // Circular aperture
289
                        Ro = Element->ParameterA/2.0;                        
22,726✔
290
                        if (r > Ro) //ray falls outsideside circular aperture
22,726✔
291
                                ZAInterceptInsideAperture = false;
2,726✔
292
                        else
293
                                ZAInterceptInsideAperture = true;
20,000✔
294
                break;
22,726✔
295
                
296
        case 'h':
×
297
        case 'H': //hexagonal aperture
298
                        Ro = Element->ParameterA/2.0;
×
299
                        
300
                        if (r > Ro) //ray falls outside circular circumference aperture
×
301
                        {
302
                                ZAInterceptInsideAperture = false;
×
303
                                //goto Label_5;
NEW
304
                                break;
×
305
                        }
306
                        
307
                        Ri = Ro*cos(30.0*(ACOSM1O180));
×
308
                        
309
                        if (r <= Ri) //ray falls inside inscribed circle
×
310
                        {
311
                                ZAInterceptInsideAperture = true;
×
312
                                //goto Label_5;
NEW
313
                                break;
×
314
                        }
315
                        
316
                        XL = sqrt(Ro*Ro - Ri*Ri); //otherwise break hexagon into 3 sections
×
317
                        if (x <= Ro && x > XL)  //1st section
×
318
                        {                        
319
                                Y1 = SLOP60*(x-Ro);
×
320
                                Y2 = -Y1;
×
321
                                if (y >= Y1 && y <= Y2)
×
322
                                {
323
                                        ZAInterceptInsideAperture = true;
×
324
                                        //goto Label_5;
NEW
325
                                        break;
×
326
                                }
327

328
                                ZAInterceptInsideAperture = false;                                        
×
329
                                //goto Label_5;
NEW
330
                                break;
×
331
                        }
332
                        
333
                        if (x <= XL && x >= -XL) //2nd section
×
334
                        {
335
                                if (y >= -Ri && y <= Ri)
×
336
                                {
337
                                        ZAInterceptInsideAperture = true;
×
338
                                        //goto Label_5;
NEW
339
                                        break;
×
340
                                }
341

342
                                ZAInterceptInsideAperture = false;
×
343
                                //goto Label_5;
NEW
344
                                break;
×
345
                        }
346
                        
347
                        if (x < -XL && x >= -Ro) //3rd section
×
348
                        {
349
                                Y3 = SLOP60*(x+Ro);
×
350
                                Y4 = -Y3;
×
351
                                if (y >= Y4 && y <= Y3)
×
352
                                {
353
                                        ZAInterceptInsideAperture = true;
×
354
                                        //goto Label_5;
NEW
355
                                        break;
×
356
                                }
357
                                
358
                                ZAInterceptInsideAperture = false;
×
359
                                //goto Label_5;
NEW
360
                                break;
×
361
                        }
362
                break;
×
363

364
        case 't':
×
365
        case 'T': //Triangular aperture
366
                        Ro = Element->ParameterA/2.0;
×
367
                        
368
                        if (r > Ro) //ray falls outside circular circumference aperture
×
369
                        {
370
                                ZAInterceptInsideAperture = false;
×
371
                                //goto Label_5;
NEW
372
                                break;
×
373
                        }
374
                        
375
                        Ri = Ro*sin(30.0*(ACOSM1O180));
×
376
                        
377
                        if (r <= Ri)  //ray falls inside inscribed circle
×
378
                        {
379
                                ZAInterceptInsideAperture = true;
×
380
                                //goto Label_5;
NEW
381
                                break;
×
382
                        }
383
                        
384
                        if (x <= Ro && x > 0.0) //1st section
×
385
                        {
386
                                Y1 = -SLOP60*(x-Ri/cos(30.0*(ACOSM1O180)));
×
387
                                Y2 = -Ri;
×
388
                                if (y <= Y1 && y >= Y2)
×
389
                                        ZAInterceptInsideAperture = true;
×
390
                                else
391
                                        ZAInterceptInsideAperture = false;
×
392
                                //goto Label_5;
NEW
393
                                break;
×
394
                        }
395
                        
396
                        if (x >= -Ro && x <= 0.0) //2nd section
×
397
                        {
398
                                Y3 = SLOP60*(x+Ri/cos(30.0*(ACOSM1O180)));
×
399
                                Y4 = -Ri;
×
400
                                if (y >= Y4 && y <= Y3)
×
401
                                        ZAInterceptInsideAperture = true;
×
402
                                else
403
                                        ZAInterceptInsideAperture = false;
×
404
                                        
405
                                //goto Label_5;
NEW
406
                                break;
×
407
                        }
408
                break;
×
409
        
410
        case 'r':
86,091✔
411
        case 'R': // Rectangular aperture
412
                
413
                        if (x > Element->ParameterA/2.0 && x < -Element->ParameterA/2.0)
86,091✔
414
                        {
415
                                ZAInterceptInsideAperture = false;
×
416
                                //goto Label_5;
NEW
417
                                break;
×
418
                        }
419

420
                        if (y > Element->ParameterB/2.0 && y < -Element->ParameterB/2.0)
86,091✔
421
                        {
422
                                ZAInterceptInsideAperture = false;
×
423
                                //goto Label_5;
NEW
424
                                break;
×
425
                        }
426
                        
427
                        ZAInterceptInsideAperture = true;
86,091✔
428
                        //goto Label_5;
429
                        
430
                break;
86,091✔
431

432
        case 'a':
×
433
        case 'A'://Annulus
434
                
435
                        if (r < Element->ParameterA || r > Element->ParameterB)
×
436
                        {
437
                                ZAInterceptInsideAperture = false;
×
438
                                //goto Label_5;
NEW
439
                                break;
×
440
                        }
441
                        
442
                        if (x >= 0.0)
×
443
                        {
444
                                if ( (asin(y/r) > Element->ParameterC*(ACOSM1O180)/2.0) 
×
445
                                                || (asin(y/r) < -Element->ParameterC*(ACOSM1O180)/2.0) )
×
446
                                        ZAInterceptInsideAperture = false;
×
447
                                else
448
                                        ZAInterceptInsideAperture = true;
×
449
                                //goto Label_5;
NEW
450
                                break;
×
451
                        }
452
                        
453
                        if (x < 0.0)
×
454
                        {
455
                                if ( (y >= 0) && ((acos(y/r)+M_PI/2.0) > Element->ParameterC*(ACOSM1O180)/2.0) )
×
456
                                {
457
                                        ZAInterceptInsideAperture = false;
×
458
                                        //goto Label_5;
NEW
459
                                        break;
×
460
                                }
461
                                else if ((y < 0) && ((-acos(-y/r)-M_PI/2.0) < -Element->ParameterC*(ACOSM1O180)/2.0) )
×
462
                                {
463
                                        ZAInterceptInsideAperture = false;
×
464
                                        //goto Label_5;
NEW
465
                                        break;
×
466
                                }
467
                        
468
                                ZAInterceptInsideAperture = true;
×
469
                                //goto Label_5;
NEW
470
                                break;
×
471
                        }
472
                        
473
                break;
×
474

475
        case 'l':
×
476
        case 'L': //off axis aperture section of line focus trough  or cylinder
477
                
NEW
478
                        if (Element->ParameterA == 0.0 && Element->ParameterB == 0.0)
×
479
                        {
480
                                //goto Label_4; //for cylinder, only need to check for limits on y
481
                        }
NEW
482
                        else if (x < Element->ParameterA || x > Element->ParameterB)
×
483
                        {
484
                                ZAInterceptInsideAperture = false;
×
485
                                //goto Label_5;
NEW
486
                                break;
×
487
                        }
488
                        
489
                        //Label_4:
490
                        if (y < -Element->ParameterC/2.0 || y > Element->ParameterC/2.0)
×
491
                        {
492
                                ZAInterceptInsideAperture = false;
×
493
                                //goto Label_5;
NEW
494
                                break;
×
495
                        }
496
                        
497
                        ZAInterceptInsideAperture = true;
×
498
                        //goto Label_5;
499
                        
UNCOV
500
                break;
×
501
                
502
        case 'i':
×
503
        case 'I': //irregular triangle
504
                        P1x = Element->ParameterA;
×
505
                        P1y = Element->ParameterB;
×
506
                        P2x = Element->ParameterC;
×
507
                        P2y = Element->ParameterD;
×
508
                        P3x = Element->ParameterE;
×
509
                        P3y = Element->ParameterF;
×
510

511
                        if (!intri( P1x, P1y, P2x, P2y, P3x, P3y, x, y ))
×
512
                        {
513
                                ZAInterceptInsideAperture = false;
×
514
                                //goto Label_5;
NEW
515
                                break;
×
516
                        }
517
                        
UNCOV
518
                        ZAInterceptInsideAperture = true;
×
519
                        //goto Label_5;
UNCOV
520
                break;
×
521
                        
522
        case 'q':
×
523
        case 'Q'://irregular quadrilateral
524
        
525
                        P1x = Element->ParameterA;
×
526
                        P1y = Element->ParameterB;
×
527
                        P2x = Element->ParameterC;
×
528
                        P2y = Element->ParameterD;
×
529
                        P3x = Element->ParameterE;
×
530
                        P3y = Element->ParameterF;
×
531
                        P4x = Element->ParameterG;
×
532
                        P4y = Element->ParameterH;
×
533

534
                        in_quad = inquad(P1x, P1y, P2x, P2y, P3x, P3y, P4x, P4y, x, y);
×
535

536
                        if (!in_quad)
×
537
                        {
538
                                ZAInterceptInsideAperture = false;
×
539
                                //goto Label_5;
NEW
540
                                break;
×
541
                        }
542
                        
UNCOV
543
                        ZAInterceptInsideAperture = true;
×
544
                        //goto Label_5;
UNCOV
545
                break;
×
546
        default:
×
547
                break;
×
548
        } // end switch
549

550

551
//Label_5:
552
//        if (in_quad && !ZAInterceptInsideAperture)
553
//                printf("ERROR\n");
554

555
        ZStart = 0.0;    //default for all surfacetypes
108,817✔
556

557
        if ( Element->SurfaceType != 3
108,817✔
558
                 && Element->SurfaceType != 4
22,726✔
559
                 && Element->SurfaceType != 9)
22,726✔
560
        {
561
                SurfaceZatXYPair(PosXYZ, Element, &FXY, ErrorFlag);    //find z value of surface at x,y
22,726✔
562
                
563
                if (PosXYZ[2] <= 0.0 && CosKLM[2] > 0.0)     //if ray position below z=0 and pointing up then
22,726✔
564
                {                                                                                             //ZStart should be z=0 plane.
565
                        ZStart = 0.0;
×
566
                        //goto Label_10;
567
                }
568
                
569
                else if (PosXYZ[2] <= FXY && CosKLM[2] > 0.0)     //if ray position is below surface equation and pointing up
22,726✔
570
                {                                                //then ZStart should be z=0 plane.
571
                        ZStart = 0.0;
×
572
                        //goto Label_10;
573
                }
574
                
575
                else if ( PosXYZ[2] <= FXY 
22,726✔
576
                                && CosKLM[2] < 0.0 
×
577
                                && PosXYZ[2] > Element->ZAperture 
×
578
                                && ZAInterceptInsideAperture )
×
579
                {                                                 //if ray position is below surface equation, above the aperture
580
                        ZStart = 0.0;                                      //plane and pointing down
×
581
                        //goto Label_10;                                            //and the interception point with aperture plane is inside of
582
                }                                                  //aperture, then ZStart should be z=0 plane.
583
                
584
                else if (PosXYZ[2] <= FXY && CosKLM[2] < 0.0)      //if ray position is below surface equation, pointing down
22,726✔
585
                {                                                 //and hits surface below aperture plane then ZStart should be
586
                        ZStart = Element->ZAperture;                        //aperture plane.
×
587
                        //goto Label_10;
588
                }
589
                
590
                else if (PosXYZ[2]  > FXY && CosKLM[2] < 0.0)      //if ray position is above surface and pointing in negative z
22,726✔
591
                {                                                 //direction then ZStart should be z=0 plane
592
                        ZStart = 0.0;
12,726✔
593
                        //goto Label_10;
594
                }
595
                
596
                else if (PosXYZ[2] > FXY && CosKLM[2] > 0.0)
10,000✔
597
                         ZStart = Element->ZAperture;  //if ray position is above the surface and
10,000✔
598
        }                                                           //pointing up then ZStart should be
599

600
     //The following calculates ZStart for surfaces described by cubic spline data only.
601

602
        if (Element->SurfaceType == 9)
108,817✔
603
        {
604
                OuterRadius = Element->CubicSplineXData[Element->CubicSplineXData.size()-1];  //outer,inner radii (or distance from origin if single axis curvature) of data set 
×
605
                InnerRadius = Element->CubicSplineXData[0];
×
606
                ApertureShapeIndex = Element->ShapeIndex;
×
607
                ZA = Element->CubicSplineYData[Element->CubicSplineYData.size()-1];  //z value at aperture plane ZA
×
608
                
609
                S00 = -PosXYZ[2]/(CosKLM[2] + 0.00000000001); //numerical fix? tim wendelin 11-20-06; //pathlength from original ray point to z=0 plane
×
610
                
611
                X10 = PosXYZ[0] + CosKLM[0]*S00;  // x,y location of intersection point in z=0 plane
×
612
                Y10 = PosXYZ[1] + CosKLM[1]*S00;
×
613
                R10 = sqrt(X10*X10+Y10*Y10);      //radius of intersection point in z=0 plane
×
614
                                
615
                S0A = (ZA - PosXYZ[2])/(CosKLM[2] + 0.00000000001); //numerical fix? tim wendelin 11-20-06;  //pathlength from original ray point to aperture plane
×
616
                
617
                X1A = PosXYZ[0] + CosKLM[0]*S0A;   // x,y location of intersection point in aperture plane
×
618
                Y1A = PosXYZ[1] + CosKLM[1]*S0A;
×
619
                R1A = sqrt(X1A*X1A+Y1A*Y1A);       //radius of intersection point in aperture plane
×
620
                
621
                
622
                //original location and direction of ray defines starting plane for Newton-Raphson.  This is split into several
623
                //sections as can be seen in the following.
624

625
          //ray at or above aperture plane, ZA, and heading toward Z0
626
                if (PosXYZ[2] >= ZA && CosKLM[2] < 0.0)
×
627
                {
628
         //move starting point for ray to aperture plane, so intersects at correct point on cylinder below,  03-20-04
629
                        PosAtZA[0] = X1A;
×
630
                        PosAtZA[1] = Y1A;
×
631
                        PosAtZA[2] = ZA;
×
632
                        
633
                        //{check R or X position depending if rotationally symmetric curvature or single axis curvature}
634
                        if (  (((ApertureShapeIndex=='a') || (ApertureShapeIndex=='A')) && (R1A > OuterRadius))
×
635
                           || (((ApertureShapeIndex=='l') || (ApertureShapeIndex=='L')) && (X1A > OuterRadius))  )
×
636
                        {
637
                                //find intersection with cylinder at outside edge of dataset.  The z value becomes the new ZStart.
638
                                //NewZStartforCubicSplineSurf(OuterRadius*0.999999, PosLoc, CosLoc, ZStartcs, PLengthcs, EFlagcs); //see PosAtZA comment above
639
                                NewZStartforCubicSplineSurf(OuterRadius*0.999999, PosAtZA, CosLoc, ApertureShapeIndex, &ZStartcs, &PLengthcs, &EFlagcs);
×
640
                                if (EFlagcs == 0)
×
641
                                {
642
                                        ZStart = ZStartcs;
×
643
                                        //goto Label_10;
644
                                }
645
                                //ray misses virtual cylinder so move on.
646
                                //goto Label_10;
647
                        }
648
                        
649
                        //{check R or X position depending if rotationally symmetric curvature or single axis curvature}
NEW
650
                        else if ((((ApertureShapeIndex == 'a') || (ApertureShapeIndex == 'A')) && (R1A <= OuterRadius))
×
651
                            || (((ApertureShapeIndex=='l') || (ApertureShapeIndex=='L')) && (X1A <= OuterRadius)) )
×
652
                        {
653
                                if (   (((ApertureShapeIndex=='a') || (ApertureShapeIndex=='A')) && (R10 >= OuterRadius))
×
654
                                    || (((ApertureShapeIndex=='l') || (ApertureShapeIndex=='L')) && (X10 >= OuterRadius)) )
×
655
                                {
656
                                         //find intersection with cylinder at outside edge of dataset.  The z value becomes the new ZStart.
657
                                         //NewZStartforCubicSplineSurf(OuterRadius*0.999999, PosLoc, CosLoc, ZStartcs, PLengthcs, EFlagcs); //see PosAtZA comment above
658
                                        NewZStartforCubicSplineSurf(OuterRadius*0.999999, PosAtZA, CosLoc, ApertureShapeIndex, &ZStartcs, &PLengthcs, &EFlagcs);
×
659
                                        if (EFlagcs == 0)
×
660
                                        {
661
                                                ZStart = ZStartcs;
×
662
                                                //goto Label_10;
663
                                        }                                
664
                                                
665
                                        //ray misses virtual cylinder so move on.
666
                                        //goto Label_10;
667
                                }
668
                                
669
                                ZStart = 0.0;
×
670
                                //goto Label_10;
671
                        }
672
                }
673
                
674
                //ray at or below Z0 plane and heading toward ZA
NEW
675
                else if (PosXYZ[2] <= 0.0 && CosKLM[2] > 0.0)
×
676
                {
677
                        //move starting point for ray to z=0 plane, so intersects at correct point on cylinder below     03/20/04
678
                        PosAtZ0[0] = X10;
×
679
                        PosAtZ0[1] = Y10;
×
680
                        PosAtZ0[2] = 0.0;
×
681
                        // {check R or X position depending if rotationally symmetric curvature or single axis curvature}
682
                        if ( (((ApertureShapeIndex=='a') || (ApertureShapeIndex=='A')) && (R10 >= OuterRadius))
×
683
                          || (((ApertureShapeIndex=='l') || (ApertureShapeIndex=='L')) && (X10 >= OuterRadius)) )
×
684
                        {
685
                                //find intersection with cylinder at outside edge of dataset.  The z value becomes the new ZStart.
686
                                //NewZStartforCubicSplineSurf(OuterRadius*0.999999, PosLoc, CosLoc, ZStartcs, PLengthcs, EFlagcs); //see PosAtZ0 comment above
687
                                NewZStartforCubicSplineSurf(OuterRadius*0.999999, PosAtZ0, CosLoc, ApertureShapeIndex, &ZStartcs, &PLengthcs, &EFlagcs);
×
688
                                if (EFlagcs == 0)
×
689
                                {
690
                                        ZStart = ZStartcs;
×
691
                                        //goto Label_10;
692
                                }
693
                                //ray misses virtual cylinder so move on.
694
                                //goto Label_10;
695
                        }
696
                  
697
                        //{check R or X position depending if rotationally symmetric curvature or single axis curvature}
NEW
698
                        else if ( (((ApertureShapeIndex=='a') || (ApertureShapeIndex=='A')) && ((R10 < OuterRadius) && (R10 > InnerRadius))) 
×
NEW
699
                                || (((ApertureShapeIndex=='l') || (ApertureShapeIndex=='L')) && ((X10 < OuterRadius) && (X10 > InnerRadius))) )
×
700
                        {
701
                                ZStart = 0.0;
×
702
                                //goto Label_10;
703
                        }
704
                  
705
                        //{check R or X position depending if rotationally symmetric curvature or single axis curvature}
NEW
706
                        else if ( (((ApertureShapeIndex=='a') || (ApertureShapeIndex=='A')) && (R10 <= InnerRadius)) 
×
NEW
707
                                || (((ApertureShapeIndex=='l') || (ApertureShapeIndex=='L')) && (X10 <= InnerRadius)) )
×
708
                        {
709
                                //find intersection with cylinder at inside edge of dataset.  The z value becomes the new ZStart.
710
                                //NewZStartforCubicSplineSurf(InnerRadius/0.999999, PosLoc, CosLoc, ZStartcs, PLengthcs, EFlagcs); //see PosAtZ0 comment above
711
                                NewZStartforCubicSplineSurf(InnerRadius/0.999999, PosAtZ0, CosLoc, ApertureShapeIndex, &ZStartcs, &PLengthcs, &EFlagcs);
×
712
                                if (EFlagcs == 0)
×
713
                                {
714
                                        ZStart = ZStartcs;
×
715
                                        //goto Label_10;
716
                                }
717
                                //ray misses virtual cylinder so move on.
718
                                //goto Label_10;
719
                        }
720
                }
721

722
                //ray in between ZA and Z0 planes and headed towared Z0
NEW
723
                else if (PosXYZ[2] < ZA && PosXYZ[2] > 0.0 && CosKLM[2] < 0.0)
×
724
                {
725
                        R1 = sqrt(PosXYZ[0]*PosXYZ[0]+PosXYZ[1]*PosXYZ[1]);  //ray radial position
×
726
                        //{check R or X position depending if rotationally symmetric curvature or single axis curvature}
727
                        if ( (((ApertureShapeIndex=='a') || (ApertureShapeIndex=='A')) && (R1 >= OuterRadius)) 
×
728
                          || (((ApertureShapeIndex=='l') || (ApertureShapeIndex=='L')) && (PosXYZ[0] >= OuterRadius)) )   //ray radial position outside of dataset
×
729
                        {
730
                                //find intersection with cylinder at outside edge of dataset.  The z value becomes the new ZStart.
731
                                NewZStartforCubicSplineSurf(OuterRadius*0.999999, PosLoc, CosLoc, ApertureShapeIndex, &ZStartcs, &PLengthcs, &EFlagcs);
×
732
                                if (EFlagcs == 0)
×
733
                                {
734
                                  ZStart = ZStartcs;
×
735
                                  //goto Label_10;
736
                                }
737
                                //ray misses virtual cylinder so move on.
738
                                //goto Label_10;
739
                        }
740
                        
741
                        //{check R or X position depending if rotationally symmetric curvature or single axis curvature}
NEW
742
                        else if ( (((ApertureShapeIndex=='a') || (ApertureShapeIndex=='A')) && ((R1 < OuterRadius) && (R1 > InnerRadius)))
×
NEW
743
                                ||  (((ApertureShapeIndex=='l') || (ApertureShapeIndex=='L')) && ((PosXYZ[0] < OuterRadius) &&(PosXYZ[0] > InnerRadius))) )  //ray radial position within dataset boundaries
×
744
                        {                                 //find z value at x,y. this determines if point is above or below curve
745
                                if (ApertureShapeIndex=='a' || ApertureShapeIndex=='A')
×
746
                                         PosInputToCS = R1;
×
747
                                else
748
                                         PosInputToCS = PosXYZ[0];
×
749
                                         
750
                                if (!splint(Element->CubicSplineXData,
×
751
                                                Element->CubicSplineYData,
×
752
                                                Element->CubicSplineY2Data,
×
753
                                                Element->CubicSplineXData.size(),
×
754
                                                PosInputToCS, &Z1, &dzdR1))
755
                                {
756
                                        *ErrorFlag = 3;
×
757
                                        return;
×
758
                                }
759
                                                
760
                                if (Z1 < PosXYZ[2])    //ray is above curve
×
761
                                {
762
                                //         {check R or X position depending if rotationally symmetric curvature or single axis curvature}
763
                                        if ( (((ApertureShapeIndex=='a') || (ApertureShapeIndex=='A')) && (R10 >= OuterRadius)) 
×
764
                                          || (((ApertureShapeIndex=='l') || (ApertureShapeIndex=='L')) && (X10 >= OuterRadius)) )
×
765
                                        {
766
                                        //find intersection with cylinder at outside edge of dataset.  The z value becomes the new ZStart.
767
                                                NewZStartforCubicSplineSurf(OuterRadius*0.999999, PosLoc, CosLoc, ApertureShapeIndex, &ZStartcs, &PLengthcs, &EFlagcs);
×
768
                                                if (EFlagcs == 0)
×
769
                                                {
770
                                                        ZStart = ZStartcs;
×
771
                                                        //goto Label_10;
772
                                                }
773
                                                //ray misses virtual cylinder so move on.
774
                                                //goto Label_10;
775
                                        }
776
                                        else 
777
                                        {
NEW
778
                                                ZStart = 0.0;
×
779
                                                //goto Label_10;
780
                                        }
781
                                        
782
                                }
783
                                
NEW
784
                                else if (Z1 >= PosXYZ[2]) //ray is below curve
×
785
                                {
786
                                         ZStart = PosXYZ[2];
×
787
                                         //ray misses virtual cylinder so move on.
788
                                         //goto Label_10;
789
                                }
790
                                else
791
                                {
792
                                        //goto Label_10;
793
                                }
794
                                
795
                        }
796
                        
797
                        //{check R or X position depending if rotationally symmetric curvature or single axis curvature}
NEW
798
                        else if ( (((ApertureShapeIndex=='a') || (ApertureShapeIndex=='A')) && (R1 <= InnerRadius))
×
799
                         ||  (((ApertureShapeIndex=='l') || (ApertureShapeIndex=='L')) && (PosXYZ[0] <= InnerRadius)) )   //ray radial position inside of dataset
×
800
                        {
801
                                //find intersection with cylinder at inside edge of dataset.  The z value becomes the new ZStart.
802
                                NewZStartforCubicSplineSurf(InnerRadius/0.999999, PosLoc, CosLoc, ApertureShapeIndex, &ZStartcs, &PLengthcs, &EFlagcs);
×
803
                                if (EFlagcs == 0)
×
804
                                {
805
                                        ZStart = ZStartcs;
×
806
                                        //goto Label_10;
807
                                }
808
                                
809
                                //ray misses virtual cylinder so move on.
810
                                //goto Label_10;
811
                        }
812
                }
813

814
                //ray in between ZA and Z0 planes and headed toward ZA
NEW
815
                else if (PosXYZ[2] < ZA && PosXYZ[2] > 0.0 && CosKLM[2] > 0.0)
×
816
                {
817
                        R1 = sqrt(PosXYZ[0]*PosXYZ[0]+PosXYZ[1]*PosXYZ[1]);  //ray radial position
×
818
                        // {check R or X position depending if rotationally symmetric curvature or single axis curvature}
819
                        if ( (((ApertureShapeIndex=='a') || (ApertureShapeIndex=='A')) && (R1 >= OuterRadius)) 
×
820
                          || (((ApertureShapeIndex=='l') || (ApertureShapeIndex=='L')) && (PosXYZ[0] >= OuterRadius)) )    //ray radial position outside of dataset
×
821
                        {
822
                                //find intersection with cylinder at outside edge of dataset.  The z value becomes the new ZStart.
823
                                NewZStartforCubicSplineSurf(OuterRadius*0.999999, PosLoc, CosLoc, ApertureShapeIndex, &ZStartcs, &PLengthcs, &EFlagcs);
×
824
                                if (EFlagcs == 0)
×
825
                                {
826
                                        ZStart = ZStartcs;
×
827
                                        //goto Label_10;
828
                                }
829
                                //ray misses virtual cylinder so move on.
830
                                //goto Label_10;
831
                        }
832
                        
833
         //  {check R or X position depending if rotationally symmetric curvature or single axis curvature}
NEW
834
                        else if ( (((ApertureShapeIndex=='a') || (ApertureShapeIndex=='A')) && ((R1 < OuterRadius) && (R1 > InnerRadius))) 
×
835
                          || (((ApertureShapeIndex=='l') || (ApertureShapeIndex=='L')) && ((PosXYZ[0] < OuterRadius) && (PosXYZ[0] > InnerRadius))) )     //ray radial position falls within dataset boundaries
×
836
                        {             //find z value at x,y. this determines if point is above or below curve
837
                        
838
                                if (ApertureShapeIndex=='a' || ApertureShapeIndex=='A')
×
839
                                         PosInputToCS = R1;
×
840
                                else
841
                                         PosInputToCS = PosXYZ[0];
×
842
                                         
843
                                if (!splint(Element->CubicSplineXData,
×
844
                                                Element->CubicSplineYData,
×
845
                                                Element->CubicSplineY2Data,
×
846
                                                Element->CubicSplineXData.size(),
×
847
                                                PosInputToCS,&Z1,&dzdR1))
848
                                {
849
                                        *ErrorFlag = 3;
×
850
                                        return;
×
851
                                }
852
                                                
853
                                if (Z1 < PosXYZ[2])    //ray is above curve
×
854
                                {
855
                                         //{check R or X position depending if rotationally symmetric curvature or single axis curvature}
856
                                        if ( (((ApertureShapeIndex=='a') || (ApertureShapeIndex=='A')) && (R1A >= OuterRadius)) 
×
857
                                         ||  (((ApertureShapeIndex=='l') || (ApertureShapeIndex=='L')) && (X1A >= OuterRadius)) )
×
858
                                        {
859
                                                //find intersection with cylinder at outside edge of dataset.  The z value becomes the new ZStart.
860
                                                NewZStartforCubicSplineSurf(OuterRadius*0.999999, PosLoc, CosLoc, ApertureShapeIndex, &ZStartcs, &PLengthcs, &EFlagcs);
×
861
                                                if (EFlagcs == 0)
×
862
                                                {
863
                                                        ZStart = ZStartcs;
×
864
                                                        //goto Label_10;
865
                                                }
866
                                                //ray misses virtual cylinder so move on.
867
                                                //goto Label_10;
868
                                        }
869
                                        //goto Label_10;
870
                                }
871
                                
NEW
872
                                else if (Z1 >= PosXYZ[2]) //ray is below curve
×
873
                                {
874
                                         //{check R or X position depending if rotationally symmetric curvature or single axis curvature}
875
                                        if ( (((ApertureShapeIndex=='a') || (ApertureShapeIndex=='A')) && (R10 < OuterRadius)) 
×
876
                                          || (((ApertureShapeIndex=='l') || (ApertureShapeIndex=='L')) && (X10 < OuterRadius)) )
×
877
                                        {
878
                                                ZStart = 0.0;
×
879
                                                //goto Label_10;
880
                                        }
881
                                        
882
                                        // {check R or X position depending if rotationally symmetric curvature or single axis curvature}
NEW
883
                                        else if ( (((ApertureShapeIndex=='a') || (ApertureShapeIndex=='A')) && (R10 >= OuterRadius))
×
884
                                          || (((ApertureShapeIndex=='l') || (ApertureShapeIndex=='L')) && (X10 >= OuterRadius)) )
×
885
                                        {
886
                                                PosDum[0] = X10;  //back up to intersection with z=0 plane
×
887
                                                PosDum[1] = Y10;
×
888
                                                PosDum[2] = 0.0;
×
889
                                        //find intersection with cylinder at outside edge of dataset.  The z value becomes the new ZStart.
890
                                                NewZStartforCubicSplineSurf(OuterRadius*0.999999, PosDum, CosLoc, ApertureShapeIndex, &ZStartcs, &PLengthcs, &EFlagcs);
×
891
                                                if (EFlagcs == 0)
×
892
                                                {
893
                                                        ZStart = ZStartcs;
×
894
                                                        //goto Label_10;
895
                                                }
896
                                                //ray misses virtual cylinder so move on.
897
                                                //goto Label_10;
898
                                        }
899
                                }
900
                        }
901
                        
902
                        // {check R or X position depending if rotationally symmetric curvature or single axis curvature}
NEW
903
                        else if ( (((ApertureShapeIndex=='a') || (ApertureShapeIndex=='A')) && (R1 <= InnerRadius)) 
×
NEW
904
                                || (((ApertureShapeIndex=='l') || (ApertureShapeIndex=='L')) && (PosXYZ[0] <= InnerRadius)) )    //ray radial position inside of dataset minimum radius
×
905
                        {
906
                                //find intersection with cylinder at outside edge of dataset.  The z value becomes the new ZStart.
907
                                NewZStartforCubicSplineSurf(OuterRadius*0.999999, PosLoc, CosLoc, ApertureShapeIndex, &ZStartcs, &PLengthcs, &EFlagcs);
×
908
                                if (EFlagcs == 0)
×
909
                                {
910
                                        ZStart = ZStartcs;
×
911
                                        //goto Label_10;
912
                                }
913
                                //ray misses virtual cylinder so move on.
914
                                //goto Label_10;
915
                        }
916
                }
917
        }
918

919
//Label_10:
920
        if (ZStart-PosXYZ[2] == 0.0)   //numerical fix? 11-16-06 Tim Wendelin
108,817✔
921
                S0 = 0.0;
×
922
        else
923
                S0 = (ZStart-PosXYZ[2])/(CosKLM[2] + 0.00000000001); //numerical fix? tim wendelin 11-20-06;   //SO is the pathlength from the initial ray position to the Newton-Raphson starting plane
108,817✔
924
                
925
        X1 = PosXYZ[0] + CosKLM[0]*S0;      // from this we calculate the x,y position on ZStart starting plane
108,817✔
926
        Y1 = PosXYZ[1] + CosKLM[1]*S0;
108,817✔
927
                 
928
        SJ1 = 0.0;
108,817✔
929

930
        // JM 10/2023: Check upper and lower bounds for S (distance along ray path from (X1,Y1,Zstart)) to restrict step size for cubic spline
931
        // This may slow down the solution - previously the iterations would find an intersection point for the spline, but it would be later disgarded because it is out of bounds, now the loop below will reach the iteration limit before failing is there is no intersection
932
        double lower_bound = -1e10;
108,817✔
933
        double upper_bound = 1e10;
108,817✔
934
        if (Element->SurfaceType == 9)
108,817✔
935
        {
936
                double s_to_xmin = (Element->CubicSplineXData[0] - X1) / (CosKLM[0] + 0.00000000001);  // Distance along ray path from (X1,Y1,Zstart) to smallest x-coordinate on surface 
×
937
                double s_to_xmax = (Element->CubicSplineXData[Element->CubicSplineXData.size() - 1] - X1) / (CosKLM[0] + 0.00000000001);  // Distance along ray path from (X1,Y1,Zstart) to largest x-coordinate on surface 
×
938
                lower_bound = fmin(s_to_xmin, s_to_xmax);
×
939
                upper_bound = fmax(s_to_xmin, s_to_xmax);
×
940
        }
941

942

943
        i = 0;
108,817✔
944
//Begin the Newton-Raphson Iteration
945
        int OKFlag = 0;
108,817✔
946

947
        while ( i++ < NumIterations)
141,506✔
948
        {
949
                SJ = SJ1;
141,506✔
950
                PosXYZ[0] = X1 + CosKLM[0]*SJ;
141,506✔
951
                PosXYZ[1] = Y1 + CosKLM[1]*SJ;
141,506✔
952
                PosXYZ[2] = ZStart + CosKLM[2]*SJ;
141,506✔
953

954
                Surface(PosXYZ, Element, &FXYZ, DFXYZ, &OKFlag);
141,506✔
955
                
956
                //if (OKFlag == 0) goto Label_40;
957
                if (OKFlag != 0)
141,506✔
958
                {
NEW
959
                        *ErrorFlag = 2;  //Interpolation error in Surface procedure
×
NEW
960
                        break;
×
961
                        //goto Label_100;
962
                }
963
                
964
//Label_40:
965
                DFDXYZ = DOT(DFXYZ, CosKLM);
141,506✔
966
                if (fabs(FXYZ) <= Epsilon * fabs(DFDXYZ))
141,506✔
967
                {
968
                        break;
108,817✔
969
                        //goto Label_100;
970
                }
971

972
                SJ1 = SJ - FXYZ/DFDXYZ;
32,689✔
973

974
                // JM 10/2023: Enforce bounds to restrict next guess for cubic spline
975
                if (Element->SurfaceType == 9)
32,689✔
976
                {
977
                        if ((FXYZ < 0 && CosKLM[2]>0) || (FXYZ > 0 && CosKLM[2] < 0)) // FXYZ < 0 if current point is below surface, FXYZ > 0 if current point is above surface
×
978
                                lower_bound = fmax(SJ, lower_bound);
×
979
                        else if ((FXYZ < 0 && CosKLM[2]<0) || (FXYZ > 0 && CosKLM[2] > 0))
×
980
                                upper_bound = fmin(SJ, upper_bound);
×
981
                        if (SJ1 < lower_bound || SJ1 > upper_bound)
×
982
                                SJ1 = 0.5 * (lower_bound + upper_bound);
×
983
                        if (upper_bound <= lower_bound)
×
984
                        {
NEW
985
                                *ErrorFlag = 1; //Failed to converge
×
UNCOV
986
                                break;
×
987
                        }
988
                }
989
        }
990
        if (i == NumIterations)
108,817✔
NEW
991
                *ErrorFlag = 1;   //Failed to converge
×
992

993
//Label_100:
994
        *PathLength = S0 + SJ;
108,817✔
995
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc