]> SALOME platform Git repositories - tools/medcoupling.git/commitdiff
Salome HOME
Add ShapeRecognMeshBuilder to build ShapeRecognMesh
authorEl Hadi Moussi <moussi@phimeca.com>
Tue, 13 Aug 2024 08:48:47 +0000 (10:48 +0200)
committerEl Hadi Moussi <moussi@phimeca.com>
Tue, 13 Aug 2024 08:48:47 +0000 (10:48 +0200)
18 files changed:
src/ShapeRecogn/CMakeLists.txt
src/ShapeRecogn/NodesBuilder.cxx
src/ShapeRecogn/NodesBuilder.hxx
src/ShapeRecogn/ShapeRecognMesh.cxx
src/ShapeRecogn/ShapeRecognMesh.hxx
src/ShapeRecogn/ShapeRecognMeshBuilder.cxx [new file with mode: 0644]
src/ShapeRecogn/ShapeRecognMeshBuilder.hxx [new file with mode: 0644]
src/ShapeRecogn/Swig/ShapeRecogn.i
src/ShapeRecogn/Test/ConeTest.cxx
src/ShapeRecogn/Test/ConeTest.hxx
src/ShapeRecogn/Test/CylinderTest.cxx
src/ShapeRecogn/Test/CylinderTest.hxx
src/ShapeRecogn/Test/PlaneTest.cxx
src/ShapeRecogn/Test/PlaneTest.hxx
src/ShapeRecogn/Test/SphereTest.cxx
src/ShapeRecogn/Test/SphereTest.hxx
src/ShapeRecogn/Test/TorusTest.cxx
src/ShapeRecogn/Test/TorusTest.hxx

index 9c4b506d8624639d274d23c528b530412c81f109..1f63ae163bc1e79642f274c13cdd9f689afa69ea 100644 (file)
@@ -47,6 +47,7 @@ SET(shaperecogn_SOURCES
   NodesBuilder.cxx
   Areas.cxx
   AreasBuilder.cxx
+  ShapeRecognMeshBuilder.cxx
   ShapeRecognMesh.cxx
 )
 
index d8752f8f070843374b7fed6079c129038c03ba98..1302d32033d5da0440d13181facb93d103248077 100644 (file)
@@ -172,6 +172,31 @@ PrimitiveType NodesBuilder::findPrimitiveType(double k1, double k2, double kdiff
         return PrimitiveType::Unknown;
 }
 
+PrimitiveType NodesBuilder::findPrimitiveType2(double k1, double k2, double kdiff0, double kis0) const
+{
+    double epsilon2 = pow(EPSILON_PRIMITIVE, 2);
+    double diffCurvature = fabs(k1 - k2);
+    double gaussianCurvature = k1 * k2;
+    double meanCurvature = (k1 + k2) / 2.0;
+    if (fabs(k1) < EPSILON_PRIMITIVE &&
+        fabs(k2) < EPSILON_PRIMITIVE &&
+        gaussianCurvature < epsilon2 &&
+        meanCurvature < EPSILON_PRIMITIVE)
+        return PrimitiveType::Plane;
+    else if (diffCurvature < EPSILON_PRIMITIVE && k1 > EPSILON_PRIMITIVE && k2 > EPSILON_PRIMITIVE)
+        return PrimitiveType::Sphere;
+    else if (
+        (fabs(k1) > EPSILON_PRIMITIVE && fabs(k2) < EPSILON_PRIMITIVE) ||
+        (fabs(k1) < EPSILON_PRIMITIVE && fabs(k2) > EPSILON_PRIMITIVE))
+        return PrimitiveType::Cylinder;
+    else if (
+        std::signbit(k1) != std::signbit(k2) ||
+        (fabs(k1) < EPSILON_PRIMITIVE && fabs(k2) < EPSILON_PRIMITIVE))
+        return PrimitiveType::Torus;
+    else
+        return PrimitiveType::Unknown;
+}
+
 std::vector<double> NodesBuilder::computeNormalCurvatureCoefficients(
     const std::vector<double> &discreteCurvatures,
     const std::vector<double> &tangents,
index bfe1376859675cfbd06182522807ad76d0cbc1b9..19011806435a257859011bccecd0d320a6466fd3 100644 (file)
@@ -42,6 +42,7 @@ namespace MEDCoupling
         void computeCurvatures(double tol = 0.000001);
         void computeCurvatures(mcIdType nodeId, double tol);
         PrimitiveType findPrimitiveType(double k1, double k2, double kdiff0, double kis0) const;
+        PrimitiveType findPrimitiveType2(double k1, double k2, double kdiff0, double kis0) const;
         std::vector<double> computeNormalCurvatureCoefficients(
             const std::vector<double> &discreteCurvatures,
             const std::vector<double> &tangents,
index 3da7a0d11faa1588dbd4f5ab2e5ed2181ec3a090..4c8ee5f9f894e79d1fefc515db64fb3885d7234d 100644 (file)
 #include "ShapeRecognMesh.hxx"
 
-#include "NodesBuilder.hxx"
-#include "AreasBuilder.hxx"
 #include "MEDLoader.hxx"
-#include "MEDCouplingFieldDouble.hxx"
 
 using namespace MEDCoupling;
 
-ShapeRecognMesh::ShapeRecognMesh(const std::string &fileName, int meshDimRelToMax)
+ShapeRecognMesh::ShapeRecognMesh()
+    : nodeK1(0), nodeK2(0), nodePrimitiveType(0),
+      nodeNormal(0), areaId(0), areaPrimitiveType(0),
+      areaNormal(0), minorRadius(0), radius(0),
+      angle(0), center(0), axis(0), apex(0)
 {
-    mesh = ReadUMeshFromFile(fileName, meshDimRelToMax);
-    if (mesh->getMeshDimension() != 2)
-        throw INTERP_KERNEL::Exception("Expect a mesh with a dimension equal to 2");
-    if (mesh->getNumberOfCellsWithType(INTERP_KERNEL::NORM_TRI3) != mesh->getNumberOfCells())
-        throw INTERP_KERNEL::Exception("Expect a mesh containing exclusively triangular cells");
 }
-
 ShapeRecognMesh::~ShapeRecognMesh()
 {
-    if (areas != nullptr)
-        delete areas;
-    if (nodes != nullptr)
-        delete nodes;
-    mesh->decrRef();
+    nodeK1->decrRef();
+    nodeK2->decrRef();
+    nodePrimitiveType->decrRef();
+    nodeNormal->decrRef();
+    areaId->decrRef();
+    areaPrimitiveType->decrRef();
+    areaNormal->decrRef();
+    minorRadius->decrRef();
+    radius->decrRef();
+    angle->decrRef();
+    center->decrRef();
+    axis->decrRef();
+    apex->decrRef();
+}
+
+std::size_t ShapeRecognMesh::getHeapMemorySizeWithoutChildren() const
+{
+    return 0;
+}
+
+std::vector<const BigMemoryObject *> ShapeRecognMesh::getDirectChildrenWithNull() const
+{
+    std::vector<const BigMemoryObject *> ret;
+    ret.push_back(nodeK1);
+    ret.push_back(nodeK2);
+    ret.push_back(nodePrimitiveType);
+    ret.push_back(nodeNormal);
+    ret.push_back(areaId);
+    ret.push_back(areaPrimitiveType);
+    ret.push_back(areaNormal);
+    ret.push_back(minorRadius);
+    ret.push_back(radius);
+    ret.push_back(angle);
+    ret.push_back(center);
+    ret.push_back(axis);
+    ret.push_back(apex);
+    return ret;
 }
 
-void ShapeRecognMesh::recognize()
+ShapeRecognMesh *ShapeRecognMesh::New()
 {
-    mesh->incrRef();
-    NodesBuilder nodesBuilder(mesh);
-    nodes = nodesBuilder.build();
-    AreasBuilder areasBuilder(nodes);
-    areasBuilder.build();
-    areas = areasBuilder.getAreas();
+    return new ShapeRecognMesh;
 }
 
-void ShapeRecognMesh::recognize(const std::string &outputFile, bool writeFromScratch)
+void ShapeRecognMesh::save(const std::string &outputFile, bool writeFromScratch) const
 {
-    recognize();
     // Nodes
     // - k1
-    MEDCouplingFieldDouble *fieldNodeK1 = buildNodeK1();
-    WriteField(outputFile, fieldNodeK1, writeFromScratch);
-    fieldNodeK1->decrRef();
+    WriteField(outputFile, nodeK1, writeFromScratch);
     // - k2
-    MEDCouplingFieldDouble *fieldNodeK2 = buildNodeK2();
-    WriteField(outputFile, fieldNodeK2, false);
-    fieldNodeK2->decrRef();
+    WriteField(outputFile, nodeK2, false);
     // - primitive types
-    MEDCouplingFieldDouble *fieldNodePrimitiveType = buildNodePrimitiveType();
-    WriteField(outputFile, fieldNodePrimitiveType, false);
-    fieldNodePrimitiveType->decrRef();
+    WriteField(outputFile, nodePrimitiveType, false);
     // - Normal
-    MEDCouplingFieldDouble *fieldNodeNormal = buildNodeNormal();
-    WriteField(outputFile, fieldNodeNormal, false);
-    fieldNodeNormal->decrRef();
+    WriteField(outputFile, nodeNormal, false);
     // Areas
     // - Area Id
-    MEDCouplingFieldDouble *fieldAreaId = buildAreaId();
-    WriteField(outputFile, fieldAreaId, false);
-    fieldAreaId->decrRef();
+    WriteField(outputFile, areaId, false);
     // - Primitive Types
-    MEDCouplingFieldDouble *fieldAreaPrimitiveType = buildAreaPrimitiveType();
-    WriteField(outputFile, fieldAreaPrimitiveType, false);
-    fieldAreaPrimitiveType->decrRef();
+    WriteField(outputFile, areaPrimitiveType, false);
     // - Normal
-    auto fieldAreaNormal = buildAreaNormal();
-    WriteField(outputFile, fieldAreaNormal, false);
-    fieldAreaNormal->decrRef();
+    WriteField(outputFile, areaNormal, false);
     // - Minor Radius
-    MEDCouplingFieldDouble *fieldAreaMinorRadius = buildMinorRadius();
-    WriteField(outputFile, fieldAreaMinorRadius, false);
-    fieldAreaMinorRadius->decrRef();
+    WriteField(outputFile, minorRadius, false);
     // - Radius
-    MEDCouplingFieldDouble *fieldAreaRadius = buildRadius();
-    WriteField(outputFile, fieldAreaRadius, false);
-    fieldAreaRadius->decrRef();
+    WriteField(outputFile, radius, false);
     // - Angle
-    MEDCouplingFieldDouble *fieldAreaAngle = buildAngle();
-    WriteField(outputFile, fieldAreaAngle, false);
-    fieldAreaAngle->decrRef();
+    WriteField(outputFile, angle, false);
     // - Center
-    MEDCouplingFieldDouble *fieldAreaCenter = buildCenter();
-    WriteField(outputFile, fieldAreaCenter, false);
-    fieldAreaCenter->decrRef();
+    WriteField(outputFile, center, false);
     // - Axis
-    MEDCouplingFieldDouble *fieldAreaAxis = buildAxis();
-    WriteField(outputFile, fieldAreaAxis, false);
-    fieldAreaAxis->decrRef();
+    WriteField(outputFile, axis, false);
     // - Apex
-    MEDCouplingFieldDouble *fieldAreaApex = buildApex();
-    WriteField(outputFile, fieldAreaApex, false);
-    fieldAreaApex->decrRef();
-}
-
-const Nodes *ShapeRecognMesh::getNodes() const
-{
-    return nodes;
-}
-
-const Areas *ShapeRecognMesh::getAreas() const
-{
-    return areas;
-}
-
-MEDCouplingFieldDouble *ShapeRecognMesh::buildNodeK1() const
-{
-    if (nodes == nullptr)
-        throw INTERP_KERNEL::Exception("recognize must be called before building any fields");
-    return buildField("K1 (Node)", 1, nodes->getK1());
-}
-
-MEDCouplingFieldDouble *ShapeRecognMesh::buildNodeK2() const
-{
-    if (nodes == nullptr)
-        throw INTERP_KERNEL::Exception("recognize must be called before building any fields");
-    return buildField("K2 (Node)", 1, nodes->getK2());
-}
-
-MEDCouplingFieldDouble *ShapeRecognMesh::buildNodePrimitiveType() const
-{
-    if (nodes == nullptr)
-        throw INTERP_KERNEL::Exception("recognize must be called before building any fields");
-    return buildField("Primitive Type (Node)", 1, nodes->getPrimitiveType());
-}
-
-MEDCouplingFieldDouble *ShapeRecognMesh::buildNodeNormal() const
-{
-    if (nodes == nullptr)
-        throw INTERP_KERNEL::Exception("recognize must be called before building any fields");
-    return buildField("Normal (Node)", 3, nodes->getNormals());
-}
-
-MEDCouplingFieldDouble *ShapeRecognMesh::buildAreaId() const
-{
-    if (areas == nullptr)
-        throw INTERP_KERNEL::Exception("recognize must be called before building any fields");
-    return buildField("Area Id", 1, areas->getAreaIdByNodes());
+    WriteField(outputFile, apex, false);
 }
 
-MEDCouplingFieldDouble *ShapeRecognMesh::buildAreaPrimitiveType() const
+MEDCouplingFieldDouble *ShapeRecognMesh::getNodeK1() const
 {
-    if (areas == nullptr)
-        throw INTERP_KERNEL::Exception("recognize must be called before building any fields");
-    double *values = buildAreaArray([](Areas *areas, mcIdType areaId) -> double
-                                    { return (double)areas->getPrimitiveType(areaId); });
-    return buildField("Primitive Type (Area)", 1, values);
+    return nodeK1;
 }
 
-MEDCouplingFieldDouble *ShapeRecognMesh::buildAreaNormal() const
+MEDCouplingFieldDouble *ShapeRecognMesh::getNodeK2() const
 {
-    if (areas == nullptr)
-        throw INTERP_KERNEL::Exception("recognize must be called before building any fields");
-    double *values = buildArea3DArray([](Areas *areas, mcIdType areaId) -> const std::array<double, 3> &
-                                      { return areas->getNormal(areaId); });
-    return buildField("Normal (Area)", 3, values);
+    return nodeK2;
 }
 
-MEDCouplingFieldDouble *ShapeRecognMesh::buildMinorRadius() const
+MEDCouplingFieldDouble *ShapeRecognMesh::getNodePrimitiveType() const
 {
-    if (areas == nullptr)
-        throw INTERP_KERNEL::Exception("recognize must be called before building any fields");
-    double *values = buildAreaArray([](Areas *areas, mcIdType areaId) -> double
-                                    { return areas->getMinorRadius(areaId); });
-    return buildField("Minor Radius (Area)", 1, values);
+    return nodePrimitiveType;
 }
 
-MEDCouplingFieldDouble *ShapeRecognMesh::buildRadius() const
+MEDCouplingFieldDouble *ShapeRecognMesh::getNodeNormal() const
 {
-    if (areas == nullptr)
-        throw INTERP_KERNEL::Exception("recognize must be called before building any fields");
-    double *values = buildAreaArray([](Areas *areas, mcIdType areaId) -> double
-                                    { return areas->getRadius(areaId); });
-    return buildField("Radius (Area)", 1, values);
+    return nodeNormal;
 }
 
-MEDCouplingFieldDouble *ShapeRecognMesh::buildAngle() const
+MEDCouplingFieldDouble *ShapeRecognMesh::getAreaId() const
 {
-    if (areas == nullptr)
-        throw INTERP_KERNEL::Exception("recognize must be called before building any fields");
-    double *values = buildAreaArray([](Areas *areas, mcIdType areaId) -> double
-                                    { return areas->getAngle(areaId); });
-    return buildField("Angle (Area)", 1, values);
+    return areaId;
 }
 
-MEDCouplingFieldDouble *ShapeRecognMesh::buildCenter() const
+MEDCouplingFieldDouble *ShapeRecognMesh::getAreaPrimitiveType() const
 {
-    if (areas == nullptr)
-        throw INTERP_KERNEL::Exception("recognize must be called before building any fields");
-    double *values = buildArea3DArray([](Areas *areas, mcIdType areaId) -> const std::array<double, 3> &
-                                      { return areas->getCenter(areaId); });
-    return buildField("Center (Area)", 3, values);
+    return areaPrimitiveType;
 }
 
-MEDCouplingFieldDouble *ShapeRecognMesh::buildAxis() const
+MEDCouplingFieldDouble *ShapeRecognMesh::getAreaNormal() const
 {
-    if (areas == nullptr)
-        throw INTERP_KERNEL::Exception("recognize must be called before building any fields");
-    double *values = buildArea3DArray([](Areas *areas, mcIdType areaId) -> const std::array<double, 3> &
-                                      { return areas->getAxis(areaId); });
-    return buildField("Axis (Area)", 3, values);
+    return areaNormal;
 }
 
-MEDCouplingFieldDouble *ShapeRecognMesh::buildApex() const
+MEDCouplingFieldDouble *ShapeRecognMesh::getMinorRadius() const
 {
-    if (areas == nullptr)
-        throw INTERP_KERNEL::Exception("recognize must be called before building any fields");
-    double *values = buildArea3DArray([](Areas *areas, mcIdType areaId) -> const std::array<double, 3> &
-                                      { return areas->getApex(areaId); });
-    return buildField("Apex (Area)", 3, values);
+    return minorRadius;
 }
 
-template <typename T>
-MEDCouplingFieldDouble *ShapeRecognMesh::buildField(
-    const std::string &name,
-    size_t nbOfCompo,
-    const std::vector<T> &values) const
+MEDCouplingFieldDouble *ShapeRecognMesh::getRadius() const
 {
-    DataArrayDouble *data = DataArrayDouble::New();
-    data->setName(name);
-    data->alloc(nodes->getNbNodes(), nbOfCompo);
-    std::copy(values.begin(), values.end(), data->getPointer());
-    data->declareAsNew();
-    return buildField(name, nbOfCompo, data);
+    return radius;
 }
 
-MEDCouplingFieldDouble *ShapeRecognMesh::buildField(
-    const std::string &name,
-    size_t nbOfCompo,
-    double *values) const
+MEDCouplingFieldDouble *ShapeRecognMesh::getAngle() const
 {
-    DataArrayDouble *data = DataArrayDouble::New();
-    data->setName(name);
-    data->useArray(
-        values,
-        true,
-        MEDCoupling::DeallocType::CPP_DEALLOC,
-        nodes->getNbNodes(),
-        nbOfCompo);
-    return buildField(name, nbOfCompo, data);
+    return angle;
 }
 
-MEDCouplingFieldDouble *ShapeRecognMesh::buildField(
-    const std::string &name,
-    size_t nbOfCompo,
-    DataArrayDouble *data) const
+MEDCouplingFieldDouble *ShapeRecognMesh::getCenter() const
 {
-    MEDCouplingFieldDouble *field = MEDCouplingFieldDouble::New(ON_NODES);
-    field->setName(name);
-    field->setMesh(mesh);
-    if (nbOfCompo == 3)
-    {
-        data->setInfoOnComponent(0, "X");
-        data->setInfoOnComponent(1, "Y");
-        data->setInfoOnComponent(2, "Z");
-    }
-    field->setArray(data);
-    data->decrRef();
-    return field;
+    return center;
 }
 
-double *ShapeRecognMesh::buildArea3DArray(
-    const std::array<double, 3> &(*areaFunc)(Areas *, mcIdType)) const
+MEDCouplingFieldDouble *ShapeRecognMesh::getAxis() const
 {
-    double *values = new double[3 * nodes->getNbNodes()];
-    const std::vector<mcIdType> &areaIdByNodes = areas->getAreaIdByNodes();
-    for (size_t nodeId = 0; nodeId < areaIdByNodes.size(); ++nodeId)
-    {
-        mcIdType areaId = areaIdByNodes[nodeId];
-        if (areaId != -1)
-        {
-            const std::array<double, 3> &areaValues = areaFunc(areas, areaId);
-            values[3 * nodeId] = areaValues[0];
-            values[3 * nodeId + 1] = areaValues[1];
-            values[3 * nodeId + 2] = areaValues[2];
-        }
-    }
-    return values;
+    return axis;
 }
 
-double *ShapeRecognMesh::buildAreaArray(double (*areaFunc)(Areas *, mcIdType)) const
+MEDCouplingFieldDouble *ShapeRecognMesh::getApex() const
 {
-    const std::vector<mcIdType> &areaIdByNodes = areas->getAreaIdByNodes();
-    double *values = new double[nodes->getNbNodes()];
-    for (size_t nodeId = 0; nodeId < areaIdByNodes.size(); ++nodeId)
-    {
-        mcIdType areaId = areaIdByNodes[nodeId];
-        if (areaId != -1)
-            values[nodeId] = areaFunc(areas, areaId);
-    }
-    return values;
+    return apex;
 }
index 6defd49a4370366acd255296fb92448f5bc426fd..02983e34a888841217348eeca75b1874dc83cec8 100644 (file)
 
 #include "MEDCouplingUMesh.hxx"
 #include "MEDCouplingFieldDouble.hxx"
+#include "MEDCouplingRefCountObject.hxx"
 
 namespace MEDCoupling
 {
-    class Nodes;
-    class Areas;
-
-    class ShapeRecognMesh
+    class ShapeRecognMesh : public RefCountObject
     {
-    public:
-        ShapeRecognMesh(const std::string &fileName, int meshDimRelToMax = 0);
-        ~ShapeRecognMesh();
+        friend class ShapeRecognMeshBuilder;
 
-        const Nodes *getNodes() const;
-        const Areas *getAreas() const;
+    public:
+        static ShapeRecognMesh *New();
+        std::size_t getHeapMemorySizeWithoutChildren() const;
+        std::vector<const BigMemoryObject *> getDirectChildrenWithNull() const;
 
-        void recognize();
-        void recognize(const std::string &outputFile, bool writeFromScratch = true);
+        void save(const std::string &outputFile, bool writeFromScratch = true) const;
 
         // Node properties
-        MEDCoupling::MEDCouplingFieldDouble *buildNodeK1() const;
-        MEDCoupling::MEDCouplingFieldDouble *buildNodeK2() const;
-        MEDCoupling::MEDCouplingFieldDouble *buildNodePrimitiveType() const;
-        MEDCoupling::MEDCouplingFieldDouble *buildNodeNormal() const;
+        MEDCoupling::MEDCouplingFieldDouble *getNodeK1() const;
+        MEDCoupling::MEDCouplingFieldDouble *getNodeK2() const;
+        MEDCoupling::MEDCouplingFieldDouble *getNodePrimitiveType() const;
+        MEDCoupling::MEDCouplingFieldDouble *getNodeNormal() const;
 
         // Area properties
-        MEDCoupling::MEDCouplingFieldDouble *buildAreaId() const;
-        MEDCoupling::MEDCouplingFieldDouble *buildAreaPrimitiveType() const;
-        MEDCoupling::MEDCouplingFieldDouble *buildAreaNormal() const;
-        MEDCoupling::MEDCouplingFieldDouble *buildMinorRadius() const;
-        MEDCoupling::MEDCouplingFieldDouble *buildRadius() const;
-        MEDCoupling::MEDCouplingFieldDouble *buildAngle() const;
-        MEDCoupling::MEDCouplingFieldDouble *buildCenter() const;
-        MEDCoupling::MEDCouplingFieldDouble *buildAxis() const;
-        MEDCoupling::MEDCouplingFieldDouble *buildApex() const;
+        MEDCoupling::MEDCouplingFieldDouble *getAreaId() const;
+        MEDCoupling::MEDCouplingFieldDouble *getAreaPrimitiveType() const;
+        MEDCoupling::MEDCouplingFieldDouble *getAreaNormal() const;
+        MEDCoupling::MEDCouplingFieldDouble *getMinorRadius() const;
+        MEDCoupling::MEDCouplingFieldDouble *getRadius() const;
+        MEDCoupling::MEDCouplingFieldDouble *getAngle() const;
+        MEDCoupling::MEDCouplingFieldDouble *getCenter() const;
+        MEDCoupling::MEDCouplingFieldDouble *getAxis() const;
+        MEDCoupling::MEDCouplingFieldDouble *getApex() const;
 
-    private:
-        template <typename T>
-        MEDCouplingFieldDouble *buildField(
-            const std::string &name,
-            size_t nbOfCompo,
-            const std::vector<T> &values) const;
-        MEDCouplingFieldDouble *buildField(
-            const std::string &name,
-            size_t nbOfCompo,
-            double *values) const;
-        MEDCouplingFieldDouble *buildField(
-            const std::string &name,
-            size_t nbOfCompo,
-            DataArrayDouble *values) const;
-        double *buildArea3DArray(const std::array<double, 3> &(*areaFunc)(Areas *, mcIdType)) const;
-        double *buildAreaArray(double (*areaFunc)(Areas *, mcIdType)) const;
+    protected:
+        ShapeRecognMesh();
+        ~ShapeRecognMesh();
 
-        const MEDCouplingUMesh *mesh;
-        Nodes *nodes = nullptr;
-        Areas *areas = nullptr;
+    private:
+        MEDCoupling::MEDCouplingFieldDouble *nodeK1;
+        MEDCoupling::MEDCouplingFieldDouble *nodeK2;
+        MEDCoupling::MEDCouplingFieldDouble *nodePrimitiveType;
+        MEDCoupling::MEDCouplingFieldDouble *nodeNormal;
+        MEDCoupling::MEDCouplingFieldDouble *areaId;
+        MEDCoupling::MEDCouplingFieldDouble *areaPrimitiveType;
+        MEDCoupling::MEDCouplingFieldDouble *areaNormal;
+        MEDCoupling::MEDCouplingFieldDouble *minorRadius;
+        MEDCoupling::MEDCouplingFieldDouble *radius;
+        MEDCoupling::MEDCouplingFieldDouble *angle;
+        MEDCoupling::MEDCouplingFieldDouble *center;
+        MEDCoupling::MEDCouplingFieldDouble *axis;
+        MEDCoupling::MEDCouplingFieldDouble *apex;
     };
 };
 
diff --git a/src/ShapeRecogn/ShapeRecognMeshBuilder.cxx b/src/ShapeRecogn/ShapeRecognMeshBuilder.cxx
new file mode 100644 (file)
index 0000000..f0a2b05
--- /dev/null
@@ -0,0 +1,250 @@
+#include "ShapeRecognMeshBuilder.hxx"
+
+#include "NodesBuilder.hxx"
+#include "AreasBuilder.hxx"
+#include "MEDLoader.hxx"
+#include "ShapeRecognMesh.hxx"
+#include "MEDCouplingFieldDouble.hxx"
+
+using namespace MEDCoupling;
+
+ShapeRecognMeshBuilder::ShapeRecognMeshBuilder(const std::string &fileName, int meshDimRelToMax)
+{
+    mesh = ReadUMeshFromFile(fileName, meshDimRelToMax);
+    if (mesh->getMeshDimension() != 2)
+        throw INTERP_KERNEL::Exception("Expect a mesh with a dimension equal to 2");
+    if (mesh->getNumberOfCellsWithType(INTERP_KERNEL::NORM_TRI3) != mesh->getNumberOfCells())
+        throw INTERP_KERNEL::Exception("Expect a mesh containing exclusively triangular cells");
+}
+
+ShapeRecognMeshBuilder::~ShapeRecognMeshBuilder()
+{
+    if (areas != nullptr)
+        delete areas;
+    if (nodes != nullptr)
+        delete nodes;
+    mesh->decrRef();
+}
+
+ShapeRecognMesh *ShapeRecognMeshBuilder::recognize()
+{
+    mesh->incrRef();
+    NodesBuilder nodesBuilder(mesh);
+    nodes = nodesBuilder.build();
+    AreasBuilder areasBuilder(nodes);
+    areasBuilder.build();
+    areas = areasBuilder.getAreas();
+    MCAuto<ShapeRecognMesh> recognMesh = ShapeRecognMesh::New();
+    recognMesh->nodeK1 = buildNodeK1();
+    recognMesh->nodeK2 = buildNodeK2();
+    recognMesh->nodePrimitiveType = buildNodePrimitiveType();
+    recognMesh->nodeNormal = buildNodeNormal();
+    recognMesh->areaId = buildAreaId();
+    recognMesh->areaPrimitiveType = buildAreaPrimitiveType();
+    recognMesh->areaNormal = buildAreaNormal();
+    recognMesh->minorRadius = buildMinorRadius();
+    recognMesh->radius = buildRadius();
+    recognMesh->angle = buildAngle();
+    recognMesh->center = buildCenter();
+    recognMesh->axis = buildAxis();
+    recognMesh->apex = buildApex();
+    return recognMesh.retn();
+}
+
+const Nodes *ShapeRecognMeshBuilder::getNodes() const
+{
+    return nodes;
+}
+
+const Areas *ShapeRecognMeshBuilder::getAreas() const
+{
+    return areas;
+}
+
+MEDCouplingFieldDouble *ShapeRecognMeshBuilder::buildNodeK1() const
+{
+    if (nodes == nullptr)
+        throw INTERP_KERNEL::Exception("recognize must be called before building any fields");
+    return buildField("K1 (Node)", 1, nodes->getK1());
+}
+
+MEDCouplingFieldDouble *ShapeRecognMeshBuilder::buildNodeK2() const
+{
+    if (nodes == nullptr)
+        throw INTERP_KERNEL::Exception("recognize must be called before building any fields");
+    return buildField("K2 (Node)", 1, nodes->getK2());
+}
+
+MEDCouplingFieldDouble *ShapeRecognMeshBuilder::buildNodePrimitiveType() const
+{
+    if (nodes == nullptr)
+        throw INTERP_KERNEL::Exception("recognize must be called before building any fields");
+    return buildField("Primitive Type (Node)", 1, nodes->getPrimitiveType());
+}
+
+MEDCouplingFieldDouble *ShapeRecognMeshBuilder::buildNodeNormal() const
+{
+    if (nodes == nullptr)
+        throw INTERP_KERNEL::Exception("recognize must be called before building any fields");
+    return buildField("Normal (Node)", 3, nodes->getNormals());
+}
+
+MEDCouplingFieldDouble *ShapeRecognMeshBuilder::buildAreaId() const
+{
+    if (areas == nullptr)
+        throw INTERP_KERNEL::Exception("recognize must be called before building any fields");
+    return buildField("Area Id", 1, areas->getAreaIdByNodes());
+}
+
+MEDCouplingFieldDouble *ShapeRecognMeshBuilder::buildAreaPrimitiveType() const
+{
+    if (areas == nullptr)
+        throw INTERP_KERNEL::Exception("recognize must be called before building any fields");
+    double *values = buildAreaArray([](Areas *areas, mcIdType areaId) -> double
+                                    { return (double)areas->getPrimitiveType(areaId); });
+    return buildField("Primitive Type (Area)", 1, values);
+}
+
+MEDCouplingFieldDouble *ShapeRecognMeshBuilder::buildAreaNormal() const
+{
+    if (areas == nullptr)
+        throw INTERP_KERNEL::Exception("recognize must be called before building any fields");
+    double *values = buildArea3DArray([](Areas *areas, mcIdType areaId) -> const std::array<double, 3> &
+                                      { return areas->getNormal(areaId); });
+    return buildField("Normal (Area)", 3, values);
+}
+
+MEDCouplingFieldDouble *ShapeRecognMeshBuilder::buildMinorRadius() const
+{
+    if (areas == nullptr)
+        throw INTERP_KERNEL::Exception("recognize must be called before building any fields");
+    double *values = buildAreaArray([](Areas *areas, mcIdType areaId) -> double
+                                    { return areas->getMinorRadius(areaId); });
+    return buildField("Minor Radius (Area)", 1, values);
+}
+
+MEDCouplingFieldDouble *ShapeRecognMeshBuilder::buildRadius() const
+{
+    if (areas == nullptr)
+        throw INTERP_KERNEL::Exception("recognize must be called before building any fields");
+    double *values = buildAreaArray([](Areas *areas, mcIdType areaId) -> double
+                                    { return areas->getRadius(areaId); });
+    return buildField("Radius (Area)", 1, values);
+}
+
+MEDCouplingFieldDouble *ShapeRecognMeshBuilder::buildAngle() const
+{
+    if (areas == nullptr)
+        throw INTERP_KERNEL::Exception("recognize must be called before building any fields");
+    double *values = buildAreaArray([](Areas *areas, mcIdType areaId) -> double
+                                    { return areas->getAngle(areaId); });
+    return buildField("Angle (Area)", 1, values);
+}
+
+MEDCouplingFieldDouble *ShapeRecognMeshBuilder::buildCenter() const
+{
+    if (areas == nullptr)
+        throw INTERP_KERNEL::Exception("recognize must be called before building any fields");
+    double *values = buildArea3DArray([](Areas *areas, mcIdType areaId) -> const std::array<double, 3> &
+                                      { return areas->getCenter(areaId); });
+    return buildField("Center (Area)", 3, values);
+}
+
+MEDCouplingFieldDouble *ShapeRecognMeshBuilder::buildAxis() const
+{
+    if (areas == nullptr)
+        throw INTERP_KERNEL::Exception("recognize must be called before building any fields");
+    double *values = buildArea3DArray([](Areas *areas, mcIdType areaId) -> const std::array<double, 3> &
+                                      { return areas->getAxis(areaId); });
+    return buildField("Axis (Area)", 3, values);
+}
+
+MEDCouplingFieldDouble *ShapeRecognMeshBuilder::buildApex() const
+{
+    if (areas == nullptr)
+        throw INTERP_KERNEL::Exception("recognize must be called before building any fields");
+    double *values = buildArea3DArray([](Areas *areas, mcIdType areaId) -> const std::array<double, 3> &
+                                      { return areas->getApex(areaId); });
+    return buildField("Apex (Area)", 3, values);
+}
+
+template <typename T>
+MEDCouplingFieldDouble *ShapeRecognMeshBuilder::buildField(
+    const std::string &name,
+    size_t nbOfCompo,
+    const std::vector<T> &values) const
+{
+    DataArrayDouble *data = DataArrayDouble::New();
+    data->setName(name);
+    data->alloc(nodes->getNbNodes(), nbOfCompo);
+    std::copy(values.begin(), values.end(), data->getPointer());
+    data->declareAsNew();
+    return buildField(name, nbOfCompo, data);
+}
+
+MEDCouplingFieldDouble *ShapeRecognMeshBuilder::buildField(
+    const std::string &name,
+    size_t nbOfCompo,
+    double *values) const
+{
+    DataArrayDouble *data = DataArrayDouble::New();
+    data->setName(name);
+    data->useArray(
+        values,
+        true,
+        MEDCoupling::DeallocType::CPP_DEALLOC,
+        nodes->getNbNodes(),
+        nbOfCompo);
+    return buildField(name, nbOfCompo, data);
+}
+
+MEDCouplingFieldDouble *ShapeRecognMeshBuilder::buildField(
+    const std::string &name,
+    size_t nbOfCompo,
+    DataArrayDouble *data) const
+{
+    MEDCouplingFieldDouble *field = MEDCouplingFieldDouble::New(ON_NODES);
+    field->setName(name);
+    field->setMesh(mesh);
+    if (nbOfCompo == 3)
+    {
+        data->setInfoOnComponent(0, "X");
+        data->setInfoOnComponent(1, "Y");
+        data->setInfoOnComponent(2, "Z");
+    }
+    field->setArray(data);
+    data->decrRef();
+    return field;
+}
+
+double *ShapeRecognMeshBuilder::buildArea3DArray(
+    const std::array<double, 3> &(*areaFunc)(Areas *, mcIdType)) const
+{
+    double *values = new double[3 * nodes->getNbNodes()];
+    const std::vector<mcIdType> &areaIdByNodes = areas->getAreaIdByNodes();
+    for (size_t nodeId = 0; nodeId < areaIdByNodes.size(); ++nodeId)
+    {
+        mcIdType areaId = areaIdByNodes[nodeId];
+        if (areaId != -1)
+        {
+            const std::array<double, 3> &areaValues = areaFunc(areas, areaId);
+            values[3 * nodeId] = areaValues[0];
+            values[3 * nodeId + 1] = areaValues[1];
+            values[3 * nodeId + 2] = areaValues[2];
+        }
+    }
+    return values;
+}
+
+double *ShapeRecognMeshBuilder::buildAreaArray(double (*areaFunc)(Areas *, mcIdType)) const
+{
+    const std::vector<mcIdType> &areaIdByNodes = areas->getAreaIdByNodes();
+    double *values = new double[nodes->getNbNodes()];
+    for (size_t nodeId = 0; nodeId < areaIdByNodes.size(); ++nodeId)
+    {
+        mcIdType areaId = areaIdByNodes[nodeId];
+        if (areaId != -1)
+            values[nodeId] = areaFunc(areas, areaId);
+    }
+    return values;
+}
diff --git a/src/ShapeRecogn/ShapeRecognMeshBuilder.hxx b/src/ShapeRecogn/ShapeRecognMeshBuilder.hxx
new file mode 100644 (file)
index 0000000..eee7c15
--- /dev/null
@@ -0,0 +1,85 @@
+// Copyright (C) 2007-2024  CEA, EDF
+//
+// This library is free software; you can redistribute it and/or
+// modify it under the terms of the GNU Lesser General Public
+// License as published by the Free Software Foundation; either
+// version 2.1 of the License, or (at your option) any later version.
+//
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+// Lesser General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public
+// License along with this library; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
+//
+// See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
+//
+
+#ifndef __SHAPERECOGNMESHBUILDER_HXX__
+#define __SHAPERECOGNMESHBUILDER_HXX__
+
+#include <string>
+
+#include "MEDCouplingUMesh.hxx"
+#include "MEDCouplingFieldDouble.hxx"
+
+namespace MEDCoupling
+{
+    class Nodes;
+    class Areas;
+    class ShapeRecognMesh;
+
+    class ShapeRecognMeshBuilder
+    {
+    public:
+        ShapeRecognMeshBuilder(const std::string &fileName, int meshDimRelToMax = 0);
+        ~ShapeRecognMeshBuilder();
+
+        const Nodes *getNodes() const;
+        const Areas *getAreas() const;
+
+        ShapeRecognMesh *recognize();
+
+    private:
+        // Node properties
+        MEDCoupling::MEDCouplingFieldDouble *buildNodeK1() const;
+        MEDCoupling::MEDCouplingFieldDouble *buildNodeK2() const;
+        MEDCoupling::MEDCouplingFieldDouble *buildNodePrimitiveType() const;
+        MEDCoupling::MEDCouplingFieldDouble *buildNodeNormal() const;
+
+        // Area properties
+        MEDCoupling::MEDCouplingFieldDouble *buildAreaId() const;
+        MEDCoupling::MEDCouplingFieldDouble *buildAreaPrimitiveType() const;
+        MEDCoupling::MEDCouplingFieldDouble *buildAreaNormal() const;
+        MEDCoupling::MEDCouplingFieldDouble *buildMinorRadius() const;
+        MEDCoupling::MEDCouplingFieldDouble *buildRadius() const;
+        MEDCoupling::MEDCouplingFieldDouble *buildAngle() const;
+        MEDCoupling::MEDCouplingFieldDouble *buildCenter() const;
+        MEDCoupling::MEDCouplingFieldDouble *buildAxis() const;
+        MEDCoupling::MEDCouplingFieldDouble *buildApex() const;
+
+        template <typename T>
+        MEDCouplingFieldDouble *buildField(
+            const std::string &name,
+            size_t nbOfCompo,
+            const std::vector<T> &values) const;
+        MEDCouplingFieldDouble *buildField(
+            const std::string &name,
+            size_t nbOfCompo,
+            double *values) const;
+        MEDCouplingFieldDouble *buildField(
+            const std::string &name,
+            size_t nbOfCompo,
+            DataArrayDouble *values) const;
+        double *buildArea3DArray(const std::array<double, 3> &(*areaFunc)(Areas *, mcIdType)) const;
+        double *buildAreaArray(double (*areaFunc)(Areas *, mcIdType)) const;
+
+        const MEDCouplingUMesh *mesh;
+        Nodes *nodes = nullptr;
+        Areas *areas = nullptr;
+    };
+};
+
+#endif // __SHAPERECOGNMESHBUILDER_HXX__
index f97e5f9eaa8c1477db4cd70476c67a52b4cb49e3..58893b0c612bec1fc935debaa8e3ef2563075755 100644 (file)
@@ -5,9 +5,11 @@
 
 %{
 #include "ShapeRecognMesh.hxx"
+#include "ShapeRecognMeshBuilder.hxx"
 using namespace MEDCoupling;
 %}
 
 %ignore getAreas() const;
 %ignore getNodes() const;
 %include "ShapeRecognMesh.hxx"
+%include "ShapeRecognMeshBuilder.hxx"
index d22fae6208587b552af479f352e9533c731c6fcc..d25f4a792f1f98a8e5c34615490c26d1668b3740 100644 (file)
@@ -1,6 +1,6 @@
 #include "ConeTest.hxx"
 
-#include "ShapeRecognMesh.hxx"
+#include "ShapeRecognMeshBuilder.hxx"
 #include "Areas.hxx"
 #include "MathOps.hxx"
 #include "TestInterpKernelUtils.hxx" // getResourceFile()
@@ -10,7 +10,7 @@ using namespace MEDCoupling;
 void ConeTest::setUp()
 {
     std::string file = INTERP_TEST::getResourceFile("ShapeRecognCone.med", 3);
-    srMesh = new ShapeRecognMesh(file);
+    srMesh = new ShapeRecognMeshBuilder(file);
     srMesh->recognize();
     areas = srMesh->getAreas();
 }
index 283bfc8458fcf997b57f8479a3ebcd6a313c0547..20b1bef3fd02e514f77b2315d44c6c6bc6f8e046 100644 (file)
@@ -25,7 +25,7 @@
 
 namespace MEDCoupling
 {
-    class ShapeRecognMesh;
+    class ShapeRecognMeshBuilder;
     class Areas;
 
     class ConeTest : public CppUnit::TestFixture
@@ -54,7 +54,7 @@ namespace MEDCoupling
         void testThirdArea();
 
     private:
-        ShapeRecognMesh *srMesh = 0;
+        ShapeRecognMeshBuilder *srMesh = 0;
         const Areas *areas;
     };
 };
index ee01878a0c8fb01a7191178e0403fb57520ae0ae..47f6ac3d3bfd76c005f144e8ff10cd30753ff6d0 100644 (file)
@@ -1,6 +1,6 @@
 #include "CylinderTest.hxx"
 
-#include "ShapeRecognMesh.hxx"
+#include "ShapeRecognMeshBuilder.hxx"
 #include "Areas.hxx"
 #include "MathOps.hxx"
 #include "TestInterpKernelUtils.hxx" // getResourceFile()
@@ -10,7 +10,7 @@ using namespace MEDCoupling;
 void CylinderTest::setUp()
 {
     std::string file = INTERP_TEST::getResourceFile("ShapeRecognCylinder.med", 3);
-    srMesh = new ShapeRecognMesh(file);
+    srMesh = new ShapeRecognMeshBuilder(file);
     srMesh->recognize();
     areas = srMesh->getAreas();
 }
index 98f32ff545e3476bd16d8cc76cd6666069c602c6..a35ac14817921873150bf878e51c3b1499227e8d 100644 (file)
@@ -25,7 +25,7 @@
 
 namespace MEDCoupling
 {
-    class ShapeRecognMesh;
+    class ShapeRecognMeshBuilder;
     class Areas;
 
     class CylinderTest : public CppUnit::TestFixture
@@ -47,7 +47,7 @@ namespace MEDCoupling
         void testThirdArea();
 
     private:
-        ShapeRecognMesh *srMesh = 0;
+        ShapeRecognMeshBuilder *srMesh = 0;
         const Areas *areas;
     };
 };
index 3bd1b62a91e41bf9d48934b1c0436323f5680f75..6f47f161c99e0587c5c7a0c778e03e7434c5c03b 100644 (file)
@@ -1,6 +1,6 @@
 #include "PlaneTest.hxx"
 
-#include "ShapeRecognMesh.hxx"
+#include "ShapeRecognMeshBuilder.hxx"
 #include "Areas.hxx"
 #include "MathOps.hxx"
 #include "TestInterpKernelUtils.hxx" // getResourceFile()
@@ -10,7 +10,7 @@ using namespace MEDCoupling;
 void PlaneTest::setUp()
 {
     std::string file = INTERP_TEST::getResourceFile("ShapeRecognPlane.med", 3);
-    srMesh = new ShapeRecognMesh(file);
+    srMesh = new ShapeRecognMeshBuilder(file);
     srMesh->recognize();
     areas = srMesh->getAreas();
 }
index b728d9c31f2fc79d67beba356529b6c010fe7677..af6eb47552294b512814f4bde47f6c66793f837c 100644 (file)
@@ -25,7 +25,7 @@
 
 namespace MEDCoupling
 {
-    class ShapeRecognMesh;
+    class ShapeRecognMeshBuilder;
     class Areas;
 
     class PlaneTest : public CppUnit::TestFixture
@@ -41,7 +41,7 @@ namespace MEDCoupling
         void testArea();
 
     private:
-        ShapeRecognMesh *srMesh = 0;
+        ShapeRecognMeshBuilder *srMesh = 0;
         const Areas *areas;
     };
 };
index 0cf12728f62b92aad8d951b26ed2ad464b9203ab..4d7f64ecb673aed1ed718acb7cc057f3f5e86041 100644 (file)
@@ -1,6 +1,6 @@
 #include "SphereTest.hxx"
 
-#include "ShapeRecognMesh.hxx"
+#include "ShapeRecognMeshBuilder.hxx"
 #include "Areas.hxx"
 #include "MathOps.hxx"
 #include "TestInterpKernelUtils.hxx" // getResourceFile()
@@ -10,7 +10,7 @@ using namespace MEDCoupling;
 void SphereTest::setUp()
 {
     std::string file = INTERP_TEST::getResourceFile("ShapeRecognSphere.med", 3);
-    srMesh = new ShapeRecognMesh(file);
+    srMesh = new ShapeRecognMeshBuilder(file);
     srMesh->recognize();
     areas = srMesh->getAreas();
 }
index abcfbfc8a51dd99526dc67640deb8d59fbe63074..6500def00b1561889adfc701ad561ddb70e51b72 100644 (file)
@@ -25,7 +25,7 @@
 
 namespace MEDCoupling
 {
-    class ShapeRecognMesh;
+    class ShapeRecognMeshBuilder;
     class Areas;
 
     class SphereTest : public CppUnit::TestFixture
@@ -41,7 +41,7 @@ namespace MEDCoupling
         void testArea();
 
     private:
-        ShapeRecognMesh *srMesh = 0;
+        ShapeRecognMeshBuilder *srMesh = 0;
         const Areas *areas;
     };
 };
index 6129138812e3b30e58a78d700732b590649f387d..6e24d10eeb4ad0a10be2ea64ca1f55dd3fa27fc6 100644 (file)
@@ -1,6 +1,6 @@
 #include "TorusTest.hxx"
 
-#include "ShapeRecognMesh.hxx"
+#include "ShapeRecognMeshBuilder.hxx"
 #include "Areas.hxx"
 #include "MathOps.hxx"
 #include "TestInterpKernelUtils.hxx" // getResourceFile()
@@ -10,7 +10,7 @@ using namespace MEDCoupling;
 void TorusTest::setUp()
 {
     std::string file = INTERP_TEST::getResourceFile("ShapeRecognTorus.med", 3);
-    srMesh = new ShapeRecognMesh(file);
+    srMesh = new ShapeRecognMeshBuilder(file);
     srMesh->recognize();
     areas = srMesh->getAreas();
 }
index 4999f579be909ff2e2fcf588aba2ea1bc9657c7a..07ae86d3aa722c599cec3e9edcd9013505f18131 100644 (file)
@@ -25,7 +25,7 @@
 
 namespace MEDCoupling
 {
-    class ShapeRecognMesh;
+    class ShapeRecognMeshBuilder;
     class Areas;
 
     class TorusTest : public CppUnit::TestFixture
@@ -41,7 +41,7 @@ namespace MEDCoupling
         void testArea();
 
     private:
-        ShapeRecognMesh *srMesh = 0;
+        ShapeRecognMeshBuilder *srMesh = 0;
         const Areas *areas;
     };
 };