0021015: EDF 1578 SMESH: Free nodes are removed when translating a mesh

* Treate orphan nodes in Transform()
 * Remove Scale() as being a paricular case of Transform()
This commit is contained in:
eap 2010-10-01 12:48:49 +00:00
parent ea89003dc2
commit ee86814502
2 changed files with 45 additions and 348 deletions

View File

@ -5108,10 +5108,17 @@ void SMESH_MeshEditor::LinearAngleVariation(const int nbSteps,
} }
//======================================================================= //================================================================================
//function : Transform /*!
//purpose : * \brief Move or copy theElements applying theTrsf to their nodes
//======================================================================= * \param theElems - elements to transform, if theElems is empty then apply to all mesh nodes
* \param theTrsf - transformation to apply
* \param theCopy - if true, create translated copies of theElems
* \param theMakeGroups - if true and theCopy, create translated groups
* \param theTargetMesh - mesh to copy translated elements into
* \retval SMESH_MeshEditor::PGroupIDs - list of ids of created groups
*/
//================================================================================
SMESH_MeshEditor::PGroupIDs SMESH_MeshEditor::PGroupIDs
SMESH_MeshEditor::Transform (TIDSortedElemSet & theElems, SMESH_MeshEditor::Transform (TIDSortedElemSet & theElems,
@ -5139,6 +5146,7 @@ SMESH_MeshEditor::Transform (TIDSortedElemSet & theElems,
groupPostfix = "translated"; groupPostfix = "translated";
break; break;
case gp_Scale: case gp_Scale:
case gp_CompoundTrsf: // different scale by axis
groupPostfix = "scaled"; groupPostfix = "scaled";
break; break;
default: default:
@ -5161,7 +5169,36 @@ SMESH_MeshEditor::Transform (TIDSortedElemSet & theElems,
// source elements for each generated one // source elements for each generated one
SMESH_SequenceOfElemPtr srcElems, srcNodes; SMESH_SequenceOfElemPtr srcElems, srcNodes;
// loop on theElems // issue 021015: EDF 1578 SMESH: Free nodes are removed when translating a mesh
list<SMDS_MeshNode> orphanCopy; // copies of orphan nodes
vector<const SMDS_MeshNode*> orphanNode; // original orphan nodes
if ( theElems.empty() ) // transform the whole mesh
{
// add all elements
SMDS_ElemIteratorPtr eIt = aMesh->elementsIterator();
while ( eIt->more() ) theElems.insert( eIt->next() );
// add orphan nodes
SMDS_MeshElementIDFactory idFactory;
SMDS_NodeIteratorPtr nIt = aMesh->nodesIterator();
while ( nIt->more() )
{
const SMDS_MeshNode* node = nIt->next();
if ( node->NbInverseElements() == 0 && !theElems.insert( node ).second )
{
// node was not inserted into theElems because an element with the same ID
// is already there. As a work around we insert a copy of node with
// an ID = -<index in orphanNode>
orphanCopy.push_back( *node ); // copy node
SMDS_MeshNode* nodeCopy = &orphanCopy.back();
int uniqueID = -orphanNode.size();
orphanNode.push_back( node );
idFactory.BindID( uniqueID, nodeCopy );
theElems.insert( nodeCopy );
}
}
}
// loop on theElems to transorm nodes
TIDSortedElemSet::iterator itElem; TIDSortedElemSet::iterator itElem;
for ( itElem = theElems.begin(); itElem != theElems.end(); itElem++ ) { for ( itElem = theElems.begin(); itElem != theElems.end(); itElem++ ) {
const SMDS_MeshElement* elem = *itElem; const SMDS_MeshElement* elem = *itElem;
@ -5172,8 +5209,10 @@ SMESH_MeshEditor::Transform (TIDSortedElemSet & theElems,
SMDS_ElemIteratorPtr itN = elem->nodesIterator(); SMDS_ElemIteratorPtr itN = elem->nodesIterator();
while ( itN->more() ) { while ( itN->more() ) {
// check if a node has been already transformed
const SMDS_MeshNode* node = cast2Node( itN->next() ); const SMDS_MeshNode* node = cast2Node( itN->next() );
if ( node->GetID() < 0 )
node = orphanNode[ -node->GetID() ];
// check if a node has been already transformed
pair<TNodeNodeMap::iterator,bool> n2n_isnew = pair<TNodeNodeMap::iterator,bool> n2n_isnew =
nodeMap.insert( make_pair ( node, node )); nodeMap.insert( make_pair ( node, node ));
if ( !n2n_isnew.second ) if ( !n2n_isnew.second )
@ -5424,331 +5463,6 @@ SMESH_MeshEditor::Transform (TIDSortedElemSet & theElems,
return newGroupIDs; return newGroupIDs;
} }
//=======================================================================
//function : Scale
//purpose :
//=======================================================================
SMESH_MeshEditor::PGroupIDs
SMESH_MeshEditor::Scale (TIDSortedElemSet & theElems,
const gp_Pnt& thePoint,
const std::list<double>& theScaleFact,
const bool theCopy,
const bool theMakeGroups,
SMESH_Mesh* theTargetMesh)
{
myLastCreatedElems.Clear();
myLastCreatedNodes.Clear();
SMESH_MeshEditor targetMeshEditor( theTargetMesh );
SMESHDS_Mesh* aTgtMesh = theTargetMesh ? theTargetMesh->GetMeshDS() : 0;
SMESHDS_Mesh* aMesh = GetMeshDS();
double scaleX=1.0, scaleY=1.0, scaleZ=1.0;
std::list<double>::const_iterator itS = theScaleFact.begin();
scaleX = (*itS);
if(theScaleFact.size()==1) {
scaleY = (*itS);
scaleZ= (*itS);
}
if(theScaleFact.size()==2) {
itS++;
scaleY = (*itS);
scaleZ= (*itS);
}
if(theScaleFact.size()>2) {
itS++;
scaleY = (*itS);
itS++;
scaleZ= (*itS);
}
// map old node to new one
TNodeNodeMap nodeMap;
// elements sharing moved nodes; those of them which have all
// nodes mirrored but are not in theElems are to be reversed
TIDSortedElemSet inverseElemSet;
// source elements for each generated one
SMESH_SequenceOfElemPtr srcElems, srcNodes;
// loop on theElems
TIDSortedElemSet::iterator itElem;
for ( itElem = theElems.begin(); itElem != theElems.end(); itElem++ ) {
const SMDS_MeshElement* elem = *itElem;
if ( !elem )
continue;
// loop on elem nodes
SMDS_ElemIteratorPtr itN = elem->nodesIterator();
while ( itN->more() ) {
// check if a node has been already transformed
const SMDS_MeshNode* node = cast2Node( itN->next() );
pair<TNodeNodeMap::iterator,bool> n2n_isnew =
nodeMap.insert( make_pair ( node, node ));
if ( !n2n_isnew.second )
continue;
//double coord[3];
//coord[0] = node->X();
//coord[1] = node->Y();
//coord[2] = node->Z();
//theTrsf.Transforms( coord[0], coord[1], coord[2] );
double dx = (node->X() - thePoint.X()) * scaleX;
double dy = (node->Y() - thePoint.Y()) * scaleY;
double dz = (node->Z() - thePoint.Z()) * scaleZ;
if ( theTargetMesh ) {
//const SMDS_MeshNode * newNode = aTgtMesh->AddNode( coord[0], coord[1], coord[2] );
const SMDS_MeshNode * newNode =
aTgtMesh->AddNode( thePoint.X()+dx, thePoint.Y()+dy, thePoint.Z()+dz );
n2n_isnew.first->second = newNode;
myLastCreatedNodes.Append(newNode);
srcNodes.Append( node );
}
else if ( theCopy ) {
//const SMDS_MeshNode * newNode = aMesh->AddNode( coord[0], coord[1], coord[2] );
const SMDS_MeshNode * newNode =
aMesh->AddNode( thePoint.X()+dx, thePoint.Y()+dy, thePoint.Z()+dz );
n2n_isnew.first->second = newNode;
myLastCreatedNodes.Append(newNode);
srcNodes.Append( node );
}
else {
//aMesh->MoveNode( node, coord[0], coord[1], coord[2] );
aMesh->MoveNode( node, thePoint.X()+dx, thePoint.Y()+dy, thePoint.Z()+dz );
// node position on shape becomes invalid
const_cast< SMDS_MeshNode* > ( node )->SetPosition
( SMDS_SpacePosition::originSpacePosition() );
}
// keep inverse elements
//if ( !theCopy && !theTargetMesh && needReverse ) {
// SMDS_ElemIteratorPtr invElemIt = node->GetInverseElementIterator();
// while ( invElemIt->more() ) {
// const SMDS_MeshElement* iel = invElemIt->next();
// inverseElemSet.insert( iel );
// }
//}
}
}
// either create new elements or reverse mirrored ones
//if ( !theCopy && !needReverse && !theTargetMesh )
if ( !theCopy && !theTargetMesh )
return PGroupIDs();
TIDSortedElemSet::iterator invElemIt = inverseElemSet.begin();
for ( ; invElemIt != inverseElemSet.end(); invElemIt++ )
theElems.insert( *invElemIt );
// replicate or reverse elements
enum {
REV_TETRA = 0, // = nbNodes - 4
REV_PYRAMID = 1, // = nbNodes - 4
REV_PENTA = 2, // = nbNodes - 4
REV_FACE = 3,
REV_HEXA = 4, // = nbNodes - 4
FORWARD = 5
};
int index[][8] = {
{ 2, 1, 0, 3, 4, 0, 0, 0 }, // REV_TETRA
{ 2, 1, 0, 3, 4, 0, 0, 0 }, // REV_PYRAMID
{ 2, 1, 0, 5, 4, 3, 0, 0 }, // REV_PENTA
{ 2, 1, 0, 3, 0, 0, 0, 0 }, // REV_FACE
{ 2, 1, 0, 3, 6, 5, 4, 7 }, // REV_HEXA
{ 0, 1, 2, 3, 4, 5, 6, 7 } // FORWARD
};
for ( itElem = theElems.begin(); itElem != theElems.end(); itElem++ )
{
const SMDS_MeshElement* elem = *itElem;
if ( !elem || elem->GetType() == SMDSAbs_Node )
continue;
int nbNodes = elem->NbNodes();
int elemType = elem->GetType();
if (elem->IsPoly()) {
// Polygon or Polyhedral Volume
switch ( elemType ) {
case SMDSAbs_Face:
{
vector<const SMDS_MeshNode*> poly_nodes (nbNodes);
int iNode = 0;
SMDS_ElemIteratorPtr itN = elem->nodesIterator();
while (itN->more()) {
const SMDS_MeshNode* node =
static_cast<const SMDS_MeshNode*>(itN->next());
TNodeNodeMap::iterator nodeMapIt = nodeMap.find(node);
if (nodeMapIt == nodeMap.end())
break; // not all nodes transformed
//if (needReverse) {
// // reverse mirrored faces and volumes
// poly_nodes[nbNodes - iNode - 1] = (*nodeMapIt).second;
//} else {
poly_nodes[iNode] = (*nodeMapIt).second;
//}
iNode++;
}
if ( iNode != nbNodes )
continue; // not all nodes transformed
if ( theTargetMesh ) {
myLastCreatedElems.Append(aTgtMesh->AddPolygonalFace(poly_nodes));
srcElems.Append( elem );
}
else if ( theCopy ) {
myLastCreatedElems.Append(aMesh->AddPolygonalFace(poly_nodes));
srcElems.Append( elem );
}
else {
aMesh->ChangePolygonNodes(elem, poly_nodes);
}
}
break;
case SMDSAbs_Volume:
{
// ATTENTION: Reversing is not yet done!!!
const SMDS_PolyhedralVolumeOfNodes* aPolyedre =
dynamic_cast<const SMDS_PolyhedralVolumeOfNodes*>( elem );
if (!aPolyedre) {
MESSAGE("Warning: bad volumic element");
continue;
}
vector<const SMDS_MeshNode*> poly_nodes;
vector<int> quantities;
bool allTransformed = true;
int nbFaces = aPolyedre->NbFaces();
for (int iface = 1; iface <= nbFaces && allTransformed; iface++) {
int nbFaceNodes = aPolyedre->NbFaceNodes(iface);
for (int inode = 1; inode <= nbFaceNodes && allTransformed; inode++) {
const SMDS_MeshNode* node = aPolyedre->GetFaceNode(iface, inode);
TNodeNodeMap::iterator nodeMapIt = nodeMap.find(node);
if (nodeMapIt == nodeMap.end()) {
allTransformed = false; // not all nodes transformed
} else {
poly_nodes.push_back((*nodeMapIt).second);
}
}
quantities.push_back(nbFaceNodes);
}
if ( !allTransformed )
continue; // not all nodes transformed
if ( theTargetMesh ) {
myLastCreatedElems.Append(aTgtMesh->AddPolyhedralVolume(poly_nodes, quantities));
srcElems.Append( elem );
}
else if ( theCopy ) {
myLastCreatedElems.Append(aMesh->AddPolyhedralVolume(poly_nodes, quantities));
srcElems.Append( elem );
}
else {
aMesh->ChangePolyhedronNodes(elem, poly_nodes, quantities);
}
}
break;
default:;
}
continue;
}
// Regular elements
int* i = index[ FORWARD ];
//if ( needReverse && nbNodes > 2) // reverse mirrored faces and volumes
// if ( elemType == SMDSAbs_Face )
// i = index[ REV_FACE ];
// else
// i = index[ nbNodes - 4 ];
if(elem->IsQuadratic()) {
static int anIds[] = {0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19};
i = anIds;
//if(needReverse) {
// if(nbNodes==3) { // quadratic edge
// static int anIds[] = {1,0,2};
// i = anIds;
// }
// else if(nbNodes==6) { // quadratic triangle
// static int anIds[] = {0,2,1,5,4,3};
// i = anIds;
// }
// else if(nbNodes==8) { // quadratic quadrangle
// static int anIds[] = {0,3,2,1,7,6,5,4};
// i = anIds;
// }
// else if(nbNodes==10) { // quadratic tetrahedron of 10 nodes
// static int anIds[] = {0,2,1,3,6,5,4,7,9,8};
// i = anIds;
// }
// else if(nbNodes==13) { // quadratic pyramid of 13 nodes
// static int anIds[] = {0,3,2,1,4,8,7,6,5,9,12,11,10};
// i = anIds;
// }
// else if(nbNodes==15) { // quadratic pentahedron with 15 nodes
// static int anIds[] = {0,2,1,3,5,4,8,7,6,11,10,9,12,14,13};
// i = anIds;
// }
// else { // nbNodes==20 - quadratic hexahedron with 20 nodes
// static int anIds[] = {0,3,2,1,4,7,6,5,11,10,9,8,15,14,13,12,16,19,18,17};
// i = anIds;
// }
//}
}
// find transformed nodes
vector<const SMDS_MeshNode*> nodes(nbNodes);
int iNode = 0;
SMDS_ElemIteratorPtr itN = elem->nodesIterator();
while ( itN->more() ) {
const SMDS_MeshNode* node =
static_cast<const SMDS_MeshNode*>( itN->next() );
TNodeNodeMap::iterator nodeMapIt = nodeMap.find( node );
if ( nodeMapIt == nodeMap.end() )
break; // not all nodes transformed
nodes[ i [ iNode++ ]] = (*nodeMapIt).second;
}
if ( iNode != nbNodes )
continue; // not all nodes transformed
if ( theTargetMesh ) {
if ( SMDS_MeshElement* copy =
targetMeshEditor.AddElement( nodes, elem->GetType(), elem->IsPoly() )) {
myLastCreatedElems.Append( copy );
srcElems.Append( elem );
}
}
else if ( theCopy ) {
if ( SMDS_MeshElement* copy = AddElement( nodes, elem->GetType(), elem->IsPoly() )) {
myLastCreatedElems.Append( copy );
srcElems.Append( elem );
}
}
else {
// reverse element as it was reversed by transformation
if ( nbNodes > 2 )
aMesh->ChangeElementNodes( elem, &nodes[0], nbNodes );
}
}
PGroupIDs newGroupIDs;
if ( theMakeGroups && theCopy ||
theMakeGroups && theTargetMesh ) {
string groupPostfix = "scaled";
newGroupIDs = generateGroups( srcNodes, srcElems, groupPostfix, theTargetMesh );
}
return newGroupIDs;
}
//======================================================================= //=======================================================================
/*! /*!
* \brief Create groups of elements made during transformation * \brief Create groups of elements made during transformation

View File

@ -390,23 +390,6 @@ public:
// Move or copy theElements applying theTrsf to their nodes // Move or copy theElements applying theTrsf to their nodes
/*!
* Generate new elements by extrusion of theElements
* param theElems - list of elements for scale
* param thePoint - base point for scale
* param theScaleFact - scale factors for axises
* param theCopy - allows copying the translated elements
* param theMakeGroups - forces the generation of new groups from existing ones
* param theTargetMesh - the name of the newly created mesh
* return instance of Mesh class
*/
PGroupIDs Scale (TIDSortedElemSet& theElements,
const gp_Pnt& thePoint,
const std::list<double>& theScaleFact,
const bool theCopy,
const bool theMakeGroups,
SMESH_Mesh* theTargetMesh=0);
typedef std::list< std::list< const SMDS_MeshNode* > > TListOfListOfNodes; typedef std::list< std::list< const SMDS_MeshNode* > > TListOfListOfNodes;
void FindCoincidentNodes (TIDSortedNodeSet & theNodes, void FindCoincidentNodes (TIDSortedNodeSet & theNodes,