From: Anthony Geay Date: Fri, 30 Aug 2024 08:41:41 +0000 (+0200) Subject: [EDF30834] : First python test X-Git-Url: http://git.salome-platform.org/gitweb/?a=commitdiff_plain;h=cbaa720c44ef85d64335446df9a2ac201873fbfe;p=tools%2Fmedcoupling.git [EDF30834] : First python test --- diff --git a/src/ShapeRecogn/ShapeRecognMesh.hxx b/src/ShapeRecogn/ShapeRecognMesh.hxx index deb44962b..efbb312e8 100644 --- a/src/ShapeRecogn/ShapeRecognMesh.hxx +++ b/src/ShapeRecogn/ShapeRecognMesh.hxx @@ -42,6 +42,8 @@ namespace MEDCoupling const MEDCouplingFieldDouble *getNodeK2() const; const MEDCouplingFieldInt32 *getNodePrimitiveType() const; const MEDCouplingFieldDouble *getNodeNormal() const; + // see ShapeRecognMeshBuilder::buildNodeWeakDirections + // see ShapeRecognMeshBuilder::buildNodeMainDirections // Area properties const MEDCouplingFieldInt32 *getAreaId() const; @@ -53,6 +55,9 @@ namespace MEDCoupling const MEDCouplingFieldDouble *getCenter() const; const MEDCouplingFieldDouble *getAxis() const; const MEDCouplingFieldDouble *getApex() const; + + // see ShapeRecognMeshBuilder::buildAreaAxisPoint + // see ShapeRecognMeshBuilder::buildAreaAffinePoint protected: ShapeRecognMesh(); diff --git a/src/ShapeRecogn/ShapeRecognMeshBuilder.cxx b/src/ShapeRecogn/ShapeRecognMeshBuilder.cxx index 6f1434065..fea8abe42 100644 --- a/src/ShapeRecogn/ShapeRecognMeshBuilder.cxx +++ b/src/ShapeRecogn/ShapeRecognMeshBuilder.cxx @@ -27,6 +27,9 @@ #include "MEDCouplingFieldInt64.hxx" #include "MEDCouplingFieldInt32.hxx" +#include +#include + using namespace MEDCoupling; ShapeRecognMeshBuilder::ShapeRecognMeshBuilder(MCAuto< MEDCouplingUMesh > mesh) @@ -166,6 +169,8 @@ T *buildAreaArrayT(Areas *areas, Nodes *nodes, std::function::max(); } return values; } @@ -185,7 +190,8 @@ MEDCouplingFieldDouble *ShapeRecognMeshBuilder::buildNodeK2() const MEDCouplingFieldInt32 *ShapeRecognMeshBuilder::buildNodePrimitiveType() const { checkNodesBeforeBuildingField(); - return nullptr;//buildField("Primitive Type (Node)", 1, nodes->getPrimitiveType(), mesh); + const std::vector tmp( nodes->getPrimitiveType() ); + return buildField("Primitive Type (Node)", 1, {tmp.begin(),tmp.end()}, mesh); } MEDCouplingFieldDouble *ShapeRecognMeshBuilder::buildNodeNormal() const @@ -194,6 +200,18 @@ MEDCouplingFieldDouble *ShapeRecognMeshBuilder::buildNodeNormal() const return buildField("Normal (Node)", 3, nodes->getNormals(), mesh); } +MEDCoupling::MCAuto ShapeRecognMeshBuilder::buildNodeWeakDirections() const +{ + checkNodesBeforeBuildingField(); + return MEDCoupling::MCAuto(buildField("WeakDirection (Node)", 3, nodes->getWeakDirections(), mesh)); +} + +MEDCoupling::MCAuto ShapeRecognMeshBuilder::buildNodeMainDirections() const +{ + checkNodesBeforeBuildingField(); + return MEDCoupling::MCAuto(buildField("MainDirection (Node)", 3, nodes->getMainDirections(), mesh)); +} + MEDCouplingFieldInt32 *ShapeRecognMeshBuilder::buildAreaId() const { checkAreasBeforeBuildingField(); @@ -203,8 +221,8 @@ MEDCouplingFieldInt32 *ShapeRecognMeshBuilder::buildAreaId() const MEDCouplingFieldInt32 *ShapeRecognMeshBuilder::buildAreaPrimitiveType() const { checkAreasBeforeBuildingField(); - std::int32_t *values = buildAreaArrayT(areas.get(),nodes.get(),[](Areas *areas, mcIdType areaId) -> std::int32_t - { return (std::int32_t)areas->getPrimitiveType(areaId); }); + Int32 *values = buildAreaArrayT(areas.get(),nodes.get(),[](Areas *areas, mcIdType areaId) -> Int32 + { return (Int32)areas->getPrimitiveType(areaId); }); return buildField("Primitive Type (Area)", 1, values, mesh); } @@ -243,7 +261,7 @@ MEDCouplingFieldDouble *ShapeRecognMeshBuilder::buildAngle() const MEDCouplingFieldDouble *ShapeRecognMeshBuilder::buildCenter() const { checkAreasBeforeBuildingField(); - double *values = buildArea3DArray([](Areas *areas, mcIdType areaId) -> const std::array & + double *values = buildArea3DArray([](Areas *areas, mcIdType areaId) -> std::array { return areas->getCenter(areaId); }); return buildField("Center (Area)", 3, values, mesh); } @@ -251,7 +269,7 @@ MEDCouplingFieldDouble *ShapeRecognMeshBuilder::buildCenter() const MEDCouplingFieldDouble *ShapeRecognMeshBuilder::buildAxis() const { checkAreasBeforeBuildingField(); - double *values = buildArea3DArray([](Areas *areas, mcIdType areaId) -> const std::array & + double *values = buildArea3DArray([](Areas *areas, mcIdType areaId) -> std::array { return areas->getAxis(areaId); }); return buildField("Axis (Area)", 3, values, mesh); } @@ -259,12 +277,28 @@ MEDCouplingFieldDouble *ShapeRecognMeshBuilder::buildAxis() const MEDCouplingFieldDouble *ShapeRecognMeshBuilder::buildApex() const { checkAreasBeforeBuildingField(); - double *values = buildArea3DArray([](Areas *areas, mcIdType areaId) -> const std::array & + double *values = buildArea3DArray([](Areas *areas, mcIdType areaId) -> std::array { return areas->getApex(areaId); }); return buildField("Apex (Area)", 3, values, mesh); } -double *ShapeRecognMeshBuilder::buildArea3DArray(std::function &(Areas *, Int32)> areaFunc) const +MEDCoupling::MCAuto ShapeRecognMeshBuilder::buildAreaAxisPoint() const +{ + checkAreasBeforeBuildingField(); + double *values = buildArea3DArray([](Areas *areas, mcIdType areaId) -> std::array + { return areas->getAxisPoint(areaId); }); + return MEDCoupling::MCAuto( buildField("AxisPoint (Area)", 3, values, mesh) ); +} + +MEDCoupling::MCAuto ShapeRecognMeshBuilder::buildAreaAffinePoint() const +{ + checkAreasBeforeBuildingField(); + double *values = buildArea3DArray([](Areas *areas, mcIdType areaId) -> std::array + { return areas->getAffinePoint(areaId); }); + return MEDCoupling::MCAuto( buildField("AffinePoint (Area)", 3, values, mesh) ); +} + +double *ShapeRecognMeshBuilder::buildArea3DArray(std::function(Areas *, Int32)> areaFunc) const { double *values = new double[3 * nodes->getNbNodes()]; const std::vector &areaIdByNodes = areas->getAreaIdByNodes(); @@ -273,11 +307,15 @@ double *ShapeRecognMeshBuilder::buildArea3DArray(std::function &areaValues = areaFunc(areas.get(), areaId); + const std::array areaValues( areaFunc(areas.get(), areaId) ); values[3 * nodeId] = areaValues[0]; values[3 * nodeId + 1] = areaValues[1]; values[3 * nodeId + 2] = areaValues[2]; } + else + { + std::for_each(values + 3 * nodeId, values + 3 * (nodeId + 1), [](double& val) { val = std::numeric_limits::max(); }); + } } return values; } diff --git a/src/ShapeRecogn/ShapeRecognMeshBuilder.hxx b/src/ShapeRecogn/ShapeRecognMeshBuilder.hxx index 051fdf65a..ab20016ea 100644 --- a/src/ShapeRecogn/ShapeRecognMeshBuilder.hxx +++ b/src/ShapeRecogn/ShapeRecognMeshBuilder.hxx @@ -49,13 +49,20 @@ namespace MEDCoupling MCAuto recognize(); + // Node properties + MEDCoupling::MCAuto buildNodeWeakDirections() const; + MEDCoupling::MCAuto buildNodeMainDirections() const; + + //Area properties + MEDCoupling::MCAuto buildAreaAxisPoint() const; + MEDCoupling::MCAuto buildAreaAffinePoint() const; private: // Node properties MEDCoupling::MEDCouplingFieldDouble *buildNodeK1() const; MEDCoupling::MEDCouplingFieldDouble *buildNodeK2() const; MEDCoupling::MEDCouplingFieldInt32 *buildNodePrimitiveType() const; MEDCoupling::MEDCouplingFieldDouble *buildNodeNormal() const; - + // Area properties MEDCoupling::MEDCouplingFieldInt32 *buildAreaId() const; MEDCoupling::MEDCouplingFieldInt32 *buildAreaPrimitiveType() const; @@ -67,7 +74,7 @@ namespace MEDCoupling MEDCoupling::MEDCouplingFieldDouble *buildAxis() const; MEDCoupling::MEDCouplingFieldDouble *buildApex() const; - double *buildArea3DArray(std::function &(Areas *, Int32)> areaFunc) const; + double *buildArea3DArray(std::function(Areas *, Int32)> areaFunc) const; double *buildAreaArray(std::function areaFunc) const; void assign(MCAuto< MEDCouplingUMesh > mesh); void checkNodesBeforeBuildingField() const; diff --git a/src/ShapeRecogn/Swig/ShapeRecognImpl.i b/src/ShapeRecogn/Swig/ShapeRecognImpl.i index 677bdb2eb..b1fdeab34 100644 --- a/src/ShapeRecogn/Swig/ShapeRecognImpl.i +++ b/src/ShapeRecogn/Swig/ShapeRecognImpl.i @@ -25,6 +25,8 @@ %feature("unref") ShapeRecognMesh "$this->decrRef();" +%newobject Areas::getNodeIds; + %newobject ShapeRecognMeshBuilder::recognize; %newobject ShapeRecognMesh::getNodeK1; @@ -52,12 +54,17 @@ public: size_t getNumberOfAreas() const; size_t getNumberOfNodes(mcIdType areaId) const; std::string getPrimitiveTypeName(mcIdType areaId) const; - /*const std::array &getNormal(mcIdType areaId) const; - const std::array &getCenter(mcIdType areaId) const; - const std::array &getAxis(mcIdType areaId) const; - const std::array &getAxisPoint(mcIdType areaId) const; - const std::array &getApex(mcIdType areaId) const; - std::array getAffinePoint(mcIdType areaId) const;*/ + %extend + { + DataArrayIdType *getNodeIds(mcIdType areaId) const + { + const std::vector &res = self->getNodeIds(areaId); + MCAuto< DataArrayIdType > ret( DataArrayIdType::New() ); + ret->alloc(res.size(),1); + std::copy(res.begin(),res.end(),ret->getPointer()); + return ret.retn(); + } + } private: Areas(); ~Areas(); @@ -69,99 +76,101 @@ class ShapeRecognMesh : public RefCountObject { public: ~ShapeRecognMesh(); - - // Node properties - MEDCouplingFieldDouble *getNodeK1() const - { - MEDCouplingFieldDouble *ret = const_cast( self->getNodeK1() ); - ret->incrRef(); - return ret; - } - - MEDCouplingFieldDouble *getNodeK2() const - { - MEDCouplingFieldDouble *ret = const_cast( self->getNodeK2() ); - ret->incrRef(); - return ret; - } - - MEDCouplingFieldDouble *getNodePrimitiveType() const - { - MEDCouplingFieldDouble *ret = const_cast( self->getNodePrimitiveType() ); - ret->incrRef(); - return ret; - } - - MEDCouplingFieldDouble *getNodeNormal() const - { - MEDCouplingFieldDouble *ret = const_cast( self->getNodeNormal() ); - ret->incrRef(); - return ret; - } - - // Area properties - - MEDCouplingFieldDouble *getAreaId() const - { - MEDCouplingFieldDouble *ret = const_cast( self->getAreaId() ); - ret->incrRef(); - return ret; - } - - MEDCouplingFieldDouble *getAreaPrimitiveType() const - { - MEDCouplingFieldDouble *ret = const_cast( self->getAreaPrimitiveType() ); - ret->incrRef(); - return ret; - } - - MEDCouplingFieldDouble *getAreaNormal() const - { - MEDCouplingFieldDouble *ret = const_cast( self->getAreaNormal() ); - ret->incrRef(); - return ret; - } - - MEDCouplingFieldDouble *getMinorRadius() const - { - MEDCouplingFieldDouble *ret = const_cast( self->getMinorRadius() ); - ret->incrRef(); - return ret; - } - - MEDCouplingFieldDouble *getRadius() const - { - MEDCouplingFieldDouble *ret = const_cast( self->getRadius() ); - ret->incrRef(); - return ret; - } - - MEDCouplingFieldDouble *getAngle() const - { - MEDCouplingFieldDouble *ret = const_cast( self->getAngle() ); - ret->incrRef(); - return ret; - } - - MEDCouplingFieldDouble *getCenter() const - { - MEDCouplingFieldDouble *ret = const_cast( self->getCenter() ); - ret->incrRef(); - return ret; - } - - MEDCouplingFieldDouble *getAxis() const - { - MEDCouplingFieldDouble *ret = const_cast( self->getAxis() ); - ret->incrRef(); - return ret; - } - - MEDCouplingFieldDouble *getApex() const + %extend { - MEDCouplingFieldDouble *ret = const_cast( self->getApex() ); - ret->incrRef(); - return ret; + // Node properties + MEDCouplingFieldDouble *getNodeK1() const + { + MEDCouplingFieldDouble *ret = const_cast( self->getNodeK1() ); + ret->incrRef(); + return ret; + } + + MEDCouplingFieldDouble *getNodeK2() const + { + MEDCouplingFieldDouble *ret = const_cast( self->getNodeK2() ); + ret->incrRef(); + return ret; + } + + MEDCouplingFieldInt32 *getNodePrimitiveType() const + { + MEDCouplingFieldInt32 *ret = const_cast( self->getNodePrimitiveType() ); + ret->incrRef(); + return ret; + } + + MEDCouplingFieldDouble *getNodeNormal() const + { + MEDCouplingFieldDouble *ret = const_cast( self->getNodeNormal() ); + ret->incrRef(); + return ret; + } + + // Area properties + + MEDCouplingFieldInt32 *getAreaId() const + { + MEDCouplingFieldInt32 *ret = const_cast( self->getAreaId() ); + ret->incrRef(); + return ret; + } + + MEDCouplingFieldInt32 *getAreaPrimitiveType() const + { + MEDCouplingFieldInt32 *ret = const_cast( self->getAreaPrimitiveType() ); + ret->incrRef(); + return ret; + } + + MEDCouplingFieldDouble *getAreaNormal() const + { + MEDCouplingFieldDouble *ret = const_cast( self->getAreaNormal() ); + ret->incrRef(); + return ret; + } + + MEDCouplingFieldDouble *getMinorRadius() const + { + MEDCouplingFieldDouble *ret = const_cast( self->getMinorRadius() ); + ret->incrRef(); + return ret; + } + + MEDCouplingFieldDouble *getRadius() const + { + MEDCouplingFieldDouble *ret = const_cast( self->getRadius() ); + ret->incrRef(); + return ret; + } + + MEDCouplingFieldDouble *getAngle() const + { + MEDCouplingFieldDouble *ret = const_cast( self->getAngle() ); + ret->incrRef(); + return ret; + } + + MEDCouplingFieldDouble *getCenter() const + { + MEDCouplingFieldDouble *ret = const_cast( self->getCenter() ); + ret->incrRef(); + return ret; + } + + MEDCouplingFieldDouble *getAxis() const + { + MEDCouplingFieldDouble *ret = const_cast( self->getAxis() ); + ret->incrRef(); + return ret; + } + + MEDCouplingFieldDouble *getApex() const + { + MEDCouplingFieldDouble *ret = const_cast( self->getApex() ); + ret->incrRef(); + return ret; + } } private: ShapeRecognMesh(); @@ -172,15 +181,41 @@ class ShapeRecognMeshBuilder public: ShapeRecognMeshBuilder(MEDCoupling::MEDCouplingUMesh *mesh); ~ShapeRecognMeshBuilder(); - - //const Nodes *getNodes() const; const Areas *getAreas() const; %extend { - ShapeRecognMesh *recognize() - { - MCAuto ret = self->recognize(); - return ret.retn(); - } + MEDCouplingFieldDouble *buildNodeWeakDirections() const + { + MCAuto ret = self->buildNodeWeakDirections(); + ret->incrRef(); + return ret; + } + + MEDCouplingFieldDouble *buildNodeMainDirections() const + { + MCAuto ret = self->buildNodeMainDirections(); + ret->incrRef(); + return ret; + } + + MEDCouplingFieldDouble *buildAreaAxisPoint() const + { + MCAuto ret = self->buildAreaAxisPoint(); + ret->incrRef(); + return ret; + } + + MEDCouplingFieldDouble *buildAreaAffinePoint() const + { + MCAuto ret = self->buildAreaAffinePoint(); + ret->incrRef(); + return ret; + } + + ShapeRecognMesh *recognize() + { + MCAuto ret = self->recognize(); + return ret.retn(); + } } }; diff --git a/src/ShapeRecogn/Test/TestShapeRecogn.py b/src/ShapeRecogn/Test/TestShapeRecogn.py new file mode 100644 index 000000000..a4be8758c --- /dev/null +++ b/src/ShapeRecogn/Test/TestShapeRecogn.py @@ -0,0 +1,76 @@ +#! /usr/bin/env python3 +# -*- coding: utf-8 -*- +# Copyright (C) 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 +# + +import ShapeRecogn as sr +import MEDLoader as ml +from numpy.testing import assert_allclose +import unittest + +def getResourceFile(filename, levelUp = 2): + ROOT_DIR_0 = "MEDCOUPLING_ROOT_DIR" + ROOT_DIR_1 = "MEDCOUPLING_RESOURCE_DIR" + import os + from pathlib import Path + if ROOT_DIR_0 in os.environ: + resourceFile = Path( os.environ[ROOT_DIR_0] ).absolute() / "share" / "resources" / "med" / filename + if resourceFile.exists(): + return f"{resourceFile}" + if ROOT_DIR_1 in os.environ: + resourceFile = Path( os.environ[ROOT_DIR_1].split(":")[-1] ).absolute() / filename + if resourceFile.exists(): + return f"{resourceFile}" + p = Path.cwd() + for i in range(levelUp): + p = p.parent + resourceFile = p / "resources" / filename + if not resourceFile.exists(): + raise RuntimeError( f"getResourceFile: could not open resource test file {filename}" ) + pass + +class MEDCouplingIterativeStatisticsTest(unittest.TestCase): + def testPlane(self): + """ + Direct translation of PlaneTest::testArea + """ + fname = "ShapeRecognPlane.med" + mesh = ml.ReadUMeshFromFile( getResourceFile( fname, 3 ),0) + srMesh = sr.ShapeRecognMeshBuilder( mesh ) + rem = srMesh.recognize() + areas = srMesh.getAreas() + assert( areas.getNumberOfAreas() == 1 ) + assert( areas.getNumberOfNodes(0) == 36 ) + nodeIds = areas.getNodeIds(0) + f = rem.getAreaPrimitiveType() + assert( areas.getPrimitiveTypeName(0) == "Plane") + f_normal = rem.getNodeNormal() + affinePoint = srMesh.buildAreaAffinePoint().getArray()[ nodeIds[0] ] + normal = f_normal.getArray()[ nodeIds[0] ] + normalRef = sr.DataArrayDouble([0.781525, 0.310606, -0.541056],1,3) + proportion0 = normal[0,0] / normalRef[0,0] + proportion1 = normal[0,1] / normalRef[0,1] + proportion2 = normal[0,2] / normalRef[0,2] + proportion3 = sr.DataArrayDouble.Dot(normal,affinePoint)[0] / sr.DataArrayDouble.Dot(normalRef,affinePoint)[0] + assert_allclose([proportion0,proportion1,proportion2,proportion3],[1.0,1.0,1.0,1.0] , rtol = 1e-5) + angle = sr.DataArrayDouble.CrossProduct(normal,normalRef).magnitude()[0] + assert_allclose( [angle], [0.0], atol = 1e-6 ) + +if __name__ == "__main__": + unittest.main()