-// Copyright (C) 2007-2010 CEA/DEN, EDF R&D, OPEN CASCADE
+// Copyright (C) 2007-2011 CEA/DEN, EDF R&D, OPEN CASCADE
//
-// Copyright (C) 2003-2007 OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN,
-// CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS
+// Copyright (C) 2003-2007 OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN,
+// CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS
//
-// This library is free software; you can redistribute it and/or
-// modify it under the terms of the GNU Lesser General Public
-// License as published by the Free Software Foundation; either
-// version 2.1 of the License.
+// This library is free software; you can redistribute it and/or
+// modify it under the terms of the GNU Lesser General Public
+// License as published by the Free Software Foundation; either
+// version 2.1 of the License.
//
-// This library is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-// Lesser General Public License for more details.
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+// Lesser General Public License for more details.
//
-// You should have received a copy of the GNU Lesser General Public
-// License along with this library; if not, write to the Free Software
-// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
-//
-// See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
+// You should have received a copy of the GNU Lesser General Public
+// License along with this library; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
//
+// See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
-// SMESH SMESH : idl implementation based on 'SMESH' unit's classes
+// SMESH SMESH : idl implementation based on 'SMESH' unit's classes
// File : SMESH_MeshEditor.cxx
// Created : Mon Apr 12 16:10:22 2004
// Author : Edward AGAPOV (eap)
-//
+
#define CHRONODEF
#include "SMESH_MeshEditor.hxx"
#include "SMESH_OctreeNode.hxx"
#include "SMESH_subMesh.hxx"
+#include <Basics_OCCTVersion.hxx>
+
#include "utilities.h"
#include <BRepAdaptor_Surface.hxx>
+#include <BRepBuilderAPI_MakeEdge.hxx>
#include <BRepClass3d_SolidClassifier.hxx>
#include <BRep_Tool.hxx>
#include <ElCLib.hxx>
#include <numeric>
#include <limits>
#include <algorithm>
+#include <sstream>
#define cast2Node(elem) static_cast<const SMDS_MeshNode*>( elem )
if ( aMesh->ShapeToMesh().IsNull() )
return 0;
- if ( theElem->GetType() == SMDSAbs_Node )
- {
- int aShapeID = theElem->getshapeId();
- if (aShapeID <= 0)
- return 0;
- else
- return aShapeID;
- }
-
- TopoDS_Shape aShape; // the shape a node is on
- SMDS_ElemIteratorPtr nodeIt = theElem->nodesIterator();
- while ( nodeIt->more() ) {
- const SMDS_MeshNode* node = static_cast<const SMDS_MeshNode*>( nodeIt->next() );
- int aShapeID = node->getshapeId();
- if (aShapeID > 0) {
- SMESHDS_SubMesh * sm = aMesh->MeshElements( aShapeID );
- if ( sm ) {
- if ( sm->Contains( theElem ))
- return aShapeID;
- if ( aShape.IsNull() )
- aShape = aMesh->IndexToShape( aShapeID );
- }
- else {
- //MESSAGE ( "::FindShape() No SubShape for aShapeID " << aShapeID );
+ int aShapeID = theElem->getshapeId();
+ if ( aShapeID < 1 )
+ return 0;
+
+ if ( SMESHDS_SubMesh * sm = aMesh->MeshElements( aShapeID ))
+ if ( sm->Contains( theElem ))
+ return aShapeID;
+
+ if ( theElem->GetType() == SMDSAbs_Node ) {
+ MESSAGE( ":( Error: invalid myShapeId of node " << theElem->GetID() );
+ }
+ else {
+ MESSAGE( ":( Error: invalid myShapeId of element " << theElem->GetID() );
+ }
+
+ TopoDS_Shape aShape; // the shape a node of theElem is on
+ if ( theElem->GetType() != SMDSAbs_Node )
+ {
+ SMDS_ElemIteratorPtr nodeIt = theElem->nodesIterator();
+ while ( nodeIt->more() ) {
+ const SMDS_MeshNode* node = static_cast<const SMDS_MeshNode*>( nodeIt->next() );
+ if ((aShapeID = node->getshapeId()) > 0) {
+ if ( SMESHDS_SubMesh * sm = aMesh->MeshElements( aShapeID ) ) {
+ if ( sm->Contains( theElem ))
+ return aShapeID;
+ if ( aShape.IsNull() )
+ aShape = aMesh->IndexToShape( aShapeID );
+ }
}
}
}
// None of nodes is on a proper shape,
// find the shape among ancestors of aShape on which a node is
- if ( aShape.IsNull() ) {
- //MESSAGE ("::FindShape() - NONE node is on shape")
- return 0;
+ if ( !aShape.IsNull() ) {
+ TopTools_ListIteratorOfListOfShape ancIt( GetMesh()->GetAncestors( aShape ));
+ for ( ; ancIt.More(); ancIt.Next() ) {
+ SMESHDS_SubMesh * sm = aMesh->MeshElements( ancIt.Value() );
+ if ( sm && sm->Contains( theElem ))
+ return aMesh->ShapeToIndex( ancIt.Value() );
+ }
}
- TopTools_ListIteratorOfListOfShape ancIt( GetMesh()->GetAncestors( aShape ));
- for ( ; ancIt.More(); ancIt.Next() ) {
- SMESHDS_SubMesh * sm = aMesh->MeshElements( ancIt.Value() );
- if ( sm && sm->Contains( theElem ))
- return aMesh->ShapeToIndex( ancIt.Value() );
+ else
+ {
+ const map<int,SMESHDS_SubMesh*>& id2sm = GetMeshDS()->SubMeshes();
+ map<int,SMESHDS_SubMesh*>::const_iterator id_sm = id2sm.begin();
+ for ( ; id_sm != id2sm.end(); ++id_sm )
+ if ( id_sm->second->Contains( theElem ))
+ return id_sm->first;
}
//MESSAGE ("::FindShape() - SHAPE NOT FOUND")
aNodes[5] = nd2;
}
+//=======================================================================
+//function : edgeConnectivity
+//purpose : auxilary
+// return number of the edges connected with the theNode.
+// if theEdges has connections with the other type of the
+// elements, return -1
+//=======================================================================
+static int nbEdgeConnectivity(const SMDS_MeshNode* theNode)
+{
+ SMDS_ElemIteratorPtr elemIt = theNode->GetInverseElementIterator();
+ int nb=0;
+ while(elemIt->more()) {
+ elemIt->next();
+ nb++;
+ }
+ return nb;
+}
+
+
//=======================================================================
//function : GetNodesFromTwoTria
//purpose : auxilary
myLastCreatedNodes.Append(newN);
// create a new element
- const SMDS_MeshNode* N[6];
if ( aBadRate1 <= aBadRate2 ) {
- N[0] = aNodes[0];
- N[1] = aNodes[1];
- N[2] = aNodes[2];
- N[3] = aNodes[4];
- N[4] = aNodes[5];
- N[5] = newN;
newElem1 = aMesh->AddFace(aNodes[2], aNodes[3], aNodes[0],
aNodes[6], aNodes[7], newN );
newElem2 = aMesh->AddFace(aNodes[2], aNodes[0], aNodes[1],
newN, aNodes[4], aNodes[5] );
}
else {
- N[0] = aNodes[1];
- N[1] = aNodes[2];
- N[2] = aNodes[3];
- N[3] = aNodes[5];
- N[4] = aNodes[6];
- N[5] = newN;
newElem1 = aMesh->AddFace(aNodes[3], aNodes[0], aNodes[1],
aNodes[7], aNodes[4], newN );
newElem2 = aMesh->AddFace(aNodes[3], aNodes[1], aNodes[2],
helper.SetIsQuadratic( false );
}
vector<const SMDS_MeshNode*> nodes( (*elem)->begin_nodes(), (*elem)->end_nodes() );
+ helper.SetElementsOnShape( true );
if ( splitMethod._baryNode )
{
// make a node at barycenter
}
// make tetras
- helper.SetElementsOnShape( true );
vector<const SMDS_MeshElement* > tetras( splitMethod._nbTetra ); // splits of a volume
const int* tetConn = splitMethod._connectivity;
for ( int i = 0; i < splitMethod._nbTetra; ++i, tetConn += 4 )
helper.SetElementsOnShape( false );
vector< const SMDS_MeshElement* > triangles;
+ // find submesh to add new triangles in
+ if ( !fSubMesh || !fSubMesh->Contains( face ))
+ {
+ int shapeID = FindShape( face );
+ fSubMesh = GetMeshDS()->MeshElements( shapeID );
+ }
map<int, const SMDS_MeshNode*>::iterator iF_n = splitMethod._faceBaryNode.find(iF);
if ( iF_n != splitMethod._faceBaryNode.end() )
{
if ( !volTool.IsFaceExternal( iF ))
swap( n2, n3 );
triangles.push_back( helper.AddFace( n1,n2,n3 ));
+
+ if ( fSubMesh && n3->getshapeId() < 1 )
+ fSubMesh->AddNode( n3 );
}
}
else
volNodes[ facet->_n3 ]));
}
}
- // find submesh to add new triangles in
- if ( !fSubMesh || !fSubMesh->Contains( face ))
- {
- int shapeID = FindShape( face );
- fSubMesh = GetMeshDS()->MeshElements( shapeID );
- }
for ( int i = 0; i < triangles.size(); ++i )
{
if ( !triangles[i] ) continue;
// create a new element
const SMDS_MeshElement* newElem1 = 0;
const SMDS_MeshElement* newElem2 = 0;
- const SMDS_MeshNode* N[6];
if ( the13Diag ) {
- N[0] = aNodes[0];
- N[1] = aNodes[1];
- N[2] = aNodes[2];
- N[3] = aNodes[4];
- N[4] = aNodes[5];
- N[5] = newN;
newElem1 = aMesh->AddFace(aNodes[2], aNodes[3], aNodes[0],
aNodes[6], aNodes[7], newN );
newElem2 = aMesh->AddFace(aNodes[2], aNodes[0], aNodes[1],
newN, aNodes[4], aNodes[5] );
}
else {
- N[0] = aNodes[1];
- N[1] = aNodes[2];
- N[2] = aNodes[3];
- N[3] = aNodes[5];
- N[4] = aNodes[6];
- N[5] = newN;
newElem1 = aMesh->AddFace(aNodes[3], aNodes[0], aNodes[1],
aNodes[7], aNodes[4], newN );
newElem2 = aMesh->AddFace(aNodes[3], aNodes[1], aNodes[2],
if ( projector.IsDone() ) {
double u, v, minVal = DBL_MAX;
for ( int i = projector.NbExt(); i > 0; i-- )
+#if OCC_VERSION_LARGE > 0x06040000 // Porting to OCCT6.5.1
+ if ( projector.SquareDistance( i ) < minVal ) {
+ minVal = projector.SquareDistance( i );
+#else
if ( projector.Value( i ) < minVal ) {
minVal = projector.Value( i );
+#endif
projector.Point( i ).Parameter( u, v );
}
result.SetCoord( u, v );
Handle(Geom_Surface) surface;
SMESHDS_SubMesh* faceSubMesh = 0;
TopoDS_Face face;
- double fToler2 = 0, vPeriod = 0., uPeriod = 0., f,l;
+ double fToler2 = 0, f,l;
double u1 = 0, u2 = 0, v1 = 0, v2 = 0;
bool isUPeriodic = false, isVPeriodic = false;
if ( *fId ) {
fToler2 *= fToler2 * 10.;
isUPeriodic = surface->IsUPeriodic();
if ( isUPeriodic )
- vPeriod = surface->UPeriod();
+ surface->UPeriod();
isVPeriodic = surface->IsVPeriodic();
if ( isVPeriodic )
- uPeriod = surface->VPeriod();
+ surface->VPeriod();
surface->Bounds( u1, u2, v1, v2 );
}
// ---------------------------------------------------------
// fix nodes on mesh boundary
if ( checkBoundaryNodes ) {
- map< NLink, int > linkNbMap; // how many times a link encounters in elemsOnFace
- map< NLink, int >::iterator link_nb;
+ map< SMESH_TLink, int > linkNbMap; // how many times a link encounters in elemsOnFace
+ map< SMESH_TLink, int >::iterator link_nb;
// put all elements links to linkNbMap
list< const SMDS_MeshElement* >::iterator elemIt = elemsOnFace.begin();
for ( ; elemIt != elemsOnFace.end(); ++elemIt ) {
const SMDS_MeshElement* elem = (*elemIt);
- int nbn = elem->NbNodes();
- if(elem->IsQuadratic())
- nbn = nbn/2;
+ int nbn = elem->NbCornerNodes();
// loop on elem links: insert them in linkNbMap
- const SMDS_MeshNode* curNode, *prevNode = elem->GetNodeWrap( nbn );
for ( int iN = 0; iN < nbn; ++iN ) {
- curNode = elem->GetNode( iN );
- NLink link;
- if ( curNode < prevNode ) link = make_pair( curNode , prevNode );
- else link = make_pair( prevNode , curNode );
- prevNode = curNode;
- link_nb = linkNbMap.find( link );
- if ( link_nb == linkNbMap.end() )
- linkNbMap.insert( make_pair ( link, 1 ));
- else
- link_nb->second++;
+ const SMDS_MeshNode* n1 = elem->GetNode( iN );
+ const SMDS_MeshNode* n2 = elem->GetNode(( iN+1 ) % nbn);
+ SMESH_TLink link( n1, n2 );
+ link_nb = linkNbMap.insert( make_pair( link, 0 )).first;
+ link_nb->second++;
}
}
// remove nodes that are in links encountered only once from setMovableNodes
for ( link_nb = linkNbMap.begin(); link_nb != linkNbMap.end(); ++link_nb ) {
if ( link_nb->second == 1 ) {
- setMovableNodes.erase( link_nb->first.first );
- setMovableNodes.erase( link_nb->first.second );
+ setMovableNodes.erase( link_nb->first.node1() );
+ setMovableNodes.erase( link_nb->first.node2() );
}
}
}
for ( int iStep = 0; iStep < nbSteps; iStep++ ) {
vTool.Set( *v );
vTool.SetExternalNormal();
+ const int nextShift = vTool.IsForward() ? +1 : -1;
list< int >::iterator ind = freeInd.begin();
list< const SMDS_MeshElement* >::iterator srcEdge = srcEdges.begin();
for ( ; ind != freeInd.end(); ++ind, ++srcEdge ) // loop on free faces
{
const SMDS_MeshNode** nodes = vTool.GetFaceNodes( *ind );
int nbn = vTool.NbFaceNodes( *ind );
- switch ( nbn ) {
- case 3: { ///// triangle
- const SMDS_MeshFace * f = aMesh->FindFace( nodes[ 0 ], nodes[ 1 ], nodes[ 2 ]);
- if ( !f )
- myLastCreatedElems.Append(aMesh->AddFace( nodes[ 0 ], nodes[ 1 ], nodes[ 2 ] ));
- else if ( nodes[ 1 ] != f->GetNodeWrap( f->GetNodeIndex( nodes[ 0 ] ) + 1 ))
+ if ( ! (*v)->IsPoly() )
+ switch ( nbn ) {
+ case 3: { ///// triangle
+ const SMDS_MeshFace * f = aMesh->FindFace( nodes[ 0 ], nodes[ 1 ], nodes[ 2 ]);
+ if ( !f ||
+ nodes[ 1 ] != f->GetNodeWrap( f->GetNodeIndex( nodes[ 0 ]) + nextShift ))
{
- myLastCreatedElems.Append(aMesh->AddFace( nodes[ 0 ], nodes[ 1 ], nodes[ 2 ] ));
- aMesh->RemoveElement(f);
+ const SMDS_MeshNode* newOrder[3] = { nodes[ 1 - nextShift ],
+ nodes[ 1 ],
+ nodes[ 1 + nextShift ] };
+ if ( f )
+ aMesh->ChangeElementNodes( f, &newOrder[0], nbn );
+ else
+ myLastCreatedElems.Append(aMesh->AddFace( newOrder[ 0 ], newOrder[ 1 ],
+ newOrder[ 2 ] ));
}
- break;
- }
- case 4: { ///// quadrangle
- const SMDS_MeshFace * f = aMesh->FindFace( nodes[ 0 ], nodes[ 1 ], nodes[ 2 ], nodes[ 3 ]);
- if ( !f )
- myLastCreatedElems.Append(aMesh->AddFace( nodes[ 0 ], nodes[ 1 ], nodes[ 2 ], nodes[ 3 ] ));
- else if ( nodes[ 1 ] != f->GetNodeWrap( f->GetNodeIndex( nodes[ 0 ] ) + 1 ))
+ break;
+ }
+ case 4: { ///// quadrangle
+ const SMDS_MeshFace * f =
+ aMesh->FindFace( nodes[ 0 ], nodes[ 1 ], nodes[ 2 ], nodes[ 3 ]);
+ if ( !f ||
+ nodes[ 1 ] != f->GetNodeWrap( f->GetNodeIndex( nodes[ 0 ]) + nextShift ))
{
- myLastCreatedElems.Append(aMesh->AddFace( nodes[ 0 ], nodes[ 1 ], nodes[ 2 ], nodes[ 3 ] ));
- aMesh->RemoveElement(f);
- }
- break;
- }
- default:
- if( (*v)->IsQuadratic() ) {
- if(nbn==6) { /////// quadratic triangle
- const SMDS_MeshFace * f = aMesh->FindFace( nodes[0], nodes[2], nodes[4],
- nodes[1], nodes[3], nodes[5] );
- if ( !f ) {
- myLastCreatedElems.Append(aMesh->AddFace(nodes[0], nodes[2], nodes[4],
- nodes[1], nodes[3], nodes[5]));
- }
- else if ( nodes[ 2 ] != f->GetNodeWrap( f->GetNodeIndex( nodes[ 0 ] ) + 1 )) {
- const SMDS_MeshNode** tmpnodes = new const SMDS_MeshNode*[6];
- tmpnodes[0] = nodes[0];
- tmpnodes[1] = nodes[2];
- tmpnodes[2] = nodes[4];
- tmpnodes[3] = nodes[1];
- tmpnodes[4] = nodes[3];
- tmpnodes[5] = nodes[5];
- myLastCreatedElems.Append(aMesh->AddFace(nodes[0], nodes[2], nodes[4],
- nodes[1], nodes[3], nodes[5]));
- aMesh->RemoveElement(f);
- }
+ const SMDS_MeshNode* newOrder[4] = { nodes[ 0 ], nodes[ 2-nextShift ],
+ nodes[ 2 ], nodes[ 2+nextShift ] };
+ if ( f )
+ aMesh->ChangeElementNodes( f, &newOrder[0], nbn );
+ else
+ myLastCreatedElems.Append(aMesh->AddFace( newOrder[ 0 ], newOrder[ 1 ],
+ newOrder[ 2 ], newOrder[ 3 ]));
}
- else { /////// quadratic quadrangle
- const SMDS_MeshFace * f = aMesh->FindFace( nodes[0], nodes[2], nodes[4], nodes[6],
- nodes[1], nodes[3], nodes[5], nodes[7] );
- if ( !f ) {
- myLastCreatedElems.Append(aMesh->AddFace(nodes[0], nodes[2], nodes[4], nodes[6],
- nodes[1], nodes[3], nodes[5], nodes[7]));
- }
- else if ( nodes[ 2 ] != f->GetNodeWrap( f->GetNodeIndex( nodes[ 0 ] ) + 1 )) {
- const SMDS_MeshNode** tmpnodes = new const SMDS_MeshNode*[8];
- tmpnodes[0] = nodes[0];
- tmpnodes[1] = nodes[2];
- tmpnodes[2] = nodes[4];
- tmpnodes[3] = nodes[6];
- tmpnodes[4] = nodes[1];
- tmpnodes[5] = nodes[3];
- tmpnodes[6] = nodes[5];
- tmpnodes[7] = nodes[7];
- myLastCreatedElems.Append(aMesh->AddFace(nodes[0], nodes[2], nodes[4], nodes[6],
- nodes[1], nodes[3], nodes[5], nodes[7]));
- aMesh->RemoveElement(f);
- }
+ break;
+ }
+ case 6: { /////// quadratic triangle
+ const SMDS_MeshFace * f = aMesh->FindFace( nodes[0], nodes[2], nodes[4],
+ nodes[1], nodes[3], nodes[5] );
+ if ( !f ||
+ nodes[2] != f->GetNodeWrap( f->GetNodeIndex( nodes[0] ) + 2*nextShift ))
+ {
+ const SMDS_MeshNode* newOrder[6] = { nodes[2 - 2*nextShift],
+ nodes[2],
+ nodes[2 + 2*nextShift],
+ nodes[3 - 2*nextShift],
+ nodes[3],
+ nodes[3 + 2*nextShift]};
+ if ( f )
+ aMesh->ChangeElementNodes( f, &newOrder[0], nbn );
+ else
+ myLastCreatedElems.Append(aMesh->AddFace( newOrder[ 0 ],
+ newOrder[ 1 ],
+ newOrder[ 2 ],
+ newOrder[ 3 ],
+ newOrder[ 4 ],
+ newOrder[ 5 ] ));
}
+ break;
}
- else { //////// polygon
- vector<const SMDS_MeshNode*> polygon_nodes ( nodes, &nodes[nbn] );
- const SMDS_MeshFace * f = aMesh->FindFace( polygon_nodes );
- if ( !f )
- myLastCreatedElems.Append(aMesh->AddPolygonalFace(polygon_nodes));
- else if ( nodes[ 1 ] != f->GetNodeWrap( f->GetNodeIndex( nodes[ 0 ] ) + 1 ))
- {
- // TODO problem ChangeElementNodes : not the same number of nodes, not the same type
- MESSAGE("ChangeElementNodes");
- aMesh->ChangeElementNodes( f, nodes, nbn );
- }
+ default: /////// quadratic quadrangle
+ const SMDS_MeshFace * f = aMesh->FindFace( nodes[0], nodes[2], nodes[4], nodes[6],
+ nodes[1], nodes[3], nodes[5], nodes[7] );
+ if ( !f ||
+ nodes[ 2 ] != f->GetNodeWrap( f->GetNodeIndex( nodes[ 0 ] ) + 2*nextShift ))
+ {
+ const SMDS_MeshNode* newOrder[8] = { nodes[0],
+ nodes[4 - 2*nextShift],
+ nodes[4],
+ nodes[4 + 2*nextShift],
+ nodes[1],
+ nodes[5 - 2*nextShift],
+ nodes[5],
+ nodes[5 + 2*nextShift] };
+ if ( f )
+ aMesh->ChangeElementNodes( f, &newOrder[0], nbn );
+ else
+ myLastCreatedElems.Append(aMesh->AddFace(newOrder[ 0 ], newOrder[ 1 ],
+ newOrder[ 2 ], newOrder[ 3 ],
+ newOrder[ 4 ], newOrder[ 5 ],
+ newOrder[ 6 ], newOrder[ 7 ]));
+ }
+ } // switch ( nbn )
+
+ else { //////// polygon
+
+ vector<const SMDS_MeshNode*> polygon_nodes ( nodes, &nodes[nbn] );
+ const SMDS_MeshFace * f = aMesh->FindFace( polygon_nodes );
+ if ( !f ||
+ nodes[ 1 ] != f->GetNodeWrap( f->GetNodeIndex( nodes[ 0 ] ) + nextShift ))
+ {
+ if ( !vTool.IsForward() )
+ std::reverse( polygon_nodes.begin(), polygon_nodes.end());
+ if ( f )
+ aMesh->ChangeElementNodes( f, &polygon_nodes[0], nbn );
+ else
+ AddElement(polygon_nodes, SMDSAbs_Face, polygon_nodes.size()>4);
}
}
+
while ( srcElements.Length() < myLastCreatedElems.Length() )
srcElements.Append( *srcEdge );
// go to the next volume
iVol = 0;
while ( iVol++ < nbVolumesByStep ) v++;
- }
- }
+
+ } // loop on steps
+ } // loop on volumes of one step
} // sweep free links into faces
// Make a ceiling face with a normal external to a volume
}
//Extrusion_Error err =
MakeEdgePathPoints(aPrms, aTrackEdge, (aN1==theN1), fullList);
- }
- else if( aS.ShapeType() == TopAbs_WIRE ) {
+ } else if( aS.ShapeType() == TopAbs_WIRE ) {
list< SMESH_subMesh* > LSM;
TopTools_SequenceOfShape Edges;
SMESH_subMeshIteratorPtr itSM = theTrack->getDependsOnIterator(false,true);
list< list<SMESH_MeshEditor_PathPoint> > LLPPs;
int startNid = theN1->GetID();
TColStd_MapOfInteger UsedNums;
+
int NbEdges = Edges.Length();
int i = 1;
for(; i<=NbEdges; i++) {
list<SMESH_MeshEditor_PathPoint> fullList;
const TopoDS_Shape& aS = theTrack->GetShapeToMesh();
- // Sub shape for the Pattern must be an Edge or Wire
- if( aS.ShapeType() == TopAbs_EDGE ) {
+
+ if( aS == SMESH_Mesh::PseudoShape() ) {
+ //Mesh without shape
+ const SMDS_MeshNode* currentNode = NULL;
+ const SMDS_MeshNode* prevNode = theN1;
+ std::vector<const SMDS_MeshNode*> aNodesList;
+ aNodesList.push_back(theN1);
+ int nbEdges = 0, conn=0;
+ const SMDS_MeshElement* prevElem = NULL;
+ const SMDS_MeshElement* currentElem = NULL;
+ int totalNbEdges = theTrack->NbEdges();
+ SMDS_ElemIteratorPtr nIt;
+ bool isClosed = false;
+
+ //check start node
+ if( !theTrack->GetMeshDS()->Contains(theN1) ) {
+ return EXTR_BAD_STARTING_NODE;
+ }
+
+ conn = nbEdgeConnectivity(theN1);
+ if(conn > 2)
+ return EXTR_PATH_NOT_EDGE;
+
+ aItE = theN1->GetInverseElementIterator();
+ prevElem = aItE->next();
+ currentElem = prevElem;
+ //Get all nodes
+ if(totalNbEdges == 1 ) {
+ nIt = currentElem->nodesIterator();
+ currentNode = static_cast<const SMDS_MeshNode*>(nIt->next());
+ if(currentNode == prevNode)
+ currentNode = static_cast<const SMDS_MeshNode*>(nIt->next());
+ aNodesList.push_back(currentNode);
+ } else {
+ nIt = currentElem->nodesIterator();
+ while( nIt->more() ) {
+ currentNode = static_cast<const SMDS_MeshNode*>(nIt->next());
+ if(currentNode == prevNode)
+ currentNode = static_cast<const SMDS_MeshNode*>(nIt->next());
+ aNodesList.push_back(currentNode);
+
+ //case of the closed mesh
+ if(currentNode == theN1) {
+ nbEdges++;
+ isClosed = true;
+ break;
+ }
+
+ conn = nbEdgeConnectivity(currentNode);
+ if(conn > 2) {
+ return EXTR_PATH_NOT_EDGE;
+ }else if( conn == 1 && nbEdges > 0 ) {
+ //End of the path
+ nbEdges++;
+ break;
+ }else {
+ prevNode = currentNode;
+ aItE = currentNode->GetInverseElementIterator();
+ currentElem = aItE->next();
+ if( currentElem == prevElem)
+ currentElem = aItE->next();
+ nIt = currentElem->nodesIterator();
+ prevElem = currentElem;
+ nbEdges++;
+ }
+ }
+ }
+
+ if(nbEdges != totalNbEdges)
+ return EXTR_PATH_NOT_EDGE;
+
+ TopTools_SequenceOfShape Edges;
+ double x1,x2,y1,y2,z1,z2;
+ list< list<SMESH_MeshEditor_PathPoint> > LLPPs;
+ int startNid = theN1->GetID();
+ for(int i = 1; i < aNodesList.size(); i++) {
+ x1 = aNodesList[i-1]->X();x2 = aNodesList[i]->X();
+ y1 = aNodesList[i-1]->Y();y2 = aNodesList[i]->Y();
+ z1 = aNodesList[i-1]->Z();z2 = aNodesList[i]->Z();
+ TopoDS_Edge e = BRepBuilderAPI_MakeEdge(gp_Pnt(x1,y1,z1),gp_Pnt(x2,y2,z2));
+ list<SMESH_MeshEditor_PathPoint> LPP;
+ aPrms.clear();
+ MakeEdgePathPoints(aPrms, e, (aNodesList[i-1]->GetID()==startNid), LPP);
+ LLPPs.push_back(LPP);
+ if( aNodesList[i-1]->GetID() == startNid ) startNid = aNodesList[i]->GetID();
+ else startNid = aNodesList[i-1]->GetID();
+
+ }
+
+ list< list<SMESH_MeshEditor_PathPoint> >::iterator itLLPP = LLPPs.begin();
+ list<SMESH_MeshEditor_PathPoint> firstList = *itLLPP;
+ list<SMESH_MeshEditor_PathPoint>::iterator itPP = firstList.begin();
+ for(; itPP!=firstList.end(); itPP++) {
+ fullList.push_back( *itPP );
+ }
+
+ SMESH_MeshEditor_PathPoint PP1 = fullList.back();
+ SMESH_MeshEditor_PathPoint PP2;
+ fullList.pop_back();
+ itLLPP++;
+ for(; itLLPP!=LLPPs.end(); itLLPP++) {
+ list<SMESH_MeshEditor_PathPoint> currList = *itLLPP;
+ itPP = currList.begin();
+ PP2 = currList.front();
+ gp_Dir D1 = PP1.Tangent();
+ gp_Dir D2 = PP2.Tangent();
+ gp_Dir Dnew( gp_Vec( (D1.X()+D2.X())/2, (D1.Y()+D2.Y())/2,
+ (D1.Z()+D2.Z())/2 ) );
+ PP1.SetTangent(Dnew);
+ fullList.push_back(PP1);
+ itPP++;
+ for(; itPP!=currList.end(); itPP++) {
+ fullList.push_back( *itPP );
+ }
+ PP1 = fullList.back();
+ fullList.pop_back();
+ }
+ fullList.push_back(PP1);
+
+ } // Sub shape for the Pattern must be an Edge or Wire
+ else if( aS.ShapeType() == TopAbs_EDGE ) {
aTrackEdge = TopoDS::Edge( aS );
// the Edge must not be degenerated
if ( BRep_Tool::Degenerated( aTrackEdge ) )
list<SMESH_MeshEditor_PathPoint> currList = *itLLPP;
itPP = currList.begin();
SMESH_MeshEditor_PathPoint PP2 = currList.front();
- gp_Pnt P1 = PP1.Pnt();
- //cout<<" PP1: Pnt("<<P1.X()<<","<<P1.Y()<<","<<P1.Z()<<")"<<endl;
- gp_Pnt P2 = PP2.Pnt();
gp_Dir D1 = PP1.Tangent();
gp_Dir D2 = PP2.Tangent();
gp_Dir Dnew( gp_Vec( (D1.X()+D2.X())/2, (D1.Y()+D2.Y())/2,
* \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
+ * \return SMESH_MeshEditor::PGroupIDs - list of ids of created groups
*/
//================================================================================
PGroupIDs newGroupIDs;
- if ( theMakeGroups && theCopy ||
- theMakeGroups && theTargetMesh )
+ if ( ( theMakeGroups && theCopy ) ||
+ ( theMakeGroups && theTargetMesh ) )
newGroupIDs = generateGroups( srcNodes, srcElems, groupPostfix, theTargetMesh );
return newGroupIDs;
//=======================================================================
/*!
- * \brief Return SMESH_ElementSearcher
+ * \brief Return SMESH_ElementSearcher acting on a sub-set of elements
*/
//=======================================================================
}
curNodes[ iCur ] = n;
bool isUnique = nodeSet.insert( n ).second;
- if ( isUnique )
+ if ( isUnique ) {
uniqueNodes[ iUnique++ ] = n;
+ if ( nbRepl && iRepl[ nbRepl-1 ] == iCur )
+ --nbRepl; // n do not stick to a node of the elem
+ }
iCur++;
}
}
continue;
- }
+ } // poly element
// Regular elements
// TODO not all the possible cases are solved. Find something more generic?
isOk = false;
SMDS_VolumeTool hexa (elem);
hexa.SetExternalNormal();
- if ( nbUniqueNodes == 4 && nbRepl == 6 ) {
- //////////////////////// ---> tetrahedron
+ if ( nbUniqueNodes == 4 && nbRepl == 4 ) {
+ //////////////////////// HEX ---> 1 tetrahedron
for ( int iFace = 0; iFace < 6; iFace++ ) {
const int *ind = hexa.GetFaceNodesIndices( iFace ); // indices of face nodes
if (curNodes[ind[ 0 ]] == curNodes[ind[ 1 ]] &&
int iOppFace = hexa.GetOppFaceIndex( iFace );
ind = hexa.GetFaceNodesIndices( iOppFace );
int nbStick = 0;
- iUnique = 2; // reverse a tetrahedron bottom
for ( iCur = 0; iCur < 4 && nbStick < 2; iCur++ ) {
if ( curNodes[ind[ iCur ]] == curNodes[ind[ iCur + 1 ]] )
nbStick++;
- else if ( iUnique >= 0 )
- uniqueNodes[ iUnique-- ] = curNodes[ind[ iCur ]];
}
if ( nbStick == 1 ) {
// ... and the opposite one - into a triangle.
}
}
}
+ else if ( nbUniqueNodes == 6 && nbRepl == 2 ) {
+ //////////////////////// HEX ---> 1 prism
+ int nbTria = 0, iTria[3];
+ const int *ind; // indices of face nodes
+ // look for triangular faces
+ for ( int iFace = 0; iFace < 6 && nbTria < 3; iFace++ ) {
+ ind = hexa.GetFaceNodesIndices( iFace );
+ TIDSortedNodeSet faceNodes;
+ for ( iCur = 0; iCur < 4; iCur++ )
+ faceNodes.insert( curNodes[ind[iCur]] );
+ if ( faceNodes.size() == 3 )
+ iTria[ nbTria++ ] = iFace;
+ }
+ // check if triangles are opposite
+ if ( nbTria == 2 && iTria[0] == hexa.GetOppFaceIndex( iTria[1] ))
+ {
+ isOk = true;
+ // set nodes of the bottom triangle
+ ind = hexa.GetFaceNodesIndices( iTria[ 0 ]);
+ vector<int> indB;
+ for ( iCur = 0; iCur < 4; iCur++ )
+ if ( ind[iCur] != iRepl[0] && ind[iCur] != iRepl[1])
+ indB.push_back( ind[iCur] );
+ if ( !hexa.IsForward() )
+ std::swap( indB[0], indB[2] );
+ for ( iCur = 0; iCur < 3; iCur++ )
+ uniqueNodes[ iCur ] = curNodes[indB[iCur]];
+ // set nodes of the top triangle
+ const int *indT = hexa.GetFaceNodesIndices( iTria[ 1 ]);
+ for ( iCur = 0; iCur < 3; ++iCur )
+ for ( int j = 0; j < 4; ++j )
+ if ( hexa.IsLinked( indB[ iCur ], indT[ j ] ))
+ {
+ uniqueNodes[ iCur + 3 ] = curNodes[ indT[ j ]];
+ break;
+ }
+ }
+ break;
+ }
else if (nbUniqueNodes == 5 && nbRepl == 4 ) {
//////////////////// HEXAHEDRON ---> 2 tetrahedrons
for ( int iFace = 0; iFace < 6; iFace++ ) {
}
}
} // if ( nbUniqueNodes == 6 && nbRepl == 4 )
+ else
+ {
+ MESSAGE("MergeNodes() removes hexahedron "<< elem);
+ }
break;
} // HEXAHEDRON
} // if ( nbNodes != nbUniqueNodes ) // some nodes stick
- if ( isOk ) {
- if (elem->IsPoly() && elem->GetType() == SMDSAbs_Volume) {
+ if ( isOk ) { // the elem remains valid after sticking nodes
+ if (elem->IsPoly() && elem->GetType() == SMDSAbs_Volume)
+ {
// Change nodes of polyedre
const SMDS_VtkVolume* aPolyedre =
dynamic_cast<const SMDS_VtkVolume*>( elem );
aMesh->ChangePolyhedronNodes( elem, poly_nodes, quantities );
}
}
- else {
- //int elemId = elem->GetID();
- //MESSAGE("Change regular element or polygon " << elemId);
- SMDSAbs_ElementType etyp = elem->GetType();
+ else // replace non-polyhedron elements
+ {
+ const SMDSAbs_ElementType etyp = elem->GetType();
+ const int elemId = elem->GetID();
+ const bool isPoly = (elem->GetEntityType() == SMDSEntity_Polygon);
uniqueNodes.resize(nbUniqueNodes);
- SMDS_MeshElement* newElem = 0;
- if (elem->GetEntityType() == SMDSEntity_Polygon)
- newElem = this->AddElement(uniqueNodes, etyp, true);
- else
- newElem = this->AddElement(uniqueNodes, etyp, false);
- if (newElem)
- {
- myLastCreatedElems.Append(newElem);
- if ( aShapeId )
- aMesh->SetMeshElementOnShape( newElem, aShapeId );
- }
- aMesh->RemoveElement(elem);
+
+ SMESHDS_SubMesh * sm = aShapeId > 0 ? aMesh->MeshElements(aShapeId) : 0;
+
+ aMesh->RemoveFreeElement(elem, sm, /*fromGroups=*/false);
+ SMDS_MeshElement* newElem = this->AddElement(uniqueNodes, etyp, isPoly, elemId);
+ if ( sm && newElem )
+ sm->AddElement( newElem );
+ if ( elem != newElem )
+ ReplaceElemInGroups( elem, newElem, aMesh );
}
}
else {
// Remove invalid regular element or invalid polygon
- //MESSAGE("Remove invalid " << elem->GetID());
rmElemIds.push_back( elem->GetID() );
}
//=======================================================================
/*!
* \brief Convert elements contained in a submesh to quadratic
- * \retval int - nb of checked elements
+ * \return int - nb of checked elements
*/
//=======================================================================
}
}
- if ( !theForce3d && !getenv("NO_FixQuadraticElements"))
+ if ( !theForce3d )
{ // setenv NO_FixQuadraticElements to know if FixQuadraticElements() is guilty of bad conversion
aHelper.SetSubShape(0); // apply FixQuadraticElements() to the whole mesh
aHelper.FixQuadraticElements();
//=======================================================================
/*!
* \brief Convert quadratic elements to linear ones and remove quadratic nodes
- * \retval int - nb of checked elements
+ * \return int - nb of checked elements
*/
//=======================================================================
}
// check similarity of elements of the sides
- if (aResult == SEW_OK && ( face[0] && !face[1] ) || ( !face[0] && face[1] )) {
+ if (aResult == SEW_OK && (( face[0] && !face[1] ) || ( !face[0] && face[1] ))) {
MESSAGE("Correspondent face not found on side " << ( face[0] ? 1 : 0 ));
if ( nReplaceMap.size() == 2 ) { // faces on input nodes not found
aResult = ( face[0] ? SEW_BAD_SIDE2_NODES : SEW_BAD_SIDE1_NODES );
* \param theSecondNode1 - a boundary node of set 1 linked with theFirstNode1
* \param theSecondNode2 - a node of set 2 corresponding to theSecondNode1
* \param nReplaceMap - output map of corresponding nodes
- * \retval bool - is a success or not
+ * \return bool - is a success or not
*/
//================================================================================
_extremum.Perform(aPnt);
if ( _extremum.IsDone() )
for ( int iSol = 1; iSol <= _extremum.NbExt() && _state == TopAbs_OUT; ++iSol)
+#if OCC_VERSION_LARGE > 0x06040000 // Porting to OCCT6.5.1
+ _state = ( _extremum.SquareDistance(iSol) <= theTol ? TopAbs_IN : TopAbs_OUT );
+#else
_state = ( _extremum.Value(iSol) <= theTol ? TopAbs_IN : TopAbs_OUT );
+#endif
}
TopAbs_State State() const
{
* The nodes of the internal faces at the boundaries of the groups are doubled.
* In option, the internal faces are replaced by flat elements.
* Triangles are transformed in prisms, and quadrangles in hexahedrons.
+ * The flat elements are stored in groups of volumes.
* @param theElems - list of groups of volumes, where a group of volume is a set of
* SMDS_MeshElements sorted by Id.
* @param createJointElems - if TRUE, create the elements
MESSAGE("----------------------------------------------");
SMESHDS_Mesh *meshDS = this->myMesh->GetMeshDS();
- meshDS->BuildDownWardConnectivity(false);
+ meshDS->BuildDownWardConnectivity(true);
CHRONO(50);
SMDS_UnstructuredGrid *grid = meshDS->getGrid();
continue;
int vtkType = grid->GetCellType(vtkId);
int downId = grid->CellIdToDownId(vtkId);
+ if (downId < 0)
+ {
+ MESSAGE("doubleNodesOnGroupBoundaries: internal algorithm problem");
+ continue; // not OK at this stage of the algorithm:
+ //no cells created after BuildDownWardConnectivity
+ }
DownIdType aCell(downId, vtkType);
if (celldom.count(vtkId))
continue;
nodeDomains[oldId][idom] = newId; // cloned node for other domains
//MESSAGE(" newNode " << newId << " oldNode " << oldId << " size=" <<nodeDomains[oldId].size());
}
+ if (nodeDomains[oldId].size() >= 3)
+ {
+ //MESSAGE("confirm multiple node " << oldId);
+ isMultipleDetected =true;
+ }
}
}
if (isMultipleDetected) // check if an edge of the face is shared between 3 or more domains
// (domain1 X domain2) = domain1 + MAXINT*domain2
std::map<int, std::map<long,int> > nodeQuadDomains;
+ std::map<std::string, SMESH_Group*> mapOfJunctionGroups;
if (createJointElems)
{
itface = faceDomains.begin();
- for( ; itface != faceDomains.end();++itface )
+ for (; itface != faceDomains.end(); ++itface)
{
DownIdType face = itface->first;
std::set<int> oldNodes;
oldNodes.clear();
grid->GetNodeIds(oldNodes, face.cellId, face.cellType);
- std::map<int,int> domvol = itface->second;
- std::map<int,int>::iterator itdom = domvol.begin();
+ std::map<int, int> domvol = itface->second;
+ std::map<int, int>::iterator itdom = domvol.begin();
int dom1 = itdom->first;
int vtkVolId = itdom->second;
itdom++;
int dom2 = itdom->first;
- grid->extrudeVolumeFromFace(vtkVolId, dom1, dom2, oldNodes, nodeDomains, nodeQuadDomains);
+ SMDS_MeshVolume *vol = grid->extrudeVolumeFromFace(vtkVolId, dom1, dom2, oldNodes, nodeDomains,
+ nodeQuadDomains);
+ stringstream grpname;
+ grpname << "j_";
+ if (dom1 < dom2)
+ grpname << dom1 << "_" << dom2;
+ else
+ grpname << dom2 << "_" << dom1;
+ int idg;
+ string namegrp = grpname.str();
+ if (!mapOfJunctionGroups.count(namegrp))
+ mapOfJunctionGroups[namegrp] = this->myMesh->AddGroup(SMDSAbs_Volume, namegrp.c_str(), idg);
+ SMESHDS_Group *sgrp = dynamic_cast<SMESHDS_Group*>(mapOfJunctionGroups[namegrp]->GetGroupDS());
+ if (sgrp)
+ sgrp->Add(vol->GetID());
}
}
{
vector<int> nodes = ite->first;
vector<int> orderDom = ite->second;
- vector<long long int> orderedNodes;
+ vector<vtkIdType> orderedNodes;
if (nodes.size() == 2)
{
//MESSAGE(" use edgesMultiDomains " << nodes[0] << " " << nodes[1]);
else
for (int idom = orderDom.size()-1; idom >=0; idom--)
orderedNodes.push_back( nodeDomains[nodes[ino]][orderDom[idom]] );
- this->GetMeshDS()->AddVolumeFromVtkIds(orderedNodes);
+ SMDS_MeshVolume* vol = this->GetMeshDS()->AddVolumeFromVtkIds(orderedNodes);
+
+ stringstream grpname;
+ grpname << "mj_";
+ grpname << 0 << "_" << 0;
+ int idg;
+ string namegrp = grpname.str();
+ if (!mapOfJunctionGroups.count(namegrp))
+ mapOfJunctionGroups[namegrp] = this->myMesh->AddGroup(SMDSAbs_Volume, namegrp.c_str(), idg);
+ SMESHDS_Group *sgrp = dynamic_cast<SMESHDS_Group*>(mapOfJunctionGroups[namegrp]->GetGroupDS());
+ if (sgrp)
+ sgrp->Add(vol->GetID());
}
else
{
+ //MESSAGE("Quadratic multiple joints not implemented");
// TODO quadratic nodes
}
}
int vtkId = l.cells[i];
int vtkType = grid->GetCellType(vtkId);
int downId = grid->CellIdToDownId(vtkId);
+ if (downId < 0)
+ continue; // new cells: not to be modified
DownIdType aCell(downId, vtkType);
int volParents[1000];
int nbvol = grid->GetParentVolumes(volParents, vtkId);
}
}
+ meshDS->CleanDownWardConnectivity(); // Mesh has been modified, downward connectivity is no more usable, free memory
grid->BuildLinks();
CHRONOSTOP(50);
return true;
}
+/*!
+ * \brief Double nodes on some external faces and create flat elements.
+ * Flat elements are mainly used by some types of mechanic calculations.
+ *
+ * Each group of the list must be constituted of faces.
+ * Triangles are transformed in prisms, and quadrangles in hexahedrons.
+ * @param theElems - list of groups of faces, where a group of faces is a set of
+ * SMDS_MeshElements sorted by Id.
+ * @return TRUE if operation has been completed successfully, FALSE otherwise
+ */
+bool SMESH_MeshEditor::CreateFlatElementsOnFacesGroups(const std::vector<TIDSortedElemSet>& theElems)
+{
+ MESSAGE("-------------------------------------------------");
+ MESSAGE("SMESH_MeshEditor::CreateFlatElementsOnFacesGroups");
+ MESSAGE("-------------------------------------------------");
+
+ SMESHDS_Mesh *meshDS = this->myMesh->GetMeshDS();
+
+ // --- For each group of faces
+ // duplicate the nodes, create a flat element based on the face
+ // replace the nodes of the faces by their clones
+
+ std::map<const SMDS_MeshNode*, const SMDS_MeshNode*> clonedNodes;
+ std::map<const SMDS_MeshNode*, const SMDS_MeshNode*> intermediateNodes;
+ clonedNodes.clear();
+ intermediateNodes.clear();
+ std::map<std::string, SMESH_Group*> mapOfJunctionGroups;
+ mapOfJunctionGroups.clear();
+
+ for (int idom = 0; idom < theElems.size(); idom++)
+ {
+ const TIDSortedElemSet& domain = theElems[idom];
+ TIDSortedElemSet::const_iterator elemItr = domain.begin();
+ for (; elemItr != domain.end(); ++elemItr)
+ {
+ SMDS_MeshElement* anElem = (SMDS_MeshElement*) *elemItr;
+ SMDS_MeshFace* aFace = dynamic_cast<SMDS_MeshFace*> (anElem);
+ if (!aFace)
+ continue;
+ // MESSAGE("aFace=" << aFace->GetID());
+ bool isQuad = aFace->IsQuadratic();
+ vector<const SMDS_MeshNode*> ln0, ln1, ln2, ln3, ln4;
+
+ // --- clone the nodes, create intermediate nodes for non medium nodes of a quad face
+
+ SMDS_ElemIteratorPtr nodeIt = aFace->nodesIterator();
+ while (nodeIt->more())
+ {
+ const SMDS_MeshNode* node = static_cast<const SMDS_MeshNode*> (nodeIt->next());
+ bool isMedium = isQuad && (aFace->IsMediumNode(node));
+ if (isMedium)
+ ln2.push_back(node);
+ else
+ ln0.push_back(node);
+
+ const SMDS_MeshNode* clone = 0;
+ if (!clonedNodes.count(node))
+ {
+ clone = meshDS->AddNode(node->X(), node->Y(), node->Z());
+ clonedNodes[node] = clone;
+ }
+ else
+ clone = clonedNodes[node];
+
+ if (isMedium)
+ ln3.push_back(clone);
+ else
+ ln1.push_back(clone);
+
+ const SMDS_MeshNode* inter = 0;
+ if (isQuad && (!isMedium))
+ {
+ if (!intermediateNodes.count(node))
+ {
+ inter = meshDS->AddNode(node->X(), node->Y(), node->Z());
+ intermediateNodes[node] = inter;
+ }
+ else
+ inter = intermediateNodes[node];
+ ln4.push_back(inter);
+ }
+ }
+
+ // --- extrude the face
+
+ vector<const SMDS_MeshNode*> ln;
+ SMDS_MeshVolume* vol = 0;
+ vtkIdType aType = aFace->GetVtkType();
+ switch (aType)
+ {
+ case VTK_TRIANGLE:
+ vol = meshDS->AddVolume(ln0[2], ln0[1], ln0[0], ln1[2], ln1[1], ln1[0]);
+ // MESSAGE("vol prism " << vol->GetID());
+ ln.push_back(ln1[0]);
+ ln.push_back(ln1[1]);
+ ln.push_back(ln1[2]);
+ break;
+ case VTK_QUAD:
+ vol = meshDS->AddVolume(ln0[3], ln0[2], ln0[1], ln0[0], ln1[3], ln1[2], ln1[1], ln1[0]);
+ // MESSAGE("vol hexa " << vol->GetID());
+ ln.push_back(ln1[0]);
+ ln.push_back(ln1[1]);
+ ln.push_back(ln1[2]);
+ ln.push_back(ln1[3]);
+ break;
+ case VTK_QUADRATIC_TRIANGLE:
+ vol = meshDS->AddVolume(ln1[0], ln1[1], ln1[2], ln0[0], ln0[1], ln0[2], ln3[0], ln3[1], ln3[2],
+ ln2[0], ln2[1], ln2[2], ln4[0], ln4[1], ln4[2]);
+ // MESSAGE("vol quad prism " << vol->GetID());
+ ln.push_back(ln1[0]);
+ ln.push_back(ln1[1]);
+ ln.push_back(ln1[2]);
+ ln.push_back(ln3[0]);
+ ln.push_back(ln3[1]);
+ ln.push_back(ln3[2]);
+ break;
+ case VTK_QUADRATIC_QUAD:
+// vol = meshDS->AddVolume(ln0[0], ln0[1], ln0[2], ln0[3], ln1[0], ln1[1], ln1[2], ln1[3],
+// ln2[0], ln2[1], ln2[2], ln2[3], ln3[0], ln3[1], ln3[2], ln3[3],
+// ln4[0], ln4[1], ln4[2], ln4[3]);
+ vol = meshDS->AddVolume(ln1[0], ln1[1], ln1[2], ln1[3], ln0[0], ln0[1], ln0[2], ln0[3],
+ ln3[0], ln3[1], ln3[2], ln3[3], ln2[0], ln2[1], ln2[2], ln2[3],
+ ln4[0], ln4[1], ln4[2], ln4[3]);
+ // MESSAGE("vol quad hexa " << vol->GetID());
+ ln.push_back(ln1[0]);
+ ln.push_back(ln1[1]);
+ ln.push_back(ln1[2]);
+ ln.push_back(ln1[3]);
+ ln.push_back(ln3[0]);
+ ln.push_back(ln3[1]);
+ ln.push_back(ln3[2]);
+ ln.push_back(ln3[3]);
+ break;
+ case VTK_POLYGON:
+ break;
+ default:
+ break;
+ }
+
+ if (vol)
+ {
+ stringstream grpname;
+ grpname << "jf_";
+ grpname << idom;
+ int idg;
+ string namegrp = grpname.str();
+ if (!mapOfJunctionGroups.count(namegrp))
+ mapOfJunctionGroups[namegrp] = this->myMesh->AddGroup(SMDSAbs_Volume, namegrp.c_str(), idg);
+ SMESHDS_Group *sgrp = dynamic_cast<SMESHDS_Group*>(mapOfJunctionGroups[namegrp]->GetGroupDS());
+ if (sgrp)
+ sgrp->Add(vol->GetID());
+ }
+
+ // --- modify the face
+
+ aFace->ChangeNodes(&ln[0], ln.size());
+ }
+ }
+ return true;
+}
+
//================================================================================
/*!
* \brief Generates skin mesh (containing 2D cells) from 3D mesh
* \param group - a group to store created boundary elements in
* \param targetMesh - a mesh to store created boundary elements in
* \param toCopyElements - if true, the checked elements will be copied into the targetMesh
- * \param toCopyExistingBondary - if true, not only new but also pre-existing
+ * \param toCopyExistingBoundary - if true, not only new but also pre-existing
* boundary elements will be copied into the targetMesh
* \param toAddExistingBondary - if true, not only new but also pre-existing
* boundary elements will be added into the new group
* \param aroundElements - if true, elements will be created on boundary of given
- * elements else, on boundary of the whole mesh. This
- * option works for 2D elements only.
+ * elements else, on boundary of the whole mesh.
* \return nb of added boundary elements
*/
//================================================================================
SMESH_Group* group/*=0*/,
SMESH_Mesh* targetMesh/*=0*/,
bool toCopyElements/*=false*/,
- bool toCopyExistingBondary/*=false*/,
+ bool toCopyExistingBoundary/*=false*/,
bool toAddExistingBondary/*= false*/,
bool aroundElements/*= false*/)
{
if ( !elements.empty() && (*elements.begin())->GetType() != elemType )
throw SALOME_Exception(LOCALIZED("wrong element type"));
- if ( aroundElements && elemType == SMDSAbs_Volume )
- throw SALOME_Exception(LOCALIZED("wrong element type for aroundElements==true"));
-
if ( !targetMesh )
- toCopyElements = toCopyExistingBondary = false;
+ toCopyElements = toCopyExistingBoundary = false;
SMESH_MeshEditor tgtEditor( targetMesh ? targetMesh : myMesh );
SMESHDS_Mesh* aMesh = GetMeshDS(), *tgtMeshDS = tgtEditor.GetMeshDS();
if ( vTool.Set(elem) ) // elem is a volume ------------------------------------------
{
vTool.SetExternalNormal();
+ const SMDS_MeshElement* otherVol = 0;
for ( int iface = 0, n = vTool.NbFaces(); iface < n; iface++ )
{
- if (!vTool.IsFreeFace(iface))
+ if ( !vTool.IsFreeFace(iface, &otherVol) &&
+ ( !aroundElements || elements.count( otherVol )))
continue;
- int nbFaceNodes = vTool.NbFaceNodes(iface);
+ const int nbFaceNodes = vTool.NbFaceNodes(iface);
const SMDS_MeshNode** nn = vTool.GetFaceNodes(iface);
if ( missType == SMDSAbs_Edge ) // boundary edges
{
presentBndElems.push_back( f );
else
missingBndElems.push_back( nodes );
+
+ if ( targetMesh != myMesh )
+ {
+ // add 1D elements on face boundary to be added to a new mesh
+ const SMDS_MeshElement* edge;
+ for ( inode = 0; inode < nbFaceNodes; inode += 1+iQuad)
+ {
+ if ( iQuad )
+ edge = aMesh->FindEdge( nn[inode], nn[inode+1], nn[inode+2]);
+ else
+ edge = aMesh->FindEdge( nn[inode], nn[inode+1]);
+ if ( edge && avoidSet.insert( edge ).second )
+ presentBndElems.push_back( edge );
+ }
+ }
}
}
}
// ---------------------------------
if ( targetMesh != myMesh )
// instead of making a map of nodes in this mesh and targetMesh,
- // we create nodes with same IDs. We can renumber them later, if needed
+ // we create nodes with same IDs.
for ( int i = 0; i < missingBndElems.size(); ++i )
{
TConnectivity& srcNodes = missingBndElems[i];
// ----------------------------------
// 3. Copy present boundary elements
// ----------------------------------
- if ( toCopyExistingBondary )
+ if ( toCopyExistingBoundary )
for ( int i = 0 ; i < presentBndElems.size(); ++i )
{
const SMDS_MeshElement* e = presentBndElems[i];
TConnectivity nodes( e->NbNodes() );
for ( inode = 0; inode < nodes.size(); ++inode )
nodes[inode] = getNodeWithSameID( tgtMeshDS, e->GetNode(inode) );
- presentEditor->AddElement(nodes, missType, e->IsPoly());
+ presentEditor->AddElement(nodes, e->GetType(), e->IsPoly());
}
else // store present elements to add them to a group
for ( int i = 0 ; i < presentBndElems.size(); ++i )