23491: EDF 15591 - Duplicate Elements / Nodes

Make AffectedElemGroupsInRegion() universal, make it available in Duplicate dialog
This commit is contained in:
eap 2017-11-14 21:15:33 +03:00
parent 62a5ed1578
commit 50d4798371
13 changed files with 807 additions and 261 deletions

Binary file not shown.

Before

Width:  |  Height:  |  Size: 23 KiB

After

Width:  |  Height:  |  Size: 22 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 28 KiB

After

Width:  |  Height:  |  Size: 27 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 20 KiB

After

Width:  |  Height:  |  Size: 18 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 22 KiB

After

Width:  |  Height:  |  Size: 19 KiB

View File

@ -42,7 +42,10 @@ Parameters to be defined in this mode:
<li><b>Group of nodes to duplicate</b> (<em>mandatory</em>): these <li><b>Group of nodes to duplicate</b> (<em>mandatory</em>): these
nodes will be duplicated.</li> nodes will be duplicated.</li>
<li><b>Group of elements to replace nodes with new ones</b> <li><b>Group of elements to replace nodes with new ones</b>
(<em>optional</em>): the new nodes will replace the duplicated nodes within these elements.</li> (<em>optional</em>): the new nodes will replace the duplicated nodes
within these elements. \b Generate button automatically creates
these groups.
</li>
<li><b>Construct group with newly created nodes</b> option <li><b>Construct group with newly created nodes</b> option
(<em>checked by default</em>): if checked - the group with newly (<em>checked by default</em>): if checked - the group with newly
created nodes will be built.</li> created nodes will be built.</li>
@ -73,7 +76,8 @@ Parameters to be defined in this mode:
group of nodes at crack bottom which will not be duplicated.</li> group of nodes at crack bottom which will not be duplicated.</li>
<li><b>Group of elements to replace nodes with new ones</b> <li><b>Group of elements to replace nodes with new ones</b>
(<em>mandatory</em>): the new nodes will replace the nodes to (<em>mandatory</em>): the new nodes will replace the nodes to
duplicate within these elements.</li> duplicate within these elements. \b Generate button automatically
creates these groups.</li>
<li><b>Construct group with newly created elements</b> option <li><b>Construct group with newly created elements</b> option
(<em>checked by default</em>): if checked - the group of newly created (<em>checked by default</em>): if checked - the group of newly created
elements will be built.</li> elements will be built.</li>

View File

@ -93,6 +93,7 @@
#include <sstream> #include <sstream>
#include <boost/tuple/tuple.hpp> #include <boost/tuple/tuple.hpp>
#include <boost/container/flat_set.hpp>
#include <Standard_Failure.hxx> #include <Standard_Failure.hxx>
#include <Standard_ErrorHandler.hxx> #include <Standard_ErrorHandler.hxx>
@ -4567,11 +4568,7 @@ void SMESH_MeshEditor::sweepElement(const SMDS_MeshElement* elem,
std::swap( itNN[0], itNN[1] ); std::swap( itNN[0], itNN[1] );
std::swap( prevNod[0], prevNod[1] ); std::swap( prevNod[0], prevNod[1] );
std::swap( nextNod[0], nextNod[1] ); std::swap( nextNod[0], nextNod[1] );
#if defined(__APPLE__)
std::swap( isSingleNode[0], isSingleNode[1] ); std::swap( isSingleNode[0], isSingleNode[1] );
#else
isSingleNode.swap( isSingleNode[0], isSingleNode[1] );
#endif
if ( nbSame > 0 ) if ( nbSame > 0 )
sames[0] = 1 - sames[0]; sames[0] = 1 - sames[0];
iNotSameNode = 1 - iNotSameNode; iNotSameNode = 1 - iNotSameNode;
@ -10596,6 +10593,559 @@ SMESH_MeshEditor::FindMatchingNodes(set<const SMDS_MeshElement*>& theSide1,
return SEW_OK; return SEW_OK;
} }
namespace // automatically find theAffectedElems for DoubleNodes()
{
bool isOut( const SMDS_MeshNode* n, const gp_XYZ& norm, const SMDS_MeshElement* elem );
//--------------------------------------------------------------------------------
// Nodes shared by adjacent FissureBorder's.
// 1 node if FissureBorder separates faces
// 2 nodes if FissureBorder separates volumes
struct SubBorder
{
const SMDS_MeshNode* _nodes[2];
int _nbNodes;
SubBorder( const SMDS_MeshNode* n1, const SMDS_MeshNode* n2 = 0 )
{
_nodes[0] = n1;
_nodes[1] = n2;
_nbNodes = bool( n1 ) + bool( n2 );
if ( _nbNodes == 2 && n1 > n2 )
std::swap( _nodes[0], _nodes[1] );
}
bool operator<( const SubBorder& other ) const
{
for ( int i = 0; i < _nbNodes; ++i )
{
if ( _nodes[i] < other._nodes[i] ) return true;
if ( _nodes[i] > other._nodes[i] ) return false;
}
return false;
}
};
//--------------------------------------------------------------------------------
// Map a SubBorder to all FissureBorder it bounds
struct FissureBorder;
typedef std::map< SubBorder, std::vector< FissureBorder* > > TBorderLinks;
typedef TBorderLinks::iterator TMappedSub;
//--------------------------------------------------------------------------------
/*!
* \brief Element border (volume facet or face edge) at a fissure
*/
struct FissureBorder
{
std::vector< const SMDS_MeshNode* > _nodes; // border nodes
const SMDS_MeshElement* _elems[2]; // volume or face adjacent to fissure
std::vector< TMappedSub > _mappedSubs; // Sub() in TBorderLinks map
std::vector< const SMDS_MeshNode* > _sortedNodes; // to compare FissureBorder's
FissureBorder( FissureBorder && from ) // move constructor
{
std::swap( _nodes, from._nodes );
std::swap( _sortedNodes, from._sortedNodes );
_elems[0] = from._elems[0];
_elems[1] = from._elems[1];
}
FissureBorder( const SMDS_MeshElement* elemToDuplicate,
std::vector< const SMDS_MeshElement* > & adjElems)
: _nodes( elemToDuplicate->NbCornerNodes() )
{
for ( size_t i = 0; i < _nodes.size(); ++i )
_nodes[i] = elemToDuplicate->GetNode( i );
SMDSAbs_ElementType type = SMDSAbs_ElementType( elemToDuplicate->GetType() + 1 );
findAdjacent( type, adjElems );
}
FissureBorder( const SMDS_MeshNode** nodes,
const size_t nbNodes,
const SMDSAbs_ElementType adjElemsType,
std::vector< const SMDS_MeshElement* > & adjElems)
: _nodes( nodes, nodes + nbNodes )
{
findAdjacent( adjElemsType, adjElems );
}
void findAdjacent( const SMDSAbs_ElementType adjElemsType,
std::vector< const SMDS_MeshElement* > & adjElems)
{
_elems[0] = _elems[1] = 0;
adjElems.clear();
if ( SMDS_Mesh::GetElementsByNodes( _nodes, adjElems, adjElemsType ))
for ( size_t i = 0; i < adjElems.size() && i < 2; ++i )
_elems[i] = adjElems[i];
}
bool operator<( const FissureBorder& other ) const
{
return GetSortedNodes() < other.GetSortedNodes();
}
const std::vector< const SMDS_MeshNode* >& GetSortedNodes() const
{
if ( _sortedNodes.empty() && !_nodes.empty() )
{
FissureBorder* me = const_cast<FissureBorder*>( this );
me->_sortedNodes = me->_nodes;
std::sort( me->_sortedNodes.begin(), me->_sortedNodes.end() );
}
return _sortedNodes;
}
size_t NbSub() const
{
return _nodes.size();
}
SubBorder Sub(size_t i) const
{
return SubBorder( _nodes[i], NbSub() > 2 ? _nodes[ (i+1)%NbSub() ] : 0 );
}
void AddSelfTo( TBorderLinks& borderLinks )
{
_mappedSubs.resize( NbSub() );
for ( size_t i = 0; i < NbSub(); ++i )
{
TBorderLinks::iterator s2b =
borderLinks.insert( std::make_pair( Sub(i), TBorderLinks::mapped_type() )).first;
s2b->second.push_back( this );
_mappedSubs[ i ] = s2b;
}
}
void Clear()
{
_nodes.clear();
}
const SMDS_MeshElement* GetMarkedElem() const
{
if ( _nodes.empty() ) return 0; // cleared
if ( _elems[0] && _elems[0]->isMarked() ) return _elems[0];
if ( _elems[1] && _elems[1]->isMarked() ) return _elems[1];
return 0;
}
gp_XYZ GetNorm() const // normal to the border
{
gp_XYZ norm;
if ( _nodes.size() == 2 )
{
gp_XYZ avgNorm( 0,0,0 ); // sum of normals of adjacent faces
if ( SMESH_MeshAlgos::FaceNormal( _elems[0], norm ))
avgNorm += norm;
if ( SMESH_MeshAlgos::FaceNormal( _elems[1], norm ))
avgNorm += norm;
gp_XYZ bordDir( SMESH_NodeXYZ( _nodes[0] ) - SMESH_NodeXYZ( _nodes[1] ));
norm = bordDir ^ avgNorm;
}
else
{
SMESH_NodeXYZ p0( _nodes[0] );
SMESH_NodeXYZ p1( _nodes[1] );
SMESH_NodeXYZ p2( _nodes[2] );
norm = ( p0 - p1 ) ^ ( p2 - p1 );
}
if ( isOut( _nodes[0], norm, GetMarkedElem() ))
norm.Reverse();
return norm;
}
void ChooseSide() // mark an _elem located at positive side of fissure
{
_elems[0]->setIsMarked( true );
gp_XYZ norm = GetNorm();
double maxX = norm.Coord(1);
if ( Abs( maxX ) < Abs( norm.Coord(2)) ) maxX = norm.Coord(2);
if ( Abs( maxX ) < Abs( norm.Coord(3)) ) maxX = norm.Coord(3);
if ( maxX < 0 )
{
_elems[0]->setIsMarked( false );
_elems[1]->setIsMarked( true );
}
}
}; // struct FissureBorder
//--------------------------------------------------------------------------------
/*!
* \brief Classifier of elements at fissure edge
*/
class FissureNormal
{
std::vector< gp_XYZ > _normals;
bool _bothIn;
public:
void Add( const SMDS_MeshNode* n, const FissureBorder& bord )
{
_bothIn = false;
_normals.reserve(2);
_normals.push_back( bord.GetNorm() );
if ( _normals.size() == 2 )
_bothIn = !isOut( n, _normals[0], bord.GetMarkedElem() );
}
bool IsIn( const SMDS_MeshNode* n, const SMDS_MeshElement* elem ) const
{
bool isIn = false;
switch ( _normals.size() ) {
case 1:
{
isIn = !isOut( n, _normals[0], elem );
break;
}
case 2:
{
bool in1 = !isOut( n, _normals[0], elem );
bool in2 = !isOut( n, _normals[1], elem );
isIn = _bothIn ? ( in1 && in2 ) : ( in1 || in2 );
}
}
return isIn;
}
};
//================================================================================
/*!
* \brief Classify an element by a plane passing through a node
*/
//================================================================================
bool isOut( const SMDS_MeshNode* n, const gp_XYZ& norm, const SMDS_MeshElement* elem )
{
SMESH_NodeXYZ p = n;
double sumDot = 0;
for ( int i = 0, nb = elem->NbCornerNodes(); i < nb; ++i )
{
SMESH_NodeXYZ pi = elem->GetNode( i );
sumDot += norm * ( pi - p );
}
return sumDot < -1e-100;
}
//================================================================================
/*!
* \brief Find FissureBorder's by nodes to duplicate
*/
//================================================================================
void findFissureBorders( const TIDSortedElemSet& theNodes,
std::vector< FissureBorder > & theFissureBorders )
{
TIDSortedElemSet::const_iterator nIt = theNodes.begin();
const SMDS_MeshNode* n = dynamic_cast< const SMDS_MeshNode*>( *nIt );
if ( !n ) return;
SMDSAbs_ElementType elemType = SMDSAbs_Volume;
if ( n->NbInverseElements( elemType ) == 0 )
{
elemType = SMDSAbs_Face;
if ( n->NbInverseElements( elemType ) == 0 )
return;
}
// unmark elements touching the fissure
for ( ; nIt != theNodes.end(); ++nIt )
SMESH_MeshAlgos::MarkElems( cast2Node(*nIt)->GetInverseElementIterator(), false );
// loop on elements touching the fissure to get their borders belonging to the fissure
std::set< FissureBorder > fissureBorders;
std::vector< const SMDS_MeshElement* > adjElems;
std::vector< const SMDS_MeshNode* > nodes;
SMDS_VolumeTool volTool;
for ( nIt = theNodes.begin(); nIt != theNodes.end(); ++nIt )
{
SMDS_ElemIteratorPtr invIt = cast2Node(*nIt)->GetInverseElementIterator( elemType );
while ( invIt->more() )
{
const SMDS_MeshElement* eInv = invIt->next();
if ( eInv->isMarked() ) continue;
eInv->setIsMarked( true );
if ( elemType == SMDSAbs_Volume )
{
volTool.Set( eInv );
int iQuad = eInv->IsQuadratic() ? 2 : 1;
for ( int iF = 0, nbF = volTool.NbFaces(); iF < nbF; ++iF )
{
const SMDS_MeshNode** nn = volTool.GetFaceNodes( iF );
int nbN = volTool.NbFaceNodes( iF ) / iQuad;
nodes.clear();
bool allOnFissure = true;
for ( int iN = 0; iN < nbN && allOnFissure; iN += iQuad )
if (( allOnFissure = theNodes.count( nn[ iN ])))
nodes.push_back( nn[ iN ]);
if ( allOnFissure )
fissureBorders.insert( std::move( FissureBorder( &nodes[0], nodes.size(),
elemType, adjElems )));
}
}
else // elemType == SMDSAbs_Face
{
const SMDS_MeshNode* nn[2] = { eInv->GetNode( eInv->NbCornerNodes()-1 ), 0 };
bool onFissure0 = theNodes.count( nn[0] ), onFissure1;
for ( int iN = 0, nbN = eInv->NbCornerNodes(); iN < nbN; ++iN )
{
nn[1] = eInv->GetNode( iN );
onFissure1 = theNodes.count( nn[1] );
if ( onFissure0 && onFissure1 )
fissureBorders.insert( std::move( FissureBorder( nn, 2, elemType, adjElems )));
nn[0] = nn[1];
onFissure0 = onFissure1;
}
}
}
}
theFissureBorders.reserve( theFissureBorders.size() + fissureBorders.size());
std::set< FissureBorder >::iterator bord = fissureBorders.begin();
for ( ; bord != fissureBorders.end(); ++bord )
{
theFissureBorders.push_back( std::move( const_cast<FissureBorder&>( *bord ) ));
}
return;
} // findFissureBorders()
//================================================================================
/*!
* \brief Find elements on one side of a fissure defined by elements or nodes to duplicate
* \param [in] theElemsOrNodes - elements or nodes to duplicate
* \param [in] theNodesNot - nodes not to duplicate
* \param [out] theAffectedElems - the found elements
*/
//================================================================================
void findAffectedElems( const TIDSortedElemSet& theElemsOrNodes,
TIDSortedElemSet& theAffectedElems)
{
if ( theElemsOrNodes.empty() ) return;
// find FissureBorder's
std::vector< FissureBorder > fissure;
std::vector< const SMDS_MeshElement* > elemsByFacet;
TIDSortedElemSet::const_iterator elIt = theElemsOrNodes.begin();
if ( (*elIt)->GetType() == SMDSAbs_Node )
{
findFissureBorders( theElemsOrNodes, fissure );
}
else
{
fissure.reserve( theElemsOrNodes.size() );
for ( ; elIt != theElemsOrNodes.end(); ++elIt )
fissure.push_back( std::move( FissureBorder( *elIt, elemsByFacet )));
}
if ( fissure.empty() )
return;
// fill borderLinks
TBorderLinks borderLinks;
for ( size_t i = 0; i < fissure.size(); ++i )
{
fissure[i].AddSelfTo( borderLinks );
}
// get theAffectedElems
// unmark elements having nodes on the fissure, theAffectedElems elements will be marked
for ( size_t i = 0; i < fissure.size(); ++i )
for ( size_t j = 0; j < fissure[i]._nodes.size(); ++j )
{
SMESH_MeshAlgos::MarkElemNodes( fissure[i]._nodes[j]->GetInverseElementIterator(),
false, /*markElem=*/true );
}
std::vector<const SMDS_MeshNode *> facetNodes;
std::map< const SMDS_MeshNode*, FissureNormal > fissEdgeNodes2Norm;
boost::container::flat_set< const SMDS_MeshNode* > fissureNodes;
// choose a side of fissure
fissure[0].ChooseSide();
theAffectedElems.insert( fissure[0].GetMarkedElem() );
size_t nbCheckedBorders = 0;
while ( nbCheckedBorders < fissure.size() )
{
// find a FissureBorder to treat
FissureBorder* bord = 0;
for ( size_t i = 0; i < fissure.size() && !bord; ++i )
if ( fissure[i].GetMarkedElem() )
bord = & fissure[i];
for ( size_t i = 0; i < fissure.size() && !bord; ++i )
if ( fissure[i].NbSub() > 0 && fissure[i]._elems[0] )
{
bord = & fissure[i];
bord->ChooseSide();
theAffectedElems.insert( bord->GetMarkedElem() );
}
if ( !bord ) return;
++nbCheckedBorders;
// treat FissureBorder's linked to bord
fissureNodes.clear();
fissureNodes.insert( bord->_nodes.begin(), bord->_nodes.end() );
for ( size_t i = 0; i < bord->NbSub(); ++i )
{
TBorderLinks::iterator l2b = bord->_mappedSubs[ i ];
if ( l2b == borderLinks.end() || l2b->second.empty() ) continue;
std::vector< FissureBorder* >& linkedBorders = l2b->second;
const SubBorder& sb = l2b->first;
const SMDS_MeshElement* bordElem = bord->GetMarkedElem();
if ( linkedBorders.size() == 1 ) // fissure edge reached, fill fissEdgeNodes2Norm
{
for ( int j = 0; j < sb._nbNodes; ++j )
fissEdgeNodes2Norm[ sb._nodes[j] ].Add( sb._nodes[j], *bord );
continue;
}
// add to theAffectedElems elems sharing nodes of a SubBorder and a node of bordElem
// until an elem adjacent to a neighbour FissureBorder is found
facetNodes.clear();
facetNodes.insert( facetNodes.end(), sb._nodes, sb._nodes + sb._nbNodes );
facetNodes.resize( sb._nbNodes + 1 );
while ( bordElem )
{
// check if bordElem is adjacent to a neighbour FissureBorder
for ( size_t j = 0; j < linkedBorders.size(); ++j )
{
FissureBorder* bord2 = linkedBorders[j];
if ( bord2 == bord ) continue;
if ( bordElem == bord2->_elems[0] || bordElem == bord2->_elems[1] )
bordElem = 0;
else
fissureNodes.insert( bord2->_nodes.begin(), bord2->_nodes.end() );
}
if ( !bordElem )
break;
// find the next bordElem
const SMDS_MeshElement* nextBordElem = 0;
for ( int iN = 0, nbN = bordElem->NbCornerNodes(); iN < nbN && !nextBordElem; ++iN )
{
const SMDS_MeshNode* n = bordElem->GetNode( iN );
if ( fissureNodes.count( n )) continue;
facetNodes[ sb._nbNodes ] = n;
elemsByFacet.clear();
if ( SMDS_Mesh::GetElementsByNodes( facetNodes, elemsByFacet ) > 1 )
{
for ( size_t iE = 0; iE < elemsByFacet.size(); ++iE )
if ( elemsByFacet[ iE ] != bordElem &&
!elemsByFacet[ iE ]->isMarked() )
{
theAffectedElems.insert( elemsByFacet[ iE ]);
elemsByFacet[ iE ]->setIsMarked( true );
if ( elemsByFacet[ iE ]->GetType() == bordElem->GetType() )
nextBordElem = elemsByFacet[ iE ];
}
}
}
bordElem = nextBordElem;
} // while ( bordElem )
linkedBorders.clear(); // not to treat this link any more
} // loop on SubBorder's of a FissureBorder
bord->Clear();
} // loop on FissureBorder's
// add elements sharing only one node of the fissure, except those sharing fissure edge nodes
// mark nodes of theAffectedElems
SMESH_MeshAlgos::MarkElemNodes( theAffectedElems.begin(), theAffectedElems.end(), true );
// unmark nodes of the fissure
elIt = theElemsOrNodes.begin();
if ( (*elIt)->GetType() == SMDSAbs_Node )
SMESH_MeshAlgos::MarkElems( elIt, theElemsOrNodes.end(), false );
else
SMESH_MeshAlgos::MarkElemNodes( elIt, theElemsOrNodes.end(), false );
std::vector< gp_XYZ > normVec;
// loop on nodes of the fissure, add elements having marked nodes
for ( elIt = theElemsOrNodes.begin(); elIt != theElemsOrNodes.end(); ++elIt )
{
const SMDS_MeshElement* e = (*elIt);
if ( e->GetType() != SMDSAbs_Node )
e->setIsMarked( true ); // avoid adding a fissure element
for ( int iN = 0, nbN = e->NbCornerNodes(); iN < nbN; ++iN )
{
const SMDS_MeshNode* n = e->GetNode( iN );
if ( fissEdgeNodes2Norm.count( n ))
continue;
SMDS_ElemIteratorPtr invIt = n->GetInverseElementIterator();
while ( invIt->more() )
{
const SMDS_MeshElement* eInv = invIt->next();
if ( eInv->isMarked() ) continue;
eInv->setIsMarked( true );
SMDS_ElemIteratorPtr nIt = eInv->nodesIterator();
while( nIt->more() )
if ( nIt->next()->isMarked())
{
theAffectedElems.insert( eInv );
SMESH_MeshAlgos::MarkElems( eInv->nodesIterator(), true );
n->setIsMarked( false );
break;
}
}
}
}
// add elements on the fissure edge
std::map< const SMDS_MeshNode*, FissureNormal >::iterator n2N;
for ( n2N = fissEdgeNodes2Norm.begin(); n2N != fissEdgeNodes2Norm.end(); ++n2N )
{
const SMDS_MeshNode* edgeNode = n2N->first;
const FissureNormal & normals = n2N->second;
SMDS_ElemIteratorPtr invIt = edgeNode->GetInverseElementIterator();
while ( invIt->more() )
{
const SMDS_MeshElement* eInv = invIt->next();
if ( eInv->isMarked() ) continue;
eInv->setIsMarked( true );
// classify eInv using normals
bool toAdd = normals.IsIn( edgeNode, eInv );
if ( toAdd ) // check if all nodes lie on the fissure edge
{
bool notOnEdge = false;
for ( int iN = 0, nbN = eInv->NbCornerNodes(); iN < nbN && !notOnEdge; ++iN )
notOnEdge = !fissEdgeNodes2Norm.count( eInv->GetNode( iN ));
toAdd = notOnEdge;
}
if ( toAdd )
{
theAffectedElems.insert( eInv );
}
}
}
return;
} // findAffectedElems()
} // namespace
//================================================================================ //================================================================================
/*! /*!
* \brief Create elements equal (on same nodes) to given ones * \brief Create elements equal (on same nodes) to given ones
@ -10613,7 +11163,6 @@ void SMESH_MeshEditor::DoubleElements( const TIDSortedElemSet& theElements )
SMDSAbs_ElementType type = SMDSAbs_All; SMDSAbs_ElementType type = SMDSAbs_All;
SMDS_ElemIteratorPtr elemIt; SMDS_ElemIteratorPtr elemIt;
vector< const SMDS_MeshElement* > allElems;
if ( theElements.empty() ) if ( theElements.empty() )
{ {
if ( mesh->NbNodes() == 0 ) if ( mesh->NbNodes() == 0 )
@ -10629,12 +11178,7 @@ void SMESH_MeshEditor::DoubleElements( const TIDSortedElemSet& theElements )
type = types[i]; type = types[i];
break; break;
} }
// put all elements in the vector <allElems>
allElems.reserve( mesh->GetMeshInfo().NbElements( type ));
elemIt = mesh->elementsIterator( type ); elemIt = mesh->elementsIterator( type );
while ( elemIt->more() )
allElems.push_back( elemIt->next());
elemIt = elemSetIterator( allElems );
} }
else else
{ {
@ -10676,8 +11220,7 @@ bool SMESH_MeshEditor::DoubleNodes( const TIDSortedElemSet& theElems,
const TIDSortedElemSet& theNodesNot, const TIDSortedElemSet& theNodesNot,
const TIDSortedElemSet& theAffectedElems ) const TIDSortedElemSet& theAffectedElems )
{ {
myLastCreatedElems.Clear(); ClearLastCreated();
myLastCreatedNodes.Clear();
if ( theElems.size() == 0 ) if ( theElems.size() == 0 )
return false; return false;
@ -10722,8 +11265,8 @@ bool SMESH_MeshEditor::doubleNodes(SMESHDS_Mesh* theMeshDS,
for ( ; elemItr != theElems.end(); ++elemItr ) for ( ; elemItr != theElems.end(); ++elemItr )
{ {
const SMDS_MeshElement* anElem = *elemItr; const SMDS_MeshElement* anElem = *elemItr;
if (!anElem) // if (!anElem)
continue; // continue;
// duplicate nodes to duplicate element // duplicate nodes to duplicate element
bool isDuplicate = false; bool isDuplicate = false;
@ -10777,8 +11320,7 @@ bool SMESH_MeshEditor::doubleNodes(SMESHDS_Mesh* theMeshDS,
bool SMESH_MeshEditor::DoubleNodes( const std::list< int >& theListOfNodes, bool SMESH_MeshEditor::DoubleNodes( const std::list< int >& theListOfNodes,
const std::list< int >& theListOfModifiedElems ) const std::list< int >& theListOfModifiedElems )
{ {
myLastCreatedElems.Clear(); ClearLastCreated();
myLastCreatedNodes.Clear();
if ( theListOfNodes.size() == 0 ) if ( theListOfNodes.size() == 0 )
return false; return false;
@ -10794,8 +11336,7 @@ bool SMESH_MeshEditor::DoubleNodes( const std::list< int >& theListOfNodes,
std::list< int >::const_iterator aNodeIter; std::list< int >::const_iterator aNodeIter;
for ( aNodeIter = theListOfNodes.begin(); aNodeIter != theListOfNodes.end(); ++aNodeIter ) for ( aNodeIter = theListOfNodes.begin(); aNodeIter != theListOfNodes.end(); ++aNodeIter )
{ {
int aCurr = *aNodeIter; const SMDS_MeshNode* aNode = aMeshDS->FindNode( *aNodeIter );
SMDS_MeshNode* aNode = (SMDS_MeshNode*)aMeshDS->FindNode( aCurr );
if ( !aNode ) if ( !aNode )
continue; continue;
@ -10810,49 +11351,28 @@ bool SMESH_MeshEditor::DoubleNodes( const std::list< int >& theListOfNodes,
} }
} }
// Create map of new nodes for modified elements // Change nodes of elements
std::map< SMDS_MeshElement*, vector<const SMDS_MeshNode*> > anElemToNodes; std::vector<const SMDS_MeshNode*> aNodeArr;
std::list< int >::const_iterator anElemIter; std::list< int >::const_iterator anElemIter;
for ( anElemIter = theListOfModifiedElems.begin(); for ( anElemIter = theListOfModifiedElems.begin();
anElemIter != theListOfModifiedElems.end(); ++anElemIter ) anElemIter != theListOfModifiedElems.end();
anElemIter++ )
{ {
int aCurr = *anElemIter; const SMDS_MeshElement* anElem = aMeshDS->FindElement( *anElemIter );
SMDS_MeshElement* anElem = (SMDS_MeshElement*)aMeshDS->FindElement( aCurr );
if ( !anElem ) if ( !anElem )
continue; continue;
vector<const SMDS_MeshNode*> aNodeArr( anElem->NbNodes() ); aNodeArr.assign( anElem->begin_nodes(), anElem->end_nodes() );
for( size_t i = 0; i < aNodeArr.size(); ++i )
SMDS_ElemIteratorPtr anIter = anElem->nodesIterator();
int ind = 0;
while ( anIter->more() )
{ {
SMDS_MeshNode* aCurrNode = (SMDS_MeshNode*)anIter->next(); std::map< const SMDS_MeshNode*, const SMDS_MeshNode* >::iterator n2n =
if ( aCurr && anOldNodeToNewNode.find( aCurrNode ) != anOldNodeToNewNode.end() ) anOldNodeToNewNode.find( aNodeArr[ i ]);
{ if ( n2n != anOldNodeToNewNode.end() )
const SMDS_MeshNode* aNewNode = anOldNodeToNewNode[ aCurrNode ]; aNodeArr[ i ] = n2n->second;
aNodeArr[ ind++ ] = aNewNode;
}
else
aNodeArr[ ind++ ] = aCurrNode;
}
anElemToNodes[ anElem ] = aNodeArr;
}
// Change nodes of elements
std::map< SMDS_MeshElement*, vector<const SMDS_MeshNode*> >::iterator
anElemToNodesIter = anElemToNodes.begin();
for ( ; anElemToNodesIter != anElemToNodes.end(); ++anElemToNodesIter )
{
const SMDS_MeshElement* anElem = anElemToNodesIter->first;
vector<const SMDS_MeshNode*> aNodeArr = anElemToNodesIter->second;
if ( anElem )
{
aMeshDS->ChangeElementNodes( anElem, &aNodeArr[ 0 ], anElem->NbNodes() );
} }
aMeshDS->ChangeElementNodes( anElem, &aNodeArr[ 0 ], aNodeArr.size() );
} }
return true; return true;
@ -10874,8 +11394,8 @@ namespace {
{ {
gp_XYZ centerXYZ (0, 0, 0); gp_XYZ centerXYZ (0, 0, 0);
SMDS_ElemIteratorPtr aNodeItr = theElem->nodesIterator(); SMDS_ElemIteratorPtr aNodeItr = theElem->nodesIterator();
while (aNodeItr->more()) while ( aNodeItr->more() )
centerXYZ += SMESH_TNodeXYZ(cast2Node( aNodeItr->next())); centerXYZ += SMESH_NodeXYZ( aNodeItr->next() );
gp_Pnt aPnt = centerXYZ / theElem->NbNodes(); gp_Pnt aPnt = centerXYZ / theElem->NbNodes();
theClassifier.Perform(aPnt, theTol); theClassifier.Perform(aPnt, theTol);
@ -10930,9 +11450,9 @@ namespace {
(select elements with a gravity center on the side given by faces normals). (select elements with a gravity center on the side given by faces normals).
This mode (null shape) is faster, but works only when theElems are faces, with coherents orientations. This mode (null shape) is faster, but works only when theElems are faces, with coherents orientations.
The replicated nodes should be associated to affected elements. The replicated nodes should be associated to affected elements.
\return groups of affected elements \return true
\sa DoubleNodeElemGroupsInRegion() \sa DoubleNodeElemGroupsInRegion()
*/ */
//================================================================================ //================================================================================
bool SMESH_MeshEditor::AffectedElemGroupsInRegion( const TIDSortedElemSet& theElems, bool SMESH_MeshEditor::AffectedElemGroupsInRegion( const TIDSortedElemSet& theElems,
@ -10942,94 +11462,7 @@ bool SMESH_MeshEditor::AffectedElemGroupsInRegion( const TIDSortedElemSet& theEl
{ {
if ( theShape.IsNull() ) if ( theShape.IsNull() )
{ {
std::set<const SMDS_MeshNode*> alreadyCheckedNodes; findAffectedElems( theElems, theAffectedElems );
std::set<const SMDS_MeshElement*> alreadyCheckedElems;
std::set<const SMDS_MeshElement*> edgesToCheck;
alreadyCheckedNodes.clear();
alreadyCheckedElems.clear();
edgesToCheck.clear();
// --- iterates on elements to be replicated and get elements by back references from their nodes
TIDSortedElemSet::const_iterator elemItr = theElems.begin();
for ( ; elemItr != theElems.end(); ++elemItr )
{
SMDS_MeshElement* anElem = (SMDS_MeshElement*)*elemItr;
if (!anElem || (anElem->GetType() != SMDSAbs_Face))
continue;
gp_XYZ normal;
SMESH_MeshAlgos::FaceNormal( anElem, normal, /*normalized=*/true );
std::set<const SMDS_MeshNode*> nodesElem;
nodesElem.clear();
SMDS_ElemIteratorPtr nodeItr = anElem->nodesIterator();
while ( nodeItr->more() )
{
const SMDS_MeshNode* aNode = cast2Node(nodeItr->next());
nodesElem.insert(aNode);
}
std::set<const SMDS_MeshNode*>::iterator nodit = nodesElem.begin();
for (; nodit != nodesElem.end(); nodit++)
{
const SMDS_MeshNode* aNode = *nodit;
if ( !aNode || theNodesNot.find(aNode) != theNodesNot.end() )
continue;
if (alreadyCheckedNodes.find(aNode) != alreadyCheckedNodes.end())
continue;
alreadyCheckedNodes.insert(aNode);
SMDS_ElemIteratorPtr backElemItr = aNode->GetInverseElementIterator();
while ( backElemItr->more() )
{
const SMDS_MeshElement* curElem = backElemItr->next();
if (alreadyCheckedElems.find(curElem) != alreadyCheckedElems.end())
continue;
if (theElems.find(curElem) != theElems.end())
continue;
alreadyCheckedElems.insert(curElem);
double x=0, y=0, z=0;
int nb = 0;
SMDS_ElemIteratorPtr nodeItr2 = curElem->nodesIterator();
while ( nodeItr2->more() )
{
const SMDS_MeshNode* anotherNode = cast2Node(nodeItr2->next());
x += anotherNode->X();
y += anotherNode->Y();
z += anotherNode->Z();
nb++;
}
gp_XYZ p;
p.SetCoord( x/nb -aNode->X(),
y/nb -aNode->Y(),
z/nb -aNode->Z() );
if (normal*p > 0)
{
theAffectedElems.insert( curElem );
}
else if (curElem->GetType() == SMDSAbs_Edge)
edgesToCheck.insert(curElem);
}
}
}
// --- add also edges lying on the set of faces (all nodes in alreadyCheckedNodes)
std::set<const SMDS_MeshElement*>::iterator eit = edgesToCheck.begin();
for( ; eit != edgesToCheck.end(); eit++)
{
bool onside = true;
const SMDS_MeshElement* anEdge = *eit;
SMDS_ElemIteratorPtr nodeItr = anEdge->nodesIterator();
while ( nodeItr->more() )
{
const SMDS_MeshNode* aNode = cast2Node(nodeItr->next());
if (alreadyCheckedNodes.find(aNode) == alreadyCheckedNodes.end())
{
onside = false;
break;
}
}
if (onside)
{
theAffectedElems.insert(anEdge);
}
}
} }
else else
{ {
@ -11051,8 +11484,6 @@ bool SMESH_MeshEditor::AffectedElemGroupsInRegion( const TIDSortedElemSet& theEl
for ( ; elemItr != theElems.end(); ++elemItr ) for ( ; elemItr != theElems.end(); ++elemItr )
{ {
SMDS_MeshElement* anElem = (SMDS_MeshElement*)*elemItr; SMDS_MeshElement* anElem = (SMDS_MeshElement*)*elemItr;
if (!anElem)
continue;
SMDS_ElemIteratorPtr nodeItr = anElem->nodesIterator(); SMDS_ElemIteratorPtr nodeItr = anElem->nodesIterator();
while ( nodeItr->more() ) while ( nodeItr->more() )
{ {

View File

@ -165,19 +165,21 @@ SMESHGUI_DuplicateNodesDlg::SMESHGUI_DuplicateNodesDlg( SMESHGUI* theModule )
mySelectButton3->setIcon(iconSelect); mySelectButton3->setIcon(iconSelect);
myLineEdit3 = new QLineEdit(myGroupArguments); myLineEdit3 = new QLineEdit(myGroupArguments);
myLineEdit3->setReadOnly(true); myLineEdit3->setReadOnly(true);
myGenerateButton3 = new QPushButton(tr("GENERATE_GROUPS"), myGroupArguments);
myCheckBox1 = new QCheckBox(tr("CONSTRUCT_NEW_GROUP_ELEMENTS"), myGroupArguments); myCheckBox1 = new QCheckBox(tr("CONSTRUCT_NEW_GROUP_ELEMENTS"), myGroupArguments);
myCheckBox2 = new QCheckBox(tr("CONSTRUCT_NEW_GROUP_NODES"), myGroupArguments); myCheckBox2 = new QCheckBox(tr("CONSTRUCT_NEW_GROUP_NODES"), myGroupArguments);
aGroupArgumentsLayout->addWidget(myTextLabel1, 0, 0); aGroupArgumentsLayout->addWidget(myTextLabel1, 0, 0);
aGroupArgumentsLayout->addWidget(mySelectButton1, 0, 1); aGroupArgumentsLayout->addWidget(mySelectButton1, 0, 1);
aGroupArgumentsLayout->addWidget(myLineEdit1, 0, 2); aGroupArgumentsLayout->addWidget(myLineEdit1, 0, 2, 1, 2);
aGroupArgumentsLayout->addWidget(myTextLabel2, 1, 0); aGroupArgumentsLayout->addWidget(myTextLabel2, 1, 0);
aGroupArgumentsLayout->addWidget(mySelectButton2, 1, 1); aGroupArgumentsLayout->addWidget(mySelectButton2, 1, 1);
aGroupArgumentsLayout->addWidget(myLineEdit2, 1, 2); aGroupArgumentsLayout->addWidget(myLineEdit2, 1, 2, 1, 2);
aGroupArgumentsLayout->addWidget(myTextLabel3, 2, 0); aGroupArgumentsLayout->addWidget(myTextLabel3, 2, 0);
aGroupArgumentsLayout->addWidget(mySelectButton3, 2, 1); aGroupArgumentsLayout->addWidget(mySelectButton3, 2, 1);
aGroupArgumentsLayout->addWidget(myLineEdit3, 2, 2); aGroupArgumentsLayout->addWidget(myLineEdit3, 2, 2);
aGroupArgumentsLayout->addWidget(myGenerateButton3,2, 3);
aGroupArgumentsLayout->addWidget(myCheckBox1, 3, 0); aGroupArgumentsLayout->addWidget(myCheckBox1, 3, 0);
aGroupArgumentsLayout->addWidget(myCheckBox2, 4, 0); aGroupArgumentsLayout->addWidget(myCheckBox2, 4, 0);
aGroupArgumentsLayout->setRowStretch(5, 1); aGroupArgumentsLayout->setRowStretch(5, 1);
@ -226,6 +228,7 @@ SMESHGUI_DuplicateNodesDlg::SMESHGUI_DuplicateNodesDlg( SMESHGUI* theModule )
connect(mySelectButton1, SIGNAL (clicked()), this, SLOT(onEditCurrentArgument())); connect(mySelectButton1, SIGNAL (clicked()), this, SLOT(onEditCurrentArgument()));
connect(mySelectButton2, SIGNAL (clicked()), this, SLOT(onEditCurrentArgument())); connect(mySelectButton2, SIGNAL (clicked()), this, SLOT(onEditCurrentArgument()));
connect(mySelectButton3, SIGNAL (clicked()), this, SLOT(onEditCurrentArgument())); connect(mySelectButton3, SIGNAL (clicked()), this, SLOT(onEditCurrentArgument()));
connect(myGenerateButton3, SIGNAL (clicked()), this, SLOT(onGenerate()));
connect(myCheckBox2, SIGNAL(stateChanged(int)), SLOT(updateButtons())); connect(myCheckBox2, SIGNAL(stateChanged(int)), SLOT(updateButtons()));
@ -302,19 +305,20 @@ void SMESHGUI_DuplicateNodesDlg::onConstructorsClicked (int constructorId)
// Set text to the group of arguments and to the first two labels // Set text to the group of arguments and to the first two labels
myGroupArguments->setTitle(tr("DUPLICATION_WITHOUT_ELEMS")); myGroupArguments->setTitle(tr("DUPLICATION_WITHOUT_ELEMS"));
myTextLabel1->setText(tr("GROUP_NODES_TO_DUPLICATE")); myTextLabel1->setText(tr("GROUP_NODES_TO_DUPLICATE"));
myTextLabel2->setText(tr("GROUP_NODES_TO_REPLACE")); myTextLabel3->setText(tr("GROUP_NODES_TO_REPLACE"));
myCheckBox1->hide(); myCheckBox1->hide();
myCheckBox2->show(); myCheckBox2->show();
myCheckBox2->setText( tr("CONSTRUCT_NEW_GROUP_NODES")); myCheckBox2->setText( tr("CONSTRUCT_NEW_GROUP_NODES"));
// Hide the third field // Hide the 2nd field
myTextLabel2->show(); myTextLabel2 ->hide();
mySelectButton2->show(); mySelectButton2 ->hide();
myLineEdit2->show(); myLineEdit2 ->hide();
myTextLabel3->hide(); myTextLabel3 ->show();
mySelectButton3->hide(); mySelectButton3 ->show();
myLineEdit3->hide(); myLineEdit3 ->show();
myGenerateButton3->show();
break; break;
} }
@ -331,13 +335,14 @@ void SMESHGUI_DuplicateNodesDlg::onConstructorsClicked (int constructorId)
myCheckBox1->setText( tr("CONSTRUCT_NEW_GROUP_ELEMENTS")); myCheckBox1->setText( tr("CONSTRUCT_NEW_GROUP_ELEMENTS"));
myCheckBox2->setText( tr("CONSTRUCT_NEW_GROUP_NODES")); myCheckBox2->setText( tr("CONSTRUCT_NEW_GROUP_NODES"));
// Show the third field // Show the 2nd field
myTextLabel2->show(); myTextLabel2 ->show();
mySelectButton2->show(); mySelectButton2 ->show();
myLineEdit2->show(); myLineEdit2 ->show();
myTextLabel3->show(); myTextLabel3 ->show();
mySelectButton3->show(); mySelectButton3 ->show();
myLineEdit3->show(); myLineEdit3 ->show();
myGenerateButton3->show();
break; break;
} }
@ -352,12 +357,13 @@ void SMESHGUI_DuplicateNodesDlg::onConstructorsClicked (int constructorId)
myCheckBox2->hide(); myCheckBox2->hide();
// Hide the second and the third field // Hide the second and the third field
myTextLabel2->hide(); myTextLabel2 ->hide();
mySelectButton2->hide(); mySelectButton2 ->hide();
myLineEdit2->hide(); myLineEdit2 ->hide();
myTextLabel3->hide(); myTextLabel3 ->hide();
mySelectButton3->hide(); mySelectButton3 ->hide();
myLineEdit3->hide(); myLineEdit3 ->hide();
myGenerateButton3->hide();
break; break;
} }
@ -373,12 +379,13 @@ void SMESHGUI_DuplicateNodesDlg::onConstructorsClicked (int constructorId)
myCheckBox2->setText( tr("ON_ALL_BOUNDARIES")); myCheckBox2->setText( tr("ON_ALL_BOUNDARIES"));
// Hide the second and the third field // Hide the second and the third field
myTextLabel2->hide(); myTextLabel2 ->hide();
mySelectButton2->hide(); mySelectButton2 ->hide();
myLineEdit2->hide(); myLineEdit2 ->hide();
myTextLabel3->hide(); myTextLabel3 ->hide();
mySelectButton3->hide(); mySelectButton3 ->hide();
myLineEdit3->hide(); myLineEdit3 ->hide();
myGenerateButton3->hide();
break; break;
} }
@ -421,9 +428,9 @@ bool SMESHGUI_DuplicateNodesDlg::onApply()
for ( int i = 0; i < myGroups1.count(); i++ ) for ( int i = 0; i < myGroups1.count(); i++ )
g1[i] = myGroups1[i]; g1[i] = myGroups1[i];
SMESH::ListOfGroups_var g2 = new SMESH::ListOfGroups(); SMESH::ListOfGroups_var g2 = new SMESH::ListOfGroups();
g2->length( myGroups2.count() ); g2->length( myGroups3.count() );
for ( int i = 0; i < myGroups2.count(); i++ ) for ( int i = 0; i < myGroups3.count(); i++ )
g2[i] = myGroups2[i]; g2[i] = myGroups3[i];
if ( toCreateNodeGroup ) { if ( toCreateNodeGroup ) {
SMESH::SMESH_GroupBase_var aNewGroup = SMESH::SMESH_GroupBase_var aNewGroup =
@ -504,10 +511,10 @@ bool SMESHGUI_DuplicateNodesDlg::onApply()
SalomeApp_Tools::QtCatchCorbaException(S_ex); SalomeApp_Tools::QtCatchCorbaException(S_ex);
} }
catch ( const std::exception& exc ) { catch ( const std::exception& exc ) {
INFOS( "Follow exception was cought:\n\t" << exc.what() ); INFOS( "Follow exception was caught:\n\t" << exc.what() );
} }
catch (...) { catch (...) {
INFOS( "Unknown exception was cought !!!" ); INFOS( "Unknown exception was caught !!!" );
} }
if (!result) { if (!result) {
@ -638,6 +645,9 @@ void SMESHGUI_DuplicateNodesDlg::updateButtons()
bool isDataValid = isValid(); bool isDataValid = isValid();
myButtonOk->setEnabled( isDataValid ); myButtonOk->setEnabled( isDataValid );
myButtonApply->setEnabled( isDataValid ); myButtonApply->setEnabled( isDataValid );
int operationMode = myGroupConstructors->checkedId();
myGenerateButton3->setEnabled( operationMode <= 1 && !myGroups1.empty() );
} }
/*! /*!
@ -690,6 +700,59 @@ void SMESHGUI_DuplicateNodesDlg::onDeactivate()
} }
} }
/*!
\brief SLOT called when Generate button is clicked
*/
void SMESHGUI_DuplicateNodesDlg::onGenerate()
{
if ( mySMESHGUI->isActiveStudyLocked() )
return;
SUIT_OverrideCursor aWaitCursor;
BusyLocker lock( myBusy );
try {
SMESH::SMESH_Mesh_var aMesh = myGroups1[0]->GetMesh();
SMESH::SMESH_MeshEditor_var aMeshEditor = aMesh->GetMeshEditor();
SMESH::ListOfGroups_var g1 = new SMESH::ListOfGroups();
g1->length( myGroups1.count() );
for ( int i = 0; i < myGroups1.count(); i++ )
g1[i] = myGroups1[i];
SMESH::ListOfGroups_var g2 = new SMESH::ListOfGroups();
g2->length( myGroups2.count() );
for ( int i = 0; i < myGroups2.count(); i++ )
g2[i] = myGroups2[i];
SMESH::ListOfGroups_var newGroups =
aMeshEditor->AffectedElemGroupsInRegion( g1, g2, GEOM::GEOM_Object::_nil() );
QString text;
switch ( newGroups->length() ) {
case 0: break;
case 1: text = SMESH::toQStr( newGroups[0]->GetName() ); break;
default: text = tr( "SMESH_OBJECTS_SELECTED" ).arg( newGroups->length() );
}
myLineEdit3->setText( text );
myGroups3.clear();
for ( CORBA::ULong i = 0; i < newGroups->length(); ++i )
myGroups3 << SMESH::SMESH_GroupBase::_duplicate( newGroups[i] );
}
catch (const SALOME::SALOME_Exception& S_ex) {
SalomeApp_Tools::QtCatchCorbaException(S_ex);
}
catch ( const std::exception& exc ) {
INFOS( "Follow exception was caught:\n\t" << exc.what() );
}
catch (...) {
INFOS( "Unknown exception was caught !!!" );
}
mySMESHGUI->updateObjBrowser(true);
updateButtons();
}
/*! /*!
\brief Receive dialog enter events. \brief Receive dialog enter events.
Activates the dialog when the mouse cursor enters. Activates the dialog when the mouse cursor enters.

View File

@ -80,8 +80,8 @@ private slots:
void onEditCurrentArgument(); void onEditCurrentArgument();
void onSelectionChanged(); void onSelectionChanged();
void onDeactivate(); void onDeactivate();
void onGenerate();
void updateButtons(); void updateButtons();
@ -97,6 +97,7 @@ private:
QPushButton* mySelectButton1; QPushButton* mySelectButton1;
QPushButton* mySelectButton2; QPushButton* mySelectButton2;
QPushButton* mySelectButton3; QPushButton* mySelectButton3;
QPushButton* myGenerateButton3;
QLineEdit* myLineEdit1; QLineEdit* myLineEdit1;
QLineEdit* myLineEdit2; QLineEdit* myLineEdit2;
QLineEdit* myLineEdit3; QLineEdit* myLineEdit3;

View File

@ -7212,6 +7212,10 @@ It is impossible to read point coordinates from file</translation>
<source>ON_ALL_BOUNDARIES</source> <source>ON_ALL_BOUNDARIES</source>
<translation>On all boundaries</translation> <translation>On all boundaries</translation>
</message> </message>
<message>
<source>GENERATE_GROUPS</source>
<translation>Generate</translation>
</message>
</context> </context>
<context> <context>
<name>SMESHGUI_Make2DFrom3DDlg</name> <name>SMESHGUI_Make2DFrom3DDlg</name>

View File

@ -154,6 +154,54 @@ namespace SMESH_MeshAlgos
std::vector< const SMDS_MeshNode*> GetCommonNodes(const SMDS_MeshElement* e1, std::vector< const SMDS_MeshNode*> GetCommonNodes(const SMDS_MeshElement* e1,
const SMDS_MeshElement* e2); const SMDS_MeshElement* e2);
/*!
* \brief Mark elements given by SMDS_Iterator
*/
template< class ElemIter >
void MarkElems( ElemIter it, const bool isMarked )
{
while ( it->more() ) it->next()->setIsMarked( isMarked );
}
/*!
* \brief Mark elements given by std iterators
*/
template< class ElemIter >
void MarkElems( ElemIter it, ElemIter end, const bool isMarked )
{
for ( ; it != end; ++it ) (*it)->setIsMarked( isMarked );
}
/*!
* \brief Mark nodes of elements given by SMDS_Iterator
*/
template< class ElemIter >
void MarkElemNodes( ElemIter it, const bool isMarked, const bool markElem = false )
{
if ( markElem )
while ( it->more() ) {
const SMDS_MeshElement* e = it->next();
e->setIsMarked( isMarked );
MarkElems( e->nodesIterator(), isMarked );
}
else
while ( it->more() )
MarkElems( it->next()->nodesIterator(), isMarked );
}
/*!
* \brief Mark elements given by std iterators
*/
template< class ElemIter >
void MarkElemNodes( ElemIter it, ElemIter end, const bool isMarked, const bool markElem = false )
{
if ( markElem )
for ( ; it != end; ++it ) {
(*it)->setIsMarked( isMarked );
MarkElems( (*it)->nodesIterator(), isMarked );
}
else
for ( ; it != end; ++it )
MarkElems( (*it)->nodesIterator(), isMarked );
}
/*! /*!
* \brief Return SMESH_NodeSearcher. The caller is responsible for deleteing it * \brief Return SMESH_NodeSearcher. The caller is responsible for deleteing it
*/ */

View File

@ -746,9 +746,10 @@ Handle(_pyCommand) _pyGen::AddCommand( const TCollection_AsciiString& theCommand
method == "DoubleNodeGroupNew" || method == "DoubleNodeGroupNew" ||
method == "DoubleNodeGroupsNew" || method == "DoubleNodeGroupsNew" ||
method == "DoubleNodeElemGroupNew" || method == "DoubleNodeElemGroupNew" ||
method == "DoubleNodeElemGroupsNew"|| method == "DoubleNodeElemGroupsNew" ||
method == "DoubleNodeElemGroup2New"|| method == "DoubleNodeElemGroup2New" ||
method == "DoubleNodeElemGroups2New" method == "DoubleNodeElemGroups2New" ||
method == "AffectedElemGroupsInRegion"
) )
groups = aCommand->GetResultValue(); groups = aCommand->GetResultValue();
else if ( method == "MakeBoundaryMesh" ) else if ( method == "MakeBoundaryMesh" )
@ -2436,7 +2437,7 @@ void _pyMeshEditor::Process( const Handle(_pyCommand)& theCommand)
"Scale","ScaleMakeMesh","RotateMakeMesh","RotateObjectMakeMesh","MakeBoundaryMesh", "Scale","ScaleMakeMesh","RotateMakeMesh","RotateObjectMakeMesh","MakeBoundaryMesh",
"MakeBoundaryElements", "SplitVolumesIntoTetra","SplitHexahedraIntoPrisms", "MakeBoundaryElements", "SplitVolumesIntoTetra","SplitHexahedraIntoPrisms",
"DoubleElements","DoubleNodes","DoubleNode","DoubleNodeGroup","DoubleNodeGroups", "DoubleElements","DoubleNodes","DoubleNode","DoubleNodeGroup","DoubleNodeGroups",
"DoubleNodeElem","DoubleNodeElemInRegion","DoubleNodeElemGroup", "DoubleNodeElem","DoubleNodeElemInRegion","DoubleNodeElemGroup","AffectedElemGroupsInRegion",
"DoubleNodeElemGroupInRegion","DoubleNodeElemGroups","DoubleNodeElemGroupsInRegion", "DoubleNodeElemGroupInRegion","DoubleNodeElemGroups","DoubleNodeElemGroupsInRegion",
"DoubleNodesOnGroupBoundaries","CreateFlatElementsOnFacesGroups","CreateHoleSkin" "DoubleNodesOnGroupBoundaries","CreateFlatElementsOnFacesGroups","CreateHoleSkin"
,"" }; // <- mark of the end ,"" }; // <- mark of the end

View File

@ -5546,10 +5546,7 @@ CORBA::Boolean SMESH_MeshEditor_i::DoubleNodeGroup(SMESH::SMESH_GroupBase_ptr th
if ( !CORBA::is_nil( theModifiedElems ) ) if ( !CORBA::is_nil( theModifiedElems ) )
aModifiedElems = theModifiedElems->GetListOfID(); aModifiedElems = theModifiedElems->GetListOfID();
else else
{
aModifiedElems = new SMESH::long_array; aModifiedElems = new SMESH::long_array;
aModifiedElems->length( 0 );
}
TPythonDump pyDump; // suppress dump by the next line TPythonDump pyDump; // suppress dump by the next line
@ -6262,12 +6259,9 @@ SMESH_MeshEditor_i::AffectedElemGroupsInRegion( const SMESH::ListOfGroups& theEl
{ {
SMESH_TRY; SMESH_TRY;
SMESH::ListOfGroups_var aListOfGroups = new SMESH::ListOfGroups(); SMESH::ListOfGroups_var aListOfGroups = new SMESH::ListOfGroups();
bool isEdgeGroup = false; SMESH::SMESH_Group_var aNewEdgeGroup = SMESH::SMESH_Group::_nil();
bool isFaceGroup = false; SMESH::SMESH_Group_var aNewFaceGroup = SMESH::SMESH_Group::_nil();
bool isVolumeGroup = false; SMESH::SMESH_Group_var aNewVolumeGroup = SMESH::SMESH_Group::_nil();
SMESH::SMESH_Group_var aNewEdgeGroup = myMesh_i->CreateGroup(SMESH::EDGE, "affectedEdges");
SMESH::SMESH_Group_var aNewFaceGroup = myMesh_i->CreateGroup(SMESH::FACE, "affectedFaces");
SMESH::SMESH_Group_var aNewVolumeGroup = myMesh_i->CreateGroup(SMESH::VOLUME, "affectedVolumes");
initData(); initData();
@ -6275,75 +6269,75 @@ SMESH_MeshEditor_i::AffectedElemGroupsInRegion( const SMESH::ListOfGroups& theEl
SMESHDS_Mesh* aMeshDS = getMeshDS(); SMESHDS_Mesh* aMeshDS = getMeshDS();
TIDSortedElemSet anElems, aNodes; TIDSortedElemSet anElems, aNodes;
listOfGroupToSet(theElems, aMeshDS, anElems, false); bool isNodeGrp = theElems.length() ? theElems[0]->GetType() == SMESH::NODE : false;
listOfGroupToSet(theElems, aMeshDS, anElems, isNodeGrp);
listOfGroupToSet(theNodesNot, aMeshDS, aNodes, true); listOfGroupToSet(theNodesNot, aMeshDS, aNodes, true);
TopoDS_Shape aShape = SMESH_Gen_i::GetSMESHGen()->GeomObjectToShape(theShape); TopoDS_Shape aShape = SMESH_Gen_i::GetSMESHGen()->GeomObjectToShape(theShape);
TIDSortedElemSet anAffected; TIDSortedElemSet anAffected;
bool aResult = aMeshEditor.AffectedElemGroupsInRegion(anElems, aNodes, aShape, anAffected); bool aResult = aMeshEditor.AffectedElemGroupsInRegion(anElems, aNodes, aShape, anAffected);
declareMeshModified( /*isReComputeSafe=*/ !aResult ); declareMeshModified( /*isReComputeSafe=*/ !aResult );
TPythonDump pyDump; TPythonDump pyDump;
if (aResult) if ( aResult && anAffected.size() > 0 )
{ {
int lg = anAffected.size();
SMESH::long_array_var volumeIds = new SMESH::long_array; SMESH::long_array_var volumeIds = new SMESH::long_array;
volumeIds->length(lg);
SMESH::long_array_var faceIds = new SMESH::long_array; SMESH::long_array_var faceIds = new SMESH::long_array;
faceIds->length(lg);
SMESH::long_array_var edgeIds = new SMESH::long_array; SMESH::long_array_var edgeIds = new SMESH::long_array;
edgeIds->length(lg); volumeIds->length( anAffected.size() );
faceIds ->length( anAffected.size() );
edgeIds ->length( anAffected.size() );
int ivol = 0; int ivol = 0;
int iface = 0; int iface = 0;
int iedge = 0; int iedge = 0;
TIDSortedElemSet::const_iterator eIt = anAffected.begin(); TIDSortedElemSet::const_iterator eIt = anAffected.begin();
for (; eIt != anAffected.end(); ++eIt) for (; eIt != anAffected.end(); ++eIt)
{ {
const SMDS_MeshElement* anElem = *eIt; const SMDS_MeshElement* anElem = *eIt;
if (!anElem)
continue;
int elemId = anElem->GetID(); int elemId = anElem->GetID();
if (myMesh->GetElementType(elemId, true) == SMDSAbs_Volume) switch ( anElem->GetType() ) {
volumeIds[ivol++] = elemId; case SMDSAbs_Volume: volumeIds[ivol++] = elemId; break;
else if (myMesh->GetElementType(elemId, true) == SMDSAbs_Face) case SMDSAbs_Face: faceIds[iface++] = elemId; break;
faceIds[iface++] = elemId; case SMDSAbs_Edge: edgeIds[iedge++] = elemId; break;
else if (myMesh->GetElementType(elemId, true) == SMDSAbs_Edge) default:;
edgeIds[iedge++] = elemId; }
} }
volumeIds->length(ivol); volumeIds->length(ivol);
faceIds->length(iface); faceIds->length(iface);
edgeIds->length(iedge); edgeIds->length(iedge);
aNewVolumeGroup->Add(volumeIds);
aNewFaceGroup->Add(faceIds);
aNewEdgeGroup->Add(edgeIds);
isVolumeGroup = (aNewVolumeGroup->Size() > 0);
isFaceGroup = (aNewFaceGroup->Size() > 0);
isEdgeGroup = (aNewEdgeGroup->Size() > 0);
}
int nbGroups = 0; int nbGroups = 0;
if (isEdgeGroup) nbGroups++; if ( ivol > 0 )
if (isFaceGroup) nbGroups++; {
if (isVolumeGroup) nbGroups++; aNewVolumeGroup = myMesh_i->CreateGroup(SMESH::VOLUME,
aListOfGroups->length(nbGroups); generateGroupName("affectedVolumes").c_str());
aNewVolumeGroup->Add(volumeIds);
int i = 0; aListOfGroups->length( nbGroups+1 );
if (isEdgeGroup) aListOfGroups[i++] = aNewEdgeGroup._retn(); aListOfGroups[ nbGroups++ ] = aNewVolumeGroup._retn();
if (isFaceGroup) aListOfGroups[i++] = aNewFaceGroup._retn(); }
if (isVolumeGroup) aListOfGroups[i++] = aNewVolumeGroup._retn(); if ( iface > 0 )
{
aNewFaceGroup = myMesh_i->CreateGroup(SMESH::FACE,
generateGroupName("affectedFaces").c_str());
aNewFaceGroup->Add(faceIds);
aListOfGroups->length( nbGroups+1 );
aListOfGroups[ nbGroups++ ] = aNewFaceGroup._retn();
}
if ( iedge > 0 )
{
aNewEdgeGroup = myMesh_i->CreateGroup(SMESH::EDGE,
generateGroupName("affectedEdges").c_str());
aNewEdgeGroup->Add(edgeIds);
aListOfGroups->length( nbGroups+1 );
aListOfGroups[ nbGroups++ ] = aNewEdgeGroup._retn();
}
}
// Update Python script // Update Python script
pyDump << "[ "; pyDump << aListOfGroups << " = " << this << ".AffectedElemGroupsInRegion( "
if (isEdgeGroup) pyDump << aNewEdgeGroup << ", ";
if (isFaceGroup) pyDump << aNewFaceGroup << ", ";
if (isVolumeGroup) pyDump << aNewVolumeGroup << ", ";
pyDump << "] = ";
pyDump << this << ".AffectedElemGroupsInRegion( "
<< &theElems << ", " << &theNodesNot << ", " << theShape << " )"; << &theElems << ", " << &theNodesNot << ", " << theShape << " )";
return aListOfGroups._retn(); return aListOfGroups._retn();

View File

@ -4904,12 +4904,12 @@ class Mesh:
## Identify the elements that will be affected by node duplication (actual duplication is not performed. ## Identify the elements that will be affected by node duplication (actual duplication is not performed.
# This method is the first step of DoubleNodeElemGroupsInRegion. # This method is the first step of DoubleNodeElemGroupsInRegion.
# @param theElems - list of groups of elements (edges or faces) to be replicated # @param theElems - list of groups of nodes or 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 replicated
# @param theShape - shape to detect affected elements (element which geometric center # @param theShape - shape to detect affected elements (element which geometric center
# located on or inside shape). # located on or inside shape).
# The replicated nodes should be associated to affected elements. # The replicated nodes should be associated to affected elements.
# @return groups of affected elements # @return groups of affected elements in order: volumes, faces, edges
# @ingroup l2_modif_duplicat # @ingroup l2_modif_duplicat
def AffectedElemGroupsInRegion(self, theElems, theNodesNot, theShape): def AffectedElemGroupsInRegion(self, theElems, theNodesNot, theShape):
return self.editor.AffectedElemGroupsInRegion(theElems, theNodesNot, theShape) return self.editor.AffectedElemGroupsInRegion(theElems, theNodesNot, theShape)