23525: EDF16278 - Perf of concatenation of meshes

This commit is contained in:
eap 2018-02-19 17:24:51 +03:00
parent 47e876676d
commit 89b15cd78e
6 changed files with 363 additions and 374 deletions

View File

@ -7729,26 +7729,55 @@ bool SMESH_MeshEditor::applyMerge( const SMDS_MeshElement* elem,
// ======================================================== // ========================================================
// class : SortableElement // class : ComparableElement
// purpose : allow sorting elements basing on their nodes // purpose : allow comparing elements basing on their nodes
// ======================================================== // ========================================================
class SortableElement : public set <const SMDS_MeshElement*>
class ComparableElement : public boost::container::flat_set< int >
{ {
typedef boost::container::flat_set< int > int_set;
const SMDS_MeshElement* myElem;
int mySumID;
mutable int myGroupID;
public: public:
SortableElement( const SMDS_MeshElement* theElem ) ComparableElement( const SMDS_MeshElement* theElem ):
myElem ( theElem ), mySumID( 0 ), myGroupID( -1 )
{ {
myElem = theElem; this->reserve( theElem->NbNodes() );
SMDS_ElemIteratorPtr nodeIt = theElem->nodesIterator(); for ( SMDS_ElemIteratorPtr nodeIt = theElem->nodesIterator(); nodeIt->more(); )
while ( nodeIt->more() ) {
this->insert( nodeIt->next() ); int id = nodeIt->next()->GetID();
mySumID += id;
this->insert( id );
}
} }
const SMDS_MeshElement* Get() const const SMDS_MeshElement* GetElem() const { return myElem; }
{ return myElem; }
int& GroupID() const { return myGroupID; }
//int& GroupID() const { return const_cast< int& >( myGroupID ); }
ComparableElement( const ComparableElement& theSource ) // move copy
{
ComparableElement& src = const_cast< ComparableElement& >( theSource );
(int_set&) (*this ) = boost::move( src );
myElem = src.myElem;
mySumID = src.mySumID;
myGroupID = src.myGroupID;
}
static int HashCode(const ComparableElement& se, int limit )
{
return ::HashCode( se.mySumID, limit );
}
static Standard_Boolean IsEqual(const ComparableElement& se1, const ComparableElement& se2 )
{
return ( se1 == se2 );
}
private:
mutable const SMDS_MeshElement* myElem;
}; };
//======================================================================= //=======================================================================
@ -7762,43 +7791,42 @@ void SMESH_MeshEditor::FindEqualElements(TIDSortedElemSet & theElements,
{ {
ClearLastCreated(); ClearLastCreated();
typedef map< SortableElement, int > TMapOfNodeSet;
typedef list<int> TGroupOfElems;
SMDS_ElemIteratorPtr elemIt; SMDS_ElemIteratorPtr elemIt;
if ( theElements.empty() ) elemIt = GetMeshDS()->elementsIterator(); if ( theElements.empty() ) elemIt = GetMeshDS()->elementsIterator();
else elemIt = SMESHUtils::elemSetIterator( theElements ); else elemIt = SMESHUtils::elemSetIterator( theElements );
vector< TGroupOfElems > arrayOfGroups; typedef NCollection_Map< ComparableElement, ComparableElement > TMapOfElements;
typedef std::list<int> TGroupOfElems;
TMapOfElements mapOfElements;
std::vector< TGroupOfElems > arrayOfGroups;
TGroupOfElems groupOfElems; TGroupOfElems groupOfElems;
TMapOfNodeSet mapOfNodeSet;
for ( int iGroup = 0; elemIt->more(); ) while ( elemIt->more() )
{ {
const SMDS_MeshElement* curElem = elemIt->next(); const SMDS_MeshElement* curElem = elemIt->next();
SortableElement SE(curElem); ComparableElement compElem = curElem;
// check uniqueness // check uniqueness
pair< TMapOfNodeSet::iterator, bool> pp = mapOfNodeSet.insert(make_pair(SE, iGroup)); const ComparableElement& elemInSet = mapOfElements.Added( compElem );
if ( !pp.second ) { // one more coincident elem if ( elemInSet.GetElem() != curElem ) // coincident elem
TMapOfNodeSet::iterator& itSE = pp.first; {
int iG = itSE->second; int& iG = elemInSet.GroupID();
arrayOfGroups[ iG ].push_back( curElem->GetID() ); if ( iG < 0 )
} {
else { iG = arrayOfGroups.size();
arrayOfGroups.push_back( groupOfElems ); arrayOfGroups.push_back( groupOfElems );
arrayOfGroups.back().push_back( curElem->GetID() ); arrayOfGroups[ iG ].push_back( elemInSet.GetElem()->GetID() );
iGroup++; }
arrayOfGroups[ iG ].push_back( curElem->GetID() );
} }
} }
groupOfElems.clear(); groupOfElems.clear();
vector< TGroupOfElems >::iterator groupIt = arrayOfGroups.begin(); std::vector< TGroupOfElems >::iterator groupIt = arrayOfGroups.begin();
for ( ; groupIt != arrayOfGroups.end(); ++groupIt ) for ( ; groupIt != arrayOfGroups.end(); ++groupIt )
{ {
if ( groupIt->size() > 1 ) { if ( groupIt->size() > 1 ) {
//groupOfElems.sort(); -- theElements is sorted already //groupOfElems.sort(); -- theElements are sorted already
theGroupsOfElementsID.push_back( groupOfElems ); theGroupsOfElementsID.emplace_back( *groupIt );
theGroupsOfElementsID.back().splice( theGroupsOfElementsID.back().end(), *groupIt );
} }
} }
} }

View File

@ -114,14 +114,15 @@ struct SMESH_NodeSearcherImpl: public SMESH_NodeSearcher
myOctreeNode->NodesAround( thePnt.Coord(), dist2Nodes, myHalfLeafSize ); myOctreeNode->NodesAround( thePnt.Coord(), dist2Nodes, myHalfLeafSize );
if ( !dist2Nodes.empty() ) if ( !dist2Nodes.empty() )
return dist2Nodes.begin()->second; return dist2Nodes.begin()->second;
std::list<const SMDS_MeshNode*> nodes;
std::vector<const SMDS_MeshNode*> nodes;
//myOctreeNode->NodesAround( &tgtNode, &nodes, myHalfLeafSize ); //myOctreeNode->NodesAround( &tgtNode, &nodes, myHalfLeafSize );
double minSqDist = DBL_MAX; double minSqDist = DBL_MAX;
if ( nodes.empty() ) // get all nodes of OctreeNode's closest to thePnt if ( nodes.empty() ) // get all nodes of OctreeNode's closest to thePnt
{ {
// sort leafs by their distance from thePnt // sort leafs by their distance from thePnt
typedef std::map< double, SMESH_OctreeNode* > TDistTreeMap; typedef std::multimap< double, SMESH_OctreeNode* > TDistTreeMap;
TDistTreeMap treeMap; TDistTreeMap treeMap;
std::list< SMESH_OctreeNode* > treeList; std::list< SMESH_OctreeNode* > treeList;
std::list< SMESH_OctreeNode* >::iterator trIt; std::list< SMESH_OctreeNode* >::iterator trIt;
@ -143,10 +144,7 @@ struct SMESH_NodeSearcherImpl: public SMESH_NodeSearcher
{ {
const Bnd_B3d& box = *tree->getBox(); const Bnd_B3d& box = *tree->getBox();
double sqDist = thePnt.SquareDistance( 0.5 * ( box.CornerMin() + box.CornerMax() )); double sqDist = thePnt.SquareDistance( 0.5 * ( box.CornerMin() + box.CornerMax() ));
std::pair<TDistTreeMap::iterator,bool> it_in =
treeMap.insert( std::make_pair( sqDist, tree )); treeMap.insert( std::make_pair( sqDist, tree ));
if ( !it_in.second ) // not unique distance to box center
treeMap.insert( it_in.first, std::make_pair( sqDist + 1e-13*treeMap.size(), tree ));
} }
} }
// find distance after which there is no sense to check tree's // find distance after which there is no sense to check tree's
@ -163,17 +161,17 @@ struct SMESH_NodeSearcherImpl: public SMESH_NodeSearcher
if ( sqDist_tree->first > sqLimit ) if ( sqDist_tree->first > sqLimit )
break; break;
SMESH_OctreeNode* tree = sqDist_tree->second; SMESH_OctreeNode* tree = sqDist_tree->second;
tree->NodesAround( tree->GetNodeIterator()->next(), &nodes ); tree->AllNodesAround( tree->GetNodeIterator()->next(), &nodes );
} }
} }
// find closest among nodes // find closest among nodes
minSqDist = DBL_MAX; minSqDist = DBL_MAX;
const SMDS_MeshNode* closestNode = 0; const SMDS_MeshNode* closestNode = 0;
std::list<const SMDS_MeshNode*>::iterator nIt = nodes.begin(); for ( size_t i = 0; i < nodes.size(); ++i )
for ( ; nIt != nodes.end(); ++nIt ) { {
double sqDist = thePnt.SquareDistance( SMESH_TNodeXYZ( *nIt ) ); double sqDist = thePnt.SquareDistance( SMESH_NodeXYZ( nodes[ i ]));
if ( minSqDist > sqDist ) { if ( minSqDist > sqDist ) {
closestNode = *nIt; closestNode = nodes[ i ];
minSqDist = sqDist; minSqDist = sqDist;
} }
} }
@ -227,7 +225,7 @@ namespace // Utils used in SMESH_ElementSearcherImpl::FindElementsByPoint()
{ {
public: public:
typedef boost::container::flat_set< const SMDS_MeshElement* > TElemSeq; typedef boost::container::flat_set< const SMDS_MeshElement*, TIDCompare > TElemSeq;
ElementBndBoxTree(const SMDS_Mesh& mesh, ElementBndBoxTree(const SMDS_Mesh& mesh,
SMDSAbs_ElementType elemType, SMDSAbs_ElementType elemType,

View File

@ -30,7 +30,9 @@
#include "SMESH_OctreeNode.hxx" #include "SMESH_OctreeNode.hxx"
#include "SMDS_SetIterator.hxx" #include "SMDS_SetIterator.hxx"
#include "SMESH_MeshAlgos.hxx"
#include "SMESH_TypeDefs.hxx" #include "SMESH_TypeDefs.hxx"
#include <gp_Pnt.hxx> #include <gp_Pnt.hxx>
using namespace std; using namespace std;
@ -48,7 +50,7 @@ using namespace std;
SMESH_OctreeNode::SMESH_OctreeNode (const TIDSortedNodeSet & theNodes, const int maxLevel, SMESH_OctreeNode::SMESH_OctreeNode (const TIDSortedNodeSet & theNodes, const int maxLevel,
const int maxNbNodes , const double minBoxSize ) const int maxNbNodes , const double minBoxSize )
:SMESH_Octree( new Limit( maxLevel,minBoxSize,maxNbNodes)), :SMESH_Octree( new Limit( maxLevel,minBoxSize,maxNbNodes)),
myNodes(theNodes) myNodes( theNodes.begin(), theNodes.end() )
{ {
compute(); compute();
} }
@ -96,12 +98,9 @@ SMESH_Octree* SMESH_OctreeNode::newChild() const
Bnd_B3d* SMESH_OctreeNode::buildRootBox() Bnd_B3d* SMESH_OctreeNode::buildRootBox()
{ {
Bnd_B3d* box = new Bnd_B3d; Bnd_B3d* box = new Bnd_B3d;
TIDSortedNodeSet::iterator it = myNodes.begin(); for ( size_t i = 0; i < myNodes.size(); ++i )
for (; it != myNodes.end(); it++) { box->Add( SMESH_NodeXYZ( myNodes[ i ]));
const SMDS_MeshNode* n1 = *it;
gp_XYZ p1( n1->X(), n1->Y(), n1->Z() );
box->Add(p1);
}
if ((int) myNodes.size() <= getMaxNbNodes() ) if ((int) myNodes.size() <= getMaxNbNodes() )
myIsLeaf = true; myIsLeaf = true;
@ -121,6 +120,7 @@ const bool SMESH_OctreeNode::isInside (const gp_XYZ& p, const double precision)
{ {
if ( precision <= 0.) if ( precision <= 0.)
return !( getBox()->IsOut(p) ); return !( getBox()->IsOut(p) );
Bnd_B3d BoxWithPrecision = *getBox(); Bnd_B3d BoxWithPrecision = *getBox();
BoxWithPrecision.Enlarge( precision ); BoxWithPrecision.Enlarge( precision );
return ! BoxWithPrecision.IsOut(p); return ! BoxWithPrecision.IsOut(p);
@ -132,27 +132,37 @@ const bool SMESH_OctreeNode::isInside (const gp_XYZ& p, const double precision)
* Shares the father's data with each of his child * Shares the father's data with each of his child
*/ */
//================================================ //================================================
void SMESH_OctreeNode::buildChildrenData() void SMESH_OctreeNode::buildChildrenData()
{ {
gp_XYZ min = getBox()->CornerMin(); gp_XYZ min = getBox()->CornerMin();
gp_XYZ max = getBox()->CornerMax(); gp_XYZ max = getBox()->CornerMax();
gp_XYZ mid = (min + max)/2.; gp_XYZ mid = (min + max)/2.;
TIDSortedNodeSet::iterator it = myNodes.begin();
while (it != myNodes.end())
{
const SMDS_MeshNode* n1 = *it;
int ChildBoxNum = getChildIndex( n1->X(), n1->Y(), n1->Z(), mid );
SMESH_OctreeNode* myChild = dynamic_cast<SMESH_OctreeNode*> (myChildren[ChildBoxNum]);
myChild->myNodes.insert(myChild->myNodes.end(),n1);
myNodes.erase( it );
it = myNodes.begin();
}
for ( int i = 0; i < 8; i++ ) for ( int i = 0; i < 8; i++ )
{ {
SMESH_OctreeNode* myChild = dynamic_cast<SMESH_OctreeNode*> (myChildren[i]); SMESH_OctreeNode* myChild = static_cast<SMESH_OctreeNode*>( myChildren[ i ]);
myChild->myNodes.reserve( myNodes.size() / 8 );
}
for ( size_t i = 0; i < myNodes.size(); ++i )
{
SMESH_NodeXYZ n = myNodes[ i ];
int ChildBoxNum = getChildIndex( n.X(), n.Y(), n.Z(), mid );
SMESH_OctreeNode* myChild = static_cast<SMESH_OctreeNode*>( myChildren[ ChildBoxNum ]);
myChild->myNodes.push_back( myNodes[ i ]);
}
SMESHUtils::FreeVector( myNodes );
for ( int i = 0; i < 8; i++ )
{
SMESH_OctreeNode* myChild = static_cast<SMESH_OctreeNode*>( myChildren[ i ]);
if ((int) myChild->myNodes.size() <= getMaxNbNodes() ) if ((int) myChild->myNodes.size() <= getMaxNbNodes() )
{
myChild->myIsLeaf = true; myChild->myIsLeaf = true;
if ( myChild->myNodes.empty() )
SMESHUtils::FreeVector( myChild->myNodes );
}
} }
} }
@ -164,11 +174,12 @@ void SMESH_OctreeNode::buildChildrenData()
* \param Result - list of Nodes potentials to be near Node * \param Result - list of Nodes potentials to be near Node
*/ */
//==================================================================== //====================================================================
void SMESH_OctreeNode::NodesAround (const SMDS_MeshNode * Node,
list<const SMDS_MeshNode*>* Result, void SMESH_OctreeNode::AllNodesAround (const SMDS_MeshNode * Node,
std::vector<const SMDS_MeshNode*>* Result,
const double precision) const double precision)
{ {
SMESH_TNodeXYZ p(Node); SMESH_NodeXYZ p = Node;
if ( isInside( p, precision )) if ( isInside( p, precision ))
{ {
if ( isLeaf() ) if ( isLeaf() )
@ -179,8 +190,8 @@ void SMESH_OctreeNode::NodesAround (const SMDS_MeshNode * Node,
{ {
for ( int i = 0; i < 8; i++ ) for ( int i = 0; i < 8; i++ )
{ {
SMESH_OctreeNode* myChild = dynamic_cast<SMESH_OctreeNode*> (myChildren[i]); SMESH_OctreeNode* myChild = static_cast<SMESH_OctreeNode*> (myChildren[i]);
myChild->NodesAround(Node, Result, precision); myChild->AllNodesAround( Node, Result, precision );
} }
} }
} }
@ -224,13 +235,12 @@ bool SMESH_OctreeNode::NodesAround(const gp_XYZ &node,
else if ( NbNodes() > 0 ) else if ( NbNodes() > 0 )
{ {
double minDist = precision * precision; double minDist = precision * precision;
TIDSortedNodeSet::iterator nIt = myNodes.begin(); for ( size_t i = 0; i < myNodes.size(); ++i )
for ( ; nIt != myNodes.end(); ++nIt )
{ {
SMESH_TNodeXYZ p2( *nIt ); SMESH_NodeXYZ p2 = myNodes[ i ];
double dist2 = ( node - p2 ).SquareModulus(); double dist2 = ( node - p2 ).SquareModulus();
if ( dist2 < minDist ) if ( dist2 < minDist )
dist2Nodes.insert( make_pair( minDist = dist2, p2._node )); dist2Nodes.insert( std::make_pair( minDist = dist2, myNodes[ i ] ));
} }
// if ( dist2Nodes.size() > 1 ) // leave only closest node in dist2Nodes // if ( dist2Nodes.size() > 1 ) // leave only closest node in dist2Nodes
// dist2Nodes.erase( ++dist2Nodes.begin(), dist2Nodes.end()); // dist2Nodes.erase( ++dist2Nodes.begin(), dist2Nodes.end());
@ -260,20 +270,19 @@ void SMESH_OctreeNode::NodesAround(const gp_XYZ& point,
if ( isLeaf() && NbNodes() ) if ( isLeaf() && NbNodes() )
{ {
double minDist2 = precision * precision; double minDist2 = precision * precision;
TIDSortedNodeSet::iterator nIt = myNodes.begin(); for ( size_t i = 0; i < myNodes.size(); ++i )
for ( ; nIt != myNodes.end(); ++nIt )
{ {
SMESH_TNodeXYZ p2( *nIt ); SMESH_NodeXYZ p2 = myNodes[ i ];
double dist2 = ( point - p2 ).SquareModulus(); double dist2 = ( point - p2 ).SquareModulus();
if ( dist2 <= minDist2 ) if ( dist2 <= minDist2 )
nodes.push_back( p2._node ); nodes.push_back( myNodes[ i ] );
} }
} }
else if ( myChildren ) else if ( myChildren )
{ {
for (int i = 0; i < 8; i++) for (int i = 0; i < 8; i++)
{ {
SMESH_OctreeNode* myChild = dynamic_cast<SMESH_OctreeNode*> (myChildren[i]); SMESH_OctreeNode* myChild = static_cast<SMESH_OctreeNode*>( myChildren[ i ]);
myChild->NodesAround( point, nodes, precision ); myChild->NodesAround( point, nodes, precision );
} }
} }
@ -292,15 +301,19 @@ void SMESH_OctreeNode::NodesAround(const gp_XYZ& point,
* \param maxNbNodes - maximum Nodes in a Leaf of the SMESH_OctreeNode constructed, default value is 5 * \param maxNbNodes - maximum Nodes in a Leaf of the SMESH_OctreeNode constructed, default value is 5
*/ */
//============================= //=============================
void SMESH_OctreeNode::FindCoincidentNodes (TIDSortedNodeSet& theSetOfNodes, void SMESH_OctreeNode::FindCoincidentNodes (TIDSortedNodeSet& theSetOfNodes,
list< list< const SMDS_MeshNode*> >* theGroupsOfNodes, TListOfNodeLists* theGroupsOfNodes,
const double theTolerance, const double theTolerance,
const int maxLevel, const int maxLevel,
const int maxNbNodes) const int maxNbNodes)
{ {
// VSR 14/10/2011: limit max number of the levels in order to avoid endless recursing // VSR 14/10/2011: limit max number of the levels in order to avoid endless recursion
const int MAX_LEVEL = 10; const int MAX_LEVEL = 10;
SMESH_OctreeNode theOctreeNode(theSetOfNodes, maxLevel < 0 ? MAX_LEVEL : maxLevel, maxNbNodes, theTolerance); SMESH_OctreeNode theOctreeNode(theSetOfNodes,
maxLevel < 0 ? MAX_LEVEL : maxLevel,
maxNbNodes,
theTolerance);
theOctreeNode.FindCoincidentNodes (&theSetOfNodes, theTolerance, theGroupsOfNodes); theOctreeNode.FindCoincidentNodes (&theSetOfNodes, theTolerance, theGroupsOfNodes);
} }
@ -314,36 +327,40 @@ void SMESH_OctreeNode::FindCoincidentNodes (TIDSortedNodeSet& theSetOfNodes,
* \param theGroupsOfNodes - list of nodes closed to each other returned * \param theGroupsOfNodes - list of nodes closed to each other returned
*/ */
//============================= //=============================
void SMESH_OctreeNode::FindCoincidentNodes ( TIDSortedNodeSet* theSetOfNodes, void SMESH_OctreeNode::FindCoincidentNodes ( TIDSortedNodeSet* theSetOfNodes,
const double theTolerance, const double theTolerance,
list< list< const SMDS_MeshNode*> >* theGroupsOfNodes) TListOfNodeLists* theGroupsOfNodes )
{ {
TIDSortedNodeSet::iterator it1 = theSetOfNodes->begin(); // un-mark all nodes; we mark nodes added to theGroupsOfNodes
list<const SMDS_MeshNode*>::iterator it2; SMESH_MeshAlgos::MarkElems( SMESHUtils::elemSetIterator( *theSetOfNodes ), false );
list<const SMDS_MeshNode*> ListOfCoincidentNodes; vector<const SMDS_MeshNode*> coincidentNodes;
TIDCompare idLess; TIDCompare idLess;
while (it1 != theSetOfNodes->end()) TIDSortedNodeSet::iterator it1 = theSetOfNodes->begin();
for ( ; it1 != theSetOfNodes->end(); ++it1 )
{ {
const SMDS_MeshNode * n1 = *it1; const SMDS_MeshNode * n1 = *it1;
if ( n1->isMarked() )
continue;
n1->setIsMarked( true );
// Searching for Nodes around n1 and put them in ListofCoincidentNodes. // Searching for Nodes around n1 and put them in coincidentNodes.
// Found nodes are also erased from theSetOfNodes // Found nodes are also erased from theSetOfNodes
FindCoincidentNodes(n1, theSetOfNodes, &ListOfCoincidentNodes, theTolerance); coincidentNodes.clear();
findCoincidentNodes( n1, theSetOfNodes, &coincidentNodes, theTolerance );
if ( !ListOfCoincidentNodes.empty() ) if ( !coincidentNodes.empty() )
{ {
// We build a list {n1 + his neighbors} and add this list in theGroupsOfNodes // We build a list {n1 + his neighbors} and add this list in theGroupsOfNodes
if ( idLess( n1, ListOfCoincidentNodes.front() )) ListOfCoincidentNodes.push_front( n1 ); std::sort( coincidentNodes.begin(), coincidentNodes.end(), idLess );
else ListOfCoincidentNodes.push_back ( n1 ); list<const SMDS_MeshNode*> newGroup;
ListOfCoincidentNodes.sort( idLess ); newGroup.push_back( n1 );
theGroupsOfNodes->push_back( list<const SMDS_MeshNode*>() ); newGroup.insert( newGroup.end(), coincidentNodes.begin(), coincidentNodes.end() );
theGroupsOfNodes->back().splice( theGroupsOfNodes->back().end(), ListOfCoincidentNodes );
}
theSetOfNodes->erase(it1); theGroupsOfNodes->emplace_back( newGroup );
it1 = theSetOfNodes->begin(); }
} }
} }
@ -357,57 +374,45 @@ void SMESH_OctreeNode::FindCoincidentNodes ( TIDSortedNodeSet*
* \param precision - Precision used * \param precision - Precision used
*/ */
//====================================================================================== //======================================================================================
void SMESH_OctreeNode::FindCoincidentNodes (const SMDS_MeshNode * Node,
void SMESH_OctreeNode::findCoincidentNodes (const SMDS_MeshNode * Node,
TIDSortedNodeSet* SetOfNodes, TIDSortedNodeSet* SetOfNodes,
list<const SMDS_MeshNode*>* Result, std::vector<const SMDS_MeshNode*>* Result,
const double precision) const double precision)
{ {
gp_Pnt p1 (Node->X(), Node->Y(), Node->Z()); SMESH_NodeXYZ p1 = Node;
bool isInsideBool = isInside( p1.XYZ(), precision );
if (isInsideBool) if ( isInside( p1, precision ))
{ {
// I'm only looking in the leaves, since all the nodes are stored there. // I'm only looking in the leaves, since all the nodes are stored there.
if ( isLeaf() ) if ( isLeaf() )
{ {
TIDSortedNodeSet::iterator it = myNodes.begin();
const double tol2 = precision * precision; const double tol2 = precision * precision;
bool squareBool;
while (it != myNodes.end()) for ( size_t i = 0; i < myNodes.size(); ++i )
{ {
const SMDS_MeshNode* n2 = *it; if ( myNodes[ i ]->isMarked() ) // coincident node already found
squareBool = false; continue;
// We're only looking at nodes with a superior Id.
// JFA: Why?
//if (Node->GetID() < n2->GetID())
if (Node->GetID() != n2->GetID()) // JFA: for bug 0020185
{
gp_Pnt p2 (n2->X(), n2->Y(), n2->Z());
// Distance optimized computation
squareBool = (p1.SquareDistance( p2 ) <= tol2);
// If n2 inside the SquareDistance, we add it in Result and remove it from SetOfNodes and myNodes //if ( Node != myNodes[ i ]) // JFA: for bug 0020185
if (squareBool)
{ {
Result->insert(Result->begin(), n2); // If n2 inside the SquareDistance, we add it in Result
SetOfNodes->erase( n2 ); bool coincide = ( p1.SquareDistance( myNodes[ i ]) <= tol2 );
myNodes.erase( *it++ ); // it++ goes forward and returns it's previous position if ( coincide )
{
Result->push_back ( myNodes[ i ]);
myNodes[ i ]->setIsMarked( true );
} }
} }
if ( !squareBool )
it++;
} }
if ( !Result->empty() )
myNodes.erase(Node); // JFA: for bug 0020185
} }
else else
{ {
// If I'm not a leaf, I'm going to see my children ! // If I'm not a leaf, I'm going to see my children !
for ( int i = 0; i < 8; i++ ) for ( int i = 0; i < 8; i++ )
{ {
SMESH_OctreeNode* myChild = dynamic_cast<SMESH_OctreeNode*> (myChildren[i]); SMESH_OctreeNode* myChild = static_cast<SMESH_OctreeNode*> (myChildren[i]);
myChild->FindCoincidentNodes(Node, SetOfNodes, Result, precision); myChild->findCoincidentNodes( Node, SetOfNodes, Result, precision );
} }
} }
} }
@ -423,17 +428,18 @@ void SMESH_OctreeNode::UpdateByMoveNode( const SMDS_MeshNode* node, const gp_Pnt
{ {
if ( isLeaf() ) if ( isLeaf() )
{ {
TIDSortedNodeSet::iterator pNode = myNodes.find( node ); std::vector< const SMDS_MeshNode* >::iterator pNode =
bool nodeInMe = ( pNode != myNodes.end() ); std::find( myNodes.begin(), myNodes.end(), node );
bool nodeInMe = ( pNode != myNodes.end() );
bool pointInMe = isInside( toPnt.Coord(), 1e-10 ); bool pointInMe = isInside( toPnt.Coord(), 1e-10 );
if ( pointInMe != nodeInMe ) if ( pointInMe != nodeInMe )
{ {
if ( pointInMe ) if ( pointInMe )
myNodes.insert( node ); myNodes.push_back( node );
else else
myNodes.erase( node ); myNodes.erase( pNode );
} }
} }
else if ( myChildren ) else if ( myChildren )
@ -454,6 +460,7 @@ void SMESH_OctreeNode::UpdateByMoveNode( const SMDS_MeshNode* node, const gp_Pnt
* \brief Return iterator over children * \brief Return iterator over children
*/ */
//================================================================================ //================================================================================
SMESH_OctreeNodeIteratorPtr SMESH_OctreeNode::GetChildrenIterator() SMESH_OctreeNodeIteratorPtr SMESH_OctreeNode::GetChildrenIterator()
{ {
return SMESH_OctreeNodeIteratorPtr return SMESH_OctreeNodeIteratorPtr
@ -466,9 +473,8 @@ SMESH_OctreeNodeIteratorPtr SMESH_OctreeNode::GetChildrenIterator()
* \brief Return nodes iterator * \brief Return nodes iterator
*/ */
//================================================================================ //================================================================================
SMDS_NodeIteratorPtr SMESH_OctreeNode::GetNodeIterator() SMDS_NodeIteratorPtr SMESH_OctreeNode::GetNodeIterator()
{ {
return SMDS_NodeIteratorPtr return boost::make_shared< SMDS_NodeVectorIterator >( myNodes.begin(), myNodes.end());
( new SMDS_SetIterator< SMDS_pNode, TIDSortedNodeSet::const_iterator >
( myNodes.begin(), myNodes.size() ? myNodes.end() : myNodes.begin()));
} }

View File

@ -49,6 +49,7 @@ class SMESH_OctreeNode;
typedef SMDS_Iterator<SMESH_OctreeNode*> SMESH_OctreeNodeIterator; typedef SMDS_Iterator<SMESH_OctreeNode*> SMESH_OctreeNodeIterator;
typedef boost::shared_ptr<SMESH_OctreeNodeIterator> SMESH_OctreeNodeIteratorPtr; typedef boost::shared_ptr<SMESH_OctreeNodeIterator> SMESH_OctreeNodeIteratorPtr;
typedef std::set< const SMDS_MeshNode*, TIDCompare > TIDSortedNodeSet; typedef std::set< const SMDS_MeshNode*, TIDCompare > TIDSortedNodeSet;
typedef std::list< std::list< const SMDS_MeshNode*> > TListOfNodeLists;
class SMESHUtils_EXPORT SMESH_OctreeNode : public SMESH_Octree class SMESHUtils_EXPORT SMESH_OctreeNode : public SMESH_Octree
{ {
@ -65,8 +66,8 @@ class SMESHUtils_EXPORT SMESH_OctreeNode : public SMESH_Octree
virtual const bool isInside(const gp_XYZ& p, const double precision = 0.); virtual const bool isInside(const gp_XYZ& p, const double precision = 0.);
// Return in Result a list of Nodes potentials to be near Node // Return in Result a list of Nodes potentials to be near Node
void NodesAround(const SMDS_MeshNode * node, void AllNodesAround(const SMDS_MeshNode * node,
std::list<const SMDS_MeshNode*>* result, std::vector<const SMDS_MeshNode*>* result,
const double precision = 0.); const double precision = 0.);
// Return in dist2Nodes nodes mapped to their square distance from Node // Return in dist2Nodes nodes mapped to their square distance from Node
@ -83,12 +84,12 @@ class SMESHUtils_EXPORT SMESH_OctreeNode : public SMESH_Octree
// Search for all the nodes in nodes // Search for all the nodes in nodes
void FindCoincidentNodes ( TIDSortedNodeSet* nodes, void FindCoincidentNodes ( TIDSortedNodeSet* nodes,
const double theTolerance, const double theTolerance,
std::list< std::list< const SMDS_MeshNode*> >* theGroupsOfNodes); TListOfNodeLists * theGroupsOfNodes);
// Static method that return in theGroupsOfNodes a list of group of nodes close to each other within // Static method that return in theGroupsOfNodes a list of group of nodes close to each other within
// theTolerance search for all the nodes in nodes // theTolerance search for all the nodes in nodes
static void FindCoincidentNodes ( TIDSortedNodeSet& nodes, static void FindCoincidentNodes ( TIDSortedNodeSet& nodes,
std::list< std::list< const SMDS_MeshNode*> >* theGroupsOfNodes, TListOfNodeLists* theGroupsOfNodes,
const double theTolerance = 0.00001, const double theTolerance = 0.00001,
const int maxLevel = -1, const int maxLevel = -1,
const int maxNbNodes = 5); const int maxNbNodes = 5);
@ -131,14 +132,14 @@ protected:
// Construct an empty SMESH_OctreeNode used by SMESH_Octree::buildChildren() // Construct an empty SMESH_OctreeNode used by SMESH_Octree::buildChildren()
virtual SMESH_Octree* newChild() const; virtual SMESH_Octree* newChild() const;
// Return in result a list of nodes closed to Node and remove it from SetOfNodes // Return in result a list of nodes closed to Node
void FindCoincidentNodes( const SMDS_MeshNode * Node, void findCoincidentNodes( const SMDS_MeshNode * Node,
TIDSortedNodeSet* SetOfNodes, TIDSortedNodeSet* SetOfNodes,
std::list<const SMDS_MeshNode*>* Result, std::vector<const SMDS_MeshNode*>* Result,
const double precision); const double precision);
// The set of nodes inside the box of the Octree (Empty if Octree is not a leaf) // The set of nodes inside the box of the Octree (Empty if Octree is not a leaf)
TIDSortedNodeSet myNodes; std::vector< const SMDS_MeshNode* > myNodes;
}; };

View File

@ -2454,281 +2454,237 @@ SMESH_Gen_i::ConcatenateCommon(const SMESH::ListOfIDSources& theMeshesArray,
CORBA::Boolean theCommonGroups) CORBA::Boolean theCommonGroups)
throw ( SALOME::SALOME_Exception ) throw ( SALOME::SALOME_Exception )
{ {
typedef list<SMESH::SMESH_Group_var> TListOfNewGroups; std::unique_ptr< TPythonDump > pPythonDump( new TPythonDump );
typedef map< pair<string, SMESH::ElementType>, TListOfNewGroups > TGroupsMap; TPythonDump& pythonDump = *pPythonDump; // prevent dump of called methods
TPythonDump* pPythonDump = new TPythonDump;
TPythonDump& aPythonDump = *pPythonDump; // prevent dump of called methods
// create mesh // create mesh
SMESH::SMESH_Mesh_var aNewMesh = CreateEmptyMesh(); SMESH::SMESH_Mesh_var newMesh = CreateEmptyMesh();
SMESH_Mesh_i* newImpl = SMESH::DownCast<SMESH_Mesh_i*>( newMesh );
if ( !newImpl ) return newMesh._retn();
if ( aNewMesh->_is_nil() ) ::SMESH_Mesh& locMesh = newImpl->GetImpl();
return aNewMesh._retn(); SMESHDS_Mesh* newMeshDS = locMesh.GetMeshDS();
SMESH_Mesh_i* aNewImpl = SMESH::DownCast<SMESH_Mesh_i*>( aNewMesh ); typedef std::list<SMESH::SMESH_Group_var> TListOfNewGroups;
if ( !aNewImpl ) typedef std::pair<string, SMESH::ElementType > TNameAndType;
return aNewMesh._retn(); typedef std::map< TNameAndType, TListOfNewGroups > TGroupsMap;
TGroupsMap groupsMap;
::SMESH_Mesh& aLocMesh = aNewImpl->GetImpl(); TListOfNewGroups listOfNewGroups;
SMESHDS_Mesh* aNewMeshDS = aLocMesh.GetMeshDS();
TGroupsMap aGroupsMap;
TListOfNewGroups aListOfNewGroups;
::SMESH_MeshEditor aNewEditor(&aLocMesh);
SMESH::ListOfGroups_var aListOfGroups;
::SMESH_MeshEditor newEditor( &locMesh );
::SMESH_MeshEditor::ElemFeatures elemType; ::SMESH_MeshEditor::ElemFeatures elemType;
std::vector<const SMDS_MeshNode*> aNodesArray;
// loop on sub-meshes // loop on sub-meshes
for ( CORBA::ULong i = 0; i < theMeshesArray.length(); i++ ) for ( CORBA::ULong i = 0; i < theMeshesArray.length(); i++ )
{ {
if ( CORBA::is_nil( theMeshesArray[i] )) continue; if ( CORBA::is_nil( theMeshesArray[i] )) continue;
SMESH::SMESH_Mesh_var anInitMesh = theMeshesArray[i]->GetMesh(); SMESH::SMESH_Mesh_var initMesh = theMeshesArray[i]->GetMesh();
if ( anInitMesh->_is_nil() ) continue; SMESH_Mesh_i* initImpl = SMESH::DownCast<SMESH_Mesh_i*>( initMesh );
SMESH_Mesh_i* anInitImpl = SMESH::DownCast<SMESH_Mesh_i*>( anInitMesh ); if ( !initImpl ) continue;
if ( !anInitImpl ) continue; initImpl->Load();
anInitImpl->Load();
//::SMESH_Mesh& aInitLocMesh = anInitImpl->GetImpl(); // assure that IDs increments by one during iteration
//SMESHDS_Mesh* anInitMeshDS = aInitLocMesh.GetMeshDS(); ::SMESH_Mesh& initLocMesh = initImpl->GetImpl();
SMESHDS_Mesh* initMeshDS = initLocMesh.GetMeshDS();
if ( initMeshDS->MaxNodeID() != initMeshDS->NbNodes() ||
initMeshDS->MaxElementID() != initMeshDS->NbElements() )
initMeshDS->CompactMesh();
// remember nb of elements before filling in // remember nb of elements before filling in
SMESH::long_array_var prevState = aNewMesh->GetNbElementsByType(); SMESH::long_array_var prevState = newMesh->GetNbElementsByType();
typedef std::map<const SMDS_MeshElement*, const SMDS_MeshElement*, TIDCompare > TEEMap; // copy nodes
TEEMap elemsMap, nodesMap;
// loop on elements of a sub-mesh std::vector< const SMDS_MeshElement* > newNodes( initMeshDS->NbNodes() + 1, 0 );
SMDS_ElemIteratorPtr itElems = anInitImpl->GetElements( theMeshesArray[i], SMESH::ALL ); SMDS_ElemIteratorPtr elemIt = initImpl->GetElements( theMeshesArray[i], SMESH::NODE );
const SMDS_MeshElement* anElem; while ( elemIt->more() )
const SMDS_MeshElement* aNewElem;
const SMDS_MeshNode* aNode;
const SMDS_MeshNode* aNewNode;
int anElemNbNodes;
while ( itElems->more() )
{ {
anElem = itElems->next(); SMESH_NodeXYZ node = elemIt->next();
anElemNbNodes = anElem->NbNodes(); newNodes[ node->GetID() ] = newMeshDS->AddNode( node.X(), node.Y(), node.Z() );
aNodesArray.resize( anElemNbNodes ); }
// loop on nodes of an element // copy elements
SMDS_ElemIteratorPtr itNodes = anElem->nodesIterator();
std::vector< const SMDS_MeshElement* > newElems( initMeshDS->NbElements() + 1, 0 );
elemIt = initImpl->GetElements( theMeshesArray[i], SMESH::ALL );
while ( elemIt->more() )
{
const SMDS_MeshElement* elem = elemIt->next();
elemType.myNodes.resize( elem->NbNodes() );
SMDS_NodeIteratorPtr itNodes = elem->nodeIterator();
for ( int k = 0; itNodes->more(); k++) for ( int k = 0; itNodes->more(); k++)
{ {
aNode = static_cast<const SMDS_MeshNode*>( itNodes->next() ); const SMDS_MeshNode* node = itNodes->next();
TEEMap::iterator n2nnIt = nodesMap.find( aNode ); elemType.myNodes[ k ] = static_cast< const SMDS_MeshNode*> ( newNodes[ node->GetID() ]);
if ( n2nnIt == nodesMap.end() )
{
aNewNode = aNewMeshDS->AddNode(aNode->X(), aNode->Y(), aNode->Z());
nodesMap.insert( make_pair( aNode, aNewNode ));
}
else
{
aNewNode = static_cast<const SMDS_MeshNode*>( n2nnIt->second );
}
aNodesArray[k] = aNewNode;
} }
// creates a corresponding element on existent nodes in new mesh // creates a corresponding element on existent nodes in new mesh
if ( anElem->GetType() == SMDSAbs_Node ) newElems[ elem->GetID() ] =
aNewElem = 0; newEditor.AddElement( elemType.myNodes, elemType.Init( elem, /*basicOnly=*/false ));
else }
aNewElem = newEditor.ClearLastCreated(); // forget the history
aNewEditor.AddElement( aNodesArray, elemType.Init( anElem, /*basicOnly=*/false ));
if ( aNewElem )
elemsMap.insert( make_pair( anElem, aNewElem ));
} //elems loop
aNewEditor.ClearLastCreated(); // forget the history
// create groups of just added elements // create groups of just added elements
SMESH::SMESH_Group_var aNewGroup; SMESH::SMESH_Group_var newGroup;
SMESH::ElementType aGroupType; SMESH::ElementType groupType;
if ( theCommonGroups ) if ( theCommonGroups )
{ {
SMESH::long_array_var curState = aNewMesh->GetNbElementsByType(); // type names
for( aGroupType = SMESH::NODE;
aGroupType < SMESH::NB_ELEMENT_TYPES;
aGroupType = (SMESH::ElementType)( aGroupType + 1 ))
{
if ( curState[ aGroupType ] <= prevState[ aGroupType ])
continue;
// make a group name
const char* typeNames[] = { "All","Nodes","Edges","Faces","Volumes","0DElems","Balls" }; const char* typeNames[] = { "All","Nodes","Edges","Faces","Volumes","0DElems","Balls" };
{ // check of typeNames: compilation failure mains that NB_ELEMENT_TYPES changed: { // check of typeNames: compilation failure mains that NB_ELEMENT_TYPES changed:
const int nbNames = sizeof(typeNames) / sizeof(const char*); const int nbNames = sizeof(typeNames) / sizeof(const char*);
int _assert[( nbNames == SMESH::NB_ELEMENT_TYPES ) ? 2 : -1 ]; _assert[0]=_assert[1]=0; int _assert[( nbNames == SMESH::NB_ELEMENT_TYPES ) ? 2 : -1 ]; _assert[0]=_assert[1]=0;
} }
string groupName = "Gr";
SALOMEDS::SObject_wrap aMeshSObj = ObjectToSObject( myCurrentStudy, theMeshesArray[i] ); SMESH::long_array_var curState = newMesh->GetNbElementsByType();
if ( aMeshSObj ) {
CORBA::String_var name = aMeshSObj->GetName(); for( groupType = SMESH::NODE;
groupType < SMESH::NB_ELEMENT_TYPES;
groupType = (SMESH::ElementType)( groupType + 1 ))
{
if ( curState[ groupType ] <= prevState[ groupType ])
continue; // no elements of groupType added from the i-th mesh
// make a group name
std::string groupName = "Gr";
SALOMEDS::SObject_wrap meshSO = ObjectToSObject( myCurrentStudy, theMeshesArray[i] );
if ( meshSO ) {
CORBA::String_var name = meshSO->GetName();
groupName += name; groupName += name;
} }
groupName += "_"; groupName += "_";
groupName += typeNames[ aGroupType ]; groupName += typeNames[ groupType ];
// make and fill a group // make and fill a group
TEEMap & e2neMap = ( aGroupType == SMESH::NODE ) ? nodesMap : elemsMap; newGroup = newImpl->CreateGroup( groupType, groupName.c_str() );
aNewGroup = aNewImpl->CreateGroup( aGroupType, groupName.c_str() ); std::vector< const SMDS_MeshElement* > & elemVec =
if ( SMESH_Group_i* grp_i = SMESH::DownCast<SMESH_Group_i*>( aNewGroup )) ( groupType == SMESH::NODE ) ? newNodes : newElems;
if ( SMESH_Group_i* grp_i = SMESH::DownCast<SMESH_Group_i*>( newGroup ))
{ {
if ( SMESHDS_Group* grpDS = dynamic_cast<SMESHDS_Group*>( grp_i->GetGroupDS() )) if ( SMESHDS_Group* grpDS = dynamic_cast<SMESHDS_Group*>( grp_i->GetGroupDS() ))
{ {
TEEMap::iterator e2neIt = e2neMap.begin(); for ( size_t j = 0; j < elemVec.size(); ++j )
for ( ; e2neIt != e2neMap.end(); ++e2neIt )
{ {
aNewElem = e2neIt->second; if ( elemVec[j] && elemVec[j]->GetType() == grpDS->GetType() )
if ( aNewElem->GetType() == grpDS->GetType() ) grpDS->Add( elemVec[j] );
{
grpDS->Add( aNewElem );
if ( prevState[ aGroupType ]++ >= curState[ aGroupType ] )
break;
} }
} }
} }
} listOfNewGroups.clear();
aListOfNewGroups.clear(); listOfNewGroups.push_back( newGroup );
aListOfNewGroups.push_back(aNewGroup); groupsMap.insert( std::make_pair( TNameAndType( groupName, groupType ),
aGroupsMap.insert(make_pair( make_pair(groupName, aGroupType), aListOfNewGroups )); listOfNewGroups ));
} }
} }
if ( SMESH_Mesh_i* anSrcImpl = SMESH::DownCast<SMESH_Mesh_i*>( theMeshesArray[i] )) if ( SMESH_Mesh_i* initImpl = SMESH::DownCast<SMESH_Mesh_i*>( theMeshesArray[i] ))
{ {
// copy orphan nodes
if ( anSrcImpl->NbNodes() > (int)nodesMap.size() )
{
SMDS_ElemIteratorPtr itNodes = anInitImpl->GetElements( theMeshesArray[i], SMESH::NODE );
while ( itNodes->more() )
{
const SMDS_MeshNode* aNode = static_cast< const SMDS_MeshNode* >( itNodes->next() );
if ( aNode->NbInverseElements() == 0 )
{
aNewNode = aNewMeshDS->AddNode(aNode->X(), aNode->Y(), aNode->Z());
nodesMap.insert( make_pair( aNode, aNewNode ));
}
}
}
// copy groups // copy groups
SMESH::SMESH_GroupBase_ptr aGroup; SMESH::SMESH_GroupBase_ptr group;
CORBA::String_var aGroupName; CORBA::String_var groupName;
SMESH::long_array_var anNewIDs = new SMESH::long_array(); SMESH::long_array_var newIDs = new SMESH::long_array();
// loop on groups of a source mesh // loop on groups of a source mesh
aListOfGroups = anSrcImpl->GetGroups(); SMESH::ListOfGroups_var listOfGroups = initImpl->GetGroups();
for ( CORBA::ULong iG = 0; iG < aListOfGroups->length(); iG++ ) for ( CORBA::ULong iG = 0; iG < listOfGroups->length(); iG++ )
{ {
aGroup = aListOfGroups[iG]; group = listOfGroups[iG];
aGroupType = aGroup->GetType(); groupType = group->GetType();
aGroupName = aGroup->GetName(); groupName = group->GetName();
string aName = aGroupName.in(); std::string name = groupName.in();
// convert a list of IDs // convert a list of IDs
anNewIDs->length( aGroup->Size() ); newIDs->length( group->Size() );
TEEMap & e2neMap = ( aGroupType == SMESH::NODE ) ? nodesMap : elemsMap; std::vector< const SMDS_MeshElement* > & elemVec =
SMDS_ElemIteratorPtr itGrElems = anSrcImpl->GetElements( aGroup, SMESH::ALL ); ( groupType == SMESH::NODE ) ? newNodes : newElems;
int iElem = 0; SMDS_ElemIteratorPtr itGrElems = initImpl->GetElements( group, SMESH::ALL );
int nbElems = 0;
while ( itGrElems->more() ) while ( itGrElems->more() )
{ {
anElem = itGrElems->next(); const SMDS_MeshElement* elem = itGrElems->next();
TEEMap::iterator e2neIt = e2neMap.find( anElem ); const SMDS_MeshElement* newElem = elemVec[ elem->GetID() ];
if ( e2neIt != e2neMap.end() ) if ( newElem )
anNewIDs[ iElem++ ] = e2neIt->second->GetID(); newIDs[ nbElems++ ] = newElem->GetID();
} }
anNewIDs->length( iElem ); newIDs->length( nbElems );
// check a current group name and type don't have identical ones in final mesh // check that a current group name and type don't have identical ones in final mesh
aListOfNewGroups.clear(); listOfNewGroups.clear();
TGroupsMap::iterator anIter = aGroupsMap.find( make_pair( aName, aGroupType )); TNameAndType nameAndType( name, groupType );
if ( anIter == aGroupsMap.end() ) { TGroupsMap::iterator anIter = groupsMap.find( nameAndType );
if ( anIter == groupsMap.end() )
{
// add a new group in the mesh // add a new group in the mesh
aNewGroup = aNewImpl->CreateGroup( aGroupType, aGroupName.in() ); newGroup = newImpl->CreateGroup( groupType, groupName.in() );
// add elements into new group newGroup->Add( newIDs );
aNewGroup->Add( anNewIDs );
aListOfNewGroups.push_back(aNewGroup); listOfNewGroups.push_back( newGroup );
aGroupsMap.insert(make_pair( make_pair(aName, aGroupType), aListOfNewGroups )); groupsMap.insert( std::make_pair( nameAndType, listOfNewGroups ));
} }
else if ( theUniteIdenticalGroups )
else if ( theUniteIdenticalGroups ) { {
// unite identical groups // unite identical groups
TListOfNewGroups& aNewGroups = anIter->second; TListOfNewGroups& aNewGroups = anIter->second;
aNewGroups.front()->Add( anNewIDs ); aNewGroups.front()->Add( newIDs );
} }
else
else { {
// rename identical groups // rename identical groups
aNewGroup = aNewImpl->CreateGroup(aGroupType, aGroupName.in()); newGroup = newImpl->CreateGroup( groupType, groupName );
aNewGroup->Add( anNewIDs ); newGroup->Add( newIDs );
TListOfNewGroups& aNewGroups = anIter->second; TListOfNewGroups& newGroups = anIter->second;
string aNewGroupName; std::string newGroupName;
if (aNewGroups.size() == 1) { if ( newGroups.size() == 1 )
aNewGroupName = aName + "_1"; {
aNewGroups.front()->SetName(aNewGroupName.c_str()); newGroupName = name + "_1";
newGroups.front()->SetName( newGroupName.c_str() );
} }
char aGroupNum[128]; newGroupName = name + "_" + SMESH_Comment( newGroups.size() + 1 );
sprintf(aGroupNum, "%u", (unsigned int)aNewGroups.size()+1); newGroup->SetName( newGroupName.c_str() );
aNewGroupName = aName + "_" + string(aGroupNum); newGroups.push_back( newGroup );
aNewGroup->SetName(aNewGroupName.c_str());
aNewGroups.push_back(aNewGroup);
} }
} //groups loop } // loop on groups
} // if an IDSource is a mesh } // if an IDSource is a mesh
} //meshes loop } //meshes loop
if ( theMergeNodesAndElements ) // merge nodes if ( theMergeNodesAndElements ) // merge nodes
{ {
TIDSortedNodeSet aMeshNodes; // no input nodes TIDSortedNodeSet meshNodes; // no input nodes == treat all
SMESH_MeshEditor::TListOfListOfNodes aGroupsOfNodes; SMESH_MeshEditor::TListOfListOfNodes groupsOfNodes;
aNewEditor.FindCoincidentNodes( aMeshNodes, theMergeTolerance, aGroupsOfNodes, newEditor.FindCoincidentNodes( meshNodes, theMergeTolerance, groupsOfNodes,
/*SeparateCornersAndMedium=*/ false ); /*SeparateCornersAndMedium=*/ false );
aNewEditor.MergeNodes( aGroupsOfNodes ); newEditor.MergeNodes( groupsOfNodes );
// merge elements // merge elements
aNewEditor.MergeEqualElements(); newEditor.MergeEqualElements();
} }
// Update Python script // Update Python script
aPythonDump << aNewMesh << " = " << this << "." pythonDump << newMesh << " = " << this
<< ( theCommonGroups ? "ConcatenateWithGroups" : "Concatenate" ) << "." << ( theCommonGroups ? "ConcatenateWithGroups" : "Concatenate" ) << "("
<< "(["; << theMeshesArray << ", "
for ( CORBA::ULong i = 0; i < theMeshesArray.length(); i++) { << theUniteIdenticalGroups << ", "
if (i > 0) aPythonDump << ", ";
aPythonDump << theMeshesArray[i];
}
aPythonDump << "], ";
aPythonDump << theUniteIdenticalGroups << ", "
<< theMergeNodesAndElements << ", " << theMergeNodesAndElements << ", "
<< TVar( theMergeTolerance ) << ")"; << TVar( theMergeTolerance ) << ")";
delete pPythonDump; // enable python dump from GetGroups() pPythonDump.reset(); // enable python dump from GetGroups()
// 0020577: EDF 1164 SMESH: Bad dump of concatenate with create common groups // 0020577: EDF 1164 SMESH: Bad dump of concatenate with create common groups
if ( !aNewMesh->_is_nil() ) if ( !newMesh->_is_nil() )
{ {
SMESH::ListOfGroups_var groups = aNewMesh->GetGroups(); SMESH::ListOfGroups_var groups = newMesh->GetGroups();
} }
// IPAL21468 Change icon of compound because it need not be computed. // IPAL21468 Change icon of compound because it need not be computed.
SALOMEDS::SObject_wrap aMeshSObj = ObjectToSObject( myCurrentStudy, aNewMesh ); SALOMEDS::SObject_wrap meshSO = ObjectToSObject( myCurrentStudy, newMesh );
SetPixMap( aMeshSObj, "ICON_SMESH_TREE_MESH" ); SetPixMap( meshSO, "ICON_SMESH_TREE_MESH" );
if (aNewMeshDS) newMeshDS->Modified();
aNewMeshDS->Modified();
return aNewMesh._retn(); return newMesh._retn();
} }
//================================================================================ //================================================================================

View File

@ -5450,7 +5450,7 @@ namespace /* Iterators used in SMESH_Mesh_i::GetElements(SMESH::SMESH_IDSource_v
{ {
const SMDS_MeshElement* res = _node; const SMDS_MeshElement* res = _node;
_node = 0; _node = 0;
while (( _elemIter->more() || _nodeIter->more() ) && !_node ) while ( !_node && ( _elemIter->more() || _nodeIter->more() ))
{ {
if ( _nodeIter->more() ) if ( _nodeIter->more() )
{ {