Geant4 9.6.0
Toolkit for the simulation of the passage of particles through matter
All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros
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