in string MeshName)
raises (SALOME::SALOME_Exception);
+ SMESH_Mesh Offset(in SMESH_IDSource theObject,
+ in double Value,
+ in boolean CopyGroups,
+ in string MeshName,
+ out ListOfGroups Groups)
+ raises (SALOME::SALOME_Exception);
+
void FindCoincidentNodes (in double Tolerance,
out array_of_long_array GroupsOfNodes,
in boolean SeparateCornersAndMedium)
* \param theElements - container of elements to duplicate.
* \param theGroupName - a name of group to contain the generated elements.
* If a group with such a name already exists, the new elements
- * are added to the existng group, else a new group is created.
+ * are added to the existing group, else a new group is created.
* If \a theGroupName is empty, new elements are not added
* in any group.
* \return a group where the new elements are added. NULL if theGroupName == "".
mesh_show.png
mesh_hide.png
mesh_deflection.png
+ mesh_offset.png
)
INSTALL(FILES ${SMESH_RESOURCES_FILES} DESTINATION ${SALOME_SMESH_INSTALL_RES_DATA})
#include "SMDS_FaceOfNodes.hxx"
#include "SMDS_IteratorOnIterators.hxx"
#include "SMDS_Mesh.hxx"
-#include "SMDS_MeshElement.hxx"
-#include "SMDS_MeshNode.hxx"
#include "SMDS_PolygonalFaceOfNodes.hxx"
#include "SMDS_SetIterator.hxx"
#include "SMDS_VolumeTool.hxx"
#include "SMESH_File.hxx"
+#include "SMESH_MeshAlgos.hxx"
#include "SMESH_TypeDefs.hxx"
-#include <Standard_ErrorHandler.hxx>
-#include <Standard_Failure.hxx>
-#include <gp_Ax2.hxx>
-
#include <limits>
return n;
}
-namespace
-{
- /*!
- * \brief Vertex of a polygon. Together with 2 neighbor Vertices represents a triangle
- */
- struct PolyVertex
- {
- SMESH_TNodeXYZ _nxyz;
- gp_XY _xy;
- PolyVertex* _prev;
- PolyVertex* _next;
-
- void SetNodeAndNext( const SMDS_MeshNode* n, PolyVertex& v )
- {
- _nxyz.Set( n );
- _next = &v;
- v._prev = this;
- }
- PolyVertex* Delete()
- {
- _prev->_next = _next;
- _next->_prev = _prev;
- return _next;
- }
- void GetTriaNodes( const SMDS_MeshNode** nodes) const
- {
- nodes[0] = _prev->_nxyz._node;
- nodes[1] = this->_nxyz._node;
- nodes[2] = _next->_nxyz._node;
- }
-
- inline static double Area( const PolyVertex* v0, const PolyVertex* v1, const PolyVertex* v2 )
- {
- gp_XY vPrev = v0->_xy - v1->_xy;
- gp_XY vNext = v2->_xy - v1->_xy;
- return vNext ^ vPrev;
- }
- double TriaArea() const { return Area( _prev, this, _next ); }
-
- bool IsInsideTria( const PolyVertex* v )
- {
- gp_XY p = _prev->_xy - v->_xy;
- gp_XY t = this->_xy - v->_xy;
- gp_XY n = _next->_xy - v->_xy;
- const double tol = -1e-12;
- return (( p ^ t ) >= tol &&
- ( t ^ n ) >= tol &&
- ( n ^ p ) >= tol );
- // return ( Area( _prev, this, v ) > 0 &&
- // Area( this, _next, v ) > 0 &&
- // Area( _next, _prev, v ) > 0 );
- }
- };
-
- //================================================================================
- /*!
- * \brief Triangulate a polygon. Assure correct orientation for concave polygons
- */
- //================================================================================
-
- bool triangulate( std::vector< const SMDS_MeshNode*>& nodes, const size_t nbNodes )
- {
- // connect nodes into a ring
- std::vector< PolyVertex > pv( nbNodes );
- for ( size_t i = 1; i < nbNodes; ++i )
- pv[i-1].SetNodeAndNext( nodes[i-1], pv[i] );
- pv[ nbNodes-1 ].SetNodeAndNext( nodes[ nbNodes-1 ], pv[0] );
-
- // get a polygon normal
- gp_XYZ normal(0,0,0), p0,v01,v02;
- p0 = pv[0]._nxyz;
- v01 = pv[1]._nxyz - p0;
- for ( size_t i = 2; i < nbNodes; ++i )
- {
- v02 = pv[i]._nxyz - p0;
- normal += v01 ^ v02;
- v01 = v02;
- }
- // project nodes to the found plane
- gp_Ax2 axes;
- try {
- axes = gp_Ax2( p0, normal, v01 );
- }
- catch ( Standard_Failure ) {
- return false;
- }
- for ( size_t i = 0; i < nbNodes; ++i )
- {
- gp_XYZ p = pv[i]._nxyz - p0;
- pv[i]._xy.SetX( axes.XDirection().XYZ() * p );
- pv[i]._xy.SetY( axes.YDirection().XYZ() * p );
- }
-
- // in a loop, find triangles with positive area and having no vertices inside
- int iN = 0, nbTria = nbNodes - 2;
- nodes.reserve( nbTria * 3 );
- const double minArea = 1e-6;
- PolyVertex* v = &pv[0], *vi;
- int nbVertices = nbNodes, nbBadTria = 0, isGoodTria;
- while ( nbBadTria < nbVertices )
- {
- if (( isGoodTria = v->TriaArea() > minArea ))
- {
- for ( vi = v->_next->_next;
- vi != v->_prev;
- vi = vi->_next )
- {
- if ( v->IsInsideTria( vi ))
- break;
- }
- isGoodTria = ( vi == v->_prev );
- }
- if ( isGoodTria )
- {
- v->GetTriaNodes( &nodes[ iN ] );
- iN += 3;
- v = v->Delete();
- if ( --nbVertices == 3 )
- {
- // last triangle remains
- v->GetTriaNodes( &nodes[ iN ] );
- return true;
- }
- nbBadTria = 0;
- }
- else
- {
- v = v->_next;
- ++nbBadTria;
- }
- }
-
- // the polygon is invalid; add triangles with positive area
- nbBadTria = 0;
- while ( nbBadTria < nbVertices )
- {
- isGoodTria = v->TriaArea() > minArea;
- if ( isGoodTria )
- {
- v->GetTriaNodes( &nodes[ iN ] );
- iN += 3;
- v = v->Delete();
- if ( --nbVertices == 3 )
- {
- // last triangle remains
- v->GetTriaNodes( &nodes[ iN ] );
- return true;
- }
- nbBadTria = 0;
- }
- else
- {
- v = v->_next;
- ++nbBadTria;
- }
- }
-
- // add all the rest triangles
- while ( nbVertices >= 3 )
- {
- v->GetTriaNodes( &nodes[ iN ] );
- iN += 3;
- v = v->Delete();
- --nbVertices;
- }
-
- return true;
-
- } // triangulate()
-} // namespace
-
-//================================================================================
-/*!
- * \brief Return nb triangles in a decomposed mesh face
- * \retval int - number of triangles
- */
-//================================================================================
-
-static int getNbTriangles( const SMDS_MeshElement* face)
-{
- // WARNING: counting triangles must be coherent with getTriangles()
- switch ( face->GetEntityType() )
- {
- case SMDSEntity_BiQuad_Triangle:
- case SMDSEntity_BiQuad_Quadrangle:
- return face->NbNodes() - 1;
- // case SMDSEntity_Triangle:
- // case SMDSEntity_Quad_Triangle:
- // case SMDSEntity_Quadrangle:
- // case SMDSEntity_Quad_Quadrangle:
- // case SMDSEntity_Polygon:
- // case SMDSEntity_Quad_Polygon:
- default:
- return face->NbNodes() - 2;
- }
- return 0;
-}
-
-//================================================================================
-/*!
- * \brief Decompose a mesh face into triangles
- * \retval int - number of triangles
- */
-//================================================================================
-
-static int getTriangles( const SMDS_MeshElement* face,
- std::vector< const SMDS_MeshNode*>& nodes)
-{
- // WARNING: decomposing into triangles must be coherent with getNbTriangles()
- int nbTria, i = 0, nbNodes = face->NbNodes();
- SMDS_NodeIteratorPtr nIt = face->interlacedNodesIterator();
- nodes.resize( nbNodes * 3 );
- nodes[ i++ ] = nIt->next();
- nodes[ i++ ] = nIt->next();
-
- const SMDSAbs_EntityType type = face->GetEntityType();
- switch ( type )
- {
- case SMDSEntity_BiQuad_Triangle:
- case SMDSEntity_BiQuad_Quadrangle:
- nbTria = ( type == SMDSEntity_BiQuad_Triangle ) ? 6 : 8;
- nodes[ i++ ] = face->GetNode( nbTria );
- for ( i = 3; i < 3*(nbTria-1); i += 3 )
- {
- nodes[ i+0 ] = nodes[ i-2 ];
- nodes[ i+1 ] = nIt->next();
- nodes[ i+2 ] = nodes[ 2 ];
- }
- nodes[ i+0 ] = nodes[ i-2 ];
- nodes[ i+1 ] = nodes[ 0 ];
- nodes[ i+2 ] = nodes[ 2 ];
- break;
- case SMDSEntity_Triangle:
- nbTria = 1;
- nodes[ i++ ] = nIt->next();
- break;
- default:
- // case SMDSEntity_Quad_Triangle:
- // case SMDSEntity_Quadrangle:
- // case SMDSEntity_Quad_Quadrangle:
- // case SMDSEntity_Polygon:
- // case SMDSEntity_Quad_Polygon:
- nbTria = nbNodes - 2;
- while ( nIt->more() )
- nodes[ i++ ] = nIt->next();
-
- if ( !triangulate( nodes, nbNodes ))
- {
- nIt = face->interlacedNodesIterator();
- nodes[ 0 ] = nIt->next();
- nodes[ 1 ] = nIt->next();
- nodes[ 2 ] = nIt->next();
- for ( i = 3; i < 3*nbTria; i += 3 )
- {
- nodes[ i+0 ] = nodes[ 0 ];
- nodes[ i+1 ] = nodes[ i-1 ];
- nodes[ i+2 ] = nIt->next();
- }
- }
- break;
- }
- return nbTria;
-}
-
// private methods
Driver_Mesh::Status DriverSTL_W_SMDS_Mesh::writeAscii() const
char sval[128];
std::vector< const SMDS_MeshNode* > triaNodes;
+ SMESH_MeshAlgos::Triangulate triangulator;
+
SMDS_ElemIteratorPtr itFaces = getFaces();
while ( itFaces->more() )
{
const SMDS_MeshElement* aFace = itFaces->next();
- int nbTria = getTriangles( aFace, triaNodes );
+ int nbTria = triangulator.GetTriangles( aFace, triaNodes );
for ( int iT = 0, iN = 0; iT < nbTria; ++iT )
{
SMESH_File aFile( myFile );
aFile.openForWriting();
+ SMESH_MeshAlgos::Triangulate triangulator;
+
// we first count the number of triangles
int nbTri = myNbVolumeTrias;
{
SMDS_FaceIteratorPtr itFaces = myMesh->facesIterator();
while ( itFaces->more() ) {
const SMDS_MeshElement* aFace = itFaces->next();
- nbTri += getNbTriangles( aFace );
+ nbTri += triangulator.GetNbTriangles( aFace );
}
}
std::string sval( LABEL_SIZE, ' ' );
while ( itFaces->more() )
{
const SMDS_MeshElement* aFace = itFaces->next();
- int nbTria = getTriangles( aFace, triaNodes );
+ int nbTria = triangulator.GetTriangles( aFace, triaNodes );
for ( int iT = 0, iN = 0; iT < nbTria; ++iT )
{
virtual void Renumber (const bool isNodes, const int startID = 1, const int deltaID = 1);
// Renumber all nodes or elements.
virtual void compactMesh();
+ virtual void CompactMesh() { compactMesh(); }
const SMDS_MeshNode *FindNode(int idnode) const;
const SMDS_MeshNode *FindNodeVtk(int idnode) const;
protected:
virtual SMDS_ElemIteratorPtr elementsIterator (SMDSAbs_ElementType type) const;
- private:
std::vector<const SMDS_MeshNode *> myNodes;
};
// constructor to use as return from begin()
SMDS_StdIterator( PtrSMDSIterator pItr )
- : _value( pItr->more() ? (VALUE)(pItr->next()) : 0 ), _piterator(pItr)
+ : _value( pItr->more() ? VALUE(pItr->next()) : VALUE(0) ), _piterator(pItr)
{}
// constructor to use as return from end()
SMDS_StdIterator(): _value( 0 )
// Step to the next one
_Self&
operator++()
- { _value = _piterator->more() ? VALUE( _piterator->next()) : 0; return *this; }
+ { _value = _piterator->more() ? VALUE( _piterator->next()) : VALUE(0); return *this; }
// Step to the next one
_Self
operator++(int)
- { _Self res = *this; _value = _piterator->more() ? VALUE( _piterator->next()) : 0; return res; }
+ { _Self res = *this; _value = _piterator->more() ? VALUE( _piterator->next()) : VALUE(0); return res; }
// Test of end
bool
using namespace std;
using namespace SMESH::Controls;
-namespace
-{
- template < class ELEM_SET >
- SMDS_ElemIteratorPtr elemSetIterator( const ELEM_SET& elements )
- {
- typedef SMDS_SetIterator
- < SMDS_pElement, typename ELEM_SET::const_iterator> TSetIterator;
- return SMDS_ElemIteratorPtr( new TSetIterator( elements.begin(), elements.end() ));
- }
-}
-
//=======================================================================
//function : SMESH_MeshEditor
//purpose :
void SMESH_MeshEditor::ClearLastCreated()
{
- myLastCreatedNodes.Clear();
- myLastCreatedElems.Clear();
+ SMESHUtils::FreeVector( myLastCreatedElems );
+ SMESHUtils::FreeVector( myLastCreatedNodes );
}
//================================================================================
default:;
}
- if ( e ) myLastCreatedElems.Append( e );
+ if ( e ) myLastCreatedElems.push_back( e );
return e;
}
int SMESH_MeshEditor::Remove (const list< int >& theIDs,
const bool isNodes )
{
- myLastCreatedElems.Clear();
- myLastCreatedNodes.Clear();
+ ClearLastCreated();
SMESHDS_Mesh* aMesh = GetMeshDS();
set< SMESH_subMesh *> smmap;
}
else
{
- elemIt = elemSetIterator( elements );
+ elemIt = SMESHUtils::elemSetIterator( elements );
}
while ( elemIt->more() )
SMDS_ElemIteratorPtr it0D = n->GetInverseElementIterator( SMDSAbs_0DElement );
if ( duplicateElements || !it0D->more() )
{
- myLastCreatedElems.Append( GetMeshDS()->Add0DElement( n ));
- all0DElems.insert( myLastCreatedElems.Last() );
+ myLastCreatedElems.push_back( GetMeshDS()->Add0DElement( n ));
+ all0DElems.insert( myLastCreatedElems.back() );
}
while ( it0D->more() )
all0DElems.insert( it0D->next() );
int SMESH_MeshEditor::FindShape (const SMDS_MeshElement * theElem)
{
- myLastCreatedElems.Clear();
- myLastCreatedNodes.Clear();
+ ClearLastCreated();
SMESHDS_Mesh * aMesh = GetMeshDS();
if ( aMesh->ShapeToMesh().IsNull() )
bool SMESH_MeshEditor::InverseDiag (const SMDS_MeshElement * theTria1,
const SMDS_MeshElement * theTria2 )
{
- myLastCreatedElems.Clear();
- myLastCreatedNodes.Clear();
+ ClearLastCreated();
if (!theTria1 || !theTria2)
return false;
bool SMESH_MeshEditor::InverseDiag (const SMDS_MeshNode * theNode1,
const SMDS_MeshNode * theNode2)
{
- myLastCreatedElems.Clear();
- myLastCreatedNodes.Clear();
+ ClearLastCreated();
const SMDS_MeshElement *tr1, *tr2;
if ( !findTriangles( theNode1, theNode2, tr1, tr2 ))
bool SMESH_MeshEditor::DeleteDiag (const SMDS_MeshNode * theNode1,
const SMDS_MeshNode * theNode2)
{
- myLastCreatedElems.Clear();
- myLastCreatedNodes.Clear();
+ ClearLastCreated();
const SMDS_MeshElement *tr1, *tr2;
if ( !findTriangles( theNode1, theNode2, tr1, tr2 ))
const SMDS_MeshElement* newElem = 0;
newElem = aMesh->AddFace( aNodes[0], aNodes[1], aNodes[2], aNodes[3] );
- myLastCreatedElems.Append(newElem);
+ myLastCreatedElems.push_back(newElem);
AddToSameGroups( newElem, tr1, aMesh );
int aShapeId = tr1->getshapeId();
if ( aShapeId )
- {
- aMesh->SetMeshElementOnShape( newElem, aShapeId );
- }
+ {
+ aMesh->SetMeshElementOnShape( newElem, aShapeId );
+ }
aMesh->RemoveElement( tr1 );
aMesh->RemoveElement( tr2 );
const SMDS_MeshElement* newElem = 0;
newElem = aMesh->AddFace( aNodes[0], aNodes[1], aNodes[2], aNodes[3],
aNodes[4], aNodes[5], aNodes[6], aNodes[7]);
- myLastCreatedElems.Append(newElem);
+ myLastCreatedElems.push_back(newElem);
AddToSameGroups( newElem, tr1, aMesh );
int aShapeId = tr1->getshapeId();
if ( aShapeId )
- {
- aMesh->SetMeshElementOnShape( newElem, aShapeId );
- }
+ {
+ aMesh->SetMeshElementOnShape( newElem, aShapeId );
+ }
aMesh->RemoveElement( tr1 );
aMesh->RemoveElement( tr2 );
bool SMESH_MeshEditor::Reorient (const SMDS_MeshElement * theElem)
{
- myLastCreatedElems.Clear();
- myLastCreatedNodes.Clear();
+ ClearLastCreated();
if (!theElem)
return false;
if ( theFaces.empty() )
faceIt = GetMeshDS()->elementsIterator( SMDSAbs_Face );
else
- faceIt = elemSetIterator( theFaces );
+ faceIt = SMESHUtils::elemSetIterator( theFaces );
vector< const SMDS_MeshNode* > faceNodes;
TIDSortedElemSet checkedVolumes;
bool SMESH_MeshEditor::QuadToTri (TIDSortedElemSet & theElems,
SMESH::Controls::NumericalFunctorPtr theCrit)
{
- myLastCreatedElems.Clear();
- myLastCreatedNodes.Clear();
+ ClearLastCreated();
if ( !theCrit.get() )
return false;
- SMESHDS_Mesh * aMesh = GetMeshDS();
-
+ SMESHDS_Mesh * aMesh = GetMeshDS();
Handle(Geom_Surface) surface;
SMESH_MesherHelper helper( *GetMesh() );
+ myLastCreatedElems.reserve( theElems.size() * 2 );
+
TIDSortedElemSet::iterator itElem;
for ( itElem = theElems.begin(); itElem != theElems.end(); itElem++ )
{
// care of a new element
- myLastCreatedElems.Append(newElem1);
- myLastCreatedElems.Append(newElem2);
+ myLastCreatedElems.push_back(newElem1);
+ myLastCreatedElems.push_back(newElem2);
AddToSameGroups( newElem1, elem, aMesh );
AddToSameGroups( newElem2, elem, aMesh );
void SMESH_MeshEditor::QuadTo4Tri (TIDSortedElemSet & theElems)
{
- myLastCreatedElems.Clear();
- myLastCreatedNodes.Clear();
+ ClearLastCreated();
+ myLastCreatedElems.reserve( theElems.size() * 4 );
SMESH_MesherHelper helper( *GetMesh() );
helper.SetElementsOnShape( true );
SMDS_ElemIteratorPtr faceIt;
if ( theElems.empty() ) faceIt = GetMeshDS()->elementsIterator(SMDSAbs_Face);
- else faceIt = elemSetIterator( theElems );
+ else faceIt = SMESHUtils::elemSetIterator( theElems );
bool checkUV;
gp_XY uv [9]; uv[8] = gp_XY(0,0);
nCentral = helper.AddNode( xyz[8].X(), xyz[8].Y(), xyz[8].Z(), /*id=*/0,
uv[8].X(), uv[8].Y() );
- myLastCreatedNodes.Append( nCentral );
+ myLastCreatedNodes.push_back( nCentral );
}
// create 4 triangles
nodes[(i+1)%4],
nCentral );
ReplaceElemInGroups( tria, quad, GetMeshDS() );
- myLastCreatedElems.Append( tria );
+ myLastCreatedElems.push_back( tria );
}
}
}
int SMESH_MeshEditor::BestSplit (const SMDS_MeshElement* theQuad,
SMESH::Controls::NumericalFunctorPtr theCrit)
{
- myLastCreatedElems.Clear();
- myLastCreatedNodes.Clear();
+ ClearLastCreated();
if (!theCrit.get())
return -1;
volTool.GetBaryCenter( bc[0], bc[1], bc[2] );
SMDS_MeshNode* gcNode = helper.AddNode( bc[0], bc[1], bc[2] );
nodes.push_back( gcNode );
- newNodes.Append( gcNode );
+ newNodes.push_back( gcNode );
}
if ( !splitMethod._faceBaryNode.empty() )
{
if ( !f_n->second )
{
volTool.GetFaceBaryCenter( iF_n->first, bc[0], bc[1], bc[2] );
- newNodes.Append( f_n->second = helper.AddNode( bc[0], bc[1], bc[2] ));
+ newNodes.push_back( f_n->second = helper.AddNode( bc[0], bc[1], bc[2] ));
}
nodes.push_back( iF_n->second = f_n->second );
}
const int* volConn = splitMethod._connectivity;
if ( splitMethod._nbCorners == 4 ) // tetra
for ( int i = 0; i < splitMethod._nbSplits; ++i, volConn += splitMethod._nbCorners )
- newElems.Append( splitVols[ i ] = helper.AddVolume( nodes[ volConn[0] ],
- nodes[ volConn[1] ],
- nodes[ volConn[2] ],
- nodes[ volConn[3] ]));
+ newElems.push_back( splitVols[ i ] = helper.AddVolume( nodes[ volConn[0] ],
+ nodes[ volConn[1] ],
+ nodes[ volConn[2] ],
+ nodes[ volConn[3] ]));
else // prisms
for ( int i = 0; i < splitMethod._nbSplits; ++i, volConn += splitMethod._nbCorners )
- newElems.Append( splitVols[ i ] = helper.AddVolume( nodes[ volConn[0] ],
- nodes[ volConn[1] ],
- nodes[ volConn[2] ],
- nodes[ volConn[3] ],
- nodes[ volConn[4] ],
- nodes[ volConn[5] ]));
+ newElems.push_back( splitVols[ i ] = helper.AddVolume( nodes[ volConn[0] ],
+ nodes[ volConn[1] ],
+ nodes[ volConn[2] ],
+ nodes[ volConn[3] ],
+ nodes[ volConn[4] ],
+ nodes[ volConn[5] ]));
ReplaceElemInGroups( elem, splitVols, GetMeshDS() );
gp_XY uv( 1e100, 1e100 );
double distXYZ[4];
if ( !fHelper.CheckNodeUV( TopoDS::Face( s ), baryNode,
- uv, /*tol=*/1e-7, /*force=*/true, distXYZ ) &&
+ uv, /*tol=*/1e-7, /*force=*/true, distXYZ ) &&
uv.X() < 1e100 )
{
// node is too far from the surface
if ( !triangles[ i ]) continue;
if ( fSubMesh )
fSubMesh->AddElement( triangles[ i ]);
- newElems.Append( triangles[ i ]);
+ newElems.push_back( triangles[ i ]);
}
ReplaceElemInGroups( face, triangles, GetMeshDS() );
GetMeshDS()->RemoveFreeElement( face, fSubMesh, /*fromGroups=*/false );
const gp_Ax1& theFacetNormal,
TFacetOfElem & theFacets)
{
- #define THIS_METHOD "SMESH_MeshEditor::GetHexaFacetsToSplit(): "
+#define THIS_METHOD "SMESH_MeshEditor::GetHexaFacetsToSplit(): "
// Find a hexa closest to the location of theFacetNormal
bool SMESH_MeshEditor::QuadToTri (TIDSortedElemSet & theElems,
const bool the13Diag)
{
- myLastCreatedElems.Clear();
- myLastCreatedNodes.Clear();
-
- SMESHDS_Mesh * aMesh = GetMeshDS();
+ ClearLastCreated();
+ myLastCreatedElems.reserve( theElems.size() * 2 );
+ SMESHDS_Mesh * aMesh = GetMeshDS();
Handle(Geom_Surface) surface;
SMESH_MesherHelper helper( *GetMesh() );
newElem1 = aMesh->AddFace( aNodes[3], aNodes[0], aNodes[1] );
newElem2 = aMesh->AddFace( aNodes[3], aNodes[1], aNodes[2] );
}
- myLastCreatedElems.Append(newElem1);
- myLastCreatedElems.Append(newElem2);
+ myLastCreatedElems.push_back(newElem1);
+ myLastCreatedElems.push_back(newElem2);
// put a new triangle on the same shape and add to the same groups
if ( aShapeId )
{
centrNode = helper.GetCentralNode( aNodes[0], aNodes[1], aNodes[2], aNodes[3],
aNodes[4], aNodes[5], aNodes[6], aNodes[7],
surface.IsNull() );
- myLastCreatedNodes.Append(centrNode);
+ myLastCreatedNodes.push_back(centrNode);
}
// create a new element
newElem2 = aMesh->AddFace(aNodes[3], aNodes[1], aNodes[2],
centrNode, aNodes[5], aNodes[6] );
}
- myLastCreatedElems.Append(newElem1);
- myLastCreatedElems.Append(newElem2);
+ myLastCreatedElems.push_back(newElem1);
+ myLastCreatedElems.push_back(newElem2);
// put a new triangle on the same shape and add to the same groups
if ( aShapeId )
{
SMESH::Controls::NumericalFunctorPtr theCrit,
const double theMaxAngle)
{
- myLastCreatedElems.Clear();
- myLastCreatedNodes.Clear();
+ ClearLastCreated();
+ myLastCreatedElems.reserve( theElems.size() / 2 );
if ( !theCrit.get() )
return false;
{
const SMDS_MeshElement* newElem = 0;
newElem = aMesh->AddFace(n12[0], n12[1], n12[2], n12[3] );
- myLastCreatedElems.Append(newElem);
+ myLastCreatedElems.push_back(newElem);
AddToSameGroups( newElem, tr1, aMesh );
int aShapeId = tr1->getshapeId();
if ( aShapeId )
else
newElem = aMesh->AddFace(aNodes[0], aNodes[1], aNodes[2], aNodes[3],
aNodes[4], aNodes[5], aNodes[6], aNodes[7]);
- myLastCreatedElems.Append(newElem);
+ myLastCreatedElems.push_back(newElem);
AddToSameGroups( newElem, tr1, aMesh );
int aShapeId = tr1->getshapeId();
if ( aShapeId )
if ( tr1->NbNodes() == 3 ) {
const SMDS_MeshElement* newElem = 0;
newElem = aMesh->AddFace(n13[0], n13[1], n13[2], n13[3] );
- myLastCreatedElems.Append(newElem);
+ myLastCreatedElems.push_back(newElem);
AddToSameGroups( newElem, tr1, aMesh );
int aShapeId = tr1->getshapeId();
if ( aShapeId )
else
newElem = aMesh->AddFace(aNodes[0], aNodes[1], aNodes[2], aNodes[3],
aNodes[4], aNodes[5], aNodes[6], aNodes[7]);
- myLastCreatedElems.Append(newElem);
+ myLastCreatedElems.push_back(newElem);
AddToSameGroups( newElem, tr1, aMesh );
int aShapeId = tr1->getshapeId();
if ( aShapeId )
return true;
}
-
-/*#define DUMPSO(txt) \
-// cout << txt << endl;
-//=============================================================================
-//
-//
-//
-//=============================================================================
-static void swap( int i1, int i2, int idNodes[], gp_Pnt P[] )
-{
-if ( i1 == i2 )
-return;
-int tmp = idNodes[ i1 ];
-idNodes[ i1 ] = idNodes[ i2 ];
-idNodes[ i2 ] = tmp;
-gp_Pnt Ptmp = P[ i1 ];
-P[ i1 ] = P[ i2 ];
-P[ i2 ] = Ptmp;
-DUMPSO( i1 << "(" << idNodes[ i2 ] << ") <-> " << i2 << "(" << idNodes[ i1 ] << ")");
-}
-
-//=======================================================================
-//function : SortQuadNodes
-//purpose : Set 4 nodes of a quadrangle face in a good order.
-// Swap 1<->2 or 2<->3 nodes and correspondingly return
-// 1 or 2 else 0.
-//=======================================================================
-
-int SMESH_MeshEditor::SortQuadNodes (const SMDS_Mesh * theMesh,
-int idNodes[] )
-{
- gp_Pnt P[4];
- int i;
- for ( i = 0; i < 4; i++ ) {
- const SMDS_MeshNode *n = theMesh->FindNode( idNodes[i] );
- if ( !n ) return 0;
- P[ i ].SetCoord( n->X(), n->Y(), n->Z() );
- }
-
- gp_Vec V1(P[0], P[1]);
- gp_Vec V2(P[0], P[2]);
- gp_Vec V3(P[0], P[3]);
-
- gp_Vec Cross1 = V1 ^ V2;
- gp_Vec Cross2 = V2 ^ V3;
-
- i = 0;
- if (Cross1.Dot(Cross2) < 0)
- {
- Cross1 = V2 ^ V1;
- Cross2 = V1 ^ V3;
-
- if (Cross1.Dot(Cross2) < 0)
- i = 2;
- else
- i = 1;
- swap ( i, i + 1, idNodes, P );
-
- // for ( int ii = 0; ii < 4; ii++ ) {
- // const SMDS_MeshNode *n = theMesh->FindNode( idNodes[ii] );
- // DUMPSO( ii << "(" << idNodes[ii] <<") : "<<n->X()<<" "<<n->Y()<<" "<<n->Z());
- // }
- }
- return i;
-}
-
-//=======================================================================
-//function : SortHexaNodes
-//purpose : Set 8 nodes of a hexahedron in a good order.
-// Return success status
-//=======================================================================
-
-bool SMESH_MeshEditor::SortHexaNodes (const SMDS_Mesh * theMesh,
- int idNodes[] )
-{
- gp_Pnt P[8];
- int i;
- DUMPSO( "INPUT: ========================================");
- for ( i = 0; i < 8; i++ ) {
- const SMDS_MeshNode *n = theMesh->FindNode( idNodes[i] );
- if ( !n ) return false;
- P[ i ].SetCoord( n->X(), n->Y(), n->Z() );
- DUMPSO( i << "(" << idNodes[i] <<") : "<<n->X()<<" "<<n->Y()<<" "<<n->Z());
- }
- DUMPSO( "========================================");
-
-
- set<int> faceNodes; // ids of bottom face nodes, to be found
- set<int> checkedId1; // ids of tried 2-nd nodes
- Standard_Real leastDist = DBL_MAX; // dist of the 4-th node from 123 plane
- const Standard_Real tol = 1.e-6; // tolerance to find nodes in plane
- int iMin, iLoop1 = 0;
-
- // Loop to try the 2-nd nodes
-
- while ( leastDist > DBL_MIN && ++iLoop1 < 8 )
- {
- // Find not checked 2-nd node
- for ( i = 1; i < 8; i++ )
- if ( checkedId1.find( idNodes[i] ) == checkedId1.end() ) {
- int id1 = idNodes[i];
- swap ( 1, i, idNodes, P );
- checkedId1.insert ( id1 );
- break;
- }
-
- // Find the 3-d node so that 1-2-3 triangle to be on a hexa face,
- // ie that all but meybe one (id3 which is on the same face) nodes
- // lay on the same side from the triangle plane.
-
- bool manyInPlane = false; // more than 4 nodes lay in plane
- int iLoop2 = 0;
- while ( ++iLoop2 < 6 ) {
-
- // get 1-2-3 plane coeffs
- Standard_Real A, B, C, D;
- gp_Vec N = gp_Vec (P[0], P[1]).Crossed( gp_Vec (P[0], P[2]) );
- if ( N.SquareMagnitude() > gp::Resolution() )
- {
- gp_Pln pln ( P[0], N );
- pln.Coefficients( A, B, C, D );
-
- // find the node (iMin) closest to pln
- Standard_Real dist[ 8 ], minDist = DBL_MAX;
- set<int> idInPln;
- for ( i = 3; i < 8; i++ ) {
- dist[i] = A * P[i].X() + B * P[i].Y() + C * P[i].Z() + D;
- if ( fabs( dist[i] ) < minDist ) {
- minDist = fabs( dist[i] );
- iMin = i;
- }
- if ( fabs( dist[i] ) <= tol )
- idInPln.insert( idNodes[i] );
- }
-
- // there should not be more than 4 nodes in bottom plane
- if ( idInPln.size() > 1 )
- {
- DUMPSO( "### idInPln.size() = " << idInPln.size());
- // idInPlane does not contain the first 3 nodes
- if ( manyInPlane || idInPln.size() == 5)
- return false; // all nodes in one plane
- manyInPlane = true;
-
- // set the 1-st node to be not in plane
- for ( i = 3; i < 8; i++ ) {
- if ( idInPln.find( idNodes[ i ] ) == idInPln.end() ) {
- DUMPSO( "### Reset 0-th node");
- swap( 0, i, idNodes, P );
- break;
- }
- }
-
- // reset to re-check second nodes
- leastDist = DBL_MAX;
- faceNodes.clear();
- checkedId1.clear();
- iLoop1 = 0;
- break; // from iLoop2;
- }
-
- // check that the other 4 nodes are on the same side
- bool sameSide = true;
- bool isNeg = dist[ iMin == 3 ? 4 : 3 ] <= 0.;
- for ( i = 3; sameSide && i < 8; i++ ) {
- if ( i != iMin )
- sameSide = ( isNeg == dist[i] <= 0.);
- }
-
- // keep best solution
- if ( sameSide && minDist < leastDist ) {
- leastDist = minDist;
- faceNodes.clear();
- faceNodes.insert( idNodes[ 1 ] );
- faceNodes.insert( idNodes[ 2 ] );
- faceNodes.insert( idNodes[ iMin ] );
- DUMPSO( "loop " << iLoop2 << " id2 " << idNodes[ 1 ] << " id3 " << idNodes[ 2 ]
- << " leastDist = " << leastDist);
- if ( leastDist <= DBL_MIN )
- break;
- }
- }
-
- // set next 3-d node to check
- int iNext = 2 + iLoop2;
- if ( iNext < 8 ) {
- DUMPSO( "Try 2-nd");
- swap ( 2, iNext, idNodes, P );
- }
- } // while ( iLoop2 < 6 )
- } // iLoop1
-
- if ( faceNodes.empty() ) return false;
-
- // Put the faceNodes in proper places
- for ( i = 4; i < 8; i++ ) {
- if ( faceNodes.find( idNodes[ i ] ) != faceNodes.end() ) {
- // find a place to put
- int iTo = 1;
- while ( faceNodes.find( idNodes[ iTo ] ) != faceNodes.end() )
- iTo++;
- DUMPSO( "Set faceNodes");
- swap ( iTo, i, idNodes, P );
- }
- }
-
-
- // Set nodes of the found bottom face in good order
- DUMPSO( " Found bottom face: ");
- i = SortQuadNodes( theMesh, idNodes );
- if ( i ) {
- gp_Pnt Ptmp = P[ i ];
- P[ i ] = P[ i+1 ];
- P[ i+1 ] = Ptmp;
- }
- // else
- // for ( int ii = 0; ii < 4; ii++ ) {
- // const SMDS_MeshNode *n = theMesh->FindNode( idNodes[ii] );
- // DUMPSO( ii << "(" << idNodes[ii] <<") : "<<n->X()<<" "<<n->Y()<<" "<<n->Z());
- // }
-
- // Gravity center of the top and bottom faces
- gp_Pnt aGCb = ( P[0].XYZ() + P[1].XYZ() + P[2].XYZ() + P[3].XYZ() ) / 4.;
- gp_Pnt aGCt = ( P[4].XYZ() + P[5].XYZ() + P[6].XYZ() + P[7].XYZ() ) / 4.;
-
- // Get direction from the bottom to the top face
- gp_Vec upDir ( aGCb, aGCt );
- Standard_Real upDirSize = upDir.Magnitude();
- if ( upDirSize <= gp::Resolution() ) return false;
- upDir / upDirSize;
-
- // Assure that the bottom face normal points up
- gp_Vec Nb = gp_Vec (P[0], P[1]).Crossed( gp_Vec (P[0], P[2]) );
- Nb += gp_Vec (P[0], P[2]).Crossed( gp_Vec (P[0], P[3]) );
- if ( Nb.Dot( upDir ) < 0 ) {
- DUMPSO( "Reverse bottom face");
- swap( 1, 3, idNodes, P );
- }
-
- // Find 5-th node - the one closest to the 1-st among the last 4 nodes.
- Standard_Real minDist = DBL_MAX;
- for ( i = 4; i < 8; i++ ) {
- // projection of P[i] to the plane defined by P[0] and upDir
- gp_Pnt Pp = P[i].Translated( upDir * ( upDir.Dot( gp_Vec( P[i], P[0] ))));
- Standard_Real sqDist = P[0].SquareDistance( Pp );
- if ( sqDist < minDist ) {
- minDist = sqDist;
- iMin = i;
- }
- }
- DUMPSO( "Set 4-th");
- swap ( 4, iMin, idNodes, P );
-
- // Set nodes of the top face in good order
- DUMPSO( "Sort top face");
- i = SortQuadNodes( theMesh, &idNodes[4] );
- if ( i ) {
- i += 4;
- gp_Pnt Ptmp = P[ i ];
- P[ i ] = P[ i+1 ];
- P[ i+1 ] = Ptmp;
- }
-
- // Assure that direction of the top face normal is from the bottom face
- gp_Vec Nt = gp_Vec (P[4], P[5]).Crossed( gp_Vec (P[4], P[6]) );
- Nt += gp_Vec (P[4], P[6]).Crossed( gp_Vec (P[4], P[7]) );
- if ( Nt.Dot( upDir ) < 0 ) {
- DUMPSO( "Reverse top face");
- swap( 5, 7, idNodes, P );
- }
-
- // DUMPSO( "OUTPUT: ========================================");
- // for ( i = 0; i < 8; i++ ) {
- // float *p = ugrid->GetPoint(idNodes[i]);
- // DUMPSO( i << "(" << idNodes[i] << ") : " << p[0] << " " << p[1] << " " << p[2]);
- // }
-
- return true;
-}*/
-
//================================================================================
/*!
* \brief Return nodes linked to the given one
double theTgtAspectRatio,
const bool the2D)
{
- myLastCreatedElems.Clear();
- myLastCreatedNodes.Clear();
+ ClearLastCreated();
if ( theTgtAspectRatio < 1.0 )
theTgtAspectRatio = 1.0;
// if ( posType != SMDS_TOP_3DSPACE )
// dist2 = pNode.SquareDistance( surface->Value( newUV.X(), newUV.Y() ));
// if ( dist2 < dist1 )
- uv = newUV;
+ uv = newUV;
}
}
// store UV in the map
break;
}
case SMDSEntity_Triangle: // TRIANGLE --->
- {
- if ( nbDouble > 0 ) break;
- if ( nbSame == 0 ) // ---> pentahedron
- aNewElem = aMesh->AddVolume (prevNod[ 0 ], prevNod[ 1 ], prevNod[ 2 ],
- nextNod[ 0 ], nextNod[ 1 ], nextNod[ 2 ] );
-
- else if ( nbSame == 1 ) // ---> pyramid
- aNewElem = aMesh->AddVolume (prevNod[ iBeforeSame ], prevNod[ iAfterSame ],
- nextNod[ iAfterSame ], nextNod[ iBeforeSame ],
- nextNod[ iSameNode ]);
-
- else // 2 same nodes: ---> tetrahedron
- aNewElem = aMesh->AddVolume (prevNod[ 0 ], prevNod[ 1 ], prevNod[ 2 ],
- nextNod[ iNotSameNode ]);
- break;
- }
+ {
+ if ( nbDouble > 0 ) break;
+ if ( nbSame == 0 ) // ---> pentahedron
+ aNewElem = aMesh->AddVolume (prevNod[ 0 ], prevNod[ 1 ], prevNod[ 2 ],
+ nextNod[ 0 ], nextNod[ 1 ], nextNod[ 2 ] );
+
+ else if ( nbSame == 1 ) // ---> pyramid
+ aNewElem = aMesh->AddVolume (prevNod[ iBeforeSame ], prevNod[ iAfterSame ],
+ nextNod[ iAfterSame ], nextNod[ iBeforeSame ],
+ nextNod[ iSameNode ]);
+
+ else // 2 same nodes: ---> tetrahedron
+ aNewElem = aMesh->AddVolume (prevNod[ 0 ], prevNod[ 1 ], prevNod[ 2 ],
+ nextNod[ iNotSameNode ]);
+ break;
+ }
case SMDSEntity_Quad_Edge: // sweep quadratic EDGE --->
+ {
+ if ( nbSame == 2 )
+ return;
+ if ( nbDouble+nbSame == 2 )
{
- if ( nbSame == 2 )
- return;
- if ( nbDouble+nbSame == 2 )
- {
- if(nbSame==0) { // ---> quadratic quadrangle
- aNewElem = aMesh->AddFace(prevNod[0], prevNod[1], nextNod[1], nextNod[0],
- prevNod[2], midlNod[1], nextNod[2], midlNod[0]);
- }
- else { //(nbSame==1) // ---> quadratic triangle
- if(sames[0]==2) {
- return; // medium node on axis
- }
- else if(sames[0]==0)
- aNewElem = aMesh->AddFace(prevNod[0], prevNod[1], nextNod[1],
- prevNod[2], midlNod[1], nextNod[2] );
- else // sames[0]==1
- aNewElem = aMesh->AddFace(prevNod[0], prevNod[1], nextNod[0],
- prevNod[2], nextNod[2], midlNod[0]);
- }
+ if(nbSame==0) { // ---> quadratic quadrangle
+ aNewElem = aMesh->AddFace(prevNod[0], prevNod[1], nextNod[1], nextNod[0],
+ prevNod[2], midlNod[1], nextNod[2], midlNod[0]);
}
- else if ( nbDouble == 3 )
- {
- if ( nbSame == 0 ) { // ---> bi-quadratic quadrangle
- aNewElem = aMesh->AddFace(prevNod[0], prevNod[1], nextNod[1], nextNod[0],
- prevNod[2], midlNod[1], nextNod[2], midlNod[0], midlNod[2]);
+ else { //(nbSame==1) // ---> quadratic triangle
+ if(sames[0]==2) {
+ return; // medium node on axis
}
+ else if(sames[0]==0)
+ aNewElem = aMesh->AddFace(prevNod[0], prevNod[1], nextNod[1],
+ prevNod[2], midlNod[1], nextNod[2] );
+ else // sames[0]==1
+ aNewElem = aMesh->AddFace(prevNod[0], prevNod[1], nextNod[0],
+ prevNod[2], nextNod[2], midlNod[0]);
}
- else
- return;
- break;
}
+ else if ( nbDouble == 3 )
+ {
+ if ( nbSame == 0 ) { // ---> bi-quadratic quadrangle
+ aNewElem = aMesh->AddFace(prevNod[0], prevNod[1], nextNod[1], nextNod[0],
+ prevNod[2], midlNod[1], nextNod[2], midlNod[0], midlNod[2]);
+ }
+ }
+ else
+ return;
+ break;
+ }
case SMDSEntity_Quadrangle: { // sweep QUADRANGLE --->
if ( nbDouble > 0 ) break;
if ( aNewElem ) {
newElems.push_back( aNewElem );
- myLastCreatedElems.Append(aNewElem);
- srcElements.Append( elem );
+ myLastCreatedElems.push_back(aNewElem);
+ srcElements.push_back( elem );
}
// set new prev nodes
if ( !isQuadratic ) {
if ( !aMesh->FindEdge( vecNewNodes[ 0 ]->second.back(),
vecNewNodes[ 1 ]->second.back())) {
- myLastCreatedElems.Append(aMesh->AddEdge(vecNewNodes[ 0 ]->second.back(),
- vecNewNodes[ 1 ]->second.back()));
- srcElements.Append( elem );
+ myLastCreatedElems.push_back(aMesh->AddEdge(vecNewNodes[ 0 ]->second.back(),
+ vecNewNodes[ 1 ]->second.back()));
+ srcElements.push_back( elem );
}
}
else {
if ( !aMesh->FindEdge( vecNewNodes[ 0 ]->second.back(),
vecNewNodes[ 1 ]->second.back(),
vecNewNodes[ 2 ]->second.back())) {
- myLastCreatedElems.Append(aMesh->AddEdge(vecNewNodes[ 0 ]->second.back(),
- vecNewNodes[ 1 ]->second.back(),
- vecNewNodes[ 2 ]->second.back()));
- srcElements.Append( elem );
+ myLastCreatedElems.push_back(aMesh->AddEdge(vecNewNodes[ 0 ]->second.back(),
+ vecNewNodes[ 1 ]->second.back(),
+ vecNewNodes[ 2 ]->second.back()));
+ srcElements.push_back( elem );
}
}
}
// make a new edge and a ceiling for a new edge
const SMDS_MeshElement* edge;
if ( ! ( edge = aMesh->FindEdge( n1, n2 ))) {
- myLastCreatedElems.Append( edge = aMesh->AddEdge( n1, n2 )); // free link edge
- srcElements.Append( myLastCreatedElems.Last() );
+ myLastCreatedElems.push_back( edge = aMesh->AddEdge( n1, n2 )); // free link edge
+ srcElements.push_back( myLastCreatedElems.back() );
}
n1 = vecNewNodes[ iNode ]->second.back();
n2 = vecNewNodes[ iNext ]->second.back();
if ( !aMesh->FindEdge( n1, n2 )) {
- myLastCreatedElems.Append(aMesh->AddEdge( n1, n2 )); // new edge ceiling
- srcElements.Append( edge );
+ myLastCreatedElems.push_back(aMesh->AddEdge( n1, n2 )); // new edge ceiling
+ srcElements.push_back( edge );
}
}
}
// make an edge and a ceiling for a new edge
// find medium node
if ( !aMesh->FindEdge( n1, n2, n3 )) {
- myLastCreatedElems.Append(aMesh->AddEdge( n1, n2, n3 )); // free link edge
- srcElements.Append( elem );
+ myLastCreatedElems.push_back(aMesh->AddEdge( n1, n2, n3 )); // free link edge
+ srcElements.push_back( elem );
}
n1 = vecNewNodes[ iNode ]->second.back();
n2 = vecNewNodes[ iNext ]->second.back();
n3 = vecNewNodes[ iNode+nbn ]->second.back();
if ( !aMesh->FindEdge( n1, n2, n3 )) {
- myLastCreatedElems.Append(aMesh->AddEdge( n1, n2, n3 )); // ceiling edge
- srcElements.Append( elem );
+ myLastCreatedElems.push_back(aMesh->AddEdge( n1, n2, n3 )); // ceiling edge
+ srcElements.push_back( elem );
}
}
}
if ( f )
aMesh->ChangeElementNodes( f, &newOrder[0], nbn );
else
- myLastCreatedElems.Append(aMesh->AddFace( newOrder[ 0 ], newOrder[ 1 ],
- newOrder[ 2 ] ));
+ myLastCreatedElems.push_back(aMesh->AddFace( newOrder[ 0 ], newOrder[ 1 ],
+ newOrder[ 2 ] ));
}
}
else if ( nbn == 4 ) ///// quadrangle
if ( f )
aMesh->ChangeElementNodes( f, &newOrder[0], nbn );
else
- myLastCreatedElems.Append(aMesh->AddFace( newOrder[ 0 ], newOrder[ 1 ],
- newOrder[ 2 ], newOrder[ 3 ]));
+ myLastCreatedElems.push_back(aMesh->AddFace( newOrder[ 0 ], newOrder[ 1 ],
+ newOrder[ 2 ], newOrder[ 3 ]));
}
}
else if ( nbn == 6 && isQuadratic ) /////// quadratic triangle
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 ] ));
+ myLastCreatedElems.push_back(aMesh->AddFace( newOrder[ 0 ],
+ newOrder[ 1 ],
+ newOrder[ 2 ],
+ newOrder[ 3 ],
+ newOrder[ 4 ],
+ newOrder[ 5 ] ));
}
}
else if ( nbn == 8 && isQuadratic ) /////// quadratic quadrangle
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 ]));
+ myLastCreatedElems.push_back(aMesh->AddFace(newOrder[ 0 ], newOrder[ 1 ],
+ newOrder[ 2 ], newOrder[ 3 ],
+ newOrder[ 4 ], newOrder[ 5 ],
+ newOrder[ 6 ], newOrder[ 7 ]));
}
}
else if ( nbn == 9 && isQuadratic ) /////// bi-quadratic quadrangle
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 ],
- newOrder[ 8 ]));
+ myLastCreatedElems.push_back(aMesh->AddFace(newOrder[ 0 ], newOrder[ 1 ],
+ newOrder[ 2 ], newOrder[ 3 ],
+ newOrder[ 4 ], newOrder[ 5 ],
+ newOrder[ 6 ], newOrder[ 7 ],
+ newOrder[ 8 ]));
}
}
else //////// polygon
}
}
- while ( srcElements.Length() < myLastCreatedElems.Length() )
- srcElements.Append( *srcEdge );
+ while ( srcElements.size() < myLastCreatedElems.size() )
+ srcElements.push_back( *srcEdge );
} // loop on free faces
AddElement( nodeVec, anyFace.Init( elem ));
- while ( srcElements.Length() < myLastCreatedElems.Length() )
- srcElements.Append( elem );
+ while ( srcElements.size() < myLastCreatedElems.size() )
+ srcElements.push_back( elem );
}
}
} // loop on swept elements
const bool theMakeGroups,
const bool theMakeWalls)
{
- myLastCreatedElems.Clear();
- myLastCreatedNodes.Clear();
+ ClearLastCreated();
+
+ setElemsFirst( theElemSets );
+ myLastCreatedElems.reserve( theElemSets[0].size() * theNbSteps );
+ myLastCreatedNodes.reserve( theElemSets[1].size() * theNbSteps );
// source elements for each generated one
SMESH_SequenceOfElemPtr srcElems, srcNodes;
+ srcElems.reserve( theElemSets[0].size() );
+ srcNodes.reserve( theElemSets[1].size() );
gp_Trsf aTrsf;
aTrsf.SetRotation( theAxis, theAngle );
myMesh->NbFaces(ORDER_QUADRATIC) +
myMesh->NbVolumes(ORDER_QUADRATIC) );
// loop on theElemSets
- setElemsFirst( theElemSets );
TIDSortedElemSet::iterator itElem;
for ( int is2ndSet = 0; is2ndSet < 2; ++is2ndSet )
{
{
aTrsf2.Transforms( coord[0], coord[1], coord[2] );
newNode = aMesh->AddNode( coord[0], coord[1], coord[2] );
- myLastCreatedNodes.Append(newNode);
- srcNodes.Append( node );
+ myLastCreatedNodes.push_back(newNode);
+ srcNodes.push_back( node );
listNewNodes.push_back( newNode );
aTrsf2.Transforms( coord[0], coord[1], coord[2] );
}
}
// create a corner node
newNode = aMesh->AddNode( coord[0], coord[1], coord[2] );
- myLastCreatedNodes.Append(newNode);
- srcNodes.Append( node );
+ myLastCreatedNodes.push_back(newNode);
+ srcNodes.push_back( node );
listNewNodes.push_back( newNode );
}
else {
P1 += myDir.XYZ() * nextStep();
// try to search in sequence of existing nodes
- // if myNodes.Length()>0 we 'nave to use given sequence
+ // if myNodes.size()>0 we 'nave to use given sequence
// else - use all nodes of mesh
const SMDS_MeshNode * node = 0;
if ( myNodes.Length() > 0 ) {
int i;
- for(i=1; i<=myNodes.Length(); i++) {
+ for ( i = 1; i <= myNodes.Length(); i++ ) {
gp_XYZ P2 = SMESH_TNodeXYZ( myNodes.Value(i) );
if (( P1 - P2 ).SquareModulus() < myTolerance * myTolerance )
{
ExtrusParam& theParams,
TTElemOfElemListMap& newElemsMap)
{
- myLastCreatedElems.Clear();
- myLastCreatedNodes.Clear();
+ ClearLastCreated();
+
+ setElemsFirst( theElemSets );
+ myLastCreatedElems.reserve( theElemSets[0].size() * theParams.NbSteps() );
+ myLastCreatedNodes.reserve( theElemSets[1].size() * theParams.NbSteps() );
// source elements for each generated one
SMESH_SequenceOfElemPtr srcElems, srcNodes;
+ srcElems.reserve( theElemSets[0].size() );
+ srcNodes.reserve( theElemSets[1].size() );
- setElemsFirst( theElemSets );
const int nbSteps = theParams.NbSteps();
theParams.SetElementsToUse( theElemSets[0], theElemSets[1] );
list<const SMDS_MeshNode*>::iterator newNodesIt = listNewNodes.begin();
for ( ; newNodesIt != listNewNodes.end(); ++newNodesIt )
{
- myLastCreatedNodes.Append( *newNodesIt );
- srcNodes.Append( node );
+ myLastCreatedNodes.push_back( *newNodesIt );
+ srcNodes.push_back( node );
}
}
else
const gp_Pnt& theRefPoint,
const bool theMakeGroups)
{
- myLastCreatedElems.Clear();
- myLastCreatedNodes.Clear();
+ ClearLastCreated();
int aNbE;
std::list<double> aPrms;
const gp_Pnt& theRefPoint,
const bool theMakeGroups)
{
- myLastCreatedElems.Clear();
- myLastCreatedNodes.Clear();
+ ClearLastCreated();
int aNbE;
std::list<double> aPrms;
// create additional node
gp_XYZ midP = 0.5 * ( aPN1.XYZ() + aPN0.XYZ() );
const SMDS_MeshNode* newNode = aMesh->AddNode( midP.X(), midP.Y(), midP.Z() );
- myLastCreatedNodes.Append(newNode);
- srcNodes.Append( node );
+ myLastCreatedNodes.push_back(newNode);
+ srcNodes.push_back( node );
listNewNodes.push_back( newNode );
}
const SMDS_MeshNode* newNode = aMesh->AddNode( aPN1.X(), aPN1.Y(), aPN1.Z() );
- myLastCreatedNodes.Append(newNode);
- srcNodes.Append( node );
+ myLastCreatedNodes.push_back(newNode);
+ srcNodes.push_back( node );
listNewNodes.push_back( newNode );
aPN0 = aPN1;
double y = ( N->Y() + P.Y() )/2.;
double z = ( N->Z() + P.Z() )/2.;
const SMDS_MeshNode* newN = aMesh->AddNode(x,y,z);
- srcNodes.Append( node );
- myLastCreatedNodes.Append(newN);
+ srcNodes.push_back( node );
+ myLastCreatedNodes.push_back(newN);
aNodes[2*i] = newN;
aNodes[2*i+1] = N;
P = gp_XYZ(N->X(),N->Y(),N->Z());
const bool theMakeGroups,
SMESH_Mesh* theTargetMesh)
{
- myLastCreatedElems.Clear();
- myLastCreatedNodes.Clear();
+ ClearLastCreated();
+ myLastCreatedElems.reserve( theElems.size() );
bool needReverse = false;
string groupPostfix;
if ( theTargetMesh ) {
const SMDS_MeshNode * newNode = aTgtMesh->AddNode( coord[0], coord[1], coord[2] );
n2n_isnew.first->second = newNode;
- myLastCreatedNodes.Append(newNode);
- srcNodes.Append( node );
+ myLastCreatedNodes.push_back(newNode);
+ srcNodes.push_back( node );
}
else if ( theCopy ) {
const SMDS_MeshNode * newNode = aMesh->AddNode( coord[0], coord[1], coord[2] );
n2n_isnew.first->second = newNode;
- myLastCreatedNodes.Append(newNode);
- srcNodes.Append( node );
+ myLastCreatedNodes.push_back(newNode);
+ srcNodes.push_back( node );
}
else {
aMesh->MoveNode( node, coord[0], coord[1], coord[2] );
if ( editor ) {
// copy in this or a new mesh
if ( editor->AddElement( nodes, elemType.Init( elem, /*basicOnly=*/false )))
- srcElems.Append( elem );
+ srcElems.push_back( elem );
}
else {
// reverse element as it was reversed by transformation
} // loop on elements
if ( editor && editor != this )
- myLastCreatedElems = editor->myLastCreatedElems;
+ myLastCreatedElems.swap( editor->myLastCreatedElems );
PGroupIDs newGroupIDs;
return newGroupIDs;
}
+//================================================================================
+/*!
+ * \brief Make an offset mesh from a source 2D mesh
+ * \param [in] theElements - source faces
+ * \param [in] theValue - offset value
+ * \param [out] theTgtMesh - a mesh to add offset elements to
+ * \param [in] theMakeGroups - to generate groups
+ * \return PGroupIDs - IDs of created groups
+ */
+//================================================================================
+
+SMESH_MeshEditor::PGroupIDs SMESH_MeshEditor::Offset( TIDSortedElemSet & theElements,
+ const double theValue,
+ SMESH_Mesh* theTgtMesh,
+ const bool theMakeGroups,
+ const bool theFixSelfIntersection)
+{
+ SMESHDS_Mesh* meshDS = GetMeshDS();
+ SMESHDS_Mesh* tgtMeshDS = theTgtMesh->GetMeshDS();
+ SMESH_MeshEditor tgtEditor( theTgtMesh );
+
+ SMDS_ElemIteratorPtr eIt;
+ if ( theElements.empty() ) eIt = meshDS->elementsIterator( SMDSAbs_Face );
+ else eIt = SMESHUtils::elemSetIterator( theElements );
+
+ SMESH_MeshAlgos::TEPairVec new2OldFaces;
+ SMESH_MeshAlgos::TNPairVec new2OldNodes;
+ std::unique_ptr< SMDS_Mesh > offsetMesh
+ ( SMESH_MeshAlgos::MakeOffset( eIt, *meshDS, theValue,
+ theFixSelfIntersection,
+ new2OldFaces, new2OldNodes ));
+
+ offsetMesh->Modified();
+ offsetMesh->CompactMesh(); // make IDs start from 1
+
+ // source elements for each generated one
+ SMESH_SequenceOfElemPtr srcElems, srcNodes;
+ srcElems.reserve( new2OldFaces.size() );
+ srcNodes.reserve( new2OldNodes.size() );
+
+ ClearLastCreated();
+ myLastCreatedElems.reserve( new2OldFaces.size() );
+ myLastCreatedNodes.reserve( new2OldNodes.size() );
+
+ // copy offsetMesh to theTgtMesh
+
+ int idShift = meshDS->MaxNodeID();
+ for ( size_t i = 0; i < new2OldNodes.size(); ++i )
+ if ( const SMDS_MeshNode* n = new2OldNodes[ i ].first )
+ {
+ if ( n->NbInverseElements() > 0 )
+ {
+ const SMDS_MeshNode* n2 =
+ tgtMeshDS->AddNodeWithID( n->X(), n->Y(), n->Z(), idShift + n->GetID() );
+ myLastCreatedNodes.push_back( n2 );
+ srcNodes.push_back( new2OldNodes[ i ].second );
+ }
+ }
+
+ ElemFeatures elemType;
+ for ( size_t i = 0; i < new2OldFaces.size(); ++i )
+ if ( const SMDS_MeshElement* f = new2OldFaces[ i ].first )
+ {
+ elemType.Init( f );
+ elemType.myNodes.clear();
+ for ( SMDS_NodeIteratorPtr nIt = f->nodeIterator(); nIt->more(); )
+ {
+ const SMDS_MeshNode* n2 = nIt->next();
+ elemType.myNodes.push_back( tgtMeshDS->FindNode( idShift + n2->GetID() ));
+ }
+ tgtEditor.AddElement( elemType.myNodes, elemType );
+ srcElems.push_back( new2OldFaces[ i ].second );
+ }
+
+ myLastCreatedElems.swap( tgtEditor.myLastCreatedElems );
+
+ PGroupIDs newGroupIDs;
+ if ( theMakeGroups )
+ newGroupIDs = generateGroups( srcNodes, srcElems, "offset", theTgtMesh, false );
+
+ return newGroupIDs;
+}
+
//=======================================================================
/*!
* \brief Create groups of elements made during transformation
* \param nodeGens - nodes making corresponding myLastCreatedNodes
* \param elemGens - elements making corresponding myLastCreatedElems
- * \param postfix - to append to names of new groups
+ * \param postfix - to push_back to names of new groups
* \param targetMesh - mesh to create groups in
- * \param topPresent - is there "top" elements that are created by sweeping
+ * \param topPresent - is there are "top" elements that are created by sweeping
*/
//=======================================================================
{
const SMESH_SequenceOfElemPtr& gens = isNodes ? nodeGens : elemGens;
const SMESH_SequenceOfElemPtr& elems = isNodes ? myLastCreatedNodes : myLastCreatedElems;
- if ( gens.Length() != elems.Length() )
+ if ( gens.size() != elems.size() )
throw SALOME_Exception("SMESH_MeshEditor::generateGroups(): invalid args");
// loop on created elements
- for (int iElem = 1; iElem <= elems.Length(); ++iElem )
+ for (size_t iElem = 0; iElem < elems.size(); ++iElem )
{
- const SMDS_MeshElement* sourceElem = gens( iElem );
+ const SMDS_MeshElement* sourceElem = gens[ iElem ];
if ( !sourceElem ) {
MESSAGE("generateGroups(): NULL source element");
continue;
}
list< TOldNewGroup > & groupsOldNew = groupsByType[ sourceElem->GetType() ];
if ( groupsOldNew.empty() ) { // no groups of this type at all
- while ( iElem < gens.Length() && gens( iElem+1 ) == sourceElem )
+ while ( iElem+1 < gens.size() && gens[ iElem+1 ] == sourceElem )
++iElem; // skip all elements made by sourceElem
continue;
}
// collect all elements made by the iElem-th sourceElem
resultElems.clear();
- if ( const SMDS_MeshElement* resElem = elems( iElem ))
+ if ( const SMDS_MeshElement* resElem = elems[ iElem ])
if ( resElem != sourceElem )
resultElems.push_back( resElem );
- while ( iElem < gens.Length() && gens( iElem+1 ) == sourceElem )
- if ( const SMDS_MeshElement* resElem = elems( ++iElem ))
+ while ( iElem+1 < gens.size() && gens[ iElem+1 ] == sourceElem )
+ if ( const SMDS_MeshElement* resElem = elems[ ++iElem ])
if ( resElem != sourceElem )
resultElems.push_back( resElem );
{
SMDS_MeshGroup & newTopGroup = gOldNew->get<2>()->SMDSGroup();
newTopGroup.Add( topElem );
- }
+ }
}
}
} // loop on created elements
TListOfListOfNodes & theGroupsOfNodes,
bool theSeparateCornersAndMedium)
{
- myLastCreatedElems.Clear();
- myLastCreatedNodes.Clear();
+ ClearLastCreated();
if ( myMesh->NbEdges ( ORDER_QUADRATIC ) +
myMesh->NbFaces ( ORDER_QUADRATIC ) +
void SMESH_MeshEditor::MergeNodes (TListOfListOfNodes & theGroupsOfNodes)
{
- myLastCreatedElems.Clear();
- myLastCreatedNodes.Clear();
+ ClearLastCreated();
SMESHDS_Mesh* aMesh = GetMeshDS();
{
const SMDS_MeshElement* newElem =
aMesh->AddPolyhedralVolume( poly_nodes, quantities );
- myLastCreatedElems.Append( newElem );
+ myLastCreatedElems.push_back( newElem );
if ( aShapeId && newElem )
aMesh->SetMeshElementOnShape( newElem, aShapeId );
rmElemIds.push_back( elem->GetID() );
if ( quantities.size() >= 4 )
{
const SMDS_MeshElement* newElem = aMesh->AddPolyhedralVolume( poly_nodes, quantities );
- myLastCreatedElems.Append( newElem );
+ myLastCreatedElems.push_back( newElem );
if ( aShapeId && newElem )
aMesh->SetMeshElementOnShape( newElem, aShapeId );
rmElemIds.push_back( elem->GetID() );
void SMESH_MeshEditor::FindEqualElements(TIDSortedElemSet & theElements,
TListOfListOfElementsID & theGroupsOfElementsID)
{
- myLastCreatedElems.Clear();
- myLastCreatedNodes.Clear();
+ ClearLastCreated();
typedef map< SortableElement, int > TMapOfNodeSet;
typedef list<int> TGroupOfElems;
- if ( theElements.empty() )
- { // get all elements in the mesh
- SMDS_ElemIteratorPtr eIt = GetMeshDS()->elementsIterator();
- while ( eIt->more() )
- theElements.insert( theElements.end(), eIt->next() );
- }
+ SMDS_ElemIteratorPtr elemIt;
+ if ( theElements.empty() ) elemIt = GetMeshDS()->elementsIterator();
+ else elemIt = SMESHUtils::elemSetIterator( theElements );
vector< TGroupOfElems > arrayOfGroups;
TGroupOfElems groupOfElems;
TMapOfNodeSet mapOfNodeSet;
- TIDSortedElemSet::iterator elemIt = theElements.begin();
- for ( int i = 0; elemIt != theElements.end(); ++elemIt )
+ for ( int i = 0; elemIt->more(); )
{
- const SMDS_MeshElement* curElem = *elemIt;
+ const SMDS_MeshElement* curElem = elemIt->next();
SortableElement SE(curElem);
// check uniqueness
pair< TMapOfNodeSet::iterator, bool> pp = mapOfNodeSet.insert(make_pair(SE, i));
void SMESH_MeshEditor::MergeElements(TListOfListOfElementsID & theGroupsOfElementsID)
{
- myLastCreatedElems.Clear();
- myLastCreatedNodes.Clear();
+ ClearLastCreated();
typedef list<int> TListOfIDs;
TListOfIDs rmElemIds; // IDs of elems to remove
if ( contNodes[0].empty() && contNodes[1].empty() )
return false;
- // append the best free border
+ // push_back the best free border
cNL = & contNodes[ contNodes[0].empty() ? 1 : 0 ];
cFL = & contFaces[ contFaces[0].empty() ? 1 : 0 ];
theNodes.pop_back(); // remove nIgnore
const bool toCreatePolygons,
const bool toCreatePolyedrs)
{
- myLastCreatedElems.Clear();
- myLastCreatedNodes.Clear();
+ ClearLastCreated();
Sew_Error aResult = SEW_OK;
// get new segments
TIDSortedElemSet segments;
SMESH_SequenceOfElemPtr newFaces;
- for ( int i = 1; i <= myLastCreatedElems.Length(); ++i )
+ for ( size_t i = 0; i < myLastCreatedElems.size(); ++i )
{
- if ( !myLastCreatedElems(i) ) continue;
- if ( myLastCreatedElems(i)->GetType() == SMDSAbs_Edge )
- segments.insert( segments.end(), myLastCreatedElems(i) );
+ if ( !myLastCreatedElems[i] ) continue;
+ if ( myLastCreatedElems[i]->GetType() == SMDSAbs_Edge )
+ segments.insert( segments.end(), myLastCreatedElems[i] );
else
- newFaces.Append( myLastCreatedElems(i) );
+ newFaces.push_back( myLastCreatedElems[i] );
}
// get segments adjacent to merged nodes
TListOfListOfNodes::iterator groupIt = nodeGroupsToMerge.begin();
myLastCreatedElems = newFaces;
TIDSortedElemSet::iterator seg = segments.begin();
for ( ; seg != segments.end(); ++seg )
- myLastCreatedElems.Append( *seg );
+ myLastCreatedElems.push_back( *seg );
}
return aResult;
if ( newElems[i] )
{
aMesh->SetMeshElementOnShape( newElems[i], theElement->getshapeId() );
- myLastCreatedElems.Append( newElems[i] );
+ myLastCreatedElems.push_back( newElems[i] );
}
ReplaceElemInGroups( theElement, newElems, aMesh );
aMesh->RemoveElement( theElement );
if ( newElems[i] )
{
aMesh->SetMeshElementOnShape( newElems[i], theFace->getshapeId() );
- myLastCreatedElems.Append( newElems[i] );
+ myLastCreatedElems.push_back( newElems[i] );
}
ReplaceElemInGroups( theFace, newElems, aMesh );
aMesh->RemoveElement(theFace);
const SMDS_MeshNode* theBetweenNode2,
list<const SMDS_MeshNode*>& theNodesToInsert)
{
- myLastCreatedElems.Clear();
- myLastCreatedNodes.Clear();
+ ClearLastCreated();
SMDS_ElemIteratorPtr invElemIt = theBetweenNode1->GetInverseElementIterator(SMDSAbs_Volume);
while (invElemIt->more()) { // loop on inverse elements of theBetweenNode1
if ( SMDS_MeshElement* newElem = aMesh->AddPolyhedralVolume( poly_nodes, quantities ))
{
aMesh->SetMeshElementOnShape( newElem, elem->getshapeId() );
- myLastCreatedElems.Append( newElem );
+ myLastCreatedElems.push_back( newElem );
ReplaceElemInGroups( elem, newElem, aMesh );
}
aMesh->RemoveElement( elem );
switch( aType )
{
case SMDSAbs_Edge :
- {
- NewElem = theHelper.AddEdge(nodes[0], nodes[1], id, theForce3d);
- break;
- }
+ {
+ NewElem = theHelper.AddEdge(nodes[0], nodes[1], id, theForce3d);
+ break;
+ }
case SMDSAbs_Face :
+ {
+ switch(nbNodes)
{
- switch(nbNodes)
- {
- case 3:
- NewElem = theHelper.AddFace(nodes[0], nodes[1], nodes[2], id, theForce3d);
- break;
- case 4:
- NewElem = theHelper.AddFace(nodes[0], nodes[1], nodes[2], nodes[3], id, theForce3d);
- break;
- default:
- NewElem = theHelper.AddPolygonalFace(nodes, id, theForce3d);
- }
+ case 3:
+ NewElem = theHelper.AddFace(nodes[0], nodes[1], nodes[2], id, theForce3d);
+ break;
+ case 4:
+ NewElem = theHelper.AddFace(nodes[0], nodes[1], nodes[2], nodes[3], id, theForce3d);
break;
+ default:
+ NewElem = theHelper.AddPolygonalFace(nodes, id, theForce3d);
}
+ break;
+ }
case SMDSAbs_Volume :
+ {
+ switch( aGeomType )
{
- switch( aGeomType )
- {
- case SMDSEntity_Tetra:
- NewElem = theHelper.AddVolume(nodes[0], nodes[1], nodes[2], nodes[3], id, theForce3d);
- break;
- case SMDSEntity_Pyramid:
- NewElem = theHelper.AddVolume(nodes[0], nodes[1], nodes[2], nodes[3], nodes[4], id, theForce3d);
- break;
- case SMDSEntity_Penta:
- NewElem = theHelper.AddVolume(nodes[0], nodes[1], nodes[2], nodes[3], nodes[4], nodes[5], id, theForce3d);
- break;
- case SMDSEntity_Hexa:
- case SMDSEntity_Quad_Hexa:
- case SMDSEntity_TriQuad_Hexa:
- NewElem = theHelper.AddVolume(nodes[0], nodes[1], nodes[2], nodes[3],
- nodes[4], nodes[5], nodes[6], nodes[7], id, theForce3d);
- break;
- case SMDSEntity_Hexagonal_Prism:
- default:
- NewElem = theHelper.AddPolyhedralVolume(nodes, nbNodeInFaces, id, theForce3d);
- }
+ case SMDSEntity_Tetra:
+ NewElem = theHelper.AddVolume(nodes[0], nodes[1], nodes[2], nodes[3], id, theForce3d);
+ break;
+ case SMDSEntity_Pyramid:
+ NewElem = theHelper.AddVolume(nodes[0], nodes[1], nodes[2], nodes[3], nodes[4], id, theForce3d);
+ break;
+ case SMDSEntity_Penta:
+ NewElem = theHelper.AddVolume(nodes[0], nodes[1], nodes[2], nodes[3], nodes[4], nodes[5], id, theForce3d);
break;
+ case SMDSEntity_Hexa:
+ case SMDSEntity_Quad_Hexa:
+ case SMDSEntity_TriQuad_Hexa:
+ NewElem = theHelper.AddVolume(nodes[0], nodes[1], nodes[2], nodes[3],
+ nodes[4], nodes[5], nodes[6], nodes[7], id, theForce3d);
+ break;
+ case SMDSEntity_Hexagonal_Prism:
+ default:
+ NewElem = theHelper.AddPolyhedralVolume(nodes, nbNodeInFaces, id, theForce3d);
}
+ break;
+ }
default :
continue;
}
if( newElem && smDS )
smDS->AddElement( newElem );
- // remove central nodes
+ // remove central nodes
for ( size_t i = nodes.size() - nbCentralNodes; i < nodes.size(); ++i )
if ( nodes[i]->NbInverseElements() == 0 )
meshDS->RemoveFreeNode( nodes[i], smDS, /*fromGroups=*/true );
}
// replace given elements by linear ones
- SMDS_ElemIteratorPtr elemIt = elemSetIterator( theElements );
+ SMDS_ElemIteratorPtr elemIt = SMESHUtils::elemSetIterator( theElements );
removeQuadElem( /*theSm=*/0, elemIt, /*theShapeID=*/0 );
// we need to convert remaining elements whose all medium nodes are in mediumNodeIDs
}
}
}
- elemIt = elemSetIterator( moreElemsToConvert );
+ elemIt = SMESHUtils::elemSetIterator( moreElemsToConvert );
removeQuadElem( /*theSm=*/0, elemIt, /*theShapeID=*/0 );
}
const SMDS_MeshNode* theSecondNode1,
const SMDS_MeshNode* theSecondNode2)
{
- myLastCreatedElems.Clear();
- myLastCreatedNodes.Clear();
+ ClearLastCreated();
if ( theSide1.size() != theSide2.size() )
return SEW_DIFF_NB_OF_ELEMENTS;
if ( faceSet1.size() != faceSet2.size() ) {
// delete temporary faces: they are in reverseElements of actual nodes
-// SMDS_FaceIteratorPtr tmpFaceIt = aTmpFacesMesh.facesIterator();
-// while ( tmpFaceIt->more() )
-// aTmpFacesMesh.RemoveElement( tmpFaceIt->next() );
-// list<const SMDS_MeshElement* >::iterator tmpFaceIt = tempFaceList.begin();
-// for (; tmpFaceIt !=tempFaceList.end(); ++tmpFaceIt)
-// aMesh->RemoveElement(*tmpFaceIt);
+ // SMDS_FaceIteratorPtr tmpFaceIt = aTmpFacesMesh.facesIterator();
+ // while ( tmpFaceIt->more() )
+ // aTmpFacesMesh.RemoveElement( tmpFaceIt->next() );
+ // list<const SMDS_MeshElement* >::iterator tmpFaceIt = tempFaceList.begin();
+ // for (; tmpFaceIt !=tempFaceList.end(); ++tmpFaceIt)
+ // aMesh->RemoveElement(*tmpFaceIt);
MESSAGE("Diff nb of faces");
return SEW_TOPO_DIFF_SETS_OF_ELEMENTS;
}
if ( aResult == SEW_OK &&
( //linkIt[0] != linkList[0].end() ||
- !faceSetPtr[0]->empty() || !faceSetPtr[1]->empty() )) {
+ !faceSetPtr[0]->empty() || !faceSetPtr[1]->empty() )) {
MESSAGE( (linkIt[0] != linkList[0].end()) <<" "<< (faceSetPtr[0]->empty()) <<
" " << (faceSetPtr[1]->empty()));
aResult = SEW_TOPO_DIFF_SETS_OF_ELEMENTS;
// ====================================================================
// delete temporary faces
-// SMDS_FaceIteratorPtr tmpFaceIt = aTmpFacesMesh.facesIterator();
-// while ( tmpFaceIt->more() )
-// aTmpFacesMesh.RemoveElement( tmpFaceIt->next() );
+ // SMDS_FaceIteratorPtr tmpFaceIt = aTmpFacesMesh.facesIterator();
+ // while ( tmpFaceIt->more() )
+ // aTmpFacesMesh.RemoveElement( tmpFaceIt->next() );
list<const SMDS_MeshElement* >::iterator tmpFaceIt = tempFaceList.begin();
for (; tmpFaceIt !=tempFaceList.end(); ++tmpFaceIt)
aMesh->RemoveElement(*tmpFaceIt);
type = types[i];
break;
}
- // put all elements in the vector <allElems>
- allElems.reserve( mesh->GetMeshInfo().NbElements( type ));
elemIt = mesh->elementsIterator( type );
- while ( elemIt->more() )
- allElems.push_back( elemIt->next());
- elemIt = elemSetIterator( allElems );
}
else
{
type = (*theElements.begin())->GetType();
- elemIt = elemSetIterator( theElements );
+ elemIt = SMESHUtils::elemSetIterator( theElements );
}
// duplicate elements
const TIDSortedElemSet& theNodesNot,
const TIDSortedElemSet& theAffectedElems )
{
- myLastCreatedElems.Clear();
- myLastCreatedNodes.Clear();
+ ClearLastCreated();
if ( theElems.size() == 0 )
return false;
aNewNode = theMeshDS->AddNode( aCurrNode->X(), aCurrNode->Y(), aCurrNode->Z() );
copyPosition( aCurrNode, aNewNode );
theNodeNodeMap[ aCurrNode ] = aNewNode;
- myLastCreatedNodes.Append( aNewNode );
+ myLastCreatedNodes.push_back( aNewNode );
}
isDuplicate |= (aCurrNode != aNewNode);
newNodes[ ind++ ] = aNewNode;
bool SMESH_MeshEditor::DoubleNodes( const std::list< int >& theListOfNodes,
const std::list< int >& theListOfModifiedElems )
{
- myLastCreatedElems.Clear();
- myLastCreatedNodes.Clear();
+ ClearLastCreated();
if ( theListOfNodes.size() == 0 )
return false;
{
copyPosition( aNode, aNewNode );
anOldNodeToNewNode[ aNode ] = aNewNode;
- myLastCreatedNodes.Append( aNewNode );
+ myLastCreatedNodes.push_back( aNewNode );
}
}
//================================================================================
/*!
- \brief Check if element located inside shape
- \return TRUE if IN or ON shape, FALSE otherwise
+ \brief Check if element located inside shape
+ \return TRUE if IN or ON shape, FALSE otherwise
*/
//================================================================================
SMDS_ElemIteratorPtr eIt;
if (elements.empty()) eIt = aMesh->elementsIterator(elemType);
- else eIt = elemSetIterator( elements );
+ else eIt = SMESHUtils::elemSetIterator( elements );
while (eIt->more())
{
else // store present elements to add them to a group
for ( size_t i = 0 ; i < presentBndElems.size(); ++i )
{
- presentEditor->myLastCreatedElems.Append( presentBndElems[ i ]);
+ presentEditor->myLastCreatedElems.push_back( presentBndElems[ i ]);
}
} // loop on given elements
if ( group )
{
if ( SMESHDS_Group* g = dynamic_cast<SMESHDS_Group*>( group->GetGroupDS() ))
- for ( int i = 0; i < tgtEditor.myLastCreatedElems.Size(); ++i )
- g->SMDSGroup().Add( tgtEditor.myLastCreatedElems( i+1 ));
+ for ( size_t i = 0; i < tgtEditor.myLastCreatedElems.size(); ++i )
+ g->SMDSGroup().Add( tgtEditor.myLastCreatedElems[ i ]);
}
- tgtEditor.myLastCreatedElems.Clear();
- tgtEditor2.myLastCreatedElems.Clear();
+ tgtEditor.myLastCreatedElems.clear();
+ tgtEditor2.myLastCreatedElems.clear();
// -----------------------
// 5. Copy given elements
if ( toCopyElements && targetMesh != myMesh )
{
if (elements.empty()) eIt = aMesh->elementsIterator(elemType);
- else eIt = elemSetIterator( elements );
+ else eIt = SMESHUtils::elemSetIterator( elements );
while (eIt->more())
{
const SMDS_MeshElement* elem = eIt->next();
tgtNodes[inode] = getNodeWithSameID( tgtMeshDS, elem->GetNode(inode) );
tgtEditor.AddElement( tgtNodes, elemToCopy.Init( elem ));
- tgtEditor.myLastCreatedElems.Clear();
+ tgtEditor.myLastCreatedElems.clear();
}
}
return nbAddedBnd;
// --------------------------------------------------------------------------------
struct ElemFeatures //!< Features of element to create
{
- SMDSAbs_ElementType myType;
- bool myIsPoly, myIsQuad;
- int myID;
- double myBallDiameter;
- std::vector<int> myPolyhedQuantities;
+ SMDSAbs_ElementType myType;
+ bool myIsPoly, myIsQuad;
+ int myID;
+ double myBallDiameter;
+ std::vector<int> myPolyhedQuantities;
+ std::vector<const SMDS_MeshNode*> myNodes; // not managed by ElemFeatures
SMESH_EXPORT ElemFeatures( SMDSAbs_ElementType type=SMDSAbs_All, bool isPoly=false, bool isQuad=false )
:myType( type ), myIsPoly(isPoly), myIsQuad(isQuad), myID(-1), myBallDiameter(0) {}
SMESH_Mesh* theTargetMesh=0);
// Move or copy theElements applying theTrsf to their nodes
+ PGroupIDs Offset( TIDSortedElemSet & theElements,
+ const double theValue,
+ SMESH_Mesh* theTgtMesh,
+ const bool theMakeGroups,
+ const bool theFixSelfIntersection);
+ // Make an offset mesh from a source 2D mesh
+
typedef std::list< std::list< const SMDS_MeshNode* > > TListOfListOfNodes;
void FindCoincidentNodes (TIDSortedNodeSet & theNodes,
{
// code is valid for convex faces only
gp_XYZ gc(0,0,0);
- for ( TIDSortedNodeSet::const_iterator n = begin(); n!=end(); ++n)
- gc += XYZ( *n ) / size();
- for (unsigned i = 0; i < _sides.size(); ++i )
+ for ( TIDSortedNodeSet::const_iterator n = begin(); n != end(); ++n )
+ gc += XYZ( *n ) / double( size() );
+ for ( size_t i = 0; i < _sides.size(); ++i )
{
if ( _sides[i] == bentLink ) continue;
gp_Vec linkNorm = _normal ^ gp_Vec( XYZ(_sides[i]->node1()), XYZ(_sides[i]->node2()));
return true;
}
return false;
-
+
}
//================================================================================
/*!
- * \brief Find pairs of continues faces
+ * \brief Find pairs of continues faces
*/
//================================================================================
SMESHGUI_RotationDlg.h
SMESHGUI_TranslationDlg.h
SMESHGUI_ScaleDlg.h
+ SMESHGUI_OffsetDlg.h
SMESHGUI_SymmetryDlg.h
SMESHGUI_SewingDlg.h
SMESHGUI_DuplicateNodesDlg.h
SMESHGUI_RotationDlg.cxx
SMESHGUI_TranslationDlg.cxx
SMESHGUI_ScaleDlg.cxx
+ SMESHGUI_OffsetDlg.cxx
SMESHGUI_SymmetryDlg.cxx
SMESHGUI_SewingDlg.cxx
SMESHGUI_DuplicateNodesDlg.cxx
#include "SMESHGUI_RevolutionDlg.h"
#include "SMESHGUI_RotationDlg.h"
#include "SMESHGUI_ScaleDlg.h"
+#include "SMESHGUI_OffsetDlg.h"
#include "SMESHGUI_Selection.h"
#include "SMESHGUI_SewingDlg.h"
#include "SMESHGUI_SingleEditDlg.h"
break;
}
+ case SMESHOp::OpOffset:
+ {
+ if(checkLock(aStudy)) break;
+ if ( vtkwnd ) {
+ EmitSignalDeactivateDialog();
+ ( new SMESHGUI_OffsetDlg( this ) )->show();
+ }
+ else {
+ SUIT_MessageBox::warning(SMESHGUI::desktop(),
+ tr("SMESH_WRN_WARNING"), tr("SMESH_WRN_VIEWER_VTK"));
+ }
+ break;
+ }
+
case SMESHOp::OpSewing:
{
if(checkLock(aStudy)) break;
createSMESHAction( SMESHOp::OpRotation, "ROT", "ICON_DLG_MESH_ROTATION" );
createSMESHAction( SMESHOp::OpSymmetry, "SYM", "ICON_SMESH_SYMMETRY_PLANE" );
createSMESHAction( SMESHOp::OpScale, "SCALE", "ICON_DLG_MESH_SCALE" );
+ createSMESHAction( SMESHOp::OpOffset, "OFFSET", "ICON_DLG_MESH_OFFSET" );
createSMESHAction( SMESHOp::OpSewing, "SEW", "ICON_SMESH_SEWING_FREEBORDERS" );
createSMESHAction( SMESHOp::OpMergeNodes, "MERGE", "ICON_SMESH_MERGE_NODES" );
createSMESHAction( SMESHOp::OpMergeElements, "MERGE_ELEMENTS", "ICON_DLG_MERGE_ELEMENTS" );
//createMenu( SMESHOp::OpRenumberingNodes, renumId, -1 );
//createMenu( SMESHOp::OpRenumberingElements, renumId, -1 );
+ createMenu( SMESHOp::OpMergeNodes, transfId, -1 );
+ createMenu( SMESHOp::OpMergeElements, transfId, -1 );
createMenu( SMESHOp::OpTranslation, transfId, -1 );
createMenu( SMESHOp::OpRotation, transfId, -1 );
createMenu( SMESHOp::OpSymmetry, transfId, -1 );
createMenu( SMESHOp::OpScale, transfId, -1 );
+ createMenu( SMESHOp::OpOffset, transfId, -1 );
createMenu( SMESHOp::OpSewing, transfId, -1 );
- createMenu( SMESHOp::OpMergeNodes, transfId, -1 );
- createMenu( SMESHOp::OpMergeElements, transfId, -1 );
createMenu( SMESHOp::OpDuplicateNodes, transfId, -1 );
+ createMenu( SMESHOp::OpConvertMeshToQuadratic, modifyId, -1 );
+ createMenu( SMESHOp::OpCreateBoundaryElements, modifyId, -1 );
+ createMenu( SMESHOp::OpExtrusion, modifyId, -1 );
+ createMenu( SMESHOp::OpExtrusionAlongAPath, modifyId, -1 );
+ createMenu( SMESHOp::OpRevolution, modifyId, -1 );
+ createMenu( SMESHOp::OpOrientation, modifyId, -1 );
+ createMenu( SMESHOp::OpReorientFaces, modifyId, -1 );
createMenu( SMESHOp::OpMoveNode, modifyId, -1 );
createMenu( SMESHOp::OpDiagonalInversion, modifyId, -1 );
createMenu( SMESHOp::OpUnionOfTwoTriangle, modifyId, -1 );
- createMenu( SMESHOp::OpOrientation, modifyId, -1 );
- createMenu( SMESHOp::OpReorientFaces, modifyId, -1 );
createMenu( SMESHOp::OpUnionOfTriangles, modifyId, -1 );
createMenu( SMESHOp::OpCuttingOfQuadrangles, modifyId, -1 );
createMenu( SMESHOp::OpSplitVolumes, modifyId, -1 );
createMenu( SMESHOp::OpSplitBiQuadratic, modifyId, -1 );
createMenu( SMESHOp::OpSmoothing, modifyId, -1 );
- createMenu( SMESHOp::OpExtrusion, modifyId, -1 );
- createMenu( SMESHOp::OpExtrusionAlongAPath , modifyId, -1 );
- createMenu( SMESHOp::OpRevolution, modifyId, -1 );
createMenu( SMESHOp::OpPatternMapping, modifyId, -1 );
- createMenu( SMESHOp::OpConvertMeshToQuadratic, modifyId, -1 );
- createMenu( SMESHOp::OpCreateBoundaryElements, modifyId, -1 );
createMenu( SMESHOp::OpMinimumDistance, measureId, -1 );
createMenu( SMESHOp::OpBoundingBox, measureId, -1 );
//createTool( SMESHOp::OpRenumberingNodes, renumbTb );
//createTool( SMESHOp::OpRenumberingElements, renumbTb );
+ createTool( SMESHOp::OpMergeNodes, transformTb );
+ createTool( SMESHOp::OpMergeElements, transformTb );
createTool( SMESHOp::OpTranslation, transformTb );
createTool( SMESHOp::OpRotation, transformTb );
createTool( SMESHOp::OpSymmetry, transformTb );
createTool( SMESHOp::OpScale, transformTb );
+ createTool( SMESHOp::OpOffset, transformTb );
createTool( SMESHOp::OpSewing, transformTb );
- createTool( SMESHOp::OpMergeNodes, transformTb );
- createTool( SMESHOp::OpMergeElements, transformTb );
createTool( SMESHOp::OpDuplicateNodes, transformTb );
+ createTool( SMESHOp::OpConvertMeshToQuadratic, modifyTb );
+ createTool( SMESHOp::OpCreateBoundaryElements, modifyTb );
+ createTool( SMESHOp::OpExtrusion, modifyTb );
+ createTool( SMESHOp::OpExtrusionAlongAPath, modifyTb );
+ createTool( SMESHOp::OpRevolution, modifyTb );
+ createTool( SMESHOp::OpOrientation, modifyTb );
+ createTool( SMESHOp::OpReorientFaces, modifyTb );
createTool( SMESHOp::OpMoveNode, modifyTb );
createTool( SMESHOp::OpDiagonalInversion, modifyTb );
createTool( SMESHOp::OpUnionOfTwoTriangle, modifyTb );
- createTool( SMESHOp::OpOrientation, modifyTb );
- createTool( SMESHOp::OpReorientFaces, modifyTb );
createTool( SMESHOp::OpUnionOfTriangles, modifyTb );
createTool( SMESHOp::OpCuttingOfQuadrangles, modifyTb );
createTool( SMESHOp::OpSplitVolumes, modifyTb );
createTool( SMESHOp::OpSplitBiQuadratic, modifyTb );
createTool( SMESHOp::OpSmoothing, modifyTb );
- createTool( SMESHOp::OpExtrusion, modifyTb );
- createTool( SMESHOp::OpExtrusionAlongAPath, modifyTb );
- createTool( SMESHOp::OpRevolution, modifyTb );
createTool( SMESHOp::OpPatternMapping, modifyTb );
- createTool( SMESHOp::OpConvertMeshToQuadratic, modifyTb );
- createTool( SMESHOp::OpCreateBoundaryElements, modifyTb );
createTool( SMESHOp::OpMinimumDistance, measuremTb );
#include <SMESH_FaceOrientationFilter.h>
#include <SMDS_Mesh.hxx>
-// SALOME GUI inclues
+// SALOME GUI includes
#include <SUIT_Desktop.h>
#include <SUIT_Session.h>
#include <SUIT_ResourceMgr.h>
#include <Qtx.h>
-// IDL incldues
+// IDL includes
#include CORBA_SERVER_HEADER(SMESH_MeshEditor)
// OCCT includes
mySimulation->SetVisibility(false);
- // hilight entered nodes
+ // highlight entered nodes
SMDS_Mesh* aMesh = 0;
if (myActor)
aMesh = myActor->GetObject()->GetMesh();
mySimulation->SetVisibility(false);
- // hilight entered nodes
+ // highlight entered nodes
SMDS_Mesh* aMesh = 0;
if (myActor)
aMesh = myActor->GetObject()->GetMesh();
buttonOk->setEnabled(false);
buttonApply->setEnabled(false);
- // hilight entered elements
+ // highlight entered elements
SMDS_Mesh* aMesh = 0;
if (myActor)
aMesh = myActor->GetObject()->GetMesh();
buttonOk->setEnabled( false );
buttonApply->setEnabled( false );
- // check entered ids of faces and hilight them
+ // check entered ids of faces and highlight them
QStringList aListId;
if ( aMesh ) {
TColStd_MapOfInteger newIndices;
myBusy = true;
- // hilight entered elements/nodes
+ // highlight entered elements/nodes
myIDSource[ iType ]->length( 0 );
}
//================================================================================
/*!
- * \brief hilight found selected elements
+ * \brief highlight found selected elements
*/
//================================================================================
*/
/*!
- \brief Contructor
+ \brief Constructor
*/
GrpComputor::GrpComputor( SMESH::SMESH_GroupBase_ptr grp,
QTreeWidgetItem* item,
activateSelection();
}
- // hilight entered elements/nodes
+ // highlight entered elements/nodes
SMDS_Mesh* aMesh = 0;
SMESH_Actor* anActor = SMESH::FindActorByObject(myMesh);
if (anActor)
if (myListBox->item(i)->isSelected())
{
int anId = myListBox->item(i)->text().toInt();
- if (anObj->GetElemVTKId(anId) >= 0) // avoid exception in hilight
+ if (anObj->GetElemVTKId(anId) >= 0) // avoid exception in highlight
anIndexes.Add(anId);
}
}
--- /dev/null
+// Copyright (C) 2007-2016 CEA/DEN, EDF R&D, OPEN CASCADE
+//
+// 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, or (at your option) any later version.
+//
+// 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
+//
+// File : SMESHGUI_OffsetDlg.cxx
+
+// SMESH includes
+
+#include "SMESHGUI_OffsetDlg.h"
+
+#include "SMESHGUI.h"
+#include "SMESHGUI_SpinBox.h"
+#include "SMESHGUI_Utils.h"
+#include "SMESHGUI_VTKUtils.h"
+#include "SMESHGUI_MeshUtils.h"
+#include "SMESHGUI_IdValidator.h"
+#include "SMESHGUI_FilterDlg.h"
+#include "SMESHGUI_MeshEditPreview.h"
+
+#include <SMESH_Actor.h>
+#include <SMESH_TypeFilter.hxx>
+#include <SMESH_LogicalFilter.hxx>
+#include <SMDS_Mesh.hxx>
+
+// SALOME GUI includes
+#include <LightApp_Application.h>
+#include <LightApp_SelectionMgr.h>
+#include <SALOME_ListIO.hxx>
+#include <SUIT_Desktop.h>
+#include <SUIT_MessageBox.h>
+#include <SUIT_OverrideCursor.h>
+#include <SUIT_ResourceMgr.h>
+#include <SUIT_Session.h>
+#include <SVTK_ViewModel.h>
+#include <SVTK_ViewWindow.h>
+#include <SalomeApp_Tools.h>
+
+// SALOME KERNEL includes
+#include <SALOMEDSClient.hxx>
+#include <SALOMEDSClient_SObject.hxx>
+
+// OCCT includes
+#include <TColStd_MapOfInteger.hxx>
+
+// Qt includes
+#include <QApplication>
+#include <QButtonGroup>
+#include <QGroupBox>
+#include <QLabel>
+#include <QLineEdit>
+#include <QPushButton>
+#include <QRadioButton>
+#include <QCheckBox>
+#include <QHBoxLayout>
+#include <QVBoxLayout>
+#include <QGridLayout>
+#include <QSpinBox>
+#include <QKeyEvent>
+
+// IDL includes
+#include <SALOMEconfig.h>
+#include CORBA_SERVER_HEADER(SMESH_Group)
+#include CORBA_SERVER_HEADER(SMESH_MeshEditor)
+
+enum { MOVE_ELEMS_BUTTON = 0, COPY_ELEMS_BUTTON, MAKE_MESH_BUTTON }; //!< action type
+
+/*!
+ \class BusyLocker
+ \brief Simple 'busy state' flag locker.
+ \internal
+*/
+class BusyLocker
+{
+public:
+ //! Constructor. Sets passed boolean flag to \c true.
+ BusyLocker( bool& busy ) : myBusy( busy ) { myBusy = true; }
+ //! Destructor. Clear external boolean flag passed as parameter to the constructor to \c false.
+ ~BusyLocker() { myBusy = false; }
+private:
+ bool& myBusy; //! External 'busy state' boolean flag
+};
+
+#define SPACING 6
+#define MARGIN 11
+
+//=================================================================================
+// class : SMESHGUI_OffsetDlg()
+// purpose :
+//=================================================================================
+SMESHGUI_OffsetDlg::SMESHGUI_OffsetDlg( SMESHGUI* theModule ) :
+ SMESHGUI_MultiPreviewDlg( theModule ),
+ mySelectionMgr( SMESH::GetSelectionMgr( theModule ) ),
+ myFilterDlg(0)
+{
+ QPixmap image0 (SMESH::GetResourceMgr( mySMESHGUI )->loadPixmap("SMESH", tr("ICON_DLG_MESH_OFFSET")));
+ QPixmap image1 (SMESH::GetResourceMgr( mySMESHGUI )->loadPixmap("SMESH", tr("ICON_SELECT")));
+
+ setModal(false);
+ setAttribute(Qt::WA_DeleteOnClose, true);
+ setWindowTitle(tr("SMESH_OFFSET_TITLE"));
+ setSizeGripEnabled(true);
+
+ QVBoxLayout* dlgLayout = new QVBoxLayout(this);
+ dlgLayout->setSpacing(SPACING);
+ dlgLayout->setMargin(MARGIN);
+
+ /***************************************************************/
+ ConstructorsBox = new QGroupBox(tr("SMESH_OFFSET"), this);
+ QHBoxLayout* ConstructorsBoxLayout = new QHBoxLayout(ConstructorsBox);
+ ConstructorsBoxLayout->setSpacing(SPACING);
+ ConstructorsBoxLayout->setMargin(MARGIN);
+
+ QRadioButton* RadioButton1= new QRadioButton(ConstructorsBox);
+ RadioButton1->setIcon(image0);
+
+ ConstructorsBoxLayout->addWidget(RadioButton1);
+
+ /***************************************************************/
+ GroupArguments = new QGroupBox(tr("SMESH_ARGUMENTS"), this);
+ QGridLayout* GroupArgumentsLayout = new QGridLayout(GroupArguments);
+ GroupArgumentsLayout->setSpacing(SPACING);
+ GroupArgumentsLayout->setMargin(MARGIN);
+
+ myIdValidator = new SMESHGUI_IdValidator(this);
+
+ // Controls for elements selection
+ TextLabelElements = new QLabel(tr("SMESH_ID_ELEMENTS"), GroupArguments);
+ // SelectElementsButton = new QPushButton(GroupArguments);
+ // SelectElementsButton->setIcon(image1);
+ LineEditElements = new QLineEdit(GroupArguments);
+ LineEditElements->setValidator(myIdValidator);
+ LineEditElements->setMaxLength(-1);
+ myFilterBtn = new QPushButton( tr( "SMESH_BUT_FILTER" ), GroupArguments );
+ connect(myFilterBtn, SIGNAL(clicked()), this, SLOT(setFilters()));
+
+ // Control for the whole mesh selection
+ CheckBoxMesh = new QCheckBox(tr("SMESH_SELECT_WHOLE_MESH"), GroupArguments);
+
+ // offset
+ QLabel* TextLabel1 = new QLabel(tr("OFFSET_VALUE"), GroupArguments);
+ SpinBox = new SMESHGUI_SpinBox(GroupArguments);
+
+
+ // switch of action type
+ ActionBox = new QGroupBox(GroupArguments);
+ ActionGroup = new QButtonGroup(GroupArguments);
+ QVBoxLayout* ActionBoxLayout = new QVBoxLayout(ActionBox);
+ ActionBoxLayout->addSpacing(SPACING);
+ ActionBoxLayout->setMargin(MARGIN);
+
+ QRadioButton* aMoveElements = new QRadioButton(tr("SMESH_MOVE_ELEMENTS"), ActionBox);
+ QRadioButton* aCopyElements = new QRadioButton(tr("SMESH_COPY_ELEMENTS"), ActionBox);
+ QRadioButton* aCreateMesh = new QRadioButton(tr("SMESH_CREATE_MESH"), ActionBox);
+
+ ActionBoxLayout->addWidget(aMoveElements);
+ ActionBoxLayout->addWidget(aCopyElements);
+ ActionBoxLayout->addWidget(aCreateMesh);
+ ActionGroup->addButton(aMoveElements, MOVE_ELEMS_BUTTON);
+ ActionGroup->addButton(aCopyElements, COPY_ELEMS_BUTTON);
+ ActionGroup->addButton(aCreateMesh, MAKE_MESH_BUTTON);
+
+ // CheckBox for groups generation
+ MakeGroupsCheck = new QCheckBox(tr("SMESH_MAKE_GROUPS"), GroupArguments);
+ MakeGroupsCheck->setChecked(false);
+
+ // Name of a mesh to create
+ LineEditNewMesh = new QLineEdit(GroupArguments);
+
+ //Preview check box
+ myPreviewCheckBox = new QCheckBox(tr("PREVIEW"), GroupArguments);
+
+ // layout
+ GroupArgumentsLayout->addWidget(TextLabelElements, 0, 0);
+ //GroupArgumentsLayout->addWidget(SelectElementsButton, 0, 1);
+ GroupArgumentsLayout->addWidget(LineEditElements, 0, 2, 1, 5);
+ GroupArgumentsLayout->addWidget(myFilterBtn, 0, 7);
+ GroupArgumentsLayout->addWidget(CheckBoxMesh, 1, 0, 1, 8);
+ GroupArgumentsLayout->addWidget(TextLabel1, 2, 0);
+ GroupArgumentsLayout->addWidget(SpinBox, 2, 3);
+ GroupArgumentsLayout->addWidget(ActionBox, 3, 0, 3, 4);
+ GroupArgumentsLayout->addWidget(MakeGroupsCheck, 4, 5, 1, 4);
+ GroupArgumentsLayout->addWidget(LineEditNewMesh, 5, 5, 1, 4);
+ GroupArgumentsLayout->addWidget(myPreviewCheckBox, 6, 0);
+
+ /***************************************************************/
+ GroupButtons = new QGroupBox(this);
+ QHBoxLayout* GroupButtonsLayout = new QHBoxLayout(GroupButtons);
+ GroupButtonsLayout->setSpacing(SPACING);
+ GroupButtonsLayout->setMargin(MARGIN);
+
+ buttonOk = new QPushButton(tr("SMESH_BUT_APPLY_AND_CLOSE"), GroupButtons);
+ buttonOk->setAutoDefault(true);
+ buttonOk->setDefault(true);
+ buttonApply = new QPushButton(tr("SMESH_BUT_APPLY"), GroupButtons);
+ buttonApply->setAutoDefault(true);
+ buttonCancel = new QPushButton(tr("SMESH_BUT_CLOSE"), GroupButtons);
+ buttonCancel->setAutoDefault(true);
+ buttonHelp = new QPushButton(tr("SMESH_BUT_HELP"), GroupButtons);
+ buttonHelp->setAutoDefault(true);
+
+ GroupButtonsLayout->addWidget(buttonOk);
+ GroupButtonsLayout->addSpacing(10);
+ GroupButtonsLayout->addWidget(buttonApply);
+ GroupButtonsLayout->addSpacing(10);
+ GroupButtonsLayout->addStretch();
+ GroupButtonsLayout->addWidget(buttonCancel);
+ GroupButtonsLayout->addWidget(buttonHelp);
+
+ /***************************************************************/
+ dlgLayout->addWidget(ConstructorsBox);
+ dlgLayout->addWidget(GroupArguments);
+ dlgLayout->addWidget(GroupButtons);
+
+ /* Initialisations */
+ SpinBox->RangeStepAndValidator(COORD_MIN, COORD_MAX, 1.0, "length_precision");
+
+ RadioButton1->setChecked(true);
+
+ mySelector = (SMESH::GetViewWindow( mySMESHGUI ))->GetSelector();
+
+ mySMESHGUI->SetActiveDialogBox((QDialog*)this);
+
+ // Costruction of the logical filter
+ SMESH_TypeFilter* aMeshOrSubMeshFilter = new SMESH_TypeFilter (SMESH::MESHorSUBMESH);
+ SMESH_TypeFilter* aSmeshGroupFilter = new SMESH_TypeFilter (SMESH::GROUP);
+
+ QList<SUIT_SelectionFilter*> aListOfFilters;
+ if (aMeshOrSubMeshFilter) aListOfFilters.append(aMeshOrSubMeshFilter);
+ if (aSmeshGroupFilter) aListOfFilters.append(aSmeshGroupFilter);
+
+ myMeshOrSubMeshOrGroupFilter =
+ new SMESH_LogicalFilter(aListOfFilters, SMESH_LogicalFilter::LO_OR);
+
+ myHelpFileName = "Offset_page.html";
+
+ Init();
+
+ /* signals and slots connections */
+ connect(buttonOk, SIGNAL(clicked()), this, SLOT(ClickOnOk()));
+ connect(buttonCancel, SIGNAL(clicked()), this, SLOT(reject()));
+ connect(buttonApply, SIGNAL(clicked()), this, SLOT(ClickOnApply()));
+ connect(buttonHelp, SIGNAL(clicked()), this, SLOT(ClickOnHelp()));
+
+ //connect(SelectElementsButton, SIGNAL (clicked()), this, SLOT(SetEditCurrentArgument()));
+
+ connect(mySMESHGUI, SIGNAL (SignalDeactivateActiveDialog()), this, SLOT(DeactivateActiveDialog()));
+ connect(mySelectionMgr, SIGNAL(currentSelectionChanged()), this, SLOT(SelectionIntoArgument()));
+ /* to close dialog if study change */
+ connect(mySMESHGUI, SIGNAL(SignalCloseAllDialogs()), this, SLOT(reject()));
+ connect(mySMESHGUI, SIGNAL(SignalActivatedViewManager()), this, SLOT(onOpenView()));
+ connect(mySMESHGUI, SIGNAL(SignalCloseView()), this, SLOT(onCloseView()));
+
+ connect(LineEditElements, SIGNAL(textChanged(const QString&)), SLOT(onTextChange(const QString&)));
+ connect(CheckBoxMesh, SIGNAL(toggled(bool)), SLOT(onSelectMesh(bool)));
+ connect(ActionGroup, SIGNAL(buttonClicked(int)), SLOT(onActionClicked(int)));
+
+ connect(SpinBox, SIGNAL(valueChanged(double)), this, SLOT(toDisplaySimulation()));
+
+ //To Connect preview check box
+ connectPreviewControl();
+
+ SelectionIntoArgument();
+ onActionClicked(MOVE_ELEMS_BUTTON);
+}
+
+//=================================================================================
+// function : ~SMESHGUI_OffsetDlg()
+// purpose : Destroys the object and frees any allocated resources
+//=================================================================================
+SMESHGUI_OffsetDlg::~SMESHGUI_OffsetDlg()
+{
+ if ( myFilterDlg ) {
+ myFilterDlg->setParent( 0 );
+ delete myFilterDlg;
+ myFilterDlg = 0;
+ }
+}
+
+//=================================================================================
+// function : Init()
+// purpose :
+//=================================================================================
+void SMESHGUI_OffsetDlg::Init (bool ResetControls)
+{
+ myBusy = false;
+ myObjects.clear();
+ myObjectsNames.clear();
+ myMeshes.clear();
+
+ LineEditElements->clear();
+ myElementsId = "";
+ myNbOkElements = 0;
+
+ buttonOk->setEnabled(false);
+ buttonApply->setEnabled(false);
+
+ myActor = 0;
+
+ if (ResetControls)
+ {
+ SpinBox->SetValue(1.0);
+ myPreviewCheckBox->setChecked(false);
+ onDisplaySimulation(false);
+
+ ActionGroup->button( MOVE_ELEMS_BUTTON )->setChecked(true);
+ CheckBoxMesh->setChecked(true);
+ onSelectMesh(true);
+ }
+}
+
+//=================================================================================
+// function : ClickOnApply()
+// purpose :
+//=================================================================================
+bool SMESHGUI_OffsetDlg::ClickOnApply()
+{
+ if (mySMESHGUI->isActiveStudyLocked())
+ return false;
+
+ if( !isValid() )
+ return false;
+
+ SUIT_OverrideCursor aWaitCursor;
+
+ if (myNbOkElements)
+ {
+ QStringList aListElementsId = myElementsId.split(" ", QString::SkipEmptyParts);
+
+ SMESH::long_array_var anElementsId = new SMESH::long_array;
+ anElementsId->length(aListElementsId.count());
+ for (int i = 0; i < aListElementsId.count(); i++)
+ anElementsId[i] = aListElementsId[i].toInt();
+
+ double offsetValue = SpinBox->value();
+
+ QStringList aParameters;
+ aParameters << SpinBox->text();
+
+ int actionButton = ActionGroup->checkedId();
+ bool makeGroups = ( MakeGroupsCheck->isEnabled() && MakeGroupsCheck->isChecked() );
+ SMESH::ListOfGroups_var groups;
+ SMESH::SMESH_Mesh_var mesh;
+ QStringList anEntryList;
+ try
+ {
+ switch ( actionButton ) {
+
+ case MOVE_ELEMS_BUTTON:
+ if ( CheckBoxMesh->isChecked() )
+ for ( int i = 0; i < myObjects.count(); i++ ) {
+ SMESH::SMESH_MeshEditor_var aMeshEditor = myMeshes[i]->GetMeshEditor();
+ myMeshes[i]->SetParameters( aParameters.join( ":" ).toLatin1().constData() );
+ mesh = aMeshEditor->Offset( myObjects[i], offsetValue, true, "", groups.out() );
+ }
+ else {
+ SMESH::SMESH_MeshEditor_var aMeshEditor = myMeshes[0]->GetMeshEditor();
+ SMESH::IDSource_wrap src = aMeshEditor->MakeIDSource(anElementsId, SMESH::FACE);
+ myMeshes[0]->SetParameters( aParameters.join( ":" ).toLatin1().constData() );
+ mesh = aMeshEditor->Offset( src, offsetValue, true, "", groups.out() );
+ }
+ break;
+
+ case COPY_ELEMS_BUTTON:
+ if ( CheckBoxMesh->isChecked() )
+ for ( int i = 0; i < myObjects.count(); i++ ) {
+ SMESH::SMESH_MeshEditor_var aMeshEditor = myMeshes[i]->GetMeshEditor();
+ myMeshes[i]->SetParameters(aParameters.join( ":" ).toLatin1().constData());
+ mesh = aMeshEditor->Offset( myObjects[i], offsetValue, makeGroups, "", groups.out() );
+ }
+ else {
+ SMESH::SMESH_MeshEditor_var aMeshEditor = myMeshes[0]->GetMeshEditor();
+ SMESH::IDSource_wrap src = aMeshEditor->MakeIDSource(anElementsId, SMESH::FACE );
+ myMeshes[0]->SetParameters(aParameters.join( ":" ).toLatin1().constData());
+ mesh = aMeshEditor->Offset( src, offsetValue, makeGroups, "", groups.out() );
+ }
+ break;
+
+ case MAKE_MESH_BUTTON: {
+ SMESH::SMESH_Mesh_var mesh;
+ if ( CheckBoxMesh->isChecked() ) {
+ for ( int i = 0; i < myObjects.count(); i++ ) {
+ QString aName =
+ SMESH::UniqueMeshName( LineEditNewMesh->text().replace( "*", myObjectsNames[i] ));
+ SMESH::SMESH_MeshEditor_var aMeshEditor = myMeshes[i]->GetMeshEditor();
+ myMeshes[i]->SetParameters(aParameters.join( ":" ).toLatin1().constData());
+ mesh = aMeshEditor->Offset( myObjects[i], offsetValue, makeGroups,
+ aName.toLatin1().data(), groups.out() );
+ if( _PTR(SObject) aSObject = SMESH::ObjectToSObject( mesh ))
+ anEntryList.append( aSObject->GetID().c_str() );
+ }
+ }
+ else {
+ SMESH::SMESH_MeshEditor_var aMeshEditor = myMeshes[0]->GetMeshEditor();
+ myMeshes[0]->SetParameters(aParameters.join( ":" ).toLatin1().constData());
+ SMESH::IDSource_wrap src = aMeshEditor->MakeIDSource(anElementsId, SMESH::FACE );
+ mesh = aMeshEditor->Offset( src, offsetValue, makeGroups,
+ LineEditNewMesh->text().toLatin1().data(), groups.out() );
+ if( _PTR(SObject) aSObject = SMESH::ObjectToSObject( mesh ) )
+ anEntryList.append( aSObject->GetID().c_str() );
+ }
+ break;
+ }
+ }
+ }
+ catch ( const SALOME::SALOME_Exception& S_ex ) {
+ SalomeApp_Tools::QtCatchCorbaException( S_ex );
+ }
+ catch (...) {
+ }
+
+ for ( int i = 0; i < myObjects.count(); i++ ) {
+ SMESH_Actor* actor = SMESH::FindActorByObject( myObjects[i] );
+ if ( actor ) SMESH::Update( actor->getIO(), true );
+ }
+
+ if ( makeGroups || actionButton == MAKE_MESH_BUTTON )
+ {
+ mySMESHGUI->updateObjBrowser(true); // new groups may appear
+ if( LightApp_Application* anApp =
+ dynamic_cast<LightApp_Application*>( SUIT_Session::session()->activeApplication() ) )
+ anApp->browseObjects( anEntryList, isApplyAndClose() );
+ }
+ if ( !isApplyAndClose() )
+ {
+ Init(false);
+ SelectionIntoArgument();
+ }
+ SMESHGUI::Modified();
+ }
+
+ return true;
+}
+
+//=================================================================================
+// function : ClickOnOk()
+// purpose :
+//=================================================================================
+void SMESHGUI_OffsetDlg::ClickOnOk()
+{
+ setIsApplyAndClose( true );
+ if( ClickOnApply() )
+ reject();
+}
+
+//=================================================================================
+// function : reject()
+// purpose :
+//=================================================================================
+void SMESHGUI_OffsetDlg::reject()
+{
+ disconnect(mySelectionMgr, 0, this, 0);
+ mySelectionMgr->clearFilters();
+ if (SMESH::GetCurrentVtkView()) {
+ SMESH::RemoveFilters(); // PAL6938 -- clean all mesh entity filters
+ SMESH::SetPointRepresentation(false);
+ }
+ if ( SVTK_ViewWindow* aViewWindow = SMESH::GetViewWindow( mySMESHGUI ))
+ aViewWindow->SetSelectionMode( ActorSelection );
+ mySMESHGUI->ResetState();
+ QDialog::reject();
+}
+
+//=================================================================================
+// function : onOpenView()
+// purpose :
+//=================================================================================
+void SMESHGUI_OffsetDlg::onOpenView()
+{
+ if ( mySelector ) {
+ SMESH::SetPointRepresentation(false);
+ }
+ else {
+ mySelector = SMESH::GetViewWindow( mySMESHGUI )->GetSelector();
+ ActivateThisDialog();
+ }
+}
+
+//=================================================================================
+// function : onCloseView()
+// purpose :
+//=================================================================================
+void SMESHGUI_OffsetDlg::onCloseView()
+{
+ DeactivateActiveDialog();
+ mySelector = 0;
+}
+
+//=================================================================================
+// function : ClickOnHelp()
+// purpose :
+//=================================================================================
+void SMESHGUI_OffsetDlg::ClickOnHelp()
+{
+ LightApp_Application* app = (LightApp_Application*)(SUIT_Session::session()->activeApplication());
+ if (app)
+ app->onHelpContextModule(mySMESHGUI ? app->moduleName(mySMESHGUI->moduleName()) : QString(""), myHelpFileName);
+ else {
+ QString platform;
+#ifdef WIN32
+ platform = "winapplication";
+#else
+ platform = "application";
+#endif
+ SUIT_MessageBox::warning(this, tr("WRN_WARNING"),
+ tr("EXTERNAL_BROWSER_CANNOT_SHOW_PAGE").
+ arg(app->resourceMgr()->stringValue("ExternalBrowser",
+ platform)).
+ arg(myHelpFileName));
+ }
+}
+
+//=======================================================================
+// function : onTextChange()
+// purpose :
+//=======================================================================
+
+void SMESHGUI_OffsetDlg::onTextChange (const QString& theNewText)
+{
+ if (myBusy) return;
+ BusyLocker lock( myBusy );
+
+ myNbOkElements = 0;
+
+ buttonOk->setEnabled(false);
+ buttonApply->setEnabled(false);
+
+ // hilight entered elements
+ SMDS_Mesh* aMesh = 0;
+ if (myActor)
+ aMesh = myActor->GetObject()->GetMesh();
+
+ if (aMesh) {
+ Handle(SALOME_InteractiveObject) anIO = myActor->getIO();
+
+ TColStd_MapOfInteger newIndices;
+
+ QStringList aListId = theNewText.split(" ", QString::SkipEmptyParts);
+ for (int i = 0; i < aListId.count(); i++)
+ {
+ if ( const SMDS_MeshElement * e = aMesh->FindElement(aListId[ i ].toInt()))
+ newIndices.Add( e->GetID() );
+ myNbOkElements++;
+ }
+
+ mySelector->AddOrRemoveIndex( anIO, newIndices, false );
+ if ( SVTK_ViewWindow* aViewWindow = SMESH::GetViewWindow( mySMESHGUI ))
+ aViewWindow->highlight( anIO, true, true );
+
+ myElementsId = theNewText;
+ }
+
+ if (myNbOkElements) {
+ buttonOk->setEnabled(true);
+ buttonApply->setEnabled(true);
+ }
+}
+
+//=================================================================================
+// function : SelectionIntoArgument()
+// purpose : Called when selection as changed or other case
+//=================================================================================
+void SMESHGUI_OffsetDlg::SelectionIntoArgument()
+{
+ if (myBusy) return;
+ if (myFilterDlg && myFilterDlg->isVisible()) return; // filter dlg active
+
+ BusyLocker lock( myBusy );
+
+ // clear
+ myActor = 0;
+ QString aString = "";
+ onDisplaySimulation(false);
+
+ LineEditElements->setText(aString);
+ myNbOkElements = 0;
+ buttonOk->setEnabled(false);
+ buttonApply->setEnabled(false);
+
+ if (!GroupButtons->isEnabled()) // inactive
+ return;
+
+ // get selected mesh
+ SALOME_ListIO aList;
+ mySelectionMgr->selectedObjects(aList);
+
+ int nbSel = aList.Extent();
+ if (nbSel < 1)
+ return;
+
+ myElementsId = "";
+ myObjects.clear();
+ myObjectsNames.clear();
+ myMeshes.clear();
+
+ for ( SALOME_ListIteratorOfListIO it( aList ); it.More(); it.Next() )
+ {
+ Handle(SALOME_InteractiveObject) IO = it.Value();
+ SMESH::SMESH_Mesh_var aMesh = SMESH::GetMeshByIO( IO );
+ if ( aMesh->_is_nil() || aMesh->NbFaces() == 0 )
+ return;
+
+ myActor = SMESH::FindActorByObject( aMesh );
+ if ( !myActor )
+ myActor = SMESH::FindActorByEntry( IO->getEntry() );
+
+ SMESH::SMESH_IDSource_var idSrc = SMESH::IObjectToInterface<SMESH::SMESH_IDSource>( IO );
+ if ( _PTR(SObject) obj = SMESH::FindSObject( idSrc ))
+ {
+ std::string name = obj->GetName();
+ if ( !name.empty() )
+ {
+ myObjects << idSrc;
+ myObjectsNames << name.c_str();
+ myMeshes << aMesh;
+ }
+ }
+ }
+
+ // MakeGroups is available if there are groups and "Copy"
+ int aNbGroups = 0;
+ for ( int i = 0; i < myMeshes.count(); i++ )
+ aNbGroups += myMeshes[i]->NbGroups();
+
+ if ( aNbGroups == 0 ) {
+ MakeGroupsCheck->setChecked(false);
+ MakeGroupsCheck->setEnabled(false);
+ }
+ else if ( ActionGroup->checkedId() != MOVE_ELEMS_BUTTON ) {
+ MakeGroupsCheck->setEnabled(true);
+ }
+
+ if (CheckBoxMesh->isChecked()) {
+ if (myMeshes.isEmpty())
+ return;
+ SMESH::GetNameOfSelectedIObjects( mySelectionMgr, aString );
+ }
+ else {
+ int aNbUnits = SMESH::GetNameOfSelectedElements(mySelector, aList.First(), aString);
+ myElementsId = aString;
+ if (aNbUnits < 1)
+ return;
+ }
+
+ myNbOkElements = true;
+
+ LineEditElements->setText(aString);
+ LineEditElements->repaint();
+ LineEditElements->setEnabled(false); // to fully update lineedit IPAL 19809
+ LineEditElements->setEnabled(true);
+ setNewMeshName();
+
+ buttonOk->setEnabled(true);
+ buttonApply->setEnabled(true);
+
+ onDisplaySimulation(true);
+}
+
+//=================================================================================
+// function : DeactivateActiveDialog()
+// purpose :
+//=================================================================================
+
+void SMESHGUI_OffsetDlg::DeactivateActiveDialog()
+{
+ if (ConstructorsBox->isEnabled())
+ {
+ ConstructorsBox->setEnabled(false);
+ GroupArguments->setEnabled(false);
+ GroupButtons->setEnabled(false);
+ mySMESHGUI->ResetState();
+ mySMESHGUI->SetActiveDialogBox(0);
+ }
+}
+
+//=================================================================================
+// function : ActivateThisDialog()
+// purpose :
+//=================================================================================
+
+void SMESHGUI_OffsetDlg::ActivateThisDialog()
+{
+ /* Emit a signal to deactivate the active dialog */
+ mySMESHGUI->EmitSignalDeactivateDialog();
+ ConstructorsBox->setEnabled(true);
+ GroupArguments->setEnabled(true);
+ GroupButtons->setEnabled(true);
+
+ mySMESHGUI->SetActiveDialogBox((QDialog*)this);
+
+ if ( SVTK_ViewWindow* aViewWindow = SMESH::GetViewWindow( mySMESHGUI ))
+ aViewWindow->SetSelectionMode( CellSelection );
+
+ SelectionIntoArgument();
+}
+
+//=================================================================================
+// function : enterEvent()
+// purpose :
+//=================================================================================
+
+void SMESHGUI_OffsetDlg::enterEvent (QEvent*)
+{
+ if (!ConstructorsBox->isEnabled()) {
+ SVTK_ViewWindow* aViewWindow = SMESH::GetViewWindow( mySMESHGUI );
+ if ( aViewWindow && !mySelector) {
+ mySelector = aViewWindow->GetSelector();
+ }
+ ActivateThisDialog();
+ }
+}
+
+//=======================================================================
+//function : onSelectMesh
+//purpose :
+//=======================================================================
+
+void SMESHGUI_OffsetDlg::onSelectMesh (bool toSelectMesh)
+{
+ if (toSelectMesh)
+ TextLabelElements->setText(tr("SMESH_NAME"));
+ else
+ TextLabelElements->setText(tr("SMESH_ID_ELEMENTS"));
+ myFilterBtn->setEnabled(!toSelectMesh);
+
+ mySelectionMgr->clearFilters();
+ SMESH::SetPointRepresentation(false);
+
+ if (toSelectMesh)
+ {
+ if ( SVTK_ViewWindow* aViewWindow = SMESH::GetViewWindow( mySMESHGUI ))
+ aViewWindow->SetSelectionMode( ActorSelection );
+ mySelectionMgr->installFilter( myMeshOrSubMeshOrGroupFilter );
+ LineEditElements->setReadOnly( true );
+ LineEditElements->setValidator( 0 );
+ }
+ else
+ {
+ if ( SVTK_ViewWindow* aViewWindow = SMESH::GetViewWindow( mySMESHGUI ))
+ aViewWindow->SetSelectionMode( FaceSelection );
+ LineEditElements->setReadOnly( false );
+ LineEditElements->setValidator( myIdValidator );
+ onTextChange(LineEditElements->text());
+ hidePreview();
+ }
+
+ SelectionIntoArgument();
+}
+
+//=======================================================================
+//function : onActionClicked
+//purpose : slot called when an action type changed
+//=======================================================================
+
+void SMESHGUI_OffsetDlg::onActionClicked(int button)
+{
+ int aNbGroups = 0;
+ for ( int i = 0; i < myMeshes.count(); i++ )
+ aNbGroups += myMeshes[i]->NbGroups();
+
+ switch ( button ) {
+ case MOVE_ELEMS_BUTTON:
+ MakeGroupsCheck->setEnabled(false);
+ LineEditNewMesh->setEnabled(false);
+ break;
+ case COPY_ELEMS_BUTTON:
+ LineEditNewMesh->setEnabled(false);
+ MakeGroupsCheck->setText( tr("SMESH_MAKE_GROUPS"));
+ MakeGroupsCheck->setEnabled( myMeshes.isEmpty() || aNbGroups > 0 );
+ break;
+ case MAKE_MESH_BUTTON:
+ LineEditNewMesh->setEnabled(true);
+ MakeGroupsCheck->setText( tr("SMESH_COPY_GROUPS"));
+ MakeGroupsCheck->setEnabled( myMeshes.isEmpty() || aNbGroups > 0 );
+ break;
+ }
+ setNewMeshName();
+ //toDisplaySimulation();
+}
+
+//=======================================================================
+//function : setNewMeshName
+//purpose : update contents of LineEditNewMesh
+//=======================================================================
+
+void SMESHGUI_OffsetDlg::setNewMeshName()
+{
+ LineEditNewMesh->setText("");
+ if ( LineEditNewMesh->isEnabled() && !myMeshes.isEmpty() ) {
+ QString name;
+ if ( CheckBoxMesh->isChecked() ) {
+ name = myObjects.count() > 1 ? "*" : LineEditElements->text();
+ }
+ else {
+ _PTR(SObject) meshSO = SMESH::FindSObject( myMeshes[0] );
+ name = meshSO->GetName().c_str();
+ }
+ if ( !name.isEmpty() )
+ LineEditNewMesh->setText( SMESH::UniqueMeshName( name, "Offset"));
+ }
+}
+
+//=================================================================================
+// function : keyPressEvent()
+// purpose :
+//=================================================================================
+
+void SMESHGUI_OffsetDlg::keyPressEvent( QKeyEvent* e )
+{
+ QDialog::keyPressEvent( e );
+ if ( e->isAccepted() )
+ return;
+
+ if ( e->key() == Qt::Key_F1 ) {
+ e->accept();
+ ClickOnHelp();
+ }
+}
+
+//=================================================================================
+// function : setFilters()
+// purpose : SLOT. Called when "Filter" button pressed.
+//=================================================================================
+
+void SMESHGUI_OffsetDlg::setFilters()
+{
+ if ( myMeshes.isEmpty() ) {
+ SUIT_MessageBox::critical(this, tr("SMESH_ERROR"), tr("NO_MESH_SELECTED"));
+ return;
+ }
+ if ( !myFilterDlg ) {
+ myFilterDlg = new SMESHGUI_FilterDlg( mySMESHGUI, SMESH::ALL );
+ connect(myFilterDlg, SIGNAL(Accepted()), SLOT(onFilterAccepted()));
+ }
+
+ myFilterDlg->Init( SMESH::FACE );
+ myFilterDlg->SetSelection();
+ myFilterDlg->SetMesh( myMeshes[0] );
+ myFilterDlg->SetSourceWg( LineEditElements );
+
+ myFilterDlg->show();
+}
+
+//=======================================================================
+// name : onFilterAccepted()
+// Purpose : SLOT. Called when Filter dlg closed with OK button.
+// Activate [Apply] if no Actor is available
+//=======================================================================
+
+void SMESHGUI_OffsetDlg::onFilterAccepted()
+{
+ if ( myMeshes.length() > 0 && !buttonOk->isEnabled() )
+ {
+ myElementsId = LineEditElements->text();
+ QStringList aListElementsId = myElementsId.split(" ", QString::SkipEmptyParts);
+ myNbOkElements = aListElementsId.count();
+ buttonOk->setEnabled ( myNbOkElements );
+ buttonApply->setEnabled( myNbOkElements );
+ }
+}
+
+//=================================================================================
+// function : isValid
+// purpose :
+//=================================================================================
+
+bool SMESHGUI_OffsetDlg::isValid()
+{
+ return true;
+}
+
+//=================================================================================
+// function : onDisplaySimulation
+// purpose : Show/Hide preview
+//=================================================================================
+void SMESHGUI_OffsetDlg::onDisplaySimulation( bool toDisplayPreview )
+{
+ SUIT_OverrideCursor aWaitCursor;
+
+ if (myPreviewCheckBox->isChecked() && toDisplayPreview)
+ {
+ if ( myNbOkElements && isValid() )
+ {
+ double offsetValue = SpinBox->value();
+
+ SMESH::ListOfGroups_var groups;
+ SMESH::SMESH_Mesh_var mesh;
+
+ try
+ {
+ QList<SMESH::MeshPreviewStruct_var> aMeshPreviewStruct;
+
+ if ( CheckBoxMesh->isChecked())
+ for ( int i = 0; i < myObjects.count(); i++ )
+ {
+ SMESH::SMESH_MeshEditor_var aMeshEditor = myMeshes[i]->GetMeshEditPreviewer();
+ mesh = aMeshEditor->Offset( myObjects[i], offsetValue, false, "", groups.out() );
+ aMeshPreviewStruct << aMeshEditor->GetPreviewData();
+ }
+ else
+ {
+ SMESH::long_array_var anElementsId = new SMESH::long_array;
+ QStringList aListElementsId = myElementsId.split(" ", QString::SkipEmptyParts);
+ anElementsId->length(aListElementsId.count());
+ for (int i = 0; i < aListElementsId.count(); i++)
+ anElementsId[i] = aListElementsId[i].toInt();
+
+ SMESH::SMESH_MeshEditor_var aMeshEditor = myMeshes[0]->GetMeshEditPreviewer();
+ SMESH::IDSource_wrap src = aMeshEditor->MakeIDSource(anElementsId, SMESH::FACE);
+ mesh = aMeshEditor->Offset( src, offsetValue, false, "", groups.out() );
+ aMeshPreviewStruct << aMeshEditor->GetPreviewData();
+ }
+ setSimulationPreview(aMeshPreviewStruct);
+
+ } catch (...) {
+ hidePreview();
+ }
+ } else {
+ hidePreview();
+ }
+ } else {
+ hidePreview();
+ }
+}
--- /dev/null
+// Copyright (C) 2007-2016 CEA/DEN, EDF R&D, OPEN CASCADE
+//
+// 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, or (at your option) any later version.
+//
+// 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
+//
+
+// SMESH SMESHGUI : GUI for SMESH component
+// File : SMESHGUI_OffsetDlg.h
+//
+#ifndef SMESHGUI_OffsetDLG_H
+#define SMESHGUI_OffsetDLG_H
+
+// SMESH includes
+#include "SMESH_SMESHGUI.hxx"
+#include "SMESHGUI_PreviewDlg.h"
+
+// IDL includes
+#include <SALOMEconfig.h>
+#include CORBA_SERVER_HEADER(SMESH_Mesh)
+
+class QButtonGroup;
+class QGroupBox;
+class QLabel;
+class QLineEdit;
+class QPushButton;
+class QRadioButton;
+class QCheckBox;
+class SMESHGUI;
+class SMESHGUI_IdValidator;
+class SMESHGUI_SpinBox;
+class SMESHGUI_FilterDlg;
+class SMESH_Actor;
+class SVTK_Selector;
+class LightApp_SelectionMgr;
+class SMESH_LogicalFilter;
+
+//=================================================================================
+// class : SMESHGUI_OffsetDlg
+// purpose :
+//=================================================================================
+class SMESHGUI_EXPORT SMESHGUI_OffsetDlg : public SMESHGUI_MultiPreviewDlg
+{
+ Q_OBJECT
+
+ public:
+ SMESHGUI_OffsetDlg( SMESHGUI* );
+ ~SMESHGUI_OffsetDlg();
+
+ private:
+ void Init( bool = true );
+ void enterEvent( QEvent* ); /* mouse enter the QWidget */
+ void keyPressEvent( QKeyEvent* );
+ int GetConstructorId();
+ void setNewMeshName();
+
+ bool isValid();
+ void getOffset( SMESH::PointStruct& thePoint,
+ SMESH::double_array_var& theOffsetFact);
+
+ SMESHGUI_IdValidator* myIdValidator;
+ LightApp_SelectionMgr* mySelectionMgr; /* User shape selection */
+ QString myElementsId;
+ int myNbOkElements; /* to check when elements are defined */
+
+ SVTK_Selector* mySelector;
+
+ QWidget* myEditCurrentArgument;
+
+ bool myBusy;
+ SMESH_Actor* myActor;
+ SMESH_LogicalFilter* myMeshOrSubMeshOrGroupFilter;
+
+ QList<SMESH::SMESH_IDSource_var> myObjects;
+ QList<QString> myObjectsNames;
+ QList<SMESH::SMESH_Mesh_var> myMeshes;
+
+
+ QGroupBox* ConstructorsBox;
+ QGroupBox* GroupButtons;
+ QPushButton* buttonOk;
+ QPushButton* buttonCancel;
+ QPushButton* buttonApply;
+ QPushButton* buttonHelp;
+ QGroupBox* GroupArguments;
+ QLabel* TextLabelElements;
+ //QPushButton* SelectElementsButton;
+ QLineEdit* LineEditElements;
+ QCheckBox* CheckBoxMesh;
+ SMESHGUI_SpinBox* SpinBox;
+ QGroupBox* ActionBox;
+ QButtonGroup* ActionGroup;
+ QCheckBox* MakeGroupsCheck;
+ QLineEdit* LineEditNewMesh;
+
+ QString myHelpFileName;
+
+ QPushButton* myFilterBtn;
+ SMESHGUI_FilterDlg* myFilterDlg;
+
+
+protected slots:
+ virtual void onDisplaySimulation( bool );
+ virtual void reject();
+ void onFilterAccepted();
+
+private slots:
+ void ClickOnOk();
+ bool ClickOnApply();
+ void ClickOnHelp();
+ void SelectionIntoArgument();
+ void DeactivateActiveDialog();
+ void ActivateThisDialog();
+ void onTextChange( const QString& );
+ void onSelectMesh( bool );
+ void onActionClicked( int );
+ void onOpenView();
+ void onCloseView();
+ void setFilters();
+};
+
+#endif // SMESHGUI_OffsetDLG_H
OpMergeNodes = 4405, // MENU MODIFICATION - TRANSFORMATION - MERGE NODES
OpMergeElements = 4406, // MENU MODIFICATION - TRANSFORMATION - MERGE ELEMENTS
OpDuplicateNodes = 4407, // MENU MODIFICATION - TRANSFORMATION - DUPLICATE NODES OR/AND ELEMENTS
+ OpOffset = 4408, // MENU MODIFICATION - TRANSFORMATION - OFFSET
OpMoveNode = 4500, // MENU MODIFICATION - MOVE NODE
OpDiagonalInversion = 4501, // MENU MODIFICATION - DIAGONAL INVERSION
OpUnionOfTwoTriangle = 4502, // MENU MODIFICATION - UNION OF TWO TRIANGLE
myNbOkElements = 0;
- // hilight entered elements
+ // highlight entered elements
if(myActor){
if(SMDS_Mesh* aMesh = myActor->GetObject()->GetMesh()){
Handle(SALOME_InteractiveObject) anIO = myActor->getIO();
myNbOkNodes = 0;
- // hilight entered nodes
+ // highlight entered nodes
if(myActor){
if(SMDS_Mesh* aMesh = myActor->GetObject()->GetMesh()){
Handle(SALOME_InteractiveObject) anIO = myActor->getIO();
buttonOk->setEnabled(false);
buttonApply->setEnabled(false);
- // hilight entered elements
+ // highlight entered elements
SMDS_Mesh* aMesh = 0;
if (myActor)
aMesh = myActor->GetObject()->GetMesh();
buttonOk->setEnabled(false);
buttonApply->setEnabled(false);
- // hilight entered elements
+ // highlight entered elements
SMDS_Mesh* aMesh = 0;
if (myActor)
aMesh = myActor->GetObject()->GetMesh();
// Purpose : Highlight object in 3d viewer
//=======================================================================
void SMESHGUI_SelectionOp::highlight( const Handle( SALOME_InteractiveObject )& obj,
- const bool hilight, const bool immediately )
+ const bool highlight, const bool immediately )
{
SVTK_ViewWindow* wnd = viewWindow();
if( wnd )
- wnd->highlight( obj, hilight, immediately );
+ wnd->highlight( obj, highlight, immediately );
}
//=======================================================================
//! Set selection mode in VTK viewer
void setSelectionMode( const Selection_Mode );
- //! Hilight object in VTK viewer
+ //! Highlight object in VTK viewer
void highlight( const Handle( SALOME_InteractiveObject )&,
const bool, const bool = true );
else if (send == LineEdit6)
myOk6 = false;
- // hilight entered elements/nodes
+ // highlight entered elements/nodes
SMDS_Mesh* aMesh = 0;
if (myActor)
myOkBtn->setEnabled(false);
myApplyBtn->setEnabled(false);
- // hilight entered edge
+ // highlight entered edge
if(myActor){
if(SMDS_Mesh* aMesh = myActor->GetObject()->GetMesh()){
Handle(SALOME_InteractiveObject) anIO = myActor->getIO();
buttonOk->setEnabled(false);
buttonApply->setEnabled(false);
- // hilight entered elements/nodes
+ // highlight entered elements/nodes
SMDS_Mesh* aMesh = myActor ? myActor->GetObject()->GetMesh() : 0;
QStringList aListId = theNewText.split(" ", QString::SkipEmptyParts);
buttonOk->setEnabled(false);
buttonApply->setEnabled(false);
- // hilight entered elements
+ // highlight entered elements
SMDS_Mesh* aMesh = 0;
if (myActor)
aMesh = myActor->GetObject()->GetMesh();
buttonOk->setEnabled(false);
buttonApply->setEnabled(false);
- // hilight entered elements
+ // highlight entered elements
SMDS_Mesh* aMesh = 0;
if (myActor)
aMesh = myActor->GetObject()->GetMesh();
<source>ICON_DLG_MESH_SCALE</source>
<translation>scale.png</translation>
</message>
+ <message>
+ <source>ICON_DLG_MESH_OFFSET</source>
+ <translation>mesh_offset.png</translation>
+ </message>
<message>
<source>ICON_DLG_SCALE_ALONG_AXES</source>
<translation>scale_along_axes.png</translation>
<source>MEN_SCALE</source>
<translation>Scale Transform</translation>
</message>
+ <message>
+ <source>MEN_OFFSET</source>
+ <translation>Offset</translation>
+ </message>
<message>
<source>MEN_DUPLICATE_NODES</source>
<translation>Duplicate Nodes or/and Elements</translation>
<translation>Hexahedrons</translation>
</message>
<message>
- <source>SMESH_HILIGHT_COLOR</source>
+ <source>SMESH_HIGHLIGHT_COLOR</source>
<translation>Highlight Color</translation>
</message>
<message>
<source>STB_SCALE</source>
<translation>Scale Transform</translation>
</message>
+ <message>
+ <source>STB_OFFSET</source>
+ <translation>Offset</translation>
+ </message>
<message>
<source>STB_DUPLICATE_NODES</source>
<translation>Duplicate Nodes or/and Elements</translation>
<source>TOP_SCALE</source>
<translation>Scale Transform</translation>
</message>
+ <message>
+ <source>TOP_OFFSET</source>
+ <translation>Offset</translation>
+ </message>
<message>
<source>TOP_DUPLICATE_NODES</source>
<translation>Duplicate Nodes or/and Elements</translation>
<translation>Export Fields</translation>
</message>
</context>
+<context>
+ <name>SMESHGUI_OffsetDlg</name>
+ <message>
+ <source>SMESH_OFFSET_TITLE</source>
+ <translation>Offset</translation>
+ </message>
+ <message>
+ <source>SMESH_OFFSET</source>
+ <translation>Offset</translation>
+ </message>
+ <message>
+ <source>OFFSET_VALUE</source>
+ <translation>Offset Value</translation>
+ </message>
+</context>
<context>
<name>SMESHGUI_AddMeshElementDlg</name>
<message>
<translation>Hexaèdres</translation>
</message>
<message>
- <source>SMESH_HILIGHT_COLOR</source>
+ <source>SMESH_HIGHLIGHT_COLOR</source>
<translation>Couleur de sélection</translation>
</message>
<message>
<translation>六面体</translation>
</message>
<message>
- <source>SMESH_HILIGHT_COLOR</source>
+ <source>SMESH_HIGHLIGHT_COLOR</source>
<translation>選択色</translation>
</message>
<message>
SMESH_MeshAlgos.hxx
SMESH_MAT2d.hxx
SMESH_ControlPnt.hxx
-)
+ )
# --- sources ---
SMESH_FreeBorders.cxx
SMESH_ControlPnt.cxx
SMESH_FillHole.cxx
-)
+ SMESH_Triangulate.cxx
+ SMESH_Offset.cxx
+ )
# --- rules ---
//-------------------------------------------------------------------------------------
// type of Branch end point
enum BranchEndType { BE_UNDEF,
- BE_ON_VERTEX, // branch ends at a convex VRTEX
+ BE_ON_VERTEX, // branch ends at a convex VERTEX
BE_BRANCH_POINT, // branch meats 2 or more other branches
BE_END // branch end equidistant from several adjacent segments
};
#include <limits>
#include <numeric>
-using namespace std;
+#include <boost/container/flat_set.hpp>
//=======================================================================
/*!
*/
const SMDS_MeshNode* FindClosestTo( const gp_Pnt& thePnt )
{
- map<double, const SMDS_MeshNode*> dist2Nodes;
+ std::map<double, const SMDS_MeshNode*> dist2Nodes;
myOctreeNode->NodesAround( thePnt.Coord(), dist2Nodes, myHalfLeafSize );
if ( !dist2Nodes.empty() )
return dist2Nodes.begin()->second;
- list<const SMDS_MeshNode*> nodes;
+ std::list<const SMDS_MeshNode*> nodes;
//myOctreeNode->NodesAround( &tgtNode, &nodes, myHalfLeafSize );
double minSqDist = DBL_MAX;
if ( nodes.empty() ) // get all nodes of OctreeNode's closest to thePnt
{
// sort leafs by their distance from thePnt
- typedef map< double, SMESH_OctreeNode* > TDistTreeMap;
+ typedef std::map< double, SMESH_OctreeNode* > TDistTreeMap;
TDistTreeMap treeMap;
- list< SMESH_OctreeNode* > treeList;
- list< SMESH_OctreeNode* >::iterator trIt;
+ std::list< SMESH_OctreeNode* > treeList;
+ std::list< SMESH_OctreeNode* >::iterator trIt;
treeList.push_back( myOctreeNode );
gp_XYZ pointNode( thePnt.X(), thePnt.Y(), thePnt.Z() );
{
const Bnd_B3d& box = *tree->getBox();
double sqDist = thePnt.SquareDistance( 0.5 * ( box.CornerMin() + box.CornerMax() ));
- pair<TDistTreeMap::iterator,bool> it_in = treeMap.insert( make_pair( sqDist, tree ));
+ std::pair<TDistTreeMap::iterator,bool> it_in =
+ treeMap.insert( std::make_pair( sqDist, tree ));
if ( !it_in.second ) // not unique distance to box center
- treeMap.insert( it_in.first, make_pair( sqDist + 1e-13*treeMap.size(), tree ));
+ 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 closest among nodes
minSqDist = DBL_MAX;
const SMDS_MeshNode* closestNode = 0;
- list<const SMDS_MeshNode*>::iterator nIt = nodes.begin();
+ std::list<const SMDS_MeshNode*>::iterator nIt = nodes.begin();
for ( ; nIt != nodes.end(); ++nIt ) {
double sqDist = thePnt.SquareDistance( SMESH_TNodeXYZ( *nIt ) );
if ( minSqDist > sqDist ) {
{
public:
+ typedef boost::container::flat_set< const SMDS_MeshElement* > TElemSeq;
+
ElementBndBoxTree(const SMDS_Mesh& mesh,
SMDSAbs_ElementType elemType,
SMDS_ElemIteratorPtr theElemIt = SMDS_ElemIteratorPtr(),
double tolerance = NodeRadius );
- void getElementsNearPoint( const gp_Pnt& point, vector<const SMDS_MeshElement*>& foundElems );
- void getElementsNearLine ( const gp_Ax1& line, vector<const SMDS_MeshElement*>& foundElems);
- void getElementsInSphere ( const gp_XYZ& center,
- const double radius,
- vector<const SMDS_MeshElement*>& foundElems);
+ void getElementsNearPoint( const gp_Pnt& point, TElemSeq& foundElems );
+ void getElementsNearLine ( const gp_Ax1& line, TElemSeq& foundElems );
+ void getElementsInBox ( const Bnd_B3d& box, TElemSeq& foundElems );
+ void getElementsInSphere ( const gp_XYZ& center, const double radius, TElemSeq& foundElems );
ElementBndBoxTree* getLeafAtPoint( const gp_XYZ& point );
protected:
struct ElementBox : public Bnd_B3d
{
const SMDS_MeshElement* _element;
- bool _isMarked;
void init(const SMDS_MeshElement* elem, double tolerance);
};
- vector< ElementBox* > _elements;
+ std::vector< ElementBox* > _elements;
typedef ObjectPool< ElementBox > TElementBoxPool;
struct LimitAndPool : public SMESH_TreeLimit
{
TElementBoxPool _elBoPool;
- std::vector< ElementBox* > _markedElems;
LimitAndPool():SMESH_TreeLimit( MaxLevel, /*minSize=*/0. ), _elBoPool(1024) {}
};
LimitAndPool* getLimitAndPool() const
*/
//================================================================================
- void ElementBndBoxTree::getElementsNearPoint( const gp_Pnt& point,
- vector<const SMDS_MeshElement*>& foundElems)
+ void ElementBndBoxTree::getElementsNearPoint( const gp_Pnt& point, TElemSeq& foundElems)
{
if ( getBox()->IsOut( point.XYZ() ))
return;
if ( isLeaf() )
{
- LimitAndPool* pool = getLimitAndPool();
-
for ( size_t i = 0; i < _elements.size(); ++i )
- if ( !_elements[i]->IsOut( point.XYZ() ) &&
- !_elements[i]->_isMarked )
- {
- foundElems.push_back( _elements[i]->_element );
- _elements[i]->_isMarked = true;
- pool->_markedElems.push_back( _elements[i] );
- }
+ if ( !_elements[i]->IsOut( point.XYZ() ))
+ foundElems.insert( _elements[i]->_element );
}
else
{
for (int i = 0; i < 8; i++)
((ElementBndBoxTree*) myChildren[i])->getElementsNearPoint( point, foundElems );
-
- if ( level() == 0 )
- {
- LimitAndPool* pool = getLimitAndPool();
- for ( size_t i = 0; i < pool->_markedElems.size(); ++i )
- pool->_markedElems[i]->_isMarked = false;
- pool->_markedElems.clear();
- }
}
}
*/
//================================================================================
- void ElementBndBoxTree::getElementsNearLine( const gp_Ax1& line,
- vector<const SMDS_MeshElement*>& foundElems)
+ void ElementBndBoxTree::getElementsNearLine( const gp_Ax1& line, TElemSeq& foundElems )
{
if ( getBox()->IsOut( line ))
return;
if ( isLeaf() )
{
- LimitAndPool* pool = getLimitAndPool();
-
for ( size_t i = 0; i < _elements.size(); ++i )
- if ( !_elements[i]->IsOut( line ) &&
- !_elements[i]->_isMarked )
- {
- foundElems.push_back( _elements[i]->_element );
- _elements[i]->_isMarked = true;
- pool->_markedElems.push_back( _elements[i] );
- }
+ if ( !_elements[i]->IsOut( line ) )
+ foundElems.insert( _elements[i]->_element );
}
else
{
for (int i = 0; i < 8; i++)
((ElementBndBoxTree*) myChildren[i])->getElementsNearLine( line, foundElems );
-
- if ( level() == 0 )
- {
- LimitAndPool* pool = getLimitAndPool();
- for ( size_t i = 0; i < pool->_markedElems.size(); ++i )
- pool->_markedElems[i]->_isMarked = false;
- pool->_markedElems.clear();
- }
}
}
*/
//================================================================================
- void ElementBndBoxTree::getElementsInSphere ( const gp_XYZ& center,
- const double radius,
- vector<const SMDS_MeshElement*>& foundElems)
+ void ElementBndBoxTree::getElementsInSphere ( const gp_XYZ& center,
+ const double radius,
+ TElemSeq& foundElems)
{
if ( getBox()->IsOut( center, radius ))
return;
if ( isLeaf() )
{
- LimitAndPool* pool = getLimitAndPool();
-
for ( size_t i = 0; i < _elements.size(); ++i )
- if ( !_elements[i]->IsOut( center, radius ) &&
- !_elements[i]->_isMarked )
- {
- foundElems.push_back( _elements[i]->_element );
- _elements[i]->_isMarked = true;
- pool->_markedElems.push_back( _elements[i] );
- }
+ if ( !_elements[i]->IsOut( center, radius ))
+ foundElems.insert( _elements[i]->_element );
}
else
{
for (int i = 0; i < 8; i++)
((ElementBndBoxTree*) myChildren[i])->getElementsInSphere( center, radius, foundElems );
+ }
+ }
- if ( level() == 0 )
- {
- LimitAndPool* pool = getLimitAndPool();
- for ( size_t i = 0; i < pool->_markedElems.size(); ++i )
- pool->_markedElems[i]->_isMarked = false;
- pool->_markedElems.clear();
- }
+ //================================================================================
+ /*!
+ * \brief Return elements from leaves intersecting the box
+ */
+ //================================================================================
+
+ void ElementBndBoxTree::getElementsInBox( const Bnd_B3d& box, TElemSeq& foundElems )
+ {
+ if ( getBox()->IsOut( box ))
+ return;
+
+ if ( isLeaf() )
+ {
+ for ( size_t i = 0; i < _elements.size(); ++i )
+ if ( !_elements[i]->IsOut( box ))
+ foundElems.insert( _elements[i]->_element );
+ }
+ else
+ {
+ for (int i = 0; i < 8; i++)
+ ((ElementBndBoxTree*) myChildren[i])->getElementsInBox( box, foundElems );
}
}
void ElementBndBoxTree::ElementBox::init(const SMDS_MeshElement* elem, double tolerance)
{
_element = elem;
- _isMarked = false;
SMDS_ElemIteratorPtr nIt = elem->nodesIterator();
while ( nIt->more() )
Add( SMESH_NodeXYZ( nIt->next() ));
struct SMESH_ElementSearcherImpl: public SMESH_ElementSearcher
{
- SMDS_Mesh* _mesh;
- SMDS_ElemIteratorPtr _meshPartIt;
- ElementBndBoxTree* _ebbTree [SMDSAbs_NbElementTypes];
- int _ebbTreeHeight[SMDSAbs_NbElementTypes];
- SMESH_NodeSearcherImpl* _nodeSearcher;
- SMDSAbs_ElementType _elementType;
- double _tolerance;
- bool _outerFacesFound;
- set<const SMDS_MeshElement*> _outerFaces; // empty means "no internal faces at all"
+ SMDS_Mesh* _mesh;
+ SMDS_ElemIteratorPtr _meshPartIt;
+ ElementBndBoxTree* _ebbTree [SMDSAbs_NbElementTypes];
+ int _ebbTreeHeight[SMDSAbs_NbElementTypes];
+ SMESH_NodeSearcherImpl* _nodeSearcher;
+ SMDSAbs_ElementType _elementType;
+ double _tolerance;
+ bool _outerFacesFound;
+ std::set<const SMDS_MeshElement*> _outerFaces; // empty means "no internal faces at all"
SMESH_ElementSearcherImpl( SMDS_Mesh& mesh,
double tol=-1,
}
if ( _nodeSearcher ) delete _nodeSearcher; _nodeSearcher = 0;
}
- virtual int FindElementsByPoint(const gp_Pnt& point,
- SMDSAbs_ElementType type,
- vector< const SMDS_MeshElement* >& foundElements);
+ virtual int FindElementsByPoint(const gp_Pnt& point,
+ SMDSAbs_ElementType type,
+ std::vector< const SMDS_MeshElement* >& foundElements);
virtual TopAbs_State GetPointState(const gp_Pnt& point);
virtual const SMDS_MeshElement* FindClosestTo( const gp_Pnt& point,
SMDSAbs_ElementType type );
- virtual void GetElementsNearLine( const gp_Ax1& line,
- SMDSAbs_ElementType type,
- vector< const SMDS_MeshElement* >& foundElems);
- virtual void GetElementsInSphere( const gp_XYZ& center,
- const double radius,
- SMDSAbs_ElementType type,
- vector< const SMDS_MeshElement* >& foundElems);
+ virtual void GetElementsNearLine( const gp_Ax1& line,
+ SMDSAbs_ElementType type,
+ std::vector< const SMDS_MeshElement* >& foundElems);
+ virtual void GetElementsInSphere( const gp_XYZ& center,
+ const double radius,
+ SMDSAbs_ElementType type,
+ std::vector< const SMDS_MeshElement* >& foundElems);
+ virtual void GetElementsInBox( const Bnd_B3d& box,
+ SMDSAbs_ElementType type,
+ std::vector< const SMDS_MeshElement* >& foundElems);
virtual gp_XYZ Project(const gp_Pnt& point,
SMDSAbs_ElementType type,
const SMDS_MeshElement** closestElem);
while ( nodeIt->more() )
{
double dist = n1.Distance( static_cast<const SMDS_MeshNode*>( nodeIt->next() ));
- elemSize = max( dist, elemSize );
+ elemSize = std::max( dist, elemSize );
}
}
_tolerance = 1e-4 * elemSize;
// and BTW find out if there are internal faces at all.
// checked links and links where outer boundary meets internal one
- set< SMESH_TLink > visitedLinks, seamLinks;
+ std::set< SMESH_TLink > visitedLinks, seamLinks;
// links to treat with already visited faces sharing them
- list < TFaceLink > startLinks;
+ std::list < TFaceLink > startLinks;
// load startLinks with the first outerFace
startLinks.push_back( TFaceLink( outerFace->GetNode(0), outerFace->GetNode(1), outerFace));
// direction from the link inside outerFace
gp_Vec dirInOF = gp_Vec( ofNorm ) ^ n1n2;
// sort all other faces by angle with the dirInOF
- map< double, const SMDS_MeshElement* > angle2Face;
- set< const SMDS_MeshElement*, TIDCompare >::const_iterator face = faces.begin();
+ std::map< double, const SMDS_MeshElement* > angle2Face;
+ std::set< const SMDS_MeshElement*, TIDCompare >::const_iterator face = faces.begin();
for ( ; face != faces.end(); ++face )
{
if ( *face == outerFace ) continue;
gp_Vec dirInF = gp_Vec( fNorm ) ^ n1n2;
double angle = dirInOF.AngleWithRef( dirInF, n1n2 );
if ( angle < 0 ) angle += 2. * M_PI;
- angle2Face.insert( make_pair( angle, *face ));
+ angle2Face.insert( std::make_pair( angle, *face ));
}
if ( !angle2Face.empty() )
outerFace2 = angle2Face.begin()->second;
//=======================================================================
int SMESH_ElementSearcherImpl::
-FindElementsByPoint(const gp_Pnt& point,
- SMDSAbs_ElementType type,
- vector< const SMDS_MeshElement* >& foundElements)
+FindElementsByPoint(const gp_Pnt& point,
+ SMDSAbs_ElementType type,
+ std::vector< const SMDS_MeshElement* >& foundElements)
{
foundElements.clear();
_elementType = type;
{
_ebbTree[_elementType] = new ElementBndBoxTree( *_mesh, type, _meshPartIt, tolerance );
}
- vector< const SMDS_MeshElement* > suspectElems;
+ ElementBndBoxTree::TElemSeq suspectElems;
_ebbTree[ type ]->getElementsNearPoint( point, suspectElems );
- vector< const SMDS_MeshElement* >::iterator elem = suspectElems.begin();
+ ElementBndBoxTree::TElemSeq::iterator elem = suspectElems.begin();
for ( ; elem != suspectElems.end(); ++elem )
if ( !SMESH_MeshAlgos::IsOut( *elem, point, tolerance ))
foundElements.push_back( *elem );
if ( !ebbTree )
ebbTree = new ElementBndBoxTree( *_mesh, type, _meshPartIt );
- vector<const SMDS_MeshElement*> suspectElems;
+ ElementBndBoxTree::TElemSeq suspectElems;
ebbTree->getElementsNearPoint( point, suspectElems );
if ( suspectElems.empty() && ebbTree->maxSize() > 0 )
}
}
double minDist = std::numeric_limits<double>::max();
- multimap< double, const SMDS_MeshElement* > dist2face;
- vector<const SMDS_MeshElement*>::iterator elem = suspectElems.begin();
+ std::multimap< double, const SMDS_MeshElement* > dist2face;
+ ElementBndBoxTree::TElemSeq::iterator elem = suspectElems.begin();
for ( ; elem != suspectElems.end(); ++elem )
{
double dist = SMESH_MeshAlgos::GetDistance( *elem, point );
if ( dist < minDist + 1e-10)
{
minDist = dist;
- dist2face.insert( dist2face.begin(), make_pair( dist, *elem ));
+ dist2face.insert( dist2face.begin(), std::make_pair( dist, *elem ));
}
}
if ( !dist2face.empty() )
{
- multimap< double, const SMDS_MeshElement* >::iterator d2f = dist2face.begin();
+ std::multimap< double, const SMDS_MeshElement* >::iterator d2f = dist2face.begin();
closestElem = d2f->second;
// if there are several elements at the same distance, select one
// with GC closest to the point
const int nbAxes = 3;
gp_Dir axisDir[ nbAxes ] = { gp::DX(), gp::DY(), gp::DZ() };
- map< double, TInters > paramOnLine2TInters[ nbAxes ];
- list< TInters > tangentInters[ nbAxes ]; // of faces whose plane includes the line
- multimap< int, int > nbInt2Axis; // to find the simplest case
+ std::map< double, TInters > paramOnLine2TInters[ nbAxes ];
+ std::list< TInters > tangentInters[ nbAxes ]; // of faces whose plane includes the line
+ std::multimap< int, int > nbInt2Axis; // to find the simplest case
for ( int axis = 0; axis < nbAxes; ++axis )
{
gp_Ax1 lineAxis( point, axisDir[axis]);
gp_Lin line ( lineAxis );
- vector<const SMDS_MeshElement*> suspectFaces; // faces possibly intersecting the line
+ ElementBndBoxTree::TElemSeq suspectFaces; // faces possibly intersecting the line
ebbTree->getElementsNearLine( lineAxis, suspectFaces );
// Intersect faces with the line
- map< double, TInters > & u2inters = paramOnLine2TInters[ axis ];
- vector<const SMDS_MeshElement*>::iterator face = suspectFaces.begin();
+ std::map< double, TInters > & u2inters = paramOnLine2TInters[ axis ];
+ ElementBndBoxTree::TElemSeq::iterator face = suspectFaces.begin();
for ( ; face != suspectFaces.end(); ++face )
{
// get face plane
double tol = 1e-4 * Sqrt( fNorm.Modulus() );
gp_Pnt intersectionPoint = intersection.Point(1);
if ( !SMESH_MeshAlgos::IsOut( *face, intersectionPoint, tol ))
- u2inters.insert(make_pair( intersection.ParamOnConic(1), TInters( *face, fNorm )));
+ u2inters.insert( std::make_pair( intersection.ParamOnConic(1), TInters( *face, fNorm )));
}
}
// Analyse intersections roughly
if ( nbIntBeforePoint == 1 || nbIntAfterPoint == 1 )
return TopAbs_IN;
- nbInt2Axis.insert( make_pair( min( nbIntBeforePoint, nbIntAfterPoint ), axis ));
+ nbInt2Axis.insert( std::make_pair( std::min( nbIntBeforePoint, nbIntAfterPoint ), axis ));
if ( _outerFacesFound ) break; // pass to thorough analysis
for ( int hasPositionInfo = _outerFacesFound; hasPositionInfo < 2; ++hasPositionInfo )
{
- multimap< int, int >::const_iterator nb_axis = nbInt2Axis.begin();
+ std::multimap< int, int >::const_iterator nb_axis = nbInt2Axis.begin();
for ( ; nb_axis != nbInt2Axis.end(); ++nb_axis )
{
int axis = nb_axis->second;
- map< double, TInters > & u2inters = paramOnLine2TInters[ axis ];
+ std::map< double, TInters > & u2inters = paramOnLine2TInters[ axis ];
gp_Ax1 lineAxis( point, axisDir[axis]);
gp_Lin line ( lineAxis );
// add tangent intersections to u2inters
double param;
- list< TInters >::const_iterator tgtInt = tangentInters[ axis ].begin();
+ std::list< TInters >::const_iterator tgtInt = tangentInters[ axis ].begin();
for ( ; tgtInt != tangentInters[ axis ].end(); ++tgtInt )
if ( getIntersParamOnLine( line, tgtInt->_face, tolerance, param ))
- u2inters.insert(make_pair( param, *tgtInt ));
+ u2inters.insert( std::make_pair( param, *tgtInt ));
tangentInters[ axis ].clear();
// Count intersections before and after the point excluding touching ones.
// If hasPositionInfo we count intersections of outer boundary only
int nbIntBeforePoint = 0, nbIntAfterPoint = 0;
- double f = numeric_limits<double>::max(), l = -numeric_limits<double>::max();
- map< double, TInters >::iterator u_int1 = u2inters.begin(), u_int2 = u_int1;
+ double f = std::numeric_limits<double>::max(), l = -std::numeric_limits<double>::max();
+ std::map< double, TInters >::iterator u_int1 = u2inters.begin(), u_int2 = u_int1;
bool ok = ! u_int1->second._coincides;
while ( ok && u_int1 != u2inters.end() )
{
// decide if we skipped a touching intersection
if ( nbSamePnt + nbTgt > 0 )
{
- double minDot = numeric_limits<double>::max(), maxDot = -numeric_limits<double>::max();
- map< double, TInters >::iterator u_int = u_int1;
+ double minDot = std::numeric_limits<double>::max(), maxDot = -minDot;
+ std::map< double, TInters >::iterator u_int = u_int1;
for ( ; u_int != u_int2; ++u_int )
{
if ( u_int->second._coincides ) continue;
if ( !hasPositionInfo )
{
// gather info on faces position - is face in the outer boundary or not
- map< double, TInters > & u2inters = paramOnLine2TInters[ 0 ];
+ std::map< double, TInters > & u2inters = paramOnLine2TInters[ 0 ];
findOuterBoundary( u2inters.begin()->second._face );
}
*/
//=======================================================================
-void SMESH_ElementSearcherImpl::GetElementsNearLine( const gp_Ax1& line,
- SMDSAbs_ElementType type,
- vector< const SMDS_MeshElement* >& foundElems)
+void SMESH_ElementSearcherImpl::
+GetElementsNearLine( const gp_Ax1& line,
+ SMDSAbs_ElementType type,
+ std::vector< const SMDS_MeshElement* >& foundElems)
{
_elementType = type;
ElementBndBoxTree*& ebbTree = _ebbTree[ type ];
if ( !ebbTree )
ebbTree = new ElementBndBoxTree( *_mesh, _elementType, _meshPartIt );
- ebbTree->getElementsNearLine( line, foundElems );
+ ElementBndBoxTree::TElemSeq elems;
+ ebbTree->getElementsNearLine( line, elems );
+
+ foundElems.insert( foundElems.end(), elems.begin(), elems.end() );
}
//=======================================================================
*/
//=======================================================================
-void SMESH_ElementSearcherImpl::GetElementsInSphere( const gp_XYZ& center,
- const double radius,
- SMDSAbs_ElementType type,
- vector< const SMDS_MeshElement* >& foundElems)
+void SMESH_ElementSearcherImpl::
+GetElementsInSphere( const gp_XYZ& center,
+ const double radius,
+ SMDSAbs_ElementType type,
+ std::vector< const SMDS_MeshElement* >& foundElems)
{
_elementType = type;
ElementBndBoxTree*& ebbTree = _ebbTree[ type ];
if ( !ebbTree )
ebbTree = new ElementBndBoxTree( *_mesh, _elementType, _meshPartIt );
- ebbTree->getElementsInSphere( center, radius, foundElems );
+ ElementBndBoxTree::TElemSeq elems;
+ ebbTree->getElementsInSphere( center, radius, elems );
+
+ foundElems.insert( foundElems.end(), elems.begin(), elems.end() );
+}
+
+//=======================================================================
+/*
+ * Return elements whose bounding box intersects a given bounding box
+ */
+//=======================================================================
+
+void SMESH_ElementSearcherImpl::
+GetElementsInBox( const Bnd_B3d& box,
+ SMDSAbs_ElementType type,
+ std::vector< const SMDS_MeshElement* >& foundElems)
+{
+ _elementType = type;
+ ElementBndBoxTree*& ebbTree = _ebbTree[ type ];
+ if ( !ebbTree )
+ ebbTree = new ElementBndBoxTree( *_mesh, _elementType, _meshPartIt, getTolerance() );
+
+ ElementBndBoxTree::TElemSeq elems;
+ ebbTree->getElementsInBox( box, elems );
+
+ foundElems.insert( foundElems.end(), elems.begin(), elems.end() );
}
//=======================================================================
const Bnd_B3d* box = ebbLeaf->getBox();
double radius = ( box->CornerMax() - box->CornerMin() ).Modulus();
- vector< const SMDS_MeshElement* > elems;
+ ElementBndBoxTree::TElemSeq elems;
ebbTree->getElementsInSphere( p, radius, elems );
while ( elems.empty() )
{
gp_XYZ proj, bestProj;
const SMDS_MeshElement* elem = 0;
double minDist = 2 * radius;
- for ( size_t i = 0; i < elems.size(); ++i )
+ ElementBndBoxTree::TElemSeq::iterator e = elems.begin();
+ for ( ; e != elems.end(); ++e )
{
- double d = SMESH_MeshAlgos::GetDistance( elems[i], p, &proj );
+ double d = SMESH_MeshAlgos::GetDistance( *e, p, &proj );
if ( d < minDist )
{
bestProj = proj;
- elem = elems[i];
+ elem = *e;
minDist = d;
}
}
// get ordered nodes
- vector< SMESH_TNodeXYZ > xyz; xyz.reserve( element->NbNodes()+1 );
+ std::vector< SMESH_TNodeXYZ > xyz; xyz.reserve( element->NbNodes()+1 );
SMDS_ElemIteratorPtr nodeIt = element->interlacedNodesElemIterator();
for ( int i = 0; nodeIt->more(); ++i )
if ( n2pSize * n2pSize > fNormSize * 100 ) return true; // point is very far
plnNorm /= n2pSize;
// for each node of the face, compute its signed distance to the cutting plane
- vector<double> dist( nbNodes + 1);
+ std::vector<double> dist( nbNodes + 1);
for ( i = 0; i < nbNodes; ++i )
{
gp_Vec n2p( xyz[i], point );
// coordinates of nodes (medium nodes, if any, ignored)
typedef SMDS_StdIterator< SMESH_TNodeXYZ, SMDS_ElemIteratorPtr > TXyzIterator;
- vector<gp_XYZ> xyz( TXyzIterator( face->nodesIterator()), TXyzIterator() );
+ std::vector<gp_XYZ> xyz( TXyzIterator( face->nodesIterator()), TXyzIterator() );
xyz.resize( face->NbCornerNodes()+1 );
// transformation to get xyz[0] lies on the origin, xyz[1] lies on the Z axis,
trsf.SetTransformation( tgtCS );
// move all the nodes to 2D
- vector<gp_XY> xy( xyz.size() );
+ std::vector<gp_XY> xy( xyz.size() );
for ( size_t i = 0;i < xyz.size()-1; ++i )
{
gp_XYZ p3d = xyz[i];
gp_XY point2D( tmpPnt.X(), tmpPnt.Z() );
// loop on edges of the face to analyze point position ralative to the face
- set< PointPos > pntPosSet;
+ std::set< PointPos > pntPosSet;
for ( size_t i = 1; i < xy.size(); ++i )
{
PointPos pos = getPointPosition( point2D, &xy[0], i-1 );
gp_Vec n1p ( xyz[ pos._index ], point );
double u = ( edge * n1p ) / edge.SquareMagnitude(); // param [0,1] on the edge
// projection of the point on the edge
- gp_XYZ proj = ( 1. - u ) * xyz[ pos._index ] + u * xyz[ pos._index+1 ];
+ gp_XYZ proj = xyz[ pos._index ] + u * edge.XYZ();
if ( closestPnt ) *closestPnt = proj;
return point.Distance( proj );
}
int i = 0, nbNodes = seg->NbNodes();
- vector< SMESH_TNodeXYZ > xyz( nbNodes );
+ std::vector< SMESH_TNodeXYZ > xyz( nbNodes );
SMDS_ElemIteratorPtr nodeIt = seg->interlacedNodesElemIterator();
while ( nodeIt->more() )
xyz[ i++ ].Set( nodeIt->next() );
break;
}
default:
- vector<const SMDS_MeshNode *> nvec( nodes, nodes + vTool.NbFaceNodes( iF ));
+ std::vector<const SMDS_MeshNode *> nvec( nodes, nodes + vTool.NbFaceNodes( iF ));
SMDS_PolygonalFaceOfNodes tmpFace( nvec );
dist = GetDistance( &tmpFace, point, closestPnt );
}
}
else if ( n2 == prevN && n1 == n )
{
- face = elem; swap( i1, i2 );
+ face = elem; std::swap( i1, i2 );
}
prevN = n;
}
normal += ( p[2] - p[1] ) ^ ( p[0] - p[1] );
}
double size2 = normal.SquareModulus();
- bool ok = ( size2 > numeric_limits<double>::min() * numeric_limits<double>::min());
+ bool ok = ( size2 > std::numeric_limits<double>::min() * std::numeric_limits<double>::min());
if ( normalized && ok )
normal /= sqrt( size2 );
//purpose : Return nodes common to two elements
//=======================================================================
-vector< const SMDS_MeshNode*> SMESH_MeshAlgos::GetCommonNodes(const SMDS_MeshElement* e1,
- const SMDS_MeshElement* e2)
+std::vector< const SMDS_MeshNode*> SMESH_MeshAlgos::GetCommonNodes(const SMDS_MeshElement* e1,
+ const SMDS_MeshElement* e2)
{
- vector< const SMDS_MeshNode*> common;
+ std::vector< const SMDS_MeshNode*> common;
for ( int i = 0 ; i < e1->NbNodes(); ++i )
if ( e2->GetNodeIndex( e1->GetNode( i )) >= 0 )
common.push_back( e1->GetNode( i ));
// Author : Edward AGAPOV (eap)
// This file holds some low level algorithms extracted from SMESH_MeshEditor
-// to make them accessible from Controls package
+// to make them accessible from Controls package, and more
#ifndef __SMESH_MeshAlgos_HXX__
class gp_Pnt;
class gp_Ax1;
+class Bnd_B3d;
class SMDS_MeshNode;
class SMDS_MeshElement;
class SMDS_Mesh;
const double radius,
SMDSAbs_ElementType type,
std::vector< const SMDS_MeshElement* >& foundElems) = 0;
+ /*!
+ * \brief Return elements whose bounding box intersects a given bounding box
+ */
+ virtual void GetElementsInBox( const Bnd_B3d& box,
+ SMDSAbs_ElementType type,
+ std::vector< const SMDS_MeshElement* >& foundElems) = 0;
/*!
* \brief Find out if the given point is out of closed 2D mesh.
*/
namespace SMESH_MeshAlgos
{
+ /*!
+ * \brief Return SMESH_NodeSearcher. The caller is responsible for deleting it
+ */
+ SMESHUtils_EXPORT
+ SMESH_NodeSearcher* GetNodeSearcher( SMDS_Mesh& mesh );
+
+ SMESHUtils_EXPORT
+ SMESH_NodeSearcher* GetNodeSearcher( SMDS_ElemIteratorPtr elemIt );
+
+ /*!
+ * \brief Return SMESH_ElementSearcher. The caller is responsible for deleting it
+ */
+ SMESHUtils_EXPORT
+ SMESH_ElementSearcher* GetElementSearcher( SMDS_Mesh& mesh,
+ double tolerance=-1.);
+ SMESHUtils_EXPORT
+ SMESH_ElementSearcher* GetElementSearcher( SMDS_Mesh& mesh,
+ SMDS_ElemIteratorPtr elemIt,
+ double tolerance=-1. );
+
+
/*!
* \brief Return true if the point is IN or ON of the element
*/
const SMDS_MeshNode* node1 );
/*!
- * \brief Return SMESH_NodeSearcher. The caller is responsible for deleteing it
+ * \brief Mark elements given by SMDS_Iterator
*/
- SMESHUtils_EXPORT
- SMESH_NodeSearcher* GetNodeSearcher( SMDS_Mesh& mesh );
-
- SMESHUtils_EXPORT
- SMESH_NodeSearcher* GetNodeSearcher( SMDS_ElemIteratorPtr elemIt );
-
+ template< class ElemIter >
+ void MarkElems( ElemIter it, const bool isMarked )
+ {
+ while ( it->more() ) it->next()->setIsMarked( isMarked );
+ }
/*!
- * \brief Return SMESH_ElementSearcher. The caller is responsible for deleting it
+ * \brief Mark elements given by std iterators
*/
- SMESHUtils_EXPORT
- SMESH_ElementSearcher* GetElementSearcher( SMDS_Mesh& mesh,
- double tolerance=-1.);
- SMESHUtils_EXPORT
- SMESH_ElementSearcher* GetElementSearcher( SMDS_Mesh& mesh,
- SMDS_ElemIteratorPtr elemIt,
- double tolerance=-1. );
+ template< class ElemIter >
+ void MarkElems( ElemIter it, ElemIter end, const bool isMarked )
+ {
+ for ( ; it != end; ++it ) (*it)->setIsMarked( isMarked );
+ }
+ /*!
+ * \brief Mark nodes of elements given by SMDS_Iterator
+ */
+ template< class ElemIter >
+ void MarkElemNodes( ElemIter it, const bool isMarked, const bool markElem = false )
+ {
+ if ( markElem )
+ while ( it->more() ) {
+ const SMDS_MeshElement* e = it->next();
+ e->setIsMarked( isMarked );
+ MarkElems( e->nodesIterator(), isMarked );
+ }
+ else
+ while ( it->more() )
+ MarkElems( it->next()->nodesIterator(), isMarked );
+ }
+ /*!
+ * \brief Mark elements given by std iterators
+ */
+ template< class ElemIter >
+ void MarkElemNodes( ElemIter it, ElemIter end, const bool isMarked, const bool markElem = false )
+ {
+ if ( markElem )
+ for ( ; it != end; ++it ) {
+ (*it)->setIsMarked( isMarked );
+ MarkElems( (*it)->nodesIterator(), isMarked );
+ }
+ else
+ for ( ; it != end; ++it )
+ MarkElems( (*it)->nodesIterator(), isMarked );
+ }
* Returns TFreeBorder's coincident within the given tolerance.
* If the tolerance <= 0.0 then one tenth of an average size of elements adjacent
* to free borders being compared is used.
- *
- * (Implemented in ./SMESH_FreeBorders.cxx)
*/
SMESHUtils_EXPORT
void FindCoincidentFreeBorders(SMDS_Mesh& mesh,
double tolerance,
CoincidentFreeBorders & foundFreeBordes);
+ // Implemented in ./SMESH_FreeBorders.cxx
+
/*!
* Returns all or only closed TFreeBorder's.
* Optionally check if the mesh is manifold and if faces are correctly oriented.
- *
- * (Implemented in ./SMESH_FreeBorders.cxx)
*/
SMESHUtils_EXPORT
void FindFreeBorders(SMDS_Mesh& mesh,
std::vector<const SMDS_MeshElement*>& newFaces);
+ typedef std::vector< std::pair< const SMDS_MeshElement*, const SMDS_MeshElement* > > TEPairVec;
+ typedef std::vector< std::pair< const SMDS_MeshNode*, const SMDS_MeshNode* > > TNPairVec;
+ /*!
+ * \brief Create an offset mesh of given faces
+ * \param [in] faceIt - the input faces
+ * \param [in] theFixIntersections - to fix self intersections of the offset mesh or not
+ * \param [out] new2OldFaces - history of faces
+ * \param [out] new2OldNodes - history of nodes
+ * \return SMDS_Mesh* - the new offset mesh, a caller should delete
+ */
+ SMESHUtils_EXPORT
+ SMDS_Mesh* MakeOffset( SMDS_ElemIteratorPtr faceIt,
+ SMDS_Mesh& mesh,
+ const double offset,
+ const bool theFixIntersections,
+ TEPairVec& new2OldFaces,
+ TNPairVec& new2OldNodes );
+ // Implemented in ./SMESH_Offset.cxx
+
+
+ /*!
+ * \brief Divide a mesh face into triangles
+ */
+ // Implemented in ./SMESH_Triangulate.cxx
+
+ class SMESHUtils_EXPORT Triangulate
+ {
+ public:
+
+ static int GetNbTriangles( const SMDS_MeshElement* face );
+
+ int GetTriangles( const SMDS_MeshElement* face,
+ std::vector< const SMDS_MeshNode*>& nodes);
+ private:
+
+ bool triangulate( std::vector< const SMDS_MeshNode*>& nodes, const size_t nbNodes );
+
+ /*!
+ * \brief Vertex of a polygon. Together with 2 neighbor Vertices represents a triangle
+ */
+ struct PolyVertex
+ {
+ SMESH_NodeXYZ _nxyz;
+ gp_XY _xy;
+ PolyVertex* _prev;
+ PolyVertex* _next;
+
+ void SetNodeAndNext( const SMDS_MeshNode* n, PolyVertex& v );
+ void GetTriaNodes( const SMDS_MeshNode** nodes) const;
+ double TriaArea() const;
+ bool IsInsideTria( const PolyVertex* v );
+ PolyVertex* Delete();
+ };
+ std::vector< PolyVertex > _pv;
+ };
+
} // SMESH_MeshAlgos
#endif
--- /dev/null
+// Copyright (C) 2007-2016 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
+//
+// 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, or (at your option) any later version.
+//
+// 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
+//
+// File : SMESH_Offset.cxx
+// Created : Mon Dec 25 15:52:38 2017
+// Author : Edward AGAPOV (eap)
+
+#include "SMESH_MeshAlgos.hxx"
+
+#include <SMDS_PolygonalFaceOfNodes.hxx>
+#include "SMDS_Mesh.hxx"
+
+#include <Utils_SALOME_Exception.hxx>
+
+#include <Bnd_B3d.hxx>
+#include <NCollection_Map.hxx>
+#include <gp_Lin.hxx>
+#include <gp_Pln.hxx>
+
+#include <boost/container/flat_set.hpp>
+#include <boost/dynamic_bitset.hpp>
+
+namespace
+{
+ const size_t theMaxNbFaces = 256; // max number of faces sharing a node
+
+ typedef NCollection_DataMap< Standard_Address, const SMDS_MeshNode* > TNNMap;
+ typedef NCollection_Map< SMESH_Link, SMESH_Link > TLinkMap;
+
+ //--------------------------------------------------------------------------------
+ /*!
+ * \brief Intersected face side storing a node created at this intersection
+ * and a intersected face
+ */
+ struct CutLink
+ {
+ bool myReverse;
+ const SMDS_MeshNode* myNode[2]; // side nodes
+ mutable SMESH_NodeXYZ myIntNode; // intersection node
+ const SMDS_MeshElement* myFace; // cutter face
+ int myIndex; // index of a node on the same link
+
+ CutLink(const SMDS_MeshNode* node1=0,
+ const SMDS_MeshNode* node2=0,
+ const SMDS_MeshElement* face=0,
+ const int index=0) { Set ( node1, node2, face, index ); }
+
+ void Set( const SMDS_MeshNode* node1,
+ const SMDS_MeshNode* node2,
+ const SMDS_MeshElement* face,
+ const int index=0)
+ {
+ myNode[0] = node1; myNode[1] = node2; myFace = face; myIndex = index; myReverse = false;
+ if ( myNode[0] && ( myReverse = ( myNode[0]->GetID() > myNode[1]->GetID() )))
+ std::swap( myNode[0], myNode[1] );
+ }
+ const SMDS_MeshNode* IntNode() const { return myIntNode.Node(); }
+ const SMDS_MeshNode* Node1() const { return myNode[ myReverse ]; }
+ const SMDS_MeshNode* Node2() const { return myNode[ !myReverse ]; }
+
+ static Standard_Integer HashCode(const CutLink& link,
+ const Standard_Integer upper)
+ {
+ Standard_Integer n = ( link.myNode[0]->GetID() +
+ link.myNode[1]->GetID() +
+ link.myIndex );
+ return ::HashCode( n, upper );
+ }
+ static Standard_Boolean IsEqual(const CutLink& link1, const CutLink& link2 )
+ {
+ return ( link1.myNode[0] == link2.myNode[0] &&
+ link1.myNode[1] == link2.myNode[1] &&
+ link1.myIndex == link2.myIndex );
+ }
+ };
+
+ typedef NCollection_Map< CutLink, CutLink > TCutLinkMap;
+
+ //--------------------------------------------------------------------------------
+ /*!
+ * \brief Part of a divided face edge
+ */
+ struct EdgePart
+ {
+ const SMDS_MeshNode* myNode1;
+ const SMDS_MeshNode* myNode2;
+ int myIndex; // positive -> side index, negative -> State
+ const SMDS_MeshElement* myFace;
+
+ enum State { _INTERNAL = -1, _COPLANAR = -2 };
+
+ void Set( const SMDS_MeshNode* Node1,
+ const SMDS_MeshNode* Node2,
+ const SMDS_MeshElement* Face = 0,
+ int EdgeIndex = _INTERNAL )
+ { myNode1 = Node1; myNode2 = Node2; myIndex = EdgeIndex; myFace = Face; }
+
+ // bool HasSameNode( const EdgePart& other ) { return ( myNode1 == other.myNode1 ||
+ // myNode1 == other.myNode2 ||
+ // myNode2 == other.myNode1 ||
+ // myNode2 == other.myNode2 );
+ // }
+ bool IsInternal() const { return myIndex < 0; }
+ bool IsTwin( const EdgePart& e ) const { return myNode1 == e.myNode2 && myNode2 == e.myNode1; }
+ bool IsSame( const EdgePart& e ) const {
+ return (( myNode1 == e.myNode2 && myNode2 == e.myNode1 ) ||
+ ( myNode1 == e.myNode1 && myNode2 == e.myNode2 )); }
+ bool ReplaceCoplanar( const EdgePart& e );
+ operator SMESH_Link() const { return SMESH_Link( myNode1, myNode2 ); }
+ operator gp_Vec() const { return SMESH_NodeXYZ( myNode2 ) - SMESH_NodeXYZ( myNode1 ); }
+ };
+
+ //--------------------------------------------------------------------------------
+ /*!
+ * \brief Loop of EdgePart's forming a new face which is a part of CutFace
+ */
+ struct EdgeLoop : public SMDS_PolygonalFaceOfNodes
+ {
+ std::vector< const EdgePart* > myLinks;
+ bool myIsBndConnected; //!< is there a path to CutFace side edges
+ bool myHasPending; //!< an edge encounters twice
+
+ EdgeLoop() : SMDS_PolygonalFaceOfNodes( std::vector<const SMDS_MeshNode *>() ) {}
+ void Clear() { myLinks.clear(); myIsBndConnected = false; myHasPending = false; }
+ bool SetConnected() { bool was = myIsBndConnected; myIsBndConnected = true; return !was; }
+ bool Contains( const SMDS_MeshNode* n ) const
+ {
+ for ( size_t i = 0; i < myLinks.size(); ++i )
+ if ( myLinks[i]->myNode1 == n ) return true;
+ return false;
+ }
+ virtual int NbNodes() const { return myLinks.size(); }
+ virtual SMDS_ElemIteratorPtr nodesIterator() const
+ {
+ return setNodes(), SMDS_PolygonalFaceOfNodes::nodesIterator();
+ }
+ virtual SMDS_NodeIteratorPtr nodeIterator() const
+ {
+ return setNodes(), SMDS_PolygonalFaceOfNodes::nodeIterator();
+ }
+ void setNodes() const //!< set nodes to SMDS_PolygonalFaceOfNodes
+ {
+ EdgeLoop* me = const_cast<EdgeLoop*>( this );
+ me->myNodes.resize( NbNodes() );
+ size_t iMin = 0;
+ for ( size_t i = 1; i < myNodes.size(); ++i ) {
+ if ( myLinks[ i ]->myNode1->GetID() < myLinks[ iMin ]->myNode1->GetID() )
+ iMin = i;
+ }
+ for ( size_t i = 0; i < myNodes.size(); ++i )
+ me->myNodes[ i ] = myLinks[ ( iMin + i ) % myNodes.size() ]->myNode1;
+ }
+ };
+
+ //--------------------------------------------------------------------------------
+ /*!
+ * \brief Set of EdgeLoop's constructed from a CutFace
+ */
+ struct EdgeLoopSet
+ {
+ std::vector< EdgeLoop > myLoops; //!< buffer of EdgeLoop's
+ size_t myNbLoops; //!< number of constructed loops
+
+ const EdgePart* myEdge0; //!< & CutFace.myLinks[0]
+ size_t myNbUsedEdges; //!< nb of EdgePart's added to myLoops
+ boost::dynamic_bitset<> myIsUsedEdge; //!< is i-th EdgePart of CutFace is in any EdgeLoop
+ std::vector< EdgeLoop* > myLoopOfEdge; //!< EdgeLoop of CutFace.myLinks[i]
+ std::vector< EdgePart* > myCandidates; //!< EdgePart's starting at the same node
+
+ EdgeLoopSet(): myLoops(100) {}
+
+ void Init( const std::vector< EdgePart >& edges )
+ {
+ size_t nb = edges.size();
+ myEdge0 = & edges[0];
+ myNbLoops = 0;
+ myNbUsedEdges = 0;
+ myIsUsedEdge.reset();
+ myIsUsedEdge.resize( nb, false );
+ myLoopOfEdge.clear();
+ myLoopOfEdge.resize( nb, (EdgeLoop*) 0 );
+ }
+ EdgeLoop& AddNewLoop()
+ {
+ if ( ++myNbLoops >= myLoops.size() )
+ myLoops.resize( myNbLoops + 10 );
+ myLoops[ myNbLoops-1 ].Clear();
+ return myLoops[ myNbLoops-1 ];
+ }
+ bool AllEdgesUsed() const { return myNbUsedEdges == myLoopOfEdge.size(); }
+
+ bool AddEdge( EdgePart& edge )
+ {
+ size_t i = Index( edge );
+ if ( myIsUsedEdge[ i ])
+ return false;
+ myLoops[ myNbLoops-1 ].myLinks.push_back( &edge );
+ myLoopOfEdge[ i ] = & myLoops[ myNbLoops-1 ];
+ myIsUsedEdge[ i ] = true;
+ ++myNbUsedEdges;
+ return true;
+ }
+ void Erase( EdgeLoop* loop )
+ {
+ for ( size_t iE = 0; iE < loop->myLinks.size(); ++iE )
+ myLoopOfEdge[ Index( *loop->myLinks[ iE ] )] = 0;
+ loop->Clear();
+ }
+ size_t Index( const EdgePart& edge ) const { return &edge - myEdge0; }
+ EdgeLoop* GetLoopOf( const EdgePart* edge ) { return myLoopOfEdge[ Index( *edge )]; }
+ };
+
+ //--------------------------------------------------------------------------------
+ /*!
+ * \brief Intersections of a face
+ */
+ struct CutFace
+ {
+ mutable std::vector< EdgePart > myLinks;
+ const SMDS_MeshElement* myInitFace;
+
+ CutFace( const SMDS_MeshElement* face ): myInitFace( face ) {}
+ void AddEdge( const CutLink& p1,
+ const CutLink& p2,
+ const SMDS_MeshElement* cutter,
+ const int nbOnPlane,
+ const int iNotOnPlane = -1) const;
+ void AddPoint( const CutLink& p1, const CutLink& p2, double tol ) const;
+ bool ReplaceNodes( const TNNMap& theRm2KeepMap ) const;
+ bool IsCut() const;
+ int NbInternalEdges() const;
+ void MakeLoops( EdgeLoopSet& loops, const gp_XYZ& theFaceNorm ) const;
+ bool RemoveInternalLoops( EdgeLoopSet& theLoops ) const;
+ void CutOffLoops( EdgeLoopSet& theLoops,
+ const double theSign,
+ const std::vector< gp_XYZ >& theNormals,
+ std::vector< EdgePart >& theCutOffLinks,
+ TLinkMap& theCutOffCoplanarLinks) const;
+ void InitLinks() const;
+ bool IsCoplanar( const EdgePart* edge ) const;
+
+ static Standard_Integer HashCode(const CutFace& f, const Standard_Integer upper)
+ {
+ return ::HashCode( f.myInitFace->GetID(), upper );
+ }
+ static Standard_Boolean IsEqual(const CutFace& f1, const CutFace& f2 )
+ {
+ return f1.myInitFace == f2.myInitFace;
+ }
+ void Dump() const;
+
+ private:
+
+ EdgePart* getTwin( const EdgePart* edge ) const;
+ };
+
+ typedef NCollection_Map< CutFace, CutFace > TCutFaceMap;
+
+ //--------------------------------------------------------------------------------
+ /*!
+ * \brief Intersection point of two edges of co-planar triangles
+ */
+ struct IntPoint2D
+ {
+ size_t myEdgeInd[2]; //!< edge indices of triangles
+ double myU [2]; //!< parameter [0,1] on edges of triangles
+ SMESH_NodeXYZ myNode; //!< intersection node
+ bool myIsCollinear;//!< edges are collinear
+
+ IntPoint2D() : myIsCollinear( false ) {}
+
+ void InitLink( CutLink& link, int iFace, const std::vector< SMESH_NodeXYZ >& nodes ) const
+ {
+ link.Set( nodes[ myEdgeInd[ iFace ] ].Node(),
+ nodes[( myEdgeInd[ iFace ] + 1 ) % nodes.size() ].Node(),
+ link.myFace );
+ link.myIntNode = myNode;
+ }
+ const SMDS_MeshNode* Node() const { return myNode.Node(); }
+ };
+ struct IntPoint2DCompare
+ {
+ int myI;
+ IntPoint2DCompare( int iFace=0 ): myI( iFace ) {}
+ bool operator() ( const IntPoint2D* ip1, const IntPoint2D* ip2 ) const
+ {
+ return ip1->myU[ myI ] < ip2->myU[ myI ];
+ }
+ bool operator() ( const IntPoint2D& ip1, const IntPoint2D& ip2 ) const
+ {
+ return ip1.myU[ myI ] < ip2.myU[ myI ];
+ }
+ };
+ typedef boost::container::flat_set< IntPoint2D, IntPoint2DCompare > TIntPointSet;
+ typedef boost::container::flat_set< IntPoint2D*, IntPoint2DCompare > TIntPointPtrSet;
+
+ //--------------------------------------------------------------------------------
+ /*!
+ * \brief Face used to find translated position of the node
+ */
+ struct Face
+ {
+ const SMDS_MeshElement* myFace;
+ SMESH_TNodeXYZ myNode1; //!< nodes neighboring another node of myFace
+ SMESH_TNodeXYZ myNode2;
+ const gp_XYZ* myNorm;
+ bool myNodeRightOrder;
+ void operator=(const SMDS_MeshElement* f) { myFace = f; }
+ const SMDS_MeshElement* operator->() { return myFace; }
+ void SetNodes( int i0, int i1 ) //!< set myNode's
+ {
+ myNode1.Set( myFace->GetNode( i1 ));
+ int i2 = ( i0 - 1 + myFace->NbCornerNodes() ) % myFace->NbCornerNodes();
+ if ( i2 == i1 )
+ i2 = ( i0 + 1 ) % myFace->NbCornerNodes();
+ myNode2.Set( myFace->GetNode( i2 ));
+ myNodeRightOrder = ( Abs( i2-i1 ) == 1 ) ? i2 > i1 : i2 < i1;
+ }
+ void SetOldNodes( const SMDS_Mesh& theSrcMesh )
+ {
+ myNode1.Set( theSrcMesh.FindNode( myNode1->GetID() ));
+ myNode2.Set( theSrcMesh.FindNode( myNode2->GetID() ));
+ }
+ bool SetNormal( const std::vector< gp_XYZ >& faceNormals )
+ {
+ myNorm = & faceNormals[ myFace->GetID() ];
+ return ( myNorm->SquareModulus() > gp::Resolution() * gp::Resolution() );
+ }
+ const gp_XYZ& Norm() const { return *myNorm; }
+ };
+
+ //--------------------------------------------------------------------------------
+ /*!
+ * \brief Offset plane used to find translated position of the node
+ */
+ struct OffsetPlane
+ {
+ gp_XYZ myNode;
+ Face* myFace;
+ gp_Pln myPln;
+ gp_Lin myLines[2]; //!< line of intersection with neighbor OffsetPlane's
+ bool myIsLineOk[2];
+ double myWeight[2];
+
+ void Init( const gp_XYZ& node, Face& tria, double offset )
+ {
+ myNode = node;
+ myFace = & tria;
+ myPln = gp_Pln( node + tria.Norm() * offset, tria.Norm() );
+ myIsLineOk[0] = myIsLineOk[1] = false;
+ myWeight[0] = myWeight[1] = 0;
+ }
+ bool ComputeIntersectionLine( OffsetPlane& pln );
+ void SetSkewLine( const gp_Lin& line );
+ gp_XYZ GetCommonPoint( int & nbOkPoints, double& sumWeight );
+ gp_XYZ ProjectNodeOnLine( int & nbOkPoints );
+ double Weight() const { return myWeight[0] + myWeight[1]; }
+ };
+
+ //================================================================================
+ /*!
+ * \brief Set the second line
+ */
+ //================================================================================
+
+ void OffsetPlane::SetSkewLine( const gp_Lin& line )
+ {
+ myLines[1] = line;
+ gp_XYZ n = myLines[0].Direction().XYZ() ^ myLines[1].Direction().XYZ();
+ if (( myIsLineOk[1] = n.SquareModulus() > gp::Resolution() ))
+ myPln = gp_Pln( myPln.Location(), n );
+ }
+
+ //================================================================================
+ /*!
+ * \brief Project myNode on myLine[0]
+ */
+ //================================================================================
+
+ gp_XYZ OffsetPlane::ProjectNodeOnLine( int & nbOkPoints )
+ {
+ gp_XYZ p = gp::Origin().XYZ();
+ if ( myIsLineOk[0] )
+ {
+ gp_Vec l2n( myLines[0].Location(), myNode );
+ double u = l2n * myLines[0].Direction();
+ p = myLines[0].Location().XYZ() + u * myLines[0].Direction().XYZ();
+ ++nbOkPoints;
+ }
+ return p;
+ }
+
+ //================================================================================
+ /*!
+ * \brief Computes intersection point of myLines
+ */
+ //================================================================================
+
+ gp_XYZ OffsetPlane::GetCommonPoint( int & nbOkPoints, double& sumWeight )
+ {
+ if ( !myIsLineOk[0] || !myIsLineOk[1] )
+ {
+ // sumWeight += myWeight[0];
+ // return ProjectNodeOnLine( nbOkPoints ) * myWeight[0];
+ return gp::Origin().XYZ();
+ }
+
+ gp_XYZ p;
+
+ gp_Vec lPerp0 = myLines[0].Direction().XYZ() ^ myPln.Axis().Direction().XYZ();
+ double dot01 = lPerp0 * myLines[1].Direction().XYZ();
+ if ( Abs( dot01 ) > 0.05 )
+ {
+ gp_Vec l0l1 = myLines[1].Location().XYZ() - myLines[0].Location().XYZ();
+ double u1 = - ( lPerp0 * l0l1 ) / dot01;
+ p = ( myLines[1].Location().XYZ() + myLines[1].Direction().XYZ() * u1 );
+ }
+ else
+ {
+ gp_Vec lv0( myLines[0].Location(), myNode), lv1(myLines[1].Location(), myNode );
+ double dot0( lv0 * myLines[0].Direction() ), dot1( lv1 * myLines[1].Direction() );
+ p = 0.5 * ( myLines[0].Location().XYZ() + myLines[0].Direction().XYZ() * dot0 );
+ p += 0.5 * ( myLines[1].Location().XYZ() + myLines[1].Direction().XYZ() * dot1 );
+ }
+
+ sumWeight += Weight();
+ ++nbOkPoints;
+
+ return p * Weight();
+ }
+
+ //================================================================================
+ /*!
+ * \brief Compute line of intersection of 2 planes
+ */
+ //================================================================================
+
+ bool OffsetPlane::ComputeIntersectionLine( OffsetPlane& theNextPln )
+ {
+ const gp_XYZ& n1 = myFace->Norm();
+ const gp_XYZ& n2 = theNextPln.myFace->Norm();
+
+ gp_XYZ lineDir = n1 ^ n2;
+ gp_Pnt linePos;
+
+ double x = Abs( lineDir.X() );
+ double y = Abs( lineDir.Y() );
+ double z = Abs( lineDir.Z() );
+
+ int cooMax; // max coordinate
+ if (x > y) {
+ if (x > z) cooMax = 1;
+ else cooMax = 3;
+ }
+ else {
+ if (y > z) cooMax = 2;
+ else cooMax = 3;
+ }
+
+ bool ok = true;
+ if ( Abs( lineDir.Coord( cooMax )) < 0.05 )
+ {
+ // parallel planes - intersection is an offset of the common edge
+ linePos = 0.5 * ( myPln.Location().XYZ() + theNextPln.myPln.Location().XYZ() );
+ lineDir = myNode - myFace->myNode2;
+ ok = false;
+ myWeight[0] = 0;
+ }
+ else
+ {
+ // the constants in the 2 plane equations
+ double d1 = - ( n1 * myPln.Location().XYZ() );
+ double d2 = - ( n2 * theNextPln.myPln.Location().XYZ() );
+
+ switch ( cooMax ) {
+ case 1:
+ linePos.SetX( 0 );
+ linePos.SetY(( d2*n1.Z() - d1*n2.Z()) / lineDir.X() );
+ linePos.SetZ(( d1*n2.Y() - d2*n1.Y()) / lineDir.X() );
+ break;
+ case 2:
+ linePos.SetX(( d1*n2.Z() - d2*n1.Z()) / lineDir.Y() );
+ linePos.SetY( 0 );
+ linePos.SetZ(( d2*n1.X() - d1*n2.X()) / lineDir.Y() );
+ break;
+ case 3:
+ linePos.SetX(( d2*n1.Y() - d1*n2.Y()) / lineDir.Z() );
+ linePos.SetY(( d1*n2.X() - d2*n1.X()) / lineDir.Z() );
+ linePos.SetZ( 0 );
+ }
+ myWeight[0] = lineDir.SquareModulus();
+ if ( n1 * n2 < 0 )
+ myWeight[0] = 2. - myWeight[0];
+ }
+ myLines [ 0 ].SetDirection( lineDir );
+ myLines [ 0 ].SetLocation ( linePos );
+ myIsLineOk[ 0 ] = ok;
+
+ theNextPln.myLines [ 1 ] = myLines[ 0 ];
+ theNextPln.myIsLineOk[ 1 ] = ok;
+ theNextPln.myWeight [ 1 ] = myWeight[ 0 ];
+
+ return ok;
+ }
+
+ //================================================================================
+ /*!
+ * \brief Return a translated position of a node
+ * \param [in] new2OldNodes - new and old nodes
+ * \param [in] faceNormals - normals to input faces
+ * \param [in] theSrcMesh - initial mesh
+ * \param [in] theNewPos - a computed normal
+ * \return bool - true if theNewPos is computed
+ */
+ //================================================================================
+
+ bool getTranslatedPosition( const SMDS_MeshNode* theNewNode,
+ const double theOffset,
+ const double theTol,
+ const double theSign,
+ const std::vector< gp_XYZ >& theFaceNormals,
+ SMDS_Mesh& theSrcMesh,
+ gp_XYZ& theNewPos)
+ {
+ bool useOneNormal = true;
+
+ // check if theNewNode needs an average position, i.e. theNewNode is convex
+ // SMDS_ElemIteratorPtr faceIt = theNewNode->GetInverseElementIterator();
+ // const SMDS_MeshElement* f0 = faceIt->next();
+ // const gp_XYZ& norm0 = theFaceNormals[ f0->GetID() ];
+ // const SMESH_NodeXYZ nodePos = theNewNode;
+ // while ( faceIt->more() )
+ // {
+ // const SMDS_MeshElement* f = faceIt->next();
+ // const int nodeInd = f->GetNodeIndex( theNewNode );
+ // SMESH_NodeXYZ nodePos2 = f->GetWrapNode( nodeInd + 1 );
+ // try {
+ // const gp_XYZ nnDir = ( nodePos2 - nodePos ).Normalized();
+ // }
+ // catch {
+ // continue;
+ // }
+ // const double dot = norm0 * nnDir;
+ // bool isConvex =
+
+
+
+ // get faces surrounding theNewNode and sort them
+ Face faces[ theMaxNbFaces ];
+ SMDS_ElemIteratorPtr faceIt = theNewNode->GetInverseElementIterator();
+ faces[0] = faceIt->next();
+ while ( !faces[0].SetNormal( theFaceNormals ) && faceIt->more() )
+ faces[0] = faceIt->next();
+ int i0 = faces[0]->GetNodeIndex( theNewNode );
+ int i1 = ( i0 + 1 ) % faces[0]->NbCornerNodes();
+ faces[0].SetNodes( i0, i1 );
+ TIDSortedElemSet elemSet, avoidSet;
+ int iFace = 0;
+ const SMDS_MeshElement* f;
+ for ( ; faceIt->more(); faceIt->next() )
+ {
+ avoidSet.insert( faces[ iFace ].myFace );
+ f = SMESH_MeshAlgos::FindFaceInSet( theNewNode, faces[ iFace ].myNode2.Node(),
+ elemSet, avoidSet, &i0, &i1 );
+ if ( !f )
+ {
+ std::reverse( &faces[0], &faces[0] + iFace + 1 );
+ for ( int i = 0; i <= iFace; ++i )
+ {
+ std::swap( faces[i].myNode1, faces[i].myNode2 );
+ faces[i].myNodeRightOrder = !faces[i].myNodeRightOrder;
+ }
+ f = SMESH_MeshAlgos::FindFaceInSet( theNewNode, faces[ iFace ].myNode2.Node(),
+ elemSet, avoidSet, &i0, &i1 );
+ if ( !f )
+ break;
+ }
+ faces[ ++iFace ] = f;
+ faces[ iFace ].SetNodes( i0, i1 );
+ faces[ iFace ].SetNormal( theFaceNormals );
+ }
+ int nbFaces = Min( iFace + 1, (int)theMaxNbFaces );
+
+ theNewPos.SetCoord( 0, 0, 0 );
+ gp_XYZ oldXYZ = SMESH_NodeXYZ( theNewNode );
+
+ // check if all faces are co-planar
+ bool isPlanar = true;
+ const double tol = 1e-2;
+ for ( int i = 1; i < nbFaces && isPlanar; ++i )
+ isPlanar = ( faces[i].Norm() - faces[i-1].Norm() ).SquareModulus() < tol*tol;
+
+ if ( isPlanar )
+ {
+ theNewPos = oldXYZ + faces[0].Norm() * theOffset;
+ return useOneNormal;
+ }
+
+ // prepare OffsetPlane's
+ OffsetPlane pln[ theMaxNbFaces ];
+ for ( int i = 0; i < nbFaces; ++i )
+ {
+ faces[i].SetOldNodes( theSrcMesh );
+ pln[i].Init( oldXYZ, faces[i], theOffset );
+ }
+ // intersect neighboring OffsetPlane's
+ int nbOkPoints = 0;
+ for ( int i = 1; i < nbFaces; ++i )
+ nbOkPoints += pln[ i-1 ].ComputeIntersectionLine( pln[ i ]);
+ nbOkPoints += pln[ nbFaces-1 ].ComputeIntersectionLine( pln[ 0 ]);
+
+ // move intersection lines to over parallel planes
+ if ( nbOkPoints > 1 )
+ for ( int i = 0; i < nbFaces; ++i )
+ if ( pln[i].myIsLineOk[0] && !pln[i].myIsLineOk[1] )
+ for ( int j = 1; j < nbFaces && !pln[i].myIsLineOk[1]; ++j )
+ {
+ int i2 = ( i + j ) % nbFaces;
+ if ( pln[i2].myIsLineOk[0] )
+ pln[i].SetSkewLine( pln[i2].myLines[0] );
+ }
+
+ // get the translated position
+ nbOkPoints = 0;
+ double sumWegith = 0;
+ const double minWeight = Sin( 30 * M_PI / 180. ) * Sin( 30 * M_PI / 180. );
+ for ( int i = 0; i < nbFaces; ++i )
+ if ( pln[ i ].Weight() > minWeight )
+ theNewPos += pln[ i ].GetCommonPoint( nbOkPoints, sumWegith );
+
+ if ( nbOkPoints == 0 )
+ {
+ // there is only one feature edge;
+ // find the theNewPos by projecting oldXYZ to any intersection line
+ for ( int i = 0; i < nbFaces; ++i )
+ theNewPos += pln[ i ].ProjectNodeOnLine( nbOkPoints );
+
+ if ( nbOkPoints == 0 )
+ {
+ theNewPos = oldXYZ + faces[0].Norm() * theOffset;
+ return useOneNormal;
+ }
+ sumWegith = nbOkPoints;
+ }
+ theNewPos /= sumWegith;
+
+
+ // mark theNewNode if it is concave
+ useOneNormal = false;
+ gp_Vec moveVec( oldXYZ, theNewPos );
+ for ( int i = 0, iPrev = nbFaces-1; i < nbFaces; iPrev = i++ )
+ {
+ gp_Vec nodeVec( oldXYZ, faces[ i ].myNode1 );
+ double u = ( moveVec * nodeVec ) / nodeVec.SquareMagnitude();
+ if ( u > 0.5 ) // param [0,1] on nodeVec
+ {
+ theNewNode->setIsMarked( true );
+ }
+ if ( !useOneNormal )
+ {
+ gp_XYZ inFaceVec = faces[ i ].Norm() ^ nodeVec.XYZ();
+ double dot = inFaceVec * faces[ iPrev ].Norm();
+ if ( !faces[ i ].myNodeRightOrder )
+ dot *= -1;
+ if ( dot * theSign < 0 )
+ {
+ gp_XYZ p1 = oldXYZ + faces[ i ].Norm() * theOffset;
+ gp_XYZ p2 = oldXYZ + faces[ iPrev ].Norm() * theOffset;
+ useOneNormal = ( p1 - p2 ).SquareModulus() > theTol * theTol;
+ }
+ }
+ if ( useOneNormal && theNewNode->isMarked() )
+ break;
+ }
+
+ return useOneNormal;
+ }
+
+ //--------------------------------------------------------------------------------
+ /*!
+ * \brief Intersect faces of a mesh
+ */
+ struct Intersector
+ {
+ SMDS_Mesh* myMesh;
+ double myTol, myEps;
+ const std::vector< gp_XYZ >& myNormals;
+ TCutLinkMap myCutLinks; //!< assure sharing of new nodes
+ TCutFaceMap myCutFaces;
+ TNNMap myRemove2KeepNodes; //!< node merge map
+
+ // data to intersect 2 faces
+ const SMDS_MeshElement* myFace1;
+ const SMDS_MeshElement* myFace2;
+ std::vector< SMESH_NodeXYZ > myNodes1, myNodes2;
+ std::vector< double > myDist1, myDist2;
+ int myInd1, myInd2; // coordinate indices on an axis-aligned plane
+ int myNbOnPlane1, myNbOnPlane2;
+ TIntPointSet myIntPointSet;
+
+ Intersector( SMDS_Mesh* mesh, double tol, const std::vector< gp_XYZ >& normals )
+ : myMesh( mesh ),
+ myTol( tol ),
+ myEps( 1e-100 ),
+ //myEps( Sqrt( std::numeric_limits<double>::min() )),
+ //myEps( gp::Resolution() ),
+ myNormals( normals )
+ {}
+ void Cut( const SMDS_MeshElement* face1,
+ const SMDS_MeshElement* face2,
+ const int nbCommonNodes );
+ void MakeNewFaces( SMESH_MeshAlgos::TEPairVec& theNew2OldFaces,
+ SMESH_MeshAlgos::TNPairVec& theNew2OldNodes,
+ const double theSign );
+
+ private:
+
+ bool isPlaneIntersected( const gp_XYZ& n2,
+ const double d2,
+ const std::vector< SMESH_NodeXYZ >& nodes1,
+ std::vector< double > & dist1,
+ int & nbOnPlane1,
+ int & iNotOnPlane1);
+ void computeIntervals( const std::vector< SMESH_NodeXYZ >& nodes,
+ const std::vector< double >& dist,
+ const int nbOnPln,
+ const int iMaxCoo,
+ double * u,
+ int* iE);
+ void cutCoplanar();
+ void addLink ( CutLink& link );
+ bool findLink( CutLink& link );
+ bool coincide( const gp_XYZ& p1, const gp_XYZ& p2, const double tol ) const
+ {
+ return ( p1 - p2 ).SquareModulus() < tol * tol;
+ }
+ gp_XY p2D( const gp_XYZ& p ) const { return gp_XY( p.Coord( myInd1 ), p.Coord( myInd2 )); }
+
+ void intersectLink( const std::vector< SMESH_NodeXYZ >& nodes1,
+ const std::vector< double > & dist1,
+ const int iEdge1,
+ const SMDS_MeshElement* face2,
+ CutLink& link1);
+ void findIntPointOnPlane( const std::vector< SMESH_NodeXYZ >& nodes,
+ const std::vector< double > & dist,
+ CutLink& link );
+ void replaceIntNode( const SMDS_MeshNode* nToKeep, const SMDS_MeshNode* nToRemove );
+ void computeIntPoint( const double u1,
+ const double u2,
+ const int iE1,
+ const int iE2,
+ CutLink & link,
+ const SMDS_MeshNode* & node1,
+ const SMDS_MeshNode* & node2);
+ void cutCollinearLink( const int iNotOnPlane1,
+ const std::vector< SMESH_NodeXYZ >& nodes1,
+ const SMDS_MeshElement* face2,
+ const CutLink& link1,
+ const CutLink& link2);
+ void setPlaneIndices( const gp_XYZ& planeNorm );
+ bool intersectEdgeEdge( const gp_XY s1p0, const gp_XY s1p1,
+ const gp_XY s2p0, const gp_XY s2p1,
+ double & t1, double & t2,
+ bool & isCollinear );
+ bool intersectEdgeEdge( int iE1, int iE2, IntPoint2D& intPoint );
+ bool isPointInTriangle( const gp_XYZ& p, const std::vector< SMESH_NodeXYZ >& nodes );
+ void intersectNewEdges( const CutFace& theCFace );
+ const SMDS_MeshNode* createNode( const gp_XYZ& p );
+ };
+
+ //================================================================================
+ /*!
+ * \brief Return coordinate index with maximal abs value
+ */
+ //================================================================================
+
+ int MaxIndex( const gp_XYZ& x )
+ {
+ int iMaxCoo = ( Abs( x.X()) < Abs( x.Y() )) + 1;
+ if ( Abs( x.Coord( iMaxCoo )) < Abs( x.Z() ))
+ iMaxCoo = 3;
+ return iMaxCoo;
+ }
+ //================================================================================
+ /*!
+ * \brief Store a CutLink
+ */
+ //================================================================================
+
+ const SMDS_MeshNode* Intersector::createNode( const gp_XYZ& p )
+ {
+ const SMDS_MeshNode* n = myMesh->AddNode( p.X(), p.Y(), p.Z() );
+ n->setIsMarked( true ); // cut nodes are marked
+ return n;
+ }
+
+ //================================================================================
+ /*!
+ * \brief Store a CutLink
+ */
+ //================================================================================
+
+ void Intersector::addLink( CutLink& link )
+ {
+ link.myIndex = 0;
+ const CutLink* added = & myCutLinks.Added( link );
+ while ( added->myIntNode.Node() != link.myIntNode.Node() )
+ {
+ if ( !added->myIntNode )
+ {
+ added->myIntNode = link.myIntNode;
+ break;
+ }
+ else
+ {
+ link.myIndex++;
+ added = & myCutLinks.Added( link );
+ }
+ }
+ link.myIndex = 0;
+ }
+
+ //================================================================================
+ /*!
+ * \brief Find a CutLink with an intersection point coincident with that of a given link
+ */
+ //================================================================================
+
+ bool Intersector::findLink( CutLink& link )
+ {
+ link.myIndex = 0;
+ while ( myCutLinks.Contains( link ))
+ {
+ const CutLink* added = & myCutLinks.Added( link );
+ if ( !!added->myIntNode && coincide( added->myIntNode, link.myIntNode, myTol ))
+ {
+ link.myIntNode = added->myIntNode;
+ return true;
+ }
+ link.myIndex++;
+ }
+ return false;
+ }
+
+ //================================================================================
+ /*!
+ * \brief Check if a triangle intersects the plane of another triangle
+ * \param [in] nodes1 - nodes of triangle 1
+ * \param [in] n2 - normal of triangle 2
+ * \param [in] d2 - a constant of the plane equation 2
+ * \param [out] dist1 - distance of nodes1 from the plane 2
+ * \param [out] nbOnPlane - number of nodes1 lying on the plane 2
+ * \return bool - true if the triangle intersects the plane 2
+ */
+ //================================================================================
+
+ bool Intersector::isPlaneIntersected( const gp_XYZ& n2,
+ const double d2,
+ const std::vector< SMESH_NodeXYZ >& nodes1,
+ std::vector< double > & dist1,
+ int & nbOnPlane1,
+ int & iNotOnPlane1)
+ {
+ iNotOnPlane1 = nbOnPlane1 = 0;
+ dist1.resize( nodes1.size() );
+ for ( size_t i = 0; i < nodes1.size(); ++i )
+ {
+ dist1[i] = n2 * nodes1[i] + d2;
+ if ( Abs( dist1[i] ) < myTol )
+ {
+ ++nbOnPlane1;
+ dist1[i] = 0.;
+ }
+ else
+ {
+ iNotOnPlane1 = i;
+ }
+ }
+ if ( nbOnPlane1 == 0 )
+ for ( size_t i = 0; i < nodes1.size(); ++i )
+ if ( dist1[iNotOnPlane1] * dist1[i] < 0 )
+ return true;
+
+ return nbOnPlane1;
+ }
+
+ //================================================================================
+ /*!
+ * \brief Compute parameters on the plane intersection line of intersections
+ * of edges of a triangle
+ * \param [in] nodes - triangle nodes
+ * \param [in] dist - distance of triangle nodes from the plane of another triangle
+ * \param [in] nbOnPln - number of nodes lying on the plane of another triangle
+ * \param [in] iMaxCoo - index of coordinate of max component of the plane intersection line
+ * \param [out] u - two computed parameters on the plane intersection line
+ * \param [out] iE - indices of intersected edges
+ */
+ //================================================================================
+
+ void Intersector::computeIntervals( const std::vector< SMESH_NodeXYZ >& nodes,
+ const std::vector< double >& dist,
+ const int nbOnPln,
+ const int iMaxCoo,
+ double * u,
+ int* iE)
+ {
+ if ( nbOnPln == 3 )
+ {
+ u[0] = u[1] = 1e+100;
+ return;
+ }
+ int nb = 0;
+ int i1 = 2, i2 = 0;
+ if ( nbOnPln == 1 && ( dist[i1] == 0. || dist[i2] == 0 ))
+ {
+ int i = dist[i1] == 0 ? i1 : i2;
+ u [ 1 ] = nodes[ i ].Coord( iMaxCoo );
+ iE[ 1 ] = i;
+ i1 = i2++;
+ }
+ for ( ; i2 < 3 && nb < 2; i1 = i2++ )
+ {
+ double dd = dist[i1] - dist[i2];
+ if ( dd != 0. && dist[i2] * dist[i1] <= 0. )
+ {
+ double x1 = nodes[i1].Coord( iMaxCoo );
+ double x2 = nodes[i2].Coord( iMaxCoo );
+ u [ nb ] = x1 + ( x2 - x1 ) * dist[i1] / dd;
+ iE[ nb ] = i1;
+ ++nb;
+ }
+ }
+ if ( u[0] > u[1] )
+ {
+ std::swap( u [0], u [1] );
+ std::swap( iE[0], iE[1] );
+ }
+ }
+
+ //================================================================================
+ /*!
+ * \brief Try to find an intersection node on a link collinear with the plane intersection line
+ */
+ //================================================================================
+
+ void Intersector::findIntPointOnPlane( const std::vector< SMESH_NodeXYZ >& nodes,
+ const std::vector< double > & dist,
+ CutLink& link )
+ {
+ int i1 = ( dist[0] == 0 ? 0 : 1 ), i2 = ( dist[2] == 0 ? 2 : 1 );
+ CutLink link2 = link;
+ link2.Set( nodes[i1].Node(), nodes[i2].Node(), 0 );
+ if ( findLink( link2 ))
+ link.myIntNode = link2.myIntNode;
+ }
+
+ //================================================================================
+ /*!
+ * \brief Compute intersection point of a link1 with a face2
+ */
+ //================================================================================
+
+ void Intersector::intersectLink( const std::vector< SMESH_NodeXYZ >& nodes1,
+ const std::vector< double > & dist1,
+ const int iEdge1,
+ const SMDS_MeshElement* face2,
+ CutLink& link1)
+ {
+ const int iEdge2 = ( iEdge1 + 1 ) % nodes1.size();
+ const SMESH_NodeXYZ& p1 = nodes1[ iEdge1 ];
+ const SMESH_NodeXYZ& p2 = nodes1[ iEdge2 ];
+
+ link1.Set( p1.Node(), p2.Node(), face2 );
+ const CutLink* link = & myCutLinks.Added( link1 );
+ if ( !link->IntNode() )
+ {
+ if ( dist1[ iEdge1 ] == 0. ) link1.myIntNode = p1;
+ else if ( dist1[ iEdge2 ] == 0. ) link1.myIntNode = p2;
+ else
+ {
+ gp_XYZ p = p1 + ( p2 - p1 ) * dist1[ iEdge1 ] / ( dist1[ iEdge1 ] - dist1[ iEdge2 ]);
+ (gp_XYZ&)link1.myIntNode = p;
+ }
+ }
+ else
+ {
+ gp_XYZ p = p1 + ( p2 - p1 ) * dist1[ iEdge1 ] / ( dist1[ iEdge1 ] - dist1[ iEdge2 ]);
+ while ( link->IntNode() )
+ {
+ if ( coincide( p, link->myIntNode, myTol ))
+ {
+ link1.myIntNode = link->myIntNode;
+ break;
+ }
+ link1.myIndex++;
+ link = & myCutLinks.Added( link1 );
+ }
+ if ( !link1.IntNode() )
+ {
+ if ( dist1[ iEdge1 ] == 0. ) link1.myIntNode = p1;
+ else if ( dist1[ iEdge2 ] == 0. ) link1.myIntNode = p2;
+ else (gp_XYZ&)link1.myIntNode = p;
+ }
+ }
+ }
+
+ //================================================================================
+ /*!
+ * \brief Store node replacement in myCutFaces
+ */
+ //================================================================================
+
+ void Intersector::replaceIntNode( const SMDS_MeshNode* nToKeep,
+ const SMDS_MeshNode* nToRemove )
+ {
+ if ( nToKeep == nToRemove )
+ return;
+ if ( nToRemove->GetID() < nToKeep->GetID() ) // keep node with lower ID
+ myRemove2KeepNodes.Bind((void*) nToKeep, nToRemove );
+ else
+ myRemove2KeepNodes.Bind((void*) nToRemove, nToKeep );
+ }
+
+ //================================================================================
+ /*!
+ * \brief Compute intersection point on a link of either of faces by choosing
+ * a link whose parameter on the intersection line in maximal
+ * \param [in] u1 - parameter on the intersection line of link iE1 of myFace1
+ * \param [in] u2 - parameter on the intersection line of link iE2 of myFace2
+ * \param [in] iE1 - index of a link myFace1
+ * \param [in] iE2 - index of a link myFace2
+ * \param [out] link - CutLink storing the intersection point
+ * \param [out] node1 - a node of the 2nd link if two links intersect
+ * \param [out] node2 - a node of the 2nd link if two links intersect
+ */
+ //================================================================================
+
+ void Intersector::computeIntPoint( const double u1,
+ const double u2,
+ const int iE1,
+ const int iE2,
+ CutLink & link,
+ const SMDS_MeshNode* & node1,
+ const SMDS_MeshNode* & node2)
+ {
+ if ( u1 > u2 + myTol )
+ {
+ intersectLink( myNodes1, myDist1, iE1, myFace2, link );
+ node1 = node2 = 0;
+ if ( myNbOnPlane2 == 2 )
+ findIntPointOnPlane( myNodes2, myDist2, link );
+ }
+ else if ( u2 > u1 + myTol )
+ {
+ intersectLink( myNodes2, myDist2, iE2, myFace1, link );
+ node1 = node2 = 0;
+ if ( myNbOnPlane1 == 2 )
+ findIntPointOnPlane( myNodes1, myDist1, link );
+ }
+ else // edges of two faces intersect the line at the same point
+ {
+ CutLink link2;
+ intersectLink( myNodes1, myDist1, iE1, myFace2, link );
+ intersectLink( myNodes2, myDist2, iE2, myFace1, link2 );
+ node1 = link2.Node1();
+ node2 = link2.Node2();
+
+ if ( !link.IntNode() && link2.IntNode() )
+ link.myIntNode = link2.myIntNode;
+
+ else if ( !link.IntNode() && !link2.IntNode() )
+ (gp_XYZ&)link.myIntNode = 0.5 * ( link.myIntNode + link2.myIntNode );
+
+ else if ( link.IntNode() && link2.IntNode() )
+ replaceIntNode( link.IntNode(), link2.IntNode() );
+ }
+ }
+
+ //================================================================================
+ /*!
+ * \brief Add intersections to a link collinear with the intersection line
+ */
+ //================================================================================
+
+ void Intersector::cutCollinearLink( const int iNotOnPlane1,
+ const std::vector< SMESH_NodeXYZ >& nodes1,
+ const SMDS_MeshElement* face2,
+ const CutLink& link1,
+ const CutLink& link2)
+
+ {
+ int iN1 = ( iNotOnPlane1 + 1 ) % 3;
+ int iN2 = ( iNotOnPlane1 + 2 ) % 3;
+ CutLink link( nodes1[ iN1 ].Node(), nodes1[ iN2 ].Node(), face2 );
+ if ( link1.myFace != face2 )
+ {
+ link.myIntNode = link1.myIntNode;
+ addLink( link );
+ }
+ if ( link2.myFace != face2 )
+ {
+ link.myIntNode = link2.myIntNode;
+ addLink( link );
+ }
+ }
+
+ //================================================================================
+ /*!
+ * \brief Choose indices on an axis-aligned plane
+ */
+ //================================================================================
+
+ void Intersector::setPlaneIndices( const gp_XYZ& planeNorm )
+ {
+ switch ( MaxIndex( planeNorm )) {
+ case 1: myInd1 = 2; myInd2 = 3; break;
+ case 2: myInd1 = 3; myInd2 = 1; break;
+ case 3: myInd1 = 1; myInd2 = 2; break;
+ }
+ }
+
+ //================================================================================
+ /*!
+ * \brief Intersect two faces
+ */
+ //================================================================================
+
+ void Intersector::Cut( const SMDS_MeshElement* face1,
+ const SMDS_MeshElement* face2,
+ const int nbCommonNodes)
+ {
+ myFace1 = face1;
+ myFace2 = face2;
+ myNodes1.assign( face1->begin_nodes(), face1->end_nodes() );
+ myNodes2.assign( face2->begin_nodes(), face2->end_nodes() );
+
+ const gp_XYZ& n1 = myNormals[ face1->GetID() ];
+ const gp_XYZ& n2 = myNormals[ face2->GetID() ];
+
+ // check if triangles intersect
+ int iNotOnPlane1, iNotOnPlane2;
+ const double d2 = -( n2 * myNodes2[0]);
+ if ( !isPlaneIntersected( n2, d2, myNodes1, myDist1, myNbOnPlane1, iNotOnPlane1 ))
+ return;
+ const double d1 = -( n1 * myNodes1[0]);
+ if ( !isPlaneIntersected( n1, d1, myNodes2, myDist2, myNbOnPlane2, iNotOnPlane2 ))
+ return;
+
+ if ( myNbOnPlane1 == 3 || myNbOnPlane2 == 3 )// triangles are co-planar
+ {
+ setPlaneIndices( myNbOnPlane1 == 3 ? n2 : n1 ); // choose indices on an axis-aligned plane
+ cutCoplanar();
+ }
+ else if ( nbCommonNodes < 2 ) // triangle planes intersect
+ {
+ gp_XYZ lineDir = n1 ^ n2; // intersection line
+
+ // check if intervals of intersections of triangles with lineDir overlap
+
+ double u1[2], u2 [2]; // parameters on lineDir of edge intersection points { minU, maxU }
+ int iE1[2], iE2[2]; // indices of edges
+ int iMaxCoo = MaxIndex( lineDir );
+ computeIntervals( myNodes1, myDist1, myNbOnPlane1, iMaxCoo, u1, iE1 );
+ computeIntervals( myNodes2, myDist2, myNbOnPlane2, iMaxCoo, u2, iE2 );
+ if ( u1[1] < u2[0] - myTol || u2[1] < u1[0] - myTol )
+ return; // intervals do not overlap
+
+ // make intersection nodes
+
+ const SMDS_MeshNode *l1n1, *l1n2, *l2n1, *l2n2;
+ CutLink link1; // intersection with smaller u on lineDir
+ computeIntPoint( u1[0], u2[0], iE1[0], iE2[0], link1, l1n1, l1n2 );
+ CutLink link2; // intersection with larger u on lineDir
+ computeIntPoint( -u1[1], -u2[1], iE1[1], iE2[1], link2, l2n1, l2n2 );
+
+ const CutFace& cf1 = myCutFaces.Added( CutFace( face1 ));
+ const CutFace& cf2 = myCutFaces.Added( CutFace( face2 ));
+
+ if ( coincide( link1.myIntNode, link2.myIntNode, myTol ))
+ {
+ // intersection is a point
+ if ( link1.IntNode() && link2.IntNode() )
+ replaceIntNode( link1.IntNode(), link2.IntNode() );
+
+ CutLink* link = link2.IntNode() ? &link2 : &link1;
+ if ( !link->IntNode() )
+ {
+ gp_XYZ p = 0.5 * ( link1.myIntNode + link2.myIntNode );
+ link->myIntNode.Set( createNode( p ));
+ }
+ if ( !link1.IntNode() ) link1.myIntNode = link2.myIntNode;
+ if ( !link2.IntNode() ) link2.myIntNode = link1.myIntNode;
+
+ cf1.AddPoint( link1, link2, myTol );
+ cf2.AddPoint( link1, link2, myTol );
+ }
+ else
+ {
+ // intersection is a line segment
+ if ( !link1.IntNode() )
+ link1.myIntNode.Set( createNode( link1.myIntNode ));
+ if ( !link2.IntNode() )
+ link2.myIntNode.Set( createNode( link2.myIntNode ));
+
+ cf1.AddEdge( link1, link2, face2, myNbOnPlane1, iNotOnPlane1 );
+ if ( l1n1 ) link1.Set( l1n1, l1n2, face2 );
+ if ( l2n1 ) link2.Set( l2n1, l2n2, face2 );
+ cf2.AddEdge( link1, link2, face1, myNbOnPlane2, iNotOnPlane2 );
+
+ // add intersections to a link collinear with the intersection line
+ if ( myNbOnPlane1 == 2 && ( link1.myFace != face2 || link2.myFace != face2 ))
+ cutCollinearLink( iNotOnPlane1, myNodes1, face2, link1, link2 );
+
+ if ( myNbOnPlane2 == 2 && ( link1.myFace != face1 || link2.myFace != face1 ))
+ cutCollinearLink( iNotOnPlane2, myNodes2, face1, link1, link2 );
+ }
+
+ addLink( link1 );
+ addLink( link2 );
+
+ } // non co-planar case
+
+ return;
+ }
+
+ //================================================================================
+ /*!
+ * \brief Intersect two 2D line segments
+ */
+ //================================================================================
+
+ bool Intersector::intersectEdgeEdge( const gp_XY s1p0, const gp_XY s1p1,
+ const gp_XY s2p0, const gp_XY s2p1,
+ double & t1, double & t2,
+ bool & isCollinear )
+ {
+ gp_XY u = s1p1 - s1p0;
+ gp_XY v = s2p1 - s2p0;
+ gp_XY w = s1p0 - s2p0;
+ double perpDotUV = u * gp_XY( -v.Y(), v.X() );
+ double perpDotVW = v * gp_XY( -w.Y(), w.X() );
+ double perpDotUW = u * gp_XY( -w.Y(), w.X() );
+ double u2 = u.SquareModulus();
+ double v2 = v.SquareModulus();
+ if ( u2 < myEps * myEps || v2 < myEps * myEps )
+ return false;
+ if ( perpDotUV * perpDotUV / u2 / v2 < 1e-6 ) // cos ^ 2
+ {
+ if ( !isCollinear )
+ return false; // no need in collinear solution
+ if ( perpDotUW * perpDotUW / u2 > myTol * myTol )
+ return false; // parallel
+
+ // collinear
+ gp_XY w2 = s1p1 - s2p0;
+ if ( Abs( v.X()) + Abs( u.X()) > Abs( v.Y()) + Abs( u.Y())) {
+ t1 = w.X() / v.X(); // params on segment 2
+ t2 = w2.X() / v.X();
+ }
+ else {
+ t1 = w.Y() / v.Y();
+ t2 = w2.Y() / v.Y();
+ }
+ if ( Max( t1,t2 ) <= 0 || Min( t1,t2 ) >= 1 )
+ return false; // no overlap
+ return true;
+ }
+ isCollinear = false;
+
+ t1 = perpDotVW / perpDotUV; // param on segment 1
+ if ( t1 < 0. || t1 > 1. )
+ return false; // intersection not within the segment
+
+ t2 = perpDotUW / perpDotUV; // param on segment 2
+ if ( t2 < 0. || t2 > 1. )
+ return false; // intersection not within the segment
+
+ return true;
+ }
+
+ //================================================================================
+ /*!
+ * \brief Intersect two edges of co-planar triangles
+ * \param [inout] iE1 - edge index of triangle 1
+ * \param [inout] iE2 - edge index of triangle 2
+ * \param [inout] intPoints - intersection points
+ * \param [inout] nbIntPoints - nb of found intersection points
+ */
+ //================================================================================
+
+ bool Intersector::intersectEdgeEdge( int iE1, int iE2, IntPoint2D& intPoint )
+ {
+ int i01 = iE1, i11 = ( iE1 + 1 ) % 3;
+ int i02 = iE2, i12 = ( iE2 + 1 ) % 3;
+ if (( !intPoint.myIsCollinear ) &&
+ ( myNodes1[ i01 ] == myNodes2[ i02 ] ||
+ myNodes1[ i01 ] == myNodes2[ i12 ] ||
+ myNodes1[ i11 ] == myNodes2[ i02 ] ||
+ myNodes1[ i11 ] == myNodes2[ i12 ] ))
+ return false;
+
+ // segment 1
+ gp_XY s1p0 = p2D( myNodes1[ i01 ]);
+ gp_XY s1p1 = p2D( myNodes1[ i11 ]);
+
+ // segment 2
+ gp_XY s2p0 = p2D( myNodes2[ i02 ]);
+ gp_XY s2p1 = p2D( myNodes2[ i12 ]);
+
+ double t1, t2;
+ if ( !intersectEdgeEdge( s1p0,s1p1, s2p0,s2p1, t1, t2, intPoint.myIsCollinear ))
+ return false;
+
+ intPoint.myEdgeInd[0] = iE1;
+ intPoint.myEdgeInd[1] = iE2;
+ intPoint.myU[0] = t1;
+ intPoint.myU[1] = t2;
+ (gp_XYZ&)intPoint.myNode = myNodes1[i01] * ( 1 - t1 ) + myNodes1[i11] * t1;
+
+ if ( intPoint.myIsCollinear )
+ return true;
+
+ // try to find existing node at intPoint.myNode
+
+ if ( myNodes1[ i01 ] == myNodes2[ i02 ] ||
+ myNodes1[ i01 ] == myNodes2[ i12 ] ||
+ myNodes1[ i11 ] == myNodes2[ i02 ] ||
+ myNodes1[ i11 ] == myNodes2[ i12 ] )
+ return false;
+
+ const double coincTol = myTol * 1e-3;
+
+ CutLink link1( myNodes1[i01].Node(), myNodes1[i11].Node(), myFace2 );
+ CutLink link2( myNodes2[i02].Node(), myNodes2[i12].Node(), myFace1 );
+
+ SMESH_NodeXYZ& n1 = myNodes1[ t1 < 0.5 ? i01 : i11 ];
+ bool same1 = coincide( n1, intPoint.myNode, coincTol );
+ if ( same1 )
+ {
+ link2.myIntNode = intPoint.myNode = n1;
+ addLink( link2 );
+ }
+ SMESH_NodeXYZ& n2 = myNodes2[ t2 < 0.5 ? i02 : i12 ];
+ bool same2 = coincide( n2, intPoint.myNode, coincTol );
+ if ( same2 )
+ {
+ link1.myIntNode = intPoint.myNode = n2;
+ addLink( link1 );
+ if ( same1 )
+ {
+ replaceIntNode( n1.Node(), n2.Node() );
+ return false;
+ }
+ return true;
+ }
+ if ( same1 )
+ return true;
+
+ link1.myIntNode = intPoint.myNode;
+ if ( findLink( link1 ))
+ {
+ intPoint.myNode = link2.myIntNode = link1.myIntNode;
+ addLink( link2 );
+ return true;
+ }
+
+ link2.myIntNode = intPoint.myNode;
+ if ( findLink( link2 ))
+ {
+ intPoint.myNode = link1.myIntNode = link2.myIntNode;
+ addLink( link1 );
+ return true;
+ }
+
+ for ( int is2nd = 0; is2nd < 2; ++is2nd )
+ {
+ const SMDS_MeshElement* f = is2nd ? myFace1 : myFace2;
+ const CutFace& cf = myCutFaces.Added( CutFace( is2nd ? myFace2 : myFace1 ));
+ for ( size_t i = 0; i < cf.myLinks.size(); ++i )
+ if ( cf.myLinks[i].myFace == f &&
+ //cf.myLinks[i].myIndex != EdgePart::_COPLANAR &&
+ coincide( intPoint.myNode, SMESH_NodeXYZ( cf.myLinks[i].myNode1 ), coincTol ))
+ {
+ intPoint.myNode.Set( cf.myLinks[i].myNode1 );
+ return true;
+ }
+ }
+
+ // make a new node
+
+ intPoint.myNode._node = createNode( intPoint.myNode );
+ link1.myIntNode = link2.myIntNode = intPoint.myNode;
+ addLink( link1 );
+ addLink( link2 );
+
+ return true;
+ }
+
+
+ //================================================================================
+ /*!
+ * \brief Check if a point is contained in a triangle
+ */
+ //================================================================================
+
+ bool Intersector::isPointInTriangle( const gp_XYZ& p, const std::vector< SMESH_NodeXYZ >& nodes )
+ {
+ double bc1, bc2;
+ SMESH_MeshAlgos::GetBarycentricCoords( p2D( p ),
+ p2D( nodes[0] ), p2D( nodes[1] ), p2D( nodes[2] ),
+ bc1, bc2 );
+ return ( 0. < bc1 && 0. < bc2 && bc1 + bc2 < 1. );
+ }
+
+ //================================================================================
+ /*!
+ * \brief Intersect two co-planar faces
+ */
+ //================================================================================
+
+ void Intersector::cutCoplanar()
+ {
+ // find intersections of edges
+
+ IntPoint2D intPoints[ 6 ];
+ int nbIntPoints = 0;
+ for ( int iE1 = 0; iE1 < 3; ++iE1 )
+ {
+ int maxNbIntPoints = nbIntPoints + 2;
+ for ( int iE2 = 0; iE2 < 3 && nbIntPoints < maxNbIntPoints; ++iE2 )
+ nbIntPoints += intersectEdgeEdge( iE1, iE2, intPoints[ nbIntPoints ]);
+ }
+ const int minNbOnPlane = Min( myNbOnPlane1, myNbOnPlane2 );
+
+ if ( nbIntPoints == 0 ) // no intersections of edges
+ {
+ bool is1in2;
+ if ( isPointInTriangle( myNodes1[0], myNodes2 )) // face2 includes face1
+ is1in2 = true;
+ else if ( isPointInTriangle( myNodes2[0], myNodes1 )) // face1 includes face2
+ is1in2 = false;
+ else
+ return;
+
+ // add edges of an inner triangle to an outer one
+
+ const std::vector< SMESH_NodeXYZ >& nodesIn = is1in2 ? myNodes1 : myNodes2;
+ const SMDS_MeshElement* faceOut = is1in2 ? myFace2 : myFace1;
+ const SMDS_MeshElement* faceIn = is1in2 ? myFace1 : myFace2;
+
+ const CutFace& outFace = myCutFaces.Added( CutFace( faceOut ));
+ CutLink link1( nodesIn.back().Node(), nodesIn.back().Node(), faceOut );
+ CutLink link2( nodesIn.back().Node(), nodesIn.back().Node(), faceOut );
+
+ link1.myIntNode = nodesIn.back();
+ for ( size_t i = 0; i < nodesIn.size(); ++i )
+ {
+ link2.myIntNode = nodesIn[ i ];
+ outFace.AddEdge( link1, link2, faceIn, minNbOnPlane );
+ link1.myIntNode = link2.myIntNode;
+ }
+ }
+ else
+ {
+ // add parts of edges to a triangle including them
+
+ CutLink link1, link2;
+ IntPoint2D ip0, ip1;
+ ip0.myU[0] = ip0.myU[1] = 0.;
+ ip1.myU[0] = ip1.myU[1] = 1.;
+ ip0.myEdgeInd[0] = ip0.myEdgeInd[1] = ip1.myEdgeInd[0] = ip1.myEdgeInd[1] = 0;
+
+ for ( int isFromFace1 = 0; isFromFace1 < 2; ++isFromFace1 )
+ {
+ const SMDS_MeshElement* faceTo = isFromFace1 ? myFace2 : myFace1;
+ const SMDS_MeshElement* faceFrom = isFromFace1 ? myFace1 : myFace2;
+ const std::vector< SMESH_NodeXYZ >& nodesTo = isFromFace1 ? myNodes2 : myNodes1;
+ const std::vector< SMESH_NodeXYZ >& nodesFrom = isFromFace1 ? myNodes1 : myNodes2;
+ const int iTo = isFromFace1 ? 1 : 0;
+ const int iFrom = isFromFace1 ? 0 : 1;
+ //const int nbOnPlaneFrom = isFromFace1 ? myNbOnPlane1 : myNbOnPlane2;
+
+ const CutFace* cutFaceTo = & myCutFaces.Added( CutFace( faceTo ));
+ // const CutFace* cutFaceFrom = 0;
+ // if ( nbOnPlaneFrom > minNbOnPlane )
+ // cutFaceFrom = & myCutFaces.Added( CutFace( faceTo ));
+
+ link1.myFace = link2.myFace = faceTo;
+
+ IntPoint2DCompare ipCompare( iFrom );
+ TIntPointPtrSet pointsOnEdge( ipCompare ); // IntPoint2D sorted by parameter on edge
+
+ for ( size_t iE = 0; iE < nodesFrom.size(); ++iE )
+ {
+ // get parts of an edge iE
+
+ ip0.myEdgeInd[ iTo ] = iE;
+ ip1.myEdgeInd[ iTo ] = ( iE + 1 ) % nodesFrom.size();
+ ip0.myNode = nodesFrom[ ip0.myEdgeInd[ iTo ]];
+ ip1.myNode = nodesFrom[ ip1.myEdgeInd[ iTo ]];
+
+ pointsOnEdge.clear();
+
+ for ( int iP = 0; iP < nbIntPoints; ++iP )
+ if ( intPoints[ iP ].myEdgeInd[ iFrom ] == iE )
+ pointsOnEdge.insert( & intPoints[ iP ] );
+
+ pointsOnEdge.insert( pointsOnEdge.begin(), & ip0 );
+ pointsOnEdge.insert( pointsOnEdge.end(), & ip1 );
+
+ // add edge parts to faceTo
+
+ TIntPointPtrSet::iterator ipIt = pointsOnEdge.begin() + 1;
+ for ( ; ipIt != pointsOnEdge.end(); ++ipIt )
+ {
+ const IntPoint2D* p1 = *(ipIt-1);
+ const IntPoint2D* p2 = *ipIt;
+ gp_XYZ middle = 0.5 * ( p1->myNode + p2->myNode );
+ if ( isPointInTriangle( middle, nodesTo ))
+ {
+ p1->InitLink( link1, iTo, ( p1 != & ip0 ) ? nodesTo : nodesFrom );
+ p2->InitLink( link2, iTo, ( p2 != & ip1 ) ? nodesTo : nodesFrom );
+ cutFaceTo->AddEdge( link1, link2, faceFrom, minNbOnPlane );
+
+ // if ( cutFaceFrom )
+ // {
+ // p1->InitLink( link1, iFrom, nodesFrom );
+ // p2->InitLink( link2, iFrom, nodesFrom );
+ // cutFaceTo->AddEdge( link1, link2, faceTo, minNbOnPlane );
+ // }
+ }
+ }
+ }
+ }
+ }
+ return;
+
+ } // Intersector::cutCoplanar()
+
+ //================================================================================
+ /*!
+ * \brief Intersect edges added to myCutFaces
+ */
+ //================================================================================
+
+ void Intersector::intersectNewEdges( const CutFace& cf )
+ {
+ IntPoint2D intPoint;
+
+ if ( cf.NbInternalEdges() < 2 )
+ return;
+
+ const gp_XYZ& faceNorm = myNormals[ cf.myInitFace->GetID() ];
+ setPlaneIndices( faceNorm ); // choose indices on an axis-aligned plane
+
+ size_t limit = cf.myLinks.size() * cf.myLinks.size() * 2;
+
+ for ( size_t i1 = 3; i1 < cf.myLinks.size(); ++i1 )
+ {
+ if ( !cf.myLinks[i1].IsInternal() )
+ continue;
+
+ myIntPointSet.clear();
+ for ( size_t i2 = i1 + 2; i2 < cf.myLinks.size(); ++i2 )
+ {
+ if ( !cf.myLinks[i2].IsInternal() )
+ continue;
+
+ // prepare to intersection
+ myFace1 = cf.myLinks[i1].myFace;
+ myNodes1[0] = cf.myLinks[i1].myNode1;
+ myNodes1[1] = cf.myLinks[i1].myNode2;
+ myFace2 = cf.myLinks[i2].myFace;
+ myNodes2[0] = cf.myLinks[i2].myNode1;
+ myNodes2[1] = cf.myLinks[i2].myNode2;
+
+ // intersect
+ intPoint.myIsCollinear = true; // to find collinear solutions
+ if ( intersectEdgeEdge( 0, 0, intPoint ))
+ {
+ if ( cf.myLinks[i1].IsSame( cf.myLinks[i2] )) // remove i2
+ {
+ cf.myLinks[i1].ReplaceCoplanar( cf.myLinks[i2] );
+ cf.myLinks.erase( cf.myLinks.begin() + i2, cf.myLinks.begin() + i2 + 2 );
+ --i2;
+ continue;
+ }
+ if ( !intPoint.myIsCollinear )
+ {
+ intPoint.myEdgeInd[1] = i2;
+ myIntPointSet.insert( intPoint );
+ }
+ else // if ( intPoint.myIsCollinear ) // overlapping edges
+ {
+ myIntPointSet.clear(); // to recompute
+
+ if ( intPoint.myU[0] > intPoint.myU[1] ) // orient in same direction
+ {
+ std::swap( intPoint.myU[0], intPoint.myU[1] );
+ std::swap( myNodes1[0], myNodes1[1] );
+ }
+ // replace _COPLANAR by _INTERNAL
+ cf.myLinks[i1].ReplaceCoplanar( cf.myLinks[i1+1] );
+ cf.myLinks[i2].ReplaceCoplanar( cf.myLinks[i2+1] );
+
+ if ( coincide( myNodes1[0], myNodes2[0], myTol ) &&
+ coincide( myNodes1[1], myNodes2[1], myTol ))
+ {
+ cf.myLinks.erase( cf.myLinks.begin() + i2, cf.myLinks.begin() + i2 + 2 );
+ --i2;
+ continue;
+ }
+
+ EdgePart common = cf.myLinks[i1];
+ common.ReplaceCoplanar( cf.myLinks[i2] );
+
+ const SMDS_MeshNode* n1 = myNodes1[0].Node(); // end nodes of an overlapping part
+ const SMDS_MeshNode* n2 = myNodes1[1].Node();
+ size_t i3 = cf.myLinks.size();
+
+ if ( myNodes1[0] != myNodes2[0] ) // a part before the overlapping one
+ {
+ if ( intPoint.myU[0] < 0 )
+ cf.myLinks[i1].Set( myNodes1[0].Node(), myNodes2[0].Node(),
+ cf.myLinks[i1].myFace, cf.myLinks[i1].myIndex );
+ else
+ cf.myLinks[i1].Set( myNodes2[0].Node(), myNodes1[0].Node(),
+ cf.myLinks[i2].myFace, cf.myLinks[i2].myIndex );
+
+ cf.myLinks[i1+1].Set( cf.myLinks[i1].myNode2,
+ cf.myLinks[i1].myNode1,
+ cf.myLinks[i1].myFace,
+ cf.myLinks[i1].myIndex);
+ n1 = cf.myLinks[i1].myNode2;
+ }
+ else
+ i3 = i1;
+
+ if ( myNodes1[1] != myNodes2[1] ) // a part after the overlapping one
+ {
+ if ( intPoint.myU[1] < 1 )
+ cf.myLinks[i2].Set( myNodes1[1].Node(), myNodes2[1].Node(),
+ cf.myLinks[i2].myFace, cf.myLinks[i2].myIndex );
+ else
+ cf.myLinks[i2].Set( myNodes2[1].Node(), myNodes1[1].Node(),
+ cf.myLinks[i1].myFace, cf.myLinks[i1].myIndex );
+
+ cf.myLinks[i2+1].Set( cf.myLinks[i2].myNode2,
+ cf.myLinks[i2].myNode1,
+ cf.myLinks[i2].myFace,
+ cf.myLinks[i2].myIndex);
+ n2 = cf.myLinks[i2].myNode1;
+ }
+ else
+ i3 = i2;
+
+ if ( i3 == cf.myLinks.size() )
+ cf.myLinks.resize( i3 + 2 );
+
+ cf.myLinks[i3].Set ( n1, n2, common.myFace, common.myIndex );
+ cf.myLinks[i3+1].Set( n2, n1, common.myFace, common.myIndex );
+
+ i2 = i1 + 1; // recheck modified i1
+ continue;
+ }
+ //else
+ // {
+ // // remember a new node
+ // CutLink link1( myNodes1[0].Node(), myNodes1[1].Node(), cf.myInitFace );
+ // CutLink link2( myNodes2[0].Node(), myNodes2[1].Node(), cf.myInitFace );
+ // link2.myIntNode = link1.myIntNode = intPoint.myNode;
+ // addLink( link1 );
+ // addLink( link2 );
+
+ // // split edges
+ // size_t i = cf.myLinks.size();
+ // if ( intPoint.myNode != cf.myLinks[ i1 ].myNode1 &&
+ // intPoint.myNode != cf.myLinks[ i1 ].myNode2 )
+ // {
+ // cf.myLinks.push_back( cf.myLinks[ i1 ]);
+ // cf.myLinks.push_back( cf.myLinks[ i1 + 1 ]);
+ // cf.myLinks[ i1 ].myNode2 = cf.myLinks[ i1 + 1 ].myNode1 = intPoint.Node();
+ // cf.myLinks[ i ].myNode1 = cf.myLinks[ i + 1 ].myNode2 = intPoint.Node();
+ // }
+ // if ( intPoint.myNode != cf.myLinks[ i2 ].myNode1 &&
+ // intPoint.myNode != cf.myLinks[ i2 ].myNode2 )
+ // {
+ // i = cf.myLinks.size();
+ // cf.myLinks.push_back( cf.myLinks[ i2 ]);
+ // cf.myLinks.push_back( cf.myLinks[ i2 + 1 ]);
+ // cf.myLinks[ i2 ].myNode2 = cf.myLinks[ i2 + 1 ].myNode1 = intPoint.Node();
+ // cf.myLinks[ i ].myNode1 = cf.myLinks[ i + 1 ].myNode2 = intPoint.Node();
+ // }
+ // }
+
+ } // if ( intersectEdgeEdge( 0, 0, intPoint ))
+
+ ++i2;
+ --limit;
+ }
+
+ // split i1 edge and all edges it intersects
+ // don't do it inside intersection loop in order not to loose direction of i1 edge
+ if ( !myIntPointSet.empty() )
+ {
+ cf.myLinks.reserve( cf.myLinks.size() + myIntPointSet.size() * 2 + 2 );
+
+ EdgePart* edge1 = &cf.myLinks[ i1 ];
+ EdgePart* twin1 = &cf.myLinks[ i1 + 1 ];
+
+ TIntPointSet::iterator ipIt = myIntPointSet.begin();
+ for ( ; ipIt != myIntPointSet.end(); ++ipIt ) // int points sorted on i1 edge
+ {
+ size_t i = cf.myLinks.size();
+ if ( ipIt->myNode != edge1->myNode1 &&
+ ipIt->myNode != edge1->myNode2 )
+ {
+ cf.myLinks.push_back( *edge1 );
+ cf.myLinks.push_back( *twin1 );
+ edge1->myNode2 = twin1->myNode1 = ipIt->Node();
+ cf.myLinks[ i ].myNode1 = cf.myLinks[ i + 1 ].myNode2 = ipIt->Node();
+ edge1 = & cf.myLinks[ i ];
+ twin1 = & cf.myLinks[ i + 1 ];
+ }
+ size_t i2 = ipIt->myEdgeInd[1];
+ if ( ipIt->myNode != cf.myLinks[ i2 ].myNode1 &&
+ ipIt->myNode != cf.myLinks[ i2 ].myNode2 )
+ {
+ i = cf.myLinks.size();
+ cf.myLinks.push_back( cf.myLinks[ i2 ]);
+ cf.myLinks.push_back( cf.myLinks[ i2 + 1 ]);
+ cf.myLinks[ i2 ].myNode2 = cf.myLinks[ i2 + 1 ].myNode1 = ipIt->Node();
+ cf.myLinks[ i ].myNode1 = cf.myLinks[ i + 1 ].myNode2 = ipIt->Node();
+ }
+ }
+ if ( cf.myLinks.size() >= limit )
+ throw SALOME_Exception( "Infinite loop in Intersector::intersectNewEdges()" );
+ }
+ ++i1; // each internal edge encounters twice
+ }
+ return;
+ }
+
+ //================================================================================
+ /*!
+ * \brief Split intersected faces
+ */
+ //================================================================================
+
+ void Intersector::MakeNewFaces( SMESH_MeshAlgos::TEPairVec& theNew2OldFaces,
+ SMESH_MeshAlgos::TNPairVec& theNew2OldNodes,
+ const double theSign)
+ {
+ // unmark all nodes except intersection ones
+
+ for ( SMDS_NodeIteratorPtr nIt = myMesh->nodesIterator(); nIt->more(); )
+ {
+ const SMDS_MeshNode* n = nIt->next();
+ if ( n->isMarked() && n->GetID()-1 < (int) theNew2OldNodes.size() )
+ n->setIsMarked( false );
+ }
+ // SMESH_MeshAlgos::MarkElems( myMesh->nodesIterator(), false );
+
+ TCutLinkMap::const_iterator cutLinksIt = myCutLinks.cbegin();
+ // for ( ; cutLinksIt != myCutLinks.cend(); ++cutLinksIt )
+ // {
+ // const CutLink& link = *cutLinksIt;
+ // if ( link.IntNode() && link.IntNode()->GetID()-1 < (int) theNew2OldNodes.size() )
+ // link.IntNode()->setIsMarked( true );
+ // }
+
+ // intersect edges added to myCutFaces
+
+ TCutFaceMap::const_iterator cutFacesIt = myCutFaces.cbegin();
+ for ( ; cutFacesIt != myCutFaces.cend(); ++cutFacesIt )
+ {
+ const CutFace& cf = *cutFacesIt;
+ cf.ReplaceNodes( myRemove2KeepNodes );
+ intersectNewEdges( cf );
+ }
+
+ // make new faces
+
+ EdgeLoopSet loopSet;
+ SMESH_MeshAlgos::Triangulate triangulator;
+ std::vector< EdgePart > cutOffLinks;
+ TLinkMap cutOffCoplanarLinks;
+ std::vector< const CutFace* > touchedFaces;
+ SMESH_MeshAlgos::TEPairVec::value_type new2OldTria;
+ CutFace cutFace(0);
+ std::vector< const SMDS_MeshNode* > nodes;
+ std::vector<const SMDS_MeshElement *> faces;
+
+ cutOffLinks.reserve( myCutFaces.Extent() * 2 );
+
+ for ( cutFacesIt = myCutFaces.cbegin(); cutFacesIt != myCutFaces.cend(); ++cutFacesIt )
+ {
+ const CutFace& cf = *cutFacesIt;
+ if ( !cf.IsCut() )
+ {
+ touchedFaces.push_back( & cf );
+ continue;
+ }
+
+ const gp_XYZ& normal = myNormals[ cf.myInitFace->GetID() ];
+
+ // form loops of new faces
+ cf.ReplaceNodes( myRemove2KeepNodes );
+ cf.MakeLoops( loopSet, normal );
+
+ // avoid loops that are not connected to boundary edges of cf.myInitFace
+ if ( cf.RemoveInternalLoops( loopSet ))
+ {
+ intersectNewEdges( cf );
+ cf.MakeLoops( loopSet, normal );
+ }
+ // erase loops that are cut off by face intersections
+ cf.CutOffLoops( loopSet, theSign, myNormals, cutOffLinks, cutOffCoplanarLinks );
+
+ int index = cf.myInitFace->GetID(); // index in theNew2OldFaces
+
+ const SMDS_MeshElement* tria;
+ for ( size_t iL = 0; iL < loopSet.myNbLoops; ++iL )
+ {
+ EdgeLoop& loop = loopSet.myLoops[ iL ];
+ if ( loop.myLinks.size() == 0 )
+ continue;
+
+ int nbTria = triangulator.GetTriangles( &loop, nodes );
+ int nbNodes = 3 * nbTria;
+ for ( int i = 0; i < nbNodes; i += 3 )
+ {
+ if ( nodes[i] == nodes[i+1] || nodes[i] == nodes[i+2] || nodes[i+1] == nodes[i+2] )
+ {
+#ifdef _DEBUG_
+ std::cerr << "BAD tria" << std::endl;
+ cf.Dump();
+#endif
+ continue;
+ }
+ if (!( tria = myMesh->FindFace( nodes[i], nodes[i+1], nodes[i+2] )))
+ tria = myMesh->AddFace( nodes[i], nodes[i+1], nodes[i+2] );
+ tria->setIsMarked( true ); // not to remove it
+
+ new2OldTria = std::make_pair( tria, theNew2OldFaces[ index ].second );
+ if ( tria->GetID() < (int)theNew2OldFaces.size() )
+ theNew2OldFaces[ tria->GetID() ] = new2OldTria;
+ else
+ theNew2OldFaces.push_back( new2OldTria );
+
+ if ( index == tria->GetID() )
+ index = 0; // do not remove tria
+ }
+ }
+ theNew2OldFaces[ index ].first = 0;
+ }
+
+ // remove split faces
+ for ( size_t id = 1; id < theNew2OldFaces.size(); ++id )
+ {
+ if ( theNew2OldFaces[id].first )
+ continue;
+ if ( const SMDS_MeshElement* f = myMesh->FindElement( id ))
+ myMesh->RemoveFreeElement( f );
+ }
+
+ // remove face connected to cut off parts of cf.myInitFace
+
+ nodes.resize(2);
+ for ( size_t i = 0; i < cutOffLinks.size(); ++i )
+ {
+ //break;
+ nodes[0] = cutOffLinks[i].myNode1;
+ nodes[1] = cutOffLinks[i].myNode2;
+
+ if ( nodes[0] != nodes[1] &&
+ myMesh->GetElementsByNodes( nodes, faces ))
+ {
+ if ( cutOffLinks[i].myFace &&
+ cutOffLinks[i].myIndex != EdgePart::_COPLANAR &&
+ faces.size() == 2 )
+ continue;
+ for ( size_t iF = 0; iF < faces.size(); ++iF )
+ {
+ int index = faces[iF]->GetID();
+ // if ( //faces[iF]->isMarked() || // kept part of cutFace
+ // !theNew2OldFaces[ index ].first ) // already removed
+ // continue;
+ cutFace.myInitFace = faces[iF];
+ // if ( myCutFaces.Contains( cutFace )) // keep cutting faces needed in CutOffLoops()
+ // {
+ // if ( !myCutFaces.Added( cutFace ).IsCut() )
+ // theNew2OldFaces[ index ].first = 0;
+ // continue;
+ // }
+ cutFace.myLinks.clear();
+ cutFace.InitLinks();
+ for ( size_t iL = 0; iL < cutFace.myLinks.size(); ++iL )
+ if ( !cutOffLinks[i].IsSame( cutFace.myLinks[ iL ]))
+ cutOffLinks.push_back( cutFace.myLinks[ iL ]);
+
+ theNew2OldFaces[ index ].first = 0;
+ myMesh->RemoveFreeElement( faces[iF] );
+ }
+ }
+ }
+
+ // replace nodes in touched faces
+
+ // treat touched faces
+ for ( size_t i = 0; i < touchedFaces.size(); ++i )
+ {
+ const CutFace& cf = *touchedFaces[i];
+
+ int index = cf.myInitFace->GetID(); // index in theNew2OldFaces
+ if ( !theNew2OldFaces[ index ].first )
+ continue; // already cut off
+
+ if ( !cf.ReplaceNodes( myRemove2KeepNodes ))
+ continue; // just keep as is
+
+ if ( cf.myLinks.size() == 3 )
+ {
+ const SMDS_MeshElement* tria = myMesh->AddFace( cf.myLinks[0].myNode1,
+ cf.myLinks[1].myNode1,
+ cf.myLinks[2].myNode1 );
+ new2OldTria = std::make_pair( tria, theNew2OldFaces[ index ].second );
+ if ( tria->GetID() < (int)theNew2OldFaces.size() )
+ theNew2OldFaces[ tria->GetID() ] = new2OldTria;
+ else
+ theNew2OldFaces.push_back( new2OldTria );
+ }
+ theNew2OldFaces[ index ].first = 0;
+ }
+
+
+ // add used new nodes to theNew2OldNodes
+ SMESH_MeshAlgos::TNPairVec::value_type new2OldNode;
+ new2OldNode.second = NULL;
+ for ( cutLinksIt = myCutLinks.cbegin(); cutLinksIt != myCutLinks.cend(); ++cutLinksIt )
+ {
+ const CutLink& link = *cutLinksIt;
+ if ( link.IntNode() ) // && link.IntNode()->NbInverseElements() > 0 )
+ {
+ new2OldNode.first = link.IntNode();
+ theNew2OldNodes.push_back( new2OldNode );
+ }
+ }
+
+ return;
+ }
+
+ //================================================================================
+ /*!
+ * \brief Debug
+ */
+ //================================================================================
+
+ void CutFace::Dump() const
+ {
+ std::cout << std::endl << "INI F " << myInitFace->GetID() << std::endl;
+ for ( size_t i = 0; i < myLinks.size(); ++i )
+ std::cout << "[" << i << "] ("
+ << char(( myLinks[i].IsInternal() ? 'j' : '0' ) + myLinks[i].myIndex ) << ") "
+ << myLinks[i].myNode1->GetID() << " - " << myLinks[i].myNode2->GetID()
+ << " " << ( myLinks[i].myFace ? 'F' : 'C' )
+ << ( myLinks[i].myFace ? myLinks[i].myFace->GetID() : 0 ) << " " << std::endl;
+ }
+
+ //================================================================================
+ /*!
+ * \brief Add an edge cutting this face
+ * \param [in] p1 - start point of the edge
+ * \param [in] p2 - end point of the edge
+ * \param [in] cutter - a face producing the added cut edge.
+ * \param [in] nbOnPlane - nb of triangle nodes lying on the plane of the cutter face
+ */
+ //================================================================================
+
+ void CutFace::AddEdge( const CutLink& p1,
+ const CutLink& p2,
+ const SMDS_MeshElement* cutterFace,
+ const int nbOnPlane,
+ const int iNotOnPlane) const
+ {
+ int iN[2] = { myInitFace->GetNodeIndex( p1.IntNode() ),
+ myInitFace->GetNodeIndex( p2.IntNode() ) };
+ if ( iN[0] >= 0 && iN[1] >= 0 )
+ {
+ // the cutting edge is a whole side
+ if (( cutterFace && nbOnPlane < 3 ) &&
+ !( cutterFace->GetNodeIndex( p1.IntNode() ) >= 0 &&
+ cutterFace->GetNodeIndex( p2.IntNode() ) >= 0 ))
+ {
+ InitLinks();
+ myLinks[ Abs( iN[0] - iN[1] ) == 1 ? Min( iN[0], iN[1] ) : 2 ].myFace = cutterFace;
+ }
+ return;
+ }
+
+ if ( p1.IntNode() == p2.IntNode() )
+ {
+ AddPoint( p1, p2, 1e-10 );
+ return;
+ }
+
+ InitLinks();
+
+ // cut side edges by a new one
+
+ int iEOnPlane = ( nbOnPlane == 2 ) ? ( iNotOnPlane + 1 ) % 3 : -1;
+
+ double dist[2];
+ for ( int is2nd = 0; is2nd < 2; ++is2nd )
+ {
+ const CutLink& p = is2nd ? p2 : p1;
+ dist[ is2nd ] = 0;
+ if ( iN[ is2nd ] >= 0 )
+ continue;
+
+ int iE = Max( iEOnPlane, myInitFace->GetNodeIndex( p.Node1() ));
+ if ( iE < 0 )
+ continue; // link of other face
+
+ SMESH_NodeXYZ n0 = myLinks[iE].myNode1;
+ dist[ is2nd ] = ( n0 - p.myIntNode ).SquareModulus();
+
+ for ( size_t i = 0; i < myLinks.size(); ++i )
+ if ( myLinks[i].myIndex == iE )
+ {
+ double d1 = n0.SquareDistance( myLinks[i].myNode1 );
+ if ( d1 < dist[ is2nd ] )
+ {
+ double d2 = n0.SquareDistance( myLinks[i].myNode2 );
+ if ( dist[ is2nd ] < d2 )
+ {
+ myLinks.push_back( myLinks[i] );
+ myLinks.back().myNode1 = myLinks[i].myNode2 = p.IntNode();
+ break;
+ }
+ }
+ }
+ }
+
+ int state = nbOnPlane == 3 ? EdgePart::_COPLANAR : EdgePart::_INTERNAL;
+
+ // look for an existing equal edge
+ if ( nbOnPlane == 2 )
+ {
+ SMESH_NodeXYZ n0 = myLinks[ iEOnPlane ].myNode1;
+ if ( iN[0] >= 0 ) dist[0] = ( n0 - p1.myIntNode ).SquareModulus();
+ if ( iN[1] >= 0 ) dist[1] = ( n0 - p2.myIntNode ).SquareModulus();
+ if ( dist[0] > dist[1] )
+ std::swap( dist[0], dist[1] );
+ for ( size_t i = 0; i < myLinks.size(); ++i )
+ {
+ if ( myLinks[i].myIndex != iEOnPlane )
+ continue;
+ gp_XYZ mid = 0.5 * ( SMESH_NodeXYZ( myLinks[i].myNode1 ) +
+ SMESH_NodeXYZ( myLinks[i].myNode2 ));
+ double d = ( n0 - mid ).SquareModulus();
+ if ( dist[0] < d && d < dist[1] )
+ myLinks[i].myFace = cutterFace;
+ }
+ return;
+ }
+ else
+ {
+ EdgePart newEdge; newEdge.Set( p1.IntNode(), p2.IntNode(), cutterFace, state );
+ for ( size_t i = 0; i < myLinks.size(); ++i )
+ {
+ if ( myLinks[i].IsSame( newEdge ))
+ {
+ // if ( !myLinks[i].IsInternal() )
+ // myLinks[ i ].myFace = cutterFace;
+ // else
+ myLinks[ i ].ReplaceCoplanar( newEdge );
+ myLinks[ i+1 ].ReplaceCoplanar( newEdge );
+ return;
+ }
+ i += myLinks[i].IsInternal();
+ }
+ }
+
+ size_t i = myLinks.size();
+ myLinks.resize( i + 2 );
+ myLinks[ i ].Set( p1.IntNode(), p2.IntNode(), cutterFace, state );
+ myLinks[ i+1 ].Set( p2.IntNode(), p1.IntNode(), cutterFace, state );
+ }
+
+ //================================================================================
+ /*!
+ * \brief Add a point cutting this face
+ */
+ //================================================================================
+
+ void CutFace::AddPoint( const CutLink& p1, const CutLink& p2, double tol ) const
+ {
+ if ( myInitFace->GetNodeIndex( p1.IntNode() ) >= 0 ||
+ myInitFace->GetNodeIndex( p2.IntNode() ) >= 0 )
+ return;
+
+ InitLinks();
+
+ const CutLink* link = &p1;
+ int iE = myInitFace->GetNodeIndex( link->Node1() );
+ if ( iE < 0 )
+ {
+ link = &p2;
+ iE = myInitFace->GetNodeIndex( link->Node1() );
+ }
+ if ( iE >= 0 )
+ {
+ // cut an existing edge by the point
+ SMESH_NodeXYZ n0 = link->Node1();
+ double d = ( n0 - link->myIntNode ).SquareModulus();
+
+ for ( size_t i = 0; i < myLinks.size(); ++i )
+ if ( myLinks[i].myIndex == iE )
+ {
+ double d1 = n0.SquareDistance( myLinks[i].myNode1 );
+ if ( d1 < d )
+ {
+ double d2 = n0.SquareDistance( myLinks[i].myNode2 );
+ if ( d < d2 )
+ {
+ myLinks.push_back( myLinks[i] );
+ myLinks.back().myNode1 = myLinks[i].myNode2 = link->IntNode();
+ return;
+ }
+ }
+ }
+ }
+ else // point is inside the triangle
+ {
+ // // check if a point already added
+ // for ( size_t i = 3; i < myLinks.size(); ++i )
+ // if ( myLinks[i].myNode1 == p1.IntNode() )
+ // return;
+
+ // // create a link between the point and the closest corner node
+ // const SMDS_MeshNode* closeNode = myLinks[0].myNode1;
+ // double minDist = p1.myIntNode.SquareDistance( closeNode );
+ // for ( int i = 1; i < 3; ++i )
+ // {
+ // double dist = p1.myIntNode.SquareDistance( myLinks[i].myNode1 );
+ // if ( dist < minDist )
+ // {
+ // minDist = dist;
+ // closeNode = myLinks[i].myNode1;
+ // }
+ // }
+ // if ( minDist > tol * tol )
+ // {
+ // size_t i = myLinks.size();
+ // myLinks.resize( i + 2 );
+ // myLinks[ i ].Set( p1.IntNode(), closeNode );
+ // myLinks[ i+1 ].Set( closeNode, p1.IntNode() );
+ // }
+ }
+ }
+
+ //================================================================================
+ /*!
+ * \brief Perform node replacement
+ */
+ //================================================================================
+
+ bool CutFace::ReplaceNodes( const TNNMap& theRm2KeepMap ) const
+ {
+ bool replaced = false;
+ for ( size_t i = 0; i < myLinks.size(); ++i )
+ {
+ while ( theRm2KeepMap.IsBound((Standard_Address) myLinks[i].myNode1 ))
+ replaced = ( myLinks[i].myNode1 = theRm2KeepMap((Standard_Address) myLinks[i].myNode1 ));
+
+ while ( theRm2KeepMap.IsBound((Standard_Address) myLinks[i].myNode2 ))
+ replaced = ( myLinks[i].myNode2 = theRm2KeepMap((Standard_Address) myLinks[i].myNode2 ));
+ }
+
+ //if ( replaced ) // remove equal links
+ {
+ for ( size_t i1 = 0; i1 < myLinks.size(); ++i1 )
+ {
+ if ( myLinks[i1].myNode1 == myLinks[i1].myNode2 )
+ {
+ myLinks.erase( myLinks.begin() + i1,
+ myLinks.begin() + i1 + 1 + myLinks[i1].IsInternal() );
+ --i1;
+ continue;
+ }
+ size_t i2 = i1 + 1 + myLinks[i1].IsInternal();
+ for ( ; i2 < myLinks.size(); ++i2 )
+ {
+ if ( !myLinks[i2].IsInternal() )
+ continue;
+ if ( myLinks[i1].IsSame( myLinks[i2] ))
+ {
+ myLinks[i1]. ReplaceCoplanar( myLinks[i2] );
+ if ( myLinks[i1].IsInternal() )
+ myLinks[i1+1].ReplaceCoplanar( myLinks[i2+1] );
+ if ( !myLinks[i1].myFace && myLinks[i2].myFace )
+ {
+ myLinks[i1]. myFace = myLinks[i2].myFace;
+ if ( myLinks[i1].IsInternal() )
+ myLinks[i1+1].myFace = myLinks[i2+1].myFace;
+ }
+ myLinks.erase( myLinks.begin() + i2,
+ myLinks.begin() + i2 + 2 );
+ --i2;
+ continue;
+ }
+ ++i2;
+ }
+ i1 += myLinks[i1].IsInternal();
+ }
+ }
+
+ return replaced;
+ }
+
+ //================================================================================
+ /*!
+ * \brief Initialize myLinks with edges of myInitFace
+ */
+ //================================================================================
+
+ void CutFace::InitLinks() const
+ {
+ if ( !myLinks.empty() ) return;
+
+ int nbNodes = myInitFace->NbNodes();
+ myLinks.reserve( nbNodes * 2 );
+ myLinks.resize( nbNodes );
+
+ for ( int i = 0; i < nbNodes; ++i )
+ {
+ const SMDS_MeshNode* n1 = myInitFace->GetNode( i );
+ const SMDS_MeshNode* n2 = myInitFace->GetNodeWrap( i + 1);
+ myLinks[i].Set( n1, n2, 0, i );
+ }
+ }
+
+ //================================================================================
+ /*!
+ * \brief Return number of internal edges
+ */
+ //================================================================================
+
+ int CutFace::NbInternalEdges() const
+ {
+ int nb = 0;
+ for ( size_t i = 3; i < myLinks.size(); ++i )
+ nb += myLinks[i].IsInternal();
+
+ return nb / 2; // each internal edge encounters twice
+ }
+
+ //================================================================================
+ /*!
+ * \brief Remove loops that are not connected to boundary edges of myFace by
+ * adding edges connecting these loops to the boundary
+ */
+ //================================================================================
+
+ bool CutFace::RemoveInternalLoops( EdgeLoopSet& theLoops ) const
+ {
+ size_t nbReachedLoops = 0;
+
+ // count loops including boundary EdgeParts
+ for ( size_t iL = 0; iL < theLoops.myNbLoops; ++iL )
+ {
+ EdgeLoop& loop = theLoops.myLoops[ iL ];
+
+ for ( size_t iE = 0; iE < loop.myLinks.size(); ++iE )
+ if ( !loop.myLinks[ iE ]->IsInternal() )
+ {
+ nbReachedLoops += loop.SetConnected();
+ break;
+ }
+ }
+ if ( nbReachedLoops == theLoops.myNbLoops )
+ return false; // no unreachable loops
+
+
+ // try to reach all loops by propagating via internal edges shared by loops
+ size_t prevNbReached;
+ do
+ {
+ prevNbReached = nbReachedLoops;
+
+ for ( size_t iL = 0; iL < theLoops.myNbLoops; ++iL )
+ {
+ EdgeLoop& loop = theLoops.myLoops[ iL ];
+ if ( !loop.myIsBndConnected )
+ continue;
+
+ for ( size_t iE = 0; iE < loop.myLinks.size(); ++iE )
+ if ( loop.myLinks[ iE ]->IsInternal() )
+ {
+ const EdgePart* twinEdge = getTwin( loop.myLinks[ iE ]);
+ EdgeLoop* loop2 = theLoops.GetLoopOf( twinEdge );
+ if ( loop2->SetConnected() && ++nbReachedLoops == theLoops.myNbLoops )
+ return false; // no unreachable loops
+ }
+ }
+ }
+ while ( prevNbReached < nbReachedLoops );
+
+
+ // add links connecting internal loops with the boundary ones
+
+ for ( size_t iL = 0; iL < theLoops.myNbLoops; ++iL )
+ {
+ EdgeLoop& loop = theLoops.myLoops[ iL ];
+ if ( loop.myIsBndConnected )
+ continue;
+
+ // find a pair of closest nodes
+ const SMDS_MeshNode *closestNode1, *closestNode2;
+ double minDist = 1e100;
+ for ( size_t iE = 0; iE < loop.myLinks.size(); ++iE )
+ {
+ SMESH_NodeXYZ n1 = loop.myLinks[ iE ]->myNode1;
+
+ for ( size_t i = 0; i < myLinks.size(); ++i )
+ {
+ if ( !loop.Contains( myLinks[i].myNode1 ))
+ {
+ double dist = n1.SquareDistance( myLinks[i].myNode1 );
+ if ( dist < minDist )
+ {
+ minDist = dist;
+ closestNode1 = loop.myLinks[ iE ]->myNode1;
+ closestNode2 = myLinks[i].myNode1;
+ }
+ }
+ if ( myLinks[i].IsInternal() )
+ ++i;
+ }
+ }
+
+ size_t i = myLinks.size();
+ myLinks.resize( i + 2 );
+ myLinks[ i ].Set( closestNode1, closestNode2 );
+ myLinks[ i+1 ].Set( closestNode2, closestNode1 );
+ }
+
+ return true;
+ }
+
+ //================================================================================
+ /*!
+ * \brief Return equal reversed edge
+ */
+ //================================================================================
+
+ EdgePart* CutFace::getTwin( const EdgePart* edge ) const
+ {
+ size_t i = edge - & myLinks[0];
+
+ if ( i > 2 && myLinks[ i-1 ].IsTwin( *edge ))
+ return & myLinks[ i-1 ];
+
+ if ( i+1 < myLinks.size() &&
+ myLinks[ i+1 ].IsTwin( *edge ))
+ return & myLinks[ i+1 ];
+
+ return 0;
+ }
+
+ //================================================================================
+ /*!
+ * \brief Fill loops of edges
+ */
+ //================================================================================
+
+ void CutFace::MakeLoops( EdgeLoopSet& theLoops, const gp_XYZ& theFaceNorm ) const
+ {
+ theLoops.Init( myLinks );
+
+ if ( myLinks.size() == 3 )
+ {
+ theLoops.AddNewLoop();
+ theLoops.AddEdge( myLinks[0] );
+ theLoops.AddEdge( myLinks[1] );
+ theLoops.AddEdge( myLinks[2] );
+ return;
+ }
+
+ while ( !theLoops.AllEdgesUsed() )
+ {
+ theLoops.AddNewLoop();
+
+ // add 1st edge to a new loop
+ size_t i1;
+ for ( i1 = theLoops.myNbLoops - 1; i1 < myLinks.size(); ++i1 )
+ if ( theLoops.AddEdge( myLinks[i1] ))
+ break;
+
+ EdgePart* lastEdge = & myLinks[ i1 ];
+ EdgePart* twinEdge = getTwin( lastEdge );
+ const SMDS_MeshNode* firstNode = lastEdge->myNode1;
+ const SMDS_MeshNode* lastNode = lastEdge->myNode2;
+
+ do // add the rest edges
+ {
+ theLoops.myCandidates.clear(); // edges starting at lastNode
+ int nbInternal = 0;
+
+ // find candidate edges
+ for ( size_t i = i1 + 1; i < myLinks.size(); ++i )
+ if ( myLinks[ i ].myNode1 == lastNode &&
+ &myLinks[ i ] != twinEdge &&
+ !theLoops.myIsUsedEdge[ i ])
+ {
+ theLoops.myCandidates.push_back( & myLinks[ i ]);
+ nbInternal += myLinks[ i ].IsInternal();
+ }
+
+ // choose among candidates
+ if ( theLoops.myCandidates.size() == 0 )
+ {
+ theLoops.GetLoopOf( lastEdge )->myHasPending = true;
+ lastEdge = twinEdge;
+ }
+ else if ( theLoops.myCandidates.size() == 1 )
+ {
+ lastEdge = theLoops.myCandidates[0];
+ }
+ else if ( nbInternal == 1 && !lastEdge->IsInternal() )
+ {
+ lastEdge = theLoops.myCandidates[ !theLoops.myCandidates[0]->IsInternal() ];
+ }
+ else
+ {
+ gp_Vec lastVec = *lastEdge;
+ double maxAngle = -2 * M_PI;
+ for ( size_t i = 0; i < theLoops.myCandidates.size(); ++i )
+ {
+ double angle = lastVec.AngleWithRef( *theLoops.myCandidates[i], theFaceNorm );
+ if ( angle > maxAngle )
+ {
+ maxAngle = angle;
+ lastEdge = theLoops.myCandidates[i];
+ }
+ }
+ }
+ theLoops.AddEdge( *lastEdge );
+ lastNode = lastEdge->myNode2;
+ twinEdge = getTwin( lastEdge );
+ }
+ while ( lastNode != firstNode );
+
+ } // while ( !theLoops.AllEdgesUsed() )
+
+ return;
+ }
+
+ //================================================================================
+ /*!
+ * \brief Erase loops that are cut off by face intersections
+ */
+ //================================================================================
+
+ void CutFace::CutOffLoops( EdgeLoopSet& theLoops,
+ const double theSign,
+ const std::vector< gp_XYZ >& theNormals,
+ std::vector< EdgePart >& theCutOffLinks,
+ TLinkMap& theCutOffCoplanarLinks) const
+ {
+ EdgePart sideEdge;
+ for ( size_t i = 0; i < myLinks.size(); ++i )
+ {
+ if ( !myLinks[i].myFace )
+ continue;
+
+ EdgeLoop* loop = theLoops.GetLoopOf( & myLinks[i] );
+ if ( !loop || loop->myLinks.empty() || loop->myHasPending )
+ continue;
+
+ bool toErase, isCoplanar = ( myLinks[i].myIndex == EdgePart::_COPLANAR );
+
+ gp_Vec iniNorm = theNormals[ myInitFace->GetID() ];
+ if ( isCoplanar )
+ {
+ toErase = ( myLinks[i].myFace->GetID() > myInitFace->GetID() );
+
+ const EdgePart* twin = getTwin( & myLinks[i] );
+ if ( !twin || twin->myFace == myLinks[i].myFace )
+ {
+ // only one co-planar face includes myLinks[i]
+ gp_Vec inFaceDir = iniNorm ^ myLinks[i];
+ gp_XYZ edgePnt = SMESH_NodeXYZ( myLinks[i].myNode1 );
+ for ( int iN = 0; iN < 3; ++iN )
+ {
+ gp_Vec inCutFaceDir = ( SMESH_NodeXYZ( myLinks[i].myFace->GetNode( iN )) - edgePnt );
+ if ( inCutFaceDir * inFaceDir < 0 )
+ {
+ toErase = false;
+ break;
+ }
+ }
+ }
+ }
+ else
+ {
+ gp_Vec cutNorm = theNormals[ myLinks[i].myFace->GetID() ];
+ gp_Vec inFaceDir = iniNorm ^ myLinks[i];
+
+ toErase = inFaceDir * cutNorm * theSign < 0;
+ if ( !toErase )
+ {
+ // erase a neighboring loop
+ loop = 0;
+ if ( const EdgePart* twin = getTwin( & myLinks[i] ))
+ loop = theLoops.GetLoopOf( twin );
+ toErase = ( loop && !loop->myLinks.empty() );
+ }
+ }
+
+ if ( toErase )
+ {
+ if ( !isCoplanar )
+ {
+ // remember whole sides of myInitFace that are cut off
+ for ( size_t iE = 0; iE < loop->myLinks.size(); ++iE )
+ {
+ if ( !loop->myLinks[ iE ]->myFace &&
+ !loop->myLinks[ iE ]->IsInternal() )// &&
+ // !loop->myLinks[ iE ]->myNode1->isMarked() && // cut nodes are marked
+ // !loop->myLinks[ iE ]->myNode2->isMarked() )
+ {
+ int i = loop->myLinks[ iE ]->myIndex;
+ sideEdge.Set( myInitFace->GetNode ( i ),
+ myInitFace->GetNodeWrap( i+1 ));
+ theCutOffLinks.push_back( sideEdge );
+
+ if ( !sideEdge.IsSame( *loop->myLinks[ iE ] )) // nodes replaced
+ {
+ theCutOffLinks.push_back( *loop->myLinks[ iE ] );
+ }
+ }
+ else if ( IsCoplanar( loop->myLinks[ iE ]))
+ {
+ // propagate erasure to a co-planar face
+ theCutOffLinks.push_back( *loop->myLinks[ iE ]);
+ }
+ else if ( loop->myLinks[ iE ]->myFace &&
+ loop->myLinks[ iE ]->IsInternal() )
+ theCutOffLinks.push_back( *loop->myLinks[ iE ]);
+ }
+
+ // clear the loop
+ theLoops.Erase( loop );
+ }
+ }
+ }
+ return;
+ }
+
+ //================================================================================
+ /*!
+ * \brief Check if the face has cut edges
+ */
+ //================================================================================
+
+ bool CutFace::IsCut() const
+ {
+ if ( myLinks.size() > 3 )
+ return true;
+
+ if ( myLinks.size() == 3 )
+ for ( size_t i = 0; i < 3; ++i )
+ if ( myLinks[i].myFace )
+ return true;
+
+ return false;
+ }
+
+ //================================================================================
+ /*!
+ * \brief Check if an edge is produced by a co-planar cut
+ */
+ //================================================================================
+
+ bool CutFace::IsCoplanar( const EdgePart* edge ) const
+ {
+ if ( edge->myIndex == EdgePart::_COPLANAR )
+ {
+ const EdgePart* twin = getTwin( edge );
+ return ( !twin || twin->myIndex == EdgePart::_COPLANAR );
+ }
+ return false;
+ }
+
+ //================================================================================
+ /*!
+ * \brief Replace _COPLANAR cut edge by _INTERNAL oe vice versa
+ */
+ //================================================================================
+
+ bool EdgePart::ReplaceCoplanar( const EdgePart& e )
+ {
+ if ( myIndex + e.myIndex == _COPLANAR + _INTERNAL )
+ {
+ //check if the faces are connected
+ int nbCommonNodes = SMESH_MeshAlgos::GetCommonNodes( e.myFace, myFace ).size();
+ bool toReplace = (( myIndex == _INTERNAL && nbCommonNodes > 1 ) ||
+ ( myIndex == _COPLANAR && nbCommonNodes < 2 ));
+ if ( toReplace )
+ {
+ myIndex = e.myIndex;
+ myFace = e.myFace;
+ return true;
+ }
+ }
+ return false;
+ }
+
+} // namespace
+
+//================================================================================
+/*!
+ * \brief Create an offsetMesh of given faces
+ * \param [in] faceIt - the input faces
+ * \param [out] new2OldFaces - history of faces
+ * \param [out] new2OldNodes - history of nodes
+ * \return SMDS_Mesh* - the new offset mesh, a caller should delete
+ */
+//================================================================================
+
+SMDS_Mesh* SMESH_MeshAlgos::MakeOffset( SMDS_ElemIteratorPtr theFaceIt,
+ SMDS_Mesh& theSrcMesh,
+ const double theOffset,
+ const bool theFixIntersections,
+ TEPairVec& theNew2OldFaces,
+ TNPairVec& theNew2OldNodes)
+{
+ SMDS_Mesh* newMesh = new SMDS_Mesh;
+ theNew2OldFaces.clear();
+ theNew2OldNodes.clear();
+ theNew2OldFaces.push_back
+ ( std::make_pair(( const SMDS_MeshElement*) 0,
+ ( const SMDS_MeshElement*) 0)); // to have index == face->GetID()
+
+ if ( theSrcMesh.GetMeshInfo().NbFaces( ORDER_QUADRATIC ) > 0 )
+ throw SALOME_Exception( "Offset of quadratic mesh not supported" );
+ if ( theSrcMesh.GetMeshInfo().NbFaces() > theSrcMesh.GetMeshInfo().NbTriangles() )
+ throw SALOME_Exception( "Offset of non-triangular mesh not supported" );
+
+ // copy input faces to the newMesh keeping IDs of nodes
+
+ double minNodeDist = 1e100;
+
+ std::vector< const SMDS_MeshNode* > nodes;
+ while ( theFaceIt->more() )
+ {
+ const SMDS_MeshElement* face = theFaceIt->next();
+ if ( face->GetType() != SMDSAbs_Face ) continue;
+
+ // copy nodes
+ nodes.assign( face->begin_nodes(), face->end_nodes() );
+ for ( size_t i = 0; i < nodes.size(); ++i )
+ {
+ const SMDS_MeshNode* newNode = newMesh->FindNode( nodes[i]->GetID() );
+ if ( !newNode )
+ {
+ SMESH_NodeXYZ xyz( nodes[i] );
+ newNode = newMesh->AddNodeWithID( xyz.X(), xyz.Y(), xyz.Z(), nodes[i]->GetID() );
+ theNew2OldNodes.push_back( std::make_pair( newNode, nodes[i] ));
+ nodes[i] = newNode;
+ }
+ }
+ const SMDS_MeshElement* newFace = 0;
+ switch ( face->GetEntityType() )
+ {
+ case SMDSEntity_Triangle:
+ newFace = newMesh->AddFace( nodes[0],nodes[1],nodes[2] );
+ break;
+ case SMDSEntity_Quad_Triangle:
+ newFace = newMesh->AddFace( nodes[0],nodes[1],nodes[2],
+ nodes[3],nodes[4],nodes[5] );
+ break;
+ case SMDSEntity_BiQuad_Triangle:
+ newFace = newMesh->AddFace( nodes[0],nodes[1],nodes[2],
+ nodes[3],nodes[4],nodes[5],nodes[6] );
+ break;
+ case SMDSEntity_Quadrangle:
+ newFace = newMesh->AddFace( nodes[0],nodes[1],nodes[2],nodes[3] );
+ break;
+ case SMDSEntity_Quad_Quadrangle:
+ newFace = newMesh->AddFace( nodes[0],nodes[1],nodes[2],nodes[3],
+ nodes[4],nodes[5],nodes[6],nodes[7] );
+ break;
+ case SMDSEntity_BiQuad_Quadrangle:
+ newFace = newMesh->AddFace( nodes[0],nodes[1],nodes[2],nodes[3],nodes[4],
+ nodes[5],nodes[6],nodes[7],nodes[8] );
+ break;
+ case SMDSEntity_Polygon:
+ newFace = newMesh->AddPolygonalFace( nodes );
+ break;
+ case SMDSEntity_Quad_Polygon:
+ newFace = newMesh->AddQuadPolygonalFace( nodes );
+ break;
+ default:
+ continue;
+ }
+ theNew2OldFaces.push_back( std::make_pair( newFace, face ));
+
+ SMESH_NodeXYZ pPrev = nodes.back(), p;
+ for ( size_t i = 0; i < nodes.size(); ++i )
+ {
+ p.Set( nodes[i] );
+ double dist = ( pPrev - p ).SquareModulus();
+ if ( dist > std::numeric_limits<double>::min() )
+ minNodeDist = dist;
+ pPrev = p;
+ }
+ } // while ( faceIt->more() )
+
+
+ // compute normals to faces
+ std::vector< gp_XYZ > normals( theNew2OldFaces.size() );
+ for ( size_t i = 1; i < normals.size(); ++i )
+ {
+ if ( !SMESH_MeshAlgos::FaceNormal( theNew2OldFaces[i].second, normals[i] ))
+ normals[i].SetCoord( 0,0,0 ); // TODO find norm by neighbors
+ }
+
+ const double tol = 1e-3 * Sqrt( minNodeDist );
+ const double sign = ( theOffset < 0 ? -1 : +1 );
+
+ // translate new nodes by normal to input faces
+ gp_XYZ newXYZ;
+ std::vector< const SMDS_MeshNode* > multiNormalNodes;
+ for ( size_t i = 0; i < theNew2OldNodes.size(); ++i )
+ {
+ const SMDS_MeshNode* newNode = theNew2OldNodes[i].first;
+
+ if ( getTranslatedPosition( newNode, theOffset, tol*10., sign, normals, theSrcMesh, newXYZ ))
+ newMesh->MoveNode( newNode, newXYZ.X(), newXYZ.Y(), newXYZ.Z() );
+ else
+ multiNormalNodes.push_back( newNode );
+ }
+ // make multi-normal translation
+ std::vector< SMESH_NodeXYZ > multiPos(10);
+ for ( size_t i = 0; i < multiNormalNodes.size(); ++i )
+ {
+ const SMDS_MeshNode* newNode = multiNormalNodes[i];
+ newNode->setIsMarked( true );
+ SMESH_NodeXYZ oldXYZ = newNode;
+ multiPos.clear();
+ for ( SMDS_ElemIteratorPtr fIt = newNode->GetInverseElementIterator(); fIt->more(); )
+ {
+ const SMDS_MeshElement* newFace = fIt->next();
+ const int faceIndex = newFace->GetID();
+ const gp_XYZ& oldNorm = normals[ faceIndex ];
+ const gp_XYZ newXYZ = oldXYZ + oldNorm * theOffset;
+ if ( multiPos.empty() )
+ {
+ newMesh->MoveNode( newNode, newXYZ.X(), newXYZ.Y(), newXYZ.Z() );
+ multiPos.emplace_back( newNode );
+ }
+ else
+ {
+ newNode = 0;
+ for ( size_t iP = 0; iP < multiPos.size() && !newNode; ++iP )
+ if (( multiPos[iP] - newXYZ ).SquareModulus() < tol * tol )
+ newNode = multiPos[iP].Node();
+ if ( !newNode )
+ {
+ newNode = newMesh->AddNode( newXYZ.X(), newXYZ.Y(), newXYZ.Z() );
+ newNode->setIsMarked( true );
+ theNew2OldNodes.push_back( std::make_pair( newNode, theNew2OldNodes[i].second ));
+ multiPos.emplace_back( newNode );
+ }
+ }
+ if ( newNode != oldXYZ.Node() )
+ {
+ nodes.assign( newFace->begin_nodes(), newFace->end_nodes() );
+ nodes[ newFace->GetNodeIndex( oldXYZ.Node() )] = newNode;
+ newMesh->ChangeElementNodes( newFace, & nodes[0], nodes.size() );
+ }
+ }
+ }
+
+ if ( !theFixIntersections )
+ return newMesh;
+
+
+ // remove new faces around concave nodes (they are marked) if the faces are inverted
+ gp_XYZ faceNorm;
+ for ( size_t i = 0; i < theNew2OldNodes.size(); ++i )
+ {
+ const SMDS_MeshNode* newNode = theNew2OldNodes[i].first;
+ //const SMDS_MeshNode* oldNode = theNew2OldNodes[i].second;
+ if ( newNode->isMarked() )
+ {
+ //gp_XYZ moveVec = sign * ( SMESH_NodeXYZ( newNode ) - SMESH_NodeXYZ( oldNode ));
+
+ //bool haveInverseFace = false;
+ for ( SMDS_ElemIteratorPtr fIt = newNode->GetInverseElementIterator(); fIt->more(); )
+ {
+ const SMDS_MeshElement* newFace = fIt->next();
+ const int faceIndex = newFace->GetID();
+ const gp_XYZ& oldNorm = normals[ faceIndex ];
+ if ( !SMESH_MeshAlgos::FaceNormal( newFace, faceNorm, /*normalize=*/false ) ||
+ //faceNorm * moveVec < 0 )
+ faceNorm * oldNorm < 0 )
+ {
+ //haveInverseFace = true;
+ theNew2OldFaces[ faceIndex ].first = 0;
+ newMesh->RemoveFreeElement( newFace );
+ //break;
+ }
+ }
+ // if ( haveInverseFace )
+ // {
+ // newMesh->MoveNode( newNode, oldNode->X(), oldNode->Y(), oldNode->Z() );
+
+ // for ( SMDS_ElemIteratorPtr fIt = newNode->GetInverseElementIterator(); fIt->more(); )
+ // {
+ // const SMDS_MeshElement* newFace = fIt->next();
+ // if ( !SMESH_MeshAlgos::FaceNormal( newFace, normals[ newFace->GetID() ] ))
+ // normals[i].SetCoord( 0,0,0 ); // TODO find norm by neighbors
+ // }
+ // }
+ }
+ // mark all new nodes located closer than theOffset from theSrcMesh
+ }
+
+ // ==================================================
+ // find self-intersections of new faces and fix them
+ // ==================================================
+
+ std::unique_ptr< SMESH_ElementSearcher > fSearcher
+ ( SMESH_MeshAlgos::GetElementSearcher( *newMesh, tol ));
+
+ Intersector intersector( newMesh, tol, normals );
+
+ std::vector< const SMDS_MeshElement* > closeFaces;
+ std::vector< const SMDS_MeshNode* > faceNodes;
+ Bnd_B3d faceBox;
+ for ( size_t iF = 1; iF < theNew2OldFaces.size(); ++iF )
+ {
+ const SMDS_MeshElement* newFace = theNew2OldFaces[iF].first;
+ if ( !newFace ) continue;
+ faceNodes.assign( newFace->begin_nodes(), newFace->end_nodes() );
+
+ bool isConcaveNode1 = false;
+ for ( size_t iN = 0; iN < faceNodes.size() && !isConcaveNode1; ++iN )
+ isConcaveNode1 = faceNodes[iN]->isMarked();
+
+ // get faces close to a newFace
+ closeFaces.clear();
+ faceBox.Clear();
+ for ( size_t i = 0; i < faceNodes.size(); ++i )
+ faceBox.Add( SMESH_NodeXYZ( faceNodes[i] ));
+ faceBox.Enlarge( tol );
+
+ fSearcher->GetElementsInBox( faceBox, SMDSAbs_Face, closeFaces );
+
+ // intersect the newFace with closeFaces
+
+ for ( size_t i = 0; i < closeFaces.size(); ++i )
+ {
+ const SMDS_MeshElement* closeFace = closeFaces[i];
+ if ( closeFace->GetID() <= newFace->GetID() )
+ continue; // this pair already treated
+
+ // do not intersect connected faces if they have no concave nodes
+ int nbCommonNodes = 0;
+ for ( size_t iN = 0; iN < faceNodes.size(); ++iN )
+ nbCommonNodes += ( closeFace->GetNodeIndex( faceNodes[iN] ) >= 0 );
+
+ if ( !isConcaveNode1 )
+ {
+ bool isConcaveNode2 = false;
+ for ( SMDS_ElemIteratorPtr nIt = closeFace->nodesIterator(); nIt->more(); )
+ if (( isConcaveNode2 = nIt->next()->isMarked() ))
+ break;
+
+ if ( !isConcaveNode2 && nbCommonNodes > 0 )
+ continue;
+ }
+
+ intersector.Cut( newFace, closeFace, nbCommonNodes );
+ }
+ }
+ intersector.MakeNewFaces( theNew2OldFaces, theNew2OldNodes, sign );
+
+ return newMesh;
+}
--- /dev/null
+// Copyright (C) 2007-2016 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
+//
+// 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, or (at your option) any later version.
+//
+// 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
+//
+// File : SMESH_Triangulate.cxx
+// Created : Thu Jan 18 18:00:13 2018
+// Author : Edward AGAPOV (eap)
+
+// Extracted from ../DriverSTL/DriverSTL_W_SMDS_Mesh.cxx
+
+#include "SMESH_MeshAlgos.hxx"
+
+#include <Standard_ErrorHandler.hxx>
+#include <Standard_Failure.hxx>
+#include <gp_Ax2.hxx>
+
+using namespace SMESH_MeshAlgos;
+
+//================================================================================
+/*!
+ * \brief Initialization
+ */
+//================================================================================
+
+void Triangulate::PolyVertex::SetNodeAndNext( const SMDS_MeshNode* n,
+ PolyVertex& v )
+{
+ _nxyz.Set( n );
+ _next = &v;
+ v._prev = this;
+}
+//================================================================================
+/*!
+ * \brief Remove self from a polygon
+ */
+//================================================================================
+
+Triangulate::PolyVertex* Triangulate::PolyVertex::Delete()
+{
+ _prev->_next = _next;
+ _next->_prev = _prev;
+ return _next;
+}
+
+//================================================================================
+/*!
+ * \brief Return nodes of a triangle
+ */
+//================================================================================
+
+void Triangulate::PolyVertex::GetTriaNodes( const SMDS_MeshNode** nodes) const
+{
+ nodes[0] = _prev->_nxyz._node;
+ nodes[1] = this->_nxyz._node;
+ nodes[2] = _next->_nxyz._node;
+}
+
+//================================================================================
+/*!
+ * \brief Compute triangle area
+ */
+//================================================================================
+
+inline static double Area( const gp_XY& xy0, const gp_XY& xy1, const gp_XY& xy2 )
+{
+ gp_XY vPrev = xy0 - xy1;
+ gp_XY vNext = xy2 - xy1;
+ return vNext ^ vPrev;
+}
+
+//================================================================================
+/*!
+ * \brief Compute triangle area
+ */
+//================================================================================
+
+double Triangulate::PolyVertex::TriaArea() const
+{
+ return Area( _prev->_xy, this->_xy, _next->_xy );
+}
+
+//================================================================================
+/*!
+ * \brief Check if a vertex is inside a triangle
+ */
+//================================================================================
+
+bool Triangulate::PolyVertex::IsInsideTria( const PolyVertex* v )
+{
+ if ( this ->_nxyz == v->_nxyz ||
+ _prev->_nxyz == v->_nxyz ||
+ _next->_nxyz == v->_nxyz )
+ return false;
+
+ gp_XY p = _prev->_xy - v->_xy;
+ gp_XY t = this->_xy - v->_xy;
+ gp_XY n = _next->_xy - v->_xy;
+ const double tol = -1e-12;
+ return (( p ^ t ) >= tol &&
+ ( t ^ n ) >= tol &&
+ ( n ^ p ) >= tol );
+ // return ( Area( _prev, this, v ) > 0 &&
+ // Area( this, _next, v ) > 0 &&
+ // Area( _next, _prev, v ) > 0 );
+}
+
+//================================================================================
+/*!
+ * \brief Triangulate a polygon. Assure correct orientation for concave polygons
+ */
+//================================================================================
+
+bool Triangulate::triangulate( std::vector< const SMDS_MeshNode*>& nodes,
+ const size_t nbNodes )
+{
+ // connect nodes into a ring
+ _pv.resize( nbNodes );
+ for ( size_t i = 1; i < nbNodes; ++i )
+ _pv[i-1].SetNodeAndNext( nodes[i-1], _pv[i] );
+ _pv[ nbNodes-1 ].SetNodeAndNext( nodes[ nbNodes-1 ], _pv[0] );
+
+ // get a polygon normal
+ gp_XYZ normal(0,0,0), p0,v01,v02;
+ p0 = _pv[0]._nxyz;
+ v01 = _pv[1]._nxyz - p0;
+ for ( size_t i = 2; i < nbNodes; ++i )
+ {
+ v02 = _pv[i]._nxyz - p0;
+ normal += v01 ^ v02;
+ v01 = v02;
+ }
+ // project nodes to the found plane
+ gp_Ax2 axes;
+ try {
+ axes = gp_Ax2( p0, normal, v01 );
+ }
+ catch ( Standard_Failure ) {
+ return false;
+ }
+ for ( size_t i = 0; i < nbNodes; ++i )
+ {
+ gp_XYZ p = _pv[i]._nxyz - p0;
+ _pv[i]._xy.SetX( axes.XDirection().XYZ() * p );
+ _pv[i]._xy.SetY( axes.YDirection().XYZ() * p );
+ }
+
+ // in a loop, find triangles with positive area and having no vertices inside
+ int iN = 0, nbTria = nbNodes - 2;
+ nodes.reserve( nbTria * 3 );
+ const double minArea = 1e-6;
+ PolyVertex* v = &_pv[0], *vi;
+ int nbVertices = nbNodes, nbBadTria = 0, isGoodTria;
+ while ( nbBadTria < nbVertices )
+ {
+ if (( isGoodTria = v->TriaArea() > minArea ))
+ {
+ for ( vi = v->_next->_next;
+ vi != v->_prev;
+ vi = vi->_next )
+ {
+ if ( v->IsInsideTria( vi ))
+ break;
+ }
+ isGoodTria = ( vi == v->_prev );
+ }
+ if ( isGoodTria )
+ {
+ v->GetTriaNodes( &nodes[ iN ] );
+ iN += 3;
+ v = v->Delete();
+ if ( --nbVertices == 3 )
+ {
+ // last triangle remains
+ v->GetTriaNodes( &nodes[ iN ] );
+ return true;
+ }
+ nbBadTria = 0;
+ }
+ else
+ {
+ v = v->_next;
+ ++nbBadTria;
+ }
+ }
+
+ // the polygon is invalid; add triangles with positive area
+ nbBadTria = 0;
+ while ( nbBadTria < nbVertices )
+ {
+ isGoodTria = v->TriaArea() > minArea;
+ if ( isGoodTria )
+ {
+ v->GetTriaNodes( &nodes[ iN ] );
+ iN += 3;
+ v = v->Delete();
+ if ( --nbVertices == 3 )
+ {
+ // last triangle remains
+ v->GetTriaNodes( &nodes[ iN ] );
+ return true;
+ }
+ nbBadTria = 0;
+ }
+ else
+ {
+ v = v->_next;
+ ++nbBadTria;
+ }
+ }
+
+ // add all the rest triangles
+ while ( nbVertices >= 3 )
+ {
+ v->GetTriaNodes( &nodes[ iN ] );
+ iN += 3;
+ v = v->Delete();
+ --nbVertices;
+ }
+
+ return true;
+
+} // triangulate()
+
+//================================================================================
+/*!
+ * \brief Return nb triangles in a decomposed mesh face
+ * \retval int - number of triangles
+ */
+//================================================================================
+
+int Triangulate::GetNbTriangles( const SMDS_MeshElement* face )
+{
+ // WARNING: counting triangles must be coherent with GetTriangles()
+ switch ( face->GetEntityType() )
+ {
+ case SMDSEntity_BiQuad_Triangle:
+ case SMDSEntity_BiQuad_Quadrangle:
+ return face->NbNodes() - 1;
+ // case SMDSEntity_Triangle:
+ // case SMDSEntity_Quad_Triangle:
+ // case SMDSEntity_Quadrangle:
+ // case SMDSEntity_Quad_Quadrangle:
+ // case SMDSEntity_Polygon:
+ // case SMDSEntity_Quad_Polygon:
+ default:
+ return face->NbNodes() - 2;
+ }
+ return 0;
+}
+
+//================================================================================
+/*!
+ * \brief Decompose a mesh face into triangles
+ * \retval int - number of triangles
+ */
+//================================================================================
+
+int Triangulate::GetTriangles( const SMDS_MeshElement* face,
+ std::vector< const SMDS_MeshNode*>& nodes)
+{
+ if ( face->GetType() != SMDSAbs_Face )
+ return 0;
+
+ // WARNING: decomposing into triangles must be coherent with getNbTriangles()
+ int nbTria, i = 0, nbNodes = face->NbNodes();
+ SMDS_NodeIteratorPtr nIt = face->interlacedNodesIterator();
+ nodes.resize( nbNodes * 3 );
+ nodes[ i++ ] = nIt->next();
+ nodes[ i++ ] = nIt->next();
+
+ const SMDSAbs_EntityType type = face->GetEntityType();
+ switch ( type )
+ {
+ case SMDSEntity_BiQuad_Triangle:
+ case SMDSEntity_BiQuad_Quadrangle:
+
+ nbTria = ( type == SMDSEntity_BiQuad_Triangle ) ? 6 : 8;
+ nodes[ i++ ] = face->GetNode( nbTria );
+ for ( i = 3; i < 3*(nbTria-1); i += 3 )
+ {
+ nodes[ i+0 ] = nodes[ i-2 ];
+ nodes[ i+1 ] = nIt->next();
+ nodes[ i+2 ] = nodes[ 2 ];
+ }
+ nodes[ i+0 ] = nodes[ i-2 ];
+ nodes[ i+1 ] = nodes[ 0 ];
+ nodes[ i+2 ] = nodes[ 2 ];
+ break;
+
+ case SMDSEntity_Triangle:
+
+ nbTria = 1;
+ nodes[ i++ ] = nIt->next();
+ break;
+
+ default:
+
+ // case SMDSEntity_Quad_Triangle:
+ // case SMDSEntity_Quadrangle:
+ // case SMDSEntity_Quad_Quadrangle:
+ // case SMDSEntity_Polygon:
+ // case SMDSEntity_Quad_Polygon:
+
+ nbTria = nbNodes - 2;
+ while ( nIt->more() )
+ nodes[ i++ ] = nIt->next();
+
+ if ( nbTria > 1 && !triangulate( nodes, nbNodes ))
+ {
+ nIt = face->interlacedNodesIterator();
+ nodes[ 0 ] = nIt->next();
+ nodes[ 1 ] = nIt->next();
+ nodes[ 2 ] = nIt->next();
+ for ( i = 3; i < 3*nbTria; i += 3 )
+ {
+ nodes[ i+0 ] = nodes[ 0 ];
+ nodes[ i+1 ] = nodes[ i-1 ];
+ nodes[ i+2 ] = nIt->next();
+ }
+ }
+ }
+
+ return nbTria;
+}
#include "SMESH_Utils.hxx"
+#include "SMDS_SetIterator.hxx"
#include "SMDS_MeshNode.hxx"
#include <gp_XYZ.hxx>
#include <set>
#include <cassert>
+#include <boost/make_shared.hpp>
+
typedef std::map<const SMDS_MeshElement*,
std::list<const SMDS_MeshElement*>, TIDCompare > TElemOfElemListMap;
typedef std::map<const SMDS_MeshElement*,
private:
ArrayDeleter( const ArrayDeleter& );
};
+
+ template < class ELEM_SET >
+ SMDS_ElemIteratorPtr elemSetIterator( const ELEM_SET& elements )
+ {
+ typedef SMDS_SetIterator
+ < SMDS_pElement, typename ELEM_SET::const_iterator> TSetIterator;
+ return boost::make_shared< TSetIterator >( elements.begin(), elements.end() );
+ }
}
//=======================================================================
return ( l1.node1() == l2.node1() && l1.node2() == l2.node2() );
}
};
+typedef SMESH_TLink SMESH_Link;
//=======================================================================
/*!
}
return false;
}
+ const SMDS_MeshNode* Node() const { return _node; }
double Distance(const SMDS_MeshNode* n) const { return (SMESH_TNodeXYZ( n )-*this).Modulus(); }
double SquareDistance(const SMDS_MeshNode* n) const { return (SMESH_TNodeXYZ( n )-*this).SquareModulus(); }
bool operator==(const SMESH_TNodeXYZ& other) const { return _node == other._node; }
+ bool operator!=(const SMESH_TNodeXYZ& other) const { return _node != other._node; }
+ bool operator!() const { return !_node; }
+ const SMDS_MeshNode* operator->() const { return _node; }
};
typedef SMESH_TNodeXYZ SMESH_NodeXYZ;
// --------------------------------------------------------------------------------
// class SMESH_SequenceOfElemPtr
-#include <NCollection_DefineSequence.hxx>
-
-class SMDS_MeshElement;
-
-typedef const SMDS_MeshElement* SMDS_MeshElementPtr;
-
-DEFINE_SEQUENCE (SMESH_SequenceOfElemPtr, SMESH_BaseCollectionElemPtr, SMDS_MeshElementPtr)
+typedef std::vector< const SMDS_MeshElement* > SMESH_SequenceOfElemPtr;
// --------------------------------------------------------------------------------
// class SMESH_SequenceOfNode
+#include <NCollection_DefineSequence.hxx>
typedef const SMDS_MeshNode* SMDS_MeshNodePtr;
DEFINE_SEQUENCE(SMESH_SequenceOfNode,
myLastObj.clear();
myLastParameters.clear();
myLastParamIndex.clear(); /* vector holding indices of virables within the string
- of all varibles used for theObject */
+ of all variables used for theObject */
int nbVars = 0;
int pos = 0, prevPos = 0, len = strlen( theParameters );
if ( len == 0 ) return;
return;
// store
- // (1) variable names in the string of all varibles used for theObject and
+ // (1) variable names in the string of all variables used for theObject and
// (2) indices of found variables in myLastParamIndex.
// remember theObject
}
void Remove( SMDSAbs_ElementType type )
{
- SMDS_ElemIteratorPtr eIt = GetMeshDS()->elementsIterator( type );
+ Remove( GetMeshDS()->elementsIterator( type ));
+ }
+ void Remove( SMDS_ElemIteratorPtr eIt )
+ {
while ( eIt->more() )
GetMeshDS()->RemoveFreeElement( eIt->next(), /*sm=*/0, /*fromGroups=*/false );
}
SMESH_TRY;
const bool hasBadElems = ( getEditor().GetError() && getEditor().GetError()->HasBadElems() );
- if ( myIsPreviewMode || hasBadElems ) { // --- MeshPreviewStruct filling ---
-
+ if ( myIsPreviewMode || hasBadElems )
+ {
list<int> aNodesConnectivity;
typedef map<int, int> TNodesMap;
TNodesMap nodesMap;
SMESHDS_Mesh* aMeshDS;
- std::auto_ptr< SMESH_MeshPartDS > aMeshPartDS;
+ std::unique_ptr< SMESH_MeshPartDS > aMeshPartDS;
if ( hasBadElems ) {
aMeshPartDS.reset( new SMESH_MeshPartDS( getEditor().GetError()->myBadElements ));
aMeshDS = aMeshPartDS.get();
SMESH::long_array_var myLastCreatedNodes = new SMESH::long_array();
const SMESH_SequenceOfElemPtr& aSeq = getEditor().GetLastCreatedNodes();
- myLastCreatedNodes->length( aSeq.Length() );
- for (int i = 1; i <= aSeq.Length(); i++)
- myLastCreatedNodes[i-1] = aSeq.Value(i)->GetID();
+ myLastCreatedNodes->length( aSeq.size() );
+ for ( size_t i = 0; i < aSeq.size(); i++)
+ myLastCreatedNodes[i] = aSeq[i]->GetID();
return myLastCreatedNodes._retn();
SMESH_CATCH( SMESH::throwCorbaException );
SMESH::long_array_var myLastCreatedElems = new SMESH::long_array();
const SMESH_SequenceOfElemPtr& aSeq = getEditor().GetLastCreatedElems();
- myLastCreatedElems->length( aSeq.Length() );
- for ( int i = 1; i <= aSeq.Length(); i++ )
- myLastCreatedElems[i-1] = aSeq.Value(i)->GetID();
+ myLastCreatedElems->length( aSeq.size() );
+ for ( size_t i = 0; i < aSeq.size(); i++ )
+ myLastCreatedElems[i] = aSeq[i]->GetID();
return myLastCreatedElems._retn();
SMESH_CATCH( SMESH::throwCorbaException );
return mesh._retn();
}
+//================================================================================
+/*!
+ * \brief Make an offset mesh from a source 2D mesh
+ * \param [inout] theObject - source mesh. New elements are added to this mesh
+ * if \a theMeshName is empty.
+ * \param [in] theValue - offset value
+ * \param [in] theCopyGroups - to generate groups
+ * \param [in] theMeshName - optional name of a new mesh
+ * \param [out] theGroups - new groups
+ * \return SMESH::SMESH_Mesh_ptr - the modified mesh
+ */
+//================================================================================
+
+SMESH::SMESH_Mesh_ptr SMESH_MeshEditor_i::Offset( SMESH::SMESH_IDSource_ptr theObject,
+ CORBA::Double theValue,
+ CORBA::Boolean theCopyGroups,
+ const char* theMeshName,
+ SMESH::ListOfGroups_out theGroups)
+ throw (SALOME::SALOME_Exception)
+{
+ SMESH_TRY;
+ initData();
+
+ SMESHDS_Mesh* aMeshDS = getMeshDS();
+
+ SMESH::SMESH_Mesh_var mesh_var;
+ ::SMESH_MeshEditor::PGroupIDs groupIds;
+
+ TPythonDump pyDump;
+
+ TIDSortedElemSet elements, copyElements;
+ if ( idSourceToSet( theObject, aMeshDS, elements, SMDSAbs_Face,
+ /*emptyIfIsMesh=*/ !myIsPreviewMode ))
+ {
+ // mesh to modify
+ SMESH_Mesh* tgtMesh = 0;
+ if ( myIsPreviewMode )
+ {
+ TPreviewMesh * tmpMesh = getPreviewMesh();
+ tgtMesh = tmpMesh;
+ tmpMesh->Copy( elements, copyElements );
+ theCopyGroups = false;
+ }
+ else
+ {
+ mesh_var =
+ *theMeshName ? makeMesh( theMeshName ) : SMESH::SMESH_Mesh::_duplicate( myMesh_i->_this() );
+ SMESH_Mesh_i* mesh_i = SMESH::DownCast<SMESH_Mesh_i*>( mesh_var );
+ tgtMesh = & mesh_i->GetImpl();
+ }
+ groupIds = getEditor().Offset( elements, theValue, tgtMesh, theCopyGroups, !myIsPreviewMode );
+
+ tgtMesh->GetMeshDS()->Modified();
+ }
+
+ if ( myIsPreviewMode )
+ {
+ getPreviewMesh()->Remove( SMESHUtils::elemSetIterator( copyElements ));
+ }
+ else
+ {
+ theGroups = theCopyGroups ? getGroups( groupIds.get() ) : new SMESH::ListOfGroups;
+
+ // result of Offset() is a tuple (mesh, groups)
+ if ( mesh_var->_is_nil() ) pyDump << myMesh_i->_this() << ", ";
+ else pyDump << mesh_var << ", ";
+ pyDump << theGroups << " = "
+ << this << ".Offset( "
+ << theValue << ", "
+ << theCopyGroups << ", "
+ << "'" << theMeshName<< "')";
+ }
+
+ return mesh_var._retn();
+
+ SMESH_CATCH( SMESH::throwCorbaException );
+ return SMESH::SMESH_Mesh::_nil();
+}
//=======================================================================
//function : findCoincidentNodes
getEditor().ClearLastCreated();
SMESH_SequenceOfElemPtr& aSeq =
const_cast<SMESH_SequenceOfElemPtr&>( getEditor().GetLastCreatedElems() );
- for ( size_t i = 0; i < newFaces.size(); ++i )
- aSeq.Append( newFaces[i] );
+ aSeq.swap( newFaces );
TPythonDump() << this << ".FillHole( SMESH.FreeBorder(" << theHole.nodeIDs << " ))";
}
* \param theElements - container of elements to duplicate.
* \param theGroupName - a name of group to contain the generated elements.
* If a group with such a name already exists, the new elements
- * are added to the existng group, else a new group is created.
+ * are added to the existing group, else a new group is created.
* If \a theGroupName is empty, new elements are not added
* in any group.
* \return a group where the new elements are added. NULL if theGroupName == "".
{
getEditor().DoubleElements( elems );
- if ( strlen( theGroupName ) && !getEditor().GetLastCreatedElems().IsEmpty() )
+ if ( strlen( theGroupName ) && !getEditor().GetLastCreatedElems().empty() )
{
// group type
SMESH::ElementType type =
- SMESH::ElementType( getEditor().GetLastCreatedElems().Value(1)->GetType() );
+ SMESH::ElementType( getEditor().GetLastCreatedElems()[0]->GetType() );
// find existing group
SMESH::ListOfGroups_var groups = myMesh_i->GetGroups();
for ( size_t i = 0; i < groups->length(); ++i )
{
SMESHDS_Group* groupDS = static_cast< SMESHDS_Group* >( group_i->GetGroupDS() );
const SMESH_SequenceOfElemPtr& aSeq = getEditor().GetLastCreatedElems();
- for ( int i = 1; i <= aSeq.Length(); i++ )
- groupDS->SMDSGroup().Add( aSeq(i) );
+ for ( size_t i = 0; i <= aSeq.size(); i++ )
+ groupDS->SMDSGroup().Add( aSeq[i] );
}
}
}
// Create group with newly created elements
CORBA::String_var elemGroupName = theElems->GetName();
std::string aNewName = generateGroupName( std::string(elemGroupName.in()) + "_double");
- if ( !getEditor().GetLastCreatedElems().IsEmpty() && theElemGroupNeeded )
+ if ( !getEditor().GetLastCreatedElems().empty() && theElemGroupNeeded )
{
SMESH::long_array_var anIds = GetLastCreatedElems();
SMESH::ElementType aGroupType = myMesh_i->GetElementType(anIds[0], true);
aNewElemGroup = myMesh_i->CreateGroup(aGroupType, aNewName.c_str());
aNewElemGroup->Add(anIds);
}
- if ( !getEditor().GetLastCreatedNodes().IsEmpty() && theNodeGroupNeeded )
+ if ( !getEditor().GetLastCreatedNodes().empty() && theNodeGroupNeeded )
{
SMESH::long_array_var anIds = GetLastCreatedNodes();
aNewNodeGroup = myMesh_i->CreateGroup(SMESH::NODE, aNewName.c_str());
// Create group with newly created elements
CORBA::String_var elemGroupName = theElems[0]->GetName();
std::string aNewName = generateGroupName( std::string(elemGroupName.in()) + "_double");
- if ( !getEditor().GetLastCreatedElems().IsEmpty() && theElemGroupNeeded )
+ if ( !getEditor().GetLastCreatedElems().empty() && theElemGroupNeeded )
{
SMESH::long_array_var anIds = GetLastCreatedElems();
SMESH::ElementType aGroupType = myMesh_i->GetElementType(anIds[0], true);
aNewElemGroup = myMesh_i->CreateGroup(aGroupType, aNewName.c_str());
aNewElemGroup->Add(anIds);
}
- if ( !getEditor().GetLastCreatedNodes().IsEmpty() && theNodeGroupNeeded )
+ if ( !getEditor().GetLastCreatedNodes().empty() && theNodeGroupNeeded )
{
SMESH::long_array_var anIds = GetLastCreatedNodes();
aNewNodeGroup = myMesh_i->CreateGroup(SMESH::NODE, aNewName.c_str());
const SMESH::double_array& theScaleFact)
throw (SALOME::SALOME_Exception);
- SMESH::SMESH_Mesh_ptr ScaleMakeMesh(SMESH::SMESH_IDSource_ptr Object,
- const SMESH::PointStruct& Point,
+ SMESH::SMESH_Mesh_ptr ScaleMakeMesh(SMESH::SMESH_IDSource_ptr Object,
+ const SMESH::PointStruct& Point,
const SMESH::double_array& theScaleFact,
- CORBA::Boolean CopyGroups,
- const char* MeshName)
+ CORBA::Boolean CopyGroups,
+ const char* MeshName)
+ throw (SALOME::SALOME_Exception);
+
+ SMESH::SMESH_Mesh_ptr Offset( SMESH::SMESH_IDSource_ptr theObject,
+ CORBA::Double Value,
+ CORBA::Boolean CopyGroups,
+ const char* MeshName,
+ SMESH::ListOfGroups_out Groups)
throw (SALOME::SALOME_Exception);
void FindCoincidentNodes (CORBA::Double Tolerance,
// temporary IDSources
struct _IDSource;
- // std::list< _IDSource* > myAuxIDSources;
- // void deleteAuxIDSources();
};
#endif
// ===========================================================================================
/*!
- * \brief Object used to make TPythonDump know that its held value can be a varible
+ * \brief Object used to make TPythonDump know that its held value can be a variable
*
* TPythonDump substitute TVar with names of notebook variables if any.
*/
self.mesh.SetParameters(Parameters)
return Mesh( self.smeshpyD, self.geompyD, mesh )
+ ## Create an offset mesh from the given 2D object
+ # @param theObject the source object (mesh, submesh, group or filter)
+ # @param theValue signed offset size
+ # @param MakeGroups forces the generation of new groups from existing ones
+ # @param NewMeshName the name of a mesh to create. If empty, offset elements are added
+ # to this mesh
+ # @return a tuple (mesh, list_of_groups)
+ # @ingroup l2_modif_trsf
+ def Offset(self, theObject, theValue, MakeGroups=False, NewMeshName=''):
+ if isinstance( theObject, Mesh ):
+ theObject = theObject.GetMesh()
+ theValue,Parameters,hasVars = ParseParameters(theValue)
+ mesh_groups = self.editor.Offset(theObject, theValue, MakeGroups, NewMeshName )
+ self.mesh.SetParameters(Parameters)
+ # if mesh_groups[0]:
+ # return Mesh( self.smeshpyD, self.geompyD, mesh_groups[0] ), mesh_groups[1]
+ return mesh_groups
+
## Finds groups of adjacent nodes within Tolerance.
# @param Tolerance the value of tolerance
# @param SeparateCornerAndMediumNodes if @c True, in quadratic mesh puts
# a Mesh, elements of highest dimension are duplicated
# @param theGroupName - a name of group to contain the generated elements.
# If a group with such a name already exists, the new elements
- # are added to the existng group, else a new group is created.
+ # are added to the existing group, else a new group is created.
# If \a theGroupName is empty, new elements are not added
# in any group.
# @return a group where the new elements are added. None if theGroupName == "".
{
enum { X = 1, Y = 2, Z = 4 }; // == 001, 010, 100
int nbFacets = 0;
- int vertex = 0, egdeMask = 0;
+ int vertex = 0, edgeMask = 0;
if ( Abs( _grid->_coords[0][ _i ] - ip->_uvw[0] ) < _grid->_tol ) {
facets[ nbFacets++ ] = SMESH_Block::ID_F0yz;
- egdeMask |= X;
+ edgeMask |= X;
}
else if ( Abs( _grid->_coords[0][ _i+1 ] - ip->_uvw[0] ) < _grid->_tol ) {
facets[ nbFacets++ ] = SMESH_Block::ID_F1yz;
vertex |= X;
- egdeMask |= X;
+ edgeMask |= X;
}
if ( Abs( _grid->_coords[1][ _j ] - ip->_uvw[1] ) < _grid->_tol ) {
facets[ nbFacets++ ] = SMESH_Block::ID_Fx0z;
- egdeMask |= Y;
+ edgeMask |= Y;
}
else if ( Abs( _grid->_coords[1][ _j+1 ] - ip->_uvw[1] ) < _grid->_tol ) {
facets[ nbFacets++ ] = SMESH_Block::ID_Fx1z;
vertex |= Y;
- egdeMask |= Y;
+ edgeMask |= Y;
}
if ( Abs( _grid->_coords[2][ _k ] - ip->_uvw[2] ) < _grid->_tol ) {
facets[ nbFacets++ ] = SMESH_Block::ID_Fxy0;
- egdeMask |= Z;
+ edgeMask |= Z;
}
else if ( Abs( _grid->_coords[2][ _k+1 ] - ip->_uvw[2] ) < _grid->_tol ) {
facets[ nbFacets++ ] = SMESH_Block::ID_Fxy1;
vertex |= Z;
- egdeMask |= Z;
+ edgeMask |= Z;
}
switch ( nbFacets )
{ SMESH_Block::ID_Ex00, 0, SMESH_Block::ID_Ex10, 0,
SMESH_Block::ID_Ex01, 0, SMESH_Block::ID_Ex11 }
};
- switch ( egdeMask ) {
+ switch ( edgeMask ) {
case X | Y: sub = edge[ 0 ][ vertex ]; break;
case X | Z: sub = edge[ 1 ][ vertex ]; break;
default: sub = edge[ 2 ][ vertex ];
// aPreviewActor holds a map od all sub-shapes of mainShape
SMESH_PreviewActorsCollection* previewActor = mySubSelectWdg->GetActorCollection();
if ( !previewActor ) return false;
- const QList<int>& egdeIDs = previewActor->GetIndices();
+ const QList<int>& edgeIDs = previewActor->GetIndices();
// Make a 'map' of WIREs of EDGE with quadrilateral WIREs only
TColStd_MapOfInteger shapeEdges;
if ( !shape.IsSame( mainShape ))
- for ( QList<TGeomID>::const_iterator ieIt = egdeIDs.begin(); ieIt != egdeIDs.end(); ++ieIt )
+ for ( QList<TGeomID>::const_iterator ieIt = edgeIDs.begin(); ieIt != edgeIDs.end(); ++ieIt )
shapeEdges.Add( *ieIt );
// loop on all EDGEs in mainShape
- for ( QList<TGeomID>::const_iterator ieIt = egdeIDs.begin(); ieIt != egdeIDs.end(); ++ieIt )
+ for ( QList<TGeomID>::const_iterator ieIt = edgeIDs.begin(); ieIt != edgeIDs.end(); ++ieIt )
{
if ( chainedEdges.Contains( *ieIt ))
continue;
if ( ch.size() < 2 )
myChains.pop_back();
}
- } // loop on egdeIDs
+ } // loop on edgeIDs
return !myChains.empty();
}
TempNames = []
for MacroObj in Config.ListObj :
if group in MacroObj.GroupNames :
- Occurences = IndexMultiOcc(MacroObj.GroupNames, group)
- for Occ in Occurences :
+ Occurrences = IndexMultiOcc(MacroObj.GroupNames, group)
+ for Occ in Occurrences :
TempGEOList += MacroObj.GetBorder(Occ)
GroupGEO.append(geompy.MakeCompound(TempGEOList))
geompy.addToStudyInFather(FinalCompound,GroupGEO[-1],'GR_'+group)
Optimisation
------------
-This is the main remeshing Option. SurfOpt always does quality improvement. It is done by point smooting and edge swapping. It can produce a regular mesh for finite element computation (initial mesh is a a geometrical mesh). In this case, the given surface trianglation is modified in accordance to a size map : an intrinsic size map is computed automatically. it is based on the surface proporties. SurfOpt is also able to produce a geometrical mesh (initial mesh is a a mesh for finite element computation). In both case, It can coarsen or enrich the mesh.
+This is the main remeshing Option. SurfOpt always does quality improvement. It is done by point smoothing and edge swapping. It can produce a regular mesh for finite element computation (initial mesh is a a geometrical mesh). In this case, the given surface trianglation is modified in accordance to a size map : an intrinsic size map is computed automatically. it is based on the surface proporties. SurfOpt is also able to produce a geometrical mesh (initial mesh is a mesh for finite element computation). In both case, It can coarsen or enrich the mesh.
- **Quality improvement**
def setupJobManager(self):
'''
- This function configures the jobmanager by transmiting the
+ This function configures the jobmanager by transmitting the
parameters required for a local execution and a remote
execution. The choice between "local" and "remote" is done at
- the initialize step, by specifing the name of the resource to
+ the initialize step, by specifying the name of the resource to
be used.
'''
# We first