Geant4 11.1.1
Toolkit for the simulation of the passage of particles through matter
All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
SoTubs.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//
28//
29/*-----------------------------HEPVis---------------------------------------*/
30/* */
31/* Node: SoTubs */
32/* Description: Represents the G4Tubs Geant Geometry entity */
33/* Author: Joe Boudreau Nov 11 1996 */
34/* */
35/*--------------------------------------------------------------------------*/
36
37// this :
38#include "HEPVis/nodes/SoTubs.h"
39
40#include <assert.h>
41#include <cmath>
42
43#include <Inventor/SbBox.h>
44#include <Inventor/actions/SoGLRenderAction.h>
45#include <Inventor/fields/SoSFFloat.h>
46#include <Inventor/misc/SoChildList.h>
47#include <Inventor/nodes/SoSeparator.h>
48#include <Inventor/nodes/SoIndexedFaceSet.h>
49#include <Inventor/nodes/SoNormal.h>
50#include <Inventor/nodes/SoCoordinate3.h>
51#include <Inventor/nodes/SoNormalBinding.h>
52#include <Inventor/SoPrimitiveVertex.h>
53#include <Inventor/elements/SoTextureCoordinateElement.h>
54
55#include "HEPVis/SbMath.h"
56
57// This statement is required
58SO_NODE_SOURCE(SoTubs)
59
60// Constructor
62
63
64 // This statement is required
65 SO_NODE_CONSTRUCTOR(SoTubs);
66
67 // Data fields are initialized like this:
68 SO_NODE_ADD_FIELD(pRMin, (0));
69 SO_NODE_ADD_FIELD(pRMax, (1));
70 SO_NODE_ADD_FIELD(pDz, (10));
71 SO_NODE_ADD_FIELD(pSPhi, (0));
72 SO_NODE_ADD_FIELD(pDPhi, ((float)(2*M_PI)));
73 SO_NODE_ADD_FIELD(alternateRep, (NULL));
74 children = new SoChildList(this);
75}
76
77// Destructor
79 delete children;
80}
81
82
83// initClass
85 // This statement is required.
86 static bool first = true;
87 if (first) {
88 first = false;
89 SO_NODE_INIT_CLASS(SoTubs,SoShape,"Shape");
90 }
91}
92
93// generatePrimitives
94void SoTubs::generatePrimitives(SoAction *action) {
95 // This variable is used to store each vertex
96 SoPrimitiveVertex pv;
97
98 // Access the stat from the action
99 SoState *state = action->getState();
100
101 // See if we have to use a texture coordinate function,
102 // rather than generating explicit texture coordinates.
103 SbBool useTexFunction=
104 (SoTextureCoordinateElement::getType(state) ==
105 SoTextureCoordinateElement::FUNCTION);
106
107 // If we need to generate texture coordinates with a function,
108 // we'll need an SoGLTextureCoordinateElement. Otherwise, we'll
109 // set up the coordinates directly.
110 const SoTextureCoordinateElement* tce = NULL;
111 SbVec4f texCoord;
112 if (useTexFunction) {
113 tce = SoTextureCoordinateElement::getInstance(state);
114 }
115 else {
116 texCoord[2] = 0.0;
117 texCoord[3] = 1.0;
118 }
119 SbVec3f point, normal;
120
121
122 ///////////////////////////////////////////////////////
123 //-----------------------------------------------------
124#define GEN_VERTEX(pv,x,y,z,s,t,nx,ny,nz) \
125 point.setValue((float)(x),(float)(y),(float)(z)); \
126 normal.setValue((float)(nx),(float)(ny),(float)(nz)); \
127 if (useTexFunction) { \
128 texCoord=tce->get(point,normal); \
129 } else { \
130 texCoord[0]=(float)(s); \
131 texCoord[1]=(float)(t); \
132 } \
133 pv.setPoint(point); \
134 pv.setNormal(normal); \
135 pv.setTextureCoords(texCoord); \
136 shapeVertex(&pv);
137 //-----------------------------------------------------
138 ///////////////////////////////////////////////////////
139
140 int NPHI = (int)(2+22*std::fabs(pDPhi.getValue()/(2.0*M_PI)));
141 double deltaPhi = pDPhi.getValue()/NPHI, phi0 = pSPhi.getValue(),phi1=phi0+pDPhi.getValue();
142 double rMax=pRMax.getValue(),rMin=pRMin.getValue();
143 double zMax=pDz.getValue(),zMin=-zMax;
144 double cosPhi0=std::cos(phi0), sinPhi0=std::sin(phi0);
145 double cosPhi1=std::cos(phi1), sinPhi1=std::sin(phi1);
146 double cosDeltaPhi=std::cos(deltaPhi),sinDeltaPhi=std::sin(deltaPhi);
147 //
148 // The outer surface!
149 //
150 int i;
151 double sinPhi,cosPhi;
152 beginShape(action,TRIANGLE_STRIP);
153 sinPhi=sinPhi0;
154 cosPhi=cosPhi0;
155 for (i = 0; i<=NPHI; i++) {
156 GEN_VERTEX(pv,rMax*cosPhi,rMax*sinPhi,zMax,0.0,0.0,cosPhi,sinPhi,0);
157 GEN_VERTEX(pv,rMax*cosPhi,rMax*sinPhi,zMin,1.0,1.0,cosPhi,sinPhi,0);
158 inc(sinPhi, cosPhi, sinDeltaPhi, cosDeltaPhi);
159 }
160 endShape();
161 //
162 // The inner surface!
163 //
164 if(rMin!=0.F) {
165 beginShape(action,TRIANGLE_STRIP);
166 sinPhi=sinPhi0;
167 cosPhi=cosPhi0;
168 for (i = 0; i<=NPHI; i++) {
169 GEN_VERTEX(pv,rMin*cosPhi,rMin*sinPhi,zMax,0.0,0.0,-cosPhi,-sinPhi,0);
170 GEN_VERTEX(pv,rMin*cosPhi,rMin*sinPhi,zMin,1.0,1.0,-cosPhi,-sinPhi,0);
171 inc(sinPhi, cosPhi, sinDeltaPhi, cosDeltaPhi);
172 }
173 endShape();
174 }
175 if (std::fabs(deltaPhi)<2.0*M_PI) {
176 //
177 // The end
178 //
179 beginShape(action,TRIANGLE_STRIP);
180 sinPhi=sinPhi0;
181 cosPhi=cosPhi0;
182 GEN_VERTEX(pv,rMax*cosPhi,rMax*sinPhi,zMax,0.0,0.0,sinPhi,-cosPhi,0);
183 GEN_VERTEX(pv,rMax*cosPhi,rMax*sinPhi,zMin,1.0,1.0,sinPhi,-cosPhi,0);
184 GEN_VERTEX(pv,rMin*cosPhi,rMin*sinPhi,zMax,1.0,0.0,sinPhi,-cosPhi,0);
185 GEN_VERTEX(pv,rMin*cosPhi,rMin*sinPhi,zMin,0.0,1.0,sinPhi,-cosPhi,0);
186 endShape();
187 //
188 // The other end
189 //
190 beginShape(action,TRIANGLE_STRIP);
191 sinPhi=sinPhi1;
192 cosPhi=cosPhi1;
193 GEN_VERTEX(pv,rMax*cosPhi,rMax*sinPhi, zMax,0.0,0.0,-sinPhi,+cosPhi,0);
194 GEN_VERTEX(pv,rMax*cosPhi,rMax*sinPhi, zMin,1.0,1.0,-sinPhi,+cosPhi,0);
195 GEN_VERTEX(pv,rMin*cosPhi,rMin*sinPhi, zMax,1.0,0.0,-sinPhi,+cosPhi,0);
196 GEN_VERTEX(pv,rMin*cosPhi,rMin*sinPhi, zMin,0.0,1.0,-sinPhi,+cosPhi,0);
197 endShape();
198 }
199 //
200 // The outer surface at z=+PDZ
201 //
202 if(rMin==0.F) {
203 beginShape(action,TRIANGLE_FAN);
204 sinPhi=sinPhi0;
205 cosPhi=cosPhi0;
206 GEN_VERTEX(pv,0,0,zMax,0.0,0.0,0,0,1);
207 for (i = 0; i<=NPHI; i++) {
208 GEN_VERTEX(pv,rMax*cosPhi,rMax*sinPhi,zMax,1.0,1.0,0,0,1);
209 inc(sinPhi, cosPhi, sinDeltaPhi, cosDeltaPhi);
210 }
211 endShape();
212 //
213 // The outer surface at z=-PDZ
214 //
215 beginShape(action,TRIANGLE_FAN);
216 sinPhi=sinPhi0;
217 cosPhi=cosPhi0;
218 GEN_VERTEX(pv,0,0,zMin,0.0,0.0,0,0,-1);
219 for (i = 0; i<=NPHI; i++) {
220 GEN_VERTEX(pv,rMax*cosPhi,rMax*sinPhi,zMin,1.0,1.0,0,0,-1);
221 inc(sinPhi, cosPhi, sinDeltaPhi, cosDeltaPhi);
222 }
223 endShape();
224 } else {
225 beginShape(action,TRIANGLE_STRIP);
226 sinPhi=sinPhi0;
227 cosPhi=cosPhi0;
228 for (i = 0; i<=NPHI; i++) {
229 GEN_VERTEX(pv,rMin*cosPhi,rMin*sinPhi,zMax,0.0,0.0,0,0,1);
230 GEN_VERTEX(pv,rMax*cosPhi,rMax*sinPhi,zMax,1.0,1.0,0,0,1);
231 inc(sinPhi, cosPhi, sinDeltaPhi, cosDeltaPhi);
232 }
233 endShape();
234 //
235 // The outer surface at z=-PDZ
236 //
237 beginShape(action,TRIANGLE_STRIP);
238 sinPhi=sinPhi0;
239 cosPhi=cosPhi0;
240 for (i = 0; i<=NPHI; i++) {
241 GEN_VERTEX(pv,rMin*cosPhi,rMin*sinPhi,zMin,0.0,0.0,0,0,-1);
242 GEN_VERTEX(pv,rMax*cosPhi,rMax*sinPhi,zMin,1.0,1.0,0,0,-1);
243 inc(sinPhi, cosPhi, sinDeltaPhi, cosDeltaPhi);
244 }
245 endShape();
246 }
247}
248
249// getChildren
250SoChildList *SoTubs::getChildren() const {
251 return children;
252}
253
254
255// computeBBox
256void SoTubs::computeBBox(SoAction *, SbBox3f &box, SbVec3f &center ){
257 SbVec3f vmin(-pRMax.getValue(),-pRMax.getValue(),-pDz.getValue()),
258 vmax( pRMax.getValue(), pRMax.getValue(), pDz.getValue());
259 center.setValue(0,0,0);
260 box.setBounds(vmin,vmax);
261}
262
263
264// updateChildren
265void SoTubs::updateChildren() {
266
267 // Redraw the G4Tubs....
268
269 assert(children->getLength()==1);
270 SoSeparator *sep = (SoSeparator *) ( *children)[0];
271 SoCoordinate3 *theCoordinates = (SoCoordinate3 *) ( sep->getChild(0));
272 SoNormal *theNormals = (SoNormal *) ( sep->getChild(1));
273 SoNormalBinding *theNormalBinding = (SoNormalBinding *) ( sep->getChild(2));
274 SoIndexedFaceSet *theFaceSet = (SoIndexedFaceSet *) ( sep->getChild(3));
275
276
277 const int NPHI=24, NPOINTS=2*(2*NPHI+2), NFACES=4*NPHI+2, NINDICES = NFACES*5;
278 float points[NPOINTS][3],normals[NFACES][3];
279#ifdef INVENTOR2_0
280 static long indices[NINDICES];
281#else
282 static int32_t indices[NINDICES];
283#endif
284
285 static int init=0;
286 double phi, pp, DeltaPhi;
287
288 // Indices need to be generated once! This is here to keep it close to the point
289 // generation, since otherwise it will be confusing.
290
291 int i;
292 if (!init) {
293 init = 1;
294 // Outer face
295 for (i = 0; i< NPHI; i++) {
296 // 0 1 3 2;
297 indices[5*i+0] = 2*i+0;
298 indices[5*i+1] = 2*i+1;
299 indices[5*i+2] = 2*i+3;
300 indices[5*i+3] = 2*i+2;
301 indices[5*i+4] = SO_END_FACE_INDEX;
302 }
303 // the inner face
304 for (i=0;i<NPHI;i++) {
305 indices[5*1*NPHI + 5*i+0] = 2*NPHI+2 + 2*i+0;
306 indices[5*1*NPHI + 5*i+1] = 2*NPHI+2 + 2*i+1;
307 indices[5*1*NPHI + 5*i+2] = 2*NPHI+2 + 2*i+3;
308 indices[5*1*NPHI + 5*i+3] = 2*NPHI+2 + 2*i+2;
309 indices[5*1*NPHI + 5*i+4] = SO_END_FACE_INDEX;
310 }
311 // the top side
312 for (i=0;i<NPHI;i++) {
313 indices[5*2*NPHI + 5*i+0] = 2*i+0;
314 indices[5*2*NPHI + 5*i+1] = 2*i+2;
315 indices[5*2*NPHI + 5*i+2] = NPOINTS - (2*i+4);
316 indices[5*2*NPHI + 5*i+3] = NPOINTS - (2*i+2);
317 indices[5*2*NPHI + 5*i+4] = SO_END_FACE_INDEX;
318 }
319 // the bottom side
320 for (i=0;i<NPHI;i++) {
321 indices[5*3*NPHI + 5*i+0] = 2*i+1;
322 indices[5*3*NPHI + 5*i+1] = NPOINTS - (2*i+1);
323 indices[5*3*NPHI + 5*i+2] = NPOINTS - (2*i+3);
324 indices[5*3*NPHI + 5*i+3] = 2*i+3;
325 indices[5*3*NPHI + 5*i+4] = SO_END_FACE_INDEX;
326 }
327 // the odd side
328 indices[5*4*NPHI +0] = 2*NPHI;
329 indices[5*4*NPHI +1] = 2*NPHI+1;
330 indices[5*4*NPHI +2] = 2*NPHI+3;
331 indices[5*4*NPHI +3] = 2*NPHI+2;
332 indices[5*4*NPHI +4] = SO_END_FACE_INDEX;
333 // aother odd side
334 indices[5*4*NPHI +5 +0] = 0;
335 indices[5*4*NPHI +5 +1] = NPOINTS-2;
336 indices[5*4*NPHI +5 +2] = NPOINTS-1;
337 indices[5*4*NPHI +5 +3] = 1;
338 indices[5*4*NPHI +5 +4] = SO_END_FACE_INDEX;
339 }
340 // Points need to be generated each time:
341 if (pDPhi.getValue()<2*M_PI) {
342 // the odd side
343 indices[5*4*NPHI +0] = 2*NPHI;
344 indices[5*4*NPHI +1] = 2*NPHI+1;
345 indices[5*4*NPHI +2] = 2*NPHI+3;
346 indices[5*4*NPHI +3] = 2*NPHI+2;
347 indices[5*4*NPHI +4] = SO_END_FACE_INDEX;
348 // aother odd side
349 indices[5*4*NPHI +5 +0] = 0;
350 indices[5*4*NPHI +5 +1] = NPOINTS-2;
351 indices[5*4*NPHI +5 +2] = NPOINTS-1;
352 indices[5*4*NPHI +5 +3] = 1;
353 indices[5*4*NPHI +5 +4] = SO_END_FACE_INDEX;
354 }
355 else {
356 // the odd side
357 indices[5*4*NPHI +0] = SO_END_FACE_INDEX;
358 indices[5*4*NPHI +1] = SO_END_FACE_INDEX;
359 indices[5*4*NPHI +2] = SO_END_FACE_INDEX;
360 indices[5*4*NPHI +3] = SO_END_FACE_INDEX;
361 indices[5*4*NPHI +4] = SO_END_FACE_INDEX;
362 // aother odd side
363 indices[5*4*NPHI +5 +0] = SO_END_FACE_INDEX;
364 indices[5*4*NPHI +5 +1] = SO_END_FACE_INDEX;
365 indices[5*4*NPHI +5 +2] = SO_END_FACE_INDEX;
366 indices[5*4*NPHI +5 +3] = SO_END_FACE_INDEX;
367 indices[5*4*NPHI +5 +4] = SO_END_FACE_INDEX;
368 }
369 // The outer surface
370 DeltaPhi = pDPhi.getValue()/NPHI, phi = pSPhi.getValue();
371 for (i = 0; i<=NPHI; i++) {
372 points[2*i+0][0] = pRMax.getValue()*FCOS(phi);
373 points[2*i+0][1]= pRMax.getValue()*FSIN(phi);
374 points[2*i+0][2] = +pDz.getValue();
375
376 points[2*i+1][0] = pRMax.getValue()*FCOS(phi);
377 points[2*i+1][1]= pRMax.getValue()*FSIN(phi);
378 points[2*i+1][2] = -pDz.getValue();
379
380 pp = phi+DeltaPhi/2.0;
381 if (i!=NPHI) {
382 normals[i][0] = FCOS(pp);
383 normals[i][1] = FSIN(pp);
384 normals[i][2] = 0;
385 }
386 phi+=DeltaPhi;
387 }
388 // The inner surface
389 phi = pSPhi.getValue() + pDPhi.getValue();
390 for (i = 0; i<=NPHI; i++) {
391 points[2*NPHI+2+2*i+0][0] = pRMin.getValue()*FCOS(phi);
392 points[2*NPHI+2+2*i+0][1] = pRMin.getValue()*FSIN(phi);
393 points[2*NPHI+2+2*i+0][2] = +pDz.getValue();
394 points[2*NPHI+2+2*i+1][0] = pRMin.getValue()*FCOS(phi);
395 points[2*NPHI+2+2*i+1][1] = pRMin.getValue()*FSIN(phi);
396 points[2*NPHI+2+2*i+1][2] = -pDz.getValue();
397 pp = phi-DeltaPhi/2.0;
398 if (i!=NPHI) {
399 normals[NPHI+i][0] = -FCOS(pp);
400 normals[NPHI+i][1] = -FSIN(pp);
401 normals[NPHI+i][2] = 0;
402 }
403 phi-=DeltaPhi;
404 }
405 // The top side
406 for (i=0;i<NPHI;i++) {
407 normals[2*NPHI+i][0]=normals[2*NPHI+i][1]=0;
408 normals[2*NPHI+i][2]= 1.0;
409 }
410 // The bottom side
411 for (i=0;i<NPHI;i++) {
412 normals[3*NPHI+i][0]=normals[3*NPHI+i][1]=0;
413 normals[3*NPHI+i][2]= -1.0;
414 }
415 // The odd side
416 phi = pSPhi.getValue();
417 normals[4*NPHI+0][0]= FSIN(phi);
418 normals[4*NPHI+0][1]= -FCOS(phi);
419 normals[4*NPHI+0][2]=0;
420
421 // Another odd side
422 phi = pSPhi.getValue()+pDPhi.getValue();
423 normals[4*NPHI+1][0]= -FSIN(phi);
424 normals[4*NPHI+1][1]= +FCOS(phi);
425 normals[4*NPHI+1][2]=0;
426
427 for (int np=0;np<NPOINTS; np++) theCoordinates->point.set1Value(np,points[np][0],points[np][1],points[np][2]);
428 for (int ni=0;ni<NINDICES;ni++) theFaceSet->coordIndex.set1Value(ni,indices[ni]);
429 for (int nf=0;nf<NFACES;nf++) theNormals->vector.set1Value(nf,normals[nf][0],normals[nf][1],normals[nf][2]);
430 theNormalBinding->value=SoNormalBinding::PER_FACE;
431}
432
433// generateChildren
434void SoTubs::generateChildren() {
435
436 // This routines creates one SoSeparator, one SoCoordinate3, and
437 // one SoLineSet, and puts it in the child list. This is done only
438 // once, whereas redrawing the position of the coordinates occurs each
439 // time an update is necessary, in the updateChildren routine.
440
441 assert(children->getLength() ==0);
442 SoSeparator *sep = new SoSeparator();
443 SoCoordinate3 *theCoordinates = new SoCoordinate3();
444 SoNormal *theNormals = new SoNormal();
445 SoNormalBinding *theNormalBinding = new SoNormalBinding();
446 SoIndexedFaceSet *theFaceSet = new SoIndexedFaceSet();
447 //
448 // This line costs some in render quality! but gives speed.
449 //
450 sep->addChild(theCoordinates);
451 sep->addChild(theNormals);
452 sep->addChild(theNormalBinding);
453 sep->addChild(theFaceSet);
454 children->append(sep);
455}
456
457// generateAlternateRep
459
460 // This routine sets the alternate representation to the child
461 // list of this mode.
462
463 if (children->getLength() == 0) generateChildren();
464 updateChildren();
465 alternateRep.setValue((SoSeparator *) ( *children)[0]);
466}
467
468// clearAlternateRep
470 alternateRep.setValue(NULL);
471}
#define FCOS(x)
Definition: SbMath.h:40
#define FSIN(x)
Definition: SbMath.h:41
#define M_PI
Definition: SbMath.h:33
#define GEN_VERTEX(pv, x, y, z, s, t, nx, ny, nz)
Definition: SoTubs.h:71
virtual SoChildList * getChildren() const
GetChildList, required whenever the class has hidden children.
Definition: SoTubs.cc:250
virtual ~SoTubs()
Destructor, required.
Definition: SoTubs.cc:78
virtual void computeBBox(SoAction *action, SbBox3f &box, SbVec3f &center)
compute bounding Box, required
Definition: SoTubs.cc:256
SoSFFloat pDz
Half-length in Z.
Definition: SoTubs.h:89
virtual void clearAlternateRep()
We better be able to clear it, too!
Definition: SoTubs.cc:469
SoSFNode alternateRep
Alternate rep - required.
Definition: SoTubs.h:101
virtual void generatePrimitives(SoAction *action)
Generate Primitives, required.
Definition: SoTubs.cc:94
SoSFFloat pDPhi
Delta-angle, in radians.
Definition: SoTubs.h:97
virtual void generateAlternateRep()
Definition: SoTubs.cc:458
SoSFFloat pSPhi
Starting angle, in radians.
Definition: SoTubs.h:93
static void initClass()
Class Initializer, required.
Definition: SoTubs.cc:84
SoSFFloat pRMin
Inside radius of the tube.
Definition: SoTubs.h:81
SoSFFloat pRMax
Outside radius of the tube.
Definition: SoTubs.h:85