-// Copyright (C) 2007-2016 CEA/DEN, EDF R&D, OPEN CASCADE
+// Copyright (C) 2007-2021 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 <Standard_Failure.hxx>
#include <Standard_ErrorHandler.hxx>
-#include <OSD_Parallel.hxx>
#include "SMESH_TryCatch.hxx" // include after OCCT headers!
+#include <smIdType.hxx>
+
#define cast2Node(elem) static_cast<const SMDS_MeshNode*>( elem )
using namespace std;
myIsQuad = elem->IsQuadratic();
if ( myType == SMDSAbs_Volume && !basicOnly )
{
- vector<int > quant = static_cast<const SMDS_VtkVolume* >( elem )->GetQuantities();
- myPolyhedQuantities.swap( quant );
+ myPolyhedQuantities = static_cast<const SMDS_MeshVolume* >( elem )->GetQuantities();
}
}
}
SMDS_MeshElement* e = 0;
int nbnode = node.size();
SMESHDS_Mesh* mesh = GetMeshDS();
- const int ID = features.myID;
+ const smIdType ID = features.myID;
switch ( features.myType ) {
case SMDSAbs_Face:
node[8], node[9], node[10],node[11],
node[12],node[13],node[14] );
}
+ else if (nbnode == 18) {
+ if ( ID >= 1 ) e = mesh->AddVolumeWithID(node[0], node[1], node[2], node[3],
+ node[4], node[5], node[6], node[7],
+ node[8], node[9], node[10],node[11],
+ node[12],node[13],node[14],
+ node[15],node[16],node[17],ID );
+ else e = mesh->AddVolume (node[0], node[1], node[2], node[3],
+ node[4], node[5], node[6], node[7],
+ node[8], node[9], node[10],node[11],
+ node[12],node[13],node[14],
+ node[15],node[16],node[17] );
+ }
else if (nbnode == 20) {
if ( ID >= 1 ) e = mesh->AddVolumeWithID(node[0], node[1], node[2], node[3],
node[4], node[5], node[6], node[7],
*/
//=======================================================================
-SMDS_MeshElement* SMESH_MeshEditor::AddElement(const vector<int> & nodeIDs,
- const ElemFeatures& features)
+SMDS_MeshElement* SMESH_MeshEditor::AddElement(const vector<smIdType> & nodeIDs,
+ const ElemFeatures& features)
{
vector<const SMDS_MeshNode*> nodes;
nodes.reserve( nodeIDs.size() );
- vector<int>::const_iterator id = nodeIDs.begin();
+ vector<smIdType>::const_iterator id = nodeIDs.begin();
while ( id != nodeIDs.end() ) {
if ( const SMDS_MeshNode* node = GetMeshDS()->FindNode( *id++ ))
nodes.push_back( node );
// Modify a compute state of sub-meshes which become empty
//=======================================================================
-int SMESH_MeshEditor::Remove (const list< int >& theIDs,
+smIdType SMESH_MeshEditor::Remove (const list< smIdType >& theIDs,
const bool isNodes )
{
ClearLastCreated();
SMESHDS_Mesh* aMesh = GetMeshDS();
set< SMESH_subMesh *> smmap;
- int removed = 0;
- list<int>::const_iterator it = theIDs.begin();
+ smIdType removed = 0;
+ list<smIdType>::const_iterator it = theIDs.begin();
for ( ; it != theIDs.end(); it++ ) {
const SMDS_MeshElement * elem;
if ( isNodes )
aNodes[5] = nd2;
}
-//=======================================================================
-//function : nbEdgeConnectivity
-//purpose : return number of the edges connected with the theNode.
-// if theEdges has connections with the other type of the
-// elements, return -1
-//=======================================================================
-
-static int nbEdgeConnectivity(const SMDS_MeshNode* theNode)
-{
- // SMDS_ElemIteratorPtr elemIt = theNode->GetInverseElementIterator();
- // int nb=0;
- // while(elemIt->more()) {
- // elemIt->next();
- // nb++;
- // }
- // return nb;
- return theNode->NbInverseElements();
-}
-
//=======================================================================
//function : getNodesFromTwoTria
//purpose :
{
ClearLastCreated();
- if (!theTria1 || !theTria2)
+ if ( !theTria1 || !theTria2 ||
+ !dynamic_cast<const SMDS_MeshCell*>( theTria1 ) ||
+ !dynamic_cast<const SMDS_MeshCell*>( theTria2 ) ||
+ theTria1->GetType() != SMDSAbs_Face ||
+ theTria2->GetType() != SMDSAbs_Face )
return false;
- const SMDS_VtkFace* F1 = dynamic_cast<const SMDS_VtkFace*>( theTria1 );
- if (!F1) return false;
- const SMDS_VtkFace* F2 = dynamic_cast<const SMDS_VtkFace*>( theTria2 );
- if (!F2) return false;
if ((theTria1->GetEntityType() == SMDSEntity_Triangle) &&
- (theTria2->GetEntityType() == SMDSEntity_Triangle)) {
-
+ (theTria2->GetEntityType() == SMDSEntity_Triangle))
+ {
// 1 +--+ A theTria1: ( 1 A B ) A->2 ( 1 2 B ) 1 +--+ A
// | /| theTria2: ( B A 2 ) B->1 ( 1 A 2 ) |\ |
// |/ | | \|
gp_Pnt xyz;
if ( F.IsNull() )
{
- xyz = ( SMESH_TNodeXYZ( nodes[3] ) +
- SMESH_TNodeXYZ( nodes[4] ) +
- SMESH_TNodeXYZ( nodes[5] )) / 3.;
+ xyz = ( SMESH_NodeXYZ( nodes[3] ) +
+ SMESH_NodeXYZ( nodes[4] ) +
+ SMESH_NodeXYZ( nodes[5] )) / 3.;
}
else
{
if ( !findTriangles( theNode1, theNode2, tr1, tr2 ))
return false;
- const SMDS_VtkFace* F1 = dynamic_cast<const SMDS_VtkFace*>( tr1 );
- if (!F1) return false;
- const SMDS_VtkFace* F2 = dynamic_cast<const SMDS_VtkFace*>( tr2 );
- if (!F2) return false;
+ if ( !dynamic_cast<const SMDS_MeshCell*>( tr1 ) ||
+ !dynamic_cast<const SMDS_MeshCell*>( tr2 ))
+ return false;
+
if ((tr1->GetEntityType() == SMDSEntity_Triangle) &&
(tr2->GetEntityType() == SMDSEntity_Triangle)) {
if ( !findTriangles( theNode1, theNode2, tr1, tr2 ))
return false;
- const SMDS_VtkFace* F1 = dynamic_cast<const SMDS_VtkFace*>( tr1 );
- if (!F1) return false;
- const SMDS_VtkFace* F2 = dynamic_cast<const SMDS_VtkFace*>( tr2 );
- if (!F2) return false;
+ if ( !dynamic_cast<const SMDS_MeshCell*>( tr1 ) ||
+ !dynamic_cast<const SMDS_MeshCell*>( tr2 ))
+ return false;
+
SMESHDS_Mesh * aMesh = GetMeshDS();
if ((tr1->GetEntityType() == SMDSEntity_Triangle) &&
- (tr2->GetEntityType() == SMDSEntity_Triangle)) {
-
+ (tr2->GetEntityType() == SMDSEntity_Triangle))
+ {
const SMDS_MeshNode* aNodes [ 4 ];
if ( ! getQuadrangleNodes( aNodes, theNode1, theNode2, tr1, tr2 ))
return false;
AddToSameGroups( newElem, tr1, aMesh );
int aShapeId = tr1->getshapeId();
if ( aShapeId )
- {
aMesh->SetMeshElementOnShape( newElem, aShapeId );
- }
+
aMesh->RemoveElement( tr1 );
aMesh->RemoveElement( tr2 );
const SMDSAbs_EntityType geomType = theElem->GetEntityType();
if ( geomType == SMDSEntity_Polyhedra ) // polyhedron
{
- const SMDS_VtkVolume* aPolyedre =
- dynamic_cast<const SMDS_VtkVolume*>( theElem );
+ const SMDS_MeshVolume* aPolyedre = SMDS_Mesh::DownCast< SMDS_MeshVolume >( theElem );
if (!aPolyedre) {
MESSAGE("Warning: bad volumic element");
return false;
}
- const int nbFaces = aPolyedre->NbFaces();
+ SMDS_VolumeTool vTool( aPolyedre );
+ const int nbFaces = vTool.NbFaces();
+ vector<int> quantities( nbFaces );
vector<const SMDS_MeshNode *> poly_nodes;
- vector<int> quantities (nbFaces);
- // reverse each face of the polyedre
- for (int iface = 1; iface <= nbFaces; iface++) {
- int inode, nbFaceNodes = aPolyedre->NbFaceNodes(iface);
- quantities[iface - 1] = nbFaceNodes;
+ // check if all facets are oriented equally
+ bool sameOri = true;
+ vector<int>& facetOri = quantities; // keep orientation in quantities so far
+ for (int iface = 0; iface < nbFaces; iface++)
+ {
+ facetOri[ iface ] = vTool.IsFaceExternal( iface );
+ if ( facetOri[ iface ] != facetOri[ 0 ])
+ sameOri = false;
+ }
- for (inode = nbFaceNodes; inode >= 1; inode--) {
- const SMDS_MeshNode* curNode = aPolyedre->GetFaceNode(iface, inode);
- poly_nodes.push_back(curNode);
- }
+ // reverse faces of the polyhedron
+ int neededOri = sameOri ? 1 - facetOri[0] : 1;
+ poly_nodes.reserve( vTool.NbNodes() );
+ for ( int iface = 0; iface < nbFaces; iface++ )
+ {
+ int nbFaceNodes = vTool.NbFaceNodes( iface );
+ const SMDS_MeshNode** nodes = vTool.GetFaceNodes( iface );
+ bool toReverse = ( facetOri[ iface ] != neededOri );
+
+ quantities[ iface ] = nbFaceNodes;
+
+ if ( toReverse )
+ for ( int inode = nbFaceNodes - 1; inode >= 0; inode-- )
+ poly_nodes.push_back( nodes[ inode ]);
+ else
+ poly_nodes.insert( poly_nodes.end(), nodes, nodes + nbFaceNodes );
}
return GetMeshDS()->ChangePolyhedronNodes( theElem, poly_nodes, quantities );
}
if ( theFaces.empty() )
{
- SMDS_FaceIteratorPtr fIt = GetMeshDS()->facesIterator(/*idInceasingOrder=*/true);
+ SMDS_FaceIteratorPtr fIt = GetMeshDS()->facesIterator(/*idInceasingOrder=true*/);
while ( fIt->more() )
theFaces.insert( theFaces.end(), fIt->next() );
}
const SMDS_MeshElement* newElem1 = 0;
const SMDS_MeshElement* newElem2 = 0;
- if ( !elem->IsQuadratic() ) // split liner quadrangle
+ if ( !elem->IsQuadratic() ) // split linear quadrangle
{
// for MaxElementLength2D functor we return minimum diagonal for splitting,
// because aBadRate1=2*len(diagonal 1-3); aBadRate2=2*len(diagonal 2-4)
SMESH_MesherHelper helper( *GetMesh() );
helper.SetElementsOnShape( true );
- SMDS_ElemIteratorPtr faceIt;
- if ( theElems.empty() ) faceIt = GetMeshDS()->elementsIterator(SMDSAbs_Face);
- else faceIt = SMESHUtils::elemSetIterator( theElems );
+ // get standalone groups of faces
+ vector< SMDS_MeshGroup* > allFaceGroups, faceGroups;
+ for ( SMESHDS_GroupBase* grBase : GetMeshDS()->GetGroups() )
+ if ( SMESHDS_Group* group = dynamic_cast<SMESHDS_Group*>( grBase ))
+ if ( group->GetType() == SMDSAbs_Face && !group->IsEmpty() )
+ allFaceGroups.push_back( & group->SMDSGroup() );
bool checkUV;
gp_XY uv [9]; uv[8] = gp_XY(0,0);
Handle(Geom_Surface) surface;
TopLoc_Location loc;
+ SMDS_ElemIteratorPtr faceIt;
+ if ( theElems.empty() ) faceIt = GetMeshDS()->elementsIterator(SMDSAbs_Face);
+ else faceIt = SMESHUtils::elemSetIterator( theElems );
+
while ( faceIt->more() )
{
const SMDS_MeshElement* quad = faceIt->next();
if ( F.IsNull() )
{
for ( ; iN < nodes.size(); ++iN )
- xyz[ iN ] = SMESH_TNodeXYZ( nodes[ iN ] );
+ xyz[ iN ] = SMESH_NodeXYZ( nodes[ iN ] );
for ( ; iN < 8; ++iN ) // mid-side points of a linear qudrangle
xyz[ iN ] = 0.5 * ( xyz[ iN - 4 ] + xyz[( iN - 3 )%4 ] );
myLastCreatedNodes.push_back( nCentral );
}
- // create 4 triangles
-
helper.SetIsQuadratic ( nodes.size() > 4 );
helper.SetIsBiQuadratic( nodes.size() == 9 );
if ( helper.GetIsQuadratic() )
helper.AddTLinks( static_cast< const SMDS_MeshFace*>( quad ));
+ // select groups to update
+ faceGroups.clear();
+ for ( SMDS_MeshGroup* group : allFaceGroups )
+ if ( group->Remove( quad ))
+ faceGroups.push_back( group );
+
+ // create 4 triangles
+
GetMeshDS()->RemoveFreeElement( quad, subMeshDS, /*fromGroups=*/false );
for ( int i = 0; i < 4; ++i )
SMDS_MeshElement* tria = helper.AddFace( nodes[ i ],
nodes[(i+1)%4],
nCentral );
- ReplaceElemInGroups( tria, quad, GetMeshDS() );
myLastCreatedElems.push_back( tria );
+ for ( SMDS_MeshGroup* group : faceGroups )
+ group->Add( tria );
}
}
}
TSplitMethod( int nbTet=0, const int* conn=0, bool addNode=false)
: _nbSplits(nbTet), _nbCorners(4), _connectivity(conn), _baryNode(addNode), _ownConn(false) {}
~TSplitMethod() { if ( _ownConn ) delete [] _connectivity; _connectivity = 0; }
+ TSplitMethod(const TSplitMethod &splitMethod)
+ : _nbSplits(splitMethod._nbSplits),
+ _nbCorners(splitMethod._nbCorners),
+ _baryNode(splitMethod._baryNode),
+ _ownConn(splitMethod._ownConn),
+ _faceBaryNode(splitMethod._faceBaryNode)
+ {
+ _connectivity = splitMethod._connectivity;
+ const_cast<TSplitMethod&>(splitMethod)._connectivity = nullptr;
+ const_cast<TSplitMethod&>(splitMethod)._ownConn = false;
+ }
bool hasFacet( const TTriangleFacet& facet ) const
{
if ( _nbCorners == 4 )
}
for ( int variant = 0; variant < nbVariants && method._nbSplits == 0; ++variant )
{
- // check method compliancy with adjacent tetras,
+ // check method compliance with adjacent tetras,
// all found splits must be among facets of tetras described by this method
method = TSplitMethod( nbTet, connVariants[variant] );
if ( hasAdjacentSplits && method._nbSplits > 0 )
const int methodFlags,
const int facetToSplit)
{
+ TSplitMethod method;
+
// order of facets in HEX according to SMDS_VolumeTool::Hexa_F :
// B, T, L, B, R, F
const int iF = ( facetToSplit < 2 ) ? 0 : 1 + ( facetToSplit-2 ) % 2; // [0,1,2]
to4methods[iF]._nbSplits = 4;
to4methods[iF]._nbCorners = 6;
}
- return to4methods[iF];
+ method = to4methods[iF];
+ to4methods[iF]._connectivity = method._connectivity; // as copy ctor resets _connectivity
+ return method;
}
// else if ( methodFlags == HEXA_TO_2_PRISMS )
- TSplitMethod method;
-
const int iQ = vol.Element()->IsQuadratic() ? 2 : 1;
const int nbVariants = 2, nbSplits = 2;
// there are adjacent prism
for ( int variant = 0; variant < nbVariants; ++variant )
{
- // check method compliancy with adjacent prisms,
+ // check method compliance with adjacent prisms,
// the found prism facets must be among facets of prisms described by current method
method._nbSplits = nbSplits;
method._nbCorners = 6;
*/
//=======================================================================
- struct TVolumeFaceKey: pair< pair< int, int>, pair< int, int> >
+ struct TVolumeFaceKey: pair< pair< smIdType, smIdType>, pair< smIdType, smIdType> >
{
TVolumeFaceKey( SMDS_VolumeTool& vol, int iF )
{
if ( fSubMesh ) // update position of the bary node on geometry
{
if ( subMesh )
- subMesh->RemoveNode( baryNode, false );
+ subMesh->RemoveNode( baryNode );
GetMeshDS()->SetNodeOnFace( baryNode, fSubMesh->GetID() );
const TopoDS_Shape& s = GetMeshDS()->IndexToShape( fSubMesh->GetID() );
if ( !s.IsNull() && s.ShapeType() == TopAbs_FACE )
:myMesh( theMesh ), myMaxID( theMesh->MaxNodeID() + 1)
{}
- long GetLinkID (const SMDS_MeshNode * n1,
+ smIdType GetLinkID (const SMDS_MeshNode * n1,
const SMDS_MeshNode * n2) const
{
- return ( Min(n1->GetID(),n2->GetID()) * myMaxID + Max(n1->GetID(),n2->GetID()));
+ return ( std::min(n1->GetID(),n2->GetID()) * myMaxID + std::max(n1->GetID(),n2->GetID()));
}
bool GetNodes (const long theLinkID,
{
projector.Perform( point );
if ( projector.IsDone() ) {
- double u, v, minVal = DBL_MAX;
+ double u = 0, v = 0, minVal = DBL_MAX;
for ( int i = projector.NbExt(); i > 0; i-- )
if ( projector.SquareDistance( i ) < minVal ) {
minVal = projector.SquareDistance( i );
// }
if ( project ) { // compute new UV
gp_XY newUV;
- gp_Pnt pNode = SMESH_TNodeXYZ( node );
+ gp_Pnt pNode = SMESH_NodeXYZ( node );
if ( !getClosestUV( projector, pNode, newUV )) {
MESSAGE("Node Projection Failed " << node);
}
const SMDS_MeshElement* QF = *elemIt;
if ( QF->IsQuadratic() )
{
- nodes.assign( SMDS_MeshElement::iterator( QF->interlacedNodesElemIterator() ),
+ nodes.assign( SMDS_MeshElement::iterator( QF->interlacedNodesIterator() ),
SMDS_MeshElement::iterator() );
nodes.push_back( nodes[0] );
gp_Pnt xyz;
xyz = surface->Value( uv.X(), uv.Y() );
}
else {
- xyz = 0.5 * ( SMESH_TNodeXYZ( nodes[i-1] ) + SMESH_TNodeXYZ( nodes[i+1] ));
+ xyz = 0.5 * ( SMESH_NodeXYZ( nodes[i-1] ) + SMESH_NodeXYZ( nodes[i+1] ));
}
- if (( SMESH_TNodeXYZ( nodes[i] ) - xyz.XYZ() ).Modulus() > disttol )
+ if (( SMESH_NodeXYZ( nodes[i] ) - xyz.XYZ() ).Modulus() > disttol )
// we have to move a medium node
aMesh->MoveNode( nodes[i], xyz.X(), xyz.Y(), xyz.Z() );
}
const int iNotSame)
{
- SMESH_TNodeXYZ pP = prevNodes[ iNotSame ];
- SMESH_TNodeXYZ pN = nextNodes[ iNotSame ];
+ SMESH_NodeXYZ pP = prevNodes[ iNotSame ];
+ SMESH_NodeXYZ pN = nextNodes[ iNotSame ];
gp_XYZ extrDir( pN - pP ), faceNorm;
SMESH_MeshAlgos::FaceNormal( face, faceNorm, /*normalized=*/false );
SMDS_VolumeTool vTool( *v, /*ignoreCentralNodes=*/false );
int iF, nbF = vTool.NbFaces();
for ( iF = 0; iF < nbF; iF ++ ) {
- if (vTool.IsFreeFace( iF ) &&
- vTool.GetFaceNodes( iF, faceNodeSet ) &&
- initNodeSet != faceNodeSet) // except an initial face
+ if ( vTool.IsFreeFace( iF ) &&
+ vTool.GetFaceNodes( iF, faceNodeSet ) &&
+ initNodeSet != faceNodeSet) // except an initial face
{
if ( nbSteps == 1 && faceNodeSet == topNodeSet )
continue;
SMESH_MeshEditor::ExtrusParam::ExtrusParam( const gp_Vec& theStep,
const int theNbSteps,
const std::list<double>& theScales,
+ const std::list<double>& theAngles,
const gp_XYZ* theBasePoint,
const int theFlags,
const double theTolerance):
for (int i=1; i<=theNbSteps; i++ )
mySteps->Append( stepSize );
- int nbScales = theScales.size();
- if ( nbScales > 0 )
+ if ( !theScales.empty() )
{
- if ( IsLinearVariation() && nbScales < theNbSteps )
+ if ( IsScaleVariation() && (int)theScales.size() < theNbSteps )
+ linearScaleVariation( theNbSteps, const_cast< std::list<double>& >( theScales ));
+
+ // add medium scales
+ std::list<double>::const_iterator s2 = theScales.begin(), s1 = s2++;
+ myScales.reserve( theNbSteps * 2 );
+ myScales.push_back( 0.5 * ( *s1 + 1. ));
+ myScales.push_back( *s1 );
+ for ( ; s2 != theScales.end(); s1 = s2++ )
{
- myScales.reserve( theNbSteps );
- std::list<double>::const_iterator scale = theScales.begin();
- double prevScale = 1.0;
- for ( int iSc = 1; scale != theScales.end(); ++scale, ++iSc )
- {
- int iStep = int( iSc / double( nbScales ) * theNbSteps + 0.5 );
- int stDelta = Max( 1, iStep - myScales.size());
- double scDelta = ( *scale - prevScale ) / stDelta;
- for ( int iStep = 0; iStep < stDelta; ++iStep )
- {
- myScales.push_back( prevScale + scDelta );
- prevScale = myScales.back();
- }
- prevScale = *scale;
- }
+ myScales.push_back( 0.5 * ( *s1 + *s2 ));
+ myScales.push_back( *s2 );
}
- else
+ }
+
+ if ( !theAngles.empty() )
+ {
+ std::list<double>& angles = const_cast< std::list<double>& >( theAngles );
+ if ( IsAngleVariation() && (int)theAngles.size() < theNbSteps )
+ linearAngleVariation( theNbSteps, angles );
+
+ // accumulate angles
+ double angle = 0;
+ int nbAngles = 0;
+ std::list<double>::iterator a1 = angles.begin(), a2;
+ for ( ; a1 != angles.end(); ++a1, ++nbAngles )
{
- myScales.assign( theScales.begin(), theScales.end() );
+ angle += *a1;
+ *a1 = angle;
+ }
+ while ( nbAngles++ < theNbSteps )
+ angles.push_back( angles.back() );
+
+ // add medium angles
+ a2 = angles.begin(), a1 = a2++;
+ myAngles.push_back( 0.5 * *a1 );
+ myAngles.push_back( *a1 );
+ for ( ; a2 != angles.end(); a1 = a2++ )
+ {
+ myAngles.push_back( 0.5 * ( *a1 + *a2 ));
+ myAngles.push_back( *a2 );
}
}
+
if ( theBasePoint )
{
myBaseP = *theBasePoint;
}
}
+//=======================================================================
+//function : ExtrusParam
+//purpose : for extrusion along path
+//=======================================================================
+
+SMESH_MeshEditor::ExtrusParam::ExtrusParam( const std::vector< PathPoint >& thePoints,
+ const gp_Pnt* theBasePoint,
+ const std::list<double>& theScales,
+ const bool theMakeGroups )
+ : myBaseP( Precision::Infinite(), 0, 0 ),
+ myFlags( EXTRUSION_FLAG_BOUNDARY | ( theMakeGroups ? EXTRUSION_FLAG_GROUPS : 0 )),
+ myPathPoints( thePoints )
+{
+ if ( theBasePoint )
+ {
+ myBaseP = theBasePoint->XYZ();
+ }
+
+ if ( !theScales.empty() )
+ {
+ // add medium scales
+ std::list<double>::const_iterator s2 = theScales.begin(), s1 = s2++;
+ myScales.reserve( thePoints.size() * 2 );
+ myScales.push_back( 0.5 * ( 1. + *s1 ));
+ myScales.push_back( *s1 );
+ for ( ; s2 != theScales.end(); s1 = s2++ )
+ {
+ myScales.push_back( 0.5 * ( *s1 + *s2 ));
+ myScales.push_back( *s2 );
+ }
+ }
+
+ myMakeNodesFun = & SMESH_MeshEditor::ExtrusParam::makeNodesAlongTrack;
+}
+
//=======================================================================
//function : ExtrusParam::SetElementsToUse
//purpose : stores elements to use for extrusion by normal, depending on
while ( itN->more() ) {
const SMDS_MeshElement* node = itN->next();
if ( newNodes.insert( node ).second )
- myBaseP += SMESH_TNodeXYZ( node );
+ myBaseP += SMESH_NodeXYZ( node );
}
}
}
std::list<const SMDS_MeshNode*> & newNodes,
const bool makeMediumNodes)
{
- gp_XYZ p = SMESH_TNodeXYZ( srcNode );
+ gp_XYZ p = SMESH_NodeXYZ( srcNode );
int nbNodes = 0;
for ( beginStepIter( makeMediumNodes ); moreSteps(); ++nbNodes ) // loop on steps
newNodes.push_back( newNode );
}
- if ( !myScales.empty() )
+ if ( !myScales.empty() || !myAngles.empty() )
{
- if ( makeMediumNodes && myMediumScales.empty() )
- {
- myMediumScales.resize( myScales.size() );
- double prevFactor = 1.;
- for ( size_t i = 0; i < myScales.size(); ++i )
- {
- myMediumScales[i] = 0.5 * ( prevFactor + myScales[i] );
- prevFactor = myScales[i];
- }
- }
- typedef std::vector<double>::iterator ScaleIt;
- ScaleIt scales[] = { myScales.begin(), myMediumScales.begin() };
-
- size_t iSc = 0, nbScales = myScales.size() + myMediumScales.size();
+ gp_XYZ center = myBaseP;
+ gp_Ax1 ratationAxis( center, myDir );
+ gp_Trsf rotation;
- gp_XYZ center = myBaseP;
std::list<const SMDS_MeshNode*>::iterator nIt = newNodes.begin();
- size_t iN = 0;
- for ( beginStepIter( makeMediumNodes ); moreSteps() && ( iN < nbScales ); ++nIt, ++iN )
+ size_t i = !makeMediumNodes;
+ for ( beginStepIter( makeMediumNodes );
+ moreSteps();
+ ++nIt, i += 1 + !makeMediumNodes )
{
center += myDir.XYZ() * nextStep();
- iSc += int( makeMediumNodes );
- ScaleIt& scale = scales[ iSc % 2 ];
-
- gp_XYZ xyz = SMESH_TNodeXYZ( *nIt );
- xyz = ( *scale * ( xyz - center )) + center;
- mesh->MoveNode( *nIt, xyz.X(), xyz.Y(), xyz.Z() );
-
- ++scale;
+ gp_XYZ xyz = SMESH_NodeXYZ( *nIt );
+ bool moved = false;
+ if ( i < myScales.size() )
+ {
+ xyz = ( myScales[i] * ( xyz - center )) + center;
+ moved = true;
+ }
+ if ( !myAngles.empty() )
+ {
+ rotation.SetRotation( ratationAxis, myAngles[i] );
+ rotation.Transforms( xyz );
+ moved = true;
+ }
+ if ( moved )
+ mesh->MoveNode( *nIt, xyz.X(), xyz.Y(), xyz.Z() );
+ else
+ break;
}
}
return nbNodes;
std::list<const SMDS_MeshNode*> & newNodes,
const bool makeMediumNodes)
{
- gp_XYZ P1 = SMESH_TNodeXYZ( srcNode );
+ gp_XYZ P1 = SMESH_NodeXYZ( srcNode );
int nbNodes = 0;
for ( beginStepIter( makeMediumNodes ); moreSteps(); ++nbNodes ) // loop on steps
// if myNodes.size()>0 we 'nave to use given sequence
// else - use all nodes of mesh
const SMDS_MeshNode * node = 0;
- if ( myNodes.Length() > 0 ) {
- int i;
- for ( i = 1; i <= myNodes.Length(); i++ ) {
- gp_XYZ P2 = SMESH_TNodeXYZ( myNodes.Value(i) );
+ if ( myNodes.Length() > 0 )
+ {
+ for ( int i = 1; i <= myNodes.Length(); i++ )
+ {
+ SMESH_NodeXYZ P2 = myNodes.Value(i);
if (( P1 - P2 ).SquareModulus() < myTolerance * myTolerance )
{
node = myNodes.Value(i);
}
}
}
- else {
+ else
+ {
SMDS_NodeIteratorPtr itn = mesh->nodesIterator();
- while(itn->more()) {
- SMESH_TNodeXYZ P2( itn->next() );
+ while(itn->more())
+ {
+ SMESH_NodeXYZ P2 = itn->next();
if (( P1 - P2 ).SquareModulus() < myTolerance * myTolerance )
{
node = P2._node;
{
const bool alongAvgNorm = ( myFlags & EXTRUSION_FLAG_BY_AVG_NORMAL );
- gp_XYZ p = SMESH_TNodeXYZ( srcNode );
+ gp_XYZ p = SMESH_NodeXYZ( srcNode );
// get normals to faces sharing srcNode
vector< gp_XYZ > norms, baryCenters;
gp_XYZ bc(0,0,0);
int nbN = 0;
for ( SMDS_ElemIteratorPtr nIt = face->nodesIterator(); nIt->more(); ++nbN )
- bc += SMESH_TNodeXYZ( nIt->next() );
+ bc += SMESH_NodeXYZ( nIt->next() );
baryCenters.push_back( bc / nbN );
}
}
//=======================================================================
int SMESH_MeshEditor::ExtrusParam::
-makeNodesByNormal1D( SMESHDS_Mesh* mesh,
+makeNodesByNormal1D( SMESHDS_Mesh* /*mesh*/,
+ const SMDS_MeshNode* /*srcNode*/,
+ std::list<const SMDS_MeshNode*> & /*newNodes*/,
+ const bool /*makeMediumNodes*/)
+{
+ throw SALOME_Exception("Extrusion 1D by Normal not implemented");
+ return 0;
+}
+
+//=======================================================================
+//function : ExtrusParam::makeNodesAlongTrack
+//purpose : create nodes for extrusion along path
+//=======================================================================
+
+int SMESH_MeshEditor::ExtrusParam::
+makeNodesAlongTrack( SMESHDS_Mesh* mesh,
const SMDS_MeshNode* srcNode,
std::list<const SMDS_MeshNode*> & newNodes,
const bool makeMediumNodes)
{
- throw SALOME_Exception("Extrusion 1D by Normal not implemented");
- return 0;
+ const Standard_Real aTolAng=1.e-4;
+
+ gp_Pnt aV0x = myBaseP;
+ gp_Pnt aPN0 = SMESH_NodeXYZ( srcNode );
+
+ const PathPoint& aPP0 = myPathPoints[0];
+ gp_Pnt aP0x = aPP0.myPnt;
+ gp_Dir aDT0x= aPP0.myTgt;
+
+ std::vector< gp_Pnt > centers;
+ centers.reserve( NbSteps() * 2 );
+
+ gp_Trsf aTrsf, aTrsfRot, aTrsfRotT1T0;
+
+ for ( size_t j = 1; j < myPathPoints.size(); ++j )
+ {
+ const PathPoint& aPP = myPathPoints[j];
+ const gp_Pnt& aP1x = aPP.myPnt;
+ const gp_Dir& aDT1x = aPP.myTgt;
+
+ // Translation
+ gp_Vec aV01x( aP0x, aP1x );
+ aTrsf.SetTranslation( aV01x );
+ gp_Pnt aV1x = aV0x.Transformed( aTrsf );
+ gp_Pnt aPN1 = aPN0.Transformed( aTrsf );
+
+ // rotation 1 [ T1,T0 ]
+ Standard_Real aAngleT1T0 = -aDT1x.Angle( aDT0x );
+ if ( fabs( aAngleT1T0 ) > aTolAng )
+ {
+ gp_Dir aDT1T0 = aDT1x ^ aDT0x;
+ aTrsfRotT1T0.SetRotation( gp_Ax1( aV1x, aDT1T0 ), aAngleT1T0 );
+
+ aPN1 = aPN1.Transformed( aTrsfRotT1T0 );
+ }
+
+ // rotation 2
+ if ( aPP.myAngle != 0. )
+ {
+ aTrsfRot.SetRotation( gp_Ax1( aV1x, aDT1x ), aPP.myAngle );
+ aPN1 = aPN1.Transformed( aTrsfRot );
+ }
+
+ // make new node
+ if ( makeMediumNodes )
+ {
+ // create additional node
+ gp_XYZ midP = 0.5 * ( aPN1.XYZ() + aPN0.XYZ() );
+ const SMDS_MeshNode* newNode = mesh->AddNode( midP.X(), midP.Y(), midP.Z() );
+ newNodes.push_back( newNode );
+
+ }
+ const SMDS_MeshNode* newNode = mesh->AddNode( aPN1.X(), aPN1.Y(), aPN1.Z() );
+ newNodes.push_back( newNode );
+
+ centers.push_back( 0.5 * ( aV0x.XYZ() + aV1x.XYZ() ));
+ centers.push_back( aV1x );
+
+ aPN0 = aPN1;
+ aP0x = aP1x;
+ aV0x = aV1x;
+ aDT0x = aDT1x;
+ }
+
+ // scale
+ if ( !myScales.empty() )
+ {
+ gp_Trsf aTrsfScale;
+ std::list<const SMDS_MeshNode*>::iterator node = newNodes.begin();
+ for ( size_t i = !makeMediumNodes;
+ i < myScales.size() && node != newNodes.end();
+ i += ( 1 + !makeMediumNodes ), ++node )
+ {
+ aTrsfScale.SetScale( centers[ i ], myScales[ i ] );
+ gp_Pnt aN = SMESH_NodeXYZ( *node );
+ gp_Pnt aP = aN.Transformed( aTrsfScale );
+ mesh->MoveNode( *node, aP.X(), aP.Y(), aP.Z() );
+ }
+ }
+
+ return myPathPoints.size() + makeMediumNodes * ( myPathPoints.size() - 2 );
}
//=======================================================================
const int theFlags,
const double theTolerance)
{
- ExtrusParam aParams( theStep, theNbSteps, std::list<double>(), 0, theFlags, theTolerance );
+ std::list<double> dummy;
+ ExtrusParam aParams( theStep, theNbSteps, dummy, dummy, 0,
+ theFlags, theTolerance );
return ExtrusionSweep( theElems, aParams, newElemsMap );
}
+namespace
+{
+
+//=======================================================================
+//function : getOriFactor
+//purpose : Return -1 or 1 depending on if order of given nodes corresponds to
+// edge curve orientation
+//=======================================================================
+
+ double getOriFactor( const TopoDS_Edge& edge,
+ const SMDS_MeshNode* n1,
+ const SMDS_MeshNode* n2,
+ SMESH_MesherHelper& helper)
+ {
+ double u1 = helper.GetNodeU( edge, n1, n2 );
+ double u2 = helper.GetNodeU( edge, n2, n1 );
+ return u1 < u2 ? 1. : -1.;
+ }
+}
//=======================================================================
//function : ExtrusionSweep
newNodesItVec.reserve( nbNodes );
// loop on elem nodes
- SMDS_ElemIteratorPtr itN = elem->nodesIterator();
+ SMDS_NodeIteratorPtr itN = elem->nodeIterator();
while ( itN->more() )
{
// check if a node has been already sweeped
- const SMDS_MeshNode* node = cast2Node( itN->next() );
+ const SMDS_MeshNode* node = itN->next();
TNodeOfNodeListMap::iterator nIt =
mapNewNodes.insert( make_pair( node, list<const SMDS_MeshNode*>() )).first;
list<const SMDS_MeshNode*>& listNewNodes = nIt->second;
}
else
{
+ if ( theParams.ToMakeBoundary() )
+ {
+ GetMeshDS()->Modified();
+ throw SALOME_Exception( SMESH_Comment("Can't extrude node #") << node->GetID() );
+ }
break; // newNodesItVec will be shorter than nbNodes
}
}
//=======================================================================
SMESH_MeshEditor::Extrusion_Error
SMESH_MeshEditor::ExtrusionAlongTrack (TIDSortedElemSet theElements[2],
- SMESH_subMesh* theTrack,
+ SMESH_Mesh* theTrackMesh,
+ SMDS_ElemIteratorPtr theTrackIterator,
const SMDS_MeshNode* theN1,
- const bool theHasAngles,
- list<double>& theAngles,
- const bool theLinearVariation,
- const bool theHasRefPoint,
- const gp_Pnt& theRefPoint,
+ std::list<double>& theAngles,
+ const bool theAngleVariation,
+ std::list<double>& theScales,
+ const bool theScaleVariation,
+ const gp_Pnt* theRefPoint,
const bool theMakeGroups)
{
ClearLastCreated();
- int aNbE;
- std::list<double> aPrms;
- TIDSortedElemSet::iterator itElem;
-
- gp_XYZ aGC;
- TopoDS_Edge aTrackEdge;
- TopoDS_Vertex aV1, aV2;
-
- SMDS_ElemIteratorPtr aItE;
- SMDS_NodeIteratorPtr aItN;
- SMDSAbs_ElementType aTypeE;
-
- TNodeOfNodeListMap mapNewNodes;
-
// 1. Check data
- aNbE = theElements[0].size() + theElements[1].size();
- // nothing to do
- if ( !aNbE )
+ if ( theElements[0].empty() && theElements[1].empty() )
return EXTR_NO_ELEMENTS;
- // 1.1 Track Pattern
- ASSERT( theTrack );
-
- SMESHDS_SubMesh* pSubMeshDS = theTrack->GetSubMeshDS();
- if ( !pSubMeshDS )
- return ExtrusionAlongTrack( theElements, theTrack->GetFather(), theN1,
- theHasAngles, theAngles, theLinearVariation,
- theHasRefPoint, theRefPoint, theMakeGroups );
-
- aItE = pSubMeshDS->GetElements();
- while ( aItE->more() ) {
- const SMDS_MeshElement* pE = aItE->next();
- aTypeE = pE->GetType();
- // Pattern must contain links only
- if ( aTypeE != SMDSAbs_Edge )
- return EXTR_PATH_NOT_EDGE;
- }
-
- list<SMESH_MeshEditor_PathPoint> fullList;
-
- const TopoDS_Shape& aS = theTrack->GetSubShape();
- // Sub-shape for the Pattern must be an Edge or Wire
- if( aS.ShapeType() == TopAbs_EDGE ) {
- aTrackEdge = TopoDS::Edge( aS );
- // the Edge must not be degenerated
- if ( SMESH_Algo::isDegenerated( aTrackEdge ) )
- return EXTR_BAD_PATH_SHAPE;
- TopExp::Vertices( aTrackEdge, aV1, aV2 );
- aItN = theTrack->GetFather()->GetSubMesh( aV1 )->GetSubMeshDS()->GetNodes();
- const SMDS_MeshNode* aN1 = aItN->next();
- aItN = theTrack->GetFather()->GetSubMesh( aV2 )->GetSubMeshDS()->GetNodes();
- const SMDS_MeshNode* aN2 = aItN->next();
- // starting node must be aN1 or aN2
- if ( !( aN1 == theN1 || aN2 == theN1 ) )
- return EXTR_BAD_STARTING_NODE;
- aItN = pSubMeshDS->GetNodes();
- while ( aItN->more() ) {
- const SMDS_MeshNode* pNode = aItN->next();
- const SMDS_EdgePosition* pEPos =
- static_cast<const SMDS_EdgePosition*>( pNode->GetPosition() );
- double aT = pEPos->GetUParameter();
- aPrms.push_back( aT );
- }
- //Extrusion_Error err =
- makeEdgePathPoints(aPrms, aTrackEdge, (aN1==theN1), fullList);
- } else if( aS.ShapeType() == TopAbs_WIRE ) {
- list< SMESH_subMesh* > LSM;
- TopTools_SequenceOfShape Edges;
- SMESH_subMeshIteratorPtr itSM = theTrack->getDependsOnIterator(false,true);
- while(itSM->more()) {
- SMESH_subMesh* SM = itSM->next();
- LSM.push_back(SM);
- const TopoDS_Shape& aS = SM->GetSubShape();
- Edges.Append(aS);
- }
- list< list<SMESH_MeshEditor_PathPoint> > LLPPs;
- int startNid = theN1->GetID();
- TColStd_MapOfInteger UsedNums;
-
- int NbEdges = Edges.Length();
- int i = 1;
- for(; i<=NbEdges; i++) {
- int k = 0;
- list< SMESH_subMesh* >::iterator itLSM = LSM.begin();
- for(; itLSM!=LSM.end(); itLSM++) {
- k++;
- if(UsedNums.Contains(k)) continue;
- aTrackEdge = TopoDS::Edge( Edges.Value(k) );
- SMESH_subMesh* locTrack = *itLSM;
- SMESHDS_SubMesh* locMeshDS = locTrack->GetSubMeshDS();
- TopExp::Vertices( aTrackEdge, aV1, aV2 );
- aItN = locTrack->GetFather()->GetSubMesh(aV1)->GetSubMeshDS()->GetNodes();
- const SMDS_MeshNode* aN1 = aItN->next();
- aItN = locTrack->GetFather()->GetSubMesh(aV2)->GetSubMeshDS()->GetNodes();
- const SMDS_MeshNode* aN2 = aItN->next();
- // starting node must be aN1 or aN2
- if ( !( aN1->GetID() == startNid || aN2->GetID() == startNid ) ) continue;
- // 2. Collect parameters on the track edge
- aPrms.clear();
- aItN = locMeshDS->GetNodes();
- while ( aItN->more() ) {
- const SMDS_MeshNode* pNode = aItN->next();
- const SMDS_EdgePosition* pEPos =
- static_cast<const SMDS_EdgePosition*>( pNode->GetPosition() );
- double aT = pEPos->GetUParameter();
- aPrms.push_back( aT );
- }
- list<SMESH_MeshEditor_PathPoint> LPP;
- //Extrusion_Error err =
- makeEdgePathPoints(aPrms, aTrackEdge,(aN1->GetID()==startNid), LPP);
- LLPPs.push_back(LPP);
- UsedNums.Add(k);
- // update startN for search following edge
- if( aN1->GetID() == startNid ) startNid = aN2->GetID();
- else startNid = aN1->GetID();
- break;
- }
- }
- list< list<SMESH_MeshEditor_PathPoint> >::iterator itLLPP = LLPPs.begin();
- list<SMESH_MeshEditor_PathPoint> firstList = *itLLPP;
- list<SMESH_MeshEditor_PathPoint>::iterator itPP = firstList.begin();
- for(; itPP!=firstList.end(); itPP++) {
- fullList.push_back( *itPP );
- }
- SMESH_MeshEditor_PathPoint PP1 = fullList.back();
- fullList.pop_back();
- itLLPP++;
- for(; itLLPP!=LLPPs.end(); itLLPP++) {
- list<SMESH_MeshEditor_PathPoint> currList = *itLLPP;
- itPP = currList.begin();
- SMESH_MeshEditor_PathPoint PP2 = currList.front();
- gp_Dir D1 = PP1.Tangent();
- gp_Dir D2 = PP2.Tangent();
- gp_Dir Dnew( gp_Vec( (D1.X()+D2.X())/2, (D1.Y()+D2.Y())/2,
- (D1.Z()+D2.Z())/2 ) );
- PP1.SetTangent(Dnew);
- fullList.push_back(PP1);
- itPP++;
- for(; itPP!=firstList.end(); itPP++) {
- fullList.push_back( *itPP );
- }
- PP1 = fullList.back();
- fullList.pop_back();
- }
- // if wire not closed
- fullList.push_back(PP1);
- // else ???
- }
- else {
- return EXTR_BAD_PATH_SHAPE;
- }
-
- return makeExtrElements(theElements, fullList, theHasAngles, theAngles, theLinearVariation,
- theHasRefPoint, theRefPoint, theMakeGroups);
-}
-
-
-//=======================================================================
-//function : ExtrusionAlongTrack
-//purpose :
-//=======================================================================
-SMESH_MeshEditor::Extrusion_Error
-SMESH_MeshEditor::ExtrusionAlongTrack (TIDSortedElemSet theElements[2],
- SMESH_Mesh* theTrack,
- const SMDS_MeshNode* theN1,
- const bool theHasAngles,
- list<double>& theAngles,
- const bool theLinearVariation,
- const bool theHasRefPoint,
- const gp_Pnt& theRefPoint,
- const bool theMakeGroups)
-{
- ClearLastCreated();
-
- int aNbE;
- std::list<double> aPrms;
- TIDSortedElemSet::iterator itElem;
-
- gp_XYZ aGC;
- TopoDS_Edge aTrackEdge;
- TopoDS_Vertex aV1, aV2;
-
- SMDS_ElemIteratorPtr aItE;
- SMDS_NodeIteratorPtr aItN;
- SMDSAbs_ElementType aTypeE;
+ ASSERT( theTrackMesh );
+ if ( ! theTrackIterator || !theTrackIterator->more() )
+ return EXTR_NO_ELEMENTS;
- TNodeOfNodeListMap mapNewNodes;
+ // 2. Get ordered nodes
+ SMESH_MeshAlgos::TElemGroupVector branchEdges;
+ SMESH_MeshAlgos::TNodeGroupVector branchNods;
+ SMESH_MeshAlgos::Get1DBranches( theTrackIterator, branchEdges, branchNods, theN1 );
+ if ( branchEdges.empty() )
+ return EXTR_PATH_NOT_EDGE;
- // 1. Check data
- aNbE = theElements[0].size() + theElements[1].size();
- // nothing to do
- if ( !aNbE )
- return EXTR_NO_ELEMENTS;
+ if ( branchEdges.size() > 1 )
+ return EXTR_BAD_PATH_SHAPE;
- // 1.1 Track Pattern
- ASSERT( theTrack );
-
- SMESHDS_Mesh* pMeshDS = theTrack->GetMeshDS();
-
- aItE = pMeshDS->elementsIterator();
- while ( aItE->more() ) {
- const SMDS_MeshElement* pE = aItE->next();
- aTypeE = pE->GetType();
- // Pattern must contain links only
- if ( aTypeE != SMDSAbs_Edge )
- return EXTR_PATH_NOT_EDGE;
- }
-
- list<SMESH_MeshEditor_PathPoint> fullList;
-
- const TopoDS_Shape& aS = theTrack->GetShapeToMesh();
-
- if ( !theTrack->HasShapeToMesh() ) {
- //Mesh without shape
- const SMDS_MeshNode* currentNode = NULL;
- const SMDS_MeshNode* prevNode = theN1;
- std::vector<const SMDS_MeshNode*> aNodesList;
- aNodesList.push_back(theN1);
- int nbEdges = 0, conn=0;
- const SMDS_MeshElement* prevElem = NULL;
- const SMDS_MeshElement* currentElem = NULL;
- int totalNbEdges = theTrack->NbEdges();
- SMDS_ElemIteratorPtr nIt;
-
- //check start node
- if( !theTrack->GetMeshDS()->Contains(theN1) ) {
- return EXTR_BAD_STARTING_NODE;
- }
-
- conn = nbEdgeConnectivity(theN1);
- if( conn != 1 )
- return EXTR_PATH_NOT_EDGE;
-
- aItE = theN1->GetInverseElementIterator();
- prevElem = aItE->next();
- currentElem = prevElem;
- //Get all nodes
- if(totalNbEdges == 1 ) {
- nIt = currentElem->nodesIterator();
- currentNode = static_cast<const SMDS_MeshNode*>(nIt->next());
- if(currentNode == prevNode)
- currentNode = static_cast<const SMDS_MeshNode*>(nIt->next());
- aNodesList.push_back(currentNode);
- } else {
- nIt = currentElem->nodesIterator();
- while( nIt->more() ) {
- currentNode = static_cast<const SMDS_MeshNode*>(nIt->next());
- if(currentNode == prevNode)
- currentNode = static_cast<const SMDS_MeshNode*>(nIt->next());
- aNodesList.push_back(currentNode);
-
- //case of the closed mesh
- if(currentNode == theN1) {
- nbEdges++;
- break;
- }
+ std::vector< const SMDS_MeshNode* >& pathNodes = branchNods[0];
+ std::vector< const SMDS_MeshElement* >& pathEdges = branchEdges[0];
+ if ( pathNodes[0] != theN1 && pathNodes[1] != theN1 )
+ return EXTR_BAD_STARTING_NODE;
- conn = nbEdgeConnectivity(currentNode);
- if(conn > 2) {
- return EXTR_PATH_NOT_EDGE;
- }else if( conn == 1 && nbEdges > 0 ) {
- //End of the path
- nbEdges++;
- break;
- }else {
- prevNode = currentNode;
- aItE = currentNode->GetInverseElementIterator();
- currentElem = aItE->next();
- if( currentElem == prevElem)
- currentElem = aItE->next();
- nIt = currentElem->nodesIterator();
- prevElem = currentElem;
- nbEdges++;
- }
- }
- }
-
- if(nbEdges != totalNbEdges)
- return EXTR_PATH_NOT_EDGE;
-
- TopTools_SequenceOfShape Edges;
- list< list<SMESH_MeshEditor_PathPoint> > LLPPs;
- int startNid = theN1->GetID();
- for ( size_t i = 1; i < aNodesList.size(); i++ )
- {
- gp_Pnt p1 = SMESH_TNodeXYZ( aNodesList[i-1] );
- gp_Pnt p2 = SMESH_TNodeXYZ( aNodesList[i] );
- TopoDS_Edge e = BRepBuilderAPI_MakeEdge( p1, p2 );
- list<SMESH_MeshEditor_PathPoint> LPP;
- aPrms.clear();
- makeEdgePathPoints(aPrms, e, (aNodesList[i-1]->GetID()==startNid), LPP);
- LLPPs.push_back(LPP);
- if ( aNodesList[i-1]->GetID() == startNid ) startNid = aNodesList[i ]->GetID();
- else startNid = aNodesList[i-1]->GetID();
- }
-
- list< list<SMESH_MeshEditor_PathPoint> >::iterator itLLPP = LLPPs.begin();
- list<SMESH_MeshEditor_PathPoint> firstList = *itLLPP;
- list<SMESH_MeshEditor_PathPoint>::iterator itPP = firstList.begin();
- for(; itPP!=firstList.end(); itPP++) {
- fullList.push_back( *itPP );
- }
-
- SMESH_MeshEditor_PathPoint PP1 = fullList.back();
- SMESH_MeshEditor_PathPoint PP2;
- fullList.pop_back();
- itLLPP++;
- for(; itLLPP!=LLPPs.end(); itLLPP++) {
- list<SMESH_MeshEditor_PathPoint> currList = *itLLPP;
- itPP = currList.begin();
- PP2 = currList.front();
- gp_Dir D1 = PP1.Tangent();
- gp_Dir D2 = PP2.Tangent();
- gp_Dir Dnew( 0.5 * ( D1.XYZ() + D2.XYZ() ));
- PP1.SetTangent(Dnew);
- fullList.push_back(PP1);
- itPP++;
- for(; itPP!=currList.end(); itPP++) {
- fullList.push_back( *itPP );
- }
- PP1 = fullList.back();
- fullList.pop_back();
- }
- fullList.push_back(PP1);
-
- } // Sub-shape for the Pattern must be an Edge or Wire
- else if ( aS.ShapeType() == TopAbs_EDGE )
- {
- aTrackEdge = TopoDS::Edge( aS );
- // the Edge must not be degenerated
- if ( SMESH_Algo::isDegenerated( aTrackEdge ) )
- return EXTR_BAD_PATH_SHAPE;
- TopExp::Vertices( aTrackEdge, aV1, aV2 );
- const SMDS_MeshNode* aN1 = SMESH_Algo::VertexNode( aV1, pMeshDS );
- const SMDS_MeshNode* aN2 = SMESH_Algo::VertexNode( aV2, pMeshDS );
- // starting node must be aN1 or aN2
- if ( !( aN1 == theN1 || aN2 == theN1 ) )
- return EXTR_BAD_STARTING_NODE;
- aItN = pMeshDS->nodesIterator();
- while ( aItN->more() ) {
- const SMDS_MeshNode* pNode = aItN->next();
- if( pNode==aN1 || pNode==aN2 ) continue;
- const SMDS_EdgePosition* pEPos =
- static_cast<const SMDS_EdgePosition*>( pNode->GetPosition() );
- double aT = pEPos->GetUParameter();
- aPrms.push_back( aT );
- }
- //Extrusion_Error err =
- makeEdgePathPoints(aPrms, aTrackEdge, (aN1==theN1), fullList);
- }
- else if( aS.ShapeType() == TopAbs_WIRE ) {
- list< SMESH_subMesh* > LSM;
- TopTools_SequenceOfShape Edges;
- TopExp_Explorer eExp(aS, TopAbs_EDGE);
- for(; eExp.More(); eExp.Next()) {
- TopoDS_Edge E = TopoDS::Edge( eExp.Current() );
- if( SMESH_Algo::isDegenerated(E) ) continue;
- SMESH_subMesh* SM = theTrack->GetSubMesh(E);
- if(SM) {
- LSM.push_back(SM);
- Edges.Append(E);
- }
- }
- list< list<SMESH_MeshEditor_PathPoint> > LLPPs;
- TopoDS_Vertex aVprev;
- TColStd_MapOfInteger UsedNums;
- int NbEdges = Edges.Length();
- int i = 1;
- for(; i<=NbEdges; i++) {
- int k = 0;
- list< SMESH_subMesh* >::iterator itLSM = LSM.begin();
- for(; itLSM!=LSM.end(); itLSM++) {
- k++;
- if(UsedNums.Contains(k)) continue;
- aTrackEdge = TopoDS::Edge( Edges.Value(k) );
- SMESH_subMesh* locTrack = *itLSM;
- SMESHDS_SubMesh* locMeshDS = locTrack->GetSubMeshDS();
- TopExp::Vertices( aTrackEdge, aV1, aV2 );
- bool aN1isOK = false, aN2isOK = false;
- if ( aVprev.IsNull() ) {
- // if previous vertex is not yet defined, it means that we in the beginning of wire
- // and we have to find initial vertex corresponding to starting node theN1
- const SMDS_MeshNode* aN1 = SMESH_Algo::VertexNode( aV1, pMeshDS );
- const SMDS_MeshNode* aN2 = SMESH_Algo::VertexNode( aV2, pMeshDS );
- // starting node must be aN1 or aN2
- aN1isOK = ( aN1 && aN1 == theN1 );
- aN2isOK = ( aN2 && aN2 == theN1 );
- }
- else {
- // we have specified ending vertex of the previous edge on the previous iteration
- // and we have just to check that it corresponds to any vertex in current segment
- aN1isOK = aVprev.IsSame( aV1 );
- aN2isOK = aVprev.IsSame( aV2 );
- }
- if ( !aN1isOK && !aN2isOK ) continue;
- // 2. Collect parameters on the track edge
- aPrms.clear();
- aItN = locMeshDS->GetNodes();
- while ( aItN->more() ) {
- const SMDS_MeshNode* pNode = aItN->next();
- const SMDS_EdgePosition* pEPos =
- static_cast<const SMDS_EdgePosition*>( pNode->GetPosition() );
- double aT = pEPos->GetUParameter();
- aPrms.push_back( aT );
- }
- list<SMESH_MeshEditor_PathPoint> LPP;
- //Extrusion_Error err =
- makeEdgePathPoints(aPrms, aTrackEdge, aN1isOK, LPP);
- LLPPs.push_back(LPP);
- UsedNums.Add(k);
- // update startN for search following edge
- if ( aN1isOK ) aVprev = aV2;
- else aVprev = aV1;
- break;
+ if ( theTrackMesh->NbEdges( ORDER_QUADRATIC ) > 0 )
+ {
+ // add medium nodes to pathNodes
+ std::vector< const SMDS_MeshNode* > pathNodes2;
+ std::vector< const SMDS_MeshElement* > pathEdges2;
+ pathNodes2.reserve( pathNodes.size() * 2 );
+ pathEdges2.reserve( pathEdges.size() * 2 );
+ for ( size_t i = 0; i < pathEdges.size(); ++i )
+ {
+ pathNodes2.push_back( pathNodes[i] );
+ pathEdges2.push_back( pathEdges[i] );
+ if ( pathEdges[i]->IsQuadratic() )
+ {
+ pathNodes2.push_back( pathEdges[i]->GetNode(2) );
+ pathEdges2.push_back( pathEdges[i] );
}
}
- list< list<SMESH_MeshEditor_PathPoint> >::iterator itLLPP = LLPPs.begin();
- list<SMESH_MeshEditor_PathPoint>& firstList = *itLLPP;
- fullList.splice( fullList.end(), firstList );
-
- SMESH_MeshEditor_PathPoint PP1 = fullList.back();
- fullList.pop_back();
- itLLPP++;
- for(; itLLPP!=LLPPs.end(); itLLPP++) {
- list<SMESH_MeshEditor_PathPoint>& currList = *itLLPP;
- SMESH_MeshEditor_PathPoint PP2 = currList.front();
- gp_Dir D1 = PP1.Tangent();
- gp_Dir D2 = PP2.Tangent();
- gp_Dir Dnew( D1.XYZ() + D2.XYZ() );
- PP1.SetTangent(Dnew);
- fullList.push_back(PP1);
- fullList.splice( fullList.end(), currList, ++currList.begin(), currList.end() );
- PP1 = fullList.back();
- fullList.pop_back();
- }
- // if wire not closed
- fullList.push_back(PP1);
- // else ???
- }
- else {
- return EXTR_BAD_PATH_SHAPE;
+ pathNodes2.push_back( pathNodes.back() );
+ pathEdges.swap( pathEdges2 );
+ pathNodes.swap( pathNodes2 );
}
- return makeExtrElements(theElements, fullList, theHasAngles, theAngles, theLinearVariation,
- theHasRefPoint, theRefPoint, theMakeGroups);
-}
+ // 3. Get path data at pathNodes
+ std::vector< ExtrusParam::PathPoint > points( pathNodes.size() );
-//=======================================================================
-//function : makeEdgePathPoints
-//purpose : auxiliary for ExtrusionAlongTrack
-//=======================================================================
-SMESH_MeshEditor::Extrusion_Error
-SMESH_MeshEditor::makeEdgePathPoints(std::list<double>& aPrms,
- const TopoDS_Edge& aTrackEdge,
- bool FirstIsStart,
- list<SMESH_MeshEditor_PathPoint>& LPP)
-{
- Standard_Real aTx1, aTx2, aL2, aTolVec, aTolVec2;
- aTolVec=1.e-7;
- aTolVec2=aTolVec*aTolVec;
- double aT1, aT2;
- TopoDS_Vertex aV1, aV2;
- TopExp::Vertices( aTrackEdge, aV1, aV2 );
- aT1=BRep_Tool::Parameter( aV1, aTrackEdge );
- aT2=BRep_Tool::Parameter( aV2, aTrackEdge );
- // 2. Collect parameters on the track edge
- aPrms.push_front( aT1 );
- aPrms.push_back( aT2 );
- // sort parameters
- aPrms.sort();
- if( FirstIsStart ) {
- if ( aT1 > aT2 ) {
- aPrms.reverse();
- }
- }
- else {
- if ( aT2 > aT1 ) {
- aPrms.reverse();
- }
- }
- // 3. Path Points
- SMESH_MeshEditor_PathPoint aPP;
- Handle(Geom_Curve) aC3D = BRep_Tool::Curve( aTrackEdge, aTx1, aTx2 );
- std::list<double>::iterator aItD = aPrms.begin();
- for(; aItD != aPrms.end(); ++aItD) {
- double aT = *aItD;
- gp_Pnt aP3D;
- gp_Vec aVec;
- aC3D->D1( aT, aP3D, aVec );
- aL2 = aVec.SquareMagnitude();
- if ( aL2 < aTolVec2 )
- return EXTR_CANT_GET_TANGENT;
- gp_Dir aTgt( FirstIsStart ? aVec : -aVec );
- aPP.SetPnt( aP3D );
- aPP.SetTangent( aTgt );
- aPP.SetParameter( aT );
- LPP.push_back(aPP);
- }
- return EXTR_OK;
-}
+ if ( theAngleVariation )
+ linearAngleVariation( points.size()-1, theAngles );
+ if ( theScaleVariation )
+ linearScaleVariation( points.size()-1, theScales );
+ theAngles.push_front( 0 ); // for the 1st point that is not transformed
+ std::list<double>::iterator angle = theAngles.begin();
-//=======================================================================
-//function : makeExtrElements
-//purpose : auxiliary for ExtrusionAlongTrack
-//=======================================================================
-SMESH_MeshEditor::Extrusion_Error
-SMESH_MeshEditor::makeExtrElements(TIDSortedElemSet theElemSets[2],
- list<SMESH_MeshEditor_PathPoint>& fullList,
- const bool theHasAngles,
- list<double>& theAngles,
- const bool theLinearVariation,
- const bool theHasRefPoint,
- const gp_Pnt& theRefPoint,
- const bool theMakeGroups)
-{
- const int aNbTP = fullList.size();
+ SMESHDS_Mesh* pathMeshDS = theTrackMesh->GetMeshDS();
- // Angles
- if( theHasAngles && !theAngles.empty() && theLinearVariation )
- linearAngleVariation(aNbTP-1, theAngles);
+ std::map< int, double > edgeID2OriFactor; // orientation of EDGEs
+ std::map< int, double >::iterator id2factor;
+ SMESH_MesherHelper pathHelper( *theTrackMesh );
+ gp_Pnt p; gp_Vec tangent;
+ const double tol2 = gp::Resolution() * gp::Resolution();
- // fill vector of path points with angles
- vector<SMESH_MeshEditor_PathPoint> aPPs;
- list<SMESH_MeshEditor_PathPoint>::iterator itPP = fullList.begin();
- list<double>::iterator itAngles = theAngles.begin();
- aPPs.push_back( *itPP++ );
- for( ; itPP != fullList.end(); itPP++) {
- aPPs.push_back( *itPP );
- if ( theHasAngles && itAngles != theAngles.end() )
- aPPs.back().SetAngle( *itAngles++ );
- }
+ for ( size_t i = 0; i < pathNodes.size(); ++i )
+ {
+ ExtrusParam::PathPoint & point = points[ i ];
- TNodeOfNodeListMap mapNewNodes;
- TElemOfVecOfNnlmiMap mapElemNewNodes;
- TTElemOfElemListMap newElemsMap;
- TIDSortedElemSet::iterator itElem;
- // source elements for each generated one
- SMESH_SequenceOfElemPtr srcElems, srcNodes;
+ point.myPnt = SMESH_NodeXYZ( pathNodes[ i ]);
- // 3. Center of rotation aV0
- gp_Pnt aV0 = theRefPoint;
- if ( !theHasRefPoint )
- {
- gp_XYZ aGC( 0.,0.,0. );
- TIDSortedElemSet newNodes;
+ if ( angle != theAngles.end() )
+ point.myAngle = *angle++;
- for ( int is2ndSet = 0; is2ndSet < 2; ++is2ndSet )
+ tangent.SetCoord( 0,0,0 );
+ const int shapeID = pathNodes[ i ]->GetShapeID();
+ const TopoDS_Shape& shape = pathMeshDS->IndexToShape( shapeID );
+ TopAbs_ShapeEnum shapeType = shape.IsNull() ? TopAbs_SHAPE : shape.ShapeType();
+ switch ( shapeType )
{
- TIDSortedElemSet& theElements = theElemSets[ is2ndSet ];
- itElem = theElements.begin();
- for ( ; itElem != theElements.end(); itElem++ )
+ case TopAbs_EDGE:
+ {
+ TopoDS_Edge edge = TopoDS::Edge( shape );
+ id2factor = edgeID2OriFactor.insert( std::make_pair( shapeID, 0 )).first;
+ if ( id2factor->second == 0 )
{
- const SMDS_MeshElement* elem = *itElem;
- SMDS_ElemIteratorPtr itN = elem->nodesIterator();
- while ( itN->more() ) {
- const SMDS_MeshElement* node = itN->next();
- if ( newNodes.insert( node ).second )
- aGC += SMESH_TNodeXYZ( node );
- }
+ if ( i ) id2factor->second = getOriFactor( edge, pathNodes[i-1], pathNodes[i], pathHelper );
+ else id2factor->second = getOriFactor( edge, pathNodes[i], pathNodes[i+1], pathHelper );
}
+ double u = pathHelper.GetNodeU( edge, pathNodes[i] ), u0, u1;
+ Handle(Geom_Curve) curve = BRep_Tool::Curve( edge, u0, u1 );
+ curve->D1( u, p, tangent );
+ tangent *= id2factor->second;
+ break;
}
- aGC /= newNodes.size();
- aV0.SetXYZ( aGC );
- } // if (!theHasRefPoint) {
-
- // 4. Processing the elements
- SMESHDS_Mesh* aMesh = GetMeshDS();
- list<const SMDS_MeshNode*> emptyList;
-
- setElemsFirst( theElemSets );
- for ( int is2ndSet = 0; is2ndSet < 2; ++is2ndSet )
- {
- TIDSortedElemSet& theElements = theElemSets[ is2ndSet ];
- for ( itElem = theElements.begin(); itElem != theElements.end(); itElem++ )
+ case TopAbs_VERTEX:
{
- const SMDS_MeshElement* elem = *itElem;
-
- vector<TNodeOfNodeListMapItr> & newNodesItVec = mapElemNewNodes[ elem ];
- newNodesItVec.reserve( elem->NbNodes() );
-
- // loop on elem nodes
- int nodeIndex = -1;
- SMDS_ElemIteratorPtr itN = elem->nodesIterator();
- while ( itN->more() )
+ int nbEdges = 0;
+ PShapeIteratorPtr shapeIt = pathHelper.GetAncestors( shape, *theTrackMesh, TopAbs_EDGE );
+ while ( const TopoDS_Shape* edgePtr = shapeIt->next() )
{
- ++nodeIndex;
- // check if a node has been already processed
- const SMDS_MeshNode* node = cast2Node( itN->next() );
- TNodeOfNodeListMap::iterator nIt = mapNewNodes.insert( make_pair( node, emptyList )).first;
- list<const SMDS_MeshNode*>& listNewNodes = nIt->second;
- if ( listNewNodes.empty() )
+ int edgeID = pathMeshDS->ShapeToIndex( *edgePtr );
+ for ( int di = -1; di <= 0; ++di )
{
- // make new nodes
- Standard_Real aAngle1x, aAngleT1T0, aTolAng;
- gp_Pnt aP0x, aP1x, aPN0, aPN1, aV0x, aV1x;
- gp_Ax1 anAx1, anAxT1T0;
- gp_Dir aDT1x, aDT0x, aDT1T0;
-
- aTolAng=1.e-4;
-
- aV0x = aV0;
- aPN0 = SMESH_TNodeXYZ( node );
-
- const SMESH_MeshEditor_PathPoint& aPP0 = aPPs[0];
- aP0x = aPP0.Pnt();
- aDT0x= aPP0.Tangent();
-
- for ( int j = 1; j < aNbTP; ++j ) {
- const SMESH_MeshEditor_PathPoint& aPP1 = aPPs[j];
- aP1x = aPP1.Pnt();
- aDT1x = aPP1.Tangent();
- aAngle1x = aPP1.Angle();
-
- gp_Trsf aTrsf, aTrsfRot, aTrsfRotT1T0;
- // Translation
- gp_Vec aV01x( aP0x, aP1x );
- aTrsf.SetTranslation( aV01x );
-
- // traslated point
- aV1x = aV0x.Transformed( aTrsf );
- aPN1 = aPN0.Transformed( aTrsf );
-
- // rotation 1 [ T1,T0 ]
- aAngleT1T0=-aDT1x.Angle( aDT0x );
- if (fabs(aAngleT1T0) > aTolAng)
+ size_t j = i + di;
+ if ( j < pathEdges.size() && edgeID == pathEdges[ j ]->GetShapeID() )
+ {
+ TopoDS_Edge edge = TopoDS::Edge( *edgePtr );
+ id2factor = edgeID2OriFactor.insert( std::make_pair( edgeID, 0 )).first;
+ if ( id2factor->second == 0 )
{
- aDT1T0=aDT1x^aDT0x;
- anAxT1T0.SetLocation( aV1x );
- anAxT1T0.SetDirection( aDT1T0 );
- aTrsfRotT1T0.SetRotation( anAxT1T0, aAngleT1T0 );
-
- aPN1 = aPN1.Transformed( aTrsfRotT1T0 );
- }
-
- // rotation 2
- if ( theHasAngles ) {
- anAx1.SetLocation( aV1x );
- anAx1.SetDirection( aDT1x );
- aTrsfRot.SetRotation( anAx1, aAngle1x );
-
- aPN1 = aPN1.Transformed( aTrsfRot );
+ if ( j < i )
+ id2factor->second = getOriFactor( edge, pathNodes[i-1], pathNodes[i], pathHelper );
+ else
+ id2factor->second = getOriFactor( edge, pathNodes[i], pathNodes[i+1], pathHelper );
}
-
- // make new node
- if ( elem->IsQuadratic() && !elem->IsMediumNode(node) )
+ double u = pathHelper.GetNodeU( edge, pathNodes[i] ), u0, u1;
+ Handle(Geom_Curve) curve = BRep_Tool::Curve( edge, u0, u1 );
+ gp_Vec du;
+ curve->D1( u, p, du );
+ double size2 = du.SquareMagnitude();
+ if ( du.SquareMagnitude() > tol2 )
{
- // create additional node
- gp_XYZ midP = 0.5 * ( aPN1.XYZ() + aPN0.XYZ() );
- const SMDS_MeshNode* newNode = aMesh->AddNode( midP.X(), midP.Y(), midP.Z() );
- myLastCreatedNodes.push_back(newNode);
- srcNodes.push_back( node );
- listNewNodes.push_back( newNode );
+ tangent += du.Divided( Sqrt( size2 )) * id2factor->second;
+ nbEdges++;
}
- const SMDS_MeshNode* newNode = aMesh->AddNode( aPN1.X(), aPN1.Y(), aPN1.Z() );
- myLastCreatedNodes.push_back(newNode);
- srcNodes.push_back( node );
- listNewNodes.push_back( newNode );
-
- aPN0 = aPN1;
- aP0x = aP1x;
- aV0x = aV1x;
- aDT0x = aDT1x;
+ break;
}
}
- else if( elem->IsQuadratic() && !elem->IsMediumNode(node) )
+ }
+ if ( nbEdges > 0 )
+ break;
+ }
+ // fall through
+ default:
+ {
+ for ( int di = -1; di <= 1; di += 2 )
+ {
+ size_t j = i + di;
+ if ( j < pathNodes.size() )
{
- // if current elem is quadratic and current node is not medium
- // we have to check - may be it is needed to insert additional nodes
- list< const SMDS_MeshNode* > & listNewNodes = nIt->second;
- if ((int) listNewNodes.size() == aNbTP-1 )
- {
- vector<const SMDS_MeshNode*> aNodes(2*(aNbTP-1));
- gp_XYZ P(node->X(), node->Y(), node->Z());
- list< const SMDS_MeshNode* >::iterator it = listNewNodes.begin();
- int i;
- for(i=0; i<aNbTP-1; i++) {
- const SMDS_MeshNode* N = *it;
- double x = ( N->X() + P.X() )/2.;
- double y = ( N->Y() + P.Y() )/2.;
- double z = ( N->Z() + P.Z() )/2.;
- const SMDS_MeshNode* newN = aMesh->AddNode(x,y,z);
- srcNodes.push_back( node );
- myLastCreatedNodes.push_back(newN);
- aNodes[2*i] = newN;
- aNodes[2*i+1] = N;
- P = gp_XYZ(N->X(),N->Y(),N->Z());
- }
- listNewNodes.clear();
- for(i=0; i<2*(aNbTP-1); i++) {
- listNewNodes.push_back(aNodes[i]);
- }
- }
+ gp_Vec dir( point.myPnt, SMESH_NodeXYZ( pathNodes[ j ]));
+ double size2 = dir.SquareMagnitude();
+ if ( size2 > tol2 )
+ tangent += dir.Divided( Sqrt( size2 )) * di;
}
-
- newNodesItVec.push_back( nIt );
}
-
- // make new elements
- sweepElement( elem, newNodesItVec, newElemsMap[elem], aNbTP-1, srcElems );
}
- }
+ } // switch ( shapeType )
- makeWalls( mapNewNodes, newElemsMap, mapElemNewNodes, theElemSets[0], aNbTP-1, srcElems );
+ if ( tangent.SquareMagnitude() < tol2 )
+ return EXTR_CANT_GET_TANGENT;
- if ( theMakeGroups )
- generateGroups( srcNodes, srcElems, "extruded");
+ point.myTgt = tangent;
+
+ } // loop on pathNodes
+
+
+ ExtrusParam nodeMaker( points, theRefPoint, theScales, theMakeGroups );
+ TTElemOfElemListMap newElemsMap;
+
+ ExtrusionSweep( theElements, nodeMaker, newElemsMap );
return EXTR_OK;
}
-
//=======================================================================
//function : linearAngleVariation
//purpose : spread values over nbSteps
}
}
-
+//=======================================================================
+//function : linearScaleVariation
+//purpose : spread values over nbSteps
+//=======================================================================
+
+void SMESH_MeshEditor::linearScaleVariation(const int theNbSteps,
+ std::list<double>& theScales)
+{
+ int nbScales = theScales.size();
+ std::vector<double> myScales;
+ myScales.reserve( theNbSteps );
+ std::list<double>::const_iterator scale = theScales.begin();
+ double prevScale = 1.0;
+ for ( int iSc = 1; scale != theScales.end(); ++scale, ++iSc )
+ {
+ int iStep = int( iSc / double( nbScales ) * theNbSteps + 0.5 );
+ int stDelta = Max( 1, iStep - myScales.size());
+ double scDelta = ( *scale - prevScale ) / stDelta;
+ for ( int iStep = 0; iStep < stDelta; ++iStep )
+ {
+ myScales.push_back( prevScale + scDelta );
+ prevScale = myScales.back();
+ }
+ prevScale = *scale;
+ }
+ theScales.assign( myScales.begin(), myScales.end() );
+}
+
//================================================================================
/*!
* \brief Move or copy theElements applying theTrsf to their nodes
if ( geomType == SMDSGeom_POLYHEDRA ) // ------------------ polyhedral volume
{
- const SMDS_VtkVolume* aPolyedre = dynamic_cast<const SMDS_VtkVolume*>( elem );
- if (!aPolyedre)
+ const SMDS_MeshVolume* aPolyedre = SMDS_Mesh::DownCast< SMDS_MeshVolume >( elem );
+ if ( !aPolyedre )
continue;
nodes.clear();
bool allTransformed = true;
* \param [in] theValue - offset value
* \param [out] theTgtMesh - a mesh to add offset elements to
* \param [in] theMakeGroups - to generate groups
- * \return PGroupIDs - IDs of created groups
+ * \return PGroupIDs - IDs of created groups. NULL means failure
*/
//================================================================================
const double theValue,
SMESH_Mesh* theTgtMesh,
const bool theMakeGroups,
+ const bool theCopyElements,
const bool theFixSelfIntersection)
{
SMESHDS_Mesh* meshDS = GetMeshDS();
if ( theElements.empty() ) eIt = meshDS->elementsIterator( SMDSAbs_Face );
else eIt = SMESHUtils::elemSetIterator( theElements );
- SMESH_MeshAlgos::TEPairVec new2OldFaces;
- SMESH_MeshAlgos::TNPairVec new2OldNodes;
+ SMESH_MeshAlgos::TElemIntPairVec new2OldFaces;
+ SMESH_MeshAlgos::TNodeIntPairVec new2OldNodes;
std::unique_ptr< SMDS_Mesh > offsetMesh
( SMESH_MeshAlgos::MakeOffset( eIt, *meshDS, theValue,
theFixSelfIntersection,
new2OldFaces, new2OldNodes ));
+ if ( offsetMesh->NbElements() == 0 )
+ return PGroupIDs(); // MakeOffset() failed
+
+
+ if ( theTgtMesh == myMesh && !theCopyElements )
+ {
+ // clear the source elements
+ if ( theElements.empty() ) eIt = meshDS->elementsIterator( SMDSAbs_Face );
+ else eIt = SMESHUtils::elemSetIterator( theElements );
+ while ( eIt->more() )
+ meshDS->RemoveFreeElement( eIt->next(), 0 );
+ }
- offsetMesh->Modified();
- offsetMesh->CompactMesh(); // make IDs start from 1
+ // offsetMesh->Modified();
+ // offsetMesh->CompactMesh(); // make IDs start from 1
// source elements for each generated one
SMESH_SequenceOfElemPtr srcElems, srcNodes;
// copy offsetMesh to theTgtMesh
- int idShift = meshDS->MaxNodeID();
+ smIdType idShift = meshDS->MaxNodeID();
for ( size_t i = 0; i < new2OldNodes.size(); ++i )
if ( const SMDS_MeshNode* n = new2OldNodes[ i ].first )
{
+#ifndef _DEBUG_
if ( n->NbInverseElements() > 0 )
+#endif
{
const SMDS_MeshNode* n2 =
tgtMeshDS->AddNodeWithID( n->X(), n->Y(), n->Z(), idShift + n->GetID() );
myLastCreatedNodes.push_back( n2 );
- srcNodes.push_back( new2OldNodes[ i ].second );
+ srcNodes.push_back( meshDS->FindNode( new2OldNodes[ i ].second ));
}
}
elemType.myNodes.push_back( tgtMeshDS->FindNode( idShift + n2->GetID() ));
}
tgtEditor.AddElement( elemType.myNodes, elemType );
- srcElems.push_back( new2OldFaces[ i ].second );
+ srcElems.push_back( meshDS->FindElement( new2OldFaces[ i ].second ));
}
myLastCreatedElems.swap( tgtEditor.myLastCreatedElems );
PGroupIDs newGroupIDs;
if ( theMakeGroups )
newGroupIDs = generateGroups( srcNodes, srcElems, "offset", theTgtMesh, false );
+ else
+ newGroupIDs.reset( new std::list< int > );
return newGroupIDs;
}
if ( theNodes.empty() ) // get all nodes in the mesh
{
TIDSortedNodeSet* nodes[2] = { &corners, &medium };
- SMDS_NodeIteratorPtr nIt = GetMeshDS()->nodesIterator(/*idInceasingOrder=*/true);
+ SMDS_NodeIteratorPtr nIt = GetMeshDS()->nodesIterator();
if ( theSeparateCornersAndMedium )
while ( nIt->more() )
{
TNodeNodeMap nodeNodeMap; // node to replace - new node
set<const SMDS_MeshElement*> elems; // all elements with changed nodes
- list< int > rmElemIds, rmNodeIds;
+ list< smIdType > rmElemIds, rmNodeIds;
vector< ElemFeatures > newElemDefs;
// Fill nodeNodeMap and elems
const SMDS_MeshNode* nToKeep = nnIt->second;
TNodeNodeMap::iterator nnIt_i = nodeNodeMap.find( nToKeep );
while ( nnIt_i != nodeNodeMap.end() && nnIt_i->second != nnIt->second )
+ {
nToKeep = nnIt_i->second;
- nnIt->second = nToKeep;
+ nnIt->second = nToKeep;
+ nnIt_i = nodeNodeMap.find( nToKeep );
+ }
}
if ( theAvoidMakingHoles )
AddToSameGroups( nToKeep, nToRemove, mesh );
// set _alwaysComputed to a sub-mesh of VERTEX to enable further mesh computing
// w/o creating node in place of merged ones.
- const SMDS_PositionPtr& pos = nToRemove->GetPosition();
+ SMDS_PositionPtr pos = nToRemove->GetPosition();
if ( pos && pos->GetTypeOfPosition() == SMDS_TOP_VERTEX )
if ( SMESH_subMesh* sm = myMesh->GetSubMeshContaining( nToRemove->getshapeId() ))
sm->SetIsAlwaysComputed( true );
for ( size_t i = 0; i < newElemDefs.size(); ++i )
{
- if ( i > 0 || !mesh->ChangeElementNodes( elem,
- & newElemDefs[i].myNodes[0],
- newElemDefs[i].myNodes.size() ))
+ bool elemChanged = false;
+ if ( i == 0 )
+ {
+ if ( elem->GetGeomType() == SMDSGeom_POLYHEDRA )
+ elemChanged = mesh->ChangePolyhedronNodes( elem,
+ newElemDefs[i].myNodes,
+ newElemDefs[i].myPolyhedQuantities );
+ else
+ elemChanged = mesh->ChangeElementNodes( elem,
+ & newElemDefs[i].myNodes[0],
+ newElemDefs[i].myNodes.size() );
+ }
+ if ( i > 0 || !elemChanged )
{
if ( i == 0 )
{
if ( nbUniqueNodes >= 4 )
{
// each face has to be analyzed in order to check volume validity
- if ( const SMDS_VtkVolume* aPolyedre = dynamic_cast<const SMDS_VtkVolume*>( elem ))
+ if ( const SMDS_MeshVolume* aPolyedre = SMDS_Mesh::DownCast< SMDS_MeshVolume >( elem ))
{
+ toRemove = false;
int nbFaces = aPolyedre->NbFaces();
vector<const SMDS_MeshNode *>& poly_nodes = newElemDefs[0].myNodes;
// purpose : allow comparing elements basing on their nodes
// ========================================================
-class ComparableElement : public boost::container::flat_set< int >
+class ComparableElement : public boost::container::flat_set< smIdType >
{
- typedef boost::container::flat_set< int > int_set;
+ typedef boost::container::flat_set< smIdType > int_set;
const SMDS_MeshElement* myElem;
- int mySumID;
+ smIdType mySumID;
mutable int myGroupID;
public:
this->reserve( theElem->NbNodes() );
for ( SMDS_ElemIteratorPtr nodeIt = theElem->nodesIterator(); nodeIt->more(); )
{
- int id = nodeIt->next()->GetID();
+ smIdType id = nodeIt->next()->GetID();
mySumID += id;
this->insert( id );
}
//int& GroupID() const { return const_cast< int& >( myGroupID ); }
ComparableElement( const ComparableElement& theSource ) // move copy
+ : int_set()
{
ComparableElement& src = const_cast< ComparableElement& >( theSource );
- (int_set&) (*this ) = boost::move( src );
+ (int_set&) (*this ) = std::move( src );
myElem = src.myElem;
mySumID = src.mySumID;
myGroupID = src.myGroupID;
static int HashCode(const ComparableElement& se, int limit )
{
- return ::HashCode( se.mySumID, limit );
+ return ::HashCode( FromSmIdType<int>(se.mySumID), limit );
}
static Standard_Boolean IsEqual(const ComparableElement& se1, const ComparableElement& se2 )
{
else elemIt = SMESHUtils::elemSetIterator( theElements );
typedef NCollection_Map< ComparableElement, ComparableElement > TMapOfElements;
- typedef std::list<int> TGroupOfElems;
+ typedef std::list<smIdType> TGroupOfElems;
TMapOfElements mapOfElements;
std::vector< TGroupOfElems > arrayOfGroups;
TGroupOfElems groupOfElems;
while ( elemIt->more() )
{
const SMDS_MeshElement* curElem = elemIt->next();
+ if ( curElem->IsNull() )
+ continue;
ComparableElement compElem = curElem;
// check uniqueness
const ComparableElement& elemInSet = mapOfElements.Added( compElem );
{
ClearLastCreated();
- typedef list<int> TListOfIDs;
+ typedef list<smIdType> TListOfIDs;
TListOfIDs rmElemIds; // IDs of elems to remove
SMESHDS_Mesh* aMesh = GetMeshDS();
theNodes.push_back( theSecondNode );
const SMDS_MeshNode *nIgnore = theFirstNode, *nStart = theSecondNode;
- TIDSortedElemSet foundElems;
+ //TIDSortedElemSet foundElems;
bool needTheLast = ( theLastNode != 0 );
+ vector<const SMDS_MeshNode*> nodes;
+
while ( nStart != theLastNode ) {
if ( nStart == theFirstNode )
return !needTheLast;
- // find all free border faces sharing form nStart
+ // find all free border faces sharing nStart
list< const SMDS_MeshElement* > curElemList;
list< const SMDS_MeshNode* > nStartList;
SMDS_ElemIteratorPtr invElemIt = nStart->GetInverseElementIterator(SMDSAbs_Face);
while ( invElemIt->more() ) {
const SMDS_MeshElement* e = invElemIt->next();
- if ( e == curElem || foundElems.insert( e ).second ) {
+ //if ( e == curElem || foundElems.insert( e ).second ) // e can encounter twice in border
+ {
// get nodes
- int iNode = 0, nbNodes = e->NbNodes();
- vector<const SMDS_MeshNode*> nodes(nbNodes+1);
-
- if ( e->IsQuadratic() ) {
- const SMDS_VtkFace* F =
- dynamic_cast<const SMDS_VtkFace*>(e);
- if (!F) throw SALOME_Exception(LOCALIZED("not an SMDS_VtkFace"));
- // use special nodes iterator
- SMDS_ElemIteratorPtr anIter = F->interlacedNodesElemIterator();
- while( anIter->more() ) {
- nodes[ iNode++ ] = cast2Node(anIter->next());
- }
- }
- else {
- SMDS_ElemIteratorPtr nIt = e->nodesIterator();
- while ( nIt->more() )
- nodes[ iNode++ ] = static_cast<const SMDS_MeshNode*>( nIt->next() );
- }
- nodes[ iNode ] = nodes[ 0 ];
+ nodes.assign( SMDS_MeshElement::iterator( e->interlacedNodesIterator() ),
+ SMDS_MeshElement::iterator() );
+ nodes.push_back( nodes[ 0 ]);
+
// check 2 links
+ int iNode = 0, nbNodes = nodes.size() - 1;
for ( iNode = 0; iNode < nbNodes; iNode++ )
- if (((nodes[ iNode ] == nStart && nodes[ iNode + 1] != nIgnore ) ||
- (nodes[ iNode + 1] == nStart && nodes[ iNode ] != nIgnore )) &&
- ControlFreeBorder( &nodes[ iNode ], e->GetID() ))
+ if ((( nodes[ iNode ] == nStart && nodes[ iNode + 1] != nIgnore ) ||
+ ( nodes[ iNode + 1] == nStart && nodes[ iNode ] != nIgnore )) &&
+ ( ControlFreeBorder( &nodes[ iNode ], e->GetID() )))
{
- nStartList.push_back( nodes[ iNode + ( nodes[ iNode ] == nStart ? 1 : 0 )]);
+ nStartList.push_back( nodes[ iNode + ( nodes[ iNode ] == nStart )]);
curElemList.push_back( e );
}
}
else if ( !contNodes[0].empty() && !contNodes[1].empty() ) {
// choice: clear a worse one
int iLongest = ( contNodes[0].size() < contNodes[1].size() ? 1 : 0 );
- int iWorse = ( needTheLast ? 1 - iLongest : iLongest );
+ int iWorse = ( needTheLast ? 1 - iLongest : iLongest );
contNodes[ iWorse ].clear();
contFaces[ iWorse ].clear();
}
// push_back the best free border
cNL = & contNodes[ contNodes[0].empty() ? 1 : 0 ];
cFL = & contFaces[ contFaces[0].empty() ? 1 : 0 ];
- theNodes.pop_back(); // remove nIgnore
+ //theNodes.pop_back(); // remove nIgnore
theNodes.pop_back(); // remove nStart
- theFaces.pop_back(); // remove curElem
- list< const SMDS_MeshNode* >::iterator nIt = cNL->begin();
- list< const SMDS_MeshElement* >::iterator fIt = cFL->begin();
- for ( ; nIt != cNL->end(); nIt++ ) theNodes.push_back( *nIt );
- for ( ; fIt != cFL->end(); fIt++ ) theFaces.push_back( *fIt );
+ //theFaces.pop_back(); // remove curElem
+ theNodes.splice( theNodes.end(), *cNL );
+ theFaces.splice( theFaces.end(), *cFL );
return true;
} // several continuations found
const SMDS_MeshNode** nodes = isVolume ? volume.GetNodes() : & faceNodes[0];
if ( isVolume ) // --volume
hasVolumes = true;
- else if ( elem->GetType()==SMDSAbs_Face ) { // --face
+ else if ( elem->GetType() == SMDSAbs_Face ) { // --face
// retrieve all face nodes and find iPrevNode - an index of the prevSideNode
- if(elem->IsQuadratic()) {
- const SMDS_VtkFace* F =
- dynamic_cast<const SMDS_VtkFace*>(elem);
- if (!F) throw SALOME_Exception(LOCALIZED("not an SMDS_VtkFace"));
- // use special nodes iterator
- SMDS_ElemIteratorPtr anIter = F->interlacedNodesElemIterator();
- while( anIter->more() ) {
- nodes[ iNode ] = cast2Node(anIter->next());
- if ( nodes[ iNode++ ] == prevSideNode )
- iPrevNode = iNode - 1;
- }
- }
- else {
- SMDS_ElemIteratorPtr nIt = elem->nodesIterator();
- while ( nIt->more() ) {
- nodes[ iNode ] = cast2Node( nIt->next() );
- if ( nodes[ iNode++ ] == prevSideNode )
- iPrevNode = iNode - 1;
- }
+ SMDS_NodeIteratorPtr nIt = elem->interlacedNodesIterator();
+ while ( nIt->more() ) {
+ nodes[ iNode ] = cast2Node( nIt->next() );
+ if ( nodes[ iNode++ ] == prevSideNode )
+ iPrevNode = iNode - 1;
}
// there are 2 links to check
nbNodes = 2;
nIt[0] = nSide[0].begin(); eIt[0] = eSide[0].begin();
nIt[1] = nSide[1].begin(); eIt[1] = eSide[1].begin();
+ // element can be split while iterating on border if it has two edges in the border
+ std::map< const SMDS_MeshElement* , const SMDS_MeshElement* > elemReplaceMap;
+ std::map< const SMDS_MeshElement* , const SMDS_MeshElement* >::iterator elemReplaceMapIt;
+
TElemOfNodeListMap insertMap;
TElemOfNodeListMap::iterator insertMapIt;
// insertMap is
const SMDS_MeshNode* nIns = *nIt [ 1 - intoBord ];
if ( intoBord == 1 ) {
// move node of the border to be on a link of elem of the side
- gp_XYZ p1 (n1->X(), n1->Y(), n1->Z());
- gp_XYZ p2 (n2->X(), n2->Y(), n2->Z());
+ SMESH_NodeXYZ p1( n1 ), p2( n2 );
double ratio = du / ( param[ 1 ][ i[1] ] - param[ 1 ][ i[1]-1 ]);
gp_XYZ p = p2 * ( 1 - ratio ) + p1 * ratio;
GetMeshDS()->MoveNode( nIns, p.X(), p.Y(), p.Z() );
}
+ elemReplaceMapIt = elemReplaceMap.find( elem );
+ if ( elemReplaceMapIt != elemReplaceMap.end() )
+ elem = elemReplaceMapIt->second;
+
insertMapIt = insertMap.find( elem );
bool notFound = ( insertMapIt == insertMap.end() );
bool otherLink = ( !notFound && (*insertMapIt).second.front() != n1 );
UpdateVolumes(n12, n22, nodeList);
}
// 3. find an element appeared on n1 and n2 after the insertion
- insertMap.erase( elem );
- elem = findAdjacentFace( n1, n2, 0 );
+ insertMap.erase( insertMapIt );
+ const SMDS_MeshElement* elem2 = findAdjacentFace( n1, n2, 0 );
+ elemReplaceMap.insert( std::make_pair( elem, elem2 ));
+ elem = elem2;
}
if ( notFound || otherLink ) {
// add element and nodes of the side into the insertMap
{
const SMDS_MeshElement* elem = (*insertMapIt).first;
list<const SMDS_MeshNode*> & nodeList = (*insertMapIt).second;
+ if ( nodeList.size() < 3 ) continue;
const SMDS_MeshNode* n1 = nodeList.front(); nodeList.pop_front();
const SMDS_MeshNode* n2 = nodeList.front(); nodeList.pop_front();
for ( ; groupIt != nodeGroupsToMerge.end(); groupIt++ )
{
const list<const SMDS_MeshNode*>& nodes = *groupIt;
+ if ( nodes.front()->IsNull() ) continue;
SMDS_ElemIteratorPtr segIt = nodes.front()->GetInverseElementIterator( SMDSAbs_Edge );
while ( segIt->more() )
segments.insert( segIt->next() );
TListOfListOfElementsID::iterator itGroups = equalGroups.begin();
for ( ; itGroups != equalGroups.end(); ++itGroups )
{
- list< int >& group = *itGroups;
- list< int >::iterator id = group.begin();
+ list< smIdType >& group = *itGroups;
+ list< smIdType >::iterator id = group.begin();
for ( ++id; id != group.end(); ++id )
if ( const SMDS_MeshElement* seg = GetMeshDS()->FindElement( *id ))
segments.erase( seg );
// add nodes of face up to first node of link
bool isFLN = false;
-
- if ( theFace->IsQuadratic() ) {
- const SMDS_VtkFace* F = dynamic_cast<const SMDS_VtkFace*>(theFace);
- if (!F) throw SALOME_Exception(LOCALIZED("not an SMDS_VtkFace"));
- // use special nodes iterator
- SMDS_ElemIteratorPtr anIter = F->interlacedNodesElemIterator();
- while( anIter->more() && !isFLN ) {
- const SMDS_MeshNode* n = cast2Node(anIter->next());
- poly_nodes[iNode++] = n;
- if (n == nodes[il1]) {
- isFLN = true;
- }
- }
- // add nodes to insert
- list<const SMDS_MeshNode*>::iterator nIt = aNodesToInsert.begin();
- for (; nIt != aNodesToInsert.end(); nIt++) {
- poly_nodes[iNode++] = *nIt;
- }
- // add nodes of face starting from last node of link
- while ( anIter->more() ) {
- poly_nodes[iNode++] = cast2Node(anIter->next());
- }
+ SMDS_NodeIteratorPtr nodeIt = theFace->interlacedNodesIterator();
+ while ( nodeIt->more() && !isFLN ) {
+ const SMDS_MeshNode* n = nodeIt->next();
+ poly_nodes[iNode++] = n;
+ isFLN = ( n == nodes[il1] );
}
- else {
- SMDS_ElemIteratorPtr nodeIt = theFace->nodesIterator();
- while ( nodeIt->more() && !isFLN ) {
- const SMDS_MeshNode* n = static_cast<const SMDS_MeshNode*>( nodeIt->next() );
- poly_nodes[iNode++] = n;
- if (n == nodes[il1]) {
- isFLN = true;
- }
- }
- // add nodes to insert
- list<const SMDS_MeshNode*>::iterator nIt = aNodesToInsert.begin();
- for (; nIt != aNodesToInsert.end(); nIt++) {
- poly_nodes[iNode++] = *nIt;
- }
- // add nodes of face starting from last node of link
- while ( nodeIt->more() ) {
- const SMDS_MeshNode* n = static_cast<const SMDS_MeshNode*>( nodeIt->next() );
- poly_nodes[iNode++] = n;
- }
+ // add nodes to insert
+ list<const SMDS_MeshNode*>::iterator nIt = aNodesToInsert.begin();
+ for (; nIt != aNodesToInsert.end(); nIt++) {
+ poly_nodes[iNode++] = *nIt;
+ }
+ // add nodes of face starting from last node of link
+ while ( nodeIt->more() ) {
+ const SMDS_MeshNode* n = static_cast<const SMDS_MeshNode*>( nodeIt->next() );
+ poly_nodes[iNode++] = n;
}
// make a new face
*/
//=======================================================================
-int SMESH_MeshEditor::convertElemToQuadratic(SMESHDS_SubMesh * theSm,
- SMESH_MesherHelper& theHelper,
- const bool theForce3d)
+smIdType SMESH_MeshEditor::convertElemToQuadratic(SMESHDS_SubMesh * theSm,
+ SMESH_MesherHelper& theHelper,
+ const bool theForce3d)
{
//MESSAGE("convertElemToQuadratic");
- int nbElem = 0;
+ smIdType nbElem = 0;
if( !theSm ) return nbElem;
vector<int> nbNodeInFaces;
}
// get elem data needed to re-create it
//
- const int id = elem->GetID();
+ const smIdType id = elem->GetID();
const int nbNodes = elem->NbCornerNodes();
nodes.assign(elem->begin_nodes(), elem->end_nodes());
if ( aGeomType == SMDSEntity_Polyhedra )
- nbNodeInFaces = static_cast<const SMDS_VtkVolume* >( elem )->GetQuantities();
+ nbNodeInFaces = static_cast<const SMDS_MeshVolume* >( elem )->GetQuantities();
else if ( aGeomType == SMDSEntity_Hexagonal_Prism )
volumeToPolyhedron( elem, nodes, nbNodeInFaces );
aHelper.ToFixNodeParameters( true );
// convert elements assigned to sub-meshes
- int nbCheckedElems = 0;
+ smIdType nbCheckedElems = 0;
if ( myMesh->HasShapeToMesh() )
{
if ( SMESH_subMesh *aSubMesh = myMesh->GetSubMeshContaining(myMesh->GetShapeToMesh()))
}
// convert elements NOT assigned to sub-meshes
- int totalNbElems = meshDS->NbEdges() + meshDS->NbFaces() + meshDS->NbVolumes();
+ smIdType totalNbElems = meshDS->NbEdges() + meshDS->NbFaces() + meshDS->NbVolumes();
if ( nbCheckedElems < totalNbElems ) // not all elements are in sub-meshes
{
aHelper.SetElementsOnShape(false);
const SMDS_MeshEdge* edge = aEdgeItr->next();
if ( !edge->IsQuadratic() )
{
- int id = edge->GetID();
+ smIdType id = edge->GetID();
const SMDS_MeshNode* n1 = edge->GetNode(0);
const SMDS_MeshNode* n2 = edge->GetNode(1);
if ( alreadyOK )
continue;
- const int id = face->GetID();
+ const smIdType id = face->GetID();
vector<const SMDS_MeshNode *> nodes ( face->begin_nodes(), face->end_nodes());
meshDS->RemoveFreeElement(face, smDS, /*fromGroups=*/false);
continue;
}
}
- const int id = volume->GetID();
+ const smIdType id = volume->GetID();
vector<const SMDS_MeshNode *> nodes (volume->begin_nodes(), volume->end_nodes());
if ( type == SMDSEntity_Polyhedra )
- nbNodeInFaces = static_cast<const SMDS_VtkVolume* >(volume)->GetQuantities();
+ nbNodeInFaces = static_cast<const SMDS_MeshVolume* >(volume)->GetQuantities();
else if ( type == SMDSEntity_Hexagonal_Prism )
volumeToPolyhedron( volume, nodes, nbNodeInFaces );
if ( alreadyOK ) continue;
const SMDSAbs_ElementType type = elem->GetType();
- const int id = elem->GetID();
+ const smIdType id = elem->GetID();
const int nbNodes = elem->NbCornerNodes();
vector<const SMDS_MeshNode *> nodes ( elem->begin_nodes(), elem->end_nodes());
//=======================================================================
/*!
* \brief Convert quadratic elements to linear ones and remove quadratic nodes
- * \return int - nb of checked elements
+ * \return smIdType - nb of checked elements
*/
//=======================================================================
-int SMESH_MeshEditor::removeQuadElem(SMESHDS_SubMesh * theSm,
- SMDS_ElemIteratorPtr theItr,
- const int theShapeID)
+smIdType SMESH_MeshEditor::removeQuadElem(SMESHDS_SubMesh * theSm,
+ SMDS_ElemIteratorPtr theItr,
+ const int /*theShapeID*/)
{
- int nbElem = 0;
+ smIdType nbElem = 0;
SMESHDS_Mesh* meshDS = GetMeshDS();
ElemFeatures elemType;
vector<const SMDS_MeshNode *> nodes;
bool SMESH_MeshEditor::ConvertFromQuadratic()
{
- int nbCheckedElems = 0;
+ smIdType nbCheckedElems = 0;
if ( myMesh->HasShapeToMesh() )
{
if ( SMESH_subMesh *aSubMesh = myMesh->GetSubMeshContaining(myMesh->GetShapeToMesh()))
}
}
- int totalNbElems =
+ smIdType totalNbElems =
GetMeshDS()->NbEdges() + GetMeshDS()->NbFaces() + GetMeshDS()->NbVolumes();
if ( nbCheckedElems < totalNbElems ) // not all elements are in submeshes
{
if ( theElements.empty() ) return;
// collect IDs of medium nodes of theElements; some of these nodes will be removed
- set<int> mediumNodeIDs;
+ set<smIdType> mediumNodeIDs;
TIDSortedElemSet::iterator eIt = theElements.begin();
for ( ; eIt != theElements.end(); ++eIt )
{
// get remaining medium nodes
TIDSortedNodeSet mediumNodes;
- set<int>::iterator nIdsIt = mediumNodeIDs.begin();
+ set<smIdType>::iterator nIdsIt = mediumNodeIDs.begin();
for ( ; nIdsIt != mediumNodeIDs.end(); ++nIdsIt )
if ( const SMDS_MeshNode* n = GetMeshDS()->FindNode( *nIdsIt ))
mediumNodes.insert( mediumNodes.end(), n );
const SMDS_MeshElement* eComplex = invIt2->next();
if ( eComplex->IsQuadratic() && !allMediumNodesIn( eComplex, mediumNodes))
{
- int nbCommonNodes = SMESH_MeshAlgos::GetCommonNodes( e, eComplex ).size();
+ int nbCommonNodes = SMESH_MeshAlgos::NbCommonNodes( e, eComplex );
if ( nbCommonNodes == e->NbNodes())
{
complexFound = true;
//cout << " F " << face[ iSide]->GetID() <<endl;
faceSetPtr[ iSide ]->erase( face[ iSide ]);
// put face nodes to fnodes
- if ( face[ iSide ]->IsQuadratic() )
- {
- // use interlaced nodes iterator
- const SMDS_VtkFace* F = dynamic_cast<const SMDS_VtkFace*>( face[ iSide ]);
- if (!F) throw SALOME_Exception(LOCALIZED("not an SMDS_VtkFace"));
- SMDS_ElemIteratorPtr nIter = F->interlacedNodesElemIterator();
- while ( nIter->more() )
- fnodes[ iSide ].push_back( cast2Node( nIter->next() ));
- }
- else
- {
- fnodes[ iSide ].assign( face[ iSide ]->begin_nodes(),
- face[ iSide ]->end_nodes() );
- }
+ SMDS_MeshElement::iterator nIt( face[ iSide ]->interlacedNodesIterator() ), nEnd;
+ fnodes[ iSide ].assign( nIt, nEnd );
fnodes[ iSide ].push_back( fnodes[ iSide ].front());
}
}
if ( aResult != SEW_OK)
return aResult;
- list< int > nodeIDsToRemove;
+ list< smIdType > nodeIDsToRemove;
vector< const SMDS_MeshNode*> nodes;
ElemFeatures elemType;
set<const SMDS_MeshElement*> * faceSetPtr[] = { &theSide1, &theSide2 };
nReplaceMap.clear();
- if ( theFirstNode1 != theFirstNode2 )
- nReplaceMap.insert( make_pair( theFirstNode1, theFirstNode2 ));
- if ( theSecondNode1 != theSecondNode2 )
- nReplaceMap.insert( make_pair( theSecondNode1, theSecondNode2 ));
+ //if ( theFirstNode1 != theFirstNode2 )
+ nReplaceMap.insert( make_pair( theFirstNode1, theFirstNode2 ));
+ //if ( theSecondNode1 != theSecondNode2 )
+ nReplaceMap.insert( make_pair( theSecondNode1, theSecondNode2 ));
set< SMESH_TLink > linkSet; // set of nodes where order of nodes is ignored
linkSet.insert( SMESH_TLink( theFirstNode1, theSecondNode1 ));
if ( SMESH_MeshAlgos::FaceNormal( _elems[1], norm ))
avgNorm += norm;
- gp_XYZ bordDir( SMESH_NodeXYZ( _nodes[0] ) - SMESH_NodeXYZ( _nodes[1] ));
+ gp_XYZ bordDir( SMESH_NodeXYZ( this->_nodes[0] ) - SMESH_NodeXYZ( this->_nodes[1] ));
norm = bordDir ^ avgNorm;
}
else
if ( maxX < 0 )
{
_elems[0]->setIsMarked( false );
- _elems[1]->setIsMarked( true );
+ if ( _elems[1] )
+ _elems[1]->setIsMarked( true );
}
}
{
fissure.reserve( theElemsOrNodes.size() );
for ( ; elIt != theElemsOrNodes.end(); ++elIt )
+ {
fissure.push_back( std::move( FissureBorder( *elIt, elemsByFacet )));
+ if ( !fissure.back()._elems[1] )
+ fissure.pop_back();
+ }
}
if ( fissure.empty() )
return;
if ( mesh->GetMeshInfo().NbElements( types[i] ))
{
type = types[i];
+ elemIt = mesh->elementsIterator( type );
break;
}
- elemIt = mesh->elementsIterator( type );
}
else
{
- type = (*theElements.begin())->GetType();
+ //type = (*theElements.begin())->GetType();
elemIt = SMESHUtils::elemSetIterator( theElements );
}
while ( elemIt->more() )
{
const SMDS_MeshElement* elem = elemIt->next();
- if ( elem->GetType() != type || elem->isMarked() )
+ if (( type != SMDSAbs_All && elem->GetType() != type ) ||
+ ( elem->isMarked() ))
continue;
elemType.Init( elem, /*basicOnly=*/false );
const double theTol)
{
gp_XYZ centerXYZ (0, 0, 0);
- SMDS_ElemIteratorPtr aNodeItr = theElem->nodesIterator();
- while ( aNodeItr->more() )
+ for ( SMDS_ElemIteratorPtr aNodeItr = theElem->nodesIterator(); aNodeItr->more(); )
centerXYZ += SMESH_NodeXYZ( aNodeItr->next() );
gp_Pnt aPnt = centerXYZ / theElem->NbNodes();
\brief Identify the elements that will be affected by node duplication (actual duplication is not performed).
This method is the first step of DoubleNodeElemGroupsInRegion.
\param theElems - list of groups of elements (edges or faces) to be replicated
- \param theNodesNot - list of groups of nodes not to replicated
+ \param theNodesNot - list of groups of nodes not to replicate
\param theShape - shape to detect affected elements (element which geometric center
located on or inside shape). If the shape is null, detection is done on faces orientations
(select elements with a gravity center on the side given by faces normals).
else
{
const double aTol = Precision::Confusion();
- auto_ptr< BRepClass3d_SolidClassifier> bsc3d;
- auto_ptr<_FaceClassifier> aFaceClassifier;
+ std::unique_ptr< BRepClass3d_SolidClassifier> bsc3d;
+ std::unique_ptr<_FaceClassifier> aFaceClassifier;
if ( theShape.ShapeType() == TopAbs_SOLID )
{
bsc3d.reset( new BRepClass3d_SolidClassifier(theShape));;
try {
return n2.AngleWithRef(n1, vref);
}
- catch ( Standard_Failure ) {
+ catch ( Standard_Failure& ) {
}
return Max( v1.Magnitude(), v2.Magnitude() );
}
SMESHDS_Mesh *meshDS = this->myMesh->GetMeshDS();
meshDS->BuildDownWardConnectivity(true);
CHRONO(50);
- SMDS_UnstructuredGrid *grid = meshDS->getGrid();
+ SMDS_UnstructuredGrid *grid = meshDS->GetGrid();
// --- build the list of faces shared by 2 domains (group of elements), with their domain and volume indexes
// build the list of cells with only a node or an edge on the border, with their domain and volume indexes
// build the list of nodes shared by 2 or more domains, with their domain indexes
std::map<DownIdType, std::map<int,int>, DownIdCompare> faceDomains; // face --> (id domain --> id volume)
- std::map<int,int>celldom; // cell vtkId --> domain
+ std::map<int,int> celldom; // cell vtkId --> domain
std::map<DownIdType, std::map<int,int>, DownIdCompare> cellDomains; // oldNode --> (id domain --> id cell)
std::map<int, std::map<int,int> > nodeDomains; // oldId --> (domainId --> newId)
- faceDomains.clear();
- celldom.clear();
- cellDomains.clear();
- nodeDomains.clear();
- std::map<int,int> emptyMap;
- std::set<int> emptySet;
- emptyMap.clear();
//MESSAGE(".. Number of domains :"<<theElems.size());
const SMDS_MeshElement* anElem = *elemItr;
if (!anElem)
continue;
- int vtkId = anElem->getVtkId();
+ vtkIdType vtkId = anElem->GetVtkID();
//MESSAGE(" vtkId " << vtkId << " smdsId " << anElem->GetID());
int neighborsVtkIds[NBMAXNEIGHBORS];
int downIds[NBMAXNEIGHBORS];
int nbNeighbors = grid->GetNeighbors(neighborsVtkIds, downIds, downTypes, vtkId);
for (int n = 0; n < nbNeighbors; n++)
{
- int smdsId = meshDS->fromVtkToSmds(neighborsVtkIds[n]);
+ smIdType smdsId = meshDS->FromVtkToSmds(neighborsVtkIds[n]);
const SMDS_MeshElement* elem = meshDS->FindElement(smdsId);
if (elem && ! domain.count(elem)) // neighbor is in another domain : face is shared
{
DownIdType face = itface->first;
//MESSAGE(" --- face " << face.cellId);
std::set<int> oldNodes;
- oldNodes.clear();
grid->GetNodeIds(oldNodes, face.cellId, face.cellType);
std::set<int>::iterator itn = oldNodes.begin();
for (; itn != oldNodes.end(); ++itn)
{
int oldId = *itn;
//MESSAGE(" node " << oldId);
- vtkCellLinks::Link l = grid->GetCellLinks()->GetLink(oldId);
+ vtkCellLinks::Link l = (static_cast <vtkCellLinks *>(grid->GetCellLinks()))->GetLink(oldId);
for (int i=0; i<l.ncells; i++)
{
int vtkId = l.cells[i];
- const SMDS_MeshElement* anElem = GetMeshDS()->FindElement(GetMeshDS()->fromVtkToSmds(vtkId));
+ const SMDS_MeshElement* anElem = GetMeshDS()->FindElement(GetMeshDS()->FromVtkToSmds(vtkId));
if (!domain.count(anElem))
continue;
int vtkType = grid->GetCellType(vtkId);
DownIdType face = itface->first;
//MESSAGE(" --- face " << face.cellId);
std::set<int> oldNodes;
- oldNodes.clear();
grid->GetNodeIds(oldNodes, face.cellId, face.cellType);
std::set<int>::iterator itn = oldNodes.begin();
for (; itn != oldNodes.end(); ++itn)
double *coords = grid->GetPoint(oldId);
SMDS_MeshNode *newNode = meshDS->AddNode(coords[0], coords[1], coords[2]);
copyPosition( meshDS->FindNodeVtk( oldId ), newNode );
- int newId = newNode->getVtkId();
+ int newId = newNode->GetVtkID();
nodeDomains[oldId][idom] = newId; // cloned node for other domains
//MESSAGE("-+-+-c oldNode " << oldId << " domain " << idomain << " newNode " << newId << " domain " << idom << " size=" <<nodeDomains[oldId].size());
}
DownIdType face = itface->first;
//MESSAGE(" --- face " << face.cellId);
std::set<int> oldNodes;
- oldNodes.clear();
grid->GetNodeIds(oldNodes, face.cellId, face.cellType);
int nbMultipleNodes = 0;
std::set<int>::iterator itn = oldNodes.begin();
gp_Pnt p1(coords[0], coords[1], coords[2]);
gp_Pnt gref;
int vtkVolIds[1000]; // an edge can belong to a lot of volumes
- map<int, SMDS_VtkVolume*> domvol; // domain --> a volume with the edge
+ map<int, SMDS_MeshVolume*> domvol; // domain --> a volume with the edge
map<int, double> angleDom; // oriented angles between planes defined by edge and volume centers
int nbvol = grid->GetParentVolumes(vtkVolIds, downEdgeIds[ie], edgeType[ie]);
for ( size_t id = 0; id < doms.size(); id++ )
const TIDSortedElemSet& domain = (idom == iRestDom) ? theRestDomElems : theElems[idom];
for ( int ivol = 0; ivol < nbvol; ivol++ )
{
- int smdsId = meshDS->fromVtkToSmds(vtkVolIds[ivol]);
- SMDS_MeshElement* elem = (SMDS_MeshElement*)meshDS->FindElement(smdsId);
+ smIdType smdsId = meshDS->FromVtkToSmds(vtkVolIds[ivol]);
+ const SMDS_MeshElement* elem = meshDS->FindElement(smdsId);
if (domain.count(elem))
{
- SMDS_VtkVolume* svol = dynamic_cast<SMDS_VtkVolume*>(elem);
- domvol[idom] = svol;
+ const SMDS_MeshVolume* svol = SMDS_Mesh::DownCast<SMDS_MeshVolume>(elem);
+ domvol[idom] = (SMDS_MeshVolume*) svol;
//MESSAGE(" domain " << idom << " volume " << elem->GetID());
- double values[3];
+ double values[3] = { 0,0,0 };
vtkIdType npts = 0;
- vtkIdType* pts = 0;
+ vtkIdType const *pts(nullptr);
grid->GetCellPoints(vtkVolIds[ivol], npts, pts);
- SMDS_VtkVolume::gravityCenter(grid, pts, npts, values);
- if (id ==0)
+ for ( vtkIdType i = 0; i < npts; ++i )
+ {
+ double *coords = grid->GetPoint( pts[i] );
+ for ( int j = 0; j < 3; ++j )
+ values[j] += coords[j] / npts;
+ }
+ if ( id == 0 )
{
- gref.SetXYZ(gp_XYZ(values[0], values[1], values[2]));
+ gref.SetCoord( values[0], values[1], values[2] );
angleDom[idom] = 0;
}
else
{
- gp_Pnt g(values[0], values[1], values[2]);
+ gp_Pnt g( values[0], values[1], values[2] );
angleDom[idom] = OrientedAngle(p0, p1, gref, g); // -pi<angle<+pi
//MESSAGE(" angle=" << angleDom[idom]);
}
std::map<std::string, SMESH_Group*> mapOfJunctionGroups;
//MESSAGE(".. Creation of elements: simple junction");
- if (createJointElems)
+ if ( createJointElems )
{
- int idg;
string joints2DName = "joints2D";
- mapOfJunctionGroups[joints2DName] = this->myMesh->AddGroup(SMDSAbs_Face, joints2DName.c_str(), idg);
+ mapOfJunctionGroups[joints2DName] = this->myMesh->AddGroup(SMDSAbs_Face, joints2DName.c_str());
SMESHDS_Group *joints2DGrp = dynamic_cast<SMESHDS_Group*>(mapOfJunctionGroups[joints2DName]->GetGroupDS());
string joints3DName = "joints3D";
- mapOfJunctionGroups[joints3DName] = this->myMesh->AddGroup(SMDSAbs_Volume, joints3DName.c_str(), idg);
+ mapOfJunctionGroups[joints3DName] = this->myMesh->AddGroup(SMDSAbs_Volume, joints3DName.c_str());
SMESHDS_Group *joints3DGrp = dynamic_cast<SMESHDS_Group*>(mapOfJunctionGroups[joints3DName]->GetGroupDS());
itface = faceDomains.begin();
DownIdType face = itface->first;
std::set<int> oldNodes;
std::set<int>::iterator itn;
- oldNodes.clear();
grid->GetNodeIds(oldNodes, face.cellId, face.cellType);
- std::map<int, int> domvol = itface->second;
+ std::map<int, int> domvol = itface->second;
std::map<int, int>::iterator itdom = domvol.begin();
- int dom1 = itdom->first;
+ int dom1 = itdom->first;
int vtkVolId = itdom->second;
itdom++;
- int dom2 = itdom->first;
+ int dom2 = itdom->first;
SMDS_MeshCell *vol = grid->extrudeVolumeFromFace(vtkVolId, dom1, dom2, oldNodes, nodeDomains,
nodeQuadDomains);
stringstream grpname;
grpname << dom2 << "_" << dom1;
string namegrp = grpname.str();
if (!mapOfJunctionGroups.count(namegrp))
- mapOfJunctionGroups[namegrp] = this->myMesh->AddGroup(vol->GetType(), namegrp.c_str(), idg);
+ mapOfJunctionGroups[namegrp] = this->myMesh->AddGroup(vol->GetType(), namegrp.c_str());
SMESHDS_Group *sgrp = dynamic_cast<SMESHDS_Group*>(mapOfJunctionGroups[namegrp]->GetGroupDS());
if (sgrp)
sgrp->Add(vol->GetID());
stringstream grpname;
grpname << "m2j_";
grpname << 0 << "_" << 0;
- int idg;
string namegrp = grpname.str();
if (!mapOfJunctionGroups.count(namegrp))
- mapOfJunctionGroups[namegrp] = this->myMesh->AddGroup(SMDSAbs_Face, namegrp.c_str(), idg);
+ mapOfJunctionGroups[namegrp] = this->myMesh->AddGroup(SMDSAbs_Face, namegrp.c_str());
SMESHDS_Group *sgrp = dynamic_cast<SMESHDS_Group*>(mapOfJunctionGroups[namegrp]->GetGroupDS());
if (sgrp)
sgrp->Add(face->GetID());
std::map<std::vector<int>, std::vector<int> >::iterator ite = edgesMultiDomains.begin();
for (; ite != edgesMultiDomains.end(); ++ite)
{
- vector<int> nodes = ite->first;
+ vector<int> nodes = ite->first;
vector<int> orderDom = ite->second;
vector<vtkIdType> orderedNodes;
if (nodes.size() == 2)
orderedNodes.push_back( nodeDomains[ nodes[ ino ]][ orderDom[ idom ]]);
SMDS_MeshVolume* vol = this->GetMeshDS()->AddVolumeFromVtkIds(orderedNodes);
- int idg;
string namegrp = "jointsMultiples";
if (!mapOfJunctionGroups.count(namegrp))
- mapOfJunctionGroups[namegrp] = this->myMesh->AddGroup(SMDSAbs_Volume, namegrp.c_str(), idg);
+ mapOfJunctionGroups[namegrp] = this->myMesh->AddGroup(SMDSAbs_Volume, namegrp.c_str());
SMESHDS_Group *sgrp = dynamic_cast<SMESHDS_Group*>(mapOfJunctionGroups[namegrp]->GetGroupDS());
if (sgrp)
sgrp->Add(vol->GetID());
std::map<DownIdType, std::map<int,int>, DownIdCompare> faceOrEdgeDom; // cellToModify --> (id domain --> id cell)
std::map<int,int> feDom; // vtk id of cell to modify --> id domain
- faceOrEdgeDom.clear();
- feDom.clear();
//MESSAGE(".. Modification of elements");
+ SMDSAbs_ElementType domainType = (*theElems[0].begin())->GetType();
for (int idomain = idom0; idomain < nbDomains; idomain++)
{
std::map<int, std::map<int, int> >::const_iterator itnod = nodeDomains.begin();
{
int oldId = itnod->first;
//MESSAGE(" node " << oldId);
- vtkCellLinks::Link l = grid->GetCellLinks()->GetLink(oldId);
+ vtkCellLinks::Link l = (static_cast< vtkCellLinks *>(grid->GetCellLinks()))->GetLink(oldId);
for (int i = 0; i < l.ncells; i++)
{
int vtkId = l.cells[i];
continue; // new cells: not to be modified
DownIdType aCell(downId, vtkType);
int volParents[1000];
- int nbvol = grid->GetParentVolumes(volParents, vtkId);
+ int nbvol = 0;
+ nbvol = grid->GetParentVolumes(volParents, vtkId);
+ if ( domainType == SMDSAbs_Volume )
+ {
+ nbvol = grid->GetParentVolumes(volParents, vtkId);
+ }
+ else // domainType == SMDSAbs_Face
+ {
+ const int nbFaces = grid->getDownArray(vtkType)->getNumberOfUpCells(downId);
+ const int *upCells = grid->getDownArray(vtkType)->getUpCells(downId);
+ const unsigned char* upTypes = grid->getDownArray(vtkType)->getUpTypes(downId);
+ for (int i=0; i< nbFaces; i++)
+ {
+ int vtkFaceId = grid->getDownArray( upTypes[i] )->getVtkCellId(upCells[i]);
+ if (vtkFaceId >= 0)
+ volParents[nbvol++] = vtkFaceId;
+ }
+ }
for (int j = 0; j < nbvol; j++)
if (celldom.count(volParents[j]) && (celldom[volParents[j]] == idomain))
if (!feDom.count(vtkId))
{
feDom[vtkId] = idomain;
- faceOrEdgeDom[aCell] = emptyMap;
faceOrEdgeDom[aCell][idomain] = vtkId; // affect face or edge to the first domain only
- //MESSAGE("affect cell " << this->GetMeshDS()->fromVtkToSmds(vtkId) << " domain " << idomain
+ //MESSAGE("affect cell " << this->GetMeshDS()->FromVtkToSmds(vtkId) << " domain " << idomain
// << " type " << vtkType << " downId " << downId);
}
}
DownIdType face = itface->first;
std::set<int> oldNodes;
std::set<int>::iterator itn;
- oldNodes.clear();
grid->GetNodeIds(oldNodes, face.cellId, face.cellType);
//MESSAGE("examine cell, downId " << face.cellId << " type " << int(face.cellType));
std::map<int, int> localClonedNodeIds;
{
int idom = itdom->first;
int vtkVolId = itdom->second;
- //MESSAGE("modify nodes of cell " << this->GetMeshDS()->fromVtkToSmds(vtkVolId) << " domain " << idom);
+ //MESSAGE("modify nodes of cell " << this->GetMeshDS()->FromVtkToSmds(vtkVolId) << " domain " << idom);
localClonedNodeIds.clear();
for (itn = oldNodes.begin(); itn != oldNodes.end(); ++itn)
{
std::map<const SMDS_MeshNode*, const SMDS_MeshNode*> clonedNodes;
std::map<const SMDS_MeshNode*, const SMDS_MeshNode*> intermediateNodes;
- clonedNodes.clear();
- intermediateNodes.clear();
std::map<std::string, SMESH_Group*> mapOfJunctionGroups;
- mapOfJunctionGroups.clear();
for ( size_t idom = 0; idom < theElems.size(); idom++ )
{
TIDSortedElemSet::const_iterator elemItr = domain.begin();
for ( ; elemItr != domain.end(); ++elemItr )
{
- SMDS_MeshElement* anElem = (SMDS_MeshElement*) *elemItr;
- SMDS_MeshFace* aFace = dynamic_cast<SMDS_MeshFace*> (anElem);
+ const SMDS_MeshFace* aFace = meshDS->DownCast<SMDS_MeshFace> ( *elemItr );
if (!aFace)
continue;
// MESSAGE("aFace=" << aFace->GetID());
// --- clone the nodes, create intermediate nodes for non medium nodes of a quad face
- SMDS_ElemIteratorPtr nodeIt = aFace->nodesIterator();
+ SMDS_NodeIteratorPtr nodeIt = aFace->nodeIterator();
while (nodeIt->more())
{
- const SMDS_MeshNode* node = static_cast<const SMDS_MeshNode*> (nodeIt->next());
- bool isMedium = isQuad && (aFace->IsMediumNode(node));
+ const SMDS_MeshNode* node = nodeIt->next();
+ bool isMedium = ( isQuad && aFace->IsMediumNode( node ));
if (isMedium)
ln2.push_back(node);
else
stringstream grpname;
grpname << "jf_";
grpname << idom;
- int idg;
string namegrp = grpname.str();
if (!mapOfJunctionGroups.count(namegrp))
- mapOfJunctionGroups[namegrp] = this->myMesh->AddGroup(SMDSAbs_Volume, namegrp.c_str(), idg);
+ mapOfJunctionGroups[namegrp] = this->myMesh->AddGroup(SMDSAbs_Volume, namegrp.c_str());
SMESHDS_Group *sgrp = dynamic_cast<SMESHDS_Group*>(mapOfJunctionGroups[namegrp]->GetGroupDS());
if (sgrp)
sgrp->Add(vol->GetID());
// --- modify the face
- aFace->ChangeNodes(&ln[0], ln.size());
+ const_cast<SMDS_MeshFace*>( aFace )->ChangeNodes( &ln[0], ln.size() );
}
}
return true;
// --- define groups to build
- int idg; // --- group of SMDS volumes
+ // --- group of SMDS volumes
string grpvName = groupName;
grpvName += "_vol";
- SMESH_Group *grp = this->myMesh->AddGroup(SMDSAbs_Volume, grpvName.c_str(), idg);
+ SMESH_Group *grp = this->myMesh->AddGroup(SMDSAbs_Volume, grpvName.c_str());
if (!grp)
{
MESSAGE("group not created " << grpvName);
}
SMESHDS_Group *sgrp = dynamic_cast<SMESHDS_Group*>(grp->GetGroupDS());
- int idgs; // --- group of SMDS faces on the skin
+ // --- group of SMDS faces on the skin
string grpsName = groupName;
grpsName += "_skin";
- SMESH_Group *grps = this->myMesh->AddGroup(SMDSAbs_Face, grpsName.c_str(), idgs);
+ SMESH_Group *grps = this->myMesh->AddGroup(SMDSAbs_Face, grpsName.c_str());
if (!grps)
{
MESSAGE("group not created " << grpsName);
}
SMESHDS_Group *sgrps = dynamic_cast<SMESHDS_Group*>(grps->GetGroupDS());
- int idgi; // --- group of SMDS faces internal (several shapes)
+ // --- group of SMDS faces internal (several shapes)
string grpiName = groupName;
grpiName += "_internalFaces";
- SMESH_Group *grpi = this->myMesh->AddGroup(SMDSAbs_Face, grpiName.c_str(), idgi);
+ SMESH_Group *grpi = this->myMesh->AddGroup(SMDSAbs_Face, grpiName.c_str());
if (!grpi)
{
MESSAGE("group not created " << grpiName);
}
SMESHDS_Group *sgrpi = dynamic_cast<SMESHDS_Group*>(grpi->GetGroupDS());
- int idgei; // --- group of SMDS faces internal (several shapes)
+ // --- group of SMDS faces internal (several shapes)
string grpeiName = groupName;
grpeiName += "_internalEdges";
- SMESH_Group *grpei = this->myMesh->AddGroup(SMDSAbs_Edge, grpeiName.c_str(), idgei);
+ SMESH_Group *grpei = this->myMesh->AddGroup(SMDSAbs_Edge, grpeiName.c_str());
if (!grpei)
{
MESSAGE("group not created " << grpeiName);
SMESHDS_Mesh *meshDS = this->myMesh->GetMeshDS();
meshDS->BuildDownWardConnectivity(true);
- SMDS_UnstructuredGrid* grid = meshDS->getGrid();
+ SMDS_UnstructuredGrid* grid = meshDS->GetGrid();
// --- set of volumes detected inside
std::set<int> setOfVolToCheck;
std::vector<gp_Pnt> gpnts;
- gpnts.clear();
if (isNodeGroup) // --- a group of nodes is provided : find all the volumes using one or more of this nodes
{
while (volItr->more())
{
vol = (SMDS_MeshElement*)volItr->next();
- setOfInsideVol.insert(vol->getVtkId());
+ setOfInsideVol.insert(vol->GetVtkID());
sgrp->Add(vol->GetID());
}
}
while (volItr->more())
{
startVol = (SMDS_MeshElement*)volItr->next();
- setOfVolToCheck.insert(startVol->getVtkId());
+ setOfVolToCheck.insert(startVol->GetVtkID());
}
if (setOfVolToCheck.empty())
{
// Fill the group of inside volumes
std::map<int, double> mapOfNodeDistance2;
- mapOfNodeDistance2.clear();
std::set<int> setOfOutsideVol;
while (!setOfVolToCheck.empty())
{
std::set<int>::iterator it = setOfVolToCheck.begin();
int vtkId = *it;
- //MESSAGE("volume to check, vtkId " << vtkId << " smdsId " << meshDS->fromVtkToSmds(vtkId));
+ //MESSAGE("volume to check, vtkId " << vtkId << " smdsId " << meshDS->FromVtkToSmds(vtkId));
bool volInside = false;
vtkIdType npts = 0;
- vtkIdType* pts = 0;
+ vtkIdType const *pts(nullptr);
grid->GetCellPoints(vtkId, npts, pts);
for (int i=0; i<npts; i++)
{
if (distance2 < radius2)
{
volInside = true; // one or more nodes inside the domain
- sgrp->Add(meshDS->fromVtkToSmds(vtkId));
+ sgrp->Add(meshDS->FromVtkToSmds(vtkId));
break;
}
}
if (volInside)
{
setOfInsideVol.insert(vtkId);
- //MESSAGE(" volume inside, vtkId " << vtkId << " smdsId " << meshDS->fromVtkToSmds(vtkId));
+ //MESSAGE(" volume inside, vtkId " << vtkId << " smdsId " << meshDS->FromVtkToSmds(vtkId));
int neighborsVtkIds[NBMAXNEIGHBORS];
int downIds[NBMAXNEIGHBORS];
unsigned char downTypes[NBMAXNEIGHBORS];
else
{
setOfOutsideVol.insert(vtkId);
- //MESSAGE(" volume outside, vtkId " << vtkId << " smdsId " << meshDS->fromVtkToSmds(vtkId));
+ //MESSAGE(" volume outside, vtkId " << vtkId << " smdsId " << meshDS->FromVtkToSmds(vtkId));
}
setOfVolToCheck.erase(vtkId);
}
int vtkId = *it;
if (grid->GetCellType(vtkId) == VTK_HEXAHEDRON)
{
- //MESSAGE("volume to recheck, vtkId " << vtkId << " smdsId " << meshDS->fromVtkToSmds(vtkId));
+ //MESSAGE("volume to recheck, vtkId " << vtkId << " smdsId " << meshDS->FromVtkToSmds(vtkId));
int countInside = 0;
int neighborsVtkIds[NBMAXNEIGHBORS];
int downIds[NBMAXNEIGHBORS];
//MESSAGE("countInside " << countInside);
if (countInside > 1)
{
- //MESSAGE(" volume inside, vtkId " << vtkId << " smdsId " << meshDS->fromVtkToSmds(vtkId));
+ //MESSAGE(" volume inside, vtkId " << vtkId << " smdsId " << meshDS->FromVtkToSmds(vtkId));
setOfInsideVol.insert(vtkId);
- sgrp->Add(meshDS->fromVtkToSmds(vtkId));
+ sgrp->Add(meshDS->FromVtkToSmds(vtkId));
addedInside = true;
}
else
for (; it != setOfInsideVol.end(); ++it)
{
int vtkId = *it;
- //MESSAGE(" vtkId " << vtkId << " smdsId " << meshDS->fromVtkToSmds(vtkId));
+ //MESSAGE(" vtkId " << vtkId << " smdsId " << meshDS->FromVtkToSmds(vtkId));
int neighborsVtkIds[NBMAXNEIGHBORS];
int downIds[NBMAXNEIGHBORS];
unsigned char downTypes[NBMAXNEIGHBORS];
int vtkFaceId = grid->getDownArray(downTypes[n])->getVtkCellId(downIds[n]);
if (vtkFaceId >= 0)
{
- sgrpi->Add(meshDS->fromVtkToSmds(vtkFaceId));
+ sgrpi->Add(meshDS->FromVtkToSmds(vtkFaceId));
// find also the smds edges on this face
int nbEdges = grid->getDownArray(downTypes[n])->getNumberOfDownCells(downIds[n]);
const int* dEdges = grid->getDownArray(downTypes[n])->getDownCells(downIds[n]);
{
int vtkEdgeId = grid->getDownArray(dTypes[i])->getVtkCellId(dEdges[i]);
if (vtkEdgeId >= 0)
- sgrpei->Add(meshDS->fromVtkToSmds(vtkEdgeId));
+ sgrpei->Add(meshDS->FromVtkToSmds(vtkEdgeId));
}
}
}
skinFaces[face] = vtkId;
int vtkFaceId = grid->getDownArray(downTypes[n])->getVtkCellId(downIds[n]);
if (vtkFaceId >= 0)
- sgrps->Add(meshDS->fromVtkToSmds(vtkFaceId));
+ sgrps->Add(meshDS->FromVtkToSmds(vtkFaceId));
}
}
}
// project polylines on subshapes, and partition, to get geom faces
std::map<int, std::set<int> > shapeIdToVtkIdSet; // shapeId --> set of vtkId on skin
- std::set<int> emptySet;
- emptySet.clear();
- std::set<int> shapeIds;
+ std::set<int> shapeIds;
SMDS_ElemIteratorPtr itelem = sgrps->GetElements();
while (itelem->more())
{
const SMDS_MeshElement *elem = itelem->next();
int shapeId = elem->getshapeId();
- int vtkId = elem->getVtkId();
+ int vtkId = elem->GetVtkID();
if (!shapeIdToVtkIdSet.count(shapeId))
{
- shapeIdToVtkIdSet[shapeId] = emptySet;
shapeIds.insert(shapeId);
}
shapeIdToVtkIdSet[shapeId].insert(vtkId);
std::map<int, std::set<DownIdType, DownIdCompare> > shapeIdToEdges; // shapeId --> set of downward edges
std::set<DownIdType, DownIdCompare> emptyEdges;
- emptyEdges.clear();
std::map<int, std::set<int> >::iterator itShape = shapeIdToVtkIdSet.begin();
for (; itShape != shapeIdToVtkIdSet.end(); ++itShape)
{
if (neighborsVtkIds[n]<0) // only smds faces are considered as neighbors here
continue;
- int smdsId = meshDS->fromVtkToSmds(neighborsVtkIds[n]);
+ smIdType smdsId = meshDS->FromVtkToSmds(neighborsVtkIds[n]);
const SMDS_MeshElement* elem = meshDS->FindElement(smdsId);
if ( shapeIds.count(elem->getshapeId()) && !sgrps->Contains(elem)) // edge : neighbor in the set of shape, not in the group
{
}
std::list<int> order;
- order.clear();
if (nodesEdges.size() > 0)
{
order.push_back(nodesEdges[0]); //MESSAGE(" --- back " << order.back()+1); // SMDS id = VTK id + 1;
// add new face based on volume nodes
if (aMesh->FindElement( nodes, SMDSAbs_Face, /*noMedium=*/false) )
{
- nbExisted++; // face already exsist
+ nbExisted++; // face already exists
}
else
{
if (elements.empty()) eIt = aMesh->elementsIterator(elemType);
else eIt = SMESHUtils::elemSetIterator( elements );
- while (eIt->more())
+ while ( eIt->more() )
{
const SMDS_MeshElement* elem = eIt->next();
const int iQuad = elem->IsQuadratic();
else if ( elem->GetType() == SMDSAbs_Face ) // elem is a face ------------------------
{
avoidSet.clear(), avoidSet.insert( elem );
- elemNodes.assign( SMDS_MeshElement::iterator( elem->interlacedNodesElemIterator() ),
+ elemNodes.assign( SMDS_MeshElement::iterator( elem->interlacedNodesIterator() ),
SMDS_MeshElement::iterator() );
elemNodes.push_back( elemNodes[0] );
nodes.resize( 2 + iQuad );
tgtNodes.resize( srcNodes.size() );
for ( inode = 0; inode < srcNodes.size(); ++inode )
tgtNodes[inode] = getNodeWithSameID( tgtMeshDS, srcNodes[inode] );
- if ( aroundElements && tgtEditor.GetMeshDS()->FindElement( tgtNodes,
- missType,
- /*noMedium=*/false))
+ if ( /*aroundElements && */tgtEditor.GetMeshDS()->FindElement( tgtNodes,
+ missType,
+ /*noMedium=*/false))
continue;
tgtEditor.AddElement( tgtNodes, elemKind.SetPoly( tgtNodes.size()/(iQuad+1) > 4 ));
++nbAddedBnd;
for ( size_t i = 0; i < missingBndElems.size(); ++i )
{
TConnectivity& nodes = missingBndElems[ i ];
- if ( aroundElements && tgtEditor.GetMeshDS()->FindElement( nodes,
- missType,
- /*noMedium=*/false))
+ if ( /*aroundElements && */tgtEditor.GetMeshDS()->FindElement( nodes,
+ missType,
+ /*noMedium=*/false))
continue;
SMDS_MeshElement* newElem =
tgtEditor.AddElement( nodes, elemKind.SetPoly( nodes.size()/(iQuad+1) > 4 ));
case SMDS_TOP_FACE:
{
- const SMDS_FacePosition* fPos = static_cast< const SMDS_FacePosition* >( pos );
+ SMDS_FacePositionPtr fPos = pos;
GetMeshDS()->SetNodeOnFace( to, from->getshapeId(),
fPos->GetUParameter(), fPos->GetVParameter() );
break;
case SMDS_TOP_EDGE:
{
// WARNING: it is dangerous to set equal nodes on one EDGE!!!!!!!!
- const SMDS_EdgePosition* ePos = static_cast< const SMDS_EdgePosition* >( pos );
+ SMDS_EdgePositionPtr ePos = pos;
GetMeshDS()->SetNodeOnEdge( to, from->getshapeId(), ePos->GetUParameter() );
break;
}
default:;
}
}
-
-namespace // utils for MakePolyLine
-{
- //================================================================================
- /*!
- * \brief Sequence of found points and a current point data
- */
- struct Path
- {
- std::vector< gp_XYZ > myPoints;
- double myLength;
-
- int mySrcPntInd; //!< start point index
- const SMDS_MeshElement* myFace;
- SMESH_NodeXYZ myNode1;
- SMESH_NodeXYZ myNode2;
- int myNodeInd1;
- int myNodeInd2;
- double myDot1;
- double myDot2;
- TIDSortedElemSet myElemSet, myAvoidSet;
-
- Path(): myLength(0.0), myFace(0) {}
-
- bool SetCutAtCorner( const SMESH_NodeXYZ& cornerNode,
- const SMDS_MeshElement* face,
- const gp_XYZ& plnNorm,
- const gp_XYZ& plnOrig );
-
- void AddPoint( const gp_XYZ& p );
-
- bool Extend( const gp_XYZ& plnNorm, const gp_XYZ& plnOrig );
-
- bool ReachSamePoint( const Path& other );
-
- static void Remove( std::vector< Path > & paths, size_t& i );
- };
-
- //================================================================================
- /*!
- * \brief Return true if this Path meats another
- */
- //================================================================================
-
- bool Path::ReachSamePoint( const Path& other )
- {
- return ( mySrcPntInd != other.mySrcPntInd &&
- myFace == other.myFace );
- }
-
- //================================================================================
- /*!
- * \brief Remove a path from a vector
- */
- //================================================================================
-
- void Path::Remove( std::vector< Path > & paths, size_t& i )
- {
- if ( paths.size() > 1 )
- {
- size_t j = paths.size() - 1; // last item to be removed
- if ( i < j )
- {
- paths[ i ].myPoints.swap( paths[ j ].myPoints );
- paths[ i ].myLength = paths[ j ].myLength;
- paths[ i ].mySrcPntInd = paths[ j ].mySrcPntInd;
- paths[ i ].myFace = paths[ j ].myFace;
- paths[ i ].myNode1 = paths[ j ].myNode1;
- paths[ i ].myNode2 = paths[ j ].myNode2;
- paths[ i ].myNodeInd1 = paths[ j ].myNodeInd1;
- paths[ i ].myNodeInd2 = paths[ j ].myNodeInd2;
- paths[ i ].myDot1 = paths[ j ].myDot1;
- paths[ i ].myDot2 = paths[ j ].myDot2;
- }
- }
- paths.pop_back();
- if ( i > 0 )
- --i;
- }
-
- //================================================================================
- /*!
- * \brief Store a point that is at a node of a face if the face is intersected by plane.
- * Return false if the node is a sole intersection point of the face and the plane
- */
- //================================================================================
-
- bool Path::SetCutAtCorner( const SMESH_NodeXYZ& cornerNode,
- const SMDS_MeshElement* face,
- const gp_XYZ& plnNorm,
- const gp_XYZ& plnOrig )
- {
- if ( face == myFace )
- return false;
- myNodeInd1 = face->GetNodeIndex( cornerNode._node );
- myNodeInd2 = ( myNodeInd1 + 1 ) % face->NbCornerNodes();
- int ind3 = ( myNodeInd1 + 2 ) % face->NbCornerNodes();
- myNode1.Set( face->GetNode( ind3 ));
- myNode2.Set( face->GetNode( myNodeInd2 ));
-
- myDot1 = plnNorm * ( myNode1 - plnOrig );
- myDot2 = plnNorm * ( myNode2 - plnOrig );
-
- bool ok = ( myDot1 * myDot2 < 0 );
- if ( !ok && myDot1 * myDot2 == 0 )
- {
- ok = ( myDot1 != myDot2 );
- if ( ok && myFace )
- ok = ( myFace->GetNodeIndex(( myDot1 == 0 ? myNode1 : myNode2 )._node ) < 0 );
- }
- if ( ok )
- {
- myFace = face;
- myDot1 = 0;
- AddPoint( cornerNode );
- }
- return ok;
- }
-
- //================================================================================
- /*!
- * \brief Store a point and update myLength
- */
- //================================================================================
-
- void Path::AddPoint( const gp_XYZ& p )
- {
- if ( !myPoints.empty() )
- myLength += ( p - myPoints.back() ).Modulus();
- else
- myLength = 0;
- myPoints.push_back( p );
- }
-
- //================================================================================
- /*!
- * \brief Try to find the next point
- * \param [in] plnNorm - cutting plane normal
- * \param [in] plnOrig - cutting plane origin
- */
- //================================================================================
-
- bool Path::Extend( const gp_XYZ& plnNorm, const gp_XYZ& plnOrig )
- {
- int nodeInd3 = ( myNodeInd1 + 1 ) % myFace->NbCornerNodes();
- if ( myNodeInd2 == nodeInd3 )
- nodeInd3 = ( myNodeInd1 + 2 ) % myFace->NbCornerNodes();
-
- SMESH_NodeXYZ node3 = myFace->GetNode( nodeInd3 );
- double dot3 = plnNorm * ( node3 - plnOrig );
-
- if ( dot3 * myDot1 < 0. )
- {
- myNode2 = node3;
- myNodeInd2 = nodeInd3;
- myDot2 = dot3;
- }
- else if ( dot3 * myDot2 < 0. )
- {
- myNode1 = node3;
- myNodeInd1 = nodeInd3;
- myDot1 = dot3;
- }
- else if ( dot3 == 0. )
- {
- SMDS_ElemIteratorPtr fIt = node3._node->GetInverseElementIterator(SMDSAbs_Face);
- while ( fIt->more() )
- if ( SetCutAtCorner( node3, fIt->next(), plnNorm, plnOrig ))
- return true;
- return false;
- }
- else if ( myDot2 == 0. )
- {
- SMESH_NodeXYZ node2 = myNode2; // copy as myNode2 changes in SetCutAtCorner()
- SMDS_ElemIteratorPtr fIt = node2._node->GetInverseElementIterator(SMDSAbs_Face);
- while ( fIt->more() )
- if ( SetCutAtCorner( node2, fIt->next(), plnNorm, plnOrig ))
- return true;
- return false;
- }
-
- double r = Abs( myDot1 / ( myDot2 - myDot1 ));
- AddPoint( myNode1 * ( 1 - r ) + myNode2 * r );
-
- myAvoidSet.clear();
- myAvoidSet.insert( myFace );
- myFace = SMESH_MeshAlgos::FindFaceInSet( myNode1._node, myNode2._node,
- myElemSet, myAvoidSet,
- &myNodeInd1, &myNodeInd2 );
- return myFace;
- }
-
- //================================================================================
- /*!
- * \brief Compute a path between two points of PolySegment
- */
- struct PolyPathCompute
- {
- SMESH_MeshEditor::TListOfPolySegments& mySegments; //!< inout PolySegment's
- std::vector< Path >& myPaths; //!< path of each of segments to compute
- SMESH_Mesh* myMesh;
- mutable std::vector< std::string > myErrors;
-
- PolyPathCompute( SMESH_MeshEditor::TListOfPolySegments& theSegments,
- std::vector< Path >& thePaths,
- SMESH_Mesh* theMesh):
- mySegments( theSegments ),
- myPaths( thePaths ),
- myMesh( theMesh ),
- myErrors( theSegments.size() )
- {
- }
-#undef SMESH_CAUGHT
-#define SMESH_CAUGHT myErrors[i] =
- void operator() ( const int i ) const
- {
- SMESH_TRY;
- const_cast< PolyPathCompute* >( this )->Compute( i );
- SMESH_CATCH( SMESH::returnError );
- }
-#undef SMESH_CAUGHT
- //================================================================================
- /*!
- * \brief Compute a path of a given segment
- */
- //================================================================================
-
- void Compute( const int iSeg )
- {
- SMESH_MeshEditor::PolySegment& polySeg = mySegments[ iSeg ];
-
- // get a cutting plane
-
- gp_XYZ p1 = SMESH_NodeXYZ( polySeg.myNode1[0] );
- gp_XYZ p2 = SMESH_NodeXYZ( polySeg.myNode1[1] );
- if ( polySeg.myNode2[0] ) p1 = 0.5 * ( p1 + SMESH_NodeXYZ( polySeg.myNode2[0] ));
- if ( polySeg.myNode2[1] ) p2 = 0.5 * ( p2 + SMESH_NodeXYZ( polySeg.myNode2[1] ));
-
- gp_XYZ plnNorm = ( p1 - p2 ) ^ polySeg.myVector.XYZ();
- gp_XYZ plnOrig = p2;
-
- // find paths connecting the 2 end points of polySeg
-
- std::vector< Path > paths; paths.reserve(10);
-
- // initialize paths
-
- for ( int iP = 0; iP < 2; ++iP ) // loop on the polySeg end points
- {
- Path path;
- path.mySrcPntInd = iP;
- size_t nbPaths = paths.size();
-
- if ( polySeg.myNode2[ iP ] && polySeg.myNode2[ iP ] != polySeg.myNode1[ iP ] )
- {
- while (( path.myFace = SMESH_MeshAlgos::FindFaceInSet( polySeg.myNode1[ iP ],
- polySeg.myNode2[ iP ],
- path.myElemSet,
- path.myAvoidSet,
- &path.myNodeInd1,
- &path.myNodeInd2 )))
- {
- path.myNode1.Set( polySeg.myNode1[ iP ]);
- path.myNode2.Set( polySeg.myNode2[ iP ]);
- path.myDot1 = plnNorm * ( path.myNode1 - plnOrig );
- path.myDot2 = plnNorm * ( path.myNode2 - plnOrig );
- path.myPoints.clear();
- path.AddPoint( 0.5 * ( path.myNode1 + path.myNode2 ));
- path.myAvoidSet.insert( path.myFace );
- paths.push_back( path );
- }
- if ( nbPaths == paths.size() )
- throw SALOME_Exception ( SMESH_Comment("No face edge found by point ") << iP+1
- << " in a PolySegment " << iSeg );
- }
- else // an end point is at node
- {
- std::set<const SMDS_MeshNode* > nodes;
- SMDS_ElemIteratorPtr fIt = polySeg.myNode1[ iP ]->GetInverseElementIterator(SMDSAbs_Face);
- while ( fIt->more() )
- {
- path.myPoints.clear();
- if ( path.SetCutAtCorner( polySeg.myNode1[ iP ], fIt->next(), plnNorm, plnOrig ))
- {
- if (( path.myDot1 * path.myDot2 != 0 ) ||
- ( nodes.insert( path.myDot1 == 0 ? path.myNode1._node : path.myNode2._node ).second ))
- paths.push_back( path );
- }
- }
- }
-
- // look for a one-segment path
- for ( size_t i = 0; i < nbPaths; ++i )
- for ( size_t j = nbPaths; j < paths.size(); ++j )
- if ( paths[i].myFace == paths[j].myFace )
- {
- myPaths[ iSeg ].myPoints.push_back( paths[i].myPoints[0] );
- myPaths[ iSeg ].myPoints.push_back( paths[j].myPoints[0] );
- paths.clear();
- }
- }
-
- // extend paths
-
- myPaths[ iSeg ].myLength = 1e100;
-
- while ( paths.size() >= 2 )
- {
- for ( size_t i = 0; i < paths.size(); ++i )
- {
- Path& path = paths[ i ];
- if ( !path.Extend( plnNorm, plnOrig ) || // path reached a mesh boundary
- path.myLength > myPaths[ iSeg ].myLength ) // path is longer than others
- {
- Path::Remove( paths, i );
- continue;
- }
-
- // join paths that reach same point
- for ( size_t j = 0; j < paths.size(); ++j )
- {
- if ( i != j && paths[i].ReachSamePoint( paths[j] ))
- {
- double distLast = ( paths[i].myPoints.back() - paths[j].myPoints.back() ).Modulus();
- double fullLength = ( paths[i].myLength + paths[j].myLength + distLast );
- if ( fullLength < myPaths[ iSeg ].myLength )
- {
- myPaths[ iSeg ].myLength = fullLength;
- std::vector< gp_XYZ > & allPoints = myPaths[ iSeg ].myPoints;
- allPoints.swap( paths[i].myPoints );
- allPoints.insert( allPoints.end(),
- paths[j].myPoints.rbegin(),
- paths[j].myPoints.rend() );
- }
- Path::Remove( paths, i );
- Path::Remove( paths, j );
- }
- }
- }
- if ( !paths.empty() && (int) paths[0].myPoints.size() > myMesh->NbFaces() )
- throw SALOME_Exception(LOCALIZED( "Infinite loop in MakePolyLine()"));
- }
-
- if ( myPaths[ iSeg ].myPoints.empty() )
- throw SALOME_Exception( SMESH_Comment("Can't find a full path for PolySegment #") << iSeg );
-
- } // PolyPathCompute::Compute()
-
- }; // struct PolyPathCompute
-
-} // namespace
-
-//=======================================================================
-//function : MakePolyLine
-//purpose : Create a polyline consisting of 1D mesh elements each lying on a 2D element of
-// the initial mesh
-//=======================================================================
-
-void SMESH_MeshEditor::MakePolyLine( TListOfPolySegments& theSegments,
- SMESHDS_Group* theGroup,
- SMESH_ElementSearcher* theSearcher)
-{
- std::vector< Path > segPaths( theSegments.size() ); // path of each of segments
-
- SMESH_ElementSearcher* searcher = theSearcher;
- SMESHUtils::Deleter<SMESH_ElementSearcher> delSearcher;
- if ( !searcher )
- {
- searcher = SMESH_MeshAlgos::GetElementSearcher( *GetMeshDS() );
- delSearcher._obj = searcher;
- }
-
- // get cutting planes
-
- std::vector< bool > isVectorOK( theSegments.size(), true );
- const double planarCoef = 0.333; // plane height in planar case
-
- for ( size_t iSeg = 0; iSeg < theSegments.size(); ++iSeg )
- {
- PolySegment& polySeg = theSegments[ iSeg ];
-
- gp_XYZ p1 = SMESH_NodeXYZ( polySeg.myNode1[0] );
- gp_XYZ p2 = SMESH_NodeXYZ( polySeg.myNode1[1] );
- if ( polySeg.myNode2[0] ) p1 = 0.5 * ( p1 + SMESH_NodeXYZ( polySeg.myNode2[0] ));
- if ( polySeg.myNode2[1] ) p2 = 0.5 * ( p2 + SMESH_NodeXYZ( polySeg.myNode2[1] ));
-
- gp_XYZ plnNorm = ( p1 - p2 ) ^ polySeg.myVector.XYZ();
-
- isVectorOK[ iSeg ] = ( plnNorm.Modulus() > std::numeric_limits<double>::min() );
- if ( !isVectorOK[ iSeg ])
- {
- gp_XYZ pMid = 0.5 * ( p1 + p2 );
- const SMDS_MeshElement* face;
- polySeg.myMidProjPoint = searcher->Project( pMid, SMDSAbs_Face, &face );
- polySeg.myVector = polySeg.myMidProjPoint.XYZ() - pMid;
-
- gp_XYZ faceNorm;
- SMESH_MeshAlgos::FaceNormal( face, faceNorm );
-
- if ( polySeg.myVector.Magnitude() < Precision::Confusion() ||
- polySeg.myVector * faceNorm < Precision::Confusion() )
- {
- polySeg.myVector = faceNorm;
- polySeg.myMidProjPoint = pMid + faceNorm * ( p1 - p2 ).Modulus() * planarCoef;
- }
- }
- else
- {
- polySeg.myVector = plnNorm ^ ( p1 - p2 );
- }
- }
-
- // assure that inverse elements are constructed, avoid their concurrent building in threads
- GetMeshDS()->nodesIterator()->next()->NbInverseElements();
-
- // find paths
-
- PolyPathCompute algo( theSegments, segPaths, myMesh );
- OSD_Parallel::For( 0, theSegments.size(), algo, theSegments.size() == 1 );
-
- for ( size_t iSeg = 0; iSeg < theSegments.size(); ++iSeg )
- if ( !algo.myErrors[ iSeg ].empty() )
- throw SALOME_Exception( algo.myErrors[ iSeg ].c_str() );
-
- // create an 1D mesh
-
- const SMDS_MeshNode *n, *nPrev = 0;
- SMESHDS_Mesh* mesh = GetMeshDS();
-
- for ( size_t iSeg = 0; iSeg < theSegments.size(); ++iSeg )
- {
- const Path& path = segPaths[iSeg];
- if ( path.myPoints.size() < 2 )
- continue;
-
- double tol = path.myLength / path.myPoints.size() / 1000.;
- if ( !nPrev || ( SMESH_NodeXYZ( nPrev ) - path.myPoints[0] ).SquareModulus() > tol*tol )
- {
- nPrev = mesh->AddNode( path.myPoints[0].X(), path.myPoints[0].Y(), path.myPoints[0].Z() );
- myLastCreatedNodes.push_back( nPrev );
- }
- for ( size_t iP = 1; iP < path.myPoints.size(); ++iP )
- {
- n = mesh->AddNode( path.myPoints[iP].X(), path.myPoints[iP].Y(), path.myPoints[iP].Z() );
- myLastCreatedNodes.push_back( n );
-
- const SMDS_MeshElement* elem = mesh->AddEdge( nPrev, n );
- myLastCreatedElems.push_back( elem );
- if ( theGroup )
- theGroup->Add( elem );
-
- nPrev = n;
- }
-
- // return a vector
-
- gp_XYZ pMid = 0.5 * ( path.myPoints[0] + path.myPoints.back() );
- if ( isVectorOK[ iSeg ])
- {
- // find the most distance point of a path
- double maxDist = 0;
- for ( size_t iP = 1; iP < path.myPoints.size(); ++iP )
- {
- double dist = Abs( theSegments[iSeg].myVector * ( path.myPoints[iP] - path.myPoints[0] ));
- if ( dist > maxDist )
- {
- maxDist = dist;
- theSegments[iSeg].myMidProjPoint = path.myPoints[iP];
- }
- }
- if ( maxDist < Precision::Confusion() ) // planar case
- theSegments[iSeg].myMidProjPoint =
- pMid + theSegments[iSeg].myVector.XYZ().Normalized() * path.myLength * planarCoef;
- }
- theSegments[iSeg].myVector = gp_Vec( pMid, theSegments[iSeg].myMidProjPoint );
- }
-
- return;
-}