From 4318bfba4f18d4814337ab508978c964e33e17bf Mon Sep 17 00:00:00 2001
From: Frank Gaede <frank.gaede@desy.de>
Date: Sun, 6 Apr 2014 16:29:09 +0000
Subject: [PATCH]  - restructured surfaces:    - modified ISurface to be pure
 abstract base (interface)       - changed method signatures    - added
 IMaterial as pure abstract base (interface)    - moved Surface from DDCore to
 DDRec      - classes VolSurface (VolPlane, VolCylinder) implement ISurface   
   - implement insideBounds using volume  - changed Vector3D to be copy of
 gear::Vector3D (slightly improved)

---
 DDRec/CMakeLists.txt                      |   1 +
 DDRec/include/DDRec/Surface.h             | 252 ++++++++++++++++
 DDRec/src/Surface.cpp                     | 123 ++++++++
 DDSurfaces/include/DDSurfaces/IMaterial.h |  39 +++
 DDSurfaces/include/DDSurfaces/ISurface.h  | 236 ++++++++++-----
 DDSurfaces/include/DDSurfaces/Vector3D.h  | 347 ++++++++++++++++++----
 6 files changed, 876 insertions(+), 122 deletions(-)
 create mode 100644 DDRec/include/DDRec/Surface.h
 create mode 100644 DDRec/src/Surface.cpp
 create mode 100644 DDSurfaces/include/DDSurfaces/IMaterial.h

diff --git a/DDRec/CMakeLists.txt b/DDRec/CMakeLists.txt
index f4bd6f5d9..efbad2154 100644
--- a/DDRec/CMakeLists.txt
+++ b/DDRec/CMakeLists.txt
@@ -4,6 +4,7 @@ project(DDRec)
 
 include_directories(${CMAKE_CURRENT_SOURCE_DIR}/include 
 		    ${ROOT_INCLUDE_DIR} ${CMAKE_SOURCE_DIR}/DDSegmentation/include 
+		    ${ROOT_INCLUDE_DIR} ${CMAKE_SOURCE_DIR}/DDSurfaces/include 
 		    ${CMAKE_SOURCE_DIR}/DDCore/include)
 
 file(GLOB sources src/*.cpp)
diff --git a/DDRec/include/DDRec/Surface.h b/DDRec/include/DDRec/Surface.h
new file mode 100644
index 000000000..f05ef7948
--- /dev/null
+++ b/DDRec/include/DDRec/Surface.h
@@ -0,0 +1,252 @@
+#ifndef DD4Surfaces_Surface_H
+#define DD4Surfaces_Surface_H
+
+#include "DD4hep/Objects.h"
+#include "DD4hep/Volumes.h"
+
+#include "DDSurfaces/ISurface.h"
+
+#include <list>
+
+
+namespace DD4hep {
+  namespace DDRec {
+  
+    using namespace DDSurfaces ;
+    
+
+    /** Wrapper class to  Geometry::Material that implements the DDSurfaces::IMaterial interface.
+     *
+     * @author F.Gaede, DESY
+     * @date Apr, 6 2014
+     * @version $Id:$
+     */
+    struct SurfaceMaterial : public virtual Geometry::Material , IMaterial{
+
+      /** Copy c'tor - copies handle */
+      SurfaceMaterial( Geometry::Material m ) : Geometry::Material( m ) {} 
+      
+      /// averaged proton number
+      virtual double Z() const { return Geometry::Material()->GetMaterial()->GetZ() ; }
+      
+      /// averaged atomic number
+      virtual double A() const { return Geometry::Material()->GetMaterial()->GetA() ; }
+      
+      /// density - units ?
+      virtual double density() const { return Geometry::Material()->GetMaterial()->GetDensity() ; } 
+      
+      /// radiation length - units ?
+      virtual double radiationLength() const { return Geometry::Material::radLength() ; } 
+      
+      /// interaction length - units ?
+      virtual double interactionLength() const  { return Geometry::Material::intLength() ; }
+
+    };
+
+    /** Helper class for holding surface data. 
+     * @author F.Gaede, DESY
+     * @date Apr, 6 2014
+     * @version $Id:$
+     */
+    struct SurfaceData{
+    
+      SurfaceType _type ;
+      Vector3D _u ;
+      Vector3D _v ;
+      Vector3D _n ;
+      Vector3D _o ;
+      double _th_i ;
+      double _th_o ;
+      Geometry::Material _innerMat ;
+      Geometry::Material _outerMat ;
+    
+      SurfaceData();
+    
+      SurfaceData( SurfaceType type, double thickness_inner ,double thickness_outer, 
+		   Vector3D u ,Vector3D v ,Vector3D n ,Vector3D o )  ;
+    
+      /// Default destructor
+      virtual ~SurfaceData() {} 
+    
+      /// Copy the object
+    
+      void copy(const SurfaceData& c) {
+	_type = c._type ;
+	_u = c._u ;
+	_v = c._v ;
+	_n = c._n ;
+	_o = c._o;
+	_th_i = c._th_i ;
+	_th_o = c._th_o ;
+	_innerMat = c._innerMat ;
+	_outerMat = c._innerMat ;
+      }
+    } ;
+  
+
+    /** Implementation of ISurface for a local surface attached to a volume. 
+     * 
+     * @author F.Gaede, DESY
+     * @date Apr, 6 2014
+     * @version $Id:$
+     */
+    class VolSurface : public Geometry::Handle< SurfaceData > , ISurface {
+    
+    protected:
+    
+      Geometry::Volume _vol ;
+    
+    public:
+    
+      virtual ~VolSurface() {} 
+
+      VolSurface() { }
+    
+      VolSurface( Geometry::Volume vol, SurfaceType type, double thickness_inner ,double thickness_outer, 
+		  Vector3D u ,Vector3D v ,Vector3D n , Vector3D o = Vector3D(0.,0.,0.) ) ;      
+    
+      Geometry::Volume volume() const { return _vol ; }
+    
+
+      /** properties of the surface encoded in Type.
+       * @see SurfaceType
+       */
+      virtual SurfaceType type() const { return object<SurfaceData>()._type ; }
+    
+      //==== geometry ====
+      
+      /** First direction of measurement U */
+      virtual const Vector3D& u( const Vector3D& point = Vector3D() ) const { return object<SurfaceData>()._u ; }
+    
+      /** Second direction of measurement V */
+      virtual const Vector3D& v(const Vector3D& point = Vector3D() ) const { return object<SurfaceData>()._v ; }
+    
+      /// Access to the normal direction at the given point
+      virtual const Vector3D& normal(const Vector3D& point = Vector3D() ) const { return object<SurfaceData>()._n ; }
+    
+      /** Get Origin of local coordinate system on surface */
+      virtual const Vector3D& origin() const { return object<SurfaceData>()._o ;}
+
+      /// Access to the material in opposite direction of the normal
+      virtual IMaterial innerMaterial() const{ return SurfaceMaterial( object<SurfaceData>()._innerMat ) ; }
+      
+      /// Access to the material in direction of the normal
+      virtual IMaterial outerMaterial() const { return  SurfaceMaterial( object<SurfaceData>()._outerMat ) ; }
+    
+      /** Thickness of inner material */
+      virtual double innerThickness() const { return object<SurfaceData>()._th_i ; }
+
+      /** Thickness of outer material */
+      virtual double outerThickness() const { return object<SurfaceData>()._th_o ; }
+
+
+      // need default implementations for putting it in list....
+      
+      /** Distance to surface */
+      virtual double distance(const Vector3D& point ) const  { return 0. ; }
+      
+      /// Checks if the given point lies within the surface
+      virtual bool insideBounds(const Vector3D& point, double epsilon=1.e-6) const { return false ; }
+    };
+
+
+    //======================================================================================================
+
+
+    /** std::list of VolSurfaces that takes ownership.
+     * @author F.Gaede, DESY
+     * @date Apr, 6 2014
+     * @version $Id:$
+     */
+    struct VolSurfaceList : std::list< VolSurface > {
+    
+      VolSurfaceList() {}
+      // required c'tors for extension mechanism
+      VolSurfaceList(const Geometry::DetElement& d){
+	// anything to do here  ?
+      }
+      VolSurfaceList(const VolSurfaceList& c,const Geometry::DetElement& det){
+	// anything to do here  ?
+      }
+    
+      virtual ~VolSurfaceList(){
+      
+	// delete all surfaces attached to this volume
+	for( VolSurfaceList::iterator i=begin(), n=end() ; i !=n ; ++i ) {
+	  delete (*i).ptr() ;
+	}
+      
+      }
+    } ;
+  
+    VolSurfaceList* volSurfaceList( Geometry::DetElement& det ) ;
+
+    //======================================================================================================
+
+    /** Implementation of planar surface attached to a volume 
+     * @author F.Gaede, DESY
+     * @date Apr, 6 2014
+     * @version $Id:$
+     */
+    class VolPlane : public VolSurface {
+      
+    public:
+      
+      VolPlane() : VolSurface() { }
+      
+      VolPlane( Geometry::Volume vol, SurfaceType type, double thickness_inner ,double thickness_outer, 
+		Vector3D u ,Vector3D v ,Vector3D n , Vector3D o = Vector3D(0.,0.,0.) ) :
+	
+	VolSurface( vol, type, thickness_inner, thickness_outer, u,v,n,o ) {
+
+	type._bits.set( SurfaceType::Cylinder , false ) ;
+	type._bits.set( SurfaceType::Plane    , true ) ;
+      }      
+      
+      /** Distance to surface */
+      virtual double distance(const Vector3D& point ) const  ;
+      
+      /// Checks if the given point lies within the surface
+      virtual bool insideBounds(const Vector3D& point, double epsilon=1.e-4) const  ;
+
+      
+    } ;
+
+    //======================================================================================================
+
+    /** Implementation of cylindrical surface attached to a volume 
+     * @author F.Gaede, DESY
+     * @date Apr, 6 2014
+     * @version $Id:$
+     */
+    class VolCylinder : public VolSurface {
+      
+    public:
+      
+      VolCylinder() : VolSurface() { }
+      
+      VolCylinder( Geometry::Volume vol, SurfaceType type, double thickness_inner ,double thickness_outer, 
+		Vector3D u ,Vector3D v ,Vector3D n , Vector3D o = Vector3D(0.,0.,0.) ) :
+	
+	VolSurface( vol, type, thickness_inner, thickness_outer, u,v,n,o ) {
+
+	type._bits.set( SurfaceType::Plane    , false ) ;
+	type._bits.set( SurfaceType::Cylinder , true ) ;
+      }      
+      
+      /** Distance to surface */
+      virtual double distance(const Vector3D& point ) const  ;
+      
+      /// Checks if the given point lies within the surface
+      virtual bool insideBounds(const Vector3D& point, double epsilon=1.e-4) const  ;
+
+    } ;
+
+    //======================================================================================================
+
+
+  
+  } /* namespace */
+} /* namespace */
+
+#endif /* Surface */
diff --git a/DDRec/src/Surface.cpp b/DDRec/src/Surface.cpp
new file mode 100644
index 000000000..b1e56758e
--- /dev/null
+++ b/DDRec/src/Surface.cpp
@@ -0,0 +1,123 @@
+#include "DDRec/Surface.h"
+#include "DD4hep/Detector.h"
+
+
+namespace DD4hep {
+  namespace DDRec {
+ 
+    using namespace Geometry ;
+
+    SurfaceData::SurfaceData() : _type( SurfaceType() ) ,
+		    _u( Vector3D() ) ,
+		    _v( Vector3D()  ) ,
+		    _n( Vector3D() ) ,
+		    _o( Vector3D() ) ,
+		    _th_i( 0. ),
+		    _th_o( 0. ),
+		    _innerMat( Material() ),
+		    _outerMat( Material() ) {
+    }
+  
+  
+    SurfaceData::SurfaceData( SurfaceType type , double thickness_inner ,double thickness_outer, 
+		 Vector3D u ,Vector3D v ,Vector3D n ,Vector3D o ) :  _type(type ) ,
+								     _u( u ) ,
+								     _v( v ) ,
+								     _n( n ) ,
+								     _o( o ),
+								     _th_i( thickness_inner ),
+								     _th_o( thickness_outer ),  
+								     _innerMat( Material() ),
+								     _outerMat( Material() ) {
+    }
+  
+  
+  
+    VolSurface::VolSurface( Volume vol, SurfaceType type, double thickness_inner ,double thickness_outer, 
+			    Vector3D u ,Vector3D v ,Vector3D n ,Vector3D o ) :  
+      
+      Handle( new SurfaceData( type, thickness_inner ,thickness_outer, u,v,n,o) ) ,
+
+      _vol( vol ) {
+    }      
+    
+
+    /** Distance to surface */
+    double VolPlane::distance(const Vector3D& point ) const {
+
+      return ( point - origin() ) *  normal()  ;
+    }
+    
+    /// Checks if the given point lies within the surface
+    bool VolPlane::insideBounds(const Vector3D& point, double epsilon) const {
+
+
+#if 1
+      double dist = std::abs ( distance( point ) ) ;
+      
+      bool inShape = volume()->GetShape()->Contains( point ) ;
+      
+      std::cout << " ** Surface::insideBound( " << point << " ) - distance = " << dist 
+ 		<< " origin = " << origin() << " normal = " << normal() 
+ 		<< " p * n = " << point * normal() 
+ 		<< " isInShape : " << inShape << std::endl ;
+	
+      return dist < epsilon && inShape ;
+ #else
+	
+      return ( std::abs ( distance() ) < epsilon )  &&  volume()->GetShape()->Contains( point ) ; 
+ #endif
+ 
+    }
+
+    /** Distance to surface */
+    double VolCylinder::distance(const Vector3D& point ) const {
+
+      return point.rho() - origin().rho()  ;
+    }
+    
+    /// Checks if the given point lies within the surface
+    bool VolCylinder::insideBounds(const Vector3D& point, double epsilon) const {
+      
+#if 1
+      double distR = std::abs( distance( point ) ) ;
+      
+      bool inShapeT = volume()->GetShape()->Contains( point ) ;
+      
+      std::cout << " ** Surface::insideBound( " << point << " ) - distance = " << distR 
+ 		<< " origin = " << origin() 
+ 		<< " isInShape : " << inShapeT << std::endl ;
+      
+      return distR < epsilon && inShapeT ;
+#else
+      
+      return ( std::abs ( distance() ) < epsilon )  &&  volume()->GetShape()->Contains( point ) ; 
+
+#endif
+    }
+
+
+
+    //====================
+
+
+    VolSurfaceList* surfaceList( DetElement& det ) {
+
+      
+      VolSurfaceList* list = 0 ;
+
+      try {
+
+	list = det.extension< VolSurfaceList >() ;
+
+      } catch( std::runtime_error e){ 
+	
+	list = det.addExtension<VolSurfaceList >(  new VolSurfaceList ) ; 
+      }
+
+      return list ;
+    }
+
+
+  } // namespace
+} // namespace
diff --git a/DDSurfaces/include/DDSurfaces/IMaterial.h b/DDSurfaces/include/DDSurfaces/IMaterial.h
new file mode 100644
index 000000000..a0b3095a8
--- /dev/null
+++ b/DDSurfaces/include/DDSurfaces/IMaterial.h
@@ -0,0 +1,39 @@
+#ifndef DDSurfaces_IMaterial_H_
+#define DDSurfaces_IMaterial_H_
+
+namespace DDSurfaces {
+  
+  /** Interface for material description for tracking. 
+   *
+   * @author F.Gaede, DESY
+   * @version $Id$
+   * @date Apr 6 2014
+   */
+  
+  class IMaterial {
+    
+  public:
+    
+    /// Destructor
+    virtual ~IMaterial() {}
+    
+    /// averaged proton number
+    virtual double Z() const =0 ;
+    
+    /// averaged atomic number
+    virtual double A() const =0 ;
+    
+    /// density - units ?
+    virtual double density() const =0 ;
+    
+    /// radiation length - units ?
+    virtual double radiationLength() const =0 ;
+    
+    /// interaction length - units ?
+    virtual double interactionLength() const =0 ;
+
+  };
+
+} /* namespace DDSurfaces */
+
+#endif /* DDSurfaces_MATERIAL_H_ */
diff --git a/DDSurfaces/include/DDSurfaces/ISurface.h b/DDSurfaces/include/DDSurfaces/ISurface.h
index 52142fab2..b60f6d0c4 100644
--- a/DDSurfaces/include/DDSurfaces/ISurface.h
+++ b/DDSurfaces/include/DDSurfaces/ISurface.h
@@ -1,79 +1,171 @@
-/*
- * ISurface.h
- *
- *  Created on: Mar 7, 2014
- *      Author: cgrefe
- */
-
-#ifndef DDSurfaces_ISURFACE_H_
-#define DDSurfaces_ISURFACE_H_
-
-#include "DDSurfaces/Material.h"
-#include "DDSurfaces/MeasurementDirections.h"
+#ifndef DDSurfaces_ISurface_H
+#define DDSurfaces_ISurface_H
+
+#include "DDSurfaces/IMaterial.h"
 #include "DDSurfaces/Vector3D.h"
 
+#include <bitset>
+
 namespace DDSurfaces {
+  
+  struct SurfaceType ;
+
+ /** Interface for tracking surfaces. 
+   * The surface provides access to vectors for u,v,n and the orgigin and
+   * the inner and outer materials with corresponding thicknesses.
+   *  
+   * @author C.Grefe, CERN, F. Gaede, DESY
+   * @version $Id: $
+   * @date Mar 7 2014
+   */
+  class ISurface {
+    
+  public:
+    /// Destructor
+    virtual ~ISurface() {}
+    
+    /// properties of the surface encoded in Type.
+    virtual SurfaceType type() const =0 ;
+    
+    /// Checks if the given point lies within the surface
+    virtual bool insideBounds(const Vector3D& point, double epsilon=1.e-4) const =0 ;
+    
+    /** First direction of measurement U */
+    virtual const Vector3D& u( const Vector3D& point = Vector3D() ) const =0 ;
+    
+    /** Second direction of measurement V */
+    virtual const Vector3D& v(const Vector3D& point = Vector3D() ) const =0 ;
+    
+    /// Access to the normal direction at the given point
+    virtual const Vector3D& normal(const Vector3D& point = Vector3D() ) const =0 ;
+    
+    /** Get Origin of local coordinate system on surface */
+    virtual const Vector3D& origin() const =0 ;
+    
+    /// Access to the material in opposite direction of the normal
+    virtual IMaterial innerMaterial() const =0 ;
+    
+    /// Access to the material in direction of the normal
+    virtual IMaterial outerMaterial() const =0 ;
+    
+    /** Thickness of inner material */
+    virtual double innerThickness() const =0 ;
+    
+    /** Thickness of outer material */
+    virtual double outerThickness() const =0 ;
+    
+    /** Distance to surface */
+    virtual double distance(const Vector3D& point ) const =0 ;
+    
+  } ;
+  
+
+  /** Helper class for describing surface properties.
+   *  Usage: SurfaceType type(  SurfaceType::Plane, SurfaceType::Sensitive ) ; 
+   *
+   * @author F. Gaede, DESY
+   * @version $Id: $
+   * @date Apr 6 2014
+   */
+  struct SurfaceType{
+  
+    /// enum for defining the bits used to decode the properties
+    enum{
+      Cylinder = 1,
+      Plane,
+      Sensitive,
+      Helper,
+      ParallelToZ,
+      OrthogonalToZ
+    } ;
+    
+    ///default c'tor
+    SurfaceType() : _bits(0) {}
+
+    // c'tor that sets one property
+    SurfaceType( unsigned prop0 ) : _bits(0) { 
+      _bits.set( prop0 ) ;
+    } 
+    
+    // c'tor that sets two properties
+    SurfaceType( unsigned prop0 , unsigned prop1 ) : _bits(0) { 
+      _bits.set( prop0 ) ;
+      _bits.set( prop1 ) ;
+    } 
+    
+    // c'tor that sets three properties
+    SurfaceType( unsigned prop0 , unsigned prop1 , unsigned prop2 ) : _bits(0) { 
+      _bits.set( prop0 ) ;
+      _bits.set( prop1 ) ;
+      _bits.set( prop2 ) ;
+    } 
+    
+    // c'tor that sets four properties
+    SurfaceType( unsigned prop0 , unsigned prop1 , unsigned prop2, unsigned prop3 ) : _bits(0) { 
+      _bits.set( prop0 ) ;
+      _bits.set( prop1 ) ;
+      _bits.set( prop2 ) ;
+      _bits.set( prop3 ) ;
+    } 
+    
+    /// set the given peorperty
+    void setProperty( unsigned prop ) { _bits.set( prop ) ;  } 
+    
+    /// true if surface is sensitive
+    bool isSensitive() const { return _bits[ SurfaceType::Sensitive ] ; }
+    
+    /// true if surface is helper surface for navigation
+    bool isHelper() const  { return _bits[ SurfaceType::Helper ] ; }
+    
+    /// true if this a planar surface
+    bool isPlane() const { return _bits[ SurfaceType::Plane ] ; } 
+    
+    /// true if this a cylindrical surface
+    bool isCylinder() const { return _bits[ SurfaceType::Cylinder ] ; } 
+
+    /// true if surface is parallel to Z
+    bool isParallelToZ() const { return _bits[ SurfaceType::ParallelToZ ] ; } 
+
+    /// true if surface is orthogonal to Z
+    bool isOrthogonalToZ() const { return _bits[ SurfaceType::OrthogonalToZ ] ; } 
+   
+   /// true if this is a cylinder parallel to Z
+    bool isZCylinder() const  { return ( _bits[ SurfaceType::Cylinder ] &&  _bits[ SurfaceType::ParallelToZ ] ) ; } 
+
+   /// true if this is a plane parallel to Z
+    bool isZPlane() const  { return ( _bits[ SurfaceType::Plane ] &&  _bits[ SurfaceType::ParallelToZ ] ) ; } 
+    
+    /// true if this is a plane orthogonal to Z
+    bool isZDisk() const  { return ( _bits[ SurfaceType::Plane ] &&  _bits[ SurfaceType::OrthogonalToZ ] ) ; } 
+
+
+    /** True if surface is parallel to Z with accuracy epsilon - result is cached in bit SurfaceType::ParallelToZ */
+    bool checkParallelToZ( const ISurface& surf , double epsilon=1.e-6 ) const { 
+      
+      double proj = std::abs( surf.normal() * Vector3D(0.,0.,1.) )  ;
+      
+      _bits.set(  SurfaceType::ParallelToZ , ( std::abs( proj - 1. ) < epsilon )  ) ;
+      
+      return  _bits[ SurfaceType::ParallelToZ ] ;
+    }
+
+    /** True if surface is orthogonal to Z with accuracy epsilon - result is cached in bit SurfaceType::OrthogonalToZ */
+    bool checkOrthogonalToZ( const ISurface& surf , double epsilon=1.e-6 ) const { 
+      
+      double proj = std::abs( surf.normal() * Vector3D(0.,0.,1.) )  ;
+      
+      _bits.set(  SurfaceType::OrthogonalToZ , ( proj < epsilon )  ) ;
+      
+      return  _bits[ SurfaceType::OrthogonalToZ ] ;
+    }
+
+    mutable std::bitset<32> _bits ;
+  } ;
+
+
+
 
-/** Generic surface class used for tracking */
-class ISurface {
-public:
-	/// Destructor
-	virtual ~ISurface() {
-		if (m_measurement) {
-			delete m_measurement;
-		}
-	}
-
-	/// Checks if the surface has measurement directions
-	virtual bool hasMeasurement() const {
-		return m_measurement != 0;
-	}
-
-	/// Checks if the given point lies within the surface
-	virtual bool isInsideBoundaries(const Vector3D& point) const = 0;
-
-	/// Access to the normal direction at the given point
-	virtual Vector3D getNormal(const Vector3D& point) const = 0;
-
-	/// Access to the measurement directions at the given point
-	virtual MeasurementDirections measurement(const Vector3D& point) const = 0;
-
-	/// Access to the material in opposite direction of the normal
-	const Material& innerMaterial() const {
-		return m_innerMaterial;
-	}
-
-	/// Access to the material in direction of the normal
-	const Material& outerMaterial() const {
-		return m_outerMaterial;
-	}
-
-	/// Sets the material in opposite direction of the normal
-	void setInnerMaterial(const Material& material) {
-		m_innerMaterial = material;
-	}
-
-	/// Sets the material in direction of the normal
-	void setOuterMaterial(const Material& material) {
-		m_outerMaterial = material;
-	}
-
-	/// Sets the nominal measurement directions
-	void setMeasurement(const MeasurementDirections& measurement) {
-		m_measurement = new MeasurementDirections(measurement);
-	}
-
-protected:
-	/// Constructor which can be used by derived classes
-	ISurface(const Material& innerMaterial = Material(), const Material& outerMaterial = Material()) :
-		m_innerMaterial(innerMaterial), m_outerMaterial(outerMaterial), m_measurement(0) {
-	}
-
-	Material m_innerMaterial; /// the material in opposite direction of the normal
-	Material m_outerMaterial; /// the material in direction of the normal
-	MeasurementDirections* m_measurement; /// the nominal measurement directions
-};
 
 } /* namespace DDSurfaces */
 
-#endif /* DDSurfaces_ISURFACE_H_ */
+#endif /* DDSurfaces_ISurface_H */
diff --git a/DDSurfaces/include/DDSurfaces/Vector3D.h b/DDSurfaces/include/DDSurfaces/Vector3D.h
index 3b710a815..7caac864f 100644
--- a/DDSurfaces/include/DDSurfaces/Vector3D.h
+++ b/DDSurfaces/include/DDSurfaces/Vector3D.h
@@ -1,54 +1,301 @@
-/*
- * Vector3D.h
- *
- *  Created on: Mar 7, 2014
- *      Author: cgrefe
- */
+#ifndef DDSurfaces_Vector3D_h
+#define DDSurfaces_Vector3D_h 1
+
+#include <math.h>
+#include <iostream> 
+#include "assert.h"
 
-#ifndef DDSurfaces_VECTOR3D_H_
-#define DDSurfaces_VECTOR3D_H_
 
 namespace DDSurfaces {
+  
+  /** Simple three dimensional vector providing the components for cartesian, 
+   *  cylindrical and spherical coordinate  systems - internal reperesentation is
+   *  cartesian. (copy of original version from gear).
+   *
+   *  @author F. Gaede, DESY
+   *  @version $Id: $
+   *  @date Apr 6 2014
+   */
+  
+  class Vector3D{
+    
+  public:
+    
+    /** Default c'tor - zero vector */
+    Vector3D() : _x(0.0),_y(0.0),_z(0.0) {}
+    
+    
+    /** Constructor for float array.*/
+    Vector3D(const float* v) : _x(v[0]),_y(v[1]),_z(v[2]) {}
+    
+    /** Constructor for double array.*/
+    Vector3D(const double* v) : _x(v[0]),_y(v[1]),_z(v[2]) {}
+    
+    
+    /** Templated c'tor - allows to have overloaded c'tors for different coordinates */
+    template <class T>
+    Vector3D( double x,double y, double z , T(&)() ) ;
+    
+    
+    /** Default corrdinate system for initialization is cartesian */
+    Vector3D( double x,double y, double z ) :
+      _x(x),
+      _y(y),
+      _z(z) {
+    }
+    
+    
+    template <class T>
+    /**Copy c'tor for three vectors from other packages - requires T::x(),T::y(), T::z().
+     */
+    Vector3D( const T& t) :
+      _x( t.x() ) , 
+      _y( t.y() ) , 
+      _z( t.z() ){
+    }
+    
+    /** Cartesian x coordinate */
+    inline double x() const { return  _x ; }
+    
+    /** Cartesian y coordinate */
+    inline double y() const { return  _y ; }
+    
+    /** Cartesian cartesian  z coordinate */
+    inline double z() const { return  _z ; }
+    
+    /** Assign to  cartesian x coordinate */
+    inline double& x() { return  _x ; }
+    
+    /**  Assign to  cartesian y coordinate */
+    inline double& y() { return  _y ; }
+    
+    /**  Assign to cartesian z coordinate */
+    inline double& z() { return  _z ; }
+    
+    
+    /** Accessing x,y,z with bracket operator */
+    inline double operator[](int i) const {
+      switch(i) {
+      case 0: return _x ; break ;
+      case 1: return _y ; break ;
+      case 2: return _z ; break ;
+      }
+      return 0.0 ;
+    }
+    /** Accessing x,y,z with bracket operator for assignment */
+    inline double& operator[](int i) {
+      switch(i) {
+      case 0: return _x ; break ;
+      case 1: return _y ; break ;
+      case 2: return _z ; break ;
+      }
+      static double dummy(0.0) ;
+      return dummy ;
+    }
+    
+    /** Azimuthal angle - cylindrical and spherical */
+    inline double phi() const {
+      
+      return _x == 0.0 && _y == 0.0 ? 0.0 : atan2(_y,_x);
+    }
+    
+    /** Transversal component - cylindrical 'r' */
+    inline double rho() const {
+      
+      return trans() ;
+    }
+    
+    /** Transversal component */
+    inline double trans() const {
+      
+      return sqrt( _x*_x + _y*_y ) ; 
+    }
+    
+    /** Transversal component squared */
+    inline double trans2() const {
+      
+      return  _x*_x + _y*_y  ;
+    }
+    
+    /** Spherical r/magnitude */
+    inline double r() const {
+      
+      return sqrt( _x*_x + _y*_y + _z*_z ) ; 
+    }
+    
+    
+    /** Spherical r/magnitude, squared */
+    inline double r2() const {
+      
+      return  _x*_x + _y*_y + _z*_z  ; 
+    }
+    
+    /** Polar angle - spherical */
+    inline double theta() const {
+      
+      return _x == 0.0 && _y == 0.0 && _z == 0.0 ? 0.0 : atan2( rho(),_z) ;
+    }
+    
+    /** Scalar product */
+    inline double dot( const Vector3D& v) const { 
+      return _x * v.x() + _y * v.y() + _z * v.z() ;
+    }
+    
+
+    /** Vector product */
+    inline Vector3D cross( const Vector3D& v) const { 
+      
+      return Vector3D( _y * v.z() - _z * v.y() ,
+		       _z * v.x() - _x * v.z() ,
+		       _x * v.y() - _y * v.x() )  ;
+    }
+    
+    /** Parallel unit vector */
+    inline Vector3D unit() const { 
+      
+      double n = r() ;
+      return Vector3D( _x / n , _y / n , _z / n ) ;
+    }
+    
+    
+    /// direct access to data as const double* 
+    inline operator const double*() const {
+      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 
+     *  causes a small performance penalty.
+     *  @see to()
+     *  
+     */
+    template <class T>
+    inline operator T() const { 
+      
+      T t( _x, _y , _z ) ;
+      
+      assert( t.x()== _x && t.y()== _y && t.z()== _z ) ;
+      
+      return t ;
+      
+      //     return T( _x, _y, _z ) ; 
+    } 
+    
+    
+    /** Explicit, unchecked conversion to anything that has a c'tor T(x,y,z). 
+     *  Example: 
+     *  CLHEP::Vector3D clhv = v.to< CLHEP::Vector3D>() ;
+     *  @see operator T()
+     */
+    template <class T>
+    inline T to() const { return T( _x, _y, _z ) ; } 
+    
+    
+  protected:
+    
+    double _x,_y,_z ;
+    
+    
+    // helper classes and function to allow 
+    // different c'tors selected at compile time
+  public:
+    
+    struct Cartesian   { } ;
+    struct Cylindrical { } ;
+    struct Spherical   { } ;
+    
+    static Cartesian   cartesian()  { return Cartesian() ; }
+    static Cylindrical cylindrical(){ return Cylindrical() ;}
+    static Spherical   spherical()  { return Spherical() ; } 
+    
+  } ;
+  
+  /** Addition of two vectors */
+  inline Vector3D operator+(  const Vector3D& a, const Vector3D& b ) { 
+    
+    return Vector3D( a.x() + b.x()  , a.y() + b.y(), a.z() + b.z()  ) ;
+  }
+  /** Subtraction of two vectors */
+  inline Vector3D operator-(  const Vector3D& a, const Vector3D& b ) { 
+    
+    return Vector3D( a.x() - b.x()  , a.y() - b.y(), a.z() - b.z()  ) ;
+  }
+  /** Comparison of two vectors */
+  inline bool operator==(  const Vector3D& a, const Vector3D& b ) { 
+    
+    if( a.x() == b.x()  &&  a.y() == b.y() && a.z() == b.z()  ) 
+      return true;
+    else
+      return false;
+  }
+  
+  /** Multiplication with scalar */
+  inline Vector3D operator*( double s , const Vector3D& v ) { 
+    
+    return Vector3D( s * v.x()  , s * v.y()  ,  s * v.z() ) ;
+  }
+  
+  /// operator for scalar product
+  inline double operator*( const Vector3D& v0, const Vector3D& v1 ){
+    return v0.dot( v1 ) ;
+  }
+
+  
+  // template specializations for constructors of  different coordinate systems
+  
+  /** Cartesian c'tor  - example: <br> 
+   *  Vector3D  v( x, y, c , Vector3D::cartesian ) ;
+   */
+  template <>
+  inline Vector3D::Vector3D( double x,double y, double z, Vector3D::Cartesian (&)() ) : 
+    _x(x),
+    _y(y),
+    _z(z) {
+  }
+  
+  /** Cylindrical c'tor  - example: <br> 
+   *  Vector3D  v( rho, phi, z , Vector3D::cylindrical ) ;
+   */
+  template <>
+  inline Vector3D::Vector3D( double rho,double phi, double z, Vector3D::Cylindrical (&)() ) : _z(z)  {
+    
+    _x = rho * cos( phi ) ;
+    _y = rho * sin( phi ) ;
+  }
+  
+  
+  /** Spherical c'tor  - example: <br> 
+   *  Vector3D  v( r, phi, theta , Vector3D::spherical ) ;
+   */
+  template <>
+  inline Vector3D::Vector3D( double r,double phi, double theta, Vector3D::Spherical (&)() ) {
+    double rst =  r * sin( theta ) ;
+    _x = rst * cos( phi ) ;
+    _y = rst * sin( phi ) ;
+    _z = r * cos( theta ) ;
+  }
+  
+  
+  
+  /** Output operator */
+  std::ostream & operator << (std::ostream & os, const Vector3D &v) {
+
+    os << "( " << v[0] << ", " << v[1] << ", " << v[2] << " )" ;
+
+    // os << "  ( " << v[0] 
+    //    << ", " << v[1]
+    //    << ", " << v[2]
+    //    << " ) -  [ phi: " << v.phi()
+    //    << " , rho: " << v.rho() << " ] "  
+    //    << "  [ theta: " << v.theta()
+    //    << " , r: " << v.r() << " ] " ;
+    
+    return os ;
+  }
+
+  
+
+} // namespace
 
-/** Generic vector class */
-class Vector3D {
-public:
-	/// Default constructor
-	Vector3D(double x = 0., double y = 0., double z = 0.) :
-		m_x(x), m_y(y), m_z(z) {
-	}
-
-	/** Copy constructor from arbitrary foreign vector class
-	 *  Requires x(), y(), z() methods to access Cartesian coordinates.
-	 */
-	template<typename T> Vector3D(const T& vector) :
-		m_x(vector.x()), m_y(vector.y()), m_z(vector.z()) {
-	}
-
-	/// Destructor
-	virtual ~Vector3D() {}
-
-	/// Access to x
-	double x() const {
-		return m_x;
-	}
-
-	/// Access to y
-	double y() const {
-		return m_y;
-	}
-
-	/// Access to z
-	double z() const {
-		return m_z;
-	}
-
-protected:
-	double m_x;
-	double m_y;
-	double m_z;
-};
-
-} /* namespace DDSurfaces */
-
-#endif /* VECTOR3D_H_ */
+#endif 
-- 
GitLab