-// Copyright (C) 2007-2016 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 "StdMeshers_ViscousLayers.hxx"
+#include "ObjectPool.hxx"
#include "SMDS_EdgePosition.hxx"
#include "SMDS_FaceOfNodes.hxx"
#include "SMDS_FacePosition.hxx"
#include "SMDS_MeshNode.hxx"
+#include "SMDS_PolygonalFaceOfNodes.hxx"
#include "SMDS_SetIterator.hxx"
#include "SMESHDS_Group.hxx"
#include "SMESHDS_Hypothesis.hxx"
#include "SMESHDS_Mesh.hxx"
#include "SMESH_Algo.hxx"
+#include "SMESH_Block.hxx"
#include "SMESH_ComputeError.hxx"
#include "SMESH_ControlsDef.hxx"
#include "SMESH_Gen.hxx"
#include "SMESH_HypoFilter.hxx"
#include "SMESH_Mesh.hxx"
#include "SMESH_MeshAlgos.hxx"
+#include "SMESH_MeshEditor.hxx"
#include "SMESH_MesherHelper.hxx"
#include "SMESH_ProxyMesh.hxx"
#include "SMESH_subMesh.hxx"
#include "SMESH_subMeshEventListener.hxx"
#include "StdMeshers_FaceSide.hxx"
+#include "StdMeshers_ProjectionUtils.hxx"
#include "StdMeshers_ViscousLayers2D.hxx"
#include <Adaptor3d_HSurface.hxx>
#include <list>
#include <queue>
#include <string>
+#include <unordered_map>
#ifdef _DEBUG_
-#define __myDEBUG
+//#define __myDEBUG
//#define __NOT_INVALIDATE_BAD_SMOOTH
//#define __NODES_AT_POS
#endif
virtual void ProcessEvent(const int event,
const int eventType,
SMESH_subMesh* subMesh,
- SMESH_subMeshEventListenerData* data,
- const SMESH_Hypothesis* hyp)
+ SMESH_subMeshEventListenerData* /*data*/,
+ const SMESH_Hypothesis* /*hyp*/)
{
if (( SMESH_subMesh::COMPUTE_EVENT == eventType ) &&
( SMESH_subMesh::CHECK_COMPUTE_STATE != event &&
double _h2lenRatio; // avgNormProj / (2*avgDist)
gp_Pnt2d _uv; // UV used in putOnOffsetSurface()
public:
- static _Curvature* New( double avgNormProj, double avgDist )
- {
- _Curvature* c = 0;
- if ( fabs( avgNormProj / avgDist ) > 1./200 )
- {
- c = new _Curvature;
- c->_r = avgDist * avgDist / avgNormProj;
- c->_k = avgDist * avgDist / c->_r / c->_r;
- //c->_k = avgNormProj / c->_r;
- c->_k *= ( c->_r < 0 ? 1/1.1 : 1.1 ); // not to be too restrictive
- c->_h2lenRatio = avgNormProj / ( avgDist + avgDist );
-
- c->_uv.SetCoord( 0., 0. );
- }
- return c;
- }
+ static _Curvature* New( double avgNormProj, double avgDist );
double lenDelta(double len) const { return _k * ( _r + len ); }
double lenDeltaByDist(double dist) const { return dist * _h2lenRatio; }
};
gp_XYZ* _plnNorm;
_2NearEdges() { _edges[0]=_edges[1]=0; _plnNorm = 0; }
+ ~_2NearEdges(){ delete _plnNorm; }
const SMDS_MeshNode* tgtNode(bool is2nd) {
return _edges[is2nd] ? _edges[is2nd]->_nodes.back() : 0;
}
_thickness = Max( _thickness, hyp->GetTotalThickness() );
_stretchFactor += hyp->GetStretchFactor();
_method = hyp->GetMethod();
+ if ( _groupName.empty() )
+ _groupName = hyp->GetGroupName();
}
}
double GetTotalThickness() const { return _thickness; /*_nbHyps ? _thickness / _nbHyps : 0;*/ }
double GetStretchFactor() const { return _nbHyps ? _stretchFactor / _nbHyps : 0; }
int GetNumberLayers() const { return _nbLayers; }
int GetMethod() const { return _method; }
+ bool ToCreateGroup() const { return !_groupName.empty(); }
+ const std::string& GetGroupName() const { return _groupName; }
bool UseSurfaceNormal() const
{ return _method == StdMeshers_ViscousLayers::SURF_OFFSET_SMOOTH; }
bool IsOffsetMethod() const
{ return _method == StdMeshers_ViscousLayers::FACE_OFFSET; }
+ bool operator==( const AverageHyp& other ) const
+ {
+ return ( _nbLayers == other._nbLayers &&
+ _method == other._method &&
+ Equals( GetTotalThickness(), other.GetTotalThickness() ) &&
+ Equals( GetStretchFactor(), other.GetStretchFactor() ));
+ }
+ static bool Equals( double v1, double v2 ) { return Abs( v1 - v2 ) < 0.01 * ( v1 + v2 ); }
+
private:
- int _nbLayers, _nbHyps, _method;
- double _thickness, _stretchFactor;
+ int _nbLayers, _nbHyps, _method;
+ double _thickness, _stretchFactor;
+ std::string _groupName;
};
//--------------------------------------------------------------------------------
vector< _EdgesOnShape* > _eosConcaVer; // edges at concave VERTEXes of a FACE
vector< _EdgesOnShape* > _eosC1; // to smooth together several C1 continues shapes
- vector< gp_XYZ > _faceNormals; // if _shape is FACE
+ typedef std::unordered_map< const SMDS_MeshElement*, gp_XYZ > TFace2NormMap;
+ TFace2NormMap _faceNormals; // if _shape is FACE
vector< _EdgesOnShape* > _faceEOS; // to get _faceNormals of adjacent FACEs
Handle(ShapeAnalysis_Surface) _offsetSurf;
_SolidData& GetData() const { return *_data; }
_EdgesOnShape(): _shapeID(-1), _subMesh(0), _toSmooth(false), _edgeSmoother(0) {}
+ ~_EdgesOnShape();
};
//--------------------------------------------------------------------------------
TopTools_MapOfShape _before; // SOLIDs to be computed before _solid
TGeomID _index; // SOLID id
_MeshOfSolid* _proxyMesh;
+ bool _done;
list< THyp > _hyps;
list< TopoDS_Shape > _hypShapes;
map< TGeomID, THyp > _face2hyp; // filled if _hyps.size() > 1
// _LayerEdge's with underlying shapes
vector< _EdgesOnShape > _edgesOnShape;
- // key: an id of shape (EDGE or VERTEX) shared by a FACE with
+ // key: an ID of shape (EDGE or VERTEX) shared by a FACE with
// layers and a FACE w/o layers
// value: the shape (FACE or EDGE) to shrink mesh on.
// _LayerEdge's basing on nodes on key shape are inflated along the value shape
// Convex FACEs whose radius of curvature is less than the thickness of layers
map< TGeomID, _ConvexFace > _convexFaces;
- // shapes (EDGEs and VERTEXes) srink from which is forbidden due to collisions with
+ // shapes (EDGEs and VERTEXes) shrink from which is forbidden due to collisions with
// the adjacent SOLID
set< TGeomID > _noShrinkShapes;
_SolidData(const TopoDS_Shape& s=TopoDS_Shape(),
_MeshOfSolid* m=0)
- :_solid(s), _proxyMesh(m), _helper(0) {}
- ~_SolidData();
+ :_solid(s), _proxyMesh(m), _done(false),_helper(0) {}
+ ~_SolidData() { delete _helper; _helper = 0; }
void SortOnEdge( const TopoDS_Edge& E, vector< _LayerEdge* >& edges);
void Sort2NeiborsOnEdge( vector< _LayerEdge* >& edges );
const double refSign );
};
struct PyDump;
+ struct Periodicity;
//--------------------------------------------------------------------------------
/*!
* \brief Builder of viscous layers
private:
- bool findSolidsWithLayers();
+ bool findSolidsWithLayers(const bool checkFaceMesh=true);
bool setBefore( _SolidData& solidBefore, _SolidData& solidAfter );
bool findFacesWithLayers(const bool onlyWith=false);
+ void findPeriodicFaces();
void getIgnoreFaces(const TopoDS_Shape& solid,
const StdMeshers_ViscousLayers* hyp,
const TopoDS_Shape& hypShape,
set<TGeomID>& ignoreFaces);
+ void makeEdgesOnShape();
bool makeLayer(_SolidData& data);
void setShapeData( _EdgesOnShape& eos, SMESH_subMesh* sm, _SolidData& data );
bool setEdgeData( _LayerEdge& edge, _EdgesOnShape& eos,
// debug
void makeGroupOfLE();
- SMESH_Mesh* _mesh;
- SMESH_ComputeErrorPtr _error;
+ SMESH_Mesh* _mesh;
+ SMESH_ComputeErrorPtr _error;
- vector< _SolidData > _sdVec;
- TopTools_IndexedMapOfShape _solids; // to find _SolidData by a solid
- TopTools_MapOfShape _shrinkedFaces;
+ vector< _SolidData > _sdVec;
+ TopTools_IndexedMapOfShape _solids; // to find _SolidData by a solid
+ TopTools_MapOfShape _shrunkFaces;
+ std::unique_ptr<Periodicity> _periodicity;
- int _tmpFaceID;
- PyDump* _pyDump;
+ int _tmpFaceID;
+ PyDump* _pyDump;
};
//--------------------------------------------------------------------------------
/*!
Handle(ShapeAnalysis_Surface)& surface,
const TopoDS_Face& F,
SMESH_MesherHelper& helper);
- bool smoothComplexEdge( _SolidData& data,
+ bool smoothComplexEdge( _SolidData& data,
Handle(ShapeAnalysis_Surface)& surface,
const TopoDS_Face& F,
SMESH_MesherHelper& helper);
/*!
* \brief Class of temporary mesh face.
* We can't use SMDS_FaceOfNodes since it's impossible to set it's ID which is
- * needed because SMESH_ElementSearcher internaly uses set of elements sorted by ID
+ * needed because SMESH_ElementSearcher internally uses set of elements sorted by ID
*/
- struct _TmpMeshFace : public SMDS_MeshElement
+ struct _TmpMeshFace : public SMDS_PolygonalFaceOfNodes
{
- vector<const SMDS_MeshNode* > _nn;
+ const SMDS_MeshElement* _srcFace;
+
_TmpMeshFace( const vector<const SMDS_MeshNode*>& nodes,
- int id, int faceID=-1, int idInFace=-1):
- SMDS_MeshElement(id), _nn(nodes) { setShapeId(faceID); setIdInShape(idInFace); }
- virtual const SMDS_MeshNode* GetNode(const int ind) const { return _nn[ind]; }
- virtual SMDSAbs_ElementType GetType() const { return SMDSAbs_Face; }
- virtual vtkIdType GetVtkType() const { return -1; }
- virtual SMDSAbs_EntityType GetEntityType() const { return SMDSEntity_Last; }
- virtual SMDSAbs_GeometryType GetGeomType() const
- { return _nn.size() == 3 ? SMDSGeom_TRIANGLE : SMDSGeom_QUADRANGLE; }
- virtual SMDS_ElemIteratorPtr elementsIterator(SMDSAbs_ElementType) const
- { return SMDS_ElemIteratorPtr( new SMDS_NodeVectorElemIterator( _nn.begin(), _nn.end()));}
+ int ID,
+ int faceID=-1,
+ const SMDS_MeshElement* srcFace=0 ):
+ SMDS_PolygonalFaceOfNodes(nodes), _srcFace( srcFace ) { setID( ID ); setShapeID( faceID ); }
+ virtual SMDSAbs_EntityType GetEntityType() const
+ { return _srcFace ? _srcFace->GetEntityType() : SMDSEntity_Quadrangle; }
+ virtual SMDSAbs_GeometryType GetGeomType() const
+ { return _srcFace ? _srcFace->GetGeomType() : SMDSGeom_QUADRANGLE; }
};
//--------------------------------------------------------------------------------
/*!
- * \brief Class of temporary mesh face storing _LayerEdge it's based on
+ * \brief Class of temporary mesh quadrangle face storing _LayerEdge it's based on
*/
struct _TmpMeshFaceOnEdge : public _TmpMeshFace
{
_TmpMeshFaceOnEdge( _LayerEdge* le1, _LayerEdge* le2, int ID ):
_TmpMeshFace( vector<const SMDS_MeshNode*>(4), ID ), _le1(le1), _le2(le2)
{
- _nn[0]=_le1->_nodes[0];
- _nn[1]=_le1->_nodes.back();
- _nn[2]=_le2->_nodes.back();
- _nn[3]=_le2->_nodes[0];
+ myNodes[0]=_le1->_nodes[0];
+ myNodes[1]=_le1->_nodes.back();
+ myNodes[2]=_le2->_nodes.back();
+ myNodes[3]=_le2->_nodes[0];
+ }
+ const SMDS_MeshNode* n( size_t i ) const
+ {
+ return myNodes[ i ];
}
gp_XYZ GetDir() const // return average direction of _LayerEdge's, normal to EDGE
{
- SMESH_TNodeXYZ p0s( _nn[0] );
- SMESH_TNodeXYZ p0t( _nn[1] );
- SMESH_TNodeXYZ p1t( _nn[2] );
- SMESH_TNodeXYZ p1s( _nn[3] );
+ SMESH_TNodeXYZ p0s( myNodes[0] );
+ SMESH_TNodeXYZ p0t( myNodes[1] );
+ SMESH_TNodeXYZ p1t( myNodes[2] );
+ SMESH_TNodeXYZ p1s( myNodes[3] );
gp_XYZ v0 = p0t - p0s;
gp_XYZ v1 = p1t - p1s;
gp_XYZ v01 = p1s - p0s;
}
gp_XYZ GetDir(_LayerEdge* le1, _LayerEdge* le2) // return average direction of _LayerEdge's
{
- _nn[0]=le1->_nodes[0];
- _nn[1]=le1->_nodes.back();
- _nn[2]=le2->_nodes.back();
- _nn[3]=le2->_nodes[0];
+ myNodes[0]=le1->_nodes[0];
+ myNodes[1]=le1->_nodes.back();
+ myNodes[2]=le2->_nodes.back();
+ myNodes[3]=le2->_nodes[0];
return GetDir();
}
};
( dot * dot ) / l1 / l2 >= ( cos * cos ));
}
+ class _Factory
+ {
+ ObjectPool< _LayerEdge > _edgePool;
+ ObjectPool< _Curvature > _curvaturePool;
+ ObjectPool< _2NearEdges > _nearEdgesPool;
+
+ static _Factory* & me()
+ {
+ static _Factory* theFactory = 0;
+ return theFactory;
+ }
+ public:
+
+ _Factory() { me() = this; }
+ ~_Factory() { me() = 0; }
+
+ static _LayerEdge* NewLayerEdge() { return me()->_edgePool.getNew(); }
+ static _Curvature * NewCurvature() { return me()->_curvaturePool.getNew(); }
+ static _2NearEdges* NewNearEdges() { return me()->_nearEdgesPool.getNew(); }
+ };
+
} // namespace VISCOUS_3D
//================================================================================
// StdMeshers_ViscousLayers hypothesis
//
-StdMeshers_ViscousLayers::StdMeshers_ViscousLayers(int hypId, int studyId, SMESH_Gen* gen)
- :SMESH_Hypothesis(hypId, studyId, gen),
+StdMeshers_ViscousLayers::StdMeshers_ViscousLayers(int hypId, SMESH_Gen* gen)
+ :SMESH_Hypothesis(hypId, gen),
_isToIgnoreShapes(1), _nbLayers(1), _thickness(1), _stretchFactor(1),
- _method( SURF_OFFSET_SMOOTH )
+ _method( SURF_OFFSET_SMOOTH ),
+ _groupName("")
{
_name = StdMeshers_ViscousLayers::GetHypType();
_param_algo_dim = -3; // auxiliary hyp used by 3D algos
if ( _method != method )
_method = method, NotifySubMeshesHypothesisModification();
} // --------------------------------------------------------------------------------
+void StdMeshers_ViscousLayers::SetGroupName(const std::string& name)
+{
+ if ( _groupName != name )
+ {
+ _groupName = name;
+ if ( !_groupName.empty() )
+ NotifySubMeshesHypothesisModification();
+ }
+} // --------------------------------------------------------------------------------
SMESH_ProxyMesh::Ptr
StdMeshers_ViscousLayers::Compute(SMESH_Mesh& theMesh,
const TopoDS_Shape& theShape,
save << " " << _shapeIds[i];
save << " " << !_isToIgnoreShapes; // negate to keep the behavior in old studies.
save << " " << _method;
+ save << " " << _groupName.size();
+ if ( !_groupName.empty() )
+ save << " " << _groupName;
return save;
} // --------------------------------------------------------------------------------
std::istream & StdMeshers_ViscousLayers::LoadFrom(std::istream & load)
_isToIgnoreShapes = !shapeToTreat;
if ( load >> method )
_method = (ExtrusionMethod) method;
+ int nameSize = 0;
+ if ( load >> nameSize && nameSize > 0 )
+ {
+ _groupName.resize( nameSize );
+ load.get( _groupName[0] ); // remove a white-space
+ load.getline( &_groupName[0], nameSize + 1 );
+ }
}
else {
_isToIgnoreShapes = true; // old behavior
}
return load;
} // --------------------------------------------------------------------------------
-bool StdMeshers_ViscousLayers::SetParametersByMesh(const SMESH_Mesh* theMesh,
- const TopoDS_Shape& theShape)
+bool StdMeshers_ViscousLayers::SetParametersByMesh(const SMESH_Mesh* /*theMesh*/,
+ const TopoDS_Shape& /*theShape*/)
{
// TODO
return false;
( std::find( _shapeIds.begin(), _shapeIds.end(), shapeIndex ) != _shapeIds.end() );
return IsToIgnoreShapes() ? !isIn : isIn;
}
+
+// --------------------------------------------------------------------------------
+SMDS_MeshGroup* StdMeshers_ViscousLayers::CreateGroup( const std::string& theName,
+ SMESH_Mesh& theMesh,
+ SMDSAbs_ElementType theType)
+{
+ SMESH_Group* group = 0;
+ SMDS_MeshGroup* groupDS = 0;
+
+ if ( theName.empty() )
+ return groupDS;
+
+ if ( SMESH_Mesh::GroupIteratorPtr grIt = theMesh.GetGroups() )
+ while( grIt->more() && !group )
+ {
+ group = grIt->next();
+ if ( !group ||
+ group->GetGroupDS()->GetType() != theType ||
+ group->GetName() != theName ||
+ !dynamic_cast< SMESHDS_Group* >( group->GetGroupDS() ))
+ group = 0;
+ }
+ if ( !group )
+ group = theMesh.AddGroup( theType, theName.c_str() );
+
+ groupDS = & dynamic_cast< SMESHDS_Group* >( group->GetGroupDS() )->SMDSGroup();
+
+ return groupDS;
+}
+
// END StdMeshers_ViscousLayers hypothesis
//================================================================================
//================================================================================
/*!
- * \brief Computes mimimal distance of face in-FACE nodes from an EDGE
+ * \brief Computes minimal distance of face in-FACE nodes from an EDGE
* \param [in] face - the mesh face to treat
* \param [in] nodeOnEdge - a node on the EDGE
* \param [out] faceSize - the computed distance
PyDump(SMESH_Mesh& m) {
int tag = 3 + m.GetId();
const char* fname = "/tmp/viscous.py";
- cout << "execfile('"<<fname<<"')"<<endl;
+ cout << "exec(open('"<<fname<<"','rb').read() )"<<endl;
py = _pyStream = new ofstream(fname);
*py << "import SMESH" << endl
<< "from salome.smesh import smeshBuilder" << endl
- << "smesh = smeshBuilder.New(salome.myStudy)" << endl
- << "meshSO = smesh.GetCurrentStudy().FindObjectID('0:1:2:" << tag <<"')" << endl
+ << "smesh = smeshBuilder.New()" << endl
+ << "meshSO = salome.myStudy.FindObjectID('0:1:2:" << tag <<"')" << endl
<< "mesh = smesh.Mesh( meshSO.GetObject() )"<<endl;
theNbPyFunc = 0;
}
{
_mesh = & theMesh;
+ _Factory factory;
+
// check if proxy mesh already computed
TopExp_Explorer exp( theShape, TopAbs_SOLID );
if ( !exp.More() )
PyDump debugDump( theMesh );
_pyDump = &debugDump;
- // TODO: ignore already computed SOLIDs
+ // TODO: ignore already computed SOLIDs
if ( !findSolidsWithLayers())
return _error;
if ( !findFacesWithLayers() )
return _error;
+ // for ( size_t i = 0; i < _sdVec.size(); ++i )
+ // {
+ // if ( ! makeLayer( _sdVec[ i ])) // create _LayerEdge's
+ // return _error;
+ // }
+
+ makeEdgesOnShape();
+
+ findPeriodicFaces();
+
for ( size_t i = 0; i < _sdVec.size(); ++i )
{
size_t iSD = 0;
for ( iSD = 0; iSD < _sdVec.size(); ++iSD ) // find next SOLID to compute
if ( _sdVec[iSD]._before.IsEmpty() &&
!_sdVec[iSD]._solid.IsNull() &&
- _sdVec[iSD]._n2eMap.empty() )
+ !_sdVec[iSD]._done )
break;
if ( ! makeLayer(_sdVec[iSD]) ) // create _LayerEdge's
addBoundaryElements(_sdVec[iSD]); // create quadrangles on prism bare sides
+ _sdVec[iSD]._done = true;
+
const TopoDS_Shape& solid = _sdVec[iSD]._solid;
for ( iSD = 0; iSD < _sdVec.size(); ++iSD )
_sdVec[iSD]._before.Remove( solid );
return SMESH_ComputeErrorPtr(); // everything already computed
- findSolidsWithLayers();
+ findSolidsWithLayers( /*checkFaceMesh=*/false );
bool ok = findFacesWithLayers( true );
// remove _MeshOfSolid's of _SolidData's
*/
//================================================================================
-bool _ViscousBuilder::findSolidsWithLayers()
+bool _ViscousBuilder::findSolidsWithLayers(const bool checkFaceMesh)
{
// get all solids
TopTools_IndexedMapOfShape allSolids;
SMESH_HypoFilter filter;
for ( int i = 1; i <= allSolids.Extent(); ++i )
{
- // find StdMeshers_ViscousLayers hyp assigned to the i-th solid
SMESH_subMesh* sm = _mesh->GetSubMesh( allSolids(i) );
if ( sm->GetSubMeshDS() && sm->GetSubMeshDS()->NbElements() > 0 )
continue; // solid is already meshed
+ // TODO: check if algo is hidden
SMESH_Algo* algo = sm->GetAlgo();
if ( !algo ) continue;
- // TODO: check if algo is hidden
+ // check if all FACEs are meshed, which can be false if Compute() a sub-shape
+ if ( checkFaceMesh )
+ {
+ bool facesMeshed = true;
+ SMESH_subMeshIteratorPtr smIt = sm->getDependsOnIterator(false,true);
+ while ( smIt->more() && facesMeshed )
+ {
+ SMESH_subMesh * faceSM = smIt->next();
+ if ( faceSM->GetSubShape().ShapeType() != TopAbs_FACE )
+ break;
+ facesMeshed = faceSM->IsMeshComputed();
+ }
+ if ( !facesMeshed )
+ continue;
+ }
+ // find StdMeshers_ViscousLayers hyp assigned to the i-th solid
const list <const SMESHDS_Hypothesis *> & allHyps =
algo->GetUsedHypothesis(*_mesh, allSolids(i), /*ignoreAuxiliary=*/false);
_SolidData* soData = 0;
for ( ; exp.More(); exp.Next() )
{
const TopoDS_Face& face = TopoDS::Face( exp.Current() );
- const TGeomID faceID = getMeshDS()->ShapeToIndex( face );
+ const TGeomID faceID = getMeshDS()->ShapeToIndex( face );
if ( //!sdVec[i]._ignoreFaceIds.count( faceID ) &&
helper.NbAncestors( face, *_mesh, TopAbs_SOLID ) > 1 &&
helper.IsReversedSubMesh( face ))
ignore[j] = _sdVec[i]._ignoreFaceIds.count( getMeshDS()->ShapeToIndex( FF[j] ));
if ( ignore[0] == ignore[1] )
continue; // nothing interesting
- TopoDS_Shape fWOL = FF[ ignore[0] ? 0 : 1 ];
+ TopoDS_Shape fWOL = FF[ ignore[0] ? 0 : 1 ]; // FACE w/o layers
// add EDGE to maps
if ( !fWOL.IsNull())
}
}
- // Add to _noShrinkShapes sub-shapes of FACE's that can't be shrinked since
+ // Add to _noShrinkShapes sub-shapes of FACE's that can't be shrunk since
// the algo of the SOLID sharing the FACE does not support it or for other reasons
set< string > notSupportAlgos; notSupportAlgos.insert( structAlgoName );
for ( size_t i = 0; i < _sdVec.size(); ++i )
bool _ViscousBuilder::makeLayer(_SolidData& data)
{
- // get all sub-shapes to make layers on
- set<TGeomID> subIds, faceIds;
- subIds = data._noShrinkShapes;
- TopExp_Explorer exp( data._solid, TopAbs_FACE );
- for ( ; exp.More(); exp.Next() )
- {
- SMESH_subMesh* fSubM = _mesh->GetSubMesh( exp.Current() );
- if ( ! data._ignoreFaceIds.count( fSubM->GetId() ))
- faceIds.insert( fSubM->GetId() );
- }
-
// make a map to find new nodes on sub-shapes shared with other SOLID
map< TGeomID, TNode2Edge* >::iterator s2ne;
map< TGeomID, TopoDS_Shape >::iterator s2s = data._shrinkShape2Shape.begin();
dumpFunction(SMESH_Comment("makeLayers_")<<data._index);
+ vector< _EdgesOnShape >& edgesByGeom = data._edgesOnShape;
+
data._stepSize = Precision::Infinite();
data._stepSizeNodes[0] = 0;
vector< const SMDS_MeshNode*> newNodes; // of a mesh face
TNode2Edge::iterator n2e2;
- // collect _LayerEdge's of shapes they are based on
- vector< _EdgesOnShape >& edgesByGeom = data._edgesOnShape;
- const int nbShapes = getMeshDS()->MaxShapeIndex();
- edgesByGeom.resize( nbShapes+1 );
-
- // set data of _EdgesOnShape's
- if ( SMESH_subMesh* sm = _mesh->GetSubMesh( data._solid ))
- {
- SMESH_subMeshIteratorPtr smIt = sm->getDependsOnIterator(/*includeSelf=*/false);
- while ( smIt->more() )
- {
- sm = smIt->next();
- if ( sm->GetSubShape().ShapeType() == TopAbs_FACE &&
- !faceIds.count( sm->GetId() ))
- continue;
- setShapeData( edgesByGeom[ sm->GetId() ], sm, data );
- }
- }
// make _LayerEdge's
- for ( set<TGeomID>::iterator id = faceIds.begin(); id != faceIds.end(); ++id )
+ for ( TopExp_Explorer exp( data._solid, TopAbs_FACE ); exp.More(); exp.Next() )
{
- const TopoDS_Face& F = TopoDS::Face( getMeshDS()->IndexToShape( *id ));
- SMESH_subMesh* sm = _mesh->GetSubMesh( F );
+ const TopoDS_Face& F = TopoDS::Face( exp.Current() );
+ SMESH_subMesh* sm = _mesh->GetSubMesh( F );
+ const TGeomID id = sm->GetId();
+ if ( edgesByGeom[ id ]._shape.IsNull() )
+ continue; // no layers
SMESH_ProxyMesh::SubMesh* proxySub =
data._proxyMesh->getFaceSubM( F, /*create=*/true);
SMESHDS_SubMesh* smDS = sm->GetSubMeshDS();
- if ( !smDS ) return error(SMESH_Comment("Not meshed face ") << *id, data._index );
+ if ( !smDS ) return error(SMESH_Comment("Not meshed face ") << id, data._index );
SMDS_ElemIteratorPtr eIt = smDS->GetElements();
while ( eIt->more() )
if ( !(*n2e).second )
{
// add a _LayerEdge
- _LayerEdge* edge = new _LayerEdge();
+ _LayerEdge* edge = _Factory::NewLayerEdge();
edge->_nodes.push_back( n );
n2e->second = edge;
edgesByGeom[ shapeID ]._edges.push_back( edge );
// create a temporary face
const SMDS_MeshElement* newFace =
- new _TmpMeshFace( newNodes, --_tmpFaceID, face->getshapeId(), face->getIdInShape() );
+ new _TmpMeshFace( newNodes, --_tmpFaceID, face->GetShapeID(), face );
proxySub->AddElement( newFace );
// compute inflation step size by min size of element on a convex surface
}
- // Fill _eosC1 to make that C1 FACEs and EGDEs between them to be smoothed as a whole
+ // Fill _eosC1 to make that C1 FACEs and EDGEs between them to be smoothed as a whole
TopTools_MapOfShape c1VV;
if ( isC1 )
{
double maxEdgeLen = 3 * Min( eov._edges[0]->_maxLen, eov._hyp.GetTotalThickness() );
- double eLen1 = SMESH_Algo::EdgeLength( TopoDS::Edge( dirOfEdges[i].first->_shape ));
- double eLen2 = SMESH_Algo::EdgeLength( TopoDS::Edge( dirOfEdges[j].first->_shape ));
- if ( eLen1 < maxEdgeLen ) eov._eosC1.push_back( dirOfEdges[i].first );
- if ( eLen2 < maxEdgeLen ) eov._eosC1.push_back( dirOfEdges[j].first );
- dirOfEdges[i].first = 0;
- dirOfEdges[j].first = 0;
+ for ( int isJ = 0; isJ < 2; ++isJ ) // loop on [i,j]
+ {
+ size_t k = isJ ? j : i;
+ const TopoDS_Edge& e = TopoDS::Edge( dirOfEdges[k].first->_shape );
+ double eLen = SMESH_Algo::EdgeLength( e );
+ if ( eLen < maxEdgeLen )
+ {
+ TopoDS_Shape oppV = SMESH_MesherHelper::IthVertex( 0, e );
+ if ( oppV.IsSame( V ))
+ oppV = SMESH_MesherHelper::IthVertex( 1, e );
+ _EdgesOnShape* eovOpp = data.GetShapeEdges( oppV );
+ if ( dirOfEdges[k].second * eovOpp->_edges[0]->_normal < 0 )
+ eov._eosC1.push_back( dirOfEdges[k].first );
+ }
+ dirOfEdges[k].first = 0;
+ }
}
}
} // fill _eosC1 of VERTEXes
return ok;
}
+//================================================================================
+/*!
+ * \brief Set up _SolidData::_edgesOnShape
+ */
+//================================================================================
+
+void _ViscousBuilder::makeEdgesOnShape()
+{
+ const int nbShapes = getMeshDS()->MaxShapeIndex();
+
+ for ( size_t i = 0; i < _sdVec.size(); ++i )
+ {
+ _SolidData& data = _sdVec[ i ];
+ vector< _EdgesOnShape >& edgesByGeom = data._edgesOnShape;
+ edgesByGeom.resize( nbShapes+1 );
+
+ // set data of _EdgesOnShape's
+ if ( SMESH_subMesh* sm = _mesh->GetSubMesh( data._solid ))
+ {
+ SMESH_subMeshIteratorPtr smIt = sm->getDependsOnIterator(/*includeSelf=*/false);
+ while ( smIt->more() )
+ {
+ sm = smIt->next();
+ if ( sm->GetSubShape().ShapeType() == TopAbs_FACE &&
+ data._ignoreFaceIds.count( sm->GetId() ))
+ continue;
+
+ setShapeData( edgesByGeom[ sm->GetId() ], sm, data );
+ }
+ }
+ }
+}
+
//================================================================================
/*!
* \brief initialize data of _EdgesOnShape
{
SMESHDS_SubMesh* smDS = sm->GetSubMeshDS();
if ( !smDS ) return;
- eos._faceNormals.resize( smDS->NbElements() );
+ eos._faceNormals.reserve( smDS->NbElements() );
+ double oriFactor = helper.IsReversedSubMesh( TopoDS::Face( eos._shape )) ? 1.: -1.;
SMDS_ElemIteratorPtr eIt = smDS->GetElements();
- for ( int iF = 0; eIt->more(); ++iF )
+ for ( ; eIt->more(); )
{
const SMDS_MeshElement* face = eIt->next();
- if ( !SMESH_MeshAlgos::FaceNormal( face, eos._faceNormals[iF], /*normalized=*/true ))
- eos._faceNormals[iF].SetCoord( 0,0,0 );
+ gp_XYZ& norm = eos._faceNormals[face];
+ if ( !SMESH_MeshAlgos::FaceNormal( face, norm, /*normalized=*/true ))
+ norm.SetCoord( 0,0,0 );
+ norm *= oriFactor;
}
-
- if ( !helper.IsReversedSubMesh( TopoDS::Face( eos._shape )))
- for ( size_t iF = 0; iF < eos._faceNormals.size(); ++iF )
- eos._faceNormals[iF].Reverse();
}
else // find EOS of adjacent FACEs
{
bool _EdgesOnShape::GetNormal( const SMDS_MeshElement* face, gp_Vec& norm )
{
bool ok = false;
- const _EdgesOnShape* eos = 0;
+ _EdgesOnShape* eos = 0;
if ( face->getshapeId() == _shapeID )
{
}
if (( eos ) &&
- ( ok = ( face->getIdInShape() < (int) eos->_faceNormals.size() )))
+ ( ok = ( eos->_faceNormals.count( face ) )))
{
- norm = eos->_faceNormals[ face->getIdInShape() ];
+ norm = eos->_faceNormals[ face ];
}
else if ( !eos )
{
return ok;
}
+//================================================================================
+/*!
+ * \brief EdgesOnShape destructor
+ */
+//================================================================================
+
+_EdgesOnShape::~_EdgesOnShape()
+{
+ delete _edgeSmoother;
+}
//================================================================================
/*!
{
const SMDS_MeshNode* node = edge._nodes[0]; // source node
- edge._len = 0;
- edge._maxLen = Precision::Infinite();
- edge._minAngle = 0;
- edge._2neibors = 0;
- edge._curvature = 0;
- edge._flags = 0;
+ edge._len = 0;
+ edge._maxLen = Precision::Infinite();
+ edge._minAngle = 0;
+ edge._2neibors = 0;
+ edge._curvature = 0;
+ edge._flags = 0;
+ edge._smooFunction = 0;
// --------------------------
// Compute _normal and _cosin
{
const SMDS_MeshNode* tgtNode = edge._nodes.back();
if ( SMESHDS_SubMesh* sm = getMeshDS()->MeshElements( data._solid ))
- sm->RemoveNode( tgtNode , /*isNodeDeleted=*/false );
+ sm->RemoveNode( tgtNode );
// set initial position which is parameters on _sWOL in this case
if ( eos.SWOLType() == TopAbs_EDGE )
if ( eos.ShapeType() == TopAbs_EDGE /*||
( onShrinkShape && posType == SMDS_TOP_VERTEX && fabs( edge._cosin ) < 1e-10 )*/)
{
- edge._2neibors = new _2NearEdges;
+ edge._2neibors = _Factory::NewNearEdges();
// target nodes instead of source ones will be set later
}
bool _ViscousBuilder::getFaceNormalAtSingularity( const gp_XY& uv,
const TopoDS_Face& face,
- SMESH_MesherHelper& helper,
+ SMESH_MesherHelper& /*helper*/,
gp_Dir& normal )
{
BRepAdaptor_Surface surface( face );
//================================================================================
/*!
- * \brief Find 2 neigbor nodes of a node on EDGE
+ * \brief Find 2 neighbor nodes of a node on EDGE
*/
//================================================================================
//================================================================================
/*!
- * \brief Set _curvature and _2neibors->_plnNorm by 2 neigbor nodes residing the same EDGE
+ * \brief Create _Curvature
+ */
+//================================================================================
+
+_Curvature* _Curvature::New( double avgNormProj, double avgDist )
+{
+ // double _r; // radius
+ // double _k; // factor to correct node smoothed position
+ // double _h2lenRatio; // avgNormProj / (2*avgDist)
+ // gp_Pnt2d _uv; // UV used in putOnOffsetSurface()
+
+ _Curvature* c = 0;
+ if ( fabs( avgNormProj / avgDist ) > 1./200 )
+ {
+ c = _Factory::NewCurvature();
+ c->_r = avgDist * avgDist / avgNormProj;
+ c->_k = avgDist * avgDist / c->_r / c->_r;
+ //c->_k = avgNormProj / c->_r;
+ c->_k *= ( c->_r < 0 ? 1/1.1 : 1.1 ); // not to be too restrictive
+ c->_h2lenRatio = avgNormProj / ( avgDist + avgDist );
+
+ c->_uv.SetCoord( 0., 0. );
+ }
+ return c;
+}
+
+//================================================================================
+/*!
+ * \brief Set _curvature and _2neibors->_plnNorm by 2 neighbor nodes residing the same EDGE
*/
//================================================================================
_2neibors->_wgt[1] = 1 - vec2.Modulus() / sumLen;
double avgNormProj = 0.5 * ( _normal * vec1 + _normal * vec2 );
double avgLen = 0.5 * ( vec1.Modulus() + vec2.Modulus() );
- if ( _curvature ) delete _curvature;
_curvature = _Curvature::New( avgNormProj, avgLen );
// if ( _curvature )
// debugMsg( _nodes[0]->GetID()
_lenFactor = other._lenFactor;
_cosin = other._cosin;
_2neibors = other._2neibors;
- _curvature = 0; std::swap( _curvature, other._curvature );
- _2neibors = 0; std::swap( _2neibors, other._2neibors );
+ _curvature = other._curvature;
+ _2neibors = other._2neibors;
+ _maxLen = Precision::Infinite();//other._maxLen;
+ _flags = 0;
+ _smooFunction = 0;
gp_XYZ lastPos( 0,0,0 );
if ( eos.SWOLType() == TopAbs_EDGE )
//================================================================================
/*!
- * \brief DEBUG. Create groups contating temorary data of _LayerEdge's
+ * \brief DEBUG. Create groups containing temporary data of _LayerEdge's
*/
//================================================================================
if ( nbBad == oldBadNb &&
nbBad > 0 &&
- step < stepLimit ) // smooth w/o chech of validity
+ step < stepLimit ) // smooth w/o check of validity
{
dumpFunctionEnd();
dumpFunction(SMESH_Comment("smoothWoCheck")<<data._index<<"_Fa"<<sInd
eos._edges[i]->Set( _LayerEdge::INTERSECTED ); // not to intersect
eos._edges[i]->Block( data ); // not to inflate
- if ( _EdgesOnShape* eof = data.GetShapeEdges( intFace->getshapeId() ))
+ //if ( _EdgesOnShape* eof = data.GetShapeEdges( intFace->getshapeId() ))
{
// block _LayerEdge's, on top of which intFace is
if ( const _TmpMeshFace* f = dynamic_cast< const _TmpMeshFace*>( intFace ))
{
- const SMDS_MeshElement* srcFace =
- eof->_subMesh->GetSubMeshDS()->GetElement( f->getIdInShape() );
- SMDS_ElemIteratorPtr nIt = srcFace->nodesIterator();
+ const SMDS_MeshElement* srcFace = f->_srcFace;
+ SMDS_ElemIteratorPtr nIt = srcFace->nodesIterator();
while ( nIt->more() )
{
const SMDS_MeshNode* srcNode = static_cast<const SMDS_MeshNode*>( nIt->next() );
} // loop on data._edgesOnShape
if ( !is1stBlocked )
+ {
dumpFunctionEnd();
+ }
if ( closestFace && le )
{
eos._offsetSurf = new ShapeAnalysis_Surface( surf );
}
- catch ( Standard_Failure )
+ catch ( Standard_Failure& )
{
}
}
<< "_InfStep" << infStep << "_" << smooStep );
for ( ; i < eos._edges.size(); ++i )
{
- if ( eos._edges[i]->Is( _LayerEdge::MARKED ))
+ if ( eos._edges[i]->Is( _LayerEdge::MARKED )) {
dumpMove( eos._edges[i]->_nodes.back() );
+ }
}
dumpFunctionEnd();
}
tgtNode->setXYZ( newPos.X(), newPos.Y(), newPos.Z() );
dumpMove( tgtNode );
- SMDS_FacePosition* pos = static_cast<SMDS_FacePosition*>( tgtNode->GetPosition() );
+ SMDS_FacePositionPtr pos = tgtNode->GetPosition();
pos->SetUParameter( newUV.X() );
pos->SetVParameter( newUV.Y() );
tgtNode->setXYZ( newPos.X(), newPos.Y(), newPos.Z() );
dumpMove( tgtNode );
- SMDS_FacePosition* pos = static_cast<SMDS_FacePosition*>( tgtNode->GetPosition() );
+ SMDS_FacePositionPtr pos = tgtNode->GetPosition();
pos->SetUParameter( newUV.X() );
pos->SetVParameter( newUV.Y() );
*/
//================================================================================
-bool _Smoother1D::smoothComplexEdge( _SolidData& data,
+bool _Smoother1D::smoothComplexEdge( _SolidData& /*data*/,
Handle(ShapeAnalysis_Surface)& surface,
const TopoDS_Face& F,
- SMESH_MesherHelper& helper)
+ SMESH_MesherHelper& /*helper*/)
{
if ( _offPoints.empty() )
return false;
void _Smoother1D::offPointsToPython() const
{
const char* fname = "/tmp/offPoints.py";
- cout << "execfile('"<<fname<<"')"<<endl;
+ cout << "exec(open('"<<fname<<"','rb').read() )"<<endl;
ofstream py(fname);
py << "import SMESH" << endl
<< "from salome.smesh import smeshBuilder" << endl
{
edge->Set( _LayerEdge::SMOOTHED_C1 );
isCurved = true;
- SMDS_FacePosition* fPos = dynamic_cast<SMDS_FacePosition*>( edge->_nodes[0]->GetPosition() );
+ SMDS_FacePositionPtr fPos = edge->_nodes[0]->GetPosition();
if ( !fPos )
for ( size_t iS = 0; iS < edge->_simplices.size() && !fPos; ++iS )
- fPos = dynamic_cast<SMDS_FacePosition*>( edge->_simplices[iS]._nPrev->GetPosition() );
+ fPos = edge->_simplices[iS]._nPrev->GetPosition();
if ( fPos )
edge->_curvature->_uv.SetCoord( fPos->GetUParameter(), fPos->GetVParameter() );
}
*/
//================================================================================
-void _ViscousBuilder::limitMaxLenByCurvature( _SolidData& data, SMESH_MesherHelper& helper )
+void _ViscousBuilder::limitMaxLenByCurvature( _SolidData& data, SMESH_MesherHelper& /*helper*/ )
{
// find intersection of neighbor _LayerEdge's to limit _maxLen
// according to local curvature (IPAL52648)
void _ViscousBuilder::limitMaxLenByCurvature( _LayerEdge* e1,
_LayerEdge* e2,
- _EdgesOnShape& eos1,
- _EdgesOnShape& eos2,
- const bool isSmoothable )
+ _EdgesOnShape& /*eos1*/,
+ _EdgesOnShape& /*eos2*/,
+ const bool /*isSmoothable*/ )
{
if (( e1->_nodes[0]->GetPosition()->GetDim() !=
e2->_nodes[0]->GetPosition()->GetDim() ) &&
_EdgesOnShape& eos = data._edgesOnShape[iS];
if ( eos._edges.empty() ) continue;
if ( eos.ShapeType() != TopAbs_EDGE && eos.ShapeType() != TopAbs_VERTEX ) continue;
+ if ( !eos._sWOL.IsNull() ) continue; // PAL23566
for ( size_t i = 0; i < eos._edges.size(); ++i )
{
src2->GetID() < edge->_nodes[0]->GetID() )
continue; // avoid using same segment twice
- // a _LayerEdge containg tgt2
+ // a _LayerEdge containing tgt2
_LayerEdge* neiborEdge = edge->_2neibors->_edges[j];
_TmpMeshFaceOnEdge* f = new _TmpMeshFaceOnEdge( edge, neiborEdge, --_tmpFaceID );
( f->_le2->IsOnEdge() && f->_le2->_2neibors->include( edge ))) continue;
}
dist1 = dist2 = Precision::Infinite();
- if ( !edge->SegTriaInter( lastSegment, f->_nn[0], f->_nn[1], f->_nn[2], dist1, eps ))
+ if ( !edge->SegTriaInter( lastSegment, f->n(0), f->n(1), f->n(2), dist1, eps ))
dist1 = Precision::Infinite();
- if ( !edge->SegTriaInter( lastSegment, f->_nn[3], f->_nn[2], f->_nn[0], dist2, eps ))
+ if ( !edge->SegTriaInter( lastSegment, f->n(3), f->n(2), f->n(0), dist2, eps ))
dist2 = Precision::Infinite();
if (( dist1 > segLen ) && ( dist2 > segLen ))
continue;
if ( edge->IsOnEdge() )
{
// skip perpendicular EDGEs
- gp_Vec fSegDir = SMESH_TNodeXYZ( f->_nn[0] ) - SMESH_TNodeXYZ( f->_nn[3] );
+ gp_Vec fSegDir = SMESH_TNodeXYZ( f->n(0) ) - SMESH_TNodeXYZ( f->n(3) );
bool isParallel = ( isLessAngle( eSegDir0, fSegDir, angle45 ) ||
isLessAngle( eSegDir1, fSegDir, angle45 ) ||
isLessAngle( eSegDir0, fSegDir.Reversed(), angle45 ) ||
if ( dist < 0.95 * ledge->_maxLen )
{
ledge->Set( _LayerEdge::UPD_NORMAL_CONV );
- if ( !ledge->_curvature ) ledge->_curvature = new _Curvature;
+ if ( !ledge->_curvature ) ledge->_curvature = _Factory::NewCurvature();
ledge->_curvature->_uv.SetCoord( uv.X(), uv.Y() );
edgesToUpdateFound = true;
}
bool _ViscousBuilder::updateNormals( _SolidData& data,
SMESH_MesherHelper& helper,
int stepNb,
- double stepSize)
+ double /*stepSize*/)
{
updateNormalsOfC1Vertices( data );
_LayerEdge* edge = e2neIt->first;
_LayerEdge& newEdge = e2neIt->second;
_EdgesOnShape* eos = data.GetShapeEdges( edge );
- if ( edge->Is( _LayerEdge::BLOCKED && newEdge._maxLen > edge->_len ))
+ if ( edge->Is( _LayerEdge::BLOCKED ) && newEdge._maxLen > edge->_len )
continue;
// Check if a new _normal is OK:
//================================================================================
bool _ViscousBuilder::updateNormalsOfSmoothed( _SolidData& data,
- SMESH_MesherHelper& helper,
+ SMESH_MesherHelper& /*helper*/,
const int nbSteps,
const double stepSize )
{
prevPosV = surface.Value( prevPosV.X(), prevPosV.Y() ).XYZ();
}
- SMDS_FacePosition* fPos;
+ SMDS_FacePositionPtr fPos;
//double r = 1. - Min( 0.9, step / 10. );
for ( set< _LayerEdge* >::iterator e = edges.begin(); e != edges.end(); ++e )
{
// set _curvature to make edgeF updated by putOnOffsetSurface()
if ( !edgeF->_curvature )
- if (( fPos = dynamic_cast<SMDS_FacePosition*>( edgeF->_nodes[0]->GetPosition() )))
+ if (( fPos = edgeF->_nodes[0]->GetPosition() ))
{
- edgeF->_curvature = new _Curvature;
+ edgeF->_curvature = _Factory::NewCurvature();
edgeF->_curvature->_r = 0;
edgeF->_curvature->_k = 0;
edgeF->_curvature->_h2lenRatio = 0;
//================================================================================
/*!
- * \brief Chooses a smoothing technic giving a position most close to an initial one.
+ * \brief Chooses a smoothing technique giving a position most close to an initial one.
* For a correct result, _simplices must contain nodes lying on geometry.
*/
//================================================================================
void _LayerEdge::ChooseSmooFunction( const set< TGeomID >& concaveVertices,
- const TNode2Edge& n2eMap)
+ const TNode2Edge& /*n2eMap*/)
{
if ( _smooFunction ) return;
}
}
- // // this coice is done only if ( !concaveVertices.empty() ) for Grids/smesh/bugs_19/X1
+ // // this choice is done only if ( !concaveVertices.empty() ) for Grids/smesh/bugs_19/X1
// // where the nodes are smoothed too far along a sphere thus creating
// // inverted _simplices
// double dist[theNbSmooFuns];
else
norm += cross;
}
- catch (Standard_Failure) { // if |cross| == 0.
+ catch (Standard_Failure&) { // if |cross| == 0.
}
}
gp_XYZ vec = newPos - pN;
//================================================================================
/*!
- * \brief Computes a new node position using weigthed node positions
+ * \brief Computes a new node position using weighted node positions
*/
//================================================================================
_pos.back().SetCoord( u, 0, 0 );
if ( _nodes.size() > 1 && uvOK )
{
- SMDS_EdgePosition* pos = static_cast<SMDS_EdgePosition*>( n->GetPosition() );
+ SMDS_EdgePositionPtr pos = n->GetPosition();
pos->SetUParameter( u );
}
}
_pos.back().SetCoord( uv.X(), uv.Y(), 0 );
if ( _nodes.size() > 1 && uvOK )
{
- SMDS_FacePosition* pos = static_cast<SMDS_FacePosition*>( n->GetPosition() );
+ SMDS_FacePositionPtr pos = n->GetPosition();
pos->SetUParameter( uv.X() );
pos->SetVParameter( uv.Y() );
}
TopLoc_Location loc;
if ( eos.SWOLType() == TopAbs_EDGE )
{
- SMDS_EdgePosition* pos = static_cast<SMDS_EdgePosition*>( n->GetPosition() );
+ SMDS_EdgePositionPtr pos = n->GetPosition();
pos->SetUParameter( nXYZ.X() );
double f,l;
Handle(Geom_Curve) curve = BRep_Tool::Curve( TopoDS::Edge( eos._sWOL ), loc, f,l);
}
else
{
- SMDS_FacePosition* pos = static_cast<SMDS_FacePosition*>( n->GetPosition() );
+ SMDS_FacePositionPtr pos = n->GetPosition();
pos->SetUParameter( nXYZ.X() );
pos->SetVParameter( nXYZ.Y() );
Handle(Geom_Surface) surface = BRep_Tool::Surface( TopoDS::Face(eos._sWOL), loc );
SMDS_PositionPtr lastPos = tgtNode->GetPosition();
if ( isOnEdge )
{
- SMDS_EdgePosition* epos = static_cast<SMDS_EdgePosition*>( lastPos );
+ SMDS_EdgePositionPtr epos = lastPos;
epos->SetUParameter( otherTgtPos.X() );
}
else
{
- SMDS_FacePosition* fpos = static_cast<SMDS_FacePosition*>( lastPos );
+ SMDS_FacePositionPtr fpos = lastPos;
fpos->SetUParameter( otherTgtPos.X() );
fpos->SetVParameter( otherTgtPos.Y() );
}
u = helper.GetNodeU( geomEdge, node );
pos = curve->Value( u ).Transformed(loc);
- SMDS_EdgePosition* epos = static_cast<SMDS_EdgePosition*>( node->GetPosition() );
+ SMDS_EdgePositionPtr epos = node->GetPosition();
epos->SetUParameter( u );
}
else
uv = helper.GetNodeUV( geomFace, node );
pos = surface->Value( uv );
- SMDS_FacePosition* fpos = static_cast<SMDS_FacePosition*>( node->GetPosition() );
+ SMDS_FacePositionPtr fpos = node->GetPosition();
fpos->SetUParameter( uv.X() );
fpos->SetVParameter( uv.Y() );
}
const TGeomID faceID = getMeshDS()->ShapeToIndex( exp.Current() );
if ( data._ignoreFaceIds.count( faceID ))
continue;
+ _EdgesOnShape* eos = data.GetShapeEdges( faceID );
+ SMDS_MeshGroup* group = StdMeshers_ViscousLayers::CreateGroup( eos->_hyp.GetGroupName(),
+ *helper.GetMesh(),
+ SMDSAbs_Volume );
+ std::vector< const SMDS_MeshElement* > vols;
const bool isReversedFace = data._reversedFaceIds.count( faceID );
SMESHDS_SubMesh* fSubM = getMeshDS()->MeshElements( exp.Current() );
SMDS_ElemIteratorPtr fIt = fSubM->GetElements();
if ( 0 < nnSet.size() && nnSet.size() < 3 )
continue;
+ vols.clear();
+ const SMDS_MeshElement* vol;
+
switch ( nbNodes )
{
case 3: // TRIA
{
// PENTA
for ( size_t iZ = 1; iZ < minZ; ++iZ )
- helper.AddVolume( (*nnVec[0])[iZ-1], (*nnVec[1])[iZ-1], (*nnVec[2])[iZ-1],
- (*nnVec[0])[iZ], (*nnVec[1])[iZ], (*nnVec[2])[iZ]);
+ {
+ vol = helper.AddVolume( (*nnVec[0])[iZ-1], (*nnVec[1])[iZ-1], (*nnVec[2])[iZ-1],
+ (*nnVec[0])[iZ], (*nnVec[1])[iZ], (*nnVec[2])[iZ]);
+ vols.push_back( vol );
+ }
for ( size_t iZ = minZ; iZ < maxZ; ++iZ )
{
int i2 = *degenEdgeInd.begin();
int i0 = helper.WrapIndex( i2 - 1, nbNodes );
int i1 = helper.WrapIndex( i2 + 1, nbNodes );
- helper.AddVolume( (*nnVec[i0])[iZ-1], (*nnVec[i1])[iZ-1],
- (*nnVec[i1])[iZ ], (*nnVec[i0])[iZ ], (*nnVec[i2]).back());
+ vol = helper.AddVolume( (*nnVec[i0])[iZ-1], (*nnVec[i1])[iZ-1],
+ (*nnVec[i1])[iZ ], (*nnVec[i0])[iZ ], (*nnVec[i2]).back());
+ vols.push_back( vol );
}
else // TETRA
{
int i3 = !degenEdgeInd.count(0) ? 0 : !degenEdgeInd.count(1) ? 1 : 2;
- helper.AddVolume( (*nnVec[ 0 ])[ i3 == 0 ? iZ-1 : nnVec[0]->size()-1 ],
- (*nnVec[ 1 ])[ i3 == 1 ? iZ-1 : nnVec[1]->size()-1 ],
- (*nnVec[ 2 ])[ i3 == 2 ? iZ-1 : nnVec[2]->size()-1 ],
- (*nnVec[ i3 ])[ iZ ]);
+ vol = helper.AddVolume( (*nnVec[ 0 ])[ i3 == 0 ? iZ-1 : nnVec[0]->size()-1 ],
+ (*nnVec[ 1 ])[ i3 == 1 ? iZ-1 : nnVec[1]->size()-1 ],
+ (*nnVec[ 2 ])[ i3 == 2 ? iZ-1 : nnVec[2]->size()-1 ],
+ (*nnVec[ i3 ])[ iZ ]);
+ vols.push_back( vol );
}
}
break; // TRIA
{
// HEX
for ( size_t iZ = 1; iZ < minZ; ++iZ )
- helper.AddVolume( (*nnVec[0])[iZ-1], (*nnVec[1])[iZ-1],
- (*nnVec[2])[iZ-1], (*nnVec[3])[iZ-1],
- (*nnVec[0])[iZ], (*nnVec[1])[iZ],
- (*nnVec[2])[iZ], (*nnVec[3])[iZ]);
+ {
+ vol = helper.AddVolume( (*nnVec[0])[iZ-1], (*nnVec[1])[iZ-1],
+ (*nnVec[2])[iZ-1], (*nnVec[3])[iZ-1],
+ (*nnVec[0])[iZ], (*nnVec[1])[iZ],
+ (*nnVec[2])[iZ], (*nnVec[3])[iZ]);
+ vols.push_back( vol );
+ }
for ( size_t iZ = minZ; iZ < maxZ; ++iZ )
{
int i0 = helper.WrapIndex( i3 + 1, nbNodes );
int i1 = helper.WrapIndex( i0 + 1, nbNodes );
- const SMDS_MeshElement* vol =
- helper.AddVolume( nnVec[i3]->back(), (*nnVec[i0])[iZ], (*nnVec[i0])[iZ-1],
- nnVec[i2]->back(), (*nnVec[i1])[iZ], (*nnVec[i1])[iZ-1]);
+ vol = helper.AddVolume( nnVec[i3]->back(), (*nnVec[i0])[iZ], (*nnVec[i0])[iZ-1],
+ nnVec[i2]->back(), (*nnVec[i1])[iZ], (*nnVec[i1])[iZ-1]);
+ vols.push_back( vol );
if ( !ok && vol )
degenVols.push_back( vol );
}
default: // degen HEX
{
- const SMDS_MeshElement* vol =
- helper.AddVolume( nnVec[0]->size() > iZ-1 ? (*nnVec[0])[iZ-1] : nnVec[0]->back(),
- nnVec[1]->size() > iZ-1 ? (*nnVec[1])[iZ-1] : nnVec[1]->back(),
- nnVec[2]->size() > iZ-1 ? (*nnVec[2])[iZ-1] : nnVec[2]->back(),
- nnVec[3]->size() > iZ-1 ? (*nnVec[3])[iZ-1] : nnVec[3]->back(),
- nnVec[0]->size() > iZ ? (*nnVec[0])[iZ] : nnVec[0]->back(),
- nnVec[1]->size() > iZ ? (*nnVec[1])[iZ] : nnVec[1]->back(),
- nnVec[2]->size() > iZ ? (*nnVec[2])[iZ] : nnVec[2]->back(),
- nnVec[3]->size() > iZ ? (*nnVec[3])[iZ] : nnVec[3]->back());
+ vol = helper.AddVolume( nnVec[0]->size() > iZ-1 ? (*nnVec[0])[iZ-1] : nnVec[0]->back(),
+ nnVec[1]->size() > iZ-1 ? (*nnVec[1])[iZ-1] : nnVec[1]->back(),
+ nnVec[2]->size() > iZ-1 ? (*nnVec[2])[iZ-1] : nnVec[2]->back(),
+ nnVec[3]->size() > iZ-1 ? (*nnVec[3])[iZ-1] : nnVec[3]->back(),
+ nnVec[0]->size() > iZ ? (*nnVec[0])[iZ] : nnVec[0]->back(),
+ nnVec[1]->size() > iZ ? (*nnVec[1])[iZ] : nnVec[1]->back(),
+ nnVec[2]->size() > iZ ? (*nnVec[2])[iZ] : nnVec[2]->back(),
+ nnVec[3]->size() > iZ ? (*nnVec[3])[iZ] : nnVec[3]->back());
+ vols.push_back( vol );
degenVols.push_back( vol );
}
}
return error("Not supported type of element", data._index);
} // switch ( nbNodes )
+
+ if ( group )
+ for ( size_t i = 0; i < vols.size(); ++i )
+ group->Add( vols[ i ]);
+
} // while ( fIt->more() )
} // loop on FACEs
SMESH_ComputeErrorPtr& err = _mesh->GetSubMesh( data._solid )->GetComputeError();
if ( !err || err->IsOK() )
{
- err.reset( new SMESH_ComputeError( COMPERR_WARNING,
- "Bad quality volumes created" ));
- err->myBadElements.insert( err->myBadElements.end(),
- degenVols.begin(),degenVols.end() );
+ SMESH_BadInputElements* badElems =
+ new SMESH_BadInputElements( getMeshDS(), COMPERR_WARNING, "Bad quality volumes created" );
+ badElems->myBadElements.insert( badElems->myBadElements.end(),
+ degenVols.begin(),degenVols.end() );
+ err.reset( badElems );
}
}
return true;
}
+namespace VISCOUS_3D
+{
+ struct ShrinkFace;
+ //--------------------------------------------------------------------------------
+ /*!
+ * \brief Pair of periodic FACEs
+ */
+ struct PeriodicFaces
+ {
+ typedef StdMeshers_ProjectionUtils::TrsfFinder3D Trsf;
+
+ ShrinkFace* _shriFace[2];
+ TNodeNodeMap _nnMap;
+ Trsf _trsf;
+
+ PeriodicFaces( ShrinkFace* sf1, ShrinkFace* sf2 ): _shriFace{ sf1, sf2 } {}
+ bool IncludeShrunk( const TopoDS_Face& face, const TopTools_MapOfShape& shrunkFaces ) const;
+ bool MoveNodes( const TopoDS_Face& tgtFace );
+ void Clear() { _nnMap.clear(); }
+ bool IsEmpty() const { return _nnMap.empty(); }
+ };
+
+ //--------------------------------------------------------------------------------
+ /*!
+ * \brief Shrink FACE data used to find periodic FACEs
+ */
+ struct ShrinkFace
+ {
+ // ................................................................................
+ struct BndPart //!< part of FACE boundary, either shrink or no-shrink
+ {
+ bool _isShrink, _isReverse;
+ int _nbSegments;
+ AverageHyp* _hyp;
+ std::vector< SMESH_NodeXYZ > _nodes;
+ TopAbs_ShapeEnum _vertSWOLType[2]; // shrink part includes VERTEXes
+ AverageHyp* _vertHyp[2];
+
+ BndPart():
+ _isShrink(0), _isReverse(0), _nbSegments(0), _hyp(0),
+ _vertSWOLType{ TopAbs_WIRE, TopAbs_WIRE }, _vertHyp{ 0, 0 }
+ {}
+
+ bool operator==( const BndPart& other ) const
+ {
+ return ( _isShrink == other._isShrink &&
+ _nbSegments == other._nbSegments &&
+ _nodes.size() == other._nodes.size() &&
+ vertSWOLType1() == other.vertSWOLType1() &&
+ vertSWOLType2() == other.vertSWOLType2() &&
+ (( !_isShrink ) ||
+ ( *_hyp == *other._hyp &&
+ vertHyp1() == other.vertHyp1() &&
+ vertHyp2() == other.vertHyp2() ))
+ );
+ }
+ bool CanAppend( const BndPart& other )
+ {
+ return ( _isShrink == other._isShrink &&
+ (( !_isShrink ) ||
+ ( *_hyp == *other._hyp &&
+ *_hyp == vertHyp2() &&
+ vertHyp2() == other.vertHyp1() ))
+ );
+ }
+ void Append( const BndPart& other )
+ {
+ _nbSegments += other._nbSegments;
+ bool hasCommonNode = ( _nodes.back()->GetID() == other._nodes.front()->GetID() );
+ _nodes.insert( _nodes.end(), other._nodes.begin() + hasCommonNode, other._nodes.end() );
+ _vertSWOLType[1] = other._vertSWOLType[1];
+ if ( _isShrink )
+ _vertHyp[1] = other._vertHyp[1];
+ }
+ const SMDS_MeshNode* Node(size_t i) const
+ {
+ return _nodes[ _isReverse ? ( _nodes.size() - 1 - i ) : i ]._node;
+ }
+ void Reverse() { _isReverse = !_isReverse; }
+ const TopAbs_ShapeEnum& vertSWOLType1() const { return _vertSWOLType[ _isReverse ]; }
+ const TopAbs_ShapeEnum& vertSWOLType2() const { return _vertSWOLType[ !_isReverse ]; }
+ const AverageHyp& vertHyp1() const { return *(_vertHyp[ _isReverse ]); }
+ const AverageHyp& vertHyp2() const { return *(_vertHyp[ !_isReverse ]); }
+ };
+ // ................................................................................
+
+ SMESH_subMesh* _subMesh;
+ _SolidData* _data1;
+ _SolidData* _data2;
+ //bool _isPeriodic;
+
+ std::list< BndPart > _boundary;
+ int _boundarySize, _nbBoundaryParts;
+
+ void Init( SMESH_subMesh* sm, _SolidData* sd1, _SolidData* sd2 )
+ {
+ _subMesh = sm; _data1 = sd1; _data2 = sd2; //_isPeriodic = false;
+ }
+ bool IsSame( const TopoDS_Face& face ) const
+ {
+ return _subMesh->GetSubShape().IsSame( face );
+ }
+ bool IsShrunk( const TopTools_MapOfShape& shrunkFaces ) const
+ {
+ return shrunkFaces.Contains( _subMesh->GetSubShape() );
+ }
+
+ //================================================================================
+ /*!
+ * Check if meshes on two FACEs are equal
+ */
+ bool IsPeriodic( ShrinkFace& other, PeriodicFaces& periodic )
+ {
+ if ( !IsSameNbElements( other ))
+ return false;
+
+ this->SetBoundary();
+ other.SetBoundary();
+ if ( this->_boundarySize != other._boundarySize ||
+ this->_nbBoundaryParts != other._nbBoundaryParts )
+ return false;
+
+ for ( int isReverse = 0; isReverse < 2; ++isReverse )
+ {
+ if ( isReverse )
+ Reverse( _boundary );
+
+ // check boundaries
+ bool equalBoundary = false;
+ for ( int iP = 0; iP < _nbBoundaryParts && !equalBoundary; ++iP )
+ {
+ if ( ! ( equalBoundary = ( this->_boundary == other._boundary )))
+ // set first part at end
+ _boundary.splice( _boundary.end(), _boundary, _boundary.begin() );
+ }
+ if ( !equalBoundary )
+ continue;
+
+ // check connectivity
+ std::set<const SMDS_MeshElement*> elemsThis, elemsOther;
+ this->GetElements( elemsThis );
+ other.GetElements( elemsOther );
+ SMESH_MeshEditor::Sew_Error err =
+ SMESH_MeshEditor::FindMatchingNodes( elemsThis, elemsOther,
+ this->_boundary.front().Node(0),
+ other._boundary.front().Node(0),
+ this->_boundary.front().Node(1),
+ other._boundary.front().Node(1),
+ periodic._nnMap );
+ if ( err != SMESH_MeshEditor::SEW_OK )
+ continue;
+
+ // check node positions
+ std::vector< gp_XYZ > srcPnts, tgtPnts;
+ this->GetBoundaryPoints( srcPnts );
+ other.GetBoundaryPoints( tgtPnts );
+ if ( !periodic._trsf.Solve( srcPnts, tgtPnts )) {
+ continue;
+ }
+ double tol = std::numeric_limits<double>::max();
+ for ( size_t i = 1; i < srcPnts.size(); ++i ) {
+ tol = Min( tol, ( srcPnts[i-1] - srcPnts[i] ).SquareModulus() );
+ }
+ tol = 0.01 * Sqrt( tol );
+ bool nodeCoincide = true;
+ TNodeNodeMap::iterator n2n = periodic._nnMap.begin();
+ for ( ; n2n != periodic._nnMap.end() && nodeCoincide; ++n2n )
+ {
+ SMESH_NodeXYZ nSrc = n2n->first;
+ SMESH_NodeXYZ nTgt = n2n->second;
+ gp_XYZ pTgt = periodic._trsf.Transform( nSrc );
+ nodeCoincide = (( pTgt - nTgt ).SquareModulus() < tol );
+ }
+ if ( nodeCoincide )
+ return true;
+ }
+ return false;
+ }
+
+ bool IsSameNbElements( ShrinkFace& other ) // check number of mesh faces
+ {
+ SMESHDS_SubMesh* sm1 = this->_subMesh->GetSubMeshDS();
+ SMESHDS_SubMesh* sm2 = other._subMesh->GetSubMeshDS();
+ return ( sm1->NbElements() == sm2->NbElements() &&
+ sm1->NbNodes() == sm2->NbNodes() );
+ }
+
+ void Reverse( std::list< BndPart >& boundary )
+ {
+ boundary.reverse();
+ for ( std::list< BndPart >::iterator part = boundary.begin(); part != boundary.end(); ++part )
+ part->Reverse();
+ }
+
+ void SetBoundary()
+ {
+ if ( !_boundary.empty() )
+ return;
+
+ TopoDS_Face F = TopoDS::Face( _subMesh->GetSubShape() );
+ if ( F.Orientation() >= TopAbs_INTERNAL ) F.Orientation( TopAbs_FORWARD );
+ std::list< TopoDS_Edge > edges;
+ std::list< int > nbEdgesInWire;
+ /*int nbWires =*/ SMESH_Block::GetOrderedEdges (F, edges, nbEdgesInWire);
+
+ // std::list< TopoDS_Edge >::iterator edgesEnd = edges.end();
+ // if ( nbWires > 1 ) {
+ // edgesEnd = edges.begin();
+ // std::advance( edgesEnd, nbEdgesInWire.front() );
+ // }
+ StdMeshers_FaceSide fSide( F, edges, _subMesh->GetFather(),
+ /*fwd=*/true, /*skipMedium=*/true );
+ _boundarySize = fSide.NbSegments();
+
+ //TopoDS_Vertex vv[2];
+ //std::list< TopoDS_Edge >::iterator edgeIt = edges.begin();
+ for ( int iE = 0; iE < nbEdgesInWire.front(); ++iE )
+ {
+ BndPart bndPart;
+ _EdgesOnShape* eos = _data1->GetShapeEdges( fSide.EdgeID( iE ));
+
+ bndPart._isShrink = ( eos->SWOLType() == TopAbs_FACE );
+ if ( bndPart._isShrink )
+ if (( _data1->_noShrinkShapes.count( eos->_shapeID )) ||
+ ( _data2 && _data2->_noShrinkShapes.count( eos->_shapeID )))
+ bndPart._isShrink = false;
+
+ if ( bndPart._isShrink )
+ {
+ bndPart._hyp = & eos->_hyp;
+ _EdgesOnShape* eov[2] = { _data1->GetShapeEdges( fSide.FirstVertex( iE )),
+ _data1->GetShapeEdges( fSide.LastVertex ( iE )) };
+ for ( int iV = 0; iV < 2; ++iV )
+ {
+ bndPart._vertHyp [iV] = & eov[iV]->_hyp;
+ bndPart._vertSWOLType[iV] = eov[iV]->SWOLType();
+ if ( _data1->_noShrinkShapes.count( eov[iV]->_shapeID ))
+ bndPart._vertSWOLType[iV] = TopAbs_SHAPE;
+ if ( _data2 && bndPart._vertSWOLType[iV] != TopAbs_SHAPE )
+ {
+ eov[iV] = _data2->GetShapeEdges( iV ? fSide.LastVertex(iE) : fSide.FirstVertex(iE ));
+ if ( _data2->_noShrinkShapes.count( eov[iV]->_shapeID ))
+ bndPart._vertSWOLType[iV] = TopAbs_SHAPE;
+ else if ( eov[iV]->SWOLType() > bndPart._vertSWOLType[iV] )
+ bndPart._vertSWOLType[iV] = eov[iV]->SWOLType();
+ }
+ }
+ }
+ std::vector<const SMDS_MeshNode*> nodes = fSide.GetOrderedNodes( iE );
+ bndPart._nodes.assign( nodes.begin(), nodes.end() );
+ bndPart._nbSegments = bndPart._nodes.size() - 1;
+
+ if ( _boundary.empty() || ! _boundary.back().CanAppend( bndPart ))
+ _boundary.push_back( bndPart );
+ else
+ _boundary.back().Append( bndPart );
+ }
+
+ _nbBoundaryParts = _boundary.size();
+ if ( _nbBoundaryParts > 1 && _boundary.front()._isShrink == _boundary.back()._isShrink )
+ {
+ _boundary.back().Append( _boundary.front() );
+ _boundary.pop_front();
+ --_nbBoundaryParts;
+ }
+ }
+
+ void GetElements( std::set<const SMDS_MeshElement*>& theElems)
+ {
+ if ( SMESHDS_SubMesh* sm = _subMesh->GetSubMeshDS() )
+ for ( SMDS_ElemIteratorPtr fIt = sm->GetElements(); fIt->more(); )
+ theElems.insert( theElems.end(), fIt->next() );
+
+ return ;
+ }
+
+ void GetBoundaryPoints( std::vector< gp_XYZ >& points )
+ {
+ points.reserve( _boundarySize );
+ size_t nb = _boundary.rbegin()->_nodes.size();
+ int lastID = _boundary.rbegin()->Node( nb - 1 )->GetID();
+ std::list< BndPart >::const_iterator part = _boundary.begin();
+ for ( ; part != _boundary.end(); ++part )
+ {
+ size_t nb = part->_nodes.size();
+ size_t iF = 0;
+ size_t iR = nb - 1;
+ size_t* i = part->_isReverse ? &iR : &iF;
+ if ( part->_nodes[ *i ]->GetID() == lastID )
+ ++iF, --iR;
+ for ( ; iF < nb; ++iF, --iR )
+ points.push_back( part->_nodes[ *i ]);
+ --iF, ++iR;
+ lastID = part->_nodes[ *i ]->GetID();
+ }
+ }
+ }; // struct ShrinkFace
+
+ //--------------------------------------------------------------------------------
+ /*!
+ * \brief Periodic FACEs
+ */
+ struct Periodicity
+ {
+ std::vector< ShrinkFace > _shrinkFaces;
+ std::vector< PeriodicFaces > _periodicFaces;
+
+ PeriodicFaces* GetPeriodic( const TopoDS_Face& face, const TopTools_MapOfShape& shrunkFaces )
+ {
+ for ( size_t i = 0; i < _periodicFaces.size(); ++i )
+ if ( _periodicFaces[ i ].IncludeShrunk( face, shrunkFaces ))
+ return & _periodicFaces[ i ];
+ return 0;
+ }
+ void ClearPeriodic( const TopoDS_Face& face )
+ {
+ for ( size_t i = 0; i < _periodicFaces.size(); ++i )
+ if ( _periodicFaces[ i ]._shriFace[0]->IsSame( face ) ||
+ _periodicFaces[ i ]._shriFace[1]->IsSame( face ))
+ _periodicFaces[ i ].Clear();
+ }
+ };
+
+ //================================================================================
+ /*!
+ * Check if a pair includes the given FACE and the other FACE is already shrunk
+ */
+ bool PeriodicFaces::IncludeShrunk( const TopoDS_Face& face,
+ const TopTools_MapOfShape& shrunkFaces ) const
+ {
+ if ( IsEmpty() ) return false;
+ return (( _shriFace[0]->IsSame( face ) && _shriFace[1]->IsShrunk( shrunkFaces )) ||
+ ( _shriFace[1]->IsSame( face ) && _shriFace[0]->IsShrunk( shrunkFaces )));
+ }
+
+ //================================================================================
+ /*!
+ * Make equal meshes on periodic faces by moving corresponding nodes
+ */
+ bool PeriodicFaces::MoveNodes( const TopoDS_Face& tgtFace )
+ {
+ int iTgt = _shriFace[1]->IsSame( tgtFace );
+ int iSrc = 1 - iTgt;
+
+ _SolidData* dataSrc = _shriFace[iSrc]->_data1;
+ _SolidData* dataTgt = _shriFace[iTgt]->_data1;
+
+ Trsf * trsf = & _trsf, trsfInverse;
+ if ( iSrc != 0 )
+ {
+ trsfInverse = _trsf;
+ if ( !trsfInverse.Invert())
+ return false;
+ trsf = &trsfInverse;
+ }
+ SMESHDS_Mesh* meshDS = dataSrc->GetHelper().GetMeshDS();
+
+ TNode2Edge::iterator n2e;
+ TNodeNodeMap::iterator n2n = _nnMap.begin();
+ for ( ; n2n != _nnMap.end(); ++n2n )
+ {
+ const SMDS_MeshNode* const* nn = & n2n->first;
+ const SMDS_MeshNode* nSrc = nn[ iSrc ];
+ const SMDS_MeshNode* nTgt = nn[ iTgt ];
+
+ if (( nSrc->GetPosition()->GetDim() == 2 ) ||
+ (( n2e = dataSrc->_n2eMap.find( nSrc )) == dataSrc->_n2eMap.end() ))
+ {
+ SMESH_NodeXYZ pSrc = nSrc;
+ gp_XYZ pTgt = trsf->Transform( pSrc );
+ meshDS->MoveNode( nTgt, pTgt.X(), pTgt.Y(), pTgt.Z() );
+ }
+ else
+ {
+ _LayerEdge* leSrc = n2e->second;
+ n2e = dataTgt->_n2eMap.find( nTgt );
+ if ( n2e == dataTgt->_n2eMap.end() )
+ break;
+ _LayerEdge* leTgt = n2e->second;
+ if ( leSrc->_nodes.size() != leTgt->_nodes.size() )
+ break;
+ for ( size_t iN = 1; iN < leSrc->_nodes.size(); ++iN )
+ {
+ SMESH_NodeXYZ pSrc = leSrc->_nodes[ iN ];
+ gp_XYZ pTgt = trsf->Transform( pSrc );
+ meshDS->MoveNode( leTgt->_nodes[ iN ], pTgt.X(), pTgt.Y(), pTgt.Z() );
+ }
+ }
+ }
+ bool done = ( n2n == _nnMap.end() );
+ debugMsg( "PeriodicFaces::MoveNodes "
+ << _shriFace[iSrc]->_subMesh->GetId() << " -> "
+ << _shriFace[iTgt]->_subMesh->GetId() << " -- "
+ << ( done ? "DONE" : "FAIL"));
+
+ return done;
+ }
+} // namespace VISCOUS_3D; Periodicity part
+
+
+//================================================================================
+/*!
+ * \brief Find FACEs to shrink, that are equally meshed before shrink (i.e. periodic)
+ * and should remain equal after shrink
+ */
+//================================================================================
+
+void _ViscousBuilder::findPeriodicFaces()
+{
+ // make map of (ids of FACEs to shrink mesh on) to (list of _SolidData containing
+ // _LayerEdge's inflated along FACE or EDGE)
+ std::map< TGeomID, std::list< _SolidData* > > id2sdMap;
+ for ( size_t i = 0 ; i < _sdVec.size(); ++i )
+ {
+ _SolidData& data = _sdVec[i];
+ std::map< TGeomID, TopoDS_Shape >::iterator s2s = data._shrinkShape2Shape.begin();
+ for (; s2s != data._shrinkShape2Shape.end(); ++s2s )
+ if ( s2s->second.ShapeType() == TopAbs_FACE )
+ id2sdMap[ getMeshDS()->ShapeToIndex( s2s->second )].push_back( &data );
+ }
+
+ _periodicity.reset( new Periodicity );
+ _periodicity->_shrinkFaces.resize( id2sdMap.size() );
+
+ std::map< TGeomID, std::list< _SolidData* > >::iterator id2sdIt = id2sdMap.begin();
+ for ( size_t i = 0; i < id2sdMap.size(); ++i, ++id2sdIt )
+ {
+ _SolidData* sd1 = id2sdIt->second.front();
+ _SolidData* sd2 = id2sdIt->second.back();
+ _periodicity->_shrinkFaces[ i ].Init( _mesh->GetSubMeshContaining( id2sdIt->first ), sd1, sd2 );
+ }
+
+ for ( size_t i1 = 0; i1 < _periodicity->_shrinkFaces.size(); ++i1 )
+ for ( size_t i2 = i1 + 1; i2 < _periodicity->_shrinkFaces.size(); ++i2 )
+ {
+ PeriodicFaces pf( & _periodicity->_shrinkFaces[ i1 ],
+ & _periodicity->_shrinkFaces[ i2 ]);
+ if ( pf._shriFace[0]->IsPeriodic( *pf._shriFace[1], pf ))
+ {
+ _periodicity->_periodicFaces.push_back( pf );
+ }
+ }
+ return;
+}
+
//================================================================================
/*!
* \brief Shrink 2D mesh on faces to let space for inflated layers
_SolidData& data = _sdVec[i];
map< TGeomID, TopoDS_Shape >::iterator s2s = data._shrinkShape2Shape.begin();
for (; s2s != data._shrinkShape2Shape.end(); ++s2s )
- if ( s2s->second.ShapeType() == TopAbs_FACE && !_shrinkedFaces.Contains( s2s->second ))
+ if ( s2s->second.ShapeType() == TopAbs_FACE && !_shrunkFaces.Contains( s2s->second ))
{
f2sdMap[ getMeshDS()->ShapeToIndex( s2s->second )].push_back( &data );
- // Put mesh faces on the shrinked FACE to the proxy sub-mesh to avoid
+ // Put mesh faces on the shrunk FACE to the proxy sub-mesh to avoid
// usage of mesh faces made in addBoundaryElements() by the 3D algo or
// by StdMeshers_QuadToTriaAdaptor
if ( SMESHDS_SubMesh* smDS = getMeshDS()->MeshElements( s2s->second ))
vector< _EdgesOnShape* > subEOS;
vector< _LayerEdge* > lEdges;
- // loop on FACEs to srink mesh on
+ // loop on FACEs to shrink mesh on
map< TGeomID, list< _SolidData* > >::iterator f2sd = f2sdMap.begin();
for ( ; f2sd != f2sdMap.end(); ++f2sd )
{
Handle(Geom_Surface) surface = BRep_Tool::Surface( F );
- _shrinkedFaces.Add( F );
+ _shrunkFaces.Add( F );
helper.SetSubShape( F );
+ // ==============================
+ // Use periodicity to move nodes
+ // ==============================
+
+ PeriodicFaces* periodic = _periodicity->GetPeriodic( F, _shrunkFaces );
+ bool movedByPeriod = ( periodic && periodic->MoveNodes( F ));
+
// ===========================
// Prepare data for shrinking
// ===========================
// Collect nodes to smooth (they are marked at the beginning of this method)
vector < const SMDS_MeshNode* > smoothNodes;
+
+ if ( !movedByPeriod )
{
SMDS_NodeIteratorPtr nIt = smDS->GetNodes();
while ( nIt->more() )
}
subEOS.push_back( eos );
- for ( size_t i = 0; i < eos->_edges.size(); ++i )
- {
- lEdges.push_back( eos->_edges[ i ] );
- prepareEdgeToShrink( *eos->_edges[ i ], *eos, helper, smDS );
- }
+ if ( !movedByPeriod )
+ for ( size_t i = 0; i < eos->_edges.size(); ++i )
+ {
+ lEdges.push_back( eos->_edges[ i ] );
+ prepareEdgeToShrink( *eos->_edges[ i ], *eos, helper, smDS );
+ }
}
}
if ( eos.SWOLType() == TopAbs_EDGE )
{
SMESH_subMesh* edgeSM = _mesh->GetSubMesh( eos._sWOL );
- _Shrinker1D& srinker = e2shrMap[ edgeSM->GetId() ];
- eShri1D.insert( & srinker );
- srinker.AddEdge( eos._edges[0], eos, helper );
VISCOUS_3D::ToClearSubWithMain( edgeSM, data._solid );
- // restore params of nodes on EGDE if the EDGE has been already
- // srinked while srinking other FACE
- srinker.RestoreParams();
+ if ( !movedByPeriod )
+ {
+ _Shrinker1D& shrinker = e2shrMap[ edgeSM->GetId() ];
+ eShri1D.insert( & shrinker );
+ shrinker.AddEdge( eos._edges[0], eos, helper );
+ // restore params of nodes on EDGE if the EDGE has been already
+ // shrunk while shrinking other FACE
+ shrinker.RestoreParams();
+ }
}
for ( size_t i = 0; i < eos._edges.size(); ++i )
{
}
bool toFixTria = false; // to improve quality of trias by diagonal swap
- if ( isConcaveFace )
+ if ( isConcaveFace && !movedByPeriod )
{
const bool hasTria = _mesh->NbTriangles(), hasQuad = _mesh->NbQuadrangles();
if ( hasTria != hasQuad ) {
// Perform shrinking
// ==================
- bool shrinked = true;
+ bool shrunk = !movedByPeriod;
int nbBad, shriStep=0, smooStep=0;
_SmoothNode::SmoothType smoothType
= isConcaveFace ? _SmoothNode::ANGULAR : _SmoothNode::LAPLACIAN;
SMESH_Comment errMsg;
- while ( shrinked )
+ while ( shrunk )
{
shriStep++;
// Move boundary nodes (actually just set new UV)
// -----------------------------------------------
dumpFunction(SMESH_Comment("moveBoundaryOnF")<<f2sd->first<<"_st"<<shriStep ); // debug
- shrinked = false;
+ shrunk = false;
for ( size_t iS = 0; iS < subEOS.size(); ++iS )
{
_EdgesOnShape& eos = * subEOS[ iS ];
for ( size_t i = 0; i < eos._edges.size(); ++i )
{
- shrinked |= eos._edges[i]->SetNewLength2d( surface, F, eos, helper );
+ shrunk |= eos._edges[i]->SetNewLength2d( surface, F, eos, helper );
}
}
dumpFunctionEnd();
// }
// }
- } // while ( shrinked )
+ } // while ( shrunk )
if ( !errMsg.empty() ) // Try to re-compute the shrink FACE
{
getMeshDS()->RemoveFreeNode( n, smDS, /*fromGroups=*/false );
}
}
+ _periodicity->ClearPeriodic( F );
+
// restore position and UV of target nodes
gp_Pnt p;
for ( size_t iS = 0; iS < subEOS.size(); ++iS )
edge->Is( _LayerEdge::SHRUNK )) continue;
if ( subEOS[iS]->SWOLType() == TopAbs_FACE )
{
- SMDS_FacePosition* pos = static_cast<SMDS_FacePosition*>( tgtNode->GetPosition() );
+ SMDS_FacePositionPtr pos = tgtNode->GetPosition();
pos->SetUParameter( edge->_pos[0].X() );
pos->SetVParameter( edge->_pos[0].Y() );
p = surface->Value( edge->_pos[0].X(), edge->_pos[0].Y() );
}
else
{
- SMDS_EdgePosition* pos = static_cast<SMDS_EdgePosition*>( tgtNode->GetPosition() );
+ SMDS_EdgePositionPtr pos = tgtNode->GetPosition();
pos->SetUParameter( edge->_pos[0].Coord( U_TGT ));
p = BRepAdaptor_Curve( TopoDS::Edge( subEOS[iS]->_sWOL )).Value( pos->GetUParameter() );
}
return error( errMsg );
} // end of re-meshing in case of failed smoothing
- else
+ else if ( !movedByPeriod )
{
// No wrongly shaped faces remain; final smooth. Set node XYZ.
bool isStructuredFixed = false;
if ( data2 )
VISCOUS_3D::ToClearSubWithMain( sm, data2->_solid );
- } // loop on FACES to srink mesh on
+ } // loop on FACES to shrink mesh on
- // Replace source nodes by target nodes in shrinked mesh edges
+ // Replace source nodes by target nodes in shrunk mesh edges
map< int, _Shrinker1D >::iterator e2shr = e2shrMap.begin();
for ( ; e2shr != e2shrMap.end(); ++e2shr )
bool _ViscousBuilder::prepareEdgeToShrink( _LayerEdge& edge,
_EdgesOnShape& eos,
SMESH_MesherHelper& helper,
- const SMESHDS_SubMesh* faceSubMesh)
+ const SMESHDS_SubMesh* /*faceSubMesh*/)
{
const SMDS_MeshNode* srcNode = edge._nodes[0];
const SMDS_MeshNode* tgtNode = edge._nodes.back();
edge._pos[0].SetCoord( tgtUV.X(), tgtUV.Y(), 0 );
// set UV of source node to target node
- SMDS_FacePosition* pos = static_cast<SMDS_FacePosition*>( tgtNode->GetPosition() );
+ SMDS_FacePositionPtr pos = tgtNode->GetPosition();
pos->SetUParameter( srcUV.X() );
pos->SetVParameter( srcUV.Y() );
}
if ( !n2 )
return error(SMESH_Comment("Wrongly meshed EDGE ") << getMeshDS()->ShapeToIndex( E ));
+ if ( n2 == tgtNode ) // for 3D_mesh_GHS3D_01/B1
+ {
+ // shrunk by other SOLID
+ edge.Set( _LayerEdge::SHRUNK ); // ???
+ return true;
+ }
+
double uSrc = helper.GetNodeU( E, srcNode, n2 );
double uTgt = helper.GetNodeU( E, tgtNode, srcNode );
double u2 = helper.GetNodeU( E, n2, srcNode );
edge._simplices[0]._nPrev = n2;
// set U of source node to the target node
- SMDS_EdgePosition* pos = static_cast<SMDS_EdgePosition*>( tgtNode->GetPosition() );
+ SMDS_EdgePositionPtr pos = tgtNode->GetPosition();
pos->SetUParameter( uSrc );
}
return true;
TopLoc_Location loc;
Handle(Geom_Curve) curve = BRep_Tool::Curve( TopoDS::Edge( S ), loc, f, l );
if ( curve.IsNull() ) return;
- SMDS_EdgePosition* ePos = static_cast<SMDS_EdgePosition*>( srcNode->GetPosition() );
+ SMDS_EdgePositionPtr ePos = srcNode->GetPosition();
p = curve->Value( ePos->GetUParameter() );
break;
}
//================================================================================
/*!
- * \brief Try to fix triangles with high aspect ratio by swaping diagonals
+ * \brief Try to fix triangles with high aspect ratio by swapping diagonals
*/
//================================================================================
*/
//================================================================================
-bool _LayerEdge::SetNewLength2d( Handle(Geom_Surface)& surface,
+bool _LayerEdge::SetNewLength2d( Handle(Geom_Surface)& /*surface*/,
const TopoDS_Face& F,
_EdgesOnShape& eos,
SMESH_MesherHelper& helper )
{
return true;
}
- SMDS_FacePosition* pos = static_cast<SMDS_FacePosition*>( tgtNode->GetPosition() );
+ SMDS_FacePositionPtr pos = tgtNode->GetPosition();
pos->SetUParameter( newUV.X() );
pos->SetVParameter( newUV.Y() );
{
const TopoDS_Edge& E = TopoDS::Edge( eos._sWOL );
const SMDS_MeshNode* n2 = _simplices[0]._nPrev;
- SMDS_EdgePosition* tgtPos = static_cast<SMDS_EdgePosition*>( tgtNode->GetPosition() );
+ SMDS_EdgePositionPtr tgtPos = tgtNode->GetPosition();
const double u2 = helper.GetNodeU( E, n2, tgtNode );
const double uSrc = _pos[0].Coord( U_SRC );
return false;
}
- SMDS_FacePosition* pos = static_cast<SMDS_FacePosition*>( _node->GetPosition() );
+ SMDS_FacePositionPtr pos = _node->GetPosition();
pos->SetUParameter( newPos.X() );
pos->SetVParameter( newPos.Y() );
//================================================================================
/*!
- * \brief Computes new UV using angle based smoothing technic
+ * \brief Computes new UV using angle based smoothing technique
*/
//================================================================================
return newPos;
}
-//================================================================================
-/*!
- * \brief Delete _SolidData
- */
-//================================================================================
-
-_SolidData::~_SolidData()
-{
- TNode2Edge::iterator n2e = _n2eMap.begin();
- for ( ; n2e != _n2eMap.end(); ++n2e )
- {
- _LayerEdge* & e = n2e->second;
- if ( e )
- {
- delete e->_curvature;
- if ( e->_2neibors )
- delete e->_2neibors->_plnNorm;
- delete e->_2neibors;
- }
- delete e;
- e = 0;
- }
- _n2eMap.clear();
-
- delete _helper;
- _helper = 0;
-}
-
//================================================================================
/*!
* \brief Keep a _LayerEdge inflated along the EDGE
if ( !discret.IsDone() )
return throw SALOME_Exception(LOCALIZED("GCPnts_AbscissaPoint failed"));
double u = discret.Parameter();
- SMDS_EdgePosition* pos = static_cast<SMDS_EdgePosition*>( _nodes[i]->GetPosition() );
+ SMDS_EdgePositionPtr pos = _nodes[i]->GetPosition();
pos->SetUParameter( u );
gp_Pnt p = C->Value( u );
const_cast< SMDS_MeshNode*>( _nodes[i] )->setXYZ( p.X(), p.Y(), p.Z() );
{
if ( !_nodes[i] ) continue;
double u = f * ( 1-_normPar[i] ) + l * _normPar[i];
- SMDS_EdgePosition* pos = static_cast<SMDS_EdgePosition*>( _nodes[i]->GetPosition() );
+ SMDS_EdgePositionPtr pos = _nodes[i]->GetPosition();
pos->SetUParameter( u );
}
}
for ( size_t i = 0; i < _nodes.size(); ++i )
{
if ( !_nodes[i] ) continue;
- SMDS_EdgePosition* pos = static_cast<SMDS_EdgePosition*>( _nodes[i]->GetPosition() );
+ SMDS_EdgePositionPtr pos = _nodes[i]->GetPosition();
pos->SetUParameter( _initU[i] );
}
_done = false;
//================================================================================
/*!
- * \brief Replace source nodes by target nodes in shrinked mesh edges
+ * \brief Replace source nodes by target nodes in shrunk mesh edges
*/
//================================================================================