const MEDCouplingFieldDouble *getNodeK2() const;
const MEDCouplingFieldInt32 *getNodePrimitiveType() const;
const MEDCouplingFieldDouble *getNodeNormal() const;
+ // see ShapeRecognMeshBuilder::buildNodeWeakDirections
+ // see ShapeRecognMeshBuilder::buildNodeMainDirections
// Area properties
const MEDCouplingFieldInt32 *getAreaId() const;
const MEDCouplingFieldDouble *getCenter() const;
const MEDCouplingFieldDouble *getAxis() const;
const MEDCouplingFieldDouble *getApex() const;
+
+ // see ShapeRecognMeshBuilder::buildAreaAxisPoint
+ // see ShapeRecognMeshBuilder::buildAreaAffinePoint
protected:
ShapeRecognMesh();
#include "MEDCouplingFieldInt64.hxx"
#include "MEDCouplingFieldInt32.hxx"
+#include <algorithm>
+#include <limits>
+
using namespace MEDCoupling;
ShapeRecognMeshBuilder::ShapeRecognMeshBuilder(MCAuto< MEDCouplingUMesh > mesh)
Int32 areaId = areaIdByNodes[nodeId];
if (areaId != -1)
values[nodeId] = areaFunc(areas, areaId);
+ else
+ values[nodeId] = std::numeric_limits<T>::max();
}
return values;
}
MEDCouplingFieldInt32 *ShapeRecognMeshBuilder::buildNodePrimitiveType() const
{
checkNodesBeforeBuildingField();
- return nullptr;//buildField<Int32>("Primitive Type (Node)", 1, nodes->getPrimitiveType(), mesh);
+ const std::vector<PrimitiveType> tmp( nodes->getPrimitiveType() );
+ return buildField<Int32>("Primitive Type (Node)", 1, {tmp.begin(),tmp.end()}, mesh);
}
MEDCouplingFieldDouble *ShapeRecognMeshBuilder::buildNodeNormal() const
return buildField<double>("Normal (Node)", 3, nodes->getNormals(), mesh);
}
+MEDCoupling::MCAuto<MEDCoupling::MEDCouplingFieldDouble> ShapeRecognMeshBuilder::buildNodeWeakDirections() const
+{
+ checkNodesBeforeBuildingField();
+ return MEDCoupling::MCAuto<MEDCoupling::MEDCouplingFieldDouble>(buildField<double>("WeakDirection (Node)", 3, nodes->getWeakDirections(), mesh));
+}
+
+MEDCoupling::MCAuto<MEDCoupling::MEDCouplingFieldDouble> ShapeRecognMeshBuilder::buildNodeMainDirections() const
+{
+ checkNodesBeforeBuildingField();
+ return MEDCoupling::MCAuto<MEDCoupling::MEDCouplingFieldDouble>(buildField<double>("MainDirection (Node)", 3, nodes->getMainDirections(), mesh));
+}
+
MEDCouplingFieldInt32 *ShapeRecognMeshBuilder::buildAreaId() const
{
checkAreasBeforeBuildingField();
MEDCouplingFieldInt32 *ShapeRecognMeshBuilder::buildAreaPrimitiveType() const
{
checkAreasBeforeBuildingField();
- std::int32_t *values = buildAreaArrayT<std::int32_t>(areas.get(),nodes.get(),[](Areas *areas, mcIdType areaId) -> std::int32_t
- { return (std::int32_t)areas->getPrimitiveType(areaId); });
+ Int32 *values = buildAreaArrayT<Int32>(areas.get(),nodes.get(),[](Areas *areas, mcIdType areaId) -> Int32
+ { return (Int32)areas->getPrimitiveType(areaId); });
return buildField<Int32>("Primitive Type (Area)", 1, values, mesh);
}
MEDCouplingFieldDouble *ShapeRecognMeshBuilder::buildCenter() const
{
checkAreasBeforeBuildingField();
- double *values = buildArea3DArray([](Areas *areas, mcIdType areaId) -> const std::array<double, 3> &
+ double *values = buildArea3DArray([](Areas *areas, mcIdType areaId) -> std::array<double, 3>
{ return areas->getCenter(areaId); });
return buildField<double>("Center (Area)", 3, values, mesh);
}
MEDCouplingFieldDouble *ShapeRecognMeshBuilder::buildAxis() const
{
checkAreasBeforeBuildingField();
- double *values = buildArea3DArray([](Areas *areas, mcIdType areaId) -> const std::array<double, 3> &
+ double *values = buildArea3DArray([](Areas *areas, mcIdType areaId) -> std::array<double, 3>
{ return areas->getAxis(areaId); });
return buildField<double>("Axis (Area)", 3, values, mesh);
}
MEDCouplingFieldDouble *ShapeRecognMeshBuilder::buildApex() const
{
checkAreasBeforeBuildingField();
- double *values = buildArea3DArray([](Areas *areas, mcIdType areaId) -> const std::array<double, 3> &
+ double *values = buildArea3DArray([](Areas *areas, mcIdType areaId) -> std::array<double, 3>
{ return areas->getApex(areaId); });
return buildField<double>("Apex (Area)", 3, values, mesh);
}
-double *ShapeRecognMeshBuilder::buildArea3DArray(std::function<const std::array<double, 3> &(Areas *, Int32)> areaFunc) const
+MEDCoupling::MCAuto<MEDCoupling::MEDCouplingFieldDouble> ShapeRecognMeshBuilder::buildAreaAxisPoint() const
+{
+ checkAreasBeforeBuildingField();
+ double *values = buildArea3DArray([](Areas *areas, mcIdType areaId) -> std::array<double, 3>
+ { return areas->getAxisPoint(areaId); });
+ return MEDCoupling::MCAuto<MEDCoupling::MEDCouplingFieldDouble>( buildField<double>("AxisPoint (Area)", 3, values, mesh) );
+}
+
+MEDCoupling::MCAuto<MEDCoupling::MEDCouplingFieldDouble> ShapeRecognMeshBuilder::buildAreaAffinePoint() const
+{
+ checkAreasBeforeBuildingField();
+ double *values = buildArea3DArray([](Areas *areas, mcIdType areaId) -> std::array<double, 3>
+ { return areas->getAffinePoint(areaId); });
+ return MEDCoupling::MCAuto<MEDCoupling::MEDCouplingFieldDouble>( buildField<double>("AffinePoint (Area)", 3, values, mesh) );
+}
+
+double *ShapeRecognMeshBuilder::buildArea3DArray(std::function<std::array<double, 3>(Areas *, Int32)> areaFunc) const
{
double *values = new double[3 * nodes->getNbNodes()];
const std::vector<Int32> &areaIdByNodes = areas->getAreaIdByNodes();
Int32 areaId = areaIdByNodes[nodeId];
if (areaId != -1)
{
- const std::array<double, 3> &areaValues = areaFunc(areas.get(), areaId);
+ const std::array<double, 3> 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<double>::max(); });
+ }
}
return values;
}
MCAuto<ShapeRecognMesh> recognize();
+ // Node properties
+ MEDCoupling::MCAuto<MEDCoupling::MEDCouplingFieldDouble> buildNodeWeakDirections() const;
+ MEDCoupling::MCAuto<MEDCoupling::MEDCouplingFieldDouble> buildNodeMainDirections() const;
+
+ //Area properties
+ MEDCoupling::MCAuto<MEDCoupling::MEDCouplingFieldDouble> buildAreaAxisPoint() const;
+ MEDCoupling::MCAuto<MEDCoupling::MEDCouplingFieldDouble> 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;
MEDCoupling::MEDCouplingFieldDouble *buildAxis() const;
MEDCoupling::MEDCouplingFieldDouble *buildApex() const;
- double *buildArea3DArray(std::function<const std::array<double, 3> &(Areas *, Int32)> areaFunc) const;
+ double *buildArea3DArray(std::function<std::array<double, 3>(Areas *, Int32)> areaFunc) const;
double *buildAreaArray(std::function<double(Areas *, Int32)> areaFunc) const;
void assign(MCAuto< MEDCouplingUMesh > mesh);
void checkNodesBeforeBuildingField() const;
%feature("unref") ShapeRecognMesh "$this->decrRef();"
+%newobject Areas::getNodeIds;
+
%newobject ShapeRecognMeshBuilder::recognize;
%newobject ShapeRecognMesh::getNodeK1;
size_t getNumberOfAreas() const;
size_t getNumberOfNodes(mcIdType areaId) const;
std::string getPrimitiveTypeName(mcIdType areaId) const;
- /*const std::array<double, 3> &getNormal(mcIdType areaId) const;
- const std::array<double, 3> &getCenter(mcIdType areaId) const;
- const std::array<double, 3> &getAxis(mcIdType areaId) const;
- const std::array<double, 3> &getAxisPoint(mcIdType areaId) const;
- const std::array<double, 3> &getApex(mcIdType areaId) const;
- std::array<double, 3> getAffinePoint(mcIdType areaId) const;*/
+ %extend
+ {
+ DataArrayIdType *getNodeIds(mcIdType areaId) const
+ {
+ const std::vector<mcIdType> &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();
{
public:
~ShapeRecognMesh();
-
- // Node properties
- MEDCouplingFieldDouble *getNodeK1() const
- {
- MEDCouplingFieldDouble *ret = const_cast<MEDCouplingFieldDouble *>( self->getNodeK1() );
- ret->incrRef();
- return ret;
- }
-
- MEDCouplingFieldDouble *getNodeK2() const
- {
- MEDCouplingFieldDouble *ret = const_cast<MEDCouplingFieldDouble *>( self->getNodeK2() );
- ret->incrRef();
- return ret;
- }
-
- MEDCouplingFieldDouble *getNodePrimitiveType() const
- {
- MEDCouplingFieldDouble *ret = const_cast<MEDCouplingFieldDouble *>( self->getNodePrimitiveType() );
- ret->incrRef();
- return ret;
- }
-
- MEDCouplingFieldDouble *getNodeNormal() const
- {
- MEDCouplingFieldDouble *ret = const_cast<MEDCouplingFieldDouble *>( self->getNodeNormal() );
- ret->incrRef();
- return ret;
- }
-
- // Area properties
-
- MEDCouplingFieldDouble *getAreaId() const
- {
- MEDCouplingFieldDouble *ret = const_cast<MEDCouplingFieldDouble *>( self->getAreaId() );
- ret->incrRef();
- return ret;
- }
-
- MEDCouplingFieldDouble *getAreaPrimitiveType() const
- {
- MEDCouplingFieldDouble *ret = const_cast<MEDCouplingFieldDouble *>( self->getAreaPrimitiveType() );
- ret->incrRef();
- return ret;
- }
-
- MEDCouplingFieldDouble *getAreaNormal() const
- {
- MEDCouplingFieldDouble *ret = const_cast<MEDCouplingFieldDouble *>( self->getAreaNormal() );
- ret->incrRef();
- return ret;
- }
-
- MEDCouplingFieldDouble *getMinorRadius() const
- {
- MEDCouplingFieldDouble *ret = const_cast<MEDCouplingFieldDouble *>( self->getMinorRadius() );
- ret->incrRef();
- return ret;
- }
-
- MEDCouplingFieldDouble *getRadius() const
- {
- MEDCouplingFieldDouble *ret = const_cast<MEDCouplingFieldDouble *>( self->getRadius() );
- ret->incrRef();
- return ret;
- }
-
- MEDCouplingFieldDouble *getAngle() const
- {
- MEDCouplingFieldDouble *ret = const_cast<MEDCouplingFieldDouble *>( self->getAngle() );
- ret->incrRef();
- return ret;
- }
-
- MEDCouplingFieldDouble *getCenter() const
- {
- MEDCouplingFieldDouble *ret = const_cast<MEDCouplingFieldDouble *>( self->getCenter() );
- ret->incrRef();
- return ret;
- }
-
- MEDCouplingFieldDouble *getAxis() const
- {
- MEDCouplingFieldDouble *ret = const_cast<MEDCouplingFieldDouble *>( self->getAxis() );
- ret->incrRef();
- return ret;
- }
-
- MEDCouplingFieldDouble *getApex() const
+ %extend
{
- MEDCouplingFieldDouble *ret = const_cast<MEDCouplingFieldDouble *>( self->getApex() );
- ret->incrRef();
- return ret;
+ // Node properties
+ MEDCouplingFieldDouble *getNodeK1() const
+ {
+ MEDCouplingFieldDouble *ret = const_cast<MEDCouplingFieldDouble *>( self->getNodeK1() );
+ ret->incrRef();
+ return ret;
+ }
+
+ MEDCouplingFieldDouble *getNodeK2() const
+ {
+ MEDCouplingFieldDouble *ret = const_cast<MEDCouplingFieldDouble *>( self->getNodeK2() );
+ ret->incrRef();
+ return ret;
+ }
+
+ MEDCouplingFieldInt32 *getNodePrimitiveType() const
+ {
+ MEDCouplingFieldInt32 *ret = const_cast<MEDCouplingFieldInt32 *>( self->getNodePrimitiveType() );
+ ret->incrRef();
+ return ret;
+ }
+
+ MEDCouplingFieldDouble *getNodeNormal() const
+ {
+ MEDCouplingFieldDouble *ret = const_cast<MEDCouplingFieldDouble *>( self->getNodeNormal() );
+ ret->incrRef();
+ return ret;
+ }
+
+ // Area properties
+
+ MEDCouplingFieldInt32 *getAreaId() const
+ {
+ MEDCouplingFieldInt32 *ret = const_cast<MEDCouplingFieldInt32 *>( self->getAreaId() );
+ ret->incrRef();
+ return ret;
+ }
+
+ MEDCouplingFieldInt32 *getAreaPrimitiveType() const
+ {
+ MEDCouplingFieldInt32 *ret = const_cast<MEDCouplingFieldInt32 *>( self->getAreaPrimitiveType() );
+ ret->incrRef();
+ return ret;
+ }
+
+ MEDCouplingFieldDouble *getAreaNormal() const
+ {
+ MEDCouplingFieldDouble *ret = const_cast<MEDCouplingFieldDouble *>( self->getAreaNormal() );
+ ret->incrRef();
+ return ret;
+ }
+
+ MEDCouplingFieldDouble *getMinorRadius() const
+ {
+ MEDCouplingFieldDouble *ret = const_cast<MEDCouplingFieldDouble *>( self->getMinorRadius() );
+ ret->incrRef();
+ return ret;
+ }
+
+ MEDCouplingFieldDouble *getRadius() const
+ {
+ MEDCouplingFieldDouble *ret = const_cast<MEDCouplingFieldDouble *>( self->getRadius() );
+ ret->incrRef();
+ return ret;
+ }
+
+ MEDCouplingFieldDouble *getAngle() const
+ {
+ MEDCouplingFieldDouble *ret = const_cast<MEDCouplingFieldDouble *>( self->getAngle() );
+ ret->incrRef();
+ return ret;
+ }
+
+ MEDCouplingFieldDouble *getCenter() const
+ {
+ MEDCouplingFieldDouble *ret = const_cast<MEDCouplingFieldDouble *>( self->getCenter() );
+ ret->incrRef();
+ return ret;
+ }
+
+ MEDCouplingFieldDouble *getAxis() const
+ {
+ MEDCouplingFieldDouble *ret = const_cast<MEDCouplingFieldDouble *>( self->getAxis() );
+ ret->incrRef();
+ return ret;
+ }
+
+ MEDCouplingFieldDouble *getApex() const
+ {
+ MEDCouplingFieldDouble *ret = const_cast<MEDCouplingFieldDouble *>( self->getApex() );
+ ret->incrRef();
+ return ret;
+ }
}
private:
ShapeRecognMesh();
public:
ShapeRecognMeshBuilder(MEDCoupling::MEDCouplingUMesh *mesh);
~ShapeRecognMeshBuilder();
-
- //const Nodes *getNodes() const;
const Areas *getAreas() const;
%extend
{
- ShapeRecognMesh *recognize()
- {
- MCAuto<ShapeRecognMesh> ret = self->recognize();
- return ret.retn();
- }
+ MEDCouplingFieldDouble *buildNodeWeakDirections() const
+ {
+ MCAuto<MEDCouplingFieldDouble> ret = self->buildNodeWeakDirections();
+ ret->incrRef();
+ return ret;
+ }
+
+ MEDCouplingFieldDouble *buildNodeMainDirections() const
+ {
+ MCAuto<MEDCouplingFieldDouble> ret = self->buildNodeMainDirections();
+ ret->incrRef();
+ return ret;
+ }
+
+ MEDCouplingFieldDouble *buildAreaAxisPoint() const
+ {
+ MCAuto<MEDCouplingFieldDouble> ret = self->buildAreaAxisPoint();
+ ret->incrRef();
+ return ret;
+ }
+
+ MEDCouplingFieldDouble *buildAreaAffinePoint() const
+ {
+ MCAuto<MEDCouplingFieldDouble> ret = self->buildAreaAffinePoint();
+ ret->incrRef();
+ return ret;
+ }
+
+ ShapeRecognMesh *recognize()
+ {
+ MCAuto<ShapeRecognMesh> ret = self->recognize();
+ return ret.retn();
+ }
}
};
--- /dev/null
+#! /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()