-// Copyright (C) 2007-2021 CEA/DEN, EDF R&D, OPEN CASCADE
+// Copyright (C) 2007-2024 CEA, EDF, OPEN CASCADE
//
// Copyright (C) 2003-2007 OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN,
// CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS
#include <Geom_Curve.hxx>
#include <Geom_Surface.hxx>
#include <Precision.hxx>
+#include <ShapeAnalysis.hxx>
+#include <ShapeAnalysis_Curve.hxx>
#include <TColStd_ListOfInteger.hxx>
#include <TopAbs_State.hxx>
#include <TopExp.hxx>
#include "SMESH_TryCatch.hxx" // include after OCCT headers!
#include <smIdType.hxx>
+#include <Basics_OCCTVersion.hxx>
#define cast2Node(elem) static_cast<const SMDS_MeshNode*>( elem )
// Modify a compute state of sub-meshes which become empty
//=======================================================================
-smIdType SMESH_MeshEditor::Remove (const list< smIdType >& theIDs,
- const bool isNodes )
+smIdType SMESH_MeshEditor::Remove (const std::list< smIdType >& theIDs,
+ const bool isNodes )
{
ClearLastCreated();
return removed;
}
+//================================================================================
+/*!
+ * \brief Remove a node and fill a hole appeared, by changing surrounding faces
+ */
+//================================================================================
+
+void SMESH_MeshEditor::RemoveNodeWithReconnection( const SMDS_MeshNode* node )
+{
+ if ( ! node )
+ return;
+
+ if ( node->NbInverseElements( SMDSAbs_Volume ) > 0 )
+ throw SALOME_Exception( "RemoveNodeWithReconnection() applies to 2D mesh only" );
+
+ // check that only triangles surround the node
+ for ( SMDS_ElemIteratorPtr fIt = node->GetInverseElementIterator( SMDSAbs_Face ); fIt->more(); )
+ {
+ const SMDS_MeshElement* face = fIt->next();
+ if ( face->GetGeomType() != SMDSGeom_TRIANGLE )
+ throw SALOME_Exception( "RemoveNodeWithReconnection() applies to triangle mesh only" );
+ if ( face->IsQuadratic() )
+ throw SALOME_Exception( "RemoveNodeWithReconnection() applies to linear mesh only" );
+ }
+
+ std::vector< const SMDS_MeshNode*> neighbours(2);
+ SMESH_MeshAlgos::IsOn2DBoundary( node, & neighbours );
+
+ bool toRemove = ( neighbours.size() > 2 ); // non-manifold ==> just remove
+
+ // if ( neighbours.size() == 2 ) // on boundary
+ // {
+ // // check if theNode and neighbours are on a line
+ // gp_Pnt pN = SMESH_NodeXYZ( node );
+ // gp_Pnt p0 = SMESH_NodeXYZ( neighbours[0] );
+ // gp_Pnt p1 = SMESH_NodeXYZ( neighbours[1] );
+ // double dist01 = p0.Distance( p1 );
+ // double tol = 0.01 * dist01;
+ // double distN = ( gp_Vec( p0, p1 ) ^ gp_Vec( p0, pN )).Magnitude() / dist01;
+ // bool onLine = distN < tol;
+ // toRemove = !onLine;
+ // }
+
+ if ( neighbours.empty() ) // not on boundary
+ {
+ TIDSortedElemSet linkedNodes;
+ GetLinkedNodes( node, linkedNodes, SMDSAbs_Face );
+ for ( const SMDS_MeshElement* e : linkedNodes ) neighbours.push_back( cast2Node( e ));
+ if ( neighbours.empty() )
+ toRemove = true;
+ }
+
+ if ( toRemove )
+ {
+ this->Remove( std::list< smIdType >( 1, node->GetID() ), /*isNode=*/true );
+ return;
+ }
+
+ // choose a node to replace by
+ const SMDS_MeshNode* nToReplace = nullptr;
+ SMESH_NodeXYZ nodeXYZ = node;
+ double minDist = Precision::Infinite();
+ for ( const SMDS_MeshNode* n : neighbours )
+ {
+ double dist = nodeXYZ.SquareDistance( n );
+ if ( dist < minDist )
+ {
+ minDist = dist;
+ nToReplace = n;
+ }
+ }
+
+ // remove node + replace by nToReplace
+ std::list< const SMDS_MeshNode* > nodeGroup = { nToReplace, node };
+ TListOfListOfNodes nodesToMerge( 1, nodeGroup );
+ this->MergeNodes( nodesToMerge );
+}
+
//================================================================================
/*!
* \brief Create 0D elements on all nodes of the given object.
- * \param elements - Elements on whose nodes to create 0D elements; if empty,
+ * \param elements - Elements on whose nodes to create 0D elements; if empty,
* the all mesh is treated
* \param all0DElems - returns all 0D elements found or created on nodes of \a elements
* \param duplicateElements - to add one more 0D element to a node or not
{
if( tr1->NbNodes() != tr2->NbNodes() )
return false;
+
// find the 4-th node to insert into tr1
const SMDS_MeshNode* n4 = 0;
SMDS_ElemIteratorPtr it = tr2->nodesIterator();
- int i=0;
- while ( !n4 && i<3 ) {
+ for ( int i = 0; !n4 && i < 3; ++i )
+ {
const SMDS_MeshNode * n = cast2Node( it->next() );
- i++;
bool isDiag = ( n == theNode1 || n == theNode2 );
if ( !isDiag )
n4 = n;
}
+
// Make an array of nodes to be in a quadrangle
int iNode = 0, iFirstDiag = -1;
it = tr1->nodesIterator();
- i=0;
- while ( i<3 ) {
+ for ( int i = 0; i < 3; ++i )
+ {
const SMDS_MeshNode * n = cast2Node( it->next() );
- i++;
bool isDiag = ( n == theNode1 || n == theNode2 );
if ( isDiag ) {
if ( iFirstDiag < 0 )
return true;
}
+//=======================================================================
+//function : SplitEdge
+//purpose : Replace each triangle bound by theNode1-theNode2 segment with
+// two triangles by connecting a node made on the link with a node opposite to the link.
+//=======================================================================
+
+void SMESH_MeshEditor::SplitEdge (const SMDS_MeshNode * theNode1,
+ const SMDS_MeshNode * theNode2,
+ double thePosition)
+{
+ ClearLastCreated();
+
+ SMESHDS_Mesh * mesh = GetMeshDS();
+
+ // Get triangles and segments to divide
+
+ std::vector<const SMDS_MeshNode *> diagNodes = { theNode1, theNode2 };
+ std::vector<const SMDS_MeshElement *> foundElems;
+ if ( !mesh->GetElementsByNodes( diagNodes, foundElems ) || foundElems.empty() )
+ throw SALOME_Exception( SMESH_Comment("No triangle is bound by the edge ")
+ << theNode1->GetID() << " - " << theNode2->GetID());
+
+ SMESH_MesherHelper helper( *GetMesh() );
+
+ for ( const SMDS_MeshElement * elem : foundElems )
+ {
+ SMDSAbs_ElementType type = elem->GetType();
+ switch ( type ) {
+ case SMDSAbs_Volume:
+ throw SALOME_Exception( "Can't split an edge of a volume");
+ break;
+
+ case SMDSAbs_Face:
+ if ( elem->GetGeomType() != SMDSGeom_TRIANGLE )
+ throw SALOME_Exception( "Can't split an edge of a face of type other than triangle");
+ if ( elem->IsQuadratic() )
+ {
+ helper.SetIsQuadratic( true );
+ helper.AddTLinks( static_cast< const SMDS_MeshFace*>( elem ));
+ helper.SetIsBiQuadratic( elem->GetEntityType() == SMDSEntity_BiQuad_Triangle );
+ }
+ break;
+
+ case SMDSAbs_Edge:
+ if ( elem->IsQuadratic() )
+ {
+ helper.SetIsQuadratic( true );
+ helper.AddTLinks( static_cast< const SMDS_MeshEdge*>( elem ));
+ }
+ break;
+ default:;
+ }
+ }
+
+ // Make a new node
+
+ const SMDS_MeshNode* nodeOnLink = helper.GetMediumNode( theNode1, theNode2,/*force3d=*/false );
+
+ gp_Pnt newNodeXYZ = ( SMESH_NodeXYZ( theNode1 ) * ( 1 - thePosition ) +
+ SMESH_NodeXYZ( theNode2 ) * thePosition );
+
+ const TopoDS_Shape& S = mesh->IndexToShape( nodeOnLink->GetShapeID() );
+ if ( !S.IsNull() && S.ShapeType() == TopAbs_FACE ) // find newNodeXYZ by UV on FACE
+ {
+ Handle(ShapeAnalysis_Surface) surface = helper.GetSurface( TopoDS::Face( S ));
+ double tol = 100 * helper.MaxTolerance( S );
+ gp_Pnt2d uv = surface->ValueOfUV( newNodeXYZ, tol );
+ if ( surface->Gap() < SMESH_NodeXYZ( theNode1 ).Distance( theNode2 ))
+ {
+ newNodeXYZ = surface->Value( uv );
+ if ( SMDS_FacePositionPtr nPos = nodeOnLink->GetPosition())
+ nPos->SetParameters( uv.X(), uv.Y() );
+ }
+ }
+ if ( !S.IsNull() && S.ShapeType() == TopAbs_EDGE ) // find newNodeXYZ by param on EDGE
+ {
+ mesh->MoveNode( nodeOnLink, newNodeXYZ.X(), newNodeXYZ.Y(), newNodeXYZ.Z() );
+ double u = Precision::Infinite(), tol = 100 * helper.MaxTolerance( S ), distXYZ[4];
+ helper.ToFixNodeParameters( true );
+ if ( helper.CheckNodeU( TopoDS::Edge( S ), nodeOnLink, u, tol, /*force3D=*/false, distXYZ ))
+ newNodeXYZ.SetCoord( distXYZ[1], distXYZ[2], distXYZ[3] );
+ }
+ mesh->MoveNode( nodeOnLink, newNodeXYZ.X(), newNodeXYZ.Y(), newNodeXYZ.Z() );
+
+ // Split triangles and segments
+
+ std::vector<const SMDS_MeshNode *> nodes( 7 );
+ for ( const SMDS_MeshElement * elem : foundElems )
+ {
+ nodes.assign( elem->begin_nodes(), elem->end_nodes() );
+ nodes.resize( elem->NbCornerNodes() + 1 );
+ nodes.back() = nodes[0];
+
+ smIdType id = elem->GetID();
+ int shapeID = elem->GetShapeID();
+
+ const SMDS_MeshNode* centralNode = nullptr;
+ if ( elem->GetEntityType() == SMDSEntity_BiQuad_Triangle )
+ centralNode = elem->GetNode( 6 );
+
+ mesh->RemoveFreeElement( elem, /*sm=*/0, /*fromGroups=*/false );
+ if ( centralNode )
+ mesh->RemoveFreeNode( centralNode, /*sm=*/0, /*fromGroups=*/true );
+
+ for ( size_t i = 1; i < nodes.size(); ++i )
+ {
+ const SMDS_MeshNode* n1 = nodes[i-1];
+ const SMDS_MeshNode* n2 = nodes[i];
+ const SMDS_MeshElement* newElem;
+ if ( nodes.size() == 4 ) // triangle
+ {
+ bool isDiag1 = ( n1 == theNode1 || n1 == theNode2 );
+ bool isDiag2 = ( n2 == theNode1 || n2 == theNode2 );
+ if ( isDiag1 && isDiag2 )
+ continue;
+
+ newElem = helper.AddFace( n1, n2, nodeOnLink, id );
+ }
+ else // segment
+ {
+ newElem = helper.AddEdge( n1, nodeOnLink, id );
+ }
+ myLastCreatedElems.push_back( newElem );
+ AddToSameGroups( newElem, elem, mesh );
+ if ( shapeID )
+ mesh->SetMeshElementOnShape( newElem, shapeID );
+ id = 0;
+ }
+ }
+ return;
+}
+
+//=======================================================================
+//function : SplitFace
+//purpose : Split a face into triangles each formed by two nodes of the
+// face and a new node added at the given coordinates.
+//=======================================================================
+
+void SMESH_MeshEditor::SplitFace (const SMDS_MeshElement * theFace,
+ double theX,
+ double theY,
+ double theZ )
+{
+ ClearLastCreated();
+
+ if ( !theFace )
+ throw SALOME_Exception("Null face given");
+ if ( theFace->GetType() != SMDSAbs_Face )
+ throw SALOME_Exception("Not a face given");
+
+ SMESHDS_Mesh * mesh = GetMeshDS();
+
+ SMESH_MesherHelper helper( *GetMesh() );
+ if ( theFace->IsQuadratic() )
+ {
+ helper.SetIsQuadratic( true );
+ helper.AddTLinks( static_cast< const SMDS_MeshFace*>( theFace ));
+ }
+ const TopoDS_Shape& shape = mesh->IndexToShape( theFace->GetShapeID() );
+ helper.SetSubShape( shape );
+ helper.SetElementsOnShape( true );
+
+ // Make a new node
+
+ const SMDS_MeshNode* centralNode = nullptr;
+ if ( theFace->GetEntityType() == SMDSEntity_BiQuad_Triangle )
+ centralNode = theFace->GetNode( 6 );
+ else if ( theFace->GetEntityType() == SMDSEntity_BiQuad_Quadrangle )
+ centralNode = theFace->GetNode( 8 );
+
+ if ( centralNode )
+ {
+ helper.SetIsBiQuadratic( true );
+ mesh->MoveNode( centralNode, theX, theY, theZ );
+ }
+ else
+ centralNode = helper.AddNode( theX, theY, theZ );
+
+
+ // Split theFace
+
+ std::vector<const SMDS_MeshNode *> nodes( theFace->NbNodes() + 1 );
+ nodes.assign( theFace->begin_nodes(), theFace->end_nodes() );
+ nodes.resize( theFace->NbCornerNodes() + 1 );
+ nodes.back() = nodes[0];
+
+ smIdType id = theFace->GetID();
+ int shapeID = theFace->GetShapeID();
+
+ mesh->RemoveFreeElement( theFace, /*sm=*/0, /*fromGroups=*/false );
+
+ for ( size_t i = 1; i < nodes.size(); ++i )
+ {
+ const SMDS_MeshElement* newElem = helper.AddFace( nodes[i-1], nodes[i], centralNode, id );
+
+ myLastCreatedElems.push_back( newElem );
+ AddToSameGroups( newElem, theFace, mesh );
+ if ( shapeID )
+ mesh->SetMeshElementOnShape( newElem, shapeID );
+ id = 0;
+ }
+ return;
+}
+
//=======================================================================
//function : Reorient
//purpose : Reverse theElement orientation
vector< const SMDS_MeshElement* > facesNearLink;
vector< std::pair< int, int > > nodeIndsOfFace;
TIDSortedElemSet avoidSet, emptySet;
- NCollection_Map< SMESH_TLink, SMESH_TLink > checkedLinks;
+ NCollection_Map< SMESH_TLink, SMESH_TLinkHasher > checkedLinks;
while ( !theRefFaces.empty() )
{
}
}
+//=======================================================================
+//function : averageBySurface
+//purpose : Auxiliar function to treat properly nodes in periodic faces in the laplacian smoother
+//=======================================================================
+void averageBySurface( const Handle(Geom_Surface)& theSurface, const SMDS_MeshNode* refNode,
+ TIDSortedElemSet& nodeSet, map< const SMDS_MeshNode*, gp_XY* >& theUVMap, double * coord )
+{
+ if ( theSurface.IsNull() )
+ {
+ TIDSortedElemSet::iterator nodeSetIt = nodeSet.begin();
+ for ( ; nodeSetIt != nodeSet.end(); nodeSetIt++ )
+ {
+ const SMDS_MeshNode* node = cast2Node(*nodeSetIt);
+ coord[0] += node->X();
+ coord[1] += node->Y();
+ coord[2] += node->Z();
+ }
+ }
+ else
+ {
+ Standard_Real Umin,Umax,Vmin,Vmax;
+ theSurface->Bounds( Umin, Umax, Vmin, Vmax );
+ ASSERT( theUVMap.find( refNode ) != theUVMap.end() );
+ gp_XY* nodeUV = theUVMap[ refNode ];
+ Standard_Real uref = nodeUV->X();
+ Standard_Real vref = nodeUV->Y();
+
+ TIDSortedElemSet::iterator nodeSetIt = nodeSet.begin();
+ for ( ; nodeSetIt != nodeSet.end(); nodeSetIt++ )
+ {
+ const SMDS_MeshNode* node = cast2Node(*nodeSetIt);
+ ASSERT( theUVMap.find( node ) != theUVMap.end() );
+ gp_XY* uv = theUVMap[ node ];
+
+ if ( theSurface->IsUPeriodic() || theSurface->IsVPeriodic() )
+ {
+ Standard_Real u = uv->X();
+ Standard_Real v = uv->Y();
+ Standard_Real uCorrected = u;
+ Standard_Real vCorrected = v;
+ bool isUTobeCorrected = (std::fabs( uref - u ) >= 0.7 * std::fabs( Umax - Umin ));
+ bool isVTobeCorrected = (std::fabs( vref - v ) >= 0.7 * std::fabs( Vmax - Vmin ));
+
+ if( isUTobeCorrected )
+ uCorrected = uref > u ? Umax + std::fabs(Umin - u) : Umin - std::fabs(Umax - u);
+
+ if( isVTobeCorrected )
+ vCorrected = vref > v ? Vmax + std::fabs(Vmin - v) : Vmin - std::fabs(Vmax - v);
+
+ coord[0] += uCorrected;
+ coord[1] += vCorrected;
+
+ }
+ else
+ {
+ coord[0] += uv->X();
+ coord[1] += uv->Y();
+ }
+ }
+ }
+}
+
//=======================================================================
//function : laplacianSmooth
//purpose : pulls theNode toward the center of surrounding nodes directly
SMESH_MeshEditor::GetLinkedNodes( theNode, nodeSet, SMDSAbs_Face );
// compute new coodrs
+ double coord[] = { 0., 0., 0. };
+
+ averageBySurface( theSurface, theNode, nodeSet, theUVMap, coord );
- double coord[] = { 0., 0., 0. };
- TIDSortedElemSet::iterator nodeSetIt = nodeSet.begin();
- for ( ; nodeSetIt != nodeSet.end(); nodeSetIt++ ) {
- const SMDS_MeshNode* node = cast2Node(*nodeSetIt);
- if ( theSurface.IsNull() ) { // smooth in 3D
- coord[0] += node->X();
- coord[1] += node->Y();
- coord[2] += node->Z();
- }
- else { // smooth in 2D
- ASSERT( theUVMap.find( node ) != theUVMap.end() );
- gp_XY* uv = theUVMap[ node ];
- coord[0] += uv->X();
- coord[1] += uv->Y();
- }
- }
int nbNodes = nodeSet.size();
if ( !nbNodes )
return;
+
coord[0] /= nbNodes;
coord[1] /= nbNodes;
gp_Pnt p3d = theSurface->Value( coord[0], coord[1] );
coord[0] = p3d.X();
coord[1] = p3d.Y();
- coord[2] = p3d.Z();
+ coord[2] = p3d.Z();
}
else
coord[2] /= nbNodes;
const_cast< SMDS_MeshNode* >( theNode )->setXYZ(coord[0],coord[1],coord[2]);
}
+//=======================================================================
+//function : correctTheValue
+//purpose : Given a boundaries of parametric space determine if the node coordinate (u,v) need correction
+// based on the reference coordinate (uref,vref)
+//=======================================================================
+void correctTheValue( Standard_Real Umax, Standard_Real Umin, Standard_Real Vmax, Standard_Real Vmin,
+ Standard_Real uref, Standard_Real vref, Standard_Real &u, Standard_Real &v )
+{
+ bool isUTobeCorrected = (std::fabs( uref - u ) >= 0.7 * std::fabs( Umax - Umin ));
+ bool isVTobeCorrected = (std::fabs( vref - v ) >= 0.7 * std::fabs( Vmax - Vmin ));
+ if ( isUTobeCorrected )
+ u = std::fabs(u-Umin) < 1e-7 ? Umax : Umin;
+ if ( isVTobeCorrected )
+ v = std::fabs(v-Vmin) < 1e-7 ? Vmax : Vmin;
+}
+
+//=======================================================================
+//function : averageByElement
+//purpose : Auxiliar function to treat properly nodes in periodic faces in the centroidal smoother
+//=======================================================================
+void averageByElement( const Handle(Geom_Surface)& theSurface, const SMDS_MeshNode* refNode, const SMDS_MeshElement* elem,
+ map< const SMDS_MeshNode*, gp_XY* >& theUVMap, SMESH::Controls::TSequenceOfXYZ& aNodePoints,
+ gp_XYZ& elemCenter )
+{
+ int nn = elem->NbNodes();
+ if(elem->IsQuadratic()) nn = nn/2;
+ int i=0;
+ SMDS_ElemIteratorPtr itN = elem->nodesIterator();
+ Standard_Real Umin,Umax,Vmin,Vmax;
+ while ( i<nn )
+ {
+ const SMDS_MeshNode* aNode = static_cast<const SMDS_MeshNode*>( itN->next() );
+ i++;
+ gp_XYZ aP( aNode->X(), aNode->Y(), aNode->Z() );
+ aNodePoints.push_back( aP );
+ if ( !theSurface.IsNull() ) // smooth in 2D
+ {
+ ASSERT( theUVMap.find( aNode ) != theUVMap.end() );
+ gp_XY* uv = theUVMap[ aNode ];
+
+ if ( theSurface->IsUPeriodic() || theSurface->IsVPeriodic() )
+ {
+ theSurface->Bounds( Umin, Umax, Vmin, Vmax );
+ Standard_Real u = uv->X();
+ Standard_Real v = uv->Y();
+ bool isSingularPoint = std::fabs(u - Umin) < 1e-7 || std::fabs(v - Vmin) < 1e-7 || std::fabs(u - Umax) < 1e-7 || std::fabs( v - Vmax ) < 1e-7;
+ if ( !isSingularPoint )
+ {
+ aP.SetCoord( uv->X(), uv->Y(), 0. );
+ }
+ else
+ {
+ gp_XY* refPoint = theUVMap[ refNode ];
+ Standard_Real uref = refPoint->X();
+ Standard_Real vref = refPoint->Y();
+ correctTheValue( Umax, Umin, Vmax, Vmin, uref, vref, u, v );
+ aP.SetCoord( u, v, 0. );
+ }
+ }
+ else
+ aP.SetCoord( uv->X(), uv->Y(), 0. );
+ }
+ elemCenter += aP;
+ }
+}
+
//=======================================================================
//function : centroidalSmooth
//purpose : pulls theNode toward the element-area-weighted centroid of the
SMESH::Controls::Area anAreaFunc;
double totalArea = 0.;
int nbElems = 0;
-
// compute new XYZ
-
+ bool notToMoveNode = false;
+ // Do not correct singular nodes
+ if ( !theSurface.IsNull() && (theSurface->IsUPeriodic() || theSurface->IsVPeriodic()) )
+ {
+ Standard_Real Umin,Umax,Vmin,Vmax;
+ theSurface->Bounds( Umin, Umax, Vmin, Vmax );
+ gp_XY* uv = theUVMap[ theNode ];
+ Standard_Real u = uv->X();
+ Standard_Real v = uv->Y();
+ notToMoveNode = std::fabs(u - Umin) < 1e-7 || std::fabs(v - Vmin) < 1e-7 || std::fabs(u - Umax) < 1e-7 || std::fabs( v - Vmax ) < 1e-7;
+ }
+
SMDS_ElemIteratorPtr elemIt = theNode->GetInverseElementIterator(SMDSAbs_Face);
- while ( elemIt->more() )
+ while ( elemIt->more() && !notToMoveNode )
{
const SMDS_MeshElement* elem = elemIt->next();
nbElems++;
gp_XYZ elemCenter(0.,0.,0.);
SMESH::Controls::TSequenceOfXYZ aNodePoints;
- SMDS_ElemIteratorPtr itN = elem->nodesIterator();
int nn = elem->NbNodes();
if(elem->IsQuadratic()) nn = nn/2;
- int i=0;
- //while ( itN->more() ) {
- while ( i<nn ) {
- const SMDS_MeshNode* aNode = static_cast<const SMDS_MeshNode*>( itN->next() );
- i++;
- gp_XYZ aP( aNode->X(), aNode->Y(), aNode->Z() );
- aNodePoints.push_back( aP );
- if ( !theSurface.IsNull() ) { // smooth in 2D
- ASSERT( theUVMap.find( aNode ) != theUVMap.end() );
- gp_XY* uv = theUVMap[ aNode ];
- aP.SetCoord( uv->X(), uv->Y(), 0. );
- }
- elemCenter += aP;
- }
+ averageByElement( theSurface, theNode, elem, theUVMap, aNodePoints, elemCenter );
+
double elemArea = anAreaFunc.GetValue( aNodePoints );
totalArea += elemArea;
elemCenter /= nn;
aNewXYZ += elemCenter * elemArea;
}
aNewXYZ /= totalArea;
- if ( !theSurface.IsNull() ) {
+
+ if ( !theSurface.IsNull() && !notToMoveNode ) {
theUVMap[ theNode ]->SetCoord( aNewXYZ.X(), aNewXYZ.Y() );
aNewXYZ = theSurface->Value( aNewXYZ.X(), aNewXYZ.Y() ).XYZ();
}
// move node
-
- const_cast< SMDS_MeshNode* >( theNode )->setXYZ(aNewXYZ.X(),aNewXYZ.Y(),aNewXYZ.Z());
+ if ( !notToMoveNode )
+ const_cast< SMDS_MeshNode* >( theNode )->setXYZ(aNewXYZ.X(),aNewXYZ.Y(),aNewXYZ.Z());
}
//=======================================================================
if ( !BRep_Tool::IsClosed( edge, face ))
continue;
SMESHDS_SubMesh* sm = aMesh->MeshElements( edge );
- if ( !sm ) continue;
+ if ( !sm )
+ continue;
// find out which parameter varies for a node on seam
double f,l;
gp_Pnt2d uv1, uv2;
std::swap( itNN[0], itNN[1] );
std::swap( prevNod[0], prevNod[1] );
std::swap( nextNod[0], nextNod[1] );
- std::swap( isSingleNode[0], isSingleNode[1] );
+ std::vector<bool>::swap(isSingleNode[0], isSingleNode[1]);
if ( nbSame > 0 )
sames[0] = 1 - sames[0];
iNotSameNode = 1 - iNotSameNode;
srcEdges.push_back(aMesh->FindEdge (commonNodes[0],commonNodes[1],commonNodes[2]));
else
srcEdges.push_back(aMesh->FindEdge (commonNodes[0],commonNodes[1]));
-#ifdef _DEBUG_
- if ( !srcEdges.back() )
+
+ if (SALOME::VerbosityActivated() && !srcEdges.back())
{
cout << "SMESH_MeshEditor::makeWalls(), no source edge found for a free face #"
- << iF << " of volume #" << vTool.ID() << endl;
+ << iF << " of volume #" << vTool.ID() << endl;
}
-#endif
}
}
if ( freeInd.empty() )
for ( size_t i = 0; i < new2OldNodes.size(); ++i )
if ( const SMDS_MeshNode* n = new2OldNodes[ i ].first )
{
-#ifndef _DEBUG_
- if ( n->NbInverseElements() > 0 )
-#endif
+
+ if (!SALOME::VerbosityActivated() || n->NbInverseElements() > 0 )
{
const SMDS_MeshNode* n2 =
tgtMeshDS->AddNodeWithID( n->X(), n->Y(), n->Z(), idShift + n->GetID() );
{
const SMDS_MeshElement* elem = *eIt;
SMESHDS_SubMesh* sm = mesh->MeshElements( elem->getshapeId() );
+ bool marked = elem->isMarked();
bool keepElem = applyMerge( elem, newElemDefs, nodeNodeMap, /*noHoles=*/false );
if ( !keepElem )
sm->AddElement( newElem );
if ( elem != newElem )
ReplaceElemInGroups( elem, newElem, mesh );
+ if ( marked && newElem )
+ newElem->setIsMarked( true );
}
}
}
// purpose : allow comparing elements basing on their nodes
// ========================================================
+struct ComparableElementHasher;
+
class ComparableElement : public boost::container::flat_set< smIdType >
{
typedef boost::container::flat_set< smIdType > int_set;
smIdType mySumID;
mutable int myGroupID;
+ friend ComparableElementHasher;
+
public:
ComparableElement( const SMDS_MeshElement* theElem ):
mySumID = src.mySumID;
myGroupID = src.myGroupID;
}
+};
+struct ComparableElementHasher
+{
+#if OCC_VERSION_LARGE < 0x07080000
static int HashCode(const ComparableElement& se, int limit )
{
return ::HashCode( FromSmIdType<int>(se.mySumID), limit );
{
return ( se1 == se2 );
}
+#else
+ size_t operator()(const ComparableElement& se) const
+ {
+ return static_cast<size_t>(FromSmIdType<int>(se.mySumID));
+ }
+ bool operator()(const ComparableElement& se1, const ComparableElement& se2) const
+ {
+ return ( se1 == se2 );
+ }
+#endif
};
//=======================================================================
if ( theElements.empty() ) elemIt = GetMeshDS()->elementsIterator();
else elemIt = SMESHUtils::elemSetIterator( theElements );
- typedef NCollection_Map< ComparableElement, ComparableElement > TMapOfElements;
- typedef std::list<smIdType> TGroupOfElems;
+ typedef NCollection_Map< ComparableElement, ComparableElementHasher > TMapOfElements;
+ typedef std::list<smIdType> TGroupOfElems;
TMapOfElements mapOfElements;
std::vector< TGroupOfElems > arrayOfGroups;
TGroupOfElems groupOfElems;
bool toCopyElements/*=false*/,
bool toCopyExistingBoundary/*=false*/,
bool toAddExistingBondary/*= false*/,
- bool aroundElements/*= false*/)
+ bool aroundElements/*= false*/,
+ bool toCreateAllElements/*= false*/)
{
SMDSAbs_ElementType missType = (dimension == BND_2DFROM3D) ? SMDSAbs_Face : SMDSAbs_Edge;
SMDSAbs_ElementType elemType = (dimension == BND_1DFROM2D) ? SMDSAbs_Face : SMDSAbs_Volume;
SMESH_MeshEditor* presentEditor;
SMESH_MeshEditor tgtEditor2( tgtEditor.GetMesh() );
presentEditor = toAddExistingBondary ? &tgtEditor : &tgtEditor2;
-
SMESH_MesherHelper helper( *myMesh );
const TopAbs_ShapeEnum missShapeType = ( missType==SMDSAbs_Face ? TopAbs_FACE : TopAbs_EDGE );
SMDS_VolumeTool vTool;
const SMDS_MeshElement* otherVol = 0;
for ( int iface = 0, n = vTool.NbFaces(); iface < n; iface++ )
{
- if ( !vTool.IsFreeFace(iface, &otherVol) &&
- ( !aroundElements || elements.count( otherVol )))
+ if ( !toCreateAllElements &&
+ !vTool.IsFreeFace(iface, &otherVol) &&
+ ( !aroundElements || elements.count( otherVol )))
continue;
freeFacets.push_back( iface );
}