-// Copyright (C) 2007-2014 CEA/DEN, EDF R&D, OPEN CASCADE
+// Copyright (C) 2007-2020 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
#include "SMDS_IteratorOnIterators.hxx"
#include "SMDS_SetIterator.hxx"
+#include "SMESHDS_Mesh.hxx"
+#include "SMESH_Mesh.hxx"
#include "SMESH_MesherHelper.hxx"
#include <TopTools_ListIteratorOfListOfShape.hxx>
#include <TopExp.hxx>
#include <TopTools_IndexedMapOfShape.hxx>
+#include <boost/container/flat_set.hpp>
+#include <boost/make_shared.hpp>
+
//================================================================================
/*!
* \brief Constructor; mesh must be set by a descendant class
*/
//================================================================================
-SMESH_ProxyMesh::SMESH_ProxyMesh():_mesh(0)
+SMESH_ProxyMesh::SMESH_ProxyMesh():_mesh(0), _subContainer(0)
+{
+}
+//================================================================================
+/*!
+ * \brief Constructor
+ */
+//================================================================================
+
+SMESH_ProxyMesh::SMESH_ProxyMesh(const SMESH_Mesh& mesh)
+ : _mesh( &mesh ),
+ _subContainer( new SubMesh( GetMeshDS() ) )
{
}
+
//================================================================================
/*!
* \brief Make a proxy mesh from components. Components become empty
*/
//================================================================================
-SMESH_ProxyMesh::SMESH_ProxyMesh(vector<SMESH_ProxyMesh::Ptr>& components):
+SMESH_ProxyMesh::SMESH_ProxyMesh(std::vector<SMESH_ProxyMesh::Ptr>& components):
_mesh(0)
{
if ( components.empty() ) return;
takeTmpElemsInMesh( m );
- if ( !_mesh ) _mesh = m->_mesh;
+ if ( !_mesh && m->_mesh ) setMesh( *( m->_mesh ));
if ( _allowedTypes.empty() ) _allowedTypes = m->_allowedTypes;
if ( _subMeshes.size() < m->_subMeshes.size() )
if ( _subMeshes[j] )
{
// unite 2 sub-meshes
- set< const SMDS_MeshElement * > elems( _subMeshes[j]->_elements.begin(),
- _subMeshes[j]->_elements.end());
+ std::set< const SMDS_MeshElement * > elems( _subMeshes[j]->_elements.begin(),
+ _subMeshes[j]->_elements.end());
elems.insert( m->_subMeshes[j]->_elements.begin(),
m->_subMeshes[j]->_elements.end());
_subMeshes[j]->_elements.assign( elems.begin(), elems.end() );
//================================================================================
/*!
- * \brief Destructor deletes proxy submeshes and tmp elemens
+ * \brief Destructor deletes proxy submeshes and tmp elements
*/
//================================================================================
SMESH_ProxyMesh::~SMESH_ProxyMesh()
{
- for ( unsigned i = 0; i < _subMeshes.size(); ++i )
+ delete _subContainer;
+
+ for ( size_t i = 0; i < _subMeshes.size(); ++i )
delete _subMeshes[i];
_subMeshes.clear();
- set< const SMDS_MeshElement* >::iterator i = _elemsInMesh.begin();
+ std::set< const SMDS_MeshElement* >::iterator i = _elemsInMesh.begin();
for ( ; i != _elemsInMesh.end(); ++i )
GetMeshDS()->RemoveFreeElement( *i, 0 );
_elemsInMesh.clear();
}
+//================================================================================
+/*!
+ * \brief Set mesh
+ */
+//================================================================================
+
+void SMESH_ProxyMesh::setMesh(const SMESH_Mesh& mesh)
+{
+ _mesh = &mesh;
+ if ( _mesh )
+ _subContainer = new SubMesh( GetMeshDS() );
+}
+
//================================================================================
/*!
* \brief Returns index of a shape
return ( shape.IsNull() || !_mesh->HasShapeToMesh() ? 0 : GetMeshDS()->ShapeToIndex(shape));
}
+//================================================================================
+/*!
+ * \brief Create a SubMesh
+ * \param [ino] index - shape index
+ * \return SubMesh* - new SubMesh
+ */
+//================================================================================
+
+SMESH_ProxyMesh::SubMesh* SMESH_ProxyMesh::newSubmesh(int index) const
+{
+ return new SubMesh( GetMeshDS(),index );
+}
+
//================================================================================
/*!
* \brief Returns the submesh of a shape; it can be a proxy sub-mesh
//================================================================================
const SMESHDS_SubMesh* SMESH_ProxyMesh::GetSubMesh(const TopoDS_Shape& shape) const
+{
+ return GetSubMesh( shapeIndex( shape ));
+}
+
+//================================================================================
+/*!
+ * \brief Return a sub-mesh by a shape ID; it can be a proxy sub-mesh
+ */
+//================================================================================
+
+const SMESHDS_SubMesh* SMESH_ProxyMesh::GetSubMesh(const int shapeID) const
{
const SMESHDS_SubMesh* sm = 0;
- int i = shapeIndex(shape);
- if ( i < _subMeshes.size() )
- sm = _subMeshes[i];
+ if ( 0 < shapeID && shapeID < (int)_subMeshes.size() )
+ sm = _subMeshes[ shapeID ];
if ( !sm )
- sm = GetMeshDS()->MeshElements( i );
+ sm = GetMeshDS()->MeshElements( shapeID );
return sm;
}
const SMESH_ProxyMesh::SubMesh*
SMESH_ProxyMesh::GetProxySubMesh(const TopoDS_Shape& shape) const
{
- int i = shapeIndex(shape);
+ size_t i = shapeIndex(shape);
return i < _subMeshes.size() ? _subMeshes[i] : 0;
}
class TFilteringIterator : public SMDS_ElemIterator
{
- SMDS_ElemIteratorPtr _iter;
- const SMDS_MeshElement * _curElem;
- vector< SMDSAbs_EntityType> _okTypes;
+ SMDS_ElemIteratorPtr _iter;
+ const SMDS_MeshElement * _curElem;
+ std::vector< SMDSAbs_EntityType> _okTypes;
public:
- TFilteringIterator( const vector< SMDSAbs_EntityType>& okTypes,
- const SMDS_ElemIteratorPtr& elemIterator)
+ TFilteringIterator( const std::vector< SMDSAbs_EntityType>& okTypes,
+ const SMDS_ElemIteratorPtr& elemIterator)
:_iter(elemIterator), _curElem(0), _okTypes(okTypes)
{
next();
return res;
}
};
+
+ //================================================================================
+ /*!
+ * \brief Iterator returning unique elements from a vector and another iterator
+ */
+ //================================================================================
+
+ class TUniqueIterator : public SMDS_ElemIterator
+ {
+ typedef boost::container::flat_set< const SMDS_MeshElement* > TElemSet;
+ typedef SMDS_SetIterator< const SMDS_MeshElement*, TElemSet::const_iterator > TSetIterator;
+
+ TElemSet _uniqueElems;
+ TSetIterator* _iterator;
+
+ public:
+ TUniqueIterator( const std::vector< const SMDS_MeshElement* >& elems,
+ const SMDS_ElemIteratorPtr& elemIterator )
+ : _uniqueElems( elems.begin(), elems.end() )
+ {
+ if ( elemIterator )
+ while ( elemIterator->more() )
+ _uniqueElems.insert( elemIterator->next() );
+
+ _iterator = new TSetIterator( _uniqueElems.begin(), _uniqueElems.end() );
+ }
+ ~TUniqueIterator()
+ {
+ delete _iterator;
+ }
+ virtual bool more()
+ {
+ return _iterator->more();
+ }
+ virtual const SMDS_MeshElement* next()
+ {
+ return _iterator->next();
+ }
+ };
+
+ //================================================================================
+ /*!
+ * \brief Return iterator on 2 element iterators
+ */
+ //================================================================================
+
+ SMDS_ElemIteratorPtr iteratorOn2Iterators( SMDS_ElemIteratorPtr it1, SMDS_ElemIteratorPtr it2 )
+ {
+ std::vector< SMDS_ElemIteratorPtr > iters; iters.reserve(2);
+ if ( it1 ) iters.push_back( it1 );
+ if ( it2 ) iters.push_back( it2 );
+
+ typedef std::vector< SMDS_ElemIteratorPtr > TElemIterVector;
+ typedef SMDS_IteratorOnIterators<const SMDS_MeshElement *, TElemIterVector> TItersIter;
+ return SMDS_ElemIteratorPtr( new TItersIter( iters ));
+ }
}
//================================================================================
if ( !_mesh->HasShapeToMesh() )
return SMDS_ElemIteratorPtr();
- _subContainer.RemoveAllSubmeshes();
+ _subContainer->RemoveAllSubmeshes();
TopTools_IndexedMapOfShape FF;
TopExp::MapShapes( shape, TopAbs_FACE, FF );
for ( int i = 1; i <= FF.Extent(); ++i )
if ( const SMESHDS_SubMesh* sm = GetSubMesh( FF(i)))
- _subContainer.AddSubMesh( sm );
+ _subContainer->AddSubMesh( sm );
- return _subContainer.SMESHDS_SubMesh::GetElements();
+ return _subContainer->SMESHDS_SubMesh::GetElements();
}
//================================================================================
if ( _mesh->HasShapeToMesh() )
return SMDS_ElemIteratorPtr();
- _subContainer.RemoveAllSubmeshes();
+ _subContainer->RemoveAllSubmeshes();
for ( unsigned i = 0; i < _subMeshes.size(); ++i )
if ( _subMeshes[i] )
- _subContainer.AddSubMesh( _subMeshes[i] );
+ _subContainer->AddSubMesh( _subMeshes[i] );
- if ( _subContainer.NbSubMeshes() == 0 ) // no elements substituted
+ if ( _subContainer->NbSubMeshes() == 0 ) // no elements substituted
return GetMeshDS()->elementsIterator(SMDSAbs_Face);
// if _allowedTypes is empty, only elements from _subMeshes are returned,...
- SMDS_ElemIteratorPtr proxyIter = _subContainer.SMESHDS_SubMesh::GetElements();
+ SMDS_ElemIteratorPtr proxyIter = _subContainer->SMESHDS_SubMesh::GetElements();
if ( _allowedTypes.empty() || NbFaces() == _mesh->NbFaces() )
return proxyIter;
// ... else elements filtered using allowedTypes are additionally returned
SMDS_ElemIteratorPtr facesIter = GetMeshDS()->elementsIterator(SMDSAbs_Face);
SMDS_ElemIteratorPtr filterIter( new TFilteringIterator( _allowedTypes, facesIter ));
- vector< SMDS_ElemIteratorPtr > iters(2);
- iters[0] = proxyIter;
- iters[1] = filterIter;
-
- typedef vector< SMDS_ElemIteratorPtr > TElemIterVector;
- typedef SMDS_IteratorOnIterators<const SMDS_MeshElement *, TElemIterVector> TItersIter;
- return SMDS_ElemIteratorPtr( new TItersIter( iters ));
+ return iteratorOn2Iterators( proxyIter, filterIter );
}
//================================================================================
{
if ( elem && elem->GetID() > 0 )
{
- set< const SMDS_MeshElement* >::iterator i = _elemsInMesh.find( elem );
+ std::set< const SMDS_MeshElement* >::iterator i = _elemsInMesh.find( elem );
if ( i != _elemsInMesh.end() )
{
+ std::vector< const SMDS_MeshNode* > nodes( elem->begin_nodes(), elem->end_nodes() );
+
GetMeshDS()->RemoveFreeElement( elem, 0 );
_elemsInMesh.erase( i );
+
+ for ( size_t i = 0; i < nodes.size(); ++i )
+ if ( nodes[i]->GetID() > 0 && nodes[i]->NbInverseElements() == 0 )
+ GetMeshDS()->RemoveFreeNode( nodes[i], 0, false );
}
}
else
SubMesh* sm = const_cast<SubMesh*>( subMesh );
if ( !subMesh->_n2n )
sm->_n2n = new TN2NMap;
- sm->_n2n->insert( make_pair( srcNode, proxyNode ));
+ sm->_n2n->insert( std::make_pair( srcNode, proxyNode ));
}
//================================================================================
return ( elem->GetID() < 1 ) || _elemsInMesh.count( elem );
}
+//================================================================================
+/*!
+ * \brief Return iterator on inverse elements of a node that may be a proxy one
+ */
+//================================================================================
+
+SMDS_ElemIteratorPtr SMESH_ProxyMesh::GetInverseElementIterator(const SMDS_MeshNode* node,
+ SMDSAbs_ElementType type) const
+{
+ typedef std::vector< const SMDS_MeshElement* > TElemVec;
+ TElemVec *elemVecPtr;
+
+ TNodeElemVecMap& inverseElements = const_cast< TNodeElemVecMap& >( _inverseElements );
+ if ( inverseElements.IsEmpty() && NbProxySubMeshes() > 0 )
+ {
+ TElemVec elemVec;
+ for ( size_t i = 0; i < _subMeshes.size(); ++i )
+ if ( _subMeshes[i] )
+ for ( size_t j = 0; j < _subMeshes[i]->_elements.size(); ++j )
+ {
+ const SMDS_MeshElement* e = _subMeshes[i]->_elements[j];
+ for ( SMDS_NodeIteratorPtr nIt = e->nodeIterator(); nIt->more(); )
+ {
+ const SMDS_MeshNode* n = nIt->next();
+ elemVecPtr = inverseElements.ChangeSeek( n );
+ if ( !elemVecPtr )
+ elemVecPtr = inverseElements.Bound( n, elemVec );
+ elemVecPtr->push_back( e );
+ }
+ }
+ }
+
+ SMDS_ElemIteratorPtr iter = node->GetInverseElementIterator( type );
+
+ if (( elemVecPtr = inverseElements.ChangeSeek( node )))
+ {
+ if ( iter->more() )
+ iter = boost::make_shared< TUniqueIterator >( *elemVecPtr, iter );
+ else
+ iter = boost::make_shared< SMDS_ElementVectorIterator> ( elemVecPtr->begin(),
+ elemVecPtr->end() );
+ }
+
+ return iter;
+}
+
+//================================================================================
+/*!
+ * \brief Check if a FACE has prisms on its both sides
+ * \param [in] smFace - sub-mesh of the FACE. NOT a proxy sub-mesh!
+ * \return bool - true if there are prisms on the two sides
+ */
+//================================================================================
+
+bool SMESH_ProxyMesh::HasPrismsOnTwoSides( SMESHDS_SubMesh* smFace )
+{
+ if ( !smFace || smFace->NbElements() == 0 )
+ return false;
+
+ SMDS_ElemIteratorPtr faces = smFace->GetElements();
+ while ( faces->more() )
+ {
+ const SMDS_MeshElement* f = faces->next();
+ std::vector<const SMDS_MeshNode*> fNodes( f->begin_nodes(), f->end_nodes() );
+ std::vector<const SMDS_MeshElement*> vols;
+ if ( SMDS_Mesh::GetElementsByNodes( fNodes, vols, SMDSAbs_Volume ) < 2 )
+ return false;
+ return ( vols[0]->NbCornerNodes() == 2 * f->NbCornerNodes() &&
+ vols[1]->NbCornerNodes() == 2 * f->NbCornerNodes() );
+ }
+ return false;
+}
+
+//================================================================================
+/*!
+ * \brief SubMesh Constructor
+ */
+//================================================================================
+
+SMESH_ProxyMesh::SubMesh::SubMesh( const SMDS_Mesh* mesh, int index )
+ : SMESHDS_SubMesh( static_cast<const SMESHDS_Mesh*>( mesh ), index ),
+ _n2n(0)
+{
+}
+
//================================================================================
/*!
* \brief Return a proxy node or an input node