CMS 3D CMS Logo

/afs/cern.ch/work/a/aaltunda/public/www/CMSSW_5_3_13_patch3/src/Fireworks/Macros/eve_macros.cc

Go to the documentation of this file.
00001 #include <vector>
00002 #include <list>
00003 #include <string>
00004 #include <cmath>
00005 
00006 #include <TEveElement.h>
00007 #include <TEveGeoNode.h>
00008 #include <TGeoNode.h>
00009 
00010 #include "eve_macros.h"
00011 
00012 // get the name from an object derived from both TEveElement and TNamed
00013 const char* get_name( const TEveElement * element ) {
00014   // try as a TEveGeoNode or TEveGeoShape
00015   if (const TEveGeoNode * node = dynamic_cast<const TEveGeoNode *>( element ))
00016     return node->GetName();
00017   if (const TEveGeoShape * shape = dynamic_cast<const TEveGeoShape *>( element ))
00018     return shape->GetName();
00019 
00020   // try to access the element as a generic named object
00021   if (const TNamed * named = dynamic_cast<const TNamed *>( element ))
00022     return named->GetName();
00023 
00024   return 0;
00025 }
00026 
00027 // get the title from an object derived from both TEveElement and TNamed
00028 const char* get_title( const TEveElement * element ) {
00029   // try as a TEveGeoNode or TEveGeoShape
00030   if (const TEveGeoNode * node = dynamic_cast<const TEveGeoNode *>( element ))
00031     return node->GetTitle();
00032   if (const TEveGeoShape * shape = dynamic_cast<const TEveGeoShape *>( element ))
00033     return shape->GetTitle();
00034 
00035   // try to access the element as a generic named object
00036   if (const TNamed * named = dynamic_cast<const TNamed *>( element ))
00037     return named->GetTitle();
00038 
00039   return 0;
00040 }
00041 
00042 // force a node to expand its internal reprsentation, so all children are actually present
00043 void expand_node( TEveElement * element )
00044 {
00045   // force a TEveGeoNode to load all its children
00046   if (TEveGeoNode * node = dynamic_cast<TEveGeoNode *>( element )) {
00047     if (node->GetNChildren() == 0 && node->GetNode()->GetVolume()->GetNdaughters() > 0) {
00048       TIter next(node->GetNode()->GetVolume()->GetNodes());
00049       TGeoNode* dnode;
00050       while ((dnode = (TGeoNode*) next()) != 0) {
00051         TEveGeoNode* node_re = new TEveGeoNode(dnode);
00052         node->AddElement(node_re);
00053       }
00054     }
00055     return;
00056   }
00057   // a TEveGeoShape is always exanded
00058   //if (TEveGeoShape * shape __attribute__ ((unused)) = dynamic_cast<TEveGeoShape *>( element )) {
00059   //  return;
00060   //}
00061   // a generic TEveElement has no knwledge on children expansion
00062   return;
00063 }
00064 
00065 // retrieves a TShape from a TEveElement
00066 const TGeoShape * get_shape( const TEveElement * element ) {
00067   // a TEveGeoNode, can look into its TGeoNode and retrieve the shape
00068   if (const TEveGeoNode * node = dynamic_cast<const TEveGeoNode *>( element )) {
00069     return node->GetNode()->GetVolume()->GetShape();
00070   }
00071   // a TEveGeoShape owns its shape
00072   if (const TEveGeoShape * shape = dynamic_cast<const TEveGeoShape *>( element )) {
00073     TEveGeoShape * nc_shape = const_cast<TEveGeoShape *>( shape );
00074     return const_cast<const TGeoShape *>( nc_shape->GetShape() );
00075   }
00076   // a TEveElement is too generic, no way to get a shape
00077   return 0;
00078 }
00079 
00080 // overloaded non-const TShape retrieval, allowed from a TGeoShape only
00081 TGeoShape * get_shape( TEveElement * element ) {
00082   // a TEveGeoNode cannot modify its shape
00083   //if (const TEveGeoNode * node __attribute__ ((unused)) = dynamic_cast<const TEveGeoNode *>( element )) {
00084   //  return 0;
00085   //}
00086   // a TEveGeoShape owns its shape, and can modifiy it
00087   if (TEveGeoShape * shape = dynamic_cast<TEveGeoShape *>( element )) {
00088     return shape->GetShape();
00089   }
00090   // a TEveElement is too generic, no way to get a shape
00091   return 0;
00092 }
00093 
00094 // return a copy of the local-to-global transformation applied to a TEveElement
00095 TGeoMatrix * get_transform( const TEveElement * element ) {
00096   if (const TEveGeoNode * node = dynamic_cast<const TEveGeoNode *>( element )) {
00097     // a TEveGeoNode is a proxy to a TGeoNode, which knows its relative transformation wrt. its parent
00098     // so we follow the TEveGeoNode hierarchy up to a TEveGeoTopNode, then jump to its TGeoManager, and go back down the branches to the TEveGeoNode's TGeoNode
00099     std::vector< const TEveGeoNode * > nodes;
00100     const TEveGeoTopNode * top = 0;
00101 
00102     while ((top = dynamic_cast<const TEveGeoTopNode *>( node )) == 0) {
00103       // save the current node
00104       nodes.push_back(node);
00105 
00106       // check that the node actually has any parents
00107       TEveGeoNode * nc_node = const_cast<TEveGeoNode *>( node );
00108       if (nc_node->BeginParents() == nc_node->EndParents())
00109         return 0;
00110 
00111       // assume the firt parent is the good one, and check that the parent type is correct
00112       node = dynamic_cast<const TEveGeoNode *>( * nc_node->BeginParents() );
00113       if (node == 0)
00114         return 0;
00115     }
00116     // reached the top level node, start from its (optional) global transormation
00117     TGeoHMatrix * matrix = new TGeoHMatrix();
00118     (const_cast<TEveGeoTopNode *>(top))->RefGlobalTrans().SetGeoHMatrix( *matrix );
00119     for (unsigned int i = 0; i < nodes.size(); ++i)
00120       *matrix *= *(nodes[i]->GetNode()->GetMatrix());
00121     return matrix;
00122   }
00123 
00124   if (const TEveGeoShape * shape = dynamic_cast<const TEveGeoShape *>( element )) {
00125     // a TEveGeoShape knows the absolute transformation of its shape
00126     TGeoHMatrix * matrix = new TGeoHMatrix();
00127     (const_cast<TEveGeoShape *>(shape))->RefHMTrans().SetGeoHMatrix( *matrix );
00128     return matrix;
00129   }
00130 
00131   return 0;
00132 }
00133 
00134 // clone a TEveGeoShape or TEveGeoNode into a new TEveGeoShape, and add it as a child to a parent if one is given
00135 TEveGeoShape * clone( const TEveElement * element, TEveElement * parent /* = 0 */)
00136 {
00137   TEveGeoShape* shape = new TEveGeoShape( get_name(element), get_title(element) );
00138 
00139   std::auto_ptr<TGeoMatrix> matrix( get_transform(element) );
00140   shape->SetTransMatrix( matrix.get() );
00141   delete matrix;
00142 
00143   TEveGeoShapeExtract extract;                  // FIXME put name and title here...
00144   extract.SetShape( (TGeoShape *) get_shape(element)->Clone() );
00145   extract.SetTrans( trans.Array() );
00146   extract.SetRnrSelf( true );
00147   extract.SetRnrElements( true );
00148 
00149   TEveGeoShape * clone = TEveGeoShape::ImportShapeExtract( &extract, parent );
00150   return clone;
00151 }
00152 
00153 // set an element's color and alpha, and possibly its children's up to levels levels deep
00154 void set_color( TEveElement * element, Color_t color, float alpha /* = 1.0 */, unsigned int levels /* = 0 */)
00155 {
00156   if (not element)
00157     return;
00158 
00159   // set this node's color
00160   element->SetMainColor( color );
00161   if (alpha > 1.) alpha = 1.;
00162   if (alpha < 0.) alpha = 0.;
00163   unsigned char transparency = (unsigned char) roundf(100. - (alpha * 100.));
00164   element->SetMainTransparency( transparency );
00165 
00166   if (levels > 0) {
00167     // set the node's children's color
00168     expand_node( element );
00169     for (std::list<TEveElement*>::iterator i = element->BeginChildren(); i != element->EndChildren(); ++i)
00170       set_color( *i, color, alpha, levels - 1);
00171   }
00172   // notify the element that it has changed
00173   element->ElementChanged(true, true);
00174 }
00175 
00176 // check if a node has any children or if it's a leaf node
00177 bool is_leaf_node( const TEveElement * element )
00178 {
00179   // a TEveGeoNode can have unaccounted-for children
00180   if (const TEveGeoNode * node = dynamic_cast<const TEveGeoNode *>( element )) {
00181     return ((node->GetNChildren() == 0) and (node->GetNode()->GetVolume()->GetNdaughters() == 0));
00182   }
00183   // a TEveGeoShape always knows its children
00184   if (const TEveGeoShape * shape = dynamic_cast<const TEveGeoShape *>( element )) {
00185     return (shape->GetNChildren() == 0);
00186   }
00187   // default implementation
00188   return (element->GetNChildren() == 0);
00189 }
00190 
00191 // toggle an elements's children visibility, based on their name
00192 // names are checked only up to their length, so for example tec:TEC will match both tec:TEC_1 and tec:TEC_2
00193 void set_children_visibility( TEveElement * element, const std::string & node_name, const std::vector<std::string> & children_name, bool visibility )
00194 {
00195   // try to access the element as a named thingy
00196   const char * name = get_name( element );
00197   if (not name or strncmp(name, node_name.c_str(), node_name.size()))
00198     // unnamed node, or wrong node
00199     return;
00200 
00201   for (std::list<TEveElement *>::iterator j = element->BeginChildren(); j != element->EndChildren(); ++j) {
00202     TEveElement * child = *j;
00203     name = get_name( child );
00204     if (not name)
00205       // unnamed node, ignore it
00206       continue;
00207 
00208     for (unsigned int i = 0; i < children_name.size(); ++i)
00209       if (not strncmp(name, children_name[i].c_str(), children_name[i].size())) {
00210         // change this child visibility
00211         if (is_leaf_node( child )) {
00212           child->SetRnrSelf( visibility );
00213           child->SetRnrChildren( false );
00214         } else {
00215           child->SetRnrSelf( false );
00216           child->SetRnrChildren( visibility );
00217         }
00218         break;
00219       }
00220   }
00221   // notify the element that is had changed
00222   element->ElementChanged(true, true);
00223 }
00224 
00225 // set Tracker's Endcaps visibility
00226 void set_tracker_endcap_visibility( TEveElement * tracker, bool visibility )
00227 {
00228   std::vector<std::string> endcap;
00229   endcap.push_back("tec:TEC");
00230   endcap.push_back("tidf:TIDF");
00231   endcap.push_back("tidb:TIDB");
00232   endcap.push_back("pixfwd:PixelForwardZPlus");
00233   endcap.push_back("pixfwd:PixelForwardZMinus");
00234   set_children_visibility( tracker, "tracker:Tracker", endcap, visibility );
00235 }
00236 
00237 // show Tracker's Endcaps
00238 void show_tracker_endcap( TEveElement * tracker )
00239 {
00240   set_tracker_endcap_visibility( tracker, true );
00241 }
00242 
00243 // hide Tracker's Endcaps
00244 void hide_tracker_endcap( TEveElement * tracker )
00245 {
00246   set_tracker_endcap_visibility( tracker, false );
00247 }
00248