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