From eafc22213fa493e34a9084770657ace143b1faf0 Mon Sep 17 00:00:00 2001
From: Joseph Boudreau <joseph.boudreau@cern.ch>
Date: Mon, 14 Oct 2024 21:02:30 +0200
Subject: [PATCH] Merge all recent work on virtual geometry into main

---
 .../GeoModelKernel/GeoAccessSurfaceAction.h   |  76 ++++
 .../GeoModelKernel/GeoAccessVolumeAction.h    |   4 +
 .../GeoModelKernel/GeoAnnulusSurface.h        |  93 +++++
 .../GeoModelKernel/GeoCountSurfaceAction.h    |  31 ++
 .../GeoModelKernel/GeoCountVolAction.h        |   5 +-
 .../GeoModelKernel/GeoDiamondSurface.h        |  81 +++++
 .../GeoModelKernel/GeoNodeAction.h            |  18 +-
 .../GeoModelKernel/GeoPrintGraphAction.h      |   9 +
 .../GeoModelKernel/GeoRectSurface.h           |  39 ++-
 .../GeoModelKernel/GeoShapeAction.h           |  21 ++
 .../GeoModelKernel/GeoSurfaceCursor.h         |   5 +-
 .../GeoModelKernel/GeoTrapezoidSurface.h      |  67 ++++
 .../GeoModelKernel/GeoVSurface.h              |  52 ++-
 .../GeoModelKernel/GeoVSurfaceShape.h         |  50 +++
 .../GeoModelKernel/GeoVolumeCursor.h          |  12 +-
 .../src/GeoAccessSurfaceAction.cxx            | 108 ++++++
 .../src/GeoAccessVolumeAction.cxx             |   7 +
 .../GeoModelKernel/src/GeoAnnulusSurface.cxx  |  41 +++
 .../src/GeoCountSurfaceAction.cxx             |  18 +
 .../GeoModelKernel/src/GeoCountVolAction.cxx  |   7 +
 .../GeoModelKernel/src/GeoDiamondSurface.cxx  |  21 ++
 .../GeoModelKernel/src/GeoNodeAction.cxx      |   6 +
 .../GeoModelKernel/src/GeoPlacement.cxx       |  11 +
 .../src/GeoPrintGraphAction.cxx               |  33 +-
 .../GeoModelKernel/src/GeoRectSurface.cxx     |   7 +
 .../GeoModelKernel/src/GeoShapeAction.cxx     |  28 ++
 .../GeoModelKernel/src/GeoSurfaceCursor.cxx   |  14 +-
 .../src/GeoTrapezoidSurface.cxx               |  19 +
 .../GeoModelKernel/src/GeoVSurface.cxx        | 125 +++++++
 .../GeoModelKernel/src/GeoVolumeCursor.cxx    |  31 +-
 GeoModelExamples/CMakeLists.txt               |   4 +
 .../SiliconSystemExample/CMakeLists.txt       |  42 +++
 .../src/SiliconSystemPlugin.cxx               | 209 +++++++++++
 .../SurfAlignTestPlugin/CMakeLists.txt        |  42 +++
 .../src/SurfAlignTestPlugin.cxx               | 239 +++++++++++++
 .../SurfAnnulusDemo/CMakeLists.txt            |  35 ++
 .../SurfAnnulusDemo/src/SurfAnnulusDemo.cxx   | 278 +++++++++++++++
 GeoModelExamples/SurfDiamond/CMakeLists.txt   |  35 ++
 .../SurfDiamond/src/SurfDiamond.cxx           | 204 +++++++++++
 .../src/SurfaceTestPlugin.cxx                 | 110 ++++--
 .../GeoModelDBManager/src/GMDBManager.cpp     | 112 +++++-
 .../GeoModelRead/GeoModelRead/ReadGeoModel.h  |  41 ++-
 .../GeoModelRead/src/BuildGeoVSurface.cpp     |  71 ++++
 .../GeoModelRead/src/BuildGeoVSurface.h       |  41 +++
 GeoModelIO/GeoModelRead/src/ReadGeoModel.cpp  | 207 ++++++++++-
 .../GeoModelWrite/WriteGeoModel.h             |  30 +-
 .../GeoModelWrite/src/WriteGeoModel.cpp       | 247 ++++++++++++-
 GeoModelVisualization/CMakeLists.txt          |   2 +-
 .../{VP1HEPVis => GXHepVis}/CMakeLists.txt    |  20 +-
 .../GXHepVis/GXHepVisUtils.h}                 |  23 +-
 .../VP1HEPVis => GXHepVis/GXHepVis}/SbPlane.h |   0
 .../GXHepVis}/SbPolyhedron.h                  |   6 +-
 .../GXHepVis}/SbRotation.h                    |   0
 .../GXHepVis}/SbTwistSurface.h                |   2 +-
 .../GXHepVis}/SbTwistTrapAlphaSide.h          |   2 +-
 .../GXHepVis}/SbTwistTrapFlatSide.h           |   2 +-
 .../GXHepVis}/SbTwistTrapParallelSide.h       |   4 +-
 .../GXHepVis}/actions/SoGL2PSAction.h         |   0
 .../VP1HEPVis => GXHepVis/GXHepVis}/gl2ps.h   |   0
 .../GXHepVis}/nodes/SoCons.h                  |  19 -
 .../GXHepVis}/nodes/SoGenericBox.h            |   4 +-
 .../GXHepVis}/nodes/SoLAr.h                   |  18 -
 .../GXHepVis}/nodes/SoPcons.h                 |  17 -
 .../GXHepVis}/nodes/SoPolyhedron.h            |   6 +-
 .../GXHepVis}/nodes/SoTessellated.h           |   3 -
 .../GXHepVis}/nodes/SoTorus.h                 |  18 -
 .../GXHepVis}/nodes/SoTransparency.h          |   0
 .../GXHepVis}/nodes/SoTubs.h                  |  18 -
 .../src/BooleanProcessor.h                    |  10 +-
 .../src/BooleanProcessor.h.original           |   0
 .../GXHepVis/src/GXHepVisUtils.cxx            |  40 +++
 .../src/PolygonTriangulator.cxx               |   0
 .../src/PolygonTriangulator.h                 |   0
 .../src/RevolutionSurfaceUtil.h               |   0
 .../{VP1HEPVis => GXHepVis}/src/SbMath.h      |   0
 .../{VP1HEPVis => GXHepVis}/src/SbPlane.cxx   |   4 +-
 .../src/SbPolyhedron.cxx                      |  32 +-
 .../src/SbRotation.cxx                        |   4 +-
 .../src/SbStringHelpers.cxx                   |   0
 .../src/SbStringHelpers.h                     |   0
 .../src/SbTwistSurface.cxx                    |   2 +-
 .../src/SbTwistTrapAlphaSide.cxx              |   2 +-
 .../src/SbTwistTrapFlatSide.cxx               |   2 +-
 .../src/SbTwistTrapParallelSide.cxx           |   2 +-
 .../{VP1HEPVis => GXHepVis}/src/SoCons.cxx    |  18 +-
 .../src/SoGL2PSAction.cxx                     |   4 +-
 .../src/SoGenericBox.cxx                      |  68 +---
 .../{VP1HEPVis => GXHepVis}/src/SoLAr.cxx     |  18 +-
 .../{VP1HEPVis => GXHepVis}/src/SoPcons.cxx   | 265 +-------------
 .../src/SoPolyhedron.cxx                      |  60 +---
 .../src/SoTessellated.cxx                     |  65 +---
 .../{VP1HEPVis => GXHepVis}/src/SoTorus.cxx   |  19 +-
 .../src/SoTransparency.cxx                    |   2 +-
 .../{VP1HEPVis => GXHepVis}/src/SoTubs.cxx    |  18 +-
 .../{VP1HEPVis => GXHepVis}/src/gl2ps.cxx     |   2 +-
 GeoModelVisualization/VP1Base/CMakeLists.txt  |   4 +-
 .../VP1Base/VP1Base/VP1ExaminerViewer.h       |   2 -
 .../VP1Base/src/VP1ExaminerViewer.cxx         |  95 +----
 .../VP1Base/src/VP1MaterialButton.cxx         |   6 +-
 .../VP1GeometrySystems/CMakeLists.txt         |   2 +-
 .../VP1GeometrySystems/DumpShape.h            |   8 +
 .../VP1GeometrySystems/PhiSectorManager.h     |   2 +
 .../VP1GeometrySystems/SoVisualizeAction.h    |  32 +-
 .../VP1GeometrySystems/VP1GeometrySystem.h    |  15 +-
 .../VP1GeometrySystems/VolumeHandle.h         |   7 +
 .../VolumeHandleSharedData.h                  |   7 +-
 .../VP1GeometrySystems/src/DumpShape.cxx      |  57 +++
 .../src/PhiSectorManager.cxx                  |  38 +-
 .../src/SbPolyhedrizeAction.cxx               |   4 +-
 .../src/SoVisualizeAction.cxx                 | 317 ++++++++++++++++-
 .../src/VP1GeometrySystem.cxx                 |  88 +++--
 .../VP1GeometrySystems/src/VolumeHandle.cxx   | 209 ++++++++---
 .../src/VolumeHandleSharedData.cxx            |  29 +-
 .../src/VolumeTreeModel.cxx                   |   8 +-
 .../VP1GuideLineSystems/CMakeLists.txt        |   2 +-
 .../VP1GuideLineSystems/src/VP1Letters.cxx    |   4 +-
 .../VP1HEPVis/src/VP1HEPVisUtils.cxx          | 328 ------------------
 cmake/GeoModel-version.cmake                  |   2 +-
 118 files changed, 3754 insertions(+), 1299 deletions(-)
 create mode 100644 GeoModelCore/GeoModelKernel/GeoModelKernel/GeoAccessSurfaceAction.h
 create mode 100644 GeoModelCore/GeoModelKernel/GeoModelKernel/GeoAnnulusSurface.h
 create mode 100644 GeoModelCore/GeoModelKernel/GeoModelKernel/GeoCountSurfaceAction.h
 create mode 100644 GeoModelCore/GeoModelKernel/GeoModelKernel/GeoDiamondSurface.h
 create mode 100644 GeoModelCore/GeoModelKernel/GeoModelKernel/GeoTrapezoidSurface.h
 create mode 100644 GeoModelCore/GeoModelKernel/GeoModelKernel/GeoVSurfaceShape.h
 create mode 100755 GeoModelCore/GeoModelKernel/src/GeoAccessSurfaceAction.cxx
 create mode 100644 GeoModelCore/GeoModelKernel/src/GeoAnnulusSurface.cxx
 create mode 100755 GeoModelCore/GeoModelKernel/src/GeoCountSurfaceAction.cxx
 create mode 100644 GeoModelCore/GeoModelKernel/src/GeoDiamondSurface.cxx
 create mode 100644 GeoModelCore/GeoModelKernel/src/GeoTrapezoidSurface.cxx
 create mode 100644 GeoModelCore/GeoModelKernel/src/GeoVSurface.cxx
 create mode 100644 GeoModelExamples/SiliconSystemExample/CMakeLists.txt
 create mode 100644 GeoModelExamples/SiliconSystemExample/src/SiliconSystemPlugin.cxx
 create mode 100644 GeoModelExamples/SurfAlignTestPlugin/CMakeLists.txt
 create mode 100644 GeoModelExamples/SurfAlignTestPlugin/src/SurfAlignTestPlugin.cxx
 create mode 100644 GeoModelExamples/SurfAnnulusDemo/CMakeLists.txt
 create mode 100644 GeoModelExamples/SurfAnnulusDemo/src/SurfAnnulusDemo.cxx
 create mode 100644 GeoModelExamples/SurfDiamond/CMakeLists.txt
 create mode 100644 GeoModelExamples/SurfDiamond/src/SurfDiamond.cxx
 create mode 100644 GeoModelIO/GeoModelRead/src/BuildGeoVSurface.cpp
 create mode 100644 GeoModelIO/GeoModelRead/src/BuildGeoVSurface.h
 rename GeoModelVisualization/{VP1HEPVis => GXHepVis}/CMakeLists.txt (66%)
 rename GeoModelVisualization/{VP1HEPVis/VP1HEPVis/VP1HEPVisUtils.h => GXHepVis/GXHepVis/GXHepVisUtils.h} (58%)
 rename GeoModelVisualization/{VP1HEPVis/VP1HEPVis => GXHepVis/GXHepVis}/SbPlane.h (100%)
 rename GeoModelVisualization/{VP1HEPVis/VP1HEPVis => GXHepVis/GXHepVis}/SbPolyhedron.h (99%)
 rename GeoModelVisualization/{VP1HEPVis/VP1HEPVis => GXHepVis/GXHepVis}/SbRotation.h (100%)
 rename GeoModelVisualization/{VP1HEPVis/VP1HEPVis => GXHepVis/GXHepVis}/SbTwistSurface.h (98%)
 rename GeoModelVisualization/{VP1HEPVis/VP1HEPVis => GXHepVis/GXHepVis}/SbTwistTrapAlphaSide.h (98%)
 rename GeoModelVisualization/{VP1HEPVis/VP1HEPVis => GXHepVis/GXHepVis}/SbTwistTrapFlatSide.h (98%)
 rename GeoModelVisualization/{VP1HEPVis/VP1HEPVis => GXHepVis/GXHepVis}/SbTwistTrapParallelSide.h (98%)
 rename GeoModelVisualization/{VP1HEPVis/VP1HEPVis => GXHepVis/GXHepVis}/actions/SoGL2PSAction.h (100%)
 rename GeoModelVisualization/{VP1HEPVis/VP1HEPVis => GXHepVis/GXHepVis}/gl2ps.h (100%)
 rename GeoModelVisualization/{VP1HEPVis/VP1HEPVis => GXHepVis/GXHepVis}/nodes/SoCons.h (86%)
 rename GeoModelVisualization/{VP1HEPVis/VP1HEPVis => GXHepVis/GXHepVis}/nodes/SoGenericBox.h (97%)
 rename GeoModelVisualization/{VP1HEPVis/VP1HEPVis => GXHepVis/GXHepVis}/nodes/SoLAr.h (84%)
 rename GeoModelVisualization/{VP1HEPVis/VP1HEPVis => GXHepVis/GXHepVis}/nodes/SoPcons.h (84%)
 rename GeoModelVisualization/{VP1HEPVis/VP1HEPVis => GXHepVis/GXHepVis}/nodes/SoPolyhedron.h (95%)
 rename GeoModelVisualization/{VP1HEPVis/VP1HEPVis => GXHepVis/GXHepVis}/nodes/SoTessellated.h (95%)
 rename GeoModelVisualization/{VP1HEPVis/VP1HEPVis => GXHepVis/GXHepVis}/nodes/SoTorus.h (92%)
 rename GeoModelVisualization/{VP1HEPVis/VP1HEPVis => GXHepVis/GXHepVis}/nodes/SoTransparency.h (100%)
 rename GeoModelVisualization/{VP1HEPVis/VP1HEPVis => GXHepVis/GXHepVis}/nodes/SoTubs.h (87%)
 rename GeoModelVisualization/{VP1HEPVis => GXHepVis}/src/BooleanProcessor.h (99%)
 rename GeoModelVisualization/{VP1HEPVis => GXHepVis}/src/BooleanProcessor.h.original (100%)
 create mode 100644 GeoModelVisualization/GXHepVis/src/GXHepVisUtils.cxx
 rename GeoModelVisualization/{VP1HEPVis => GXHepVis}/src/PolygonTriangulator.cxx (100%)
 rename GeoModelVisualization/{VP1HEPVis => GXHepVis}/src/PolygonTriangulator.h (100%)
 rename GeoModelVisualization/{VP1HEPVis => GXHepVis}/src/RevolutionSurfaceUtil.h (100%)
 rename GeoModelVisualization/{VP1HEPVis => GXHepVis}/src/SbMath.h (100%)
 rename GeoModelVisualization/{VP1HEPVis => GXHepVis}/src/SbPlane.cxx (97%)
 rename GeoModelVisualization/{VP1HEPVis => GXHepVis}/src/SbPolyhedron.cxx (98%)
 rename GeoModelVisualization/{VP1HEPVis => GXHepVis}/src/SbRotation.cxx (98%)
 rename GeoModelVisualization/{VP1HEPVis => GXHepVis}/src/SbStringHelpers.cxx (100%)
 rename GeoModelVisualization/{VP1HEPVis => GXHepVis}/src/SbStringHelpers.h (100%)
 rename GeoModelVisualization/{VP1HEPVis => GXHepVis}/src/SbTwistSurface.cxx (99%)
 rename GeoModelVisualization/{VP1HEPVis => GXHepVis}/src/SbTwistTrapAlphaSide.cxx (98%)
 rename GeoModelVisualization/{VP1HEPVis => GXHepVis}/src/SbTwistTrapFlatSide.cxx (99%)
 rename GeoModelVisualization/{VP1HEPVis => GXHepVis}/src/SbTwistTrapParallelSide.cxx (98%)
 rename GeoModelVisualization/{VP1HEPVis => GXHepVis}/src/SoCons.cxx (96%)
 rename GeoModelVisualization/{VP1HEPVis => GXHepVis}/src/SoGL2PSAction.cxx (99%)
 rename GeoModelVisualization/{VP1HEPVis => GXHepVis}/src/SoGenericBox.cxx (89%)
 rename GeoModelVisualization/{VP1HEPVis => GXHepVis}/src/SoLAr.cxx (97%)
 rename GeoModelVisualization/{VP1HEPVis => GXHepVis}/src/SoPcons.cxx (69%)
 rename GeoModelVisualization/{VP1HEPVis => GXHepVis}/src/SoPolyhedron.cxx (90%)
 rename GeoModelVisualization/{VP1HEPVis => GXHepVis}/src/SoTessellated.cxx (72%)
 rename GeoModelVisualization/{VP1HEPVis => GXHepVis}/src/SoTorus.cxx (98%)
 rename GeoModelVisualization/{VP1HEPVis => GXHepVis}/src/SoTransparency.cxx (98%)
 rename GeoModelVisualization/{VP1HEPVis => GXHepVis}/src/SoTubs.cxx (97%)
 rename GeoModelVisualization/{VP1HEPVis => GXHepVis}/src/gl2ps.cxx (99%)
 delete mode 100644 GeoModelVisualization/VP1HEPVis/src/VP1HEPVisUtils.cxx

diff --git a/GeoModelCore/GeoModelKernel/GeoModelKernel/GeoAccessSurfaceAction.h b/GeoModelCore/GeoModelKernel/GeoModelKernel/GeoAccessSurfaceAction.h
new file mode 100644
index 000000000..a3a617acc
--- /dev/null
+++ b/GeoModelCore/GeoModelKernel/GeoModelKernel/GeoAccessSurfaceAction.h
@@ -0,0 +1,76 @@
+/*
+  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+*/
+
+#ifndef GeoAccessSurfaceAction_h
+#define GeoAccessSurfaceAction_h 1
+
+#include "GeoModelKernel/GeoNodeAction.h"
+#include "GeoModelKernel/GeoDefinitions.h"
+#include <vector>
+
+class GeoVSurface;
+class GeoVPhysVol;
+class GeoTransform;
+class GeoVAlignmentStore;
+using VSConstLink = GeoIntrusivePtr<const GeoVSurface>;
+/**
+ * @class GeoAccessSurfaceAction
+ *
+ * @brief Accesses virtual surfaces, returning the ith surface and also its transformation relative to the parent.
+ */
+
+class GeoAccessSurfaceAction final : public GeoNodeAction
+{
+ public:
+  GeoAccessSurfaceAction (unsigned int Index, const GeoVAlignmentStore* store);
+  virtual ~GeoAccessSurfaceAction() override;
+
+  /// Handles a Transform.
+  virtual void handleTransform (const GeoTransform *xform) override;
+  
+  /// Handles a physical volume, to refresh the pendingTransformlist
+  virtual void handlePhysVol (const GeoPhysVol *vol) override;
+  
+  /// Handles a full physical volume, to refresh the pendingTransformlist
+  virtual void handleFullPhysVol (const GeoFullPhysVol *vol) override;  
+  
+  /// Handles a virtual surface.
+  virtual void handleVSurface (const GeoVSurface *surface) override;
+
+  /// Returns the selected virtual surface or nullptr if not found.
+  VSConstLink getSurface () const;
+
+  /// Returns the transformation to the surface.
+  const GeoTrf::Transform3D & getTransform () const;
+
+  /// Returns the default ransformation to the surface.
+  const GeoTrf::Transform3D & getDefTransform () const;
+
+ private:
+
+  GeoAccessSurfaceAction(const GeoAccessSurfaceAction &right);
+  GeoAccessSurfaceAction & operator=(const GeoAccessSurfaceAction &right);
+
+  /// Returns a pointer to the ith virtual surface under this one.
+  VSConstLink m_surface{};
+
+  /// The transformation to the ith surface.
+  GeoTrf::Transform3D m_transform{GeoTrf::Transform3D::Identity()};
+
+  /// The default transformation to the ith surface.
+  GeoTrf::Transform3D m_defTransform{GeoTrf::Transform3D::Identity()};
+
+  /// The surface which we are interested in seeking.
+  unsigned int m_index{0};
+
+  /// The surface which we are interested in seeking.
+  unsigned int m_counter{0};
+
+  /// List of Pending Transformations.
+  std::vector<const GeoTransform *>  m_pendingTransformList{};
+
+  const GeoVAlignmentStore* m_alignStore{nullptr};
+};
+
+#endif
diff --git a/GeoModelCore/GeoModelKernel/GeoModelKernel/GeoAccessVolumeAction.h b/GeoModelCore/GeoModelKernel/GeoModelKernel/GeoAccessVolumeAction.h
index 64e9b24a9..1418bfe05 100644
--- a/GeoModelCore/GeoModelKernel/GeoModelKernel/GeoAccessVolumeAction.h
+++ b/GeoModelCore/GeoModelKernel/GeoModelKernel/GeoAccessVolumeAction.h
@@ -9,6 +9,7 @@
 #include "GeoModelKernel/GeoDefinitions.h"
 #include <vector>
 
+class GeoVSurface;
 class GeoVPhysVol;
 class GeoTransform;
 class GeoVAlignmentStore;
@@ -35,6 +36,9 @@ class GeoAccessVolumeAction final : public GeoNodeAction
   /// Handles a physical volume.
   virtual void handleFullPhysVol (const GeoFullPhysVol *vol) override;
 
+  /// Handles a virtual surface, to refresh the pendingTransformlist
+  virtual void handleVSurface (const GeoVSurface *surface) override;
+
   /// Returns the selected physical volume or nullptr if not found.
   PVConstLink getVolume () const;
 
diff --git a/GeoModelCore/GeoModelKernel/GeoModelKernel/GeoAnnulusSurface.h b/GeoModelCore/GeoModelKernel/GeoModelKernel/GeoAnnulusSurface.h
new file mode 100644
index 000000000..2f85c16c9
--- /dev/null
+++ b/GeoModelCore/GeoModelKernel/GeoModelKernel/GeoAnnulusSurface.h
@@ -0,0 +1,93 @@
+/*
+  Copyright (C) 2002-2024 CERN for the benefit of the ATLAS collaboration
+*/
+
+/*
+ *
+ * Created on: July, 2024
+ * Author: Rui XUE <r.xue@cern.ch><rux23@pitt.edu>
+ *
+ */
+
+#ifndef GEOMODELKERNAL_GEOANNULUSSURFACE_H
+#define GEOMODELKERNAL_GEOANNULUSSURFACE_H
+
+#include "GeoModelKernel/GeoVSurfaceShape.h"
+
+class GeoAnnulusSurface : public GeoVSurfaceShape
+{
+    public:
+      
+      // Constructor for a GeoAnnulusSurface
+      // The default position of the cyllinder center is at (0,0,0)
+      // Ox, Oy: the deviation of the focusing point from the default position
+      // radius_in: the inner radius of the annulus
+      // radius_out: the outer radius of the annulus
+      // phi: the span angle of the deviated circular sector, when phi = 2*PI, it is an annulus
+      GeoAnnulusSurface(double Ox, double Oy, double radius_in, double radius_out, double phi);
+
+      // Returns the area of the annulus
+      // Proposed method: using Monte Carlo method to calculate the area
+      //                  it would need isInside() method to check if a point is inside the annulus 
+      //double area() const;
+
+      // Returns Ox
+      double getOx() const
+      {
+          return m_Ox;
+      }
+
+      // Returns Oy
+      double getOy() const
+      {
+          return m_Oy;
+      }
+
+      // Returns the inner radius of the annulus
+      double getRadiusIn() const
+      {
+          return m_radius_in;
+      }
+
+      // Returns the outer radius of the annulus
+      double getRadiusOut() const
+      {
+          return m_radius_out;
+      }
+
+      // Returns the span angle of the deviated circular sector
+      double getPhi() const
+      {
+          return m_phi;
+      }
+
+      // Determine if a point is inside the annulus
+      // x, y: the coordinates of the point
+      // coming soon!
+      //bool isInside(double x, double y) const;
+
+      virtual const std::string & type() const{
+        return s_classType;
+      }
+
+      virtual ShapeType typeID() const{
+        return s_classTypeID;
+      }
+
+      void exec (GeoShapeAction *action) const override final;
+
+    
+    protected:
+
+      virtual ~GeoAnnulusSurface() = default;
+      static const std::string s_classType;
+      static const ShapeType s_classTypeID;
+
+      double m_Ox{0.0};
+      double m_Oy{0.0};
+      double m_radius_in{0.0};
+      double m_radius_out{0.1};
+      double m_phi{2*M_PI};
+};
+
+#endif
\ No newline at end of file
diff --git a/GeoModelCore/GeoModelKernel/GeoModelKernel/GeoCountSurfaceAction.h b/GeoModelCore/GeoModelKernel/GeoModelKernel/GeoCountSurfaceAction.h
new file mode 100644
index 000000000..5295fa6b9
--- /dev/null
+++ b/GeoModelCore/GeoModelKernel/GeoModelKernel/GeoCountSurfaceAction.h
@@ -0,0 +1,31 @@
+/*
+  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+*/
+
+#ifndef GEOMODELKERNEL_GEOCOUNTSURFACEACTION_H
+#define GEOMODELKERNEL_GEOCOUNTSURFACEACTION_H
+
+#include "GeoModelKernel/GeoNodeAction.h"
+
+class GeoCountSurfaceAction final: public GeoNodeAction
+{
+ public:
+  GeoCountSurfaceAction ();
+  virtual ~GeoCountSurfaceAction();
+
+  //	Handles a virtual surface.
+  virtual void handleVSurface (const GeoVSurface *) override;
+  
+  //	The virtual surface count.
+  unsigned int getCount () const;
+
+
+  unsigned int m_count{0};
+};
+
+inline unsigned int GeoCountSurfaceAction::getCount () const
+{
+  return m_count;
+}
+
+#endif
diff --git a/GeoModelCore/GeoModelKernel/GeoModelKernel/GeoCountVolAction.h b/GeoModelCore/GeoModelKernel/GeoModelKernel/GeoCountVolAction.h
index 916670735..48bf26163 100644
--- a/GeoModelCore/GeoModelKernel/GeoModelKernel/GeoCountVolAction.h
+++ b/GeoModelCore/GeoModelKernel/GeoModelKernel/GeoCountVolAction.h
@@ -21,7 +21,10 @@ class GeoCountVolAction : public GeoNodeAction
   
   //	Handles a Serial Transformer
   virtual void handleSerialTransformer (const GeoSerialTransformer  *st);
-
+  
+  //	Handles a virtual surface.
+  virtual void handleVSurface (const GeoVSurface *) override;
+  
   //	The volume count.
   unsigned int getCount () const;
 
diff --git a/GeoModelCore/GeoModelKernel/GeoModelKernel/GeoDiamondSurface.h b/GeoModelCore/GeoModelKernel/GeoModelKernel/GeoDiamondSurface.h
new file mode 100644
index 000000000..a44801b50
--- /dev/null
+++ b/GeoModelCore/GeoModelKernel/GeoModelKernel/GeoDiamondSurface.h
@@ -0,0 +1,81 @@
+/*
+  Copyright (C) 2002-2024 CERN for the benefit of the ATLAS collaboration
+*/
+
+/*
+ *
+ * Created on: Oct, 2024
+ * Author: Rui XUE <r.xue@cern.ch><rux23@pitt.edu>
+ *
+ */
+
+
+#ifndef GEOMODELKERNEL_GEODIAMONDSURFACE_H
+#define GEOMODELKERNEL_GEODIAMONDSURFACE_H
+
+#include "GeoModelKernel/GeoVSurfaceShape.h"
+
+class GeoDiamondSurface : public GeoVSurfaceShape
+{
+ public:
+  //    Constructor for the Trapezoid Surface
+  GeoDiamondSurface (double X_bottom_half, double X_mid_half, double X_top_half, double Y_bottom_half, double Y_top_half);
+
+  //    Returns the area of the surface
+  double area() const;
+
+  //    Bottom Half Length in the x direction
+  double getXbottomHalf () const
+  {
+      return m_XbottomHalf;
+  }
+
+  //    Midddle Half Length in the x direction
+  double getXmidHalf () const
+  {
+    return m_XmidHalf;
+  }
+
+  //    Top Half Length in the x direction
+  double getXtopHalf () const
+  {
+    return m_XtopHalf;
+  }
+  
+  //    Bottom Half Length in the y direction
+  double getYbottomHalf () const
+  {
+    return m_YbottomHalf;
+  }
+
+  //    Top Half Length in the y direction
+  double getYtopHalf () const
+  {
+    return m_YtopHalf;
+  }  
+
+  virtual const std::string & type () const{
+     return s_classType;
+  }
+
+  virtual ShapeType typeID () const{
+     return s_classTypeID;
+  }
+
+  //     Executes a GeoShapeAction
+  void exec (GeoShapeAction *action) const override final;
+
+ protected:
+  virtual ~GeoDiamondSurface() = default;
+  
+  static const std::string s_classType;
+  static const ShapeType s_classTypeID;
+  double m_XbottomHalf{0.};
+  double m_XmidHalf{0.};
+  double m_XtopHalf{0.};
+  double m_YbottomHalf{0.};
+  double m_YtopHalf{0.};
+};
+
+
+#endif
diff --git a/GeoModelCore/GeoModelKernel/GeoModelKernel/GeoNodeAction.h b/GeoModelCore/GeoModelKernel/GeoModelKernel/GeoNodeAction.h
index bc08ace01..8232f0010 100644
--- a/GeoModelCore/GeoModelKernel/GeoModelKernel/GeoNodeAction.h
+++ b/GeoModelCore/GeoModelKernel/GeoModelKernel/GeoNodeAction.h
@@ -27,6 +27,9 @@
 #include "GeoModelKernel/GeoSerialTransformer.h"
 #include "GeoModelKernel/GeoVSurface.h"
 #include "GeoModelKernel/GeoRectSurface.h"
+#include "GeoModelKernel/GeoTrapezoidSurface.h"
+#include "GeoModelKernel/GeoAnnulusSurface.h"
+#include "GeoModelKernel/GeoDiamondSurface.h"
 #include "GeoModelKernel/GeoNodePath.h"
 
 class GeoNodeAction 
@@ -38,6 +41,8 @@ class GeoNodeAction
 
  public:
   GeoNodeAction();
+  GeoNodeAction(const GeoNodeAction &right) = delete;
+  GeoNodeAction & operator=(const GeoNodeAction &right) = delete; 
   virtual ~GeoNodeAction();
   
   //	Handles a Node.
@@ -70,9 +75,18 @@ class GeoNodeAction
   //    Handle GeoVSurface
   virtual void handleVSurface (const GeoVSurface *surface);
 
-  //    Handle GeoVSurface
+  //    Handle Rectangle Virtual Surface
   virtual void handleRectSurface (const GeoRectSurface *surface);
 
+  //    Handle Trapezoid Virtual Surface
+  virtual void handleTrapezoidSurface (const GeoTrapezoidSurface *surface);
+
+  //    Handle Annulus Virtual Surface
+  virtual void handleAnnulusSurface (const GeoAnnulusSurface *surface);
+
+  //    Handle Diamond Virtual Surface
+  virtual void handleDiamondSurface (const GeoDiamondSurface *surface);
+
   //	Returns a pointer to the path object.
   GeoNodePath* getPath ();
   
@@ -98,8 +112,6 @@ class GeoNodeAction
   bool m_terminate;
 
  private:
-  GeoNodeAction(const GeoNodeAction &right);
-  GeoNodeAction & operator=(const GeoNodeAction &right);
   
   //	A limit may be placed upon the depth to which the action
   //	descends.  0 = self.  1 = self and children.
diff --git a/GeoModelCore/GeoModelKernel/GeoModelKernel/GeoPrintGraphAction.h b/GeoModelCore/GeoModelKernel/GeoModelKernel/GeoPrintGraphAction.h
index dd803947c..cfa8bd2bf 100644
--- a/GeoModelCore/GeoModelKernel/GeoModelKernel/GeoPrintGraphAction.h
+++ b/GeoModelCore/GeoModelKernel/GeoModelKernel/GeoPrintGraphAction.h
@@ -57,6 +57,15 @@ class GeoPrintGraphAction : public GeoNodeAction
   //    Handle a rectangular surface.
   virtual void handleRectSurface( const GeoRectSurface *rect) override final; 
 
+  //    Handle a trapezoid surface.
+  virtual void handleTrapezoidSurface( const GeoTrapezoidSurface *trapezoid) override final; 
+
+  //    Handle an annulus surface.
+  virtual void handleAnnulusSurface( const GeoAnnulusSurface *annulus) override final;
+
+  //    Handle a diamond surface.
+  virtual void handleDiamondSurface( const GeoDiamondSurface *diamond) override final;
+
   //	Sets the notification state.  Default: everything on.
   void setNotification (Type type, bool state);
   
diff --git a/GeoModelCore/GeoModelKernel/GeoModelKernel/GeoRectSurface.h b/GeoModelCore/GeoModelKernel/GeoModelKernel/GeoRectSurface.h
index 40f267001..efc8e655b 100644
--- a/GeoModelCore/GeoModelKernel/GeoModelKernel/GeoRectSurface.h
+++ b/GeoModelCore/GeoModelKernel/GeoModelKernel/GeoRectSurface.h
@@ -1,30 +1,57 @@
+/*
+  Copyright (C) 2002-2024 CERN for the benefit of the ATLAS collaboration
+*/
+
+/*
+ *
+ * Created on: April, 2024
+ * Author: Rui XUE <r.xue@cern.ch><rux23@pitt.edu>
+ *
+ */
+
+
 #ifndef GEOMODELKERNEL_GEORECTSURFACE_H
 #define GEOMODELKERNEL_GEORECTSURFACE_H
 
-#include "GeoModelKernel/GeoVSurface.h"
+#include "GeoModelKernel/GeoVSurfaceShape.h"
 
-class GeoRectSurface : public GeoVSurface
+class GeoRectSurface : public GeoVSurfaceShape
 {
  public:
   //    Constructor for the Rectangular Surface
   GeoRectSurface (double XHalfLength, double YHalfLength);
 
   //    Returns the area of the surface
-  double area() const override;
+  double area() const;
 
   //    Half length in the x-direction
-  double getXHalfLength () const {
+  double getXHalfLength () const
+  {
       return m_xHalfLength;
   }
 
   //    Half-length in the y direction
-  double getYHalfLength () const {
+  double getYHalfLength () const
+  {
     return m_yHalfLength;
   }
 
+  virtual const std::string & type () const{
+     return s_classType;
+  }
+
+  virtual ShapeType typeID () const{
+     return s_classTypeID;
+  }
+
+  //     Executes a GeoShapeAction
+  void exec (GeoShapeAction *action) const override final;
+
  protected:
   virtual ~GeoRectSurface() = default;
-
+  
+  static const std::string s_classType;
+  static const ShapeType s_classTypeID;
   double m_xHalfLength{0.};
   double m_yHalfLength{0.};
 };
diff --git a/GeoModelCore/GeoModelKernel/GeoModelKernel/GeoShapeAction.h b/GeoModelCore/GeoModelKernel/GeoModelKernel/GeoShapeAction.h
index df4a430f1..a6ec5e36d 100644
--- a/GeoModelCore/GeoModelKernel/GeoModelKernel/GeoShapeAction.h
+++ b/GeoModelCore/GeoModelKernel/GeoModelKernel/GeoShapeAction.h
@@ -40,6 +40,12 @@ class GeoTessellatedSolid;
 
 class GeoGenericTrap;
 
+class GeoVSurfaceShape;
+class GeoRectSurface;
+class GeoTrapezoidSurface;
+class GeoAnnulusSurface;
+class GeoDiamondSurface;
+
 class GeoShapeAction 
 {
  public:
@@ -104,6 +110,21 @@ class GeoShapeAction
 
   //	Handles a tubs shape.
   virtual void handleTubs (const GeoTubs *tubs);
+  
+  //	Handles a virtual surface.
+  virtual void handleShape (const GeoVSurfaceShape *);
+  
+  //    Handles a rectangular surface.
+  virtual void handleRectSurface (const GeoRectSurface *surf);
+
+  //    Handles a trapezoid surface.
+  virtual void handleTrapezoidSurface (const GeoTrapezoidSurface *surf);
+
+  //    Handles an annulus surface.
+  virtual void handleAnnulusSurface (const GeoAnnulusSurface *surf);
+
+  //    Handles a diamond surface.
+  virtual void handleDiamondSurface (const GeoDiamondSurface *surf);
 
   //	Returns a pointer to the path object.
   GeoShapePath * getPath ();
diff --git a/GeoModelCore/GeoModelKernel/GeoModelKernel/GeoSurfaceCursor.h b/GeoModelCore/GeoModelKernel/GeoModelKernel/GeoSurfaceCursor.h
index 76f45bf79..980ce2da6 100644
--- a/GeoModelCore/GeoModelKernel/GeoModelKernel/GeoSurfaceCursor.h
+++ b/GeoModelCore/GeoModelKernel/GeoModelKernel/GeoSurfaceCursor.h
@@ -29,7 +29,10 @@ class GeoSurfaceCursor final : public GeoNodeAction
   
   /// Returns the default ransformation to the surface or volume.
   GeoTrf::Transform3D getDefTransform () const;
-        
+/*
+  /// Returns the name of the surface. All are called VSurface for now.
+  std::string getName () const;
+*/
  private:
   /// Handles a Transform.
   virtual void handleTransform (const GeoTransform *xform) override; 
diff --git a/GeoModelCore/GeoModelKernel/GeoModelKernel/GeoTrapezoidSurface.h b/GeoModelCore/GeoModelKernel/GeoModelKernel/GeoTrapezoidSurface.h
new file mode 100644
index 000000000..420966f1b
--- /dev/null
+++ b/GeoModelCore/GeoModelKernel/GeoModelKernel/GeoTrapezoidSurface.h
@@ -0,0 +1,67 @@
+/*
+  Copyright (C) 2002-2024 CERN for the benefit of the ATLAS collaboration
+*/
+
+/*
+ *
+ * Created on: July, 2024
+ * Author: Rui XUE <r.xue@cern.ch><rux23@pitt.edu>
+ *
+ */
+
+
+#ifndef GEOMODELKERNEL_GEOTRAPEZOIDSURFACE_H
+#define GEOMODELKERNEL_GEOTRAPEZOIDSURFACE_H
+
+#include "GeoModelKernel/GeoVSurfaceShape.h"
+
+class GeoTrapezoidSurface : public GeoVSurfaceShape
+{
+ public:
+  //    Constructor for the Trapezoid Surface
+  GeoTrapezoidSurface (double XHalfLengthMin, double XHalfLengthMax, double YHalfLength);
+
+  //    Returns the area of the surface
+  double area() const;
+
+  //    Minimum Half length in the x-direction
+  double getXHalfLengthMin () const
+  {
+      return m_xHalfLengthMin;
+  }
+
+  //    Maximum Half-length in the x direction
+  double getXHalfLengthMax () const
+  {
+    return m_xHalfLengthMax;
+  }
+  
+  //    Height Half-length in the y direction
+  double getYHalfLength () const
+  {
+    return m_yHalfLength;
+  }  
+
+  virtual const std::string & type () const{
+     return s_classType;
+  }
+
+  virtual ShapeType typeID () const{
+     return s_classTypeID;
+  }
+
+  //     Executes a GeoShapeAction
+  void exec (GeoShapeAction *action) const override final;
+
+ protected:
+  virtual ~GeoTrapezoidSurface() = default;
+  
+  static const std::string s_classType;
+  static const ShapeType s_classTypeID;
+  double m_xHalfLengthMin{0.};
+  double m_xHalfLengthMax{0.};
+  double m_yHalfLength{0.};
+};
+
+
+#endif
diff --git a/GeoModelCore/GeoModelKernel/GeoModelKernel/GeoVSurface.h b/GeoModelCore/GeoModelKernel/GeoModelKernel/GeoVSurface.h
index cecb1be89..fef8ee09f 100644
--- a/GeoModelCore/GeoModelKernel/GeoModelKernel/GeoVSurface.h
+++ b/GeoModelCore/GeoModelKernel/GeoModelKernel/GeoVSurface.h
@@ -1,6 +1,11 @@
 /*
   Copyright (C) 2002-2024 CERN for the benefit of the ATLAS collaboration
-*/
+ * 
+ *
+ * Created on: April, 2024
+ * Author: Rui XUE <r.xue@cern.ch><rux23@pitt.edu>
+ *
+ */
 #ifndef GEOMODELKERNEL_GeoVSurface_H
 #define GEOMODELKERNEL_GeoVSurface_H
 
@@ -10,26 +15,51 @@
  * @brief An abstract class of virtual surfaces
  *
  */
-
+#include "GeoModelKernel/GeoVSurfaceShape.h"
+#include "GeoModelKernel/GeoIntrusivePtr.h"
 #include "GeoModelKernel/GeoPlacement.h"
 #include "GeoModelKernel/GeoNodePositioning.h"
 #include "GeoModelKernel/GeoDefinitions.h"
+#include <iostream>
 
+#include <exception>
+#include <sstream>
 
+#define THROW_EXCEPTION(MESSAGE)                      \
+    {                                                 \
+        std::stringstream except_str{};               \
+        except_str<<__FILE__<<":"<<__LINE__<<" --- "; \
+        except_str<<MESSAGE;                          \
+        throw std::runtime_error(except_str.str());   \
+    }
+    
 class GeoVSurface : public GeoPlacement, public GeoNodePositioning {
  public:
-    GeoVSurface():
-      GeoNodePositioning{this}{
-    }
-  
-  virtual double area() const=0;	// calculate the area of a surface
-  
-  // method from GeoPlacement
+    using VSConstLink = GeoIntrusivePtr<const GeoVSurface>;
+    
+    GeoVSurface(const GeoVSurfaceShape *SurfShape):
+      GeoNodePositioning{this}, m_surfaceshape{SurfShape}{}
+    
+    // method from GeoPlacement
+    virtual void exec(GeoNodeAction *action) const;
 
+    /// Returns the number of child nodes, virtual surface has no child, return 0
+    unsigned int getNChildVols() const {return 0;}    
+    
+    //	Returns the shape of the virtual surface.
+    const GeoVSurfaceShape* getShape () const {
+        return m_surfaceshape;
+    }
+    
+    //  Justify whether the point is on the surface
+    bool isOnSurface(const double Px, const double Py, const double Pz) const;
   
  protected:
-  virtual ~GeoVSurface() = default;  
+  virtual ~GeoVSurface() = default;
+  
+ private:
+   GeoIntrusivePtr<const GeoVSurfaceShape>  m_surfaceshape;
 };
 
-
+using VSConstLink = GeoVSurface::VSConstLink;
 #endif
diff --git a/GeoModelCore/GeoModelKernel/GeoModelKernel/GeoVSurfaceShape.h b/GeoModelCore/GeoModelKernel/GeoModelKernel/GeoVSurfaceShape.h
new file mode 100644
index 000000000..a378f9e99
--- /dev/null
+++ b/GeoModelCore/GeoModelKernel/GeoModelKernel/GeoVSurfaceShape.h
@@ -0,0 +1,50 @@
+/*
+  Copyright (C) 2002-2023 CERN for the benefit of the ATLAS collaboration
+ * 
+ *
+ * Created on: Jul, 2024
+ * Author: Rui XUE <r.xue@cern.ch><rux23@pitt.edu>
+ *
+ */
+
+#ifndef GEOMODELKERNEL_GEOVSURFACESHAPE_H
+#define GEOMODELKERNEL_GEOVSURFACESHAPE_H
+
+
+#include "GeoModelKernel/RCBase.h"
+#include "GeoModelKernel/GeoShapeAction.h"
+#include <GeoModelKernel/GeoDefinitions.h>
+#include <string>
+#include <exception>
+#include <sstream>
+
+#define THROW_EXCEPTION(MESSAGE)                      \
+    {                                                 \
+        std::stringstream except_str{};               \
+        except_str<<__FILE__<<":"<<__LINE__<<" --- "; \
+        except_str<<MESSAGE;                          \
+        throw std::runtime_error(except_str.str());   \
+    }
+using SurfaceShapeType = unsigned int; // here use decimal numbers. (why use hexadecimal int?)
+
+class GeoVSurfaceShape : public RCBase
+{
+ public:
+  //    Constructor for shape. Must provide the name, a string to identify this shape.
+  GeoVSurfaceShape () = default;
+
+  //    Returns the shape type, as a string.
+  virtual const std::string & type () const = 0;
+
+  //    Returns the shape type, as an coded integer.
+  virtual SurfaceShapeType typeID () const = 0;
+
+  //    Executes a GeoShapeAction
+  //    TODO: Introduce GeoVSurfaceShapeAction in future
+  virtual void exec (GeoShapeAction *action) const = 0;
+
+ protected:
+  virtual ~GeoVSurfaceShape() = default;
+};
+
+#endif
diff --git a/GeoModelCore/GeoModelKernel/GeoModelKernel/GeoVolumeCursor.h b/GeoModelCore/GeoModelKernel/GeoModelKernel/GeoVolumeCursor.h
index c694b85fb..b70ae1bef 100644
--- a/GeoModelCore/GeoModelKernel/GeoModelKernel/GeoVolumeCursor.h
+++ b/GeoModelCore/GeoModelKernel/GeoModelKernel/GeoVolumeCursor.h
@@ -7,6 +7,7 @@
 
 #include "GeoModelKernel/GeoNodeAction.h"
 #include "GeoModelKernel/GeoDefinitions.h"
+#include "GeoModelKernel/GeoVSurface.h"
 #include <vector>
 
 class GeoVAlignmentStore;
@@ -14,6 +15,7 @@ class GeoVAlignmentStore;
 class GeoVolumeCursor final : public GeoNodeAction
 {
  public:
+  using VSConstLink = GeoVSurface::VSConstLink;
   GeoVolumeCursor (PVConstLink parent, GeoVAlignmentStore* store=nullptr);
   virtual ~GeoVolumeCursor() override;
  
@@ -29,6 +31,9 @@ class GeoVolumeCursor final : public GeoNodeAction
   /// Returns the selected physical volume or nullptr if not found.
   PVConstLink getVolume () const;
 
+  /// Returns the selected virtual surface or nullptr if not found.
+  VSConstLink getSurface () const;
+
   /// Returns the transformation to the volume.
   GeoTrf::Transform3D getTransform () const;
   
@@ -52,7 +57,10 @@ class GeoVolumeCursor final : public GeoNodeAction
 
   /// Handles a physical volume.
   virtual void handleFullPhysVol (const GeoFullPhysVol *vol) override;
-
+  
+  /// Handles a virtual surface.
+  virtual void handleVSurface (const GeoVSurface *surf) override;
+  
   /// Handles a Name Tag.
   virtual void handleNameTag (const GeoNameTag *nameTag) override;
 
@@ -74,6 +82,7 @@ class GeoVolumeCursor final : public GeoNodeAction
 
   PVConstLink                           m_parent;
   PVConstLink                           m_volume;
+  VSConstLink                           m_surface;
   GeoTrf::Transform3D                           m_transform;
   GeoTrf::Transform3D                           m_defTransform;
   
@@ -90,7 +99,6 @@ class GeoVolumeCursor final : public GeoNodeAction
   const GeoSerialIdentifier            *m_serialIdentifier;
   unsigned int                          m_serialIdentPosition;
   unsigned int                          m_volCount;
-  
   bool                                  m_hasAlignTrans;
 
   GeoVAlignmentStore                   *m_alignStore;
diff --git a/GeoModelCore/GeoModelKernel/src/GeoAccessSurfaceAction.cxx b/GeoModelCore/GeoModelKernel/src/GeoAccessSurfaceAction.cxx
new file mode 100755
index 000000000..ed9ecd431
--- /dev/null
+++ b/GeoModelCore/GeoModelKernel/src/GeoAccessSurfaceAction.cxx
@@ -0,0 +1,108 @@
+/*
+  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+*/
+
+#include "GeoModelKernel/GeoAccessSurfaceAction.h"
+
+#include <string>
+
+GeoAccessSurfaceAction::GeoAccessSurfaceAction(unsigned int Index, const GeoVAlignmentStore* store)
+  : m_transform(GeoTrf::Transform3D::Identity())
+  , m_defTransform(GeoTrf::Transform3D::Identity())
+  , m_index(Index)
+  , m_alignStore(store)
+{
+  setDepthLimit (1);
+  m_pendingTransformList.reserve(1);
+}
+
+GeoAccessSurfaceAction::~GeoAccessSurfaceAction() = default;
+
+void GeoAccessSurfaceAction::handleTransform (const GeoTransform *xform)
+{
+  m_pendingTransformList.push_back (xform);
+}
+
+
+// in this action, we only care about virtual surface
+// get rid of transformations corresponding to physics volume
+void GeoAccessSurfaceAction::handlePhysVol (const GeoPhysVol *vol)
+{
+  if(getPath()->getLength()-1 == 0)
+    return;
+
+  else{
+    m_pendingTransformList.erase (m_pendingTransformList.begin (),
+				  m_pendingTransformList.end ());    
+  }
+}
+
+
+// in this action, we only care about virtual surface
+// get rid of transformations corresponding to full physics volume
+void GeoAccessSurfaceAction::handleFullPhysVol (const GeoFullPhysVol *vol)
+{
+  if(getPath()->getLength()-1 == 0)
+    return;
+
+  else{
+    m_pendingTransformList.erase (m_pendingTransformList.begin (),
+				  m_pendingTransformList.end ());    
+  }
+}
+
+
+void GeoAccessSurfaceAction::handleVSurface (const GeoVSurface *surf)
+{
+  // Virtual Surface is the child of a Physical Volume, so no need to check.        
+  //
+  /*     
+  if(getPath()->getLength()-1 == 0)
+    return;
+  //
+  */
+       
+  // check if the index equals the counter:     
+  //       
+  if(m_index == m_counter) {
+    m_surface = surf;
+    unsigned int listSize = m_pendingTransformList.size ();
+    if(listSize == 0) {
+      // do nothing.... 
+    }
+    else if(listSize == 1) {
+      m_transform = m_pendingTransformList[0]->getTransform(m_alignStore);
+      m_defTransform = m_pendingTransformList[0]->getDefTransform(m_alignStore);
+    }
+    else {
+      for(unsigned int t = 0; t < m_pendingTransformList.size (); t++) {
+	m_transform = m_transform * m_pendingTransformList[t]->getTransform(m_alignStore);
+	m_defTransform = m_defTransform * m_pendingTransformList[t]->getDefTransform(m_alignStore);
+      }
+    }
+    terminate();
+  }
+  else {
+    m_pendingTransformList.erase (m_pendingTransformList.begin (),
+				  m_pendingTransformList.end ());
+  }
+  //     
+  // Increment the counter:     
+  //     
+  m_counter++;
+}
+
+VSConstLink GeoAccessSurfaceAction::getSurface () const
+{
+  return m_surface;
+}
+
+const GeoTrf::Transform3D & GeoAccessSurfaceAction::getTransform () const
+{
+  return m_transform;
+}
+
+const GeoTrf::Transform3D & GeoAccessSurfaceAction::getDefTransform () const
+{
+  return m_defTransform;
+}
diff --git a/GeoModelCore/GeoModelKernel/src/GeoAccessVolumeAction.cxx b/GeoModelCore/GeoModelKernel/src/GeoAccessVolumeAction.cxx
index a0af0873a..9b7713902 100755
--- a/GeoModelCore/GeoModelKernel/src/GeoAccessVolumeAction.cxx
+++ b/GeoModelCore/GeoModelKernel/src/GeoAccessVolumeAction.cxx
@@ -115,6 +115,13 @@ void GeoAccessVolumeAction::handleFullPhysVol (const GeoFullPhysVol *vol)
   m_counter++;
 }
 
+void GeoAccessVolumeAction::handleVSurface (const GeoVSurface *surface)
+{
+    m_pendingTransformList.erase (m_pendingTransformList.begin (),
+				  m_pendingTransformList.end ());
+}
+
+
 PVConstLink GeoAccessVolumeAction::getVolume () const
 {
   return m_volume;
diff --git a/GeoModelCore/GeoModelKernel/src/GeoAnnulusSurface.cxx b/GeoModelCore/GeoModelKernel/src/GeoAnnulusSurface.cxx
new file mode 100644
index 000000000..d230629d9
--- /dev/null
+++ b/GeoModelCore/GeoModelKernel/src/GeoAnnulusSurface.cxx
@@ -0,0 +1,41 @@
+# include "GeoModelKernel/GeoAnnulusSurface.h"
+
+const std::string GeoAnnulusSurface::s_classType = "AnnulusSurface";
+const ShapeType GeoAnnulusSurface::s_classTypeID = 36;
+
+GeoAnnulusSurface::GeoAnnulusSurface(double Ox, double Oy, double radius_in, double radius_out, double phi){
+    
+    m_Ox = Ox;
+    m_Oy = Oy;
+    m_radius_in = radius_in;
+    m_radius_out = radius_out;
+    m_phi = phi;
+
+    // if the deviation point is out of the inner ring, throw an error
+    if (Ox * Ox + Oy * Oy > radius_in * radius_in){
+        THROW_EXCEPTION("\n \n ERROR!!! \n THE DEVIATION POINT IS OUT OF THE INNER RING!!! \n \n");
+    }
+
+    // if the outer ring is smaller than the inner ring, throw an error
+    if (radius_out < radius_in){
+        THROW_EXCEPTION("\n \n ERROR!!! \n THE OUTTER RING IS SMALLER THAN THE INNER RING!!! \n \n");
+    }
+
+    // if the inner ring has negative radius, throw an error
+    if (radius_in < 0){
+        THROW_EXCEPTION("\n \n ERROR!!! \n THE INNER RING IS NEGATIVE!!! \n \n");
+    }
+
+    // if the outer ring has non-positive radius, throw an error
+    if (radius_out <= 0){
+        THROW_EXCEPTION("\n \n ERROR!!! \n THE OUTTER RING MUST BE POSITIVE!!! \n \n");
+    }
+}
+
+void GeoAnnulusSurface::exec(GeoShapeAction *action) const{
+    action->handleAnnulusSurface(this);
+}
+
+// bool GeoAnnulusSurface::isInside(double x, double y){}
+
+// double GeoAnnulusSurface::area() const{}
diff --git a/GeoModelCore/GeoModelKernel/src/GeoCountSurfaceAction.cxx b/GeoModelCore/GeoModelKernel/src/GeoCountSurfaceAction.cxx
new file mode 100755
index 000000000..359901d08
--- /dev/null
+++ b/GeoModelCore/GeoModelKernel/src/GeoCountSurfaceAction.cxx
@@ -0,0 +1,18 @@
+/*
+  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+*/
+
+#include "GeoModelKernel/GeoCountSurfaceAction.h"
+
+GeoCountSurfaceAction::GeoCountSurfaceAction ()
+{
+  setDepthLimit (1);
+}
+
+GeoCountSurfaceAction::~GeoCountSurfaceAction() = default;
+
+void GeoCountSurfaceAction::handleVSurface (const GeoVSurface *)
+{
+  // count the number of all virtual surfaces.    
+  m_count++;
+}
diff --git a/GeoModelCore/GeoModelKernel/src/GeoCountVolAction.cxx b/GeoModelCore/GeoModelKernel/src/GeoCountVolAction.cxx
index 1299bf045..613d35e9f 100755
--- a/GeoModelCore/GeoModelKernel/src/GeoCountVolAction.cxx
+++ b/GeoModelCore/GeoModelKernel/src/GeoCountVolAction.cxx
@@ -32,6 +32,13 @@ void GeoCountVolAction::handleFullPhysVol (const GeoFullPhysVol *)
     m_count++;
 }
 
+void GeoCountVolAction::handleVSurface (const GeoVSurface *)
+{
+  // Virtual Surface is always child of Physical Volume  
+  m_count++;
+}
+
+
 void GeoCountVolAction::handleSerialTransformer (const GeoSerialTransformer  *st)
 {
   m_count += st->getNCopies ();
diff --git a/GeoModelCore/GeoModelKernel/src/GeoDiamondSurface.cxx b/GeoModelCore/GeoModelKernel/src/GeoDiamondSurface.cxx
new file mode 100644
index 000000000..4e8e221eb
--- /dev/null
+++ b/GeoModelCore/GeoModelKernel/src/GeoDiamondSurface.cxx
@@ -0,0 +1,21 @@
+#include "GeoModelKernel/GeoDiamondSurface.h"
+
+const std::string GeoDiamondSurface::s_classType = "DiamondSurface";
+const ShapeType GeoDiamondSurface::s_classTypeID = 37; // here use decimal numbers for simplicity
+
+GeoDiamondSurface::GeoDiamondSurface (double X_bottom_half, double X_mid_half, double X_top_half, double Y_bottom_half, double Y_top_half):
+  m_XbottomHalf {X_bottom_half},
+  m_XmidHalf {X_mid_half},
+  m_XtopHalf {X_top_half},
+  m_YbottomHalf {Y_bottom_half},
+  m_YtopHalf {Y_top_half} {}
+
+
+double GeoDiamondSurface::area () const {
+  return (m_XmidHalf+m_XtopHalf)*m_YtopHalf + (m_XmidHalf+m_XbottomHalf)*m_YbottomHalf;
+}
+
+void GeoDiamondSurface::exec (GeoShapeAction *action) const {
+  action->handleDiamondSurface(this);
+}
+
diff --git a/GeoModelCore/GeoModelKernel/src/GeoNodeAction.cxx b/GeoModelCore/GeoModelKernel/src/GeoNodeAction.cxx
index 04748c32a..bd12c594f 100755
--- a/GeoModelCore/GeoModelKernel/src/GeoNodeAction.cxx
+++ b/GeoModelCore/GeoModelKernel/src/GeoNodeAction.cxx
@@ -87,5 +87,11 @@ void GeoNodeAction::handleVSurface (const GeoVSurface *surface) {
 void GeoNodeAction::handleRectSurface (const GeoRectSurface *rect) {
 }
 
+void GeoNodeAction::handleTrapezoidSurface (const GeoTrapezoidSurface *trapezoid) {
+}
 
+void GeoNodeAction::handleAnnulusSurface (const GeoAnnulusSurface *annulus) {
+}
 
+void GeoNodeAction::handleDiamondSurface (const GeoDiamondSurface *diamond) {
+}
\ No newline at end of file
diff --git a/GeoModelCore/GeoModelKernel/src/GeoPlacement.cxx b/GeoModelCore/GeoModelKernel/src/GeoPlacement.cxx
index e1d1fae37..258b08962 100644
--- a/GeoModelCore/GeoModelKernel/src/GeoPlacement.cxx
+++ b/GeoModelCore/GeoModelKernel/src/GeoPlacement.cxx
@@ -4,6 +4,7 @@
 #include "GeoModelKernel/GeoPlacement.h"
 #include "GeoModelKernel/GeoSerialTransformer.h"
 #include "GeoModelKernel/GeoVPhysVol.h"
+#include "GeoModelKernel/GeoVSurface.h"
 #include "GeoModelKernel/GeoTransform.h"
 
 
@@ -49,6 +50,11 @@ GeoTrf::Transform3D GeoPlacement::getX(const GeoVAlignmentStore* store) const {
     if (dynamic_cast<const GeoVPhysVol *>(*current)) break;              //
     //-------------------------------------------------------------------//
 
+    // If this happens, we are done, compute & return--------------------//
+    //                                                                   //
+    if (dynamic_cast<const GeoVSurface *>(*current)) break;              //
+    //-------------------------------------------------------------------//
+
     // If this happens, we are done, compute & return--------------------//
     //                                                                   //
     if (dynamic_cast<const GeoSerialTransformer *>(*current)) break;     //
@@ -88,6 +94,11 @@ GeoTrf::Transform3D GeoPlacement::getDefX(const GeoVAlignmentStore* store) const
     if (dynamic_cast<const GeoVPhysVol *>(*current)) break;              //
     //-------------------------------------------------------------------//
 
+    // If this happens, we are done, compute & return--------------------//
+    //                                                                   //
+    if (dynamic_cast<const GeoVSurface *>(*current)) break;              //
+    //-------------------------------------------------------------------//
+
     // If this happens, we are done, compute & return--------------------//
     //                                                                   //
     if (dynamic_cast<const GeoSerialTransformer *>(*current)) break;     //
diff --git a/GeoModelCore/GeoModelKernel/src/GeoPrintGraphAction.cxx b/GeoModelCore/GeoModelKernel/src/GeoPrintGraphAction.cxx
index 9bf48b1d8..737d56e14 100755
--- a/GeoModelCore/GeoModelKernel/src/GeoPrintGraphAction.cxx
+++ b/GeoModelCore/GeoModelKernel/src/GeoPrintGraphAction.cxx
@@ -87,20 +87,45 @@ void GeoPrintGraphAction::handleIdentifierTag (const GeoIdentifierTag *idTag)
 }
 
 
-//    Handle GeoVirSurface
+//    Handle GeoVSurface
 void GeoPrintGraphAction::handleVSurface (const GeoVSurface *surface) {
   indent();
-  m_o << "HELLO from VirtualSurface" << std::endl;
+  m_o << " Virtual Surface" << std::endl;
+  m_pendingTransformList.erase(m_pendingTransformList.begin(),m_pendingTransformList.end());
+  m_indented=false;
 }
 
-  //    Handle GeoVSurface
+  //    Handle GeoRectSurface
 void GeoPrintGraphAction::handleRectSurface (const GeoRectSurface *surface) {
   indent();
-  m_o << "HELLO from RectSurface" << std::endl;
+  m_o << " Rectangle Surface" << std::endl;
+  m_pendingTransformList.erase(m_pendingTransformList.begin(),m_pendingTransformList.end());
+  m_indented=false;
 }
 
+  //    Handle GeoTrapezoidSurface
+void GeoPrintGraphAction::handleTrapezoidSurface (const GeoTrapezoidSurface *surface) {
+  indent();
+  m_o << " Trapezoid Surface" << std::endl;
+  m_pendingTransformList.erase(m_pendingTransformList.begin(),m_pendingTransformList.end());
+  m_indented=false;
+}
 
+  //    Handle GeoAnnulusSurface
+void GeoPrintGraphAction::handleAnnulusSurface (const GeoAnnulusSurface *surface) {
+  indent();
+  m_o << " Annulus Surface" << std::endl;
+  m_pendingTransformList.erase(m_pendingTransformList.begin(),m_pendingTransformList.end());
+  m_indented=false;
+}
 
+  //    Handle GeoDiamondSurface
+void GeoPrintGraphAction::handleDiamondSurface (const GeoDiamondSurface *surface) {
+  indent();
+  m_o << " Diamond Surface" << std::endl;
+  m_pendingTransformList.erase(m_pendingTransformList.begin(),m_pendingTransformList.end());
+  m_indented=false;
+}
 
 void GeoPrintGraphAction::setNotification (Type type, bool state)
 {
diff --git a/GeoModelCore/GeoModelKernel/src/GeoRectSurface.cxx b/GeoModelCore/GeoModelKernel/src/GeoRectSurface.cxx
index 3d267b268..af5b45cab 100644
--- a/GeoModelCore/GeoModelKernel/src/GeoRectSurface.cxx
+++ b/GeoModelCore/GeoModelKernel/src/GeoRectSurface.cxx
@@ -1,5 +1,8 @@
 #include "GeoModelKernel/GeoRectSurface.h"
 
+const std::string GeoRectSurface::s_classType = "RectangleSurface";
+const ShapeType GeoRectSurface::s_classTypeID = 34; // here use decimal numbers for simplicity
+
 GeoRectSurface::GeoRectSurface (double XHalfLength, double YHalfLength):
   m_xHalfLength {XHalfLength},
   m_yHalfLength {YHalfLength} {}
@@ -9,3 +12,7 @@ double GeoRectSurface::area () const {
   return 4.0 * m_xHalfLength * m_yHalfLength;
 }
 
+void GeoRectSurface::exec (GeoShapeAction *action) const {
+  action->handleRectSurface(this);
+}
+
diff --git a/GeoModelCore/GeoModelKernel/src/GeoShapeAction.cxx b/GeoModelCore/GeoModelKernel/src/GeoShapeAction.cxx
index b6e7485f9..283854ba9 100755
--- a/GeoModelCore/GeoModelKernel/src/GeoShapeAction.cxx
+++ b/GeoModelCore/GeoModelKernel/src/GeoShapeAction.cxx
@@ -18,6 +18,10 @@
 #include "GeoModelKernel/GeoTube.h"
 #include "GeoModelKernel/GeoTubs.h"
 #include "GeoModelKernel/GeoPara.h"
+#include "GeoModelKernel/GeoRectSurface.h"
+#include "GeoModelKernel/GeoTrapezoidSurface.h"
+#include "GeoModelKernel/GeoAnnulusSurface.h"
+#include "GeoModelKernel/GeoDiamondSurface.h"
 
 #include "GeoModelKernel/GeoSimplePolygonBrep.h"
 #include "GeoModelKernel/GeoTessellatedSolid.h"
@@ -64,6 +68,10 @@ void GeoShapeAction::handleShape (const GeoShape *)
 {
 }
 
+void GeoShapeAction::handleShape (const GeoVSurfaceShape *)
+{
+}
+
 void GeoShapeAction::handleShift (const GeoShapeShift *shift)
 {
   handleShape(shift);
@@ -134,6 +142,26 @@ void GeoShapeAction::handleTubs (const GeoTubs *tubs)
   handleShape(tubs);
 }
 
+void GeoShapeAction::handleRectSurface (const GeoRectSurface *surf)
+{
+  handleShape(surf);
+}
+
+void GeoShapeAction::handleTrapezoidSurface (const GeoTrapezoidSurface *surf)
+{
+  handleShape(surf);
+}
+
+void GeoShapeAction::handleAnnulusSurface (const GeoAnnulusSurface *surf)
+{
+  handleShape(surf);
+}
+
+void GeoShapeAction::handleDiamondSurface (const GeoDiamondSurface *surf)
+{
+  handleShape(surf);
+}
+
 GeoShapePath * GeoShapeAction::getPath ()
 {
   return &m_path;
diff --git a/GeoModelCore/GeoModelKernel/src/GeoSurfaceCursor.cxx b/GeoModelCore/GeoModelKernel/src/GeoSurfaceCursor.cxx
index b8cfa5c28..c7acd719b 100644
--- a/GeoModelCore/GeoModelKernel/src/GeoSurfaceCursor.cxx
+++ b/GeoModelCore/GeoModelKernel/src/GeoSurfaceCursor.cxx
@@ -12,6 +12,7 @@ GeoSurfaceCursor::GeoSurfaceCursor (PVConstLink parent, GeoVAlignmentStore* stor
   , m_surfCount(0)
   , m_alignStore(store)  
 {
+  // depth is set to be 0, with next(), go to the child node
   setDepthLimit(0);
   next();
 }
@@ -31,8 +32,6 @@ void GeoSurfaceCursor::next() {
  	                        m_pendingTransformList.end ());  
  	                        
   int N = m_parent->getNChildNodes();
-  std::cout << " ChildNodes = " << N << std::endl;////////////
-  std::cout << " m_majorIndex = " << m_majorIndex << std::endl;////////////
   if (N==0) return;  
   
   const GeoGraphNode * const *node  = m_parent->getChildNode(m_majorIndex);
@@ -50,13 +49,9 @@ void GeoSurfaceCursor::next() {
       
       if (dynamic_cast<const GeoVPhysVol*> (*flag)){
         m_volCount++;
-        std::cout << " PHYSICS VOLUME " << std::endl;
-        std::cout << " volume count = " << m_volCount << std::endl;////////////
       }
       else if (dynamic_cast<const GeoVSurface*> (*flag)){
         m_surfCount++;
-        std::cout << " VIRTUAL SURFACE " << std::endl;
-        std::cout << " surf count = " << m_surfCount << std::endl;////////////
       }
       
       break;
@@ -161,3 +156,10 @@ GeoTrf::Transform3D GeoSurfaceCursor::getDefTransform () const
     return m_defTransform;
   //}
 }
+/*
+std::string GeoSurfaceCursor::getName() const
+{ 
+    std::string name = "VSurface";
+    return name;
+}
+*/
diff --git a/GeoModelCore/GeoModelKernel/src/GeoTrapezoidSurface.cxx b/GeoModelCore/GeoModelKernel/src/GeoTrapezoidSurface.cxx
new file mode 100644
index 000000000..765d70a89
--- /dev/null
+++ b/GeoModelCore/GeoModelKernel/src/GeoTrapezoidSurface.cxx
@@ -0,0 +1,19 @@
+#include "GeoModelKernel/GeoTrapezoidSurface.h"
+
+const std::string GeoTrapezoidSurface::s_classType = "TrapezoidSurface";
+const ShapeType GeoTrapezoidSurface::s_classTypeID = 35; // here use decimal numbers for simplicity
+
+GeoTrapezoidSurface::GeoTrapezoidSurface (double XHalfLengthMin, double XHalfLengthMax, double YHalfLength):
+  m_xHalfLengthMin {XHalfLengthMin},
+  m_xHalfLengthMax {XHalfLengthMax},
+  m_yHalfLength {YHalfLength} {}
+
+
+double GeoTrapezoidSurface::area () const {
+  return (m_xHalfLengthMin + m_xHalfLengthMax)*m_yHalfLength*2 ;
+}
+
+void GeoTrapezoidSurface::exec (GeoShapeAction *action) const {
+  action->handleTrapezoidSurface(this);
+}
+
diff --git a/GeoModelCore/GeoModelKernel/src/GeoVSurface.cxx b/GeoModelCore/GeoModelKernel/src/GeoVSurface.cxx
new file mode 100644
index 000000000..332646b31
--- /dev/null
+++ b/GeoModelCore/GeoModelKernel/src/GeoVSurface.cxx
@@ -0,0 +1,125 @@
+#include "GeoModelKernel/GeoVSurface.h"
+#include "GeoModelKernel/GeoNodeAction.h"
+
+
+void GeoVSurface::exec(GeoNodeAction *action) const{
+  action->handleVSurface(this);
+}
+
+bool GeoVSurface::isOnSurface(const double Px, const double Py, const double Pz) const{
+  GeoTrf::Vector3D P_prime(Px, Py, Pz);    
+  Eigen::Vector4d P_prime_4d(Px, Py, Pz, 1.0);
+  P_prime_4d = this->getX().inverse() * P_prime_4d;
+  double Pp_x = P_prime_4d[0];
+  double Pp_y = P_prime_4d[1];
+  double Pp_z = P_prime_4d[2];
+  // std::cout << " " << std::endl;
+  // std::cout << " AFTER INVERSE TRANSFORMATION " << std::endl;
+  // std::cout << "Pp_x: " << Pp_x << " Pp_y: " << Pp_y << " Pp_z: " << Pp_z << std::endl;
+// The Point is not even on the same plane as the Annulus Surface
+  if(Pp_z != 0 && Pp_z > 1e-5 && Pp_z < -1e-5){
+    // what is the tolerance for the point to be on the surface?
+    // now I take it as 1e-5
+    // std::cout << "FLAG 1" << std::endl;
+    return false;
+  }
+  if (dynamic_cast<const GeoAnnulusSurface*>(m_surfaceshape.get())){
+    const GeoAnnulusSurface *annulus_shape = dynamic_cast<const GeoAnnulusSurface*>(m_surfaceshape.get());
+
+    // The Annulus Shape starts from theta = 0
+    double real_theta = annulus_shape -> getPhi();
+    int quotient = floor(real_theta/(2.0*M_PI));
+    double theta = real_theta - quotient*2.0*M_PI;
+    
+    if (theta == 0.0 && real_theta > 0.0){
+      theta = 2.0*M_PI;
+    }
+    // std::cout << "theta: " << theta << std::endl;
+
+    double radius_in = annulus_shape -> getRadiusIn();
+    double radius_out = annulus_shape -> getRadiusOut();
+    double Ox = annulus_shape -> getOx();
+    double Oy = annulus_shape -> getOy();
+    
+  // Make sure the Point is located in the general Annulus Ring
+    if (Pp_x * Pp_x + Pp_y * Pp_y - radius_in * radius_in < -1e-5 || Pp_x * Pp_x + Pp_y * Pp_y - radius_out * radius_out > 1e-5){
+      // std::cout << " RADIUS " << Pp_x * Pp_x + Pp_y * Pp_y <<  std::endl;
+      // std::cout << "FLAG 2" << std::endl;
+      return false;
+    }
+    // else if (Pp_x * Pp_x + Pp_y * Pp_y < radius_in * radius_in || Pp_x * Pp_x + Pp_y * Pp_y > radius_out * radius_out){
+    //   std::cout << " RADIUS QUESTIONED" << Pp_x * Pp_x + Pp_y * Pp_y <<  std::endl;
+    // }
+
+  // Make sure the Point is located in the Deviated Circular Sector
+    double Dx = Pp_x - Ox; // X direction distance from the deviation center to the point
+    double Dy = Pp_y - Oy; // Y direction distance from the deviation center to the point
+    // std::cout << "Dx: " << Dx << " Dy: " << Dy << std::endl;
+ 
+    double angle = atan2(Dy, Dx); // the range of atan2 is (-pi, pi]
+    if (angle < 0.0){
+      angle += 2*M_PI;
+    }
+    // std::cout << "angle: " << angle << " theta: " << theta << std::endl;
+    if (angle <= theta){
+      return true;
+    }
+    else{
+      // std::cout << "FLAG 3" << std::endl;
+      return false;
+    }
+  }
+  else if (dynamic_cast<const GeoRectSurface*>(m_surfaceshape.get())){
+    const GeoRectSurface* rect_shape = dynamic_cast<const GeoRectSurface*>(m_surfaceshape.get());
+    double half_x = rect_shape -> getXHalfLength();
+    double half_y = rect_shape -> getYHalfLength();
+    double p1x = half_x; double p1y = -half_y;
+    double p2x = half_x; double p2y = half_y;
+    double p3x = -half_x; double p3y = half_y;
+    double p4x = -half_x; double p4y = -half_y;
+    if( (p2x-p1x)*(Pp_y-p1y) - (p2y-p1y)*(Pp_x-p1x) < -1e-5 ) return false;
+    if( (p3x-p2x)*(Pp_y-p2y) - (p3y-p2y)*(Pp_x-p2x) < -1e-5 ) return false;
+    if( (p4x-p3x)*(Pp_y-p3y) - (p4y-p3y)*(Pp_x-p3x) < -1e-5 ) return false;
+    if( (p1x-p4x)*(Pp_y-p4y) - (p1y-p4y)*(Pp_x-p4x) < -1e-5 ) return false;
+    return true;
+  }
+  else if (dynamic_cast<const GeoTrapezoidSurface*>(m_surfaceshape.get())){
+    const GeoTrapezoidSurface* trapezoid_shape = dynamic_cast<const GeoTrapezoidSurface*>(m_surfaceshape.get());
+    double half_x_max = trapezoid_shape -> getXHalfLengthMax();
+    double half_x_min = trapezoid_shape -> getXHalfLengthMin();
+    double half_y = trapezoid_shape -> getYHalfLength();
+    double p1x = half_x_min; double p1y = -half_y;
+    double p2x = half_x_max; double p2y = half_y;
+    double p3x = -half_x_max; double p3y = half_y;
+    double p4x = -half_x_min; double p4y = -half_y;
+    if( (p2x-p1x)*(Pp_y-p1y) - (p2y-p1y)*(Pp_x-p1x) < -1e-5 ) return false;
+    if( (p3x-p2x)*(Pp_y-p2y) - (p3y-p2y)*(Pp_x-p2x) < -1e-5 ) return false;
+    if( (p4x-p3x)*(Pp_y-p3y) - (p4y-p3y)*(Pp_x-p3x) < -1e-5 ) return false;
+    if( (p1x-p4x)*(Pp_y-p4y) - (p1y-p4y)*(Pp_x-p4x) < -1e-5 ) return false;
+    return true;
+  }
+  else if (dynamic_cast<const GeoDiamondSurface*>(m_surfaceshape.get())){
+    const GeoDiamondSurface* diamond_shape = dynamic_cast<const GeoDiamondSurface*>(m_surfaceshape.get());
+    double x_bot = diamond_shape -> getXbottomHalf(); double y_bot = diamond_shape -> getYbottomHalf();
+    double x_mid = diamond_shape -> getXmidHalf();
+    double x_top = diamond_shape -> getXtopHalf(); double y_top = diamond_shape -> getYtopHalf();
+    double p1x = x_bot; double p1y = -y_bot;
+    double p2x = x_mid; double p2y = 0.0;
+    double p3x = x_top; double p3y = y_top;
+    double p4x = -x_top; double p4y = y_top;
+    double p5x = -x_mid; double p5y = 0.0;
+    double p6x = -x_bot; double p6y = -y_bot;
+    if( (p2x-p1x)*(Pp_y-p1y) - (p2y-p1y)*(Pp_x-p1x) < -1e-5 ) return false;
+    if( (p3x-p2x)*(Pp_y-p2y) - (p3y-p2y)*(Pp_x-p2x) < -1e-5 ) return false;
+    if( (p4x-p3x)*(Pp_y-p3y) - (p4y-p3y)*(Pp_x-p3x) < -1e-5 ) return false;
+    if( (p5x-p4x)*(Pp_y-p4y) - (p5y-p4y)*(Pp_x-p4x) < -1e-5 ) return false;
+    if( (p6x-p5x)*(Pp_y-p5y) - (p6y-p5y)*(Pp_x-p5x) < -1e-5 ) return false;
+    if( (p1x-p6x)*(Pp_y-p6y) - (p1y-p6y)*(Pp_x-p6x) < -1e-5 ) return false;
+    return true;
+  }
+  else{
+    THROW_EXCEPTION("The Surface Shape is Unknown!");
+  }
+  // std::cout << "FLAG 10" << std::endl;
+  return false;
+}
diff --git a/GeoModelCore/GeoModelKernel/src/GeoVolumeCursor.cxx b/GeoModelCore/GeoModelKernel/src/GeoVolumeCursor.cxx
index 7119c5aac..a6d9575d3 100755
--- a/GeoModelCore/GeoModelKernel/src/GeoVolumeCursor.cxx
+++ b/GeoModelCore/GeoModelKernel/src/GeoVolumeCursor.cxx
@@ -59,6 +59,7 @@ void GeoVolumeCursor::next() {
 				  m_pendingTransformList.end ());
     m_hasAlignTrans = false;
     m_volume=nullptr;
+    m_surface=nullptr;
     
     int N = m_parent->getNChildNodes();
     if(N==0) return;
@@ -67,6 +68,7 @@ void GeoVolumeCursor::next() {
     const GeoGraphNode * const *end   = back+1;
     while (node!=end) {
       (*node)->exec(this);
+      const GeoGraphNode * const * flag = node;
       if (m_minorLimit) { // We have stepped into ST
       }
       else {            // We have not stepped into ST.
@@ -86,7 +88,8 @@ void GeoVolumeCursor::resuscitate() {
 }
 
 bool GeoVolumeCursor::atEnd() const {
-  return !m_volume;
+  //return !m_volume;
+  return (!m_volume and !m_surface);
 }
 
 void GeoVolumeCursor::handleTransform (const GeoTransform *xform)
@@ -135,6 +138,27 @@ void GeoVolumeCursor::handleFullPhysVol (const GeoFullPhysVol *vol)
   terminate ();
 }
 
+void GeoVolumeCursor::handleVSurface (const GeoVSurface *surf)
+{
+  m_surface = surf;
+  
+  unsigned int listSize = m_pendingTransformList.size ();
+  if (listSize == 0) {
+    m_transform    = GeoTrf::Transform3D::Identity();
+    m_defTransform = GeoTrf::Transform3D::Identity();
+  }
+  else {
+    m_transform = m_pendingTransformList[0]->getTransform(m_alignStore);
+    m_defTransform = m_pendingTransformList[0]->getDefTransform(m_alignStore);
+    for (unsigned int t = 1; t < m_pendingTransformList.size (); t++) {
+      m_transform    = m_transform    * m_pendingTransformList[t]->getTransform(m_alignStore);
+      m_defTransform = m_defTransform * m_pendingTransformList[t]->getDefTransform(m_alignStore);
+    }
+  }  
+  
+  terminate ();
+}
+
 void GeoVolumeCursor::handleSerialTransformer (const GeoSerialTransformer  *sT)
 {
   
@@ -191,6 +215,11 @@ PVConstLink GeoVolumeCursor::getVolume () const
   return m_volume;
 }
 
+VSConstLink GeoVolumeCursor::getSurface () const
+{
+  return m_surface;
+}
+
 GeoTrf::Transform3D GeoVolumeCursor::getTransform () const
 {
   if (m_minorLimit) {
diff --git a/GeoModelExamples/CMakeLists.txt b/GeoModelExamples/CMakeLists.txt
index 82ab2656d..c3071f150 100644
--- a/GeoModelExamples/CMakeLists.txt
+++ b/GeoModelExamples/CMakeLists.txt
@@ -13,6 +13,10 @@ project( "GeoModelExamples" VERSION 4.1.0 LANGUAGES CXX )
 add_subdirectory( KitchenSinkPlugin )
 add_subdirectory( MinimalPlugin )
 add_subdirectory( SurfaceTestPlugin )
+add_subdirectory( SurfAlignTestPlugin )
+add_subdirectory( SurfAnnulusDemo )
+add_subdirectory( SiliconSystemExample )
+add_subdirectory( SurfDiamond )
 
 add_subdirectory( HelloGeo )
 # add_subdirectory( HelloGeoWrite )
diff --git a/GeoModelExamples/SiliconSystemExample/CMakeLists.txt b/GeoModelExamples/SiliconSystemExample/CMakeLists.txt
new file mode 100644
index 000000000..f0745122e
--- /dev/null
+++ b/GeoModelExamples/SiliconSystemExample/CMakeLists.txt
@@ -0,0 +1,42 @@
+# Copyright (C) 2002-2024 CERN for the benefit of the ATLAS collaboration
+
+################################################################################
+# Package: HelloGeo
+# author: Riccardo Maria BIANCHI @ CERN - Nov, 2018
+################################################################################
+
+cmake_minimum_required(VERSION 3.16...3.26)
+
+# Compile with C++17
+set(CMAKE_CXX_STANDARD 17)
+set(CMAKE_CXX_STANDARD_REQUIRED ON)
+set(CMAKE_CXX_EXTENSIONS ON)
+
+
+# Find the needed dependencies, when building individually
+  message (${CMAKE_SOURCE_DIR})
+  message (${PROJECT_SOURCE_DIR})
+
+if ( CMAKE_SOURCE_DIR STREQUAL PROJECT_SOURCE_DIR ) # when buildingindividually
+   find_package( GeoModelCore REQUIRED  )
+endif()
+
+
+# Find the header and source files.
+file( GLOB SOURCES src/*.cxx )
+
+add_library( SiliconSystemPlugin SHARED ${SOURCES} )
+target_link_libraries( SiliconSystemPlugin PUBLIC GeoModelCore::GeoModelKernel)
+
+source_group( "src" FILES ${SOURCES} )
+
+set_target_properties( SiliconSystemPlugin PROPERTIES
+   VERSION ${PROJECT_VERSION}
+   SOVERSION ${PROJECT_VERSION_MAJOR} )
+
+# Install the library.
+install( TARGETS SiliconSystemPlugin
+   EXPORT ${PROJECT_NAME}-export
+   LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}
+   COMPONENT Runtime
+   NAMELINK_SKIP )
diff --git a/GeoModelExamples/SiliconSystemExample/src/SiliconSystemPlugin.cxx b/GeoModelExamples/SiliconSystemExample/src/SiliconSystemPlugin.cxx
new file mode 100644
index 000000000..abfeb3933
--- /dev/null
+++ b/GeoModelExamples/SiliconSystemExample/src/SiliconSystemPlugin.cxx
@@ -0,0 +1,209 @@
+/*
+  Copyright (C) 2002-2023 CERN for the benefit of the ATLAS collaboration
+*/
+
+// -------------------------------------------------------------------
+//
+// Kitchen Sink Plugin
+// Joe Boudreau Jan 11 2021
+//
+// This is an example plugin. It compiles to a shared library 
+// (with .so or .dylib extension) which can be viewed with gmex.
+// In this example there is no "envelope", all the components of
+// the kitchen sink are placed into the world.  This example
+// contains a geometry clash or two.  Therefore it may also be
+// used to test clash detection.
+//
+// This example illustrates the use of:
+//
+//    --the plugin mechanism.
+//    --simple shapes, logical volumes, physical volumes
+//    --Boolean operations
+//    --define air 
+//    --pure materials (aluminium)
+//    --mixtures (stainless steel)
+//
+// --------------------------------------------------------------------
+
+#include "GeoModelKernel/GeoVGeometryPlugin.h"
+#include "GeoModelKernel/GeoDefinitions.h"
+#include "GeoModelKernel/GeoMaterial.h"
+#include "GeoModelKernel/GeoBox.h"
+#include "GeoModelKernel/GeoTrd.h"
+#include "GeoModelKernel/GeoTube.h"
+#include "GeoModelKernel/GeoLogVol.h"
+#include "GeoModelKernel/GeoPhysVol.h"
+#include "GeoModelKernel/GeoFullPhysVol.h"
+#include "GeoModelKernel/GeoAlignableTransform.h"
+#include "GeoModelKernel/GeoTransform.h"
+#include "GeoModelKernel/GeoShapeSubtraction.h"
+#include "GeoModelKernel/GeoShapeShift.h"
+#include "GeoModelKernel/Units.h"
+#include "GeoModelKernel/GeoRectSurface.h"
+#include "GeoModelKernel/GeoTrapezoidSurface.h"
+#include "GeoModelKernel/GeoVSurface.h"
+#include <random>
+using namespace GeoModelKernelUnits;
+std::mt19937 engine;
+// Class Declaration
+const double degrees=M_PI/180.0;
+class SiliconSystemPlugin : public GeoVGeometryPlugin  {
+
+ public:
+
+  // Constructor:
+  SiliconSystemPlugin();
+
+  // Destructor:
+  ~SiliconSystemPlugin();
+
+  // Creation of geometry:
+  virtual void create(GeoVPhysVol *world, bool publish=false);
+
+ private:
+
+  // Illegal operations:
+  const SiliconSystemPlugin & operator=(const SiliconSystemPlugin &right)=delete;
+  SiliconSystemPlugin(const SiliconSystemPlugin &right) = delete;
+
+};
+
+
+// Class definition:
+
+// Constructor
+SiliconSystemPlugin::SiliconSystemPlugin()
+{
+}
+
+// Destructor
+SiliconSystemPlugin::~SiliconSystemPlugin()
+{
+}
+
+// The create algorithm creates a tree of physical volumes rooted under the
+// "world" physical volume. The optional flag publish is not used in this
+// example (normally one may "publish" a list of FullPhysVol's and Alignable
+// transforms, but this example has none such).
+//
+void SiliconSystemPlugin::create(GeoVPhysVol *world, bool /*publish*/) {
+  const double degree = M_PI / 180.0;
+
+  // Define elements used in this example:
+  GeoElement  *oxygen        = new GeoElement("Oxygen",    "O",   19,  39*gram/mole);
+  GeoElement  *nitrogen      = new GeoElement("Nitrogen",  "N",   7,  14*gram/mole);
+  GeoElement  *argon         = new GeoElement("Argon",     "Ar", 18,  40*gram/mole);
+  GeoElement  *aluminium     = new GeoElement("Aluminium", "Al", 13,  26*gram/mole);
+  GeoElement  *iron          = new GeoElement("Iron",      "Fe", 26,  55.8*gram/mole);
+  GeoElement  *chromium      = new GeoElement("Chromium",  "Cr", 24,  52*gram/mole);
+
+  // Define materials:
+  
+  // Define Air:
+  double densityOfAir     = 1.2E-3*gram/cm3;               // g/cm^3
+  GeoMaterial *Air           = new GeoMaterial("Air",densityOfAir);
+  Air->add(oxygen,2*0.21);                        // diatomic   oxygen   21% by volume.
+  Air->add(nitrogen,2*0.78);                        // diatomic   nitrogen 78% by volume.
+  Air->add(argon,0.01);                          // monoatomic argon    78% by volume.
+  Air->lock();
+
+  std::normal_distribution<double> normal;
+  
+  // Define Aluminium
+  double densityOfAluminium=2.7*gram/cm3;                  // g/cm^3
+  GeoMaterial *Aluminium     = new GeoMaterial("Aluminium", densityOfAluminium);
+  Aluminium->add(aluminium,1.0);
+  Aluminium->lock();
+
+  GeoBox     *boxShape = new GeoBox(10,10,10);
+  GeoLogVol  *boxLog = new GeoLogVol("BoxLog",boxShape,Air);
+  GeoPhysVol *worldBOX = new GeoPhysVol(boxLog);
+
+  for (int k=0;k<3;k++) {
+    for (int j=0;j<3;j++)  {
+      GeoBox *box = new GeoBox (0.1,(j+1)*1.7,20);
+      GeoLogVol  *boxLog=new GeoLogVol("SiDet", box, Aluminium);
+
+      GeoRectSurface* rectSurface = new GeoRectSurface((j+1)*1.9, 20.2);
+      GeoVSurface* surf = new GeoVSurface(rectSurface);
+
+      for (int i=0;i<16;i++) {
+        double theta = i/16.0*2*M_PI;
+        GeoFullPhysVol *boxPhys=new GeoFullPhysVol(boxLog);
+
+        // Initial transform is very tricky. Because the Virtual surface is always facing to Z axis initially.
+        GeoAlignableTransform* xf0 = new GeoAlignableTransform(GeoTrf::RotateZ3D(theta)*GeoTrf::TranslateX3D((j+1)*8.0+0.4*(i%2))*GeoTrf::TranslateX3D(0.5)*GeoTrf::TranslateZ3D((k-1)*44.0)*GeoTrf::RotateX3D(M_PI/2.0)*GeoTrf::RotateY3D(M_PI/2.0));
+        GeoAlignableTransform *xf = new GeoAlignableTransform(GeoTrf::RotateZ3D(theta)*GeoTrf::TranslateX3D((j+1)*8.0+0.4*(i%2)));
+
+        double rndTheta=normal(engine)*5*degrees;
+        double rndPhi=normal(engine)*5*degrees;
+        double rndPsi=normal(engine)*5*degrees;
+
+        // The Delta Setting is really tricky. The local axis are different because of different initialization order.
+        Eigen::Matrix3d m;
+        m = Eigen::AngleAxisd(rndTheta, Eigen::Vector3d::UnitZ())
+          * Eigen::AngleAxisd(rndPhi,   Eigen::Vector3d::UnitY())
+          * Eigen::AngleAxisd(rndPsi,   Eigen::Vector3d::UnitZ());
+
+        Eigen::Matrix3d m0;
+        m0 = Eigen::AngleAxisd(rndTheta, Eigen::Vector3d::UnitY())
+           * Eigen::AngleAxisd(rndPhi,   Eigen::Vector3d::UnitX())
+           * Eigen::AngleAxisd(rndPsi,   Eigen::Vector3d::UnitY());
+        
+        xf0->setDelta(GeoTrf::Transform3D(m0));
+        xf->setDelta(GeoTrf::Transform3D(m));
+        worldBOX->add(new GeoTransform(GeoTrf::TranslateZ3D((k-1)*44.0)));
+                
+        worldBOX->add(xf);
+        worldBOX->add(boxPhys);
+
+        worldBOX->add(xf0);
+        worldBOX->add(surf);
+      }
+    }
+    
+  }
+  for (int j=0;j<16;j++) {
+    for (int i=-1;i<2;i+=2)  {     
+
+      double L=10.0;
+      GeoTrapezoidSurface* trapezoid = new GeoTrapezoidSurface(1.2, 5.2, L);
+      GeoVSurface* surf = new GeoVSurface(trapezoid);
+      GeoTrd *trd=new GeoTrd(.2, .2, 1, 5, L);
+      GeoLogVol *trdLog=new GeoLogVol("SiDetEnd", trd,Aluminium);
+      GeoFullPhysVol *trdPhys=new GeoFullPhysVol(trdLog);
+
+      GeoTransform *sf0=new GeoTransform(GeoTrf::RotateY3D(j*2*M_PI/16.0)*GeoTrf::RotateX3D(M_PI/2.0)*GeoTrf::TranslateY3D(1.5*L));
+      GeoAlignableTransform* sf1 = nullptr;
+      if(i==-1){
+        std::cout << "i = -1" << std::endl;
+        sf1 = new GeoAlignableTransform(GeoTrf::TranslateZ3D(i*80.0+2.0*(j%2))*GeoTrf::TranslateZ3D(-1.0)*GeoTrf::RotateX3D(M_PI/2.0)*GeoTrf::RotateY3D(M_PI/2.0));
+      }
+      else{
+        std::cout << "i = 1" << std::endl;
+        sf1 = new GeoAlignableTransform(GeoTrf::TranslateZ3D(i*80.0+2.0*(j%2))*GeoTrf::TranslateZ3D(1.0)*GeoTrf::RotateX3D(M_PI/2.0)*GeoTrf::RotateY3D(M_PI/2.0));
+      }
+      
+      GeoTransform *xf0=new GeoTransform(GeoTrf::RotateZ3D(j*2*M_PI/16.0)*GeoTrf::RotateY3D(M_PI/2.0)*GeoTrf::TranslateZ3D(1.5*L));
+      GeoAlignableTransform *xf1= new GeoAlignableTransform (GeoTrf::TranslateZ3D(i*80.0+2.0*(j%2)));
+     
+      
+      worldBOX->add(xf1);
+      worldBOX->add(xf0);
+      worldBOX->add(trdPhys);
+      worldBOX->add(sf1);
+      worldBOX->add(sf0);
+      worldBOX->add(surf);
+    }
+  }
+  world->add(worldBOX);
+    //--------------------------------------//
+}
+
+// The name of this routine must correspond to the name of the class,
+// and also to the name of the source code file (this file)
+
+extern "C" SiliconSystemPlugin *createSiliconSystemPlugin() {
+  return new SiliconSystemPlugin;
+}
+
diff --git a/GeoModelExamples/SurfAlignTestPlugin/CMakeLists.txt b/GeoModelExamples/SurfAlignTestPlugin/CMakeLists.txt
new file mode 100644
index 000000000..fb011ac2a
--- /dev/null
+++ b/GeoModelExamples/SurfAlignTestPlugin/CMakeLists.txt
@@ -0,0 +1,42 @@
+# Copyright (C) 2002-2024 CERN for the benefit of the ATLAS collaboration
+
+################################################################################
+# Package: HelloGeo
+# author: Riccardo Maria BIANCHI @ CERN - Nov, 2018
+################################################################################
+
+cmake_minimum_required(VERSION 3.16...3.26)
+
+# Compile with C++17
+set(CMAKE_CXX_STANDARD 17)
+set(CMAKE_CXX_STANDARD_REQUIRED ON)
+set(CMAKE_CXX_EXTENSIONS ON)
+
+
+# Find the needed dependencies, when building individually
+  message (${CMAKE_SOURCE_DIR})
+  message (${PROJECT_SOURCE_DIR})
+
+if ( CMAKE_SOURCE_DIR STREQUAL PROJECT_SOURCE_DIR ) # when buildingindividually
+   find_package( GeoModelCore REQUIRED  )
+endif()
+
+
+# Find the header and source files.
+file( GLOB SOURCES src/*.cxx )
+
+add_library( SurfAlignTestPlugin SHARED ${SOURCES} )
+target_link_libraries( SurfAlignTestPlugin PUBLIC GeoModelCore::GeoModelKernel GeoModelCore::GeoModelHelpers)
+
+source_group( "src" FILES ${SOURCES} )
+
+set_target_properties( SurfAlignTestPlugin PROPERTIES
+   VERSION ${PROJECT_VERSION}
+   SOVERSION ${PROJECT_VERSION_MAJOR} )
+
+# Install the library.
+install( TARGETS SurfAlignTestPlugin
+   EXPORT ${PROJECT_NAME}-export
+   LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}
+   COMPONENT Runtime
+   NAMELINK_SKIP )
diff --git a/GeoModelExamples/SurfAlignTestPlugin/src/SurfAlignTestPlugin.cxx b/GeoModelExamples/SurfAlignTestPlugin/src/SurfAlignTestPlugin.cxx
new file mode 100644
index 000000000..ddd184777
--- /dev/null
+++ b/GeoModelExamples/SurfAlignTestPlugin/src/SurfAlignTestPlugin.cxx
@@ -0,0 +1,239 @@
+/*
+  Copyright (C) 2002-2023 CERN for the benefit of the ATLAS collaboration
+*/
+
+// -------------------------------------------------------------------
+//
+// Kitchen Sink Plugin
+// Joe Boudreau Jan 11 2021
+//
+// This is an example plugin. It compiles to a shared library 
+// (with .so or .dylib extension) which can be viewed with gmex.
+//
+// This plugin is used to test and develop surfaces, our first 
+// example of virtual geometry. 
+//
+//
+// --------------------------------------------------------------------
+
+#include "GeoModelKernel/GeoVGeometryPlugin.h"
+#include "GeoModelKernel/GeoDefinitions.h"
+#include "GeoModelKernel/GeoMaterial.h"
+#include "GeoModelKernel/GeoBox.h"
+#include "GeoModelKernel/GeoTube.h"
+#include "GeoModelKernel/GeoPrintGraphAction.h"
+#include "GeoModelKernel/GeoVolumeCursor.h"
+
+#include "GeoModelKernel/GeoLogVol.h"
+#include "GeoModelKernel/GeoPhysVol.h"
+#include "GeoModelKernel/GeoFullPhysVol.h"
+#include "GeoModelKernel/GeoTransform.h"
+#include "GeoModelKernel/GeoAlignableTransform.h"
+#include "GeoModelKernel/GeoShapeSubtraction.h"
+#include "GeoModelKernel/GeoShapeShift.h"
+#include "GeoModelKernel/GeoRectSurface.h"
+#include "GeoModelKernel/GeoTrapezoidSurface.h"
+#include "GeoModelKernel/GeoDiamondSurface.h"
+#include "GeoModelKernel/GeoVSurface.h"
+#include "GeoModelKernel/Units.h"
+#include "GeoModelHelpers/defineWorld.h"
+
+#include "GeoModelKernel/GeoSurfaceCursor.h"
+#include "GeoModelKernel/GeoCountSurfaceAction.h"
+#include "GeoModelKernel/GeoCountVolAction.h"
+#include "GeoModelKernel/GeoAccessSurfaceAction.h"
+#include "GeoModelKernel/GeoAccessVolumeAction.h"
+using namespace GeoModelKernelUnits;
+
+// Class Declaration
+
+class SurfAlignTestPlugin : public GeoVGeometryPlugin  {
+
+ public:
+
+  // Constructor:
+  SurfAlignTestPlugin();
+
+  // Destructor:
+  ~SurfAlignTestPlugin();
+
+  // Creation of geometry:
+  virtual void create(GeoVPhysVol *world, bool publish=false);
+
+ private:
+
+  // Illegal operations:
+  const SurfAlignTestPlugin & operator=(const SurfAlignTestPlugin &right)=delete;
+  SurfAlignTestPlugin(const SurfAlignTestPlugin &right) = delete;
+
+};
+
+
+// Class definition:
+
+// Constructor
+SurfAlignTestPlugin::SurfAlignTestPlugin()
+{
+}
+
+// Destructor
+SurfAlignTestPlugin::~SurfAlignTestPlugin()
+{
+}
+
+// The create algorithm creates a tree of physical volumes rooted under the
+// "world" physical volume. The optional flag publish is not used in this
+// example (normally one may "publish" a list of FullPhysVol's and Alignable
+// transforms, but this example has none such).
+//
+void SurfAlignTestPlugin::create(GeoVPhysVol *world, bool /*publish*/) {
+  // Define elements used in this example:
+  GeoElement  *oxygen        = new GeoElement("Oxygen",    "O",   19,  39*gram/mole);
+  GeoElement  *nitrogen      = new GeoElement("Nitrogen",  "N",   7,  14*gram/mole);
+  GeoElement  *argon         = new GeoElement("Argon",     "Ar", 18,  40*gram/mole);
+  GeoElement  *aluminium     = new GeoElement("Aluminium", "Al", 13,  26*gram/mole);
+
+  // Define materials:
+  
+  // Define Air:
+  double densityOfAir     = 1.2E-3*gram/cm3;               // g/cm^3
+  GeoMaterial *Air           = new GeoMaterial("Air",densityOfAir);
+  Air->add(oxygen,2*0.21);                        // diatomic   oxygen   21% by volume.
+  Air->add(nitrogen,2*0.78);                        // diatomic   nitrogen 78% by volume.
+  Air->add(argon,0.01);                          // monoatomic argon    78% by volume.
+  Air->lock();
+
+  // Define Aluminium
+  double densityOfAluminium=2.7*gram/cm3;                  // g/cm^3
+  GeoMaterial *Aluminium     = new GeoMaterial("Aluminium", densityOfAluminium);
+  Aluminium->add(aluminium,1.0);
+  Aluminium->lock();
+
+  GeoBox     *boxShape = new GeoBox(10,15,20);
+  GeoLogVol  *boxLog = new GeoLogVol("BoxLog",boxShape,Air);
+  GeoPhysVol *boxPhys = new GeoPhysVol(boxLog);
+
+
+  {
+
+////////////////////////////////////////////////////////////////////////////////////////////////
+    GeoBox     *boxShape = new GeoBox(3,7,5);
+    GeoLogVol  *boxLog = new GeoLogVol("BoxLog",boxShape,Air);
+    GeoFullPhysVol *boxPhys1 = new GeoFullPhysVol(boxLog);
+    GeoRectSurface* rectSurface1 = new GeoRectSurface(5, 9);
+    GeoVSurface* surf1 = new GeoVSurface(rectSurface1);
+    GeoAlignableTransform *move_together1=new GeoAlignableTransform(GeoTrf::TranslateX3D(0));
+    //GeoTransform * initial_rot = new GeoTransform(GeoTrf::RotateY3D(1.571));
+    
+    boxPhys->add(move_together1);
+    boxPhys->add(boxPhys1);
+    
+    boxPhys->add(move_together1);
+    //boxPhys->add(initial_rot);
+    boxPhys->add(surf1);
+    move_together1->setDelta(GeoTrf::RotateZ3D(1)*GeoTrf::RotateY3D(0.5));
+    
+    GeoBox     *boxShape2 = new GeoBox(4,4,4);
+    GeoLogVol  *boxLog2 = new GeoLogVol("BoxLog",boxShape2,Air);
+    GeoFullPhysVol *boxPhys4 = new GeoFullPhysVol(boxLog2);
+    boxPhys1->add(boxPhys4);
+    
+    //GeoRectSurface *rectSurface3 = new GeoRectSurface(7, 7);
+    //GeoVSurface* surf4 = new GeoVSurface(rectSurface3);
+    // GeoTrapezoidSurface* trapezoid = new GeoTrapezoidSurface(9, 7, 5);
+    // GeoVSurface* surf4 = new GeoVSurface(trapezoid);
+    GeoDiamondSurface* diamond = new GeoDiamondSurface(4, 6, 2, 5, 3);
+    GeoVSurface* surf4 = new GeoVSurface(diamond);
+    GeoTransform * initial_rot = new GeoTransform(GeoTrf::RotateY3D(1.571));
+    boxPhys1->add(initial_rot);
+    boxPhys1->add(surf4);
+////////////////////////////////////////////////////////////////////////////////////////////////
+
+    GeoFullPhysVol *boxPhys2 = new GeoFullPhysVol(boxLog);
+    //GeoRectSurface *rectSurface2 = new GeoRectSurface(8, 8);
+    //GeoVSurface* surf2 = new GeoVSurface(rectSurface2);
+    // GeoTrapezoidSurface* trapezoid2 = new GeoTrapezoidSurface(4, 6, 8);
+    // GeoVSurface* surf2 = new GeoVSurface(trapezoid2);
+    GeoDiamondSurface* diamond2 = new GeoDiamondSurface(8, 12, 4, 10, 6);
+    GeoVSurface* surf2 = new GeoVSurface(diamond2);
+    GeoAlignableTransform *move_together2=new GeoAlignableTransform(GeoTrf::TranslateX3D(-20));
+    
+    boxPhys->add(move_together2);
+    boxPhys->add(boxPhys2);
+    boxPhys->add(move_together2);
+    boxPhys->add(surf2);
+    move_together2->setDelta(GeoTrf::RotateZ3D(0));
+    
+////////////////////////////////////////////////////////////////////////////////////////////////
+    
+    GeoFullPhysVol *boxPhys3 = new GeoFullPhysVol(boxLog);
+    //GeoRectSurface *rectSurface3 = new GeoRectSurface(8, 8);
+    //GeoVSurface* surf3 = new GeoVSurface(rectSurface2);
+    GeoTrapezoidSurface* trapezoid2 = new GeoTrapezoidSurface(4, 6, 8);   
+    GeoVSurface* surf3 = new GeoVSurface(trapezoid2);
+    GeoAlignableTransform *move_together3=new GeoAlignableTransform(GeoTrf::TranslateX3D(20));
+    
+    boxPhys->add(move_together3);
+    boxPhys->add(boxPhys3);
+    boxPhys->add(move_together3);
+    boxPhys->add(surf3);
+    move_together3->setDelta(GeoTrf::RotateX3D(0));
+
+  }
+  
+    GeoTrapezoidSurface* trapezoid2 = new GeoTrapezoidSurface(9, 12, 8);
+    GeoVSurface* surf5 = new GeoVSurface(trapezoid2);
+    GeoAlignableTransform *move_together5=new GeoAlignableTransform(GeoTrf::TranslateX3D(40));
+    
+    boxPhys->add(move_together5);
+    boxPhys->add(surf5);
+    move_together5->setDelta(GeoTrf::RotateX3D(1));
+    
+  world->add(boxPhys);
+  GeoPrintGraphAction printGraphAction(std::cout);
+  world->exec(&printGraphAction);;
+
+  {
+    int i = 0;
+    
+    std::cout << " " << std::endl;
+    std::cout << " " << std::endl;    
+    std::cout << " cursor at i= " << i << std::endl;
+    GeoVolumeCursor cursor(boxPhys);
+    //GeoSurfaceCursor cursor(boxPhys);
+    
+    while (!cursor.atEnd()) {
+      i += 1;
+      std::cout << "!!! " << std::endl;
+      std::cout << cursor.getTransform().rotation() << std::endl;
+      std::cout << "!!! " << std::endl; 
+      std::cout << cursor.getTransform().translation() << std::endl;
+      std::cout << " " << std::endl;
+      cursor.next();
+    }
+  }
+
+
+  GeoCountSurfaceAction countSurface;
+  boxPhys->exec(&countSurface);
+  std::cout << "Number of Virtual Surface: " << countSurface.getCount() << std::endl;
+  unsigned int totalVSurface = countSurface.getCount();
+  
+  for (unsigned int i = 0; i< totalVSurface; i++){
+    GeoAccessSurfaceAction surfaceAccess (i, nullptr);
+    boxPhys->exec(&surfaceAccess);
+    std::cout << "surface transform rotation: " << surfaceAccess.getTransform().rotation() << std::endl;
+    std::cout << "surface transform trans: " << surfaceAccess.getTransform().translation() << std::endl;
+  }
+   std::cout << "surface5 transform trans: " << surf5->getX().rotation() << std::endl;
+   std::cout << "surface5 transform trans: " << surf5->getX().translation() << std::endl;
+  //--------------------------------------//
+}
+
+// The name of this routine must correspond to the name of the class,
+// and also to the name of the source code file (this file)
+
+extern "C" SurfAlignTestPlugin *createSurfAlignTestPlugin() {
+  return new SurfAlignTestPlugin;
+}
+
diff --git a/GeoModelExamples/SurfAnnulusDemo/CMakeLists.txt b/GeoModelExamples/SurfAnnulusDemo/CMakeLists.txt
new file mode 100644
index 000000000..4bb45aee0
--- /dev/null
+++ b/GeoModelExamples/SurfAnnulusDemo/CMakeLists.txt
@@ -0,0 +1,35 @@
+cmake_minimum_required(VERSION 3.16...3.26)
+
+# Compile with C++17
+set(CMAKE_CXX_STANDARD 17)
+set(CMAKE_CXX_STANDARD_REQUIRED ON)
+set(CMAKE_CXX_EXTENSIONS ON)
+
+
+# Find the needed dependencies, when building individually
+  message (${CMAKE_SOURCE_DIR})
+  message (${PROJECT_SOURCE_DIR})
+
+if ( CMAKE_SOURCE_DIR STREQUAL PROJECT_SOURCE_DIR ) # when buildingindividually
+   find_package( GeoModelCore REQUIRED  )
+endif()
+
+
+# Find the header and source files.
+file( GLOB SOURCES src/*.cxx )
+
+add_library( SurfAnnulusDemo SHARED ${SOURCES} )
+target_link_libraries( SurfAnnulusDemo PUBLIC GeoModelCore::GeoModelKernel GeoModelCore::GeoModelHelpers)
+
+source_group( "src" FILES ${SOURCES} )
+
+set_target_properties( SurfAnnulusDemo PROPERTIES
+   VERSION ${PROJECT_VERSION}
+   SOVERSION ${PROJECT_VERSION_MAJOR} )
+
+# Install the library.
+install( TARGETS SurfAnnulusDemo
+   EXPORT ${PROJECT_NAME}-export
+   LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}
+   COMPONENT Runtime
+   NAMELINK_SKIP )
diff --git a/GeoModelExamples/SurfAnnulusDemo/src/SurfAnnulusDemo.cxx b/GeoModelExamples/SurfAnnulusDemo/src/SurfAnnulusDemo.cxx
new file mode 100644
index 000000000..1a21ac27f
--- /dev/null
+++ b/GeoModelExamples/SurfAnnulusDemo/src/SurfAnnulusDemo.cxx
@@ -0,0 +1,278 @@
+/*
+  Copyright (C) 2002-2023 CERN for the benefit of the ATLAS collaboration
+*/
+
+// -------------------------------------------------------------------
+//
+// Annulus Surface Demo Plugin
+// Rui Xue, July 2024
+//
+//
+// This plugin is used to test and develop Annulus Surface
+// 
+//
+// --------------------------------------------------------------------
+
+#include "GeoModelKernel/GeoVGeometryPlugin.h"
+#include "GeoModelKernel/GeoDefinitions.h"
+#include "GeoModelKernel/GeoMaterial.h"
+#include "GeoModelKernel/GeoBox.h"
+#include "GeoModelKernel/GeoTube.h"
+#include "GeoModelKernel/GeoPrintGraphAction.h"
+#include "GeoModelKernel/GeoVolumeCursor.h"
+
+#include "GeoModelKernel/GeoLogVol.h"
+#include "GeoModelKernel/GeoPhysVol.h"
+#include "GeoModelKernel/GeoFullPhysVol.h"
+#include "GeoModelKernel/GeoTransform.h"
+#include "GeoModelKernel/GeoAlignableTransform.h"
+#include "GeoModelKernel/GeoShapeSubtraction.h"
+#include "GeoModelKernel/GeoShapeShift.h"
+#include "GeoModelKernel/GeoRectSurface.h"
+#include "GeoModelKernel/GeoTrapezoidSurface.h"
+#include "GeoModelKernel/GeoAnnulusSurface.h"
+#include "GeoModelKernel/GeoVSurface.h"
+#include "GeoModelKernel/Units.h"
+#include "GeoModelHelpers/defineWorld.h"
+
+#include "GeoModelKernel/GeoSurfaceCursor.h"
+#include "GeoModelKernel/GeoCountSurfaceAction.h"
+#include "GeoModelKernel/GeoCountVolAction.h"
+#include "GeoModelKernel/GeoAccessSurfaceAction.h"
+#include "GeoModelKernel/GeoAccessVolumeAction.h"
+
+#include <Eigen/Dense>
+#include <Eigen/Geometry>
+#include <iostream>
+#include <cmath>
+using namespace GeoModelKernelUnits;
+
+// Class Declaration
+
+class SurfAnnulusDemo : public GeoVGeometryPlugin  {
+
+ public:
+
+  // Constructor:
+  SurfAnnulusDemo();
+
+  // Destructor:
+  ~SurfAnnulusDemo();
+
+  // Creation of geometry:
+  virtual void create(GeoVPhysVol *world, bool publish=false);
+
+ private:
+
+  // Illegal operations:
+  const SurfAnnulusDemo & operator=(const SurfAnnulusDemo &right)=delete;
+  SurfAnnulusDemo(const SurfAnnulusDemo &right) = delete;
+
+};
+
+
+// Class definition:
+
+// Constructor
+SurfAnnulusDemo::SurfAnnulusDemo()
+{
+}
+
+// Destructor
+SurfAnnulusDemo::~SurfAnnulusDemo()
+{
+}
+
+// The create algorithm creates a tree of physical volumes rooted under the
+// "world" physical volume. The optional flag publish is not used in this
+// example (normally one may "publish" a list of FullPhysVol's and Alignable
+// transforms, but this example has none such).
+//
+void SurfAnnulusDemo::create(GeoVPhysVol *world, bool /*publish*/) {
+  // Define elements used in this example:
+  GeoElement  *oxygen        = new GeoElement("Oxygen",    "O",   19,  39*gram/mole);
+  GeoElement  *nitrogen      = new GeoElement("Nitrogen",  "N",   7,  14*gram/mole);
+  GeoElement  *argon         = new GeoElement("Argon",     "Ar", 18,  40*gram/mole);
+  GeoElement  *aluminium     = new GeoElement("Aluminium", "Al", 13,  26*gram/mole);
+
+  // Define materials:
+  
+  // Define Air:
+  double densityOfAir     = 1.2E-3*gram/cm3;               // g/cm^3
+  GeoMaterial *Air           = new GeoMaterial("Air",densityOfAir);
+  Air->add(oxygen,2*0.21);                        // diatomic   oxygen   21% by volume.
+  Air->add(nitrogen,2*0.78);                        // diatomic   nitrogen 78% by volume.
+  Air->add(argon,0.01);                          // monoatomic argon    78% by volume.
+  Air->lock();
+
+  // Define Aluminium
+  double densityOfAluminium=2.7*gram/cm3;                  // g/cm^3
+  GeoMaterial *Aluminium     = new GeoMaterial("Aluminium", densityOfAluminium);
+  Aluminium->add(aluminium,1.0);
+  Aluminium->lock();
+
+  GeoBox     *boxShape = new GeoBox(10,15,20);
+  GeoLogVol  *boxLog = new GeoLogVol("BoxLog",boxShape,Air);
+  GeoPhysVol *boxPhys = new GeoPhysVol(boxLog);
+
+
+  {
+    GeoBox    *point_box = new GeoBox(0.2, 0.2, 0.2);
+    GeoLogVol *point_log = new GeoLogVol("PointLog", point_box, Air);
+    GeoBox    *point_box2 = new GeoBox(0.05, 0.05, 0.05);
+    GeoLogVol *point_log2 = new GeoLogVol("PointLog", point_box2, Air);
+
+    GeoFullPhysVol *point_phys = new GeoFullPhysVol(point_log);
+
+    // The point initial position, definitely on the initial surface
+    // after a series of transformations, the point should still be on the surface
+    // this part is to test the GeoVSurface::isOnSurface method
+    // it should return true
+    const double point_x =  5.66; 
+    const double point_y = -5.66; 
+    const double point_z = 0.0;
+    Eigen::Vector4d point_vec(point_x, point_y, point_z, 1.0);
+    Eigen::Vector4d origin_p(0.0, 0.0, 0.0, 1.0);
+    Eigen::Vector4d trans_point_vec;
+    Eigen::Vector4d trans_origin_p0;
+    Eigen::Vector4d trans_origin_p;
+
+    GeoTransform * transform_point = new GeoTransform(GeoTrf::RotateY3D(0.4*M_PI)*GeoTrf::TranslateX3D(20)*GeoTrf::TranslateX3D(5.66)*GeoTrf::TranslateY3D(-5.66));
+
+    GeoBox     *boxShape = new GeoBox(3,3,3);
+    GeoLogVol  *boxLog = new GeoLogVol("BoxLog",boxShape,Air);
+    GeoFullPhysVol *boxPhys3 = new GeoFullPhysVol(boxLog);
+
+    GeoAnnulusSurface* annulus = new GeoAnnulusSurface(-4.0, -5.0, 7.0, 10.0, 2*M_PI); // Ox, Oy, Rin, Rout, Phi
+    GeoVSurface* surf3 = new GeoVSurface(annulus);
+    GeoAlignableTransform *move_together3=new GeoAlignableTransform(GeoTrf::RotateY3D(0.4*M_PI)*GeoTrf::TranslateX3D(20));
+    //GeoTransform * point_trans = new GeoTransform(GeoTrf::RotateY3D(0.4*M_PI)*GeoTrf::TranslateX3D(20));
+
+
+    boxPhys->add(move_together3);
+    boxPhys->add(boxPhys3);
+    boxPhys->add(move_together3);   
+    boxPhys->add(surf3);
+    // boxPhys->add(transform_point); // move the point (initially at (0,0,0)) to the starting position (5.66, -5.66, 0)
+    // boxPhys->add(point_phys);
+    move_together3->setDelta(GeoTrf::RotateY3D(0));
+    
+    GeoFullPhysVol *point_phys2;
+    GeoTransform * translate_point2;
+
+    for(int i = 0; i < 11; i++){
+      for(int j = 0; j < 11; j++){
+        //for(int k = 0; k < 3; k++){
+          double test_x =  -10.0 + i*2;
+          double test_y =  -10.0 + j*2; 
+          double test_z =  0.0;//-1.0  + k*1.0;
+          Eigen::Vector4d test_point(test_x, test_y, test_z, 1.0);
+          test_point = surf3->getX() * test_point;
+          test_x = test_point[0]; test_y = test_point[1]; test_z = test_point[2];
+
+          //GeoFullPhysVol *point_phys2 = new GeoFullPhysVol(point_log);
+          //GeoTransform * translate_point2 = new GeoTransform(GeoTrf::TranslateX3D(test_x)*GeoTrf::TranslateY3D(test_y)*GeoTrf::TranslateZ3D(test_z));
+          //boxPhys->add(translate_point2);
+          //boxPhys->add(point_phys2);
+
+          if (surf3->isOnSurface(test_x, test_y, test_z))
+          { 
+            point_phys2 = new GeoFullPhysVol(point_log); 
+            std::cout << "  the point is on the surface " << std::endl;
+          }
+          else{
+            point_phys2 = new GeoFullPhysVol(point_log2);
+            std::cout << " NOT ON THE SURFACE " << std::endl;
+          }
+          translate_point2 = new GeoTransform(GeoTrf::TranslateX3D(test_x)*GeoTrf::TranslateY3D(test_y)*GeoTrf::TranslateZ3D(test_z));
+          boxPhys->add(translate_point2);
+          boxPhys->add(point_phys2);            
+        //}
+      }
+    }
+
+  }
+  
+    // GeoTrapezoidSurface* trapezoid2 = new GeoTrapezoidSurface(9, 12, 8);
+    // GeoVSurface* surf5 = new GeoVSurface(trapezoid2);
+    // GeoAlignableTransform *move_together5=new GeoAlignableTransform(GeoTrf::TranslateZ3D(20)*GeoTrf::TranslateX3D(40));
+    
+    // boxPhys->add(move_together5);
+    // boxPhys->add(surf5);
+    // move_together5->setDelta(GeoTrf::RotateX3D(1));
+    
+  world->add(boxPhys);
+  GeoPrintGraphAction printGraphAction(std::cout);
+  world->exec(&printGraphAction);;
+
+  {
+    int i = 0;
+    
+    // std::cout << " " << std::endl;
+    // std::cout << " " << std::endl;    
+    // std::cout << " cursor at i= " << i << std::endl;
+    GeoVolumeCursor cursor(boxPhys);
+    //GeoSurfaceCursor cursor(boxPhys);
+    
+    while (!cursor.atEnd()) {
+      i += 1;
+      // std::cout << "!!! " << std::endl;
+      // std::cout << cursor.getTransform().rotation() << std::endl;
+      // std::cout << "!!! " << std::endl; 
+      // std::cout << cursor.getTransform().translation() << std::endl;
+      // std::cout << " " << std::endl;
+      cursor.next();
+    }
+  }
+
+  GeoCountSurfaceAction countSurface;
+  boxPhys->exec(&countSurface);
+  // std::cout << "Number of Virtual Surface: " << countSurface.getCount() << std::endl;
+  unsigned int totalVSurface = countSurface.getCount();
+  
+  for (unsigned int i = 0; i< totalVSurface; i++){
+    GeoAccessSurfaceAction surfaceAccess (i, nullptr);
+    boxPhys->exec(&surfaceAccess);
+    // std::cout << "surface transform rotation: " << surfaceAccess.getTransform().rotation() << std::endl;
+    // std::cout << "surface transform trans: " << surfaceAccess.getTransform().translation() << std::endl;
+  }
+   
+  //  // cannot use GeoNodePositioning::getAbsoluteTransform(). Is there an error in the method?
+  //  std::cout << "surface5 transform rot: " << surf5->getX().rotation() << std::endl;
+  //  std::cout << " " << std::endl;
+  //  //surf5->PrintRotation();
+   
+  //  GeoTrf::Vector3D vec(0.0, 0.0, 1.0);
+  //  std::cout << " ROTATE VECTOR " << surf5->getX().rotation()*vec << std::endl;
+   
+  //  std::cout << " " << std::endl;
+  //  std::cout << " " << std::endl;
+  //  //surf5->PrintTranslation();
+  //  std::cout << "surface5 transform trans: " << surf5->getX().translation() << std::endl;
+   
+  //  Eigen::Matrix4d M_4d = Eigen::Matrix4d::Identity();
+  //  M_4d.block<3,3>(0,0) = surf5->getX().rotation();
+  //  M_4d.block<3,1>(0,3) = surf5->getX().translation();
+  //  std::cout << " 4x4 matrix " << M_4d << std::endl;
+   
+  //  Eigen::Vector4d vec_4d;
+  //  vec_4d << vec, 1.0;
+  //  //Eigen::Vector4d trans_vec_4d = M_4d * vec_4d;
+  //  Eigen::Vector4d trans_vec_4d = surf5->getX() * vec_4d;
+  //  Eigen::Vector3d trans_vec = trans_vec_4d.head<3>();
+   
+  //  Eigen::Vector4d origin_vec_4d = surf5->getX().inverse() * trans_vec_4d;
+  //  Eigen::Vector3d origin_vec = origin_vec_4d.head<3>();   
+  //  std::cout << " TRANS VECTOR " << trans_vec << std::endl;
+  //  std::cout << " ORIGIN VECTOR " << origin_vec << std::endl;
+
+  //--------------------------------------//
+}
+
+// The name of this routine must correspond to the name of the class,
+// and also to the name of the source code file (this file)
+
+extern "C" SurfAnnulusDemo *createSurfAnnulusDemo() {
+  return new SurfAnnulusDemo;
+}
+
diff --git a/GeoModelExamples/SurfDiamond/CMakeLists.txt b/GeoModelExamples/SurfDiamond/CMakeLists.txt
new file mode 100644
index 000000000..4e69c99ef
--- /dev/null
+++ b/GeoModelExamples/SurfDiamond/CMakeLists.txt
@@ -0,0 +1,35 @@
+cmake_minimum_required(VERSION 3.16...3.26)
+
+# Compile with C++17
+set(CMAKE_CXX_STANDARD 17)
+set(CMAKE_CXX_STANDARD_REQUIRED ON)
+set(CMAKE_CXX_EXTENSIONS ON)
+
+
+# Find the needed dependencies, when building individually
+  message (${CMAKE_SOURCE_DIR})
+  message (${PROJECT_SOURCE_DIR})
+
+if ( CMAKE_SOURCE_DIR STREQUAL PROJECT_SOURCE_DIR ) # when buildingindividually
+   find_package( GeoModelCore REQUIRED  )
+endif()
+
+
+# Find the header and source files.
+file( GLOB SOURCES src/*.cxx )
+
+add_library( SurfDiamond SHARED ${SOURCES} )
+target_link_libraries( SurfDiamond PUBLIC GeoModelCore::GeoModelKernel GeoModelCore::GeoModelHelpers)
+
+source_group( "src" FILES ${SOURCES} )
+
+set_target_properties( SurfDiamond PROPERTIES
+   VERSION ${PROJECT_VERSION}
+   SOVERSION ${PROJECT_VERSION_MAJOR} )
+
+# Install the library.
+install( TARGETS SurfDiamond
+   EXPORT ${PROJECT_NAME}-export
+   LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}
+   COMPONENT Runtime
+   NAMELINK_SKIP )
diff --git a/GeoModelExamples/SurfDiamond/src/SurfDiamond.cxx b/GeoModelExamples/SurfDiamond/src/SurfDiamond.cxx
new file mode 100644
index 000000000..640a6f950
--- /dev/null
+++ b/GeoModelExamples/SurfDiamond/src/SurfDiamond.cxx
@@ -0,0 +1,204 @@
+/*
+  Copyright (C) 2002-2023 CERN for the benefit of the ATLAS collaboration
+*/
+
+// -------------------------------------------------------------------
+//
+// Diamond Surface Demo Plugin
+// Rui Xue, Oct 2024
+//
+//
+// This plugin is used to test and develop Diamond Surface
+// 
+//
+// --------------------------------------------------------------------
+
+#include "GeoModelKernel/GeoVGeometryPlugin.h"
+#include "GeoModelKernel/GeoDefinitions.h"
+#include "GeoModelKernel/GeoMaterial.h"
+#include "GeoModelKernel/GeoBox.h"
+#include "GeoModelKernel/GeoTube.h"
+#include "GeoModelKernel/GeoPrintGraphAction.h"
+#include "GeoModelKernel/GeoVolumeCursor.h"
+
+#include "GeoModelKernel/GeoLogVol.h"
+#include "GeoModelKernel/GeoPhysVol.h"
+#include "GeoModelKernel/GeoFullPhysVol.h"
+#include "GeoModelKernel/GeoTransform.h"
+#include "GeoModelKernel/GeoAlignableTransform.h"
+#include "GeoModelKernel/GeoShapeSubtraction.h"
+#include "GeoModelKernel/GeoShapeShift.h"
+#include "GeoModelKernel/GeoRectSurface.h"
+#include "GeoModelKernel/GeoTrapezoidSurface.h"
+#include "GeoModelKernel/GeoAnnulusSurface.h"
+#include "GeoModelKernel/GeoDiamondSurface.h"
+#include "GeoModelKernel/GeoVSurface.h"
+#include "GeoModelKernel/Units.h"
+#include "GeoModelHelpers/defineWorld.h"
+
+#include "GeoModelKernel/GeoSurfaceCursor.h"
+#include "GeoModelKernel/GeoCountSurfaceAction.h"
+#include "GeoModelKernel/GeoCountVolAction.h"
+#include "GeoModelKernel/GeoAccessSurfaceAction.h"
+#include "GeoModelKernel/GeoAccessVolumeAction.h"
+
+#include <Eigen/Dense>
+#include <Eigen/Geometry>
+#include <iostream>
+#include <cmath>
+using namespace GeoModelKernelUnits;
+
+// Class Declaration
+
+class SurfDiamond : public GeoVGeometryPlugin  {
+
+ public:
+
+  // Constructor:
+  SurfDiamond();
+
+  // Destructor:
+  ~SurfDiamond();
+
+  // Creation of geometry:
+  virtual void create(GeoVPhysVol *world, bool publish=false);
+
+ private:
+
+  // Illegal operations:
+  const SurfDiamond & operator=(const SurfDiamond &right)=delete;
+  SurfDiamond(const SurfDiamond &right) = delete;
+
+};
+
+
+// Class definition:
+
+// Constructor
+SurfDiamond::SurfDiamond()
+{
+}
+
+// Destructor
+SurfDiamond::~SurfDiamond()
+{
+}
+
+// The create algorithm creates a tree of physical volumes rooted under the
+// "world" physical volume. The optional flag publish is not used in this
+// example (normally one may "publish" a list of FullPhysVol's and Alignable
+// transforms, but this example has none such).
+//
+void SurfDiamond::create(GeoVPhysVol *world, bool /*publish*/) {
+  // Define elements used in this example:
+  GeoElement  *oxygen        = new GeoElement("Oxygen",    "O",   19,  39*gram/mole);
+  GeoElement  *nitrogen      = new GeoElement("Nitrogen",  "N",   7,  14*gram/mole);
+  GeoElement  *argon         = new GeoElement("Argon",     "Ar", 18,  40*gram/mole);
+  GeoElement  *aluminium     = new GeoElement("Aluminium", "Al", 13,  26*gram/mole);
+
+  // Define materials:
+  
+  // Define Air:
+  double densityOfAir     = 1.2E-3*gram/cm3;               // g/cm^3
+  GeoMaterial *Air           = new GeoMaterial("Air",densityOfAir);
+  Air->add(oxygen,2*0.21);                        // diatomic   oxygen   21% by volume.
+  Air->add(nitrogen,2*0.78);                        // diatomic   nitrogen 78% by volume.
+  Air->add(argon,0.01);                          // monoatomic argon    78% by volume.
+  Air->lock();
+
+  // Define Aluminium
+  double densityOfAluminium=2.7*gram/cm3;                  // g/cm^3
+  GeoMaterial *Aluminium     = new GeoMaterial("Aluminium", densityOfAluminium);
+  Aluminium->add(aluminium,1.0);
+  Aluminium->lock();
+
+  GeoBox     *boxShape = new GeoBox(10,15,20);
+  GeoLogVol  *boxLog = new GeoLogVol("BoxLog",boxShape,Air);
+  GeoPhysVol *boxPhys = new GeoPhysVol(boxLog);
+
+
+  {
+    GeoBox    *point_box = new GeoBox(0.2, 0.2, 0.2);
+    GeoLogVol *point_log = new GeoLogVol("PointLog", point_box, Air);
+    GeoBox    *point_box2 = new GeoBox(0.05, 0.05, 0.05);
+    GeoLogVol *point_log2 = new GeoLogVol("PointLog", point_box2, Air);
+
+    GeoFullPhysVol *point_phys = new GeoFullPhysVol(point_log);
+
+    // The point initial position, definitely on the initial surface
+    // after a series of transformations, the point should still be on the surface
+    // this part is to test the GeoVSurface::isOnSurface method
+    // it should return true
+    const double point_x =  5.66; 
+    const double point_y = -5.66; 
+    const double point_z = 0.0;
+    Eigen::Vector4d point_vec(point_x, point_y, point_z, 1.0);
+    Eigen::Vector4d origin_p(0.0, 0.0, 0.0, 1.0);
+    Eigen::Vector4d trans_point_vec;
+    Eigen::Vector4d trans_origin_p0;
+    Eigen::Vector4d trans_origin_p;
+
+    GeoTransform * transform_point = new GeoTransform(GeoTrf::RotateY3D(0.4*M_PI)*GeoTrf::TranslateX3D(20)*GeoTrf::TranslateX3D(5.66)*GeoTrf::TranslateY3D(-5.66));
+
+    GeoBox     *boxShape = new GeoBox(3,3,3);
+    GeoLogVol  *boxLog = new GeoLogVol("BoxLog",boxShape,Air);
+    GeoFullPhysVol *boxPhys3 = new GeoFullPhysVol(boxLog);
+
+    // GeoAnnulusSurface* annulus = new GeoAnnulusSurface(-4.0, -5.0, 7.0, 10.0, 2*M_PI); // Ox, Oy, Rin, Rout, Phi
+    // GeoVSurface* surf3 = new GeoVSurface(annulus);
+    GeoDiamondSurface* diamond = new GeoDiamondSurface(4, 9.5, 7, 5.5, 6);
+    GeoVSurface* surf3 = new GeoVSurface(diamond);
+    // GeoRectSurface* rect = new GeoRectSurface(5, 9);
+    // GeoVSurface* surf3 = new GeoVSurface(rect);
+    // GeoTrapezoidSurface* trapezoid = new GeoTrapezoidSurface(9, 7, 5);
+    // GeoVSurface* surf3 = new GeoVSurface(trapezoid);
+
+    GeoAlignableTransform *move_together3=new GeoAlignableTransform(GeoTrf::RotateY3D(0.4*M_PI)*GeoTrf::TranslateX3D(20));
+    //GeoTransform * point_trans = new GeoTransform(GeoTrf::RotateY3D(0.4*M_PI)*GeoTrf::TranslateX3D(20));
+    boxPhys->add(move_together3);   
+    boxPhys->add(surf3);
+    // boxPhys->add(transform_point); // move the point (initially at (0,0,0)) to the starting position (5.66, -5.66, 0)
+    // boxPhys->add(point_phys);
+    move_together3->setDelta(GeoTrf::RotateY3D(0));
+    
+    GeoFullPhysVol *point_phys2;
+    GeoTransform * translate_point2;
+
+    for(int i = 0; i < 11; i++){
+      for(int j = 0; j < 11; j++){
+        //for(int k = 0; k < 3; k++){
+          double test_x =  -10.0 + i*2;
+          double test_y =  -10.0 + j*2; 
+          double test_z =  0.0;//-1.0  + k*1.0;
+          Eigen::Vector4d test_point(test_x, test_y, test_z, 1.0);
+          test_point = surf3->getX() * test_point;
+          test_x = test_point[0]; test_y = test_point[1]; test_z = test_point[2];
+
+          if (surf3->isOnSurface(test_x, test_y, test_z))
+          { 
+            point_phys2 = new GeoFullPhysVol(point_log); 
+            // std::cout << "  the point is on the surface " << std::endl;
+          }
+          else{
+            point_phys2 = new GeoFullPhysVol(point_log2);
+            // std::cout << " NOT ON THE SURFACE " << std::endl;
+          }
+          translate_point2 = new GeoTransform(GeoTrf::TranslateX3D(test_x)*GeoTrf::TranslateY3D(test_y)*GeoTrf::TranslateZ3D(test_z));
+          boxPhys->add(translate_point2);
+          boxPhys->add(point_phys2);            
+        //}
+      }
+    }
+
+  }
+    
+  world->add(boxPhys);
+}
+
+// The name of this routine must correspond to the name of the class,
+// and also to the name of the source code file (this file)
+
+extern "C" SurfDiamond *createSurfDiamond() {
+  return new SurfDiamond;
+}
+
diff --git a/GeoModelExamples/SurfaceTestPlugin/src/SurfaceTestPlugin.cxx b/GeoModelExamples/SurfaceTestPlugin/src/SurfaceTestPlugin.cxx
index 9dd5e22f9..34b589523 100644
--- a/GeoModelExamples/SurfaceTestPlugin/src/SurfaceTestPlugin.cxx
+++ b/GeoModelExamples/SurfaceTestPlugin/src/SurfaceTestPlugin.cxx
@@ -31,10 +31,15 @@
 #include "GeoModelKernel/GeoShapeSubtraction.h"
 #include "GeoModelKernel/GeoShapeShift.h"
 #include "GeoModelKernel/GeoRectSurface.h"
+#include "GeoModelKernel/GeoVSurface.h"
 #include "GeoModelKernel/Units.h"
 #include "GeoModelHelpers/defineWorld.h"
 
 #include "GeoModelKernel/GeoSurfaceCursor.h"
+#include "GeoModelKernel/GeoCountSurfaceAction.h"
+#include "GeoModelKernel/GeoCountVolAction.h"
+#include "GeoModelKernel/GeoAccessSurfaceAction.h"
+#include "GeoModelKernel/GeoAccessVolumeAction.h"
 using namespace GeoModelKernelUnits;
 
 // Class Declaration
@@ -105,30 +110,76 @@ void SurfaceTestPlugin::create(GeoVPhysVol *world, bool /*publish*/) {
   GeoLogVol  *boxLog = new GeoLogVol("BoxLog",boxShape,Air);
   GeoPhysVol *boxPhys = new GeoPhysVol(boxLog);
 
+
+  {
+/*
 // define a virtual surface
-  GeoRectSurface *rectSurface = new GeoRectSurface(5, 7.5);
-  GeoAlignableTransform *surf_rot=new GeoAlignableTransform(GeoTrf::TranslateZ3D(12));  
+  GeoRectSurface *rectSurface = new GeoRectSurface(5, 5);
+  GeoAlignableTransform *surf_rot=new GeoAlignableTransform(GeoTrf::TranslateY3D(18));  
   boxPhys->add(surf_rot);
   boxPhys->add(rectSurface);
-  surf_rot->setDelta(GeoTrf::RotateX3D(0.1)*GeoTrf::RotateY3D(0.15));
+  surf_rot->setDelta(GeoTrf::RotateX3D(1.2));
+  */
 //
-  {
     GeoBox     *boxShape = new GeoBox(5,5,5);
     GeoLogVol  *boxLog = new GeoLogVol("BoxLog",boxShape,Air);
     GeoPhysVol *boxPhys2 = new GeoPhysVol(boxLog);
+
+    GeoAlignableTransform *xf_initial=new GeoAlignableTransform(GeoTrf::TranslateZ3D(3));
+    boxPhys->add(xf_initial);
     boxPhys->add(boxPhys2);
+    xf_initial->setDelta(GeoTrf::RotateX3D(1.2));
 
-    GeoAlignableTransform *xf=new GeoAlignableTransform(GeoTrf::TranslateZ3D(12));
-    GeoPhysVol *boxPhys3 = new GeoPhysVol(boxLog);
+// define a virtual surface
+  GeoRectSurface* rectSurface = new GeoRectSurface(5, 5);
+/*  GeoVSurface* surf = new GeoVSurface(rectSurface);
+  GeoAlignableTransform *surf_rot=new GeoAlignableTransform(GeoTrf::TranslateY3D(10));  
+  boxPhys->add(surf_rot);
+  boxPhys->add(surf);
+  surf_rot->setDelta(GeoTrf::RotateY3D(1.2));*/
 
-    boxPhys->add(xf);
-    boxPhys->add(boxPhys3);
 
+// define a virtual surface2
+  GeoRectSurface *rectSurface2 = new GeoRectSurface(5, 7.5);
+/*  GeoVSurface* surf2 = new GeoVSurface(rectSurface2);
+  GeoAlignableTransform *surf_rot2=new GeoAlignableTransform(GeoTrf::TranslateX3D(-20));  
+  boxPhys->add(surf_rot2);
+  boxPhys->add(surf2);
+  surf_rot2->setDelta(GeoTrf::RotateY3D(0.8));*/
+//
+
+    GeoAlignableTransform *xf=new GeoAlignableTransform(GeoTrf::TranslateZ3D(18));
+    GeoPhysVol *boxPhys3 = new GeoPhysVol(boxLog);
+    GeoPhysVol *boxPhys4 = new GeoPhysVol(boxLog);
+    
+    boxPhys3->add(xf);
+    boxPhys3->add(boxPhys4);
+    
+  GeoRectSurface *rectSurface2_2 = new GeoRectSurface(7.5, 7.5);
+/*  GeoVSurface* surf2_2 = new GeoVSurface(rectSurface2_2);
+  GeoAlignableTransform *surf_rot2_2 = new GeoAlignableTransform(GeoTrf::TranslateX3D(-10));  
+  boxPhys3->add(surf_rot2_2);
+  boxPhys3->add(surf2_2);
+  surf_rot2_2->setDelta(GeoTrf::RotateY3D(1.0));*/    
+   
+   boxPhys->add(xf);
+    boxPhys->add(boxPhys3);
     xf->setDelta(GeoTrf::RotateX3D(0.1)*GeoTrf::RotateY3D(0.15));
+
+// define a virtual surface3
+  GeoRectSurface *rectSurface3 = new GeoRectSurface(10, 12);
+/*  GeoVSurface* surf3 = new GeoVSurface(rectSurface3);
+  GeoAlignableTransform *surf_rot3=new GeoAlignableTransform(GeoTrf::TranslateX3D(10)*GeoTrf::TranslateY3D(15)*GeoTrf::TranslateZ3D(20));  
+  boxPhys->add(surf_rot3);
+  boxPhys->add(surf3);
+  surf_rot3->setDelta(GeoTrf::RotateZ3D(0.9));*/
+//    
+
   }
-  
+  GeoLogVol  *boxLog5 = new GeoLogVol("BoxLog5",boxShape,Air);
+  GeoPhysVol *boxPhys5 = new GeoPhysVol(boxLog5);
   world->add(boxPhys);
-
+  //world->add(boxPhys5);
   GeoPrintGraphAction printGraphAction(std::cout);
   world->exec(&printGraphAction);;
 
@@ -138,25 +189,44 @@ void SurfaceTestPlugin::create(GeoVPhysVol *world, bool /*publish*/) {
     std::cout << " " << std::endl;
     std::cout << " " << std::endl;    
     std::cout << " cursor at i= " << i << std::endl;
-    //GeoVolumeCursor cursor(boxPhys);
-    GeoSurfaceCursor cursor(boxPhys);
+    GeoVolumeCursor cursor(boxPhys);
+    //GeoSurfaceCursor cursor(boxPhys);
     
     while (!cursor.atEnd()) {
       i += 1;
-      //std::cout << "!!! " << cursor.getVolume()->getLogVol() << std::endl;
-      std::cout << "!!! " << cursor.getTransform().rotation() << std::endl;
-      std::cout << "!!! " << cursor.getTransform().translation() << std::endl;
-      std::cout << " " << std::endl;
+      std::cout << "!!! " << std::endl;
+      std::cout << cursor.getTransform().rotation() << std::endl;
+      std::cout << "!!! " << std::endl; 
+      std::cout << cursor.getTransform().translation() << std::endl;
       std::cout << " " << std::endl;
-      std::cout << " cursor at i= " << i << std::endl;
       cursor.next();
-      //std::cout << " FINISHED NEXT " << std::endl;
-      std::cout << " " << std::endl;
     }
   }
 
+/*  
+  GeoCountVolAction countVol;
+  boxPhys->exec(&countVol);
+  std::cout << "Number of Physical Volume: " << countVol.getCount() << std::endl;  
+
+  unsigned int index = 2;
+  GeoAccessVolumeAction volumeAccess (index, nullptr);
+  boxPhys->exec(&volumeAccess);
+  std::cout << "volume transform rotation: " << volumeAccess.getTransform().rotation() << std::endl;
+  std::cout << "volume transform trans: " << volumeAccess.getTransform().translation() << std::endl;
+*/ 
+
+  GeoCountSurfaceAction countSurface;
+  boxPhys->exec(&countSurface);
+  std::cout << "Number of Virtual Surface: " << countSurface.getCount() << std::endl;
+  unsigned int totalVSurface = countSurface.getCount();
   
-  
+  for (unsigned int i = 0; i< totalVSurface; i++){
+    GeoAccessSurfaceAction surfaceAccess (i, nullptr);
+    boxPhys->exec(&surfaceAccess);
+    std::cout << "surface transform rotation: " << surfaceAccess.getTransform().rotation() << std::endl;
+    std::cout << "surface transform trans: " << surfaceAccess.getTransform().translation() << std::endl;
+  }
+ 
   //--------------------------------------//
 }
 
diff --git a/GeoModelIO/GeoModelDBManager/src/GMDBManager.cpp b/GeoModelIO/GeoModelDBManager/src/GMDBManager.cpp
index 0fe998d67..70d3382bc 100644
--- a/GeoModelIO/GeoModelDBManager/src/GMDBManager.cpp
+++ b/GeoModelIO/GeoModelDBManager/src/GMDBManager.cpp
@@ -18,6 +18,9 @@
  *              New DB format to extend the storage of numbers as REAL instead of TEXT,
  *              New methods to handle vector<variants> as input of records,
  *              Set precision to all conversions Double --> String
+ * - Jul 2024 - Rui Xue, <r.xue@cern.ch><rux23@pitt.edu>,
+ *              Added support for virtual surfaces, including:
+ *              GeoRectSurface, GeoTrapezoidSurface, GeoAnnulusSurface, GeoDiamondSurface
  */
 
 #include <GeoModelDBManager/GMDBManager.h>
@@ -745,7 +748,6 @@ bool GMDBManager::addListOfRecords(
     const DBRowsList& records) {
     //  if (m_debug) qDebug() << "GMDBManager::addListOfRecords():" <<
     //  geoType;
-
     std::string tableName = m_childType_tableName[geoType];
 
     if (tableName.size() == 0) {
@@ -755,7 +757,7 @@ bool GMDBManager::addListOfRecords(
     if (records.size() > 0) {
         return addListOfRecordsToTable(
             tableName, records);  // needs SQLite >= 3.7.11
-    } else {
+    } else {  
         if (m_debug)
             std::cout << "Info: no records to save for geoType '" << geoType
                       << "'. Skipping..." << std::endl;
@@ -2341,7 +2343,113 @@ bool GMDBManager::createTables() {
         storeNodeType(geoNode, tableName);
     }
     tab.clear();
+//----------------------------------------------------------------------------
+    // VSurface table
+    // ID = 33 in GeoNodesTypes, so that .db files introduced before Virtual Surface won't crush
+    geoNode = "GeoVSurface";
+    tableName = "VirtualSurface";
+    m_childType_tableName[geoNode] = tableName;
+    tab.push_back(tableName);
+    tab.push_back("id");
+    tab.push_back("shapeType");
+    tab.push_back("shapeId");
+    storeTableColumnNames(tab);
+    queryStr = fmt::format(
+        "create table {0}({1} integer primary key, {2} varchar not null, {3} integer not null)",
+        tab[0], tab[1], tab[2], tab[3]);
+    if (0 == (rc = execQuery(queryStr))) {
+        storeNodeType(geoNode, tableName);
+    }
+    tab.clear();
+
+    // Surface-Rectangle table
+    // ID = 34 in GeoNodesTypes
+    // ID, XHalfLength, YHalfLength
+    geoNode = "RectangleSurface";
+    tableName = "Surface_Rectangle";
+    m_childType_tableName[geoNode] = tableName;
+    tab.push_back(tableName);
+    tab.push_back("id");
+    tab.push_back("computedArea");
+    tab.push_back("XHalfLength");
+    tab.push_back("YHalfLength");
+    storeTableColumnNames(tab);
+    queryStr = fmt::format(
+        "create table {0}({1} integer primary key, {2} real, {3} real, {4} real)",
+        tab[0], tab[1], tab[2], tab[3], tab[4]);
+    if (0 == (rc = execQuery(queryStr))) {
+        storeNodeType(geoNode, tableName);
+    }
+    tab.clear();
+    
+    // Surface-Trapezoid table
+    // ID = 35 in GeoNodesTypes
+    // ID, XHalfLengthMin, XHalfLengthMax, YHalfLength
+    geoNode = "TrapezoidSurface";
+    tableName = "Surface_Trapezoid";
+    m_childType_tableName[geoNode] = tableName;
+    tab.push_back(tableName);
+    tab.push_back("id");
+    tab.push_back("computedArea");
+    tab.push_back("XHalfLengthMin");
+    tab.push_back("XHalfLengthMax");
+    tab.push_back("YHalfLength");
+    storeTableColumnNames(tab);
+    queryStr = fmt::format(
+        "create table {0}({1} integer primary key, {2} real, {3} real, {4} real, {5} real)",
+        tab[0], tab[1], tab[2], tab[3], tab[4], tab[5]);
+    if (0 == (rc = execQuery(queryStr))) {
+        storeNodeType(geoNode, tableName);
+    }
+    tab.clear();
+
+    // Surface-Annulus table
+    // ID = 36 in GeoNodesTypes
+    // ID, Ox, Oy, radius_in, radius_out, phi
+    geoNode = "AnnulusSurface";
+    tableName = "Surface_Annulus";
+    m_childType_tableName[geoNode] = tableName;
+    tab.push_back(tableName);
+    tab.push_back("id");
+    tab.push_back("computedArea");
+    tab.push_back("Ox");
+    tab.push_back("Oy");
+    tab.push_back("radius_in");
+    tab.push_back("radius_out");
+    tab.push_back("phi");
+    storeTableColumnNames(tab);
+    queryStr = fmt::format(
+        "create table {0}({1} integer primary key, {2} real, {3} real, {4} real, {5} real, {6} real, {7} real)",
+        tab[0], tab[1], tab[2], tab[3], tab[4], tab[5], tab[6], tab[7]);
+    if (0 == (rc = execQuery(queryStr))) {
+        storeNodeType(geoNode, tableName);
+    }
+    tab.clear();
+
+    // Surface-Diamond table
+    // ID = 37 in GeoNodesTypes
+    // ID, X_bottom_half, X_mid_half, X_top_half, Y_bottom_half, Y_top_half
+    geoNode = "DiamondSurface";
+    tableName = "Surface_Diamond";
+    m_childType_tableName[geoNode] = tableName;
+    tab.push_back(tableName);
+    tab.push_back("id");
+    tab.push_back("computedArea");
+    tab.push_back("X_bottom_half");
+    tab.push_back("X_mid_half");
+    tab.push_back("X_top_half");
+    tab.push_back("Y_bottom_half");
+    tab.push_back("Y_top_half");
+    storeTableColumnNames(tab);
+    queryStr = fmt::format(
+        "create table {0}({1} integer primary key, {2} real, {3} real, {4} real, {5} real, {6} real, {7} real)",
+        tab[0], tab[1], tab[2], tab[3], tab[4], tab[5], tab[6], tab[7]);
+    if (0 == (rc = execQuery(queryStr))) {
+        storeNodeType(geoNode, tableName);
+    }
+    tab.clear();     
 
+//----------------------------------------------------------------------------
     if (m_debug) {
         std::cout << "All these tables have been successfully created:"
                   << std::endl;  // debug
diff --git a/GeoModelIO/GeoModelRead/GeoModelRead/ReadGeoModel.h b/GeoModelIO/GeoModelRead/GeoModelRead/ReadGeoModel.h
index 39aaf8051..1651106ab 100644
--- a/GeoModelIO/GeoModelRead/GeoModelRead/ReadGeoModel.h
+++ b/GeoModelIO/GeoModelRead/GeoModelRead/ReadGeoModel.h
@@ -26,6 +26,10 @@
  *   Added method to get records out of custom tables from client code.
  * - Feb 2023, R.M.Bianchi <riccardo.maria.bianchi@cern.ch>
  *             Added 'setLoglevel' method, to steer output messages
+ *
+ * - Jun 2024, R.Xue  <r.xue@cern.ch><rux23@pitt.edu>
+ *             Added methods to read in virtual surfaces from .db files
+ *
  */
 
 #ifndef GeoModelRead_ReadGeoModel_H_
@@ -53,6 +57,12 @@
 class GeoVPhysVol;
 class GeoPhysVol;
 class GeoFullPhysVol;
+class GeoRectSurface;
+class GeoTrapezoidSurface;
+class GeoAnnulusSurface;
+class GeoDiamondSurface;
+class GeoVSurface;
+class GeoVSurfaceShape;
 class GeoLogVol;
 class GeoShape;
 class GeoMaterial;
@@ -82,7 +92,7 @@ class BuildGeoShapes_Pgon;
 class BuildGeoShapes_SimplePolygonBrep;
 class BuildGeoShapes_GenericTrap;
 class BuildGeoShapes_UnidentifiedShape;
-
+class BuildGeoVSurface;
 // type definitions
 typedef const GeoXF::Function& TRANSFUNCTION;
 // containers for boolean shapes' information
@@ -210,6 +220,10 @@ class ReadGeoModel {
     void buildAllSerialTransformers();
     void buildAllNameTags();
 
+    void buildAllVSurfaces();
+    void buildVSurface(const unsigned int id);
+    GeoVSurfaceShape* BuildWhichSurface(std::string_view shapeType, const unsigned int shapeId);
+
     GeoVPhysVol* buildGeoModelPrivate();
 
     GeoBox* buildDummyShape();
@@ -275,6 +289,11 @@ class ReadGeoModel {
     // caching methods
     // TODO: perhaps we could merge all those 'isBuiltYYY' methods in a single
     // one, with the GeoModel class as a second argument ? (RMB)
+    bool isBuiltVSurface(const unsigned int shapeId);
+    bool isBuiltRectSurface(const unsigned int shapeId);
+    bool isBuiltTrapezoidSurface(const unsigned int shapeId);
+    bool isBuiltAnnulusSurface(const unsigned int shapeId);
+    bool isBuiltDiamondSurface(const unsigned int shapeId);
     bool isBuiltShape(const unsigned id);
     bool isBuiltShape_Operators_Shift(const unsigned id);
     bool isBuiltShape_Operators_Subtraction(const unsigned id);
@@ -289,7 +308,12 @@ class ReadGeoModel {
     void storeBuiltShapeOperators_Subtraction(const unsigned, GeoShape* node);
     void storeBuiltShapeOperators_Union(const unsigned, GeoShape* node);
     void storeBuiltShapeOperators_Intersection(const unsigned, GeoShape* node);
-
+    void storeBuiltRectSurface(GeoRectSurface* nodePtr);
+    void storeBuiltTrapezoidSurface(GeoTrapezoidSurface* nodePtr);
+    void storeBuiltDiamondSurface(GeoDiamondSurface* nodePtr);
+    void storeBuiltAnnulusSurface(GeoAnnulusSurface* nodePtr);
+    void storeBuiltVSurface(GeoVSurface* nodePtr);
+    
     bool isBuiltTransform(const unsigned id);
     void storeBuiltTransform(GeoTransform* node);
     GeoTransform* getBuiltTransform(const unsigned id);
@@ -379,6 +403,7 @@ class ReadGeoModel {
 
     //! builders
     // std::unique_ptr<BuildGeoShapes_Box> m_builderShape_Box;
+    BuildGeoVSurface*   buildsurfTool{};
     BuildGeoShapes_Box* m_builderShape_Box{};
     BuildGeoShapes_Tube* m_builderShape_Tube{};
     BuildGeoShapes_Cons* m_builderShape_Cons{};
@@ -414,6 +439,13 @@ class ReadGeoModel {
     DBRowsList m_logVols;
     DBRowsList m_allchildren;
 
+    // containers to store virtual surfaces
+    DBRowsList m_rectangle_surface;  // For Virtual Surface Shape
+    DBRowsList m_trapezoid_surface;
+    DBRowsList m_annulus_surface;
+    DBRowsList m_diamond_surface;
+    DBRowsList m_VSurface;           // For Virtual Surface Abstract Class
+
     // containers to store shapes' parameters
     DBRowsList m_shapes_Box;
     DBRowsList m_shapes_Tube;
@@ -471,6 +503,11 @@ class ReadGeoModel {
     std::vector<GeoLogVol*> m_memMapLogVols;
     std::vector<GeoMaterial*> m_memMapMaterials;
     std::vector<GeoElement*> m_memMapElements;
+    std::vector<GeoRectSurface*> m_memMapRectSurface;
+    std::vector<GeoTrapezoidSurface*> m_memMapTrapezoidSurface;
+    std::vector<GeoAnnulusSurface*> m_memMapAnnulusSurface;
+    std::vector<GeoDiamondSurface*> m_memMapDiamondSurface;
+    std::vector<GeoVSurface*> m_memMapVSurface;
     //  std::vector<GeoXF::Function*> m_memMapFunctions; // FIXME:
     
     // we need keys, because shapes are not built following the ID order
diff --git a/GeoModelIO/GeoModelRead/src/BuildGeoVSurface.cpp b/GeoModelIO/GeoModelRead/src/BuildGeoVSurface.cpp
new file mode 100644
index 000000000..39f273288
--- /dev/null
+++ b/GeoModelIO/GeoModelRead/src/BuildGeoVSurface.cpp
@@ -0,0 +1,71 @@
+/*
+  Copyright (C) 2002-2024 CERN for the benefit of the ATLAS collaboration
+*/
+
+/*
+ * BuildGeoVSurfaces.h
+ *
+ * Created on: June, 2024
+ * Author: Rui XUE <r.xue@cern.ch><rux23@pitt.edu>
+ *
+ */
+#include "BuildGeoVSurface.h"
+
+GeoRectSurface* BuildGeoVSurface::buildRectSurface(const DBRowEntry row)
+{
+    // shape area
+    const double surfArea = GeoModelHelpers::variantHelper::getFromVariant_Double(row[1], "SurfaceRect_Area");
+    // shape parameters
+    const double XHalfLength = GeoModelHelpers::variantHelper::getFromVariant_Double(row[2], "SurfaceRect_XHalfLength");
+    const double YHalfLength = GeoModelHelpers::variantHelper::getFromVariant_Double(row[3], "SurfaceRect_YHalfLength");
+
+    GeoRectSurface *rectsurface = new GeoRectSurface(XHalfLength, YHalfLength);
+    
+    return rectsurface;
+}
+
+GeoTrapezoidSurface* BuildGeoVSurface::buildTrapezoidSurface(const DBRowEntry row)
+{
+    // shape area
+    const double surfArea = GeoModelHelpers::variantHelper::getFromVariant_Double(row[1], "SurfaceTrapezoid_Area");
+    // shape parameters
+    const double XHalfLengthMin = GeoModelHelpers::variantHelper::getFromVariant_Double(row[2], "SurfaceTrapezoid_XHalfLengthMin");
+    const double XHalfLengthMax = GeoModelHelpers::variantHelper::getFromVariant_Double(row[3], "SurfaceTrapezoid_XHalfLengthMax");    
+    const double YHalfLength = GeoModelHelpers::variantHelper::getFromVariant_Double(row[4], "SurfaceTrapezoid_YHalfLength");
+
+    GeoTrapezoidSurface *trapezoid = new GeoTrapezoidSurface(XHalfLengthMin, XHalfLengthMax, YHalfLength);
+    
+    return trapezoid;
+}
+
+GeoAnnulusSurface* BuildGeoVSurface::buildAnnulusSurface(const DBRowEntry row)
+{
+    // shape area
+    const double surfArea = GeoModelHelpers::variantHelper::getFromVariant_Double(row[1], "SurfaceAnnulus_Area");
+    // shape parameters
+    const double Ox = GeoModelHelpers::variantHelper::getFromVariant_Double(row[2], "SurfaceAnnulus_Ox");
+    const double Oy = GeoModelHelpers::variantHelper::getFromVariant_Double(row[3], "SurfaceAnnulus_Oy");
+    const double radius_in = GeoModelHelpers::variantHelper::getFromVariant_Double(row[4], "SurfaceAnnulus_RadiusIn");
+    const double radius_out = GeoModelHelpers::variantHelper::getFromVariant_Double(row[5], "SurfaceAnnulus_RadiusOut");
+    const double phi = GeoModelHelpers::variantHelper::getFromVariant_Double(row[6], "SurfaceAnnulus_Phi");
+
+    GeoAnnulusSurface *annulus = new GeoAnnulusSurface(Ox, Oy, radius_in, radius_out, phi);
+    
+    return annulus;
+}
+
+GeoDiamondSurface* BuildGeoVSurface::buildDiamondSurface(const DBRowEntry row)
+{
+    // shape area
+    const double surfArea = GeoModelHelpers::variantHelper::getFromVariant_Double(row[1], "SurfaceDiamond_Area");
+    // shape parameters
+    const double X_bottom_half = GeoModelHelpers::variantHelper::getFromVariant_Double(row[2], "SurfaceDiamond_XBottomHalf");
+    const double X_mid_half = GeoModelHelpers::variantHelper::getFromVariant_Double(row[3], "SurfaceDiamond_XMidHalf");
+    const double X_top_half = GeoModelHelpers::variantHelper::getFromVariant_Double(row[4], "SurfaceDiamond_XTopHalf");
+    const double Y_bottom_half = GeoModelHelpers::variantHelper::getFromVariant_Double(row[5], "SurfaceDiamond_YBottomHalf");
+    const double Y_top_half = GeoModelHelpers::variantHelper::getFromVariant_Double(row[6], "SurfaceDiamond_YTopHalf");
+
+    GeoDiamondSurface *diamond = new GeoDiamondSurface(X_bottom_half, X_mid_half, X_top_half, Y_bottom_half, Y_top_half);
+    
+    return diamond;
+}
\ No newline at end of file
diff --git a/GeoModelIO/GeoModelRead/src/BuildGeoVSurface.h b/GeoModelIO/GeoModelRead/src/BuildGeoVSurface.h
new file mode 100644
index 000000000..8bd5e751d
--- /dev/null
+++ b/GeoModelIO/GeoModelRead/src/BuildGeoVSurface.h
@@ -0,0 +1,41 @@
+/*
+  Copyright (C) 2002-2024 CERN for the benefit of the ATLAS collaboration
+*/
+
+/*
+ * BuildGeoVSurfaces.h
+ *
+ * Created on: June, 2024
+ * Author: Rui XUE <r.xue@cern.ch><rux23@pitt.edu>
+ *
+ */
+
+#ifndef GEOMODELREAD_BUILDGEOVSURFACE_H
+#define GEOMODELREAD_BUILDGEOVSURFACE_H
+
+#include "GeoModelDBManager/definitions.h"
+#include "GeoModelHelpers/variantHelpers.h"
+
+#include "GeoModelKernel/GeoRectSurface.h"
+#include "GeoModelKernel/GeoTrapezoidSurface.h"
+#include "GeoModelKernel/GeoAnnulusSurface.h"
+#include "GeoModelKernel/GeoDiamondSurface.h"
+
+#include <iostream>
+#include <vector>
+#include <variant>
+#include <string>
+
+class BuildGeoVSurface
+{
+public:
+
+  BuildGeoVSurface() = default;
+  GeoRectSurface* buildRectSurface(const DBRowEntry row);
+  GeoTrapezoidSurface* buildTrapezoidSurface(const DBRowEntry row);
+  GeoAnnulusSurface* buildAnnulusSurface(const DBRowEntry row);
+  GeoDiamondSurface* buildDiamondSurface(const DBRowEntry row);
+  // left for other surfaces
+};
+
+#endif
diff --git a/GeoModelIO/GeoModelRead/src/ReadGeoModel.cpp b/GeoModelIO/GeoModelRead/src/ReadGeoModel.cpp
index c380fa008..60044fa1d 100644
--- a/GeoModelIO/GeoModelRead/src/ReadGeoModel.cpp
+++ b/GeoModelIO/GeoModelRead/src/ReadGeoModel.cpp
@@ -25,6 +25,10 @@
  *              https://gitlab.cern.ch/GeoModelDev/GeoModel/-/issues/39
  *  - May 2024, R.M.Bianchi <riccardo.maria.bianchi@cern.ch>
  *              Major re-write: moved to the new DB schema based on numeric data
+ *
+ *  - Jun 2024, R.Xue  <r.xue@cern.ch><rux23@pitt.edu>
+ *              Added methods to read in virtual surfaces from .db files
+ *
  */
 
 // local includes
@@ -43,6 +47,8 @@
 #include "BuildGeoShapes_GenericTrap.h"
 #include "BuildGeoShapes_UnidentifiedShape.h"
 
+#include "BuildGeoVSurface.h"
+
 #include "GeoModelRead/ReadGeoModel.h"
 
 // TFPersistification includes
@@ -64,6 +70,12 @@
 #include "GeoModelKernel/GeoTransform.h"
 #include "GeoModelKernel/GeoUtilFunctions.h"
 #include "GeoModelKernel/GeoVPhysVol.h"
+#include "GeoModelKernel/GeoVSurface.h"
+#include "GeoModelKernel/GeoVSurfaceShape.h"
+#include "GeoModelKernel/GeoRectSurface.h"
+#include "GeoModelKernel/GeoTrapezoidSurface.h"
+#include "GeoModelKernel/GeoAnnulusSurface.h"
+#include "GeoModelKernel/GeoDiamondSurface.h"
 
 // GeoModel shapes
 #include "GeoModelKernel/GeoBox.h"
@@ -341,6 +353,12 @@ void ReadGeoModel::loadDB() {
     // m_funcExprData = m_dbManager->getTableFromTableNameVecVecData("FuncExprData");
     m_funcExprData = m_dbManager->getTableFromTableName_DequeDouble("FuncExprData");
     
+    // get virtual surface shape and class from DB
+    m_rectangle_surface = m_dbManager->getTableFromNodeType_VecVecData("RectangleSurface");
+    m_trapezoid_surface = m_dbManager->getTableFromNodeType_VecVecData("TrapezoidSurface");
+    m_annulus_surface = m_dbManager->getTableFromNodeType_VecVecData("AnnulusSurface");
+    m_diamond_surface = m_dbManager->getTableFromNodeType_VecVecData("DiamondSurface");
+    m_VSurface = m_dbManager->getTableFromNodeType_VecVecData("GeoVSurface");
 
     // get the children table from DB
     m_allchildren = m_dbManager->getChildrenTable();
@@ -432,9 +450,11 @@ GeoVPhysVol* ReadGeoModel::buildGeoModelPrivate() {
         // needs LogVols
         std::thread t5(&ReadGeoModel::buildAllPhysVols, this);
         std::thread t6(&ReadGeoModel::buildAllFullPhysVols, this);
-
+        std::thread t29(&ReadGeoModel::buildAllVSurfaces, this);
+        
         t5.join();  // ok, all PhysVols have been built
         t6.join();  // ok, all FullPhysVols have been built
+        t29.join();        
         //  t7.join(); // ok, all Functions have been built
         // needs Functions, PhysVols, FullPhysVols
         std::thread t12(&ReadGeoModel::buildAllSerialTransformers, this);
@@ -478,6 +498,7 @@ GeoVPhysVol* ReadGeoModel::buildGeoModelPrivate() {
         buildAllPhysVols();
         buildAllFullPhysVols();
         buildAllSerialTransformers();
+        buildAllVSurfaces();          // Virtual Surface!
     }
     auto end = std::chrono::system_clock::now();  // timing: get end time
     auto diff =
@@ -974,6 +995,29 @@ void ReadGeoModel::buildAllMaterials() {
         std::cout << "All " << nSize << " Materials have been built!\n";
 }
 
+//! Iterate over the list of nodes, build them all, and store their pointers
+void ReadGeoModel::buildAllVSurfaces()
+{
+    if (m_loglevel >= 1)
+        std::cout << "Building all Virtual Surfaces...\n";
+    size_t nSize = m_VSurface.size();
+    BuildGeoVSurface* buildsurfTool = new BuildGeoVSurface();  // TODO: change the name of this class
+    for (unsigned int ii = 0; ii < nSize; ++ii)
+    {
+        try
+        {
+            const unsigned int nodeID = std::get<int>(m_VSurface[ii][0]);
+            buildVSurface(nodeID);
+        }
+        catch (std::bad_variant_access const &ex)
+        {
+            std::cout << ex.what() << ": Virtual Surface 'ID' is not an 'int' value!\n";
+        }
+    }
+    if (nSize > 0)
+        std::cout << "All " << nSize << " Virtual Surface have been built!\n";
+}
+
 //! Iterate over the list of nodes, build them all, and store their pointers
 void ReadGeoModel::buildAllLogVols()
 {
@@ -1284,6 +1328,9 @@ void ReadGeoModel::processParentChild(
         GeoFullPhysVol* childNode = dynamic_cast<GeoFullPhysVol*>(
             buildVPhysVolInstance(childId, childTableId, childCopyN));
         volAddHelper(parentVol, childNode);
+    } else if (childNodeType == "GeoVSurface") {
+        GeoVSurface* childNode = m_memMapVSurface[childId-1];
+        volAddHelper(parentVol, childNode);
     } else if (childNodeType == "GeoSerialDenominator") {
         GeoSerialDenominator* childNode = getBuiltSerialDenominator(childId);
         volAddHelper(parentVol, childNode);
@@ -1328,7 +1375,6 @@ void ReadGeoModel::processParentChild(
     //     std::cout << std::endl;
     //     muxCout.unlock();
     // }
-
     // safety check
     if (parentchild.size() < 8) {
         std::cout << "ERROR!!! Probably you are using an old geometry file. "
@@ -1383,6 +1429,9 @@ void ReadGeoModel::processParentChild(
         GeoFullPhysVol* childNode = dynamic_cast<GeoFullPhysVol*>(
             buildVPhysVolInstance(childId, childTableId, childCopyN));
         volAddHelper(parentVol, childNode);
+    } else if (childNodeType == "GeoVSurface") {
+        GeoVSurface* childNode = m_memMapVSurface[childId-1];
+        volAddHelper(parentVol, childNode);
     } else if (childNodeType == "GeoSerialDenominator") {
         GeoSerialDenominator* childNode = getBuiltSerialDenominator(childId);
         volAddHelper(parentVol, childNode);
@@ -2909,6 +2958,26 @@ GeoBox* ReadGeoModel::buildDummyShape() {
                       30 * SYSTEM_OF_UNITS::cm);
 }
 
+void ReadGeoModel::buildVSurface(const unsigned int id) {
+    if (m_loglevel >= 3) {
+        muxCout.lock();
+        std::cout << "buildVSurface(), testing VSurface id: " << id << "...\n";
+        ;
+        muxCout.unlock();
+    }
+    
+    if(!isBuiltVSurface(id)){  // the VSurface hasnt been built yet
+      DBRowEntry values = m_VSurface[id - 1];
+      const std::string shapeType = GeoModelHelpers::variantHelper::getFromVariant_String(values[1], "VSurf_shapeType");
+      const unsigned int shapeId = GeoModelHelpers::variantHelper::getFromVariant_Int(values[2], "VSurf_shapeID");
+      GeoVSurfaceShape* buildVSurfShape = BuildWhichSurface(shapeType, shapeId);  // build the shape of surface
+      GeoVSurface* buildVSurf = new GeoVSurface(buildVSurfShape);                 // build the virtual surface class itself
+      storeBuiltVSurface(buildVSurf);
+    }
+    // else do nothing
+}
+//-----------------------------------------------------------------------
+
 GeoLogVol* ReadGeoModel::buildLogVol(const unsigned int id) {
     if (m_loglevel >= 3) {
         muxCout.lock();
@@ -3292,6 +3361,7 @@ const std::set<std::string> shapesNewDB{"Box", "Tube", "Pcon", "Cons", "Para", "
 void ReadGeoModel::storeBuiltShape(const unsigned id, GeoShape* nodePtr) {
     m_memMapShapes[id] = nodePtr;
 }
+
 void ReadGeoModel::storeBuiltShape(const std::string_view type, const unsigned id, GeoShape *nodePtr)
 {
     if ("Shift" == type)
@@ -3318,6 +3388,139 @@ void ReadGeoModel::storeBuiltShapeOperators_Intersection(const unsigned id, GeoS
 void ReadGeoModel::storeBuiltShapeOperators_Union(const unsigned id, GeoShape* nodePtr) {
     m_memMapShapes_Union[id] = nodePtr;
 }
+
+//------------------------------------------------------------------------------------------
+
+GeoVSurfaceShape* ReadGeoModel::BuildWhichSurface(std::string_view shapeType, const unsigned int shapeId)
+{   
+  
+  if ("RectangleSurface" == shapeType){
+          m_memMapRectSurface.reserve(m_rectangle_surface.size());      
+     if(!isBuiltRectSurface(shapeId)){
+          // Not built yet
+          DBRowEntry row = m_rectangle_surface[shapeId - 1];
+          GeoRectSurface* builtSurface = buildsurfTool->buildRectSurface(row);
+          storeBuiltRectSurface(builtSurface);
+          return builtSurface;     
+     }
+     else{
+          GeoRectSurface* builtSurface = m_memMapRectSurface[shapeId - 1];
+          return builtSurface;
+     }
+     
+  }
+  else if ("TrapezoidSurface" == shapeType){
+          m_memMapTrapezoidSurface.reserve(m_trapezoid_surface.size());      
+     if(!isBuiltTrapezoidSurface(shapeId)){
+          // Not built yet
+          DBRowEntry row = m_trapezoid_surface[shapeId - 1];
+          GeoTrapezoidSurface* builtSurface = buildsurfTool->buildTrapezoidSurface(row);
+          storeBuiltTrapezoidSurface(builtSurface);
+          return builtSurface;     
+     }
+     else{
+          GeoTrapezoidSurface* builtSurface = m_memMapTrapezoidSurface[shapeId - 1];
+          return builtSurface;
+     }
+     
+  }
+  else if ("AnnulusSurface" == shapeType){
+          m_memMapAnnulusSurface.reserve(m_annulus_surface.size());
+     if(!isBuiltAnnulusSurface(shapeId)){
+          // Not built yet
+          DBRowEntry row = m_annulus_surface[shapeId - 1];
+          GeoAnnulusSurface* builtSurface = buildsurfTool->buildAnnulusSurface(row);
+          storeBuiltAnnulusSurface(builtSurface);
+          return builtSurface;
+     }
+     else{
+          GeoAnnulusSurface* builtSurface = m_memMapAnnulusSurface[shapeId - 1];
+          return builtSurface;
+     }
+
+  }
+  else if ("DiamondSurface" == shapeType){
+        m_memMapDiamondSurface.reserve(m_diamond_surface.size());
+        if(!isBuiltDiamondSurface(shapeId)){
+            // Not built yet
+            DBRowEntry row = m_diamond_surface[shapeId - 1];
+            GeoDiamondSurface* builtSurface = buildsurfTool->buildDiamondSurface(row);
+            storeBuiltDiamondSurface(builtSurface);
+            return builtSurface;
+        }
+        else{
+            GeoDiamondSurface* builtSurface = m_memMapDiamondSurface[shapeId - 1];
+            return builtSurface;
+        }
+            
+  }
+  else{
+    THROW_EXCEPTION("ERROR!!! VSurface '" + std::string(shapeType) + "' is not built correctly!");
+  }    
+}
+
+bool ReadGeoModel::isBuiltVSurface(const unsigned int shapeId) {
+    return (shapeId <= m_memMapVSurface.size());
+}
+
+//------------------------------------------------------------------------------------------
+
+bool ReadGeoModel::isBuiltRectSurface(const unsigned int shapeId) {
+    return (shapeId <= m_memMapRectSurface.size());
+}
+
+void ReadGeoModel::storeBuiltRectSurface(GeoRectSurface* nodePtr) {
+    if (!nodePtr)
+        THROW_EXCEPTION(" RECTANGLE SURFACE POINTER IS NULL, NO RECT SURFS ARE BUILT YET ");
+    m_memMapRectSurface.push_back(nodePtr);
+}
+
+//------------------------------------------------------------------------------------------
+
+bool ReadGeoModel::isBuiltTrapezoidSurface(const unsigned int shapeId) {
+    return (shapeId <= m_memMapTrapezoidSurface.size());
+}
+
+void ReadGeoModel::storeBuiltTrapezoidSurface(GeoTrapezoidSurface* nodePtr) {
+    if (!nodePtr)
+        THROW_EXCEPTION(" TRAPEZOID SURFACE POINTER IS NULL, NO TRAPE SURFS ARE BUILT YET ");
+    m_memMapTrapezoidSurface.push_back(nodePtr);
+}
+
+//------------------------------------------------------------------------------------------
+
+bool ReadGeoModel::isBuiltAnnulusSurface(const unsigned int shapeId) {
+    return (shapeId <= m_memMapAnnulusSurface.size());
+}
+
+void ReadGeoModel::storeBuiltAnnulusSurface(GeoAnnulusSurface* nodePtr) {
+    if (!nodePtr)
+        THROW_EXCEPTION(" ANNULUS SURFACE POINTER IS NULL, NO ANNULUS SURFS ARE BUILT YET ");
+    m_memMapAnnulusSurface.push_back(nodePtr);
+}
+
+//------------------------------------------------------------------------------------------
+
+bool ReadGeoModel::isBuiltDiamondSurface(const unsigned int shapeId) {
+    return (shapeId <= m_memMapDiamondSurface.size());
+}
+
+void ReadGeoModel::storeBuiltDiamondSurface(GeoDiamondSurface* nodePtr) {
+    if (!nodePtr)
+        THROW_EXCEPTION(" DIAMOND SURFACE POINTER IS NULL, NO DIAMOND SURFS ARE BUILT YET ");
+    m_memMapDiamondSurface.push_back(nodePtr);
+}
+
+//------------------------------------------------------------------------------------------
+
+void ReadGeoModel::storeBuiltVSurface(GeoVSurface* nodePtr) {
+    if (!nodePtr)
+        THROW_EXCEPTION(" VIRTUAL SURFACE POINTER IS NULL, NO VSURFS ARE BUILT YET ");
+    m_memMapVSurface.push_back(nodePtr);    
+}
+
+//------------------------------------------------------------------------------------------
+
 GeoShape *ReadGeoModel::getBuiltShape(const unsigned shapeId, std::string_view shapeType)
 {
 
diff --git a/GeoModelIO/GeoModelWrite/GeoModelWrite/WriteGeoModel.h b/GeoModelIO/GeoModelWrite/GeoModelWrite/WriteGeoModel.h
index 71aff6afc..192082eb6 100644
--- a/GeoModelIO/GeoModelWrite/GeoModelWrite/WriteGeoModel.h
+++ b/GeoModelIO/GeoModelWrite/GeoModelWrite/WriteGeoModel.h
@@ -20,6 +20,9 @@
  *              Also added methods to get the numbers of visited nodes.
  * - Feb 2023 - R.M.Bianchi <riccardo.maria.bianchi@cern.ch>
  *              Added 'setLoglevel' method, to steer output messages
+ *
+ * - Jun 2024 - R.Xue <r.xue@cern.ch><rux23@pitt.edu>
+ *              Added methods to write out virtual surfaces to .db files
  */
 
 #ifndef GeoModelWrite_WriteGeoModel_H
@@ -40,6 +43,7 @@
 #include "GeoModelKernel/GeoNodeAction.h"
 #include "GeoModelKernel/GeoShape.h"
 #include "GeoModelKernel/GeoXF.h"
+#include "GeoModelKernel/GeoVSurfaceShape.h"
 
 // C++ includes
 #include <set>
@@ -102,6 +106,8 @@ class WriteGeoModel : public GeoNodeAction {
         const GeoPhysVol *vol);  //	Handles a physical volume.
     virtual void handleFullPhysVol(
         const GeoFullPhysVol *vol);  //	Handles a full physical volume.
+    virtual void handleVSurface(
+        const GeoVSurface* surf);  //	Handles a virtual surface.        
     virtual void handleSerialDenominator(
         const GeoSerialDenominator *sD);  //	Handles a Serial Denominator.
     virtual void handleSerialTransformer(
@@ -178,7 +184,7 @@ class WriteGeoModel : public GeoNodeAction {
     WriteGeoModel &operator=(const WriteGeoModel &right);
 
     void handleVPhysVolObjects(const GeoVPhysVol *vol);
-
+    void handleVSurfaceObjects(const GeoVSurface *surf);
     /// Handles a physical volume referenced by a SerialTrasformer
     void handleReferencedVPhysVol(const GeoVPhysVol *vol);
 
@@ -190,7 +196,18 @@ class WriteGeoModel : public GeoNodeAction {
     unsigned int storeMaterial(const GeoMaterial *mat);
     unsigned int storeElement(const GeoElement *el);
     unsigned int storeTranform(const GeoTransform *node);
-
+    
+    // virtual surface ---------------------------------------------------------------------
+    unsigned int storeSurfaceShape(const GeoVSurfaceShape* surf);
+    std::pair<DBRowEntry, DBRowsList> getSurfaceParameters(const GeoVSurfaceShape* surf_shape);
+    unsigned int addSurfaceShape(const std::string &type,  const DBRowEntry &parameters);
+    unsigned int storeVSurface(const GeoVSurface* pointer, const unsigned int& surfShapeId, const std::string& surfShapeType);
+    unsigned int addVSurface(const std::string &type, const unsigned int& surfShapeId);
+    unsigned int storeObj(const GeoVSurfaceShape* pointer, const std::string& shapeName, 
+                          DBRowEntry& parameters, const DBRowsList &shapeData);
+    unsigned int setSurfaceCopyNumber(const unsigned int& VSurfaceId, const std::string& surfType);                          
+    //--------------------------------------------------------------------------------------
+    
     unsigned int storeObj(const GeoMaterial *pointer, const std::string &name,
                           const double &density, const DBRowsList &materialData);
     unsigned int storeObj(const GeoElement *pointer, const std::string &name,
@@ -313,6 +330,8 @@ class WriteGeoModel : public GeoNodeAction {
     std::string getAddressStringFromPointer(const GeoLogVol *pointer);
     std::string getAddressStringFromPointer(const GeoPhysVol *pointer);
     std::string getAddressStringFromPointer(const GeoVPhysVol *pointer);
+    std::string getAddressStringFromPointer(const GeoVSurface *pointer);
+    std::string getAddressStringFromPointer(const GeoVSurfaceShape *pointer);
     std::string getAddressStringFromPointer(
         const GeoSerialDenominator *pointer);
     std::string getAddressStringFromPointer(const GeoSerialIdentifier *pointer);
@@ -353,6 +372,7 @@ class WriteGeoModel : public GeoNodeAction {
     std::set<std::string> m_linkSet;
     std::unordered_map<std::string, unsigned int> m_parentChildrenMap;
     std::unordered_map<std::string, unsigned int> m_volumeCopiesMap;
+    std::unordered_map<std::string, unsigned int> m_surfaceCopiesMap;
     std::unordered_map<std::string, unsigned int> m_memMap;
     std::unordered_map<std::string, unsigned int> m_memMap_Tables;
 
@@ -415,7 +435,11 @@ class WriteGeoModel : public GeoNodeAction {
 
     DBRowsList m_shapes_UnidentifiedShape;
 
-
+    DBRowsList m_rectangle_surface;  // For Virtual Surface Shape
+    DBRowsList m_trapezoid_surface;
+    DBRowsList m_annulus_surface;
+    DBRowsList m_diamond_surface;
+    DBRowsList m_VSurface;           // For Virtual Surface Abstract Class
     
     // std::vector<std::vector<std::string>> m_functions;
     DBRowsList m_functions; // operators used in Function's expression
diff --git a/GeoModelIO/GeoModelWrite/src/WriteGeoModel.cpp b/GeoModelIO/GeoModelWrite/src/WriteGeoModel.cpp
index 87732d22d..4091dc8da 100644
--- a/GeoModelIO/GeoModelWrite/src/WriteGeoModel.cpp
+++ b/GeoModelIO/GeoModelWrite/src/WriteGeoModel.cpp
@@ -21,9 +21,11 @@
 // - Nov 2023 - R.M.Bianchi <riccardo.maria.bianchi@cern.ch>
 //              Updated to use the AlignableTransform 'default position', 
 //              which does not include alignment constants
+//
 // - May 2024 - Major change: we move to the new DB schema that uses numerical data
 //              instead of strings/TEXT
-//
+// - Jun 2024 - R.Xue  <r.xue@cern.ch><rux23@pitt.edu>
+//              Added methods to write out virtual surfaces to .db files
 
 // local includes
 #include "GeoModelWrite/WriteGeoModel.h"
@@ -58,6 +60,10 @@
 #include "GeoModelKernel/GeoTubs.h"
 #include "GeoModelKernel/GeoTwistedTrap.h"
 #include "GeoModelKernel/GeoUnidentifiedShape.h"
+#include "GeoModelKernel/GeoRectSurface.h"
+#include "GeoModelKernel/GeoTrapezoidSurface.h"
+#include "GeoModelKernel/GeoAnnulusSurface.h"
+#include "GeoModelKernel/GeoDiamondSurface.h"
 
 #include "GeoModelHelpers/throwExcept.h"
 #include "GeoModelHelpers/StringUtils.h"
@@ -125,6 +131,22 @@ unsigned int WriteGeoModel::setVolumeCopyNumber(const unsigned int& volId,
     return m_volumeCopiesMap[key];
 }
 
+unsigned int WriteGeoModel::setSurfaceCopyNumber(const unsigned int& VSurfaceId,
+                                                 const std::string& surfType) {
+    const unsigned int tableId = getIdFromNodeType(surfType); // deal with DBManager
+    std::string key =
+        std::to_string(tableId) + ":" + std::to_string(VSurfaceId);  // INT
+
+    std::unordered_map<std::string, unsigned int>::iterator it =
+        m_surfaceCopiesMap.find(key);
+    if (it == m_surfaceCopiesMap.end()) {
+        m_surfaceCopiesMap[key] = 1;    // if not found, copy number is 1
+    } else {
+        ++m_surfaceCopiesMap[key];      // if found, copy number increase by 1
+    }
+    return m_surfaceCopiesMap[key];
+}
+
 unsigned int WriteGeoModel::getLatestParentCopyNumber(
     const unsigned int& parentId, const std::string& parentType) {
     const unsigned int tableId = getIdFromNodeType(parentType);
@@ -149,6 +171,63 @@ void WriteGeoModel::handleFullPhysVol(const GeoFullPhysVol* vol) {
     handleVPhysVolObjects(vol);
 }
 
+//------------------------------------------------------------------------
+
+void WriteGeoModel::handleVSurface(const GeoVSurface* surf) {
+    handleVSurfaceObjects(surf);
+}
+
+void WriteGeoModel::handleVSurfaceObjects(const GeoVSurface* surf) {
+    if (m_loglevel >= 3) {
+        std::cout << "WriteGeoModel::handleVSurfaceObjects() -- visiting... "
+                  << surf << std::endl;
+    }
+
+    std::string address = getAddressStringFromPointer(surf);
+    unsigned int surfShapeId;
+    std::string surfShapeType;    
+    unsigned int VSurfaceId;
+    std::string surfTypeStr = "GeoVSurface";
+    GeoNodePath* path = getPath();
+    unsigned int len = path->getLength() + 1; // VS must have parent node and must not have child node, and is never added to GeoNodePath
+    const GeoVPhysVol* upperVol = nullptr;
+    upperVol = path->getItem(len - 2);        // VS definitely has NodePath lenghth larger than 1
+
+    /*
+     * VSurface features:
+     * - 1 parent VPhysVol (definitely) // add at ChildPosition member function
+     * - 1 Shape
+     */
+     
+    unsigned int parentId = 0;
+    const GeoVPhysVol* parentNode = upperVol;
+    std::string parentAddress = getAddressStringFromPointer(parentNode);
+    parentId = getStoredIdFromAddress(parentAddress);
+    
+    if (!isAddressStored(address)) {   // The VSurface is new, needs to store
+        const GeoVSurfaceShape* surf_shape = surf->getShape();
+        surfShapeId = storeSurfaceShape(surf_shape);                    // surfShapeId is given by the size of container named "&m_(shape)_surface"
+        surfShapeType = surf_shape->type();
+        VSurfaceId = storeVSurface(surf, surfShapeId, surfShapeType);   // VSurfaceId is given by the size of container named "&m_VSurface"
+
+    } else {
+        VSurfaceId = getStoredIdFromAddress(address);
+    }    
+    const unsigned int surfCopyN = setSurfaceCopyNumber(VSurfaceId, surfTypeStr);
+   
+   // store the parent-child relationship in the DB
+    std::string parentType = getGeoTypeFromVPhysVol(parentNode);
+    
+    // get the copy number of the parent
+    // virtual surfaces always have PV as parents
+    const unsigned int parentCopyN = getLatestParentCopyNumber(parentId, parentType);
+    storeChildPosition(parentId, parentType, VSurfaceId, parentCopyN,
+                       getChildPosition(parentId, parentType, parentCopyN),
+                       surfTypeStr, surfCopyN);   
+}
+
+//------------------------------------------------------------------------
+
 void WriteGeoModel::handleVPhysVolObjects(const GeoVPhysVol* vol) {
     if (m_loglevel >= 3) {
         std::cout << "WriteGeoModel::handleVPhysVolObjects() -- visiting... "
@@ -156,13 +235,13 @@ void WriteGeoModel::handleVPhysVolObjects(const GeoVPhysVol* vol) {
     }
     // get the address string for the current volume
     std::string address = getAddressStringFromPointer(vol);
-
     // variables used to persistify the object
     unsigned int physId;
 
     // check the volume position in the geometry tree
     GeoNodePath* path = getPath();
     unsigned int len = path->getLength();
+
     //    const GeoVPhysVol* tailVol = path->getTail();
     //    const GeoVPhysVol* headVol = path->getHead();
     const GeoVPhysVol* upperVol = nullptr;
@@ -353,7 +432,7 @@ void WriteGeoModel::handleVPhysVolObjects(const GeoVPhysVol* vol) {
         // get the copy number of the parent
         const unsigned int parentCopyN =
             getLatestParentCopyNumber(parentId, parentType);
-        std::string childType = getGeoTypeFromVPhysVol(vol);
+        std::string childType = getGeoTypeFromVPhysVol(vol);  // TODO: dummy variable, same as volTypeStr
         storeChildPosition(parentId, parentType, physId, parentCopyN,
                            getChildPosition(parentId, parentType, parentCopyN),
                            childType, volCopyN);
@@ -976,9 +1055,59 @@ void WriteGeoModel::handleReferencedVPhysVol(const GeoVPhysVol* vol) {
 }
 
 // Get shape parameters
-std::pair<DBRowEntry,
-          DBRowsList>
-WriteGeoModel::getShapeParametersV(const GeoShape *shape, const bool data)
+
+          
+std::pair<DBRowEntry, DBRowsList> WriteGeoModel::getSurfaceParameters(const GeoVSurfaceShape* surf_shape)
+{
+    const std::string shapeType = surf_shape->type();
+    
+    DBRowEntry shapePars;
+    DBRowsList shapeData;
+    std::pair<DBRowEntry, DBRowsList> shapePair;
+    DBRowEntry dataRow;
+    
+    double computedAreaDummy = -1;
+    shapePars.push_back(computedAreaDummy);
+    
+    if ("RectangleSurface" == shapeType){
+        const GeoRectSurface* rect_surf = dynamic_cast<const GeoRectSurface*>(surf_shape); 
+        shapePars.push_back(rect_surf->getXHalfLength());
+        shapePars.push_back(rect_surf->getYHalfLength());
+    }
+    else if ("TrapezoidSurface" == shapeType){
+        const GeoTrapezoidSurface* trapezoid = dynamic_cast<const GeoTrapezoidSurface*>(surf_shape); 
+        shapePars.push_back(trapezoid->getXHalfLengthMin());
+        shapePars.push_back(trapezoid->getXHalfLengthMax());        
+        shapePars.push_back(trapezoid->getYHalfLength());    
+    }
+    else if ("AnnulusSurface" == shapeType){
+        const GeoAnnulusSurface* annulus = dynamic_cast<const GeoAnnulusSurface*>(surf_shape); 
+        shapePars.push_back(annulus->getOx());
+        shapePars.push_back(annulus->getOy());
+        shapePars.push_back(annulus->getRadiusIn());
+        shapePars.push_back(annulus->getRadiusOut());
+        shapePars.push_back(annulus->getPhi());
+    }
+    else if ("DiamondSurface" == shapeType){
+        const GeoDiamondSurface* diamond = dynamic_cast<const GeoDiamondSurface*>(surf_shape);
+        shapePars.push_back(diamond->getXbottomHalf());
+        shapePars.push_back(diamond->getXmidHalf());
+        shapePars.push_back(diamond->getXtopHalf());
+        shapePars.push_back(diamond->getYbottomHalf());
+        shapePars.push_back(diamond->getYtopHalf());
+    }
+    else
+    {
+        std::cout << "\n\tGeoModelWrite -- WARNING!!! - Shape '" << shapeType
+                  << "' is not supported in the new DB format, yet.\n\n";
+    }
+
+    shapePair.first = shapePars;
+    shapePair.second = shapeData;
+    return shapePair;    
+}
+          
+std::pair<DBRowEntry, DBRowsList> WriteGeoModel::getShapeParametersV(const GeoShape *shape, const bool data)
 {
     const std::string shapeType = shape->type();
 
@@ -1528,6 +1657,54 @@ unsigned int WriteGeoModel::storeObj(const GeoFullPhysVol* pointer,
     return physvolId;
 }
 
+//__________________________________________________________________
+
+unsigned int WriteGeoModel::storeVSurface(const GeoVSurface* pointer, const unsigned int& surfShapeId, const std::string& surfShapeType) {
+    // SurfaceShape address is different from VSurface address
+    // VSurface has position info, similar to GeoFullPhysVol
+    unsigned int VSurfaceId;
+    std::string address = getAddressStringFromPointer(pointer);
+    VSurfaceId = addVSurface(surfShapeType, surfShapeId);
+    storeAddress(address, VSurfaceId);
+    return VSurfaceId;
+}
+
+
+unsigned int WriteGeoModel::storeSurfaceShape(const GeoVSurfaceShape* surf_shape) {
+
+    std::string shapeType = surf_shape->type();
+    std::pair<DBRowEntry, DBRowsList> shapePair = getSurfaceParameters(surf_shape);
+    DBRowEntry shapePars = shapePair.first;
+    DBRowsList shapeData = shapePair.second; 
+    return storeObj(surf_shape, shapeType, shapePars, shapeData); // return surfShapeId
+}
+
+unsigned int WriteGeoModel::storeObj(const GeoVSurfaceShape* pointer, const std::string& shapeName, DBRowEntry& parameters, const DBRowsList &shapeData) {
+    
+    std::string address = getAddressStringFromPointer(pointer);
+    unsigned int surfShapeId;
+    if (!isAddressStored(address)) {
+         //if (shapeData.size() > 0)
+        //{
+            // Store the node's additional data
+            // Rectangualr Virtual Surface now doesn't need to do this
+        //    std::pair<unsigned, unsigned> dataRows = addShapeData(shapeName, shapeData); //TODO: need to be revised for more complicated surfaces in future
+        //    unsigned dataStart = dataRows.first;
+        //    unsigned dataEnd = dataRows.second;
+        //    parameters.push_back(dataStart);
+        //    parameters.push_back(dataEnd);
+        //}
+        surfShapeId = addSurfaceShape(shapeName, parameters); // store parameters for surfaceShape
+        storeAddress(address, surfShapeId); // TODO: check if this step of storing the address and the ID is still used/needed.
+    } else {
+        // TODO: check if that is still needed/used! And if it's consistent with the new DB schema.
+        surfShapeId = getStoredIdFromAddress(address); // TODO: this is needed, because we need to check whether the surface shape could be shared,
+    }                                                  //       then return ID to VSurface, and VSurface cannot be shared
+    return surfShapeId;
+}
+
+//__________________________________________________________________
+
 unsigned int WriteGeoModel::storeObj(const GeoSerialIdentifier* pointer,
                                      const int& baseId) {
     const std::string address = getAddressStringFromPointer(pointer);
@@ -1956,6 +2133,7 @@ unsigned int WriteGeoModel::addShape(const std::string& type,
     values.push_back(parameters);
     return addRecord(container, values);
 }
+
 unsigned int WriteGeoModel::addShape(const std::string &type,
                                      const DBRowEntry &parameters)
 {
@@ -2075,6 +2253,44 @@ unsigned int WriteGeoModel::addFullPhysVol(
     return idx;
 }
 
+//------------------------------------------------------------------------
+unsigned int WriteGeoModel::addVSurface(const std::string &type, const unsigned int& surfShapeId) {
+    DBRowsList* container = &m_VSurface;
+    DBRowEntry values;
+    values.push_back(type);
+    values.push_back(surfShapeId);  // INT
+    unsigned int idx = addRecord(container, values);
+    return idx;
+}
+
+unsigned int WriteGeoModel::addSurfaceShape(const std::string &type,
+                                            const DBRowEntry &parameters)
+{
+    DBRowsList *container = nullptr;
+    if ("RectangleSurface" == type)
+    {
+        container = &m_rectangle_surface;
+    }
+    else if ("TrapezoidSurface" == type)
+    {
+        container = &m_trapezoid_surface;
+    }
+    else if ("AnnulusSurface" == type)
+    {
+        container = &m_annulus_surface;
+    }
+    else if ("DiamondSurface" == type)
+    {
+        container = &m_diamond_surface;
+    }    
+    else{
+        THROW_EXCEPTION("ERROR!!! Cannot recognize '" << type << "' while adding the surface shape!");
+    }
+    unsigned int idx = addRecord(container, parameters);
+    return idx;
+}
+//------------------------------------------------------------------------
+
 unsigned int WriteGeoModel::addLogVol(const std::string& name,
                                       const unsigned int& shapeId,
                                       std::string_view shapeType,
@@ -2149,6 +2365,7 @@ void WriteGeoModel::saveToDB(std::vector<GeoPublisher*>& publishers) {
     m_dbManager->addListOfRecords("GeoIdentifierTag", m_identifierTags);
     m_dbManager->addListOfRecords("GeoPhysVol", m_physVols);
     m_dbManager->addListOfRecords("GeoFullPhysVol", m_fullPhysVols);
+    m_dbManager->addListOfRecords("GeoVSurface", m_VSurface);
     m_dbManager->addListOfRecords("GeoLogVol", m_logVols);
     
     m_dbManager->addRecordsToTable("FuncExprData", m_exprData);
@@ -2182,7 +2399,11 @@ void WriteGeoModel::saveToDB(std::vector<GeoPublisher*>& publishers) {
 
     m_dbManager->addListOfRecords("GeoUnidentifiedShape", m_shapes_UnidentifiedShape); // new version, with shape's parameters as numbers
 
-
+    m_dbManager->addListOfRecords("RectangleSurface", m_rectangle_surface); 
+    m_dbManager->addListOfRecords("TrapezoidSurface", m_trapezoid_surface);
+    m_dbManager->addListOfRecords("AnnulusSurface", m_annulus_surface);
+    m_dbManager->addListOfRecords("DiamondSurface", m_diamond_surface);
+    
     m_dbManager->addListOfChildrenPositions(m_childrenPositions);
     m_dbManager->addRootVolume(m_rootVolume);
 
@@ -2439,6 +2660,18 @@ std::string WriteGeoModel::getAddressStringFromPointer(
     oss << pointer;
     return getQStringFromOss(oss);
 }
+std::string WriteGeoModel::getAddressStringFromPointer(
+    const GeoVSurface* pointer) {
+    std::ostringstream oss;
+    oss << pointer;
+    return getQStringFromOss(oss);
+}
+std::string WriteGeoModel::getAddressStringFromPointer(
+    const GeoVSurfaceShape* pointer) {
+    std::ostringstream oss;
+    oss << pointer;
+    return getQStringFromOss(oss);
+}
 // get pointer string
 std::string WriteGeoModel::getAddressStringFromPointer(
     const GeoSerialDenominator* pointer) {
diff --git a/GeoModelVisualization/CMakeLists.txt b/GeoModelVisualization/CMakeLists.txt
index bd48e9695..135776857 100644
--- a/GeoModelVisualization/CMakeLists.txt
+++ b/GeoModelVisualization/CMakeLists.txt
@@ -82,7 +82,7 @@ add_subdirectory(GXClashPointSystems)
 add_subdirectory(GeoModelExplorer)
 add_subdirectory(VP1Gui)
 add_subdirectory(VP1Base)
-add_subdirectory(VP1HEPVis)
+add_subdirectory(GXHepVis)
 add_subdirectory(VP1GuideLineSystems)
 add_subdirectory(GXHitDisplaySystems)
 add_subdirectory(GXTrackDisplaySystems)
diff --git a/GeoModelVisualization/VP1HEPVis/CMakeLists.txt b/GeoModelVisualization/GXHepVis/CMakeLists.txt
similarity index 66%
rename from GeoModelVisualization/VP1HEPVis/CMakeLists.txt
rename to GeoModelVisualization/GXHepVis/CMakeLists.txt
index a512c64bf..aa1006ccd 100644
--- a/GeoModelVisualization/VP1HEPVis/CMakeLists.txt
+++ b/GeoModelVisualization/GXHepVis/CMakeLists.txt
@@ -2,34 +2,34 @@
 
 # Find the header and source files.
 file( GLOB SOURCES src/*.cxx )
-file( GLOB HEADERS VP1HEPVis/*.h )
+file( GLOB HEADERS GXHepVis/*.h )
 
 # Add the library.
-add_library( GXHEPVis SHARED ${SOURCES} ${HEADERS} )
-target_include_directories( GXHEPVis PUBLIC
+add_library( GXHepVis SHARED ${SOURCES} ${HEADERS} )
+target_include_directories( GXHepVis PUBLIC
    $<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}>
    $<INSTALL_INTERFACE:${CMAKE_INSTALL_INCLUDEDIR}> )
-target_link_libraries( GXHEPVis
+target_link_libraries( GXHepVis
     PUBLIC Coin::Coin OpenGL::GL GeoModelCore::GeoModelKernel)
-source_group( "VP1HEPVis" FILES ${HEADERS} )
+source_group( "GXHepVis" FILES ${HEADERS} )
 source_group( "src" FILES ${SOURCES} )
-set_target_properties( GXHEPVis PROPERTIES
+set_target_properties( GXHepVis PROPERTIES
    VERSION ${PROJECT_VERSION}
    SOVERSION ${PROJECT_VERSION_MAJOR} )
 if( GEOMODEL_USE_BUILTIN_COIN3D )
-   add_dependencies( GXHEPVis Coin3DBuiltIn )
+   add_dependencies( GXHepVis Coin3DBuiltIn )
 endif()
 
 # Set up an alias with the same name that you would get by "finding" a pre-built
 # version of the library.
-add_library( GeoModelVisualization::GXHEPVis ALIAS GXHEPVis )
+add_library( GeoModelVisualization::GXHepVis ALIAS GXHepVis )
 
 # Install the library.
-install( TARGETS GXHEPVis
+install( TARGETS GXHepVis
    EXPORT ${PROJECT_NAME}-export
    LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}
    COMPONENT Runtime
    NAMELINK_COMPONENT Development )
-install( DIRECTORY VP1HEPVis
+install( DIRECTORY GXHepVis
    DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}
    COMPONENT Development )
diff --git a/GeoModelVisualization/VP1HEPVis/VP1HEPVis/VP1HEPVisUtils.h b/GeoModelVisualization/GXHepVis/GXHepVis/GXHepVisUtils.h
similarity index 58%
rename from GeoModelVisualization/VP1HEPVis/VP1HEPVis/VP1HEPVisUtils.h
rename to GeoModelVisualization/GXHepVis/GXHepVis/GXHepVisUtils.h
index ebda823a1..c898a6960 100644
--- a/GeoModelVisualization/VP1HEPVis/VP1HEPVis/VP1HEPVisUtils.h
+++ b/GeoModelVisualization/GXHepVis/GXHepVis/GXHepVisUtils.h
@@ -5,9 +5,9 @@
 
 ////////////////////////////////////////////////////////////////
 //                                                            //
-//  Header file for class VP1HEPVisUtils                      //
+//  Header file for class GXHepVisUtils                      //
 //                                                            //
-//  Description: Utilities connected to the VP1HEPVis         //
+//  Description: Utilities connected to the GXHepVis         //
 //               classes.                                     //
 //                                                            //
 //  Author: Thomas H. Kittelmann (Thomas.Kittelmann@cern.ch)  //
@@ -15,30 +15,23 @@
 //                                                            //
 ////////////////////////////////////////////////////////////////
 
-#ifndef VP1HEPVISUTILS_H
-#define VP1HEPVISUTILS_H
+#ifndef GXHEPVISUTILS_H
+#define GXHEPVISUTILS_H
 
 class SoGroup;
 class SoNode;
 
-class VP1HEPVisUtils {
+class GXHepVisUtils {
 public:
 
   static void initAllCustomClasses();//calls ::initClass() on all custom classes.
 
-  static SoGroup* convertToStandardScene(SoGroup*);
-  static bool isCustomNode(SoNode*);
-  static SoNode * convertCustomNodeToAlternateRep(SoNode*);//Returns empty group node if not custom or without alternate rep.
-
-  static void updateAllAlternativeReps(SoGroup*);
-  static void clearAllAlternativeReps(SoGroup*);
-
+  
 private:
 
-  VP1HEPVisUtils();
-  ~VP1HEPVisUtils();
+  GXHepVisUtils();
+  ~GXHepVisUtils();
 
-  class Imp;
 };
 
 #endif
diff --git a/GeoModelVisualization/VP1HEPVis/VP1HEPVis/SbPlane.h b/GeoModelVisualization/GXHepVis/GXHepVis/SbPlane.h
similarity index 100%
rename from GeoModelVisualization/VP1HEPVis/VP1HEPVis/SbPlane.h
rename to GeoModelVisualization/GXHepVis/GXHepVis/SbPlane.h
diff --git a/GeoModelVisualization/VP1HEPVis/VP1HEPVis/SbPolyhedron.h b/GeoModelVisualization/GXHepVis/GXHepVis/SbPolyhedron.h
similarity index 99%
rename from GeoModelVisualization/VP1HEPVis/VP1HEPVis/SbPolyhedron.h
rename to GeoModelVisualization/GXHepVis/GXHepVis/SbPolyhedron.h
index 3d4628711..397f4ad3f 100644
--- a/GeoModelVisualization/VP1HEPVis/VP1HEPVis/SbPolyhedron.h
+++ b/GeoModelVisualization/GXHepVis/GXHepVis/SbPolyhedron.h
@@ -176,8 +176,8 @@
 
 
 // VP1 change
-#include <VP1HEPVis/SbRotation.h> //using doubles instead of floats.
-#include <VP1HEPVis/SbTwistSurface.h>
+#include <GXHepVis/SbRotation.h> //using doubles instead of floats.
+#include <GXHepVis/SbTwistSurface.h>
 //---
 
 
@@ -210,7 +210,7 @@ typedef HVPoint3D HVVector3D;
 // rbianchi change
 //typedef SbPlane HVPlane3D;
 //typedef SbPlane HVPlane3D;
-#include <VP1HEPVis/SbPlane.h>
+#include <GXHepVis/SbPlane.h>
 typedef HEPVis::SbPlane HVPlane3D;
 //---
 typedef SbRotation HVRotation;
diff --git a/GeoModelVisualization/VP1HEPVis/VP1HEPVis/SbRotation.h b/GeoModelVisualization/GXHepVis/GXHepVis/SbRotation.h
similarity index 100%
rename from GeoModelVisualization/VP1HEPVis/VP1HEPVis/SbRotation.h
rename to GeoModelVisualization/GXHepVis/GXHepVis/SbRotation.h
diff --git a/GeoModelVisualization/VP1HEPVis/VP1HEPVis/SbTwistSurface.h b/GeoModelVisualization/GXHepVis/GXHepVis/SbTwistSurface.h
similarity index 98%
rename from GeoModelVisualization/VP1HEPVis/VP1HEPVis/SbTwistSurface.h
rename to GeoModelVisualization/GXHepVis/GXHepVis/SbTwistSurface.h
index 87a088057..1b3c46a55 100644
--- a/GeoModelVisualization/VP1HEPVis/VP1HEPVis/SbTwistSurface.h
+++ b/GeoModelVisualization/GXHepVis/GXHepVis/SbTwistSurface.h
@@ -17,7 +17,7 @@
 
 #include <string>
 #include "GeoModelKernel/GeoDefinitions.h"
-#include <VP1HEPVis/SbRotation.h>
+#include <GXHepVis/SbRotation.h>
 #include <Inventor/SbVec4d.h>
 
 #define SBSURFACENXX 10
diff --git a/GeoModelVisualization/VP1HEPVis/VP1HEPVis/SbTwistTrapAlphaSide.h b/GeoModelVisualization/GXHepVis/GXHepVis/SbTwistTrapAlphaSide.h
similarity index 98%
rename from GeoModelVisualization/VP1HEPVis/VP1HEPVis/SbTwistTrapAlphaSide.h
rename to GeoModelVisualization/GXHepVis/GXHepVis/SbTwistTrapAlphaSide.h
index e6898a4b8..c2bde0b60 100644
--- a/GeoModelVisualization/VP1HEPVis/VP1HEPVis/SbTwistTrapAlphaSide.h
+++ b/GeoModelVisualization/GXHepVis/GXHepVis/SbTwistTrapAlphaSide.h
@@ -12,7 +12,7 @@
 #ifndef SBTWISTTRAPALPHASIDE_HH
 #define SBTWISTTRAPALPHASIDE_HH
 
-#include "VP1HEPVis/SbTwistSurface.h"
+#include "GXHepVis/SbTwistSurface.h"
 
 #include <vector>
 
diff --git a/GeoModelVisualization/VP1HEPVis/VP1HEPVis/SbTwistTrapFlatSide.h b/GeoModelVisualization/GXHepVis/GXHepVis/SbTwistTrapFlatSide.h
similarity index 98%
rename from GeoModelVisualization/VP1HEPVis/VP1HEPVis/SbTwistTrapFlatSide.h
rename to GeoModelVisualization/GXHepVis/GXHepVis/SbTwistTrapFlatSide.h
index a00c76877..954b019a5 100644
--- a/GeoModelVisualization/VP1HEPVis/VP1HEPVis/SbTwistTrapFlatSide.h
+++ b/GeoModelVisualization/GXHepVis/GXHepVis/SbTwistTrapFlatSide.h
@@ -12,7 +12,7 @@
 #ifndef SBTWISTTRAPFLATSIDE_HH
 #define SBTWISTTRAPFLATSIDE_HH
 
-#include "VP1HEPVis/SbTwistSurface.h"
+#include "GXHepVis/SbTwistSurface.h"
 #include <string>
 
 class SbTwistTrapFlatSide : public SbTwistSurface
diff --git a/GeoModelVisualization/VP1HEPVis/VP1HEPVis/SbTwistTrapParallelSide.h b/GeoModelVisualization/GXHepVis/GXHepVis/SbTwistTrapParallelSide.h
similarity index 98%
rename from GeoModelVisualization/VP1HEPVis/VP1HEPVis/SbTwistTrapParallelSide.h
rename to GeoModelVisualization/GXHepVis/GXHepVis/SbTwistTrapParallelSide.h
index 9b8c0ebcd..42d5bd185 100644
--- a/GeoModelVisualization/VP1HEPVis/VP1HEPVis/SbTwistTrapParallelSide.h
+++ b/GeoModelVisualization/GXHepVis/GXHepVis/SbTwistTrapParallelSide.h
@@ -12,8 +12,8 @@
 #ifndef SBTWISTTRAPPARALLELSIDE_HH
 #define SBTWISTTRAPPARALLELSIDE_HH
 
-#include "VP1HEPVis/SbTwistSurface.h"
-#include "VP1HEPVis/SbPolyhedron.h"
+#include "GXHepVis/SbTwistSurface.h"
+#include "GXHepVis/SbPolyhedron.h"
 
 #include <vector>
 #include <cmath>
diff --git a/GeoModelVisualization/VP1HEPVis/VP1HEPVis/actions/SoGL2PSAction.h b/GeoModelVisualization/GXHepVis/GXHepVis/actions/SoGL2PSAction.h
similarity index 100%
rename from GeoModelVisualization/VP1HEPVis/VP1HEPVis/actions/SoGL2PSAction.h
rename to GeoModelVisualization/GXHepVis/GXHepVis/actions/SoGL2PSAction.h
diff --git a/GeoModelVisualization/VP1HEPVis/VP1HEPVis/gl2ps.h b/GeoModelVisualization/GXHepVis/GXHepVis/gl2ps.h
similarity index 100%
rename from GeoModelVisualization/VP1HEPVis/VP1HEPVis/gl2ps.h
rename to GeoModelVisualization/GXHepVis/GXHepVis/gl2ps.h
diff --git a/GeoModelVisualization/VP1HEPVis/VP1HEPVis/nodes/SoCons.h b/GeoModelVisualization/GXHepVis/GXHepVis/nodes/SoCons.h
similarity index 86%
rename from GeoModelVisualization/VP1HEPVis/VP1HEPVis/nodes/SoCons.h
rename to GeoModelVisualization/GXHepVis/GXHepVis/nodes/SoCons.h
index 893a3267c..c7ceb1ad4 100644
--- a/GeoModelVisualization/VP1HEPVis/VP1HEPVis/nodes/SoCons.h
+++ b/GeoModelVisualization/GXHepVis/GXHepVis/nodes/SoCons.h
@@ -91,11 +91,6 @@ public:
   //! Put field to 0 (the default) to ignore it.
   //
   SoSFInt32 pOverrideNPhi;
-  //
-  //! Alternate rep required - for use by users without HEPVis shared objects
-  //
-  SoSFNode  alternateRep;
-
   //
   //! Constructor, required
   //
@@ -106,20 +101,6 @@ public:
   //
   static void initClass();
 
-  //
-  //! Generate AlternateRep, required.  Generating an alternate representation
-  //! must be done upon users request.  It allows an Inventor program to read
-  //! back the file without requiring *this* code to be dynamically linked.
-  //! If the users expects that *this* code will be dynamically linked, he
-  //! need not invoke this method.
-  //
-  virtual void generateAlternateRep();
-
-  //
-  //! We better be able to clear it, too!
-  //
-  virtual void clearAlternateRep();
-
 protected:
 
   //
diff --git a/GeoModelVisualization/VP1HEPVis/VP1HEPVis/nodes/SoGenericBox.h b/GeoModelVisualization/GXHepVis/GXHepVis/nodes/SoGenericBox.h
similarity index 97%
rename from GeoModelVisualization/VP1HEPVis/VP1HEPVis/nodes/SoGenericBox.h
rename to GeoModelVisualization/GXHepVis/GXHepVis/nodes/SoGenericBox.h
index 895c7d251..a7c3ba154 100644
--- a/GeoModelVisualization/VP1HEPVis/VP1HEPVis/nodes/SoGenericBox.h
+++ b/GeoModelVisualization/GXHepVis/GXHepVis/nodes/SoGenericBox.h
@@ -32,7 +32,6 @@ public:
   //Fields:
   SoSFBool drawEdgeLines;//Default: False
   SoSFBool forceEdgeLinesInBaseColour;//Default: True
-  SoSFNode alternateRep;
 
   //NB: For performance reason we deviate from the standard Inventor
   //way here. We keep the points in an array, and the user must use
@@ -78,6 +77,7 @@ public:
 			     float x6, float y6, float z6,
 			     float x7, float y7, float z7 );
 
+
   //Todo: We could even add a transformation for the TRD (or anything
   //else... perhaps an "applyTransform" method to call after the first
   //setParameters...?)
@@ -87,8 +87,6 @@ public:
   //Required stuff:
   SoGenericBox();
   static void initClass();//You can call this as many times as you like
-  virtual void generateAlternateRep();
-  virtual void clearAlternateRep();
 
 protected:
 
diff --git a/GeoModelVisualization/VP1HEPVis/VP1HEPVis/nodes/SoLAr.h b/GeoModelVisualization/GXHepVis/GXHepVis/nodes/SoLAr.h
similarity index 84%
rename from GeoModelVisualization/VP1HEPVis/VP1HEPVis/nodes/SoLAr.h
rename to GeoModelVisualization/GXHepVis/GXHepVis/nodes/SoLAr.h
index 081be90ea..0a5ca8b4b 100644
--- a/GeoModelVisualization/VP1HEPVis/VP1HEPVis/nodes/SoLAr.h
+++ b/GeoModelVisualization/GXHepVis/GXHepVis/nodes/SoLAr.h
@@ -69,10 +69,6 @@ public:
   //! Put field to 0 (the default) to ignore it.
   //
   SoSFInt32 pOverrideNPhi;
-  //
-  //! Alternate rep required - for use by users without HEPVis shared objects
-  //
-  SoSFNode  alternateRep;
 
   //
   //! Constructor, required
@@ -84,20 +80,6 @@ public:
   //
   static void initClass();
 
-  //
-  //! Generate AlternateRep, required.  Generating an alternate representation
-  //! must be done upon users request.  It allows an Inventor program to read
-  //! back the file without requiring *this* code to be dynamically linked.
-  //! If the users expects that *this* code will be dynamically linked, he
-  //! need not invoke this method.
-  //
-  virtual void generateAlternateRep();
-
-  //
-  //! We better be able to clear it, too!
-  //
-  virtual void clearAlternateRep();
-
 protected:
 
   //
diff --git a/GeoModelVisualization/VP1HEPVis/VP1HEPVis/nodes/SoPcons.h b/GeoModelVisualization/GXHepVis/GXHepVis/nodes/SoPcons.h
similarity index 84%
rename from GeoModelVisualization/VP1HEPVis/VP1HEPVis/nodes/SoPcons.h
rename to GeoModelVisualization/GXHepVis/GXHepVis/nodes/SoPcons.h
index 282934279..c66b289f3 100644
--- a/GeoModelVisualization/VP1HEPVis/VP1HEPVis/nodes/SoPcons.h
+++ b/GeoModelVisualization/GXHepVis/GXHepVis/nodes/SoPcons.h
@@ -73,9 +73,6 @@ public:
   //
   SoSFInt32 pOverrideNPhi;
   //
-  //! Alternate rep required - for use by users without HEPVis shared objects
-  //
-  SoSFNode  alternateRep;//FIXED
 
   SoSFBool drawEdgeLines;//Default: False
 
@@ -89,20 +86,6 @@ public:
   //
   static void initClass();
 
-  //
-  //! Generate AlternateRep, required.  Generating an alternate representation
-  //! must be done upon users request.  It allows an Inventor program to read
-  //! back the file without requiring *this* code to be dynamically linked.
-  //! If the users expects that *this* code will be dynamically linked, he
-  //! need not invoke this method.
-  //
-  virtual void generateAlternateRep();//FIXME: NOT IMPLEMENTED
-
-  //
-  //! We better be able to clear it, too!
-  //
-  virtual void clearAlternateRep();//FIXME: NOT IMPLEMENTED
-
 protected:
 
   //
diff --git a/GeoModelVisualization/VP1HEPVis/VP1HEPVis/nodes/SoPolyhedron.h b/GeoModelVisualization/GXHepVis/GXHepVis/nodes/SoPolyhedron.h
similarity index 95%
rename from GeoModelVisualization/VP1HEPVis/VP1HEPVis/nodes/SoPolyhedron.h
rename to GeoModelVisualization/GXHepVis/GXHepVis/nodes/SoPolyhedron.h
index fe940ddfb..d783570a9 100644
--- a/GeoModelVisualization/VP1HEPVis/VP1HEPVis/nodes/SoPolyhedron.h
+++ b/GeoModelVisualization/GXHepVis/GXHepVis/nodes/SoPolyhedron.h
@@ -51,7 +51,6 @@ class SoPolyhedron : public SoShape {
 public:
   //SoSFBool solid;
   //SoSFBool reducedWireFrame;
-  SoSFNode      alternateRep;
 public:
   SoPolyhedron();
   SoPolyhedron(const SbPolyhedron&);
@@ -82,10 +81,7 @@ public:
   long     m_icount;
   long     hasVertex(Vertex* vertices, long len, Vertex& v);
   void     makeShape(SbPolyhedron*);
-public:
- virtual void generateAlternateRep();
- virtual void clearAlternateRep();
- //---------------------//
+
 };
 
 #endif
diff --git a/GeoModelVisualization/VP1HEPVis/VP1HEPVis/nodes/SoTessellated.h b/GeoModelVisualization/GXHepVis/GXHepVis/nodes/SoTessellated.h
similarity index 95%
rename from GeoModelVisualization/VP1HEPVis/VP1HEPVis/nodes/SoTessellated.h
rename to GeoModelVisualization/GXHepVis/GXHepVis/nodes/SoTessellated.h
index c148e7274..7ee8ca9f7 100644
--- a/GeoModelVisualization/VP1HEPVis/VP1HEPVis/nodes/SoTessellated.h
+++ b/GeoModelVisualization/GXHepVis/GXHepVis/nodes/SoTessellated.h
@@ -30,7 +30,6 @@ class SoTessellated : public SoShape
   //Fields:
   SoSFBool drawEdgeLines;              //Default: False
   SoSFBool forceEdgeLinesInBaseColour; //Default: True
-  SoSFNode alternateRep;
 
   // Following two methods add facets to the solid
   //
@@ -56,8 +55,6 @@ class SoTessellated : public SoShape
   //_____ Required stuff _____ 
   SoTessellated();
   static void initClass();
-  virtual void generateAlternateRep();
-  virtual void clearAlternateRep();
 
  protected:
 
diff --git a/GeoModelVisualization/VP1HEPVis/VP1HEPVis/nodes/SoTorus.h b/GeoModelVisualization/GXHepVis/GXHepVis/nodes/SoTorus.h
similarity index 92%
rename from GeoModelVisualization/VP1HEPVis/VP1HEPVis/nodes/SoTorus.h
rename to GeoModelVisualization/GXHepVis/GXHepVis/nodes/SoTorus.h
index e002505bc..223c82f22 100644
--- a/GeoModelVisualization/VP1HEPVis/VP1HEPVis/nodes/SoTorus.h
+++ b/GeoModelVisualization/GXHepVis/GXHepVis/nodes/SoTorus.h
@@ -103,10 +103,6 @@ public:
   //
   SoSFInt32 pOverrideNPhi;
   //
-  //! Alternate rep required - for use by users without HEPVis shared objects
-  //
-  SoSFNode  alternateRep;
-
   //
   //! Constructor, required
   //
@@ -117,20 +113,6 @@ public:
   //
   static void initClass();
 
-  //
-  //! Generate AlternateRep, required.  Generating an alternate representation
-  //! must be done upon users request.  It allows an Inventor program to read
-  //! back the file without requiring *this* code to be dynamically linked.
-  //! If the users expects that *this* code will be dynamically linked, he
-  //! need not invoke this method.
-  //
-  virtual void generateAlternateRep();
-
-  //
-  //! We better be able to clear it, too!
-  //
-  virtual void clearAlternateRep();
-
 protected:
 
   //
diff --git a/GeoModelVisualization/VP1HEPVis/VP1HEPVis/nodes/SoTransparency.h b/GeoModelVisualization/GXHepVis/GXHepVis/nodes/SoTransparency.h
similarity index 100%
rename from GeoModelVisualization/VP1HEPVis/VP1HEPVis/nodes/SoTransparency.h
rename to GeoModelVisualization/GXHepVis/GXHepVis/nodes/SoTransparency.h
diff --git a/GeoModelVisualization/VP1HEPVis/VP1HEPVis/nodes/SoTubs.h b/GeoModelVisualization/GXHepVis/GXHepVis/nodes/SoTubs.h
similarity index 87%
rename from GeoModelVisualization/VP1HEPVis/VP1HEPVis/nodes/SoTubs.h
rename to GeoModelVisualization/GXHepVis/GXHepVis/nodes/SoTubs.h
index 88d23be80..b2083153a 100644
--- a/GeoModelVisualization/VP1HEPVis/VP1HEPVis/nodes/SoTubs.h
+++ b/GeoModelVisualization/GXHepVis/GXHepVis/nodes/SoTubs.h
@@ -79,10 +79,6 @@ public:
   //! Put field to 0 (the default) to ignore it.
   //
   SoSFInt32 pOverrideNPhi;
-  //
-  //! Alternate rep - required
-  //
-  SoSFNode  alternateRep;
 
   SoSFBool drawEdgeLines;//Default: False
 
@@ -96,20 +92,6 @@ public:
   //
   static void initClass();
 
-  //
-  //! Generate AlternateRep, required.  Generating an alternate representation
-  //! must be done upon users request.  It allows an Inventor program to read
-  //! back the file without requiring *this* code to be dynamically linked.
-  //! If the users expects that *this* code will be dynamically linked, he
-  //! need not invoke this method.
-  //
-  virtual void generateAlternateRep();
-
-  //
-  //! We better be able to clear it, too!
-  //
-  virtual void clearAlternateRep();
-
 protected:
 
   //
diff --git a/GeoModelVisualization/VP1HEPVis/src/BooleanProcessor.h b/GeoModelVisualization/GXHepVis/src/BooleanProcessor.h
similarity index 99%
rename from GeoModelVisualization/VP1HEPVis/src/BooleanProcessor.h
rename to GeoModelVisualization/GXHepVis/src/BooleanProcessor.h
index ec3782dd6..999c3441c 100644
--- a/GeoModelVisualization/VP1HEPVis/src/BooleanProcessor.h
+++ b/GeoModelVisualization/GXHepVis/src/BooleanProcessor.h
@@ -15,7 +15,7 @@
  * NOTES:
  *
  * ===================
- * VP1 Customization:
+ * VP1/GMEX Customization:
  *
  *  - look into the code for comments "// VP1 change"
  *
@@ -63,7 +63,7 @@ typedef G4Normal3D HVNormal3D;
 
 // VP1 change
 //#include <HEPVis/SbPlane.h>
-#include <VP1HEPVis/SbPlane.h>
+#include <GXHepVis/SbPlane.h>
 typedef HEPVis::SbPlane HVPlane3D;
 //---
 
@@ -2071,14 +2071,14 @@ HepPolyhedron BooleanProcessor::execute(int op,
     case OP_UNION:
       return b;
     case OP_INTERSECTION:
-      if ( getenv("VP1MSG_DEBUG_OUTPUT") ) { // TODO: to be replaced by VP1Msg::debug(), when moved outside of VP1Base
+      if ( getenv("GMXMSG_DEBUG_OUTPUT") ) { 
     	std::cerr
         << "BooleanProcessor: intersection with empty polyhedron"
         << std::endl;
       }
       return HepPolyhedron();
     case OP_SUBTRACTION:
-      if ( getenv("VP1MSG_DEBUG_OUTPUT") ) { // TODO: to be replaced by VP1Msg::debug(), when moved outside of VP1Base
+      if ( getenv("GMXMSG_DEBUG_OUTPUT") ) { 
     	std::cerr
         << "BooleanProcessor: subtraction from empty polyhedron"
         << std::endl;
@@ -2092,7 +2092,7 @@ HepPolyhedron BooleanProcessor::execute(int op,
     case OP_UNION:
       return a;
     case OP_INTERSECTION:
-      if ( getenv("VP1MSG_DEBUG_OUTPUT") ) { // TODO: to be replaced by VP1Msg::debug(), when moved outside of VP1Base
+      if ( getenv("GMXMSG_DEBUG_OUTPUT") ) { 
     	std::cerr
         << "BooleanProcessor: intersection with empty polyhedron"
         << std::endl;
diff --git a/GeoModelVisualization/VP1HEPVis/src/BooleanProcessor.h.original b/GeoModelVisualization/GXHepVis/src/BooleanProcessor.h.original
similarity index 100%
rename from GeoModelVisualization/VP1HEPVis/src/BooleanProcessor.h.original
rename to GeoModelVisualization/GXHepVis/src/BooleanProcessor.h.original
diff --git a/GeoModelVisualization/GXHepVis/src/GXHepVisUtils.cxx b/GeoModelVisualization/GXHepVis/src/GXHepVisUtils.cxx
new file mode 100644
index 000000000..e0eb6c5ad
--- /dev/null
+++ b/GeoModelVisualization/GXHepVis/src/GXHepVisUtils.cxx
@@ -0,0 +1,40 @@
+/*
+  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+*/
+
+
+////////////////////////////////////////////////////////////////
+//                                                            //
+//  Implementation of class GXHepVisUtils                    //
+//                                                            //
+//  Author: Thomas H. Kittelmann (Thomas.Kittelmann@cern.ch)  //
+//  Initial version: November 2008                            //
+//  Update: Giorgi Gvaberidze (ggvaberi@cern.ch)              //
+//  Update  version: November 2010                            //
+//  Truncated to almost zero: J. Boudreau June 2024           //
+//                                                            //
+////////////////////////////////////////////////////////////////
+
+#include "GXHepVis/GXHepVisUtils.h"
+
+#include "GXHepVis/nodes/SoCons.h"
+#include "GXHepVis/nodes/SoGenericBox.h"
+#include "GXHepVis/nodes/SoLAr.h"
+#include "GXHepVis/nodes/SoPcons.h"
+#include "GXHepVis/nodes/SoPolyhedron.h"
+#include "GXHepVis/nodes/SoTransparency.h"
+#include "GXHepVis/nodes/SoTubs.h"
+#include "GXHepVis/nodes/SoTessellated.h"
+
+//____________________________________________________________________
+void GXHepVisUtils::initAllCustomClasses()
+{
+  SoCons::initClass();
+  SoGenericBox::initClass();
+  SoLAr::initClass();
+  SoPcons::initClass();
+  SoPolyhedron::initClass();
+  SoTransparency::initClass();
+  SoTubs::initClass();
+  SoTessellated::initClass();
+}
diff --git a/GeoModelVisualization/VP1HEPVis/src/PolygonTriangulator.cxx b/GeoModelVisualization/GXHepVis/src/PolygonTriangulator.cxx
similarity index 100%
rename from GeoModelVisualization/VP1HEPVis/src/PolygonTriangulator.cxx
rename to GeoModelVisualization/GXHepVis/src/PolygonTriangulator.cxx
diff --git a/GeoModelVisualization/VP1HEPVis/src/PolygonTriangulator.h b/GeoModelVisualization/GXHepVis/src/PolygonTriangulator.h
similarity index 100%
rename from GeoModelVisualization/VP1HEPVis/src/PolygonTriangulator.h
rename to GeoModelVisualization/GXHepVis/src/PolygonTriangulator.h
diff --git a/GeoModelVisualization/VP1HEPVis/src/RevolutionSurfaceUtil.h b/GeoModelVisualization/GXHepVis/src/RevolutionSurfaceUtil.h
similarity index 100%
rename from GeoModelVisualization/VP1HEPVis/src/RevolutionSurfaceUtil.h
rename to GeoModelVisualization/GXHepVis/src/RevolutionSurfaceUtil.h
diff --git a/GeoModelVisualization/VP1HEPVis/src/SbMath.h b/GeoModelVisualization/GXHepVis/src/SbMath.h
similarity index 100%
rename from GeoModelVisualization/VP1HEPVis/src/SbMath.h
rename to GeoModelVisualization/GXHepVis/src/SbMath.h
diff --git a/GeoModelVisualization/VP1HEPVis/src/SbPlane.cxx b/GeoModelVisualization/GXHepVis/src/SbPlane.cxx
similarity index 97%
rename from GeoModelVisualization/VP1HEPVis/src/SbPlane.cxx
rename to GeoModelVisualization/GXHepVis/src/SbPlane.cxx
index ba6c2b115..0fb67714c 100644
--- a/GeoModelVisualization/VP1HEPVis/src/SbPlane.cxx
+++ b/GeoModelVisualization/GXHepVis/src/SbPlane.cxx
@@ -3,7 +3,7 @@
 */
 
 /*
- * VP1HEPVis
+ * GXHepVis
  * SbPlane.cxx
  *
  *  Created on: Dec 13, 2012
@@ -35,7 +35,7 @@
 // this :
 // VP1 change
 //#include <HEPVis/SbPlane.h>
-#include <VP1HEPVis/SbPlane.h>
+#include <GXHepVis/SbPlane.h>
 //---
 
 
diff --git a/GeoModelVisualization/VP1HEPVis/src/SbPolyhedron.cxx b/GeoModelVisualization/GXHepVis/src/SbPolyhedron.cxx
similarity index 98%
rename from GeoModelVisualization/VP1HEPVis/src/SbPolyhedron.cxx
rename to GeoModelVisualization/GXHepVis/src/SbPolyhedron.cxx
index 5b389bf62..2c46f7191 100644
--- a/GeoModelVisualization/VP1HEPVis/src/SbPolyhedron.cxx
+++ b/GeoModelVisualization/GXHepVis/src/SbPolyhedron.cxx
@@ -11,10 +11,10 @@
 ////////////////////////////////////////////////////////////////
 
 
-#include <VP1HEPVis/SbPolyhedron.h>
-#include <VP1HEPVis/SbTwistTrapAlphaSide.h>
-#include <VP1HEPVis/SbTwistTrapParallelSide.h>
-#include <VP1HEPVis/SbTwistTrapFlatSide.h>
+#include <GXHepVis/SbPolyhedron.h>
+#include <GXHepVis/SbTwistTrapAlphaSide.h>
+#include <GXHepVis/SbTwistTrapParallelSide.h>
+#include <GXHepVis/SbTwistTrapFlatSide.h>
 
 #include "GeoModelKernel/Units.h"
 
@@ -1769,7 +1769,7 @@ SbPolyhedronCons::SbPolyhedronCons(double Rmn1,
   if (dphi > wholeCircle) k += 4;
 
   if (k != 0) {
-      if ( getenv("VP1MSG_DEBUG_OUTPUT") ) { // TODO: to be replaced by VP1Msg::debug(), when moved outside of VP1Base
+      if ( getenv("GMXMSG_DEBUG_OUTPUT") ) { 
           std::cerr << "SbPolyhedronCone(s)/Tube(s): error in input parameters";
           if ((k & 1) != 0) std::cerr << " (radiuses)";
           if ((k & 2) != 0) std::cerr << " (half-length)";
@@ -1850,7 +1850,7 @@ SbPolyhedronPgon::SbPolyhedronPgon(double phi,
   //   C H E C K   I N P U T   P A R A M E T E R S
 
   if (dphi <= 0. || dphi > 2*M_PI) {
-      if ( getenv("VP1MSG_DEBUG_OUTPUT") ) { // TODO: to be replaced by VP1Msg::debug(), when moved outside of VP1Base
+      if ( getenv("GMXMSG_DEBUG_OUTPUT") ) { 
     std::cerr
       << "SbPolyhedronPgon/Pcon: wrong delta phi = " << dphi
       << std::endl;
@@ -1859,7 +1859,7 @@ SbPolyhedronPgon::SbPolyhedronPgon(double phi,
   }
 
   if (nz < 2) {
-      if ( getenv("VP1MSG_DEBUG_OUTPUT") ) { // TODO: to be replaced by VP1Msg::debug(), when moved outside of VP1Base
+      if ( getenv("GMXMSG_DEBUG_OUTPUT") ) { 
     std::cerr
       << "SbPolyhedronPgon/Pcon: number of z-planes less than two = " << nz
       << std::endl;
@@ -1868,7 +1868,7 @@ SbPolyhedronPgon::SbPolyhedronPgon(double phi,
   }
 
   if (npdv < 0) {
-      if ( getenv("VP1MSG_DEBUG_OUTPUT") ) { // TODO: to be replaced by VP1Msg::debug(), when moved outside of VP1Base
+      if ( getenv("GMXMSG_DEBUG_OUTPUT") ) { 
     std::cerr
       << "SbPolyhedronPgon/Pcon: error in number of phi-steps =" << npdv
       << std::endl;
@@ -1879,7 +1879,7 @@ SbPolyhedronPgon::SbPolyhedronPgon(double phi,
   int i;
   for (i=0; i<nz; i++) {
     if (rmin[i] < 0. || rmax[i] < 0. || rmin[i] > rmax[i]) {
-      if ( getenv("VP1MSG_DEBUG_OUTPUT") ) { // TODO: to be replaced by VP1Msg::debug(), when moved outside of VP1Base
+      if ( getenv("GMXMSG_DEBUG_OUTPUT") ) { 
       std::cerr
         << "SbPolyhedronPgon: error in radiuses rmin[" << i << "]="
         << rmin[i] << " rmax[" << i << "]=" << rmax[i]
@@ -1952,7 +1952,7 @@ SbPolyhedronSphere::SbPolyhedronSphere(double rmin, double rmax,
   //   C H E C K   I N P U T   P A R A M E T E R S
 
   if (dphi <= 0. || dphi > 2*M_PI) {
-      if ( getenv("VP1MSG_DEBUG_OUTPUT") ) { // TODO: to be replaced by VP1Msg::debug(), when moved outside of VP1Base
+      if ( getenv("GMXMSG_DEBUG_OUTPUT") ) { 
     std::cerr
       << "SbPolyhedronSphere: wrong delta phi = " << dphi
       << std::endl;
@@ -1961,7 +1961,7 @@ SbPolyhedronSphere::SbPolyhedronSphere(double rmin, double rmax,
   }
 
   if (the < 0. || the > M_PI) {
-      if ( getenv("VP1MSG_DEBUG_OUTPUT") ) { // TODO: to be replaced by VP1Msg::debug(), when moved outside of VP1Base
+      if ( getenv("GMXMSG_DEBUG_OUTPUT") ) { 
     std::cerr
       << "SbPolyhedronSphere: wrong theta = " << the
       << std::endl;
@@ -1970,7 +1970,7 @@ SbPolyhedronSphere::SbPolyhedronSphere(double rmin, double rmax,
   }
 
   if (dthe <= 0. || dthe > M_PI) {
-      if ( getenv("VP1MSG_DEBUG_OUTPUT") ) { // TODO: to be replaced by VP1Msg::debug(), when moved outside of VP1Base
+      if ( getenv("GMXMSG_DEBUG_OUTPUT") ) { 
     std::cerr
       << "SbPolyhedronSphere: wrong delta theta = " << dthe
       << std::endl;
@@ -1982,7 +1982,7 @@ SbPolyhedronSphere::SbPolyhedronSphere(double rmin, double rmax,
     dthe = M_PI - the; //G.Barrand : coming from LHCb/S.Ponce.
 
   if (the+dthe > M_PI) {
-      if ( getenv("VP1MSG_DEBUG_OUTPUT") ) { // TODO: to be replaced by VP1Msg::debug(), when moved outside of VP1Base
+      if ( getenv("GMXMSG_DEBUG_OUTPUT") ) { 
     std::cerr
       << "SbPolyhedronSphere: wrong theta + delta theta = "
       << the << " " << dthe
@@ -1992,7 +1992,7 @@ SbPolyhedronSphere::SbPolyhedronSphere(double rmin, double rmax,
   }
 
   if (rmin < 0. || rmin >= rmax) {
-      if ( getenv("VP1MSG_DEBUG_OUTPUT") ) { // TODO: to be replaced by VP1Msg::debug(), when moved outside of VP1Base
+      if ( getenv("GMXMSG_DEBUG_OUTPUT") ) { 
     std::cerr
       << "SbPolyhedronSphere: error in radiuses"
       << " rmin=" << rmin << " rmax=" << rmax
@@ -2063,7 +2063,7 @@ SbPolyhedronTorus::SbPolyhedronTorus(double rmin,
   //   C H E C K   I N P U T   P A R A M E T E R S
 
   if (dphi <= 0. || dphi > 2*M_PI) {
-      if ( getenv("VP1MSG_DEBUG_OUTPUT") ) { // TODO: to be replaced by VP1Msg::debug(), when moved outside of VP1Base
+      if ( getenv("GMXMSG_DEBUG_OUTPUT") ) { 
     std::cerr
       << "SbPolyhedronTorus: wrong delta phi = " << dphi
       << std::endl;
@@ -2072,7 +2072,7 @@ SbPolyhedronTorus::SbPolyhedronTorus(double rmin,
   }
 
   if (rmin < 0. || rmin >= rmax || rmax >= rtor) {
-      if ( getenv("VP1MSG_DEBUG_OUTPUT") ) { // TODO: to be replaced by VP1Msg::debug(), when moved outside of VP1Base
+      if ( getenv("GMXMSG_DEBUG_OUTPUT") ) { 
     std::cerr
       << "SbPolyhedronTorus: error in radiuses"
       << " rmin=" << rmin << " rmax=" << rmax << " rtorus=" << rtor
diff --git a/GeoModelVisualization/VP1HEPVis/src/SbRotation.cxx b/GeoModelVisualization/GXHepVis/src/SbRotation.cxx
similarity index 98%
rename from GeoModelVisualization/VP1HEPVis/src/SbRotation.cxx
rename to GeoModelVisualization/GXHepVis/src/SbRotation.cxx
index 24427bdc0..ba72e42b6 100644
--- a/GeoModelVisualization/VP1HEPVis/src/SbRotation.cxx
+++ b/GeoModelVisualization/GXHepVis/src/SbRotation.cxx
@@ -3,7 +3,7 @@
 */
 
 /*
- * VP1HEPVis
+ * GXHepVis
  * SbRotation.cxx
  *
  *  Created on: Dec 13, 2012
@@ -36,7 +36,7 @@
 
 // this :
 // VP1 change
-#include <VP1HEPVis/SbRotation.h>
+#include <GXHepVis/SbRotation.h>
 //---
 
 #include <math.h>
diff --git a/GeoModelVisualization/VP1HEPVis/src/SbStringHelpers.cxx b/GeoModelVisualization/GXHepVis/src/SbStringHelpers.cxx
similarity index 100%
rename from GeoModelVisualization/VP1HEPVis/src/SbStringHelpers.cxx
rename to GeoModelVisualization/GXHepVis/src/SbStringHelpers.cxx
diff --git a/GeoModelVisualization/VP1HEPVis/src/SbStringHelpers.h b/GeoModelVisualization/GXHepVis/src/SbStringHelpers.h
similarity index 100%
rename from GeoModelVisualization/VP1HEPVis/src/SbStringHelpers.h
rename to GeoModelVisualization/GXHepVis/src/SbStringHelpers.h
diff --git a/GeoModelVisualization/VP1HEPVis/src/SbTwistSurface.cxx b/GeoModelVisualization/GXHepVis/src/SbTwistSurface.cxx
similarity index 99%
rename from GeoModelVisualization/VP1HEPVis/src/SbTwistSurface.cxx
rename to GeoModelVisualization/GXHepVis/src/SbTwistSurface.cxx
index 112fa234a..89fa5f4ee 100644
--- a/GeoModelVisualization/VP1HEPVis/src/SbTwistSurface.cxx
+++ b/GeoModelVisualization/GXHepVis/src/SbTwistSurface.cxx
@@ -11,7 +11,7 @@
 #include <iomanip>
 #include <iostream>
 
-#include "VP1HEPVis/SbTwistSurface.h"
+#include "GXHepVis/SbTwistSurface.h"
 
 //=====================================================================
 //* constructors ------------------------------------------------------
diff --git a/GeoModelVisualization/VP1HEPVis/src/SbTwistTrapAlphaSide.cxx b/GeoModelVisualization/GXHepVis/src/SbTwistTrapAlphaSide.cxx
similarity index 98%
rename from GeoModelVisualization/VP1HEPVis/src/SbTwistTrapAlphaSide.cxx
rename to GeoModelVisualization/GXHepVis/src/SbTwistTrapAlphaSide.cxx
index a88642542..62cb98c1d 100644
--- a/GeoModelVisualization/VP1HEPVis/src/SbTwistTrapAlphaSide.cxx
+++ b/GeoModelVisualization/GXHepVis/src/SbTwistTrapAlphaSide.cxx
@@ -9,7 +9,7 @@
 #include <cmath>
 #include <iostream>
 
-#include "VP1HEPVis/SbTwistTrapAlphaSide.h"
+#include "GXHepVis/SbTwistTrapAlphaSide.h"
 
 //=====================================================================
 //* constructors ------------------------------------------------------
diff --git a/GeoModelVisualization/VP1HEPVis/src/SbTwistTrapFlatSide.cxx b/GeoModelVisualization/GXHepVis/src/SbTwistTrapFlatSide.cxx
similarity index 99%
rename from GeoModelVisualization/VP1HEPVis/src/SbTwistTrapFlatSide.cxx
rename to GeoModelVisualization/GXHepVis/src/SbTwistTrapFlatSide.cxx
index 7f63c25c1..092216fab 100644
--- a/GeoModelVisualization/VP1HEPVis/src/SbTwistTrapFlatSide.cxx
+++ b/GeoModelVisualization/GXHepVis/src/SbTwistTrapFlatSide.cxx
@@ -6,7 +6,7 @@
 // Adapted from Geant4 to GMEX
 // --------------------------------------------------------------------
 
-#include "VP1HEPVis/SbTwistTrapFlatSide.h"
+#include "GXHepVis/SbTwistTrapFlatSide.h"
 #include <cmath>
 #include <iostream> 
 
diff --git a/GeoModelVisualization/VP1HEPVis/src/SbTwistTrapParallelSide.cxx b/GeoModelVisualization/GXHepVis/src/SbTwistTrapParallelSide.cxx
similarity index 98%
rename from GeoModelVisualization/VP1HEPVis/src/SbTwistTrapParallelSide.cxx
rename to GeoModelVisualization/GXHepVis/src/SbTwistTrapParallelSide.cxx
index bc20ad016..fc33b5117 100644
--- a/GeoModelVisualization/VP1HEPVis/src/SbTwistTrapParallelSide.cxx
+++ b/GeoModelVisualization/GXHepVis/src/SbTwistTrapParallelSide.cxx
@@ -9,7 +9,7 @@
 #include <cmath>
 #include <iostream>
 
-#include "VP1HEPVis/SbTwistTrapParallelSide.h"
+#include "GXHepVis/SbTwistTrapParallelSide.h"
 
 //=====================================================================
 //* constructors ------------------------------------------------------
diff --git a/GeoModelVisualization/VP1HEPVis/src/SoCons.cxx b/GeoModelVisualization/GXHepVis/src/SoCons.cxx
similarity index 96%
rename from GeoModelVisualization/VP1HEPVis/src/SoCons.cxx
rename to GeoModelVisualization/GXHepVis/src/SoCons.cxx
index 9e46376af..52219f4f1 100644
--- a/GeoModelVisualization/VP1HEPVis/src/SoCons.cxx
+++ b/GeoModelVisualization/GXHepVis/src/SoCons.cxx
@@ -11,7 +11,7 @@
 /*--------------------------------------------------------------------------*/
 
 // this :
-#include <VP1HEPVis/nodes/SoCons.h>
+#include <GXHepVis/nodes/SoCons.h>
 #include "RevolutionSurfaceUtil.h"
 
 #include <cassert>
@@ -48,7 +48,6 @@ SoCons::SoCons() {
   SO_NODE_ADD_FIELD(fDPhi,             ((float)(2*M_PI)));
   SO_NODE_ADD_FIELD(smoothDraw,          (TRUE));
   SO_NODE_ADD_FIELD(pOverrideNPhi,       (0));
-  SO_NODE_ADD_FIELD(alternateRep,        (NULL));
   m_children = new SoChildList(this);
 
   setNodeType(EXTENSION);
@@ -429,18 +428,3 @@ void SoCons::generateChildren() {
   m_children->append(sep);
 }
 
-// generateAlternateRep
-void SoCons::generateAlternateRep() {
-
-  // This routine sets the alternate representation to the child
-  // list of this mode.
-
-  if (m_children->getLength() == 0) generateChildren();
-  updateChildren();
-  alternateRep.setValue((SoSeparator *)  ( *m_children)[0]);
-}
-
-// clearAlternateRep
-void SoCons::clearAlternateRep() {
-  alternateRep.setValue(NULL);
-}
diff --git a/GeoModelVisualization/VP1HEPVis/src/SoGL2PSAction.cxx b/GeoModelVisualization/GXHepVis/src/SoGL2PSAction.cxx
similarity index 99%
rename from GeoModelVisualization/VP1HEPVis/src/SoGL2PSAction.cxx
rename to GeoModelVisualization/GXHepVis/src/SoGL2PSAction.cxx
index 07a2dba0f..e5ca272f3 100644
--- a/GeoModelVisualization/VP1HEPVis/src/SoGL2PSAction.cxx
+++ b/GeoModelVisualization/GXHepVis/src/SoGL2PSAction.cxx
@@ -3,7 +3,7 @@
 */
 
 // this :
-#include <VP1HEPVis/actions/SoGL2PSAction.h>
+#include <GXHepVis/actions/SoGL2PSAction.h>
 
 // Inventor :
 #include <Inventor/nodes/SoDrawStyle.h>
@@ -15,7 +15,7 @@
 //LD HEPVis specific #include <HEPVis/SbStyles.h>
 #include "SbStringHelpers.h"
 
-#include "VP1HEPVis/gl2ps.h"
+#include "GXHepVis/gl2ps.h"
 
 #include <stdio.h>
 
diff --git a/GeoModelVisualization/VP1HEPVis/src/SoGenericBox.cxx b/GeoModelVisualization/GXHepVis/src/SoGenericBox.cxx
similarity index 89%
rename from GeoModelVisualization/VP1HEPVis/src/SoGenericBox.cxx
rename to GeoModelVisualization/GXHepVis/src/SoGenericBox.cxx
index 3def8d508..70ccc7a3b 100644
--- a/GeoModelVisualization/VP1HEPVis/src/SoGenericBox.cxx
+++ b/GeoModelVisualization/GXHepVis/src/SoGenericBox.cxx
@@ -12,7 +12,7 @@
 //                                                            //
 ////////////////////////////////////////////////////////////////
 
-#include "VP1HEPVis/nodes/SoGenericBox.h"
+#include "GXHepVis/nodes/SoGenericBox.h"
 
 #include <Inventor/SbBox.h>
 #include <Inventor/actions/SoPickAction.h>
@@ -75,7 +75,6 @@ SoGenericBox::SoGenericBox()
   SO_NODE_CONSTRUCTOR(SoGenericBox);
   SO_NODE_ADD_FIELD(drawEdgeLines, (false));
   SO_NODE_ADD_FIELD(forceEdgeLinesInBaseColour, (true));
-  SO_NODE_ADD_FIELD(alternateRep,(NULL));
   setNodeType(EXTENSION);
 }
 
@@ -88,7 +87,6 @@ SoGenericBox::~SoGenericBox()
 
 //____________________________________________________________________
 void SoGenericBox::generatePrimitives(SoAction *action) {
-
   if (!m_points)
     setupDefaultPoints();
 
@@ -349,7 +347,6 @@ void SoGenericBox::setParametersForTrapezoid( float dz, float theta, float phi,
   pointsUpdated();
 }
 
-
 //____________________________________________________________________
 void SoGenericBox::setGenericParameters( float x0, float y0, float z0,
 					 float x1, float y1, float z1,
@@ -376,22 +373,24 @@ void SoGenericBox::setGenericParameters( float x0, float y0, float z0,
 void SoGenericBox::pointsUpdated()
 {
   //Normals:
-  if (!m_normals)
+  //if (!m_normals)
     m_normals = new float[SOGENERICBOX_NFACES*3];
+  
+  std::cout << " " << std::endl;
   for (int iface = 0; iface < SOGENERICBOX_NFACES; ++iface) {
     const int index_v1 = sogenericbox_vindices[iface*4+0];
     const int index_v2 = sogenericbox_vindices[iface*4+1];
     const int index_v3 = sogenericbox_vindices[iface*4+2];
-
-    //Figure out normal: (v2-v1)(x)(v3-v1)
+        
+    //Figure out normal: (v2-v1)(x)(v3-v1) // Use cross-product to find out norm of a plane
     const double v1X(m_points[index_v1*3+0]), v1Y(m_points[index_v1*3+1]), v1Z(m_points[index_v1*3+2]);
     const double edge1X(m_points[index_v2*3+0]-v1X), edge1Y(m_points[index_v2*3+1]-v1Y), edge1Z(m_points[index_v2*3+2]-v1Z);
     const double edge2X(m_points[index_v3*3+0]-v1X), edge2Y(m_points[index_v3*3+1]-v1Y), edge2Z(m_points[index_v3*3+2]-v1Z);
 
-    double nx(edge1Y*edge2Z-edge1Z*edge2Y);
-    double ny(edge1Z*edge2X-edge1X*edge2Z);
-    double nz(edge1X*edge2Y-edge1Y*edge2X);
-    double nl(nx*nx+ny*ny+nz*nz);
+    double nx(edge1Y*edge2Z-edge1Z*edge2Y);  // x component of norm
+    double ny(edge1Z*edge2X-edge1X*edge2Z);  // y component of norm
+    double nz(edge1X*edge2Y-edge1Y*edge2X);  // z component of norm
+    double nl(nx*nx+ny*ny+nz*nz);            // length of norm
     if (nl<=0) {
       std::cout<<"SoGenericBox::Error Could not calculate normal due to degenerate face edge"<<std::endl;
       nx=1.0;ny=0.0;nz=0.0;nl=1;
@@ -404,6 +403,7 @@ void SoGenericBox::pointsUpdated()
     m_normals[iface*3+0] = nx*s;
     m_normals[iface*3+1] = ny*s;
     m_normals[iface*3+2] = nz*s;
+    
   }
 
   //BBox:
@@ -421,49 +421,3 @@ void SoGenericBox::pointsUpdated()
   drawEdgeLines.touch();
 }
 
-
-///////////////////////////////
-//  Stuff for alternate rep  //
-///////////////////////////////
-
-//____________________________________________________________________
-void SoGenericBox::generateAlternateRep()
-{
-  if (!m_points)
-    setupDefaultPoints();
-  if (alternateRep.getValue())
-    clearAlternateRep();
-  SoSeparator * sep = new SoSeparator;
-
-  //Vertice coordinates:
-  SoVertexProperty *vertices = new SoVertexProperty();
-  for (int i=0;i<SOGENERICBOX_NPOINTS;++i)
-    vertices->vertex.set1Value ( i, m_points[i*3+0],m_points[i*3+1],m_points[i*3+2] );
-  SoIndexedFaceSet * faceset = new SoIndexedFaceSet;
-  faceset->coordIndex.setValues(0,5*6, sogenericbox_vindices_foraltrepfaces);
-  faceset->vertexProperty = vertices;
-  sep->addChild(faceset);
-
-  if (drawEdgeLines.getValue()) {
-//Disable the lightmodel now since we in any case gets baselightning with the lineset defined this way...
-//     if (forceEdgeLinesInBaseColour.getValue()) {
-//       SoLightModel * lm = new SoLightModel;//Fixme: share
-//       lm->model = SoLightModel::BASE_COLOR;
-//       sep->addChild(lm);
-//     }
-    SoIndexedLineSet * lineset = new SoIndexedLineSet;
-    lineset->coordIndex.setValues(0,20,sogenericbox_vindices_foraltreplines);
-    lineset->vertexProperty = vertices;
-    sep->addChild(lineset);
-  }
-
-  alternateRep.setValue(sep);
-
-}
-
-//____________________________________________________________________
-void SoGenericBox::clearAlternateRep()
-{
-  alternateRep.setValue(NULL);
-  //Hmm... no ref/unref??
-}
diff --git a/GeoModelVisualization/VP1HEPVis/src/SoLAr.cxx b/GeoModelVisualization/GXHepVis/src/SoLAr.cxx
similarity index 97%
rename from GeoModelVisualization/VP1HEPVis/src/SoLAr.cxx
rename to GeoModelVisualization/GXHepVis/src/SoLAr.cxx
index c661e0c28..bd283a199 100644
--- a/GeoModelVisualization/VP1HEPVis/src/SoLAr.cxx
+++ b/GeoModelVisualization/GXHepVis/src/SoLAr.cxx
@@ -10,7 +10,7 @@
 /*                                                                          */
 /*--------------------------------------------------------------------------*/
 
-#include <VP1HEPVis/nodes/SoLAr.h>
+#include <GXHepVis/nodes/SoLAr.h>
 #include "RevolutionSurfaceUtil.h"
 
 #include <iostream>
@@ -44,7 +44,6 @@ SoLAr::SoLAr() {
   SO_NODE_ADD_FIELD(fDPhi,             ((float)(2*M_PI)));
   SO_NODE_ADD_FIELD(smoothDraw,          (TRUE));
   SO_NODE_ADD_FIELD(pOverrideNPhi,       (0));
-  SO_NODE_ADD_FIELD(alternateRep,        (NULL));
   m_children = new SoChildList(this);
 
   float rMinDef[]={10.0,  15.0, 10.0};
@@ -490,18 +489,3 @@ void SoLAr::generateChildren() {
 #endif
 }
 
-// generateAlternateRep
-void SoLAr::generateAlternateRep() {
-
-  // This routine sets the alternate representation to the child
-  // list of this mode.
-
-  if (m_children->getLength() == 0) generateChildren();
-  updateChildren();
-  alternateRep.setValue((SoSeparator *)  ( *m_children)[0]);
-}
-
-// clearAlternateRep
-void SoLAr::clearAlternateRep() {
-  alternateRep.setValue(NULL);
-}
diff --git a/GeoModelVisualization/VP1HEPVis/src/SoPcons.cxx b/GeoModelVisualization/GXHepVis/src/SoPcons.cxx
similarity index 69%
rename from GeoModelVisualization/VP1HEPVis/src/SoPcons.cxx
rename to GeoModelVisualization/GXHepVis/src/SoPcons.cxx
index 658b9afc6..3d45e584e 100644
--- a/GeoModelVisualization/VP1HEPVis/src/SoPcons.cxx
+++ b/GeoModelVisualization/GXHepVis/src/SoPcons.cxx
@@ -7,12 +7,8 @@
 /* Node:             SoPcons                                                */
 /* Description:      Represents the G4Pcons Geant Geometry entity           */
 /* Author:           Joe Boudreau Nov 11 1996                               */
-/* Update:  Giorgi   Gvaberidze (ggvaberi@cern.ch)                          */ 
-/*          April    2011                                                   */
-/*          Fixed:   Generating of alternate rep,  for export in *.iv file  */
-/*                                                                          */
 /*--------------------------------------------------------------------------*/
-#include <VP1HEPVis/nodes/SoPcons.h>
+#include <GXHepVis/nodes/SoPcons.h>
 #include "RevolutionSurfaceUtil.h"
 
 #include <cassert>
@@ -47,7 +43,6 @@ SoPcons::SoPcons() {
   SO_NODE_ADD_FIELD(fDPhi,             ((float)(2*M_PI)));
   SO_NODE_ADD_FIELD(smoothDraw,          (TRUE));
   SO_NODE_ADD_FIELD(pOverrideNPhi,       (0));
-  SO_NODE_ADD_FIELD(alternateRep,        (NULL));
   SO_NODE_ADD_FIELD(drawEdgeLines,       (false));
 
   m_children = new SoChildList(this);
@@ -576,261 +571,3 @@ void SoPcons::generateChildren() {
 #endif
 }
 
-// generateAlternateRep
-#include <vector>
-
-void SoPcons::generateAlternateRep() {
-  
-  // This routine sets the alternate representation to the child
-  // list of this mode.
-  
-  //if (m_children->getLength() == 0) generateChildren();
-  //updateChildren();
-  //  alternateRep.setValue((SoSeparator *)  ( *m_children)[0]);
-
-
-  /*         updated for generate fullfill alternaterep 
-   ***********************************************
-   As First we collect point and triangle strip 
-   bounds same as in draw function.
-   there is copied draw function contents and 
-   replased unused part;
-
-   Source code was taked from render part, and modified
-   for collect nessesary information, and build alternate
-   geometry.
-   **********************************************
-   */
-  const int NPHI = 96; 
-
-  // This variable is used to store each vertex
-  SoPrimitiveVertex pv;
-
-  //For collect points in Pcon geometry chunk
-  std::vector<SoPrimitiveVertex> vls; //Vertex List
-
-  //For collect all triangles
-  std::vector<SoPrimitiveVertex> fls; //Face list. face here is qudrangle
-
-  // See if we have to use a texture coordinate function,
-  // rather than generating explicit texture coordinates.
-
-  SbVec4f texCoord;
-  texCoord[2] = 0.0;
-  texCoord[3] = 1.0;
-  SbVec3f point, normal;
-
-  ///////////////////////////////////////////////////////
-  //-----------------------------------------------------
-#define N_GEN_VERTEX(ls, pv,x,y,z,s,t,nx,ny,nz)		\
-  point.setValue((float)(x),(float)(y),(float)(z));     \
-  normal.setValue((float)(nx),(float)(ny),(float)(nz)); \
-  texCoord[0]=(float)(s);                               \
-  texCoord[1]=(float)(t);                               \
-  pv.setPoint(point);                                   \
-  pv.setNormal(normal);                                 \
-  pv.setTextureCoords(texCoord);                        \
-  ls.push_back(pv);
-  //-----------------------------------------------------
-  ///////////////////////////////////////////////////////
-  if (fRmin.getNum()!=fRmax.getNum() || fRmax.getNum() != fDz.getNum()) {
-    return;
-  }
-  
-  int nSeg = fRmin.getNum()-1;
-  if (nSeg<1)  {
-    return;
-  }
-  
-  for (int p=0;p<nSeg;p++) {
-    
-    double rMin1= fRmin[p];
-    double rMin2= fRmin[p+1];
-    
-    double rMax1= fRmax[p];
-    double rMax2= fRmax[p+1];
-    
-    double zMin = fDz[p];
-    double zMax= fDz[p+1];
-    
-    double deltaPhi = fDPhi.getValue()/NPHI;
-    double phi0     = fSPhi.getValue();
-    double phi1     = phi0 + fDPhi.getValue();
-    double cosPhi0  = cos(phi0);
-    double sinPhi0  = sin(phi0);
-    double cosPhi1  = cos(phi1);
-    double sinPhi1  = sin(phi1);
-    double cosDeltaPhi = cos(deltaPhi);
-    double sinDeltaPhi = sin(deltaPhi);
-    
-    int    i;
-    double sinPhi;
-    double cosPhi;
-    
-    const bool noPhiCutout=fabs(fDPhi.getValue())==0.F || fabs(fabs(fDPhi.getValue())-2.0*M_PI)<0.01; // FIXME - better way to do this?
-    
-    //
-    // The outer surface!
-    //
-    double dR =rMax2-rMax1;
-    double dZ =zMax-zMin;
-    double cosTheta = -dR/sqrt(dR*dR+dZ*dZ);
-    double sinTheta =  dZ/sqrt(dR*dR+dZ*dZ);
-    
-    sinPhi=sinPhi0;
-    cosPhi=cosPhi0;
-    for (i = 0; i<=NPHI; i++) {
-      N_GEN_VERTEX(vls,pv,rMax2*cosPhi,rMax2*sinPhi,zMax,0.0,0.0,sinTheta*cosPhi,sinTheta*sinPhi,cosTheta);
-      N_GEN_VERTEX(vls,pv,rMax1*cosPhi,rMax1*sinPhi,zMin,1.0,1.0,sinTheta*cosPhi,sinTheta*sinPhi,cosTheta);
-      inc(sinPhi, cosPhi, sinDeltaPhi, cosDeltaPhi);
-    }
-
-    for(i = 0; i < ((int)vls.size() - 2); i += 2){
-      fls.push_back(vls[i + 0]);
-      fls.push_back(vls[i + 1]);
-      fls.push_back(vls[i + 3]);
-      fls.push_back(vls[i + 2]);
-    }
-    vls.clear();
-    
-    //
-    // The inner surface!
-    //
-    sinPhi=sinPhi0;
-    cosPhi=cosPhi0;
-    
-     dR =rMin2-rMin1;
-     dZ =zMax-zMin;
-     cosTheta = -dR/sqrt(dR*dR+dZ*dZ);
-     sinTheta =  dZ/sqrt(dR*dR+dZ*dZ);
-    
-    for (i = 0; i<=NPHI; i++) {
-      N_GEN_VERTEX(vls,pv,rMin2*cosPhi,rMin2*sinPhi,zMax,0.0,0.0,-cosPhi*sinTheta,-sinPhi*sinTheta,-cosTheta);
-      N_GEN_VERTEX(vls,pv,rMin1*cosPhi,rMin1*sinPhi,zMin,1.0,1.0,-cosPhi*sinTheta,-sinPhi*sinTheta,-cosTheta);
-      inc(sinPhi, cosPhi, sinDeltaPhi, cosDeltaPhi);
-    }
-    for(i = 0; i < ((int)vls.size() - 2); i += 2){
-      fls.push_back(vls[i + 1]);
-      fls.push_back(vls[i + 0]);
-      fls.push_back(vls[i + 2]);
-      fls.push_back(vls[i + 3]);
-    }
-    vls.clear();
-    
-    
-    if (!noPhiCutout) {
-        //
-        // The end
-        //
-        sinPhi=sinPhi0;
-        cosPhi=cosPhi0;
-        N_GEN_VERTEX(vls, pv,rMax2*cosPhi,rMax2*sinPhi,zMax,0.0,0.0,sinPhi,-cosPhi,0);
-        N_GEN_VERTEX(vls, pv,rMax1*cosPhi,rMax1*sinPhi,zMin,1.0,1.0,sinPhi,-cosPhi,0);
-        N_GEN_VERTEX(vls, pv,rMin2*cosPhi,rMin2*sinPhi,zMax,1.0,0.0,sinPhi,-cosPhi,0);
-        N_GEN_VERTEX(vls, pv,rMin1*cosPhi,rMin1*sinPhi,zMin,0.0,1.0,sinPhi,-cosPhi,0);
-        fls.push_back(vls[1]);
-        fls.push_back(vls[0]);
-        fls.push_back(vls[2]);
-        fls.push_back(vls[3]);
-	vls.clear();
-
-        //
-        // The other end
-        //
-        sinPhi=sinPhi1;
-        cosPhi=cosPhi1;
-        N_GEN_VERTEX(vls, pv,rMax2*cosPhi,rMax2*sinPhi, zMax,0.0,0.0,-sinPhi,+cosPhi,0);
-        N_GEN_VERTEX(vls, pv,rMax1*cosPhi,rMax1*sinPhi, zMin,1.0,1.0,-sinPhi,+cosPhi,0);
-        N_GEN_VERTEX(vls, pv,rMin2*cosPhi,rMin2*sinPhi, zMax,1.0,0.0,-sinPhi,+cosPhi,0);
-        N_GEN_VERTEX(vls, pv,rMin1*cosPhi,rMin1*sinPhi, zMin,0.0,1.0,-sinPhi,+cosPhi,0);
-        fls.push_back(vls[0]);
-        fls.push_back(vls[1]);
-        fls.push_back(vls[3]);
-        fls.push_back(vls[2]);
-        vls.clear();
-    }
-    if (p==(nSeg-1)) {
-      //
-      // The outer surface at z=+PDZ
-      //
-      sinPhi=sinPhi0;
-      cosPhi=cosPhi0;
-      for (i = 0; i<=NPHI; i++) {
-        N_GEN_VERTEX(vls, pv,rMin2*cosPhi,rMin2*sinPhi,zMax,0.0,0.0,0,0,1);
-        N_GEN_VERTEX(vls, pv,rMax2*cosPhi,rMax2*sinPhi,zMax,1.0,1.0,0,0,1);
-        inc(sinPhi, cosPhi, sinDeltaPhi, cosDeltaPhi);
-      }
-      for(i = 0; i < ((int)vls.size() - 2); i += 2){
-        fls.push_back(vls[i + 0]);
-        fls.push_back(vls[i + 1]);
-        fls.push_back(vls[i + 3]);
-        fls.push_back(vls[i + 2]);
-      }
-      vls.clear();
-    }
-    if (p==0) {
-      //
-      // The outer surface at z=-PDZ
-      //
-      sinPhi=sinPhi0;
-      cosPhi=cosPhi0;
-      for (i = 0; i<=NPHI; i++) {
-        N_GEN_VERTEX(vls, pv,rMin1*cosPhi,rMin1*sinPhi,zMin,0.0,0.0,0,0,-1);
-        N_GEN_VERTEX(vls, pv,rMax1*cosPhi,rMax1*sinPhi,zMin,1.0,1.0,0,0,-1);
-        inc(sinPhi, cosPhi, sinDeltaPhi, cosDeltaPhi);
-      }
-      for(i = 0; i < ((int)vls.size() - 2); i += 2){
-        fls.push_back(vls[i + 1]);
-        fls.push_back(vls[i + 0]);
-        fls.push_back(vls[i + 2]);
-        fls.push_back(vls[i + 3]);
-      }
-      vls.clear();
-    }
-  }
-  /*
-   *********************************************
-   After finish colecting points of quadrangles, 
-   must be builded one monolit geometry,
-   with indexed triangles
-   *********************************************
-   */
-  int numFaces = fls.size() / 4;  //Becouse used quadrangular primitives
-  if(numFaces < 0) 
-   numFaces = 0;
-
-  SoVertexProperty *vertices = new SoVertexProperty();
-  for(int i = 0; i < (int)fls.size(); i++){
-    vertices->vertex.set1Value (i, fls[i].getPoint()[0], 
-				   fls[i].getPoint()[1], 
-				   fls[i].getPoint()[2]);
-  }
-  fls.clear();   //clearing collected vertices
-
-  int* faces = new int[5 * numFaces];
-  fprintf(stderr, "\nallocate  Faces: %i", numFaces);
-  for(int i = 0; i < numFaces; i++){
-    faces[5 * i]     = 4 * i;
-    faces[5 * i + 1] = 4 * i + 1;
-    faces[5 * i + 2] = 4 * i + 2;
-    faces[5 * i + 3] = 4 * i + 3;
-    faces[5 * i + 4] = -1;
-  }
-
-  SoIndexedFaceSet * faceset = new SoIndexedFaceSet;
-  faceset->coordIndex.setValues(0, 5 * numFaces, faces);
-  delete [] faces;
-  faceset->vertexProperty = vertices;
-  alternateRep.setValue(faceset);
-  fprintf(stderr, "\n");
-  /*
-   *********************************************
-   Finish
-   *********************************************
-   */
-}
-
-// clearAlternateRep
-void SoPcons::clearAlternateRep() {
-  alternateRep.setValue(NULL);
-}
diff --git a/GeoModelVisualization/VP1HEPVis/src/SoPolyhedron.cxx b/GeoModelVisualization/GXHepVis/src/SoPolyhedron.cxx
similarity index 90%
rename from GeoModelVisualization/VP1HEPVis/src/SoPolyhedron.cxx
rename to GeoModelVisualization/GXHepVis/src/SoPolyhedron.cxx
index e49ebd574..42c18a02f 100644
--- a/GeoModelVisualization/VP1HEPVis/src/SoPolyhedron.cxx
+++ b/GeoModelVisualization/GXHepVis/src/SoPolyhedron.cxx
@@ -18,7 +18,7 @@
 //                                                            //
 ////////////////////////////////////////////////////////////////
 
-#include <VP1HEPVis/nodes/SoPolyhedron.h>
+#include <GXHepVis/nodes/SoPolyhedron.h>
 
 #include <Inventor/SbBox.h>
 #include <Inventor/actions/SoAction.h>
@@ -34,11 +34,7 @@
 #include <Inventor/C/glue/gl.h>
 
 #include "SbMath.h"
-#include <VP1HEPVis/SbPolyhedron.h>
-
-//// debug messages
-//#include "VP1Base/VP1Msg.h"
-//#include <QString>
+#include <GXHepVis/SbPolyhedron.h>
 
 
 SO_NODE_SOURCE(SoPolyhedron)
@@ -63,7 +59,6 @@ SoPolyhedron::SoPolyhedron(
   SO_NODE_CONSTRUCTOR(SoPolyhedron);
   //  SO_NODE_ADD_FIELD(solid,(TRUE));
   //  SO_NODE_ADD_FIELD(reducedWireFrame,(TRUE));
-  SO_NODE_ADD_FIELD(alternateRep,(NULL));
   setNodeType(EXTENSION);
 }
 //////////////////////////////////////////////////////////////////////////////
@@ -77,7 +72,6 @@ SoPolyhedron::SoPolyhedron(
   SO_NODE_CONSTRUCTOR(SoPolyhedron);
   //  SO_NODE_ADD_FIELD(solid,(TRUE));
   //  SO_NODE_ADD_FIELD(reducedWireFrame,(TRUE));
-  SO_NODE_ADD_FIELD(alternateRep,(NULL));
 
   m_polyhedron = new SbPolyhedron(aPolyhedron);
   setNodeType(EXTENSION);
@@ -94,7 +88,6 @@ SoPolyhedron::SoPolyhedron(
   SO_NODE_CONSTRUCTOR(SoPolyhedron);
   //  SO_NODE_ADD_FIELD(solid,(TRUE));
   //  SO_NODE_ADD_FIELD(reducedWireFrame,(TRUE));
-  SO_NODE_ADD_FIELD(alternateRep,(NULL));
 
   m_polyhedron = new SbPolyhedron(*aPolyhedron);
   setNodeType(EXTENSION);
@@ -374,55 +367,6 @@ void SoPolyhedron::getPrimitiveCount(SoGetPrimitiveCountAction * action)
 }
 //*/
 
-///*
-void SoPolyhedron::generateAlternateRep()
-{
- if (alternateRep.getValue())
-  clearAlternateRep();
- if( m_polyhedron && ( m_polyhedron->GetNoFacets() > 0 ) ){
-  //SoSeparator *sep = new SoSeparator;
-  SoVertexProperty *vertices = new SoVertexProperty();
-
-  //Retreive geometry from polyhedron
-  int vno = m_polyhedron->GetNoVertices();
-  for(int i = 0; i < vno; i++){
-   HVPoint3D vertex;
-   vertex = m_polyhedron->GetVertex(i + 1);
-   vertices->vertex.set1Value (i, vertex[0], vertex[1], vertex[2]);
-  }
-
-  int  fno = m_polyhedron->GetNoFacets();
-  int  fcr = 0;
-  int* aface = new int[8 * fno];
-  for(int i = 0; i < fno; i++){
-	  int n, inodes[4];
-	  //SbVec3d nr = m_polyhedron->GetNormal(i + 1); // not used, gives warning, commenting out:
-	  //---
-	  m_polyhedron->GetFacet(i + 1, n, inodes);
-	  aface[fcr] = (inodes[0] <= vno) ? (inodes[0] - 1) : (0); fcr++;
-	  aface[fcr] = (inodes[1] <= vno) ? (inodes[1] - 1) : (0); fcr++;
-	  aface[fcr] = (inodes[2] <= vno) ? (inodes[2] - 1) : (0); fcr++;
-	  if(n == 4) { aface[fcr] = (inodes[3] <= vno) ? (inodes[3] - 1) : (0); fcr++; }
-	  aface[fcr] = -1; fcr++;
-  }
-  SoIndexedFaceSet * faceset = new SoIndexedFaceSet;
-  faceset->coordIndex.setValues(0, fcr, aface);
-  delete [] aface;
-  faceset->vertexProperty = vertices;
-  //sep->addChild(faceset);
-  alternateRep.setValue(faceset);
- }
-}
-//*/
-
-//____________________________________________________________________
-///*
-void SoPolyhedron::clearAlternateRep()
-{
-  alternateRep.setValue(NULL);
-  //Hmm... no ref/unref??
-}
-//*/
 
 //____________________________________________________________________
 ///*
diff --git a/GeoModelVisualization/VP1HEPVis/src/SoTessellated.cxx b/GeoModelVisualization/GXHepVis/src/SoTessellated.cxx
similarity index 72%
rename from GeoModelVisualization/VP1HEPVis/src/SoTessellated.cxx
rename to GeoModelVisualization/GXHepVis/src/SoTessellated.cxx
index 343500eff..5863d7a54 100644
--- a/GeoModelVisualization/VP1HEPVis/src/SoTessellated.cxx
+++ b/GeoModelVisualization/GXHepVis/src/SoTessellated.cxx
@@ -2,7 +2,7 @@
   Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
 */
 
-#include "VP1HEPVis/nodes/SoTessellated.h"
+#include "GXHepVis/nodes/SoTessellated.h"
 
 #include <Inventor/SbBox.h>
 #include <Inventor/actions/SoPickAction.h>
@@ -31,7 +31,6 @@ SoTessellated::SoTessellated()
   SO_NODE_CONSTRUCTOR(SoTessellated);
   SO_NODE_ADD_FIELD(drawEdgeLines, (false));
   SO_NODE_ADD_FIELD(forceEdgeLinesInBaseColour, (true));
-  SO_NODE_ADD_FIELD(alternateRep,(NULL));
   setNodeType(EXTENSION);
 }
 
@@ -193,65 +192,3 @@ void SoTessellated::computeBBox(SoAction *, SbBox3f &box, SbVec3f &center ){
   center = m_center;
 }
 
-//____________________________________________________________________
-void SoTessellated::generateAlternateRep()
-{
-  if(m_points.size()==0)
-    setupDefaultPoints();
-  if (alternateRep.getValue())
-    clearAlternateRep();
-
-  SoSeparator * sep = new SoSeparator;
-
-  // Faceset representing the shape
-  SoVertexProperty* vertices = new SoVertexProperty();
-  vertices->normalBinding.setValue( SoVertexProperty::PER_VERTEX );
-  vertices->materialBinding.setValue( SoVertexProperty::OVERALL ); // so the face is enlightened on both face
-  for(size_t i=0;i<m_normals.size();++i)
-    vertices->vertex.set1Value(i,m_points[i*3+0],m_points[i*3+1],m_points[i*3+2]);
-  SoIndexedFaceSet* faceset = new SoIndexedFaceSet;
-  int j=0;
-  for(size_t i=0;i<m_normals.size();++i) {
-    faceset->coordIndex.set1Value(j++,i);
-    if((i>1) && ((i-2)%3==0)) {
-      faceset->coordIndex.set1Value(j++,SO_END_FACE_INDEX);
-    }
-  }
-
-  faceset->vertexProperty = vertices;
-  sep->addChild(faceset);
-
-  // Lineset representing the outline
-  //
-  // -- ToDo: this can be optimized. We are currently drawing edges twice
-  // -- and we could also eliminate 'diagonal' lines coming from
-  // -- quadrangular shapes
-  //
-  if (drawEdgeLines.getValue()) {
-    SoVertexProperty* verticesL = new SoVertexProperty();
-    SoIndexedLineSet* lineset = new SoIndexedLineSet;
-    int kk=0, jj=0;
-    for(size_t i=0;i<m_points.size()-9;i+=9) {
-      verticesL->vertex.set1Value(kk,m_points[i],m_points[i+1],m_points[i+2]);
-      lineset->coordIndex.set1Value(jj++,kk++);
-      verticesL->vertex.set1Value(kk,m_points[i+3],m_points[i+4],m_points[i+5]);
-      lineset->coordIndex.set1Value(jj++,kk++);
-      verticesL->vertex.set1Value(kk,m_points[i+6],m_points[i+7],m_points[i+8]);
-      lineset->coordIndex.set1Value(jj++,kk++);
-      verticesL->vertex.set1Value(kk,m_points[i],m_points[i+1],m_points[i+2]);
-      lineset->coordIndex.set1Value(jj++,kk++);
-      lineset->coordIndex.set1Value(jj++,SO_END_LINE_INDEX);
-    }
-    lineset->vertexProperty = verticesL;
-    sep->addChild(lineset);
-  }
-
-  alternateRep.setValue(sep);
-}
-
-//____________________________________________________________________
-void SoTessellated::clearAlternateRep()
-{
-  alternateRep.setValue(NULL);
-}
-
diff --git a/GeoModelVisualization/VP1HEPVis/src/SoTorus.cxx b/GeoModelVisualization/GXHepVis/src/SoTorus.cxx
similarity index 98%
rename from GeoModelVisualization/VP1HEPVis/src/SoTorus.cxx
rename to GeoModelVisualization/GXHepVis/src/SoTorus.cxx
index 26faa1075..19714a2ad 100644
--- a/GeoModelVisualization/VP1HEPVis/src/SoTorus.cxx
+++ b/GeoModelVisualization/GXHepVis/src/SoTorus.cxx
@@ -11,7 +11,7 @@
 /*--------------------------------------------------------------------------*/
 
 // this :
-#include <VP1HEPVis/nodes/SoTorus.h>
+#include <GXHepVis/nodes/SoTorus.h>
 #include "RevolutionSurfaceUtil.h"
 
 #include <cassert>
@@ -80,7 +80,6 @@ SoTorus::SoTorus()
   SO_NODE_ADD_FIELD(fDPhi,             ((float)(2*M_PI)));
   SO_NODE_ADD_FIELD(smoothDraw,          (TRUE));
   SO_NODE_ADD_FIELD(pOverrideNPhi,       (0));
-  SO_NODE_ADD_FIELD(alternateRep,        (NULL));
   m_children = new SoChildList(this);
 
   setNodeType(EXTENSION);
@@ -792,22 +791,6 @@ void SoTorus::generateChildren() {
   */
 }
 
-// generateAlternateRep
-void SoTorus::generateAlternateRep() {
-
-  // This routine sets the alternate representation to the child
-  // list of this mode.
-
-  if (m_children->getLength() == 0) generateChildren();
-  updateChildren();
-  alternateRep.setValue((SoSeparator *)  ( *m_children)[0]);
-}
-
-// clearAlternateRep
-void SoTorus::clearAlternateRep() {
-  alternateRep.setValue(NULL);
-}
-
 
 // #undef SPHERE_NUM_SLICES
 // #undef SPHERE_NUM_STACKS
diff --git a/GeoModelVisualization/VP1HEPVis/src/SoTransparency.cxx b/GeoModelVisualization/GXHepVis/src/SoTransparency.cxx
similarity index 98%
rename from GeoModelVisualization/VP1HEPVis/src/SoTransparency.cxx
rename to GeoModelVisualization/GXHepVis/src/SoTransparency.cxx
index ac1a86dda..2b4fa5d99 100644
--- a/GeoModelVisualization/VP1HEPVis/src/SoTransparency.cxx
+++ b/GeoModelVisualization/GXHepVis/src/SoTransparency.cxx
@@ -16,7 +16,7 @@
 //                                                            //
 ////////////////////////////////////////////////////////////////
 
-#include "VP1HEPVis/nodes/SoTransparency.h"
+#include "GXHepVis/nodes/SoTransparency.h"
 #include <Inventor/actions/SoCallbackAction.h>
 #include <Inventor/actions/SoGLRenderAction.h>
 #include <Inventor/bundles/SoMaterialBundle.h>
diff --git a/GeoModelVisualization/VP1HEPVis/src/SoTubs.cxx b/GeoModelVisualization/GXHepVis/src/SoTubs.cxx
similarity index 97%
rename from GeoModelVisualization/VP1HEPVis/src/SoTubs.cxx
rename to GeoModelVisualization/GXHepVis/src/SoTubs.cxx
index e945d4f38..d01baad39 100644
--- a/GeoModelVisualization/VP1HEPVis/src/SoTubs.cxx
+++ b/GeoModelVisualization/GXHepVis/src/SoTubs.cxx
@@ -10,7 +10,7 @@
 /*                                                                          */
 /*--------------------------------------------------------------------------*/
 
-#include <VP1HEPVis/nodes/SoTubs.h>
+#include <GXHepVis/nodes/SoTubs.h>
 #include "RevolutionSurfaceUtil.h"
 
 #include <cassert>
@@ -50,7 +50,6 @@ SoTubs::SoTubs() {
   SO_NODE_ADD_FIELD(pSPhi,               (0));
   SO_NODE_ADD_FIELD(pDPhi,               ((float)(2*M_PI)));
   SO_NODE_ADD_FIELD(pOverrideNPhi,       (0));
-  SO_NODE_ADD_FIELD(alternateRep,        (NULL));
   SO_NODE_ADD_FIELD(drawEdgeLines,       (false));
 
   m_children = new SoChildList(this);
@@ -559,18 +558,3 @@ void SoTubs::generateChildren() {
   m_children->append(sep);
 }
 
-// generateAlternateRep
-void SoTubs::generateAlternateRep() {
-
-  // This routine sets the alternate representation to the child
-  // list of this mode.
-
-  if (m_children->getLength() == 0) generateChildren();
-  updateChildren();
-  alternateRep.setValue((SoSeparator *)  ( *m_children)[0]);
-}
-
-// clearAlternateRep
-void SoTubs::clearAlternateRep() {
-  alternateRep.setValue(NULL);
-}
diff --git a/GeoModelVisualization/VP1HEPVis/src/gl2ps.cxx b/GeoModelVisualization/GXHepVis/src/gl2ps.cxx
similarity index 99%
rename from GeoModelVisualization/VP1HEPVis/src/gl2ps.cxx
rename to GeoModelVisualization/GXHepVis/src/gl2ps.cxx
index c2834d5dd..696dc4df8 100644
--- a/GeoModelVisualization/VP1HEPVis/src/gl2ps.cxx
+++ b/GeoModelVisualization/GXHepVis/src/gl2ps.cxx
@@ -37,7 +37,7 @@
 // #define GL2PS_HAVE_ZLIB
 
 
-#include "VP1HEPVis/gl2ps.h"
+#include "GXHepVis/gl2ps.h"
 
 #include <math.h>
 #include <string.h>
diff --git a/GeoModelVisualization/VP1Base/CMakeLists.txt b/GeoModelVisualization/VP1Base/CMakeLists.txt
index 0118b8277..acb7e4d3a 100644
--- a/GeoModelVisualization/VP1Base/CMakeLists.txt
+++ b/GeoModelVisualization/VP1Base/CMakeLists.txt
@@ -11,11 +11,11 @@ add_library( GXBase SHARED ${SOURCES} ${HEADERS} ${UIS} ${RCS} )
 if (GEOMODEL_USE_QT6)
   target_link_libraries( GXBase
      PUBLIC Coin::Coin Qt${QT_VERSION}::Core Qt${QT_VERSION}::Gui Qt${QT_VERSION}::Widgets Qt${QT_VERSION}::Core5Compat SoQt::SoQt
-     PRIVATE Qt${QT_VERSION}::PrintSupport Qt${QT_VERSION}::OpenGL GXHEPVis )
+     PRIVATE Qt${QT_VERSION}::PrintSupport Qt${QT_VERSION}::OpenGL GXHepVis )
 else()
   target_link_libraries( GXBase
      PUBLIC Coin::Coin Qt${QT_VERSION}::Core Qt${QT_VERSION}::Gui Qt${QT_VERSION}::Widgets SoQt::SoQt
-     PRIVATE Qt${QT_VERSION}::PrintSupport Qt${QT_VERSION}::OpenGL GXHEPVis )
+     PRIVATE Qt${QT_VERSION}::PrintSupport Qt${QT_VERSION}::OpenGL GXHepVis )
 endif()
 
 target_include_directories( GXBase PUBLIC
diff --git a/GeoModelVisualization/VP1Base/VP1Base/VP1ExaminerViewer.h b/GeoModelVisualization/VP1Base/VP1Base/VP1ExaminerViewer.h
index 89ec8ac52..bd2c7a553 100644
--- a/GeoModelVisualization/VP1Base/VP1Base/VP1ExaminerViewer.h
+++ b/GeoModelVisualization/VP1Base/VP1Base/VP1ExaminerViewer.h
@@ -71,8 +71,6 @@ public:
 	void startTour();
 	bool startTourEachEvent() const;
 	void startCustomTour();
-	void dumpSceneToFile(QString filename="");//empty file names causes file dialog to be launched
-	void dumpSceneToVRMLFile(QString filename="");//empty file names causes file dialog to be launched
 	void produceSVGImage(QString filename="");//empty file names causes file dialog to be launched
 	void produceEPSImage(QString filename="");//empty file names causes file dialog to be launched
 
diff --git a/GeoModelVisualization/VP1Base/src/VP1ExaminerViewer.cxx b/GeoModelVisualization/VP1Base/src/VP1ExaminerViewer.cxx
index ed7847e27..36d265745 100644
--- a/GeoModelVisualization/VP1Base/src/VP1ExaminerViewer.cxx
+++ b/GeoModelVisualization/VP1Base/src/VP1ExaminerViewer.cxx
@@ -27,9 +27,9 @@
 #include "VP1Base/VP1Settings.h"
 #include "VP1Base/VP1CustomTourEditor.h"
 #include "VP1Base/VP1CustomStereoEditor.h"
-#include "VP1HEPVis/VP1HEPVisUtils.h"
-#include "VP1HEPVis/actions/SoGL2PSAction.h"
-#include "VP1HEPVis/gl2ps.h"
+#include "GXHepVis/GXHepVisUtils.h"
+#include "GXHepVis/actions/SoGL2PSAction.h"
+#include "GXHepVis/gl2ps.h"
 
 #include <Inventor/nodes/SoSphere.h>
 #include <Inventor/nodes/SoGroup.h>
@@ -83,8 +83,6 @@ public:
   popup_bgdColAction(0),
   popup_ambientLightAction(0),
   popup_focalLengthAction(0),
-  popup_dumpSceneAction(0),
-  popup_dumpSceneVRMLAction(0),
   popup_toSVGAction(0),
   popup_toEPSAction(0),
   popup_resetCameraAction(0),
@@ -217,8 +215,6 @@ public:
 	QAction* popup_bgdColAction;
 	QAction* popup_ambientLightAction;
 	QAction* popup_focalLengthAction;
-	QAction* popup_dumpSceneAction;
-	QAction* popup_dumpSceneVRMLAction;
 	QAction* popup_toSVGAction;
 	QAction* popup_toEPSAction;
 	QAction* popup_resetCameraAction;
@@ -1932,8 +1928,6 @@ bool VP1ExaminerViewer::Imp::ensureMenuInit()
 	popup_hidedecorationsaction = advancedmenu->addAction("Hide &controls");
 	popup_headLightAction = advancedmenu->addAction("&Headlight");
 	popup_ambientLightAction = advancedmenu->addAction("dummy");
-	popup_dumpSceneAction = advancedmenu->addAction("Dump &scene to file");
-	popup_dumpSceneVRMLAction = advancedmenu->addAction("Dump &scene to VRML file");
 	popup_toSVGAction = advancedmenu->addAction("Produce SV&G image");
 	popup_toEPSAction = advancedmenu->addAction("Produce &EPS image");
 
@@ -2255,78 +2249,6 @@ void VP1ExaminerViewer::Imp::updatePopupMenuStates()
 
 }
 
-//____________________________________________________________________
-void VP1ExaminerViewer::dumpSceneToFile(QString filename)
-{
-	VP1Msg::messageVerbose("VP1ExaminerViewer::dumpSceneToFile()");
-
-	SoNode * rootnode = getSceneGraph();
-	if (!rootnode)
-		return;
-
-	QWidget * w = getWidget();
-	if (!w)
-		return;
-
-	if(filename.isEmpty()) {
-		if (isAnimating())
-			stopAnimating();
-		filename = QFileDialog::getSaveFileName(w, "Select output file",
-				(m_d->lastDumpFile.isEmpty()?VP1Settings::defaultFileSelectDirectory():m_d->lastDumpFile),
-				"Inventor files (*.iv)",0,QFileDialog::DontResolveSymlinks);
-		if(filename.isEmpty())
-			return;
-		if (!filename.endsWith(".iv"))
-			filename += ".iv";
-		m_d->lastDumpFile=filename;
-	}
-
-	SoGroup * standardisedRoot(0);
-	if ( rootnode->getTypeId().isDerivedFrom(SoGroup::getClassTypeId()))
-		standardisedRoot = VP1HEPVisUtils::convertToStandardScene(static_cast<SoGroup*>(rootnode));
-
-	if (standardisedRoot&&VP1QtInventorUtils::writeGraphToFile(standardisedRoot, filename))
-		VP1Msg::messageDebug("VP1ExaminerViewer: Dumped scene to file "+filename);
-	else
-		VP1Msg::messageDebug("VP1ExaminerViewer: Error: Problems dumping scene to file "+filename);
-
-}
-
-void VP1ExaminerViewer::dumpSceneToVRMLFile(QString filename){
-	VP1Msg::messageVerbose("VP1ExaminerViewer::dumpSceneToVRMLFile()");
-
-	SoNode * rootnode = getSceneGraph();
-	if (!rootnode)
-		return;
-
-	QWidget * w = getWidget();
-	if (!w)
-		return;
-
-	if(filename.isEmpty()) {
-		if (isAnimating())
-			stopAnimating();
-		filename = QFileDialog::getSaveFileName(w, "Select output file",
-				(m_d->lastDumpFile.isEmpty()?VP1Settings::defaultFileSelectDirectory():m_d->lastDumpFile),
-				"VRML2.0/X3D files (*.wrl)",0,QFileDialog::DontResolveSymlinks);
-		if(filename.isEmpty())
-			return;
-		if (!filename.endsWith(".wrl"))
-			filename += ".wrl";
-		m_d->lastDumpFile=filename;
-	}
-
-	SoGroup * standardisedRoot(0);
-	if ( rootnode->getTypeId().isDerivedFrom(SoGroup::getClassTypeId()))
-		standardisedRoot = VP1HEPVisUtils::convertToStandardScene(static_cast<SoGroup*>(rootnode));
-
-	if (standardisedRoot&&VP1QtInventorUtils::writeGraphToVRMLFile(standardisedRoot, filename))
-		VP1Msg::messageDebug("VP1ExaminerViewer: Dumped scene to VRML file "+filename);
-	else
-		VP1Msg::messageDebug("VP1ExaminerViewer: Error: Problems dumping scene to VRML file "+filename);
-
-}
-
 //____________________________________________________________________
 void VP1ExaminerViewer::produceSVGImage(QString filename)
 {
@@ -2494,17 +2416,6 @@ void VP1ExaminerViewer::showPopupMenu()
         VP1Msg::messageVerbose("Anti-aliasing, done.");
         return;
 	}
-    if ( selAct == m_d->popup_dumpSceneAction ) {
-        VP1Msg::messageVerbose("VP1ExaminerViewer::showPopupMenu Dump scene to an *.iv (OpenInventor) file");
-		dumpSceneToFile();
-		return;
-	}
-    if ( selAct == m_d->popup_dumpSceneVRMLAction ) {
-        VP1Msg::messageVerbose("VP1ExaminerViewer::showPopupMenu Dump scene to a *.wrl (VRML) file");
-		dumpSceneToVRMLFile();
-		return;
-	}
-
 	if ( selAct == m_d->popup_toSVGAction ) {
 		VP1Msg::messageVerbose("VP1ExaminerViewer::showPopupMenu Produce SVG image");
 		produceSVGImage();
diff --git a/GeoModelVisualization/VP1Base/src/VP1MaterialButton.cxx b/GeoModelVisualization/VP1Base/src/VP1MaterialButton.cxx
index 69cbbcf17..2cc465e7d 100644
--- a/GeoModelVisualization/VP1Base/src/VP1MaterialButton.cxx
+++ b/GeoModelVisualization/VP1Base/src/VP1MaterialButton.cxx
@@ -248,10 +248,12 @@ void VP1MaterialButton::copyValuesFromMaterial(SoMaterial*m)
   }
   m->ref();
   if (m->ambientColor.getNum()!=1
-      ||m->diffuseColor.getNum()!=1
+      ||(m->diffuseColor.getNum()!=1
+      &&m->diffuseColor.getNum()!=2)
       ||m->specularColor.getNum()!=1
       ||m->emissiveColor.getNum()!=1
-      ||m->transparency.getNum()!=1
+      ||(m->transparency.getNum()!=1
+      &&m->transparency.getNum()!=2)
       ||m->shininess.getNum()!=1) {
     message("VP1MaterialButton::copyValuesFromMaterial Error: Passed material must have exactly one value in each of the 6 fields!!");
     m->unrefNoDelete();
diff --git a/GeoModelVisualization/VP1GeometrySystems/CMakeLists.txt b/GeoModelVisualization/VP1GeometrySystems/CMakeLists.txt
index c8c3eed5c..4c176d359 100644
--- a/GeoModelVisualization/VP1GeometrySystems/CMakeLists.txt
+++ b/GeoModelVisualization/VP1GeometrySystems/CMakeLists.txt
@@ -12,7 +12,7 @@ target_link_libraries( GXGeometrySystems
    PUBLIC Coin::Coin Qt${QT_VERSION}::Core Qt${QT_VERSION}::Gui Qt${QT_VERSION}::Widgets
           GeoModelCore::GeoModelKernel GXBase
    PRIVATE nlohmann_json::nlohmann_json GeoModelIO::GeoModelRead
-           GeoModelIO::GeoModelWrite GeoModelIO::GeoModelDBManager GXHEPVis )
+           GeoModelIO::GeoModelWrite GeoModelIO::GeoModelDBManager GXHepVis )
 target_include_directories( GXGeometrySystems PUBLIC
    $<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}>
    $<INSTALL_INTERFACE:${CMAKE_INSTALL_INCLUDEDIR}> )
diff --git a/GeoModelVisualization/VP1GeometrySystems/VP1GeometrySystems/DumpShape.h b/GeoModelVisualization/VP1GeometrySystems/VP1GeometrySystems/DumpShape.h
index 0e6c30ccc..3a0047382 100644
--- a/GeoModelVisualization/VP1GeometrySystems/VP1GeometrySystems/DumpShape.h
+++ b/GeoModelVisualization/VP1GeometrySystems/VP1GeometrySystems/DumpShape.h
@@ -13,16 +13,24 @@
 // Original code by Joe Boudreau, adapted                            //
 // in the present form by T. Kittelmann                              //
 //                                                                   //
+// Updates:                                                          //
+// Jun 2024, Rui Xue                                                 //
+//           Add new method for Virtual Surface.                     //
+//                                                                   //
+//                                                                   //
 ///////////////////////////////////////////////////////////////////////
 
 #include <QStringList>
 
 class GeoShape;
+class GeoVSurfaceShape;
 
 class DumpShape {
 public:
 
   static QStringList shapeToStringList(const GeoShape* shape);
+  static QStringList shapeToStringList(const GeoVSurfaceShape* surf_shape);
+  
 private:
 
   DumpShape(){};
diff --git a/GeoModelVisualization/VP1GeometrySystems/VP1GeometrySystems/PhiSectorManager.h b/GeoModelVisualization/VP1GeometrySystems/VP1GeometrySystems/PhiSectorManager.h
index 896f9e110..4d380652f 100644
--- a/GeoModelVisualization/VP1GeometrySystems/VP1GeometrySystems/PhiSectorManager.h
+++ b/GeoModelVisualization/VP1GeometrySystems/VP1GeometrySystems/PhiSectorManager.h
@@ -41,6 +41,8 @@ public:
 
   //Volume handles first call this method to figure out what kind of volume they are:
   int getVolumeType(const SbMatrix& transform, SoNode * shape) const;
+  
+  int getSurfaceType(const SbMatrix& transform, SoNode * shape) const;
   //The return value, iphi, indicates the type:
   // 0...(nphi-1): Volume with a bounding box not around the Z axis.
   //  -1: Volume has bounding box around Z-axis, but can not be dynamically altered  (probably boolean)
diff --git a/GeoModelVisualization/VP1GeometrySystems/VP1GeometrySystems/SoVisualizeAction.h b/GeoModelVisualization/VP1GeometrySystems/VP1GeometrySystems/SoVisualizeAction.h
index 247d8ca6c..4ca3f7994 100644
--- a/GeoModelVisualization/VP1GeometrySystems/VP1GeometrySystems/SoVisualizeAction.h
+++ b/GeoModelVisualization/VP1GeometrySystems/VP1GeometrySystems/SoVisualizeAction.h
@@ -15,6 +15,12 @@
 #include "GeoModelKernel/GeoShapeAction.h"
 
 class SoShape;
+#include <Inventor/nodes/SoSeparator.h>
+#include <Inventor/nodes/SoMaterialBinding.h>
+#include <Inventor/nodes/SoNormal.h>
+#include <Inventor/nodes/SoNormalBinding.h>
+#include <Inventor/nodes/SoCoordinate3.h>
+#include <Inventor/nodes/SoFaceSet.h>
 
 class SoVisualizeAction : public GeoShapeAction {
 
@@ -49,9 +55,23 @@ public:
   virtual void handleTessellatedSolid (const GeoTessellatedSolid *);
 
   virtual void handleGenericTrap (const GeoGenericTrap *);
+  
+  virtual void handleRectSurface (const GeoRectSurface *);
+
+  virtual void handleTrapezoidSurface (const GeoTrapezoidSurface *);
+
+  virtual void handleAnnulusSurface (const GeoAnnulusSurface *);
+
+  virtual void handleDiamondSurface (const GeoDiamondSurface *);
 
   SoShape * getShape() { return m_shape; }
   void reset() { m_shape = 0; }
+  void reset_separator() { vs_shape = new SoSeparator; }
+  SoNormal * getNormal() { return surfaceNorms; }
+  SoNormalBinding * getNormalBinding() { return surfBinding; }
+  SoMaterialBinding * getMaterialBinding() { return surfMaterialBinding; }
+  SoCoordinate3 * getCoords() { return coords; }
+  SoSeparator * getVSurfaceShape() { return vs_shape; }
 
 private:
 
@@ -59,11 +79,13 @@ private:
   const SoVisualizeAction & operator=(const SoVisualizeAction &);
 
   SoShape *m_shape;
-};
-
-
-
-
+  SoNormal *surfaceNorms = new SoNormal;
+  SoNormalBinding* surfBinding = new SoNormalBinding;
+  SoMaterialBinding* surfMaterialBinding = new SoMaterialBinding;
+  SoCoordinate3 *coords;
+  SoSeparator* vs_shape = new SoSeparator;
 
+  
+};
 
 #endif
diff --git a/GeoModelVisualization/VP1GeometrySystems/VP1GeometrySystems/VP1GeometrySystem.h b/GeoModelVisualization/VP1GeometrySystems/VP1GeometrySystems/VP1GeometrySystem.h
index 139ac0f36..4f11ebb4b 100644
--- a/GeoModelVisualization/VP1GeometrySystems/VP1GeometrySystems/VP1GeometrySystem.h
+++ b/GeoModelVisualization/VP1GeometrySystems/VP1GeometrySystems/VP1GeometrySystem.h
@@ -18,7 +18,8 @@
 //  - Jul 2021, Riccardo Maria Bianchi <riccardo.maria.bianchi@cern.ch>
 //              * Added the 'filter volumes' tool
 //              * Added signal/slot to update transparency type in the 3D window
-//                                                                     
+//  - Jun 2024, Rui Xue  <r.xue@cern.ch><rux23@pitt.edu>
+//              * Added methods to print out virtual surface information                                                                     
 /////////////////////////////////////////////////////////////////////////
 
 #include "VP1Base/IVP13DSystemSimple.h"
@@ -26,12 +27,24 @@
 #include "VP1GeometrySystems/VolumeHandle.h"//fixme
 
 #include "GeoModelKernel/GeoPhysVol.h"
+#include "GeoModelKernel/GeoVSurface.h"
 
 #include <set>
 #include <map>
 #include <QStack>
 #include <QString>
 
+#include <iostream>
+#include <exception>
+#include <sstream>
+
+#define THROW_EXCEPTION(MESSAGE)                      \
+    {                                                 \
+        std::stringstream except_str{};               \
+        except_str<<__FILE__<<":"<<__LINE__<<" --- "; \
+        except_str<<MESSAGE;                          \
+        throw std::runtime_error(except_str.str());   \
+    }
 
 
 
diff --git a/GeoModelVisualization/VP1GeometrySystems/VP1GeometrySystems/VolumeHandle.h b/GeoModelVisualization/VP1GeometrySystems/VP1GeometrySystems/VolumeHandle.h
index f21666c22..3a1d2de18 100644
--- a/GeoModelVisualization/VP1GeometrySystems/VP1GeometrySystems/VolumeHandle.h
+++ b/GeoModelVisualization/VP1GeometrySystems/VP1GeometrySystems/VolumeHandle.h
@@ -9,6 +9,7 @@
 
 #include "VP1GeometrySystems/VP1GeoFlags.h"
 #include "GeoModelKernel/GeoVPhysVol.h"
+#include "GeoModelKernel/GeoVSurface.h"
 #include <QString>
 
 //Only initialises child classes on demand. And even then their SoNodes are not initialised until they must be shown.
@@ -16,6 +17,7 @@ class VolumeHandleSharedData;
 class SoMaterial;
 class SoSeparator;
 class GeoMaterial;
+class SoMaterialBinding;
 #include <Inventor/C/errors/debugerror.h>
 #include <Inventor/SbMatrix.h>
 
@@ -26,6 +28,9 @@ public:
   VolumeHandle(VolumeHandleSharedData * ,VolumeHandle * parent, const PVConstLink&,int childNumber,
 	       const SbMatrix& accumTrans = SbMatrix() );
 
+  VolumeHandle(VolumeHandleSharedData * ,VolumeHandle * parent, const VSConstLink&,int childNumber,
+	       const SbMatrix& accumTrans = SbMatrix() );
+
   virtual ~VolumeHandle();//lots of stuff to do here!
   //Used (recursively) upon deletion (never delete before children are deleted).
   void initialiseChildren();
@@ -40,6 +45,7 @@ public:
   quint32 hashID() const;//For vp1 persistification
 
   PVConstLink geoPVConstLink() const;
+  VSConstLink geoVSConstLink() const;
   const GeoMaterial * geoMaterial() const;
   std::string getNameStdString() const;
 
@@ -121,6 +127,7 @@ private:
   bool haveParentsNotExpanded() const;
   void attachAllContractedChildren();//also checks children of expanded children (recursively).
   void detachAllContractedChildren();//also checks children of expanded children (recursively).
+  //SoMaterial * SurfaceMaterial() const;
 };
 
 /////////////////
diff --git a/GeoModelVisualization/VP1GeometrySystems/VP1GeometrySystems/VolumeHandleSharedData.h b/GeoModelVisualization/VP1GeometrySystems/VP1GeometrySystems/VolumeHandleSharedData.h
index 1ca256c39..1acd7d0db 100644
--- a/GeoModelVisualization/VP1GeometrySystems/VP1GeometrySystems/VolumeHandleSharedData.h
+++ b/GeoModelVisualization/VP1GeometrySystems/VP1GeometrySystems/VolumeHandleSharedData.h
@@ -9,8 +9,11 @@
 //for all volume handle nodes under a given top-level handle.
 
 #include "GeoModelKernel/GeoVPhysVol.h"
+#include "GeoModelKernel/GeoVSurface.h"
 #include "VP1GeometrySystems/VP1GeoFlags.h"
+#include <Inventor/nodes/SoShape.h>
 #include <map>
+
 class SoNode;
 class SoGroup;
 class SoSeparator;
@@ -32,7 +35,7 @@ public:
   ~VolumeHandleSharedData();
   void ref();
   void unref();
-
+   
   //Fixme: Inline?
   PVConstLink geoPVConstLinkOfTreeTopsMother() const;
   PhiSectorManager* phiSectorManager() const;
@@ -47,6 +50,8 @@ public:
   void removeZappedVolumesFromGui(VolumeHandle*);
 
   SoNode * toShapeNode(const PVConstLink& pV, bool *shapeIsKnown=nullptr);//Returns shape of pV->getLogVol() (uses shared instancing as appropriate)
+  
+  SoNode * toShapeNode(const VSConstLink& vS, SoSeparator* nodesep);
   SoNode * getSoCylinderOrientedLikeGeoTube(const double& radius, const double& halfLength);//(uses shared instancing as appropriate)
 
   void registerNodeSepForVolumeHandle(SoSeparator*,VolumeHandle*);
diff --git a/GeoModelVisualization/VP1GeometrySystems/src/DumpShape.cxx b/GeoModelVisualization/VP1GeometrySystems/src/DumpShape.cxx
index c505cbd13..ffbbf43e9 100644
--- a/GeoModelVisualization/VP1GeometrySystems/src/DumpShape.cxx
+++ b/GeoModelVisualization/VP1GeometrySystems/src/DumpShape.cxx
@@ -20,7 +20,13 @@
 #include "GeoModelKernel/GeoShapeIntersection.h"
 #include "GeoModelKernel/GeoShapeSubtraction.h"
 #include "GeoModelKernel/GeoGenericTrap.h"
+#include "GeoModelKernel/GeoVSurfaceShape.h"
+#include "GeoModelKernel/GeoRectSurface.h"
+#include "GeoModelKernel/GeoTrapezoidSurface.h"
+#include "GeoModelKernel/GeoAnnulusSurface.h"
+#include "GeoModelKernel/GeoDiamondSurface.h"
 
+#include "GeoModelHelpers/throwExcept.h"
 #include "Inventor/SbMatrix.h"
 #include <cassert>
 
@@ -29,6 +35,57 @@
 //TODO: Add support for the SimpleBREP GeoShape.
 //TODO: Add GeoTorus
 
+QStringList DumpShape::shapeToStringList(const GeoVSurfaceShape* surf_shape)
+{
+  QStringList out;
+  static const double mm=1.0;
+  if(surf_shape->type() == "RectangleSurface"){
+    const GeoRectSurface* rectsurf = dynamic_cast<const GeoRectSurface*>(surf_shape);
+    if(rectsurf){
+      out << " =========> Rectangle Surface:";
+      out << "  X = "+QString::number(rectsurf->getXHalfLength()/mm)+" mm";
+      out << "  Y = "+QString::number(rectsurf->getYHalfLength()/mm)+" mm";
+    }
+  }
+  else if(surf_shape->type() == "TrapezoidSurface"){
+    const GeoTrapezoidSurface* trapezoid = dynamic_cast<const GeoTrapezoidSurface*>(surf_shape);
+    if(trapezoid){
+      out << " =========> Trapezoid Surface:";
+      out << "  Short Half Base = "+QString::number(trapezoid->getXHalfLengthMin()/mm)+" mm";
+      out << "  Long Half Base = "+QString::number(trapezoid->getXHalfLengthMax()/mm)+" mm";
+      out << "  Height = "+QString::number(trapezoid->getYHalfLength()/mm)+" mm";
+    }
+  }
+  else if(surf_shape->type() == "AnnulusSurface"){
+    const GeoAnnulusSurface* annulus = dynamic_cast<const GeoAnnulusSurface*>(surf_shape);
+    if(annulus){
+      out << " =========> Annulus Surface:";
+      out << "  Ox (Deviation in X-direction) = "+QString::number(annulus->getOx()/mm)+" mm";
+      out << "  Oy (Deviation in Y-direction) = "+QString::number(annulus->getOy()/mm)+" mm";
+      out << "  Inner Radius = "+QString::number(annulus->getRadiusIn()/mm)+" mm";
+      out << "  Outer Radius = "+QString::number(annulus->getRadiusOut()/mm)+" mm";
+      out << "  Phi (Span Angle) = "+QString::number(annulus->getPhi())+" rad"; 
+    }
+  }
+  else if(surf_shape->type() == "DiamondSurface"){
+    const GeoDiamondSurface* diamond = dynamic_cast<const GeoDiamondSurface*>(surf_shape);
+    if(diamond){
+      out << " =========> Diamond Surface:";
+      out << "  X1 = "+QString::number(diamond->getXbottomHalf()/mm)+" mm";
+      out << "  X2 = "+QString::number(diamond->getXmidHalf()/mm)+" mm";
+      out << "  X3 = "+QString::number(diamond->getXtopHalf()/mm)+" mm";
+      out << "  Y1 = "+QString::number(diamond->getYbottomHalf()/mm)+" mm";
+      out << "  Y2 = "+QString::number(diamond->getYtopHalf()/mm)+" mm";
+    }
+  }
+  else{
+    //out << " =========> Unknown surface...";
+    THROW_EXCEPTION("ERROR!!! VSurfaceShape is Unknown, cannot print out shape information!");
+  }
+  
+  return out; 
+}
+
 //____________________________________________________________________
 QStringList DumpShape::shapeToStringList(const GeoShape* shape)
 {
diff --git a/GeoModelVisualization/VP1GeometrySystems/src/PhiSectorManager.cxx b/GeoModelVisualization/VP1GeometrySystems/src/PhiSectorManager.cxx
index cdd5f4f08..54a11293e 100644
--- a/GeoModelVisualization/VP1GeometrySystems/src/PhiSectorManager.cxx
+++ b/GeoModelVisualization/VP1GeometrySystems/src/PhiSectorManager.cxx
@@ -18,10 +18,10 @@
 #include "VP1Base/VP1Msg.h"
 #include "VP1Base/IVP1System.h"
 
-#include <VP1HEPVis/nodes/SoTubs.h>
-#include "VP1HEPVis/nodes/SoPcons.h"
-#include "VP1HEPVis/nodes/SoCons.h"
-#include "VP1HEPVis/nodes/SoLAr.h"
+#include <GXHepVis/nodes/SoTubs.h>
+#include "GXHepVis/nodes/SoPcons.h"
+#include "GXHepVis/nodes/SoCons.h"
+#include "GXHepVis/nodes/SoLAr.h"
 
 #include <Inventor/nodes/SoSwitch.h>
 #include <Inventor/nodes/SoSeparator.h>
@@ -261,6 +261,36 @@ int PhiSectorManager::getVolumeType(const SbMatrix& transform, SoNode * shape) c
 
 }
 
+//____________________________________________________________________
+
+int PhiSectorManager::getSurfaceType(const SbMatrix& transform, SoNode * shape) const {
+ 
+  int iphi;
+  
+  float x = 0.0;
+  float y = 0.0;
+  float z = 0.0;
+
+  float a = 0.0;
+  float b = 0.0;
+  float c = 0.0;
+  
+  a = x*transform[0][0] + y*transform[1][0] + z*transform[2][0] + transform[3][0];
+  b = x*transform[0][1] + y*transform[1][1] + z*transform[2][1] + transform[3][1];
+  c = x*transform[0][2] + y*transform[1][2] + z*transform[2][2] + transform[3][2];
+  
+  if ( a == 0 && b == 0){
+    iphi = -1;
+  }
+  else{
+    double angle = atan2(b,a);
+    while (angle<0) angle+=(2*M_PI);
+    while (angle>=(2*M_PI)) angle-=(2*M_PI);
+    if (angle<0.0) angle=0.0;
+    iphi = static_cast<int>(36*angle/((2*M_PI)));
+  }
+  return iphi;
+}
 //____________________________________________________________________
 PhiSectorManager::PhiSectorManager(PhiSectionWidget * psw, IVP1System * sys, QObject*parent)
   : QObject(parent), m_d(new Imp)
diff --git a/GeoModelVisualization/VP1GeometrySystems/src/SbPolyhedrizeAction.cxx b/GeoModelVisualization/VP1GeometrySystems/src/SbPolyhedrizeAction.cxx
index 3f013f02d..d392f7489 100644
--- a/GeoModelVisualization/VP1GeometrySystems/src/SbPolyhedrizeAction.cxx
+++ b/GeoModelVisualization/VP1GeometrySystems/src/SbPolyhedrizeAction.cxx
@@ -24,7 +24,7 @@
 #include "GeoModelKernel/GeoDefinitions.h"
 #include "VP1GeometrySystems/SbPolyhedrizeAction.h"
 
-#include "VP1HEPVis/SbPolyhedron.h"
+#include "GXHepVis/SbPolyhedron.h"
 
 #include <map>
 
@@ -53,7 +53,7 @@ void SbPolyhedrizeAction::handleShift(const GeoShapeShift *shift)
 //			  rotation.xz(),rotation.yz(),rotation.zz(),0,
 //			  0,0,0,1));
   SbVec3d    trx(translation.x(),translation.y(),translation.z());
-  #include <VP1HEPVis/SbRotation.h> //using doubles instead of floats.
+  #include <GXHepVis/SbRotation.h> //using doubles instead of floats.
   HEPVis::SbRotation rot(rotation(0,0),rotation(1,0),rotation(2,0),0,
 			 rotation(0,1),rotation(1,1),rotation(2,1),0,
 			 rotation(0,2),rotation(1,2),rotation(2,2),0,
diff --git a/GeoModelVisualization/VP1GeometrySystems/src/SoVisualizeAction.cxx b/GeoModelVisualization/VP1GeometrySystems/src/SoVisualizeAction.cxx
index 888ad34e2..fe805f195 100644
--- a/GeoModelVisualization/VP1GeometrySystems/src/SoVisualizeAction.cxx
+++ b/GeoModelVisualization/VP1GeometrySystems/src/SoVisualizeAction.cxx
@@ -16,30 +16,33 @@
 #include "GeoModelKernel/GeoTessellatedSolid.h"
 #include "GeoModelKernel/GeoFacet.h"
 #include "GeoModelKernel/GeoGenericTrap.h"
-#include "VP1HEPVis/nodes/SoTubs.h"
-#include "VP1HEPVis/nodes/SoCons.h"
-#include "VP1HEPVis/nodes/SoTorus.h"
-#include "VP1HEPVis/nodes/SoGenericBox.h"
-#include "VP1HEPVis/nodes/SoPcons.h"
-#include "VP1HEPVis/nodes/SoTessellated.h"
-#include "VP1HEPVis/SbPolyhedron.h"
-#include "VP1HEPVis/nodes/SoLAr.h"
-#include "VP1HEPVis/nodes/SoPolyhedron.h"
-#include "VP1HEPVis/VP1HEPVisUtils.h"
+#include "GXHepVis/nodes/SoTubs.h"
+#include "GXHepVis/nodes/SoCons.h"
+#include "GXHepVis/nodes/SoTorus.h"
+#include "GXHepVis/nodes/SoGenericBox.h"
+#include "GXHepVis/nodes/SoPcons.h"
+#include "GXHepVis/nodes/SoTessellated.h"
+#include "GXHepVis/SbPolyhedron.h"
+#include "GXHepVis/nodes/SoLAr.h"
+#include "GXHepVis/nodes/SoPolyhedron.h"
+#include "GXHepVis/GXHepVisUtils.h"
 #include "VP1GeometrySystems/SbPolyhedrizeAction.h"
 #include <Inventor/nodes/SoSphere.h>
+
+#include "GeoModelKernel/GeoRectSurface.h"
+#include "GeoModelKernel/GeoTrapezoidSurface.h"
+#include "GeoModelKernel/GeoAnnulusSurface.h"
+#include "GeoModelKernel/GeoDiamondSurface.h"
 // System of units
 #include "GeoModelKernel/Units.h"
 #define SYSTEM_OF_UNITS GeoModelKernelUnits // --> 'GeoModelKernelUnits::cm'
 #include <iostream>
-
-
-
+#include <cmath>
 
 SoVisualizeAction::SoVisualizeAction()
   : m_shape(0)
 {
-  VP1HEPVisUtils::initAllCustomClasses();
+  GXHepVisUtils::initAllCustomClasses();
   setDepthLimit(0);
 }
 
@@ -268,3 +271,289 @@ void SoVisualizeAction::handleGenericTrap(const GeoGenericTrap *gentrap)
 			   trapVertices[0].x(),trapVertices[0].y(),dZ);
   m_shape=gb;
 }
+
+// In the near future, I should separate those handle VS methods from SoVisualizationAction
+
+void SoVisualizeAction::handleRectSurface(const GeoRectSurface *surf)
+{
+  static float norms[2][3]={
+    {0.0, 0.0, -1.0}, {0.0, 0.0, 1.0}
+  };
+  surfaceNorms->vector.setValues(0, 2, norms);
+  surfBinding->value = SoNormalBinding::PER_FACE;
+  surfMaterialBinding->value = SoMaterialBinding::PER_FACE;
+  
+  float dx = surf->getXHalfLength();
+  float dy = surf->getYHalfLength();
+
+  float vertices[8][3]={
+  {dx,dy,0}, {-dx,dy,0},{-dx,-dy,0}, {dx,-dy,0},
+  {dx,dy,0}, {-dx,dy,0},{-dx,-dy,0}, {dx,-dy,0}
+  };
+  SoCoordinate3 *coords_ = new SoCoordinate3;
+  coords_->point.setValues(0,8, vertices);
+  coords = coords_;
+  
+  int32_t numvertices[2] = {4, 4};
+  SoFaceSet * faceset = new SoFaceSet;
+  faceset->numVertices.setValues(0, 2, numvertices);
+  m_shape = faceset;
+  
+  vs_shape->addChild(surfaceNorms);
+  vs_shape->addChild(surfBinding);
+  vs_shape->addChild(surfMaterialBinding);
+  vs_shape->addChild(coords);
+  vs_shape->addChild(m_shape);
+
+}
+
+void SoVisualizeAction::handleTrapezoidSurface(const GeoTrapezoidSurface *surf)
+{
+  static float norms[2][3]={
+    {0.0, 0.0, -1.0}, {0.0, 0.0, 1.0}
+  };
+  surfaceNorms->vector.setValues(0, 2, norms);
+  surfBinding->value = SoNormalBinding::PER_FACE;
+  surfMaterialBinding->value = SoMaterialBinding::PER_FACE;
+  
+  float dx_min = surf->getXHalfLengthMin();
+  float dx_max = surf->getXHalfLengthMax();
+  float dy = surf->getYHalfLength();
+
+  float vertices[8][3]={
+  {dx_max,dy,0}, {-dx_max,dy,0},{-dx_min,-dy,0}, {dx_min,-dy,0},
+  {dx_max,dy,0}, {-dx_max,dy,0},{-dx_min,-dy,0}, {dx_min,-dy,0}
+  };
+  SoCoordinate3 *coords_ = new SoCoordinate3;
+  coords_->point.setValues(0,8, vertices);
+  coords = coords_;
+  
+  int32_t numvertices[2] = {4, 4};
+  SoFaceSet * faceset = new SoFaceSet;
+  faceset->numVertices.setValues(0, 2, numvertices);
+  m_shape = faceset;
+
+  vs_shape->addChild(surfaceNorms);
+  vs_shape->addChild(surfBinding);
+  vs_shape->addChild(surfMaterialBinding);
+  vs_shape->addChild(coords);
+  vs_shape->addChild(m_shape);
+}
+
+// Here I'm working on AnnulusSurface, also, this part should be separated from SoVisualizationAction
+
+// use static keyword to make the function private
+static int initialize_N(double theta){
+  int N;
+
+  if (theta <= 0.0){
+    throw std::runtime_error("Theta cannot be zero or negative");
+  }
+  else{
+    double phi = 2.0*M_PI;
+    double angle = fmod(theta, phi);    // make sure that angle is between 0 and 2*pi
+    if (angle != 0.0){
+      N = 4*std::ceil(360*angle/phi); // 360 is the number of rectangles in the circle
+                                      // 4 is the number of vertices in each rectangle
+    }
+    else{
+      N = 360;
+    }
+  }                                    
+  return N;
+}
+
+static int which_quadrant(double theta){
+  double phi = 2.0*M_PI;
+  double angle = fmod(theta, phi);
+  if (angle < phi/4.0){
+    return 0;
+  } else if (angle < 2.0*phi/4.0){
+    return 1;
+  } else if (angle < 3.0*phi/4.0){
+    return 2;
+  } else {
+    return 3;
+  }
+}
+
+static double solve_X(double k, double Ox, double Oy, double radius, double theta){
+  if(std::isinf(k) || k > 1e5 || k < -1e5){
+    return Ox;
+  }
+  else{
+    double a = 1.0 + k*k;
+    double b = 2*k*Oy - 2*k*k*Ox;
+    double c = k*k*Ox*Ox - 2*k*Ox*Oy + Oy*Oy - radius*radius;
+    double delta = b*b - 4*a*c;
+
+    if (delta < 0){
+      throw std::runtime_error("No solution for X");
+    }
+
+    double X1 = (-b + sqrt(delta))/(2*a);
+    double X2 = (-b - sqrt(delta))/(2*a);
+
+    int quadrant = which_quadrant(theta);
+    if (quadrant == 0 || quadrant == 3){
+      return X1;
+    } else {
+      return X2;
+    }
+  }
+}
+
+static double solve_Y(double X, double k, double Ox, double Oy, double radius, double theta){
+  if(std::isinf(k)){
+    int quadrant = which_quadrant(theta);
+    if (quadrant == 0 || quadrant == 1){
+      return sqrt(radius*radius - X*X);
+    } else {
+      return -sqrt(radius*radius - X*X);
+    }
+  }
+  else if (k > 1e5 || k < -1e5){
+    int quadrant = which_quadrant(theta);
+    if (quadrant == 0 || quadrant == 1){
+      return sqrt(radius*radius - X*X);
+    } else {
+      return -sqrt(radius*radius - X*X);
+    }
+  }
+  else{
+    return k*X + Oy - k*Ox;
+  }
+}
+
+static void tiny_rect( double Ox, double Oy, double radius_in, double radius_out, double angle, double delta_angle, float **rect_vertices ){
+
+  double X1, X2, X3, X4, Y1, Y2, Y3, Y4;
+  double k = tan(angle);
+  double k_plus = tan(angle + delta_angle);
+
+  X1 = solve_X(k, Ox, Oy, radius_out, angle);
+  Y1 = solve_Y(X1, k, Ox, Oy, radius_out, angle);
+
+  X2 = solve_X(k_plus, Ox, Oy, radius_out, angle + delta_angle);
+  Y2 = solve_Y(X2, k_plus, Ox, Oy, radius_out, angle + delta_angle);
+
+  X3 = solve_X(k_plus, Ox, Oy, radius_in, angle + delta_angle);
+  Y3 = solve_Y(X3, k_plus, Ox, Oy, radius_in, angle + delta_angle);
+
+  X4 = solve_X(k, Ox, Oy, radius_in, angle);
+  Y4 = solve_Y(X4, k, Ox, Oy, radius_in, angle);
+
+  // generate vertices for the tiny rectangle
+  rect_vertices[0][0] = static_cast<float>(X1);
+  rect_vertices[0][1] = static_cast<float>(Y1);
+  rect_vertices[0][2] = 0.0f;
+  
+  rect_vertices[1][0] = static_cast<float>(X2);
+  rect_vertices[1][1] = static_cast<float>(Y2);
+  rect_vertices[1][2] = 0.0f;
+  
+  rect_vertices[2][0] = static_cast<float>(X3);
+  rect_vertices[2][1] = static_cast<float>(Y3);
+  rect_vertices[2][2] = 0.0f;
+
+  rect_vertices[3][0] = static_cast<float>(X4);
+  rect_vertices[3][1] = static_cast<float>(Y4);
+  rect_vertices[3][2] = 0.0f;
+}
+
+void SoVisualizeAction::handleAnnulusSurface(const GeoAnnulusSurface *surf)
+{
+
+  double real_theta = surf->getPhi();
+  double Ox = surf->getOx();
+  double Oy = surf->getOy();
+  double radius_in = surf->getRadiusIn();
+  double radius_out = surf->getRadiusOut();
+  double angle;  
+  int n = initialize_N(real_theta);  // initialize the number of rectangles, also make sure that real theta is positive
+
+  int quotient = floor(real_theta/(2.0*M_PI));
+  double theta = real_theta - quotient*2.0*M_PI;
+  if (theta == 0.0){
+    theta = 2.0*M_PI;
+  }  
+  double delta_angle = theta/n;
+  
+  // size of rect_vertices is 4x3
+  float **rect_vertices = new float*[4];
+  for (int i = 0; i < 4; ++i) {
+      rect_vertices[i] = new float[3];
+  }
+
+  float vertices[8][3];
+  
+  // add material (fake material, for drawing purposes) bindings to the surface
+  surfMaterialBinding->value = SoMaterialBinding::PER_FACE;
+  vs_shape->addChild(surfMaterialBinding);
+  
+  // set the surface normal properties
+  static float norms[2][3]={
+    {0.0, 0.0, -1.0}, {0.0, 0.0, 1.0}
+  };
+  surfaceNorms->vector.setValues(0, 2, norms);
+  surfBinding->value = SoNormalBinding::PER_FACE;
+  vs_shape->addChild(surfaceNorms);
+  vs_shape->addChild(surfBinding);
+  SoCoordinate3 *coords = new SoCoordinate3;
+  // Add coordinates & faceSet child for each rectangle
+  for(int i = 0; i < n; i++){
+    angle = 0.0 + i*delta_angle;    
+    tiny_rect(Ox, Oy, radius_in, radius_out, angle, delta_angle, rect_vertices);
+
+    SoCoordinate3 *coords = new SoCoordinate3;
+    SoFaceSet     *faceSet= new SoFaceSet;
+
+    for (int i = 0; i < 2; i++){
+      for (int j = 0; j < 4; j++){
+        for (int k = 0; k < 3; k++){
+          vertices[i*4 + j][k] = rect_vertices[j][k];
+        }
+      }
+    }
+    coords->point.setValues(0, 8, vertices); // front side + back side = 8 vertices
+    int32_t numvertices[2] = {4, 4};
+    faceSet->numVertices.setValues(0, 2, numvertices);
+    vs_shape->addChild(coords);
+    vs_shape->addChild(faceSet);
+  }
+}
+
+void SoVisualizeAction::handleDiamondSurface(const GeoDiamondSurface *surf)
+{
+  static float norms[2][3]={
+    {0.0, 0.0, -1.0}, {0.0, 0.0, 1.0}
+  };
+  surfaceNorms->vector.setValues(0, 2, norms);
+  surfBinding->value = SoNormalBinding::PER_FACE;
+  surfMaterialBinding->value = SoMaterialBinding::PER_FACE;
+  
+  float dx1 = surf->getXbottomHalf();
+  float dx2 = surf->getXmidHalf();
+  float dx3 = surf->getXtopHalf();
+  float dy1 = surf->getYbottomHalf();
+  float dy2 = surf->getYtopHalf();
+
+  float vertices[12][3]={
+  {dx3,dy2,0}, {-dx3,dy2,0},{-dx2,0,0}, {-dx1,-dy1,0}, {dx1,-dy1,0}, {dx2,0,0},
+  {dx3,dy2,0}, {-dx3,dy2,0},{-dx2,0,0}, {-dx1,-dy1,0}, {dx1,-dy1,0}, {dx2,0,0}
+  };
+  SoCoordinate3 *coords_ = new SoCoordinate3;
+  coords_->point.setValues(0,12, vertices);
+  coords = coords_;
+  
+  int32_t numvertices[2] = {6, 6};
+  SoFaceSet * faceset = new SoFaceSet;
+  faceset->numVertices.setValues(0, 2, numvertices);
+  m_shape = faceset;
+
+  vs_shape->addChild(surfaceNorms);
+  vs_shape->addChild(surfBinding);
+  vs_shape->addChild(surfMaterialBinding);
+  vs_shape->addChild(coords);
+  vs_shape->addChild(m_shape);
+}
\ No newline at end of file
diff --git a/GeoModelVisualization/VP1GeometrySystems/src/VP1GeometrySystem.cxx b/GeoModelVisualization/VP1GeometrySystems/src/VP1GeometrySystem.cxx
index 6b4b49449..e6402e77c 100644
--- a/GeoModelVisualization/VP1GeometrySystems/src/VP1GeometrySystem.cxx
+++ b/GeoModelVisualization/VP1GeometrySystems/src/VP1GeometrySystem.cxx
@@ -19,7 +19,8 @@
 //  - Jul 2021, Riccardo Maria Bianchi <riccardo.maria.bianchi@cern.ch> 
 //              * Added the 'filter volumes' tool
 //              * Added signal/slot to update transparency type in the 3D window
-//                                                                     
+//  - Jun 2024, Rui Xue  <r.xue@cern.ch><rux23@pitt.edu>
+//              * Added methods to print out virtual surface information                 
 /////////////////////////////////////////////////////////////////////////
 
 // local includes
@@ -59,7 +60,8 @@
 #include <Inventor/nodes/SoLightModel.h>
 #include <Inventor/nodes/SoTransform.h>
 #include <Inventor/nodes/SoScale.h>
-
+#include <Inventor/nodes/SoSelection.h>
+#include <Inventor/nodes/SoFaceSet.h>
 // GeoModelCore includes
 #include "GeoModelKernel/GeoVolumeCursor.h"
 #include "GeoModelKernel/GeoPrintGraphAction.h"
@@ -398,6 +400,9 @@ void VP1GeometrySystem::buildPermanentSceneGraph(StoreGateSvc*/*detstore*/, SoSe
 
 	  found = true;
 	  //We did... now, time to extract info:
+    if(av.getVolume() == nullptr) {
+      THROW_EXCEPTION(" \n \n ERROR!!! \n Virtual Surface Cannot Serve As TreeTop Info \n \n");
+    }
 	  subsys->treetopinfo.resize(subsys->treetopinfo.size()+1);
 	  subsys->treetopinfo.back().pV = av.getVolume();
 	  subsys->treetopinfo.back().xf = av.getTransform();
@@ -703,7 +708,6 @@ void VP1GeometrySystem::userPickedNode(SoNode* , SoPath *pickedPath)
   // all phi-slices of the part gets highlighted (since more than one
   // soshape node represents the volume).
 
-
 	VP1Msg::messageDebug("VP1GeometrySystem::userPickedNode()");
 
   if (pickedPath->getNodeFromTail(0)->getTypeId()==SoCylinder::getClassTypeId())
@@ -715,8 +719,18 @@ void VP1GeometrySystem::userPickedNode(SoNode* , SoPath *pickedPath)
   }
 
   SoSeparator * nodesep(0);
-
-  if (pickedPath->getNodeFromTail(1)->getTypeId()==SoSeparator::getClassTypeId()
+  
+  if (pickedPath->getNodeFromTail(0)->getTypeId()==SoFaceSet::getClassTypeId()
+   && pickedPath->getNodeFromTail(1)->getTypeId()==SoSeparator::getClassTypeId()
+   && pickedPath->getNodeFromTail(2)->getTypeId()==SoSelection::getClassTypeId()){
+
+    //Scenario 0: this is a virtual surface
+      nodesep = static_cast<SoSeparator*>(pickedPath->getNodeFromTail(3));
+      pickedPath->pop();
+      pickedPath->pop();
+      pickedPath->pop();
+  }  
+  else if (pickedPath->getNodeFromTail(1)->getTypeId()==SoSeparator::getClassTypeId()
       && pickedPath->getNodeFromTail(2)->getTypeId()==SoSwitch::getClassTypeId()
       && pickedPath->getNodeFromTail(3)->getTypeId()==SoSeparator::getClassTypeId())
   {
@@ -883,13 +897,19 @@ void VP1GeometrySystem::userPickedNode(SoNode* , SoPath *pickedPath)
 
   message("===> Selected Node: "+volhandle->getName());
   if (m_d->controller->printInfoOnClick_Shape()) {
-    foreach (QString str, DumpShape::shapeToStringList(volhandle->geoPVConstLink()->getLogVol()->getShape()))
-      message(str);
-  }
+    if(volhandle->geoPVConstLink()){
+      foreach (QString str, DumpShape::shapeToStringList(volhandle->geoPVConstLink()->getLogVol()->getShape()))
+        message(str);}
+    else{
+      foreach (QString str, DumpShape::shapeToStringList(volhandle->geoVSConstLink()->getShape()))
+        message(str);}
+  }       
 
   if (m_d->controller->printInfoOnClick_Material()) {
+      message("===> Material:");
+      if(volhandle->geoPVConstLink()){
 	  const GeoMaterial* mat = volhandle->geoMaterial();
-	  message("===> Material:");
+	  
 	  QStringList out;
 	  out << VP1GeomUtils::geoMaterialToStringList(mat);
 	  message("     "+out.join(" "));
@@ -905,6 +925,10 @@ void VP1GeometrySystem::userPickedNode(SoNode* , SoPath *pickedPath)
 	  } else {
 		  message("          (the material has no elements defined)");
 	  }
+      }
+      else{
+          message("     Virtual Surface has no material.");
+      }
   }
 
   if ( m_d->controller->printInfoOnClick_CopyNumber() ) {
@@ -966,21 +990,32 @@ void VP1GeometrySystem::userPickedNode(SoNode* , SoPath *pickedPath)
   }
 
   if (m_d->controller->printInfoOnClick_Tree()) {
-    std::ostringstream str;
-    GeoPrintGraphAction pg(str);
-    volhandle->geoPVConstLink()->exec(&pg);
     message("===> Tree:");
-    foreach (QString line, QString(str.str().c_str()).split("\n"))
-      message("     "+line);
+    if(volhandle->geoPVConstLink()){
+        std::ostringstream str;
+        GeoPrintGraphAction pg(str);
+        volhandle->geoPVConstLink()->exec(&pg);
+        foreach (QString line, QString(str.str().c_str()).split("\n"))
+          message("     "+line);
+    }
+    else{
+        message("        Virtual Surface has no child node.");
+    }    
   }
 
   if (m_d->controller->printInfoOnClick_Mass()) {
     //FIXME: Move the mass calculations to the volume handles, and let
     //the common data cache some of the volume information by
     //logVolume).
-    message("===> Total Mass &lt;===");
-    message("Inclusive "+QString::number(Imp::inclusiveMass(volhandle->geoPVConstLink())/SYSTEM_OF_UNITS::kilogram)+" kg");
-    message("Exclusive "+QString::number(Imp::exclusiveMass(volhandle->geoPVConstLink())/SYSTEM_OF_UNITS::kilogram)+" kg");
+    if(volhandle->geoPVConstLink()){
+        message("===> Total Mass &lt;===");
+        message("Inclusive "+QString::number(Imp::inclusiveMass(volhandle->geoPVConstLink())/SYSTEM_OF_UNITS::kilogram)+" kg");
+        message("Exclusive "+QString::number(Imp::exclusiveMass(volhandle->geoPVConstLink())/SYSTEM_OF_UNITS::kilogram)+" kg");
+    }
+    else{
+        message("===> Total Mass: ");
+        message("        Virtual Surface has no mass.");
+    }
   }
 
 }
@@ -1120,15 +1155,16 @@ double VP1GeometrySystem::Imp::inclusiveMass(const PVConstLink& pv) {
 
   GeoVolumeCursor av(pv);
   while (!av.atEnd()) {
-    std::string materialName=av.getVolume()->getLogVol()->getMaterial()->getName();
-    
-    if (QString(materialName.c_str()).endsWith("Ether") || QString(materialName.c_str()).endsWith("HyperUranium")) {
-      // Do nothing.  These are not real volumes. 
-    }
-    else {
-      double delta =  inclusiveMass(av.getVolume()) -  (volume(av.getVolume())*density);
-      mass += delta;
-    }
+    if(av.getVolume()){
+      std::string materialName=av.getVolume()->getLogVol()->getMaterial()->getName();    
+      if (QString(materialName.c_str()).endsWith("Ether") || QString(materialName.c_str()).endsWith("HyperUranium")) {
+        // Do nothing.  These are not real volumes. 
+      }
+      else {
+        double delta =  inclusiveMass(av.getVolume()) -  (volume(av.getVolume())*density);
+        mass += delta;
+      }
+    }    
     av.next();
   }
   return mass;
diff --git a/GeoModelVisualization/VP1GeometrySystems/src/VolumeHandle.cxx b/GeoModelVisualization/VP1GeometrySystems/src/VolumeHandle.cxx
index 804eede1d..518786679 100644
--- a/GeoModelVisualization/VP1GeometrySystems/src/VolumeHandle.cxx
+++ b/GeoModelVisualization/VP1GeometrySystems/src/VolumeHandle.cxx
@@ -13,12 +13,13 @@
 #include "VP1Base/VP1Msg.h"
 // #include "VP1Base/VP1QtInventorUtils.h"
 //#include "VP1Utils/VP1LinAlgUtils.h"
-#include "VP1HEPVis/nodes/SoTransparency.h"
-#include "VP1HEPVis/nodes/SoPolyhedron.h"
-#include "VP1HEPVis/nodes/SoPcons.h"
-#include "VP1HEPVis/VP1HEPVisUtils.h"
+#include "GXHepVis/nodes/SoTransparency.h"
+#include "GXHepVis/nodes/SoPolyhedron.h"
+#include "GXHepVis/nodes/SoPcons.h"
+#include "GXHepVis/GXHepVisUtils.h"
 
 #include "GeoModelKernel/GeoVolumeCursor.h"
+#include "GeoModelKernel/GeoSurfaceCursor.h"
 #include "GeoModelKernel/GeoShapeShift.h"
 #include "GeoModelKernel/GeoTube.h"
 #include "GeoModelKernel/GeoTubs.h"
@@ -40,14 +41,22 @@
 #include <QMap>
 #include <QDataStream>
 #include <unistd.h>
+#include "GeoModelKernel/GeoRectSurface.h"
+#include "GeoModelKernel/Units.h"
+using namespace GeoModelKernelUnits;
 //____________________________________________________________________
 class VolumeHandle::Imp {
 public:
   Imp(VolumeHandleSharedData * the_cd, const PVConstLink& the_pV, const SbMatrix& the_ac)
     : commondata(the_cd), pV(the_pV),accumTrans(the_ac),attachsepHelper(0),attachlabelSepHelper(0),nodesep(0), material(0), label_sep(0), labels(0), isattached(false) {}
-
+  //overload Imp constructor
+  Imp(VolumeHandleSharedData * the_cd, const VSConstLink& the_vS, const SbMatrix& the_ac)
+    : commondata(the_cd), vS(the_vS),accumTrans(the_ac),attachsepHelper(0),attachlabelSepHelper(0),nodesep(0), material(0), label_sep(0), labels(0), isattached(false) {}
+    
   VolumeHandleSharedData * commondata;
   PVConstLink pV;
+  VSConstLink vS;
+  
   const SbMatrix accumTrans;//FIXME: Use pointer - and free once children are created AND nodesep has been build. Or just construct on the fly!
 
   VP1ExtraSepLayerHelper * attachsepHelper;
@@ -91,8 +100,9 @@ QDataStream & operator>> ( QDataStream & in, VolumeHandle::Imp::VolState & vs )
 
 //____________________________________________________________________
 VolumeHandle::VolumeHandle(VolumeHandleSharedData * cd,VolumeHandle * parent, const PVConstLink& pV, int childNumber, const SbMatrix& accumTrans)
-  : m_d(new Imp(cd,pV,accumTrans)), m_childNumber(childNumber), m_nchildren(childNumber>=0?pV->getNChildVols():0), m_parent(parent),
-    m_state(VP1GeoFlags::CONTRACTED)
+: m_d(new Imp(cd,pV,accumTrans)), m_childNumber(childNumber), m_nchildren(childNumber>=0?pV->getNChildVols():0), m_parent(parent),
+  //m_d(new Imp(cd,pV,accumTrans)), m_childNumber(childNumber), m_nchildren(childNumber>=0?3:0), m_parent(parent),
+  m_state(VP1GeoFlags::CONTRACTED)
 {
   if (cd) {
     cd->ref();
@@ -101,6 +111,17 @@ VolumeHandle::VolumeHandle(VolumeHandleSharedData * cd,VolumeHandle * parent, co
   }
 }
 
+//overload VolumeHandle
+VolumeHandle::VolumeHandle(VolumeHandleSharedData * cd,VolumeHandle * parent, const VSConstLink& vS, int childNumber, const SbMatrix& accumTrans)
+: m_d(new Imp(cd,vS,accumTrans)), m_childNumber(childNumber), m_nchildren(childNumber>=0?vS->getNChildVols():0), m_parent(parent),
+  m_state(VP1GeoFlags::CONTRACTED)
+{
+  if (cd) {
+    cd->ref();
+    if (!haveParentsNotExpanded())
+      m_d->attach(this);
+  }
+}
 //____________________________________________________________________
 VolumeHandle::~VolumeHandle()
 {
@@ -131,10 +152,11 @@ void VolumeHandle::initialiseChildren()
     return;
 
   assert(m_nchildren);
-
+  
   //Loop over children:
   m_children.reserve(m_nchildren);
   unsigned ichild(0);
+  
   GeoVolumeCursor av(m_d->pV);
   while (!av.atEnd()) {
 
@@ -146,13 +168,20 @@ void VolumeHandle::initialiseChildren()
 		  mtx(0,3),mtx(1,3),mtx(2,3),mtx(3,3));
 
     matr.multRight(m_d->accumTrans);
-    m_children.push_back(new VolumeHandle(m_d->commondata,this,av.getVolume(),ichild++,matr));
+
+    if(av.getVolume()){
+        //cursor at physics volume
+        m_children.push_back(new VolumeHandle(m_d->commondata,this,av.getVolume(),ichild++,matr));
+    }
+    else{
+        //cursor at virtual surface volume
+        m_children.push_back(new VolumeHandle(m_d->commondata,this,av.getSurface(),ichild++,matr));
+    }
     m_children.back()->expandMothersRecursivelyToNonEther();
-    av.next();
+    av.next();    
   }
-
+  
   assert(ichild==m_nchildren&&m_children.size()==m_nchildren);
-
 }
 
 //____________________________________________________________________
@@ -161,10 +190,20 @@ PVConstLink VolumeHandle::geoPVConstLink() const
   return m_d->pV;
 }
 
+VSConstLink VolumeHandle::geoVSConstLink() const
+{
+  return m_d->vS;
+}
+
 //____________________________________________________________________
 QString VolumeHandle::getName() const
 {
-  return m_d->pV->getLogVol()->getName().c_str();
+  if(m_d->pV){
+      return m_d->pV->getLogVol()->getName().c_str();
+  }
+  else{
+      return m_d->vS->getShape()->type().c_str();
+  }
 }
 
 //____________________________________________________________________
@@ -182,15 +221,32 @@ bool VolumeHandle::hasName(const std::string& n) const
 //____________________________________________________________________
 SoMaterial * VolumeHandle::material()
 {
+  if(m_d->pV){
   VP1Msg::messageDebug2("VolumeHandle::material() - LogVol name: " + QString::fromStdString(m_d->pV->getLogVol()->getName()));
+  }
   // if it's not the first time here and
   // the material has been assigned already, then return that
   if (m_d->material)
     return m_d->material;
-
   // if it's the first timne here, the material has not been assigned yet, then...
-
   //Then, see if the "databases" of defined volumes/material know about this volume:
+  
+  if(!m_d->pV){
+    SoMaterial *surf_material = new SoMaterial;
+    static float colors[2][3] = {
+      {0.0, 1.0, 0.0}, {1.0, 0.0, 0.0}
+    };
+    static float transps[2] = {0.6, 0.6};
+    
+    surf_material->diffuseColor.setValues(0, 2, colors);
+    surf_material->transparency.setValues(0, 2, transps);
+    m_d->material = surf_material;
+//      m_d->material = SurfaceMaterial();
+    assert(m_d->material);
+    m_d->material->ref();      
+    return m_d->material;
+  }
+  
   SoMaterial * mat = m_d->commondata->volVisAttributes()->get(m_d->pV->getLogVol()->getName());
   if (mat) {
     m_d->material = mat;
@@ -216,7 +272,7 @@ SoMaterial * VolumeHandle::material()
     m_d->material->ref();
     return m_d->material;
   }
-
+  
   if (m_parent) {
     m_d->material = m_parent->material();
     assert(m_d->material);
@@ -229,6 +285,7 @@ SoMaterial * VolumeHandle::material()
   m_d->material->ref();
   return m_d->material;
 }
+      
 
 //____________________________________________________________________
 SoSeparator * VolumeHandle::nodeSoSeparator() const
@@ -238,7 +295,7 @@ SoSeparator * VolumeHandle::nodeSoSeparator() const
 
 //____________________________________________________________________
 void VolumeHandle::ensureBuildNodeSep()
-{
+{ 
   VP1Msg::messageDebug3("VolumeHandle::ensureBuildNodeSep()");
   if (m_d->nodesep && m_d->label_sep)
     return;
@@ -250,7 +307,7 @@ void VolumeHandle::ensureBuildNodeSep()
   //   m_d->nodesep->renderCaching.setValue(SoSeparator::ON);
   //   m_d->nodesep->boundingBoxCaching.setValue(SoSeparator::ON);
   m_d->nodesep->ref();//Since we are keeping it around irrespective of whether it is attached or not.
-
+  
   //Transform:
   {
     SoTransform *xf=new SoTransform();
@@ -258,10 +315,18 @@ void VolumeHandle::ensureBuildNodeSep()
     m_d->nodesep->addChild(xf);
   }
 
-
   //VP1Msg::messageDebug("calling toShapeNode()...");
-  bool shapeIsKnown;
-  SoNode * shape = m_d->commondata->toShapeNode(m_d->pV, &shapeIsKnown);//NB: Ignore contained transformation of GeoShapeShifts.
+  bool shapeIsKnown=true;
+
+  SoNode * shape = nullptr;
+  if(m_d->pV){
+      shape = m_d->commondata->toShapeNode(m_d->pV, &shapeIsKnown);//NB: Ignore contained transformation of GeoShapeShifts.  
+  }
+  else{
+    shape = m_d->commondata->toShapeNode(m_d->vS, m_d->nodesep);
+    shapeIsKnown = true;
+  }  
+  
   static const char *unknownShapeTextureFile[]={"/usr/share/gmex/unknownShape.jpg","/usr/local/share/gmex/unknownShape.jpg"};
   SoTexture2 *skin=nullptr;
   if (!shapeIsKnown) {
@@ -281,40 +346,50 @@ void VolumeHandle::ensureBuildNodeSep()
   }
 
   //What phi sector do we belong in?
-  int iphi = m_d->commondata->phiSectorManager()->getVolumeType(m_d->accumTrans, shape);
-
-  if (iphi >= -1 ) {
-    //VP1Msg::messageDebug("Cylinders [iphi >= -1]...");
-    //Substitute shapes that are essentially cylinders with such. This
-    //can be done safely since this tube won't need
-    //phi-slicing and is done to gain render performance.
-    if ( m_d->pV->getLogVol()->getShape()->typeID()==GeoTube::getClassTypeID() )
-    {
-      //VP1Msg::messageDebug("GeoTube...");
-      const GeoTube * geotube = static_cast<const GeoTube*>(m_d->pV->getLogVol()->getShape());
-      if (geotube->getRMin()==0.0)
-        shape = m_d->commondata->getSoCylinderOrientedLikeGeoTube(geotube->getRMax(),geotube->getZHalfLength());
-    }
-    else if ( m_d->pV->getLogVol()->getShape()->typeID()==GeoTubs::getClassTypeID() )
-    {
-      //VP1Msg::messageDebug("GeoTubs...");
-      const GeoTubs * geotubs = static_cast<const GeoTubs*>(m_d->pV->getLogVol()->getShape());
-      if (geotubs->getRMin()==0.0 && geotubs->getDPhi() >= 2*M_PI-1.0e-6)
-        shape = m_d->commondata->getSoCylinderOrientedLikeGeoTube(geotubs->getRMax(),geotubs->getZHalfLength());
-    }
+  int iphi;
+  if (m_d -> pV){
+  iphi = m_d->commondata->phiSectorManager()->getVolumeType(m_d->accumTrans, shape);
   }
+  else{
+  iphi = m_d->commondata->phiSectorManager()->getSurfaceType(m_d->accumTrans, shape);
+  }
+  // SKIP FOR VIRTUAL SURFACE
+  if(m_d->pV){
+      if (iphi >= -1 ) {
+        //VP1Msg::messageDebug("Cylinders [iphi >= -1]...");
+        //Substitute shapes that are essentially cylinders with such. This
+        //can be done safely since this tube won't need
+        //phi-slicing and is done to gain render performance.
+
+        if ( m_d->pV->getLogVol()->getShape()->typeID()==GeoTube::getClassTypeID() )
+        { 
+          //VP1Msg::messageDebug("GeoTube...");
+          const GeoTube * geotube = static_cast<const GeoTube*>(m_d->pV->getLogVol()->getShape());
+          if (geotube->getRMin()==0.0)
+            shape = m_d->commondata->getSoCylinderOrientedLikeGeoTube(geotube->getRMax(),geotube->getZHalfLength());
+        }
+        else if ( m_d->pV->getLogVol()->getShape()->typeID()==GeoTubs::getClassTypeID() )
+        {
+          //VP1Msg::messageDebug("GeoTubs...");
+          const GeoTubs * geotubs = static_cast<const GeoTubs*>(m_d->pV->getLogVol()->getShape());
+          if (geotubs->getRMin()==0.0 && geotubs->getDPhi() >= 2*M_PI-1.0e-6)
+            shape = m_d->commondata->getSoCylinderOrientedLikeGeoTube(geotubs->getRMax(),geotubs->getZHalfLength());
+        }
+      }
+  
 
   //In the case of a GeoShapeShift we add its contained transformation here:
   //Fixme: Remember to use this extra transformation for phisector cuts also!
-  if (m_d->pV->getLogVol()->getShape()->typeID()==GeoShapeShift::getClassTypeID()) {
-    const GeoTrf::Transform3D::MatrixType &mtx=dynamic_cast<const GeoShapeShift*>(m_d->pV->getLogVol()->getShape())->getX().matrix();
-    SbMatrix matr(mtx(0,0),mtx(1,0),mtx(2,0),mtx(3,0),  // Beware, conventions
-		  mtx(0,1),mtx(1,1),mtx(2,1),mtx(3,1),  // differ!
-		  mtx(0,2),mtx(1,2),mtx(2,2),mtx(3,2),
-		  mtx(0,3),mtx(1,3),mtx(2,3),mtx(3,3));
-    SoTransform *xf=new SoTransform();
-    m_d->nodesep->addChild(xf);
-    xf->setMatrix(matr);
+      if (m_d->pV->getLogVol()->getShape()->typeID()==GeoShapeShift::getClassTypeID()) {
+        const GeoTrf::Transform3D::MatrixType &mtx=dynamic_cast<const GeoShapeShift*>(m_d->pV->getLogVol()->getShape())->getX().matrix();
+        SbMatrix matr(mtx(0,0),mtx(1,0),mtx(2,0),mtx(3,0),  // Beware, conventions
+	        mtx(0,1),mtx(1,1),mtx(2,1),mtx(3,1),  // differ!
+	        mtx(0,2),mtx(1,2),mtx(2,2),mtx(3,2),
+	        mtx(0,3),mtx(1,3),mtx(2,3),mtx(3,3));
+        SoTransform *xf=new SoTransform();
+        m_d->nodesep->addChild(xf);
+        xf->setMatrix(matr);
+      }
   }
   //Add shape child(ren) and get the separator (helper) where we attach the nodesep when volume is visible:
   if (iphi >= -1) {
@@ -344,7 +419,7 @@ void VolumeHandle::ensureBuildNodeSep()
 
 //____________________________________________________________________
 void VolumeHandle::Imp::attach(VolumeHandle*vh)
-{
+{ 
   VP1Msg::messageDebug3("VolumeHandle::Imp::attach() - name: " + vh->getName());
   if (!isattached) {
     vh->ensureBuildNodeSep();
@@ -473,9 +548,9 @@ bool VolumeHandle::haveParentsNotExpanded() const
 
 //____________________________________________________________________
 void VolumeHandle::attachAllContractedChildren() {
-
   if (!m_nchildren)
     return;
+    
   if (!childrenAreInitialised())
     initialiseChildren();
 
@@ -558,23 +633,42 @@ bool VolumeHandle::isAttached() const
 
 //____________________________________________________________________
 const GeoMaterial * VolumeHandle::geoMaterial() const {
+  if(!geoPVConstLink()){
+  
+  GeoElement  *oxygen        = new GeoElement("Oxygen",    "O",   19,  39*gram/mole);
+  GeoElement  *nitrogen      = new GeoElement("Nitrogen",  "N",   7,  14*gram/mole);
+  GeoElement  *argon         = new GeoElement("Argon",     "Ar", 18,  40*gram/mole);
+  GeoElement  *aluminium     = new GeoElement("Aluminium", "Al", 13,  26*gram/mole);  
+  
+    // Define Air:
+  double densityOfAir     = 1.2E-3*gram/cm3;               // g/cm^3
+  GeoMaterial *Air           = new GeoMaterial("Air",densityOfAir);
+  Air->add(oxygen,2*0.21);                        // diatomic   oxygen   21% by volume.
+  Air->add(nitrogen,2*0.78);                        // diatomic   nitrogen 78% by volume.
+  Air->add(argon,0.01);                          // monoatomic argon    78% by volume.
+  Air->lock();
+  
+     return Air;
+  }
   return geoPVConstLink()->getLogVol()->getMaterial();
 }
 
 //____________________________________________________________________
 bool VolumeHandle::isEther() const
 {
+  if(!m_d->pV){
+      return false;
+  }
   return QString(geoMaterial()->getName().c_str()).endsWith("Ether") ||
     QString(geoMaterial()->getName().c_str()).endsWith("HyperUranium");
 }
 
 //____________________________________________________________________
 void VolumeHandle::expandMothersRecursivelyToNonEther() {
-
   if (!nChildren()||!isEther()) {
     return;
   }
-
+  
   setState(VP1GeoFlags::ZAPPED);
   initialiseChildren();
   VolumeHandleListItr childItrE = m_children.end();
@@ -655,7 +749,7 @@ VolumeHandle::Imp::VolState VolumeHandle::Imp::getChildStates(const VolumeHandle
 
 //____________________________________________________________________
 void VolumeHandle::Imp::applyChildStates(const VolState& vs,VolumeHandle*theclass)
-{
+{ 
   bool hasExpandedChildren = !vs.m_expandedChildren.isEmpty();
   bool hasZappedChildren = !vs.m_zappedChildren.isEmpty();
   if (!hasExpandedChildren&&!hasZappedChildren)
@@ -665,6 +759,7 @@ void VolumeHandle::Imp::applyChildStates(const VolState& vs,VolumeHandle*theclas
   QSet<quint32>::const_iterator zapItr, zapItrEnd = vs.m_zappedChildren.end();
 
   theclass->initialiseChildren();
+  
   VolumeHandleListConstItr it, itE = theclass->m_children.end();
   for (it = theclass->m_children.begin(); it!=itE; ++it) {
     quint32 id = (*it)->hashID();
@@ -705,7 +800,7 @@ bool VolumeHandle::Imp::hasNonStandardShapeChildren(const SoGroup*g)
 //____________________________________________________________________
 bool VolumeHandle::isInitialisedAndHasNonStandardShape() const
 {
-  VP1HEPVisUtils::initAllCustomClasses();
+  GXHepVisUtils::initAllCustomClasses();
   return m_d->nodesep ? Imp::hasNonStandardShapeChildren(m_d->nodesep) : false;
 }
 
diff --git a/GeoModelVisualization/VP1GeometrySystems/src/VolumeHandleSharedData.cxx b/GeoModelVisualization/VP1GeometrySystems/src/VolumeHandleSharedData.cxx
index a12d57dd2..211d8af01 100644
--- a/GeoModelVisualization/VP1GeometrySystems/src/VolumeHandleSharedData.cxx
+++ b/GeoModelVisualization/VP1GeometrySystems/src/VolumeHandleSharedData.cxx
@@ -9,17 +9,19 @@
 
 #include "GeoModelKernel/GeoVPhysVol.h"
 #include "GeoModelKernel/GeoShapeShift.h"
-#include "VP1HEPVis/nodes/SoGenericBox.h"
-#include "VP1HEPVis/nodes/SoTubs.h"
-#include "VP1HEPVis/nodes/SoPcons.h"
-#include "VP1HEPVis/nodes/SoTessellated.h"
+#include "GXHepVis/nodes/SoGenericBox.h"
+#include "GXHepVis/nodes/SoTubs.h"
+#include "GXHepVis/nodes/SoPcons.h"
+#include "GXHepVis/nodes/SoTessellated.h"
 
 #include <Inventor/nodes/SoCylinder.h>
 #include <Inventor/nodes/SoRotationXYZ.h>
 #include <Inventor/nodes/SoSeparator.h>
+#include <Inventor/nodes/SoSelection.h>
 
-#include <map>
 
+#include <map>
+#include <iostream>
 //____________________________________________________________________
 class VolumeHandleSharedData::Imp {
 public:
@@ -209,6 +211,23 @@ SoNode * VolumeHandleSharedData::toShapeNode(const PVConstLink& pV, bool * shape
   return shape;
 }
 
+
+//____________________________________________________________________
+SoNode * VolumeHandleSharedData::toShapeNode(const VSConstLink& vS, SoSeparator* nodesep)
+{ 
+  SoSelection * integrate_shape = new SoSelection;
+  SoSeparator * shape = new SoSeparator;
+  //SoGroup * shape = new SoGroup;
+  m_d->visaction.reset_separator();
+  const GeoVSurfaceShape* surf_shape = vS->getShape();
+  surf_shape->exec(&(m_d->visaction));
+  shape = m_d->visaction.getVSurfaceShape();
+  integrate_shape->addChild(shape);
+  //shape->ref();
+  integrate_shape->ref();
+  return integrate_shape;
+}
+
 //____________________________________________________________________
 SoNode * VolumeHandleSharedData::getSoCylinderOrientedLikeGeoTube(const double& radius, const double& halfLength)
 {
diff --git a/GeoModelVisualization/VP1GeometrySystems/src/VolumeTreeModel.cxx b/GeoModelVisualization/VP1GeometrySystems/src/VolumeTreeModel.cxx
index 511b78df6..37c1c66d6 100644
--- a/GeoModelVisualization/VP1GeometrySystems/src/VolumeTreeModel.cxx
+++ b/GeoModelVisualization/VP1GeometrySystems/src/VolumeTreeModel.cxx
@@ -346,8 +346,12 @@ QVariant VolumeTreeModel::data(const QModelIndex& index, int role) const
 
     if (volumeHandle->nChildren()>0)
       return volumeHandle->getName() + " (" + QString::fromStdString(volumeHandle->geoMaterial()->getName()) + ") [" + QString::number(volumeHandle->nChildren())+"] ("+ volState + ")" ;
-    else
-      return volumeHandle->getName() + " (" + QString::fromStdString(volumeHandle->geoMaterial()->getName()) + ") ("+ volState + ")" ;
+    else{
+      if (volumeHandle->geoVSConstLink())
+        return volumeHandle->getName();
+      else
+        return volumeHandle->getName() + " (" + QString::fromStdString(volumeHandle->geoMaterial()->getName()) + ") ("+ volState + ")" ;
+    }
   }
 
   if (role==Qt::ForegroundRole)
diff --git a/GeoModelVisualization/VP1GuideLineSystems/CMakeLists.txt b/GeoModelVisualization/VP1GuideLineSystems/CMakeLists.txt
index a9dbb0d75..ef5110d66 100644
--- a/GeoModelVisualization/VP1GuideLineSystems/CMakeLists.txt
+++ b/GeoModelVisualization/VP1GuideLineSystems/CMakeLists.txt
@@ -9,7 +9,7 @@ file( GLOB UIS src/*.ui )
 add_library( GXGuideLineSystems SHARED ${SOURCES} ${HEADERS} ${UIS} )
 target_link_libraries( GXGuideLineSystems
    PUBLIC Coin::Coin Qt${QT_VERSION}::Core Qt${QT_VERSION}::Gui Qt${QT_VERSION}::Widgets GXBase
-   PRIVATE GeoModelCore::GeoModelKernel GXHEPVis )
+   PRIVATE GeoModelCore::GeoModelKernel GXHepVis )
 target_include_directories( GXGuideLineSystems PUBLIC
    $<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}>
    $<INSTALL_INTERFACE:${CMAKE_INSTALL_INCLUDEDIR}> )
diff --git a/GeoModelVisualization/VP1GuideLineSystems/src/VP1Letters.cxx b/GeoModelVisualization/VP1GuideLineSystems/src/VP1Letters.cxx
index 569885f71..6ae750150 100644
--- a/GeoModelVisualization/VP1GuideLineSystems/src/VP1Letters.cxx
+++ b/GeoModelVisualization/VP1GuideLineSystems/src/VP1Letters.cxx
@@ -13,8 +13,8 @@
 ////////////////////////////////////////////////////////////////
 
 #include "VP1GuideLineSystems/VP1Letters.h"
-#include "VP1HEPVis/SbPolyhedron.h"
-#include "VP1HEPVis/nodes/SoPolyhedron.h"
+#include "GXHepVis/SbPolyhedron.h"
+#include "GXHepVis/nodes/SoPolyhedron.h"
 #include <Inventor/nodes/SoMaterial.h>
 #include <Inventor/nodes/SoCube.h>
 #include <Inventor/nodes/SoSeparator.h>
diff --git a/GeoModelVisualization/VP1HEPVis/src/VP1HEPVisUtils.cxx b/GeoModelVisualization/VP1HEPVis/src/VP1HEPVisUtils.cxx
deleted file mode 100644
index d8cdf1297..000000000
--- a/GeoModelVisualization/VP1HEPVis/src/VP1HEPVisUtils.cxx
+++ /dev/null
@@ -1,328 +0,0 @@
-/*
-  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
-*/
-
-
-////////////////////////////////////////////////////////////////
-//                                                            //
-//  Implementation of class VP1HEPVisUtils                    //
-//                                                            //
-//  Author: Thomas H. Kittelmann (Thomas.Kittelmann@cern.ch)  //
-//  Initial version: November 2008                            //
-//  Update: Giorgi Gvaberidze (ggvaberi@cern.ch)              //
-//  Update  version: November 2010                            //  
-//                                                            //
-////////////////////////////////////////////////////////////////
-
-#include "VP1HEPVis/VP1HEPVisUtils.h"
-
-#include <Inventor/C/errors/debugerror.h>
-#include <Inventor/nodes/SoSelection.h>
-#include <Inventor/nodes/SoSeparator.h>
-#include <Inventor/nodes/SoSwitch.h>
-//---
-#include <Inventor/nodes/SoSphere.h>
-
-#include "VP1HEPVis/nodes/SoCons.h"
-#include "VP1HEPVis/nodes/SoGenericBox.h"
-#include "VP1HEPVis/nodes/SoLAr.h"
-#include "VP1HEPVis/nodes/SoPcons.h"
-#include "VP1HEPVis/nodes/SoPolyhedron.h"
-#include "VP1HEPVis/nodes/SoTransparency.h"
-#include "VP1HEPVis/nodes/SoTubs.h"
-#include "VP1HEPVis/nodes/SoTessellated.h"
-
-#include <Inventor/nodes/SoSeparator.h>
-#include <Inventor/nodes/SoIndexedFaceSet.h>
-#include <Inventor/nodes/SoVertexProperty.h>
-#include <VP1HEPVis/SbPolyhedron.h>
-
-#include <iostream>//fixme
-
-//____________________________________________________________________
-class VP1HEPVisUtils::Imp {
-public:
-  template <class T>
-  static SoNode * convertToAlternateRep(SoNode *);
-
-  template <class T>
-  static void clearAlternateRep(SoNode *);
-
-  template <class T>
-  static void updateAlternateRepIfNull(SoNode *);
-
-  static bool isGroup(SoNode* n);
-  static bool isNonCustomTree(SoGroup* g);
-  static SoGroup * convertToStandardGroupNode(SoGroup* g,bool transferChildren);
-  static SoGroup * convertToStandardScene(SoGroup* g);
-  static void updateAllNullAlternativeReps(SoGroup*g);
-};
-
-//____________________________________________________________________
-bool VP1HEPVisUtils::Imp::isNonCustomTree(SoGroup* g)
-{
-  if (!g)
-    return true;//well...
-
-  if (isCustomNode(g))
-    return false;
-
-  for (int i = 0; i<g->getNumChildren();++i) {
-    SoNode * n = g->getChild(i);
-    if ( Imp::isGroup(n) ) {
-      if (!isNonCustomTree(static_cast<SoGroup*>(n)))
-	return false;
-    } else {
-      if (isCustomNode(n))
-	return false;
-    }
-  }
-  return true;
-}
-
-//____________________________________________________________________
-SoGroup * VP1HEPVisUtils::Imp::convertToStandardGroupNode(SoGroup* g,bool transferChildren)
-{
-  //Create new non-custom node and transfer relevant fields:
-  SoGroup * newgroup(0);
-  if ( g->getTypeId().isDerivedFrom(SoSeparator::getClassTypeId()) &&
-       ! g->getTypeId().isDerivedFrom(SoSelection::getClassTypeId()) ) {
-    SoSeparator * sep = new SoSeparator;
-    SoSeparator * origsep = static_cast<SoSeparator*>(g);
-    sep->renderCaching.setValue(origsep->renderCaching.getValue());
-    sep->boundingBoxCaching.setValue(origsep->boundingBoxCaching.getValue());
-    sep->renderCulling.setValue(origsep->renderCulling.getValue());
-    sep->pickCulling.setValue(origsep->pickCulling.getValue());
-    newgroup = sep;
-  } else if ( g->getTypeId().isDerivedFrom(SoSelection::getClassTypeId()) ) {
-    SoSelection * sel = new SoSelection;
-    SoSelection * origsel = static_cast<SoSelection*>(g);
-    sel->renderCaching.setValue(origsel->renderCaching.getValue());
-    sel->boundingBoxCaching.setValue(origsel->boundingBoxCaching.getValue());
-    sel->renderCulling.setValue(origsel->renderCulling.getValue());
-    sel->pickCulling.setValue(origsel->pickCulling.getValue());
-    sel->policy.setValue(origsel->policy.getValue());
-    newgroup = sel;
-  } else if ( g->getTypeId().isDerivedFrom(SoSwitch::getClassTypeId()) ) {
-    SoSwitch *sw = new SoSwitch;
-    sw->whichChild.setValue(static_cast<SoSwitch*>(g)->whichChild.getValue());
-    newgroup = sw;
-  } else {
-    //Everything else is just treated like a group (we could add more specialisations):
-    newgroup = new SoGroup;
-  }
-
-  //Transfer name:
-  newgroup->setName(g->getName());
-
-  //Transfer children:
-  if (transferChildren)
-    for (int i = 0; i<g->getNumChildren();++i)
-      newgroup->addChild(g->getChild(i));
-
-  return newgroup;
-}
-
-//____________________________________________________________________
-SoGroup * VP1HEPVisUtils::Imp::convertToStandardScene(SoGroup* g)
-{
-  if (Imp::isNonCustomTree(g))
-    return g;
-
-  //We have to change something underneath, so we must get a new (and non-custom) group node:
-  SoGroup * thegroup = convertToStandardGroupNode(g,false/*don't transfer children*/);
-  if (!thegroup)
-    std::cout <<"BAAAAAAAAAD!"<<std::endl;
-  for (int i = 0; i<g->getNumChildren();++i) {
-    SoNode * n = g->getChild(i);
-    if (isGroup(n)) {
-      SoGroup * standard = convertToStandardScene(static_cast<SoGroup*>(n));
-      if (standard)
-	thegroup->addChild(standard);
-      else
-	std::cout <<"BAD 1"<<std::endl;
-    } else {
-      SoNode * ntoadd = isCustomNode(n)?convertCustomNodeToAlternateRep(n):n;
-      if (ntoadd)
-	thegroup->addChild(isCustomNode(n)?convertCustomNodeToAlternateRep(n):n);
-      else
-	std::cout <<"BAD 2"<<std::endl;
-    }
-  }
-
-  return thegroup;
-}
-
-
-//____________________________________________________________________
-SoGroup * VP1HEPVisUtils::convertToStandardScene(SoGroup* g)
-{
-  if (!g)
-    return 0;
-
-  initAllCustomClasses();
-
-  if (Imp::isNonCustomTree(g))
-    return g;
-
-
-  g->ref();
-
-  updateAllAlternativeReps(g);
-
-  SoGroup* thegroup = Imp::convertToStandardScene(g);
-  thegroup->ref();
-
-  clearAllAlternativeReps(g);
-
-  g->unrefNoDelete();
-  thegroup->unrefNoDelete();
-  return thegroup;
-}
-
-//____________________________________________________________________
-bool VP1HEPVisUtils::isCustomNode(SoNode* n)
-{
-  if (!n)
-    return false;
-
-  return n->getNodeType() & SoNode::EXTENSION;
-}
-
-//____________________________________________________________________
-template <class T>
-SoNode * VP1HEPVisUtils::Imp::convertToAlternateRep(SoNode * n)
-{
-  if (!n)
-    return 0;
-  T * t = static_cast<T*>(n);
-  SoNode * n_alt = t->alternateRep.getValue();
-  if (n_alt) {
-    //Don't clear the alternateRep, since it was there before.
-  } else {
-    t->generateAlternateRep();
-    n_alt = t->alternateRep.getValue();
-    if (n_alt) {
-      //Clear the alternateRep, since it was not there before.
-      n_alt->ref();
-      t->clearAlternateRep();
-      n_alt->unrefNoDelete();
-    } else {
-      return 0;
-    }
-  }
-  n_alt->setName(n->getName());
-  return n_alt;
-}
-
-//____________________________________________________________________
-template <class T>
-void VP1HEPVisUtils::Imp::clearAlternateRep(SoNode * n)
-{
-  T * t = static_cast<T*>(n);
-  if (t&&t->alternateRep.getValue())
-    t->clearAlternateRep();
-}
-
-//____________________________________________________________________
-template <class T>
-void VP1HEPVisUtils::Imp::updateAlternateRepIfNull(SoNode * n)
-{
-  T * t = static_cast<T*>(n);
-  if (t&&!t->alternateRep.getValue()) {
-    t->generateAlternateRep();
-    t->clearAlternateRep();
-  }
-}
-
-//____________________________________________________________________
-SoNode * VP1HEPVisUtils::convertCustomNodeToAlternateRep(SoNode*n)
-{
-  if (!n)
-    return 0;
-
-  initAllCustomClasses();
-
-  if ( n->getTypeId().isDerivedFrom(SoCons::getClassTypeId()) ) return Imp::convertToAlternateRep<SoCons>(n);
-  if ( n->getTypeId().isDerivedFrom(SoLAr::getClassTypeId()) ) return Imp::convertToAlternateRep<SoLAr>(n);
-//NOT IMPLEMENTED   if ( n->getTypeId().isDerivedFrom(SoPcons::getClassTypeId()) ) return Imp::convertToAlternateRep<SoPcons>(n);
-  if ( n->getTypeId().isDerivedFrom(SoPcons::getClassTypeId()) ) return Imp::convertToAlternateRep<SoPcons>(n);
-  if ( n->getTypeId().isDerivedFrom(SoGenericBox::getClassTypeId()) ) return Imp::convertToAlternateRep<SoGenericBox>(n);
-  if ( n->getTypeId().isDerivedFrom(SoTubs::getClassTypeId()) ) return Imp::convertToAlternateRep<SoTubs>(n);
-  if ( n->getTypeId().isDerivedFrom(SoPolyhedron::getClassTypeId()) ) return Imp::convertToAlternateRep<SoPolyhedron>(n);
-  if ( n->getTypeId().isDerivedFrom(SoTessellated::getClassTypeId()) ) return Imp::convertToAlternateRep<SoTessellated>(n);
-
-  //A bit special. Probably should not get called here.
-  if ( Imp::isGroup(n) ) return Imp::convertToStandardGroupNode(static_cast<SoGroup*>(n),false /*transferChildren*/);
-  SoGroup * g = new SoGroup;
-  return g;//fixme: share this
-}
-
-//____________________________________________________________________
-bool VP1HEPVisUtils::Imp::isGroup(SoNode* n)
-{
-  return n->getTypeId().isDerivedFrom(SoGroup::getClassTypeId());
-}
-
-//____________________________________________________________________
-void VP1HEPVisUtils::Imp::updateAllNullAlternativeReps(SoGroup*g)
-{
-  for (int i = 0; i<g->getNumChildren();++i) {
-    SoNode * n = g->getChild(i);
-    if ( Imp::isGroup(n) ) {
-      updateAllNullAlternativeReps(static_cast<SoGroup*>(n));
-    } else if (VP1HEPVisUtils::isCustomNode(n)) {
-      if ( n->getTypeId().isDerivedFrom(SoCons::getClassTypeId()) ) return Imp::updateAlternateRepIfNull<SoCons>(n);
-      if ( n->getTypeId().isDerivedFrom(SoLAr::getClassTypeId()) ) return Imp::updateAlternateRepIfNull<SoLAr>(n);
-      //NOT IMPLEMENTED if ( n->getTypeId().isDerivedFrom(SoPcons::getClassTypeId()) ) return Imp::updateAlternateRepIfNull<SoPcons>(n);
-      if ( n->getTypeId().isDerivedFrom(SoPcons::getClassTypeId()) ) return Imp::updateAlternateRepIfNull<SoPcons>(n);
-      if ( n->getTypeId().isDerivedFrom(SoGenericBox::getClassTypeId()) ) return Imp::updateAlternateRepIfNull<SoGenericBox>(n);
-      if ( n->getTypeId().isDerivedFrom(SoTubs::getClassTypeId()) ) return Imp::updateAlternateRepIfNull<SoTubs>(n);
-      if ( n->getTypeId().isDerivedFrom(SoPolyhedron::getClassTypeId()) ) return Imp::updateAlternateRepIfNull<SoPolyhedron>(n);
-      if ( n->getTypeId().isDerivedFrom(SoTessellated::getClassTypeId()) ) return Imp::updateAlternateRepIfNull<SoTessellated>(n);
-    }
-  }
-}
-
-//____________________________________________________________________
-void VP1HEPVisUtils::updateAllAlternativeReps(SoGroup*g)
-{
-  clearAllAlternativeReps(g);//To make sure all altReps. are NULL
-			     //(thus, we only update those with null,
-			     //avoiding repeated updates on shared
-			     //instances)
-  Imp::updateAllNullAlternativeReps(g);
-}
-
-//____________________________________________________________________
-void VP1HEPVisUtils::clearAllAlternativeReps(SoGroup*g)
-{
-  for (int i = 0; i<g->getNumChildren();++i) {
-    SoNode * n = g->getChild(i);
-    if ( Imp::isGroup(n) ) {
-      clearAllAlternativeReps(static_cast<SoGroup*>(n));
-    } else if (isCustomNode(n)) {
-      if ( n->getTypeId().isDerivedFrom(SoCons::getClassTypeId()) ) return Imp::clearAlternateRep<SoCons>(n);
-      if ( n->getTypeId().isDerivedFrom(SoLAr::getClassTypeId()) ) return Imp::clearAlternateRep<SoLAr>(n);
-      //NOT IMPLEMENTED if ( n->getTypeId().isDerivedFrom(SoPcons::getClassTypeId()) ) return Imp::clearAlternateRep<SoPcons>(n);
-      if ( n->getTypeId().isDerivedFrom(SoPcons::getClassTypeId()) ) return Imp::clearAlternateRep<SoPcons>(n);
-      if ( n->getTypeId().isDerivedFrom(SoGenericBox::getClassTypeId()) ) return Imp::clearAlternateRep<SoGenericBox>(n);
-      if ( n->getTypeId().isDerivedFrom(SoTubs::getClassTypeId()) ) return Imp::clearAlternateRep<SoTubs>(n);
-      if ( n->getTypeId().isDerivedFrom(SoPolyhedron::getClassTypeId()) ) return Imp::clearAlternateRep<SoPolyhedron>(n);
-      if ( n->getTypeId().isDerivedFrom(SoTessellated::getClassTypeId()) ) return Imp::clearAlternateRep<SoTessellated>(n);
-    }
-  }
-}
-
-//____________________________________________________________________
-void VP1HEPVisUtils::initAllCustomClasses()
-{
-  SoCons::initClass();
-  SoGenericBox::initClass();
-  SoLAr::initClass();
-  SoPcons::initClass();
-  SoPolyhedron::initClass();
-  SoTransparency::initClass();
-  SoTubs::initClass();
-  SoTessellated::initClass();
-}
diff --git a/cmake/GeoModel-version.cmake b/cmake/GeoModel-version.cmake
index 7229a9c5f..e45a1f3b5 100644
--- a/cmake/GeoModel-version.cmake
+++ b/cmake/GeoModel-version.cmake
@@ -1,5 +1,5 @@
 # Set up the version of GeoModel as a cache variable, so that other
 # sub-projects could use this value.
-set( GeoModel_VERSION "6.5.0" CACHE STRING
+set( GeoModel_VERSION "7.0.0" CACHE STRING
     "Version of the GeoModel project" )
 
-- 
GitLab