From 8391c6f222ae91a8100b377b89a17951a0209f21 Mon Sep 17 00:00:00 2001
From: Frank Gaede <frank.gaede@desy.de>
Date: Thu, 17 Apr 2014 09:51:11 +0000
Subject: [PATCH]  - added functionality to draw surfaces in teve_display  -
 new method Surface::getVertices() (only planes so far)  - added some
 convenient methods to Vector3D

---
 DDRec/include/DDRec/Surface.h            |  12 +-
 DDRec/src/Surface.cpp                    | 129 ++++++++++++++++
 DDSurfaces/include/DDSurfaces/Vector3D.h |  25 +++-
 UtilityApps/CMakeLists.txt               |   8 +-
 UtilityApps/src/teve_display.cpp         | 180 ++++++++++++++++++++++-
 examples/ILDExSimu/src/test_surfaces.cc  |  27 +++-
 6 files changed, 365 insertions(+), 16 deletions(-)

diff --git a/DDRec/include/DDRec/Surface.h b/DDRec/include/DDRec/Surface.h
index 9f7ba349c..605947e0b 100644
--- a/DDRec/include/DDRec/Surface.h
+++ b/DDRec/include/DDRec/Surface.h
@@ -297,7 +297,6 @@ namespace DD4hep {
       Vector3D _n ;
       Vector3D _o ;
 
-    
       Surface() :_det( Geometry::DetElement() ), _volSurf( VolSurface() ), _wtM( 0 ) , _id( 0)  { }
 
     public:
@@ -314,6 +313,11 @@ namespace DD4hep {
        */
       virtual const SurfaceType& type() const { return _type ; }
     
+      Geometry::Volume volume() const { return _volSurf.volume()  ; }
+
+      VolSurface volSurface() const { return _volSurf ; }
+
+
       //==== geometry ====
       
       /** First direction of measurement U */
@@ -346,6 +350,12 @@ namespace DD4hep {
       /// Checks if the given point lies within the surface
       virtual bool insideBounds(const Vector3D& point, double epsilon=1.e-4) const ;
 
+      //---------------------------------------------------
+      /** Get vertices constraining the surface for drawing ( might not be exact boundaries) -
+       *  at most nMax points are returned.
+       */
+      std::vector< Vector3D > getVertices( unsigned nMax=360 ) ;
+
     protected:
       void initialize() ;
 
diff --git a/DDRec/src/Surface.cpp b/DDRec/src/Surface.cpp
index 02dcf69cf..9f2081ec2 100644
--- a/DDRec/src/Surface.cpp
+++ b/DDRec/src/Surface.cpp
@@ -6,6 +6,8 @@
 #include <exception>
 
 #include "TGeoMatrix.h"
+#include "TGeoShape.h"
+#include "TRotation.h"
 
 namespace DD4hep {
   namespace DDRec {
@@ -374,6 +376,133 @@ namespace DD4hep {
     }
     //===================================================================================================================
       
+    std::vector< Vector3D > Surface::getVertices(unsigned nMax) {
+
+
+      const static double epsilon = 1e-6 ; 
+
+      std::vector< Vector3D > _vert ;
+
+	
+      // get local and global surface vectors
+      const DDSurfaces::Vector3D& lu = _volSurf.u() ;
+      const DDSurfaces::Vector3D& lv = _volSurf.v() ;
+      const DDSurfaces::Vector3D& ln = _volSurf.normal() ;
+      const DDSurfaces::Vector3D& lo = _volSurf.origin() ;
+      
+      Volume vol = volume() ; 
+      const TGeoShape* shape = vol->GetShape() ;
+      
+      
+      if( type().isPlane() ) {
+	
+	if( shape->IsA() == TGeoBBox::Class() ) {
+	  
+	  TGeoBBox* box = ( TGeoBBox* ) shape  ;
+	  
+	  DDSurfaces::Vector3D boxDim(  box->GetDX() , box->GetDY() , box->GetDZ() ) ;  
+	  
+	  
+	  bool isYZ = std::fabs(  ln.x() - 1.0 ) < epsilon  ; // normal parallel to x
+	  bool isXZ = std::fabs(  ln.y() - 1.0 ) < epsilon  ; // normal parallel to y
+	  bool isXY = std::fabs(  ln.z() - 1.0 ) < epsilon  ; // normal parallel to z
+	  
+	  
+	  if( isYZ || isXZ || isXY ) {  // plane is parallel to one of the box' sides -> need 4 vertices from box dimensions
+	    
+	    // if isYZ :
+	    unsigned uidx = 1 ;
+	    unsigned vidx = 2 ;
+	    
+	    DDSurfaces::Vector3D ubl(  0., 1., 0. ) ; 
+	    DDSurfaces::Vector3D vbl(  0., 0., 1. ) ;
+	    
+	    if( isXZ ) {
+	      
+	      ubl.fill( 1., 0., 0. ) ;
+	      vbl.fill( 0., 0., 1. ) ;
+	      uidx = 0 ;
+	      vidx = 2 ;
+	      
+	    } else if( isXY ) {
+	      
+	      ubl.fill( 1., 0., 0. ) ;
+	      vbl.fill( 0., 1., 0. ) ;
+	      uidx = 0 ;
+	      vidx = 1 ;
+	    }
+	    
+	    DDSurfaces::Vector3D ub ;
+	    DDSurfaces::Vector3D vb ;
+	    _wtM->LocalToMasterVect( ubl , ub.array() ) ;
+	    _wtM->LocalToMasterVect( vbl , vb.array() ) ;
+	    
+	    _vert.resize(4) ;
+	    
+	    _vert[0] = _o + boxDim[ uidx ] * ub  + boxDim[ vidx ] * vb ;
+	    _vert[1] = _o - boxDim[ uidx ] * ub  + boxDim[ vidx ] * vb ;
+	    _vert[2] = _o - boxDim[ uidx ] * ub  - boxDim[ vidx ] * vb ;
+	    _vert[3] = _o + boxDim[ uidx ] * ub  - boxDim[ vidx ] * vb ;
+	    
+	    return _vert ;
+	  }	    
+	}
+	
+	// ===== default for arbitrary planes in arbitrary shapes ================= 
+	
+	// We create nMax vertices by rotating the local u vector around the normal
+	// and checking the distance to the volume boundary in that direction.
+	// This is brute force and not very smart, as many points are created on straight 
+	// lines and the edges are still rounded. 
+	// The alterative would be to compute the true intersections a plane and the most
+	// common shapes - at least for boxes that should be not too hard. To be done...
+	
+	_vert.resize( nMax ) ;
+	
+	double dAlpha =  2.* ROOT::Math::Pi() / double( nMax ) ; 
+
+	TVector3 normal( ln.x() , ln.y() , ln.z() ) ;
+
+	for(unsigned i=0 ; i< nMax ; ++i ){ 
+	  
+	  double alpha = double(i) * dAlpha ;
+	  
+	  TVector3 vec( lu.x() , lu.y() , lu.z() ) ;
+
+	  TRotation rot ;
+	  rot.Rotate( alpha , normal );
+	
+	  TVector3 vecR = rot * vec ;
+	  
+	  DDSurfaces::Vector3D luRot ;
+	  luRot.fill( vecR ) ;
+ 	  
+	  double dist = shape->DistFromInside( lo, luRot , 3, 0.1 ) ;
+	  
+	  // local point at volume boundary
+	  DDSurfaces::Vector3D lp = lo + dist * luRot ;
+
+	  DDSurfaces::Vector3D gp ;
+	  
+	  _wtM->LocalToMaster( lp , gp.array() ) ;
+
+	  //	  std::cout << " **** normal:" << ln << " lu:" << lu  << " alpha:" << alpha << " luRot:" << luRot << " lp :" << lp  << " gp:" << gp << std::endl;
+
+	  _vert[i] = gp ;
+	}
+
+
+      } else { // cylinder 
+
+	  // TODO
+      }
+
+      return _vert ;
+
+    }
+
+    //===================================================================================================================
+
 
   } // namespace
 } // namespace
diff --git a/DDSurfaces/include/DDSurfaces/Vector3D.h b/DDSurfaces/include/DDSurfaces/Vector3D.h
index 530d73634..dae2cc3f4 100644
--- a/DDSurfaces/include/DDSurfaces/Vector3D.h
+++ b/DDSurfaces/include/DDSurfaces/Vector3D.h
@@ -55,18 +55,28 @@ namespace DDSurfaces {
     // }
     
 
+    /// fill vector from arbitrary class that defines operator[] 
+    template <class T>
+    inline const Vector3D& fill(  const T& v  ) {    
+
+      _x = v[0] ; _y = v[1] ; _z = v[2] ; 
+      return *this ;
+    }  
+
+    /// fill vector from double array
     inline const Vector3D& fill( const double* v) {    
 
       _x = v[0] ; _y = v[1] ; _z = v[2] ; 
       return *this ;
     }  
 
+    /// fill from double values
     inline const Vector3D& fill( double x, double y, double z) {    
-
       _x = x ; _y = y ; _z = z ; 
       return *this ;
     }  
 
+
     /** Cartesian x coordinate */
     inline double x() const { return  _x ; }
     
@@ -86,7 +96,7 @@ namespace DDSurfaces {
     inline double& z() { return  _z ; }
     
     
-    /** Accessing x,y,z with bracket operator */
+   /** Accessing x,y,z with bracket operator */
     inline double operator[](int i) const {
       switch(i) {
       case 0: return _x ; break ;
@@ -176,6 +186,11 @@ namespace DDSurfaces {
       return &_x ;
     }
 
+    /// direct access to data as double* - allows modification 
+    inline double* array() {
+      return &_x ;
+    }
+
 
     /** Implicit templated conversion to anything that has a c'tor T(x,y,z) 
      *  and accessor functions x(),y(),z(). For safety the result is checked which 
@@ -249,6 +264,12 @@ namespace DDSurfaces {
     return Vector3D( s * v.x()  , s * v.y()  ,  s * v.z() ) ;
   }
   
+ /** Negative vector */
+  inline Vector3D operator-(  const Vector3D& v) { 
+    
+    return Vector3D( -v.x(), - v.y(), - v.z()  ) ;
+  }
+
   /// operator for scalar product
   inline double operator*( const Vector3D& v0, const Vector3D& v1 ){
     return v0.dot( v1 ) ;
diff --git a/UtilityApps/CMakeLists.txt b/UtilityApps/CMakeLists.txt
index 5517871f9..300988a62 100644
--- a/UtilityApps/CMakeLists.txt
+++ b/UtilityApps/CMakeLists.txt
@@ -2,11 +2,13 @@ cmake_minimum_required(VERSION 2.8.3 FATAL_ERROR)
 
 include_directories( ${CMAKE_SOURCE_DIR}/DDCore/include 
                      ${ROOT_INCLUDE_DIR}
-                     ${CMAKE_SOURCE_DIR}/DDSegmentation/include)
+                     ${CMAKE_SOURCE_DIR}/DDSegmentation/include
+                     ${CMAKE_SOURCE_DIR}/DDSurfaces/include
+                     ${CMAKE_SOURCE_DIR}/DDRec/include )
 
 #-----------------------------------------------------------------------------------
 add_executable(geoDisplay src/display.cpp)
-target_link_libraries(geoDisplay DD4hepCore)
+target_link_libraries(geoDisplay DD4hepCore )
 #-----------------------------------------------------------------------------------
 add_executable(geoConverter src/converter.cpp)
 target_link_libraries(geoConverter DD4hepCore)
@@ -15,7 +17,7 @@ add_executable(geoPluginRun src/plugin_runner.cpp)
 target_link_libraries(geoPluginRun DD4hepCore)
 #-----------------------------------------------------------------------------------
 add_executable(teveDisplay src/teve_display.cpp)
-target_link_libraries(teveDisplay DD4hepCore ${ROOT_EVE_LIBRARIES})
+target_link_libraries(teveDisplay DD4hepCore ${ROOT_EVE_LIBRARIES} DD4hepRec )
 
 #--- install target-------------------------------------
 
diff --git a/UtilityApps/src/teve_display.cpp b/UtilityApps/src/teve_display.cpp
index 5bec5df6d..3a2378cbe 100644
--- a/UtilityApps/src/teve_display.cpp
+++ b/UtilityApps/src/teve_display.cpp
@@ -10,6 +10,9 @@
 //====================================================================
 #include "DD4hep/Factories.h"
 #include "DD4hep/LCDD.h"
+#include "DDRec/SurfaceManager.h"
+
+
 #include "run_plugin.h"
 #include "TRint.h"
 #include "TEveGeoNode.h"
@@ -25,26 +28,194 @@
 #define private public
 #include "TEveManager.h"
 
+#include "TEveStraightLineSet.h"
+#include "TRandom.h"
+#include "TGeoShape.h"
+
+using namespace DD4hep ;
+using namespace DDRec ;
+using namespace Geometry ;
+using namespace DDSurfaces ;
+
+//=====================================================================================
+TEveStraightLineSet* drawSurfaceVectors() {
+
+  TEveStraightLineSet* ls = new TEveStraightLineSet("SurfaceVectors");
+
+  LCDD& lcdd = LCDD::getInstance();
+
+  DetElement world = lcdd.world() ;
+
+  // create a list of all surfaces in the detector:
+  SurfaceManager surfMan(  world ) ;
+
+  const SurfaceList& sL = surfMan.surfaceList() ;
+
+  for( SurfaceList::const_iterator it = sL.begin() ; it != sL.end() ; ++it ){
+
+    ISurface* surf = *it ;
+    const DDSurfaces::Vector3D& u = surf->u() ;
+    const DDSurfaces::Vector3D& v = surf->v() ;
+    const DDSurfaces::Vector3D& n = surf->normal() ;
+    const DDSurfaces::Vector3D& o = surf->origin() ;
+
+    DDSurfaces::Vector3D ou = o + u ;
+    DDSurfaces::Vector3D ov = o + v ;
+    DDSurfaces::Vector3D on = o + n ;
+ 
+    ls->AddLine( o.x(), o.y(), o.z(), ou.x() , ou.y() , ou.z()  ) ;
+    ls->AddLine( o.x(), o.y(), o.z(), ov.x() , ov.y() , ov.z()  ) ;
+    ls->AddLine( o.x(), o.y(), o.z(), on.x() , on.y() , on.z()  ) ;
+
+    ls->AddMarker(  o.x(), o.y(), o.z() );
+  }
+  ls->SetLineColor( kGreen ) ;
+  ls->SetMarkerColor( kBlue ) ;
+  ls->SetMarkerSize(1);
+  ls->SetMarkerStyle(4);
+  
+  gEve->AddElement(ls);
+
+  return ls;
+}
+//=====================================================================================
+TEveStraightLineSet* drawSurfaces() {
+
+  TEveStraightLineSet* ls = new TEveStraightLineSet("Surfaces");
+
+  LCDD& lcdd = LCDD::getInstance();
+
+  DetElement world = lcdd.world() ;
+
+  // create a list of all surfaces in the detector:
+  SurfaceManager surfMan(  world ) ;
+
+  const SurfaceList& sL = surfMan.surfaceList() ;
+
+  for( SurfaceList::const_iterator it = sL.begin() ; it != sL.end() ; ++it ){
+
+    Surface* surf = *it ;
+
+    const std::vector< Vector3D > vert = surf->getVertices() ;
+
+    if( vert.empty() )
+      std::cout << " **** drawSurfaces() : empty vertices for surface " << *surf << std::endl ;
+
+    unsigned nV = vert.size() ;
+
+    for( unsigned i=0 ; i<nV ; ++i){
+
+      unsigned j = ( i < nV-1 ?  i+1 : 0 ) ;
+
+      ls->AddLine( vert[i].x(), vert[i].y(), vert[i].z(), vert[j].x() , vert[j].y() , vert[j].z()  ) ;
+    }
+    
+
+    // Volume vol = surf->volume() ; 
+    // const TGeoShape* shape = vol->GetShape() ;
+
+    // // get extend of surface volume along u and v
+    // VolSurface volSurf = surf->volSurface() ;
+
+    // const DDSurfaces::Vector3D& lu = volSurf.u() ;
+    // const DDSurfaces::Vector3D& lv = volSurf.v() ;
+    // const DDSurfaces::Vector3D& ln = volSurf.normal() ;
+    // const DDSurfaces::Vector3D& lo = volSurf.origin() ;
+
+
+    // // TGeoShape::DistFromInside(Double_t *point[3], Double_t *dir[3],
+    // //                               Int_t iact, Double_t step, Double_t *safe)
+ 
+    // double safe = 0. ; 
+    // double lup = shape->DistFromInside( lo,  lu, 2, 0.1 , &safe ) ;
+    // double lun = shape->DistFromInside( lo, -lu, 2, 0.1 , &safe ) ;
+    // double lvp = shape->DistFromInside( lo,  lv, 2, 0.1 , &safe ) ;
+    // double lvn = shape->DistFromInside( lo, -lv, 2, 0.1 , &safe ) ;
+    
+    
+    // // std::cout << "*** lu : " << lu << " lv : " << lv << " ln : " << ln << " lo : " << lo << std::endl ; 
+    // // std::cout << "*** lup : " << lup << " lun : " << lun << " lvp : " << lvp << " lvn : " << lvn << std::endl ; 
+
+    // const DDSurfaces::Vector3D& u = surf->u() ;
+    // const DDSurfaces::Vector3D& v = surf->v() ;
+    // const DDSurfaces::Vector3D& n = surf->normal() ;
+    // const DDSurfaces::Vector3D& o = surf->origin() ;
+    
+
+    // if( surf->type().isPlane() ) {
+      
+    //   DDSurfaces::Vector3D c0 = o + lup * u  + lvp * v ;
+    //   DDSurfaces::Vector3D c1 = o + lup * u  - lvn * v ;
+    //   DDSurfaces::Vector3D c2 = o - lun * u  - lvn * v ;
+    //   DDSurfaces::Vector3D c3 = o - lun * u  + lvn * v ;
+      
+      
+    //   ls->AddLine( c0.x(), c0.y(), c0.z(), c1.x() , c1.y() , c1.z()  ) ;
+    //   ls->AddLine( c1.x(), c1.y(), c1.z(), c2.x() , c2.y() , c2.z()  ) ;
+    //   ls->AddLine( c2.x(), c2.y(), c2.z(), c3.x() , c3.y() , c3.z()  ) ;
+    //   ls->AddLine( c3.x(), c3.y(), c3.z(), c0.x() , c0.y() , c0.z()  ) ;
+      
+    //   //    ls->AddMarker(  o.x(), o.y(), o.z() );
+    // }
+
+    ls->SetLineColor( kRed ) ;
+    ls->SetMarkerColor( kRed ) ;
+    ls->SetMarkerSize(.1);
+    ls->SetMarkerStyle(4);
+
+  } // don't know what to do ...
+
+  gEve->AddElement(ls);
+
+  return ls;
+}
+//=====================================================================================
+
+
 static long teve_display(LCDD& lcdd, int /* argc */, char** /* argv */) {
   TGeoManager* mgr = &lcdd.manager();
   TEveManager::Create();
   gEve->fGeometries->Add(new TObjString("DefaultGeometry"),mgr);
   TEveGeoTopNode* tn = new TEveGeoTopNode(mgr, mgr->GetTopNode());
   tn->SetVisLevel(4);
-  gEve->AddGlobalElement(tn);
 
+
+  // // ---- try to set transparency - does not seem to work ...
+  // TGeoNode* node1 = gGeoManager->GetTopNode();
+  // int k_nodes = node1->GetNdaughters();
+  // for(int i=0; i<k_nodes; i++) {
+  //   TGeoNode * CurrentNode = node1->GetDaughter(i);
+  //   CurrentNode->GetMedium()->GetMaterial()->SetTransparency(80);
+  //   // TEveGeoNode CurrentNode( node1->GetDaughter(i) ) ;
+  //   // CurrentNode.SetMainTransparency( 80 ) ;
+  // }
+  // this code seems to have no effect either ...
+  tn->CSCApplyMainTransparencyToAllChildren() ;
+  tn->SetMainTransparency( 80 ) ;
+
+
+  drawSurfaceVectors() ;
+  drawSurfaces() ;
+
+  gEve->AddGlobalElement(tn);
   gEve->FullRedraw3D(kTRUE);
 
+
   // EClipType not exported to CINT (see TGLUtil.h):
   // 0 - no clip, 1 - clip plane, 2 - clip box
   TGLViewer *v = gEve->GetDefaultGLViewer();
-  v->GetClipSet()->SetClipType(TGLClip::kClipPlane);
-  v->ColorSet().Background().SetColor(kMagenta+4);
+
+  //  v->GetClipSet()->SetClipType(TGLClip::kClipPlane);
+  //  v->ColorSet().Background().SetColor(kMagenta+4);
+  v->ColorSet().Background().SetColor(kWhite);
+
   v->SetGuideState(TGLUtil::kAxesEdge, kTRUE, kFALSE, 0);
   v->RefreshPadEditor(v);
-  v->CurrentCamera().RotateRad(-1.2, 0.5);
+  //  v->CurrentCamera().RotateRad(-1.2, 0.5);
   v->DoDraw();
   return 1;
+
+
 }
 DECLARE_APPLY(DD4hepTEveDisplay,teve_display)
 
@@ -52,3 +223,4 @@ DECLARE_APPLY(DD4hepTEveDisplay,teve_display)
 int main(int argc,char** argv)  {
   return main_default("DD4hepTEveDisplay",argc,argv);
 }
+
diff --git a/examples/ILDExSimu/src/test_surfaces.cc b/examples/ILDExSimu/src/test_surfaces.cc
index ff94f0b9c..e5b79cce6 100644
--- a/examples/ILDExSimu/src/test_surfaces.cc
+++ b/examples/ILDExSimu/src/test_surfaces.cc
@@ -84,7 +84,7 @@ int main(int argc, char** argv ){
 
   std::vector< std::string > colNames ;
   colNames.push_back( "VXDCollection" ) ;
-  colNames.push_back( "SITCollection" ) ;
+  //  colNames.push_back( "SITCollection" ) ;
 
   while( ( evt = rdr->readNextEvent() ) != 0 ){
 
@@ -132,11 +132,15 @@ int main(int argc, char** argv ){
 	  
 	  test( isInside , true , sst.str() ) ;
 	  
-	  // std::cout << " found surface with same id " <<  *surf << std::endl 
-	  // 	  << " point : " << point 
-	  // 	  << " is inside : " <<  isInside
-	  // 	  << " distance from surface : " << dist/tgeo::mm << std::endl 
-	  // 	  << std::endl ;
+	  if( ! isInside ) {
+
+	    std::cout << " found surface " <<  *surf << std::endl
+		      << " id : " << idDecoder 
+		      << " point : " << point 
+		      << " is inside : " <<  isInside
+		      << " distance from surface : " << dist/tgeo::mm << std::endl 
+		      << std::endl ;
+	  }
 
 	  // ====== test that slightly moved hit points are inside their surface ================================
 	  
@@ -146,6 +150,17 @@ int main(int argc, char** argv ){
 	  isInside = surf->insideBounds( point2 )  ;
 	  test( isInside , true , sst.str() ) ;
 	  
+	  if( ! isInside ) {
+
+	    std::cout << " found surface " <<  *surf << std::endl
+		      << " id : " << idDecoder 
+		      << " point : " << point 
+		      << " is inside : " <<  isInside
+		      << " distance from surface : " << dist/tgeo::mm << std::endl 
+		      << std::endl ;
+
+	  }
+
 	  // ====== test that moved hit points are outside their surface ================================
 	  
 	  Vector3D point3 = point + 1e-3 * surf->normal() ;
-- 
GitLab