23491: EDF 15591 - Duplicate Elements / Nodes
Make AffectedElemGroupsInRegion() universal, make it available in Duplicate dialog
Before Width: | Height: | Size: 23 KiB After Width: | Height: | Size: 22 KiB |
Before Width: | Height: | Size: 28 KiB After Width: | Height: | Size: 27 KiB |
Before Width: | Height: | Size: 20 KiB After Width: | Height: | Size: 18 KiB |
Before Width: | Height: | Size: 22 KiB After Width: | Height: | Size: 19 KiB |
@ -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>
|
||||||
|
@ -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() )
|
||||||
{
|
{
|
||||||
|
@ -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.
|
||||||
|
@ -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;
|
||||||
|
@ -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>
|
||||||
|
@ -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
|
||||||
*/
|
*/
|
||||||
|
@ -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
|
||||||
|
@ -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();
|
||||||
|
@ -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)
|
||||||
|