Geant4  10.00.p01
SoCons.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: SoCons.cc 66373 2012-12-18 09:41:34Z gcosmo $
29 //
30 /*-----------------------------HEPVis---------------------------------------*/
31 /* */
32 /* Node: SoCons */
33 /* Description: Represents the G4Cons 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/SoCons.h"
42 
43 #include <assert.h>
44 #include <cmath>
45 #include <Inventor/SbBox.h>
46 #include <Inventor/actions/SoAction.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(SoCons)
61 
62 // Constructor
63 SoCons::SoCons() {
64  // This statement is required
65  SO_NODE_CONSTRUCTOR(SoCons);
66 
67  // Data fields are initialized like this:
68  SO_NODE_ADD_FIELD(fRmin1, (0.0));
69  SO_NODE_ADD_FIELD(fRmin2, (0.0));
70  SO_NODE_ADD_FIELD(fRmax1, (1.0));
71  SO_NODE_ADD_FIELD(fRmax2, (1.0));
72  SO_NODE_ADD_FIELD(fDz, (10.0));
73  SO_NODE_ADD_FIELD(fSPhi, (0.0));
74  SO_NODE_ADD_FIELD(fDPhi, ((float)(2*M_PI)));
75  SO_NODE_ADD_FIELD(smoothDraw, (TRUE));
76  SO_NODE_ADD_FIELD(alternateRep, (NULL));
77  children = new SoChildList(this);
78 }
79 
80 // Destructor
81 SoCons::~SoCons() {
82  delete children;
83 }
84 
85 
86 // initClass
87 void SoCons::initClass(){
88  // This statement is required.
89  SO_NODE_INIT_CLASS(SoCons,SoShape,"Shape");
90 }
91 
92 
93 // generatePrimitives
94 void SoCons::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  } else {
115  texCoord[2] = 0.0;
116  texCoord[3] = 1.0;
117  }
118  SbVec3f point, normal;
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 
139  int NPHI = (int)(2+22*std::fabs(fDPhi.getValue()/(2.0*M_PI)));
140  double deltaPhi = fDPhi.getValue()/NPHI;
141  double phi0 = fSPhi.getValue();
142  double phi1 = phi0 + fDPhi.getValue();
143  double rMax1 = fRmax1.getValue();
144  double rMin1 = fRmin1.getValue();
145  double rMax2 = fRmax2.getValue();
146  double rMin2 = fRmin2.getValue();
147  double zMax = fDz.getValue();
148  double zMin = -zMax;
149  double cosPhi0 = std::cos(phi0);
150  double sinPhi0 = std::sin(phi0);
151  double cosPhi1 = std::cos(phi1);
152  double sinPhi1 = std::sin(phi1);
153  double cosDeltaPhi = std::cos(deltaPhi);
154  double sinDeltaPhi = std::sin(deltaPhi);
155  //
156  // The outer surface!
157  //
158  beginShape(action,TRIANGLE_STRIP);
159  int i;
160  double sinPhi=sinPhi0;
161  double cosPhi=cosPhi0;
162  for (i = 0; i<=NPHI; i++) {
163  GEN_VERTEX(pv,rMax2*cosPhi,rMax2*sinPhi,zMax,0.0,0.0,cosPhi,sinPhi,0);
164  GEN_VERTEX(pv,rMax1*cosPhi,rMax1*sinPhi,zMin,1.0,1.0,cosPhi,sinPhi,0);
165  inc(sinPhi, cosPhi, sinDeltaPhi, cosDeltaPhi);
166  }
167  endShape();
168  //
169  // The inner surface!
170  //
171  beginShape(action,TRIANGLE_STRIP);
172  sinPhi=sinPhi0;
173  cosPhi=cosPhi0;
174  for (i = 0; i<=NPHI; i++) {
175  GEN_VERTEX(pv,rMin2*cosPhi,rMin2*sinPhi,zMax,0.0,0.0,-cosPhi,-sinPhi,0);
176  GEN_VERTEX(pv,rMin1*cosPhi,rMin1*sinPhi,zMin,1.0,1.0,-cosPhi,-sinPhi,0);
177  inc(sinPhi, cosPhi, sinDeltaPhi, cosDeltaPhi);
178  }
179  endShape();
180  if (std::fabs(deltaPhi)<2.0*M_PI) {
181  //
182  // The end
183  //
184  beginShape(action,TRIANGLE_STRIP);
185  sinPhi=sinPhi0;
186  cosPhi=cosPhi0;
187  GEN_VERTEX(pv,rMax2*cosPhi,rMax2*sinPhi,zMax,0.0,0.0,sinPhi,-cosPhi,0);
188  GEN_VERTEX(pv,rMax1*cosPhi,rMax1*sinPhi,zMin,1.0,1.0,sinPhi,-cosPhi,0);
189  GEN_VERTEX(pv,rMin2*cosPhi,rMin2*sinPhi,zMax,1.0,0.0,sinPhi,-cosPhi,0);
190  GEN_VERTEX(pv,rMin1*cosPhi,rMin1*sinPhi,zMin,0.0,1.0,sinPhi,-cosPhi,0);
191  endShape();
192  //
193  // The other end
194  //
195  beginShape(action,TRIANGLE_STRIP);
196  sinPhi=sinPhi1;
197  cosPhi=cosPhi1;
198  GEN_VERTEX(pv,rMax2*cosPhi,rMax2*sinPhi, zMax,0.0,0.0,-sinPhi,+cosPhi,0);
199  GEN_VERTEX(pv,rMax1*cosPhi,rMax1*sinPhi, zMin,1.0,1.0,-sinPhi,+cosPhi,0);
200  GEN_VERTEX(pv,rMin2*cosPhi,rMin2*sinPhi, zMax,1.0,0.0,-sinPhi,+cosPhi,0);
201  GEN_VERTEX(pv,rMin1*cosPhi,rMin1*sinPhi, zMin,0.0,1.0,-sinPhi,+cosPhi,0);
202  endShape();
203  }
204 
205  //
206  // The outer surface at z=+PDZ
207  //
208  beginShape(action,TRIANGLE_STRIP);
209  sinPhi=sinPhi0;
210  cosPhi=cosPhi0;
211  for (i = 0; i<=NPHI; i++) {
212  GEN_VERTEX(pv,rMin2*cosPhi,rMin2*sinPhi,zMax,0.0,0.0,0,0,1);
213  GEN_VERTEX(pv,rMax2*cosPhi,rMax2*sinPhi,zMax,1.0,1.0,0,0,1);
214  inc(sinPhi, cosPhi, sinDeltaPhi, cosDeltaPhi);
215  }
216  endShape();
217  //
218  // The outer surface at z=-PDZ
219  //
220  beginShape(action,TRIANGLE_STRIP);
221  sinPhi=sinPhi0;
222  cosPhi=cosPhi0;
223  for (i = 0; i<=NPHI; i++) {
224  GEN_VERTEX(pv,rMin1*cosPhi,rMin1*sinPhi,zMin,0.0,0.0,0,0,-1);
225  GEN_VERTEX(pv,rMax1*cosPhi,rMax1*sinPhi,zMin,1.0,1.0,0,0,-1);
226  inc(sinPhi, cosPhi, sinDeltaPhi, cosDeltaPhi);
227  }
228  endShape();
229 
230 }
231 
232 // getChildren
233 SoChildList *SoCons::getChildren() const {
234  return children;
235 }
236 
237 
238 // computeBBox
239 void SoCons::computeBBox(SoAction *, SbBox3f &box, SbVec3f &center ){
240  float fRmax= fRmax1.getValue();
241  if (fRmax2.getValue() > fRmax) fRmax = fRmax2.getValue();
242 
243  SbVec3f vmin(-fRmax,-fRmax,-fDz.getValue()),
244  vmax( fRmax, fRmax, fDz.getValue());
245  center.setValue(0,0,0);
246  box.setBounds(vmin,vmax);
247 }
248 
249 
250 
251 
252 // updateChildren
253 void SoCons::updateChildren() {
254 
255 
256  // Redraw the G4Cons....
257 
258  assert(children->getLength()==1);
259  SoSeparator *sep = (SoSeparator *) ( *children)[0];
260  SoCoordinate3 *theCoordinates = (SoCoordinate3 *) ( sep->getChild(0));
261  SoNormal *theNormals = (SoNormal *) ( sep->getChild(1));
262  SoNormalBinding *theNormalBinding = (SoNormalBinding *) ( sep->getChild(2));
263  SoIndexedFaceSet *theFaceSet = (SoIndexedFaceSet *) ( sep->getChild(3));
264 
265  const int NPHI=24, NPOINTS=2*(2*NPHI+2), NFACES=4*NPHI+2, NINDICES = NFACES*5;
266  float points[NPOINTS][3], normals[NFACES][3];
267 #ifdef INVENTOR2_0
268  static long indices[NINDICES];
269 #else
270  static int32_t indices[NINDICES];
271 #endif
272  static int init=0;
273  double phi, pp, DeltaPhi;
274 
275  // Indices need to be generated once! This is here to keep it close to the point
276  // generation, since otherwise it will be confusing.
277 
278  int i;
279  if (!init) {
280  init = 1;
281  // Outer face
282  for (i = 0; i< NPHI; i++) {
283  // 0 1 3 2;
284  indices[5*i+0] = 2*i+0;
285  indices[5*i+1] = 2*i+1;
286  indices[5*i+2] = 2*i+3;
287  indices[5*i+3] = 2*i+2;
288  indices[5*i+4] = SO_END_FACE_INDEX;
289  }
290  // the inner face
291  for (i=0;i<NPHI;i++) {
292  indices[5*1*NPHI + 5*i+0] = 2*NPHI+2 + 2*i+0;
293  indices[5*1*NPHI + 5*i+1] = 2*NPHI+2 + 2*i+1;
294  indices[5*1*NPHI + 5*i+2] = 2*NPHI+2 + 2*i+3;
295  indices[5*1*NPHI + 5*i+3] = 2*NPHI+2 + 2*i+2;
296  indices[5*1*NPHI + 5*i+4] = SO_END_FACE_INDEX;
297  }
298  // the top side
299  for (i=0;i<NPHI;i++) {
300  indices[5*2*NPHI + 5*i+0] = 2*i+0;
301  indices[5*2*NPHI + 5*i+1] = 2*i+2;
302  indices[5*2*NPHI + 5*i+2] = NPOINTS - (2*i+4);
303  indices[5*2*NPHI + 5*i+3] = NPOINTS - (2*i+2);
304  indices[5*2*NPHI + 5*i+4] = SO_END_FACE_INDEX;
305  }
306  // the bottom side
307  for (i=0;i<NPHI;i++) {
308  indices[5*3*NPHI + 5*i+0] = 2*i+1;
309  indices[5*3*NPHI + 5*i+1] = NPOINTS - (2*i+1);
310  indices[5*3*NPHI + 5*i+2] = NPOINTS - (2*i+3);
311  indices[5*3*NPHI + 5*i+3] = 2*i+3;
312  indices[5*3*NPHI + 5*i+4] = SO_END_FACE_INDEX;
313  }
314  // the odd side
315  indices[5*4*NPHI +0] = 2*NPHI;
316  indices[5*4*NPHI +1] = 2*NPHI+1;
317  indices[5*4*NPHI +2] = 2*NPHI+3;
318  indices[5*4*NPHI +3] = 2*NPHI+2;
319  indices[5*4*NPHI +4] = SO_END_FACE_INDEX;
320  // aother odd side
321  indices[5*4*NPHI +5 +0] = 0;
322  indices[5*4*NPHI +5 +1] = NPOINTS-2;
323  indices[5*4*NPHI +5 +2] = NPOINTS-1;
324  indices[5*4*NPHI +5 +3] = 1;
325  indices[5*4*NPHI +5 +4] = SO_END_FACE_INDEX;
326  }
327  // Points need to be generated each time:
328  // The outer surface
329  DeltaPhi = fDPhi.getValue()/NPHI, phi = fSPhi.getValue();
330  float t,st,ct;
331  t = FATAN((fRmax2.getValue()-fRmax1.getValue())/(2*fDz.getValue()));
332  st = FSIN(t);
333  ct = FCOS(t);
334  for (i = 0; i<=NPHI; i++) {
335  points[2*i+0][0] = fRmax2.getValue()*FCOS(phi);
336  points[2*i+0][1] = fRmax2.getValue()*FSIN(phi);
337  points[2*i+0][2] = +fDz.getValue();
338  points[2*i+1][0] = fRmax1.getValue()*FCOS(phi);
339  points[2*i+1][1] = fRmax1.getValue()*FSIN(phi);
340  points[2*i+1][2] = -fDz.getValue();
341  pp = phi+DeltaPhi/2.0;
342  if (i!=NPHI) {
343  normals[i][0] = ct * FCOS(pp);
344  normals[i][1] = ct * FSIN(pp);
345  normals[i][2] = -st;
346  }
347  phi+=DeltaPhi;
348  }
349  // The inner surface
350  phi = fSPhi.getValue() + fDPhi.getValue();
351  t = FATAN((fRmin2.getValue()-fRmin1.getValue())/(2*fDz.getValue()));
352  st = FSIN(t);
353  ct = FCOS(t);
354  for (i = 0; i<=NPHI; i++) {
355  points[2*NPHI+2+2*i+0][0] = fRmin2.getValue()*FCOS(phi);
356  points[2*NPHI+2+2*i+0][1] = fRmin2.getValue()*FSIN(phi);
357  points[2*NPHI+2+2*i+0][2] = +fDz.getValue();
358  points[2*NPHI+2+2*i+1][0] = fRmin1.getValue()*FCOS(phi);
359  points[2*NPHI+2+2*i+1][1] = fRmin1.getValue()*FSIN(phi);
360  points[2*NPHI+2+2*i+1][2] = -fDz.getValue();
361  pp = phi-DeltaPhi/2.0;
362  if (i!=NPHI) {
363  normals[NPHI+i][0] = -ct*FCOS(pp);
364  normals[NPHI+i][1] = -ct*FSIN(pp);
365  normals[NPHI+i][2] = st;
366  }
367  phi-=DeltaPhi;
368  }
369  // The top side
370  for (i=0;i<NPHI;i++) {
371  normals[2*NPHI+i][0]=normals[2*NPHI+i][1]=0;
372  normals[2*NPHI+i][2]= 1.0;
373  }
374  // The bottom side
375  for (i=0;i<NPHI;i++) {
376  normals[3*NPHI+i][0]=normals[3*NPHI+i][1]=0;
377  normals[3*NPHI+i][2]= -1.0;
378  }
379  // The odd side
380  phi = fSPhi.getValue();
381  normals[4*NPHI+0][0]= FSIN(phi);
382  normals[4*NPHI+0][1]= -FCOS(phi);
383  normals[4*NPHI+0][2]= 0;
384 
385  // Another odd side
386  phi = fSPhi.getValue()+fDPhi.getValue();
387  normals[4*NPHI+1][0]= -FSIN(phi);
388  normals[4*NPHI+1][1]= +FCOS(phi);
389  normals[4*NPHI+1][2]=0;
390 
391  for (int np=0;np<NPOINTS;np++) theCoordinates->point.set1Value(np,points[np][0],points[np][1],points[np][2]);
392  theFaceSet->coordIndex.setValues(0,NINDICES,indices);
393  if (smoothDraw.getValue()) {
394  // This Line is replaced by the next one because of an apparent Bug in Inventor (mem. leak).
395  // theNormals->vector.deleteValues(0);
396  for (int nf=0;nf<NFACES;nf++) theNormals->vector.set1Value(nf,normals[nf][0],normals[nf][1],normals[nf][2]);
397  theNormalBinding->value=SoNormalBinding::PER_FACE;
398  }
399  else {
400  for (int nf=0;nf<NFACES;nf++) theNormals->vector.set1Value(nf,normals[nf][0],normals[nf][1],normals[nf][2]);
401  theNormalBinding->value=SoNormalBinding::PER_FACE;
402  }
403 }
404 
405 // generateChildren
406 void SoCons::generateChildren() {
407 
408  // This routines creates one SoSeparator, one SoCoordinate3, and
409  // one SoLineSet, and puts it in the child list. This is done only
410  // once, whereas redrawing the position of the coordinates occurs each
411  // time an update is necessary, in the updateChildren routine.
412 
413  assert(children->getLength() ==0);
414  SoSeparator *sep = new SoSeparator();
415  SoCoordinate3 *theCoordinates = new SoCoordinate3();
416  SoNormal *theNormals = new SoNormal();
417  SoNormalBinding *theNormalBinding = new SoNormalBinding();
418  SoIndexedFaceSet *theFaceSet = new SoIndexedFaceSet();
419  //
420  // This line costs some in render quality! but gives speed.
421  //
422  sep->addChild(theCoordinates);
423  sep->addChild(theNormals);
424  sep->addChild(theNormalBinding);
425  sep->addChild(theFaceSet);
426  children->append(sep);
427 }
428 
429 // generateAlternateRep
430 void SoCons::generateAlternateRep() {
431 
432  // This routine sets the alternate representation to the child
433  // list of this mode.
434 
435  if (children->getLength() == 0) generateChildren();
436  updateChildren();
437  alternateRep.setValue((SoSeparator *) ( *children)[0]);
438 }
439 
440 // clearAlternateRep
441 void SoCons::clearAlternateRep() {
442  alternateRep.setValue(NULL);
443 }
444 
445 #endif
#define assert(x)
Definition: mymalloc.cc:1309
static double normal(HepRandomEngine *eptr)
Definition: RandPoisson.cc:77
#define TRUE
Definition: globals.hh:55