SoPolyhedron.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 #ifdef G4VIS_BUILD_OI_DRIVER
00027 
00028 /*----------------------------HEPVis----------------------------------------*/
00029 /*                                                                          */
00030 /* Node:             SoPolyhedron                                           */
00031 /* Description:      SoNode to represent HepPolyhedron                      */
00032 /* Author:           Guy Barrand                                            */
00033 /*                                                                          */
00034 /*--------------------------------------------------------------------------*/
00035 
00036 // this :
00037 #include "Geant4_SoPolyhedron.h"
00038 
00039 #include <Inventor/SbBox.h>
00040 #include <Inventor/actions/SoAction.h>
00041 #include <Inventor/SoPrimitiveVertex.h>
00042 #include <Inventor/elements/SoTextureCoordinateElement.h>
00043 #include <Inventor/nodes/SoSeparator.h>
00044 
00045 //#include <HEPVis/SbMath.h>
00046 #define SbMinimum(a,b) ((a)<(b)?a:b)
00047 #define SbMaximum(a,b) ((a)>(b)?a:b)
00048 
00049 #include <HEPVis/actions/SoAlternateRepAction.h>
00050 
00051 #include "G4Polyhedron.hh"
00052 
00053 //typedef SbVec3f HVPoint3D;
00054 //typedef SbVec3f HVNormal3D;
00055 
00056 typedef HepGeom::Point3D<double> HVPoint3D;
00057 typedef HepGeom::Normal3D<double> HVNormal3D;
00058 
00059 SO_NODE_SOURCE(Geant4_SoPolyhedron) 
00060 
00061 void Geant4_SoPolyhedron::initClass(
00062 )
00065 {
00066   SO_NODE_INIT_CLASS(Geant4_SoPolyhedron,SoShape,"Shape");
00067 }
00069 Geant4_SoPolyhedron::Geant4_SoPolyhedron(
00070 )
00071 :fPolyhedron(0)
00074 {
00075   SO_NODE_CONSTRUCTOR(Geant4_SoPolyhedron);
00076   SO_NODE_ADD_FIELD(solid,(TRUE));
00077   SO_NODE_ADD_FIELD(reducedWireFrame,(TRUE));
00078   SO_NODE_ADD_FIELD(alternateRep,(NULL));
00079 }
00081 Geant4_SoPolyhedron::Geant4_SoPolyhedron(
00082  const G4Polyhedron& aPolyhedron
00083 )
00084 :fPolyhedron(0)
00087 {
00088   SO_NODE_CONSTRUCTOR(Geant4_SoPolyhedron);
00089   SO_NODE_ADD_FIELD(solid,(TRUE));
00090   SO_NODE_ADD_FIELD(reducedWireFrame,(TRUE));
00091   SO_NODE_ADD_FIELD(alternateRep,(NULL));
00092 
00093   fPolyhedron = new G4Polyhedron(aPolyhedron);
00094 }
00096 Geant4_SoPolyhedron::Geant4_SoPolyhedron(
00097  G4Polyhedron* aPolyhedron
00098 )
00099 :fPolyhedron(aPolyhedron)
00102 {
00103   SO_NODE_CONSTRUCTOR(Geant4_SoPolyhedron);
00104   SO_NODE_ADD_FIELD(solid,(TRUE));
00105   SO_NODE_ADD_FIELD(reducedWireFrame,(TRUE));
00106   SO_NODE_ADD_FIELD(alternateRep,(NULL));
00107 }
00109 Geant4_SoPolyhedron::~Geant4_SoPolyhedron(
00110 )
00113 {
00114   delete fPolyhedron;
00115 }
00117 void Geant4_SoPolyhedron::generatePrimitives(
00118  SoAction* aAction
00119 ) 
00120 
00121 
00122 {
00123   if(!fPolyhedron) return;
00124   if(fPolyhedron->GetNoFacets()<=0) return; // Abnormal polyhedron.
00125 
00126   SoState *state = aAction->getState();
00127   SbBool useTexFunction =
00128     (SoTextureCoordinateElement::getType(state) == 
00129      SoTextureCoordinateElement::FUNCTION);
00130   const SoTextureCoordinateElement *tce = NULL;
00131   SbVec4f texCoord(0.,0.,0.,0.);
00132   if (useTexFunction) {
00133     tce = SoTextureCoordinateElement::getInstance(state);
00134   } else {
00135     texCoord[2] = 0.0;
00136     texCoord[3] = 1.0;
00137   }
00138 
00139   if(solid.getValue()==TRUE) {
00140     SoPrimitiveVertex pv;
00141     SbVec3f point, normal;
00143     //----------------------------------------
00144 #define GEN_VERTEX(pv,x,y,z,s,t,nx,ny,nz)  \
00145   point.setValue(x,y,z);                   \
00146   normal.setValue(nx,ny,nz);               \
00147   if (useTexFunction) {                    \
00148     texCoord=tce->get(point,normal);       \
00149   } else {                                 \
00150     texCoord[0]=s;                         \
00151     texCoord[1]=t;                         \
00152   }                                        \
00153   pv.setPoint(point);                      \
00154   pv.setNormal(normal);                    \
00155   pv.setTextureCoords(texCoord);           \
00156   shapeVertex(&pv);
00157   //----------------------------------------
00159 
00160     // Assume all facets are convex quadrilaterals :
00161     bool notLastFace;
00162     do {
00163       HVNormal3D unitNormal;
00164       notLastFace = fPolyhedron->GetNextUnitNormal(unitNormal);
00165 
00166       beginShape(aAction,POLYGON);
00167       bool notLastEdge;
00168       int edgeFlag = 1;
00169       do {
00170         HVPoint3D vertex;
00171         notLastEdge = fPolyhedron->GetNextVertex(vertex,edgeFlag);
00172         GEN_VERTEX(pv,
00173                    vertex[0],
00174                    vertex[1],
00175                    vertex[2],
00176                    0.0,0.0,
00177                    unitNormal[0],
00178                    unitNormal[1],
00179                    unitNormal[2]);
00180       } while (notLastEdge);
00181       endShape();
00182     } while (notLastFace);
00183   } else {
00184     SoPrimitiveVertex pvb,pve;
00185     pve.setTextureCoords(texCoord);
00186     pvb.setTextureCoords(texCoord);
00187 
00188 #ifdef __COIN__ // To bypass a bug in invokeLineSegment when picking.
00189     beginShape(aAction,POLYGON);
00190     endShape();
00191 #endif
00192 
00193     SbVec3f point;
00194     bool notLastFace;
00195     do {
00196       HVNormal3D unitNormal;
00197       notLastFace = fPolyhedron->GetNextUnitNormal(unitNormal);
00198 
00199       SbVec3f normal;
00200       normal.setValue(unitNormal[0],unitNormal[1],unitNormal[2]);
00201 
00202       // Treat edges :
00203       int edgeFlag = 1;
00204       int prevEdgeFlag = edgeFlag;
00205       bool notLastEdge;
00206       SbBool firstEdge = TRUE;
00207       do {
00208         HVPoint3D vertex;
00209         notLastEdge = fPolyhedron->GetNextVertex(vertex,edgeFlag);
00210         if(reducedWireFrame.getValue()==FALSE) edgeFlag = 1;        
00211         if(firstEdge) {
00212           if(edgeFlag > 0) {
00213             pvb.setNormal(normal);
00214             point.setValue(vertex[0],vertex[1],vertex[2]);
00215             pvb.setPoint(point);
00216           } else {
00217           }
00218           firstEdge = FALSE;
00219           prevEdgeFlag = edgeFlag;
00220         } else {
00221           if(edgeFlag!=prevEdgeFlag) { 
00222             if(edgeFlag > 0) { // Pass to a visible edge :
00223               pvb.setNormal(normal);
00224               point.setValue(vertex[0],vertex[1],vertex[2]);
00225               pvb.setPoint(point);
00226             } else { // Pass to an invisible edge :
00227               pve.setNormal(normal);
00228               point.setValue(vertex[0],vertex[1],vertex[2]);
00229               pve.setPoint(point);
00230               invokeLineSegmentCallbacks(aAction,&pvb,&pve);
00231             }
00232             prevEdgeFlag = edgeFlag;
00233           } else {
00234             if(edgeFlag > 0) {
00235               pve.setNormal(normal);
00236               point.setValue(vertex[0],vertex[1],vertex[2]);
00237               pve.setPoint(point);
00238               invokeLineSegmentCallbacks(aAction,&pvb,&pve);
00239               pvb = pve;
00240             } else {
00241             }
00242           }
00243         }
00244       } while (notLastEdge);
00245     } while (notLastFace);
00246   }
00247 
00248 }
00250 void Geant4_SoPolyhedron::computeBBox(
00251  SoAction*
00252 ,SbBox3f& aBox
00253 ,SbVec3f& aCenter
00254 )
00257 {
00258   if(!fPolyhedron) return;
00259   if(fPolyhedron->GetNoFacets()<=0) { // Abnormal polyhedron.
00260     SbVec3f vmin(-1,-1,-1);
00261     SbVec3f vmax( 1, 1, 1);
00262     aBox.setBounds(vmin,vmax);
00263     aCenter.setValue(0,0,0);
00264   } else {
00265     SbBool first = TRUE;
00266     float xmn = 0,ymn = 0,zmn = 0;
00267     float xmx = 0,ymx = 0,zmx = 0;
00268     float xct = 0,yct = 0,zct = 0;
00269     SbVec3f point;
00270     int count = 0;
00271     // Assume all facets are convex quadrilaterals :
00272     bool notLastFace;
00273     do {
00274       HVNormal3D unitNormal;
00275       notLastFace = fPolyhedron->GetNextUnitNormal(unitNormal);
00276       bool notLastEdge;
00277       do {
00278         HVPoint3D vertex;
00279         int edgeFlag = 1;
00280         notLastEdge = fPolyhedron->GetNextVertex(vertex,edgeFlag);
00281         point.setValue(vertex[0],vertex[1],vertex[2]);
00282         if(first==TRUE) {
00283           xct = xmx = xmn = point[0];
00284           yct = ymx = ymn = point[1];
00285           zct = zmx = zmn = point[2];
00286           count++;
00287           first = FALSE;
00288         } else {
00289           xmn = SbMinimum(xmn,point[0]);
00290           ymn = SbMinimum(ymn,point[1]);
00291           zmn = SbMinimum(zmn,point[2]);
00292           //
00293           xmx = SbMaximum(xmx,point[0]);
00294           ymx = SbMaximum(ymx,point[1]);
00295           zmx = SbMaximum(zmx,point[2]);
00296           //
00297           xct += point[0];
00298           yct += point[1];
00299           zct += point[2];
00300           count++;
00301         }
00302         //
00303       } while (notLastEdge);
00304     } while (notLastFace);
00305     SbVec3f vmin(xmn,ymn,zmn);
00306     SbVec3f vmax(xmx,ymx,zmx);
00307     aBox.setBounds(vmin,vmax);
00308     if(count==0)
00309       aCenter.setValue(0,0,0);
00310     else
00311       aCenter.setValue(xct/count,yct/count,zct/count);
00312   }
00313 }
00314 
00315 #include <Inventor/nodes/SoNormalBinding.h>
00316 #include <Inventor/nodes/SoNormal.h>
00317 #include <Inventor/nodes/SoCoordinate3.h>
00318 #include <Inventor/nodes/SoIndexedFaceSet.h>
00319 #include <Inventor/nodes/SoIndexedLineSet.h>
00321 void Geant4_SoPolyhedron::generateAlternateRep(
00322 ) 
00323 
00324 
00325 {
00326   if(!fPolyhedron) return;
00327   if(fPolyhedron->GetNoFacets()<=0) return; // Abnormal polyhedron.
00328   if(fPolyhedron->GetNoVertices()<=0) return; // Abnormal polyhedron.
00329 
00330   if(solid.getValue()==TRUE) {
00331 
00332     SoSeparator* separator = new SoSeparator;
00333 
00334     SoNormalBinding* normalBinding = new SoNormalBinding;
00335     normalBinding->value = SoNormalBinding::PER_FACE;
00336     separator->addChild(normalBinding);
00337 
00338     SoCoordinate3* coordinate3 = new SoCoordinate3;
00339     separator->addChild(coordinate3);
00340     SoNormal* normal = new SoNormal;
00341     separator->addChild(normal);
00342     SoIndexedFaceSet* indexedFaceSet = new SoIndexedFaceSet;
00343     separator->addChild(indexedFaceSet);
00344 
00345     int nvert = fPolyhedron->GetNoVertices();
00346     int nface = fPolyhedron->GetNoFacets();
00347 
00348     SbVec3f* normals = new SbVec3f[nface];
00349     //FIXME : have the exact booking.
00350     SbVec3f* points = new SbVec3f[nvert];
00351     int32_t* coords = new int32_t[nvert+1];
00352 
00353     int inormal = 0;
00354     int icoord = 0;
00355     int iindex = 0;
00356 
00357     // Assume all facets are convex quadrilaterals :
00358     bool notLastFace;
00359     do {
00360       HVNormal3D unitNormal;
00361       notLastFace = fPolyhedron->GetNextUnitNormal(unitNormal);
00362 
00363       // begin face POLYGON
00364       int ipoint = 0;
00365 
00366       bool notLastEdge;
00367       int edgeFlag = 1;
00368       do {
00369         HVPoint3D vertex;
00370         notLastEdge = fPolyhedron->GetNextVertex(vertex,edgeFlag);
00371         points[ipoint].setValue(vertex[0],vertex[1],vertex[2]);
00372         coords[ipoint] = icoord + ipoint;
00373         ipoint++;
00374       } while (notLastEdge);
00375 
00376       // end face.
00377       coords[ipoint] = SO_END_FACE_INDEX;
00378       coordinate3->point.setValues(icoord,ipoint,points);
00379       icoord += ipoint;
00380 
00381       normals[inormal].setValue(unitNormal[0],unitNormal[1],unitNormal[2]);
00382       inormal++;  
00383 
00384       indexedFaceSet->coordIndex.setValues(iindex,(ipoint+1),coords);
00385       iindex += ipoint+1;
00386 
00387     } while (notLastFace);
00388 
00389     normal->vector.setValues(0,inormal,normals);
00390 
00391     delete [] normals;
00392     delete [] coords;
00393     delete [] points;
00394 
00395     alternateRep.setValue(separator);
00396 
00397   } else {
00398 
00399     SoSeparator* separator = new SoSeparator;
00400 
00401     int nvert = fPolyhedron->GetNoVertices();
00402 
00403     //FIXME : have the exact booking.
00404     int nedge = nvert * 3;
00405     int npoint = nedge*2;
00406     SbVec3f* points = new SbVec3f[npoint];
00407     int ncoord = nedge*3;
00408     int32_t* coords = new int32_t[ncoord];
00409 
00410     SbVec3f pvb(0.,0.,0.), pve(0.,0.,0.);
00411 
00412     SbBool empty = TRUE;
00413     int ipoint = 0;
00414     int icoord = 0;
00415 
00416     bool notLastFace;
00417     do {
00418       HVNormal3D unitNormal;
00419       notLastFace = fPolyhedron->GetNextUnitNormal(unitNormal);
00420 
00421       //SbVec3f normal;
00422       //if( (fProjection==SbProjectionRZ) || (fProjection==SbProjectionZR) ) {
00423         //normal.setValue(0,0,1);
00424       //} else {
00425         //normal.setValue(unitNormal[0],unitNormal[1],unitNormal[2]);
00426       //}
00427 
00428       // Treat edges :
00429       int edgeFlag = 1;
00430       int prevEdgeFlag = edgeFlag;
00431       bool notLastEdge;
00432       SbBool firstEdge = TRUE;
00433       do {
00434         HVPoint3D vertex;
00435         notLastEdge = fPolyhedron->GetNextVertex(vertex,edgeFlag);
00436         if(reducedWireFrame.getValue()==FALSE) edgeFlag = 1;        
00437         if(firstEdge) {
00438           if(edgeFlag > 0) {
00439             pvb.setValue(vertex[0],vertex[1],vertex[2]);
00440           } else {
00441           }
00442           firstEdge = FALSE;
00443           prevEdgeFlag = edgeFlag;
00444         } else {
00445           if(edgeFlag!=prevEdgeFlag) { 
00446             if(edgeFlag > 0) { // Pass to a visible edge :
00447               pvb.setValue(vertex[0],vertex[1],vertex[2]);
00448             } else { // Pass to an invisible edge :
00449               pve.setValue(vertex[0],vertex[1],vertex[2]);
00450 
00451               if((ipoint+1)>=npoint) {
00452                 int new_npoint = 2 * npoint;
00453                 SbVec3f* new_points = new SbVec3f[new_npoint];
00454                 for(int i=0;i<npoint;i++) new_points[i] = points[i];
00455                 delete [] points;
00456                 npoint = new_npoint;
00457                 points = new_points;
00458               }
00459 
00460               if((icoord+2)>=ncoord) {
00461                 int new_ncoord = 2 * ncoord;
00462                 int32_t* new_coords = new int32_t[new_ncoord];
00463                 for(int i=0;i<ncoord;i++) new_coords[i] = coords[i];
00464                 delete [] coords;
00465                 ncoord = new_ncoord;
00466                 coords = new_coords;
00467               }
00468 
00469               points[ipoint+0] = pvb;
00470               points[ipoint+1] = pve;
00471               coords[icoord+0] = ipoint + 0;
00472               coords[icoord+1] = ipoint + 1;
00473               coords[icoord+2] = SO_END_LINE_INDEX;
00474               ipoint += 2;
00475               icoord += 3;
00476               empty = FALSE;
00477             }
00478             prevEdgeFlag = edgeFlag;
00479           } else {
00480             if(edgeFlag > 0) {
00481               pve.setValue(vertex[0],vertex[1],vertex[2]);
00482 
00483               if((ipoint+1)>=npoint) {
00484                 int new_npoint = 2 * npoint;
00485                 SbVec3f* new_points = new SbVec3f[new_npoint];
00486                 for(int i=0;i<npoint;i++) new_points[i] = points[i];
00487                 delete [] points;
00488                 npoint = new_npoint;
00489                 points = new_points;
00490               }
00491 
00492               if((icoord+2)>=ncoord) {
00493                 int new_ncoord = 2 * ncoord;
00494                 int32_t* new_coords = new int32_t[new_ncoord];
00495                 for(int i=0;i<ncoord;i++) new_coords[i] = coords[i];
00496                 delete [] coords;
00497                 ncoord = new_ncoord;
00498                 coords = new_coords;
00499               }
00500 
00501               points[ipoint+0] = pvb;
00502               points[ipoint+1] = pve;
00503               coords[icoord+0] = ipoint + 0;
00504               coords[icoord+1] = ipoint + 1;
00505               coords[icoord+2] = SO_END_LINE_INDEX;
00506               ipoint += 2;
00507               icoord += 3;
00508               empty = FALSE;
00509 
00510               pvb = pve;
00511             } else {
00512             }
00513           }
00514         }
00515       } while (notLastEdge);
00516     } while (notLastFace);
00517 
00518     SoCoordinate3* coordinate3 = new SoCoordinate3;
00519     coordinate3->point.setValues(0,ipoint,points);
00520     separator->addChild(coordinate3);
00521 
00522     SoIndexedLineSet* indexedLineSet = new SoIndexedLineSet;
00523     indexedLineSet->coordIndex.setValues(0,icoord,coords);
00524     separator->addChild(indexedLineSet);
00525 
00526     delete [] coords;
00527     delete [] points;
00528 
00529     if(empty==TRUE) {
00530       separator->unref();
00531     } else {
00532       alternateRep.setValue(separator);
00533     }
00534   }
00535 }
00537 void Geant4_SoPolyhedron::clearAlternateRep(
00538 ) 
00539 
00540 
00541 {
00542   alternateRep.setValue(NULL);
00543 }
00545 void Geant4_SoPolyhedron::doAction(
00546  SoAction* aAction
00547 )
00550 {
00551   SO_ALTERNATEREP_DO_ACTION(aAction)
00552   SoShape::doAction(aAction);
00553 }
00554 
00555 #endif

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