X-Git-Url: http://git.salome-platform.org/gitweb/?p=modules%2Fsmesh.git;a=blobdiff_plain;f=src%2FDriverSTL%2FDriverSTL_W_SMDS_Mesh.cxx;h=d0239cfe14a2906b2aa3bece58d65b037fd7375d;hp=cd33b025338f4f5f47d92dbee97d3fa09b0f3d3f;hb=HEAD;hpb=741a54331a691355c38e17548fbc14475cfe9b6b diff --git a/src/DriverSTL/DriverSTL_W_SMDS_Mesh.cxx b/src/DriverSTL/DriverSTL_W_SMDS_Mesh.cxx index cd33b0253..1dee48d8b 100644 --- a/src/DriverSTL/DriverSTL_W_SMDS_Mesh.cxx +++ b/src/DriverSTL/DriverSTL_W_SMDS_Mesh.cxx @@ -1,4 +1,4 @@ -// Copyright (C) 2007-2015 CEA/DEN, EDF R&D, OPEN CASCADE +// Copyright (C) 2007-2024 CEA, EDF, OPEN CASCADE // // Copyright (C) 2003-2007 OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN, // CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS @@ -31,18 +31,13 @@ #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 -#include -#include - #include @@ -176,7 +171,7 @@ static void writeFloat( const Standard_ShortReal& theVal, SMESH_File& ofile) { union { Standard_ShortReal f; - char c[4]; + char c[4]; } u; u.f = theVal; @@ -208,234 +203,6 @@ static gp_XYZ getNormale( const SMDS_MeshNode* n1, 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; - return (( p ^ t ) > 0 && - ( t ^ n ) > 0 && - ( n ^ p ) > 0 ); - // 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; - } - } - return false; - - } // 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 ); - while ( i < 3*(nbTria-1) ) - { - nodes[ i++ ] = nodes[ i-2 ]; - nodes[ i++ ] = nIt->next(); - nodes[ i++ ] = nodes[ 2 ]; - } - nodes[ i++ ] = nodes[ i-2 ]; - nodes[ i++ ] = nodes[ 0 ]; - nodes[ i++ ] = 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 @@ -449,17 +216,20 @@ Driver_Mesh::Status DriverSTL_W_SMDS_Mesh::writeAscii() const SMESH_File aFile( myFile, /*openForReading=*/false ); aFile.openForWriting(); - std::string buf("solid\n"); + std::string buf("solid "); + buf += myName + "\n"; aFile.writeRaw( buf.c_str(), buf.size() ); 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 ) { @@ -484,7 +254,8 @@ Driver_Mesh::Status DriverSTL_W_SMDS_Mesh::writeAscii() const " endfacet\n", 21 ); } } - aFile.writeRaw ("endsolid\n" , 9 ); + buf = "endsolid " + myName + "\n"; + aFile.writeRaw( buf.c_str(), buf.size() ); return aResult; } @@ -508,16 +279,23 @@ Driver_Mesh::Status DriverSTL_W_SMDS_Mesh::writeBinary() const 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, ' ' ); + if ( !myName.empty() ) + { + sval = "name: " + myName; + sval.resize( LABEL_SIZE, ' ' ); + } aFile.write( sval.c_str(), LABEL_SIZE ); // write number of triangles @@ -533,7 +311,7 @@ Driver_Mesh::Status DriverSTL_W_SMDS_Mesh::writeBinary() const 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 ) {