//=======================================================================
//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 )))
}
}
+//=======================================================================
+/*!
+ * \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
{
gp_Pnt2d uv( Precision::Infinite(), Precision::Infinite() );
- const SMDS_PositionPtr Pos = n->GetPosition();
+ SMDS_PositionPtr pos = n->GetPosition();
bool uvOK = false;
- if ( Pos->GetTypeOfPosition() == SMDS_TOP_FACE )
+ if ( pos->GetTypeOfPosition() == SMDS_TOP_FACE )
{
// node has position on face
- const SMDS_FacePosition* fpos = static_cast<const SMDS_FacePosition*>( Pos );
+ SMDS_FacePositionPtr fpos = pos;
uv.SetCoord( fpos->GetUParameter(), fpos->GetVParameter() );
if ( check )
uvOK = CheckNodeUV( F, n, uv.ChangeCoord(), 2.*getFaceMaxTol( F )); // 2. from 22830
}
- else if ( Pos->GetTypeOfPosition() == SMDS_TOP_EDGE )
+ else if ( pos->GetTypeOfPosition() == SMDS_TOP_EDGE )
{
// node has position on EDGE => it is needed to find
// corresponding EDGE from FACE, get pcurve for this
// EDGE and retrieve value from this pcurve
- const SMDS_EdgePosition* epos = static_cast<const SMDS_EdgePosition*>( Pos );
+ SMDS_EdgePositionPtr epos = pos;
const int edgeID = n->getshapeId();
const TopoDS_Edge& E = TopoDS::Edge( GetMeshDS()->IndexToShape( edgeID ));
double f, l, u = epos->GetUParameter();
uv = newUV;
}
}
- else if ( Pos->GetTypeOfPosition() == SMDS_TOP_VERTEX )
+ else if ( pos->GetTypeOfPosition() == SMDS_TOP_VERTEX )
{
if ( int vertexID = n->getshapeId() ) {
const TopoDS_Vertex& V = TopoDS::Vertex(GetMeshDS()->IndexToShape(vertexID));
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 );
//=======================================================================
//function : GetProjector
-//purpose : Return projector intitialized by given face without location, which is returned
+//purpose : Return projector initialized by given face without location, which is returned
//=======================================================================
GeomAPI_ProjectPointOnSurf& SMESH_MesherHelper::GetProjector(const TopoDS_Face& F,
const SMDS_PositionPtr pos = n->GetPosition();
if ( pos->GetTypeOfPosition()==SMDS_TOP_EDGE )
{
- const SMDS_EdgePosition* epos = static_cast<const SMDS_EdgePosition*>( pos );
- param = epos->GetUParameter();
+ param = pos->GetParameters()[0];
}
else if( pos->GetTypeOfPosition() == SMDS_TOP_VERTEX )
{
MESSAGE( "SMESH_MesherHelper::CheckNodeU() failed to project" );
return false;
}
- Quantity_Parameter U = projector->LowerDistanceParameter();
+ Standard_Real U = projector->LowerDistanceParameter();
u = double( U );
curvPnt = curve->Value( u );
dist = nodePnt.Distance( curvPnt );
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 );
}
// nb rows of nodes
- size_t prevNbRows = theParam2ColumnMap.begin()->second.size(); // current, at least 1 here
+ 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
//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;
for ( size_t i = 0; i < nodes.size(); ++n, ++i )
nodes[ i ] = *n;
- // avoid elems on degenarate shapes as UV on them can be wrong
+ // avoid elems on degenerate shapes as UV on them can be wrong
if ( helper.HasDegeneratedEdges() )
{
bool isOnDegen = false;
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 )
* \brief Find out elements orientation on a geometrical face
* \param theFace - The face correctly oriented in the shape being meshed
* \retval bool - true if the face normal and the normal of first element
- * in the correspoding submesh point in different directions
+ * in the corresponding submesh point in different directions
*/
//================================================================================
//=======================================================================
//function : IsSubShape
-//purpose :
+//purpose :
//=======================================================================
bool SMESH_MesherHelper::IsSubShape( const TopoDS_Shape& shape,
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 {
//=======================================================================
{
// code is valid for convex faces only
gp_XYZ gc(0,0,0);
- for ( TIDSortedNodeSet::const_iterator n = begin(); n!=end(); ++n)
- gc += XYZ( *n ) / size();
- for (unsigned i = 0; i < _sides.size(); ++i )
+ for ( TIDSortedNodeSet::const_iterator n = begin(); n != end(); ++n )
+ gc += XYZ( *n ) / double( size() );
+ for ( size_t i = 0; i < _sides.size(); ++i )
{
if ( _sides[i] == bentLink ) continue;
gp_Vec linkNorm = _normal ^ gp_Vec( XYZ(_sides[i]->node1()), XYZ(_sides[i]->node2()));
return true;
}
return false;
-
+
}
//================================================================================
/*!
- * \brief Find pairs of continues faces
+ * \brief Find pairs of continues faces
*/
//================================================================================
// | Between _faces of link x2 two vertical faces are continues
// x1----x2-----x3 and two horizontal faces are continues. We set vertical faces
// | to _faces[0] and _faces[1] and horizontal faces to
- // v2 | v3 _faces[2] and _faces[3] (or vise versa).
+ // v2 | v3 _faces[2] and _faces[3] (or vice versa).
// x4
if ( _faces.empty() )
vector< TChain> & resultChains,
SMDS_TypeOfPosition pos )
{
- // put links in the set and evalute number of result chains by number of boundary links
+ // put links in the set and evaluate number of result chains by number of boundary links
TLinkSet linkSet;
size_t nbBndLinks = 0;
for ( TChain::iterator lnk = allLinks.begin(); lnk != allLinks.end(); ++lnk ) {
TopoDS_Shape shape = theHelper.GetSubShape().Oriented( TopAbs_FORWARD );
if ( shape.IsNull() ) return;
- if ( !theError ) theError = SMESH_ComputeError::New();
-
+ if ( !dynamic_cast<SMESH_BadInputElements*>( theError.get() ))
+ {
+ if ( !theError )
+ theError.reset( new SMESH_BadInputElements( meshDS ));
+ else
+ theError.reset( new SMESH_BadInputElements( meshDS,
+ theError->myName,
+ theError->myComment,
+ theError->myAlgo));
+ }
gp_XYZ faceNorm;
if ( shape.ShapeType() == TopAbs_FACE ) // 2D
gp_XYZ pMid3D = 0.5 * ( pN0 + SMESH_TNodeXYZ( nOnEdge[1] ));
meshDS->MoveNode( n, pMid3D.X(), pMid3D.Y(), pMid3D.Z() );
MSG( "move OUT of face " << n );
- theError->myBadElements.push_back( f );
+ static_cast<SMESH_BadInputElements*>( theError.get() )->add( f );
}
}
}
}
}
- if ( !theError->myBadElements.empty() )
+ if ( theError->HasBadElems() )
theError->myName = EDITERR_NO_MEDIUM_ON_GEOM;
return;
MSG( "move OUT of solid " << nMedium );
}
}
- theError->myBadElements.push_back( vol );
+ static_cast<SMESH_BadInputElements*>( theError.get() )->add( vol );
}
} // loop on volumes sharing a node on FACE
} // loop on nodes on FACE
} // loop on FACEs of a SOLID
- if ( !theError->myBadElements.empty() )
+ if ( theError->HasBadElems() )
theError->myName = EDITERR_NO_MEDIUM_ON_GEOM;
} // 3D case
}
* \brief Move medium nodes of faces and volumes to fix distorted elements
* \param error - container of fixed distorted elements
* \param volumeOnly - to fix nodes on faces or not, if the shape is solid
- *
+ *
* Issue 0020307: EDF 992 SMESH : Linea/Quadratic with Medium Node on Geometry
*/
//=======================================================================
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;
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() );
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
gp_XY newUV = ApplyIn2D( s, oldUV, gp_XY( move.X(),move.Y()), gp_XY_Added );
gp_Pnt newPnt = s->Value( newUV.X(), newUV.Y());
move = gp_Vec( XYZ((*link1)->_mediumNode), newPnt.Transformed(loc) );
- if ( SMDS_FacePosition* nPos =
- dynamic_cast< SMDS_FacePosition* >((*link1)->_mediumNode->GetPosition()))
+ if ( SMDS_FacePositionPtr nPos = (*link1)->_mediumNode->GetPosition())
nPos->SetParameters( newUV.X(), newUV.Y() );
#ifdef _DEBUG_
if ( (XYZ((*link1)->node1()) - XYZ((*link1)->node2())).SquareModulus() <
// 4. Move nodes
// -------------
- TIDSortedElemSet biQuadQuas, biQuadTris, triQuadHexa;
+ TIDSortedElemSet biQuadQuas, biQuadTris, triQuadHexa, biQuadPenta;
const bool toFixCentralNodes = ( myMesh->NbBiQuadQuadrangles() +
myMesh->NbBiQuadTriangles() +
- myMesh->NbTriQuadraticHexas() );
+ myMesh->NbTriQuadraticHexas() +
+ myMesh->NbBiQuadPrisms());
double distXYZ[4];
faceHlp.ToFixNodeParameters( true );
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();