From 8eb4f73172848d9610a12649c7aba18ebad4730c Mon Sep 17 00:00:00 2001
From: Riccardo Maria Bianchi <riccardo.maria.bianchi@cern.ch>
Date: Wed, 26 Jun 2024 16:53:01 +0200
Subject: [PATCH] Add GenericTrap to Read.

---
 .../GeoModelRead/GeoModelRead/ReadGeoModel.h  |  8 +-
 .../src/BuildGeoShapes_GenericTrap.cpp        | 84 +++++++++++++++++++
 .../src/BuildGeoShapes_GenericTrap.h          | 30 +++++++
 .../src/BuildGeoShapes_SimplePolygonBrep.cpp  |  2 +-
 GeoModelIO/GeoModelRead/src/ReadGeoModel.cpp  | 43 +++++++++-
 5 files changed, 162 insertions(+), 5 deletions(-)
 create mode 100644 GeoModelIO/GeoModelRead/src/BuildGeoShapes_GenericTrap.cpp
 create mode 100644 GeoModelIO/GeoModelRead/src/BuildGeoShapes_GenericTrap.h

diff --git a/GeoModelIO/GeoModelRead/GeoModelRead/ReadGeoModel.h b/GeoModelIO/GeoModelRead/GeoModelRead/ReadGeoModel.h
index 48e661229..d659f787a 100644
--- a/GeoModelIO/GeoModelRead/GeoModelRead/ReadGeoModel.h
+++ b/GeoModelIO/GeoModelRead/GeoModelRead/ReadGeoModel.h
@@ -100,6 +100,7 @@ class BuildGeoShapes_TwistedTrap;
 class BuildGeoShapes_Pcon;
 class BuildGeoShapes_Pgon;
 class BuildGeoShapes_SimplePolygonBrep;
+class BuildGeoShapes_GenericTrap;
 class BuildGeoShapes_UnidentifiedShape;
 
 // type definitions
@@ -183,6 +184,7 @@ class ReadGeoModel {
     unsigned long getNShapes_Pcon() { return m_shapes_Pcon.size(); };
     unsigned long getNShapes_Pgon() { return m_shapes_Pgon.size(); };
     unsigned long getNShapes_SimplePolygonBrep() { return m_shapes_SimplePolygonBrep.size(); };
+    unsigned long getNShapes_GenericTrap() { return m_shapes_GenericTrap.size(); };
     unsigned long getNShapes_Trap() { return m_shapes_Trap.size(); };
     unsigned long getNShapes_Trd() { return m_shapes_Trd.size(); };
     unsigned long getNShapes_Tube() { return m_shapes_Tube.size(); };
@@ -206,10 +208,11 @@ class ReadGeoModel {
     void buildAllShapes_Tubs();
     void buildAllShapes_Torus();
     void buildAllShapes_TwistedTrap();
+    void buildAllShapes_UnidentifiedShape();
     void buildAllShapes_Pcon();
     void buildAllShapes_Pgon();
     void buildAllShapes_SimplePolygonBrep();
-    void buildAllShapes_UnidentifiedShape();
+    void buildAllShapes_GenericTrap();
     void buildAllShapes_Operators();
 
 
@@ -408,6 +411,7 @@ class ReadGeoModel {
     BuildGeoShapes_Pcon* m_builderShape_Pcon;
     BuildGeoShapes_Pgon* m_builderShape_Pgon;
     BuildGeoShapes_SimplePolygonBrep* m_builderShape_SimplePolygonBrep;
+    BuildGeoShapes_GenericTrap* m_builderShape_GenericTrap;
     BuildGeoShapes_UnidentifiedShape* m_builderShape_UnidentifiedShape;
 
     //! containers to store the list of GeoModel nodes coming from the DB
@@ -443,6 +447,7 @@ class ReadGeoModel {
     DBRowsList m_shapes_Pcon;
     DBRowsList m_shapes_Pgon;
     DBRowsList m_shapes_SimplePolygonBrep;
+    DBRowsList m_shapes_GenericTrap;
     DBRowsList m_shapes_UnidentifiedShape;
     
     // containers to store shapes' data, 
@@ -450,6 +455,7 @@ class ReadGeoModel {
     DBRowsList m_shapes_Pcon_data;
     DBRowsList m_shapes_Pgon_data;
     DBRowsList m_shapes_SimplePolygonBrep_data;
+    DBRowsList m_shapes_GenericTrap_data;
 
     // containers to store shape operators / boolean shapes
     DBRowsList m_shapes_Shift;
diff --git a/GeoModelIO/GeoModelRead/src/BuildGeoShapes_GenericTrap.cpp b/GeoModelIO/GeoModelRead/src/BuildGeoShapes_GenericTrap.cpp
new file mode 100644
index 000000000..dc265b92c
--- /dev/null
+++ b/GeoModelIO/GeoModelRead/src/BuildGeoShapes_GenericTrap.cpp
@@ -0,0 +1,84 @@
+/*
+  Copyright (C) 2002-2024 CERN for the benefit of the ATLAS collaboration
+*/
+
+/*
+ * Created on: May, 2024
+ * Author: Riccardo Maria BIANCHI <riccardo.maria.bianchi@cern.ch>
+ */
+
+#include "BuildGeoShapes_GenericTrap.h"
+
+#include "GeoModelKernel/GeoGenericTrap.h"
+#include "GeoModelHelpers/variantHelpers.h"
+#include "GeoModelHelpers/throwExcept.h"
+
+#include <vector>
+#include <iostream>
+
+void BuildGeoShapes_GenericTrap::buildShape(const DBRowEntry row)
+{
+    if (!(m_shape_data.size()))
+    {
+        THROW_EXCEPTION("ERROR! GeoGenericTrap shape has no ZPlanes data!! [m_shape_data.size() == 0]");
+    }
+
+    // === get shape numeric data from the DB row
+    // shape ID
+    const int shapeId = GeoModelHelpers::variantHelper::getFromVariant_Int(row[0], "GenericTrap:shapeID");
+    // shape volume
+    const double shapeVolume = GeoModelHelpers::variantHelper::getFromVariant_Double(row[1], "GenericTrap:shapeVolume");
+    // shape parameters
+    const double zHalfLength = GeoModelHelpers::variantHelper::getFromVariant_Double(row[2], "GenericTrap:ZHalfLength");
+    const unsigned int NVertices = GeoModelHelpers::variantHelper::getFromVariant_Int(row[3], "GenericTrap:NVertices");
+    // pointers to variable shape data stored in a separate table
+    const int dataStart = GeoModelHelpers::variantHelper::getFromVariant_Int(row[4], "GenericTrap:dataStart");
+    const int dataEnd = GeoModelHelpers::variantHelper::getFromVariant_Int(row[5], "GenericTrap:dataEnd");
+
+    // and now loop over the additional shape's data,
+    // to get the parameters of all vertices
+
+    //container for GenericTrap vertices
+    GeoGenericTrapVertices vertices; 
+
+    // extract subvector
+    // NOTE: we use (dataStart-1) to cope with the difference between the DB rows starting from '1',
+    //       which is what the 'dataStart' stores, and the vector items, which start '0';
+    //       also, the constructor of the sub-vector takes the element from 'begin+dataStart-1' included
+    //       and 'begin+dataEnd' excluded.
+    const DBRowsList thisShapeData(m_shape_data.begin() + (dataStart - 1),
+                                   m_shape_data.begin() + (dataEnd));
+    if (!(thisShapeData.size()))
+    {
+        THROW_EXCEPTION("ERROR! GeoGenericTrap shape ZPlanes data have not been retrieved!!");
+    }
+    if (!(NVertices == thisShapeData.size()))
+    {
+        THROW_EXCEPTION("ERROR! GeoGenericTrap shape : size of ZPlanes data does not correspond to the number of ZPlanes declared!!");
+    }
+    // loop over the data defining the ZPlanes
+    for (const DBRowEntry &dataRow : thisShapeData)
+    {
+        const double xV = GeoModelHelpers::variantHelper::getFromVariant_Double(dataRow[1], "GenericTrap:data_xV");
+        const double yV = GeoModelHelpers::variantHelper::getFromVariant_Double(dataRow[2], "GenericTrap:data_yV");
+        // add a vertex to the collection of all GeoGenericTrap vertices
+        vertices.push_back(GeoTwoVector(xV, yV));
+    }
+
+    // build the basic GeoGenericTrap shape
+    GeoGenericTrap *shape = new GeoGenericTrap(zHalfLength, vertices);
+
+    // sanity checks on the resulting GenericTrap shape
+    if (shape->getVertices().size() != NVertices)
+    {
+        THROW_EXCEPTION("ERROR! GeoGenericTrap actual number of vertices: " + std::to_string(shape->getVertices().size()) + " is not equal to the original size! --> " + std::to_string(NVertices));
+    }
+    // if (!shape->isValid())
+    // {
+    //     THROW_EXCEPTION("ERROR! GeoGenericTrap shape is not valid!!");
+    // }
+
+    storeBuiltShape(shapeId, shape);
+
+    return;
+}
diff --git a/GeoModelIO/GeoModelRead/src/BuildGeoShapes_GenericTrap.h b/GeoModelIO/GeoModelRead/src/BuildGeoShapes_GenericTrap.h
new file mode 100644
index 000000000..5370afcf6
--- /dev/null
+++ b/GeoModelIO/GeoModelRead/src/BuildGeoShapes_GenericTrap.h
@@ -0,0 +1,30 @@
+/*
+  Copyright (C) 2002-2024 CERN for the benefit of the ATLAS collaboration
+*/
+
+/*
+ * BuildGeoShapes_GenericTrap.h
+ *
+ * Created on: June, 2024
+ * Author: Riccardo Maria BIANCHI <riccardo.maria.bianchi@cern.ch>
+ *
+ */
+
+#ifndef GEOMODELREAD_BuildGeoShapes_GenericTrap_H
+#define GEOMODELREAD_BuildGeoShapes_GenericTrap_H
+
+#include "BuildGeoShapes.h"
+
+#include "GeoModelDBManager/definitions.h"
+
+#include <vector>
+#include <variant>
+
+class BuildGeoShapes_GenericTrap : public BuildGeoShapes
+{
+public:
+  BuildGeoShapes_GenericTrap(const unsigned size, DBRowsList shapeData):BuildGeoShapes("GenericTrap", size, shapeData){};
+  void buildShape(const DBRowEntry row) override;
+};
+
+#endif
diff --git a/GeoModelIO/GeoModelRead/src/BuildGeoShapes_SimplePolygonBrep.cpp b/GeoModelIO/GeoModelRead/src/BuildGeoShapes_SimplePolygonBrep.cpp
index d78a1eb11..3a73172d1 100644
--- a/GeoModelIO/GeoModelRead/src/BuildGeoShapes_SimplePolygonBrep.cpp
+++ b/GeoModelIO/GeoModelRead/src/BuildGeoShapes_SimplePolygonBrep.cpp
@@ -61,7 +61,7 @@ void BuildGeoShapes_SimplePolygonBrep::buildShape(const DBRowEntry row)
     {
         const double xV = GeoModelHelpers::variantHelper::getFromVariant_Double(dataRow[1], "SimplePolygonBrep:data_xV");
         const double yV = GeoModelHelpers::variantHelper::getFromVariant_Double(dataRow[2], "SimplePolygonBrep:data_yV");
-        // add a Z plane to the GeoSimplePolygonBrep
+        // add a vertex to the GeoSimplePolygonBrep
         shape->addVertex(xV, yV);
     }
 
diff --git a/GeoModelIO/GeoModelRead/src/ReadGeoModel.cpp b/GeoModelIO/GeoModelRead/src/ReadGeoModel.cpp
index e2c3d98a6..1558b3fcf 100644
--- a/GeoModelIO/GeoModelRead/src/ReadGeoModel.cpp
+++ b/GeoModelIO/GeoModelRead/src/ReadGeoModel.cpp
@@ -40,6 +40,7 @@
 #include "BuildGeoShapes_Torus.h"
 #include "BuildGeoShapes_TwistedTrap.h"
 #include "BuildGeoShapes_SimplePolygonBrep.h"
+#include "BuildGeoShapes_GenericTrap.h"
 #include "BuildGeoShapes_UnidentifiedShape.h"
 
 #include "GeoModelRead/ReadGeoModel.h"
@@ -77,6 +78,7 @@
 #include "GeoModelKernel/GeoShapeSubtraction.h"
 #include "GeoModelKernel/GeoShapeUnion.h"
 #include "GeoModelKernel/GeoSimplePolygonBrep.h"
+#include "GeoModelKernel/GeoGenericTrap.h"
 #include "GeoModelKernel/GeoTessellatedSolid.h"
 #include "GeoModelKernel/GeoTorus.h"
 #include "GeoModelKernel/GeoTrap.h"
@@ -238,6 +240,7 @@ ReadGeoModel::~ReadGeoModel() {
     delete m_builderShape_Torus;
     delete m_builderShape_TwistedTrap;
     delete m_builderShape_SimplePolygonBrep;
+    delete m_builderShape_GenericTrap;
     delete m_builderShape_UnidentifiedShape;
     m_builderShape_Box = nullptr;
     m_builderShape_Tube = nullptr;
@@ -250,6 +253,7 @@ ReadGeoModel::~ReadGeoModel() {
     m_builderShape_Torus = nullptr;
     m_builderShape_TwistedTrap = nullptr;
     m_builderShape_SimplePolygonBrep = nullptr;
+    m_builderShape_GenericTrap = nullptr;
     m_builderShape_UnidentifiedShape = nullptr;
 }
 
@@ -316,16 +320,19 @@ void ReadGeoModel::loadDB() {
     m_shapes_Tubs = m_dbManager->getTableFromNodeType_VecVecData("GeoTubs");
     m_shapes_Torus = m_dbManager->getTableFromNodeType_VecVecData("GeoTorus");
     m_shapes_TwistedTrap = m_dbManager->getTableFromNodeType_VecVecData("GeoTwistedTrap");
+    m_shapes_UnidentifiedShape = m_dbManager->getTableFromNodeType_VecVecData("GeoUnidentifiedShape");
     
+    // shapes with variable build parameters stored in a separate table
     m_shapes_Pcon = m_dbManager->getTableFromNodeType_VecVecData("GeoPcon");
     m_shapes_Pgon = m_dbManager->getTableFromNodeType_VecVecData("GeoPgon");
     m_shapes_SimplePolygonBrep = m_dbManager->getTableFromNodeType_VecVecData("GeoSimplePolygonBrep");
-    m_shapes_UnidentifiedShape = m_dbManager->getTableFromNodeType_VecVecData("GeoUnidentifiedShape");
+    m_shapes_GenericTrap = m_dbManager->getTableFromNodeType_VecVecData("GeoGenericTrap");
 
     // shapes' data, when needed by shapes that have variable numbers of build parameters
     m_shapes_Pcon_data = m_dbManager->getTableFromTableName_VecVecData("Shapes_Pcon_Data");
     m_shapes_Pgon_data = m_dbManager->getTableFromTableName_VecVecData("Shapes_Pgon_Data");
     m_shapes_SimplePolygonBrep_data = m_dbManager->getTableFromTableName_VecVecData("Shapes_SimplePolygonBrep_Data");
+    m_shapes_GenericTrap_data = m_dbManager->getTableFromTableName_VecVecData("Shapes_GenericTrap_Data");
 
     // shape operators & boolean shapes
     m_shapes_Shift = m_dbManager->getTableFromNodeType_VecVecData("GeoShapeShift");
@@ -392,6 +399,7 @@ GeoVPhysVol* ReadGeoModel::buildGeoModelPrivate() {
         std::thread t25(&ReadGeoModel::buildAllShapes_SimplePolygonBrep, this);
         std::thread t26(&ReadGeoModel::buildAllShapes_UnidentifiedShape, this);
         std::thread t27(&ReadGeoModel::buildAllShapes_Torus, this);
+        std::thread t28(&ReadGeoModel::buildAllShapes_GenericTrap, this);
         
 
         t2.join();  // ok, all Elements have been built
@@ -412,6 +420,7 @@ GeoVPhysVol* ReadGeoModel::buildGeoModelPrivate() {
         t25.join();  // ok, all Shapes-SimplePolygonBrep have been built
         t26.join();  // ok, all Shapes-UnidentifiedShape have been built
         t27.join();  // ok, all Shapes-Torus have been built
+        t28.join();  // ok, all Shapes-GenericTrap have been built
 
 	    // Build boolean shapes and shape operators,
         // this needs Shapes to be built
@@ -457,6 +466,7 @@ GeoVPhysVol* ReadGeoModel::buildGeoModelPrivate() {
         buildAllShapes_Pcon();
         buildAllShapes_Pgon();
         buildAllShapes_SimplePolygonBrep();
+        buildAllShapes_GenericTrap();
         buildAllShapes_UnidentifiedShape();
         buildAllShapes_Cons();
         buildAllShapes_Para();
@@ -866,6 +876,25 @@ void ReadGeoModel::buildAllShapes_SimplePolygonBrep()
     }
 }
 
+//! Iterate over the list of GeoGenericTrap shape nodes, build them all, 
+//! and store their pointers
+void ReadGeoModel::buildAllShapes_GenericTrap()
+{
+    // create a builder and reserve size of memory map
+    size_t nSize = m_shapes_GenericTrap.size();
+    m_builderShape_GenericTrap = new BuildGeoShapes_GenericTrap(nSize, m_shapes_GenericTrap_data);
+    // loop over the DB rows and build the shapes
+    for (const auto &row : m_shapes_GenericTrap)
+    {
+        // GeoModelIO::CppHelper::printStdVectorVariants(row); // DEBUG MSG
+        m_builderShape_GenericTrap->buildShape(row);
+    }
+    // m_builderShape_GenericTrap->printBuiltShapes(); // DEBUG MSG
+    if (nSize > 0) {
+        std::cout << "All " << nSize << " Shapes-GenericTrap have been built!\n";
+    }
+}
+
 //! Iterate over the list of GeoTube shape nodes, build them all, 
 //! and store their pointers
 void ReadGeoModel::buildAllShapes_UnidentifiedShape()
@@ -3870,7 +3899,7 @@ return (!(m_memMapShapes_Union.find(id) == m_memMapShapes_Union.end()));
 }
 // --- methods for caching GeoShape nodes ---
 bool ReadGeoModel::isBuiltShape(std::string_view shapeType, const unsigned shapeId) {
-const std::set<std::string> shapesNewDB{"Box", "Tube", "Pcon", "Cons", "Para", "Pgon", "Trap", "Trd", "Tubs", "Torus", "TwistedTrap", "SimplePolygonBrep", "Shift", "Subtraction", "Intersection", "Union"};
+const std::set<std::string> shapesNewDB{"Box", "Tube", "Pcon", "Cons", "Para", "Pgon", "Trap", "Trd", "Tubs", "Torus", "TwistedTrap", "SimplePolygonBrep", "GenericTrap", "Shift", "Subtraction", "Intersection", "Union"};
     // get shape parameters
     if (std::count(shapesNewDB.begin(), shapesNewDB.end(), shapeType))
     {
@@ -3922,6 +3951,10 @@ const std::set<std::string> shapesNewDB{"Box", "Tube", "Pcon", "Cons", "Para", "
         {
             return m_builderShape_SimplePolygonBrep->isBuiltShape(shapeId);
         } 
+        else if ("GenericTrap" == shapeType)
+        {
+            return m_builderShape_GenericTrap->isBuiltShape(shapeId);
+        } 
         else if ("Shift" == shapeType)
         {
             return isBuiltShape_Operators_Shift(shapeId);
@@ -3977,7 +4010,7 @@ void ReadGeoModel::storeBuiltShapeOperators_Union(const unsigned id, GeoShape* n
 GeoShape *ReadGeoModel::getBuiltShape(const unsigned shapeId, std::string_view shapeType)
 {
 
-    const std::set<std::string> shapesNewDB{"Box", "Tube", "Pcon", "Cons", "Para", "Pgon", "Trap", "Trd", "Tubs", "Torus", "TwistedTrap", "SimplePolygonBrep", "Shift", "Intersection", "Subtraction", "Union", "UnidentifiedShape"};
+    const std::set<std::string> shapesNewDB{"Box", "Tube", "Pcon", "Cons", "Para", "Pgon", "Trap", "Trd", "Tubs", "Torus", "TwistedTrap", "SimplePolygonBrep", "GenericTrap", "Shift", "Intersection", "Subtraction", "Union", "UnidentifiedShape"};
     // get shape parameters
     if (std::count(shapesNewDB.begin(), shapesNewDB.end(), shapeType))
     {
@@ -4029,6 +4062,10 @@ GeoShape *ReadGeoModel::getBuiltShape(const unsigned shapeId, std::string_view s
         {
             return m_builderShape_SimplePolygonBrep->getBuiltShape(shapeId);
         } 
+        else if ("GenericTrap" == shapeType)
+        {
+            return m_builderShape_GenericTrap->getBuiltShape(shapeId);
+        } 
         else if ("UnidentifiedShape" == shapeType)
         {
             return m_builderShape_UnidentifiedShape->getBuiltShape(shapeId);
-- 
GitLab