X-Git-Url: http://git.salome-platform.org/gitweb/?p=modules%2Fsmesh.git;a=blobdiff_plain;f=src%2FStdMeshers%2FStdMeshers_Cartesian_3D.cxx;h=eb23a493a1f8da1ddcfe981a2a0658f13f0b79c1;hp=b8c4a92ff98a1233763cf18499be6c8e925e9851;hb=b56d0083b994de9f7e50b3dc7c76aea9b3bc18a5;hpb=cd3ffac3fabc68b4d1dee2ad199302f04b20d2c8 diff --git a/src/StdMeshers/StdMeshers_Cartesian_3D.cxx b/src/StdMeshers/StdMeshers_Cartesian_3D.cxx index b8c4a92ff..eb23a493a 100644 --- a/src/StdMeshers/StdMeshers_Cartesian_3D.cxx +++ b/src/StdMeshers/StdMeshers_Cartesian_3D.cxx @@ -1,4 +1,4 @@ -// Copyright (C) 2007-2013 CEA/DEN, EDF R&D, OPEN CASCADE +// Copyright (C) 2007-2014 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 @@ -6,7 +6,7 @@ // 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. +// 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 @@ -54,6 +54,8 @@ #include #include #include +#include +#include #include #include #include @@ -83,6 +85,8 @@ #include #include +#include + #undef WITH_TBB #ifdef WITH_TBB #include @@ -179,7 +183,7 @@ namespace B_IntersectPoint(): _node(NULL) {} void Add( const vector< TGeomID >& fIDs, const SMDS_MeshNode* n=0 ) const; - bool HasCommonFace( const B_IntersectPoint * other ) const; + int HasCommonFace( const B_IntersectPoint * other, int avoidFace=-1 ) const; bool IsOnFace( int faceID ) const; virtual ~B_IntersectPoint() {} }; @@ -277,7 +281,7 @@ namespace { vector< double > _coords[3]; // coordinates of grid nodes gp_XYZ _axes [3]; // axis directions - vector< GridLine > _lines [3]; // in 3 directions + vector< GridLine > _lines [3]; // in 3 directions double _tol, _minCellSize; gp_XYZ _origin; gp_Mat _invB; // inverted basis of _axes @@ -289,6 +293,8 @@ namespace list< E_IntersectPoint > _edgeIntP; // intersections with EDGEs TopTools_IndexedMapOfShape _shapes; + SMESH_MesherHelper* _helper; + size_t CellIndex( size_t i, size_t j, size_t k ) const { return i + j*(_coords[0].size()-1) + k*(_coords[0].size()-1)*(_coords[1].size()-1); @@ -440,16 +446,22 @@ namespace // -------------------------------------------------------------------------------- struct _Node //!< node either at a hexahedron corner or at intersection { - const SMDS_MeshNode* _node; // mesh node at hexahedron corner + const SMDS_MeshNode* _node; // mesh node at hexahedron corner const B_IntersectPoint* _intPoint; + const _Face* _usedInFace; - _Node(const SMDS_MeshNode* n=0, const B_IntersectPoint* ip=0):_node(n), _intPoint(ip) {} + _Node(const SMDS_MeshNode* n=0, const B_IntersectPoint* ip=0) + :_node(n), _intPoint(ip), _usedInFace(0) {} const SMDS_MeshNode* Node() const { return ( _intPoint && _intPoint->_node ) ? _intPoint->_node : _node; } - const F_IntersectPoint* FaceIntPnt() const - { return static_cast< const F_IntersectPoint* >( _intPoint ); } + //const F_IntersectPoint* FaceIntPnt() const + //{ return static_cast< const F_IntersectPoint* >( _intPoint ); } const E_IntersectPoint* EdgeIntPnt() const { return static_cast< const E_IntersectPoint* >( _intPoint ); } + bool IsUsedInFace( const _Face* polygon = 0 ) + { + return polygon ? ( _usedInFace == polygon ) : bool( _usedInFace ); + } void Add( const E_IntersectPoint* ip ) { if ( !_intPoint ) { @@ -463,9 +475,10 @@ namespace _intPoint->Add( ip->_faceIDs ); } } - bool IsLinked( const B_IntersectPoint* other ) const + int IsLinked( const B_IntersectPoint* other, + int avoidFace=-1 ) const // returns id of a common face { - return _intPoint && _intPoint->HasCommonFace( other ); + return _intPoint ? _intPoint->HasCommonFace( other, avoidFace ) : 0; } bool IsOnFace( int faceID ) const // returns true if faceID is found { @@ -485,9 +498,11 @@ namespace struct _Link // link connecting two _Node's { _Node* _nodes[2]; - vector< _Node > _intNodes; // _Node's at GridLine intersections - vector< _Link > _splits; - vector< _Face*> _faces; + _Face* _faces[2]; // polygons sharing a link + vector< const F_IntersectPoint* > _fIntPoints; // GridLine intersections with FACEs + vector< _Node* > _fIntNodes; // _Node's at _fIntPoints + vector< _Link > _splits; + _Link() { _faces[0] = 0; } }; // -------------------------------------------------------------------------------- struct _OrientedLink @@ -502,9 +517,9 @@ namespace return _OrientedLink(&_link->_splits[_reverse ? NbResultLinks()-i-1 : i],_reverse); } _Node* FirstNode() const { return _link->_nodes[ _reverse ]; } - _Node* LastNode() const { return _link->_nodes[ !_reverse ]; } + _Node* LastNode() const { return _link->_nodes[ !_reverse ]; } operator bool() const { return _link; } - vector< TGeomID > GetNotUsedFace(const set& usedIDs ) const // returns a supporting FACEs + vector< TGeomID > GetNotUsedFace(const set& usedIDs ) const // returns supporting FACEs { vector< TGeomID > faces; const B_IntersectPoint *ip0, *ip1; @@ -518,32 +533,67 @@ namespace } return faces; } + bool HasEdgeNodes() const + { + return ( dynamic_cast< const E_IntersectPoint* >( _link->_nodes[0]->_intPoint ) || + dynamic_cast< const E_IntersectPoint* >( _link->_nodes[1]->_intPoint )); + } + int NbFaces() const + { + return !_link->_faces[0] ? 0 : 1 + bool( _link->_faces[1] ); + } + void AddFace( _Face* f ) + { + if ( _link->_faces[0] ) + { + _link->_faces[1] = f; + } + else + { + _link->_faces[0] = f; + _link->_faces[1] = 0; + } + } + void RemoveFace( _Face* f ) + { + if ( !_link->_faces[0] ) return; + + if ( _link->_faces[1] == f ) + { + _link->_faces[1] = 0; + } + else if ( _link->_faces[0] == f ) + { + _link->_faces[0]; + if ( _link->_faces[1] ) + { + _link->_faces[0] = _link->_faces[1]; + _link->_faces[1] = 0; + } + } + } }; // -------------------------------------------------------------------------------- struct _Face { vector< _OrientedLink > _links; // links on GridLine's vector< _Link > _polyLinks; // links added to close a polygonal face - vector< _Node > _edgeNodes; // nodes at intersection with EDGEs + vector< _Node* > _eIntNodes; // nodes at intersection with EDGEs + bool isPolyLink( const _OrientedLink& ol ) + { + return _polyLinks.empty() ? false : + ( &_polyLinks[0] <= ol._link && ol._link <= &_polyLinks.back() ); + } }; // -------------------------------------------------------------------------------- struct _volumeDef // holder of nodes of a volume mesh element { - //vector< const SMDS_MeshNode* > _nodes; vector< _Node* > _nodes; vector< int > _quantities; typedef boost::shared_ptr<_volumeDef> Ptr; void set( const vector< _Node* >& nodes, const vector< int >& quant = vector< int >() ) { _nodes = nodes; _quantities = quant; } - // static Ptr New( const vector< const SMDS_MeshNode* >& nodes, - // const vector< int > quant = vector< int >() ) - // { - // _volumeDef* def = new _volumeDef; - // def->_nodes = nodes; - // def->_quantities = quant; - // return Ptr( def ); - // } }; // topology of a hexahedron @@ -556,10 +606,13 @@ namespace vector< _Face > _polygons; // intresections with EDGEs - vector< const E_IntersectPoint* > _edgeIntPnts; + vector< const E_IntersectPoint* > _eIntPoints; + + // additional nodes created at intersection points + vector< _Node > _intNodes; // nodes inside the hexahedron (at VERTEXes) - vector< _Node > _vertexNodes; + vector< _Node* > _vIntNodes; // computed volume elements //vector< _volumeDef::Ptr > _volumeDefs; @@ -567,7 +620,7 @@ namespace Grid* _grid; double _sizeThreshold, _sideLength[3]; - int _nbCornerNodes, _nbIntNodes, _nbBndNodes; + int _nbCornerNodes, _nbFaceIntNodes, _nbBndNodes; int _origNodeInd; // index of _hexNodes[0] node within the _grid size_t _i,_j,_k; @@ -593,20 +646,24 @@ namespace vector< Hexahedron* >& hexes, int ijk[], int dIJK[] ); bool findChain( _Node* n1, _Node* n2, _Face& quad, vector<_Node*>& chainNodes ); + bool closePolygon( _Face* polygon, vector<_Node*>& chainNodes ) const; int addElements(SMESH_MesherHelper& helper); + bool is1stNodeOut( _Link& link ) const; bool isInHole() const; bool checkPolyhedronSize() const; bool addHexa (); bool addTetra(); bool addPenta(); bool addPyra (); - _Node* FindEqualNode( vector< _Node >& nodes, + bool debugDumpLink( _Link* link ); + _Node* FindEqualNode( vector< _Node* >& nodes, const E_IntersectPoint* ip, const double tol2 ) { for ( size_t i = 0; i < nodes.size(); ++i ) - if ( nodes[i].Point().SquareDistance( ip->_point ) <= tol2 ) - return & nodes[i]; + if ( nodes[i]->EdgeIntPnt() == ip || + nodes[i]->Point().SquareDistance( ip->_point ) <= tol2 ) + return nodes[i]; return 0; } }; @@ -725,7 +782,8 @@ namespace return ( ipBef->_transition == Trans_OUT ); return ( ipBef->_transition != Trans_OUT ); } - return prevIsOut; // _transition == Trans_TANGENT + // _transition == Trans_TANGENT + return !prevIsOut; } //================================================================================ /* @@ -749,15 +807,16 @@ namespace } //================================================================================ /* - * Returns \c true if \a other B_IntersectPoint holds the same face ID + * Returns index of a common face if any, else zero */ - bool B_IntersectPoint::HasCommonFace( const B_IntersectPoint * other ) const + int B_IntersectPoint::HasCommonFace( const B_IntersectPoint * other, int avoidFace ) const { if ( other ) for ( size_t i = 0; i < other->_faceIDs.size(); ++i ) - if ( IsOnFace( other->_faceIDs[i] ) ) - return true; - return false; + if ( avoidFace != other->_faceIDs[i] && + IsOnFace ( other->_faceIDs[i] )) + return other->_faceIDs[i]; + return 0; } //================================================================================ /* @@ -1452,7 +1511,7 @@ namespace * \brief Creates topology of the hexahedron */ Hexahedron::Hexahedron(const double sizeThreshold, Grid* grid) - : _grid( grid ), _sizeThreshold( sizeThreshold ), _nbIntNodes(0) + : _grid( grid ), _sizeThreshold( sizeThreshold ), _nbFaceIntNodes(0) { _polygons.reserve(100); // to avoid reallocation; @@ -1485,8 +1544,6 @@ namespace _Link& link = _hexLinks[ SMESH_Block::ShapeIndex( linkID )]; link._nodes[0] = &_hexNodes[ SMESH_Block::ShapeIndex( idVec[0] )]; link._nodes[1] = &_hexNodes[ SMESH_Block::ShapeIndex( idVec[1] )]; - link._intNodes.reserve( 10 ); // to avoid reallocation - link._splits.reserve( 10 ); } // set links to faces @@ -1517,7 +1574,7 @@ namespace * \brief Copy constructor */ Hexahedron::Hexahedron( const Hexahedron& other ) - :_grid( other._grid ), _sizeThreshold( other._sizeThreshold ), _nbIntNodes(0) + :_grid( other._grid ), _sizeThreshold( other._sizeThreshold ), _nbFaceIntNodes(0) { _polygons.reserve(100); // to avoid reallocation; @@ -1530,8 +1587,6 @@ namespace _Link& tgtLink = this->_hexLinks[ i ]; tgtLink._nodes[0] = _hexNodes + ( srcLink._nodes[0] - other._hexNodes ); tgtLink._nodes[1] = _hexNodes + ( srcLink._nodes[1] - other._hexNodes ); - tgtLink._intNodes.reserve( 10 ); // to avoid reallocation - tgtLink._splits.reserve( 10 ); } for ( int i = 0; i < 6; ++i ) @@ -1572,33 +1627,57 @@ namespace _sideLength[1] = _grid->_coords[1][j+1] - _grid->_coords[1][j]; _sideLength[2] = _grid->_coords[2][k+1] - _grid->_coords[2][k]; - if ( _nbIntNodes + _edgeIntPnts.size() > 0 && - _nbIntNodes + _nbCornerNodes + _edgeIntPnts.size() > 3) + _intNodes.clear(); + _vIntNodes.clear(); + + if ( _nbFaceIntNodes + _eIntPoints.size() > 0 && + _nbFaceIntNodes + _nbCornerNodes + _eIntPoints.size() > 3) { + _intNodes.reserve( 3 * _nbBndNodes + _nbFaceIntNodes + _eIntPoints.size() ); + _Link split; - // create sub-links (_splits) by splitting links with _intNodes + // create sub-links (_splits) by splitting links with _fIntPoints for ( int iLink = 0; iLink < 12; ++iLink ) { _Link& link = _hexLinks[ iLink ]; + link._fIntNodes.resize( link._fIntPoints.size() ); + for ( size_t i = 0; i < link._fIntPoints.size(); ++i ) + { + _intNodes.push_back( _Node( 0, link._fIntPoints[i] )); + link._fIntNodes[ i ] = & _intNodes.back(); + } + link._splits.clear(); split._nodes[ 0 ] = link._nodes[0]; - bool isOut = ( ! link._nodes[0]->Node() ); - //int iEnd = link._intNodes.size() - bool( link._nodes[1]->_intPoint ); - for ( size_t i = 0; i < link._intNodes.size(); ++i ) + bool isOut = ( ! link._nodes[0]->Node() ); // is1stNodeOut( iLink ); + bool checkTransition; + for ( size_t i = 0; i < link._fIntNodes.size(); ++i ) { - if ( link._intNodes[i].Node() ) + if ( link._fIntNodes[i]->Node() ) // intersection non-coinsident with a grid node { if ( split._nodes[ 0 ]->Node() && !isOut ) { - split._nodes[ 1 ] = &link._intNodes[i]; + split._nodes[ 1 ] = link._fIntNodes[i]; link._splits.push_back( split ); } - split._nodes[ 0 ] = &link._intNodes[i]; + split._nodes[ 0 ] = link._fIntNodes[i]; + checkTransition = true; } - switch ( link._intNodes[i].FaceIntPnt()->_transition ) { - case Trans_OUT: isOut = true; break; - case Trans_IN : isOut = false; break; - default:; // isOut remains the same + else // FACE intersection coinsident with a grid node + { + checkTransition = ( link._nodes[0]->Node() ); + } + if ( checkTransition ) + { + switch ( link._fIntPoints[i]->_transition ) { + case Trans_OUT: isOut = true; break; + case Trans_IN : isOut = false; break; + default: + if ( !link._fIntNodes[i]->Node() && i == 0 ) + isOut = is1stNodeOut( link ); + else + ; // isOut remains the same + } } } if ( link._nodes[ 1 ]->Node() && split._nodes[ 0 ]->Node() && !isOut ) @@ -1613,21 +1692,21 @@ namespace const double tol2 = _grid->_tol * _grid->_tol; int facets[3], nbFacets, subEntity; - for ( size_t iP = 0; iP < _edgeIntPnts.size(); ++iP ) + for ( size_t iP = 0; iP < _eIntPoints.size(); ++iP ) { - nbFacets = getEntity( _edgeIntPnts[iP], facets, subEntity ); + nbFacets = getEntity( _eIntPoints[iP], facets, subEntity ); _Node* equalNode = 0; switch( nbFacets ) { case 1: // in a _Face { _Face& quad = _hexQuads[ facets[0] - SMESH_Block::ID_FirstF ]; - equalNode = FindEqualNode( quad._edgeNodes, _edgeIntPnts[ iP ], tol2 ); + equalNode = FindEqualNode( quad._eIntNodes, _eIntPoints[ iP ], tol2 ); if ( equalNode ) { - equalNode->Add( _edgeIntPnts[ iP ] ); + equalNode->Add( _eIntPoints[ iP ] ); } else { - quad._edgeNodes.push_back( _Node( 0, _edgeIntPnts[ iP ])); - ++_nbIntNodes; + _intNodes.push_back( _Node( 0, _eIntPoints[ iP ])); + quad._eIntNodes.push_back( & _intNodes.back() ); } break; } @@ -1636,22 +1715,22 @@ namespace _Link& link = _hexLinks[ subEntity - SMESH_Block::ID_FirstE ]; if ( link._splits.size() > 0 ) { - equalNode = FindEqualNode( link._intNodes, _edgeIntPnts[ iP ], tol2 ); + equalNode = FindEqualNode( link._fIntNodes, _eIntPoints[ iP ], tol2 ); if ( equalNode ) - equalNode->Add( _edgeIntPnts[ iP ] ); + equalNode->Add( _eIntPoints[ iP ] ); } else { + _intNodes.push_back( _Node( 0, _eIntPoints[ iP ])); for ( int iF = 0; iF < 2; ++iF ) { _Face& quad = _hexQuads[ facets[iF] - SMESH_Block::ID_FirstF ]; - equalNode = FindEqualNode( quad._edgeNodes, _edgeIntPnts[ iP ], tol2 ); + equalNode = FindEqualNode( quad._eIntNodes, _eIntPoints[ iP ], tol2 ); if ( equalNode ) { - equalNode->Add( _edgeIntPnts[ iP ] ); + equalNode->Add( _eIntPoints[ iP ] ); } else { - quad._edgeNodes.push_back( _Node( 0, _edgeIntPnts[ iP ])); - ++_nbIntNodes; + quad._eIntNodes.push_back( & _intNodes.back() ); } } } @@ -1663,41 +1742,43 @@ namespace if ( node.Node() > 0 ) { if ( node._intPoint ) - node._intPoint->Add( _edgeIntPnts[ iP ]->_faceIDs, _edgeIntPnts[ iP ]->_node ); + node._intPoint->Add( _eIntPoints[ iP ]->_faceIDs, _eIntPoints[ iP ]->_node ); } else { + _intNodes.push_back( _Node( 0, _eIntPoints[ iP ])); for ( int iF = 0; iF < 3; ++iF ) { _Face& quad = _hexQuads[ facets[iF] - SMESH_Block::ID_FirstF ]; - equalNode = FindEqualNode( quad._edgeNodes, _edgeIntPnts[ iP ], tol2 ); + equalNode = FindEqualNode( quad._eIntNodes, _eIntPoints[ iP ], tol2 ); if ( equalNode ) { - equalNode->Add( _edgeIntPnts[ iP ] ); + equalNode->Add( _eIntPoints[ iP ] ); } else { - quad._edgeNodes.push_back( _Node( 0, _edgeIntPnts[ iP ])); - ++_nbIntNodes; + quad._eIntNodes.push_back( & _intNodes.back() ); } } } break; } - default: // inside a hex + } // switch( nbFacets ) + + if ( nbFacets == 0 || + _grid->_shapes( _eIntPoints[ iP ]->_shapeID ).ShapeType() == TopAbs_VERTEX ) { - equalNode = FindEqualNode( _vertexNodes, _edgeIntPnts[ iP ], tol2 ); + equalNode = FindEqualNode( _vIntNodes, _eIntPoints[ iP ], tol2 ); if ( equalNode ) { - equalNode->Add( _edgeIntPnts[ iP ] ); + equalNode->Add( _eIntPoints[ iP ] ); } else { - _vertexNodes.push_back( _Node( 0, _edgeIntPnts[iP] )); - ++_nbIntNodes; + if ( _intNodes.empty() || _intNodes.back().EdgeIntPnt() != _eIntPoints[ iP ]) + _intNodes.push_back( _Node( 0, _eIntPoints[ iP ])); + _vIntNodes.push_back( & _intNodes.back() ); } } - } // switch( nbFacets ) - - } // loop on _edgeIntPnts + } // loop on _eIntPoints } - else if ( 3 < _nbCornerNodes && _nbCornerNodes < 8 ) // _nbIntNodes == 0 + else if ( 3 < _nbCornerNodes && _nbCornerNodes < 8 ) // _nbFaceIntNodes == 0 { _Link split; // create sub-links (_splits) of whole links @@ -1737,22 +1818,25 @@ namespace { Init(); - if ( _nbCornerNodes + _nbIntNodes < 4 ) + int nbIntersections = _nbFaceIntNodes + _eIntPoints.size(); + if ( _nbCornerNodes + nbIntersections < 4 ) return; - if ( _nbBndNodes == _nbCornerNodes && _nbIntNodes == 0 && isInHole() ) + if ( _nbBndNodes == _nbCornerNodes && nbIntersections == 0 && isInHole() ) return; _polygons.clear(); - _polygons.reserve( 10 ); + _polygons.reserve( 20 ); - // create polygons from quadrangles and get their nodes + // Create polygons from quadrangles + // -------------------------------- - _Link polyLink; + _Link polyLink; vector< _OrientedLink > splits; - vector<_Node*> chainNodes; + vector<_Node*> chainNodes, usedEdgeNodes; + _Face* coplanarPolyg; - bool hasEdgeIntersections = !_edgeIntPnts.empty(); + bool hasEdgeIntersections = !_eIntPoints.empty(); for ( int iF = 0; iF < 6; ++iF ) // loop on 6 sides of a hexahedron { @@ -1771,23 +1855,15 @@ namespace // polygon's boundary closed int nbSplits = splits.size(); - if ( nbSplits < 2 && quad._edgeNodes.empty() ) + if ( nbSplits < 2 && quad._eIntNodes.empty() ) nbSplits = 0; - if ( nbSplits == 0 && !quad._edgeNodes.empty() ) - { - // make _vertexNodes from _edgeNodes of an empty quad - const double tol2 = _grid->_tol * _grid->_tol; - for ( size_t iP = 0; iP < quad._edgeNodes.size(); ++iP ) - { - _Node* equalNode = - FindEqualNode( _vertexNodes, quad._edgeNodes[ iP ].EdgeIntPnt(), tol2 ); - if ( equalNode ) - equalNode->Add( quad._edgeNodes[ iP ].EdgeIntPnt() ); - else - _vertexNodes.push_back( quad._edgeNodes[ iP ]); - } - } +#ifdef _DEBUG_ + for ( size_t iP = 0; iP < quad._eIntNodes.size(); ++iP ) + if ( quad._eIntNodes[ iP ]->IsUsedInFace( polygon )) + quad._eIntNodes[ iP ]->_usedInFace = 0; +#endif + int nbUsedEdgeNodes = 0; while ( nbSplits > 0 ) { @@ -1815,8 +1891,8 @@ namespace n1 = split.FirstNode(); if ( n1 != n2 ) { - // try to connect to intersections with EDGES - if ( quad._edgeNodes.size() > 0 && + // try to connect to intersections with EDGEs + if ( quad._eIntNodes.size() > nbUsedEdgeNodes && findChain( n2, n1, quad, chainNodes )) { for ( size_t i = 1; i < chainNodes.size(); ++i ) @@ -1825,6 +1901,13 @@ namespace polyLink._nodes[1] = chainNodes[i]; polygon->_polyLinks.push_back( polyLink ); polygon->_links.push_back( _OrientedLink( &polygon->_polyLinks.back() )); + nbUsedEdgeNodes += ( polyLink._nodes[1]->IsUsedInFace( polygon )); + } + if ( chainNodes.back() != n1 ) + { + n2 = chainNodes.back(); + --iS; + continue; } } // try to connect to a split ending on the same FACE @@ -1870,13 +1953,18 @@ namespace if ( nFirst != n2 ) // close a polygon { - findChain( n2, nFirst, quad, chainNodes ); + if ( !findChain( n2, nFirst, quad, chainNodes )) + { + if ( !closePolygon( polygon, chainNodes )) + chainNodes.push_back( nFirst ); + } for ( size_t i = 1; i < chainNodes.size(); ++i ) { polyLink._nodes[0] = chainNodes[i-1]; polyLink._nodes[1] = chainNodes[i]; polygon->_polyLinks.push_back( polyLink ); polygon->_links.push_back( _OrientedLink( &polygon->_polyLinks.back() )); + nbUsedEdgeNodes += bool( polyLink._nodes[1]->IsUsedInFace( polygon )); } } @@ -1887,21 +1975,44 @@ namespace } } // while ( nbSplits > 0 ) + // if ( quad._eIntNodes.size() > nbUsedEdgeNodes ) + // { + // // make _vIntNodes from not used _eIntNodes + // const double tol = 0.05 * Min( Min( _sideLength[0], _sideLength[1] ), _sideLength[0] ); + // for ( size_t iP = 0; iP < quad._eIntNodes.size(); ++iP ) + // { + // if ( quad._eIntNodes[ iP ]->IsUsedInFace() ) continue; + // _Node* equalNode = + // FindEqualNode( _vIntNodes, quad._eIntNodes[ iP ].EdgeIntPnt(), tol*tol ); + // if ( equalNode ) + // equalNode->Add( quad._eIntNodes[ iP ].EdgeIntPnt() ); + // else + // _vIntNodes.push_back( quad._eIntNodes[ iP ]); + // } + // } + if ( polygon->_links.size() < 3 ) + { _polygons.pop_back(); + //usedEdgeNodes.resize( usedEdgeNodes.size() - nbUsedEdgeNodes ); + } + } // loop on 6 hexahedron sides - } // loop on 6 sides of a hexahedron + // Create polygons closing holes in a polyhedron + // ---------------------------------------------- - // create polygons closing holes in a polyhedron + // clear _usedInFace + for ( size_t iN = 0; iN < _intNodes.size(); ++iN ) + _intNodes[ iN ]._usedInFace = 0; - // add polygons to their links + // add polygons to their links and mark used nodes for ( size_t iP = 0; iP < _polygons.size(); ++iP ) { _Face& polygon = _polygons[ iP ]; for ( size_t iL = 0; iL < polygon._links.size(); ++iL ) { - polygon._links[ iL ]._link->_faces.reserve( 2 ); - polygon._links[ iL ]._link->_faces.push_back( &polygon ); + polygon._links[ iL ].AddFace( &polygon ); + polygon._links[ iL ].FirstNode()->_usedInFace = &polygon; } } // find free links @@ -1911,25 +2022,54 @@ namespace { _Face& polygon = _polygons[ iP ]; for ( size_t iL = 0; iL < polygon._links.size(); ++iL ) - if ( polygon._links[ iL ]._link->_faces.size() < 2 ) + if ( polygon._links[ iL ].NbFaces() < 2 ) + { freeLinks.push_back( & polygon._links[ iL ]); + freeLinks.back()->FirstNode()->IsUsedInFace() == true; + } } int nbFreeLinks = freeLinks.size(); - if ( 0 < nbFreeLinks && nbFreeLinks < 3 ) return; + if ( nbFreeLinks > 0 && nbFreeLinks < 3 ) return; + + // put not used intersection nodes to _vIntNodes + int nbVertexNodes = 0; // nb not used vertex nodes + { + for ( size_t iN = 0; iN < _vIntNodes.size(); ++iN ) + nbVertexNodes += ( !_vIntNodes[ iN ]->IsUsedInFace() ); + + const double tol = 1e-3 * Min( Min( _sideLength[0], _sideLength[1] ), _sideLength[0] ); + for ( size_t iN = _nbFaceIntNodes; iN < _intNodes.size(); ++iN ) + { + if ( _intNodes[ iN ].IsUsedInFace() ) continue; + if ( dynamic_cast< const F_IntersectPoint* >( _intNodes[ iN ]._intPoint )) continue; + _Node* equalNode = + FindEqualNode( _vIntNodes, _intNodes[ iN ].EdgeIntPnt(), tol*tol ); + if ( !equalNode /*|| equalNode->IsUsedInFace()*/ ) + { + _vIntNodes.push_back( &_intNodes[ iN ]); + ++nbVertexNodes; + } + } + } set usedFaceIDs; + TGeomID curFace = 0; + const size_t nbQuadPolygons = _polygons.size(); - // make closed chains of free links + // create polygons by making closed chains of free links + size_t iPolygon = _polygons.size(); while ( nbFreeLinks > 0 ) { - _polygons.resize( _polygons.size() + 1 ); - _Face& polygon = _polygons.back(); + if ( iPolygon == _polygons.size() ) + _polygons.resize( _polygons.size() + 1 ); + _Face& polygon = _polygons[ iPolygon ]; polygon._polyLinks.reserve( 20 ); polygon._links.reserve( 20 ); _OrientedLink* curLink = 0; _Node* curNode; - if ( !hasEdgeIntersections ) + if (( !hasEdgeIntersections ) || + ( nbFreeLinks < 4 && nbVertexNodes == 0 )) { // get a remaining link to start from for ( size_t iL = 0; iL < freeLinks.size() && !curLink; ++iL ) @@ -1954,26 +2094,45 @@ namespace } else // there are intersections with EDGEs { - TGeomID curFace; // get a remaining link to start from, one lying on minimal // nb of FACEs { - map< vector< TGeomID >, int > facesOfLink; - map< vector< TGeomID >, int >::iterator f2l; + vector< pair< TGeomID, int > > facesOfLink[3]; + pair< TGeomID, int > faceOfLink( -1, -1 ); + vector< TGeomID > faces; for ( size_t iL = 0; iL < freeLinks.size(); ++iL ) if ( freeLinks[ iL ] ) { - f2l = facesOfLink.insert - ( make_pair( freeLinks[ iL ]->GetNotUsedFace( usedFaceIDs ), iL )).first; - if ( f2l->first.size() == 1 ) - break; + faces = freeLinks[ iL ]->GetNotUsedFace( usedFaceIDs ); + if ( faces.size() == 1 ) + { + faceOfLink = make_pair( faces[0], iL ); + if ( !freeLinks[ iL ]->HasEdgeNodes() ) + break; + facesOfLink[0].push_back( faceOfLink ); + } + else if ( facesOfLink[0].empty() ) + { + faceOfLink = make_pair(( faces.empty() ? -1 : faces[0]), iL ); + facesOfLink[ 1 + faces.empty() ].push_back( faceOfLink ); + } + } + for ( int i = 0; faceOfLink.second < 0 && i < 3; ++i ) + if ( !facesOfLink[i].empty() ) + faceOfLink = facesOfLink[i][0]; + + if ( faceOfLink.first < 0 ) // all faces used + { + for ( size_t i = 0; i < facesOfLink[2].size() && faceOfLink.first < 1; ++i ) + { + curLink = freeLinks[ facesOfLink[2][i].second ]; + faceOfLink.first = curLink->FirstNode()->IsLinked( curLink->LastNode()->_intPoint ); } - f2l = facesOfLink.begin(); - if ( f2l->first.empty() ) - return; - curFace = f2l->first[0]; - curLink = freeLinks[ f2l->second ]; - freeLinks[ f2l->second ] = 0; + usedFaceIDs.clear(); + } + curFace = faceOfLink.first; + curLink = freeLinks[ faceOfLink.second ]; + freeLinks[ faceOfLink.second ] = 0; } usedFaceIDs.insert( curFace ); polygon._links.push_back( *curLink ); @@ -2021,36 +2180,35 @@ namespace if ( polygon._links[0].LastNode() != curNode ) { - if ( !_vertexNodes.empty() ) + if ( nbVertexNodes > 0 ) { - // add links with _vertexNodes if not already used - for ( size_t iN = 0; iN < _vertexNodes.size(); ++iN ) - if ( _vertexNodes[ iN ].IsOnFace( curFace )) + // add links with _vIntNodes if not already used + for ( size_t iN = 0; iN < _vIntNodes.size(); ++iN ) + if ( !_vIntNodes[ iN ]->IsUsedInFace() && + _vIntNodes[ iN ]->IsOnFace( curFace )) { - bool used = ( curNode == &_vertexNodes[ iN ] ); - for ( size_t iL = 0; iL < polygon._links.size() && !used; ++iL ) - used = ( &_vertexNodes[ iN ] == polygon._links[ iL ].LastNode() ); - if ( !used ) - { - polyLink._nodes[0] = &_vertexNodes[ iN ]; - polyLink._nodes[1] = curNode; - polygon._polyLinks.push_back( polyLink ); - polygon._links.push_back( _OrientedLink( &polygon._polyLinks.back() )); - freeLinks.push_back( &polygon._links.back() ); - ++nbFreeLinks; - curNode = &_vertexNodes[ iN ]; - } - // TODO: to reorder _vertexNodes within polygon, if there are several ones + _vIntNodes[ iN ]->_usedInFace = &polygon; + --nbVertexNodes; + polyLink._nodes[0] = _vIntNodes[ iN ]; + polyLink._nodes[1] = curNode; + polygon._polyLinks.push_back( polyLink ); + polygon._links.push_back( _OrientedLink( &polygon._polyLinks.back() )); + freeLinks.push_back( &polygon._links.back() ); + ++nbFreeLinks; + curNode = _vIntNodes[ iN ]; + // TODO: to reorder _vIntNodes within polygon, if there are several ones } } - polyLink._nodes[0] = polygon._links[0].LastNode(); - polyLink._nodes[1] = curNode; - polygon._polyLinks.push_back( polyLink ); - polygon._links.push_back( _OrientedLink( &polygon._polyLinks.back() )); - freeLinks.push_back( &polygon._links.back() ); - ++nbFreeLinks; + // if ( polygon._links.size() > 1 ) + { + polyLink._nodes[0] = polygon._links[0].LastNode(); + polyLink._nodes[1] = curNode; + polygon._polyLinks.push_back( polyLink ); + polygon._links.push_back( _OrientedLink( &polygon._polyLinks.back() )); + freeLinks.push_back( &polygon._links.back() ); + ++nbFreeLinks; + } } - } // if there are intersections with EDGEs if ( polygon._links.size() < 2 || @@ -2059,18 +2217,105 @@ namespace if ( polygon._links.size() == 2 ) { + if ( freeLinks.back() == &polygon._links.back() ) + { + freeLinks.pop_back(); + --nbFreeLinks; + } + if ( polygon._links.front().NbFaces() > 0 ) + polygon._links.back().AddFace( polygon._links.front()._link->_faces[0] ); + if ( polygon._links.back().NbFaces() > 0 ) + polygon._links.front().AddFace( polygon._links.back()._link->_faces[0] ); + _polygons.pop_back(); } - else + else // polygon._links.size() >= 2 { // add polygon to its links for ( size_t iL = 0; iL < polygon._links.size(); ++iL ) { - polygon._links[ iL ]._link->_faces.reserve( 2 ); - polygon._links[ iL ]._link->_faces.push_back( &polygon ); + polygon._links[ iL ].AddFace( &polygon ); polygon._links[ iL ].Reverse(); } - } + if ( hasEdgeIntersections && iPolygon == _polygons.size() - 1 ) + { + // check that a polygon does not lie in the plane of another polygon + coplanarPolyg = 0; + for ( size_t iL = 0; iL < polygon._links.size() && !coplanarPolyg; ++iL ) + { + if ( polygon._links[ iL ].NbFaces() < 2 ) + continue; // it's a just added free link + // look for a polygon made on a hexa side and sharing + // two or more haxa links + size_t iL2; + coplanarPolyg = polygon._links[ iL ]._link->_faces[0]; + for ( iL2 = iL + 1; iL2 < polygon._links.size(); ++iL2 ) + if ( polygon._links[ iL2 ]._link->_faces[0] == coplanarPolyg && + !coplanarPolyg->isPolyLink( polygon._links[ iL2 ]) && + coplanarPolyg < & _polygons[ nbQuadPolygons ]) + break; + if ( iL2 == polygon._links.size() ) + coplanarPolyg = 0; + } + if ( 0 /*coplanarPolyg*/ ) // coplanar polygon found + { + freeLinks.resize( freeLinks.size() - polygon._polyLinks.size() ); + nbFreeLinks -= polygon._polyLinks.size(); + + // fill freeLinks with links not shared by coplanarPolyg and polygon + for ( size_t iL = 0; iL < polygon._links.size(); ++iL ) + if ( polygon._links[ iL ]._link->_faces[1] && + polygon._links[ iL ]._link->_faces[0] != coplanarPolyg ) + { + _Face* p = polygon._links[ iL ]._link->_faces[0]; + for ( size_t iL2 = 0; iL2 < p->_links.size(); ++iL2 ) + if ( p->_links[ iL2 ]._link == polygon._links[ iL ]._link ) + { + freeLinks.push_back( & p->_links[ iL2 ] ); + ++nbFreeLinks; + freeLinks.back()->RemoveFace( &polygon ); + break; + } + } + for ( size_t iL = 0; iL < coplanarPolyg->_links.size(); ++iL ) + if ( coplanarPolyg->_links[ iL ]._link->_faces[1] && + coplanarPolyg->_links[ iL ]._link->_faces[1] != &polygon ) + { + _Face* p = coplanarPolyg->_links[ iL ]._link->_faces[0]; + if ( p == coplanarPolyg ) + p = coplanarPolyg->_links[ iL ]._link->_faces[1]; + for ( size_t iL2 = 0; iL2 < p->_links.size(); ++iL2 ) + if ( p->_links[ iL2 ]._link == coplanarPolyg->_links[ iL ]._link ) + { + freeLinks.push_back( & p->_links[ iL2 ] ); + ++nbFreeLinks; + freeLinks.back()->RemoveFace( coplanarPolyg ); + break; + } + } + // set coplanarPolyg to be re-created next + for ( size_t iP = 0; iP < _polygons.size(); ++iP ) + if ( coplanarPolyg == & _polygons[ iP ] ) + { + iPolygon = iP; + _polygons[ iPolygon ]._links.clear(); + _polygons[ iPolygon ]._polyLinks.clear(); + break; + } + if ( freeLinks.back() == &polygon._links.back() ) + { + freeLinks.pop_back(); + --nbFreeLinks; + } + _polygons.pop_back(); + usedFaceIDs.erase( curFace ); + continue; + } // if ( coplanarPolyg ) + } // if ( hasEdgeIntersections ) + + iPolygon = _polygons.size(); + + } // end of case ( polygon._links.size() > 2 ) } // while ( nbFreeLinks > 0 ) if ( ! checkPolyhedronSize() ) @@ -2079,7 +2324,7 @@ namespace } // create a classic cell if possible - const int nbNodes = _nbCornerNodes + _nbIntNodes; + const int nbNodes = _nbCornerNodes + nbIntersections; bool isClassicElem = false; if ( nbNodes == 8 && _polygons.size() == 6 ) isClassicElem = addHexa(); else if ( nbNodes == 4 && _polygons.size() == 4 ) isClassicElem = addTetra(); @@ -2131,7 +2376,7 @@ namespace multiset< F_IntersectPoint >::const_iterator ip = line._intPoints.begin(); for ( ; ip != line._intPoints.end(); ++ip ) { - //if ( !ip->_node ) continue; + // if ( !ip->_node ) continue; // intersection at a grid node lineInd.SetIndexOnLine( ip->_indexOnLine ); for ( int iL = 0; iL < 4; ++iL ) // loop on 4 cells sharing a link { @@ -2153,8 +2398,9 @@ namespace ++nbIntHex; } const int iLink = iL + iDir * 4; - hex->_hexLinks[iLink]._intNodes.push_back( _Node( 0, &(*ip) )); - hex->_nbIntNodes += bool( ip->_node ); + hex->_hexLinks[iLink]._fIntPoints.push_back( &(*ip) ); + //hex->_hexLinks[iLink]._fIntNodes.push_back( _Node( 0, &(*ip) )); + hex->_nbFaceIntNodes += bool( ip->_node ); } } } @@ -2173,14 +2419,16 @@ namespace if ( hex ) { intHexInd[ nbIntHex++ ] = i; - if ( hex->_nbIntNodes > 0 ) continue; // treat intersected hex later + if ( hex->_nbFaceIntNodes > 0 || hex->_eIntPoints.size() > 0 ) + continue; // treat intersected hex later this->init( hex->_i, hex->_j, hex->_k ); } else { this->init( i ); } - if ( _nbCornerNodes == 8 && ( _nbBndNodes < _nbCornerNodes || !isInHole() )) + if (( _nbCornerNodes == 8 ) && + ( _nbBndNodes < _nbCornerNodes || !isInHole() )) { // order of _hexNodes is defined by enum SMESH_Block::TShapeID SMDS_MeshElement* el = @@ -2325,9 +2573,11 @@ namespace if ( iDirZ == 0 ) { ip._point = p1; + ip._shapeID = _grid->_shapes.Add( v1 ); _grid->_edgeIntP.push_back( ip ); if ( !addIntersection( _grid->_edgeIntP.back(), hexes, ijk, d000 )) _grid->_edgeIntP.pop_back(); + ip._shapeID = edgeID; } for ( int iP = 2; iP <= discret.NbPoints(); ++iP ) { @@ -2335,7 +2585,9 @@ namespace gp_XYZ p2 = discret.Value( iP ).XYZ(); double u2 = discret.Parameter( iP ); double zProj2 = planes._zNorm * ( p2 - _grid->_origin ); - int iZ2 = iZ1; + int iZ2 = iZ1; + if ( Abs( zProj2 - zProj1 ) <= std::numeric_limits::min() ) + continue; locateValue( iZ2, zProj2, planes._zProjs, dIJK[ iDirZ ], tol ); // treat intersections with planes between 2 end points of a segment @@ -2370,6 +2622,7 @@ namespace // add the 2nd vertex point to a hexahedron if ( iDirZ == 0 ) { + ip._shapeID = _grid->_shapes.Add( v2 ); ip._point = p1; _grid->ComputeUVW( p1, ip._uvw ); locateValue( ijk[iDirX], ip._uvw[iDirX], _grid->_coords[iDirX], dIJK[iDirX], tol ); @@ -2378,6 +2631,7 @@ namespace _grid->_edgeIntP.push_back( ip ); if ( !addIntersection( _grid->_edgeIntP.back(), hexes, ijk, d000 )) _grid->_edgeIntP.pop_back(); + ip._shapeID = edgeID; } } // loop on 3 grid directions } // loop on EDGEs @@ -2391,16 +2645,16 @@ namespace // for ( int iF = 0; iF < 6; ++iF ) // { // _Face& quad = h->_hexQuads[ iF ]; - // for ( size_t iP = 0; iP < quad._edgeNodes.size(); ++iP ) - // if ( !quad._edgeNodes[ iP ]._node ) - // if (( eip = quad._edgeNodes[ iP ].EdgeIntPnt() )) - // quad._edgeNodes[ iP ]._intPoint->_node = helper.AddNode( eip->_point.X(), + // for ( size_t iP = 0; iP < quad._eIntNodes.size(); ++iP ) + // if ( !quad._eIntNodes[ iP ]._node ) + // if (( eip = quad._eIntNodes[ iP ].EdgeIntPnt() )) + // quad._eIntNodes[ iP ]._intPoint->_node = helper.AddNode( eip->_point.X(), // eip->_point.Y(), // eip->_point.Z() ); // } - // for ( size_t iP = 0; iP < hexes[i]->_vertexNodes.size(); ++iP ) - // if (( eip = h->_vertexNodes[ iP ].EdgeIntPnt() )) - // h->_vertexNodes[ iP ]._intPoint->_node = helper.AddNode( eip->_point.X(), + // for ( size_t iP = 0; iP < hexes[i]->_vIntNodes.size(); ++iP ) + // if (( eip = h->_vIntNodes[ iP ].EdgeIntPnt() )) + // h->_vIntNodes[ iP ]._intPoint->_node = helper.AddNode( eip->_point.X(), // eip->_point.Y(), // eip->_point.Z() ); // } @@ -2540,7 +2794,7 @@ namespace ( _grid->_coords[2][ h->_k+1 ] + _grid->_tol < ip._uvw[2] )) throw SALOME_Exception("ip outside a hex"); #endif - h->_edgeIntPnts.push_back( & ip ); + h->_eIntPoints.push_back( & ip ); added = true; } } @@ -2557,24 +2811,163 @@ namespace { chn.clear(); chn.push_back( n1 ); - bool found = false; + for ( size_t iP = 0; iP < quad._eIntNodes.size(); ++iP ) + if ( !quad._eIntNodes[ iP ]->IsUsedInFace( &quad ) && + n1->IsLinked( quad._eIntNodes[ iP ]->_intPoint ) && + n2->IsLinked( quad._eIntNodes[ iP ]->_intPoint )) + { + chn.push_back( quad._eIntNodes[ iP ]); + chn.push_back( n2 ); + quad._eIntNodes[ iP ]->_usedInFace = &quad; + return true; + } + bool found; do { found = false; - for ( size_t iP = 0; iP < quad._edgeNodes.size(); ++iP ) - if (( std::find( ++chn.begin(), chn.end(), & quad._edgeNodes[iP]) == chn.end()) && - chn.back()->IsLinked( quad._edgeNodes[ iP ]._intPoint )) + for ( size_t iP = 0; iP < quad._eIntNodes.size(); ++iP ) + if ( !quad._eIntNodes[ iP ]->IsUsedInFace( &quad ) && + chn.back()->IsLinked( quad._eIntNodes[ iP ]->_intPoint )) { - chn.push_back( & quad._edgeNodes[ iP ]); - found = true; + chn.push_back( quad._eIntNodes[ iP ]); + found = quad._eIntNodes[ iP ]->_usedInFace = &quad; break; } - } while ( found && chn.back() != n2 ); + } while ( found && ! chn.back()->IsLinked( n2->_intPoint ) ); - if ( chn.back() != n2 ) + if ( chn.back() != n2 && chn.back()->IsLinked( n2->_intPoint )) chn.push_back( n2 ); - return chn.size() > 2; + return chn.size() > 1; + } + //================================================================================ + /*! + * \brief Try to heal a polygon whose ends are not connected + */ + bool Hexahedron::closePolygon( _Face* polygon, vector<_Node*>& chainNodes ) const + { + int i = -1, nbLinks = polygon->_links.size(); + if ( nbLinks < 3 ) + return false; + vector< _OrientedLink > newLinks; + // find a node lying on the same FACE as the last one + _Node* node = polygon->_links.back().LastNode(); + int avoidFace = node->IsLinked( polygon->_links.back().FirstNode()->_intPoint ); + for ( i = nbLinks - 2; i >= 0; --i ) + if ( node->IsLinked( polygon->_links[i].FirstNode()->_intPoint, avoidFace )) + break; + if ( i >= 0 ) + { + for ( ; i < nbLinks; ++i ) + newLinks.push_back( polygon->_links[i] ); + } + else + { + // find a node lying on the same FACE as the first one + node = polygon->_links[0].FirstNode(); + avoidFace = node->IsLinked( polygon->_links[0].LastNode()->_intPoint ); + for ( i = 1; i < nbLinks; ++i ) + if ( node->IsLinked( polygon->_links[i].LastNode()->_intPoint, avoidFace )) + break; + if ( i < nbLinks ) + for ( nbLinks = i + 1, i = 0; i < nbLinks; ++i ) + newLinks.push_back( polygon->_links[i] ); + } + if ( newLinks.size() > 1 ) + { + polygon->_links.swap( newLinks ); + chainNodes.clear(); + chainNodes.push_back( polygon->_links.back().LastNode() ); + chainNodes.push_back( polygon->_links[0].FirstNode() ); + return true; + } + return false; + } + //================================================================================ + /*! + * \brief Checks transition at the 1st node of a link + */ + bool Hexahedron::is1stNodeOut( _Link& link /*int iLink*/ ) const + { + // new version is for the case: tangent transition at the 1st node + bool isOut = false; + if ( link._fIntNodes.size() > 1 ) + { + // check transition at the next intersection + switch ( link._fIntPoints[1]->_transition ) { + case Trans_OUT: return false; + case Trans_IN : return true; + default: ; // tangent transition + } + } + gp_Pnt p1 = link._nodes[0]->Point(); + gp_Pnt p2 = link._nodes[1]->Point(); + gp_Pnt testPnt = 0.8 * p1.XYZ() + 0.2 * p2.XYZ(); + + TGeomID faceID = link._fIntPoints[0]->_faceIDs[0]; + const TopoDS_Face& face = TopoDS::Face( _grid->_shapes( faceID )); + TopLoc_Location loc; + GeomAPI_ProjectPointOnSurf& proj = + _grid->_helper->GetProjector( face, loc, 0.1*_grid->_tol ); + testPnt.Transform( loc ); + proj.Perform( testPnt ); + if ( proj.IsDone() && + proj.NbPoints() > 0 && + proj.LowerDistance() > _grid->_tol ) + { + Quantity_Parameter u,v; + proj.LowerDistanceParameters( u,v ); + gp_Dir normal; + if ( GeomLib::NormEstim( BRep_Tool::Surface( face, loc ), + gp_Pnt2d( u,v ), + 0.1*_grid->_tol, + normal ) < 3 ) + { + if ( face.Orientation() == TopAbs_REVERSED ) + normal.Reverse(); + gp_Vec v( proj.NearestPoint(), testPnt ); + return v * normal > 0; + } + } + // if ( !_hexLinks[ iLink ]._nodes[0]->Node() ) // no node + // return true; + // if ( !_hexLinks[ iLink ]._nodes[0]->_intPoint ) // no intersection with geometry + // return false; + // switch ( _hexLinks[ iLink ]._nodes[0]->FaceIntPnt()->_transition ) { + // case Trans_OUT: return true; + // case Trans_IN : return false; + // default: ; // tangent transition + // } + +// // ijk of a GridLine corresponding to the link +// int iDir = iLink / 4; +// int indSub = iLink % 4; +// LineIndexer li = _grid->GetLineIndexer( iDir ); +// li.SetIJK( _i,_j,_k ); +// size_t lineIndex[4] = { li.LineIndex (), +// li.LineIndex10(), +// li.LineIndex01(), +// li.LineIndex11() }; +// GridLine& line = _grid->_lines[ iDir ][ lineIndex[ indSub ]]; + +// // analyze transition of previous ip +// bool isOut = true; +// multiset< F_IntersectPoint >::const_iterator ip = line._intPoints.begin(); +// for ( ; ip != line._intPoints.end(); ++ip ) +// { +// if ( &(*ip) == _hexLinks[ iLink ]._nodes[0]->_intPoint ) +// break; +// switch ( ip->_transition ) { +// case Trans_OUT: isOut = true; +// case Trans_IN : isOut = false; +// default:; +// } +// } +// #ifdef _DEBUG_ +// if ( ip == line._intPoints.end() ) +// cout << "BUG: Wrong GridLine. IKJ = ( "<< _i << " " << _j << " " << _k << " )" << endl; +// #endif + return isOut; } //================================================================================ /*! @@ -2630,7 +3023,7 @@ namespace */ bool Hexahedron::isInHole() const { - if ( !_vertexNodes.empty() ) + if ( !_vIntNodes.empty() ) return false; const int ijk[3] = { _i, _j, _k }; @@ -2662,9 +3055,9 @@ namespace --ip; firstIntPnt = &(*ip); } - else if ( !link._intNodes.empty() ) + else if ( !link._fIntPoints.empty() ) { - firstIntPnt = link._intNodes[0].FaceIntPnt(); + firstIntPnt = link._fIntPoints[0]; } if ( firstIntPnt ) @@ -2728,7 +3121,9 @@ namespace // find a top node above the base node _Link* link = _polygons[0]._links[iL]._link; - ASSERT( link->_faces.size() > 1 ); + //ASSERT( link->_faces.size() > 1 ); + if ( !link->_faces[0] || !link->_faces[1] ) + return debugDumpLink( link ); // a quadrangle sharing with _polygons[0] _Face* quad = link->_faces[ bool( link->_faces[0] == & _polygons[0] )]; for ( int i = 0; i < 4; ++i ) @@ -2757,7 +3152,9 @@ namespace nodes[2] = _polygons[0]._links[2].FirstNode(); _Link* link = _polygons[0]._links[0]._link; - ASSERT( link->_faces.size() > 1 ); + //ASSERT( link->_faces.size() > 1 ); + if ( !link->_faces[0] || !link->_faces[1] ) + return debugDumpLink( link ); // a triangle sharing with _polygons[0] _Face* tria = link->_faces[ bool( link->_faces[0] == & _polygons[0] )]; @@ -2795,7 +3192,9 @@ namespace // find a top node above the base node _Link* link = _polygons[ iTri ]._links[iL]._link; - ASSERT( link->_faces.size() > 1 ); + //ASSERT( link->_faces.size() > 1 ); + if ( !link->_faces[0] || !link->_faces[1] ) + return debugDumpLink( link ); // a quadrangle sharing with a base triangle _Face* quad = link->_faces[ bool( link->_faces[0] == & _polygons[ iTri ] )]; if ( quad->_links.size() != 4 ) return false; @@ -2834,7 +3233,9 @@ namespace nodes[3] = _polygons[iQuad]._links[3].FirstNode(); _Link* link = _polygons[iQuad]._links[0]._link; - ASSERT( link->_faces.size() > 1 ); + //ASSERT( link->_faces.size() > 1 ); + if ( !link->_faces[0] || !link->_faces[1] ) + return debugDumpLink( link ); // a triangle sharing with a base quadrangle _Face* tria = link->_faces[ bool( link->_faces[0] == & _polygons[ iQuad ] )]; @@ -2849,6 +3250,20 @@ namespace return false; } + //================================================================================ + /*! + * \brief Dump a link and return \c false + */ + bool Hexahedron::debugDumpLink( Hexahedron::_Link* link ) + { +#ifdef _DEBUG_ + gp_Pnt p1 = link->_nodes[0]->Point(), p2 = link->_nodes[1]->Point(); + cout << "BUG: not shared link. IKJ = ( "<< _i << " " << _j << " " << _k << " )" << endl + << "n1 (" << p1.X() << ", "<< p1.Y() << ", "<< p1.Z() << " )" << endl + << "n2 (" << p2.X() << ", "<< p2.Y() << ", "<< p2.Z() << " )" << endl; +#endif + return false; + } //================================================================================ /*! @@ -2964,9 +3379,12 @@ bool StdMeshers_Cartesian_3D::Compute(SMESH_Mesh & theMesh, _computeCanceled = false; + SMESH_MesherHelper helper( theMesh ); + try { Grid grid; + grid._helper = &helper; vector< TopoDS_Shape > faceVec; { @@ -2992,12 +3410,16 @@ bool StdMeshers_Cartesian_3D::Compute(SMESH_Mesh & theMesh, shapeBox.Add( facesItersectors[i].GetFaceBndBox() ); if ( _hyp->GetToAddEdges() ) + { + helper.SetSubShape( faceVec[i] ); for ( eExp.Init( faceVec[i], TopAbs_EDGE ); eExp.More(); eExp.Next() ) { const TopoDS_Edge& edge = TopoDS::Edge( eExp.Current() ); - if ( !SMESH_Algo::isDegenerated( edge )) + if ( !SMESH_Algo::isDegenerated( edge ) && + !helper.IsRealSeam( edge )) edge2faceIDsMap[ grid._shapes.Add( edge )].push_back( facesItersectors[i]._faceID ); } + } } getExactBndBox( faceVec, _hyp->GetAxisDirs(), shapeBox ); @@ -3037,7 +3459,6 @@ bool StdMeshers_Cartesian_3D::Compute(SMESH_Mesh & theMesh, for ( size_t i = 0; i < facesItersectors.size(); ++i ) facesItersectors[i].StoreIntersections(); - SMESH_MesherHelper helper( theMesh ); TopExp_Explorer solidExp (theShape, TopAbs_SOLID); helper.SetSubShape( solidExp.Current() ); helper.SetElementsOnShape( true );