G4XXXSGSceneHandler.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 // $Id$
00028 //
00029 // 
00030 // John Allison  10th March 2006
00031 // A template for a sophisticated graphics driver with a scene graph.
00032 //?? Lines beginning like this require specialisation for your driver.
00033 
00034 #include "G4XXXSGSceneHandler.hh"
00035 
00036 #include "G4XXXSGViewer.hh"
00037 #include "G4PhysicalVolumeModel.hh"
00038 #include "G4LogicalVolumeModel.hh"
00039 #include "G4VPhysicalVolume.hh"
00040 #include "G4LogicalVolume.hh"
00041 #include "G4Box.hh"
00042 #include "G4Polyline.hh"
00043 #include "G4Text.hh"
00044 #include "G4Circle.hh"
00045 #include "G4Square.hh"
00046 #include "G4Polyhedron.hh"
00047 #include "G4UnitsTable.hh"
00048 
00049 #include <sstream>
00050 
00051 G4int G4XXXSGSceneHandler::fSceneIdCount = 0;
00052 // Counter for XXX scene handlers.
00053 
00054 G4XXXSGSceneHandler::G4XXXSGSceneHandler(G4VGraphicsSystem& system,
00055                                              const G4String& name):
00056   G4VSceneHandler(system, fSceneIdCount++, name)
00057 {}
00058 
00059 G4XXXSGSceneHandler::~G4XXXSGSceneHandler() {}
00060 
00061 #ifdef G4XXXSGDEBUG
00062 // Useful function...
00063 void G4XXXSGSceneHandler::PrintThings() {
00064   G4cout <<
00065     "  with transformation "
00066          << (void*)fpObjectTransformation;
00067   if (fpModel) {
00068     G4cout << " from " << fpModel->GetCurrentDescription()
00069            << " (tag " << fpModel->GetCurrentTag()
00070            << ')';
00071   } else {
00072     G4cout << "(not from a model)";
00073   }
00074   G4PhysicalVolumeModel* pPVModel =
00075     dynamic_cast<G4PhysicalVolumeModel*>(fpModel);
00076   if (pPVModel) {
00077     G4cout <<
00078       "\n  current physical volume: "
00079            << pPVModel->GetCurrentPV()->GetName() <<
00080       "\n  current logical volume: "
00081 // There might be a problem with the LV pointer if this is a G4LogicalVolumeModel
00082            << pPVModel->GetCurrentLV()->GetName() <<
00083       "\n  current depth of geometry tree: "
00084            << pPVModel->GetCurrentDepth();
00085   }
00086   G4cout << G4endl;
00087 }
00088 #endif
00089 
00090 void G4XXXSGSceneHandler::CreateCurrentItem(const G4String& /*header*/) {
00091   // Utility for PreAddSolid and BeginPrimitives.
00092   
00093   G4PhysicalVolumeModel* pPVModel =
00094     dynamic_cast<G4PhysicalVolumeModel*>(fpModel);
00095   G4LogicalVolumeModel* pLVModel =
00096     dynamic_cast<G4LogicalVolumeModel*>(pPVModel);
00097   if (pPVModel && !pLVModel) {
00098 
00099     // This call comes from a G4PhysicalVolumeModel.  drawnPVPath is
00100     // the path of the current drawn (non-culled) volume in terms of
00101     // drawn (non-culled) ancesters.  Each node is identified by a
00102     // PVNodeID object, which is a physical volume and copy number.  It
00103     // is a vector of PVNodeIDs corresponding to the geometry hierarchy
00104     // actually selected, i.e., not culled.
00105     typedef G4PhysicalVolumeModel::G4PhysicalVolumeNodeID PVNodeID;
00106     typedef std::vector<PVNodeID> PVPath;
00107     const PVPath& drawnPVPath = pPVModel->GetDrawnPVPath();
00108     //G4int currentDepth = pPVModel->GetCurrentDepth();
00109     //G4VPhysicalVolume* pCurrentPV = pPVModel->GetCurrentPV();
00110     //G4LogicalVolume* pCurrentLV = pPVModel->GetCurrentLV();
00111     //G4Material* pCurrentMaterial = pPVModel->GetCurrentMaterial();
00112     // Note: pCurrentMaterial may be zero (parallel world).
00113 
00114     // The simplest algorithm, used by the Open Inventor Driver
00115     // developers, is to rely on the fact the G4PhysicalVolumeModel
00116     // traverses the geometry hierarchy in an orderly manner.  The last
00117     // mother, if any, will be the node to which the volume should be
00118     // added.  So it is enough to keep a map of scene graph nodes keyed
00119     // on the volume path ID.  Actually, it is enough to use the logical
00120     // volume as the key.  (An alternative would be to keep the PVNodeID
00121     // in the tree and match the PVPath from the root down.)
00122 
00123     // BUT IN OPENGL, IF THERE ARE TRANSPARENT OBJECTS, VOLUMES DO NOT
00124     // ARRIVE IN THE ABOVE ORDER.  (TRANSPARENT OBJECTS ARE DRWAN
00125     // LAST.)  SO WE MUST BE MORE SOPHISTICATED IN CONSTRUCTING A
00126     // TREE.
00127 
00128     /* Debug
00129     for (size_t i = 0; i < drawnPVPath.size(); ++i) {
00130       std::cout << drawnPVPath[i].GetPhysicalVolume()->GetName() << ":"
00131             << drawnPVPath[i].GetCopyNo() << " ("
00132             << currentPOListIndex << "), ";
00133     }
00134     std::cout << std::endl;
00135     */
00136 
00137     static G4int index = 0;  // Some index for future reference
00138     JA::Insert(&drawnPVPath[0],drawnPVPath.size(),index++,&fSceneGraph);
00139     //JA::PrintTree(std::cout,&root);
00140 
00141     /***  Old algorithm, left here for historical interest!!
00142     // Find mother.  ri points to drawn mother, if any.
00143     PVPath::const_reverse_iterator ri = ++drawnPVPath.rbegin();
00144     if (ri != drawnPVPath.rend()) {
00145       // This volume has a mother.
00146       G4LogicalVolume* drawnMotherLV =
00147         ri->GetPhysicalVolume()->GetLogicalVolume();
00148       LVMapIterator mother = fLVMap.find(drawnMotherLV);
00149       if (mother != fLVMap.end()) {
00150         // This adds a child in Troy's tree...
00151         fCurrentItem = mother->second.push_back(header);
00152       } else {
00153         // Mother not previously encountered.  Shouldn't happen, since
00154         // G4PhysicalVolumeModel sends volumes as it encounters them,
00155         // i.e., mothers before daughters, in its descent of the
00156         // geometry tree.  Error!
00157         G4cout << "ERROR: G4XXXSGSceneHandler::PreAddSolid: Mother "
00158                << ri->GetPhysicalVolume()->GetName()
00159                << ':' << ri->GetCopyNo()
00160                << " not previously encountered."
00161           "\nShouldn't happen!  Please report to visualization coordinator."
00162                << G4endl;
00163         // Continue anyway.  Add to root of scene graph tree...
00164         fCurrentItem = fPermanentsRoot.push_back(header);
00165       }
00166     } else {
00167       // This volume has no mother.  Must be a top level un-culled
00168       // volume.  Add to root of scene graph tree...
00169       fCurrentItem = fPermanentsRoot.push_back(header);
00170     }
00171 
00172     std::ostringstream oss;
00173     oss << "Path of drawn PVs: ";
00174     for (PVPath::const_iterator i = drawnPVPath.begin();
00175          i != drawnPVPath.end(); ++i) {
00176       oss << '/' << i->GetPhysicalVolume()->GetName()
00177           << ':' << i->GetCopyNo();
00178     }
00179     oss << std::endl;
00180     *fCurrentItem += oss.str();
00181 
00182     // Store for future searches.  Overwrites previous entries for this
00183     // LV, so entry is always the *last* LV.
00184     fLVMap[pCurrentLV] = fCurrentItem;
00185     ***/
00186 
00187   } else {  // Not from a G4PhysicalVolumeModel.
00188 
00189     /***
00190     // Create a place for current solid in root...
00191     if (fReadyForTransients) {
00192       fCurrentItem = fTransientsRoot.push_back(header);
00193     } else {
00194       fCurrentItem = fPermanentsRoot.push_back(header);
00195     }
00196     ***/
00197   }
00198 }
00199 
00200 void G4XXXSGSceneHandler::PreAddSolid
00201 (const G4Transform3D& objectTransformation,
00202  const G4VisAttributes& visAttribs)
00203 {  
00204   G4VSceneHandler::PreAddSolid(objectTransformation, visAttribs);
00205   CreateCurrentItem(G4String("\nPreAddSolid:\n"));
00206 }
00207 
00208 void G4XXXSGSceneHandler::PostAddSolid()
00209 {
00210   G4VSceneHandler::PostAddSolid();
00211 }
00212 
00213 void G4XXXSGSceneHandler::BeginPrimitives
00214 (const G4Transform3D& objectTransformation)
00215 {
00216   G4VSceneHandler::BeginPrimitives(objectTransformation);
00217 }
00218 
00219 void G4XXXSGSceneHandler::EndPrimitives ()
00220 {
00221   G4VSceneHandler::EndPrimitives ();
00222 }
00223 
00224 // Note: This function overrides G4VSceneHandler::AddSolid(const
00225 // G4Box&).  You may not want to do this, but this is how it's done if
00226 // you do.  Certain other specific solids may be treated this way -
00227 // see G4VSceneHandler.hh.  The simplest possible driver would *not*
00228 // implement these polymorphic functions, with the effect that the
00229 // default versions in G4VSceneHandler are used, which simply call
00230 // G4VSceneHandler::RequestPrimitives to turn the solid into a
00231 // G4Polyhedron usually.
00232 // Don't forget, solids can be transients too (e.g., representing a hit).
00233 void G4XXXSGSceneHandler::AddSolid(const G4Box& box) {
00234 #ifdef G4XXXSGDEBUG
00235   G4cout <<
00236     "G4XXXSGSceneHandler::AddSolid(const G4Box& box) called for "
00237          << box.GetName()
00238          << G4endl;
00239 #endif
00240   //?? Process your box...
00241   std::ostringstream oss;
00242   oss << "G4Box(" <<
00243     G4String
00244     (G4BestUnit
00245      (G4ThreeVector
00246       (box.GetXHalfLength(), box.GetYHalfLength(), box.GetZHalfLength()),
00247       "Length")).strip() << ')' << std::endl;
00248   //*fCurrentItem += oss.str();
00249 }
00250 
00251 void G4XXXSGSceneHandler::AddPrimitive(const G4Polyline& polyline) {
00252 #ifdef G4XXXSGDEBUG
00253   G4cout <<
00254     "G4XXXSGSceneHandler::AddPrimitive(const G4Polyline& polyline) called.\n"
00255          << polyline
00256          << G4endl;
00257 #endif
00258   // Get vis attributes - pick up defaults if none.
00259   //const G4VisAttributes* pVA =
00260   //  fpViewer -> GetApplicableVisAttributes (polyline.GetVisAttributes ());
00261   //?? Process polyline.
00262   std::ostringstream oss;
00263   oss << polyline << std::endl;
00264   //*fCurrentItem += oss.str();
00265 }
00266 
00267 void G4XXXSGSceneHandler::AddPrimitive(const G4Text& text) {
00268 #ifdef G4XXXSGDEBUG
00269   G4cout <<
00270     "G4XXXSGSceneHandler::AddPrimitive(const G4Text& text) called.\n"
00271          << text
00272          << G4endl;
00273 #endif
00274   // Get text colour - special method since default text colour is
00275   // determined by the default text vis attributes, which may be
00276   // specified independent of default vis attributes of other types of
00277   // visible objects.
00278   //const G4Colour& c = GetTextColour (text);  // Picks up default if none.
00279   //?? Process text.
00280   std::ostringstream oss;
00281   oss << text << std::endl;
00282   //*fCurrentItem += oss.str();
00283 }
00284 
00285 void G4XXXSGSceneHandler::AddPrimitive(const G4Circle& circle) {
00286 #ifdef G4XXXSGDEBUG
00287   G4cout <<
00288     "G4XXXSGSceneHandler::AddPrimitive(const G4Circle& circle) called.\n"
00289          << circle
00290          << G4endl; 
00291   MarkerSizeType sizeType;
00292   G4double size = GetMarkerSize (circle, sizeType);
00293   switch (sizeType) {
00294   default:
00295   case screen:
00296     // Draw in screen coordinates.
00297     G4cout << "screen";
00298     break;
00299   case world:
00300     // Draw in world coordinates.
00301     G4cout << "world";
00302     break;
00303   }
00304   G4cout << " size: " << size << G4endl;
00305 #endif
00306   // Get vis attributes - pick up defaults if none.
00307   //const G4VisAttributes* pVA =
00308   //  fpViewer -> GetApplicableVisAttributes (circle.GetVisAttributes ());
00309   //?? Process circle.
00310   std::ostringstream oss;
00311   oss << circle << std::endl;
00312   //*fCurrentItem += oss.str();
00313 }
00314 
00315 void G4XXXSGSceneHandler::AddPrimitive(const G4Square& square) {
00316 #ifdef G4XXXSGDEBUG
00317   G4cout <<
00318     "G4XXXSGSceneHandler::AddPrimitive(const G4Square& square) called.\n"
00319          << square
00320          << G4endl;
00321   MarkerSizeType sizeType;
00322   G4double size = GetMarkerSize (square, sizeType);
00323   switch (sizeType) {
00324   default:
00325   case screen:
00326     // Draw in screen coordinates.
00327     G4cout << "screen";
00328     break;
00329   case world:
00330     // Draw in world coordinates.
00331     G4cout << "world";
00332     break;
00333   }
00334   G4cout << " size: " << size << G4endl;
00335 #endif
00336   // Get vis attributes - pick up defaults if none.
00337   //const G4VisAttributes* pVA =
00338   //  fpViewer -> GetApplicableVisAttributes (square.GetVisAttributes ());
00339   //?? Process square.
00340   std::ostringstream oss;
00341   oss << square << std::endl;
00342   //*fCurrentItem += oss.str();
00343 }
00344 
00345 void G4XXXSGSceneHandler::AddPrimitive(const G4Polyhedron& polyhedron) {
00346 #ifdef G4XXXSGDEBUG
00347   G4cout <<
00348  "G4XXXSGSceneHandler::AddPrimitive(const G4Polyhedron& polyhedron) called.\n"
00349          << polyhedron
00350          << G4endl;
00351 #endif
00352   //?? Process polyhedron.
00353   std::ostringstream oss;
00354   oss << polyhedron;
00355   //*fCurrentItem += oss.str();
00356 
00357   //?? Or... here are some ideas for decomposing into polygons...
00358   //Assume all facets are convex quadrilaterals.
00359   //Draw each G4Facet individually
00360   
00361   //Get colour, etc..
00362   if (polyhedron.GetNoFacets() == 0) return;
00363 
00364   // Get vis attributes - pick up defaults if none.
00365   const G4VisAttributes* pVA =
00366     fpViewer -> GetApplicableVisAttributes (polyhedron.GetVisAttributes ());
00367 
00368   // Get view parameters that the user can force through the vis
00369   // attributes, thereby over-riding the current view parameter.
00370   G4ViewParameters::DrawingStyle drawing_style = GetDrawingStyle (pVA);
00371   //G4bool isAuxEdgeVisible = GetAuxEdgeVisible (pVA);
00372   
00373   //Get colour, etc..
00374   //const G4Colour& c = pVA -> GetColour ();
00375   
00376   // Initial action depending on drawing style.
00377   switch (drawing_style) {
00378   case (G4ViewParameters::hsr):
00379     {
00380       break;
00381     }
00382   case (G4ViewParameters::hlr):
00383     {
00384       break;
00385     }
00386   case (G4ViewParameters::wireframe):
00387     {
00388       break;
00389     }
00390   default:
00391     {
00392       break;
00393     }     
00394   }
00395 
00396   // Loop through all the facets...
00397 
00398   // Look at G4OpenGLSceneHandler::AddPrimitive(const G4Polyhedron&)
00399   // for an example of how to get facets out of a G4Polyhedron,
00400   // including how to cope with triangles if that's a problem.
00401 }
00402 
00403 void G4XXXSGSceneHandler::AddPrimitive(const G4NURBS&) {
00404 #ifdef G4XXXSGDEBUG
00405   G4cout <<
00406     "G4XXXSGSceneHandler::AddPrimitive(const G4NURBS& nurbs) called."
00407          << G4endl;
00408 #endif
00409   //?? Don't bother implementing this.  NURBS are not functional.
00410 }
00411 
00412 void G4XXXSGSceneHandler::ClearStore ()
00413 {
00414   JA::Clear(&fSceneGraph);
00415 }
00416 
00417 void G4XXXSGSceneHandler::ClearTransientStore ()
00418 {
00419   JA::Clear(&fSceneGraph);
00420 }
00421 
00422 namespace JA {
00423 // Ad hoc tree class and utilities.
00424 
00425 #include "G4VPhysicalVolume.hh"
00426 
00427 void Insert(const PVNodeID* pvPath, size_t pathLength,
00428                 G4int index, Node* node) {
00429   // Path passed as a PVNodeID* to avoid copying.
00430 
00431   /* Debug
00432   for (size_t i = 0; i < pathLength; ++i) {
00433     std::cout << pvPath[i].GetPhysicalVolume()->GetName() << ":"
00434               << pvPath[i].GetCopyNo() << " ("
00435               << index << "), ";
00436   }
00437   */
00438 
00439   // See if node has been encountered before
00440   G4bool found = false; size_t foundPosition = 0;
00441   for (size_t i = 0; i < node->fDaughters.size(); ++i) {
00442     PVNodeID& daughterPVNodeID = node->fDaughters[i]->fPVNodeID;
00443     // It is enough to compare volume and copy number at a given position in the tree
00444     if (daughterPVNodeID.GetPhysicalVolume() == pvPath[0].GetPhysicalVolume() &&
00445         daughterPVNodeID.GetCopyNo() == pvPath[0].GetCopyNo()) {
00446       found = true;
00447       foundPosition = i;
00448       break;
00449     }
00450   }
00451 
00452   if (pathLength == 1) {  // This is a leaf
00453     if (found) {  // Update index
00454       node->fDaughters[foundPosition]->fIndex = index;
00455     } else {      // Make a new full entry
00456       node->fDaughters.push_back(new Node(pvPath[0],index));
00457     }
00458     /* Debug
00459     std::cout << std::endl;
00460     */
00461   } else {  // Not a leaf - carry on with rest of path
00462     if (found) {  // Just carry on
00463       Insert(pvPath+1,--pathLength,index,
00464              node->fDaughters[foundPosition]);
00465     } else {      // Insert place holder, then carry on
00466       node->fDaughters.push_back(new Node(pvPath[0]));
00467       Insert(pvPath+1,--pathLength,index,
00468              node->fDaughters[node->fDaughters.size()-1]);
00469     }
00470   }
00471 }
00472 
00473 void PrintTree(std::ostream& os, Node* node)
00474 {
00475   static G4int depth = -1;
00476   depth++;
00477   PVNodeID& thisPVNodeID = node->fPVNodeID;
00478   G4int& thisIndex = node->fIndex;
00479   const size_t& nDaughters = node->fDaughters.size();
00480   G4VPhysicalVolume* thisPhysicalVolume= thisPVNodeID.GetPhysicalVolume();
00481   if (!thisPhysicalVolume) os << "Root" << std::endl;
00482   else {
00483     for (G4int i = 0; i < depth; ++i) os << "__";
00484     os << thisPVNodeID.GetPhysicalVolume()->GetName() << ":"
00485        << thisPVNodeID.GetCopyNo() << " ("
00486        << thisIndex << ")" << std::endl;;
00487   }
00488   for (size_t i = 0; i < nDaughters; ++i) {
00489     PrintTree(os, node->fDaughters[i]);
00490   }
00491   depth--;
00492 }
00493 
00494 void Clear(Node* node)
00495 {
00496   const size_t& nDaughters = node->fDaughters.size();
00497   for (size_t i = 0; i < nDaughters; ++i) {
00498     Clear(node->fDaughters[i]);
00499     delete node->fDaughters[i];
00500   }
00501 }
00502 
00503 } // End namespace JA

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