//=======================================================================
//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
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 );
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;
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 )
//=======================================================================
//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 : 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 {
//=======================================================================
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() );
// 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();