mirror of
https://git.salome-platform.org/gitpub/modules/smesh.git
synced 2025-01-31 22:00:34 +05:00
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:
parent
ea89003dc2
commit
ee86814502
@ -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::Transform (TIDSortedElemSet & theElems,
|
||||
@ -5139,6 +5146,7 @@ SMESH_MeshEditor::Transform (TIDSortedElemSet & theElems,
|
||||
groupPostfix = "translated";
|
||||
break;
|
||||
case gp_Scale:
|
||||
case gp_CompoundTrsf: // different scale by axis
|
||||
groupPostfix = "scaled";
|
||||
break;
|
||||
default:
|
||||
@ -5161,7 +5169,36 @@ SMESH_MeshEditor::Transform (TIDSortedElemSet & theElems,
|
||||
// source elements for each generated one
|
||||
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;
|
||||
for ( itElem = theElems.begin(); itElem != theElems.end(); itElem++ ) {
|
||||
const SMDS_MeshElement* elem = *itElem;
|
||||
@ -5172,8 +5209,10 @@ SMESH_MeshEditor::Transform (TIDSortedElemSet & theElems,
|
||||
SMDS_ElemIteratorPtr itN = elem->nodesIterator();
|
||||
while ( itN->more() ) {
|
||||
|
||||
// check if a node has been already transformed
|
||||
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 =
|
||||
nodeMap.insert( make_pair ( node, node ));
|
||||
if ( !n2n_isnew.second )
|
||||
@ -5424,331 +5463,6 @@ SMESH_MeshEditor::Transform (TIDSortedElemSet & theElems,
|
||||
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
|
||||
|
@ -390,23 +390,6 @@ public:
|
||||
// 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;
|
||||
|
||||
void FindCoincidentNodes (TIDSortedNodeSet & theNodes,
|
||||
|
Loading…
Reference in New Issue
Block a user