#include "SMDS_VolumeTool.hxx"
#include "SMDS_VolumeOfNodes.hxx"
#include "SMDS_EdgePosition.hxx"
+#include "SMESH_Comment.hxx"
#include "utilities.h"
-#include <BRepAdaptor_Curve.hxx>
-#include <BRepAdaptor_Curve2d.hxx>
-#include <BRep_Builder.hxx>
#include <BRep_Tool.hxx>
#include <Geom2dAdaptor_Curve.hxx>
#include <Geom2d_Line.hxx>
+#include <TopExp.hxx>
+#include <TopExp_Explorer.hxx>
#include <TopTools_ListIteratorOfListOfShape.hxx>
+#include <TopoDS.hxx>
using namespace std;
-#define RETURN_BAD_RESULT(msg) { MESSAGE(msg); return false; }
+#define RETURN_BAD_RESULT(msg) { MESSAGE(")-: Error: " << msg); return false; }
#define gpXYZ(n) gp_XYZ(n->X(),n->Y(),n->Z())
#define SHOWYXZ(msg, xyz) // {\
// gp_Pnt p (xyz); \
// }
typedef StdMeshers_ProjectionUtils TAssocTool;
+typedef SMESH_Comment TCom;
enum { ID_BOT_FACE = SMESH_Block::ID_Fxy0,
ID_TOP_FACE = SMESH_Block::ID_Fxy1,
const SMDS_MeshNode* & node1,
const SMDS_MeshNode* & node2)
{
- if ( param == 1.0 || column->size() == 1) {
+ if ( param >= 1.0 || column->size() == 1) {
node1 = node2 = column->back();
return 0;
}
SMESH_Hypothesis::Hypothesis_Status& aStatus)
{
// Check shape geometry
-
+/* PAL16229
aStatus = SMESH_Hypothesis::HYP_BAD_GEOMETRY;
// find not quadrangle faces
if ( nbFace != nbEdge + 2 )
RETURN_BAD_RESULT("Bad nb of faces: " << nbFace << " but must be " << nbEdge + 2);
}
-
+*/
// no hypothesis
aStatus = SMESH_Hypothesis::HYP_OK;
return true;
bool StdMeshers_Prism_3D::Compute(SMESH_Mesh& theMesh, const TopoDS_Shape& theShape)
{
- myHelper = new SMESH_MesherHelper( theMesh );
- // to delete helper at exit from Compute()
- std::auto_ptr<SMESH_MesherHelper> helperDeleter( myHelper );
+ SMESH_MesherHelper helper( theMesh );
+ myHelper = &helper;
myHelper->IsQuadraticSubMesh( theShape );
// Analyse mesh and geomerty to find block subshapes and submeshes
if ( !myBlock.Init( myHelper, theShape ))
- return false;
+ return error( myBlock.GetError());
SMESHDS_Mesh* meshDS = theMesh.GetMeshDS();
TNodeColumn& column = bot_column->second;
// bottom node parameters and coords
- gp_XYZ botParams = tBotNode.GetParams();
myShapeXYZ[ ID_BOT_FACE ] = tBotNode.GetCoords();
+ gp_XYZ botParams = tBotNode.GetParams();
// compute top node parameters
- gp_XYZ topParams;
myShapeXYZ[ ID_TOP_FACE ] = gpXYZ( column.back() );
- gp_Pnt topCoords = myShapeXYZ[ ID_TOP_FACE ];
- if ( !myBlock.ComputeParameters( topCoords, topParams, ID_TOP_FACE ))
- RETURN_BAD_RESULT("ComputeParameters() on the top face failed");
+ gp_XYZ topParams = botParams;
+ topParams.SetZ( 1 );
+ if ( column.size() > 2 ) {
+ gp_Pnt topCoords = myShapeXYZ[ ID_TOP_FACE ];
+ if ( !myBlock.ComputeParameters( topCoords, topParams, ID_TOP_FACE, topParams ))
+ return error(TCom("Can't compute normalized parameters ")
+ << "for node " << column.back()->GetID()
+ << " on the face #"<< column.back()->GetPosition()->GetShapeId() );
+ }
// vertical loop
TNodeColumn::iterator columnNodes = column.begin();
// compute coords for a new node
gp_XYZ coords;
if ( !SMESH_Block::ShellPoint( params, myShapeXYZ, coords ))
- RETURN_BAD_RESULT("SMESH_Block::ShellPoint() failed");
+ return error("Can't compute coordinates by normalized parameters");
+
+ SHOWYXZ("TOPFacePoint ",myShapeXYZ[ ID_TOP_FACE]);
+ SHOWYXZ("BOT Node "<< tBotNode.myNode->GetID(),gpXYZ(tBotNode.myNode));
+ SHOWYXZ("ShellPoint ",coords);
// create a node
node = meshDS->AddNode( coords.X(), coords.Y(), coords.Z() );
// Create volumes
SMESHDS_SubMesh* smDS = myBlock.SubMeshDS( ID_BOT_FACE );
- if ( !smDS ) RETURN_BAD_RESULT("Null submesh");
+ if ( !smDS ) return error(COMPERR_BAD_INPUT_MESH, "Null submesh");
// loop on bottom mesh faces
SMDS_ElemIteratorPtr faceIt = smDS->GetElements();
if ( n->GetPosition()->GetTypeOfPosition() == SMDS_TOP_FACE ) {
bot_column = myBotToColumnMap.find( n );
if ( bot_column == myBotToColumnMap.end() )
- RETURN_BAD_RESULT(" node column for a node not found");
+ return error(TCom("No nodes found above node ") << n->GetID() );
columns[ i ] = & bot_column->second;
}
else {
columns[ i ] = myBlock.GetNodeColumn( n );
if ( !columns[ i ] )
- RETURN_BAD_RESULT(" node column not found for a node " << n->GetID() );
+ return error(TCom("No side nodes found above node ") << n->GetID() );
}
}
// create prisms
int shapeID = helper->GetSubShapeID();
int nbNodes = columns.size();
+ int nbZ = columns[0]->size();
+ if ( nbZ < 2 ) return;
+
+ // find out orientation
+ bool isForward = true;
+ SMDS_VolumeTool vTool;
+ int z = 1;
+ switch ( nbNodes ) {
+ case 3: {
+ const SMDS_MeshNode* botNodes[3] = { (*columns[0])[z-1],
+ (*columns[1])[z-1],
+ (*columns[2])[z-1] };
+ const SMDS_MeshNode* topNodes[3] = { (*columns[0])[z],
+ (*columns[1])[z],
+ (*columns[2])[z] };
+ SMDS_VolumeOfNodes tmpVol ( botNodes[0], botNodes[1], botNodes[2],
+ topNodes[0], topNodes[1], topNodes[2]);
+ vTool.Set( &tmpVol );
+ isForward = vTool.IsForward();
+ break;
+ }
+ case 4: {
+ const SMDS_MeshNode* botNodes[4] = { (*columns[0])[z-1], (*columns[1])[z-1],
+ (*columns[2])[z-1], (*columns[3])[z-1] };
+ const SMDS_MeshNode* topNodes[4] = { (*columns[0])[z], (*columns[1])[z],
+ (*columns[2])[z], (*columns[3])[z] };
+ SMDS_VolumeOfNodes tmpVol ( botNodes[0], botNodes[1], botNodes[2], botNodes[3],
+ topNodes[0], topNodes[1], topNodes[2], topNodes[3]);
+ vTool.Set( &tmpVol );
+ isForward = vTool.IsForward();
+ break;
+ }
+ }
// vertical loop on columns
- for ( int z = 1; z < columns[0]->size(); ++z)
+ for ( z = 1; z < nbZ; ++z )
{
SMDS_MeshElement* vol = 0;
- SMDS_VolumeTool vTool;
switch ( nbNodes ) {
case 3: {
const SMDS_MeshNode* topNodes[3] = { (*columns[0])[z],
(*columns[1])[z],
(*columns[2])[z] };
- // assure good orientation
- SMDS_VolumeOfNodes tmpVol ( botNodes[0], botNodes[1], botNodes[2],
- topNodes[0], topNodes[1], topNodes[2]);
- vTool.Set( &tmpVol );
- if ( vTool.IsForward() )
+ if ( isForward )
vol = helper->AddVolume( botNodes[0], botNodes[1], botNodes[2],
topNodes[0], topNodes[1], topNodes[2]);
else
(*columns[2])[z-1], (*columns[3])[z-1] };
const SMDS_MeshNode* topNodes[4] = { (*columns[0])[z], (*columns[1])[z],
(*columns[2])[z], (*columns[3])[z] };
- // assure good orientation
- SMDS_VolumeOfNodes tmpVol ( botNodes[0], botNodes[1], botNodes[2], botNodes[3],
- topNodes[0], topNodes[1], topNodes[2], topNodes[3]);
- vTool.Set( &tmpVol );
- if ( vTool.IsForward() )
+ if ( isForward )
vol = helper->AddVolume( botNodes[0], botNodes[1], botNodes[2], botNodes[3],
topNodes[0], topNodes[1], topNodes[2], topNodes[3]);
else
SMESHDS_SubMesh * topSMDS = topSM->GetSubMeshDS();
if ( !botSMDS || botSMDS->NbElements() == 0 )
- RETURN_BAD_RESULT("Empty horiz submesh");
+ return error(TCom("No elememts on face #") << botSM->GetId());
bool needProject = false;
if ( !topSMDS ||
botSMDS->NbNodes() != topSMDS->NbNodes())
{
if ( myBlock.HasNotQuadElemOnTop() )
- RETURN_BAD_RESULT("Different triangles on 2 sides");
+ return error(TCom("Mesh on faces #") << botSM->GetId()
+ <<" and #"<< topSM->GetId() << " seems different" );
needProject = true;
}
if ( 0/*needProject && !myProjectTriangles*/ )
- RETURN_BAD_RESULT("Need to project but not allowed");
+ return error(TCom("Mesh on faces #") << botSM->GetId()
+ <<" and #"<< topSM->GetId() << " seems different" );
+ ///RETURN_BAD_RESULT("Need to project but not allowed");
if ( needProject )
{
if ( !TAssocTool::FindSubShapeAssociation( botFace, myBlock.Mesh(),
topFace, myBlock.Mesh(),
shape2ShapeMap) )
- RETURN_BAD_RESULT("FindSubShapeAssociation failed");
+ return error(TCom("Topology of faces #") << botSM->GetId()
+ <<" and #"<< topSM->GetId() << " seems different" );
- // Find matching nodes of in and out faces
+ // Find matching nodes of top and bottom faces
TNodeNodeMap n2nMap;
if ( ! TAssocTool::FindMatchingNodesOnFaces( botFace, myBlock.Mesh(),
topFace, myBlock.Mesh(),
shape2ShapeMap, n2nMap ))
- RETURN_BAD_RESULT("Different mesh on top and bottom faces");
+ return error(TCom("Mesh on faces #") << botSM->GetId()
+ <<" and #"<< topSM->GetId() << " seems different" );
// Fill myBotToColumnMap
int zSize = myBlock.VerticalSize();
+ TNode prevTNode;
TNodeNodeMap::iterator bN_tN = n2nMap.begin();
for ( ; bN_tN != n2nMap.end(); ++bN_tN )
{
continue; // wall columns are contained in myBlock
// compute bottom node params
TNode bN( botNode );
- if ( !myBlock.ComputeParameters( bN.GetCoords(), bN.ChangeParams(), ID_BOT_FACE ))
- RETURN_BAD_RESULT("ComputeParameters() on the bottom face failed");
+ if ( zSize > 2 ) {
+ gp_XYZ paramHint(-1,-1,-1);
+ if ( prevTNode.IsNeighbor( bN ))
+ paramHint = prevTNode.GetParams();
+ if ( !myBlock.ComputeParameters( bN.GetCoords(), bN.ChangeParams(),
+ ID_BOT_FACE, paramHint ))
+ return error(TCom("Can't compute normalized parameters for node ")
+ << botNode->GetID() << " on the face #"<< botSM->GetId() );
+ prevTNode = bN;
+ }
// create node column
TNode2ColumnMap::iterator bN_col =
myBotToColumnMap.insert( make_pair ( bN, TNodeColumn() )).first;
// Fill myBotToColumnMap
int zSize = myBlock.VerticalSize();
+ TNode prevTNode;
SMDS_NodeIteratorPtr nIt = botSMDS->GetNodes();
while ( nIt->more() )
{
continue; // strange
// compute bottom node params
TNode bN( botNode );
- if ( !myBlock.ComputeParameters( bN.GetCoords(), bN.ChangeParams(), ID_BOT_FACE ))
- RETURN_BAD_RESULT("ComputeParameters() on the bottom face failed");
+ gp_XYZ paramHint(-1,-1,-1);
+ if ( prevTNode.IsNeighbor( bN ))
+ paramHint = prevTNode.GetParams();
+ if ( !myBlock.ComputeParameters( bN.GetCoords(), bN.ChangeParams(),
+ ID_BOT_FACE, paramHint ))
+ return error(TCom("Can't compute normalized parameters for node ")
+ << botNode->GetID() << " on the face #"<< botSM->GetId() );
+ prevTNode = bN;
// compute top node coords
gp_XYZ topXYZ; gp_XY topUV;
if ( !myBlock.FacePoint( ID_TOP_FACE, bN.GetParams(), topXYZ ) ||
!myBlock.FaceUV ( ID_TOP_FACE, bN.GetParams(), topUV ))
- RETURN_BAD_RESULT("SMESH_Block::FacePoint() on the top face failed");
+ return error(TCom("Can't compute coordinates "
+ "by normalized parameters on the face #")<< topSM->GetId() );
SMDS_MeshNode * topNode = meshDS->AddNode( topXYZ.X(),topXYZ.Y(),topXYZ.Z() );
meshDS->SetNodeOnFace( topNode, topFaceID, topUV.X(), topUV.Y() );
// create node column
if ( n->GetPosition()->GetTypeOfPosition() == SMDS_TOP_FACE ) {
TNode2ColumnMap::iterator bot_column = myBotToColumnMap.find( n );
if ( bot_column == myBotToColumnMap.end() )
- RETURN_BAD_RESULT(" node column for a node not found");
+ return error(TCom("No nodes found above node ") << n->GetID() );
nodes[ i ] = bot_column->second.back();
}
else {
const TNodeColumn* column = myBlock.GetNodeColumn( n );
if ( !column )
- RETURN_BAD_RESULT(" node column not found for a node " << n->GetID() );
+ return error(TCom("No side nodes found above node ") << n->GetID() );
nodes[ i ] = column->back();
}
}
return true;
}
+//================================================================================
+/*!
+ * \brief Return true if this node and other one belong to one face
+ */
+//================================================================================
+
+bool TNode::IsNeighbor( const TNode& other ) const
+{
+ if ( !other.myNode || !myNode ) return false;
+
+ SMDS_ElemIteratorPtr fIt = other.myNode->GetInverseElementIterator(SMDSAbs_Face);
+ while ( fIt->more() )
+ if ( fIt->next()->GetNodeIndex( myNode ) >= 0 )
+ return true;
+ return false;
+}
+
//================================================================================
/*!
* \brief Constructor. Initialization is needed
mySide = new TSideFace( sideFaces, params );
myHelper = helper;
- SMESHDS_Mesh* meshDS = myHelper->GetMesh()->GetMeshDS();
+ SMESHDS_Mesh* meshDS = myHelper->GetMeshDS();
SMESH_Block::init();
myShapeIDMap.Clear();
SMESH_Block::ID_Fx1z, SMESH_Block::ID_F0yz
};
+ myError = SMESH_ComputeError::New();
+
// -------------------------------------------------------------
// Look for top and bottom faces: not quadrangle ones or meshed
// with not quadrangle elements
int nbFaces = 0;
//
SMESH_subMesh* mainSubMesh = myHelper->GetMesh()->GetSubMeshContaining( shape3D );
- if ( !mainSubMesh ) RETURN_BAD_RESULT("Null submesh of shape3D");
- //
- const map< int, SMESH_subMesh * >& subSM = mainSubMesh->DependsOn();
- map< int, SMESH_subMesh * >::const_iterator i_subSM = subSM.begin();
- for ( ; i_subSM != subSM.end(); ++i_subSM )
+ if ( !mainSubMesh ) return error(COMPERR_BAD_INPUT_MESH,"Null submesh of shape3D");
+
+ // analyse face submeshes
+ SMESH_subMeshIteratorPtr smIt = mainSubMesh->getDependsOnIterator(false,false);
+ while ( smIt->more() )
{
- SMESH_subMesh* sm = i_subSM->second;
+ SMESH_subMesh* sm = smIt->next();
const TopoDS_Shape& face = sm->GetSubShape();
if ( face.ShapeType() != TopAbs_FACE )
continue;
nbFaces++;
// is quadrangle face?
- if ( TAssocTool::Count( face, TopAbs_EDGE, 0 ) != 4 ||
- TAssocTool::Count( face, TopAbs_WIRE, 0 ) != 1 )
+ list< TopoDS_Edge > orderedEdges;
+ list< int > nbEdgesInWires;
+ TopoDS_Vertex V000;
+ int nbWires = GetOrderedEdges( TopoDS::Face( face ),
+ V000, orderedEdges, nbEdgesInWires );
+ if ( nbWires != 1 || nbEdgesInWires.front() != 4 )
notQuadGeomSubMesh.push_back( sm );
- // count not quadrangle mesh elements
+ // look for not quadrangle mesh elements
if ( SMESHDS_SubMesh* smDS = sm->GetSubMeshDS() ) {
- SMDS_ElemIteratorPtr eIt = smDS->GetElements();
bool hasNotQuad = false;
+ SMDS_ElemIteratorPtr eIt = smDS->GetElements();
while ( eIt->more() && !hasNotQuad ) {
const SMDS_MeshElement* elem = eIt->next();
if ( elem->GetType() == SMDSAbs_Face ) {
notQuadElemSubMesh.push_back( sm );
}
else {
- RETURN_BAD_RESULT("not meshed face");
+ return error(COMPERR_BAD_INPUT_MESH,TCom("Not meshed face #")<<sm->GetId());
+ }
+ // check if a quadrangle face is meshed with a quadranglar grid
+ if ( notQuadGeomSubMesh.back() != sm &&
+ notQuadElemSubMesh.back() != sm )
+ {
+ // count nb edges on face sides
+ vector< int > nbEdges;
+ nbEdges.reserve( nbEdgesInWires.front() );
+ for ( list< TopoDS_Edge >::iterator edge = orderedEdges.begin();
+ edge != orderedEdges.end(); ++edge )
+ {
+ if ( SMESHDS_SubMesh* smDS = meshDS->MeshElements( *edge ))
+ nbEdges.push_back ( smDS->NbElements() );
+ else
+ nbEdges.push_back ( 0 );
+ }
+ int nbQuads = sm->GetSubMeshDS()->NbElements();
+ if ( nbEdges[0] * nbEdges[1] != nbQuads ||
+ nbEdges[0] != nbEdges[2] ||
+ nbEdges[1] != nbEdges[3] )
+ notQuadElemSubMesh.push_back( sm );
}
}
// detect bad cases
if ( nbNotQuad > 0 && nbNotQuad != 2 )
- RETURN_BAD_RESULT("Wrong shape geometry");
+ return error(COMPERR_BAD_SHAPE,
+ TCom("More than 2 not quadrilateral faces: ")
+ <<nbNotQuad);
if ( nbNotQuadMeshed > 2 )
- RETURN_BAD_RESULT("More then 2 faces meshed with not quadrangle elements");
+ return error(COMPERR_BAD_INPUT_MESH,
+ TCom("More than 2 faces with not quadrangle elements: ")
+ <<nbNotQuadMeshed);
// get found submeshes
if ( hasNotQuad )
else
ok = ( notQuadGeomSubMesh == notQuadElemSubMesh );
if ( !ok )
- RETURN_BAD_RESULT("Side face meshed with not quadrangle elements");
+ return error(COMPERR_BAD_INPUT_MESH, "Side face meshed with not quadrangle elements");
}
myNotQuadOnTop = ( nbNotQuadMeshed > 1 );
-
+
// ----------------------------------------------------------
if ( nbNotQuad == 0 ) // Standard block of 6 quadrangle faces ?
const TopoDS_Shape & ancestor = ancestIt.Value();
if ( ancestor.ShapeType() == TopAbs_EDGE && !edgeMap.FindIndex( ancestor ))
{
- Vtop = TopExp::LastVertex( TopoDS::Edge( ancestor ));
- if ( Vbot.IsSame ( Vtop ))
- Vtop = TopExp::FirstVertex( TopoDS::Edge( ancestor ));
+ TopoDS_Vertex V1, V2;
+ TopExp::Vertices( TopoDS::Edge( ancestor ), V1, V2);
+ if ( Vbot.IsSame ( V1 )) Vtop = V2;
+ else if ( Vbot.IsSame ( V2 )) Vtop = V1;
+ // check that Vtop belongs to shape3D
+ TopExp_Explorer exp( shape3D, TopAbs_VERTEX );
+ for ( ; exp.More(); exp.Next() )
+ if ( Vtop.IsSame( exp.Current() ))
+ break;
+ if ( !exp.More() )
+ Vtop.Nullify();
}
}
}
// Load geometry in SMESH_Block
if ( !SMESH_Block::FindBlockShapes( shell, Vbot, Vtop, myShapeIDMap )) {
if ( !hasNotQuad )
- RETURN_BAD_RESULT("Can not detect top and bottom");
+ return error(COMPERR_BAD_SHAPE, "Can't detect top and bottom of a prism");
}
else {
if ( !botSM ) botSM = Mesh()->GetSubMeshContaining( myShapeIDMap( ID_BOT_FACE ));
// Get Wall faces corresponding to the ordered bottom edges
list< TopoDS_Face > wallFaces;
if ( !GetWallFaces( Mesh(), shape3D, botSM->GetSubShape(), orderedEdges, wallFaces))
- RETURN_BAD_RESULT("GetWallFaces() failed");
+ return error(COMPERR_BAD_SHAPE, "Can't find side faces");
// Find columns of wall nodes and calculate edges' lengths
// --------------------------------------------------------
{
TParam2ColumnMap & faceColumns = myParam2ColumnMaps[ iE ];
if ( !myHelper->LoadNodeColumns( faceColumns, *faceIt, *edgeIt, meshDS ))
- RETURN_BAD_RESULT("SMESH_MesherHelper::LoadNodeColumns() failed");
+ return error(COMPERR_BAD_INPUT_MESH, TCom("Can't find regular quadrangle mesh ")
+ << "on a side face #" << MeshDS()->ShapeToIndex( *faceIt ));
SHOWYXZ("\np1 F "<<iE, gpXYZ(faceColumns.begin()->second.front() ));
SHOWYXZ("p2 F "<<iE, gpXYZ(faceColumns.rbegin()->second.front() ));
{
SMESHDS_SubMesh* smDS = meshDS->MeshElements( *edgeIt);
if ( !smDS )
- RETURN_BAD_RESULT("Null submesh on a bottom edge");
+ return error(COMPERR_BAD_INPUT_MESH, TCom("Null submesh on the edge #")
+ << MeshDS()->ShapeToIndex( *edgeIt ));
// assure length uniqueness
edgeLength[ iE ] *= smDS->NbNodes() + edgeLength[ iE ] / ( 1000 + iE );
len2edgeMap[ edgeLength[ iE ]] = iE;
{
TParam2ColumnMap & faceColumns = myParam2ColumnMaps[ iE ];
if ( !myHelper->LoadNodeColumns( faceColumns, *faceIt, *edgeIt, meshDS ))
- RETURN_BAD_RESULT("SMESH_MesherHelper::LoadNodeColumns() failed");
+ return error(COMPERR_BAD_INPUT_MESH, TCom("Can't find regular quadrangle mesh ")
+ << "on a side face #" << MeshDS()->ShapeToIndex( *faceIt ));
// edge columns
int id = MeshDS()->ShapeToIndex( *edgeIt );
bool isForward = true; // meaningless for intenal wires
SMESH_Block::TFace& tFace = myFace[ fID - ID_FirstF ];
tFace.Set( fID, sideFace->Surface(), pcurves, isForward );
- SHOWYXZ( endl<<"F "<< iF << " id " << fID << " FRW " << sideFace->IsForward(), );
+ SHOWYXZ( endl<<"F "<< iF << " id " << fID << " FRW " << sideFace->IsForward(), sideFace->Value(0,0));
// edges 3D geometry
vector< int > edgeIdVec;
SMESH_Block::GetFaceEdgesIDs( fID, edgeIdVec );
}
default:;
}
- if ( !edge.IsNull() || edge.ShapeType() == TopAbs_EDGE )
+ if ( !edge.IsNull() && edge.ShapeType() == TopAbs_EDGE )
return TopoDS::Edge( edge );
// find edge by 2 vertices