Geant4 9.6.0
Toolkit for the simulation of the passage of particles through matter
Loading...
Searching...
No Matches
G4NURBS.cc
Go to the documentation of this file.
1//
2// ********************************************************************
3// * License and Disclaimer *
4// * *
5// * The Geant4 software is copyright of the Copyright Holders of *
6// * the Geant4 Collaboration. It is provided under the terms and *
7// * conditions of the Geant4 Software License, included in the file *
8// * LICENSE and available at http://cern.ch/geant4/license . These *
9// * include a list of copyright holders. *
10// * *
11// * Neither the authors of this software system, nor their employing *
12// * institutes,nor the agencies providing financial support for this *
13// * work make any representation or warranty, express or implied, *
14// * regarding this software system or assume any liability for its *
15// * use. Please see the license in the file LICENSE and URL above *
16// * for the full disclaimer and the limitation of liability. *
17// * *
18// * This code implementation is the result of the scientific and *
19// * technical work of the GEANT4 collaboration. *
20// * By using, copying, modifying or distributing the software (or *
21// * any work based on the software) you agree to acknowledge its *
22// * use in resulting scientific publications, and indicate your *
23// * acceptance of all terms of the Geant4 Software license. *
24// ********************************************************************
25//
26//
27// $Id$
28//
29//
30// Olivier Crumeyrolle 12 September 1996
31
32// G4NURBS.cc
33// Implementation of class G4NURBS
34// OC 100796
35
36
37#include "G4NURBS.hh"
38
39// G4NURBS.hh includes globals.hh which includes a lot of others
40// so no more includes required here
41
42////////////////////////////////////////////////////////////////////////
43// Here start the real world. Please, check your armored jacket. //
44////////////////////////////////////////////////////////////////////////
45
46std::ostream & operator << (std::ostream & inout_outStream,
47 const G4NURBS & in_kNurb)
48{
49 inout_outStream
50 // the magic could be changed for good reasons only
51 << "##ojc{NURBS}def[1.01.96.7] Just a magic. Could be added to /etc/magic"
52 << "\n# NURBS Definition File (human and computer readable format)"
53 << "\n# :" << in_kNurb.Whoami()
54 << "\n# U order\tV order : "
55 << '\n' << in_kNurb.GetUorder() << "\t\t" << in_kNurb.GetVorder();
56 // number of knots and knots themselves for U and V
58 /*(*(G4int *)(&dir))++*/ dir=(G4NURBS::t_direction)(((G4int)(dir))+1) )
59 {
60 inout_outStream
61 << "\n# Number of knots along " << G4NURBS::Tochar(dir)
62 << '\n' << in_kNurb.GetnbrKnots(dir)
63 << "\n# " << G4NURBS::Tochar(dir) << " knots vector (as a column)";
64 { // begin knots iteration
65 G4double oneKnot;
66 G4NURBS::KnotsIterator knotI(in_kNurb,dir);
67 G4bool otherKnots;
68 do
69 {
70 otherKnots = knotI.pick(&oneKnot);
71 inout_outStream << "\n\t\t" << oneKnot;
72 }
73 while (otherKnots);
74 } // end of knots iteration
75 } // end of direction loop
76
77 // number of control points in U and V direction
78 // and controlpoints
79 inout_outStream
80 << "\n# Number of control points along U and V"
81 << '\n' << in_kNurb.GetUnbrCtrlPts()
82 << " " << in_kNurb.GetVnbrCtrlPts()
83 << "\n# Control Points (one by line, U increasing first)";
84 { // begin of control points iteration
86 G4NURBS::CtrlPtsIterator cpI(in_kNurb);
87 G4bool otherCPs;
88 do
89 {
90 otherCPs = cpI.pick(&oneCP);
91 inout_outStream
92 << "\n\t" << oneCP[G4NURBS::X]
93 << "\t" << oneCP[G4NURBS::Y]
94 << "\t" << oneCP[G4NURBS::Z]
95 << "\t" << oneCP[G4NURBS::W];
96 }
97 while (otherCPs);
98 } // end of control point iteration
99
100 inout_outStream << "\n# That's all!"
101 << G4endl; // endl do an \n and a flush
102 return inout_outStream;
103}
104
105// the CC compiler issue some "maybe no value returned"
106// but everything is ok
107
109{
110 in_dir = (t_direction)(in_dir & DMask);
111 if ( in_index < m[in_dir].nbrKnots )
112 return ((G4float)(m[in_dir].pKnots[in_index]));
113 else
114 {
115 G4cerr << "\nERROR: G4NURBS::GetfloatKnot: index out of range\n"
116 << "\n\t in_dir : " << G4int(in_dir)
117 << ", in_index : " << G4int(in_index)
118 << "m[in_dir].nbrKnots : " << m[in_dir].nbrKnots << G4endl;
119 return ((G4float)m[in_dir].pKnots[m[in_dir].nbrKnots-1]);
120 }
121}
122
124{
125 in_dir = (t_direction)(in_dir & DMask);
126 if ( in_index < m[in_dir].nbrKnots )
127 return (G4double)(m[in_dir].pKnots[in_index]);
128 else
129 {
130 G4cerr << "\nERROR: G4NURBS::GetdoubleKnot: index out of range"
131 << "\n\t in_dir : " << G4int(in_dir)
132 << ", in_index : " << G4int(in_index)
133 << "m[in_dir].nbrKnots : " << m[in_dir].nbrKnots
134 << G4endl;
135 return (G4double)(m[in_dir].pKnots[m[in_dir].nbrKnots-1]);
136 }
137}
138
141{
142 if (in_onedimindex < mtotnbrCtrlPts)
143 return TofloatCtrlPt(mpCtrlPts[in_onedimindex]);
144 else
145 {
146 G4cerr << "\nERROR: G4NURBS::GetfloatCtrlPt: index out of range"
147 << "\n\t in_onedimindex : " << in_onedimindex
148 << " , mtotnbrCtrlPts : " << mtotnbrCtrlPts << G4endl;
150 }
151}
152
155{
156 if ( (in_Uindex < m[U].nbrCtrlPts) && (in_Vindex < m[V].nbrCtrlPts) )
157 return TofloatCtrlPt(mpCtrlPts[To1d(in_Uindex, in_Vindex)]);
158 else
159 {
160 G4cerr << "\nERROR: G4NURBS::GetfloatCtrlPt: index(s) out of range"
161 << "\n\t in_Uindex : " << in_Uindex
162 << " , in_Vindex : " << in_Vindex
163 << " , UnbrCtrlPts : " << m[U].nbrCtrlPts
164 << " , VnbrCtrlPts : " << m[V].nbrCtrlPts << G4endl;
166 }
167}
168
171{
172 if ( in_onedimindex < mtotnbrCtrlPts )
173 return TodoubleCtrlPt(mpCtrlPts[in_onedimindex]);
174 else
175 {
176 G4cerr << "\nERROR: G4NURBS::getdoubleCtrlPts: index out of range"
177 << "\n\t in_onedimindex : " << in_onedimindex
178 << " , mtotnbrCtrlPts : " << mtotnbrCtrlPts << G4endl;
180 }
181}
182
185{
186 if ( (in_Uindex < m[U].nbrCtrlPts) && (in_Vindex < m[V].nbrCtrlPts) )
187 return TodoubleCtrlPt(mpCtrlPts[To1d(in_Uindex, in_Vindex)]);
188 else
189 {
190 G4cerr << "\nERROR: G4NURBS::GetdoubleCtrlPt: index(s) out of range"
191 << "\n\t in_Uindex : " << in_Uindex
192 << " , in_Vindex : " << in_Vindex
193 << " , UnbrCtrlPts : " << m[U].nbrCtrlPts
194 << " , VnbrCtrlPts : " << m[V].nbrCtrlPts << G4endl;
196 }
197}
198
199// Total copy
201{
202 in_dir = (t_direction)(in_dir & DMask);
203 G4float * p = new G4float [m[in_dir].nbrKnots];
204 for (t_indKnot i = 0; i < m[in_dir].nbrKnots; i++)
205 p[i] = (G4float)m[in_dir].pKnots[i];
206 return p;
207}
208
210{
211 in_dir = (t_direction)(in_dir & DMask);
212 G4double * p = new G4double [m[in_dir].nbrKnots];
213 for (t_indKnot i = 0; i < m[in_dir].nbrKnots; i++)
214 p[i] = (G4double)m[in_dir].pKnots[i];
215 return p;
216}
217
219{
221 for (t_indKnot i = 0; i < mtotnbrCtrlPts*NofC; i++)
222 p[i] = (G4float)(((t_Coord *)mpCtrlPts)[i]);
223 return p;
224}
225
227{
229 for (t_indKnot i = 0; i < mtotnbrCtrlPts*NofC; i++)
230 p[i] = (G4double)(((t_Coord *)mpCtrlPts)[i]);
231 return p;
232}
233
234// Iterators
235
238 t_indKnot in_startIndex)
239 : kmdir((G4NURBS::t_direction)(in_dir & G4NURBS::DMask)),
240 kmpMax(in_rNurb.m[kmdir].pKnots + in_rNurb.m[kmdir].nbrKnots)
241{
242 if (in_startIndex < in_rNurb.m[kmdir].nbrKnots)
243 mp = in_rNurb.m[kmdir].pKnots + in_startIndex;
244 else
245 {
246 G4cerr << "\nERROR: G4NURBS::KnotsIterator: in_startIndex out of range"
247 << "\n\tin_startIndex : " << in_startIndex
248 << ", nbr of knots : " << in_rNurb.m[kmdir].nbrKnots
249 << "\n\t mp set to NULL, calls to picking functions will fail"
250 << G4endl;
251 mp = 0;
252 }
253}
254
256{
257 (*inout_pDbl) = (G4double)(*mp);
258 return (G4bool)((++mp)<kmpMax);
259}
260
262{
263 (*inout_pFlt) = (G4float)(*mp);
264 return (G4bool)((++mp)<kmpMax);
265}
266
268 t_indCtrlPt in_startCtrlPtIndex)
269 : kmpMax((const t_Coord *)(in_rNurb.mpCtrlPts + in_rNurb.mtotnbrCtrlPts))
270{
271 if (in_startCtrlPtIndex < in_rNurb.mtotnbrCtrlPts )
272 mp = (const t_Coord *)(in_rNurb.mpCtrlPts + in_startCtrlPtIndex);
273 else
274 {
275 G4cerr << "\nERROR: G4NURBS::CtrlPtsCoordsIterator: "
276 << "in_startCtrlPtIndex out of range"
277 << "\n\tin_startCtrlPtIndex : " << in_startCtrlPtIndex
278 << ", nbr of CtrlPts : " << in_rNurb.mtotnbrCtrlPts
279 << "\n\t mp set to NULL, calls to picking functions will fail"
280 << G4endl;
281 mp = 0;
282 }
283}
284
286{
287 (*inout_pDbl) = (G4double)((*mp));
288 return (G4bool)((++mp)<kmpMax);
289}
290
292{
293 (*inout_pFlt) = (G4float)((*mp));
294 return (G4bool)((++mp)<kmpMax);
295}
296
298 t_indCtrlPt in_startIndex)
299 : kmpMax(in_rNurb.mpCtrlPts + in_rNurb.mtotnbrCtrlPts)
300{
301 if (in_startIndex < in_rNurb.mtotnbrCtrlPts )
302 mp = (in_rNurb.mpCtrlPts + in_startIndex);
303 else
304 {
305 G4cerr << "\nERROR: G4NURBS::CtrlPtsIterator: in_startIndex out of range"
306 << "\n\tin_startIndex : " << in_startIndex
307 << ", nbr of CtrlPts : " << in_rNurb.mtotnbrCtrlPts
308 << "\n\t mp set to NULL, calls to picking functions will fail"
309 << G4endl;
310 mp = 0;
311 }
312}
313
315{
316 for (t_indCoord i = G4NURBS::X; i < G4NURBS::NofC; i++)
317 (*inout_pDblCtrlPt)[i] = (G4double)((*mp)[i]);
318 return (G4bool)((++mp)<kmpMax);
319}
320
322{
323 for (t_indCoord i = G4NURBS::X; i < G4NURBS::NofC; i++)
324 (*inout_pFltCtrlPt)[i] = (G4float)((*mp)[i]);
325 return (G4bool)((++mp)<kmpMax);
326}
327
328////////////////////////////////////////////////////////////////////////
329// Building functions
330
332{
333 G4bool isgood = (io_d.order + io_d.nbrCtrlPts == io_d.nbrKnots)
334 && (io_d.pKnots == 0);
335 if ( isgood )
336 {
337 io_d.pKnots = new t_Knot [io_d.nbrKnots];
338 if (in_KVGFlag != UserDefined)
339 { // let's do the knots
340 t_indKnot indKnot = 0;
341 t_index nbrCentralDistinctKnots = io_d.nbrCtrlPts-io_d.order;
342 if ( (nbrCentralDistinctKnots % in_KVGFlag) == 0)
343 {
344 nbrCentralDistinctKnots /= in_KVGFlag;
345 // first and last knots repeated 'order' Times
346 for (t_index i=0; i < io_d.order; indKnot++,i++)
347 {
348 io_d.pKnots[indKnot] = 0;
349 io_d.pKnots[indKnot+io_d.nbrCtrlPts] = 1;
350 }
351
352 t_Knot stepKnot = 1.0/(t_Knot)(nbrCentralDistinctKnots+1);
353 t_Knot valKnot = stepKnot;
354
355 // central knots
356 for (t_indKnot j=0; j<nbrCentralDistinctKnots; valKnot+=stepKnot, j++)
357 {
358 for (t_indKnot k=0; k<t_indKnot(in_KVGFlag); indKnot++, k++)
359 io_d.pKnots[indKnot] = valKnot;
360 }
361 }
362 else isgood = false;
363 } // end of knots making
364 }
365 return isgood;
366}
367
368
369std::ostream & operator << (std::ostream & io_ostr,
371{
372 switch (in_f)
373 {
374 case G4NURBS::UserDefined: io_ostr << "UserDefined"; break;
375 case G4NURBS::Regular: io_ostr << "Regular"; break;
376 case G4NURBS::RegularRep: io_ostr << "RegularRep"; break;
377 default: io_ostr << (G4int)in_f;
378 }
379 return io_ostr;
380}
381
382////////////////////////////////////////////////////////////////////////
383// Constructors and co
384
385void G4NURBS::Conscheck() const
386{
387 G4int dummy;
388 t_direction dir;
389 for (dummy=0; (dummy?(dir=V):(dir=U)),(dummy < NofD); dummy++)
390 {
391 if (m[dir].order<=0)
392 {
394 ed << "The order in the "
395 << G4NURBS::Tochar(dir)
396 << " direction must be >= 1" << G4endl;
397 G4Exception("G4NURBS::Conscheck()",
398 "greps9001", FatalException, ed);
399 }
400 if (m[dir].nbrCtrlPts<=0)
401 {
403 ed << "The number of control points "
404 << G4NURBS::Tochar(dir)
405 << " direction must be >= 1" << G4endl;
406 G4Exception("G4NURBS::Conscheck()",
407 "greps9002", FatalException, ed);
408 }
409 } // end of dummy
410}
411
412G4NURBS::G4NURBS ( t_order in_Uorder, t_order in_Vorder,
413 t_inddCtrlPt in_UnbrCtrlPts, t_inddCtrlPt in_VnbrCtrlPts,
414 t_CtrlPt * in_pCtrlPts,
415 t_Knot * in_pUKnots, t_Knot * in_pVKnots,
416 t_CheckFlag in_CheckFlag )
417{
418 m[U].order=in_Uorder; m[V].order=in_Vorder;
419 m[U].nbrCtrlPts=in_UnbrCtrlPts; m[V].nbrCtrlPts=in_VnbrCtrlPts;
420
422 m[U].nbrKnots = m[U].order + m[U].nbrCtrlPts;
423 m[V].nbrKnots = m[V].order + m[V].nbrCtrlPts;
424
425 if (in_CheckFlag)
426 Conscheck();
427
428 // CtrlPts
429 if (! (mpCtrlPts = in_pCtrlPts) )
430 {
432 ed << "A NURBS MUST HAVE CONTROL POINTS!\n"
433 << "\teven if they are defined later, the array must be allocated."
434 << G4endl;
435 G4Exception("G4NURBS::G4NURBS()",
436 "greps9003", FatalException, ed);
437 }
438 //mnbralias = 0;
439
440 // Knots
441 t_direction dir;
442 G4int dummy;
443 for (dummy=0; (dummy?(dir=V):(dir=U)),(dummy < NofD); dummy++)
444 {
445 if ( !(m[dir].pKnots = (dummy?in_pVKnots:in_pUKnots)) )
446 { // make some regular knots between 0 & 1
447 if(!MakeKnotVector(m[dir], Regular))
448 {
450 ed << "Unable to make a Regular knot vector along "
451 << G4NURBS::Tochar(dir)
452 << " direction."
453 << G4endl;
454 G4Exception("G4NURBS::G4NURBS()",
455 "greps9004", FatalException, ed);
456 }
457 //m[dir].nbralias = 0;
458 } // end of knots-making
459 } // end for dummy
460} // end of G4NURBS::G4NURBS
461
462// second constructor
463
464G4NURBS::G4NURBS( t_order in_Uorder, t_order in_Vorder,
465 t_inddCtrlPt in_UnbrCtrlPts, t_inddCtrlPt in_VnbrCtrlPts,
466 t_KnotVectorGenFlag in_UKVGFlag,
467 t_KnotVectorGenFlag in_VKVGFlag,
468 t_CheckFlag in_CheckFlag )
469{
470 m[U].order=in_Uorder; m[V].order=in_Vorder;
471 m[U].nbrCtrlPts=in_UnbrCtrlPts; m[V].nbrCtrlPts=in_VnbrCtrlPts;
472
474 m[U].nbrKnots = m[U].order + m[U].nbrCtrlPts;
475 m[V].nbrKnots = m[V].order + m[V].nbrCtrlPts;
476
477 if (in_CheckFlag)
478 Conscheck();
479
480 // Allocate CtrlPts
482 //mnbralias = 0;
483
484 // Knots
485 t_direction dir;
486 G4int dummy;
487 for (dummy=0; (dummy?(dir=V):(dir=U)),(dummy < NofD); dummy++)
488 {
489 t_KnotVectorGenFlag flag = (dummy?in_VKVGFlag:in_UKVGFlag);
490 m[dir].pKnots = 0; // (allocation under our control)
491 if ( flag != UserDefined && !MakeKnotVector(m[dir], flag) )
492 {
494 ed << "Unable to make knot vector along "
495 << G4NURBS::Tochar(dir)
496 << " direction. (" << m[dir].nbrKnots
497 << " knots requested for a "
498 << flag
499 << " knots vector)"
500 << G4endl;
501 G4Exception("G4NURBS::G4NURBS()",
502 "greps9005", FatalException, ed);
503 }
504 //m[dir].nbralias = 0;
505 }
506}
507
508G4NURBS::G4NURBS(const G4NURBS & in_krNurb)
509 : G4Visible(in_krNurb)
510{
511 // we assume the in nurbs is ok
512
513 // the number of CtrlPts can be copied straightly
514 mtotnbrCtrlPts = in_krNurb.mtotnbrCtrlPts;
515
516 // the main datas
517
518 // but as m is an array of t_Dir and as t_Dir
519 // is just a structure and not a class with a copy cons
520 // whe need to duplicate the knots
521 t_direction dir;
522 G4int dummy;
523 for (dummy=0; (dummy?(dir=V):(dir=U)),(dummy < NofD); dummy++)
524 {
525 // first we do a 'stupid' copy of m[dir]
526 m[dir] = in_krNurb.m[dir];
527 // but as m is an array of t_Dir and as t_Dir
528 // is just a structure and not a class with a copy cons
529 // whe need to duplicate the knots
530 m[dir].pKnots = new G4double [m[dir].nbrKnots];
531 // we copy the knots with memcpy. This function should be the fastest
532 memcpy(m[dir].pKnots, in_krNurb.m[dir].pKnots,
533 m[dir].nbrKnots * sizeof(G4double));
534 } // end of dummy loop
535
536 // the control points
537 // once again we need to do the copy
539 memcpy(mpCtrlPts, in_krNurb.mpCtrlPts, mtotnbrCtrlPts*sizeof(t_CtrlPt));
540
541 // and as it's very strange to copy a nurbs in G4
542 // we issue a warning :
543 G4cerr << "\nWARNING: G4NURBS::G4NURBS(const G4NURBS &) used" << G4endl;
544}
545
547{
548 // we must free the two knots vector
549 t_direction dir;
550 G4int dummy;
551 for (dummy=0; (dummy?(dir=V):(dir=U)),(dummy < NofD); dummy++)
552 {
553 if (m[dir].pKnots)
554 delete m[dir].pKnots; // [m[dir].nbrKnots] if t_Knot become a class
555 m[dir].pKnots = 0;
556 }
557 // now we free the CtrlPts array
558 if (mpCtrlPts)
559 delete [] mpCtrlPts; // [mtotnbrCtrlPts] if t_CtrlPt become a class
560 mpCtrlPts = 0;
561}
562
563/************************************************************************
564 * *
565 * Return the current knot the parameter u is less than or equal to. *
566 * Find this "breakpoint" allows the evaluation routines to concentrate *
567 * on only those control points actually effecting the curve around u.] *
568 * *
569 * np is the number of points on the curve (or surface direction) *
570 * k is the order of the curve (or surface direction) *
571 * kv is the knot vector ([0..np+k-1]) to find the break point in. *
572 * *
573 ************************************************************************/
574static G4int FindBreakPoint(G4double u, const Float *kv, G4int np, G4int k)
575{
576 G4int i;
577 if (u == kv[np+1]) return np; /* Special case for closed interval */
578 i = np + k;
579 while ((u < kv[i]) && (i > 0)) i--;
580 return(i);
581}
582
583/************************************************************************
584 * *
585 * Compute Bi,k(u), for i = 0..k. *
586 * u the parameter of the spline to find the basis functions for*
587 * brkPoint the start of the knot interval ("segment") *
588 * kv the knot vector *
589 * k the order of the curve *
590 * bvals the array of returned basis values. *
591 * *
592 * (From Bartels, Beatty & Barsky, p.387) *
593 * *
594 ************************************************************************/
595static void BasisFunctions(G4double u, G4int brkPoint,
596 const Float *kv, G4int k, G4double *bvals)
597{
598 G4int r, q, i;
599 G4double omega;
600
601 bvals[0] = 1.0;
602 for (r=2; r <= k; r++)
603 {
604 i = brkPoint - r + 1;
605 bvals[r-1] = 0.0;
606 for (q=r-2; q >= 0; q--)
607 {
608 i++;
609 if (i < 0)
610 {
611 omega = 0.0;
612 }
613 else
614 {
615 omega = (u - kv[i]) / (kv[i+r-1] - kv[i]);
616 }
617 bvals[q+1] = bvals[q+1] + (1.0-omega) * bvals[q];
618 bvals[q] = omega * bvals[q];
619 }
620 }
621}
622
623/************************************************************************
624 * *
625 * Compute derivatives of the basis functions Bi,k(u)' *
626 * *
627 ************************************************************************/
628static void BasisDerivatives(G4double u, G4int brkPoint,
629 const Float *kv, G4int k, G4double *dvals)
630{
631 G4int q, i;
632 G4double omega, knotScale;
633
634 BasisFunctions(u, brkPoint, kv, k-1, dvals);
635
636 dvals[k-1] = 0.0; /* BasisFunctions misses this */
637
638 knotScale = kv[brkPoint+1] - kv[brkPoint];
639
640 i = brkPoint - k + 1;
641 for (q=k-2; q >= 0; q--)
642 {
643 i++;
644 omega = knotScale * ((G4double)(k-1)) / (kv[i+k-1] - kv[i]);
645 dvals[q+1] += -omega * dvals[q];
646 dvals[q] *= omega;
647 }
648}
649
650/***********************************************************************
651 * *
652 * Calculate a point p on NurbSurface n at a specific u, v *
653 * using the tensor product. *
654 * *
655 * Note the valid parameter range for u and v is *
656 * (kvU[orderU] <= u < kvU[numU), (kvV[orderV] <= v < kvV[numV]) *
657 * *
658 ***********************************************************************/
660 G4Vector3D &utan, G4Vector3D &vtan) const
661{
662#define MAXORDER 50
663 struct Point4
664 {
665 G4double x, y, z, w;
666 };
667
668 G4int i, j, ri, rj;
669 G4int ubrkPoint, ufirst;
670 G4double bu[MAXORDER], buprime[MAXORDER];
671 G4int vbrkPoint, vfirst;
672 G4double bv[MAXORDER], bvprime[MAXORDER];
673 Point4 r, rutan, rvtan;
674
675 r.x = 0.0; r.y = 0.0; r.z = 0.0; r.w = 0.0;
676 rutan = r; rvtan = r;
677
678 G4int numU = GetUnbrCtrlPts();
679 G4int numV = GetVnbrCtrlPts();
680 G4int orderU = GetUorder();
681 G4int orderV = GetVorder();
682
683 /* Evaluate non-uniform basis functions (and derivatives) */
684
685 ubrkPoint = FindBreakPoint(u, m[U].pKnots, numU-1, orderU);
686 ufirst = ubrkPoint - orderU + 1;
687 BasisFunctions (u, ubrkPoint, m[U].pKnots, orderU, bu);
688 BasisDerivatives(u, ubrkPoint, m[U].pKnots, orderU, buprime);
689
690 vbrkPoint = FindBreakPoint(v, m[V].pKnots, numV-1, orderV);
691 vfirst = vbrkPoint - orderV + 1;
692 BasisFunctions (v, vbrkPoint, m[V].pKnots, orderV, bv);
693 BasisDerivatives(v, vbrkPoint, m[V].pKnots, orderV, bvprime);
694
695 /* Weight control points against the basis functions */
696
697 t_doubleCtrlPt *cpoint;
698 Point4 cp;
699 G4double tmp;
700
701 for (i=0; i<orderV; i++)
702 {
703 for (j=0; j<orderU; j++)
704 {
705 ri = orderV - 1 - i;
706 rj = orderU - 1 - j;
707
708 tmp = bu[rj] * bv[ri];
709
710 cpoint = GetdoubleCtrlPt(j+ufirst, i+vfirst);
711 cp.x = *cpoint[G4NURBS::X];
712 cp.y = *cpoint[G4NURBS::Y];
713 cp.z = *cpoint[G4NURBS::Z];
714 cp.w = *cpoint[G4NURBS::W];
715 delete [] cpoint;
716
717 r.x += cp.x * tmp;
718 r.y += cp.y * tmp;
719 r.z += cp.z * tmp;
720 r.w += cp.w * tmp;
721
722 tmp = buprime[rj] * bv[ri];
723 rutan.x += cp.x * tmp;
724 rutan.y += cp.y * tmp;
725 rutan.z += cp.z * tmp;
726 rutan.w += cp.w * tmp;
727
728 tmp = bu[rj] * bvprime[ri];
729 rvtan.x += cp.x * tmp;
730 rvtan.y += cp.y * tmp;
731 rvtan.z += cp.z * tmp;
732 rvtan.w += cp.w * tmp;
733 }
734 }
735
736 /* Project tangents, using the quotient rule for differentiation */
737
738 G4double wsqrdiv = 1.0 / (r.w * r.w);
739
740 utan.setX((r.w * rutan.x - rutan.w * r.x) * wsqrdiv);
741 utan.setY((r.w * rutan.y - rutan.w * r.y) * wsqrdiv);
742 utan.setZ((r.w * rutan.z - rutan.w * r.z) * wsqrdiv);
743
744 vtan.setX((r.w * rvtan.x - rvtan.w * r.x) * wsqrdiv);
745 vtan.setY((r.w * rvtan.y - rvtan.w * r.y) * wsqrdiv);
746 vtan.setZ((r.w * rvtan.z - rvtan.w * r.z) * wsqrdiv);
747
748 p.setX(r.x / r.w);
749 p.setY(r.y / r.w);
750 p.setZ(r.z / r.w);
751}
@ FatalException
std::ostream & operator<<(std::ostream &inout_outStream, const G4NURBS &in_kNurb)
Definition: G4NURBS.cc:46
#define MAXORDER
double G4double
Definition: G4Types.hh:64
float G4float
Definition: G4Types.hh:65
int G4int
Definition: G4Types.hh:66
bool G4bool
Definition: G4Types.hh:67
#define G4endl
Definition: G4ios.hh:52
G4DLLIMPORT std::ostream G4cerr
CtrlPtsCoordsIterator(const G4NURBS &in_rNurb, t_indCtrlPt in_startCtrlPtIndex=0)
Definition: G4NURBS.cc:267
G4bool pick(G4double *inout_pDbl)
Definition: G4NURBS.cc:285
G4bool pick(t_doubleCtrlPt *inout_pDblCtrlPt)
Definition: G4NURBS.cc:314
const t_CtrlPt * mp
Definition: G4NURBS.hh:262
CtrlPtsIterator(const G4NURBS &in_rNurb, t_indCtrlPt in_startIndex=0)
Definition: G4NURBS.cc:297
const t_Knot * mp
Definition: G4NURBS.hh:224
KnotsIterator(const G4NURBS &in_rNurb, t_direction in_dir, t_indKnot in_startIndex=0)
Definition: G4NURBS.cc:236
G4bool pick(G4double *inout_pDbl)
Definition: G4NURBS.cc:255
const t_direction kmdir
Definition: G4NURBS.hh:222
G4double * GetdoubleAllKnots(t_direction in_dir) const
Definition: G4NURBS.cc:209
t_floatCtrlPt * GetfloatCtrlPt(t_indCtrlPt in_onedimindex) const
Definition: G4NURBS.cc:140
unsigned int t_indCoord
Definition: G4NURBS.hh:90
G4double t_doubleCtrlPt[NofC]
Definition: G4NURBS.hh:110
t_Coord t_CtrlPt[NofC]
Definition: G4NURBS.hh:182
t_CtrlPt * mpCtrlPts
Definition: G4NURBS.hh:350
static char Tochar(t_direction in_dir)
Definition: G4NURBS.hh:467
static G4bool MakeKnotVector(t_Dir &inout_dirdat, t_KnotVectorGenFlag in_KVGFlag)
Definition: G4NURBS.cc:331
t_indCtrlPt mtotnbrCtrlPts
Definition: G4NURBS.hh:349
t_CheckFlag
Definition: G4NURBS.hh:280
G4int GetnbrKnots(t_direction in_dir) const
Definition: G4NURBS.hh:459
friend std::ostream & operator<<(std::ostream &inout_OutStream, t_KnotVectorGenFlag in_KVGFlag)
Definition: G4NURBS.cc:369
G4double * GetdoubleAllCtrlPts() const
Definition: G4NURBS.cc:226
G4float * GetfloatAllCtrlPts() const
Definition: G4NURBS.cc:218
t_index t_indKnot
Definition: G4NURBS.hh:87
G4Float t_Knot
Definition: G4NURBS.hh:176
static t_doubleCtrlPt * TodoubleCtrlPt(const t_CtrlPt &)
Definition: G4NURBS.hh:498
G4NURBS(t_order in_Uorder, t_order in_Vorder, t_inddCtrlPt in_UnbrCtrlPts, t_inddCtrlPt in_VnbrCtrlPts, t_CtrlPt *in_pCtrlPts, t_Knot *in_pUKnots=0, t_Knot *in_pVKnots=0, t_CheckFlag in_CheckFlag=check)
Definition: G4NURBS.cc:412
G4double GetdoubleKnot(t_direction in_dir, t_indKnot in_index) const
Definition: G4NURBS.cc:123
G4float t_floatCtrlPt[NofC]
Definition: G4NURBS.hh:111
@ NofC
Definition: G4NURBS.hh:106
G4float GetfloatKnot(t_direction in_dir, t_indKnot in_index) const
Definition: G4NURBS.cc:108
virtual ~G4NURBS()
Definition: G4NURBS.cc:546
G4int GetUorder() const
Definition: G4NURBS.hh:431
G4int GetVorder() const
Definition: G4NURBS.hh:432
virtual const char * Whoami() const =0
t_doubleCtrlPt * GetdoubleCtrlPt(t_indCtrlPt in_onedimindex) const
Definition: G4NURBS.cc:170
unsigned int t_indCtrlPt
Definition: G4NURBS.hh:91
G4Float t_Coord
Definition: G4NURBS.hh:181
t_KnotVectorGenFlag
Definition: G4NURBS.hh:320
@ Regular
Definition: G4NURBS.hh:324
@ UserDefined
Definition: G4NURBS.hh:321
@ RegularRep
Definition: G4NURBS.hh:328
G4int GetUnbrCtrlPts() const
Definition: G4NURBS.hh:435
t_index t_inddCtrlPt
Definition: G4NURBS.hh:92
G4int GetVnbrCtrlPts() const
Definition: G4NURBS.hh:436
t_index t_order
Definition: G4NURBS.hh:173
static t_floatCtrlPt * TofloatCtrlPt(const t_CtrlPt &)
Definition: G4NURBS.hh:488
t_Dir m[NofD]
Definition: G4NURBS.hh:348
void CalcPoint(G4double u, G4double v, G4Point3D &p, G4Vector3D &utan, G4Vector3D &vtan) const
Definition: G4NURBS.cc:659
t_direction
Definition: G4NURBS.hh:72
@ NofD
Definition: G4NURBS.hh:76
@ DMask
Definition: G4NURBS.hh:75
t_indCtrlPt To1d(t_inddCtrlPt in_Uindex, t_inddCtrlPt in_Vindex) const
Definition: G4NURBS.hh:481
G4float * GetfloatAllKnots(t_direction in_dir) const
Definition: G4NURBS.cc:200
unsigned int t_index
Definition: G4NURBS.hh:84
void G4Exception(const char *originOfException, const char *exceptionCode, G4ExceptionSeverity severity, const char *comments)
Definition: G4Exception.cc:41
std::ostringstream G4ExceptionDescription
Definition: globals.hh:76
t_indKnot nbrKnots
Definition: G4NURBS.hh:274
t_inddCtrlPt nbrCtrlPts
Definition: G4NURBS.hh:273
t_Knot * pKnots
Definition: G4NURBS.hh:275
t_order order
Definition: G4NURBS.hh:272
double Float
Definition: templates.hh:66
#define const
Definition: zconf.h:118