diff --git a/DDCAD/include/DDCAD/ASSIMPReader.h b/DDCAD/include/DDCAD/ASSIMPReader.h
index 59d74f9cdc9490af0303f35b1a1f0b7228939188..80fdf5ada35195e4010dd9446fcf3f5e6eecb0e0 100644
--- a/DDCAD/include/DDCAD/ASSIMPReader.h
+++ b/DDCAD/include/DDCAD/ASSIMPReader.h
@@ -24,16 +24,30 @@ namespace dd4hep {
   /// Namespace for implementation details of the AIDA detector description toolkit
   namespace cad  {
 
+    /// Reader class to input geometry shapes from CAD files
+    /**
+     *  As a helper the ASSIMP library is used to interprete the 
+     *  CAD formats.
+     *
+     *  \author  M.Frank
+     *  \version 1.0
+     *  \ingroup DD4HEP_DDCAD
+     */
     class ASSIMPReader : public InputReader   {
     public:
       using InputReader::InputReader;
+
       /// Default destructor
       virtual ~ASSIMPReader() = default;
+
       /// Read input file
       virtual std::vector<std::unique_ptr<TGeoTessellated> >
-      read(const std::string& source, double unit_Length)  const  override;      
+      readShapes(const std::string& source, double unit_Length)  const  override;
+      
+      /// Read input file and create a volume-set
+      virtual std::vector<std::unique_ptr<TGeoVolume> >
+      readVolumes(const std::string& source, double unit_length)  const override;
     };
-    
   }        /* End namespace cad                      */
 }          /* End namespace dd4hep                   */
 #endif // DDCAD_ASSIMPREADER_H
diff --git a/DDCAD/include/DDCAD/ASSIMPWriter.h b/DDCAD/include/DDCAD/ASSIMPWriter.h
new file mode 100644
index 0000000000000000000000000000000000000000..4d08da066363892e73b186d089af652b66976b7d
--- /dev/null
+++ b/DDCAD/include/DDCAD/ASSIMPWriter.h
@@ -0,0 +1,51 @@
+//==========================================================================
+//  AIDA Detector description implementation 
+//--------------------------------------------------------------------------
+// Copyright (C) Organisation europeenne pour la Recherche nucleaire (CERN)
+// All rights reserved.
+//
+// For the licensing terms see $DD4hepINSTALL/LICENSE.
+// For the list of contributors see $DD4hepINSTALL/doc/CREDITS.
+//
+// Author     : M.Frank
+//
+//==========================================================================
+#ifndef DDCAD_ASSIMPWRITER_H
+#define DDCAD_ASSIMPWRITER_H
+
+/// Framework include files
+#include <DDCAD/OutputWriter.h>
+
+/// C/C++ include files
+
+/// Namespace for the AIDA detector description toolkit
+namespace dd4hep {
+
+  /// Namespace for implementation details of the AIDA detector description toolkit
+  namespace cad  {
+
+    /// Writer class to output geometry shapes from CAD files
+    /**
+     *  As a helper the ASSIMP library is used to interprete the 
+     *  CAD formats.
+     *
+     *  \author  M.Frank
+     *  \version 1.0
+     *  \ingroup DD4HEP_DDCAD
+     */
+    class ASSIMPWriter : public OutputWriter   {
+    public:
+      using OutputWriter::OutputWriter;
+      /// Default destructor
+      virtual ~ASSIMPWriter() = default;
+      /// Write output file
+      virtual int write(const std::string& output_file,
+			const std::string& output_type,
+			const VolumePlacements& places,
+			bool   recursive,
+			double unit_scale = 1.0)  const  override;      
+    };
+    
+  }        /* End namespace cad                      */
+}          /* End namespace dd4hep                   */
+#endif // DDCAD_ASSIMPWRITER_H
diff --git a/DDCAD/include/DDCAD/InputReader.h b/DDCAD/include/DDCAD/InputReader.h
index 69ebd1eefadf55bd181c0f3b6e77f6db691c3994..c68d544538a3ff293f3be7fc9f66d0a04ec2cfcb 100644
--- a/DDCAD/include/DDCAD/InputReader.h
+++ b/DDCAD/include/DDCAD/InputReader.h
@@ -16,6 +16,8 @@
 // Framework include files
 #include <DD4hep/config.h>
 
+/// ROOT include files
+#include <TGeoVolume.h>
 #include <TGeoTessellated.h>
 
 /// C/C++ include files
@@ -26,18 +28,38 @@
 /// Namespace for the AIDA detector description toolkit
 namespace dd4hep {
 
+  /// Forward declarations
+  class Detector;
+  
   /// Namespace for implementation details of the AIDA detector description toolkit
   namespace cad  {
 
+    /// Interface of the reader class to input geometry shapes from CAD files
+    /**
+     *
+     *  \author  M.Frank
+     *  \version 1.0
+     *  \ingroup DD4HEP_DDCAD
+     */
     class InputReader   {
+    public:
+      /// Reference to the detector object
+      Detector& detector;
+      
     public:
       /// Default constructor
-      InputReader();
+      InputReader(Detector& detector);
+
       /// Default destructor
       virtual ~InputReader();
+
       /// Read input file
       virtual std::vector<std::unique_ptr<TGeoTessellated> >
-      read(const std::string& source, double unit_length)  const  = 0;
+      readShapes(const std::string& source, double unit_length)  const  = 0;
+
+      /// Read input file and create a volume-set
+      virtual std::vector<std::unique_ptr<TGeoVolume> >
+      readVolumes(const std::string& source, double unit_length)  const = 0;
     };
     
   }        /* End namespace cad                      */
diff --git a/DDCAD/include/DDCAD/OutputWriter.h b/DDCAD/include/DDCAD/OutputWriter.h
new file mode 100644
index 0000000000000000000000000000000000000000..2f98ca215adc61e65273196f9c2e9576c01e4c6b
--- /dev/null
+++ b/DDCAD/include/DDCAD/OutputWriter.h
@@ -0,0 +1,69 @@
+//==========================================================================
+//  AIDA Detector description implementation 
+//--------------------------------------------------------------------------
+// Copyright (C) Organisation europeenne pour la Recherche nucleaire (CERN)
+// All rights reserved.
+//
+// For the licensing terms see $DD4hepINSTALL/LICENSE.
+// For the list of contributors see $DD4hepINSTALL/doc/CREDITS.
+//
+// Author     : M.Frank
+//
+//==========================================================================
+#ifndef DDCAD_INPUTWRITER_H
+#define DDCAD_INPUTWRITER_H
+
+// Framework include files
+#include <DD4hep/config.h>
+#include <DD4hep/Volumes.h>
+
+/// C/C++ include files
+#include <string>
+#include <vector>
+#include <memory>
+
+/// Namespace for the AIDA detector description toolkit
+namespace dd4hep {
+
+  /// Forward declarations
+  class Detector;
+  
+  /// Namespace for implementation details of the AIDA detector description toolkit
+  namespace cad  {
+
+    /// Interface of the writer class to output geometry shapes from CAD files
+    /**
+     *
+     *  \author  M.Frank
+     *  \version 1.0
+     *  \ingroup DD4HEP_DDCAD
+     */
+    class OutputWriter   {
+    public:
+      enum output_flags   {
+	EXPORT_POINT_CLOUDS = 1 << 1,
+	LAST = 0
+      };
+    public:
+      /// Reference to the detector object
+      Detector& detector;
+      /// Output configuration flags
+      unsigned long flags  { 0 };
+
+    public:
+      typedef std::vector<PlacedVolume> VolumePlacements;
+      /// Default constructor
+      OutputWriter(Detector& detector);
+      /// Default destructor
+      virtual ~OutputWriter();
+      /// Write output file
+      virtual int write(const std::string& output_file,
+			const std::string& output_type,
+			const VolumePlacements& places,
+			bool   recursive,
+			double unit_scale = 1.0)  const = 0;      
+    };
+    
+  }        /* End namespace cad                      */
+}          /* End namespace dd4hep                   */
+#endif // DDCAD_INPUTWRITER_H
diff --git a/DDCAD/src/ASSIMPReader.cpp b/DDCAD/src/ASSIMPReader.cpp
index 4b7ffd606d8b780bf27e10089f7639a9b4b2ba42..d4793bf20de8a5d8fcfbcc8b65b11c2a3a1c7ace 100644
--- a/DDCAD/src/ASSIMPReader.cpp
+++ b/DDCAD/src/ASSIMPReader.cpp
@@ -14,6 +14,7 @@
 /// Framework include files
 #include <DD4hep/Shapes.h>
 #include <DD4hep/Printout.h>
+#include <DD4hep/Detector.h>
 #include <DDCAD/ASSIMPReader.h>
 
 /// Open Asset Importer Library
@@ -22,15 +23,16 @@
 #include "assimp/scene.h"
 #include "assimp/postprocess.h"
 
-using namespace std;
 using namespace dd4hep;
 using namespace dd4hep::cad;
 
 /// Read input file
-vector<unique_ptr<TGeoTessellated> >
-ASSIMPReader::read(const string& source, double unit_length)  const  {
-  vector<unique_ptr<TGeoTessellated> > result;
-  unique_ptr<Assimp::Importer> importer = make_unique<Assimp::Importer>();
+std::vector<std::unique_ptr<TGeoTessellated> >
+ASSIMPReader::readShapes(const std::string& source, double unit_length)  const
+{
+  typedef TessellatedSolid::Vertex Vertex;
+  std::vector<std::unique_ptr<TGeoTessellated> > result;
+  std::unique_ptr<Assimp::Importer> importer = std::make_unique<Assimp::Importer>();
   int flags = aiProcess_Triangulate|aiProcess_JoinIdenticalVertices|aiProcess_CalcTangentSpace;
   auto scene = importer->ReadFile( source.c_str(), flags);
   if ( !scene )  {
@@ -46,23 +48,102 @@ ASSIMPReader::read(const string& source, double unit_length)  const  {
       for(unsigned int i=0; i < mesh->mNumFaces; i++)  {
         const aiFace&     face = mesh->mFaces[i];
         const unsigned int* idx = face.mIndices;
-        Tessellated::Vertex_t a(v[idx[0]].x*unit, v[idx[0]].y*unit, v[idx[0]].z*unit); 
-        Tessellated::Vertex_t b(v[idx[1]].x*unit, v[idx[1]].y*unit, v[idx[1]].z*unit); 
-        Tessellated::Vertex_t c(v[idx[2]].x*unit, v[idx[2]].y*unit, v[idx[2]].z*unit); 
+        Vertex a(v[idx[0]].x*unit, v[idx[0]].y*unit, v[idx[0]].z*unit); 
+        Vertex b(v[idx[1]].x*unit, v[idx[1]].y*unit, v[idx[1]].z*unit); 
+        Vertex c(v[idx[2]].x*unit, v[idx[2]].y*unit, v[idx[2]].z*unit); 
+        shape->AddFacet(a,b,c);
+      }
+      if ( shape->GetNfacets() > 2 )   {
+        result.emplace_back(std::unique_ptr<TGeoTessellated>(shape.ptr()));
+        continue;
+      }
+      delete shape.ptr();
+    }
+  }
+  printout(ALWAYS,"ASSIMPReader","+++ Read %ld meshes from %s",
+	   result.size(), source.c_str());
+  return result;
+}
+
+/// Read input file and create a volume-set
+std::vector<std::unique_ptr<TGeoVolume> >
+ASSIMPReader::readVolumes(const std::string& source, double unit_length)  const
+{
+  typedef TessellatedSolid::Vertex Vertex;
+  std::vector<std::unique_ptr<TGeoVolume> > result;
+  std::unique_ptr<Assimp::Importer> importer = std::make_unique<Assimp::Importer>();
+  int flags = aiProcess_Triangulate|aiProcess_JoinIdenticalVertices|aiProcess_CalcTangentSpace;
+  auto scene = importer->ReadFile( source.c_str(), flags);
+  char text[128];
+  
+  if ( !scene )  {
+    except("ASSIMPReader","+++ FileNotFound: %s",source.c_str());
+  }
+  double unit = unit_length;
+  for (unsigned int index = 0; index < scene->mNumMeshes; index++)   {
+    aiMesh* mesh = scene->mMeshes[index];
+    if ( mesh->mNumFaces > 0 )   {
+      auto name = mesh->mName.C_Str();
+      TessellatedSolid shape(name, mesh->mNumFaces);
+      const aiVector3D* v = mesh->mVertices;
+      for(unsigned int i=0; i < mesh->mNumFaces; i++)  {
+        const aiFace&     face = mesh->mFaces[i];
+        const unsigned int* idx = face.mIndices;
+        Vertex a(v[idx[0]].x*unit, v[idx[0]].y*unit, v[idx[0]].z*unit); 
+        Vertex b(v[idx[1]].x*unit, v[idx[1]].y*unit, v[idx[1]].z*unit); 
+        Vertex c(v[idx[2]].x*unit, v[idx[2]].y*unit, v[idx[2]].z*unit); 
         shape->AddFacet(a,b,c);
-#if 0
-        if ( scene->HasMaterials() )   {
-          const aiMaterial* mat = scene->mMaterials[mesh->mMaterialIndex];
-          printout(INFO,"ASSIMPReader","+++ Material: %p",mat);
-        }
-#endif
       }
       if ( shape->GetNfacets() > 2 )   {
-        result.emplace_back(unique_ptr<TGeoTessellated>(shape.ptr()));
+	std::string nam;
+	Material mat;
+	VisAttr  vis;
+        if ( scene->HasMaterials() )   {
+          aiMaterial* ai_mat = scene->mMaterials[mesh->mMaterialIndex];
+	  nam = ai_mat->GetName().C_Str();
+	  mat = detector.material(nam);
+        }
+	if ( !mat.isValid() )   {
+	  printout(ERROR, "ASSIMPReader",
+		   "+++ %s: No material named '%s' FOUND. Will use Air. [Missing material]",
+		   text, nam.c_str());
+ 	  mat = detector.air();
+	}
+	::snprintf(text,sizeof(text),"tessellated_%ld", result.size());
+	text[sizeof(text)-1] = 0;
+	Volume vol(text, Solid(shape.ptr()), mat);
+	if ( mesh->HasVertexColors(0) )   {
+	  const aiColor4D* col = mesh->mColors[0];
+	  if ( col )   {
+	    for( const auto& _v : detector.visAttributes() )   {
+	      float a, r, g, b, eps = 0.05;
+	      VisAttr(_v.second).argb(a, r, g, b);
+	      if( std::abs(col->a-a) < eps && std::abs(col->r-r) < eps &&
+		  std::abs(col->g-g) < eps && std::abs(col->b-b) < eps )   {
+		vis = _v.second;
+		break;
+	      }
+	    }
+	    if ( !vis.isValid() )   {
+	      ::snprintf(text,sizeof(text),"vis_tessellated_%p", (void*)vol.ptr());
+	      text[sizeof(text)-1] = 0;
+	      vis = VisAttr(text);
+	      vis.setColor(col->a,col->r,col->g,col->b);
+	      detector.add(vis);
+	    }
+	    vol.setVisAttributes(vis);
+	  }
+	}
+	printout(INFO,"ASSIMPReader",
+		 "+++ %-17s Material: %-16s  Viualization: %s",
+		 vol.name(), mat.name(), vis.isValid() ? vis.name() : "NONE");
+        result.emplace_back(std::unique_ptr<TGeoVolume>(vol.ptr()));
         continue;
       }
       delete shape.ptr();
     }
   }
+  printout(ALWAYS,"ASSIMPReader","+++ Read %ld meshes from %s",
+	   result.size(), source.c_str());
   return result;
 }
diff --git a/DDCAD/src/ASSIMPWriter.cpp b/DDCAD/src/ASSIMPWriter.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..a01f5cb755b4acf04fed367aab007e961e7004df
--- /dev/null
+++ b/DDCAD/src/ASSIMPWriter.cpp
@@ -0,0 +1,375 @@
+//==========================================================================
+//  AIDA Detector description implementation 
+//--------------------------------------------------------------------------
+// Copyright (C) Organisation europeenne pour la Recherche nucleaire (CERN)
+// All rights reserved.
+//
+// For the licensing terms see $DD4hepINSTALL/LICENSE.
+// For the list of contributors see $DD4hepINSTALL/doc/CREDITS.
+//
+// Author     : M.Frank
+//
+//==========================================================================
+
+/// Framework include files
+#include <DD4hep/Shapes.h>
+#include <DD4hep/Objects.h>
+#include <DD4hep/Printout.h>
+#include <DDCAD/ASSIMPWriter.h>
+
+/// Open Asset Importer Library
+#include "assimp/postprocess.h"
+#include "assimp/Exporter.hpp"
+#include "assimp/scene.h"
+
+#include <TBuffer3D.h>
+#include <TGeoMatrix.h>
+
+/// C/C++ include files
+#include <set>
+
+using namespace std;
+using namespace dd4hep;
+using namespace dd4hep::cad;
+
+namespace  {
+
+  void _collect(std::vector<std::pair<PlacedVolume,TGeoHMatrix*> >& cont,
+		bool recursive, const TGeoHMatrix& to_global, PlacedVolume pv)
+  {
+    Volume v = pv.volume();
+    for(Int_t i=0; i<v->GetNdaughters(); ++i)  {
+      PlacedVolume p = v->GetNode(i);
+      Solid sol = p.volume().solid();
+      // TessellatedSolid sol = p.volume().solid();
+      // if ( sol.isValid() ) cont.push_back(p);
+      unique_ptr<TGeoHMatrix> mother(new TGeoHMatrix(to_global));
+      mother->Multiply(p->GetMatrix());
+
+      if ( sol->IsA() != TGeoShapeAssembly::Class() )
+	cont.push_back(make_pair(p, mother.get()));
+      if ( recursive )
+	_collect(cont, recursive, *mother, p);	
+      if ( sol->IsA() != TGeoShapeAssembly::Class() )
+	mother.release();
+    }
+  }
+  struct vertex{ double x,y,z;
+    vertex() = default;
+    vertex(const vertex& copy) = default;
+    vertex(double vx, double vy, double vz) : x(vx), y(vy), z(vz) {}
+    vertex(const Tessellated::Vertex_t& v) : x(v.x()), y(v.y()), z(v.z()) {}
+    vertex& operator=(const vertex& v) = default;
+    vertex& operator=(const Tessellated::Vertex_t& v)
+    { x = v.x(); y = v.y(); z = v.z(); return *this;  }
+    operator Tessellated::Vertex_t () const
+    { return Tessellated::Vertex_t(x,y,z); }
+  };
+  vertex operator-(const vertex& v1, const vertex& v2)
+  {  return vertex(v1.x-v2.x, v1.y-v2.y, v1.z-v2.z);   }
+  vertex operator+(const vertex& v1, const vertex& v2)
+  {  return vertex(v1.x+v2.x, v1.y+v2.y, v1.z+v2.z);   }
+
+#if 0
+      num_facet = tes->GetNfacets();
+      int *nn = new int[num_facet];
+      bool* flipped = new bool[num_facet];
+      for( i=0; i < num_facet; ++i )
+	flipped[i] = false, nn[0] = 0;
+      for( i=0; i < num_facet; ++i )   {
+	for( size_t j= i+1; j < num_facet; ++j)   {
+	  bool isneighbour = tes->GetFacet(i).IsNeighbour(tes->GetFacet(j), flipped[j]);
+	  if ( isneighbour )  {
+	    if ( flipped[i] ) flipped[j] = !flipped[j];
+	    ++nn[i];
+	    ++nn[j];
+	    if ( nn[i] == tes->GetFacet(i).GetNvert() )
+	      break;
+	  }
+ 	}
+      }
+      for( i=0; i < num_facet; ++i )  {
+	if ( flipped[i] )  {
+	  const_cast<TGeoFacet*>(&tes->GetFacet(i))->Flip();
+	}
+      }
+      delete [] flipped;
+      delete [] nn;
+#endif
+#if 0
+   template <typename TGBinder>
+   TPlane3 compute_plane(const TGBinder &poly)   {
+      TPoint3 plast(poly[poly.Size()-1]);
+      TPoint3 pivot;
+      TVector3 edge;
+      Int_t j;
+      for (j = 0; j < poly.Size(); j++) {
+         pivot = poly[j];
+         edge =  pivot - plast;
+         if (!edge.FuzzyZero()) break;
+      }
+      for (; j < poly.Size(); j++) {
+         TVector3 v2 = poly[j] - pivot;
+         TVector3 v3 = edge.Cross(v2);
+         if (!v3.FuzzyZero())
+            return TPlane3(v3,pivot);
+      }
+
+      return TPlane3();
+   }
+
+
+	/* ------------------------------------------------------------
+	//   Convert quadri-linear facet to 2 tri-linear facets
+	//
+	//    f1 +---------------+ v2/v3: f0
+	//      /                / 
+	//     /                /
+	//    /                /
+	//    +---------------+
+	//  v0             v1 v2/v3
+	// --------------------------------------------------------- */
+	int num_points[3];
+	pol_t* pol = (pol_t*)q;
+	int s1 = pol->segs[0], s2 = pol->segs[1];
+        int ends[4] = {segs[s1]._1,segs[s1]._2,segs[s2]._1,segs[s2]._2};
+
+	q += (2+pol->n);
+	if (ends[0] == ends[2]) {
+	  numPnts[0] = ends[1];
+	  numPnts[1] = ends[0];
+	  numPnts[2] = ends[3];
+	}
+	else if (ends[0] == ends[3]) {
+	  numPnts[0] = ends[1];
+	  numPnts[1] = ends[0];
+	  numPnts[2] = ends[2];
+	}
+	else if (ends[1] == ends[2]) {
+	  numPnts[0] = ends[0];
+	  numPnts[1] = ends[1];
+	  numPnts[2] = ends[3];
+	}
+	else {
+	  numPnts[0] = ends[0];
+	  numPnts[1] = ends[1];
+	  numPnts[2] = ends[2];
+	}
+	Int_t lastAdded = numPnts[2];
+	for( int j=pol->n; j != 2; --j )   {
+	  ends[0] = segs[pol->segs[j]]._1;
+	  ends[1] = segs[pol->segs[j]]._2;
+	  if (ends[0] == lastAdded) {
+	    lastAdded = ends[1];
+	  }
+	  else  {
+	    lastAdded = ends[0];
+	  }
+	}
+
+  
+#endif
+}
+
+/// Write output file
+int ASSIMPWriter::write(const std::string& file_name,
+			const std::string& file_type,
+			const VolumePlacements& places,
+			bool   recursive,
+			double unit_scale)  const
+{
+  std::vector<std::pair<PlacedVolume,TGeoHMatrix*> > placements;
+  vector<Material>        materials;
+  TGeoHMatrix             toGlobal;
+    
+  for( auto pv : places )
+    _collect(placements, recursive, toGlobal, pv);
+
+  size_t num_mesh = placements.size();
+
+  aiScene scene;
+  scene.mNumMaterials = 0;
+  scene.mNumMeshes    = 0;
+  scene.mMeshes       = new aiMesh* [num_mesh];
+  scene.mMaterials    = new aiMaterial* [num_mesh];
+
+  aiNode *root        = new aiNode();
+  scene.mRootNode     = root;
+  root->mName.Set("<STL>");
+  root->mNumMeshes    = 0;
+  root->mNumChildren  = 0;
+  root->mChildren     = new aiNode* [num_mesh];
+  root->mMeshes       = 0;//new unsigned int[root->mNumMeshes];
+
+  for( size_t imesh=0; imesh < num_mesh; ++imesh )   {
+    unique_ptr<TGeoHMatrix> trafo(placements[imesh].second);
+    PlacedVolume     pv  = placements[imesh].first;
+    Volume           v   = pv.volume();
+    Material         m   = v.material();
+    TessellatedSolid tes = v.solid();
+    aiString         node_name(v.name());
+
+    //
+    unique_ptr<TGeoTessellated> buf;
+    if ( !tes.isValid() )   {
+      typedef vertex vtx_t;
+      unique_ptr<TBuffer3D> buf3D(v.solid()->MakeBuffer3D());
+      struct pol_t { int c, n; int segs[1]; } *pol;
+      struct seg_t { int c, _1, _2;         };
+      const  seg_t* segs = (seg_t*)buf3D->fSegs;
+      const  vtx_t* vtcs = (vtx_t*)buf3D->fPnts;
+      size_t i, num_facet = 0;
+      const  Int_t* q;
+
+      for( i=0, q=buf3D->fPols; i<buf3D->NbPols(); ++i, q += (2+pol->n))  {
+	pol = (pol_t*)q;
+	for( int j=0; j < pol->n-1; ++j ) num_facet += 2;
+      }
+      
+      buf = make_unique<TGeoTessellated>(v.name(), num_facet);
+      tes = buf.get();
+      q = buf3D->fPols;
+      for( i=0, q=buf3D->fPols; i<buf3D->NbPols(); ++i)  {
+	pol_t* pol = (pol_t*)q;
+	q += (2+pol->n);
+	for( int j=0; j < pol->n; j += 2 )   {
+	  /* ------------------------------------------------------------
+	  //   Convert quadri-linear facet to 2 tri-linear facets
+	  //
+	  //    f1 +---------------+ v2/v3: f0
+	  //      /                / 
+	  //     /                /
+	  //    /                /
+	  //    +---------------+
+	  //  v0             v1 v2/v3
+	  // --------------------------------------------------------- */
+	  const int    s1  = pol->segs[j], s2 = pol->segs[(j+1)%pol->n];
+	  const int    s[] = { segs[s1]._1, segs[s1]._2, segs[s2]._1, segs[s2]._2 };
+	  const vtx_t& v0  = vtcs[s[0]], &v1=vtcs[s[1]], &v2=vtcs[s[2]], &v3=vtcs[s[3]];
+
+          if ( s[0] == s[2] )   {       // Points are ( s[1], s[0], s[3] )
+	    tes->AddFacet(v1, v0, v3);
+          }
+          else if ( s[0] == s[3] )   {  // Points are ( s[1], s[0], s[2] )
+	    tes->AddFacet(v1, v0, v2);
+	  }
+          else if ( s[1] == s[2] )   {  // Points are ( s[0], s[1], s[3] )
+	    tes->AddFacet(v0, v1, v3);
+	  }
+          else   {                      // Points are ( s[0], s[1], s[2] )
+	    tes->AddFacet(v0, v1, v2);
+	  }
+	}
+      }
+    }
+    if ( tes->GetNfacets() == 0 )   {
+      continue;
+    }
+    
+    size_t num_vert = 0;
+    for( long j=0, n=tes->GetNfacets(); j < n; ++j )
+      num_vert += tes->GetFacet(j).GetNvert();
+
+    size_t index = std::numeric_limits<size_t>::max();
+    for( size_t j=0; j<materials.size(); ++j )  {
+      if( materials[j] == m )   {
+	index = j;
+	break;
+      }
+    }
+    if ( index > materials.size() )   {
+      aiString name(m.name());
+      auto* ai_mat = new aiMaterial();
+      index = materials.size();
+      materials.push_back(m);
+      ai_mat->AddProperty(&name, AI_MATKEY_NAME);
+      scene.mMaterials[scene.mNumMaterials] = ai_mat;
+      ++scene.mNumMaterials;
+    }
+    aiMesh* mesh = new aiMesh;
+    mesh->mName = node_name;
+    mesh->mMaterialIndex = index;
+    if ( v.visAttributes().isValid() )   {
+      float r = 0e0, g = 0e0, b = 0e0, a = 0e0;
+      v.visAttributes().argb(a, r, g, b);
+      mesh->mColors[0] = new aiColor4D(r, g, b, a);
+    }
+    mesh->mFaces       = new aiFace[tes->GetNfacets()];
+    mesh->mVertices    = new aiVector3D[num_vert];
+    mesh->mNormals     = new aiVector3D[num_vert];
+    mesh->mTangents    = nullptr;
+    mesh->mBitangents  = nullptr;
+    mesh->mNumFaces    = 0;
+    mesh->mNumVertices = 0;
+
+    for( long j=0, n=tes->GetNfacets(); j < n; ++j )   {
+      aiFace& face = mesh->mFaces[j];
+      face.mNumIndices = 0;
+      face.mIndices = nullptr;
+    }
+    vertex vtx, tmp, norm;
+    for( long j=0, nvx=0, n=tes->GetNfacets(); j < n; ++j )  {
+      bool degenerated  = false;
+      const auto& facet = tes->GetFacet(j);
+      tmp = facet.ComputeNormal(degenerated);
+      if ( !degenerated && facet.GetNvert() > 0 )   {
+	aiFace& face  = mesh->mFaces[mesh->mNumFaces];
+	double  u     = unit_scale;
+
+	face.mIndices = new unsigned int[facet.GetNvert()];
+	trafo->LocalToMaster(&tmp.x, &norm.x);
+	face.mNumIndices = 0;
+	for( long k=0; k < facet.GetNvert(); ++k )  {
+	  tmp = facet.GetVertex(k);
+	  trafo->LocalToMaster(&tmp.x, &vtx.x);
+	  face.mIndices[face.mNumIndices] = nvx;
+	  mesh->mNormals[nvx]  = aiVector3D(norm.x, norm.y, norm.z);
+	  mesh->mVertices[nvx] = aiVector3D(vtx.x*u,vtx.y*u,vtx.z*u);
+	  ++mesh->mNumVertices;
+	  ++face.mNumIndices;
+	  ++nvx;
+	}
+	++mesh->mNumFaces;
+      }
+    }
+    if ( imesh == 122585 )
+      break;
+    else if ( imesh == 122586 )
+      mesh->mNumFaces = 0;
+    else if ( imesh == 122587 )
+      mesh->mNumFaces = 0;
+
+    /// Check if we have here a valid mesh
+    if ( 0 == mesh->mNumFaces || 0 == mesh->mNumVertices )    {
+      delete [] mesh->mVertices;
+      mesh->mNumVertices = 0;
+      delete [] mesh->mNormals;
+      delete [] mesh->mFaces;
+      mesh->mNumFaces = 0;
+      continue;
+    }
+    
+    scene.mMeshes[scene.mNumMeshes] = mesh;
+
+    aiNode *node      = new aiNode;
+    node->mMeshes     = new unsigned int[node->mNumMeshes=1];
+    node->mMeshes[0]  = scene.mNumMeshes;
+    node->mParent     = root;
+    node->mName.Set("<STL>");
+
+    root->mChildren[root->mNumChildren] = node;
+    ++root->mNumChildren;
+    ++scene.mNumMeshes;
+  }
+  printout(ALWAYS,"ASSIMPWriter","+++ Analysed %ld of %ld meshes.",
+	   scene.mNumMeshes, placements.size());
+  if ( scene.mNumMeshes > 0 )   {
+    Assimp::Exporter exporter;
+    Assimp::ExportProperties *props = new Assimp::ExportProperties;
+    props->SetPropertyBool(AI_CONFIG_EXPORT_POINT_CLOUDS,
+			   flags&EXPORT_POINT_CLOUDS ? true : false);
+    exporter.Export(&scene, file_type.c_str(), file_name.c_str(), 0, props);
+    return 1;
+  }
+  return 0;
+}
diff --git a/DDCAD/src/InputReader.cpp b/DDCAD/src/InputReader.cpp
index d581ac31afef637c527843de420bed8370d43a24..2bf36f2821c6637a55ce931f6ed9c0087b6660fe 100644
--- a/DDCAD/src/InputReader.cpp
+++ b/DDCAD/src/InputReader.cpp
@@ -18,7 +18,8 @@ using namespace dd4hep;
 using namespace dd4hep::cad;
 
 /// Default constructor
-InputReader::InputReader()
+InputReader::InputReader(Detector& det)
+  : detector(det)
 {
 }
 
diff --git a/DDCAD/src/OutputWriter.cpp b/DDCAD/src/OutputWriter.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..4104d022af7ab6c1163dac9ce78d157282341c85
--- /dev/null
+++ b/DDCAD/src/OutputWriter.cpp
@@ -0,0 +1,29 @@
+//==========================================================================
+//  AIDA Detector description implementation 
+//--------------------------------------------------------------------------
+// Copyright (C) Organisation europeenne pour la Recherche nucleaire (CERN)
+// All rights reserved.
+//
+// For the licensing terms see $DD4hepINSTALL/LICENSE.
+// For the list of contributors see $DD4hepINSTALL/doc/CREDITS.
+//
+// Author     : M.Frank
+//
+//==========================================================================
+
+/// Framework include files
+#include "DDCAD/OutputWriter.h"
+
+using namespace dd4hep;
+using namespace dd4hep::cad;
+
+/// Default constructor
+OutputWriter::OutputWriter(Detector& det)
+  : detector(det)
+{
+}
+
+/// Default destructor
+OutputWriter::~OutputWriter()
+{
+}
diff --git a/DDCAD/src/plugins/CADPlugins.cpp b/DDCAD/src/plugins/CADPlugins.cpp
index 1c7dc8aec4d7c7964bfd1f7d2e08cdb2a1847c51..cbbb1a462e1a8691a499d775509e682c11f5eabc 100644
--- a/DDCAD/src/plugins/CADPlugins.cpp
+++ b/DDCAD/src/plugins/CADPlugins.cpp
@@ -13,9 +13,11 @@
 
 /// Framework include files
 #include <DD4hep/DetFactoryHelper.h>
+#include <DD4hep/DetectorTools.h>
 #include <DD4hep/Printout.h>
 #include <XML/Utilities.h>
 #include <DDCAD/ASSIMPReader.h>
+#include <DDCAD/ASSIMPWriter.h>
 
 // C/C++ include files
 
@@ -23,11 +25,48 @@ using namespace std;
 using namespace dd4hep;
 using namespace dd4hep::detail;
 
-static Handle<TObject> create_CAD_Shape(Detector&, xml_h e)   {
+static void* read_CAD_Volume(Detector& dsc, int argc, char** argv)   {
+  string fname;
+  double scale = 1.0;
+  bool   help  = false;
+  for(int i = 0; i < argc && argv[i]; ++i)  {
+    if (      0 == ::strncmp( "-input",argv[i],4) )  fname = argv[++i];
+    else if ( 0 == ::strncmp("--input",argv[i],5) )  fname = argv[++i];
+    else if ( 0 == ::strncmp( "-scale",argv[i],4) )  scale = ::atof(argv[++i]);
+    else if ( 0 == ::strncmp("--scale",argv[i],5) )  scale = ::atof(argv[++i]);
+    else if ( 0 == ::strncmp( "-help",argv[i],2) )   help  = true;
+    else if ( 0 == ::strncmp("--help",argv[i],3) )   help  = true;
+  }
+
+  if ( fname.empty() || help )    {
+    cout <<
+      "Usage: -plugin DD4hep_CAD_export -arg [-arg]                           \n\n"
+      "     -output   <string> Output file name.                                \n"
+      "     -type     <string> Output file type.                                \n"
+      "     -recursive         Export volume/detector element and all daughters.\n"
+      "     -volume   <string> Path to the volume to be exported.               \n"
+      "     -detector <string> Path to the detector element to be exported.     \n"
+      "     -help              Print this help output.                          \n"
+      "     -scale    <number> Unit scale before writing output data.           \n"
+      "     Arguments given: " << arguments(argc,argv) << endl << flush;
+    ::exit(EINVAL);
+  }
+
+  auto volumes = cad::ASSIMPReader(dsc).readVolumes(fname, scale);
+  if ( volumes.empty() )   {
+    except("CAD_Volume","+++ CAD file: %s does not contain any "
+           "understandable tessellated volumes.", fname.c_str());
+  }
+  auto* result = new std::vector<std::unique_ptr<TGeoVolume> >(move(volumes));
+  return result;
+}
+DECLARE_DD4HEP_CONSTRUCTOR(DD4hep_read_CAD_volumes,read_CAD_Volume)
+
+static Handle<TObject> create_CAD_Shape(Detector& dsc, xml_h e)   {
   xml_elt_t elt(e);
   string fname = elt.attr<string>(_U(ref));
   double unit  = elt.hasAttr(_U(unit)) ? elt.attr<double>(_U(unit)) : dd4hep::cm;
-  auto shapes = cad::ASSIMPReader().read(fname, unit);
+  auto shapes = cad::ASSIMPReader(dsc).readShapes(fname, unit);
   if ( shapes.empty() )   {
     except("CAD_Shape","+++ CAD file: %s does not contain any "
            "understandable tessellated shapes.", fname.c_str());
@@ -56,29 +95,23 @@ static Handle<TObject> create_CAD_Shape(Detector&, xml_h e)   {
 }
 DECLARE_XML_SHAPE(CAD_Shape__shape_constructor,create_CAD_Shape)
 
-
-static Handle<TObject> create_CAD_MultiShape_Assembly(Detector&, xml_h e)   {
+static Handle<TObject> create_CAD_Assembly(Detector& dsc, xml_h e)   {
   xml_elt_t elt(e);
   string fname = elt.attr<string>(_U(ref));
   double unit  = elt.hasAttr(_U(unit)) ? elt.attr<double>(_U(unit)) : dd4hep::cm;
-  auto shapes = cad::ASSIMPReader().read(fname, unit);
-  if ( shapes.empty() )   {
+  auto volumes = cad::ASSIMPReader(dsc).readVolumes(fname, unit);
+  if ( volumes.empty() )   {
     except("CAD_Shape","+++ CAD file: %s does not contain any "
-           "understandable tessellated shapes.", fname.c_str());
+           "understandable tessellated volumes.", fname.c_str());
   }
   Assembly assembly("assembly");
-  for(size_t i=0; i < shapes.size(); ++i)   {
-    Solid solid = shapes[i].release();
-    if ( solid.isValid() )   {
-      Volume vol(_toString(int(i),"vol_%d"), solid, Detector::getInstance().material("Air"));
-      assembly.placeVolume(vol);
-    }
-  }
+  for(size_t i=0; i < volumes.size(); ++i)
+    assembly.placeVolume(volumes[i].release());
+
   if ( elt.hasAttr(_U(name)) ) assembly->SetName(elt.attr<string>(_U(name)).c_str());
   return assembly;
 }
-DECLARE_XML_VOLUME(CAD_Assembly__volume_constructor,create_CAD_MultiShape_Assembly)
-
+DECLARE_XML_VOLUME(CAD_Assembly__volume_constructor,create_CAD_Assembly)
 
 /// CAD volume importer plugin
 /**
@@ -126,10 +159,10 @@ static Handle<TObject> create_CAD_Volume(Detector& dsc, xml_h e)   {
   xml_elt_t elt(e);
   string fname = elt.attr<string>(_U(ref));
   double unit  = elt.attr<double>(_U(unit));
-  auto shapes = cad::ASSIMPReader().read(fname, unit);
-  if ( shapes.empty() )   {
+  auto volumes = cad::ASSIMPReader(dsc).readVolumes(fname, unit);
+  if ( volumes.empty() )   {
     except("CAD_Volume","+++ CAD file: %s does not contain any "
-           "understandable tessellated shapes.", fname.c_str());
+           "understandable tessellated volumes.", fname.c_str());
   }
   Volume envelope;
   if ( elt.hasChild(_U(envelope)) )   {
@@ -165,26 +198,28 @@ static Handle<TObject> create_CAD_Volume(Detector& dsc, xml_h e)   {
   else if ( elt.hasAttr(_U(material)) ) default_material = dsc.material(elt.attr<string>(_U(material)));
 
   if ( elt.hasChild(_U(volume)) )   {
-    map<int, xml_h> shape_map;
+    map<int, xml_h> volume_map;
     for (xml_coll_t c(elt,_U(volume)); c; ++c )
-      shape_map.emplace(xml_dim_t(c).id(),c);
-
-    for (size_t i=0; i < shapes.size(); ++i)   {
-      Solid       sol = shapes[i].release();
-      Material    mat = default_material;
-      auto is = shape_map.find(i);
-      if ( is == shape_map.end() )   {
-        Volume vol(_toString(int(i),"vol_%d"), sol, mat);
+      volume_map.emplace(xml_dim_t(c).id(),c);
+
+    for (size_t i=0; i < volumes.size(); ++i)   {
+      Volume   vol = volumes[i].release();
+      Material mat = default_material;
+      auto is = volume_map.find(i);
+      if ( is == volume_map.end() )   {
         envelope.placeVolume(vol);
       }
       else   {
         xml_dim_t x_vol = (*is).second;
         xml_dim_t x_pos = x_vol.child(_U(position),false);
         xml_dim_t x_rot = x_vol.child(_U(rotation),false);
-        string     vnam = x_vol.hasAttr(_U(name)) ? x_vol.attr<string>(_U(name)) : _toString(int(i),"vol_%d");
 
         if ( x_vol.hasAttr(_U(material)) )  {
-          mat = dsc.material(x_vol.attr<string>(_U(material)));
+	  string mat_name = x_vol.attr<string>(_U(material));
+          mat = dsc.material(mat_name);
+	  if ( !mat.isValid() )
+	    except("CAD_MultiVolume","+++ Failed to access material "+mat_name);
+	  vol.setMaterial(mat);
         }
         Position    pos;
         RotationZYX rot;
@@ -197,7 +232,6 @@ static Handle<TObject> create_CAD_Volume(Detector& dsc, xml_h e)   {
         else if ( x_rot )
           rot = RotationZYX(x_rot.z(0), x_rot.y(0), x_rot.x(0));
       
-        Volume vol(vnam, sol, mat);
         PlacedVolume pv = envelope.placeVolume(vol,env_trafo*Transform3D(rot, pos));
         vol.setAttributes(dsc, x_vol.regionStr(), x_vol.limitsStr(), x_vol.visStr());
         for (xml_coll_t cc(x_vol,_U(physvolid)); cc; ++cc )   {
@@ -208,10 +242,11 @@ static Handle<TObject> create_CAD_Volume(Detector& dsc, xml_h e)   {
     }
   }
   else   {
-    for(size_t i=0; i < shapes.size(); ++i)   {
-      Solid solid = shapes[i].release();
-      if ( solid.isValid() )   {
-        Volume vol(_toString(int(i),"vol_%d"), solid, default_material);
+    for(size_t i=0; i < volumes.size(); ++i)   {
+      Volume vol = volumes[i].release();
+      if ( vol.isValid() )   {
+	if ( (vol.material() == dsc.air()) && default_material.isValid() )
+	  vol.setMaterial(default_material);
         envelope.placeVolume(vol);
       }
     }
@@ -220,3 +255,77 @@ static Handle<TObject> create_CAD_Volume(Detector& dsc, xml_h e)   {
   return envelope;
 }
 DECLARE_XML_VOLUME(CAD_MultiVolume__volume_constructor,create_CAD_Volume)
+
+/// CAD volume importer plugin
+/**
+ *
+ */
+static long CAD_export(Detector& description, int argc, char** argv)   {
+  bool recursive = false, help = false;
+  string volume, detector, fname, ftype;
+  double scale = 1.0;
+  
+  for(int i = 0; i < argc && argv[i]; ++i)  {
+    if (      0 == ::strncmp( "-output",argv[i],4) )    fname     = argv[++i];
+    else if ( 0 == ::strncmp("--output",argv[i],5) )    fname     = argv[++i];
+    else if ( 0 == ::strncmp( "-type",argv[i],4) )      ftype     = argv[++i];
+    else if ( 0 == ::strncmp("--type",argv[i],5) )      ftype     = argv[++i];
+    else if ( 0 == ::strncmp( "-detector",argv[i],4) )  detector  = argv[++i];
+    else if ( 0 == ::strncmp("--detector",argv[i],5) )  detector  = argv[++i];
+    else if ( 0 == ::strncmp( "-volume",argv[i],4) )    volume    = argv[++i];
+    else if ( 0 == ::strncmp("--volume",argv[i],5) )    volume    = argv[++i];
+    else if ( 0 == ::strncmp( "-recursive",argv[i],4) ) recursive = true;
+    else if ( 0 == ::strncmp("--recursive",argv[i],5) ) recursive = true;
+    else if ( 0 == ::strncmp( "-scale",argv[i],4) )     scale     = ::atof(argv[++i]);
+    else if ( 0 == ::strncmp("--scale",argv[i],5) )     scale     = ::atof(argv[++i]);
+    else if ( 0 == ::strncmp( "-help",argv[i],2) )      help      = true;
+    else if ( 0 == ::strncmp("--help",argv[i],3) )      help      = true;
+  }
+
+  if ( fname.empty() || ftype.empty() ) help = true;
+  if ( volume.empty() && detector.empty() ) help = true;
+  if ( help )   {
+    cout <<
+      "Usage: -plugin DD4hep_CAD_export -arg [-arg]                           \n\n"
+      "     -output   <string> Output file name.                                \n"
+      "     -type     <string> Output file type.                                \n"
+      "     -recursive         Export volume/detector element and all daughters.\n"
+      "     -volume   <string> Path to the volume to be exported.               \n"
+      "     -detector <string> Path to the detector element to be exported.     \n"
+      "     -help              Print this help output.                          \n"
+      "     -scale    <number> Unit scale before writing output data.           \n"
+      "     Arguments given: " << arguments(argc,argv) << endl << flush;
+    ::exit(EINVAL);
+  }
+
+  PlacedVolume pv;
+  if ( !detector.empty() )   {
+    DetElement elt;
+    if ( detector == "/world" )
+      elt = description.world();
+    else
+      elt = detail::tools::findElement(description,detector);
+    if ( !elt.isValid() )  {
+      except("DD4hep_CAD_export","+++ Invalid DetElement path: %s",detector.c_str());
+    }
+    if ( !elt.placement().isValid() )   {
+      except("DD4hep_CAD_export","+++ Invalid DetElement placement: %s",detector.c_str());
+    }
+    pv = elt.placement();
+  }
+  else if ( !volume.empty() )   {
+    pv = detail::tools::findNode(description.world().placement(), volume);
+    if ( !pv.isValid() )   {
+      except("DD4hep_CAD_export","+++ Invalid placement path: %s",volume.c_str());
+    }
+  }
+  cad::ASSIMPWriter wr(description);
+  std::vector<PlacedVolume> places {pv};
+  auto num_mesh = wr.write(fname, ftype, places, recursive, scale);
+  if ( num_mesh < 0 )   {
+    printout(ERROR, "DD4hep_CAD_export","+++ Failed to export shapes to CAD file: %s [%s]",
+	     fname.c_str(), ftype.c_str());
+  }
+  return 1;
+}
+DECLARE_APPLY(DD4hep_CAD_export,CAD_export)
diff --git a/DDCore/include/DD4hep/Shapes.h b/DDCore/include/DD4hep/Shapes.h
index ae9102ee9f3bb03cd1c2f12d39f48c2151874ac4..952ea6b1458a4b44143eb17b4cd5cfe2da3496f2 100644
--- a/DDCore/include/DD4hep/Shapes.h
+++ b/DDCore/include/DD4hep/Shapes.h
@@ -1776,8 +1776,10 @@ namespace dd4hep {
     void make(const std::string& nam, const std::vector<Object::Vertex_t>& vertices);
 
   public:
-    typedef Object::Vertex_t Vertex_t;
-    
+    typedef Object::Vertex_t  Vertex;
+    typedef TGeoFacet         Facet;
+
+  public:
     /// Default constructor
     TessellatedSolid() = default;
     /// Move Constructor
@@ -1794,7 +1796,7 @@ namespace dd4hep {
     { this->make("", num_facets);    }
 
     /// Constructor to create a new identified object with attribute initialization
-    TessellatedSolid(const std::vector<Vertex_t>& vertices)
+    TessellatedSolid(const std::vector<Vertex>& vertices)
     { this->make("", vertices);   }
 
     /// Constructor to create a new anonymous object with attribute initialization
@@ -1802,7 +1804,7 @@ namespace dd4hep {
     { 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)
+    TessellatedSolid(const std::string& nam, const std::vector<Vertex>& vertices)
     { this->make(nam, vertices);   }
 
     /// Move Assignment operator
@@ -1810,13 +1812,22 @@ namespace dd4hep {
     /// 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;
+    bool addFacet(const Vertex& pt0, const Vertex& pt1, const Vertex& 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;
+    bool addFacet(const Vertex& pt0, const Vertex& pt1, const Vertex& pt2, const Vertex& 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;
+
+    /// Access the number of facets in the shape
+    int num_facet()   const;
+    /// Access a facet from the built shape
+    const Facet& facet(int index)    const;
+    /// Access the number of vertices in the shape
+    int num_vertex()   const;
+    /// Access a single vertex from the shape
+    const Vertex& vertex(int index)    const;
   };
 #endif
   
diff --git a/DDCore/src/ShapeUtilities.cpp b/DDCore/src/ShapeUtilities.cpp
index f455af8bec3b5bba6230190510807aed61a33d0a..9050c489f4f5b8655949e87451379f25c145662d 100644
--- a/DDCore/src/ShapeUtilities.cpp
+++ b/DDCore/src/ShapeUtilities.cpp
@@ -752,7 +752,7 @@ namespace dd4hep {
   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;
+    std::vector<TessellatedSolid::Vertex> 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)   {
diff --git a/DDCore/src/Shapes.cpp b/DDCore/src/Shapes.cpp
index 812ced7be7214410cd11ea04268147feb6fe0be6..9786e02e0589084099a1cce37b83797167fb0ec2 100644
--- a/DDCore/src/Shapes.cpp
+++ b/DDCore/src/Shapes.cpp
@@ -794,17 +794,17 @@ void TessellatedSolid::make(const std::string& nam, int num_facets)   {
 }
 
 /// Internal helper method to support object construction
-void TessellatedSolid::make(const std::string& nam, const std::vector<Object::Vertex_t>& vertices)   {
+void TessellatedSolid::make(const std::string& nam, const std::vector<Vertex>& 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 {
+bool TessellatedSolid::addFacet(const Vertex& pt0, const Vertex& pt1, const Vertex& 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 {
+bool TessellatedSolid::addFacet(const Vertex& pt0, const Vertex& pt1, const Vertex& pt2, const Vertex& pt3)  const {
   return access()->AddFacet(pt0, pt1, pt2, pt3);
 }
 
@@ -817,6 +817,26 @@ bool TessellatedSolid::addFacet(const int pt0, const int pt1, const int pt2)  co
 bool TessellatedSolid::addFacet(const int pt0, const int pt1, const int pt2, const int pt3)  const   {
   return access()->AddFacet(pt0, pt1, pt2, pt3);
 }
+
+/// Access the number of facets in the shape
+int TessellatedSolid::num_facet()   const   {
+  return access()->GetNvertices();
+}
+
+/// Access a facet from the built shape
+const TessellatedSolid::Facet& TessellatedSolid::facet(int index)    const   {
+  return ptr()->GetFacet(index);
+}
+
+/// Access the number of vertices in the shape
+int TessellatedSolid::num_vertex()   const   {
+  return access()->GetNvertices();
+}
+
+/// Access a single vertex from the shape
+const TessellatedSolid::Vertex& TessellatedSolid::vertex(int index)    const    {
+  return ptr()->GetVertex(index);
+}
 #endif
 
 /// Access right solid of the boolean
diff --git a/DDCore/src/plugins/ShapePlugins.cpp b/DDCore/src/plugins/ShapePlugins.cpp
index d456c166360094bd490db9c8a26ce798b1bc3a83..e2444890a1da76341b1da8ff108f2f63ff930a4a 100644
--- a/DDCore/src/plugins/ShapePlugins.cpp
+++ b/DDCore/src/plugins/ShapePlugins.cpp
@@ -394,7 +394,7 @@ 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;
+  std::vector<TessellatedSolid::Vertex> 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());
diff --git a/DDCore/src/plugins/StandardPlugins.cpp b/DDCore/src/plugins/StandardPlugins.cpp
index 4eb52cb0fa729a97756e6bd523b94cb9acdc3d09..34211d8bf7a5b4dc023397c3a275ef24a89a7a8e 100644
--- a/DDCore/src/plugins/StandardPlugins.cpp
+++ b/DDCore/src/plugins/StandardPlugins.cpp
@@ -1437,20 +1437,20 @@ template <int flag> long dump_detelement_tree(Detector& description, int argc, c
     else   {
       cout << "  "
            << (flag==0 ? "DD4hep_DetectorDump" : "DD4hep_DetectorVolumeDump") << " -arg [-arg]     \n"
-        "    --sensitive            Process only sensitive volumes.                                \n"
+        "   --sensitive             Process only sensitive volumes.                                \n"
         "    -sensitive             dto.                                                           \n"
-        "    --no-sensitive         Invert sensitive only flag.                                    \n"
+        "   --no-sensitive          Invert sensitive only flag.                                    \n"
         "    -no-sensitive          dto.                                                           \n"
-        "    --shapes               Print shape information.                                       \n"
+        "   --shapes                Print shape information.                                       \n"
         "    -shapes                dto.                                                           \n"
-        "    --positions            Print position information.                                    \n"
+        "   --positions             Print position information.                                    \n"
         "    -positions             dto.                                                           \n"
-        "    --materials            Print material information.                                    \n"
+        "   --materials             Print material information.                                    \n"
         "    -materials             dto.                                                           \n"
-        "    --detector   <path>    Process elements only if <path> is part of the DetElement path.\n"
+        "   --detector   <path>     Process elements only if <path> is part of the DetElement path.\n"
         "    -detector    <path>    dto.                                                           \n"
         "    -level       <number>  Maximal depth to be explored by the scan                       \n"
-        "    --level       <number> dto.                                                           \n"
+        "   --level       <number>  dto.                                                           \n"
         "\tArguments given: " << arguments(argc,argv) << endl << flush;        
       ::exit(EINVAL);
     }
diff --git a/DDG4/include/DDG4/Geant4PhysicsList.h b/DDG4/include/DDG4/Geant4PhysicsList.h
index d15c19fb654f9a508ba0315eca6d5628c7ef29aa..8fe5f2ef014776abc99e07de4bcd55ed81fafb51 100644
--- a/DDG4/include/DDG4/Geant4PhysicsList.h
+++ b/DDG4/include/DDG4/Geant4PhysicsList.h
@@ -65,6 +65,11 @@ namespace dd4hep {
       typedef std::map<std::string, ParticleProcesses> PhysicsProcesses;
 
       /// Structure describing a G4 particle constructor
+      /**
+       *  \author  M.Frank
+       *  \version 1.0
+       *  \ingroup DD4HEP_SIMULATION
+       */
       class ParticleConstructor : public std::string {
       public:
         /// Default constructor
@@ -141,6 +146,9 @@ namespace dd4hep {
       /// Access discrete processes for one particle type (CONST)
       const ParticleProcesses& discreteProcesses(const std::string& part_name) const;
 
+      /// Access physics constructor by name
+      PhysicsConstructor physics(const std::string& name)  const;
+      
       /// Access all physics particles
       ParticleConstructors& particles() {
         return m_particles;
diff --git a/DDG4/plugins/Geant4SDActions.cpp b/DDG4/plugins/Geant4SDActions.cpp
index a51a99b4c5224ece19c7961ef6a2fe8e81593015..f624521f6800d505fdca3b2db657e3323ffa5c37 100644
--- a/DDG4/plugins/Geant4SDActions.cpp
+++ b/DDG4/plugins/Geant4SDActions.cpp
@@ -47,12 +47,16 @@ namespace dd4hep {
     }
 
     /// Method for generating hit(s) using the information of G4Step object.
-    template <> bool Geant4SensitiveAction<Geant4VoidSensitive>::process(G4Step* /*step*/,G4TouchableHistory* /*hist*/ ) {
+    template <> bool
+    Geant4SensitiveAction<Geant4VoidSensitive>::process(G4Step*             /* step */,
+							G4TouchableHistory* /* hist */) {
       return true;
     }
     
     /// Method for generating hit(s) using the information of G4Step object.
-    template <> bool Geant4SensitiveAction<Geant4VoidSensitive>::processGFlash(G4GFlashSpot* /*spot*/,G4TouchableHistory* /*hist*/ ) {
+    template <> bool
+    Geant4SensitiveAction<Geant4VoidSensitive>::processGFlash(G4GFlashSpot*       /* spot */,
+							      G4TouchableHistory* /* hist */) {
       return true;
     }
     typedef Geant4SensitiveAction<Geant4VoidSensitive> Geant4VoidSensitiveAction;
@@ -75,7 +79,8 @@ namespace dd4hep {
     }
 
     /// Method for generating hit(s) using the information of G4Step object.
-    template <> bool Geant4SensitiveAction<Geant4Tracker>::process(G4Step* step,G4TouchableHistory* /*hist*/ ) {
+    template <> bool
+    Geant4SensitiveAction<Geant4Tracker>::process(G4Step* step,G4TouchableHistory* /* hist */) {
       typedef Geant4Tracker::Hit Hit;
       Geant4StepHandler h(step);
       Position prePos    = h.prePos();
@@ -111,8 +116,9 @@ namespace dd4hep {
     }
     
     /// Method for generating hit(s) using the information of G4Step object.
-    template <> bool Geant4SensitiveAction<Geant4Tracker>::processGFlash(G4GFlashSpot* spot,
-									 G4TouchableHistory* /*hist*/ )
+    template <> bool
+    Geant4SensitiveAction<Geant4Tracker>::processGFlash(G4GFlashSpot*          spot,
+							G4TouchableHistory* /* hist */)
     {
       typedef Geant4Tracker::Hit Hit;
       Geant4GFlashSpotHandler h(spot);
@@ -155,7 +161,8 @@ namespace dd4hep {
     }
 
     /// Method for generating hit(s) using the information of G4Step object.
-    template <> bool Geant4SensitiveAction<Geant4Calorimeter>::process(G4Step* step,G4TouchableHistory*) {
+    template <> bool
+    Geant4SensitiveAction<Geant4Calorimeter>::process(G4Step* step,G4TouchableHistory*) {
       typedef Geant4Calorimeter::Hit Hit;
       Geant4StepHandler    h(step);
       HitContribution      contrib = Hit::extractContribution(step);
diff --git a/DDG4/src/Geant4PhysicsList.cpp b/DDG4/src/Geant4PhysicsList.cpp
index e87478af1b8dae818aa1fd34ea2e439ba2ac0ae4..f63f863b25a22687f2772e375108d4719b848054 100644
--- a/DDG4/src/Geant4PhysicsList.cpp
+++ b/DDG4/src/Geant4PhysicsList.cpp
@@ -199,6 +199,19 @@ const Geant4PhysicsList::ParticleProcesses& Geant4PhysicsList::discreteProcesses
   throw runtime_error("Failed to access the physics process"); // never called anyway
 }
 
+/// Access physics constructor by name (CONST)
+Geant4PhysicsList::PhysicsConstructor Geant4PhysicsList::physics(const std::string& nam)  const    {
+  for ( const auto& ctor : m_physics )   {
+    if ( ctor == nam )  {
+      if ( nullptr == ctor.pointer )
+	except("Failed to instaniate the physics for constructor '%s'", nam.c_str());
+      return ctor;
+    }
+  }
+  except("Failed to access the physics for constructor '%s' [Unknown physics]", nam.c_str());
+  throw runtime_error("Failed to access the physics process"); // never called anyway
+}
+
 /// Add PhysicsConstructor by name
 void Geant4PhysicsList::adoptPhysicsConstructor(Geant4Action* action)  {
   if ( 0 != action )   {
@@ -219,11 +232,10 @@ void Geant4PhysicsList::constructPhysics(G4VModularPhysicsList* physics_pointer)
   debug("constructPhysics %p", physics_pointer);
   for ( auto& ctor : m_physics )   {
     if ( 0 == ctor.pointer )   {
-      if ( G4VPhysicsConstructor* p = PluginService::Create<G4VPhysicsConstructor*>(ctor) )  {
+      if ( G4VPhysicsConstructor* p = PluginService::Create<G4VPhysicsConstructor*>(ctor) )
 	ctor.pointer = p;
-	continue;
-      }
-      except("Failed to create the physics for G4VPhysicsConstructor '%s'", ctor.c_str());
+      else
+	except("Failed to create the physics for G4VPhysicsConstructor '%s'", ctor.c_str());
     }
     physics_pointer->RegisterPhysics(ctor.pointer);
     info("Registered Geant4 physics constructor %s to physics list", ctor.c_str());
@@ -239,7 +251,7 @@ void Geant4PhysicsList::constructParticles(G4VUserPhysicsList* physics_pointer)
     if ( !def )  {
       /// Check if we have here a particle group constructor
       long* result = (long*) PluginService::Create<long>(ctor);
-      if (!result || *result != 1L)   {
+      if ( !result || *result != 1L )   {
         except("Failed to create particle type '%s' result=%d", ctor.c_str(), result);
       }
       info("Constructed Geant4 particle %s [using signature long (*)()]",ctor.c_str());
@@ -249,7 +261,7 @@ void Geant4PhysicsList::constructParticles(G4VUserPhysicsList* physics_pointer)
   for ( const auto& ctor : m_particlegroups )  {
     /// Check if we have here a particle group constructor
     long* result = (long*) PluginService::Create<long>(ctor);
-    if (!result || *result != 1L)  {
+    if ( !result || *result != 1L )  {
       except("Failed to create particle type '%s' result=%d", ctor.c_str(), result);
     }
     info("Constructed Geant4 particle group %s [using signature long (*)()]",ctor.c_str());
diff --git a/examples/DDCAD/compact/Check_Shape_MS3D_jeep.xml b/examples/DDCAD/compact/Check_Shape_MS3D_jeep.xml
index e7a5c4830d62000bfd2fbbec9e90c99caebb7bf2..257ba1f67b48a0b54ededaee3aa27c55bad3e0dc 100644
--- a/examples/DDCAD/compact/Check_Shape_MS3D_jeep.xml
+++ b/examples/DDCAD/compact/Check_Shape_MS3D_jeep.xml
@@ -18,7 +18,7 @@
   <detectors>
     <detector id="1" name="Shape_OBJ" type="DD4hep_TestShape_Creator">
       <check vis="Shape1_vis">
-        <shape type="CAD_Assembly" ref="${DD4hepExamplesINSTALL}/examples/DDCAD/models/MS3D/jeep1.ms3d"/>
+        <shape type="CAD_MultiVolume" ref="${DD4hepExamplesINSTALL}/examples/DDCAD/models/MS3D/jeep1.ms3d"/>
       </check>
       <test1  type="DD4hep_Mesh_Verifier" ref="${DD4hepExamplesINSTALL}/examples/DDCAD/ref/Ref_OBJ_spider.txt" create="CheckShape_create"/>
     </detector>