Some fixes

This commit is contained in:
jfa 2024-07-26 13:46:11 +01:00
parent 2a2216e5d2
commit 02ad02e211
5 changed files with 84 additions and 71 deletions

View File

@ -19,7 +19,7 @@
// File : HexahedronCanonicalShapesTest.cxx // File : HexahedronCanonicalShapesTest.cxx
// Module : SMESH // Module : SMESH
// Purpose: Implement unit tests for StdMeshers_Cartesian_3D_Hexahedron class to reproduce bugs that manifest in integration tests. // Purpose: Implement unit tests for StdMeshers_Cartesian_3D_Hexahedron class to reproduce bugs that manifest in integration tests.
// The main difference between this unit test and integration tests is the fine grained control we have over the class methods and the hability to diagnose/solve bugs before the code goes into production enviroment. // The main difference between this unit test and integration tests is the fine grained control we have over the class methods and the hability to diagnose/solve bugs before the code goes into production enviroment.
// This test class can be used as reference for the development of future tests in other stdMesh algorithms // This test class can be used as reference for the development of future tests in other stdMesh algorithms
#include "StdMeshers_Cartesian_3D_Hexahedron.hxx" #include "StdMeshers_Cartesian_3D_Hexahedron.hxx"
@ -28,7 +28,7 @@
// CPP TEST // CPP TEST
#include <cppunit/TestAssert.h> #include <cppunit/TestAssert.h>
// OCC // OCC
#include <BRep_Builder.hxx> #include <BRep_Builder.hxx>
#include <BRepTools.hxx> #include <BRepTools.hxx>
#include <BRepPrimAPI_MakeBox.hxx> #include <BRepPrimAPI_MakeBox.hxx>
@ -62,10 +62,10 @@ struct SMESH_Mesh_Test: public SMESH_Mesh
*/ */
struct CartesianHypo: public StdMeshers_CartesianParameters3D struct CartesianHypo: public StdMeshers_CartesianParameters3D
{ {
CartesianHypo() : StdMeshers_CartesianParameters3D(0/*zero hypoId*/, nullptr/*NULL generator*/) CartesianHypo() : StdMeshers_CartesianParameters3D(0/*zero hypoId*/, nullptr/*NULL generator*/)
{ {
} }
}; };
/*! /*!
* \brief Initialize the grid and intesersectors of grid with the geometry * \brief Initialize the grid and intesersectors of grid with the geometry
@ -73,7 +73,7 @@ struct CartesianHypo: public StdMeshers_CartesianParameters3D
void GridInitAndIntersectWithShape (Grid& grid, void GridInitAndIntersectWithShape (Grid& grid,
double gridSpacing, double gridSpacing,
double theSizeThreshold, double theSizeThreshold,
const TopoDS_Shape theShape, const TopoDS_Shape theShape,
TEdge2faceIDsMap& edge2faceIDsMap, TEdge2faceIDsMap& edge2faceIDsMap,
const int theNumOfThreads) const int theNumOfThreads)
{ {
@ -82,7 +82,7 @@ void GridInitAndIntersectWithShape (Grid& grid,
std::vector<std::string> grdSpace = { std::to_string(gridSpacing) }; std::vector<std::string> grdSpace = { std::to_string(gridSpacing) };
std::vector<double> intPnts; std::vector<double> intPnts;
std::unique_ptr<CartesianHypo> aHypo ( new CartesianHypo() ); std::unique_ptr<CartesianHypo> aHypo ( new CartesianHypo() );
aHypo->SetGridSpacing(grdSpace, intPnts, 0 ); // Spacing in dir 0 aHypo->SetGridSpacing(grdSpace, intPnts, 0 ); // Spacing in dir 0
aHypo->SetGridSpacing(grdSpace, intPnts, 1 ); // Spacing in dir 1 aHypo->SetGridSpacing(grdSpace, intPnts, 1 ); // Spacing in dir 1
aHypo->SetGridSpacing(grdSpace, intPnts, 2 ); // Spacing in dir 2 aHypo->SetGridSpacing(grdSpace, intPnts, 2 ); // Spacing in dir 2
@ -119,6 +119,9 @@ bool testShape (const TopoDS_Shape theShape,
GridInitAndIntersectWithShape( grid, theGridSpacing, theSizeThreshold, GridInitAndIntersectWithShape( grid, theGridSpacing, theSizeThreshold,
theShape, edge2faceIDsMap, 1 ); theShape, edge2faceIDsMap, 1 );
SMESH_subMesh * aSubMesh = aMesh->GetSubMesh(theShape);
aSubMesh->DependsOn(); // init sub-meshes
Hexahedron hex( &grid ); Hexahedron hex( &grid );
int nbAdded = hex.MakeElements( helper, edge2faceIDsMap, 1 ); int nbAdded = hex.MakeElements( helper, edge2faceIDsMap, 1 );
if (nbAdded != theNbCreatedExpected) { if (nbAdded != theNbCreatedExpected) {
@ -144,7 +147,7 @@ bool testPrimitives()
// Test fitting of a box // Test fitting of a box
BRepPrimAPI_MakeBox aMakeBox (10, 20, 30); BRepPrimAPI_MakeBox aMakeBox (10, 20, 30);
aMakeBox.Build(); aMakeBox.Build();
CPPUNIT_ASSERT_MESSAGE( "Could not create the box!", aMakeBox.IsDone() ); CPPUNIT_ASSERT_MESSAGE( "Could not create the box!", aMakeBox.IsDone() );
TopoDS_Shape aShape = aMakeBox.Shape(); TopoDS_Shape aShape = aMakeBox.Shape();
// Test exact fitting of a box // Test exact fitting of a box
@ -155,10 +158,9 @@ bool testPrimitives()
/*gridSpacing*/10, /*theSizeThreshold*/4, /*theNbCreatedExpected*/6)) /*gridSpacing*/10, /*theSizeThreshold*/4, /*theNbCreatedExpected*/6))
isOK = false; isOK = false;
// TODO: debug this case if (!testShape (aShape, /*toAddEdges*/false, /*toCreateFaces*/true,
//if (!testShape (aShape, /*toAddEdges*/false, /*toCreateFaces*/true, /*gridSpacing*/10, /*theSizeThreshold*/4, /*theNbCreatedExpected*/6))
// /*gridSpacing*/10, /*theSizeThreshold*/4, /*theNbCreatedExpected*/8)) isOK = false;
// isOK = false;
if (!testShape (aShape, /*toAddEdges*/false, /*toCreateFaces*/false, if (!testShape (aShape, /*toAddEdges*/false, /*toCreateFaces*/false,
/*gridSpacing*/5, /*theSizeThreshold*/4, /*theNbCreatedExpected*/48)) /*gridSpacing*/5, /*theSizeThreshold*/4, /*theNbCreatedExpected*/48))
@ -173,7 +175,7 @@ bool testPrimitives()
gp_Ax2 anAxes (gp::Origin(), gp::DZ()); gp_Ax2 anAxes (gp::Origin(), gp::DZ());
BRepPrimAPI_MakeCylinder aMakeCyl (anAxes, 20., 30.); BRepPrimAPI_MakeCylinder aMakeCyl (anAxes, 20., 30.);
aMakeCyl.Build(); aMakeCyl.Build();
CPPUNIT_ASSERT_MESSAGE( "Could not create the cylinder!", aMakeCyl.IsDone() ); CPPUNIT_ASSERT_MESSAGE( "Could not create the cylinder!", aMakeCyl.IsDone() );
aShape = aMakeCyl.Shape(); aShape = aMakeCyl.Shape();
// test for different threshold values // test for different threshold values
@ -187,7 +189,7 @@ bool testPrimitives()
// Test fitting of a sphere // Test fitting of a sphere
BRepPrimAPI_MakeSphere aMakeSph (anAxes, 30.); BRepPrimAPI_MakeSphere aMakeSph (anAxes, 30.);
aMakeSph.Build(); aMakeSph.Build();
CPPUNIT_ASSERT_MESSAGE( "Could not create the sphere!", aMakeSph.IsDone() ); CPPUNIT_ASSERT_MESSAGE( "Could not create the sphere!", aMakeSph.IsDone() );
aShape = aMakeSph.Shape(); aShape = aMakeSph.Shape();
// test for different threshold values // test for different threshold values
@ -201,7 +203,7 @@ bool testPrimitives()
// Test fitting of a cone // Test fitting of a cone
BRepPrimAPI_MakeCone aMakeCon (anAxes, 30., 0., 40.); BRepPrimAPI_MakeCone aMakeCon (anAxes, 30., 0., 40.);
aMakeCon.Build(); aMakeCon.Build();
CPPUNIT_ASSERT_MESSAGE( "Could not create the cone!", aMakeCon.IsDone() ); CPPUNIT_ASSERT_MESSAGE( "Could not create the cone!", aMakeCon.IsDone() );
aShape = aMakeCon.Shape(); aShape = aMakeCon.Shape();
// test for different threshold values // test for different threshold values
@ -218,7 +220,7 @@ bool testPrimitives()
// truncated cone // truncated cone
aMakeCon = BRepPrimAPI_MakeCone(anAxes, 30., 15., 20.); aMakeCon = BRepPrimAPI_MakeCone(anAxes, 30., 15., 20.);
aMakeCon.Build(); aMakeCon.Build();
CPPUNIT_ASSERT_MESSAGE( "Could not create the cone!", aMakeCon.IsDone() ); CPPUNIT_ASSERT_MESSAGE( "Could not create the cone!", aMakeCon.IsDone() );
aShape = aMakeCon.Shape(); aShape = aMakeCon.Shape();
// test for different threshold values // test for different threshold values

View File

@ -19,7 +19,7 @@
// File : HexahedronTest.cxx // File : HexahedronTest.cxx
// Module : SMESH // Module : SMESH
// Purpose: Implement unit tests for StdMeshers_Cartesian_3D_Hexahedron class to reproduce bugs that manifest in integration tests. // Purpose: Implement unit tests for StdMeshers_Cartesian_3D_Hexahedron class to reproduce bugs that manifest in integration tests.
// The main difference between this unit test and integration tests is the fine grained control we have over the class methods and the hability to diagnose/solve bugs before the code goes into production enviroment. // The main difference between this unit test and integration tests is the fine grained control we have over the class methods and the hability to diagnose/solve bugs before the code goes into production enviroment.
// This test class can be used as reference for the development of future tests in other stdMesh algorithms // This test class can be used as reference for the development of future tests in other stdMesh algorithms
#include "StdMeshers_Cartesian_3D_Hexahedron.hxx" #include "StdMeshers_Cartesian_3D_Hexahedron.hxx"
@ -28,7 +28,7 @@
// CPP TEST // CPP TEST
#include <cppunit/TestAssert.h> #include <cppunit/TestAssert.h>
// OCC // OCC
#include <BRep_Builder.hxx> #include <BRep_Builder.hxx>
#include <BRepTools.hxx> #include <BRepTools.hxx>
#include <BRepPrimAPI_MakeBox.hxx> #include <BRepPrimAPI_MakeBox.hxx>
@ -62,10 +62,10 @@ struct SMESH_Mesh_Test: public SMESH_Mesh
*/ */
struct CartesianHypo: public StdMeshers_CartesianParameters3D struct CartesianHypo: public StdMeshers_CartesianParameters3D
{ {
CartesianHypo() : StdMeshers_CartesianParameters3D(0/*zero hypoId*/, nullptr/*NULL generator*/) CartesianHypo() : StdMeshers_CartesianParameters3D(0/*zero hypoId*/, nullptr/*NULL generator*/)
{ {
} }
}; };
/*! /*!
* \brief Shape loader * \brief Shape loader
@ -73,7 +73,7 @@ struct CartesianHypo: public StdMeshers_CartesianParameters3D
void loadBrepShape( std::string shapeName, TopoDS_Shape & shape ) void loadBrepShape( std::string shapeName, TopoDS_Shape & shape )
{ {
BRep_Builder b; BRep_Builder b;
BRepTools::Read(shape, shapeName.c_str(), b); BRepTools::Read(shape, shapeName.c_str(), b);
} }
/*! /*!
@ -82,7 +82,7 @@ void loadBrepShape( std::string shapeName, TopoDS_Shape & shape )
void GridInitAndIntersectWithShape (Grid& grid, void GridInitAndIntersectWithShape (Grid& grid,
double gridSpacing, double gridSpacing,
double theSizeThreshold, double theSizeThreshold,
const TopoDS_Shape theShape, const TopoDS_Shape theShape,
TEdge2faceIDsMap& edge2faceIDsMap, TEdge2faceIDsMap& edge2faceIDsMap,
const int theNumOfThreads) const int theNumOfThreads)
{ {
@ -91,7 +91,7 @@ void GridInitAndIntersectWithShape (Grid& grid,
std::vector<std::string> grdSpace = { std::to_string(gridSpacing) }; std::vector<std::string> grdSpace = { std::to_string(gridSpacing) };
std::vector<double> intPnts; std::vector<double> intPnts;
std::unique_ptr<CartesianHypo> aHypo ( new CartesianHypo() ); std::unique_ptr<CartesianHypo> aHypo ( new CartesianHypo() );
aHypo->SetAxisDirs(axisDirs); aHypo->SetAxisDirs(axisDirs);
aHypo->SetGridSpacing(grdSpace, intPnts, 0 ); // Spacing in dir 0 aHypo->SetGridSpacing(grdSpace, intPnts, 0 ); // Spacing in dir 0
aHypo->SetGridSpacing(grdSpace, intPnts, 1 ); // Spacing in dir 1 aHypo->SetGridSpacing(grdSpace, intPnts, 1 ); // Spacing in dir 1
@ -108,7 +108,7 @@ bool testNRTM1()
{ {
TopoDS_Shape aShape; TopoDS_Shape aShape;
loadBrepShape( "data/HexahedronTest/NRTM1.brep", aShape ); loadBrepShape( "data/HexahedronTest/NRTM1.brep", aShape );
CPPUNIT_ASSERT_MESSAGE( "Could not load the brep shape!", !aShape.IsNull() ); CPPUNIT_ASSERT_MESSAGE( "Could not load the brep shape!", !aShape.IsNull() );
const auto numOfCores = std::thread::hardware_concurrency() == 0 ? 1 : std::thread::hardware_concurrency(); const auto numOfCores = std::thread::hardware_concurrency() == 0 ? 1 : std::thread::hardware_concurrency();
std::vector<int> numberOfThreads(numOfCores); std::vector<int> numberOfThreads(numOfCores);
@ -130,15 +130,18 @@ bool testNRTM1()
grid._toUseThresholdForInternalFaces = false; grid._toUseThresholdForInternalFaces = false;
grid._toUseQuanta = false; grid._toUseQuanta = false;
grid._sizeThreshold = 4.0; grid._sizeThreshold = 4.0;
TEdge2faceIDsMap edge2faceIDsMap; TEdge2faceIDsMap edge2faceIDsMap;
GridInitAndIntersectWithShape( grid, 1.0, 4.0, aShape, edge2faceIDsMap, nThreads ); GridInitAndIntersectWithShape( grid, 1.0, 4.0, aShape, edge2faceIDsMap, nThreads );
SMESH_subMesh * aSubMesh = aMesh->GetSubMesh(aShape);
aSubMesh->DependsOn(); // init sub-meshes
Hexahedron hex( &grid ); Hexahedron hex( &grid );
int nbAdded = hex.MakeElements( helper, edge2faceIDsMap, nThreads ); int nbAdded = hex.MakeElements( helper, edge2faceIDsMap, nThreads );
CPPUNIT_ASSERT_MESSAGE( "Number of computed elements does not match", nbAdded == 1024 ); CPPUNIT_ASSERT_MESSAGE( "Number of computed elements does not match", nbAdded == 1024 );
} }
} }
return true; return true;
} }
@ -149,7 +152,7 @@ bool testNRTJ4()
{ {
TopoDS_Shape aShape; TopoDS_Shape aShape;
loadBrepShape( "data/HexahedronTest/NRTMJ4.brep", aShape ); loadBrepShape( "data/HexahedronTest/NRTMJ4.brep", aShape );
CPPUNIT_ASSERT_MESSAGE( "Could not load the brep shape!", !aShape.IsNull() ); CPPUNIT_ASSERT_MESSAGE( "Could not load the brep shape!", !aShape.IsNull() );
const auto numOfCores = std::thread::hardware_concurrency() == 0 ? 1 : std::thread::hardware_concurrency()/2; const auto numOfCores = std::thread::hardware_concurrency() == 0 ? 1 : std::thread::hardware_concurrency()/2;
std::vector<int> numberOfThreads(numOfCores); std::vector<int> numberOfThreads(numOfCores);
@ -173,14 +176,19 @@ bool testNRTJ4()
double testThreshold = 1.000001; double testThreshold = 1.000001;
grid._toCreateFaces = true; grid._toCreateFaces = true;
grid._sizeThreshold = testThreshold; grid._sizeThreshold = testThreshold;
TEdge2faceIDsMap edge2faceIDsMap; TEdge2faceIDsMap edge2faceIDsMap;
GridInitAndIntersectWithShape( grid, 2.0, testThreshold, aShape, edge2faceIDsMap, nThreads ); GridInitAndIntersectWithShape( grid, 2.0, testThreshold,
aShape, edge2faceIDsMap, nThreads );
SMESH_subMesh * aSubMesh = aMesh->GetSubMesh(aShape);
aSubMesh->DependsOn(); // init sub-meshes
Hexahedron hex( &grid ); Hexahedron hex( &grid );
int nbAdded = hex.MakeElements( helper, edge2faceIDsMap, nThreads ); int nbAdded = hex.MakeElements( helper, edge2faceIDsMap, nThreads );
CPPUNIT_ASSERT_MESSAGE( "Number of computed elements does not match", nbAdded == 35150 ); CPPUNIT_ASSERT_MESSAGE( "Number of computed elements does not match", nbAdded == 35150 );
} }
} }
return true; return true;
} }

View File

@ -361,9 +361,13 @@ void StdMeshers_CartesianParameters3D::ComputeCoordinates(const double x0,
++iCell; ++iCell;
} }
} }
const double lastCellLen = coords.back() - coords[ coords.size() - 2 ]; if (coords.size() < 2)
if ( fabs( coords.back() - p1 ) > 0.5 * lastCellLen )
coords.push_back ( p1 ); coords.push_back ( p1 );
else {
const double lastCellLen = coords.back() - coords[ coords.size() - 2 ];
if ( fabs( coords.back() - p1 ) > 0.5 * lastCellLen )
coords.push_back ( p1 );
}
} }
// correct coords if a forced point is too close to a neighbor node // correct coords if a forced point is too close to a neighbor node

View File

@ -277,7 +277,7 @@ Hexahedron::Hexahedron(Grid* grid)
{ {
_polygons.reserve(100); // to avoid reallocation; _polygons.reserve(100); // to avoid reallocation;
//set nodes shift within grid->_nodes from the node 000 //set nodes shift within grid->_nodes from the node 000
size_t dx = _grid->NodeIndexDX(); size_t dx = _grid->NodeIndexDX();
size_t dy = _grid->NodeIndexDY(); size_t dy = _grid->NodeIndexDY();
size_t dz = _grid->NodeIndexDZ(); size_t dz = _grid->NodeIndexDZ();
@ -365,7 +365,7 @@ Hexahedron::Hexahedron( const Hexahedron& other, size_t i, size_t j, size_t k, i
tgtLink._link = _hexLinks + ( srcLink._link - other._hexLinks ); tgtLink._link = _hexLinks + ( srcLink._link - other._hexLinks );
} }
} }
if (SALOME::VerbosityActivated()) if (SALOME::VerbosityActivated())
_cellID = cellID; _cellID = cellID;
} }
@ -572,13 +572,13 @@ void Hexahedron::init( size_t i, size_t j, size_t k, const Solid* solid )
{ {
_hexNodes[iN]._isInternalFlags = 0; _hexNodes[iN]._isInternalFlags = 0;
// Grid node // Grid node
_hexNodes[iN]._node = _grid->_nodes [ _origNodeInd + _grid->_nodeShift[iN] ]; _hexNodes[iN]._node = _grid->_nodes [ _origNodeInd + _grid->_nodeShift[iN] ];
_hexNodes[iN]._intPoint = _grid->_gridIntP[ _origNodeInd + _grid->_nodeShift[iN] ]; _hexNodes[iN]._intPoint = _grid->_gridIntP[ _origNodeInd + _grid->_nodeShift[iN] ];
if ( _grid->_allBorderNodes[ _origNodeInd + _grid->_nodeShift[iN] ] ) if ( _grid->_allBorderNodes[ _origNodeInd + _grid->_nodeShift[iN] ] )
_hexNodes[iN]._boundaryCornerNode = _grid->_allBorderNodes [ _origNodeInd + _grid->_nodeShift[iN] ]; _hexNodes[iN]._boundaryCornerNode = _grid->_allBorderNodes [ _origNodeInd + _grid->_nodeShift[iN] ];
if ( _hexNodes[iN]._node && !solid->Contains( _hexNodes[iN]._node->GetShapeID() )) if ( _hexNodes[iN]._node && !solid->Contains( _hexNodes[iN]._node->GetShapeID() ))
_hexNodes[iN]._node = 0; _hexNodes[iN]._node = 0;
@ -1100,7 +1100,7 @@ size_t Hexahedron::findCoplanarPolygon
const size_t nbQuadPolygons, const size_t nbQuadPolygons,
std::vector< _OrientedLink* >& freeLinks, std::vector< _OrientedLink* >& freeLinks,
int& nbFreeLinks, int& nbFreeLinks,
const E_IntersectPoint ipTmp, const E_IntersectPoint& ipTmp,
std::set< StdMeshers::Cartesian3D::TGeomID >& usedFaceIDs, std::set< StdMeshers::Cartesian3D::TGeomID >& usedFaceIDs,
std::map< StdMeshers::Cartesian3D::TGeomID, std::vector< const B_IntersectPoint* > >& tmpAddedFace, std::map< StdMeshers::Cartesian3D::TGeomID, std::vector< const B_IntersectPoint* > >& tmpAddedFace,
const StdMeshers::Cartesian3D::TGeomID& curFace) const StdMeshers::Cartesian3D::TGeomID& curFace)
@ -1472,7 +1472,7 @@ bool Hexahedron::compute( const Solid* solid, const IsInternalFlag intFlag )
gp_XYZ uvwCenter = 0.5 * ( _grid->_coords[0][_i] + _grid->_coords[0][_i+1] ) * _grid->_axes[0] + gp_XYZ uvwCenter = 0.5 * ( _grid->_coords[0][_i] + _grid->_coords[0][_i+1] ) * _grid->_axes[0] +
0.5 * ( _grid->_coords[1][_j] + _grid->_coords[1][_j+1] ) * _grid->_axes[1] + 0.5 * ( _grid->_coords[1][_j] + _grid->_coords[1][_j+1] ) * _grid->_axes[1] +
0.5 * ( _grid->_coords[2][_k] + _grid->_coords[2][_k+1] ) * _grid->_axes[2]; 0.5 * ( _grid->_coords[2][_k] + _grid->_coords[2][_k+1] ) * _grid->_axes[2];
for ( size_t i = _polygons.size() - 1; _polygons[i]._name == SMESH_Block::ID_NONE; --i ) for ( size_t i = _polygons.size() - 1; _polygons[i]._name == SMESH_Block::ID_NONE; --i )
{ {
_Face& face = _polygons[ i ]; _Face& face = _polygons[ i ];
@ -1485,7 +1485,7 @@ bool Hexahedron::compute( const Solid* solid, const IsInternalFlag intFlag )
{ {
gp_XYZ p = SMESH_NodeXYZ( n->Node() ); gp_XYZ p = SMESH_NodeXYZ( n->Node() );
_grid->ComputeUVW( p, uvw.ChangeCoord().ChangeData() ); _grid->ComputeUVW( p, uvw.ChangeCoord().ChangeData() );
bb.Add( uvw ); bb.Add( uvw );
} }
} }
gp_Pnt pMin = bb.CornerMin(); gp_Pnt pMin = bb.CornerMin();
@ -1498,7 +1498,7 @@ bool Hexahedron::compute( const Solid* solid, const IsInternalFlag intFlag )
} }
} }
/* This call is irrelevant here because _volumeDefs datas were not filled! /* This call is irrelevant here because _volumeDefs datas were not filled!
or .... it is potentialy filled by other thread?? */ or .... it is potentialy filled by other thread?? */
_volumeDefs._nodes.clear(); _volumeDefs._nodes.clear();
_volumeDefs._quantities.clear(); _volumeDefs._quantities.clear();
@ -1553,8 +1553,8 @@ void computeHexa(Type& hex)
* \brief Create elements in the mesh * \brief Create elements in the mesh
*/ */
int Hexahedron::MakeElements(SMESH_MesherHelper& helper, int Hexahedron::MakeElements(SMESH_MesherHelper& helper,
const map< TGeomID, vector< TGeomID > >& edge2faceIDsMap, const map< TGeomID, vector< TGeomID > >& edge2faceIDsMap,
const int numOfThreads ) const int numOfThreads )
{ {
SMESHDS_Mesh* mesh = helper.GetMeshDS(); SMESHDS_Mesh* mesh = helper.GetMeshDS();
@ -1604,7 +1604,7 @@ int Hexahedron::MakeElements(SMESH_MesherHelper& helper,
TGeomID solidIDs[20]; TGeomID solidIDs[20];
vector< Hexahedron* > intHexa; intHexa.reserve( nbIntHex ); vector< Hexahedron* > intHexa; intHexa.reserve( nbIntHex );
vector< const SMDS_MeshElement* > boundaryVolumes; boundaryVolumes.reserve( nbIntHex * 1.1 ); vector< const SMDS_MeshElement* > boundaryVolumes; boundaryVolumes.reserve( nbIntHex * 1.1 );
for ( size_t i = 0; i < allHexa.size(); ++i ) for ( size_t i = 0; i < allHexa.size(); ++i )
{ {
// initialize this by not cut allHexa[ i ] // initialize this by not cut allHexa[ i ]
@ -1660,10 +1660,10 @@ int Hexahedron::MakeElements(SMESH_MesherHelper& helper,
intHexa.push_back( hex ); intHexa.push_back( hex );
} }
} }
// compute definitions of volumes resulted from hexadron intersection // compute definitions of volumes resulted from hexadron intersection
#ifdef WITH_TBB #ifdef WITH_TBB
parallel_for(intHexa.begin(), intHexa.end(), computeHexa<Hexahedron*>, numOfThreads ); parallel_for(intHexa.begin(), intHexa.end(), computeHexa<Hexahedron*>, numOfThreads );
#else #else
for ( size_t i = 0; i < intHexa.size(); ++i ) for ( size_t i = 0; i < intHexa.size(); ++i )
if ( Hexahedron * hex = intHexa[ i ] ) if ( Hexahedron * hex = intHexa[ i ] )
@ -1686,7 +1686,7 @@ int Hexahedron::MakeElements(SMESH_MesherHelper& helper,
for ( size_t i = 0; i < intHexa.size(); ++i ) for ( size_t i = 0; i < intHexa.size(); ++i )
if ( Hexahedron * hex = intHexa[ i ] ) if ( Hexahedron * hex = intHexa[ i ] )
nbAdded += hex->addVolumes( helper ); nbAdded += hex->addVolumes( helper );
// fill boundaryVolumes with volumes neighboring too small skipped volumes // fill boundaryVolumes with volumes neighboring too small skipped volumes
if ( _grid->_toCreateFaces ) if ( _grid->_toCreateFaces )
{ {
@ -2586,7 +2586,7 @@ bool Hexahedron::isOutPoint( _Link& link, int iP,
GeomAPI_ProjectPointOnSurf& proj = helper.GetProjector( face, loc, 0.1*_grid->_tol ); GeomAPI_ProjectPointOnSurf& proj = helper.GetProjector( face, loc, 0.1*_grid->_tol );
gp_Pnt testPnt = pOnLink.Transformed( loc.Transformation().Inverted() ); gp_Pnt testPnt = pOnLink.Transformed( loc.Transformation().Inverted() );
proj.Perform( testPnt ); proj.Perform( testPnt );
if ( proj.IsDone() && proj.NbPoints() > 0 ) if ( proj.IsDone() && proj.NbPoints() > 0 )
{ {
Standard_Real u,v; Standard_Real u,v;
proj.LowerDistanceParameters( u,v ); proj.LowerDistanceParameters( u,v );
@ -2807,9 +2807,9 @@ int Hexahedron::addVolumes( SMESH_MesherHelper& helper )
} }
} // loop to get nodes } // loop to get nodes
const SMDS_MeshElement* v = 0; const SMDS_MeshElement* v = 0;
if ( !volDef->_quantities.empty() ) if ( !volDef->_quantities.empty() )
{ {
if ( !useQuanta ) if ( !useQuanta )
{ {
// split polyhedrons of with disjoint volumes // split polyhedrons of with disjoint volumes
@ -2834,13 +2834,12 @@ int Hexahedron::addVolumes( SMESH_MesherHelper& helper )
{ {
const double quanta = _grid->_quanta; const double quanta = _grid->_quanta;
double polyVol = volDef->_size; double polyVol = volDef->_size;
double hexaVolume = _sideLength[0] * _sideLength[1] * _sideLength[2]; double hexaVolume = _sideLength[0] * _sideLength[1] * _sideLength[2];
if ( hexaVolume > 0.0 && polyVol/hexaVolume >= quanta /*set the volume if the relation is satisfied*/) if ( hexaVolume > 0.0 && polyVol/hexaVolume >= quanta /*set the volume if the relation is satisfied*/)
v = helper.AddVolume( _hexNodes[0].BoundaryNode(), _hexNodes[2].BoundaryNode(), v = helper.AddVolume( _hexNodes[0].BoundaryNode(), _hexNodes[2].BoundaryNode(),
_hexNodes[3].BoundaryNode(), _hexNodes[1].BoundaryNode(), _hexNodes[3].BoundaryNode(), _hexNodes[1].BoundaryNode(),
_hexNodes[4].BoundaryNode(), _hexNodes[6].BoundaryNode(), _hexNodes[4].BoundaryNode(), _hexNodes[6].BoundaryNode(),
_hexNodes[7].BoundaryNode(), _hexNodes[5].BoundaryNode() ); _hexNodes[7].BoundaryNode(), _hexNodes[5].BoundaryNode() );
} }
} }
else else
@ -3062,9 +3061,9 @@ bool Hexahedron::checkPolyhedronSize( bool cutByInternalFace, double & volume) c
* In case more than one polyhedron is detected. The function return the set of quantities and nodes defining separates elements. * In case more than one polyhedron is detected. The function return the set of quantities and nodes defining separates elements.
* Reference to issue #bos[38521][EDF] Generate polyhedron with separate volume. * Reference to issue #bos[38521][EDF] Generate polyhedron with separate volume.
*/ */
int Hexahedron::checkPolyhedronValidity( _volumeDef* volDef, std::vector<std::vector<int>>& splitQuantities, int Hexahedron::checkPolyhedronValidity( _volumeDef* volDef, std::vector<std::vector<int>>& splitQuantities,
std::vector<std::vector<const SMDS_MeshNode*>>& splitNodes ) std::vector<std::vector<const SMDS_MeshNode*>>& splitNodes )
{ {
int mySet = 1; int mySet = 1;
std::map<int,int> numberOfSets; // define set id with the number of faces associated! std::map<int,int> numberOfSets; // define set id with the number of faces associated!
if ( !volDef->_quantities.empty() ) if ( !volDef->_quantities.empty() )
@ -3084,7 +3083,7 @@ int Hexahedron::checkPolyhedronValidity( _volumeDef* volDef, std::vector<std::ve
elementSet.insert( volDef->_nodes[ n ].Node()->GetID() ); elementSet.insert( volDef->_nodes[ n ].Node()->GetID() );
splitNodes.back().push_back( volDef->_nodes[ n ].Node() ); splitNodes.back().push_back( volDef->_nodes[ n ].Node() );
} }
numberOfSets.insert( std::pair<int,int>(mySet,1) ); numberOfSets.insert( std::pair<int,int>(mySet,1) );
while ( connectedFaces != allFaces.size() ) while ( connectedFaces != allFaces.size() )
{ {
@ -3099,7 +3098,7 @@ int Hexahedron::checkPolyhedronValidity( _volumeDef* volDef, std::vector<std::ve
for (int n = 0; n < connectivity[ innerId ]; n++) for (int n = 0; n < connectivity[ innerId ]; n++)
{ {
int nodeId = volDef->_nodes[ accum + n ].Node()->GetID(); int nodeId = volDef->_nodes[ accum + n ].Node()->GetID();
if ( elementSet.count( nodeId ) != 0 ) if ( elementSet.count( nodeId ) != 0 )
faceCounter++; faceCounter++;
} }
if ( faceCounter >= 2 ) // found coincidences nodes if ( faceCounter >= 2 ) // found coincidences nodes
@ -3158,17 +3157,17 @@ int Hexahedron::checkPolyhedronValidity( _volumeDef* volDef, std::vector<std::ve
if ( k.second <= 2 ) if ( k.second <= 2 )
allMoreThan2Faces &= false; allMoreThan2Faces &= false;
} }
if ( allMoreThan2Faces ) if ( allMoreThan2Faces )
{ {
// The separate objects are suspect to be closed // The separate objects are suspect to be closed
return numberOfSets.size(); return numberOfSets.size();
} }
else else
{ {
// Have to index the last face nodes to the final set // Have to index the last face nodes to the final set
// contrary case return as it were a valid polyhedron for backward compatibility // contrary case return as it were a valid polyhedron for backward compatibility
return 1; return 1;
} }
} }
} }
@ -3180,7 +3179,7 @@ int Hexahedron::checkPolyhedronValidity( _volumeDef* volDef, std::vector<std::ve
/*! /*!
* \brief add original or separated polyhedrons to the mesh * \brief add original or separated polyhedrons to the mesh
*/ */
const SMDS_MeshElement* Hexahedron::addPolyhedronToMesh( _volumeDef* volDef, SMESH_MesherHelper& helper, const std::vector<const SMDS_MeshNode*>& nodes, const SMDS_MeshElement* Hexahedron::addPolyhedronToMesh( _volumeDef* volDef, SMESH_MesherHelper& helper, const std::vector<const SMDS_MeshNode*>& nodes,
const std::vector<int>& quantities ) const std::vector<int>& quantities )
{ {
const SMDS_MeshElement* v = helper.AddPolyhedralVolume( nodes, quantities ); const SMDS_MeshElement* v = helper.AddPolyhedralVolume( nodes, quantities );
@ -3471,10 +3470,10 @@ void Hexahedron::addFaces( SMESH_MesherHelper& helper,
SMESH_MeshEditor::ElemFeatures face( SMDSAbs_Face ); SMESH_MeshEditor::ElemFeatures face( SMDSAbs_Face );
SMESHDS_Mesh* meshDS = helper.GetMeshDS(); SMESHDS_Mesh* meshDS = helper.GetMeshDS();
bool isQuantaSet = _grid->_toUseQuanta; bool isQuantaSet = _grid->_toUseQuanta;
// check if there are internal or shared FACEs // check if there are internal or shared FACEs
bool hasInternal = ( !_grid->_geometry.IsOneSolid() || bool hasInternal = ( !_grid->_geometry.IsOneSolid() ||
_grid->_geometry._soleSolid.HasInternalFaces() ); _grid->_geometry._soleSolid.HasInternalFaces() );
for ( size_t iV = 0; iV < boundaryVolumes.size(); ++iV ) for ( size_t iV = 0; iV < boundaryVolumes.size(); ++iV )
{ {
@ -3727,7 +3726,7 @@ void Hexahedron::getBoundaryElems( vector< const SMDS_MeshElement* > & boundaryE
if ( _grid->IsInternal( faceID ) || if ( _grid->IsInternal( faceID ) ||
_grid->IsShared( faceID ) //|| _grid->IsShared( faceID ) //||
//_grid->IsBoundaryFace( faceID ) -- commented for #19887 //_grid->IsBoundaryFace( faceID ) -- commented for #19887
) )
break; // create only if a new face will be used by other 3D algo break; // create only if a new face will be used by other 3D algo
} }
@ -3761,7 +3760,7 @@ void Hexahedron::getBoundaryElems( vector< const SMDS_MeshElement* > & boundaryE
{ {
_bro->setIsMarked( true ); _bro->setIsMarked( true );
boundaryElems.push_back( _bro ); boundaryElems.push_back( _bro );
} }
} }
} }
} }
@ -3778,7 +3777,7 @@ void Hexahedron::removeExcessSideDivision(const vector< Hexahedron* >& allHexa)
{ {
if ( ! _volumeDefs.IsPolyhedron() ) if ( ! _volumeDefs.IsPolyhedron() )
return; // not a polyhedron return; // not a polyhedron
// look for a divided side adjacent to a small hexahedron // look for a divided side adjacent to a small hexahedron
int di[6] = { 0, 0, 0, 0,-1, 1 }; int di[6] = { 0, 0, 0, 0,-1, 1 };

View File

@ -24,7 +24,7 @@
#ifndef _SMESH_Cartesian_3D_HEXAHEDRON_HXX_ #ifndef _SMESH_Cartesian_3D_HEXAHEDRON_HXX_
#define _SMESH_Cartesian_3D_HEXAHEDRON_HXX_ #define _SMESH_Cartesian_3D_HEXAHEDRON_HXX_
// BOOST // BOOST
#include <boost/container/flat_map.hpp> #include <boost/container/flat_map.hpp>
// STD // STD
@ -107,7 +107,7 @@ namespace Cartesian3D
char _isInternalFlags; char _isInternalFlags;
_Node(const SMDS_MeshNode* n=0, const StdMeshers::Cartesian3D::B_IntersectPoint* ip=0) _Node(const SMDS_MeshNode* n=0, const StdMeshers::Cartesian3D::B_IntersectPoint* ip=0)
:_node(n), _intPoint(ip), _usedInFace(0), _isInternalFlags(0) {} :_node(n), _boundaryCornerNode(0), _intPoint(ip), _usedInFace(0), _isInternalFlags(0) {}
const SMDS_MeshNode* Node() const const SMDS_MeshNode* Node() const
{ return ( _intPoint && _intPoint->_node ) ? _intPoint->_node : _node; } { return ( _intPoint && _intPoint->_node ) ? _intPoint->_node : _node; }
const SMDS_MeshNode* BoundaryNode() const const SMDS_MeshNode* BoundaryNode() const
@ -166,7 +166,7 @@ namespace Cartesian3D
std::vector< const StdMeshers::Cartesian3D::F_IntersectPoint* > _fIntPoints; // GridLine intersections with FACEs std::vector< const StdMeshers::Cartesian3D::F_IntersectPoint* > _fIntPoints; // GridLine intersections with FACEs
std::vector< _Node* > _fIntNodes; // _Node's at _fIntPoints std::vector< _Node* > _fIntNodes; // _Node's at _fIntPoints
std::vector< _Link > _splits; std::vector< _Link > _splits;
_Link(): _faces{ 0, 0 } {} _Link(): _nodes{ 0, 0 }, _faces{ 0, 0 } {}
}; };
// -------------------------------------------------------------------------------- // --------------------------------------------------------------------------------
@ -337,7 +337,7 @@ namespace Cartesian3D
StdMeshers::Cartesian3D::TGeomID _solidID; StdMeshers::Cartesian3D::TGeomID _solidID;
double _size; double _size;
const SMDS_MeshElement* _volume; // new volume const SMDS_MeshElement* _volume; // new volume
std::vector<const SMDS_MeshElement*> _brotherVolume; // produced due to poly split std::vector<const SMDS_MeshElement*> _brotherVolume; // produced due to poly split
std::vector< SMESH_Block::TShapeID > _names; // name of side a polygon originates from std::vector< SMESH_Block::TShapeID > _names; // name of side a polygon originates from
_volumeDef(): _next(0), _solidID(0), _size(0), _volume(0) {} _volumeDef(): _next(0), _solidID(0), _size(0), _volume(0) {}
@ -460,7 +460,7 @@ namespace Cartesian3D
const size_t nbQuadPolygons, const size_t nbQuadPolygons,
std::vector< _OrientedLink* >& freeLinks, std::vector< _OrientedLink* >& freeLinks,
int& nbFreeLinks, int& nbFreeLinks,
const E_IntersectPoint ipTmp, const E_IntersectPoint& ipTmp,
std::set< StdMeshers::Cartesian3D::TGeomID >& usedFaceIDs, std::set< StdMeshers::Cartesian3D::TGeomID >& usedFaceIDs,
std::map< StdMeshers::Cartesian3D::TGeomID, std::vector< const B_IntersectPoint* > >& tmpAddedFace, std::map< StdMeshers::Cartesian3D::TGeomID, std::vector< const B_IntersectPoint* > >& tmpAddedFace,
const StdMeshers::Cartesian3D::TGeomID& curFace); const StdMeshers::Cartesian3D::TGeomID& curFace);
@ -485,7 +485,7 @@ namespace Cartesian3D
bool isInHole() const; bool isInHole() const;
bool hasStrangeEdge() const; bool hasStrangeEdge() const;
bool checkPolyhedronSize( bool isCutByInternalFace, double & volSize ) const; bool checkPolyhedronSize( bool isCutByInternalFace, double & volSize ) const;
int checkPolyhedronValidity( _volumeDef* volDef, std::vector<std::vector<int>>& splitQuantities, int checkPolyhedronValidity( _volumeDef* volDef, std::vector<std::vector<int>>& splitQuantities,
std::vector<std::vector<const SMDS_MeshNode*>>& splitNodes ); std::vector<std::vector<const SMDS_MeshNode*>>& splitNodes );
const SMDS_MeshElement* addPolyhedronToMesh( _volumeDef* volDef, const SMDS_MeshElement* addPolyhedronToMesh( _volumeDef* volDef,
SMESH_MesherHelper& helper, SMESH_MesherHelper& helper,