1 // libSNL - Simple Nurbs Library
2 // Copyright 2006 Scott A.E. Lanham, Australia.
3 // --------------------------------------------
4 // This program is free software; you can redistribute it and/or modify
5 // it under the terms of the GNU General Public License as published by
6 // the Free Software Foundation; either version 2 of the License, or
7 // (at your option) any later version.
8 //
9 // This program is distributed in the hope that it will be useful,
10 // but WITHOUT ANY WARRANTY; without even the implied warranty of
11 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 // GNU General Public License for more details.
13
14 // snlSurface projection related functions.
15
16 #include "snlSurface_projection.h"
17
project_depr(snlPoint * toProject,int numPoints,double convergTol,double normTol,int maxPass)18 snlVertex* snlSurface::project_depr ( snlPoint* toProject, int numPoints, double convergTol,
19 double normTol, int maxPass )
20 {
21 //! Project an array of points to surface.
22 // --------------------------------------
23 //! @param toProject Array of snlPoints to project to surface.
24 //! @param numPoints Number of points being projected. ie size of points array.
25 //! @param convergTol If the difference between successive newton iterations converges and is
26 //! below this value then the point is taken to be projected.
27 //! @param normTol If the cosine of the angle between the projection vector and the
28 //! projected points normal is under this value then the projection is used.
29 //! @param maxPass Maximum number of mesh refinement passes allowed. Stops infinite loops
30 //! if projections don't converge.
31 //!
32 //! Notes: This function is now deprecated but stays around as a cross reference for
33 //! new projection work.
34
35 sLocn* projections = new sLocn [ numPoints ];
36
37 ptrList < sLocn >* ambig = projPtSurf ( *this, toProject, numPoints, projections,
38 convergTol, normTol, maxPass );
39
40 // Create vertexes to return and populate with converted sLocn's.
41 // -------------------------------------------------------------
42
43 snlVertex* retVertexes = new snlVertex [ numPoints ];
44
45 for ( int index = 0; index < numPoints; index ++ )
46 {
47 retVertexes [ index ] = projections [ index ].pt;
48
49 retVertexes [ index ].evalParamU ( projections [ index ].paramT );
50 retVertexes [ index ].evalParamV ( projections [ index ].paramU );
51
52 retVertexes [ index ].flag = projections [ index ].flag;
53 }
54
55 delete ambig;
56 delete[] projections;
57
58 return retVertexes;
59 }
60
invert(snlPoint * toInvert,int numPoints,int * retArraySize,double convergTol,double normTol,int maxPass)61 snlSurfLocn* snlSurface::invert ( snlPoint* toInvert, int numPoints, int* retArraySize,
62 double convergTol, double normTol, int maxPass )
63 {
64 //! Find parametric location of given points
65 // ----------------------------------------
66 //! @param toInvert Array of snlPoints to find on surface.
67 //! @param numPoints Number of points being inverted. ie size of points array.
68 //! @param retArraySize Size of array of surface locations that is returned.
69 //! @param convergTol If the difference between successive newton iterations converges and is
70 //! below this value then the point is taken to be inverted.
71 //! @param normTol How close to perpendicular the projection of the given point to the point
72 //! found gets to the surface tangents at the found point for convergence to be
73 //! successful.
74 //! @param maxPass Maximum number of refinement passes allowed. Stops infinite loops if
75 //! projections don't converge.
76
77 // Generate point mask. If false, entry is not processed during pass.
78
79 bool* pointMask = new bool [ numPoints ];
80
81 for ( int index = 0; index < numPoints; index ++ )
82 pointMask [ index ] = true;
83
84 // Calculate best guess for each point to be inverted.
85
86 ptrList <snlSurfLocnGuess>* guesses = guessInvLocation ( toInvert, numPoints, pointMask,
87 degU, degV );
88
89 delete[] pointMask;
90
91 return processGuesses ( toInvert, numPoints, retArraySize, guesses, convergTol,
92 normTol, maxPass );
93 }
94
project(snlPoint * toProject,int numPoints,int * retArraySize,double convergTol,double normTol,int maxPass)95 snlSurfLocn* snlSurface::project ( snlPoint* toProject, int numPoints, int* retArraySize,
96 double convergTol, double normTol, int maxPass )
97 {
98 //! Find parametric location of given points
99 // ----------------------------------------
100 //! @param toProject Array of snlPoints to find projections of on surface.
101 //! @param numPoints Number of points being inverted. ie size of points array.
102 //! @param retArraySize Size of array of surface locations that is returned.
103 //! @param convergTol If the difference between successive newton iterations converges and is
104 //! below this value then the point is taken to be inverted.
105 //! @param normTol How close to perpendicular the projection of the given point to the point
106 //! found gets to the surface tangents at the found point for convergence to be
107 //! successful.
108 //! @param maxPass Maximum number of refinement passes allowed. Stops infinite loops if
109 //! projections don't converge.
110
111 // Generate point mask. If false, entry is not processed during pass.
112
113 bool* pointMask = new bool [ numPoints ];
114
115 for ( int index = 0; index < numPoints; index ++ )
116 pointMask [ index ] = true;
117
118 // Only work on copy of surface.
119
120 snlSurface* tmpSurf = new snlSurface ( *this );
121
122 tmpSurf -> createConvexBezierSegments( 0, 0, 0.00009 ); // Sensitivity of 0.05 degrees.
123
124 // Calculate best guess for each point to be inverted.
125
126 ptrList <snlSurfLocnGuess>* guesses = tmpSurf -> guessProjLocation ( toProject, numPoints,
127 pointMask );
128
129 snlSurfLocn* retArray = processGuesses ( toProject, numPoints, retArraySize, guesses,
130 convergTol, normTol, maxPass, true );
131
132 // Clean up and return.
133
134 delete[] pointMask;
135
136 delete tmpSurf;
137
138 return retArray;
139 }
140
fastProject(snlPoint * toProject,int numPoints,int * retArraySize,double convergTol,double normTol,int maxPass,int sensitivity,int maxLocns)141 snlSurfLocn* snlSurface::fastProject ( snlPoint* toProject, int numPoints, int* retArraySize,
142 double convergTol, double normTol, int maxPass,
143 int sensitivity, int maxLocns )
144 {
145 //! Find parametric location of given points
146 // ----------------------------------------
147 //! @param toProject Array of snlPoints to find projections of on surface.
148 //! @param numPoints Number of points being inverted. ie size of points array.
149 //! @param retArraySize Size of array of surface locations that is returned.
150 //! @param convergTol If the difference between successive newton iterations converges and is
151 //! below this value then the point is taken to be inverted.
152 //! @param normTol How close to perpendicular the projection of the given point to the point
153 //! found gets to the surface tangents at the found point for convergence to be
154 //! successful.
155 //! @param maxPass Maximum number of refinement passes allowed. Stops infinite loops if
156 //! projections don't converge.
157 //! @param sensitivity The higher this number the more accurate the initial guess phase is but
158 //! the function becomes slower. Increases the number of subdivisions per
159 //! knot span by this amount. Must be a positive integer
160 //! @param maxLocns Maximum number of surface locations to return. If a surface is known to
161 //! have ambiguous areas then this number should be greater than one. Value is
162 //! clamped to be greater than zero.
163 //!
164 //! Notes: Fast project is not nearly as accurate as other project or invert functions.
165
166 ptrList <snlSurfLocnGuess>* guesses = guessFastProjLocation ( toProject, numPoints, maxLocns,
167 degU + sensitivity,
168 degV + sensitivity );
169
170 snlSurfLocn* retArray = processGuesses ( toProject, numPoints, retArraySize, guesses,
171 convergTol, normTol, maxPass, true, true );
172
173 return retArray;
174 }
175
processGuesses(snlPoint * points,int numPoints,int * retArraySize,ptrList<snlSurfLocnGuess> * guesses,double convergTol,double normTol,int maxPass,bool retNonConverged,bool noCull,int numVelocity,int numNewton)176 snlSurfLocn* snlSurface::processGuesses ( snlPoint* points, int numPoints, int* retArraySize,
177 ptrList <snlSurfLocnGuess>* guesses, double convergTol,
178 double normTol, int maxPass, bool retNonConverged,
179 bool noCull, int numVelocity, int numNewton )
180 {
181 //! Refine parametric location of given points
182 // ------------------------------------------
183 //! @param points Array of snlPoints to find on surface.
184 //! @param numPoints Number of points being inverted. ie size of points array.
185 //! @param retArraySize Size of array of surface locations that is returned.
186 //! @param guesses Parametric location guesses for given points.
187 //! @param convergTol If the difference between successive newton iterations converges and is
188 //! below this value then the point is taken to be inverted.
189 //! @param normTol How close to perpendicular the projection of the given point to the point
190 //! found gets to the surface tangents at the found point for convergence to be
191 //! successful.
192 //! @param maxPass Maximum number of refinement passes allowed. Stops infinite loops if
193 //! projections don't converge.
194 //! @param retNonConverged Return non converged points. Used for projection.
195 //! @param noCull Do not cull guesses that converge to the same point.
196 //! @param numVelocity Number of velocity iterations to perform per pass.
197 //! @param numNewton Number of newton iterations to perform per pass.
198
199 // Converge to points using multiple passes if necessary.
200
201 for ( int pass = 0; pass < maxPass; pass ++ )
202 {
203 bool converged = convergeVelocity ( points, guesses, numVelocity, convergTol, normTol );
204
205 if ( ! converged )
206 converged = convergeNewton ( points, guesses, numNewton, convergTol, normTol );
207
208 // If all guesses have been culled for a given point then reprocess one of them.
209
210 snlSurfLocnGuess* guess = guesses -> first();
211
212 for ( int index = 0; index < numPoints; index ++ )
213 {
214 bool allCulled = true;
215
216 snlSurfLocnGuess* bestGuess = guess;
217
218 if ( guess )
219 {
220 while ( guess )
221 {
222
223 if ( guess -> origPtIndex != index ) break;
224
225 if ( ! guess -> culled )
226 allCulled = false;
227 else if ( guess -> dist < bestGuess -> dist )
228 bestGuess = guess;
229
230 guess = guesses -> next();
231 }
232
233 if ( allCulled )
234 {
235 // Force another pass to be performed.
236
237 bestGuess -> ignoreParamBounds = true;
238 bestGuess -> culled = false;
239 converged = false;
240 }
241 }
242 }
243 }
244
245 // Cull duplicate guesses that have converged to the same point. Keep best one.
246
247 snlSurfLocnGuess* guess = guesses -> first();
248
249 int pointIndex = -1;
250
251 ptrList <snlSurfLocnGuess> pointGuesses;
252
253 while ( guess && ! noCull )
254 {
255 if ( ! guess -> culled && ( guess -> converged || retNonConverged ) )
256 {
257 if ( guess -> origPtIndex != pointIndex )
258 {
259 // Move onto next point indexes guesses.
260
261 pointIndex = guess -> origPtIndex;
262
263 pointGuesses.clear();
264
265 pointGuesses.append ( guess, false );
266 }
267 else
268 {
269 // Compare point with others found. Take best one.
270
271 snlSurfLocnGuess* ptGuess = pointGuesses.first();
272
273 while ( ptGuess )
274 {
275 if ( ! ptGuess -> culled )
276 {
277 // If other guesses param bounds overlap current guess
278 // then assume they have converged to the same point.
279
280 if ( guess -> paramU >= ptGuess -> minU
281 && guess -> paramU <= ptGuess -> maxU )
282 {
283 if ( guess -> paramV >= ptGuess -> minV
284 && guess -> paramV <= ptGuess -> maxV )
285 {
286 // Both guesses are in same param zone. Cull guess with largest
287 // distance.
288
289 if ( guess -> dist > ptGuess -> dist )
290 guess -> culled = true;
291 else
292 ptGuess -> culled = true;
293 }
294 }
295 }
296
297 ptGuess = pointGuesses.next();
298 }
299
300 pointGuesses.append ( guess, false );
301 }
302 }
303
304 guess = guesses -> next();
305 }
306
307 // Assemble best found points.
308
309 // Get total number of points found.
310
311 int totalCount = 0;
312
313 guess = guesses -> first();
314
315 while ( guess )
316 {
317 if ( ! guess -> culled && ( guess -> converged || retNonConverged ) )
318 totalCount ++;
319
320 guess = guesses -> next();
321 }
322
323 snlSurfLocn* retLocns = new snlSurfLocn [ totalCount ];
324
325 int index = 0;
326
327 guess = guesses -> first();
328
329 while ( guess )
330 {
331 if ( ( retNonConverged || guess -> converged ) && ! guess -> culled )
332 {
333 retLocns [ index ].paramU = guess -> paramU;
334 retLocns [ index ].paramV = guess -> paramV;
335 retLocns [ index ].pt = guess -> pt;
336 retLocns [ index ].dist = sqrt ( guess -> dist );
337 retLocns [ index ].origPtIndex = guess -> origPtIndex;
338 retLocns [ index ].cos = guess -> cos;
339
340 index ++;
341 }
342
343 guess = guesses -> next();
344 }
345
346 // Clean up and return.
347
348 delete guesses;
349
350 if ( retArraySize )
351 *retArraySize = totalCount;
352
353 return retLocns;
354 }
355
convergeVelocity(snlPoint * convergToPts,ptrList<snlSurfLocnGuess> * guesses,int numIterations,double convergTol,double normTol)356 bool snlSurface::convergeVelocity ( snlPoint* convergToPts, ptrList <snlSurfLocnGuess>* guesses,
357 int numIterations, double convergTol, double normTol )
358 {
359 //! Converge guesses to given points using velocity technique.
360 // ----------------------------------------------------------
361 //! @param convergToPts Array of points that are to be converged to. ie Points to be found.
362 //! @param guesses List of current guesses to be converged.
363 //! @param numIterations Maximum number of convergence iterations to perform.
364 //! @param convergTol Maximum distance between point and guess allowed for convergence to be
365 //! successful.
366 //! @param normTol How close to perpendicular the projection of the given point to the guessed
367 //! point gets to the surface tangents at the guessed point for convergence to be
368 //! successful.
369
370 cout.precision ( 16 );
371
372 double convTolSqrd = convergTol * convergTol;
373
374 knot minU = knotVectU -> min();
375 knot maxU = knotVectU -> max();
376
377 knot minV = knotVectV -> min();
378 knot maxV = knotVectV -> max();
379
380 snlSurfLocnGuess* guess = guesses -> first();
381
382 snlVector velocityU, velocityV;
383 snlPoint evalPoint;
384
385 bool converged = true;
386
387 while ( guess )
388 {
389 if ( ! guess -> converged && ! guess -> culled )
390 {
391 if ( guess -> dist >= convTolSqrd )
392 {
393 // Generate new guess.
394
395 snlSurfLocnGuess newGuess = *guess;
396
397 for ( int iteration = 0; iteration < numIterations; iteration ++ )
398 {
399 // Get Initial velocities at guessed point
400
401 if ( ! iteration )
402 velocities ( newGuess.paramU, newGuess.paramV, evalPoint, velocityU,
403 velocityV );
404
405 // Calculate new parameters based on velocities.
406
407 snlVector guessToPt ( newGuess.pt, convergToPts [ newGuess.origPtIndex ] );
408
409 double lengthU = velocityU.length();
410
411 if ( lengthU == 0.0 ) break;
412
413 double distU = guessToPt.dot ( velocityU ) / lengthU;
414 knot deltaU = distU / lengthU;
415
416 double lengthV = velocityV.length();
417
418 if ( lengthV == 0.0 ) break;
419
420 double distV = guessToPt.dot ( velocityV ) / lengthV;
421 knot deltaV = distV / lengthV;
422
423 knot newU = newGuess.paramU + deltaU;
424 knot newV = newGuess.paramV + deltaV;
425
426 if ( newU < minU ) newU = minU;
427 if ( newU > maxU ) newU = maxU;
428
429 if ( newV < minV ) newV = minV;
430 if ( newV > maxV ) newV = maxV;
431
432 // If the distance travelled exceeds the required distance by more than 10% then
433 // recalculate the param deltas.
434
435 evalPoint = eval ( newU, newV );
436
437 double newDist = evalPoint.distSqrd ( convergToPts [ newGuess.origPtIndex ] );
438
439
440 int loopCount = -1;
441
442 while ( newDist > newGuess.dist * 1.1 )
443 {
444 // Calculate new parameters based on actual distance travelled.
445
446 loopCount ++;
447
448 snlVector newGuessToPt ( newGuess.pt, evalPoint );
449
450 double newDistU = newGuessToPt.dot ( velocityU ) / lengthU;
451 double newDistV = newGuessToPt.dot ( velocityV ) / lengthV;
452
453 if ( newDistU == 0.0 && newDistV == 0.0 )
454 break;
455
456 double loopAdj = 1.0 / (double) ( loopCount + 1 );
457
458 knot newAdjustU;
459 knot newAdjustV;
460
461 if ( newDistU != 0.0 )
462 newAdjustU = newGuess.paramU + ( ( distU * loopAdj / newDistU )
463 * ( newU - newGuess.paramU ) );
464 else
465 newAdjustU = newU;
466
467 if ( newDistV != 0.0 )
468 newAdjustV = newGuess.paramV + ( ( distV * loopAdj / newDistV )
469 * ( newV - newGuess.paramV ) );
470 else
471 newAdjustV = newV;
472
473 // Do out of bounds check.
474
475 if ( newAdjustU < minU ) newAdjustU = minU;
476 if ( newAdjustU > maxU ) newAdjustU = maxU;
477
478 if ( newAdjustV < minV ) newAdjustV = minV;
479 if ( newAdjustV > maxV ) newAdjustV = maxV;
480
481 // Test for infinite loop.
482
483 if ( newU == newAdjustU && newV == newAdjustV )
484 break;
485
486 newU = newAdjustU;
487 newV = newAdjustV;
488
489 // Re-evaluate parameters.
490
491 evalPoint = eval ( newU, newV );
492
493 newDist = evalPoint.distSqrd ( convergToPts [ newGuess.origPtIndex ] );
494 }
495
496 // Store point and velocities that match new params.
497
498 velocities ( newU, newV, evalPoint, velocityU, velocityV );
499
500 newGuess.paramU = newU;
501 newGuess.paramV = newV;
502
503 newGuess.pt = evalPoint;
504
505 newGuess.dist = evalPoint.distSqrd ( convergToPts [ newGuess.origPtIndex ] );
506
507 // Test for guess going out of parametric bounds.
508
509 if ( ! newGuess.ignoreParamBounds )
510 {
511 if ( newGuess.paramU < newGuess.minU || newGuess.paramU > newGuess.maxU )
512 {
513 guess -> culled = true;
514 break;
515 }
516
517 if ( newGuess.paramV < newGuess.minV || newGuess.paramV > newGuess.maxV )
518 {
519 guess -> culled = true;
520 break;
521 }
522 }
523
524 // Test for convergence.
525
526 if ( newGuess.dist < convTolSqrd )
527 {
528 newGuess.converged = true;
529 break;
530 }
531
532 snlVector projToSurf ( convergToPts [ newGuess.origPtIndex ], evalPoint );
533
534 basis cosU = projToSurf.calcAbsCos ( velocityU );
535
536 basis cosV = projToSurf.calcAbsCos ( velocityV );
537
538 newGuess.cos = cosU > cosV ? cosU : cosV;
539
540 if ( cosU <= normTol && cosV <= normTol )
541 {
542 newGuess.converged = true;
543 break;
544 }
545 }
546
547 // If new guess is better than old and hasn't been culled then replace old guess.
548
549 if ( ! guess -> culled )
550 {
551 // If parameters haven't changed over all iterations then set as converged.
552
553 if ( guess -> paramU == newGuess.paramU && guess -> paramV == newGuess.paramV )
554 newGuess.converged = true;
555
556 *guess = newGuess;
557 }
558 }
559 else
560 guess -> converged = true;
561
562 // Test for guess going out of parametric bounds.
563 if ( ! guess -> ignoreParamBounds && guess -> culled )
564 {
565 if ( guess -> paramU < guess -> minU || guess -> paramU > guess -> maxU )
566 guess -> culled = true;
567
568 if ( guess -> paramV < guess -> minV || guess -> paramV > guess -> maxV )
569 guess -> culled = true;
570 }
571 }
572
573 if ( ! guess -> converged && ! guess -> culled ) converged = false;
574
575 guess = guesses -> next();
576 }
577
578 return converged;
579 }
580
convergeNewton(snlPoint * convergToPts,ptrList<snlSurfLocnGuess> * guesses,int numIterations,double convergTol,double normTol)581 bool snlSurface::convergeNewton ( snlPoint* convergToPts, ptrList <snlSurfLocnGuess>* guesses,
582 int numIterations, double convergTol, double normTol )
583 {
584 //! Converge guesses to given points using Newton iteration
585 // -------------------------------------------------------
586 //! @param convergToPts Array of points that are to be converged to. ie Points to be found.
587 //! @param guesses List of current guesses to be converged.
588 //! @param numIterations Maximum number of convergence iterations to perform.
589 //! @param convergTol Maximum distance between point and guess allowed for convergence to be
590 //! successful.
591 //! @param normTol Cosine of angle between normal to surface at guess and projection from
592 //! guess to given point. If cosine is below this angle then iterations stop.
593
594 double convTolSqrd = convergTol * convergTol;
595
596 knot minU = knotVectU -> min();
597 knot maxU = knotVectU -> max();
598
599 knot minV = knotVectV -> min();
600 knot maxV = knotVectV -> max();
601
602 snlSurfLocnGuess* guess = guesses -> first();
603
604 snlPoint* derivs;
605
606 bool converged = true;
607
608 while ( guess )
609 {
610 derivs = 0;
611
612 if ( ! guess -> converged && ! guess -> culled )
613 {
614 snlSurfLocnGuess newGuess = *guess;
615
616 if ( guess -> dist >= convTolSqrd )
617 {
618 for ( int iteration = 0; iteration < numIterations; iteration ++ )
619 {
620 // Get 1st and 2nd derivatives.
621
622 if ( ! derivs )
623 derivs = evalDerivs ( newGuess.paramU, newGuess.paramV, 2, 2 );
624
625 // Generate next Newton approximation.
626
627 knot deltaU, deltaV;
628
629 if ( degU > 1 && degV > 1 )
630 {
631 if ( ! newtonIterStepSurf ( derivs, convergToPts + newGuess.origPtIndex,
632 &deltaU, &deltaV ) )
633 break; // Param deltas would have gone to infinity.
634 }
635 else
636 {
637 // At least one of the degrees is 1.
638
639 snlPoint uDerivs [ 3 ];
640
641 uDerivs [ 0 ] = derivs [ 0 ];
642 uDerivs [ 1 ] = derivs [ 3 ];
643 uDerivs [ 2 ] = derivs [ 6 ];
644
645 if ( degU == 1 )
646 {
647 if ( ! lineIterStepCurve ( uDerivs, convergToPts + newGuess.origPtIndex,
648 &deltaU ) )
649 break;
650 }
651 else
652 {
653 if ( ! newtonIterStepCurve ( uDerivs,
654 convergToPts + newGuess.origPtIndex,
655 &deltaU ) )
656 break;
657 }
658
659 if ( degV == 1 )
660 {
661 if ( ! lineIterStepCurve ( derivs, convergToPts + newGuess.origPtIndex,
662 &deltaV ) )
663 break;
664 }
665 else
666 {
667 if ( ! newtonIterStepCurve ( derivs, convergToPts +
668 newGuess.origPtIndex, &deltaV ) )
669 break;
670 }
671 }
672
673 // Calcualte and clamp new parameters.
674
675 knot newU = newGuess.paramU + deltaU;
676 knot newV = newGuess.paramV + deltaV;
677
678 if ( newU < minU ) newU = minU;
679 if ( newU > maxU ) newU = maxU;
680
681 if ( newV < minV ) newV = minV;
682 if ( newV > maxV ) newV = maxV;
683
684 // If parameters haven't changed between iterations then guess has converged.
685
686 if ( newU == newGuess.paramU && newV == newGuess.paramV )
687 {
688 newGuess.converged = true;
689 break;
690 }
691
692 newGuess.paramU = newU;
693 newGuess.paramV = newV;
694
695 // Evaluate new parameters.
696
697 delete[] derivs;
698 derivs = evalDerivs ( newGuess.paramU, newGuess.paramV, 2, 2 );
699
700 newGuess.pt = derivs [ 0 ];
701
702 newGuess.dist = derivs [ 0 ].distSqrd ( convergToPts [ newGuess.origPtIndex ] );
703
704 // Check for distance and cosine tolerances.
705
706 if ( newGuess.dist < convTolSqrd )
707 {
708 newGuess.converged = true;
709 break;
710 }
711
712 snlVector velocityU ( derivs [ 3 ] );
713 snlVector velocityV ( derivs [ 1 ] );
714
715 snlVector projToSurf ( convergToPts [ newGuess.origPtIndex ], newGuess.pt );
716
717 basis cosU = projToSurf.calcAbsCos ( velocityU );
718
719 basis cosV = projToSurf.calcAbsCos ( velocityV );
720
721 newGuess.cos = cosU > cosV ? cosU : cosV;
722
723 if ( cosU <= normTol && cosV <= normTol )
724 {
725 newGuess.converged = true;
726 break;
727 }
728 }
729 }
730 else
731 guess -> converged = true;
732
733 if ( ! guess -> culled && newGuess.dist < guess -> dist )
734 *guess = newGuess;
735 }
736
737 // Test for guess going out of parametric bounds.
738
739 if ( ! guess -> ignoreParamBounds && ! guess -> culled )
740 {
741 if ( guess -> paramU < guess -> minU || guess -> paramU > guess -> maxU )
742 guess -> culled = true;
743
744 if ( guess -> paramV < guess -> minV || guess -> paramV > guess -> maxV )
745 guess -> culled = true;
746 }
747
748 if ( ! guess -> converged && ! guess -> culled ) converged = false;
749
750 guess = guesses -> next();
751
752 // Clean up.
753
754 if ( derivs ) delete[] derivs;
755 }
756
757 return converged;
758 }
759
guessInvLocation(snlPoint * points,int numPoints,bool * pointMask,int granU,int granV)760 ptrList <snlSurfLocnGuess>* snlSurface::guessInvLocation ( snlPoint* points, int numPoints,
761 bool* pointMask, int granU,
762 int granV )
763 {
764 //! Guess parametric location of given points.
765 // ------------------------------------------
766 //! @param points Array of points to find matches with.
767 //! @param numPoints Number of points in array.
768 //! @param pointMask Array specifying which points to process. Corresponding index to points
769 //! array. Must be true to process.
770 //! @param granU Granularity of each span in U direction.
771 //! @param granV Granularity of each span in V direction.
772 //!
773 //! @return Array of surface location guess structs. Caller owns this array.
774 //!
775 //! Notes: This function will return one guess per parametric span.
776
777 int index;
778
779 int numSpansU = knotVectU -> getNumSpans();
780 int numSpansV = knotVectV -> getNumSpans();
781
782 int numEvalU = granU * numSpansU + 1;
783 int numEvalV = granV * numSpansV + 1;
784
785 // Pre-calculate parametric positions.
786
787 knot* paramU = new knot [ numEvalU ];
788 int* spanU = new int [ numEvalU ];
789
790 knot* paramV = new knot [ numEvalV ];
791 int* spanV = new int [ numEvalV ];
792
793 // U direction.
794
795 int cSpan = knotVectU -> getFirstSpan();
796
797 knot paramStart = knotVectU -> val ( cSpan );
798
799 cSpan = knotVectU -> getNextSpan ( cSpan );
800
801 knot paramEnd;
802
803 if ( cSpan )
804 paramEnd = knotVectU -> val ( cSpan );
805 else
806 paramEnd = knotVectU -> max();
807
808
809 int numSteps;
810
811 int paramIndex = 0;
812
813 basis param;
814
815 for ( int span = 0; span < numSpansU; span ++ )
816 {
817 basis paramStep = ( paramEnd - paramStart ) / (double) granU;
818
819 param = paramStart;
820
821 if ( span )
822 {
823 numSteps = granU;
824 param += paramStep;
825 }
826 else
827 {
828 numSteps = granU + 1;
829 }
830
831 // Generate params for span.
832
833 for ( index = 0; index < numSteps; index ++ )
834 {
835 paramU [ paramIndex ] = param;
836
837 spanU [ paramIndex ++ ] = span;
838
839 param += paramStep;
840
841 if ( param > paramEnd ) param = paramEnd; // Round off error trap.
842 }
843
844 paramStart = paramEnd;
845
846 cSpan = knotVectU -> getNextSpan ( cSpan );
847
848 if ( cSpan )
849 paramEnd = knotVectU -> val ( cSpan );
850 else
851 paramEnd = knotVectU -> max();
852 }
853
854 // V direction.
855
856 cSpan = knotVectV -> getFirstSpan();
857
858 paramStart = knotVectV -> val ( cSpan );
859
860 cSpan = knotVectV -> getNextSpan ( cSpan );
861
862 if ( cSpan )
863 paramEnd = knotVectV -> val ( cSpan );
864 else
865 paramEnd = knotVectV -> max();
866
867 paramIndex = 0;
868
869 for ( int span = 0; span < numSpansV; span ++ )
870 {
871 basis paramStep = ( paramEnd - paramStart ) / (double) granV;
872
873 param = paramStart;
874
875 if ( span )
876 {
877 numSteps = granV;
878 param += paramStep;
879 }
880 else
881 {
882 numSteps = granV + 1;
883 }
884
885 for ( index = 0; index < numSteps; index ++ )
886 {
887 paramV [ paramIndex ] = param;
888
889 spanV [ paramIndex ++ ] = span;
890
891 param += paramStep;
892
893 if ( param > paramEnd ) param = paramEnd; // Round off error trap.
894 }
895
896 paramStart = paramEnd;
897
898 cSpan = knotVectV -> getNextSpan ( cSpan );
899
900 if ( cSpan )
901 paramEnd = knotVectV -> val ( cSpan );
902 else
903 paramEnd = knotVectV -> max();
904 }
905
906 // Pre-evaluate basis functions.
907
908 basis** basisU = new basis* [ numEvalU ];
909 basis** basisV = new basis* [ numEvalV ];
910
911 for ( index = 0; index < numEvalU; index ++ )
912 basisU [ index ] = knotVectU -> evalBasis ( paramU [ index ] );
913
914 for ( index = 0; index < numEvalV; index ++ )
915 basisV [ index ] = knotVectV -> evalBasis ( paramV [ index ] );
916
917 // Evaluate surface points and vectors.
918
919 int numEvalPts = numEvalU * numEvalV;
920
921 snlPoint* evalPts = new snlPoint [ numEvalPts ];
922
923 index = 0;
924
925 for ( int indexU = 0; indexU < numEvalU; indexU ++ )
926 {
927 for ( int indexV = 0; indexV < numEvalV; indexV ++ )
928 {
929 evalPts [ index ] = eval ( paramU [ indexU ], paramV [ indexV ], basisU [ indexU ],
930 basisV [ indexV ] );
931
932 index ++;
933 }
934 }
935
936 // Calculate bounding distances. They are used for culling improbable guesses.
937
938 double* boundDist = new double [ numEvalPts ];
939
940 index = 0;
941
942 for ( int indexU = 0; indexU < numEvalU; indexU ++ )
943 {
944 for ( int indexV = 0; indexV < numEvalV; indexV ++ )
945 {
946 double maxDist = 0;
947 double dist;
948
949 if ( indexU > 0 )
950 {
951 // U before current index.
952
953 if ( indexV > 0 )
954 {
955 dist = evalPts [ index - numEvalV - 1 ].distSqrd ( evalPts [ index ] );
956 if ( dist > maxDist ) maxDist = dist;
957 }
958
959 if ( indexV < numEvalV - 1 )
960 {
961 dist = evalPts [ index - numEvalV + 1 ].distSqrd ( evalPts [ index ] );
962 if ( dist > maxDist ) maxDist = dist;
963 }
964 }
965
966 if ( indexU < numEvalU - 1 )
967 {
968 // U after current index.
969
970 if ( indexV > 0 )
971 {
972 dist = evalPts [ index + numEvalV - 1 ].distSqrd ( evalPts [ index ] );
973 if ( dist > maxDist ) maxDist = dist;
974 }
975
976 if ( indexV < numEvalV - 1 )
977 {
978 dist = evalPts [ index + numEvalV + 1 ].distSqrd ( evalPts [ index ] );
979 if ( dist > maxDist ) maxDist = dist;
980 }
981 }
982
983 boundDist [ index ] = maxDist;
984
985 index ++;
986 }
987 }
988
989 // Compare given points to evaluated points. One entry per span.
990
991 int numSpans = numSpansU * numSpansV;
992
993 int numSpanPoints = numPoints * numSpans;
994
995 // Two dimensional arrays [ given point index ] [ span index ].
996
997 int* uIndexes = new int [ numSpanPoints ]; // NOT control point indexes.
998 int* vIndexes = new int [ numSpanPoints ];
999 double* distances = new double [ numSpanPoints ];
1000 bool* populated = new bool [ numSpanPoints ]; // If false distances have not been populated.
1001
1002 for ( index = 0; index < numSpanPoints; index ++ )
1003 populated [ index ] = false;
1004
1005 double distSqrd;
1006
1007 int numToReturn = 0;
1008
1009 index = 0;
1010
1011 for ( int indexU = 0; indexU < numEvalU; indexU ++ )
1012 {
1013 for ( int indexV = 0; indexV < numEvalV; indexV ++ )
1014 {
1015 int spanIndex = spanU [ indexU ] * numSpansV + spanV [ indexV ];
1016
1017 for ( int ptIndex = 0; ptIndex < numPoints; ptIndex ++ )
1018 {
1019 if ( pointMask [ ptIndex ] )
1020 {
1021 int ptIndexOffset = ptIndex * numSpans;
1022
1023 distSqrd = evalPts [ index ].distSqrd ( points [ ptIndex ] );
1024
1025 // Only process span point if distance is within probable bounds.
1026
1027 if ( distSqrd < boundDist [ index ] )
1028 {
1029 if ( distances [ ptIndexOffset + spanIndex ] > distSqrd
1030 || ! populated [ ptIndexOffset + spanIndex ])
1031 {
1032 if ( ! populated [ ptIndexOffset + spanIndex ] )
1033 {
1034 numToReturn ++;
1035 populated [ ptIndexOffset + spanIndex ] = true;
1036 }
1037
1038 distances [ ptIndexOffset + spanIndex ] = distSqrd;
1039 uIndexes [ ptIndexOffset + spanIndex ] = indexU;
1040 vIndexes [ ptIndexOffset + spanIndex ] = indexV;
1041 }
1042 }
1043 }
1044 }
1045
1046 index ++;
1047 }
1048 }
1049
1050 // Build array of surface locations to return.
1051
1052 ptrList <snlSurfLocnGuess>* retList = new ptrList <snlSurfLocnGuess>;
1053
1054 int indexU, indexV;
1055
1056 index = 0;
1057
1058 for ( int ptIndex = 0; ptIndex < numPoints; ptIndex ++ )
1059 {
1060 for ( int spanIndex = 0; spanIndex < numSpans; spanIndex ++ )
1061 {
1062 if ( populated [ index ] )
1063 {
1064 snlSurfLocnGuess* guessLocn = new snlSurfLocnGuess;
1065
1066 indexU = uIndexes [ index ];
1067 indexV = vIndexes [ index ];
1068
1069 guessLocn -> paramU = paramU [ indexU ];
1070 guessLocn -> paramV = paramV [ indexV ];
1071
1072 guessLocn -> pt = evalPts [ indexU * numEvalV + indexV ];
1073
1074 guessLocn -> dist = distances [ index ];
1075
1076 guessLocn -> origPtIndex = ptIndex;
1077
1078 guessLocn -> spanNumber = spanIndex;
1079
1080 if ( indexU > 0 )
1081 guessLocn -> minU = paramU [ indexU - 1 ];
1082 else
1083 guessLocn -> minU = paramU [ indexU ];
1084
1085 if ( indexU < numEvalU - 1 )
1086 guessLocn -> maxU = paramU [ indexU + 1 ];
1087 else
1088 guessLocn -> maxU = paramU [ indexU ];
1089
1090 if ( indexV > 0 )
1091 guessLocn -> minV = paramV [ indexV - 1 ];
1092 else
1093 guessLocn -> minV = paramV [ indexV ];
1094
1095 if ( indexV < numEvalV -1 )
1096 guessLocn -> maxV = paramV [ indexV + 1 ];
1097 else
1098 guessLocn -> maxV = paramV [ indexV ];
1099
1100 guessLocn -> culled = false;
1101 guessLocn -> ignoreParamBounds = false;
1102 guessLocn -> converged = false;
1103
1104 retList -> append ( guessLocn, true );
1105 }
1106
1107 index ++;
1108 }
1109 }
1110
1111 // Clean up
1112
1113 delete[] uIndexes;
1114 delete[] vIndexes;
1115 delete[] distances;
1116 delete[] populated;
1117
1118 delete[] evalPts;
1119 delete[] boundDist;
1120
1121 delete[] paramU;
1122 delete[] paramV;
1123
1124 delete[] spanU;
1125 delete[] spanV;
1126
1127 for ( int index = 0; index < numEvalU; index ++ )
1128 delete[] basisU [ index ];
1129
1130 for ( int index = 0; index < numEvalV; index ++ )
1131 delete[] basisV [ index ];
1132
1133 delete[] basisU;
1134 delete[] basisV;
1135
1136 return retList;
1137 }
1138
guessProjLocation(snlPoint * points,int numPoints,bool * pointMask)1139 ptrList <snlSurfLocnGuess>* snlSurface::guessProjLocation ( snlPoint* points, int numPoints,
1140 bool* pointMask )
1141 {
1142 //! Guess parametric location of given points.
1143 // ------------------------------------------
1144 //! @param points Array of points to find matches with.
1145 //! @param numPoints Number of points in array.
1146 //! @param pointMask Array specifying which points to process. Corresponding index to points
1147 //! array. Must be true to process.
1148 //!
1149 //! @return List of surface location guess structs. Caller owns this list.
1150 //!
1151 //! @par Notes: Function expects all spans to be convex Bezier segments. It will _not_ work
1152 //! if this is not so.
1153
1154 int index;
1155
1156 int numSpansU = knotVectU -> getNumSpans();
1157 int numSpansV = knotVectV -> getNumSpans();
1158
1159 int numEvalU = numSpansU + 1;
1160 int numEvalV = numSpansV + 1;
1161
1162 // Pre-calculate parametric positions.
1163
1164 knot* paramU = new knot [ numEvalU ];
1165
1166 knot* paramV = new knot [ numEvalV ];
1167
1168 // U Direction.
1169
1170 int cSpan = knotVectU -> getFirstSpan();
1171
1172 for ( int evalIndex = 0; evalIndex < numEvalU - 1; evalIndex ++ )
1173 {
1174 paramU [ evalIndex ] = knotVectU -> val ( cSpan );
1175
1176 cSpan = knotVectU -> getNextSpan ( cSpan );
1177 }
1178
1179 paramU [ numEvalU - 1 ] = knotVectU -> max();
1180
1181 // V Direction.
1182
1183 cSpan = knotVectV -> getFirstSpan();
1184
1185 for ( int evalIndex = 0; evalIndex < numEvalV - 1; evalIndex ++ )
1186 {
1187 paramV [ evalIndex ] = knotVectV -> val ( cSpan );
1188
1189 cSpan = knotVectV -> getNextSpan ( cSpan );
1190 }
1191
1192 paramV [ numEvalV - 1 ] = knotVectV -> max();
1193
1194 // Evaluate surface points and velocities.
1195 // Because the surface is segmented into Bezier segements the segment
1196 // corners are the control points and the velocities are calculated
1197 // directly from the control points without the need for basis functions.
1198
1199 int numEvalPts = numEvalU * numEvalV;
1200
1201 snlPoint* evalPts = new snlPoint [ numEvalPts ];
1202
1203 snlVector* edgeNormalU = new snlVector [ 4 ];
1204 snlVector* edgeNormalV = new snlVector [ 4 ];
1205
1206 bool* hasGuess = new bool [ numPoints ];
1207 snlSurfLocnGuess** lastGuess = new snlSurfLocnGuess* [ numPoints ];
1208
1209 for ( int ptIndex = 0; ptIndex < numPoints; ptIndex ++ )
1210 hasGuess [ ptIndex ] = false;
1211
1212 index = 0;
1213
1214 int ctrlPtIndex;
1215
1216 const snlCtrlPoint* ctrlPts = ctrlPtNet -> getCtrlPts();
1217
1218 int vSize = sizeV();
1219
1220 for ( int indexU = 0; indexU < numEvalU; indexU ++ )
1221 {
1222 ctrlPtIndex = degU * indexU * vSize;
1223
1224 for ( int indexV = 0; indexV < numEvalV; indexV ++ )
1225 {
1226 evalPts [ index ] = ctrlPts [ ctrlPtIndex ];
1227
1228 index ++;
1229
1230 ctrlPtIndex += degV;
1231 }
1232 }
1233
1234 ptrList <snlSurfLocnGuess>* tmpList = new ptrList <snlSurfLocnGuess>; // List of out of order
1235 // guesses.
1236
1237 int spanEvalIndex = 0;
1238
1239 int spanNum = 0;
1240
1241 for ( int spanU = 0; spanU < numSpansU; spanU ++ )
1242 {
1243 for ( int spanV = 0; spanV < numSpansV; spanV ++ )
1244 {
1245 // Calculate eight edge normals per segment. 4 per parametric direction.
1246 //
1247 // Edge normal orientation per segment:
1248 //
1249 // 1 ---- 2 --- V
1250 // | |
1251 // 3 ---- 4
1252 // |
1253 // U
1254
1255 snlVector velocityU;
1256 snlVector velocityV;
1257 snlVector normal;
1258 snlVector edge;
1259
1260 int baseIndex = spanU * degU * vSize + spanV * degV;
1261
1262 // Calculate and orient first set of edge normals
1263
1264 velocityU.calc ( ctrlPts [ baseIndex ], ctrlPts [ baseIndex + vSize ] );
1265 velocityV.calc ( ctrlPts [ baseIndex ], ctrlPts [ baseIndex + 1 ] );
1266
1267 normal.crossProduct ( velocityU, velocityV );
1268
1269 edge.calc ( evalPts [ spanEvalIndex ], evalPts [ spanEvalIndex + 1 ] );
1270 edgeNormalU [ 0 ].crossProduct ( normal, edge );
1271
1272 snlVector orient ( evalPts [ spanEvalIndex ], evalPts [ spanEvalIndex + numEvalV ] );
1273 if ( edgeNormalU [ 0 ].dot ( orient ) < 0.0 ) edgeNormalU [ 0 ] *= - 1.0;
1274
1275 if ( edgeNormalU [ 0 ].dot ( velocityV ) < 0.0 )
1276 {
1277 // If velocity vectors are outside of edge then use them for edge normal calculation
1278 // instead.
1279
1280 edgeNormalU [ 0 ].crossProduct ( normal, velocityV );
1281 if ( edgeNormalU [ 0 ].dot ( orient ) < 0.0 ) edgeNormalU [ 0 ] *= - 1.0;
1282 }
1283
1284 edge.calc ( evalPts [ spanEvalIndex ], evalPts [ spanEvalIndex + numEvalV ] );
1285 edgeNormalV [ 0 ].crossProduct ( normal, edge );
1286
1287 orient.calc ( evalPts [ spanEvalIndex ], evalPts [ spanEvalIndex + 1 ] );
1288 if ( edgeNormalV [ 0 ].dot ( orient ) < 0.0 ) edgeNormalV [ 0 ] *= - 1.0;
1289
1290 if ( edgeNormalV [ 0 ].dot ( velocityU ) < 0.0 )
1291 {
1292 edgeNormalV [ 0 ].crossProduct ( normal, velocityU );
1293 if ( edgeNormalV [ 0 ].dot ( orient ) < 0.0 ) edgeNormalV [ 0 ] *= - 1.0;
1294 }
1295
1296 // Calculate and orient second set of edge normals
1297
1298 velocityU.calc ( ctrlPts [ baseIndex + degV ], ctrlPts [ baseIndex + degV + vSize ] );
1299 velocityV.calc ( ctrlPts [ baseIndex + degV ], ctrlPts [ baseIndex + degV - 1 ] );
1300
1301 normal.crossProduct ( velocityU, velocityV );
1302
1303 edge.calc ( evalPts [ spanEvalIndex + 1 ], evalPts [ spanEvalIndex ] );
1304 edgeNormalU [ 1 ].crossProduct ( normal, edge );
1305
1306 orient.calc ( evalPts [ spanEvalIndex + 1 ], evalPts [ spanEvalIndex + numEvalV + 1 ] );
1307 if ( edgeNormalU [ 1 ].dot ( orient ) < 0.0 ) edgeNormalU [ 1 ] *= - 1.0;
1308
1309 if ( edgeNormalU [ 1 ].dot ( velocityV ) < 0.0 )
1310 {
1311 edgeNormalU [ 1 ].crossProduct ( normal, velocityV );
1312 if ( edgeNormalU [ 1 ].dot ( orient ) < 0.0 ) edgeNormalU [ 1 ] *= - 1.0;
1313 }
1314
1315 edge.calc ( evalPts [ spanEvalIndex + 1 ], evalPts [ spanEvalIndex + numEvalV + 1] );
1316 edgeNormalV [ 1 ].crossProduct ( normal, edge );
1317
1318 orient.calc ( evalPts [ spanEvalIndex + 1 ], evalPts [ spanEvalIndex ] );
1319 if ( edgeNormalV [ 1 ].dot ( orient ) < 0.0 ) edgeNormalV [ 1 ] *= - 1.0;
1320
1321 if ( edgeNormalV [ 1 ].dot ( velocityU ) < 0.0 )
1322 {
1323 edgeNormalV [ 1 ].crossProduct ( normal, velocityU );
1324 if ( edgeNormalV [ 1 ].dot ( orient ) < 0.0 ) edgeNormalV [ 1 ] *= - 1.0;
1325 }
1326
1327 baseIndex += degU * vSize;
1328
1329 // Calculate and orient third set of edge normals
1330
1331 velocityU.calc ( ctrlPts [ baseIndex ], ctrlPts [ baseIndex - vSize ] );
1332 velocityV.calc ( ctrlPts [ baseIndex ], ctrlPts [ baseIndex + 1 ] );
1333
1334 normal.crossProduct ( velocityU, velocityV );
1335
1336 edge.calc ( evalPts [ spanEvalIndex + numEvalV ],
1337 evalPts [ spanEvalIndex + numEvalV + 1 ] );
1338
1339 edgeNormalU [ 2 ].crossProduct ( normal, edge );
1340
1341 orient.calc ( evalPts [ spanEvalIndex + numEvalV ], evalPts [ spanEvalIndex ] );
1342
1343 if ( edgeNormalU [ 2 ].dot ( orient ) < 0.0 ) edgeNormalU [ 2 ] *= - 1.0;
1344
1345 if ( edgeNormalU [ 2 ].dot ( velocityV ) < 0.0 )
1346 {
1347 edgeNormalU [ 2 ].crossProduct ( normal, velocityV );
1348 if ( edgeNormalU [ 2 ].dot ( orient ) < 0.0 ) edgeNormalU [ 2 ] *= - 1.0;
1349 }
1350
1351 edge.calc ( evalPts [ spanEvalIndex + numEvalV ], evalPts [ spanEvalIndex ] );
1352 edgeNormalV [ 2 ].crossProduct ( normal, edge );
1353
1354 orient.calc ( evalPts [ spanEvalIndex + numEvalV ],
1355 evalPts [ spanEvalIndex + numEvalV + 1 ] );
1356
1357 if ( edgeNormalV [ 2 ].dot ( orient ) < 0.0 ) edgeNormalV [ 2 ] *= - 1.0;
1358
1359 if ( edgeNormalV [ 2 ].dot ( velocityU ) < 0.0 )
1360 {
1361 edgeNormalV [ 2 ].crossProduct ( normal, velocityU );
1362 if ( edgeNormalV [ 2 ].dot ( orient ) < 0.0 ) edgeNormalV [ 2 ] *= - 1.0;
1363 }
1364
1365 // Calculate and orient fourth set of edge normals
1366
1367 velocityU.calc ( ctrlPts [ baseIndex + degV ], ctrlPts [ baseIndex + degV - vSize ] );
1368 velocityV.calc ( ctrlPts [ baseIndex + degV ], ctrlPts [ baseIndex + degV - 1 ] );
1369
1370 normal.crossProduct ( velocityU, velocityV );
1371
1372 edge.calc ( evalPts [ spanEvalIndex + numEvalV + 1 ],
1373 evalPts [ spanEvalIndex + numEvalV ] );
1374
1375 edgeNormalU [ 3 ].crossProduct ( normal, edge );
1376
1377 orient.calc ( evalPts [ spanEvalIndex + numEvalV + 1 ], evalPts [ spanEvalIndex + 1 ] );
1378
1379 if ( edgeNormalU [ 3 ].dot ( orient ) < 0.0 ) edgeNormalU [ 3 ] *= - 1.0;
1380
1381 if ( edgeNormalU [ 3 ].dot ( velocityV ) < 0.0 )
1382 {
1383 edgeNormalU [ 3 ].crossProduct ( normal, velocityV );
1384 if ( edgeNormalU [ 3 ].dot ( orient ) < 0.0 ) edgeNormalU [ 3 ] *= - 1.0;
1385 }
1386
1387 edge.calc ( evalPts [ spanEvalIndex + numEvalV + 1 ], evalPts [ spanEvalIndex + 1 ] );
1388 edgeNormalV [ 3 ].crossProduct ( normal, edge );
1389
1390 orient.calc ( evalPts [ spanEvalIndex + numEvalV + 1 ],
1391 evalPts [ spanEvalIndex + numEvalV ] );
1392
1393 if ( edgeNormalV [ 3 ].dot ( orient ) < 0.0 ) edgeNormalV [ 3 ] *= - 1.0;
1394
1395 if ( edgeNormalV [ 3 ].dot ( velocityU ) < 0.0 )
1396 {
1397 edgeNormalV [ 3 ].crossProduct ( normal, velocityU );
1398 if ( edgeNormalV [ 3 ].dot ( orient ) < 0.0 ) edgeNormalV [ 3 ] *= - 1.0;
1399 }
1400
1401 // Step through each given point and check to see if it is probable that it belongs
1402 // to this patch. If it is, create a guess for it.
1403
1404 knot minU = paramU [ spanU ];
1405 knot maxU = paramU [ spanU + 1 ];
1406 knot minV = paramV [ spanV ];
1407 knot maxV = paramV [ spanV + 1 ];
1408
1409 for ( int ptIndex = 0; ptIndex < numPoints; ptIndex ++ )
1410 {
1411 bool withinEdge1_2 = false;
1412 bool withinEdge2_4 = false;
1413 bool withinEdge4_3 = false;
1414 bool withinEdge3_1 = false;
1415
1416 // Corner 1.
1417
1418 orient.calc ( evalPts [ spanEvalIndex ], points [ ptIndex ] );
1419
1420 if ( orient.dot ( edgeNormalU [ 0 ] ) >= 0.0 )
1421 withinEdge1_2 = true;
1422
1423 if ( orient.dot ( edgeNormalV [ 0 ] ) >= 0.0 )
1424 withinEdge3_1 = true;
1425
1426 // Corner 2.
1427
1428 orient.calc ( evalPts [ spanEvalIndex + 1 ], points [ ptIndex ] );
1429
1430 if ( orient.dot ( edgeNormalU [ 1 ] ) >= 0.0 )
1431 withinEdge1_2 = true;
1432
1433 if ( orient.dot ( edgeNormalV [ 1 ] ) >= 0.0 )
1434 withinEdge2_4 = true;
1435
1436 // Corner 3.
1437
1438 orient.calc ( evalPts [ spanEvalIndex + numEvalV ], points [ ptIndex ] );
1439
1440 if ( orient.dot ( edgeNormalU [ 2 ] ) >= 0.0 )
1441 withinEdge4_3 = true;
1442
1443 if ( orient.dot ( edgeNormalV [ 2 ] ) >= 0.0 )
1444 withinEdge3_1 = true;
1445
1446 // Corner 4.
1447
1448 orient.calc ( evalPts [ spanEvalIndex + numEvalV + 1 ], points [ ptIndex ] );
1449
1450 if ( orient.dot ( edgeNormalU [ 3 ] ) >= 0.0 )
1451 withinEdge4_3 = true;
1452
1453 if ( orient.dot ( edgeNormalV [ 3 ] ) >= 0.0 )
1454 withinEdge2_4 = true;
1455
1456 // If point is within all edges then a guess needs to be created.
1457
1458 if ( withinEdge1_2 && withinEdge2_4 && withinEdge4_3 && withinEdge3_1 )
1459 {
1460 snlSurfLocnGuess* newGuess = new snlSurfLocnGuess;
1461
1462 newGuess -> paramU = ( ( maxU - minU ) / 2 ) + minU;
1463 newGuess -> paramV = ( ( maxV - minV ) / 2 ) + minV;
1464 newGuess -> pt = eval ( newGuess -> paramU, newGuess -> paramV );
1465 newGuess -> dist = ( newGuess -> pt ).distSqrd ( points [ ptIndex ] );
1466 newGuess -> origPtIndex = ptIndex;
1467 newGuess -> spanNumber = spanNum;
1468 newGuess -> minU = minU;
1469 newGuess -> maxU= maxU;
1470 newGuess -> minV = minV;
1471 newGuess -> maxV = maxV;
1472 newGuess -> culled = false;
1473 newGuess -> ignoreParamBounds = false;
1474 newGuess -> converged = false;
1475
1476 tmpList -> append ( newGuess, false );
1477
1478 hasGuess [ ptIndex ] = true;
1479 lastGuess [ ptIndex ] = newGuess;
1480 }
1481 }
1482
1483 spanNum ++;
1484
1485 spanEvalIndex ++;
1486 }
1487
1488 spanEvalIndex ++;
1489 }
1490
1491 // If a candidate span is not found for a given point then find closest evaluated point
1492 // but don't impose parametric bounds to the guess.
1493
1494 for ( int ptIndex = 0; ptIndex < numPoints; ptIndex ++ )
1495 {
1496 if ( ! hasGuess [ ptIndex ] )
1497 {
1498 snlSurfLocnGuess* newGuess = new snlSurfLocnGuess;
1499
1500 index = 0;
1501
1502 for ( int indexU = 0; indexU < numEvalU; indexU ++ )
1503 {
1504 for ( int indexV = 0; indexV < numEvalV; indexV ++ )
1505 {
1506 double distSqrd = points [ ptIndex ].distSqrd ( evalPts [ index ] );
1507
1508 if ( ( ! indexU && ! indexV ) || ( newGuess -> dist > distSqrd ) )
1509 {
1510 newGuess -> dist = distSqrd;
1511 newGuess -> paramU = paramU [ indexU ];
1512 newGuess -> paramV = paramV [ indexV ];
1513 newGuess -> pt = evalPts [ index ];
1514 }
1515
1516 index ++;
1517 }
1518 }
1519
1520 // Fill in rest of guess data.
1521
1522 newGuess -> origPtIndex = ptIndex;
1523 newGuess -> culled = false;
1524 newGuess -> ignoreParamBounds = true;
1525 newGuess -> converged = false;
1526
1527 tmpList -> append ( newGuess, false );
1528
1529 lastGuess [ ptIndex ] = newGuess;
1530 }
1531 }
1532
1533 // Build properly ordered return list.
1534
1535 ptrList <snlSurfLocnGuess>* retList = new ptrList <snlSurfLocnGuess>; // List of guesses to
1536 // return.
1537
1538 for ( int ptIndex = 0; ptIndex < numPoints; ptIndex ++ )
1539 {
1540 snlSurfLocnGuess* guess = tmpList -> first();
1541
1542 while ( guess )
1543 {
1544 if ( guess -> origPtIndex == ptIndex )
1545 retList -> append ( guess, true );
1546
1547 guess = tmpList -> next();
1548 }
1549 }
1550
1551 // Clean up and return.
1552
1553 delete[] paramU;
1554 delete[] paramV;
1555
1556 delete[] evalPts;
1557
1558 delete[] edgeNormalU;
1559 delete[] edgeNormalV;
1560
1561 delete[] hasGuess;
1562 delete[] lastGuess;
1563
1564 delete tmpList;
1565
1566 return retList;
1567 }
1568
guessFastProjLocation(snlPoint * points,int numPoints,int numGuessesPerPt,int granU,int granV)1569 ptrList <snlSurfLocnGuess>* snlSurface::guessFastProjLocation ( snlPoint* points, int numPoints, int numGuessesPerPt,
1570 int granU, int granV )
1571 {
1572 //! Guess parametric location of given points.
1573 // ------------------------------------------
1574 //! @param points Array of points to find matches with.
1575 //! @param numPoints Number of points in array.
1576 //! @param numGuessesPerPt Number of guesses to return per point.
1577 //! @param granU Number of guesses per span.
1578 //! @param granV Number of guesses per span.
1579 //!
1580 //! @return List of surface location guess structs. Caller owns this lists.
1581
1582 int index;
1583
1584 int numSpansU = knotVectU -> getNumSpans();
1585 int numSpansV = knotVectV -> getNumSpans();
1586
1587 int numEvalU = granU * numSpansU + 1;
1588 int numEvalV = granV * numSpansV + 1;
1589
1590 // Pre-calculate parametric positions.
1591
1592 knot* paramU = new knot [ numEvalU ];
1593 int* spanU = new int [ numEvalU ];
1594
1595 knot* paramV = new knot [ numEvalV ];
1596 int* spanV = new int [ numEvalV ];
1597
1598 // U direction.
1599
1600 int cSpan = knotVectU -> getFirstSpan();
1601
1602 knot paramStart = knotVectU -> val ( cSpan );
1603
1604 cSpan = knotVectU -> getNextSpan ( cSpan );
1605
1606 knot paramEnd;
1607
1608 if ( cSpan )
1609 paramEnd = knotVectU -> val ( cSpan );
1610 else
1611 paramEnd = knotVectU -> max();
1612
1613
1614 int numSteps;
1615
1616 int paramIndex = 0;
1617
1618 basis param;
1619
1620 for ( int span = 0; span < numSpansU; span ++ )
1621 {
1622 basis paramStep = ( paramEnd - paramStart ) / (double) granU;
1623
1624 param = paramStart;
1625
1626 if ( span )
1627 {
1628 numSteps = granU;
1629 param += paramStep;
1630 }
1631 else
1632 {
1633 numSteps = granU + 1;
1634 }
1635
1636 // Generate params for span.
1637
1638 for ( index = 0; index < numSteps; index ++ )
1639 {
1640 paramU [ paramIndex ] = param;
1641
1642 spanU [ paramIndex ++ ] = span;
1643
1644 param += paramStep;
1645
1646 if ( param > paramEnd ) param = paramEnd; // Round off error trap.
1647 }
1648
1649 paramStart = paramEnd;
1650
1651 cSpan = knotVectU -> getNextSpan ( cSpan );
1652
1653 if ( cSpan )
1654 paramEnd = knotVectU -> val ( cSpan );
1655 else
1656 paramEnd = knotVectU -> max();
1657 }
1658
1659 // V direction.
1660
1661 cSpan = knotVectV -> getFirstSpan();
1662
1663 paramStart = knotVectV -> val ( cSpan );
1664
1665 cSpan = knotVectV -> getNextSpan ( cSpan );
1666
1667 if ( cSpan )
1668 paramEnd = knotVectV -> val ( cSpan );
1669 else
1670 paramEnd = knotVectV -> max();
1671
1672 paramIndex = 0;
1673
1674 for ( int span = 0; span < numSpansV; span ++ )
1675 {
1676 basis paramStep = ( paramEnd - paramStart ) / (double) granV;
1677
1678 param = paramStart;
1679
1680 if ( span )
1681 {
1682 numSteps = granV;
1683 param += paramStep;
1684 }
1685 else
1686 {
1687 numSteps = granV + 1;
1688 }
1689
1690 for ( index = 0; index < numSteps; index ++ )
1691 {
1692 paramV [ paramIndex ] = param;
1693
1694 spanV [ paramIndex ++ ] = span;
1695
1696 param += paramStep;
1697
1698 if ( param > paramEnd ) param = paramEnd; // Round off error trap.
1699 }
1700
1701 paramStart = paramEnd;
1702
1703 cSpan = knotVectV -> getNextSpan ( cSpan );
1704
1705 if ( cSpan )
1706 paramEnd = knotVectV -> val ( cSpan );
1707 else
1708 paramEnd = knotVectV -> max();
1709 }
1710
1711 // Pre-evaluate basis functions.
1712
1713 basis** basisU = new basis* [ numEvalU ];
1714 basis** basisV = new basis* [ numEvalV ];
1715
1716 for ( index = 0; index < numEvalU; index ++ )
1717 basisU [ index ] = knotVectU -> evalBasis ( paramU [ index ] );
1718
1719 for ( index = 0; index < numEvalV; index ++ )
1720 basisV [ index ] = knotVectV -> evalBasis ( paramV [ index ] );
1721
1722 // Evaluate surface points and vectors.
1723
1724 int numEvalPts = numEvalU * numEvalV;
1725
1726 snlPoint* evalPts = new snlPoint [ numEvalPts ];
1727
1728 index = 0;
1729
1730 for ( int indexU = 0; indexU < numEvalU; indexU ++ )
1731 {
1732 for ( int indexV = 0; indexV < numEvalV; indexV ++ )
1733 {
1734 evalPts [ index ] = eval ( paramU [ indexU ], paramV [ indexV ], basisU [ indexU ],
1735 basisV [ indexV ] );
1736
1737 index ++;
1738 }
1739 }
1740
1741 // Compare given points to evaluated points.
1742
1743 int totalNumGuesses = numGuessesPerPt * numPoints;
1744
1745 snlSurfLocnGuess** guesses = new snlSurfLocnGuess* [ totalNumGuesses ];
1746
1747 for ( int guessIndex = 0; guessIndex < totalNumGuesses; guessIndex ++ )
1748 guesses [ guessIndex ] = 0;
1749
1750 index = 0;
1751
1752 for ( int indexU = 0; indexU < numEvalU; indexU ++ )
1753 {
1754 for ( int indexV = 0; indexV < numEvalV; indexV ++ )
1755 {
1756 for ( int ptIndex = 0; ptIndex < numPoints; ptIndex ++ )
1757 {
1758 double distSqrd = evalPts [ index ].distSqrd ( points [ ptIndex ] );
1759
1760 // If no guesses in available guess position then add a new one.
1761
1762 int guessOffset = ptIndex * numGuessesPerPt;
1763
1764 bool guessInserted = false;
1765
1766 for ( int guessIndex = 0; guessIndex < numGuessesPerPt; guessIndex ++ )
1767 {
1768 if ( ! guesses [ guessIndex + guessOffset ] )
1769 {
1770 // Create new guess.
1771
1772 snlSurfLocnGuess* newGuess = new snlSurfLocnGuess;
1773
1774 newGuess -> paramU = paramU [ indexU ];
1775 newGuess -> paramV = paramV [ indexV ];
1776 newGuess -> pt = evalPts [ index ];
1777 newGuess -> dist = distSqrd;
1778 newGuess -> origPtIndex = ptIndex;
1779 newGuess -> spanNumber = - 1;
1780 newGuess -> culled = false;
1781 newGuess -> ignoreParamBounds = true;
1782 newGuess -> converged = false;
1783
1784 guesses [ guessIndex + guessOffset ] = newGuess;
1785
1786 guessInserted = true;
1787
1788 break;
1789 }
1790 }
1791
1792 if ( ! guessInserted )
1793 {
1794 // Find guess with largest distance.
1795
1796 int replaceIndex = guessOffset;
1797 double dist = guesses [ guessOffset ] -> dist;
1798
1799 for ( int guessIndex = 1; guessIndex < numGuessesPerPt; guessIndex ++ )
1800 {
1801 if ( guesses [ guessIndex + guessOffset ] -> dist > dist )
1802 {
1803 replaceIndex = guessIndex + guessOffset;
1804 dist = guesses [ guessIndex + guessOffset ] -> dist;
1805 }
1806 }
1807
1808 if ( dist > distSqrd )
1809 {
1810 // Replace guess.
1811
1812 guesses [ replaceIndex ] -> paramU = paramU [ indexU ];
1813 guesses [ replaceIndex ] -> paramV = paramV [ indexV ];
1814 guesses [ replaceIndex ] -> pt = evalPts [ index ];
1815 guesses [ replaceIndex ] -> dist = distSqrd;
1816 guesses [ replaceIndex ] -> origPtIndex = ptIndex;
1817 }
1818 }
1819 }
1820
1821 index ++;
1822 }
1823 }
1824
1825 // Assemble return list.
1826
1827 ptrList <snlSurfLocnGuess>* retList = new ptrList <snlSurfLocnGuess>; // List of guesses to return.
1828
1829 for ( int guessIndex = 0; guessIndex < totalNumGuesses; guessIndex ++ )
1830 {
1831 if ( guesses [ guessIndex ] )
1832 retList -> append ( guesses [ guessIndex ], true );
1833 }
1834
1835 // Clean up and return.
1836
1837 delete[] evalPts;
1838
1839 delete[] guesses;
1840
1841 delete[] paramU;
1842 delete[] paramV;
1843
1844 delete[] spanU;
1845 delete[] spanV;
1846
1847 for ( int index = 0; index < numEvalU; index ++ )
1848 delete[] basisU [ index ];
1849
1850 for ( int index = 0; index < numEvalV; index ++ )
1851 delete[] basisV [ index ];
1852
1853 delete[] basisU;
1854 delete[] basisV;
1855
1856 return retList;
1857 }
1858
1859 //ptrList <snlSurfLocnGuess>* snlSurface::guessProjLocation_triMethod ( snlPoint* points, int numPoints, bool* pointMask )
1860 //{
1861 // //! Guess parametric location of given points using triangular decomposition.
1862 // // -------------------------------------------------------------------------
1863 // //! @param points Array of points to find matches with.
1864 // //! @param numPoints Number of points in array.
1865 // //! @param pointMask Array specifying which points to process. Corresponding index to points
1866 // //! array. Must be true to process.
1867 // //!
1868 // //! @return List of surface location guess structs. Caller owns this list.
1869 //
1870 //
1871 //
1872 //}
1873
hasAmbigEdges(sEdge * results,double tolerance)1874 int snlSurface::hasAmbigEdges ( sEdge* results, double tolerance )
1875 {
1876 //! See if the surface has ambiguous edges
1877 // --------------------------------------
1878 //! @param results Array of sEdge. Should be size 4.
1879 //! @param tolerance Tolerance of edge detection.
1880 //!
1881 //! @return Number of ambiguous edges.
1882
1883 snlPoint evalPt [ 4 ]; // Current evaled non-homogeneous point.
1884
1885 knot min_u, max_u, min_v, max_v;
1886
1887 min_u = knotVectU -> min();
1888 max_u = knotVectU -> max();
1889 min_v = knotVectV -> min();
1890 max_v = knotVectV -> max();
1891
1892 // Generate points to process.
1893
1894 knot mid_u = ( max_u - min_u ) / 2.0 + min_u;
1895 knot mid_v = ( max_v - min_v ) / 2.0 + min_v;
1896
1897 // Min / Max U
1898
1899 evalPt [ 0 ] = eval ( min_u, mid_v );
1900
1901 evalPt [ 1 ] = eval ( max_u, mid_v );
1902
1903 // Min / Max V
1904
1905 evalPt [ 2 ] = eval ( mid_u, min_v );
1906
1907 evalPt [ 3 ] = eval ( mid_u, max_v );
1908
1909 // Generate initial guesses. 3 Per edge.
1910
1911 ptrList <snlSurfLocnGuess>* guessList = new ptrList <snlSurfLocnGuess>;
1912
1913 snlSurfLocnGuess guessTemplate;
1914 guessTemplate.culled = false;
1915 guessTemplate.ignoreParamBounds = true;
1916 guessTemplate.converged = false;
1917
1918 // Edge: Min U. Eval index 0.
1919
1920 snlSurfLocnGuess* guess;
1921
1922 // Max U.
1923 guess = new snlSurfLocnGuess;
1924 *guess = guessTemplate;
1925 guess -> paramU = max_u;
1926 guess -> paramV = mid_v;
1927 guess -> pt = evalPt [ 1 ];
1928 guess -> dist = evalPt [ 1 ].distSqrd ( evalPt [ 0 ] );
1929 guess -> origPtIndex = 0;
1930 guessList -> append ( guess, true );
1931
1932 // Min V.
1933
1934 guess = new snlSurfLocnGuess;
1935 *guess = guessTemplate;
1936 guess -> paramU = mid_u;
1937 guess -> paramV = min_v;
1938 guess -> pt = evalPt [ 2 ];
1939 guess -> dist = evalPt [ 2 ].distSqrd ( evalPt [ 0 ] );
1940 guess -> origPtIndex = 0;
1941 guessList -> append ( guess, true );
1942
1943 // Max V.
1944
1945 guess = new snlSurfLocnGuess;
1946 *guess = guessTemplate;
1947 guess -> paramU = mid_u;
1948 guess -> paramV = max_v;
1949 guess -> pt = evalPt [ 3 ];
1950 guess -> dist = evalPt [ 3 ].distSqrd ( evalPt [ 0 ] );
1951 guess -> origPtIndex = 0;
1952 guessList -> append ( guess, true );
1953
1954 // Edge: Max U. Eval index 1.
1955
1956 // Min U.
1957
1958 guess = new snlSurfLocnGuess;
1959 *guess = guessTemplate;
1960 guess -> paramU = min_u;
1961 guess -> paramV = mid_v;
1962 guess -> pt = evalPt [ 0 ];
1963 guess -> dist = evalPt [ 0 ].distSqrd ( evalPt [ 1 ] );
1964 guess -> origPtIndex = 1;
1965 guessList -> append ( guess, true );
1966
1967 // Min V.
1968
1969 guess = new snlSurfLocnGuess;
1970 *guess = guessTemplate;
1971 guess -> paramU = mid_u;
1972 guess -> paramV = min_v;
1973 guess -> pt = evalPt [ 2 ];
1974 guess -> dist = evalPt [ 2 ].distSqrd ( evalPt [ 1 ] );
1975 guess -> origPtIndex = 1;
1976 guessList -> append ( guess, true );
1977
1978 // Max V.
1979
1980 guess = new snlSurfLocnGuess;
1981 *guess = guessTemplate;
1982 guess -> paramU = mid_u;
1983 guess -> paramV = max_v;
1984 guess -> pt = evalPt [ 3 ];
1985 guess -> dist = evalPt [ 3 ].distSqrd ( evalPt [ 1 ] );
1986 guess -> origPtIndex = 1;
1987 guessList -> append ( guess, true );
1988
1989 // Edge: Min V. Eval index 2.
1990
1991 // Max V.
1992
1993 guess = new snlSurfLocnGuess;
1994 *guess = guessTemplate;
1995 guess -> paramU = mid_u;
1996 guess -> paramV = max_v;
1997 guess -> pt = evalPt [ 3 ];
1998 guess -> dist = evalPt [ 3 ].distSqrd ( evalPt [ 2 ] );
1999 guess -> origPtIndex = 2;
2000 guessList -> append ( guess, true );
2001
2002 // Min U.
2003
2004 guess = new snlSurfLocnGuess;
2005 *guess = guessTemplate;
2006 guess -> paramU = min_u;
2007 guess -> paramV = mid_v;
2008 guess -> pt = evalPt [ 0 ];
2009 guess -> dist = evalPt [ 0 ].distSqrd ( evalPt [ 2 ] );
2010 guess -> origPtIndex = 2;
2011 guessList -> append ( guess, true );
2012
2013 // Max U.
2014
2015 guess = new snlSurfLocnGuess;
2016 *guess = guessTemplate;
2017 guess -> paramU = max_u;
2018 guess -> paramV = mid_v;
2019 guess -> pt = evalPt [ 1 ];
2020 guess -> dist = evalPt [ 1 ].distSqrd ( evalPt [ 2 ] );
2021 guess -> origPtIndex = 2;
2022 guessList -> append ( guess, true );
2023
2024 // Edge: Max V. Eval index 3.
2025
2026 // Min V.
2027
2028 guess = new snlSurfLocnGuess;
2029 *guess = guessTemplate;
2030 guess -> paramU = mid_u;
2031 guess -> paramV = min_v;
2032 guess -> pt = evalPt [ 2 ];
2033 guess -> dist = evalPt [ 2 ].distSqrd ( evalPt [ 3 ] );
2034 guess -> origPtIndex = 3;
2035 guessList -> append ( guess, true );
2036
2037 // Min U.
2038
2039 guess = new snlSurfLocnGuess;
2040 *guess = guessTemplate;
2041 guess -> paramU = min_u;
2042 guess -> paramV = mid_v;
2043 guess -> pt = evalPt [ 0 ];
2044 guess -> dist = evalPt [ 0 ].distSqrd ( evalPt [ 3 ] );
2045 guess -> origPtIndex = 3;
2046 guessList -> append ( guess, true );
2047
2048 // Max U.
2049
2050 guess = new snlSurfLocnGuess;
2051 *guess = guessTemplate;
2052 guess -> paramU = max_u;
2053 guess -> paramV = mid_v;
2054 guess -> pt = evalPt [ 1 ];
2055 guess -> dist = evalPt [ 1 ].distSqrd ( evalPt [ 3 ] );
2056 guess -> origPtIndex = 3;
2057 guessList -> append ( guess, true );
2058
2059 // Process guesses.
2060
2061 int arraySize;
2062
2063 snlSurfLocn* locns = processGuesses ( evalPt, 4, &arraySize, guessList, tolerance, tolerance,
2064 10, true, true );
2065
2066 // Check for projected points remaining, within tolerance, on their original edge.
2067
2068 bool edgeIsAmbig [ 4 ] = { false, false, false, false };
2069
2070 for ( int index = 0; index < arraySize; index ++ )
2071 {
2072 if ( locns [ index ].dist > tolerance ) continue;
2073
2074 switch ( locns [ index ].origPtIndex )
2075 {
2076 case 0:
2077
2078 // Min U.
2079
2080 if ( locns [ index ].paramU < min_u + tolerance )
2081 edgeIsAmbig [ 0 ] = true;
2082
2083 break;
2084
2085 case 1:
2086
2087 // Max U.
2088
2089 if ( locns [ index ].paramU > max_u - tolerance )
2090 edgeIsAmbig [ 1 ] = true;
2091
2092 break;
2093
2094 case 2:
2095
2096 // Min V.
2097
2098 if ( locns [ index ].paramV < min_v + tolerance )
2099 edgeIsAmbig [ 2 ] = true;
2100
2101 break;
2102
2103 case 3:
2104
2105 // Max V.
2106
2107 if ( locns [ index ].paramV > max_v - tolerance )
2108 edgeIsAmbig [ 3 ] = true;
2109
2110 break;
2111 }
2112 }
2113
2114 int cIndex = 0;
2115 int numAmbig = 0;
2116
2117 // Process ambiguous points to find edges.
2118
2119 if ( edgeIsAmbig [ 0 ] )
2120 {
2121 results [ cIndex ].direction = 0;
2122 results [ cIndex ].pVal = min_u;
2123
2124 numAmbig++;
2125 cIndex++;
2126 }
2127
2128 if ( edgeIsAmbig [ 1 ] )
2129 {
2130 results [ cIndex ].direction = 0;
2131 results [ cIndex ].pVal = max_u;
2132
2133 numAmbig++;
2134 cIndex++;
2135 }
2136
2137 if ( edgeIsAmbig [ 2 ] )
2138 {
2139 results [ cIndex ].direction = 1;
2140 results [ cIndex ].pVal = min_v;
2141
2142 numAmbig++;
2143 cIndex++;
2144 }
2145
2146 if ( edgeIsAmbig [ 3 ] )
2147 {
2148 results [ cIndex ].direction = 1;
2149 results [ cIndex ].pVal = max_v;
2150
2151 numAmbig++;
2152 }
2153
2154 delete[] locns;
2155
2156 return numAmbig;
2157 }
2158
hasAmbigEdges_depr(sEdge * results)2159 int snlSurface::hasAmbigEdges_depr ( sEdge* results )
2160 {
2161 //! See if the surface has ambiguous edges
2162 //! --------------------------------------
2163 //! @param results Array of sEdge. Should be size 4.
2164 //!
2165 //! @return Number of ambiguous edges.
2166 //!
2167 //! Notes: Function is now deprecated.
2168
2169 snlPoint evalPt [ 4 ]; // Current evaled non-homogeneous point.
2170
2171 knot minT, maxT, minU, maxU;
2172
2173 minT = knotVectU -> min();
2174 maxT = knotVectU -> max();
2175 minU = knotVectV -> min();
2176 maxU = knotVectV -> max();
2177
2178 // Min / Max T
2179
2180 evalPt [ 0 ] = eval ( minT, ( ( maxU - minU ) / 2 ) + minU );
2181
2182 evalPt [ 1 ] = eval ( maxT, ( ( maxU - minU ) / 2 ) + minU );
2183
2184 // Min / Max U
2185
2186 evalPt [ 2 ] = eval (( ( maxT - minT ) / 2 ) + minT, minU );
2187
2188 evalPt [ 3 ] = eval (( ( maxT - minT ) / 2 ) + minT, maxU );
2189
2190 // Get projection function to do the work.
2191
2192 ptrList < sLocn >* ambig;
2193
2194 sLocn projns [ 4 ];
2195
2196 ambig = projPtSurf ( *this, evalPt, 4, projns,
2197 0.000001, 0.00001, 3 );
2198
2199 int cIndex = 0;
2200 int numAmbig = 0;
2201
2202 // Process ambiguous points to find edges.
2203
2204 if ( projns [ 0 ].flag > 1 )
2205 {
2206 results [ cIndex ].direction = 0;
2207 results [ cIndex ].pVal = minT;
2208
2209 numAmbig++;
2210 cIndex++;
2211 }
2212
2213 if ( projns [ 1 ].flag > 1 )
2214 {
2215 results [ cIndex ].direction = 0;
2216 results [ cIndex ].pVal = maxT;
2217
2218 numAmbig++;
2219 cIndex++;
2220 }
2221
2222 if ( projns [ 2 ].flag > 1 )
2223 {
2224 results [ cIndex ].direction = 1;
2225 results [ cIndex ].pVal = minU;
2226
2227 numAmbig++;
2228 cIndex++;
2229 }
2230
2231 if ( projns [ 3 ].flag > 1 )
2232 {
2233 results [ cIndex ].direction = 1;
2234 results [ cIndex ].pVal = maxU;
2235
2236 numAmbig++;
2237 }
2238
2239 delete ambig;
2240
2241 return numAmbig;
2242 }
2243
2244