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