-// Copyright (C) 2007-2015 CEA/DEN, EDF R&D, OPEN CASCADE
+// Copyright (C) 2007-2016 CEA/DEN, EDF R&D, OPEN CASCADE
//
// Copyright (C) 2003-2007 OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN,
// CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS
#include "SMDS_FacePosition.hxx"
#include "SMDS_IteratorOnIterators.hxx"
#include "SMDS_VolumeTool.hxx"
+#include "SMESHDS_Mesh.hxx"
#include "SMESH_Block.hxx"
#include "SMESH_HypoFilter.hxx"
+#include "SMESH_Mesh.hxx"
#include "SMESH_MeshAlgos.hxx"
#include "SMESH_ProxyMesh.hxx"
#include "SMESH_subMesh.hxx"
}
}
+//================================================================================
+/*!
+ * \brief Return SMESH_Gen
+ */
+//================================================================================
+
+SMESH_Gen* SMESH_MesherHelper::GetGen() const
+{
+ return GetMesh()->GetGen();
+}
+
+//================================================================================
+/*!
+ * \brief Return mesh DS
+ */
+//================================================================================
+
+SMESHDS_Mesh* SMESH_MesherHelper::GetMeshDS() const
+{
+ return GetMesh()->GetMeshDS();
+}
+
//=======================================================================
//function : IsQuadraticSubMesh
-//purpose : Check submesh for given shape: if all elements on this shape
+//purpose : Check sub-meshes of a given shape: if all elements on sub-shapes
// are quadratic, quadratic elements will be created.
-// Also fill myTLinkNodeMap
+// Fill myTLinkNodeMap
//=======================================================================
bool SMESH_MesherHelper::IsQuadraticSubMesh(const TopoDS_Shape& aSh)
SMESHDS_Mesh* meshDS = GetMeshDS();
// we can create quadratic elements only if all elements
// created on sub-shapes of given shape are quadratic
- // also we have to fill myTLinkNodeMap
myCreateQuadratic = true;
mySeamShapeIds.clear();
myDegenShapeIds.clear();
}
SMDSAbs_ElementType elemType( subType==TopAbs_FACE ? SMDSAbs_Face : SMDSAbs_Edge );
-
- int nbOldLinks = myTLinkNodeMap.size();
-
if ( !myMesh->HasShapeToMesh() )
{
if (( myCreateQuadratic = myMesh->NbFaces( ORDER_QUADRATIC )))
double u2 = uv1.Coord(1);
myPar1[0] = Min( u1, u2 );
myPar2[0] = Max( u1, u2 );
+ myParIndex |= U_periodic;
}
else
{
double v2 = uv1.Coord(2);
myPar1[1] = Min( v1, v2 );
myPar2[1] = Max( v1, v2 );
+ myParIndex |= V_periodic;
}
}
else //if ( !isSeam )
{
double f,l, r = 0.2345;
Handle(Geom2d_Curve) C2d = BRep_Tool::CurveOnSurface( edge, face, f, l );
- uv2 = C2d->Value( f * r + l * ( 1.-r ));
- if ( du < Precision::PConfusion() )
- isSeam = ( Abs( uv1.Coord(1) - uv2.Coord(1) ) < Precision::PConfusion() );
+ if ( C2d.IsNull() )
+ {
+ isSeam = false;
+ }
else
- isSeam = ( Abs( uv1.Coord(2) - uv2.Coord(2) ) < Precision::PConfusion() );
+ {
+ uv2 = C2d->Value( f * r + l * ( 1.-r ));
+ if ( du < Precision::PConfusion() )
+ isSeam = ( Abs( uv1.Coord(1) - uv2.Coord(1) ) < Precision::PConfusion() );
+ else
+ isSeam = ( Abs( uv1.Coord(2) - uv2.Coord(2) ) < Precision::PConfusion() );
+ }
}
}
if ( isSeam )
}
}
+//=======================================================================
+/*!
+ * \brief Copy shape information from another helper. Used to improve performance
+ * since SetSubShape() can be time consuming if there are many edges
+ */
+//=======================================================================
+
+void SMESH_MesherHelper::CopySubShapeInfo(const SMESH_MesherHelper& other)
+{
+ this->myShape = other.myShape;
+ this->myShapeID = other.myShapeID;
+ this->myDegenShapeIds = other.myDegenShapeIds;
+ this->mySeamShapeIds = other.mySeamShapeIds;
+ this->myPar1[0] = other.myPar1[0];
+ this->myPar1[1] = other.myPar1[1];
+ this->myPar2[0] = other.myPar2[0];
+ this->myPar2[1] = other.myPar2[1];
+ this->myParIndex = other.myParIndex;
+ this->myFace2Surface = other.myFace2Surface;
+}
+
+//=======================================================================
+//function : ShapeToIndex
+//purpose : Convert a shape to its index in the SMESHDS_Mesh
+//=======================================================================
+
+int SMESH_MesherHelper::ShapeToIndex( const TopoDS_Shape& S ) const
+{
+ return GetMeshDS()->ShapeToIndex( S );
+}
+
//=======================================================================
//function : GetNodeUVneedInFaceNode
//purpose : Check if inFaceNode argument is necessary for call GetNodeUV(F,..)
{
if ( !IsSubShape( V, F ))
{
- MESSAGE ( "SMESH_MesherHelper::GetNodeUV(); Vertex " << vertexID
- << " not in face " << GetMeshDS()->ShapeToIndex( F ) );
+ MESSAGE("GetNodeUV() Vertex "<< vertexID <<" not in face "<< GetMeshDS()->ShapeToIndex(F));
// get UV of a vertex closest to the node
double dist = 1e100;
gp_Pnt pn = XYZ( n );
MESSAGE( "SMESH_MesherHelper::CheckNodeUV() failed to project" );
return false;
}
- Quantity_Parameter U,V;
+ Standard_Real U,V;
projector.LowerDistanceParameters(U,V);
uv.SetCoord( U,V );
surfPnt = surface->Value( U, V );
MESSAGE( "SMESH_MesherHelper::CheckNodeU() failed to project" );
return false;
}
- Quantity_Parameter U = projector->LowerDistanceParameter();
+ Standard_Real U = projector->LowerDistanceParameter();
u = double( U );
- MESSAGE(" f " << f << " l " << l << " u " << u);
curvPnt = curve->Value( u );
dist = nodePnt.Distance( curvPnt );
if ( distXYZ ) {
}
if ( dist > tol )
{
- MESSAGE( "SMESH_MesherHelper::CheckNodeU(), invalid projection" );
- MESSAGE("distance " << dist << " " << tol );
+ MESSAGE( "CheckNodeU(), invalid projection; distance " << dist << "; tol " << tol );
return false;
}
// store the fixed U on the edge
// get type of shape for the new medium node
int faceID = -1, edgeID = -1;
- TopoDS_Edge E; double u [2];
+ TopoDS_Edge E; double u [2] = {0.,0.};
TopoDS_Face F; gp_XY uv[2];
bool uvOK[2] = { true, true };
const bool useCurSubShape = ( !myShape.IsNull() && myShape.ShapeType() == TopAbs_EDGE );
if ( !bestEdge.IsNull() )
{
- // move n12 to position of a successfull projection
+ // move n12 to position of a successful projection
//double tol = BRep_Tool::Tolerance(edges[ iOkEdge ]);
if ( !force3d /*&& distMiddleProj > 2*tol*/ )
{
{
vector<const SMDS_MeshNode*> newNodes( nodes.size() * 2 );
newNodes = nodes;
- for ( int i = 0; i < nodes.size(); ++i )
+ for ( size_t i = 0; i < nodes.size(); ++i )
{
const SMDS_MeshNode* n1 = nodes[i];
const SMDS_MeshNode* n2 = nodes[(i+1)%nodes.size()];
const SMDS_MeshNode* n14 = GetMediumNode( n1, n4, force3d, TopAbs_SOLID );
const SMDS_MeshNode* n25 = GetMediumNode( n2, n5, force3d, TopAbs_SOLID );
const SMDS_MeshNode* n36 = GetMediumNode( n3, n6, force3d, TopAbs_SOLID );
+ if ( myCreateBiQuadratic )
+ {
+ const SMDS_MeshNode* n1245 = GetCentralNode( n1,n2,n4,n5,n12,n25,n45,n14,force3d );
+ const SMDS_MeshNode* n1346 = GetCentralNode( n1,n3,n4,n6,n31,n36,n64,n14,force3d );
+ const SMDS_MeshNode* n2356 = GetCentralNode( n2,n3,n6,n5,n23,n36,n56,n25,force3d );
- if(id)
- elem = meshDS->AddVolumeWithID(n1, n2, n3, n4, n5, n6,
- n12, n23, n31, n45, n56, n64, n14, n25, n36, id);
+ if(id)
+ elem = meshDS->AddVolumeWithID(n1, n2, n3, n4, n5, n6,
+ n12, n23, n31, n45, n56, n64, n14, n25, n36,
+ n1245, n2356, n1346, id);
+ else
+ elem = meshDS->AddVolume(n1, n2, n3, n4, n5, n6,
+ n12, n23, n31, n45, n56, n64, n14, n25, n36,
+ n1245, n2356, n1346);
+ }
else
- elem = meshDS->AddVolume(n1, n2, n3, n4, n5, n6,
- n12, n23, n31, n45, n56, n64, n14, n25, n36);
+ {
+ if(id)
+ elem = meshDS->AddVolumeWithID(n1, n2, n3, n4, n5, n6,
+ n12, n23, n31, n45, n56, n64, n14, n25, n36, id);
+ else
+ elem = meshDS->AddVolume(n1, n2, n3, n4, n5, n6,
+ n12, n23, n31, n45, n56, n64, n14, n25, n36);
+ }
}
if ( mySetElemOnShape && myShapeID > 0 )
meshDS->SetMeshElementOnShape( elem, myShapeID );
{
vector<const SMDS_MeshNode*> newNodes;
vector<int> newQuantities;
- for ( int iFace=0, iN=0; iFace < quantities.size(); ++iFace)
+ for ( size_t iFace = 0, iN = 0; iFace < quantities.size(); ++iFace )
{
int nbNodesInFace = quantities[iFace];
newQuantities.push_back(0);
const SMDS_MeshNode* n1 = nodes[ iN + i ];
newNodes.push_back( n1 );
newQuantities.back()++;
-
+
const SMDS_MeshNode* n2 = nodes[ iN + ( i+1==nbNodesInFace ? 0 : i+1 )];
-// if ( n1->GetPosition()->GetTypeOfPosition() != SMDS_TOP_3DSPACE &&
-// n2->GetPosition()->GetTypeOfPosition() != SMDS_TOP_3DSPACE )
+ // if ( n1->GetPosition()->GetTypeOfPosition() != SMDS_TOP_3DSPACE &&
+ // n2->GetPosition()->GetTypeOfPosition() != SMDS_TOP_3DSPACE )
{
const SMDS_MeshNode* n12 = GetMediumNode( n1, n2, force3d, TopAbs_SOLID );
newNodes.push_back( n12 );
}
// get nodes on theBaseEdge sorted by param on edge and initialize theParam2ColumnMap with them
+ const SMDS_MeshNode* prevEndNodes[2] = { 0, 0 };
edge = theBaseSide.begin();
for ( int iE = 0; edge != theBaseSide.end(); ++edge, ++iE )
{
const double prevPar = theParam2ColumnMap.empty() ? 0 : theParam2ColumnMap.rbegin()->first;
for ( u_n = sortedBaseNN.begin(); u_n != sortedBaseNN.end(); u_n++ )
{
+ if ( u_n->second == prevEndNodes[0] ||
+ u_n->second == prevEndNodes[1] )
+ continue;
double par = prevPar + coeff * ( u_n->first - f );
TParam2ColumnMap::iterator u2nn =
theParam2ColumnMap.insert( theParam2ColumnMap.end(), make_pair( par, TNodeColumn()));
u2nn->second.push_back( u_n->second );
}
+ prevEndNodes[0] = sortedBaseNN.begin()->second;
+ prevEndNodes[1] = sortedBaseNN.rbegin()->second;
}
if ( theParam2ColumnMap.size() < 2 )
return false;
}
// nb rows of nodes
- int prevNbRows = theParam2ColumnMap.begin()->second.size(); // current, at least 1 here
- int expectedNbRows = faceSubMesh->NbElements() / ( theParam2ColumnMap.size()-1 ); // to be added
+ size_t prevNbRows = theParam2ColumnMap.begin()->second.size(); // current, at least 1 here
+ size_t expectNbRows = faceSubMesh->NbElements() / ( theParam2ColumnMap.size()-1 ); // to be added
// fill theParam2ColumnMap column by column by passing from nodes on
// theBaseEdge up via mesh faces on theFace
{
vector<const SMDS_MeshNode*>& nCol1 = par_nVec_1->second;
vector<const SMDS_MeshNode*>& nCol2 = par_nVec_2->second;
- nCol1.resize( prevNbRows + expectedNbRows );
- nCol2.resize( prevNbRows + expectedNbRows );
+ nCol1.resize( prevNbRows + expectNbRows );
+ nCol2.resize( prevNbRows + expectNbRows );
- int i1, i2, foundNbRows = 0;
+ int i1, i2; size_t foundNbRows = 0;
const SMDS_MeshNode *n1 = nCol1[ prevNbRows-1 ];
const SMDS_MeshNode *n2 = nCol2[ prevNbRows-1 ];
// find face sharing node n1 and n2 and belonging to faceSubMesh
int nbNodes = face->NbCornerNodes();
if ( nbNodes != 4 )
return false;
- if ( foundNbRows + 1 > expectedNbRows )
+ if ( foundNbRows + 1 > expectNbRows )
return false;
n1 = face->GetNode( (i2+2) % 4 ); // opposite corner of quadrangle face
n2 = face->GetNode( (i1+2) % 4 );
}
avoidSet.insert( face );
}
- if ( foundNbRows != expectedNbRows )
+ if ((size_t) foundNbRows != expectNbRows )
return false;
avoidSet.clear();
}
return ( theParam2ColumnMap.size() > 1 &&
- theParam2ColumnMap.begin()->second.size() == prevNbRows + expectedNbRows );
+ theParam2ColumnMap.begin()->second.size() == prevNbRows + expectNbRows );
}
namespace
//purpose : Return true if 2D mesh on FACE is ditorted
//=======================================================================
-bool SMESH_MesherHelper::IsDistorted2D( SMESH_subMesh* faceSM,
- bool checkUV)
+bool SMESH_MesherHelper::IsDistorted2D( SMESH_subMesh* faceSM,
+ bool checkUV,
+ SMESH_MesherHelper* faceHelper)
{
if ( !faceSM || faceSM->GetSubShape().ShapeType() != TopAbs_FACE )
return false;
bool haveBadFaces = false;
SMESH_MesherHelper helper( *faceSM->GetFather() );
+ if ( faceHelper )
+ helper.CopySubShapeInfo( *faceHelper );
helper.SetSubShape( faceSM->GetSubShape() );
const TopoDS_Face& F = TopoDS::Face( faceSM->GetSubShape() );
SMESHDS_SubMesh* smDS = helper.GetMeshDS()->MeshElements( F );
if ( !smDS || smDS->NbElements() == 0 ) return false;
+ bool subIdsValid = true; // shape ID of nodes is OK
+ if ( helper.HasSeam() )
+ {
+ // check if nodes are bound to seam edges
+ SMESH_subMeshIteratorPtr smIt = faceSM->getDependsOnIterator(/*includeSelf=*/false);
+ while ( smIt->more() && subIdsValid )
+ {
+ SMESH_subMesh* sm = smIt->next();
+ if ( helper.IsSeamShape( sm->GetId() ) && sm->IsEmpty() )
+ subIdsValid = false;
+ }
+ }
SMDS_ElemIteratorPtr faceIt = smDS->GetElements();
double prevArea = 0;
vector< const SMDS_MeshNode* > nodes;
if ( isOnDegen )
continue;
}
- // prepare to getting UVs
+ // prepare for getting UVs
const SMDS_MeshNode* inFaceNode = 0;
if ( helper.HasSeam() ) {
for ( size_t i = 0; ( i < nodes.size() && !inFaceNode ); ++i )
if ( !helper.IsSeamShape( nodes[ i ]->getshapeId() ))
+ {
inFaceNode = nodes[ i ];
+ if ( !subIdsValid )
+ {
+ gp_XY uv = helper.GetNodeUV( F, inFaceNode );
+ if ( helper.IsOnSeam( uv ))
+ inFaceNode = NULL;
+ }
+ }
if ( !inFaceNode )
continue;
}
for ( size_t i = 0; i < nodes.size(); ++i )
uv[ i ] = helper.GetNodeUV( F, nodes[ i ], inFaceNode, toCheckUV );
+ if ( !subIdsValid ) // fix uv on seam
+ {
+ gp_XY uvInFace = helper.GetNodeUV( F, inFaceNode );
+ for ( size_t i = 0; i < uv.size(); ++i )
+ if ( helper.IsOnSeam( uv[i] ))
+ uv[i] = helper.getUVOnSeam( uv[i], uvInFace ).XY();
+ }
+
// compare orientation of triangles
double faceArea = 0;
for ( int iT = 0, nbT = nodes.size()-2; iT < nbT; ++iT )
TopoDS_Shape s0 = GetSubShapeByNode( nn[0], GetMeshDS() );
TopoDS_Shape s1 = GetSubShapeByNode( nn[1], GetMeshDS() );
TopoDS_Shape E = GetCommonAncestor( s0, s1, *myMesh, TopAbs_EDGE );
- if ( !E.IsNull() && !s0.IsSame( s1 ))
+ if ( !E.IsNull() && !s0.IsSame( s1 ) && E.Orientation() != TopAbs_INTERNAL )
{
// is E seam edge?
int nb = 0;
double u0 = GetNodeU( TopoDS::Edge( E ), nn[0], nn[1], &ok );
double u1 = GetNodeU( TopoDS::Edge( E ), nn[1], nn[0], &ok );
if ( ok )
+ {
+ // check that the 2 nodes are connected with a segment (IPAL53055)
+ ok = false;
+ const SMDS_MeshElement* seg;
+ if ( SMESHDS_SubMesh* sm = GetMeshDS()->MeshElements( E ))
+ if (( sm->NbElements() > 0 ) &&
+ ( seg = GetMeshDS()->FindEdge( nn[0], nn[1] )))
+ ok = sm->Contains( seg );
+ }
+ if ( ok )
{
isReversed = ( u0 > u1 );
if ( E.Orientation() == TopAbs_REVERSED )
//=======================================================================
//function : IsSubShape
-//purpose :
+//purpose :
//=======================================================================
bool SMESH_MesherHelper::IsSubShape( const TopoDS_Shape& shape,
if ( shape.IsSame( exp.Current() ))
return true;
}
- SCRUTE((shape.IsNull()));
- SCRUTE((mainShape.IsNull()));
return false;
}
* of the FACE normal
* \return double - the angle (between -Pi and Pi), negative if the angle is concave,
* 1e100 in case of failure
- * \waring Care about order of the EDGEs and their orientation to be as they are
+ * \warning Care about order of the EDGEs and their orientation to be as they are
* within the FACE! Don't pass degenerated EDGEs neither!
*/
//================================================================================
return fabs(param-myPar1[i]) < fabs(param-myPar2[i]) ? myPar2[i] : myPar1[i];
}
+//=======================================================================
+//function : NbRealSeam
+//purpose : Return a number of real seam edges in the shape set through
+// IsQuadraticSubMesh() or SetSubShape(). A real seam edge encounters twice in a wire
+//=======================================================================
+
+size_t SMESH_MesherHelper::NbRealSeam() const
+{
+ size_t nb = 0;
+
+ std::set< int >::const_iterator id = mySeamShapeIds.begin();
+ for ( ; id != mySeamShapeIds.end(); ++id )
+ if ( *id < 0 ) ++nb;
+ else break;
+
+ return nb;
+}
+
+//=======================================================================
+//function : IsOnSeam
+//purpose : Check if UV is on seam. Return 0 if not, 1 for U seam, 2 for V seam
+//=======================================================================
+
+int SMESH_MesherHelper::IsOnSeam(const gp_XY& uv) const
+{
+ for ( int i = U_periodic; i <= V_periodic ; ++i )
+ if ( myParIndex & i )
+ {
+ double p = uv.Coord( i );
+ double tol = ( myPar2[i-1] - myPar1[i-1] ) / 100.;
+ if ( Abs( p - myPar1[i-1] ) < tol ||
+ Abs( p - myPar2[i-1] ) < tol )
+ return i;
+ }
+ return 0;
+}
+
namespace {
//=======================================================================
TopTools_ListIteratorOfListOfShape _ancIter;
TopAbs_ShapeEnum _type;
TopTools_MapOfShape _encountered;
- TAncestorsIterator( const TopTools_ListOfShape& ancestors, TopAbs_ShapeEnum type)
+ TopTools_IndexedMapOfShape _allowed;
+ TAncestorsIterator( const TopTools_ListOfShape& ancestors,
+ TopAbs_ShapeEnum type,
+ const TopoDS_Shape* container/* = 0*/)
: _ancIter( ancestors ), _type( type )
{
+ if ( container && !container->IsNull() )
+ TopExp::MapShapes( *container, type, _allowed);
if ( _ancIter.More() ) {
- if ( _ancIter.Value().ShapeType() != _type ) next();
+ if ( !isCurrentAllowed() ) next();
else _encountered.Add( _ancIter.Value() );
}
}
const TopoDS_Shape* s = _ancIter.More() ? & _ancIter.Value() : 0;
if ( _ancIter.More() )
for ( _ancIter.Next(); _ancIter.More(); _ancIter.Next())
- if ( _ancIter.Value().ShapeType() == _type && _encountered.Add( _ancIter.Value() ))
+ if ( isCurrentAllowed() && _encountered.Add( _ancIter.Value() ))
break;
return s;
}
+ bool isCurrentAllowed()
+ {
+ return (( _ancIter.Value().ShapeType() == _type ) &&
+ ( _allowed.IsEmpty() || _allowed.Contains( _ancIter.Value() )));
+ }
};
} // namespace
//=======================================================================
/*!
- * \brief Return iterator on ancestors of the given type
+ * \brief Return iterator on ancestors of the given type, included into a container shape
*/
//=======================================================================
PShapeIteratorPtr SMESH_MesherHelper::GetAncestors(const TopoDS_Shape& shape,
const SMESH_Mesh& mesh,
- TopAbs_ShapeEnum ancestorType)
+ TopAbs_ShapeEnum ancestorType,
+ const TopoDS_Shape* container)
{
- return PShapeIteratorPtr( new TAncestorsIterator( mesh.GetAncestors(shape), ancestorType));
+ return PShapeIteratorPtr
+ ( new TAncestorsIterator( mesh.GetAncestors(shape), ancestorType, container));
}
//=======================================================================
int NbVolumes() const { return !_volumes[0] ? 0 : !_volumes[1] ? 1 : 2; }
void AddSelfToLinks() const {
- for ( int i = 0; i < _sides.size(); ++i )
+ for ( size_t i = 0; i < _sides.size(); ++i )
_sides[i]->_faces.push_back( this );
}
int LinkIndex( const QLink* side ) const {
- for (int i=0; i<_sides.size(); ++i ) if ( _sides[i] == side ) return i;
+ for (size_t i = 0; i<_sides.size(); ++i ) if ( _sides[i] == side ) return i;
return -1;
}
bool GetLinkChain( int iSide, TChain& chain, SMDS_TypeOfPosition pos, int& err) const;
const SMDS_MeshNode* nodeToContain) const;
const SMDS_MeshNode* GetNodeInFace() const {
- for ( int iL = 0; iL < _sides.size(); ++iL )
+ for ( size_t iL = 0; iL < _sides.size(); ++iL )
if ( _sides[iL]->MediumPos() == SMDS_TOP_FACE ) return _sides[iL]->_mediumNode;
return 0;
}
_sides = links;
_sideIsAdded[0]=_sideIsAdded[1]=_sideIsAdded[2]=_sideIsAdded[3]=false;
_normal.SetCoord(0,0,0);
- for ( int i = 1; i < _sides.size(); ++i ) {
+ for ( size_t i = 1; i < _sides.size(); ++i ) {
const QLink *l1 = _sides[i-1], *l2 = _sides[i];
insert( l1->node1() ); insert( l1->node2() );
// compute normal
* \brief Make up a chain of links
* \param iSide - link to add first
* \param chain - chain to fill in
- * \param pos - postion of medium nodes the links should have
+ * \param pos - position of medium nodes the links should have
* \param error - out, specifies what is wrong
* \retval bool - false if valid chain can't be built; "valid" means that links
* of the chain belongs to rectangles bounding hexahedrons
bool QFace::GetLinkChain( int iSide, TChain& chain, SMDS_TypeOfPosition pos, int& error) const
{
- if ( iSide >= _sides.size() ) // wrong argument iSide
+ if ( iSide >= (int)_sides.size() ) // wrong argument iSide
return false;
if ( _sideIsAdded[ iSide ]) // already in chain
return true;
- if ( _sides.size() != 4 ) { // triangle - visit all my continous faces
+ if ( _sides.size() != 4 ) { // triangle - visit all my continuous faces
MSGBEG( *this );
TLinkSet links;
list< const QFace* > faces( 1, this );
while ( !faces.empty() ) {
const QFace* face = faces.front();
- for ( int i = 0; i < face->_sides.size(); ++i ) {
+ for ( size_t i = 0; i < face->_sides.size(); ++i ) {
if ( !face->_sideIsAdded[i] && face->_sides[i] ) {
face->_sideIsAdded[i] = true;
// find a face side in the chain
if ( link->MediumPos() >= pos ) {
int nbLinkFaces = link->_faces.size();
if ( nbLinkFaces == 4 || (/*nbLinkFaces < 4 && */link->OnBoundary())) {
- // hexahedral mesh or boundary quadrangles - goto a continous face
+ // hexahedral mesh or boundary quadrangles - goto a continuous face
if ( const QFace* f = link->GetContinuesFace( this ))
if ( f->_sides.size() == 4 )
return f->GetLinkChain( *chLink, chain, pos, error );
typedef list< pair< const QFace*, TLinkInSet > > TFaceLinkList;
TFaceLinkList adjacentFaces;
- for ( int iL = 0; iL < _sides.size(); ++iL )
+ for ( size_t iL = 0; iL < _sides.size(); ++iL )
{
if ( avoidLink._qlink == _sides[iL] )
continue;
const TChainLink& avoidLink,
const SMDS_MeshNode* nodeToContain) const
{
- for ( int i = 0; i < _sides.size(); ++i )
+ for ( size_t i = 0; i < _sides.size(); ++i )
if ( avoidLink._qlink != _sides[i] &&
(_sides[i]->node1() == nodeToContain || _sides[i]->node2() == nodeToContain ))
- return links.find( _sides[ i ]);
+ return links.find( _sides[i] );
return links.end();
}
* \brief Move medium node of theLink according to its distance from boundary
* \param theLink - link to fix
* \param theRefVec - movement of boundary
- * \param theLinks - all adjacent links of continous triangles
+ * \param theLinks - all adjacent links of continuous triangles
* \param theFaceHelper - helper is not used so far
* \param thePrevLen - distance from the boundary
* \param theStep - number of steps till movement propagation limit
if ( !theStep )
return thePrevLen; // propagation limit reached
- int iL; // index of theLink
+ size_t iL; // index of theLink
for ( iL = 0; iL < _sides.size(); ++iL )
if ( theLink._qlink == _sides[ iL ])
break;
int iFaceCont = -1, nbBoundary = 0, iBoundary[2]={-1,-1};
if ( _faces[0]->IsBoundary() )
iBoundary[ nbBoundary++ ] = 0;
- for ( int iF = 1; iFaceCont < 0 && iF < _faces.size(); ++iF )
+ for ( size_t iF = 1; iFaceCont < 0 && iF < _faces.size(); ++iF )
{
// look for a face bounding none of volumes bound by _faces[0]
bool sameVol = false;
const QFace* QLink::GetContinuesFace( const QFace* face ) const
{
- for ( int i = 0; i < _faces.size(); ++i ) {
- if ( _faces[i] == face ) {
- int iF = i < 2 ? 1-i : 5-i;
- return iF < _faces.size() ? _faces[iF] : 0;
+ if ( _faces.size() <= 4 )
+ for ( size_t i = 0; i < _faces.size(); ++i ) {
+ if ( _faces[i] == face ) {
+ int iF = i < 2 ? 1-i : 5-i;
+ return iF < (int)_faces.size() ? _faces[iF] : 0;
+ }
}
- }
return 0;
}
//================================================================================
bool QLink::OnBoundary() const
{
- for ( int i = 0; i < _faces.size(); ++i )
+ for ( size_t i = 0; i < _faces.size(); ++i )
if (_faces[i] && _faces[i]->IsBoundary()) return true;
return false;
}
for ( ; bnd != bndEnd; ++bnd )
{
const QLink* bndLink = *bnd;
- for ( int i = 0; i < bndLink->_faces.size(); ++i ) // loop on faces of bndLink
+ for ( size_t i = 0; i < bndLink->_faces.size(); ++i ) // loop on faces of bndLink
{
const QFace* face = bndLink->_faces[i]; // quadrange lateral face of a prism
if ( !face ) continue;
{
// put links in the set and evalute number of result chains by number of boundary links
TLinkSet linkSet;
- int nbBndLinks = 0;
+ size_t nbBndLinks = 0;
for ( TChain::iterator lnk = allLinks.begin(); lnk != allLinks.end(); ++lnk ) {
linkSet.insert( *lnk );
nbBndLinks += lnk->IsBoundary();
TLinkInSet botLink = startLink; // current horizontal link to go up from
corner = startCorner; // current corner the botLink ends at
- int iRow = 0;
+ size_t iRow = 0;
while ( botLink != linksEnd ) // loop on rows
{
// add botLink to the columnChain
// In the linkSet, there must remain the last links of rowChains; add them
if ( linkSet.size() != rowChains.size() )
return _BAD_SET_SIZE;
- for ( int iRow = 0; iRow < rowChains.size(); ++iRow ) {
+ for ( size_t iRow = 0; iRow < rowChains.size(); ++iRow ) {
// find the link (startLink) ending at startCorner
corner = 0;
for ( startLink = linkSet.begin(); startLink != linksEnd; ++startLink ) {
{
continue;
}
+ default:;
}
// get nodes shared by faces that may be distorted
SMDS_NodeIteratorPtr nodeIt;
{
concaveFaces.push_back( face );
}
+ default:;
}
}
if ( concaveFaces.empty() )
< const SMDS_MeshElement*, vector< SMDS_ElemIteratorPtr > > TIterOnIter;
SMDS_ElemIteratorPtr faceIter( new TIterOnIter( faceIterVec ));
- // a seacher to check if a volume is close to a concave face
- std::auto_ptr< SMESH_ElementSearcher > faceSearcher
+ // search to check if a volume is close to a concave face
+ SMESHUtils::Deleter< SMESH_ElementSearcher > faceSearcher
( SMESH_MeshAlgos::GetElementSearcher( *theHelper.GetMeshDS(), faceIter ));
// classifier
while ( volIt->more() )
{
const SMDS_MeshElement* vol = volIt->next();
- int nbN = vol->NbCornerNodes();
+ size_t nbN = vol->NbCornerNodes();
if ( ( nbN != 4 && nbN != 5 ) ||
!solidSM->Contains( vol ) ||
!checkedVols.insert( vol ).second )
gp_Pnt pMedium = SMESH_TNodeXYZ( linkIt->second );
double hMedium = faceNorm * gp_Vec( pOnFace0, pMedium ).XYZ();
double hVol = faceNorm * gp_Vec( pOnFace0, pInSolid ).XYZ();
- isDistorted = ( Abs( hMedium ) > Abs( hVol * 0.5 ));
+ isDistorted = ( Abs( hMedium ) > Abs( hVol * 0.75 ));
}
}
}
void SMESH_MesherHelper::FixQuadraticElements(SMESH_ComputeErrorPtr& compError,
bool volumeOnly)
{
+ //MESSAGE("FixQuadraticElements " << volumeOnly);
// setenv NO_FixQuadraticElements to know if FixQuadraticElements() is guilty of bad conversion
if ( getenv("NO_FixQuadraticElements") )
return;
}
// fix nodes on geom faces
#ifdef _DEBUG_
- int nbfaces = faces.Extent(); /*avoid "unused varianbles": */ nbfaces++, nbfaces--;
+ int nbfaces = nbSolids;
+ nbfaces = faces.Extent(); /*avoid "unused varianbles": */ nbfaces++, nbfaces--;
#endif
for ( TopTools_MapIteratorOfMapOfShape fIt( faces ); fIt.More(); fIt.Next() ) {
+ MESSAGE("FIX FACE " << nbfaces-- << " #" << GetMeshDS()->ShapeToIndex(fIt.Key()));
MSG("FIX FACE " << nbfaces-- << " #" << GetMeshDS()->ShapeToIndex(fIt.Key()));
SMESH_MesherHelper h(*myMesh);
h.SetSubShape( fIt.Key() );
else {
continue;
}
- for ( int iC = 0; iC < chains.size(); ++iC )
+ for ( size_t iC = 0; iC < chains.size(); ++iC )
{
TChain& chain = chains[iC];
if ( chain.empty() ) continue;
MSG("Internal chain - ignore");
continue;
}
- // mesure chain length and compute link position along the chain
+ // measure chain length and compute link position along the chain
double chainLen = 0;
vector< double > linkPos;
TChain savedChain; // backup
"uv2: "<<uv2.X()<<", "<<uv2.Y()<<" \t" <<
"uvOld: "<<oldUV.X()<<", "<<oldUV.Y()<<" \t" <<
"newUV: "<<newUV.X()<<", "<<newUV.Y()<<" \t");
+ uv0.SetX( uv2.X() ); // avoid warning: variable set but not used
}
#endif
(*link1)->Move( move, /*sum=*/false, /*is2dFixed=*/true );
// 4. Move nodes
// -------------
- TIDSortedElemSet biQuadQuas, biQuadTris, triQuadHexa;
- const SMDS_MeshElement *biQuadQua, *triQuadHex;
+ TIDSortedElemSet biQuadQuas, biQuadTris, triQuadHexa, biQuadPenta;
const bool toFixCentralNodes = ( myMesh->NbBiQuadQuadrangles() +
myMesh->NbBiQuadTriangles() +
- myMesh->NbTriQuadraticHexas() );
+ myMesh->NbTriQuadraticHexas() +
+ myMesh->NbBiQuadPrisms());
double distXYZ[4];
faceHlp.ToFixNodeParameters( true );
// collect bi-quadratic elements
if ( toFixCentralNodes )
{
- biQuadQua = triQuadHex = 0;
SMDS_ElemIteratorPtr eIt = pLink->_mediumNode->GetInverseElementIterator();
while ( eIt->more() )
{
case SMDSEntity_BiQuad_Quadrangle: biQuadQuas.insert( e ); break;
case SMDSEntity_BiQuad_Triangle: biQuadTris.insert( e ); break;
case SMDSEntity_TriQuad_Hexa: triQuadHexa.insert( e ); break;
+ case SMDSEntity_BiQuad_Penta: biQuadPenta.insert( e ); break;
default:;
}
}
nCenterCoords.X(), nCenterCoords.Y(), nCenterCoords.Z());
}
}
+ // treat tri-quadratic hexahedra
+ {
+ SMDS_VolumeTool volExp;
+ TIDSortedElemSet::iterator pentIt = biQuadPenta.begin();
+ for ( ; pentIt != biQuadPenta.end(); ++pentIt )
+ {
+ MESSAGE("---");
+ volExp.Set( *pentIt, /*ignoreCentralNodes=*/false );
+ }
+ }
+#ifdef _DEBUG_
+ // avoid warning: defined but not used operator<<()
+ SMESH_Comment() << *links.begin() << *faces.begin();
+#endif
}
+
+//================================================================================
+/*!
+ * \brief DEBUG
+ */
+//================================================================================
+
+void SMESH_MesherHelper::WriteShape(const TopoDS_Shape& s)
+{
+ const char* name = "/tmp/shape.brep";
+ BRepTools::Write( s, name );
+#ifdef _DEBUG_
+ std::cout << name << std::endl;
+#endif
+}
+