From 8ba8e004ddafff2ee66ef519aefb1ca7313700f9 Mon Sep 17 00:00:00 2001
From: Markus Frank <Markus.Frank@cern.ch>
Date: Wed, 5 Feb 2020 09:49:20 +0100
Subject: [PATCH] Add support of tessellated shapes for ROOT > 6.19.0

---
 DDCore/include/DD4hep/ShapeTags.h             |  51 ++---
 DDCore/include/DD4hep/Shapes.h                |  67 ++++++
 DDCore/include/Parsers/detail/Dimension.h     |  49 +++++
 DDCore/include/Parsers/detail/Dimension.imp   |  14 ++
 DDCore/include/XML/UnicodeValues.h            |  19 ++
 DDCore/src/Handle.cpp                         |   2 +
 DDCore/src/ShapeUtilities.cpp                 |  66 ++++++
 DDCore/src/Shapes.cpp                         |  33 ++-
 DDCore/src/plugins/ShapePlugins.cpp           |  33 +++
 DDG4/src/Geant4Converter.cpp                  |   2 +
 DDG4/src/Geant4ShapeConverter.cpp             |  50 ++++-
 examples/ClientTests/CMakeLists.txt           |   2 +-
 .../compact/Check_Shape_Tesselated.xml        | 202 ++++++++++++++++++
 examples/ClientTests/ref/Ref_Tesselated.txt   |  35 +++
 14 files changed, 595 insertions(+), 30 deletions(-)
 create mode 100644 examples/ClientTests/compact/Check_Shape_Tesselated.xml
 create mode 100644 examples/ClientTests/ref/Ref_Tesselated.txt

diff --git a/DDCore/include/DD4hep/ShapeTags.h b/DDCore/include/DD4hep/ShapeTags.h
index b46d9cdf5..4436c34b7 100644
--- a/DDCore/include/DD4hep/ShapeTags.h
+++ b/DDCore/include/DD4hep/ShapeTags.h
@@ -13,32 +13,33 @@
 #ifndef DD4HEP_DDCORE_SHAPETAGS_H
 #define DD4HEP_DDCORE_SHAPETAGS_H
 
-#define SHAPELESS_TAG       "Assembly"
-#define BOX_TAG             "Box"
-#define HALFSPACE_TAG       "HalfSpace"
-#define POLYCONE_TAG        "Polycone"
-#define CONE_TAG            "Cone"
-#define TUBE_TAG            "Tube"
-#define CUTTUBE_TAG         "CutTube"
-#define CONESEGMENT_TAG     "ConeSegment"
-#define TRD1_TAG            "Trd1"
-#define TRD2_TAG            "Trd2"
-#define PARABOLOID_TAG      "Paraboloid"
-#define HYPERBOLOID_TAG     "Hyperboloid"
-#define ELLIPTICALTUBE_TAG  "EllipticalTube"
-#define TWISTEDTUBE_TAG     "TwistedTube"
-#define SPHERE_TAG          "Sphere"
-#define TORUS_TAG           "Torus"
-#define TRAP_TAG            "Trap"
-#define POLYHEDRA_TAG       "Polyhedra"
-#define EXTRUDEDPOLYGON_TAG "ExtrudedPolygon"
-#define EIGHTPOINTSOLID_TAG "EightPointSolid"
+#define SHAPELESS_TAG           "Assembly"
+#define BOX_TAG                 "Box"
+#define HALFSPACE_TAG           "HalfSpace"
+#define POLYCONE_TAG            "Polycone"
+#define CONE_TAG                "Cone"
+#define TUBE_TAG                "Tube"
+#define CUTTUBE_TAG             "CutTube"
+#define CONESEGMENT_TAG         "ConeSegment"
+#define TRD1_TAG                "Trd1"
+#define TRD2_TAG                "Trd2"
+#define PARABOLOID_TAG          "Paraboloid"
+#define HYPERBOLOID_TAG         "Hyperboloid"
+#define ELLIPTICALTUBE_TAG      "EllipticalTube"
+#define TWISTEDTUBE_TAG         "TwistedTube"
+#define SPHERE_TAG              "Sphere"
+#define TORUS_TAG               "Torus"
+#define TRAP_TAG                "Trap"
+#define POLYHEDRA_TAG           "Polyhedra"
+#define EXTRUDEDPOLYGON_TAG     "ExtrudedPolygon"
+#define EIGHTPOINTSOLID_TAG     "EightPointSolid"
+#define TESSELLATEDSOLID_TAG    "TessellatedSolid"
 
-#define TRUNCATEDTUBE_TAG   "TruncatedTube"
-#define PSEUDOTRAP_TAG      "PseudoTrap"
-#define UNION_TAG           "Union"
-#define SUBTRACTION_TAG     "Subtraction"
-#define INTERSECTION_TAG    "Intersection"
+#define TRUNCATEDTUBE_TAG       "TruncatedTube"
+#define PSEUDOTRAP_TAG          "PseudoTrap"
+#define UNION_TAG               "Union"
+#define SUBTRACTION_TAG         "Subtraction"
+#define INTERSECTION_TAG        "Intersection"
 
 
 #endif // DD4HEP_DDCORE_SHAPETAGS_H
diff --git a/DDCore/include/DD4hep/Shapes.h b/DDCore/include/DD4hep/Shapes.h
index 7cfe5aa5a..71d94314d 100644
--- a/DDCore/include/DD4hep/Shapes.h
+++ b/DDCore/include/DD4hep/Shapes.h
@@ -25,6 +25,7 @@
 #pragma GCC diagnostic push
 #pragma GCC diagnostic ignored "-Wdeprecated" // Code that causes warning goes here
 #endif
+
 // ROOT include files
 #include "TGeoCone.h"
 #include "TGeoPgon.h"
@@ -42,6 +43,10 @@
 #include "TGeoParaboloid.h"
 #include "TGeoCompositeShape.h"
 #include "TGeoShapeAssembly.h"
+#if ROOT_VERSION_CODE > ROOT_VERSION(6,19,0)
+#include "TGeoTessellated.h"
+#endif
+
 #ifdef __GNUC__
 #pragma GCC diagnostic pop
 #endif
@@ -1417,6 +1422,68 @@ namespace dd4hep {
     EightPointSolid& operator=(const EightPointSolid& copy) = default;
   };
 
+#if ROOT_VERSION_CODE > ROOT_VERSION(6,19,0)
+  /// Class describing a tessellated shape
+  /**
+   *   For any further documentation please see the following ROOT documentation:
+   *   \see http://root.cern.ch/root/html/TGeoTessellated.html
+   *
+   *   \author  M.Frank
+   *   \version 1.0
+   *   \ingroup DD4HEP_CORE
+   */
+  class TessellatedSolid : public Solid_type<TGeoTessellated> {
+  private:
+    /// Internal helper method to support object construction
+    void make(const std::string& nam, int num_facets);
+    /// Internal helper method to support object construction
+    void make(const std::string& nam, const std::vector<Object::Vertex_t>& vertices);
+
+  public:
+    typedef Object::Vertex_t Vertex_t;
+    
+    /// Default constructor
+    TessellatedSolid() = default;
+    /// Move Constructor
+    TessellatedSolid(TessellatedSolid&& e) = default;
+    /// Copy Constructor
+    TessellatedSolid(const TessellatedSolid& e) = default;
+    /// Constructor to be used with an existing object
+    template <typename Q> TessellatedSolid(const Q* p) : Solid_type<Object>(p) { }
+    /// Constructor to be used when passing an already created object
+    template <typename Q> TessellatedSolid(const Handle<Q>& e) : Solid_type<Object>(e) { }
+
+    /// Constructor to create a new anonymous object with attribute initialization
+    TessellatedSolid(int num_facets)
+    { this->make("", num_facets);    }
+
+    /// Constructor to create a new identified object with attribute initialization
+    TessellatedSolid(const std::vector<Vertex_t>& vertices)
+    { this->make("", vertices);   }
+
+    /// Constructor to create a new anonymous object with attribute initialization
+    TessellatedSolid(const std::string& nam, int num_facets)
+    { this->make(nam, num_facets);    }
+
+    /// Constructor to create a new identified object with attribute initialization
+    TessellatedSolid(const std::string& nam, const std::vector<Vertex_t>& vertices)
+    { this->make(nam, vertices);   }
+
+    /// Move Assignment operator
+    TessellatedSolid& operator=(TessellatedSolid&& copy) = default;
+    /// Copy Assignment operator
+    TessellatedSolid& operator=(const TessellatedSolid& copy) = default;
+    /// Add new facet to the shape
+    bool addFacet(const Vertex_t& pt0, const Vertex_t& pt1, const Vertex_t& pt2)  const;
+    /// Add new facet to the shape
+    bool addFacet(const Vertex_t& pt0, const Vertex_t& pt1, const Vertex_t& pt2, const Vertex_t& pt3)  const;
+    /// Add new facet to the shape. Call only if the tessellated shape was constructed with vertices
+    bool addFacet(const int pt0, const int pt1, const int pt2)  const;
+    /// Add new facet to the shape. Call only if the tessellated shape was constructed with vertices
+    bool addFacet(const int pt0, const int pt1, const int pt2, const int pt3)  const;
+  };
+#endif
+  
   /// Base class describing boolean (=union,intersection,subtraction) solids
   /**
    *   For any further documentation please see the following ROOT documentation:
diff --git a/DDCore/include/Parsers/detail/Dimension.h b/DDCore/include/Parsers/detail/Dimension.h
index 0723a291f..d0cc8d4cf 100644
--- a/DDCore/include/Parsers/detail/Dimension.h
+++ b/DDCore/include/Parsers/detail/Dimension.h
@@ -254,6 +254,55 @@ namespace dd4hep {
       /// Access attribute values: inner_r
       double inner_r() const;
 
+      /// Access parameters: v
+      double v() const;
+      /// Access parameters: v, if not present returns default
+      double v(double default_val) const;
+      /// Access parameters: V
+      double V() const;
+      /// Access parameters: V, if not present returns default
+      double V(double default_val) const;
+      /// Access parameters: dv
+      double dv() const;
+      /// Access parameters: dv, if not present returns default
+      double dv(double default_val) const;
+      /// Access parameters: v0
+      double v0() const;
+      /// Access parameters: v0, if not present returns default
+      double v0(double default_val) const;
+      /// Access parameters: v1
+      double v1() const;
+      /// Access parameters: v1, if not present returns default
+      double v1(double default_val) const;
+      /// Access parameters: v2
+      double v2() const;
+      /// Access parameters: v2, if not present returns default
+      double v2(double default_val) const;
+      /// Access parameters: v3
+      double v3() const;
+      /// Access parameters: v3, if not present returns default
+      double v3(double default_val) const;
+      /// Access parameters: v4
+      double v4() const;
+      /// Access parameters: v4, if not present returns default
+      double v4(double default_val) const;
+      /// Access parameters: vmin
+      double vmin() const;
+      /// Access parameters: vmin, if not present returns default
+      double vmin(double default_val) const;
+      /// Access parameters: vmax
+      double vmax() const;
+      /// Access parameters: vmax, if not present returns default
+      double vmax(double default_val) const;
+      /// Access parameters: v_offset
+      double v_offset() const;
+      /// Access parameters: v_offset, if not present returns default
+      double v_offset(double default_val) const;
+      /// Access parameters: dim_v
+      double dim_v() const;
+      /// Access parameters: dim_v, if not present returns default
+      double dim_v(double default_val) const;
+
       /// Access parameters: x
       double x() const;
       /// Access parameters: x, if not present returns default
diff --git a/DDCore/include/Parsers/detail/Dimension.imp b/DDCore/include/Parsers/detail/Dimension.imp
index 8bf5d2b6d..0e5f05ce2 100644
--- a/DDCore/include/Parsers/detail/Dimension.imp
+++ b/DDCore/include/Parsers/detail/Dimension.imp
@@ -24,6 +24,20 @@ XML_ATTR_ACCESSOR_INT(id)
 XML_ATTR_ACCESSOR(bool, combineHits)
 XML_ATTR_ACCESSOR(int, station)
 
+XML_ATTR_ACCESSOR_DOUBLE(v)
+XML_ATTR_ACCESSOR_DOUBLE(V)
+XML_ATTR_ACCESSOR_DOUBLE(dv)
+
+XML_ATTR_ACCESSOR_DOUBLE(v0)
+XML_ATTR_ACCESSOR_DOUBLE(v1)
+XML_ATTR_ACCESSOR_DOUBLE(v2)
+XML_ATTR_ACCESSOR_DOUBLE(v3)
+XML_ATTR_ACCESSOR_DOUBLE(v4)
+XML_ATTR_ACCESSOR_DOUBLE(vmin)
+XML_ATTR_ACCESSOR_DOUBLE(vmax)
+XML_ATTR_ACCESSOR_DOUBLE(v_offset)
+XML_ATTR_ACCESSOR_DOUBLE(dim_v)
+
 XML_ATTR_ACCESSOR_DOUBLE(x)
 XML_ATTR_ACCESSOR_DOUBLE(X)
 XML_ATTR_ACCESSOR_DOUBLE(dx)
diff --git a/DDCore/include/XML/UnicodeValues.h b/DDCore/include/XML/UnicodeValues.h
index 7ad2367fa..3fee876d6 100644
--- a/DDCore/include/XML/UnicodeValues.h
+++ b/DDCore/include/XML/UnicodeValues.h
@@ -147,6 +147,8 @@ UNICODE (eval);
 
 UNICODE (f);
 UNICODE (F);
+UNICODE (facet);
+UNICODE (facets);
 UNICODE (false);
 UNICODE (field);
 UNICODE (fields);
@@ -506,27 +508,44 @@ UNICODE (url);
 
 UNICODE (v);
 UNICODE (V);
+UNICODE (dv);
+UNICODE (v0);
+UNICODE (v0x);
+UNICODE (v0y);
+UNICODE (v1);
 UNICODE (v1x);
 UNICODE (v1y);
+UNICODE (v2);
 UNICODE (v2x);
 UNICODE (v2y);
+UNICODE (v3);
 UNICODE (v3x);
 UNICODE (v3y);
+UNICODE (v4);
 UNICODE (v4x);
 UNICODE (v4y);
+UNICODE (v5);
 UNICODE (v5x);
 UNICODE (v5y);
+UNICODE (v6);
 UNICODE (v6x);
 UNICODE (v6y);
+UNICODE (v7);
 UNICODE (v7x);
 UNICODE (v7y);
+UNICODE (v8);
 UNICODE (v8x);
 UNICODE (v8y);
+UNICODE (vmin);
+UNICODE (vmax);
+UNICODE (v_offset);
+UNICODE (dim_v);
 UNICODE (Vacuum);
 UNICODE (value);
 UNICODE (values);
 UNICODE (verbose);
 UNICODE (version);
+UNICODE (vertex);
 UNICODE (vis);
 UNICODE (visible);
 UNICODE (visref);
diff --git a/DDCore/src/Handle.cpp b/DDCore/src/Handle.cpp
index 01504728e..998501ccf 100644
--- a/DDCore/src/Handle.cpp
+++ b/DDCore/src/Handle.cpp
@@ -368,6 +368,7 @@ DD4HEP_INSTANTIATE_HANDLE(TGeoNodeOffset);
 #include "TGeoParaboloid.h"
 #include "TGeoSphere.h"
 #include "TGeoTorus.h"
+#include "TGeoTessellated.h"
 #include "TGeoBoolNode.h"
 #include "TGeoVolume.h"
 #include "TGeoCompositeShape.h"
@@ -402,6 +403,7 @@ DD4HEP_INSTANTIATE_SHAPE_HANDLE(TGeoTrd1);
 DD4HEP_INSTANTIATE_SHAPE_HANDLE(TGeoTrd2);
 DD4HEP_INSTANTIATE_SHAPE_HANDLE(TGeoSphere);
 DD4HEP_INSTANTIATE_SHAPE_HANDLE(TGeoTorus);
+DD4HEP_INSTANTIATE_SHAPE_HANDLE(TGeoTessellated);
 DD4HEP_INSTANTIATE_SHAPE_HANDLE(TGeoHalfSpace);
 DD4HEP_INSTANTIATE_SHAPE_HANDLE(TGeoShapeAssembly);
 DD4HEP_INSTANTIATE_SHAPE_HANDLE(TGeoCompositeShape);
diff --git a/DDCore/src/ShapeUtilities.cpp b/DDCore/src/ShapeUtilities.cpp
index 61a5aed5f..e6feee8c5 100644
--- a/DDCore/src/ShapeUtilities.cpp
+++ b/DDCore/src/ShapeUtilities.cpp
@@ -77,6 +77,7 @@ namespace dd4hep {
   template bool isInstance<PolyhedraRegular>  (const Handle<TGeoShape>& solid);
   template bool isInstance<Polyhedra>         (const Handle<TGeoShape>& solid);
   template bool isInstance<ExtrudedPolygon>   (const Handle<TGeoShape>& solid);
+  template bool isInstance<TessellatedSolid>   (const Handle<TGeoShape>& solid);
   template bool isInstance<BooleanSolid>      (const Handle<TGeoShape>& solid);
 
   template <> bool isInstance<Cone>(const Handle<TGeoShape>& solid)  {
@@ -148,6 +149,7 @@ namespace dd4hep {
   template bool isA<ExtrudedPolygon>(const Handle<TGeoShape>& solid);
   template bool isA<Polycone>(const Handle<TGeoShape>& solid);
   template bool isA<EightPointSolid>(const Handle<TGeoShape>& solid);
+  template bool isA<TessellatedSolid>(const Handle<TGeoShape>& solid);
 
   template <> bool isA<TwistedTube>(const Handle<TGeoShape>& solid)   {
     return check_shape_type<TwistedTubeObject>(solid)
@@ -332,6 +334,30 @@ namespace dd4hep {
     for(auto p : s_pars) pars.push_back(p);
     return pars;
   }
+  template <> vector<double> dimensions<TGeoTessellated>(const TGeoShape* shape)    {
+    TGeoTessellated* sh = get_ptr<TGeoTessellated>(shape);
+    int num_facet = sh->GetNfacets();
+    int num_vtx   = sh->GetNvertices();
+    vector<double> pars;
+
+    printout(DEBUG,"TessellatedSolid","+++ Saving %d vertices, %d facets",num_vtx, num_facet);
+    pars.reserve(num_facet*5+num_vtx*3+2);
+    pars.emplace_back(num_vtx);
+    pars.emplace_back(num_facet);
+    for(int i=0; i<num_vtx; ++i)  {
+      const auto& v = sh->GetVertex(i);
+      pars.emplace_back(v.x());
+      pars.emplace_back(v.y());
+      pars.emplace_back(v.z());
+    }
+    for(int i=0; i<num_facet; ++i)  {
+      const TGeoFacet& f = sh->GetFacet(i);
+      pars.emplace_back(double(f.GetNvert()));
+      for(int j=0, n=f.GetNvert(); j<n; ++j)
+        pars.emplace_back(double(f.GetVertexIndex(j)));
+    }
+    return pars;
+  }
   template <> vector<double> dimensions<TGeoCompositeShape>(const TGeoShape* shape)    {
     const TGeoCompositeShape* sh = get_ptr<TGeoCompositeShape>(shape);
     const TGeoBoolNode*  boolean = sh->GetBoolNode();
@@ -383,6 +409,7 @@ namespace dd4hep {
   template vector<double> dimensions<Polyhedra>        (const Handle<TGeoShape>& shape);
   template vector<double> dimensions<ExtrudedPolygon>  (const Handle<TGeoShape>& shape);
   template vector<double> dimensions<EightPointSolid>  (const Handle<TGeoShape>& shape); 
+  template vector<double> dimensions<TessellatedSolid>  (const Handle<TGeoShape>& shape); 
   template vector<double> dimensions<BooleanSolid>     (const Handle<TGeoShape>& shape);
   template vector<double> dimensions<SubtractionSolid> (const Handle<TGeoShape>& shape);
   template vector<double> dimensions<UnionSolid>       (const Handle<TGeoShape>& shape);
@@ -475,6 +502,8 @@ namespace dd4hep {
         return dimensions<TGeoXtru>(shape.ptr());
       else if (cl == TGeoScaledShape::Class())
         return dimensions<TGeoScaledShape>(shape.ptr());
+      else if (cl == TGeoTessellated::Class())
+        return dimensions<TGeoTessellated>(shape.ptr());
       else if (isA<TruncatedTube>(shape.ptr()))
         return dimensions<TruncatedTube>(shape);
       else if (isA<PseudoTrap>(shape.ptr()))
@@ -704,6 +733,39 @@ namespace dd4hep {
     auto pars = params;
     s_sh.access()->SetDimensions(&pars[3]);
   }
+  template <> void set_dimensions(TGeoTessellated* sh, const std::vector<double>& params)    {
+    int num_vtx   = params[0];
+    int num_facet = params[1];
+    std::vector<TessellatedSolid::Vertex_t> vertices;
+    size_t i_par = 1;
+    printout(DEBUG,"TessellatedSolid","+++ Loading %d vertices, %d facets",num_vtx, num_facet);
+    for (int i=0; i<num_vtx; ++i)   {
+      double x = params[++i_par];
+      double y = params[++i_par];
+      double z = params[++i_par];
+      vertices.emplace_back(x, y, z);
+    }
+    string nam = sh->GetName();
+    string tit = sh->GetTitle();
+    sh->~TGeoTessellated();
+    new(sh) TGeoTessellated(nam.c_str(), vertices);
+    sh->SetTitle(tit.c_str());
+    int nfacet = 0;
+    for (int i=0; i<num_facet; ++i)   {
+      int i0, i1, i2, i3;
+      int n_vtx = params[++i_par];
+      i0 = n_vtx>0 ? params[++i_par] : -1;
+      i1 = n_vtx>1 ? params[++i_par] : -1;
+      i2 = n_vtx>2 ? params[++i_par] : -1;
+      i3 = n_vtx>3 ? params[++i_par] : -1;
+      if ( n_vtx == 3 )
+        sh->AddFacet(i0,i1,i2);
+      else if ( n_vtx == 4 )
+        sh->AddFacet(i0,i1,i2,i3);
+    }
+    sh->CloseShape(true, true, false);
+  }
+
   template <> void set_dimensions(TGeoCompositeShape*, const std::vector<double>&)   {
     // In general TGeoCompositeShape instances have an empty SetDimension call
 #if 0
@@ -762,6 +824,8 @@ namespace dd4hep {
   {  set_dimensions(shape.ptr(), params);   }
   template <> void set_dimensions(EightPointSolid shape, const std::vector<double>& params)
   {  set_dimensions(shape.ptr(), params);   }
+  template <> void set_dimensions(TessellatedSolid shape, const std::vector<double>& params)
+  {  set_dimensions(shape.ptr(), params);   }
   template <> void set_dimensions(BooleanSolid shape, const std::vector<double>& params)
   {  set_dimensions(shape.ptr(), params);   }
   template <> void set_dimensions(SubtractionSolid shape, const std::vector<double>& params)
@@ -962,6 +1026,8 @@ namespace dd4hep {
         set_dimensions(ExtrudedPolygon(shape), params);
       else if (cl == TGeoArb8::Class())
         set_dimensions(EightPointSolid(shape), params);
+      else if (cl == TGeoTessellated::Class())
+        set_dimensions(TessellatedSolid(shape), params);
       else if (cl == TGeoScaledShape::Class())  {
         TGeoScaledShape* sh = (TGeoScaledShape*) shape.ptr();
         set_dimensions(sh, params);
diff --git a/DDCore/src/Shapes.cpp b/DDCore/src/Shapes.cpp
index c81b9eb47..d401c9cb0 100644
--- a/DDCore/src/Shapes.cpp
+++ b/DDCore/src/Shapes.cpp
@@ -711,11 +711,41 @@ void ExtrudedPolygon::make(const string& nam,
     solid->DefineSection(i, sec_z[i], sec_x[i], sec_y[i], sec_scale[i]);
 }
 
-/// Creator method
+/// Creator method for arbitrary eight point solids
 void EightPointSolid::make(const string& nam, double dz, const double* vtx)   {
   _assign(new TGeoArb8(nam.c_str(), dz, (double*)vtx), "", EIGHTPOINTSOLID_TAG, true);
 }
 
+/// Internal helper method to support object construction
+void TessellatedSolid::make(const std::string& nam, int num_facets)   {
+  _assign(new TGeoTessellated(nam.c_str(), num_facets), nam, TESSELLATEDSOLID_TAG, false);
+}
+
+/// Internal helper method to support object construction
+void TessellatedSolid::make(const std::string& nam, const std::vector<Object::Vertex_t>& vertices)   {
+  _assign(new TGeoTessellated(nam.c_str(), vertices), nam, TESSELLATEDSOLID_TAG, false);
+}
+
+/// Add new facet to the shape
+bool TessellatedSolid::addFacet(const Vertex_t& pt0, const Vertex_t& pt1, const Vertex_t& pt2)  const {
+  return access()->AddFacet(pt0, pt1, pt2);
+}
+
+/// Add new facet to the shape
+bool TessellatedSolid::addFacet(const Vertex_t& pt0, const Vertex_t& pt1, const Vertex_t& pt2, const Vertex_t& pt3)  const {
+  return access()->AddFacet(pt0, pt1, pt2, pt3);
+}
+
+/// Add new facet to the shape. Call only if the tessellated shape was constructed with vertices
+bool TessellatedSolid::addFacet(const int pt0, const int pt1, const int pt2)  const    {
+  return access()->AddFacet(pt0, pt1, pt2);
+}
+
+/// Add new facet to the shape. Call only if the tessellated shape was constructed with vertices
+bool TessellatedSolid::addFacet(const int pt0, const int pt1, const int pt2, const int pt3)  const   {
+  return access()->AddFacet(pt0, pt1, pt2, pt3);
+}
+
 /// Constructor to be used when creating a new object. Position is identity, Rotation is the identity rotation
 SubtractionSolid::SubtractionSolid(const Solid& shape1, const Solid& shape2) {
   TGeoSubtraction* sub = new TGeoSubtraction(shape1, shape2, detail::matrix::_identity(), detail::matrix::_identity());
@@ -918,4 +948,5 @@ INSTANTIATE(TGeoHype);
 INSTANTIATE(TGeoTrap);
 INSTANTIATE(TGeoTrd1);
 INSTANTIATE(TGeoTrd2);
+INSTANTIATE(TGeoTessellated);
 INSTANTIATE(TGeoCompositeShape);
diff --git a/DDCore/src/plugins/ShapePlugins.cpp b/DDCore/src/plugins/ShapePlugins.cpp
index 470beb7ec..9ea5bd52f 100644
--- a/DDCore/src/plugins/ShapePlugins.cpp
+++ b/DDCore/src/plugins/ShapePlugins.cpp
@@ -255,6 +255,7 @@ static Handle<TObject> create_PolyhedraRegular(Detector&, xml_h element)   {
 }
 DECLARE_XML_SHAPE(PolyhedraRegular__shape_constructor,create_PolyhedraRegular)
 
+/// Plugin factory to created polyhedra shapes
 static Handle<TObject> create_Polyhedra(Detector&, xml_h element)   {
   xml_dim_t e(element);
   std::vector<double> z, rmin, rmax;
@@ -270,6 +271,7 @@ static Handle<TObject> create_Polyhedra(Detector&, xml_h element)   {
 }
 DECLARE_XML_SHAPE(Polyhedra__shape_constructor,create_Polyhedra)
 
+/// Plugin factory to created extruded polygons
 static Handle<TObject> create_ExtrudedPolygon(Detector&, xml_h element)   {
   xml_dim_t e(element);
   std::vector<double> pt_x, pt_y, sec_z, sec_x, sec_y, sec_scale;
@@ -291,6 +293,7 @@ static Handle<TObject> create_ExtrudedPolygon(Detector&, xml_h element)   {
 }
 DECLARE_XML_SHAPE(ExtrudedPolygon__shape_constructor,create_ExtrudedPolygon)
 
+/// Plugin factory to created arbitrary 8-point solids
 static Handle<TObject> create_EightPointSolid(Detector&, xml_h element)   {
   xml_dim_t e(element);
   double v[8][2];
@@ -307,6 +310,32 @@ static Handle<TObject> create_EightPointSolid(Detector&, xml_h element)   {
 }
 DECLARE_XML_SHAPE(EightPointSolid__shape_constructor,create_EightPointSolid)
 
+/// Plugin factory to created tessellated shapes
+static Handle<TObject> create_TessellatedSolid(Detector&, xml_h element)   {
+  xml_dim_t e(element);
+  std::vector<TessellatedSolid::Vertex_t> vertices;
+  for ( xml_coll_t vtx(element, _U(vertex)); vtx; ++vtx )   {
+    xml_dim_t v(vtx);
+    vertices.emplace_back(v.x(), v.y(), v.z());
+  }
+  int num_facets = 0;
+  for ( xml_coll_t facet(element, _U(facet)); facet; ++facet ) ++num_facets;
+  TessellatedSolid solid = TessellatedSolid(num_facets);
+  if ( e.hasAttr(_U(name)) ) solid->SetName(e.attr<string>(_U(name)).c_str());
+  for ( xml_coll_t facet(element, _U(facet)); facet; ++facet )   {
+    xml_dim_t f(facet);
+    int i0 = f.attr<int>(_U(v0)), i1 = f.attr<int>(_U(v1)), i2 = f.attr<int>(_U(v2));
+    if ( f.hasAttr(_U(v3)) )   {
+      int i3 = f.attr<int>(_U(v3));
+      solid.addFacet(vertices[i0], vertices[i1], vertices[i2], vertices[i3]);
+    }
+    else   {
+      solid.addFacet(vertices[i0], vertices[i1], vertices[i2]);
+    }
+  }
+  return solid;
+}
+DECLARE_XML_SHAPE(TessellatedSolid__shape_constructor,create_TessellatedSolid)
 
 /** Plugin function for creating a boolean solid from an xml element <shape type=\"BooleanShape\"/>. 
  *  Expects exactly two child elements <shape/> and a string attribute 'operation', which is one of
@@ -600,6 +629,8 @@ static Ref_t create_shape(Detector& description, xml_h e, Ref_t /* sens */)  {
       instance_test = isInstance<EllipticalTube>(solid);
     else if ( 0 == strcasecmp(solid->GetTitle(),EXTRUDEDPOLYGON_TAG) )
       instance_test = isInstance<ExtrudedPolygon>(solid);
+    else if ( 0 == strcasecmp(solid->GetTitle(),TESSELLATEDSOLID_TAG) )
+      instance_test = isInstance<TessellatedSolid>(solid);
     else if ( 0 == strcasecmp(solid->GetTitle(),POLYCONE_TAG) )
       instance_test = isInstance<Polycone>(solid);
     else if ( 0 == strcasecmp(solid->GetTitle(),TWISTEDTUBE_TAG) )   {
@@ -804,6 +835,8 @@ void* shape_mesh_verifier(Detector& description, int argc, char** argv)    {
       os << toStringMesh(place, 2);
     }
     if ( ref_str != os.str() )  {
+      printout(DEBUG,"Mesh_Verifier","+++ REFERENCE shape mesh:\n%s",ref_str.c_str());
+      printout(DEBUG,"Mesh_Verifier","+++ REDIMENSIONED shape mesh:\n%s",os.str().c_str());
       printout(ERROR,"Mesh_Verifier","+++ Output and reference differ after re-dimension! Please check.");
       return Constant("FAILURE",os.str().c_str()).ptr();
     }
diff --git a/DDG4/src/Geant4Converter.cpp b/DDG4/src/Geant4Converter.cpp
index 231f38610..f97cbcfa8 100644
--- a/DDG4/src/Geant4Converter.cpp
+++ b/DDG4/src/Geant4Converter.cpp
@@ -574,6 +574,8 @@ void* Geant4Converter::handleSolid(const string& name, const TGeoShape* shape) c
       solid = convertShape<TGeoTrap>(shape);
     else if (isa == TGeoArb8::Class()) 
       solid = convertShape<TGeoArb8>(shape);
+    else if (isa == TGeoTessellated::Class()) 
+      solid = convertShape<TGeoTessellated>(shape);
     else if (isa == TGeoScaledShape::Class())  {
       TGeoScaledShape* sh = (TGeoScaledShape*) shape;
       const double*    vals = sh->GetScale()->GetScale();
diff --git a/DDG4/src/Geant4ShapeConverter.cpp b/DDG4/src/Geant4ShapeConverter.cpp
index 3e12a1074..8ff8888eb 100644
--- a/DDG4/src/Geant4ShapeConverter.cpp
+++ b/DDG4/src/Geant4ShapeConverter.cpp
@@ -43,6 +43,9 @@
 #include "G4GenericTrap.hh"
 #include "G4ExtrudedSolid.hh"
 #include "G4EllipticalTube.hh"
+#include "G4TessellatedSolid.hh"
+#include "G4TriangularFacet.hh"
+#include "G4QuadrangularFacet.hh"
 
 // C/C++ include files
 
@@ -93,7 +96,8 @@ namespace dd4hep {
       const Double_t* hn = sh->GetNhigh();
       G4ThreeVector   lowNorm (ln[0], ln[1], ln[2]);
       G4ThreeVector   highNorm(hn[0], hn[1], hn[2]);
-      return new G4CutTubs(sh->GetName(), sh->GetRmin() * CM_2_MM, sh->GetRmax() * CM_2_MM, sh->GetDz() * CM_2_MM,
+      return new G4CutTubs(sh->GetName(),
+                           sh->GetRmin() * CM_2_MM, sh->GetRmax() * CM_2_MM, sh->GetDz() * CM_2_MM,
                            sh->GetPhi1() * DEGREE_2_RAD, (sh->GetPhi2()-sh->GetPhi1()) * DEGREE_2_RAD, lowNorm, highNorm);
     }
 
@@ -112,13 +116,17 @@ namespace dd4hep {
 
     template <> G4VSolid* convertShape<TGeoTrd1>(const TGeoShape* shape)  {
       const TGeoTrd1* sh = (const TGeoTrd1*) shape;
-      return new G4Trd(sh->GetName(), sh->GetDx1() * CM_2_MM, sh->GetDx2() * CM_2_MM, sh->GetDy() * CM_2_MM, sh->GetDy() * CM_2_MM,
+      return new G4Trd(sh->GetName(),
+                       sh->GetDx1() * CM_2_MM, sh->GetDx2() * CM_2_MM,
+                       sh->GetDy() * CM_2_MM, sh->GetDy() * CM_2_MM,
                        sh->GetDz() * CM_2_MM);
     }
 
     template <> G4VSolid* convertShape<TGeoTrd2>(const TGeoShape* shape)  {
       const TGeoTrd2* sh = (const TGeoTrd2*) shape;
-      return new G4Trd(sh->GetName(), sh->GetDx1() * CM_2_MM, sh->GetDx2() * CM_2_MM, sh->GetDy1() * CM_2_MM, sh->GetDy2() * CM_2_MM,
+      return new G4Trd(sh->GetName(),
+                       sh->GetDx1() * CM_2_MM, sh->GetDx2() * CM_2_MM,
+                       sh->GetDy1() * CM_2_MM, sh->GetDy2() * CM_2_MM,
                        sh->GetDz() * CM_2_MM);
     }
 
@@ -214,6 +222,42 @@ namespace dd4hep {
                         sh->GetH2() * CM_2_MM, sh->GetBl2() * CM_2_MM, sh->GetTl2() * CM_2_MM, sh->GetAlpha2() * DEGREE_2_RAD);
     }
 
+    template <> G4VSolid* convertShape<TGeoTessellated>(const TGeoShape* shape)  {
+      TGeoTessellated*   sh  = (TGeoTessellated*) shape;
+      G4TessellatedSolid* g4 = new G4TessellatedSolid(sh->GetName());
+      int num_facet = sh->GetNfacets();
+
+      printout(DEBUG,"TessellatedSolid","+++ %s> Converting %d facets", sh->GetName(), num_facet);
+      for(int i=0; i<num_facet; ++i)  {
+        const TGeoFacet& facet = sh->GetFacet(i);
+        int nv = facet.GetNvert();
+        const auto& v0 = sh->GetVertex(facet.GetVertexIndex(0));
+        const auto& v1 = sh->GetVertex(facet.GetVertexIndex(1));
+        const auto& v2 = sh->GetVertex(facet.GetVertexIndex(2));
+        G4VFacet* g4f = 0;
+        if ( nv == 3 )    {
+          g4f = new G4TriangularFacet(G4ThreeVector(v0.x() * CM_2_MM, v0.y() * CM_2_MM, v0.z() * CM_2_MM),
+                                      G4ThreeVector(v1.x() * CM_2_MM, v1.y() * CM_2_MM, v1.z() * CM_2_MM),
+                                      G4ThreeVector(v2.x() * CM_2_MM, v2.y() * CM_2_MM, v2.z() * CM_2_MM),
+                                      ABSOLUTE);
+        }
+        else if ( nv == 4 )    {
+          const auto& v3 = sh->GetVertex(facet.GetVertexIndex(3));
+          g4f = new G4QuadrangularFacet(G4ThreeVector(v0.x() * CM_2_MM, v0.y() * CM_2_MM, v0.z() * CM_2_MM),
+                                        G4ThreeVector(v1.x() * CM_2_MM, v1.y() * CM_2_MM, v1.z() * CM_2_MM),
+                                        G4ThreeVector(v2.x() * CM_2_MM, v2.y() * CM_2_MM, v2.z() * CM_2_MM),
+                                        G4ThreeVector(v3.x() * CM_2_MM, v3.y() * CM_2_MM, v3.z() * CM_2_MM),
+                                        ABSOLUTE);
+        }
+        else   {
+          except("TGeoTessellated", "Tessellated shape [%s] has facet with wrong number of vertices: %d",
+                 sh->GetName(), nv);
+        }
+        g4->AddFacet(g4f);
+      }
+      return g4;
+    }
+
     template <> G4VSolid* convertShape<G4GenericTrap>(const TGeoShape* shape)  {
       vector<G4TwoVector> vertices;
       TGeoTrap* sh = (TGeoTrap*) shape;
diff --git a/examples/ClientTests/CMakeLists.txt b/examples/ClientTests/CMakeLists.txt
index ad85a0ce4..754393b0f 100644
--- a/examples/ClientTests/CMakeLists.txt
+++ b/examples/ClientTests/CMakeLists.txt
@@ -191,7 +191,7 @@ dd4hep_add_test_reg( ClientTests_Save_ROOT_MiniTel_LONGTEST
 #  Test basic shapes by comparing mesh vertices with reference file
 foreach (test Box Cone ConeSegment Tube ElTube
     CutTube Hyperboloid Paraboloid EightPointSolid Eightpoint_Reflect_Volume Eightpoint_Reflect_DetElement
-    Polycone Polyhedra PseudoTrap PseudoTrap2 Sphere Torus
+    Polycone Polyhedra PseudoTrap PseudoTrap2 Sphere Torus Tesselated
     Trap Trd1 Trd2 TruncatedTube ExtrudedPolygon)
   dd4hep_add_test_reg( ClientTests_Check_Shape_${test}
       COMMAND    "${CMAKE_INSTALL_PREFIX}/bin/run_test_ClientTests.sh"
diff --git a/examples/ClientTests/compact/Check_Shape_Tesselated.xml b/examples/ClientTests/compact/Check_Shape_Tesselated.xml
new file mode 100644
index 000000000..0ac494040
--- /dev/null
+++ b/examples/ClientTests/compact/Check_Shape_Tesselated.xml
@@ -0,0 +1,202 @@
+<lccdd>
+  <includes>
+    <gdmlFile ref="CheckShape.xml"/>
+  </includes>
+  <define>
+    <constant name="sqrt5" value="sqrt(5.0)"/>
+  </define>
+
+  <detectors>
+    <detector id="1" name="Shape_Tessellated" type="DD4hep_TestShape_Creator">
+      <check vis="Shape1_vis">
+        <shape type="TessellatedSolid">
+          <vertex x="0" y="0.5 * (1 + sqrt5)" z="-1"/>
+          <vertex x="0" y="0.5 * (-1 + sqrt5)" z="0.5 * (-1 - sqrt5)"/>
+          <vertex x="-1" y="0" z="0.5 * (-1 - sqrt5)"/>
+          <vertex x="-1" y="1" z="-1"/>
+
+          <vertex x="1" y="1" z="-1"/>
+          <vertex x="0" y="0.5 * (1 + sqrt5)" z="-1"/>
+          <vertex x="0" y="0.5 * (-1 + sqrt5)" z="0.5 * (-1 - sqrt5)"/>
+          <vertex x="1" y="0" z="0.5 * (-1 - sqrt5)"/>
+
+          <vertex x="1" y="1" z="-1"/>
+          <vertex x="0" y="0.5 * (1 + sqrt5)" z="-1"/>
+          <vertex x="0.5 * (-1 + sqrt5)" y="0.5 * (1 + sqrt5)" z="0"/>
+          <vertex x="0.5 * (1 + sqrt5)" y="1" z="0"/>
+
+          <vertex x="0.5 * (1 - sqrt5)" y="0.5 * (1 + sqrt5)" z="0"/>
+          <vertex x="0" y="0.5 * (1 + sqrt5)" z="-1"/>
+          <vertex x="0.5 * (-1 + sqrt5)" y="0.5 * (1 + sqrt5)" z="0"/>
+          <vertex x="0" y="0.5 * (1 + sqrt5)" z="1"/>
+
+          <vertex x="0.5 * (1 - sqrt5)" y="0.5 * (1 + sqrt5)" z="0"/>
+          <vertex x="0" y="0.5 * (1 + sqrt5)" z="-1"/>
+          <vertex x="-1" y="1" z="-1"/>
+          <vertex x="0.5 * (-1 - sqrt5)" y="1" z="0"/>
+
+          <vertex x="1" y="1" z="-1"/>
+          <vertex x="0.5 * (1 + sqrt5)" y="1" z="0"/>
+          <vertex x="0.5 * (1 + sqrt5)" y="0" z="0.5 * (1 - sqrt5)"/>
+          <vertex x="1" y="0" z="0.5 * (-1 - sqrt5)"/>
+
+          <vertex x="0.5 * (1 + sqrt5)" y="0" z="0.5 * (1 - sqrt5)"/>
+          <vertex x="0.5 * (1 + sqrt5)" y="-1" z="0"/>
+          <vertex x="1" y="-1" z="-1"/>
+          <vertex x="1" y="0" z="0.5 * (-1 - sqrt5)"/>
+
+          <vertex x="1" y="-1" z="-1"/>
+          <vertex x="0" y="0.5 * (-1 - sqrt5)" z="-1"/>
+          <vertex x="0" y="0.5 * (1 - sqrt5)" z="0.5 * (-1 - sqrt5)"/>
+          <vertex x="1" y="0" z="0.5 * (-1 - sqrt5)"/>
+
+          <vertex x="1" y="0" z="0.5 * (-1 - sqrt5)"/>
+          <vertex x="0" y="0.5 * (-1 + sqrt5)" z="0.5 * (-1 - sqrt5)"/>
+          <vertex x="-1" y="0" z="0.5 * (-1 - sqrt5)"/>
+          <vertex x="0" y="0.5 * (1 - sqrt5)" z="0.5 * (-1 - sqrt5)"/>
+
+          <vertex x="0.5 * (-1 + sqrt5)" y="0.5 * (1 + sqrt5)" z="0"/>
+          <vertex x="0.5 * (1 + sqrt5)" y="1" z="0"/>
+          <vertex x="1" y="1" z="1"/>
+          <vertex x="0" y="0.5 * (1 + sqrt5)" z="1"/>
+
+          <vertex x="0.5 * (1 + sqrt5)" y="1" z="0"/>
+          <vertex x="1" y="1" z="1"/>
+          <vertex x="1" y="0" z="0.5 * (1 + sqrt5)"/>
+          <vertex x="0.5 * (1 + sqrt5)" y="0" z="0.5 * (-1 + sqrt5)"/>
+
+          <vertex x="0.5 * (1 + sqrt5)" y="0" z="0.5 * (1 - sqrt5)"/>
+          <vertex x="0.5 * (1 + sqrt5)" y="1" z="0"/>
+          <vertex x="0.5 * (1 + sqrt5)" y="0" z="0.5 * (-1 + sqrt5)"/>
+          <vertex x="0.5 * (1 + sqrt5)" y="-1" z="0"/>
+
+          <vertex x="0.5 * (1 - sqrt5)" y="0.5 * (1 + sqrt5)" z="0"/>
+          <vertex x="0" y="0.5 * (1 + sqrt5)" z="1"/>
+          <vertex x="-1" y="1" z="1"/>
+          <vertex x="0.5 * (-1 - sqrt5)" y="1" z="0"/>
+
+          <vertex x="0" y="0.5 * (1 + sqrt5)" z="1"/>
+          <vertex x="0" y="0.5 * (-1 + sqrt5)" z="0.5 * (1 + sqrt5)"/>
+          <vertex x="-1" y="0" z="0.5 * (1 + sqrt5)"/>
+          <vertex x="-1" y="1" z="1"/>
+
+          <vertex x="1" y="1" z="1"/>
+          <vertex x="0" y="0.5 * (1 + sqrt5)" z="1"/>
+          <vertex x="0" y="0.5 * (-1 + sqrt5)" z="0.5 * (1 + sqrt5)"/>
+          <vertex x="1" y="0" z="0.5 * (1 + sqrt5)"/>
+
+          <vertex x="0" y="0.5 * (1 - sqrt5)" z="0.5 * (1 + sqrt5)"/>
+          <vertex x="-1" y="0" z="0.5 * (1 + sqrt5)"/>
+          <vertex x="0" y="0.5 * (-1 + sqrt5)" z="0.5 * (1 + sqrt5)"/>
+          <vertex x="1" y="0" z="0.5 * (1 + sqrt5)"/>
+
+          <vertex x="0" y="0.5 * (1 - sqrt5)" z="0.5 * (1 + sqrt5)"/>
+          <vertex x="1" y="0" z="0.5 * (1 + sqrt5)"/>
+          <vertex x="1" y="-1" z="1"/>
+          <vertex x="0" y="0.5 * (-1 - sqrt5)" z="1"/>
+
+          <vertex x="0.5 * (1 + sqrt5)" y="0" z="0.5 * (-1 + sqrt5)"/>
+          <vertex x="0.5 * (1 + sqrt5)" y="-1" z="0"/>
+          <vertex x="1" y="-1" z="1"/>
+          <vertex x="1" y="0" z="0.5 * (1 + sqrt5)"/>
+
+          <vertex x="-1" y="0" z="0.5 * (1 + sqrt5)"/>
+          <vertex x="-1" y="1" z="1"/>
+          <vertex x="0.5 * (-1 - sqrt5)" y="1" z="0"/>
+          <vertex x="0.5 * (-1 - sqrt5)" y="0" z="0.5 * (-1 + sqrt5)"/>
+
+          <vertex x="-1" y="-1" z="1"/>
+          <vertex x="-1" y="0" z="0.5 * (1 + sqrt5)"/>
+          <vertex x="0.5 * (-1 - sqrt5)" y="0" z="0.5 * (-1 + sqrt5)"/>
+          <vertex x="0.5 * (-1 - sqrt5)" y="-1" z="0"/>
+
+          <vertex x="0" y="0.5 * (1 - sqrt5)" z="0.5 * (1 + sqrt5)"/>
+          <vertex x="-1" y="0" z="0.5 * (1 + sqrt5)"/>
+          <vertex x="-1" y="-1" z="1"/>
+          <vertex x="0" y="0.5 * (-1 - sqrt5)" z="1"/>
+
+          <vertex x="0.5 * (-1 - sqrt5)" y="-1" z="0"/>
+          <vertex x="0.5 * (-1 - sqrt5)" y="0" z="0.5 * (1 - sqrt5)"/>
+          <vertex x="0.5 * (-1 - sqrt5)" y="1" z="0"/>
+          <vertex x="0.5 * (-1 - sqrt5)" y="0" z="0.5 * (-1 + sqrt5)"/>
+
+          <vertex x="0.5 * (-1 - sqrt5)" y="-1" z="0"/>
+          <vertex x="0.5 * (-1 - sqrt5)" y="0" z="0.5 * (1 - sqrt5)"/>
+          <vertex x="-1" y="0" z="0.5 * (-1 - sqrt5)"/>
+          <vertex x="-1" y="-1" z="-1"/>
+
+          <vertex x="0" y="0.5 * (-1 - sqrt5)" z="-1"/>
+          <vertex x="0.5 * (1 - sqrt5)" y="0.5 * (-1 - sqrt5)" z="0"/>
+          <vertex x="0.5 * (-1 - sqrt5)" y="-1" z="0"/>
+          <vertex x="-1" y="-1" z="-1"/>
+
+          <vertex x="0.5 * (1 - sqrt5)" y="0.5 * (-1 - sqrt5)" z="0"/>
+          <vertex x="0.5 * (-1 - sqrt5)" y="-1" z="0"/>
+          <vertex x="-1" y="-1" z="1"/>
+          <vertex x="0" y="0.5 * (-1 - sqrt5)" z="1"/>
+
+          <vertex x="-1" y="1" z="-1"/>
+          <vertex x="-1" y="0" z="0.5 * (-1 - sqrt5)"/>
+          <vertex x="0.5 * (-1 - sqrt5)" y="0" z="0.5 * (1 - sqrt5)"/>
+          <vertex x="0.5 * (-1 - sqrt5)" y="1" z="0"/>
+
+          <vertex x="0" y="0.5 * (-1 - sqrt5)" z="-1"/>
+          <vertex x="0" y="0.5 * (1 - sqrt5)" z="0.5 * (-1 - sqrt5)"/>
+          <vertex x="-1" y="0" z="0.5 * (-1 - sqrt5)"/>
+          <vertex x="-1" y="-1" z="-1"/>
+
+          <vertex x="0" y="0.5 * (-1 - sqrt5)" z="-1"/>
+          <vertex x="0.5 * (1 - sqrt5)" y="0.5 * (-1 - sqrt5)" z="0"/>
+          <vertex x="0" y="0.5 * (-1 - sqrt5)" z="1"/>
+          <vertex x="0.5 * (-1 + sqrt5)" y="0.5 * (-1 - sqrt5)" z="0"/>
+
+          <vertex x="1" y="-1" z="-1"/>
+          <vertex x="0.5 * (1 + sqrt5)" y="-1" z="0"/>
+          <vertex x="0.5 * (-1 + sqrt5)" y="0.5 * (-1 - sqrt5)" z="0"/>
+          <vertex x="0" y="0.5 * (-1 - sqrt5)" z="-1"/>
+
+          <vertex x="0.5 * (1 + sqrt5)" y="-1" z="0"/>
+          <vertex x="1" y="-1" z="1"/>
+          <vertex x="0" y="0.5 * (-1 - sqrt5)" z="1"/>
+          <vertex x="0.5 * (-1 + sqrt5)" y="0.5 * (-1 - sqrt5)" z="0"/>
+
+          <facet v0="0"  v1="1"  v2="2"  v3="3"/>
+          <facet v0="4"  v1="7"  v2="6"  v3="5"/>
+          <facet v0="8"  v1="9"  v2="10" v3="11"/>
+          <facet v0="12" v1="15" v2="14" v3="13"/>
+          <facet v0="16" v1="17" v2="18" v3="19"/>
+          <facet v0="20" v1="21" v2="22" v3="23"/>
+          <facet v0="24" v1="25" v2="26" v3="27"/>
+          <facet v0="28" v1="29" v2="30" v3="31"/>
+          <facet v0="32" v1="35" v2="34" v3="33"/>
+          <facet v0="36" v1="39" v2="38" v3="37"/>
+          <facet v0="40" v1="41" v2="42" v3="43"/>
+          <facet v0="44" v1="45" v2="46" v3="47"/>
+          <facet v0="48" v1="51" v2="50" v3="49"/>
+          <facet v0="52" v1="55" v2="54" v3="53"/>
+          <facet v0="56" v1="57" v2="58" v3="59"/>
+          <facet v0="60" v1="63" v2="62" v3="61"/>
+          <facet v0="64" v1="67" v2="66" v3="65"/>
+          <facet v0="68" v1="71" v2="70" v3="69"/>
+          <facet v0="72" v1="73" v2="74" v3="75"/>
+          <facet v0="76" v1="77" v2="78" v3="79"/>
+          <facet v0="80" v1="81" v2="82" v3="83"/>
+          <facet v0="84" v1="87" v2="86" v3="85"/>
+          <facet v0="88" v1="89" v2="90" v3="91"/>
+          <facet v0="92" v1="93" v2="94" v3="95"/>
+          <facet v0="96" v1="99" v2="98" v3="97"/>
+          <facet v0="100" v1="101" v2="102" v3="103"/>
+          <facet v0="104" v1="107" v2="106" v3="105"/>
+          <facet v0="108" v1="111" v2="110" v3="109"/>
+          <facet v0="112" v1="113" v2="114" v3="115"/>
+          <facet v0="116" v1="117" v2="118" v3="119"/>
+
+        </shape>
+        <position x="0"  y="0" z="0"/>
+        <rotation x="0"   y="0" z="0"/>
+      </check>
+      <test  type="DD4hep_Mesh_Verifier" ref="${DD4hepExamplesINSTALL}/examples/ClientTests/ref/Ref_Tessellated.txt" create="CheckShape_create"/>
+      <test_writing_reference  type="DD4hep_Mesh_Verifier" ref="${DD4hepExamplesINSTALL}/examples/ClientTests/ref/Ref_Tessellated.txt" create="1"/>
+    </detector>
+  </detectors>
+</lccdd>
diff --git a/examples/ClientTests/ref/Ref_Tesselated.txt b/examples/ClientTests/ref/Ref_Tesselated.txt
new file mode 100644
index 000000000..ff07fdbee
--- /dev/null
+++ b/examples/ClientTests/ref/Ref_Tesselated.txt
@@ -0,0 +1,35 @@
+ShapeCheck[0] TGeoTessellated  32 Mesh-points:
+TGeoTessellated  TessellatedSolid N(mesh)=32  N(vert)=32  N(seg)=120  N(pols)=30
+TGeoTessellated  0   Local  (   0.00,    1.62,   -1.00) Global (   0.00,    1.62,   -1.00)
+TGeoTessellated  1   Local  (   0.00,    0.62,   -1.62) Global (   0.00,    0.62,   -1.62)
+TGeoTessellated  2   Local  (  -1.00,    0.00,   -1.62) Global (  -1.00,    0.00,   -1.62)
+TGeoTessellated  3   Local  (  -1.00,    1.00,   -1.00) Global (  -1.00,    1.00,   -1.00)
+TGeoTessellated  4   Local  (   1.00,    1.00,   -1.00) Global (   1.00,    1.00,   -1.00)
+TGeoTessellated  5   Local  (   1.00,    0.00,   -1.62) Global (   1.00,    0.00,   -1.62)
+TGeoTessellated  6   Local  (   0.62,    1.62,    0.00) Global (   0.62,    1.62,    0.00)
+TGeoTessellated  7   Local  (   1.62,    1.00,    0.00) Global (   1.62,    1.00,    0.00)
+TGeoTessellated  8   Local  (  -0.62,    1.62,    0.00) Global (  -0.62,    1.62,    0.00)
+TGeoTessellated  9   Local  (   0.00,    1.62,    1.00) Global (   0.00,    1.62,    1.00)
+TGeoTessellated  10  Local  (  -1.62,    1.00,    0.00) Global (  -1.62,    1.00,    0.00)
+TGeoTessellated  11  Local  (   1.62,    0.00,   -0.62) Global (   1.62,    0.00,   -0.62)
+TGeoTessellated  12  Local  (   1.62,   -1.00,    0.00) Global (   1.62,   -1.00,    0.00)
+TGeoTessellated  13  Local  (   1.00,   -1.00,   -1.00) Global (   1.00,   -1.00,   -1.00)
+TGeoTessellated  14  Local  (   0.00,   -1.62,   -1.00) Global (   0.00,   -1.62,   -1.00)
+TGeoTessellated  15  Local  (   0.00,   -0.62,   -1.62) Global (   0.00,   -0.62,   -1.62)
+TGeoTessellated  16  Local  (   1.00,    1.00,    1.00) Global (   1.00,    1.00,    1.00)
+TGeoTessellated  17  Local  (   1.00,    0.00,    1.62) Global (   1.00,    0.00,    1.62)
+TGeoTessellated  18  Local  (   1.62,    0.00,    0.62) Global (   1.62,    0.00,    0.62)
+TGeoTessellated  19  Local  (  -1.00,    1.00,    1.00) Global (  -1.00,    1.00,    1.00)
+TGeoTessellated  20  Local  (  -1.00,    0.00,    1.62) Global (  -1.00,    0.00,    1.62)
+TGeoTessellated  21  Local  (   0.00,    0.62,    1.62) Global (   0.00,    0.62,    1.62)
+TGeoTessellated  22  Local  (   0.00,   -0.62,    1.62) Global (   0.00,   -0.62,    1.62)
+TGeoTessellated  23  Local  (   0.00,   -1.62,    1.00) Global (   0.00,   -1.62,    1.00)
+TGeoTessellated  24  Local  (   1.00,   -1.00,    1.00) Global (   1.00,   -1.00,    1.00)
+TGeoTessellated  25  Local  (  -1.62,    0.00,    0.62) Global (  -1.62,    0.00,    0.62)
+TGeoTessellated  26  Local  (  -1.00,   -1.00,    1.00) Global (  -1.00,   -1.00,    1.00)
+TGeoTessellated  27  Local  (  -1.62,   -1.00,    0.00) Global (  -1.62,   -1.00,    0.00)
+TGeoTessellated  28  Local  (  -1.62,    0.00,   -0.62) Global (  -1.62,    0.00,   -0.62)
+TGeoTessellated  29  Local  (  -1.00,   -1.00,   -1.00) Global (  -1.00,   -1.00,   -1.00)
+TGeoTessellated  30  Local  (  -0.62,   -1.62,    0.00) Global (  -0.62,   -1.62,    0.00)
+TGeoTessellated  31  Local  (   0.62,   -1.62,    0.00) Global (   0.62,   -1.62,    0.00)
+TGeoTessellated  Bounding box:  dx=   1.62 dy=   1.62 dz=   1.62 Origin: x=   0.00 y=   0.00 z=   0.00
-- 
GitLab