SoTubs.cc

Go to the documentation of this file.
00001 //
00002 // ********************************************************************
00003 // * License and Disclaimer                                           *
00004 // *                                                                  *
00005 // * The  Geant4 software  is  copyright of the Copyright Holders  of *
00006 // * the Geant4 Collaboration.  It is provided  under  the terms  and *
00007 // * conditions of the Geant4 Software License,  included in the file *
00008 // * LICENSE and available at  http://cern.ch/geant4/license .  These *
00009 // * include a list of copyright holders.                             *
00010 // *                                                                  *
00011 // * Neither the authors of this software system, nor their employing *
00012 // * institutes,nor the agencies providing financial support for this *
00013 // * work  make  any representation or  warranty, express or implied, *
00014 // * regarding  this  software system or assume any liability for its *
00015 // * use.  Please see the license in the file  LICENSE  and URL above *
00016 // * for the full disclaimer and the limitation of liability.         *
00017 // *                                                                  *
00018 // * This  code  implementation is the result of  the  scientific and *
00019 // * technical work of the GEANT4 collaboration.                      *
00020 // * By using,  copying,  modifying or  distributing the software (or *
00021 // * any work based  on the software)  you  agree  to acknowledge its *
00022 // * use  in  resulting  scientific  publications,  and indicate your *
00023 // * acceptance of all terms of the Geant4 Software license.          *
00024 // ********************************************************************
00025 //
00026 //
00027 //
00028 // $Id$
00029 //
00030 /*-----------------------------HEPVis---------------------------------------*/
00031 /*                                                                          */
00032 /* Node:             SoTubs                                                 */
00033 /* Description:      Represents the G4Tubs Geant Geometry entity            */
00034 /* Author:           Joe Boudreau Nov 11 1996                               */
00035 /*                                                                          */
00036 /*--------------------------------------------------------------------------*/
00037 
00038 #ifdef G4VIS_BUILD_OI_DRIVER
00039 
00040 // this :
00041 #include "HEPVis/nodes/SoTubs.h"
00042 
00043 #include <assert.h>
00044 #include <cmath>
00045 
00046 #include <Inventor/SbBox.h>
00047 #include <Inventor/actions/SoGLRenderAction.h>
00048 #include <Inventor/fields/SoSFFloat.h>
00049 #include <Inventor/misc/SoChildList.h>
00050 #include <Inventor/nodes/SoSeparator.h>
00051 #include <Inventor/nodes/SoIndexedFaceSet.h>
00052 #include <Inventor/nodes/SoNormal.h>
00053 #include <Inventor/nodes/SoCoordinate3.h>
00054 #include <Inventor/nodes/SoNormalBinding.h>
00055 #include <Inventor/SoPrimitiveVertex.h>
00056 #include <Inventor/elements/SoTextureCoordinateElement.h>
00057 
00058 #include "HEPVis/SbMath.h"
00059 
00060 // This statement is required
00061 SO_NODE_SOURCE(SoTubs)
00062 
00063 // Constructor
00064 SoTubs::SoTubs() {
00065 
00066 
00067   // This statement is required
00068   SO_NODE_CONSTRUCTOR(SoTubs);
00069 
00070   // Data fields are initialized like this:
00071   SO_NODE_ADD_FIELD(pRMin,               (0));
00072   SO_NODE_ADD_FIELD(pRMax,               (1));
00073   SO_NODE_ADD_FIELD(pDz,                 (10));
00074   SO_NODE_ADD_FIELD(pSPhi,               (0));
00075   SO_NODE_ADD_FIELD(pDPhi,               ((float)(2*M_PI)));
00076   SO_NODE_ADD_FIELD(alternateRep,        (NULL));
00077   children = new SoChildList(this);
00078 }
00079 
00080 // Destructor
00081 SoTubs::~SoTubs() {
00082   delete children;
00083 }
00084 
00085 
00086 // initClass
00087 void SoTubs::initClass(){
00088   // This statement is required.
00089   SO_NODE_INIT_CLASS(SoTubs,SoShape,"Shape");
00090 }
00091 
00092 // generatePrimitives
00093 void SoTubs::generatePrimitives(SoAction *action) {
00094   // This variable is used to store each vertex
00095   SoPrimitiveVertex pv;
00096 
00097   // Access the stat from the action
00098   SoState *state = action->getState();
00099 
00100   // See if we have to use a texture coordinate function,
00101   // rather than generating explicit texture coordinates.
00102   SbBool useTexFunction=
00103     (SoTextureCoordinateElement::getType(state) == 
00104      SoTextureCoordinateElement::FUNCTION);
00105 
00106   // If we need to generate texture coordinates with a function,
00107   // we'll need an SoGLTextureCoordinateElement.  Otherwise, we'll
00108   // set up the coordinates directly.
00109   const SoTextureCoordinateElement* tce = NULL;
00110   SbVec4f texCoord;
00111   if (useTexFunction) {
00112     tce = SoTextureCoordinateElement::getInstance(state);
00113   }
00114   else {
00115     texCoord[2] = 0.0;
00116     texCoord[3] = 1.0;
00117   }
00118   SbVec3f point, normal;
00119 
00120 
00122   //-----------------------------------------------------
00123 #define GEN_VERTEX(pv,x,y,z,s,t,nx,ny,nz)               \
00124   point.setValue((float)(x),(float)(y),(float)(z));     \
00125   normal.setValue((float)(nx),(float)(ny),(float)(nz)); \
00126   if (useTexFunction) {                                 \
00127     texCoord=tce->get(point,normal);                    \
00128   } else {                                              \
00129     texCoord[0]=(float)(s);                             \
00130     texCoord[1]=(float)(t);                             \
00131   }                                                     \
00132   pv.setPoint(point);                                   \
00133   pv.setNormal(normal);                                 \
00134   pv.setTextureCoords(texCoord);                        \
00135   shapeVertex(&pv);
00136   //-----------------------------------------------------
00138 
00139   int NPHI = (int)(2+22*std::fabs(pDPhi.getValue()/(2.0*M_PI)));
00140   double deltaPhi = pDPhi.getValue()/NPHI, phi0 = pSPhi.getValue(),phi1=phi0+pDPhi.getValue();
00141   double rMax=pRMax.getValue(),rMin=pRMin.getValue();
00142   double zMax=pDz.getValue(),zMin=-zMax;
00143   double cosPhi0=std::cos(phi0), sinPhi0=std::sin(phi0);
00144   double cosPhi1=std::cos(phi1), sinPhi1=std::sin(phi1);
00145   double cosDeltaPhi=std::cos(deltaPhi),sinDeltaPhi=std::sin(deltaPhi);
00146   //
00147   // The outer surface!
00148   //
00149   int i;
00150   double sinPhi,cosPhi;
00151   beginShape(action,TRIANGLE_STRIP);
00152   sinPhi=sinPhi0;
00153   cosPhi=cosPhi0;
00154   for (i = 0; i<=NPHI; i++) {
00155     GEN_VERTEX(pv,rMax*cosPhi,rMax*sinPhi,zMax,0.0,0.0,cosPhi,sinPhi,0);   
00156     GEN_VERTEX(pv,rMax*cosPhi,rMax*sinPhi,zMin,1.0,1.0,cosPhi,sinPhi,0);   
00157     inc(sinPhi, cosPhi, sinDeltaPhi, cosDeltaPhi);    
00158   }
00159   endShape();
00160   //
00161   // The inner surface!
00162   //
00163   if(rMin!=0.F) {
00164     beginShape(action,TRIANGLE_STRIP);
00165     sinPhi=sinPhi0;
00166     cosPhi=cosPhi0;
00167     for (i = 0; i<=NPHI; i++) {
00168       GEN_VERTEX(pv,rMin*cosPhi,rMin*sinPhi,zMax,0.0,0.0,-cosPhi,-sinPhi,0);   
00169       GEN_VERTEX(pv,rMin*cosPhi,rMin*sinPhi,zMin,1.0,1.0,-cosPhi,-sinPhi,0);   
00170       inc(sinPhi, cosPhi, sinDeltaPhi, cosDeltaPhi);    
00171     } 
00172     endShape();
00173   }
00174   if (std::fabs(deltaPhi)<2.0*M_PI) { 
00175     //
00176     // The end 
00177     //
00178     beginShape(action,TRIANGLE_STRIP);
00179     sinPhi=sinPhi0;
00180     cosPhi=cosPhi0;
00181     GEN_VERTEX(pv,rMax*cosPhi,rMax*sinPhi,zMax,0.0,0.0,sinPhi,-cosPhi,0);   
00182     GEN_VERTEX(pv,rMax*cosPhi,rMax*sinPhi,zMin,1.0,1.0,sinPhi,-cosPhi,0);   
00183     GEN_VERTEX(pv,rMin*cosPhi,rMin*sinPhi,zMax,1.0,0.0,sinPhi,-cosPhi,0);   
00184     GEN_VERTEX(pv,rMin*cosPhi,rMin*sinPhi,zMin,0.0,1.0,sinPhi,-cosPhi,0);   
00185     endShape();
00186     //
00187     // The other end 
00188     //
00189     beginShape(action,TRIANGLE_STRIP);
00190     sinPhi=sinPhi1;
00191     cosPhi=cosPhi1;
00192     GEN_VERTEX(pv,rMax*cosPhi,rMax*sinPhi, zMax,0.0,0.0,-sinPhi,+cosPhi,0);   
00193     GEN_VERTEX(pv,rMax*cosPhi,rMax*sinPhi, zMin,1.0,1.0,-sinPhi,+cosPhi,0);   
00194     GEN_VERTEX(pv,rMin*cosPhi,rMin*sinPhi, zMax,1.0,0.0,-sinPhi,+cosPhi,0);   
00195     GEN_VERTEX(pv,rMin*cosPhi,rMin*sinPhi, zMin,0.0,1.0,-sinPhi,+cosPhi,0);   
00196     endShape();
00197   }
00198   //
00199   // The outer surface at z=+PDZ
00200   //
00201   if(rMin==0.F) {
00202     beginShape(action,TRIANGLE_FAN);
00203     sinPhi=sinPhi0;
00204     cosPhi=cosPhi0;
00205     GEN_VERTEX(pv,0,0,zMax,0.0,0.0,0,0,1);   
00206     for (i = 0; i<=NPHI; i++) {
00207       GEN_VERTEX(pv,rMax*cosPhi,rMax*sinPhi,zMax,1.0,1.0,0,0,1);   
00208       inc(sinPhi, cosPhi, sinDeltaPhi, cosDeltaPhi);    
00209     }
00210     endShape();
00211     //
00212     // The outer surface at z=-PDZ
00213     //
00214     beginShape(action,TRIANGLE_FAN);
00215     sinPhi=sinPhi0;
00216     cosPhi=cosPhi0;
00217     GEN_VERTEX(pv,0,0,zMin,0.0,0.0,0,0,-1);   
00218     for (i = 0; i<=NPHI; i++) {
00219       GEN_VERTEX(pv,rMax*cosPhi,rMax*sinPhi,zMin,1.0,1.0,0,0,-1);   
00220       inc(sinPhi, cosPhi, sinDeltaPhi, cosDeltaPhi);    
00221     }
00222     endShape();
00223   } else {
00224     beginShape(action,TRIANGLE_STRIP);
00225     sinPhi=sinPhi0;
00226     cosPhi=cosPhi0;
00227     for (i = 0; i<=NPHI; i++) {
00228       GEN_VERTEX(pv,rMin*cosPhi,rMin*sinPhi,zMax,0.0,0.0,0,0,1);   
00229       GEN_VERTEX(pv,rMax*cosPhi,rMax*sinPhi,zMax,1.0,1.0,0,0,1);   
00230       inc(sinPhi, cosPhi, sinDeltaPhi, cosDeltaPhi);    
00231     }
00232     endShape();
00233     //
00234     // The outer surface at z=-PDZ
00235     //
00236     beginShape(action,TRIANGLE_STRIP);
00237     sinPhi=sinPhi0;
00238     cosPhi=cosPhi0;
00239     for (i = 0; i<=NPHI; i++) {
00240       GEN_VERTEX(pv,rMin*cosPhi,rMin*sinPhi,zMin,0.0,0.0,0,0,-1);   
00241       GEN_VERTEX(pv,rMax*cosPhi,rMax*sinPhi,zMin,1.0,1.0,0,0,-1);   
00242       inc(sinPhi, cosPhi, sinDeltaPhi, cosDeltaPhi);    
00243     }
00244     endShape();
00245   }
00246 }
00247 
00248 // getChildren
00249 SoChildList *SoTubs::getChildren() const {
00250   return children;
00251 }
00252 
00253 
00254 // computeBBox
00255 void SoTubs::computeBBox(SoAction *, SbBox3f &box, SbVec3f &center ){
00256   SbVec3f vmin(-pRMax.getValue(),-pRMax.getValue(),-pDz.getValue()), 
00257           vmax( pRMax.getValue(), pRMax.getValue(), pDz.getValue());
00258   center.setValue(0,0,0);
00259   box.setBounds(vmin,vmax);
00260 }
00261 
00262 
00263 // updateChildren
00264 void SoTubs::updateChildren() {
00265 
00266   // Redraw the G4Tubs....
00267 
00268   assert(children->getLength()==1);
00269   SoSeparator       *sep                = (SoSeparator *)  ( *children)[0];
00270   SoCoordinate3     *theCoordinates     = (SoCoordinate3 *)      ( sep->getChild(0));
00271   SoNormal          *theNormals         = (SoNormal *)           ( sep->getChild(1)); 
00272   SoNormalBinding   *theNormalBinding   = (SoNormalBinding *)    ( sep->getChild(2));
00273   SoIndexedFaceSet  *theFaceSet         = (SoIndexedFaceSet *)   ( sep->getChild(3));
00274   
00275   
00276   const int NPHI=24, NPOINTS=2*(2*NPHI+2), NFACES=4*NPHI+2, NINDICES = NFACES*5;
00277   float points[NPOINTS][3],normals[NFACES][3];
00278 #ifdef INVENTOR2_0
00279   static long     indices[NINDICES];
00280 #else
00281   static int32_t  indices[NINDICES];
00282 #endif
00283     
00284   static int init=0;
00285   double phi, pp, DeltaPhi;
00286     
00287   // Indices need to be generated once! This is here to keep it close to the point
00288   // generation, since otherwise it will be confusing.
00289     
00290   int i;
00291   if (!init) {
00292     init = 1;
00293     // Outer face
00294     for (i = 0; i< NPHI; i++) {
00295       // 0 1 3 2;
00296       indices[5*i+0] =  2*i+0;
00297       indices[5*i+1] =  2*i+1;
00298       indices[5*i+2] =  2*i+3;
00299       indices[5*i+3] =  2*i+2;
00300       indices[5*i+4] = SO_END_FACE_INDEX;
00301     }
00302     // the inner face
00303     for (i=0;i<NPHI;i++) {
00304       indices[5*1*NPHI + 5*i+0] = 2*NPHI+2 + 2*i+0;  
00305       indices[5*1*NPHI + 5*i+1] = 2*NPHI+2 + 2*i+1;
00306       indices[5*1*NPHI + 5*i+2] = 2*NPHI+2 + 2*i+3;
00307       indices[5*1*NPHI + 5*i+3] = 2*NPHI+2 + 2*i+2;
00308       indices[5*1*NPHI + 5*i+4] = SO_END_FACE_INDEX;
00309     }
00310     // the top side
00311     for (i=0;i<NPHI;i++) {
00312       indices[5*2*NPHI + 5*i+0] = 2*i+0;
00313       indices[5*2*NPHI + 5*i+1] = 2*i+2;
00314       indices[5*2*NPHI + 5*i+2] = NPOINTS - (2*i+4);
00315       indices[5*2*NPHI + 5*i+3] = NPOINTS - (2*i+2);
00316       indices[5*2*NPHI + 5*i+4] = SO_END_FACE_INDEX;
00317     }
00318     // the bottom side
00319     for (i=0;i<NPHI;i++) {
00320       indices[5*3*NPHI + 5*i+0] = 2*i+1;
00321       indices[5*3*NPHI + 5*i+1] = NPOINTS - (2*i+1);
00322       indices[5*3*NPHI + 5*i+2] = NPOINTS - (2*i+3);
00323       indices[5*3*NPHI + 5*i+3] = 2*i+3;
00324       indices[5*3*NPHI + 5*i+4] = SO_END_FACE_INDEX;
00325     }
00326     // the odd side
00327     indices[5*4*NPHI +0] = 2*NPHI;
00328     indices[5*4*NPHI +1] = 2*NPHI+1;
00329     indices[5*4*NPHI +2] = 2*NPHI+3;
00330     indices[5*4*NPHI +3] = 2*NPHI+2;
00331     indices[5*4*NPHI +4] = SO_END_FACE_INDEX;
00332     // aother odd side
00333     indices[5*4*NPHI +5 +0] = 0;
00334     indices[5*4*NPHI +5 +1] = NPOINTS-2;
00335     indices[5*4*NPHI +5 +2] = NPOINTS-1;
00336     indices[5*4*NPHI +5 +3] = 1;
00337     indices[5*4*NPHI +5 +4] = SO_END_FACE_INDEX;
00338   }
00339   // Points need to be generated each time:
00340   if (pDPhi.getValue()<2*M_PI) {
00341     // the odd side
00342     indices[5*4*NPHI +0] = 2*NPHI;
00343     indices[5*4*NPHI +1] = 2*NPHI+1;
00344     indices[5*4*NPHI +2] = 2*NPHI+3;
00345     indices[5*4*NPHI +3] = 2*NPHI+2;
00346     indices[5*4*NPHI +4] = SO_END_FACE_INDEX;
00347     // aother odd side
00348     indices[5*4*NPHI +5 +0] = 0;
00349     indices[5*4*NPHI +5 +1] = NPOINTS-2;
00350     indices[5*4*NPHI +5 +2] = NPOINTS-1;
00351     indices[5*4*NPHI +5 +3] = 1;
00352     indices[5*4*NPHI +5 +4] = SO_END_FACE_INDEX;
00353   } 
00354   else {
00355     // the odd side
00356     indices[5*4*NPHI +0] = SO_END_FACE_INDEX;
00357     indices[5*4*NPHI +1] = SO_END_FACE_INDEX;
00358     indices[5*4*NPHI +2] = SO_END_FACE_INDEX;
00359     indices[5*4*NPHI +3] = SO_END_FACE_INDEX;
00360     indices[5*4*NPHI +4] = SO_END_FACE_INDEX;
00361     // aother odd side
00362     indices[5*4*NPHI +5 +0] = SO_END_FACE_INDEX;
00363     indices[5*4*NPHI +5 +1] = SO_END_FACE_INDEX;
00364     indices[5*4*NPHI +5 +2] = SO_END_FACE_INDEX;
00365     indices[5*4*NPHI +5 +3] = SO_END_FACE_INDEX;
00366     indices[5*4*NPHI +5 +4] = SO_END_FACE_INDEX;
00367   }
00368   // The outer surface
00369   DeltaPhi = pDPhi.getValue()/NPHI, phi = pSPhi.getValue();
00370   for (i = 0; i<=NPHI; i++) {
00371     points[2*i+0][0] = pRMax.getValue()*FCOS(phi); 
00372     points[2*i+0][1]= pRMax.getValue()*FSIN(phi); 
00373     points[2*i+0][2] = +pDz.getValue();
00374 
00375     points[2*i+1][0] = pRMax.getValue()*FCOS(phi); 
00376     points[2*i+1][1]= pRMax.getValue()*FSIN(phi); 
00377     points[2*i+1][2] = -pDz.getValue();
00378 
00379     pp = phi+DeltaPhi/2.0;
00380     if (i!=NPHI) {
00381       normals[i][0] = FCOS(pp); 
00382       normals[i][1] = FSIN(pp); 
00383       normals[i][2] = 0;
00384     }
00385     phi+=DeltaPhi;
00386   }
00387   // The inner surface
00388   phi = pSPhi.getValue() + pDPhi.getValue();
00389   for (i = 0; i<=NPHI; i++) {
00390     points[2*NPHI+2+2*i+0][0] = pRMin.getValue()*FCOS(phi); 
00391     points[2*NPHI+2+2*i+0][1] = pRMin.getValue()*FSIN(phi); 
00392     points[2*NPHI+2+2*i+0][2] = +pDz.getValue();
00393     points[2*NPHI+2+2*i+1][0] = pRMin.getValue()*FCOS(phi); 
00394     points[2*NPHI+2+2*i+1][1] = pRMin.getValue()*FSIN(phi); 
00395     points[2*NPHI+2+2*i+1][2] = -pDz.getValue();
00396     pp = phi-DeltaPhi/2.0;
00397     if (i!=NPHI) {
00398       normals[NPHI+i][0] = -FCOS(pp); 
00399       normals[NPHI+i][1] = -FSIN(pp); 
00400       normals[NPHI+i][2] = 0;
00401     }
00402     phi-=DeltaPhi;
00403   }
00404   // The top side
00405   for (i=0;i<NPHI;i++) {
00406     normals[2*NPHI+i][0]=normals[2*NPHI+i][1]=0; 
00407     normals[2*NPHI+i][2]=  1.0;
00408   } 
00409   // The bottom side
00410   for (i=0;i<NPHI;i++) {
00411     normals[3*NPHI+i][0]=normals[3*NPHI+i][1]=0; 
00412     normals[3*NPHI+i][2]= -1.0;
00413   } 
00414   // The odd side
00415   phi = pSPhi.getValue(); 
00416   normals[4*NPHI+0][0]=  FSIN(phi); 
00417   normals[4*NPHI+0][1]= -FCOS(phi); 
00418   normals[4*NPHI+0][2]=0;
00419     
00420     // Another odd side
00421   phi = pSPhi.getValue()+pDPhi.getValue(); 
00422   normals[4*NPHI+1][0]= -FSIN(phi); 
00423   normals[4*NPHI+1][1]= +FCOS(phi); 
00424   normals[4*NPHI+1][2]=0;
00425     
00426   for (int np=0;np<NPOINTS; np++) theCoordinates->point.set1Value(np,points[np][0],points[np][1],points[np][2]);
00427   for (int ni=0;ni<NINDICES;ni++) theFaceSet->coordIndex.set1Value(ni,indices[ni]);
00428   for (int nf=0;nf<NFACES;nf++) theNormals->vector.set1Value(nf,normals[nf][0],normals[nf][1],normals[nf][2]);
00429   theNormalBinding->value=SoNormalBinding::PER_FACE;
00430 }
00431 
00432 // generateChildren
00433 void SoTubs::generateChildren() {
00434 
00435   // This routines creates one SoSeparator, one SoCoordinate3, and
00436   // one SoLineSet, and puts it in the child list.  This is done only
00437   // once, whereas redrawing the position of the coordinates occurs each
00438   // time an update is necessary, in the updateChildren routine. 
00439 
00440   assert(children->getLength() ==0);
00441   SoSeparator      *sep              = new SoSeparator(); 
00442   SoCoordinate3    *theCoordinates   = new SoCoordinate3();
00443   SoNormal         *theNormals       = new SoNormal(); 
00444   SoNormalBinding  *theNormalBinding = new SoNormalBinding();
00445   SoIndexedFaceSet *theFaceSet       = new SoIndexedFaceSet();
00446   // 
00447   // This line costs some in render quality! but gives speed.
00448   // 
00449   sep->addChild(theCoordinates);
00450   sep->addChild(theNormals);
00451   sep->addChild(theNormalBinding);
00452   sep->addChild(theFaceSet);
00453   children->append(sep);
00454 }
00455 
00456 // generateAlternateRep
00457 void SoTubs::generateAlternateRep() {
00458 
00459   // This routine sets the alternate representation to the child
00460   // list of this mode.  
00461 
00462   if (children->getLength() == 0) generateChildren();
00463   updateChildren();
00464   alternateRep.setValue((SoSeparator *)  ( *children)[0]);
00465 }
00466 
00467 // clearAlternateRep
00468 void SoTubs::clearAlternateRep() {
00469   alternateRep.setValue(NULL);
00470 }
00471 
00472 #endif

Generated on Mon May 27 17:50:35 2013 for Geant4 by  doxygen 1.4.7