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