#include "StdMeshers_FaceSide.hxx"
#include <BRepAdaptor_Curve2d.hxx>
+#include <BRepAdaptor_Surface.hxx>
+#include <BRepLProp_SLProps.hxx>
#include <BRep_Tool.hxx>
#include <Bnd_B2d.hxx>
#include <Bnd_B3d.hxx>
#include <Geom2d_Line.hxx>
#include <Geom2d_TrimmedCurve.hxx>
#include <GeomAdaptor_Curve.hxx>
+#include <GeomLib.hxx>
#include <Geom_Circle.hxx>
#include <Geom_Curve.hxx>
#include <Geom_Line.hxx>
#include <Geom_TrimmedCurve.hxx>
#include <Precision.hxx>
#include <Standard_ErrorHandler.hxx>
+#include <Standard_Failure.hxx>
#include <TColStd_Array1OfReal.hxx>
#include <TopExp.hxx>
#include <TopExp_Explorer.hxx>
enum UIndex { U_TGT = 1, U_SRC, LEN_TGT };
+ const double theMinSmoothCosin = 0.1;
+
/*!
* \brief SMESH_ProxyMesh computed by _ViscousBuilder for a SOLID.
* It is stored in a SMESH_subMesh of the SOLID as SMESH_subMeshEventListenerData
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 );
}
_2NearEdges() { _nodes[0]=_nodes[1]=0; _plnNorm = 0; }
void reverse() {
std::swap( _nodes[0], _nodes[1] );
- std::swap( _wgt[0], _wgt[1] );
+ std::swap( _wgt [0], _wgt [1] );
+ std::swap( _edges[0], _edges[1] );
}
};
//--------------------------------------------------------------------------------
gp_XYZ _normal; // to solid surface
vector<gp_XYZ> _pos; // points computed during inflation
- double _len; // length achived with the last step
+ double _len; // length achived with the last inflation step
double _cosin; // of angle (_normal ^ surface)
double _lenFactor; // to compute _len taking _cosin into account
void SetDataByNeighbors( const SMDS_MeshNode* n1,
const SMDS_MeshNode* n2,
SMESH_MesherHelper& helper);
- void InvalidateStep( int curStep );
+ void InvalidateStep( int curStep, bool restoreLength=false );
bool Smooth(int& badNb);
bool SmoothOnEdge(Handle(Geom_Surface)& surface,
const TopoDS_Face& F,
double& dist,
const double& epsilon) const;
gp_Ax1 LastSegment(double& segLen) const;
- bool IsOnEdge() const { return _2neibors; }
- void Copy( _LayerEdge& other, SMESH_MesherHelper& helper );
- void SetCosin( double cosin );
+ bool IsOnEdge() const { return _2neibors; }
+ gp_XYZ Copy( _LayerEdge& other, SMESH_MesherHelper& helper );
+ void SetCosin( double cosin );
};
struct _LayerEdgeCmp
{
return cmpNodes ? ( e1->_nodes[0]->GetID() < e2->_nodes[0]->GetID()) : ( e1 < e2 );
}
};
+ //--------------------------------------------------------------------------------
+ /*!
+ * \brief Convex FACE whose radius of curvature is less than the thickness of
+ * layers. It is used to detect distortion of prisms based on a convex
+ * FACE and to update normals to enable further increasing the thickness
+ */
+ struct _ConvexFace
+ {
+ TopoDS_Face _face;
+
+ // edges whose _simplices are used to detect prism destorsion
+ vector< _LayerEdge* > _simplexTestEdges;
+
+ // map a sub-shape to it's index in _SolidData::_endEdgeOnShape vector
+ map< TGeomID, int > _subIdToEdgeEnd;
+
+ bool _normalsFixed;
+
+ bool GetCenterOfCurvature( _LayerEdge* ledge,
+ BRepLProp_SLProps& surfProp,
+ SMESH_MesherHelper& helper,
+ gp_Pnt & center ) const;
+ bool CheckPrisms() const;
+ };
+
//--------------------------------------------------------------------------------
typedef map< const SMDS_MeshNode*, _LayerEdge*, TIDCompare > TNode2Edge;
TopoDS_Shape _hypShape;
_MeshOfSolid* _proxyMesh;
set<TGeomID> _reversedFaceIds;
- set<TGeomID> _ignoreFaceIds;
+ set<TGeomID> _ignoreFaceIds; // WOL FACEs and FACEs of other SOLIDS
double _stepSize, _stepSizeCoeff;
const SMDS_MeshNode* _stepSizeNodes[2];
TNode2Edge _n2eMap;
+ // map to find _n2eMap of another _SolidData by a shrink shape shared by two _SolidData's
+ map< TGeomID, TNode2Edge* > _s2neMap;
// edges of _n2eMap. We keep same data in two containers because
// iteration over the map is 5 time longer than over the vector
vector< _LayerEdge* > _edges;
// _LayerEdge's basing on nodes on key shape are inflated along the value shape
map< TGeomID, TopoDS_Shape > _shrinkShape2Shape;
+ // Convex FACEs whose radius of curvature is less than the thickness of layers
+ map< TGeomID, _ConvexFace > _convexFaces;
+
// FACE's WOL, srink on which is forbiden due to algo on the adjacent SOLID
set< TGeomID > _noShrinkFaces;
- // <EDGE to smooth on> to <it's curve>
+ // <EDGE to smooth on> to <it's curve> -- for analytic smooth
map< TGeomID,Handle(Geom_Curve)> _edge2curve;
- // end indices in _edges of _LayerEdge on one shape to smooth
- vector< int > _endEdgeToSmooth;
+ // end indices in _edges of _LayerEdge on each shape, first go shapes to smooth
+ vector< int > _endEdgeOnShape;
+ int _nbShapesToSmooth;
double _epsilon; // precision for SegTriaInter()
Handle(Geom_Surface)& surface,
const TopoDS_Face& F,
SMESH_MesherHelper& helper);
+
+ void SortOnEdge( const TopoDS_Edge& E,
+ const int iFrom,
+ const int iTo,
+ SMESH_MesherHelper& helper);
+
+ _ConvexFace* GetConvexFace( const TGeomID faceID )
+ {
+ map< TGeomID, _ConvexFace >::iterator id2face = _convexFaces.find( faceID );
+ return id2face == _convexFaces.end() ? 0 : & id2face->second;
+ }
+ void GetEdgesOnShape( size_t end, int & iBeg, int & iEnd )
+ {
+ iBeg = end > 0 ? _endEdgeOnShape[ end-1 ] : 0;
+ iEnd = _endEdgeOnShape[ end ];
+ }
+
+ bool GetShapeEdges(const TGeomID shapeID, size_t& edgeEnd, int* iBeg=0, int* iEnd=0 ) const;
+
+ void AddShapesToSmooth( const set< TGeomID >& shapeIDs );
+ };
+ //--------------------------------------------------------------------------------
+ /*!
+ * \brief Container of centers of curvature at nodes on an EDGE bounding _ConvexFace
+ */
+ struct _CentralCurveOnEdge
+ {
+ bool _isDegenerated;
+ vector< gp_Pnt > _curvaCenters;
+ vector< _LayerEdge* > _ledges;
+ vector< gp_XYZ > _normals; // new normal for each of _ledges
+ vector< double > _segLength2;
+
+ TopoDS_Edge _edge;
+ TopoDS_Face _adjFace;
+ bool _adjFaceToSmooth;
+
+ void Append( const gp_Pnt& center, _LayerEdge* ledge )
+ {
+ if ( _curvaCenters.size() > 0 )
+ _segLength2.push_back( center.SquareDistance( _curvaCenters.back() ));
+ _curvaCenters.push_back( center );
+ _ledges.push_back( ledge );
+ _normals.push_back( ledge->_normal );
+ }
+ bool FindNewNormal( const gp_Pnt& center, gp_XYZ& newNormal );
+ void SetShapes( const TopoDS_Edge& edge,
+ const _ConvexFace& convFace,
+ const _SolidData& data,
+ SMESH_MesherHelper& helper);
};
//--------------------------------------------------------------------------------
/*!
struct _SmoothNode
{
const SMDS_MeshNode* _node;
- //vector<const SMDS_MeshNode*> _nodesAround;
vector<_Simplex> _simplices; // for quality check
enum SmoothType { LAPLACIAN, CENTROIDAL, ANGULAR, TFI };
bool makeLayer(_SolidData& data);
bool setEdgeData(_LayerEdge& edge, const set<TGeomID>& subIds,
SMESH_MesherHelper& helper, _SolidData& data);
+ gp_XYZ getFaceNormal(const SMDS_MeshNode* n,
+ const TopoDS_Face& face,
+ SMESH_MesherHelper& helper,
+ bool& isOK,
+ bool shiftInside=false);
+ gp_XYZ getWeigthedNormal( const SMDS_MeshNode* n,
+ std::pair< TGeomID, gp_XYZ > fId2Normal[],
+ const int nbFaces );
bool findNeiborsOnEdge(const _LayerEdge* edge,
const SMDS_MeshNode*& n1,
const SMDS_MeshNode*& n2,
const set<TGeomID>& ingnoreShapes,
const _SolidData* dataToCheckOri = 0,
const bool toSort = false);
+ void findSimplexTestEdges( _SolidData& data,
+ vector< vector<_LayerEdge*> >& edgesByGeom);
bool sortEdges( _SolidData& data,
vector< vector<_LayerEdge*> >& edgesByGeom);
+ void limitStepSizeByCurvature( _SolidData& data );
void limitStepSize( _SolidData& data,
const SMDS_MeshElement* face,
- const double cosin);
+ const _LayerEdge* maxCosinEdge );
void limitStepSize( _SolidData& data, const double minSize);
bool inflate(_SolidData& data);
bool smoothAndCheck(_SolidData& data, const int nbSteps, double & distToIntersection);
Handle(Geom_Surface)& surface,
const TopoDS_Face& F,
SMESH_MesherHelper& helper);
- bool updateNormals( _SolidData& data, SMESH_MesherHelper& helper );
+ bool updateNormals( _SolidData& data, SMESH_MesherHelper& helper, int stepNb );
+ bool updateNormalsOfConvexFaces( _SolidData& data,
+ SMESH_MesherHelper& helper,
+ int stepNb );
bool refine(_SolidData& data);
bool shrink();
bool prepareEdgeToShrink( _LayerEdge& edge, const TopoDS_Face& F,
* 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
*/
- struct TmpMeshFace : public SMDS_MeshElement
+ struct _TmpMeshFace : public SMDS_MeshElement
{
vector<const SMDS_MeshNode* > _nn;
- TmpMeshFace( const vector<const SMDS_MeshNode*>& nodes, int id):
- SMDS_MeshElement(id), _nn(nodes) {}
+ _TmpMeshFace( const vector<const SMDS_MeshNode*>& nodes, int id, int faceID=-1):
+ SMDS_MeshElement(id), _nn(nodes) { setShapeId(faceID); }
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; }
/*!
* \brief Class of temporary mesh face storing _LayerEdge it's based on
*/
- struct TmpMeshFaceOnEdge : public TmpMeshFace
+ struct _TmpMeshFaceOnEdge : public _TmpMeshFace
{
_LayerEdge *_le1, *_le2;
- TmpMeshFaceOnEdge( _LayerEdge* le1, _LayerEdge* le2, int ID ):
- TmpMeshFace( vector<const SMDS_MeshNode*>(4), ID ), _le1(le1), _le2(le2)
+ _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();
* \brief Retriever of node coordinates either directly of from a surface by node UV.
* \warning Location of a surface is ignored
*/
- struct NodeCoordHelper
+ struct _NodeCoordHelper
{
SMESH_MesherHelper& _helper;
const TopoDS_Face& _face;
Handle(Geom_Surface) _surface;
- gp_XYZ (NodeCoordHelper::* _fun)(const SMDS_MeshNode* n) const;
+ gp_XYZ (_NodeCoordHelper::* _fun)(const SMDS_MeshNode* n) const;
- NodeCoordHelper(const TopoDS_Face& F, SMESH_MesherHelper& helper, bool is2D)
+ _NodeCoordHelper(const TopoDS_Face& F, SMESH_MesherHelper& helper, bool is2D)
: _helper( helper ), _face( F )
{
if ( is2D )
_surface = BRep_Tool::Surface( _face, loc );
}
if ( _surface.IsNull() )
- _fun = & NodeCoordHelper::direct;
+ _fun = & _NodeCoordHelper::direct;
else
- _fun = & NodeCoordHelper::byUV;
+ _fun = & _NodeCoordHelper::byUV;
}
gp_XYZ operator()(const SMDS_MeshNode* n) const { return (this->*_fun)( n ); }
};
} // namespace VISCOUS_3D
+
+
//================================================================================
// StdMeshers_ViscousLayers hypothesis
//
if ( node->GetPosition()->GetTypeOfPosition() == SMDS_TOP_VERTEX &&
helper.IsClosedEdge( fromE ))
{
- if ( fabs(u-f) < fabs(u-l )) c->D1( l, p, dv );
- else c->D1( f, p, dv );
+ if ( fabs(u-f) < fabs(u-l)) c->D1( l, p, dv );
+ else c->D1( f, p, dv );
if ( o == TopAbs_REVERSED )
dv.Reverse();
gp_Vec dir2 = norm ^ dv;
const SMDS_MeshNode* node, SMESH_MesherHelper& helper,
bool& ok, double* cosin=0)
{
+ TopoDS_Face faceFrw = F;
+ faceFrw.Orientation( TopAbs_FORWARD );
double f,l; TopLoc_Location loc;
- vector< TopoDS_Edge > edges; // sharing a vertex
- PShapeIteratorPtr eIt = helper.GetAncestors( fromV, *helper.GetMesh(), TopAbs_EDGE);
- while ( eIt->more())
- {
- const TopoDS_Edge* e = static_cast<const TopoDS_Edge*>( eIt->next() );
- if ( helper.IsSubShape( *e, F ) && !BRep_Tool::Curve( *e, loc,f,l).IsNull() )
- edges.push_back( *e );
- }
- gp_XYZ dir(0,0,0);
- if ( !( ok = ( edges.size() > 0 ))) return dir;
- // get average dir of edges going fromV
- gp_XYZ edgeDir;
- //if ( edges.size() > 1 )
- for ( size_t i = 0; i < edges.size(); ++i )
+ TopoDS_Edge edges[2]; // sharing a vertex
+ int nbEdges = 0;
+ {
+ TopoDS_Vertex VV[2];
+ TopExp_Explorer exp( faceFrw, TopAbs_EDGE );
+ for ( ; exp.More() && nbEdges < 2; exp.Next() )
{
- edgeDir = getEdgeDir( edges[i], fromV );
- double size2 = edgeDir.SquareModulus();
- if ( size2 > numeric_limits<double>::min() )
- edgeDir /= sqrt( size2 );
- else
- ok = false;
- dir += edgeDir;
+ const TopoDS_Edge& e = TopoDS::Edge( exp.Current() );
+ if ( SMESH_Algo::isDegenerated( e )) continue;
+ TopExp::Vertices( e, VV[0], VV[1], /*CumOri=*/true );
+ if ( VV[1].IsSame( fromV )) {
+ edges[ 0 ] = e;
+ nbEdges++;
+ }
+ else if ( VV[0].IsSame( fromV )) {
+ edges[ 1 ] = e;
+ nbEdges++;
+ }
+ }
+ }
+ gp_XYZ dir(0,0,0), edgeDir[2];
+ if ( nbEdges == 2 )
+ {
+ // get dirs of edges going fromV
+ ok = true;
+ for ( size_t i = 0; i < nbEdges && ok; ++i )
+ {
+ edgeDir[i] = getEdgeDir( edges[i], fromV );
+ double size2 = edgeDir[i].SquareModulus();
+ if (( ok = size2 > numeric_limits<double>::min() ))
+ edgeDir[i] /= sqrt( size2 );
+ }
+ if ( !ok ) return dir;
+
+ // get angle between the 2 edges
+ gp_Vec faceNormal;
+ double angle = helper.GetAngle( edges[0], edges[1], faceFrw, &faceNormal );
+ if ( Abs( angle ) < 5 * M_PI/180 )
+ {
+ dir = ( faceNormal.XYZ() ^ edgeDir[0].Reversed()) + ( faceNormal.XYZ() ^ edgeDir[1] );
+ }
+ else
+ {
+ dir = edgeDir[0] + edgeDir[1];
+ if ( angle < 0 )
+ dir.Reverse();
}
- gp_XYZ fromEdgeDir = getFaceDir( F, edges[0], node, helper, ok );
- if ( edges.size() == 1 )
- dir = fromEdgeDir;
- else if ( dir.SquareModulus() < 0.1 ) // ~< 20 degrees
- dir = fromEdgeDir + getFaceDir( F, edges[1], node, helper, ok );
- else if ( dir * fromEdgeDir < 0 )
- dir *= -1;
- if ( ok )
- {
- //dir /= edges.size();
if ( cosin ) {
- double angle = gp_Vec( edgeDir ).Angle( dir );
- *cosin = cos( angle );
+ double angle = gp_Vec( edgeDir[0] ).Angle( dir );
+ *cosin = Cos( angle );
}
}
+ else if ( nbEdges == 1 )
+ {
+ dir = getFaceDir( faceFrw, edges[0], node, helper, ok );
+ if ( cosin ) *cosin = 1.;
+ }
+ else
+ {
+ ok = false;
+ }
+
return dir;
}
//================================================================================
cross = -cross;
isConvex = ( cross > 0.1 ); //-1e-9 );
}
- // check if concavity is strong enough to care about it
- //const double maxAngle = 5 * Standard_PI180;
if ( !isConvex )
{
//cout << "Concave FACE " << helper.GetMeshDS()->ShapeToIndex( F ) << endl;
return true;
- // map< double, const SMDS_MeshNode* > u2nodes;
- // if ( !SMESH_Algo::GetSortedNodesOnEdge( helper.GetMeshDS(), E,
- // /*ignoreMedium=*/true, u2nodes))
- // continue;
- // map< double, const SMDS_MeshNode* >::iterator u2n = u2nodes.begin();
- // gp_Pnt2d uvPrev = helper.GetNodeUV( F, u2n->second );
- // double uPrev = u2n->first;
- // for ( ++u2n; u2n != u2nodes.end(); ++u2n )
- // {
- // gp_Pnt2d uv = helper.GetNodeUV( F, u2n->second );
- // gp_Vec2d segmentDir( uvPrev, uv );
- // curve.D1( uPrev, p, drv1 );
- // try {
- // if ( fabs( segmentDir.Angle( drv1 )) > maxAngle )
- // return true;
- // }
- // catch ( ... ) {}
- // uvPrev = uv;
- // uPrev = u2n->first;
- // }
}
}
// check angles at VERTEXes
}
//--------------------------------------------------------------------------------
// DEBUG. Dump intermediate node positions into a python script
+ // HOWTO use: run python commands written in a console to see
+ // construction steps of viscous layers
#ifdef __myDEBUG
ofstream* py;
+ int theNbFunc;
struct PyDump {
PyDump() {
const char* fname = "/tmp/viscous.py";
<< "smesh = smeshBuilder.New(salome.myStudy)" << endl
<< "meshSO = smesh.GetCurrentStudy().FindObjectID('0:1:2:3')" << endl
<< "mesh = smesh.Mesh( meshSO.GetObject() )"<<endl;
+ theNbFunc = 0;
}
void Finish() {
- if (py)
- *py << "mesh.MakeGroup('Viscous Prisms',SMESH.VOLUME,SMESH.FT_ElemGeomType,'=',SMESH.Geom_PENTA)"<<endl;
+ if (py) {
+ *py << "mesh.GroupOnFilter(SMESH.VOLUME,'Viscous Prisms',"
+ "smesh.GetFilter(SMESH.VOLUME,SMESH.FT_ElemGeomType,'=',SMESH.Geom_PENTA))"<<endl;
+ *py << "mesh.GroupOnFilter(SMESH.VOLUME,'Neg Volumes',"
+ "smesh.GetFilter(SMESH.VOLUME,SMESH.FT_Volume3D,'<',0))"<<endl;
+ }
delete py; py=0;
}
- ~PyDump() { Finish(); }
+ ~PyDump() { Finish(); cout << "NB FUNCTIONS: " << theNbFunc << endl; }
};
#define dumpFunction(f) { _dumpFunction(f, __LINE__);}
#define dumpMove(n) { _dumpMove(n, __LINE__);}
#define dumpCmd(txt) { _dumpCmd(txt, __LINE__);}
void _dumpFunction(const string& fun, int ln)
- { if (py) *py<< "def "<<fun<<"(): # "<< ln <<endl; cout<<fun<<"()"<<endl;}
+ { if (py) *py<< "def "<<fun<<"(): # "<< ln <<endl; cout<<fun<<"()"<<endl; ++theNbFunc; }
void _dumpMove(const SMDS_MeshNode* n, int ln)
{ if (py) *py<< " mesh.MoveNode( "<<n->GetID()<< ", "<< n->X()
<< ", "<<n->Y()<<", "<< n->Z()<< ")\t\t # "<< ln <<endl; }
{ if (py) { *py<< " mesh.ChangeElemNodes( " << f->GetID()<<", [";
for ( int i=1; i < f->NbNodes(); ++i ) *py << f->GetNode(i-1)->GetID()<<", ";
*py << f->GetNode( f->NbNodes()-1 )->GetID() << " ])"<< endl; }}
+#define debugMsg( txt ) { cout << txt << " (line: " << __LINE__ << ")" << endl; }
#else
struct PyDump { void Finish() {} };
#define dumpFunction(f) f
#define dumpCmd(txt)
#define dumpFunctionEnd()
#define dumpChangeNodes(f)
+#define debugMsg( txt ) {}
#endif
}
}
}
+ // add FACEs of other SOLIDs to _ignoreFaceIds
+ for ( size_t i = 0; i < _sdVec.size(); ++i )
+ {
+ shapes.Clear();
+ TopExp::MapShapes(_sdVec[i]._solid, TopAbs_FACE, shapes);
+
+ for ( exp.Init( _mesh->GetShapeToMesh(), TopAbs_FACE ); exp.More(); exp.Next() )
+ {
+ if ( !shapes.Contains( exp.Current() ))
+ _sdVec[i]._ignoreFaceIds.insert( getMeshDS()->ShapeToIndex( exp.Current() ));
+ }
+ }
+
return true;
}
}
// make a map to find new nodes on sub-shapes shared with other SOLID
- map< TGeomID, TNode2Edge* > s2neMap;
map< TGeomID, TNode2Edge* >::iterator s2ne;
map< TGeomID, TopoDS_Shape >::iterator s2s = data._shrinkShape2Shape.begin();
for (; s2s != data._shrinkShape2Shape.end(); ++s2s )
if ( s2s2 != _sdVec[i]._shrinkShape2Shape.end() &&
*s2s == *s2s2 && !_sdVec[i]._n2eMap.empty() )
{
- s2neMap.insert( make_pair( shapeInd, &_sdVec[i]._n2eMap ));
+ data._s2neMap.insert( make_pair( shapeInd, &_sdVec[i]._n2eMap ));
break;
}
}
const SMDS_MeshElement* face = eIt->next();
newNodes.resize( face->NbCornerNodes() );
double faceMaxCosin = -1;
+ _LayerEdge* maxCosinEdge = 0;
for ( int i = 0 ; i < face->NbCornerNodes(); ++i )
{
const SMDS_MeshNode* n = face->GetNode(i);
const int shapeID = n->getshapeId();
edgesByGeom[ shapeID ].push_back( edge );
+ SMESH_TNodeXYZ xyz( n );
+
// set edge data or find already refined _LayerEdge and get data from it
if ( n->GetPosition()->GetTypeOfPosition() != SMDS_TOP_FACE &&
- ( s2ne = s2neMap.find( shapeID )) != s2neMap.end() &&
+ ( s2ne = data._s2neMap.find( shapeID )) != data._s2neMap.end() &&
( n2e2 = (*s2ne).second->find( n )) != s2ne->second->end())
{
_LayerEdge* foundEdge = (*n2e2).second;
- edge->Copy( *foundEdge, helper );
- // location of the last node is modified but we can restore
- // it by node position on _sWOL stored by the node
+ gp_XYZ lastPos = edge->Copy( *foundEdge, helper );
+ foundEdge->_pos.push_back( lastPos );
+ // location of the last node is modified and we restore it by foundEdge->_pos.back()
const_cast< SMDS_MeshNode* >
- ( edge->_nodes.back() )->setXYZ( n->X(), n->Y(), n->Z() );
+ ( edge->_nodes.back() )->setXYZ( xyz.X(), xyz.Y(), xyz.Z() );
}
else
{
- edge->_nodes.push_back( helper.AddNode( n->X(), n->Y(), n->Z() ));
+ edge->_nodes.push_back( helper.AddNode( xyz.X(), xyz.Y(), xyz.Z() ));
if ( !setEdgeData( *edge, subIds, helper, data ))
return false;
}
dumpMove(edge->_nodes.back());
- if ( edge->_cosin > 0.01 )
+
+ if ( edge->_cosin > faceMaxCosin )
{
- if ( edge->_cosin > faceMaxCosin )
- faceMaxCosin = edge->_cosin;
+ faceMaxCosin = edge->_cosin;
+ maxCosinEdge = edge;
}
}
newNodes[ i ] = n2e->second->_nodes.back();
}
// create a temporary face
- const SMDS_MeshElement* newFace = new TmpMeshFace( newNodes, --_tmpFaceID );
+ const SMDS_MeshElement* newFace =
+ new _TmpMeshFace( newNodes, --_tmpFaceID, face->getshapeId() );
proxySub->AddElement( newFace );
// compute inflation step size by min size of element on a convex surface
- if ( faceMaxCosin > 0.1 )
- limitStepSize( data, face, faceMaxCosin );
+ if ( faceMaxCosin > theMinSmoothCosin )
+ limitStepSize( data, face, maxCosinEdge );
} // loop on 2D elements on a FACE
} // loop on FACEs of a SOLID
data._epsilon *= data._stepSize;
// Put _LayerEdge's into the vector data._edges
-
if ( !sortEdges( data, edgesByGeom ))
return false;
- // Set target nodes into _Simplex and _2NearEdges
+ // limit data._stepSize depending on surface curvature and fill data._convexFaces
+ limitStepSizeByCurvature( data ); // !!! it must be before node substitution in _Simplex
+
+ // Set target nodes into _Simplex and _2NearEdges of _LayerEdge's
TNode2Edge::iterator n2e;
for ( size_t i = 0; i < data._edges.size(); ++i )
{
n = (*n2e).second->_nodes.back();
data._edges[i]->_2neibors->_edges[j] = n2e->second;
}
- else
- for ( size_t j = 0; j < data._edges[i]->_simplices.size(); ++j )
- {
- _Simplex& s = data._edges[i]->_simplices[j];
- s._nNext = data._n2eMap[ s._nNext ]->_nodes.back();
- s._nPrev = data._n2eMap[ s._nPrev ]->_nodes.back();
- }
+ //else
+ for ( size_t j = 0; j < data._edges[i]->_simplices.size(); ++j )
+ {
+ _Simplex& s = data._edges[i]->_simplices[j];
+ s._nNext = data._n2eMap[ s._nNext ]->_nodes.back();
+ s._nPrev = data._n2eMap[ s._nPrev ]->_nodes.back();
+ }
}
dumpFunctionEnd();
void _ViscousBuilder::limitStepSize( _SolidData& data,
const SMDS_MeshElement* face,
- const double cosin)
+ const _LayerEdge* maxCosinEdge )
{
int iN = 0;
double minSize = 10 * data._stepSize;
for ( int i = 0; i < nbNodes; ++i )
{
const SMDS_MeshNode* nextN = face->GetNode( SMESH_MesherHelper::WrapIndex( i+1, nbNodes ));
- const SMDS_MeshNode* curN = face->GetNode( i );
+ const SMDS_MeshNode* curN = face->GetNode( i );
if ( nextN->GetPosition()->GetTypeOfPosition() == SMDS_TOP_FACE ||
- curN->GetPosition()->GetTypeOfPosition() == SMDS_TOP_FACE )
+ curN-> GetPosition()->GetTypeOfPosition() == SMDS_TOP_FACE )
{
- double dist = SMESH_TNodeXYZ( face->GetNode(i)).Distance( nextN );
+ double dist = SMESH_TNodeXYZ( curN ).Distance( nextN );
if ( dist < minSize )
minSize = dist, iN = i;
}
}
- double newStep = 0.8 * minSize / cosin;
+ double newStep = 0.8 * minSize / maxCosinEdge->_lenFactor;
if ( newStep < data._stepSize )
{
data._stepSize = newStep;
- data._stepSizeCoeff = 0.8 / cosin;
+ data._stepSizeCoeff = 0.8 / maxCosinEdge->_lenFactor;
data._stepSizeNodes[0] = face->GetNode( iN );
data._stepSizeNodes[1] = face->GetNode( SMESH_MesherHelper::WrapIndex( iN+1, nbNodes ));
}
*/
//================================================================================
-void _ViscousBuilder::limitStepSize( _SolidData& data, const double minSize)
+void _ViscousBuilder::limitStepSize( _SolidData& data, const double minSize )
{
if ( minSize < data._stepSize )
{
}
}
+//================================================================================
+/*!
+ * \brief Limit data._stepSize by evaluating curvature of shapes and fill data._convexFaces
+ */
+//================================================================================
+
+void _ViscousBuilder::limitStepSizeByCurvature( _SolidData& data )
+{
+ const int nbTestPnt = 5; // on a FACE sub-shape
+ const double minCurvature = 0.9 / data._hyp->GetTotalThickness();
+
+ BRepLProp_SLProps surfProp( 2, 1e-6 );
+ SMESH_MesherHelper helper( *_mesh );
+
+ data._convexFaces.clear();
+
+ TopExp_Explorer face( data._solid, TopAbs_FACE );
+ for ( ; face.More(); face.Next() )
+ {
+ const TopoDS_Face& F = TopoDS::Face( face.Current() );
+ BRepAdaptor_Surface surface( F, false );
+ surfProp.SetSurface( surface );
+
+ bool isTooCurved = false;
+ int iBeg, iEnd;
+
+ _ConvexFace cnvFace;
+ SMESH_subMesh * sm = _mesh->GetSubMesh( F );
+ const TGeomID faceID = sm->GetId();
+ if ( data._ignoreFaceIds.count( faceID )) continue;
+ const double oriFactor = ( F.Orientation() == TopAbs_REVERSED ? +1. : -1. );
+ SMESH_subMeshIteratorPtr smIt = sm->getDependsOnIterator(/*includeSelf=*/true);
+ while ( smIt->more() )
+ {
+ sm = smIt->next();
+ const TGeomID subID = sm->GetId();
+ // find _LayerEdge's of a sub-shape
+ size_t edgesEnd;
+ if ( data.GetShapeEdges( subID, edgesEnd, &iBeg, &iEnd ))
+ cnvFace._subIdToEdgeEnd.insert( make_pair( subID, edgesEnd ));
+ else
+ continue;
+ // check concavity and curvature and limit data._stepSize
+ int nbLEdges = iEnd - iBeg;
+ int step = Max( 1, nbLEdges / nbTestPnt );
+ for ( ; iBeg < iEnd; iBeg += step )
+ {
+ gp_XY uv = helper.GetNodeUV( F, data._edges[ iBeg ]->_nodes[0] );
+ surfProp.SetParameters( uv.X(), uv.Y() );
+ if ( !surfProp.IsCurvatureDefined() )
+ continue;
+ if ( surfProp.MaxCurvature() * oriFactor > minCurvature )
+ {
+ limitStepSize( data, 0.9 / surfProp.MaxCurvature() * oriFactor );
+ isTooCurved = true;
+ }
+ if ( surfProp.MinCurvature() * oriFactor > minCurvature )
+ {
+ limitStepSize( data, 0.9 / surfProp.MinCurvature() * oriFactor );
+ isTooCurved = true;
+ }
+ }
+ } // loop on sub-shapes of the FACE
+
+ if ( !isTooCurved ) continue;
+
+ _ConvexFace & convFace =
+ data._convexFaces.insert( make_pair( faceID, cnvFace )).first->second;
+
+ convFace._face = F;
+ convFace._normalsFixed = false;
+
+ // Fill _ConvexFace::_simplexTestEdges. These _LayerEdge's are used to detect
+ // prism distortion.
+ map< TGeomID, int >::iterator id2end = convFace._subIdToEdgeEnd.find( faceID );
+ if ( id2end != convFace._subIdToEdgeEnd.end() )
+ {
+ // there are _LayerEdge's on the FACE it-self;
+ // select _LayerEdge's near EDGEs
+ data.GetEdgesOnShape( id2end->second, iBeg, iEnd );
+ for ( ; iBeg < iEnd; ++iBeg )
+ {
+ _LayerEdge* ledge = data._edges[ iBeg ];
+ for ( size_t j = 0; j < ledge->_simplices.size(); ++j )
+ if ( ledge->_simplices[j]._nNext->GetPosition()->GetDim() < 2 )
+ {
+ convFace._simplexTestEdges.push_back( ledge );
+ break;
+ }
+ }
+ }
+ else
+ {
+ // where there are no _LayerEdge's on a _ConvexFace,
+ // as e.g. on a fillet surface with no internal nodes - issue 22580,
+ // so that collision of viscous internal faces is not detected by check of
+ // intersection of _LayerEdge's with the viscous internal faces.
+
+ set< const SMDS_MeshNode* > usedNodes;
+
+ // look for _LayerEdge's with null _sWOL
+ map< TGeomID, int >::iterator id2end = convFace._subIdToEdgeEnd.begin();
+ for ( ; id2end != convFace._subIdToEdgeEnd.end(); ++id2end )
+ {
+ data.GetEdgesOnShape( id2end->second, iBeg, iEnd );
+ if ( iBeg >= iEnd || !data._edges[ iBeg ]->_sWOL.IsNull() )
+ continue;
+ for ( ; iBeg < iEnd; ++iBeg )
+ {
+ _LayerEdge* ledge = data._edges[ iBeg ];
+ const SMDS_MeshNode* srcNode = ledge->_nodes[0];
+ if ( !usedNodes.insert( srcNode ).second ) continue;
+
+ getSimplices( srcNode, ledge->_simplices, data._ignoreFaceIds, &data );
+ for ( size_t i = 0; i < ledge->_simplices.size(); ++i )
+ {
+ usedNodes.insert( ledge->_simplices[i]._nPrev );
+ usedNodes.insert( ledge->_simplices[i]._nNext );
+ }
+ convFace._simplexTestEdges.push_back( ledge );
+ }
+ }
+ }
+ } // loop on FACEs of data._solid
+}
+
//================================================================================
/*!
* \brief Separate shapes (and _LayerEdge's on them) to smooth from the rest ones
{
vector<_LayerEdge*>& eS = edgesByGeom[iS];
if ( eS.empty() ) continue;
- TopoDS_Shape S = getMeshDS()->IndexToShape( iS );
+ const TopoDS_Shape& S = getMeshDS()->IndexToShape( iS );
bool needSmooth = false;
switch ( S.ShapeType() )
{
TGeomID iV = getMeshDS()->ShapeToIndex( vIt.Value() );
vector<_LayerEdge*>& eV = edgesByGeom[ iV ];
if ( eV.empty() ) continue;
- double cosin = eV[0]->_cosin;
- bool badCosin =
- ( !eV[0]->_sWOL.IsNull() && ( eV[0]->_sWOL.ShapeType() == TopAbs_EDGE || !isShrinkEdge));
- if ( badCosin )
- {
- gp_Vec dir1, dir2;
- if ( eV[0]->_sWOL.ShapeType() == TopAbs_EDGE )
- dir1 = getEdgeDir( TopoDS::Edge( eV[0]->_sWOL ), TopoDS::Vertex( vIt.Value() ));
- else
- dir1 = getFaceDir( TopoDS::Face( eV[0]->_sWOL ), TopoDS::Vertex( vIt.Value() ),
- eV[0]->_nodes[0], helper, ok);
- dir2 = getEdgeDir( TopoDS::Edge( S ), TopoDS::Vertex( vIt.Value() ));
- double angle = dir1.Angle( dir2 );
- cosin = cos( angle );
- }
- needSmooth = ( cosin > 0.1 );
+ // double cosin = eV[0]->_cosin;
+ // bool badCosin =
+ // ( !eV[0]->_sWOL.IsNull() && ( eV[0]->_sWOL.ShapeType() == TopAbs_EDGE || !isShrinkEdge));
+ // if ( badCosin )
+ // {
+ // gp_Vec dir1, dir2;
+ // if ( eV[0]->_sWOL.ShapeType() == TopAbs_EDGE )
+ // dir1 = getEdgeDir( TopoDS::Edge( eV[0]->_sWOL ), TopoDS::Vertex( vIt.Value() ));
+ // else
+ // dir1 = getFaceDir( TopoDS::Face( eV[0]->_sWOL ), TopoDS::Vertex( vIt.Value() ),
+ // eV[0]->_nodes[0], helper, ok);
+ // dir2 = getEdgeDir( TopoDS::Edge( S ), TopoDS::Vertex( vIt.Value() ));
+ // double angle = dir1.Angle( dir2 );
+ // cosin = cos( angle );
+ // }
+ gp_Vec eDir = getEdgeDir( TopoDS::Edge( S ), TopoDS::Vertex( vIt.Value() ));
+ double angle = eDir.Angle( eV[0]->_normal );
+ double cosin = Cos( angle );
+ needSmooth = ( cosin > theMinSmoothCosin );
}
break;
}
if ( eE[0]->_sWOL.IsNull() )
{
for ( size_t i = 0; i < eE.size() && !needSmooth; ++i )
- needSmooth = ( eE[i]->_cosin > 0.1 );
+ needSmooth = ( eE[i]->_cosin > theMinSmoothCosin );
}
else
{
gp_Vec dir2 = getFaceDir( F2, E, eE[i]->_nodes[0], helper, ok );
double angle = dir1.Angle( dir2 );
double cosin = cos( angle );
- needSmooth = ( cosin > 0.1 );
+ needSmooth = ( cosin > theMinSmoothCosin );
}
}
}
} // loop on edgesByGeom
data._edges.reserve( data._n2eMap.size() );
- data._endEdgeToSmooth.clear();
+ data._endEdgeOnShape.clear();
// first we put _LayerEdge's on shapes to smooth
+ data._nbShapesToSmooth = 0;
list< TGeomID >::iterator gIt = shapesToSmooth.begin();
for ( ; gIt != shapesToSmooth.end(); ++gIt )
{
vector<_LayerEdge*>& eVec = edgesByGeom[ *gIt ];
if ( eVec.empty() ) continue;
data._edges.insert( data._edges.end(), eVec.begin(), eVec.end() );
- data._endEdgeToSmooth.push_back( data._edges.size() );
+ data._endEdgeOnShape.push_back( data._edges.size() );
+ data._nbShapesToSmooth++;
eVec.clear();
}
for ( size_t iS = 0; iS < edgesByGeom.size(); ++iS )
{
vector<_LayerEdge*>& eVec = edgesByGeom[iS];
+ if ( eVec.empty() ) continue;
data._edges.insert( data._edges.end(), eVec.begin(), eVec.end() );
- eVec.clear();
+ data._endEdgeOnShape.push_back( data._edges.size() );
+ //eVec.clear();
}
return ok;
const SMDS_MeshNode* node = edge._nodes[0]; // source node
SMDS_TypeOfPosition posType = node->GetPosition()->GetTypeOfPosition();
- edge._len = 0;
- edge._2neibors = 0;
+ edge._len = 0;
+ edge._2neibors = 0;
edge._curvature = 0;
// --------------------------
edge._normal.SetCoord(0,0,0);
int totalNbFaces = 0;
- gp_Pnt p;
- gp_Vec du, dv, geomNorm;
+ gp_Vec geomNorm;
bool normOK = true;
- TGeomID shapeInd = node->getshapeId();
+ const TGeomID shapeInd = node->getshapeId();
map< TGeomID, TopoDS_Shape >::const_iterator s2s = data._shrinkShape2Shape.find( shapeInd );
- bool onShrinkShape ( s2s != data._shrinkShape2Shape.end() );
- TopoDS_Shape vertEdge;
+ const bool onShrinkShape ( s2s != data._shrinkShape2Shape.end() );
if ( onShrinkShape ) // one of faces the node is on has no layers
{
- vertEdge = getMeshDS()->IndexToShape( s2s->first ); // vertex or edge
+ TopoDS_Shape vertEdge = getMeshDS()->IndexToShape( s2s->first ); // vertex or edge
if ( s2s->second.ShapeType() == TopAbs_EDGE )
{
// inflate from VERTEX along EDGE
set<TGeomID>::iterator id = faceIds.begin();
TopoDS_Face F;
+ std::pair< TGeomID, gp_XYZ > id2Norm[20];
for ( ; id != faceIds.end(); ++id )
{
const TopoDS_Shape& s = getMeshDS()->IndexToShape( *id );
if ( s.IsNull() || s.ShapeType() != TopAbs_FACE || !subIds.count( *id ))
continue;
- totalNbFaces++;
F = TopoDS::Face( s );
+ geomNorm = getFaceNormal( node, F, helper, normOK );
+ if ( !normOK ) continue;
- // IDEA: if there is a problem with finding a normal,
- // we can compute an area-weighted sum of normals of all faces sharing the node
- gp_XY uv = helper.GetNodeUV( F, node, 0, &normOK );
- Handle(Geom_Surface) surface = BRep_Tool::Surface( F );
- surface->D1( uv.X(), uv.Y(), p, du,dv );
- geomNorm = du ^ dv;
- double size2 = geomNorm.SquareMagnitude();
- if ( size2 < 1e-10 ) // singularity
- {
- SMDS_ElemIteratorPtr fIt = node->GetInverseElementIterator(SMDSAbs_Face);
- while ( fIt->more() )
- {
- const SMDS_MeshElement* f = fIt->next();
- if ( editor.FindShape( f ) == *id )
- {
- SMESH_MeshAlgos::FaceNormal( f, (gp_XYZ&) geomNorm.XYZ(), /*normalized=*/false );
- size2 = geomNorm.SquareMagnitude();
- break;
- }
- }
- // double ddu = 0, ddv = 0;
- // if ( du.SquareMagnitude() > dv.SquareMagnitude() )
- // ddu = 1e-3;
- // else
- // ddv = 1e-3;
- // surface->D1( uv.X()+ddu, uv.Y()+ddv, p, du,dv );
- // geomNorm = du ^ dv;
- // size2 = geomNorm.SquareMagnitude();
- // if ( size2 < 1e-10 )
- // {
- // surface->D1( uv.X()-ddu, uv.Y()-ddv, p, du,dv );
- // geomNorm = du ^ dv;
- // size2 = geomNorm.SquareMagnitude();
- // }
- }
- if ( size2 > numeric_limits<double>::min() )
- geomNorm /= sqrt( size2 );
- else
- normOK = false;
if ( helper.GetSubShapeOri( data._solid, F ) != TopAbs_REVERSED )
geomNorm.Reverse();
+ id2Norm[ totalNbFaces ].first = *id;
+ id2Norm[ totalNbFaces ].second = geomNorm.XYZ();
+ totalNbFaces++;
edge._normal += geomNorm.XYZ();
}
if ( totalNbFaces == 0 )
return error(SMESH_Comment("Can't get normal to node ") << node->GetID(), data._index);
- edge._normal /= totalNbFaces;
+ if ( normOK && edge._normal.Modulus() < 1e-3 && totalNbFaces > 1 )
+ {
+ // opposite normals, re-get normals at shifted positions (IPAL 52426)
+ edge._normal.SetCoord( 0,0,0 );
+ for ( int i = 0; i < totalNbFaces; ++i )
+ {
+ const TopoDS_Face& F = TopoDS::Face( getMeshDS()->IndexToShape( id2Norm[i].first ));
+ geomNorm = getFaceNormal( node, F, helper, normOK, /*shiftInside=*/true );
+ if ( helper.GetSubShapeOri( data._solid, F ) != TopAbs_REVERSED )
+ geomNorm.Reverse();
+ if ( normOK )
+ id2Norm[ i ].second = geomNorm.XYZ();
+ edge._normal += id2Norm[ i ].second;
+ }
+ }
+
+ if ( totalNbFaces < 3 )
+ {
+ //edge._normal /= totalNbFaces;
+ }
+ else
+ {
+ edge._normal = getWeigthedNormal( node, id2Norm, totalNbFaces );
+ }
switch ( posType )
{
case SMDS_TOP_EDGE: {
TopoDS_Edge E = TopoDS::Edge( helper.GetSubShapeByNode( node, getMeshDS()));
- gp_Vec inFaceDir = getFaceDir( F, E, node, helper, normOK);
+ gp_Vec inFaceDir = getFaceDir( F, E, node, helper, normOK );
double angle = inFaceDir.Angle( edge._normal ); // [0,PI]
edge._cosin = cos( angle );
//cout << "Cosin on EDGE " << edge._cosin << " node " << node->GetID() << endl;
}
case SMDS_TOP_VERTEX: {
TopoDS_Vertex V = TopoDS::Vertex( helper.GetSubShapeByNode( node, getMeshDS()));
- gp_XYZ inFaceDir = getFaceDir( F, V, node, helper, normOK);
- double angle = gp_Vec( inFaceDir).Angle( edge._normal ); // [0,PI]
+ gp_Vec inFaceDir = getFaceDir( F, V, node, helper, normOK );
+ double angle = inFaceDir.Angle( edge._normal ); // [0,PI]
edge._cosin = cos( angle );
//cout << "Cosin on VERTEX " << edge._cosin << " node " << node->GetID() << endl;
break;
default:
return error(SMESH_Comment("Invalid shape position of node ")<<node, data._index);
}
- }
+ } // case _sWOL.IsNull()
double normSize = edge._normal.SquareModulus();
if ( normSize < numeric_limits<double>::min() )
return true;
}
+//================================================================================
+/*!
+ * \brief Return normal to a FACE at a node
+ * \param [in] n - node
+ * \param [in] face - FACE
+ * \param [in] helper - helper
+ * \param [out] isOK - true or false
+ * \param [in] shiftInside - to find normal at a position shifted inside the face
+ * \return gp_XYZ - normal
+ */
+//================================================================================
+
+gp_XYZ _ViscousBuilder::getFaceNormal(const SMDS_MeshNode* node,
+ const TopoDS_Face& face,
+ SMESH_MesherHelper& helper,
+ bool& isOK,
+ bool shiftInside)
+{
+ gp_XY uv;
+ if ( shiftInside )
+ {
+ // get a shifted position
+ gp_Pnt p = SMESH_TNodeXYZ( node );
+ gp_XYZ shift( 0,0,0 );
+ TopoDS_Shape S = helper.GetSubShapeByNode( node, helper.GetMeshDS() );
+ switch ( S.ShapeType() ) {
+ case TopAbs_VERTEX:
+ {
+ shift = getFaceDir( face, TopoDS::Vertex( S ), node, helper, isOK );
+ break;
+ }
+ case TopAbs_EDGE:
+ {
+ shift = getFaceDir( face, TopoDS::Edge( S ), node, helper, isOK );
+ break;
+ }
+ default:
+ isOK = false;
+ }
+ if ( isOK )
+ shift.Normalize();
+ p.Translate( shift * 1e-5 );
+
+ TopLoc_Location loc;
+ GeomAPI_ProjectPointOnSurf& projector = helper.GetProjector( face, loc, 1e-7 );
+
+ if ( !loc.IsIdentity() ) p.Transform( loc.Transformation().Inverted() );
+
+ projector.Perform( p );
+ if ( !projector.IsDone() || projector.NbPoints() < 1 )
+ {
+ isOK = false;
+ return p.XYZ();
+ }
+ Quantity_Parameter U,V;
+ projector.LowerDistanceParameters(U,V);
+ uv.SetCoord( U,V );
+ }
+ else
+ {
+ uv = helper.GetNodeUV( face, node, 0, &isOK );
+ }
+
+ gp_Dir normal;
+ isOK = false;
+
+ Handle(Geom_Surface) surface = BRep_Tool::Surface( face );
+ if ( GeomLib::NormEstim( surface, uv, 1e-10, normal ) < 3 )
+ {
+ normal;
+ isOK = true;
+ }
+ else // hard singularity
+ {
+ const TGeomID faceID = helper.GetMeshDS()->ShapeToIndex( face );
+
+ SMDS_ElemIteratorPtr fIt = node->GetInverseElementIterator(SMDSAbs_Face);
+ while ( fIt->more() )
+ {
+ const SMDS_MeshElement* f = fIt->next();
+ if ( f->getshapeId() == faceID )
+ {
+ isOK = SMESH_MeshAlgos::FaceNormal( f, (gp_XYZ&) normal.XYZ(), /*normalized=*/true );
+ if ( isOK )
+ {
+ if ( helper.IsReversedSubMesh( face ))
+ normal.Reverse();
+ break;
+ }
+ }
+ }
+ }
+ return normal.XYZ();
+}
+
+//================================================================================
+/*!
+ * \brief Return a normal at a node weighted with angles taken by FACEs
+ * \param [in] n - the node
+ * \param [in] fId2Normal - FACE ids and normals
+ * \param [in] nbFaces - nb of FACEs meeting at the node
+ * \return gp_XYZ - computed normal
+ */
+//================================================================================
+
+gp_XYZ _ViscousBuilder::getWeigthedNormal( const SMDS_MeshNode* n,
+ std::pair< TGeomID, gp_XYZ > fId2Normal[],
+ const int nbFaces )
+{
+ gp_XYZ resNorm(0,0,0);
+ TopoDS_Shape V = SMESH_MesherHelper::GetSubShapeByNode( n, getMeshDS() );
+ if ( V.ShapeType() != TopAbs_VERTEX )
+ {
+ for ( int i = 0; i < nbFaces; ++i )
+ resNorm += fId2Normal[i].second / nbFaces ;
+ return resNorm;
+ }
+
+ double angles[30];
+ for ( int i = 0; i < nbFaces; ++i )
+ {
+ const TopoDS_Face& F = TopoDS::Face( getMeshDS()->IndexToShape( fId2Normal[i].first ));
+
+ // look for two EDGEs shared by F and other FACEs within fId2Normal
+ TopoDS_Edge ee[2];
+ int nbE = 0;
+ PShapeIteratorPtr eIt = SMESH_MesherHelper::GetAncestors( V, *_mesh, TopAbs_EDGE );
+ while ( const TopoDS_Shape* E = eIt->next() )
+ {
+ if ( !SMESH_MesherHelper::IsSubShape( *E, F ))
+ continue;
+ bool isSharedEdge = false;
+ for ( int j = 0; j < nbFaces && !isSharedEdge; ++j )
+ {
+ if ( i == j ) continue;
+ const TopoDS_Shape& otherF = getMeshDS()->IndexToShape( fId2Normal[j].first );
+ isSharedEdge = SMESH_MesherHelper::IsSubShape( *E, otherF );
+ }
+ if ( !isSharedEdge )
+ continue;
+ ee[ nbE ] = TopoDS::Edge( *E );
+ ee[ nbE ].Orientation( SMESH_MesherHelper::GetSubShapeOri( F, *E ));
+ if ( ++nbE == 2 )
+ break;
+ }
+
+ // get an angle between the two EDGEs
+ angles[i] = 0;
+ if ( nbE < 1 ) continue;
+ if ( nbE == 1 )
+ {
+ ee[ 1 ] == ee[ 0 ];
+ }
+ else
+ {
+ TopoDS_Vertex v10 = SMESH_MesherHelper::IthVertex( 1, ee[ 0 ]);
+ TopoDS_Vertex v01 = SMESH_MesherHelper::IthVertex( 0, ee[ 1 ]);
+ if ( !v10.IsSame( v01 ))
+ std::swap( ee[0], ee[1] );
+ }
+ angles[i] = SMESH_MesherHelper::GetAngle( ee[0], ee[1], F );
+ }
+
+ // compute a weighted normal
+ double sumAngle = 0;
+ for ( int i = 0; i < nbFaces; ++i )
+ {
+ angles[i] = ( angles[i] > 2*M_PI ) ? 0 : M_PI - angles[i];
+ sumAngle += angles[i];
+ }
+ for ( int i = 0; i < nbFaces; ++i )
+ resNorm += angles[i] / sumAngle * fId2Normal[i].second;
+
+ return resNorm;
+}
+
//================================================================================
/*!
* \brief Find 2 neigbor nodes of a node on EDGE
double avgLen = 0.5 * ( vec1.Modulus() + vec2.Modulus() );
if ( _curvature ) delete _curvature;
_curvature = _Curvature::New( avgNormProj, avgLen );
-#ifdef __myDEBUG
-// if ( _curvature )
-// cout << _nodes[0]->GetID()
-// << " CURV r,k: " << _curvature->_r<<","<<_curvature->_k
-// << " proj = "<<avgNormProj<< " len = " << avgLen << "| lenDelta(0) = "
-// << _curvature->lenDelta(0) << endl;
-#endif
+ // if ( _curvature )
+ // debugMsg( _nodes[0]->GetID()
+ // << " CURV r,k: " << _curvature->_r<<","<<_curvature->_k
+ // << " proj = "<<avgNormProj<< " len = " << avgLen << "| lenDelta(0) = "
+ // << _curvature->lenDelta(0) );
// Set _plnNorm
*/
//================================================================================
-void _LayerEdge::Copy( _LayerEdge& other, SMESH_MesherHelper& helper )
+gp_XYZ _LayerEdge::Copy( _LayerEdge& other, SMESH_MesherHelper& helper )
{
_nodes = other._nodes;
_normal = other._normal;
_curvature = 0; std::swap( _curvature, other._curvature );
_2neibors = 0; std::swap( _2neibors, other._2neibors );
+ gp_XYZ lastPos( 0,0,0 );
if ( _sWOL.ShapeType() == TopAbs_EDGE )
{
double u = helper.GetNodeU( TopoDS::Edge( _sWOL ), _nodes[0] );
_pos.push_back( gp_XYZ( u, 0, 0));
+
+ u = helper.GetNodeU( TopoDS::Edge( _sWOL ), _nodes.back() );
+ lastPos.SetX( u );
}
else // TopAbs_FACE
{
gp_XY uv = helper.GetNodeUV( TopoDS::Face( _sWOL ), _nodes[0]);
_pos.push_back( gp_XYZ( uv.X(), uv.Y(), 0));
+
+ uv = helper.GetNodeUV( TopoDS::Face( _sWOL ), _nodes.back() );
+ lastPos.SetX( uv.X() );
+ lastPos.SetY( uv.Y() );
}
+ return lastPos;
}
//================================================================================
void _LayerEdge::SetCosin( double cosin )
{
_cosin = cosin;
- _lenFactor = ( _cosin > 0.1 ) ? 1./sqrt(1-_cosin*_cosin) : 1.0;
+ cosin = Abs( _cosin );
+ _lenFactor = ( /*0.1 < cosin &&*/ cosin < 1-1e-12 ) ? 1./sqrt(1-cosin*cosin) : 1.0;
}
//================================================================================
for ( size_t i = 0 ; i < _sdVec.size(); ++i )
{
if ( _sdVec[i]._edges.empty() ) continue;
-// string name = SMESH_Comment("_LayerEdge's_") << i;
-// int id;
-// SMESH_Group* g = _mesh->AddGroup(SMDSAbs_Edge, name.c_str(), id );
-// SMESHDS_Group* gDS = (SMESHDS_Group*)g->GetGroupDS();
-// SMESHDS_Mesh* mDS = _mesh->GetMeshDS();
dumpFunction( SMESH_Comment("make_LayerEdge_") << i );
for ( size_t j = 0 ; j < _sdVec[i]._edges.size(); ++j )
for ( size_t iN = 1; iN < le->_nodes.size(); ++iN )
dumpCmd(SMESH_Comment("mesh.AddEdge([ ") <<le->_nodes[iN-1]->GetID()
<< ", " << le->_nodes[iN]->GetID() <<"])");
- //gDS->SMDSGroup().Add( mDS->AddEdge( le->_nodes[iN-1], le->_nodes[iN]));
}
dumpFunctionEnd();
}
dumpFunctionEnd();
-// name = SMESH_Comment("tmp_faces ") << i;
-// g = _mesh->AddGroup(SMDSAbs_Face, name.c_str(), id );
-// gDS = (SMESHDS_Group*)g->GetGroupDS();
-// SMESH_MeshEditor editor( _mesh );
dumpFunction( SMESH_Comment("makeTmpFaces_") << i );
TopExp_Explorer fExp( _sdVec[i]._solid, TopAbs_FACE );
for ( ; fExp.More(); fExp.Next() )
for ( int j=0; j < e->NbCornerNodes(); ++j )
cmd << e->GetNode(j)->GetID() << (j+1<e->NbCornerNodes() ? ",": "])");
dumpCmd( cmd );
- //vector<const SMDS_MeshNode*> nodes( e->begin_nodes(), e->end_nodes() );
- //gDS->SMDSGroup().Add( editor.AddElement( nodes, e->GetType(), e->IsPoly()));
}
}
}
if ( data._stepSize < 1. )
data._epsilon = data._stepSize * 1e-7;
-#ifdef __myDEBUG
- cout << "-- geomSize = " << geomSize << ", stepSize = " << data._stepSize << endl;
-#endif
+ debugMsg( "-- geomSize = " << geomSize << ", stepSize = " << data._stepSize );
double avgThick = 0, curThick = 0, distToIntersection = Precision::Infinite();
int nbSteps = 0, nbRepeats = 0;
}
dumpFunctionEnd();
- if ( !nbSteps )
- if ( !updateNormals( data, helper ) )
- return false;
+ if ( !updateNormals( data, helper, nbSteps ))
+ return false;
// Improve and check quality
if ( !smoothAndCheck( data, nbSteps, distToIntersection ))
for ( size_t i = 0; i < data._edges.size(); ++i )
avgThick += data._edges[i]->_len;
avgThick /= data._edges.size();
-#ifdef __myDEBUG
- cout << "-- Thickness " << avgThick << " reached" << endl;
-#endif
+ debugMsg( "-- Thickness " << avgThick << " reached" );
if ( distToIntersection < avgThick*1.5 )
{
-#ifdef __myDEBUG
- cout << "-- Stop inflation since distToIntersection( "<<distToIntersection<<" ) < avgThick( "
- << avgThick << " ) * 1.5" << endl;
-#endif
+ debugMsg( "-- Stop inflation since "
+ << " distToIntersection( "<<distToIntersection<<" ) < avgThick( "
+ << avgThick << " ) * 1.5" );
break;
}
// new step size
if ( data._stepSizeNodes[0] )
data._stepSize = data._stepSizeCoeff *
SMESH_TNodeXYZ(data._stepSizeNodes[0]).Distance(data._stepSizeNodes[1]);
- }
+
+ } // while ( 1.01 * avgThick < tgtThick )
if (nbSteps == 0 )
return error("failed at the very first inflation step", data._index);
+ if ( 1.01 * avgThick < tgtThick )
+ if ( SMESH_subMesh* sm = _mesh->GetSubMeshContaining( data._index ))
+ {
+ SMESH_ComputeErrorPtr& smError = sm->GetComputeError();
+ if ( !smError || smError->IsOK() )
+ smError.reset
+ ( new SMESH_ComputeError (COMPERR_WARNING,
+ SMESH_Comment("Thickness ") << tgtThick <<
+ " of viscous layers not reached,"
+ " average reached thickness is " << avgThick ));
+ }
+
return true;
}
const int nbSteps,
double & distToIntersection)
{
- if ( data._endEdgeToSmooth.empty() )
+ if ( data._nbShapesToSmooth == 0 )
return true; // no shapes needing smoothing
bool moved, improved;
TopoDS_Face F;
int iBeg, iEnd = 0;
- for ( size_t iS = 0; iS < data._endEdgeToSmooth.size(); ++iS )
+ for ( int iS = 0; iS < data._nbShapesToSmooth; ++iS )
{
iBeg = iEnd;
- iEnd = data._endEdgeToSmooth[ iS ];
+ iEnd = data._endEdgeOnShape[ iS ];
if ( !data._edges[ iBeg ]->_sWOL.IsNull() &&
data._edges[ iBeg ]->_sWOL.ShapeType() == TopAbs_FACE )
dumpCmd( SMESH_Comment("# end step ")<<step);
}
while ( moved && step++ < 5 );
- //cout << " NB STEPS: " << step << endl;
}
dumpFunctionEnd();
}
else
{
// smooth on FACE's
- int step = 0, badNb = 0; moved = true;
- while (( ++step <= 5 && moved ) || improved )
+ int step = 0, stepLimit = 5, badNb = 0; moved = true;
+ while (( ++step <= stepLimit && moved ) || improved )
{
dumpFunction(SMESH_Comment("smooth")<<data._index<<"_Fa"<<sInd
<<"_InfStep"<<nbSteps<<"_"<<step); // debug
int oldBadNb = badNb;
badNb = 0;
moved = false;
- for ( int i = iBeg; i < iEnd; ++i )
- moved |= data._edges[i]->Smooth(badNb);
+ if ( step % 2 )
+ for ( int i = iBeg; i < iEnd; ++i )
+ moved |= data._edges[i]->Smooth(badNb);
+ else
+ for ( int i = iEnd-1; i >= iBeg; --i )
+ moved |= data._edges[i]->Smooth(badNb);
improved = ( badNb < oldBadNb );
+ // issue 22576 -- no bad faces but still there are intersections to fix
+ if ( improved && badNb == 0 )
+ stepLimit = step + 3;
+
dumpFunctionEnd();
}
if ( badNb > 0 )
}
} // loop on shapes to smooth
+ // Check orientation of simplices of _ConvexFace::_simplexTestEdges
+ map< TGeomID, _ConvexFace >::iterator id2face = data._convexFaces.begin();
+ for ( ; id2face != data._convexFaces.end(); ++id2face )
+ {
+ _ConvexFace & convFace = (*id2face).second;
+ if ( !convFace._simplexTestEdges.empty() &&
+ convFace._simplexTestEdges[0]->_nodes[0]->GetPosition()->GetDim() == 2 )
+ continue; // _simplexTestEdges are based on FACE -- already checked while smoothing
+
+ if ( !convFace.CheckPrisms() )
+ return false;
+ }
+
// Check if the last segments of _LayerEdge intersects 2D elements;
// checked elements are either temporary faces or faces on surfaces w/o the layers
distToIntersection = Precision::Infinite();
double dist;
const SMDS_MeshElement* intFace = 0;
-#ifdef __myDEBUG
const SMDS_MeshElement* closestFace = 0;
int iLE = 0;
-#endif
for ( size_t i = 0; i < data._edges.size(); ++i )
{
+ if ( !data._edges[i]->_sWOL.IsNull() )
+ continue;
if ( data._edges[i]->FindIntersection( *searcher, dist, data._epsilon, &intFace ))
return false;
if ( distToIntersection > dist )
{
- distToIntersection = dist;
-#ifdef __myDEBUG
+ // ignore intersection of a _LayerEdge based on a _ConvexFace with a face
+ // lying on this _ConvexFace
+ if ( _ConvexFace* convFace = data.GetConvexFace( intFace->getshapeId() ))
+ if ( convFace->_subIdToEdgeEnd.count ( data._edges[i]->_nodes[0]->getshapeId() ))
+ continue;
+
+ distToIntersection = dist;
iLE = i;
closestFace = intFace;
-#endif
}
}
#ifdef __myDEBUG
if ( i2curve == _edge2curve.end() )
{
// sort _LayerEdge's by position on the EDGE
- {
- map< double, _LayerEdge* > u2edge;
- for ( int i = iFrom; i < iTo; ++i )
- u2edge.insert( make_pair( helper.GetNodeU( E, _edges[i]->_nodes[0] ), _edges[i] ));
-
- ASSERT( u2edge.size() == iTo - iFrom );
- map< double, _LayerEdge* >::iterator u2e = u2edge.begin();
- for ( int i = iFrom; i < iTo; ++i, ++u2e )
- _edges[i] = u2e->second;
-
- // set _2neibors according to the new order
- for ( int i = iFrom; i < iTo-1; ++i )
- if ( _edges[i]->_2neibors->_nodes[1] != _edges[i+1]->_nodes.back() )
- _edges[i]->_2neibors->reverse();
- if ( u2edge.size() > 1 &&
- _edges[iTo-1]->_2neibors->_nodes[0] != _edges[iTo-2]->_nodes.back() )
- _edges[iTo-1]->_2neibors->reverse();
- }
+ SortOnEdge( E, iFrom, iTo, helper );
SMESHDS_SubMesh* smDS = helper.GetMeshDS()->MeshElements( eIndex );
return i2curve->second;
}
+//================================================================================
+/*!
+ * \brief Sort _LayerEdge's by a parameter on a given EDGE
+ */
+//================================================================================
+
+void _SolidData::SortOnEdge( const TopoDS_Edge& E,
+ const int iFrom,
+ const int iTo,
+ SMESH_MesherHelper& helper)
+{
+ map< double, _LayerEdge* > u2edge;
+ for ( int i = iFrom; i < iTo; ++i )
+ u2edge.insert( make_pair( helper.GetNodeU( E, _edges[i]->_nodes[0] ), _edges[i] ));
+
+ ASSERT( u2edge.size() == iTo - iFrom );
+ map< double, _LayerEdge* >::iterator u2e = u2edge.begin();
+ for ( int i = iFrom; i < iTo; ++i, ++u2e )
+ _edges[i] = u2e->second;
+
+ // set _2neibors according to the new order
+ for ( int i = iFrom; i < iTo-1; ++i )
+ if ( _edges[i]->_2neibors->_nodes[1] != _edges[i+1]->_nodes.back() )
+ _edges[i]->_2neibors->reverse();
+ if ( u2edge.size() > 1 &&
+ _edges[iTo-1]->_2neibors->_nodes[0] != _edges[iTo-2]->_nodes.back() )
+ _edges[iTo-1]->_2neibors->reverse();
+}
+
+//================================================================================
+/*!
+ * \brief Return index corresponding to the shape in _endEdgeOnShape
+ */
+//================================================================================
+
+bool _SolidData::GetShapeEdges(const TGeomID shapeID,
+ size_t & edgesEnd,
+ int* iBeg,
+ int* iEnd ) const
+{
+ int beg = 0, end = 0;
+ for ( edgesEnd = 0; edgesEnd < _endEdgeOnShape.size(); ++edgesEnd )
+ {
+ end = _endEdgeOnShape[ edgesEnd ];
+ TGeomID sID = _edges[ beg ]->_nodes[0]->getshapeId();
+ if ( sID == shapeID )
+ {
+ if ( iBeg ) *iBeg = beg;
+ if ( iEnd ) *iEnd = end;
+ return true;
+ }
+ beg = end;
+ }
+ return false;
+}
+
+//================================================================================
+/*!
+ * \brief Add faces for smoothing
+ */
+//================================================================================
+
+void _SolidData::AddShapesToSmooth( const set< TGeomID >& faceIDs )
+{
+ // convert faceIDs to indices in _endEdgeOnShape
+ set< size_t > iEnds;
+ size_t end;
+ set< TGeomID >::const_iterator fId = faceIDs.begin();
+ for ( ; fId != faceIDs.end(); ++fId )
+ if ( GetShapeEdges( *fId, end ) && end >= _nbShapesToSmooth )
+ iEnds.insert( end );
+
+ set< size_t >::iterator endsIt = iEnds.begin();
+
+ // "add" by move of _nbShapesToSmooth
+ int nbFacesToAdd = iEnds.size();
+ while ( endsIt != iEnds.end() && *endsIt == _nbShapesToSmooth )
+ {
+ ++endsIt;
+ ++_nbShapesToSmooth;
+ --nbFacesToAdd;
+ }
+ if ( endsIt == iEnds.end() )
+ return;
+
+ // Move _LayerEdge's on FACEs just after _nbShapesToSmooth
+
+ vector< _LayerEdge* > nonSmoothLE, smoothLE;
+ size_t lastSmooth = *iEnds.rbegin();
+ int iBeg, iEnd;
+ for ( size_t i = _nbShapesToSmooth; i <= lastSmooth; ++i )
+ {
+ vector< _LayerEdge* > & edgesVec = iEnds.count(i) ? smoothLE : nonSmoothLE;
+ iBeg = i ? _endEdgeOnShape[ i-1 ] : 0;
+ iEnd = _endEdgeOnShape[ i ];
+ edgesVec.insert( edgesVec.end(), _edges.begin() + iBeg, _edges.begin() + iEnd );
+ }
+
+ iBeg = _nbShapesToSmooth ? _endEdgeOnShape[ _nbShapesToSmooth-1 ] : 0;
+ std::copy( smoothLE.begin(), smoothLE.end(), &_edges[ iBeg ] );
+ std::copy( nonSmoothLE.begin(), nonSmoothLE.end(), &_edges[ iBeg + smoothLE.size()]);
+
+ // update _endEdgeOnShape
+ for ( size_t i = _nbShapesToSmooth; i < _endEdgeOnShape.size(); ++i )
+ {
+ TGeomID curShape = _edges[ iBeg ]->_nodes[0]->getshapeId();
+ while ( ++iBeg < _edges.size() &&
+ curShape == _edges[ iBeg ]->_nodes[0]->getshapeId() );
+
+ _endEdgeOnShape[ i ] = iBeg;
+ }
+
+ _nbShapesToSmooth += nbFacesToAdd;
+}
+
//================================================================================
/*!
* \brief smooth _LayerEdge's on a staight EDGE or circular EDGE
gp_Vec2d vec1( center, uv1 );
double uLast = vec0.Angle( vec1 ); // -PI - +PI
double uMidl = vec0.Angle( vecM );
- if ( uLast * uMidl < 0. )
+ if ( uLast * uMidl <= 0. )
uLast += ( uMidl > 0 ? +2. : -2. ) * M_PI;
const double radius = 0.5 * ( vec0.Magnitude() + vec1.Magnitude() );
//================================================================================
bool _ViscousBuilder::updateNormals( _SolidData& data,
- SMESH_MesherHelper& helper )
+ SMESH_MesherHelper& helper,
+ int stepNb )
{
+ if ( stepNb > 0 )
+ return updateNormalsOfConvexFaces( data, helper, stepNb );
+
// make temporary quadrangles got by extrusion of
// mesh edges along _LayerEdge._normal's
extrudedLinks.erase( link_isnew.first );
continue; // already extruded and will no more encounter
}
- // look for a _LayerEdge containg tgt2
-// _LayerEdge* neiborEdge = 0;
-// size_t di = 0; // check _edges[i+di] and _edges[i-di]
-// while ( !neiborEdge && ++di <= data._edges.size() )
-// {
-// if ( i+di < data._edges.size() && data._edges[i+di]->_nodes.back() == tgt2 )
-// neiborEdge = data._edges[i+di];
-// else if ( di <= i && data._edges[i-di]->_nodes.back() == tgt2 )
-// neiborEdge = data._edges[i-di];
-// }
-// if ( !neiborEdge )
-// return error("updateNormals(): neighbor _LayerEdge not found", data._index);
+ // a _LayerEdge containg tgt2
_LayerEdge* neiborEdge = edge->_2neibors->_edges[j];
- TmpMeshFaceOnEdge* f = new TmpMeshFaceOnEdge( edge, neiborEdge, --_tmpFaceID );
+ _TmpMeshFaceOnEdge* f = new _TmpMeshFaceOnEdge( edge, neiborEdge, --_tmpFaceID );
tmpFaces.push_back( f );
dumpCmd(SMESH_Comment("mesh.AddFace([ ")
for ( size_t i = 0; i < data._edges.size(); ++i )
{
_LayerEdge* edge = data._edges[i];
- if ( !edge->IsOnEdge() || !edge->_sWOL.IsNull() ) continue;
+ if (( !edge->IsOnEdge() ) &&
+ ( edge->_sWOL.IsNull() || edge->_sWOL.ShapeType() != TopAbs_FACE ))
+ continue;
if ( edge->FindIntersection( *searcher, dist, eps, &face ))
{
- const TmpMeshFaceOnEdge* f = (const TmpMeshFaceOnEdge*) face;
+ const _TmpMeshFaceOnEdge* f = (const _TmpMeshFaceOnEdge*) face;
set< _LayerEdge*, _LayerEdgeCmp > & ee = edge2CloseEdge[ edge ];
ee.insert( f->_le1 );
ee.insert( f->_le2 );
{
dumpFunction(SMESH_Comment("updateNormals")<<data._index);
+ set< TGeomID > shapesToSmooth;
+
+ // vector to store new _normal and _cosin for each edge in edge2CloseEdge
+ vector< pair< _LayerEdge*, _LayerEdge > > edge2newEdge( edge2CloseEdge.size() );
+
TLEdge2LEdgeSet::iterator e2ee = edge2CloseEdge.begin();
- for ( ; e2ee != edge2CloseEdge.end(); ++e2ee )
+ for ( size_t iE = 0; e2ee != edge2CloseEdge.end(); ++e2ee, ++iE )
{
- _LayerEdge* edge1 = e2ee->first;
- _LayerEdge* edge2 = 0;
- set< _LayerEdge*, _LayerEdgeCmp >& ee = e2ee->second;
+ _LayerEdge* edge1 = e2ee->first;
+ _LayerEdge* edge2 = 0;
+ set< _LayerEdge*, _LayerEdgeCmp >& ee = e2ee->second;
+
+ edge2newEdge[ iE ].first = NULL;
// find EDGEs the edges reside
- TopoDS_Edge E1, E2;
- TopoDS_Shape S = helper.GetSubShapeByNode( edge1->_nodes[0], getMeshDS() );
- if ( S.ShapeType() != TopAbs_EDGE )
- continue; // TODO: find EDGE by VERTEX
- E1 = TopoDS::Edge( S );
+ // TopoDS_Edge E1, E2;
+ // TopoDS_Shape S = helper.GetSubShapeByNode( edge1->_nodes[0], getMeshDS() );
+ // if ( S.ShapeType() != TopAbs_EDGE )
+ // continue; // TODO: find EDGE by VERTEX
+ // E1 = TopoDS::Edge( S );
set< _LayerEdge*, _LayerEdgeCmp >::iterator eIt = ee.begin();
- while ( E2.IsNull() && eIt != ee.end())
+ for ( ; !edge2 && eIt != ee.end(); ++eIt )
{
- _LayerEdge* e2 = *eIt++;
- TopoDS_Shape S = helper.GetSubShapeByNode( e2->_nodes[0], getMeshDS() );
- if ( S.ShapeType() == TopAbs_EDGE )
- E2 = TopoDS::Edge( S ), edge2 = e2;
+ if ( edge1->_sWOL == (*eIt)->_sWOL )
+ edge2 = *eIt;
}
- if ( E2.IsNull() ) continue; // TODO: find EDGE by VERTEX
+ if ( !edge2 ) continue;
+
+ edge2newEdge[ iE ].first = edge1;
+ _LayerEdge& newEdge = edge2newEdge[ iE ].second;
+ // while ( E2.IsNull() && eIt != ee.end())
+ // {
+ // _LayerEdge* e2 = *eIt++;
+ // TopoDS_Shape S = helper.GetSubShapeByNode( e2->_nodes[0], getMeshDS() );
+ // if ( S.ShapeType() == TopAbs_EDGE )
+ // E2 = TopoDS::Edge( S ), edge2 = e2;
+ // }
+ // if ( E2.IsNull() ) continue; // TODO: find EDGE by VERTEX
// find 3 FACEs sharing 2 EDGEs
- TopoDS_Face FF1[2], FF2[2];
- PShapeIteratorPtr fIt = helper.GetAncestors(E1, *_mesh, TopAbs_FACE);
- while ( fIt->more() && FF1[1].IsNull())
+ // TopoDS_Face FF1[2], FF2[2];
+ // PShapeIteratorPtr fIt = helper.GetAncestors(E1, *_mesh, TopAbs_FACE);
+ // while ( fIt->more() && FF1[1].IsNull() )
+ // {
+ // const TopoDS_Face *F = (const TopoDS_Face*) fIt->next();
+ // if ( helper.IsSubShape( *F, data._solid))
+ // FF1[ FF1[0].IsNull() ? 0 : 1 ] = *F;
+ // }
+ // fIt = helper.GetAncestors(E2, *_mesh, TopAbs_FACE);
+ // while ( fIt->more() && FF2[1].IsNull())
+ // {
+ // const TopoDS_Face *F = (const TopoDS_Face*) fIt->next();
+ // if ( helper.IsSubShape( *F, data._solid))
+ // FF2[ FF2[0].IsNull() ? 0 : 1 ] = *F;
+ // }
+ // // exclude a FACE common to E1 and E2 (put it to FFn[1] )
+ // if ( FF1[0].IsSame( FF2[0]) || FF1[0].IsSame( FF2[1]))
+ // std::swap( FF1[0], FF1[1] );
+ // if ( FF2[0].IsSame( FF1[0]) )
+ // std::swap( FF2[0], FF2[1] );
+ // if ( FF1[0].IsNull() || FF2[0].IsNull() )
+ // continue;
+
+ // get a new normal for edge1
+ //bool ok;
+ gp_Vec dir1 = edge1->_normal, dir2 = edge2->_normal;
+ // if ( edge1->_cosin < 0 )
+ // dir1 = getFaceDir( FF1[0], E1, edge1->_nodes[0], helper, ok ).Normalized();
+ // if ( edge2->_cosin < 0 )
+ // dir2 = getFaceDir( FF2[0], E2, edge2->_nodes[0], helper, ok ).Normalized();
+
+ double cos1 = Abs( edge1->_cosin ), cos2 = Abs( edge2->_cosin );
+ double wgt1 = ( cos1 + 0.001 ) / ( cos1 + cos2 + 0.002 );
+ double wgt2 = ( cos2 + 0.001 ) / ( cos1 + cos2 + 0.002 );
+ newEdge._normal = ( wgt1 * dir1 + wgt2 * dir2 ).XYZ();
+ newEdge._normal.Normalize();
+
+ // cout << edge1->_nodes[0]->GetID() << " "
+ // << edge2->_nodes[0]->GetID() << " NORM: "
+ // << newEdge._normal.X() << ", " << newEdge._normal.Y() << ", " << newEdge._normal.Z() << endl;
+
+ // get new cosin
+ if ( cos1 < theMinSmoothCosin )
{
- const TopoDS_Face *F = (const TopoDS_Face*) fIt->next();
- if ( helper.IsSubShape( *F, data._solid))
- FF1[ FF1[0].IsNull() ? 0 : 1 ] = *F;
+ newEdge._cosin = edge2->_cosin;
}
- fIt = helper.GetAncestors(E2, *_mesh, TopAbs_FACE);
- while ( fIt->more() && FF2[1].IsNull())
+ else if ( cos2 > theMinSmoothCosin ) // both cos1 and cos2 > theMinSmoothCosin
{
- const TopoDS_Face *F = (const TopoDS_Face*) fIt->next();
- if ( helper.IsSubShape( *F, data._solid))
- FF2[ FF2[0].IsNull() ? 0 : 1 ] = *F;
+ // gp_Vec dirInFace;
+ // if ( edge1->_cosin < 0 )
+ // dirInFace = dir1;
+ // else
+ // dirInFace = getFaceDir( FF1[0], E1, edge1->_nodes[0], helper, ok );
+ // double angle = dirInFace.Angle( edge1->_normal ); // [0,PI]
+ // edge1->SetCosin( Cos( angle ));
+ //newEdge._cosin = 0; // ???????????
+ newEdge._cosin = ( wgt1 * cos1 + wgt2 * cos2 ) * edge1->_cosin / cos1;
}
- // exclude a FACE common to E1 and E2 (put it at [1] in FF* )
- if ( FF1[0].IsSame( FF2[0]) || FF1[0].IsSame( FF2[1]))
- std::swap( FF1[0], FF1[1] );
- if ( FF2[0].IsSame( FF1[0]) )
- std::swap( FF2[0], FF2[1] );
- if ( FF1[0].IsNull() || FF2[0].IsNull() )
- continue;
-
-// // get a new normal for edge1
- bool ok;
- gp_Vec dir1 = edge1->_normal, dir2 = edge2->_normal;
- if ( edge1->_cosin < 0 )
- dir1 = getFaceDir( FF1[0], E1, edge1->_nodes[0], helper, ok ).Normalized();
- if ( edge2->_cosin < 0 )
- dir2 = getFaceDir( FF2[0], E2, edge2->_nodes[0], helper, ok ).Normalized();
- // gp_Vec dir1 = getFaceDir( FF1[0], E1, edge1->_nodes[0], helper, ok );
-// gp_Vec dir2 = getFaceDir( FF2[0], E2, edge2->_nodes[0], helper, ok2 );
-// double wgt1 = ( edge1->_cosin + 1 ) / ( edge1->_cosin + edge2->_cosin + 2 );
-// double wgt2 = ( edge2->_cosin + 1 ) / ( edge1->_cosin + edge2->_cosin + 2 );
-// gp_Vec newNorm = wgt1 * dir1 + wgt2 * dir2;
-// newNorm.Normalize();
-
- double wgt1 = ( edge1->_cosin + 1 ) / ( edge1->_cosin + edge2->_cosin + 2 );
- double wgt2 = ( edge2->_cosin + 1 ) / ( edge1->_cosin + edge2->_cosin + 2 );
- gp_Vec newNorm = wgt1 * dir1 + wgt2 * dir2;
- newNorm.Normalize();
-
- edge1->_normal = newNorm.XYZ();
-
- // update data of edge1 depending on _normal
- const SMDS_MeshNode *n1, *n2;
- n1 = edge1->_2neibors->_edges[0]->_nodes[0];
- n2 = edge1->_2neibors->_edges[1]->_nodes[0];
- //if ( !findNeiborsOnEdge( edge1, n1, n2, data ))
- //continue;
- edge1->SetDataByNeighbors( n1, n2, helper );
- gp_Vec dirInFace;
- if ( edge1->_cosin < 0 )
- dirInFace = dir1;
else
- getFaceDir( FF1[0], E1, edge1->_nodes[0], helper, ok );
- double angle = dir1.Angle( edge1->_normal ); // [0,PI]
- edge1->SetCosin( cos( angle ));
+ {
+ newEdge._cosin = edge1->_cosin;
+ }
- // limit data._stepSize
- if ( edge1->_cosin > 0.1 )
+ // find shapes that need smoothing due to change of _normal
+ if ( edge1->_cosin < theMinSmoothCosin &&
+ newEdge._cosin > theMinSmoothCosin )
{
- SMDS_ElemIteratorPtr fIt = edge1->_nodes[0]->GetInverseElementIterator(SMDSAbs_Face);
- while ( fIt->more() )
- limitStepSize( data, fIt->next(), edge1->_cosin );
+ if ( edge1->_sWOL.IsNull() )
+ {
+ SMDS_ElemIteratorPtr fIt = edge1->_nodes[0]->GetInverseElementIterator(SMDSAbs_Face);
+ while ( fIt->more() )
+ shapesToSmooth.insert( fIt->next()->getshapeId() );
+ //limitStepSize( data, fIt->next(), edge1->_cosin ); // too late
+ }
+ else // edge1 inflates along a FACE
+ {
+ TopoDS_Shape V = helper.GetSubShapeByNode( edge1->_nodes[0], getMeshDS() );
+ PShapeIteratorPtr eIt = helper.GetAncestors( V, *_mesh, TopAbs_EDGE );
+ while ( const TopoDS_Shape* E = eIt->next() )
+ {
+ if ( !helper.IsSubShape( *E, /*FACE=*/edge1->_sWOL ))
+ continue;
+ gp_Vec edgeDir = getEdgeDir( TopoDS::Edge( *E ), TopoDS::Vertex( V ));
+ double angle = edgeDir.Angle( newEdge._normal ); // [0,PI]
+ if ( angle < M_PI / 2 )
+ shapesToSmooth.insert( getMeshDS()->ShapeToIndex( *E ));
+ }
+ }
}
- // set new XYZ of target node
+ }
+
+ data.AddShapesToSmooth( shapesToSmooth );
+
+ // Update data of edges depending on a new _normal
+
+ for ( size_t iE = 0; iE < edge2newEdge.size(); ++iE )
+ {
+ _LayerEdge* edge1 = edge2newEdge[ iE ].first;
+ _LayerEdge& newEdge = edge2newEdge[ iE ].second;
+ if ( !edge1 ) continue;
+
+ edge1->_normal = newEdge._normal;
+ edge1->SetCosin( newEdge._cosin );
edge1->InvalidateStep( 1 );
edge1->_len = 0;
edge1->SetNewLength( data._stepSize, helper );
- }
+ if ( edge1->IsOnEdge() )
+ {
+ const SMDS_MeshNode * n1 = edge1->_2neibors->_edges[0]->_nodes[0];
+ const SMDS_MeshNode * n2 = edge1->_2neibors->_edges[1]->_nodes[0];
+ edge1->SetDataByNeighbors( n1, n2, helper );
+ }
- // Update normals and other dependent data of not intersecting _LayerEdge's
- // neighboring the intersecting ones
+ // Update normals and other dependent data of not intersecting _LayerEdge's
+ // neighboring the intersecting ones
- for ( e2ee = edge2CloseEdge.begin(); e2ee != edge2CloseEdge.end(); ++e2ee )
- {
- _LayerEdge* edge1 = e2ee->first;
if ( !edge1->_2neibors )
continue;
for ( int j = 0; j < 2; ++j ) // loop on 2 neighbors
if ( edge2CloseEdge.count ( neighbor ))
continue; // j-th neighbor is also intersected
_LayerEdge* prevEdge = edge1;
- const int nbSteps = 6;
+ const int nbSteps = 10;
for ( int step = nbSteps; step; --step ) // step from edge1 in j-th direction
{
if ( !neighbor->_2neibors )
_LayerEdge* nextEdge = neighbor->_2neibors->_edges[iNext];
if ( nextEdge == prevEdge )
nextEdge = neighbor->_2neibors->_edges[ ++iNext ];
-// const double& wgtPrev = neighbor->_2neibors->_wgt[1-iNext];
-// const double& wgtNext = neighbor->_2neibors->_wgt[iNext];
double r = double(step-1)/nbSteps;
if ( !nextEdge->_2neibors )
r = 0.5;
return true;
}
+//================================================================================
+/*!
+ * \brief Modify normals of _LayerEdge's on _ConvexFace's
+ */
+//================================================================================
+
+bool _ViscousBuilder::updateNormalsOfConvexFaces( _SolidData& data,
+ SMESH_MesherHelper& helper,
+ int stepNb )
+{
+ SMESHDS_Mesh* meshDS = helper.GetMeshDS();
+ bool isOK;
+
+ map< TGeomID, _ConvexFace >::iterator id2face = data._convexFaces.begin();
+ for ( ; id2face != data._convexFaces.end(); ++id2face )
+ {
+ _ConvexFace & convFace = (*id2face).second;
+ if ( convFace._normalsFixed )
+ continue; // already fixed
+ if ( convFace.CheckPrisms() )
+ continue; // nothing to fix
+
+ convFace._normalsFixed = true;
+
+ BRepAdaptor_Surface surface ( convFace._face, false );
+ BRepLProp_SLProps surfProp( surface, 2, 1e-6 );
+
+ // check if the convex FACE is of spherical shape
+
+ Bnd_B3d centersBox; // bbox of centers of curvature of _LayerEdge's on VERTEXes
+ Bnd_B3d nodesBox;
+ gp_Pnt center;
+ int iBeg, iEnd;
+
+ map< TGeomID, int >::iterator id2end = convFace._subIdToEdgeEnd.begin();
+ for ( ; id2end != convFace._subIdToEdgeEnd.end(); ++id2end )
+ {
+ data.GetEdgesOnShape( id2end->second, iBeg, iEnd );
+
+ if ( meshDS->IndexToShape( id2end->first ).ShapeType() == TopAbs_VERTEX )
+ {
+ _LayerEdge* ledge = data._edges[ iBeg ];
+ if ( convFace.GetCenterOfCurvature( ledge, surfProp, helper, center ))
+ centersBox.Add( center );
+ }
+ for ( ; iBeg < iEnd; ++iBeg )
+ nodesBox.Add( SMESH_TNodeXYZ( data._edges[ iBeg ]->_nodes[0] ));
+ }
+ if ( centersBox.IsVoid() )
+ {
+ debugMsg( "Error: centersBox.IsVoid()" );
+ return false;
+ }
+ const bool isSpherical =
+ ( centersBox.SquareExtent() < 1e-6 * nodesBox.SquareExtent() );
+
+ int nbEdges = helper.Count( convFace._face, TopAbs_EDGE, /*ignoreSame=*/false );
+ vector < _CentralCurveOnEdge > centerCurves( nbEdges );
+
+ if ( isSpherical )
+ {
+ // set _LayerEdge::_normal as average of all normals
+
+ // WARNING: different density of nodes on EDGEs is not taken into account that
+ // can lead to an improper new normal
+
+ gp_XYZ avgNormal( 0,0,0 );
+ nbEdges = 0;
+ id2end = convFace._subIdToEdgeEnd.begin();
+ for ( ; id2end != convFace._subIdToEdgeEnd.end(); ++id2end )
+ {
+ data.GetEdgesOnShape( id2end->second, iBeg, iEnd );
+ // set data of _CentralCurveOnEdge
+ const TopoDS_Shape& S = meshDS->IndexToShape( id2end->first );
+ if ( S.ShapeType() == TopAbs_EDGE )
+ {
+ _CentralCurveOnEdge& ceCurve = centerCurves[ nbEdges++ ];
+ ceCurve.SetShapes( TopoDS::Edge(S), convFace, data, helper );
+ if ( !data._edges[ iBeg ]->_sWOL.IsNull() )
+ ceCurve._adjFace.Nullify();
+ else
+ ceCurve._ledges.insert( ceCurve._ledges.end(),
+ &data._edges[ iBeg ], &data._edges[ iEnd ]);
+ }
+ // summarize normals
+ for ( ; iBeg < iEnd; ++iBeg )
+ avgNormal += data._edges[ iBeg ]->_normal;
+ }
+ double normSize = avgNormal.SquareModulus();
+ if ( normSize < 1e-200 )
+ {
+ debugMsg( "updateNormalsOfConvexFaces(): zero avgNormal" );
+ return false;
+ }
+ avgNormal /= Sqrt( normSize );
+
+ // compute new _LayerEdge::_cosin on EDGEs
+ double avgCosin = 0;
+ int nbCosin = 0;
+ gp_Vec inFaceDir;
+ for ( size_t iE = 0; iE < centerCurves.size(); ++iE )
+ {
+ _CentralCurveOnEdge& ceCurve = centerCurves[ iE ];
+ if ( ceCurve._adjFace.IsNull() )
+ continue;
+ for ( size_t iLE = 0; iLE < ceCurve._ledges.size(); ++iLE )
+ {
+ const SMDS_MeshNode* node = ceCurve._ledges[ iLE ]->_nodes[0];
+ inFaceDir = getFaceDir( ceCurve._adjFace, ceCurve._edge, node, helper, isOK );
+ if ( isOK )
+ {
+ double angle = inFaceDir.Angle( avgNormal ); // [0,PI]
+ ceCurve._ledges[ iLE ]->_cosin = Cos( angle );
+ avgCosin += ceCurve._ledges[ iLE ]->_cosin;
+ nbCosin++;
+ }
+ }
+ }
+ if ( nbCosin > 0 )
+ avgCosin /= nbCosin;
+
+ // set _LayerEdge::_normal = avgNormal
+ id2end = convFace._subIdToEdgeEnd.begin();
+ for ( ; id2end != convFace._subIdToEdgeEnd.end(); ++id2end )
+ {
+ data.GetEdgesOnShape( id2end->second, iBeg, iEnd );
+ const TopoDS_Shape& S = meshDS->IndexToShape( id2end->first );
+ if ( S.ShapeType() != TopAbs_EDGE )
+ for ( int i = iBeg; i < iEnd; ++i )
+ data._edges[ i ]->_cosin = avgCosin;
+
+ for ( ; iBeg < iEnd; ++iBeg )
+ data._edges[ iBeg ]->_normal = avgNormal;
+ }
+ }
+ else // if ( isSpherical )
+ {
+ // We suppose that centers of curvature at all points of the FACE
+ // lie on some curve, let's call it "central curve". For all _LayerEdge's
+ // having a common center of curvature we define the same new normal
+ // as a sum of normals of _LayerEdge's on EDGEs among them.
+
+ // get all centers of curvature for each EDGE
+
+ helper.SetSubShape( convFace._face );
+ _LayerEdge* vertexLEdges[2], **edgeLEdge, **edgeLEdgeEnd;
+
+ TopExp_Explorer edgeExp( convFace._face, TopAbs_EDGE );
+ for ( int iE = 0; edgeExp.More(); edgeExp.Next(), ++iE )
+ {
+ const TopoDS_Edge& edge = TopoDS::Edge( edgeExp.Current() );
+
+ // set adjacent FACE
+ centerCurves[ iE ].SetShapes( edge, convFace, data, helper );
+
+ // get _LayerEdge's of the EDGE
+ TGeomID edgeID = meshDS->ShapeToIndex( edge );
+ id2end = convFace._subIdToEdgeEnd.find( edgeID );
+ if ( id2end == convFace._subIdToEdgeEnd.end() )
+ {
+ // no _LayerEdge's on EDGE, use _LayerEdge's on VERTEXes
+ for ( int iV = 0; iV < 2; ++iV )
+ {
+ TopoDS_Vertex v = helper.IthVertex( iV, edge );
+ TGeomID vID = meshDS->ShapeToIndex( v );
+ int end = convFace._subIdToEdgeEnd[ vID ];
+ int iBeg = end > 0 ? data._endEdgeOnShape[ end-1 ] : 0;
+ vertexLEdges[ iV ] = data._edges[ iBeg ];
+ }
+ edgeLEdge = &vertexLEdges[0];
+ edgeLEdgeEnd = edgeLEdge + 2;
+
+ centerCurves[ iE ]._adjFace.Nullify();
+ }
+ else
+ {
+ data.GetEdgesOnShape( id2end->second, iBeg, iEnd );
+ if ( id2end->second >= data._nbShapesToSmooth )
+ data.SortOnEdge( edge, iBeg, iEnd, helper );
+ edgeLEdge = &data._edges[ iBeg ];
+ edgeLEdgeEnd = edgeLEdge + iEnd - iBeg;
+ vertexLEdges[0] = data._edges[ iBeg ]->_2neibors->_edges[0];
+ vertexLEdges[1] = data._edges[ iEnd-1 ]->_2neibors->_edges[1];
+
+ if ( ! data._edges[ iBeg ]->_sWOL.IsNull() )
+ centerCurves[ iE ]._adjFace.Nullify();
+ }
+
+ // Get curvature centers
+
+ centersBox.Clear();
+
+ if ( edgeLEdge[0]->IsOnEdge() &&
+ convFace.GetCenterOfCurvature( vertexLEdges[0], surfProp, helper, center ))
+ { // 1st VERTEX
+ centerCurves[ iE ].Append( center, vertexLEdges[0] );
+ centersBox.Add( center );
+ }
+ for ( ; edgeLEdge < edgeLEdgeEnd; ++edgeLEdge )
+ if ( convFace.GetCenterOfCurvature( *edgeLEdge, surfProp, helper, center ))
+ { // EDGE or VERTEXes
+ centerCurves[ iE ].Append( center, *edgeLEdge );
+ centersBox.Add( center );
+ }
+ if ( edgeLEdge[-1]->IsOnEdge() &&
+ convFace.GetCenterOfCurvature( vertexLEdges[1], surfProp, helper, center ))
+ { // 2nd VERTEX
+ centerCurves[ iE ].Append( center, vertexLEdges[1] );
+ centersBox.Add( center );
+ }
+ centerCurves[ iE ]._isDegenerated =
+ ( centersBox.IsVoid() || centersBox.SquareExtent() < 1e-6 * nodesBox.SquareExtent() );
+
+ } // loop on EDGES of convFace._face to set up data of centerCurves
+
+ // Compute new normals for _LayerEdge's on EDGEs
+
+ double avgCosin = 0;
+ int nbCosin = 0;
+ gp_Vec inFaceDir;
+ for ( size_t iE1 = 0; iE1 < centerCurves.size(); ++iE1 )
+ {
+ _CentralCurveOnEdge& ceCurve = centerCurves[ iE1 ];
+ if ( ceCurve._isDegenerated )
+ continue;
+ const vector< gp_Pnt >& centers = ceCurve._curvaCenters;
+ vector< gp_XYZ > & newNormals = ceCurve._normals;
+ for ( size_t iC1 = 0; iC1 < centers.size(); ++iC1 )
+ {
+ isOK = false;
+ for ( size_t iE2 = 0; iE2 < centerCurves.size() && !isOK; ++iE2 )
+ {
+ if ( iE1 != iE2 )
+ isOK = centerCurves[ iE2 ].FindNewNormal( centers[ iC1 ], newNormals[ iC1 ]);
+ }
+ if ( isOK && !ceCurve._adjFace.IsNull() )
+ {
+ // compute new _LayerEdge::_cosin
+ const SMDS_MeshNode* node = ceCurve._ledges[ iC1 ]->_nodes[0];
+ inFaceDir = getFaceDir( ceCurve._adjFace, ceCurve._edge, node, helper, isOK );
+ if ( isOK )
+ {
+ double angle = inFaceDir.Angle( newNormals[ iC1 ] ); // [0,PI]
+ ceCurve._ledges[ iC1 ]->_cosin = Cos( angle );
+ avgCosin += ceCurve._ledges[ iC1 ]->_cosin;
+ nbCosin++;
+ }
+ }
+ }
+ }
+ // set new normals to _LayerEdge's of NOT degenerated central curves
+ for ( size_t iE = 0; iE < centerCurves.size(); ++iE )
+ {
+ if ( centerCurves[ iE ]._isDegenerated )
+ continue;
+ for ( size_t iLE = 0; iLE < centerCurves[ iE ]._ledges.size(); ++iLE )
+ centerCurves[ iE ]._ledges[ iLE ]->_normal = centerCurves[ iE ]._normals[ iLE ];
+ }
+ // set new normals to _LayerEdge's of degenerated central curves
+ for ( size_t iE = 0; iE < centerCurves.size(); ++iE )
+ {
+ if ( !centerCurves[ iE ]._isDegenerated ||
+ centerCurves[ iE ]._ledges.size() < 3 )
+ continue;
+ // new normal is an average of new normals at VERTEXes that
+ // was computed on non-degenerated _CentralCurveOnEdge's
+ gp_XYZ newNorm = ( centerCurves[ iE ]._ledges.front()->_normal +
+ centerCurves[ iE ]._ledges.back ()->_normal );
+ double sz = newNorm.Modulus();
+ if ( sz < 1e-200 )
+ continue;
+ newNorm /= sz;
+ double newCosin = ( 0.5 * centerCurves[ iE ]._ledges.front()->_cosin +
+ 0.5 * centerCurves[ iE ]._ledges.back ()->_cosin );
+ for ( size_t iLE = 1, nb = centerCurves[ iE ]._ledges.size() - 1; iLE < nb; ++iLE )
+ {
+ centerCurves[ iE ]._ledges[ iLE ]->_normal = newNorm;
+ centerCurves[ iE ]._ledges[ iLE ]->_cosin = newCosin;
+ }
+ }
+
+ // Find new normals for _LayerEdge's based on FACE
+
+ if ( nbCosin > 0 )
+ avgCosin /= nbCosin;
+ const TGeomID faceID = meshDS->ShapeToIndex( convFace._face );
+ map< TGeomID, int >::iterator id2end = convFace._subIdToEdgeEnd.find( faceID );
+ if ( id2end != convFace._subIdToEdgeEnd.end() )
+ {
+ int iE = 0;
+ gp_XYZ newNorm;
+ data.GetEdgesOnShape( id2end->second, iBeg, iEnd );
+ for ( ; iBeg < iEnd; ++iBeg )
+ {
+ _LayerEdge* ledge = data._edges[ iBeg ];
+ if ( !convFace.GetCenterOfCurvature( ledge, surfProp, helper, center ))
+ continue;
+ for ( size_t i = 0; i < centerCurves.size(); ++i, ++iE )
+ {
+ iE = iE % centerCurves.size();
+ if ( centerCurves[ iE ]._isDegenerated )
+ continue;
+ newNorm.SetCoord( 0,0,0 );
+ if ( centerCurves[ iE ].FindNewNormal( center, newNorm ))
+ {
+ ledge->_normal = newNorm;
+ ledge->_cosin = avgCosin;
+ break;
+ }
+ }
+ }
+ }
+
+ } // not a quasi-spherical FACE
+
+ // Update _LayerEdge's data according to a new normal
+
+ dumpFunction(SMESH_Comment("updateNormalsOfConvexFaces")<<data._index
+ <<"_F"<<meshDS->ShapeToIndex( convFace._face ));
+
+ id2end = convFace._subIdToEdgeEnd.begin();
+ for ( ; id2end != convFace._subIdToEdgeEnd.end(); ++id2end )
+ {
+ data.GetEdgesOnShape( id2end->second, iBeg, iEnd );
+ for ( ; iBeg < iEnd; ++iBeg )
+ {
+ _LayerEdge* & ledge = data._edges[ iBeg ];
+ double len = ledge->_len;
+ ledge->InvalidateStep( stepNb + 1, /*restoreLength=*/true );
+ ledge->SetCosin( ledge->_cosin );
+ ledge->SetNewLength( len, helper );
+ }
+
+ } // loop on sub-shapes of convFace._face
+
+ // Find FACEs adjacent to convFace._face that got necessity to smooth
+ // as a result of normals modification
+
+ set< TGeomID > adjFacesToSmooth;
+ for ( size_t iE = 0; iE < centerCurves.size(); ++iE )
+ {
+ if ( centerCurves[ iE ]._adjFace.IsNull() ||
+ centerCurves[ iE ]._adjFaceToSmooth )
+ continue;
+ for ( size_t iLE = 0; iLE < centerCurves[ iE ]._ledges.size(); ++iLE )
+ {
+ if ( centerCurves[ iE ]._ledges[ iLE ]->_cosin > theMinSmoothCosin )
+ {
+ adjFacesToSmooth.insert( meshDS->ShapeToIndex( centerCurves[ iE ]._adjFace ));
+ break;
+ }
+ }
+ }
+ data.AddShapesToSmooth( adjFacesToSmooth );
+
+ dumpFunctionEnd();
+
+
+ } // loop on data._convexFaces
+
+ return true;
+}
+
+//================================================================================
+/*!
+ * \brief Finds a center of curvature of a surface at a _LayerEdge
+ */
+//================================================================================
+
+bool _ConvexFace::GetCenterOfCurvature( _LayerEdge* ledge,
+ BRepLProp_SLProps& surfProp,
+ SMESH_MesherHelper& helper,
+ gp_Pnt & center ) const
+{
+ gp_XY uv = helper.GetNodeUV( _face, ledge->_nodes[0] );
+ surfProp.SetParameters( uv.X(), uv.Y() );
+ if ( !surfProp.IsCurvatureDefined() )
+ return false;
+
+ const double oriFactor = ( _face.Orientation() == TopAbs_REVERSED ? +1. : -1. );
+ double surfCurvatureMax = surfProp.MaxCurvature() * oriFactor;
+ double surfCurvatureMin = surfProp.MinCurvature() * oriFactor;
+ if ( surfCurvatureMin > surfCurvatureMax )
+ center = surfProp.Value().Translated( surfProp.Normal().XYZ() / surfCurvatureMin * oriFactor );
+ else
+ center = surfProp.Value().Translated( surfProp.Normal().XYZ() / surfCurvatureMax * oriFactor );
+
+ return true;
+}
+
+//================================================================================
+/*!
+ * \brief Check that prisms are not distorted
+ */
+//================================================================================
+
+bool _ConvexFace::CheckPrisms() const
+{
+ for ( size_t i = 0; i < _simplexTestEdges.size(); ++i )
+ {
+ const _LayerEdge* edge = _simplexTestEdges[i];
+ SMESH_TNodeXYZ tgtXYZ( edge->_nodes.back() );
+ for ( size_t j = 0; j < edge->_simplices.size(); ++j )
+ if ( !edge->_simplices[j].IsForward( edge->_nodes[0], &tgtXYZ ))
+ {
+ debugMsg( "Bad simplex of _simplexTestEdges ("
+ << " "<< edge->_nodes[0]->GetID()<< " "<< tgtXYZ._node->GetID()
+ << " "<< edge->_simplices[j]._nPrev->GetID()
+ << " "<< edge->_simplices[j]._nNext->GetID() << " )" );
+ return false;
+ }
+ }
+ return true;
+}
+
+//================================================================================
+/*!
+ * \brief Try to compute a new normal by interpolating normals of _LayerEdge's
+ * stored in this _CentralCurveOnEdge.
+ * \param [in] center - curvature center of a point of another _CentralCurveOnEdge.
+ * \param [in,out] newNormal - current normal at this point, to be redefined
+ * \return bool - true if succeeded.
+ */
+//================================================================================
+
+bool _CentralCurveOnEdge::FindNewNormal( const gp_Pnt& center, gp_XYZ& newNormal )
+{
+ if ( this->_isDegenerated )
+ return false;
+
+ // find two centers the given one lies between
+
+ for ( size_t i = 0, nb = _curvaCenters.size()-1; i < nb; ++i )
+ {
+ double sl2 = 1.001 * _segLength2[ i ];
+
+ double d1 = center.SquareDistance( _curvaCenters[ i ]);
+ if ( d1 > sl2 )
+ continue;
+
+ double d2 = center.SquareDistance( _curvaCenters[ i+1 ]);
+ if ( d2 > sl2 || d2 + d1 < 1e-100 )
+ continue;
+
+ d1 = Sqrt( d1 );
+ d2 = Sqrt( d2 );
+ double r = d1 / ( d1 + d2 );
+ gp_XYZ norm = (( 1. - r ) * _ledges[ i ]->_normal +
+ ( r ) * _ledges[ i+1 ]->_normal );
+ norm.Normalize();
+
+ newNormal += norm;
+ double sz = newNormal.Modulus();
+ if ( sz < 1e-200 )
+ break;
+ newNormal /= sz;
+ return true;
+ }
+ return false;
+}
+
+//================================================================================
+/*!
+ * \brief Set shape members
+ */
+//================================================================================
+
+void _CentralCurveOnEdge::SetShapes( const TopoDS_Edge& edge,
+ const _ConvexFace& convFace,
+ const _SolidData& data,
+ SMESH_MesherHelper& helper)
+{
+ _edge = edge;
+
+ PShapeIteratorPtr fIt = helper.GetAncestors( edge, *helper.GetMesh(), TopAbs_FACE );
+ while ( const TopoDS_Shape* F = fIt->next())
+ if ( !convFace._face.IsSame( *F ))
+ {
+ _adjFace = TopoDS::Face( *F );
+ _adjFaceToSmooth = false;
+ // _adjFace already in a smoothing queue ?
+ size_t end;
+ TGeomID adjFaceID = helper.GetMeshDS()->ShapeToIndex( *F );
+ if ( data.GetShapeEdges( adjFaceID, end ))
+ _adjFaceToSmooth = ( end < data._nbShapesToSmooth );
+ break;
+ }
+}
+
//================================================================================
/*!
* \brief Looks for intersection of it's last segment with faces
bool segmentIntersected = false;
distance = Precision::Infinite();
int iFace = -1; // intersected face
- for ( size_t j = 0 ; j < suspectFaces.size() && !segmentIntersected; ++j )
+ for ( size_t j = 0 ; j < suspectFaces.size() /*&& !segmentIntersected*/; ++j )
{
const SMDS_MeshElement* face = suspectFaces[j];
if ( face->GetNodeIndex( _nodes.back() ) >= 0 ||
{
const SMDS_MeshNode* tria[3];
tria[0] = *nIt++;
- tria[1] = *nIt++;;
+ tria[1] = *nIt++;
for ( int n2 = 2; n2 < nbNodes && !intFound; ++n2 )
{
tria[2] = *nIt++;
}
if ( intFound )
{
- if ( dist < segLen*(1.01) && dist > -(_len-segLen) )
+ if ( dist < segLen*(1.01) && dist > -(_len*_lenFactor-segLen) )
segmentIntersected = true;
if ( distance > dist )
distance = dist, iFace = j;
}
}
if ( iFace != -1 && face ) *face = suspectFaces[iFace];
-// if ( distance && iFace > -1 )
-// {
-// // distance is used to limit size of inflation step which depends on
-// // whether the intersected face bears viscous layers or not
-// bool faceHasVL = suspectFaces[iFace]->GetID() < 1;
-// if ( faceHasVL )
-// *distance /= 2;
-// }
+
if ( segmentIntersected )
{
#ifdef __myDEBUG
/* calculate distance from vert0 to ray origin */
gp_XYZ tvec = orig - vert0;
- if ( tvec * dir > EPSILON )
+ //if ( tvec * dir > EPSILON )
// intersected face is at back side of the temporary face this _LayerEdge belongs to
- return false;
+ //return false;
gp_XYZ edge1 = vert1 - vert0;
gp_XYZ edge2 = vert2 - vert0;
double det = edge1 * pvec;
if (det > -EPSILON && det < EPSILON)
- return 0;
+ return false;
double inv_det = 1.0 / det;
/* calculate U parameter and test bounds */
double u = ( tvec * pvec ) * inv_det;
- if (u < 0.0 || u > 1.0)
- return 0;
+ //if (u < 0.0 || u > 1.0)
+ if (u < -EPSILON || u > 1.0 + EPSILON)
+ return false;
/* prepare to test V parameter */
gp_XYZ qvec = tvec ^ edge1;
/* calculate V parameter and test bounds */
double v = (dir * qvec) * inv_det;
- if ( v < 0.0 || u + v > 1.0 )
- return 0;
+ //if ( v < 0.0 || u + v > 1.0 )
+ if ( v < -EPSILON || u + v > 1.0 + EPSILON)
+ return false;
/* calculate t, ray intersects triangle */
t = (edge2 * qvec) * inv_det;
- // if (det < EPSILON)
- // return false;
-
- // /* calculate distance from vert0 to ray origin */
- // gp_XYZ tvec = orig - vert0;
-
- // /* calculate U parameter and test bounds */
- // double u = tvec * pvec;
- // if (u < 0.0 || u > det)
-// return 0;
-
-// /* prepare to test V parameter */
-// gp_XYZ qvec = tvec ^ edge1;
-
-// /* calculate V parameter and test bounds */
-// double v = dir * qvec;
-// if (v < 0.0 || u + v > det)
-// return 0;
-
-// /* calculate t, scale parameters, ray intersects triangle */
-// double t = edge2 * qvec;
-// double inv_det = 1.0 / det;
-// t *= inv_det;
-// //u *= inv_det;
-// //v *= inv_det;
-
- return true;
+ //return true;
+ return t > 0.;
}
//================================================================================
newPos += SMESH_TNodeXYZ( _simplices[i]._nPrev );
newPos /= _simplices.size();
+ const gp_XYZ& curPos ( _pos.back() );
+ const gp_Pnt prevPos( _pos[ _pos.size()-2 ]);
if ( _curvature )
- newPos += _normal * _curvature->lenDelta( _len );
-
- gp_Pnt prevPos( _pos[ _pos.size()-2 ]);
-// if ( _cosin < -0.1)
-// {
-// // Avoid decreasing length of edge on concave surface
-// //gp_Vec oldMove( _pos[ _pos.size()-2 ], _pos.back() );
-// gp_Vec newMove( prevPos, newPos );
-// newPos = _pos.back() + newMove.XYZ();
-// }
-// else if ( _cosin > 0.3 )
-// {
-// // Avoid increasing length of edge too much
-
-// }
+ {
+ double delta = _curvature->lenDelta( _len );
+ if ( delta > 0 )
+ newPos += _normal * delta;
+ else
+ {
+ double segLen = _normal * ( newPos - prevPos.XYZ() );
+ if ( segLen + delta > 0 )
+ newPos += _normal * delta;
+ }
+ // double segLenChange = _normal * ( curPos - newPos );
+ // newPos += 0.5 * _normal * segLenChange;
+ }
+
// count quality metrics (orientation) of tetras around _tgtNode
int nbOkBefore = 0;
- SMESH_TNodeXYZ tgtXYZ( _nodes.back() );
for ( size_t i = 0; i < _simplices.size(); ++i )
- nbOkBefore += _simplices[i].IsForward( _nodes[0], &tgtXYZ );
+ nbOkBefore += _simplices[i].IsForward( _nodes[0], &curPos );
int nbOkAfter = 0;
for ( size_t i = 0; i < _simplices.size(); ++i )
*/
//================================================================================
-void _LayerEdge::InvalidateStep( int curStep )
+void _LayerEdge::InvalidateStep( int curStep, bool restoreLength )
{
if ( _pos.size() > curStep )
{
+ if ( restoreLength )
+ _len -= ( _pos[ curStep-1 ] - _pos.back() ).Modulus();
+
_pos.resize( curStep );
gp_Pnt nXYZ = _pos.back();
SMDS_MeshNode* n = const_cast< SMDS_MeshNode*>( _nodes.back() );
Handle(Geom_Surface) surface;
TopoDS_Edge geomEdge;
TopoDS_Face geomFace;
+ TopoDS_Shape prevSWOL;
TopLoc_Location loc;
- double f,l, u/*, distXYZ[4]*/;
+ double f,l, u;
gp_XY uv;
bool isOnEdge;
+ TGeomID prevBaseId = -1;
+ TNode2Edge* n2eMap = 0;
+ TNode2Edge::iterator n2e;
for ( size_t i = 0; i < data._edges.size(); ++i )
{
edge._nodes[1] = 0;
edge._nodes.back() = tgtNode;
}
- if ( !edge._sWOL.IsNull() )
+ // get data of a shrink shape
+ if ( !edge._sWOL.IsNull() && edge._sWOL != prevSWOL )
{
isOnEdge = ( edge._sWOL.ShapeType() == TopAbs_EDGE );
- // restore position of the last node
-// gp_Pnt p;
if ( isOnEdge )
{
geomEdge = TopoDS::Edge( edge._sWOL );
- curve = BRep_Tool::Curve( geomEdge, loc, f,l);
-// double u = helper.GetNodeU( tgtNode );
-// p = curve->Value( u );
+ curve = BRep_Tool::Curve( geomEdge, loc, f,l);
}
else
{
geomFace = TopoDS::Face( edge._sWOL );
- surface = BRep_Tool::Surface( geomFace, loc );
-// gp_XY uv = helper.GetNodeUV( tgtNode );
-// p = surface->Value( uv.X(), uv.Y() );
+ surface = BRep_Tool::Surface( geomFace, loc );
+ }
+ prevSWOL = edge._sWOL;
+ }
+ // restore shapePos of the last node by already treated _LayerEdge of another _SolidData
+ const TGeomID baseShapeId = edge._nodes[0]->getshapeId();
+ if ( baseShapeId != prevBaseId )
+ {
+ map< TGeomID, TNode2Edge* >::iterator s2ne = data._s2neMap.find( baseShapeId );
+ n2eMap = ( s2ne == data._s2neMap.end() ) ? 0 : n2eMap = s2ne->second;
+ prevBaseId = baseShapeId;
+ }
+ if ( n2eMap && (( n2e = n2eMap->find( edge._nodes[0] )) != n2eMap->end() ))
+ {
+ _LayerEdge* foundEdge = n2e->second;
+ const gp_XYZ& foundPos = foundEdge->_pos.back();
+ SMDS_PositionPtr lastPos = tgtNode->GetPosition();
+ if ( isOnEdge )
+ {
+ SMDS_EdgePosition* epos = static_cast<SMDS_EdgePosition*>( lastPos );
+ epos->SetUParameter( foundPos.X() );
+ }
+ else
+ {
+ SMDS_FacePosition* fpos = static_cast<SMDS_FacePosition*>( lastPos );
+ fpos->SetUParameter( foundPos.X() );
+ fpos->SetVParameter( foundPos.Y() );
}
-// p.Transform( loc );
-// const_cast< SMDS_MeshNode* >( tgtNode )->setXYZ( p.X(), p.Y(), p.Z() );
}
// calculate height of the first layer
double h0;
if ( isOnEdge )
{
u = pos.X();
- pos = curve->Value( u ).Transformed(loc);
+ if ( !node )
+ pos = curve->Value( u ).Transformed(loc);
}
else
{
uv.SetCoord( pos.X(), pos.Y() );
- pos = surface->Value( pos.X(), pos.Y() ).Transformed(loc);
+ if ( !node )
+ pos = surface->Value( pos.X(), pos.Y() ).Transformed(loc);
}
}
// create or update the node
{
u = 0.5 * ( u + helper.GetNodeU( geomEdge, node ));
pos = curve->Value( u ).Transformed(loc);
+
+ SMDS_EdgePosition* epos = static_cast<SMDS_EdgePosition*>( node->GetPosition() );
+ epos->SetUParameter( u );
}
else
{
uv = 0.5 * ( uv + helper.GetNodeUV( geomFace, node ));
pos = surface->Value( uv.X(), uv.Y()).Transformed(loc);
+
+ SMDS_FacePosition* fpos = static_cast<SMDS_FacePosition*>( node->GetPosition() );
+ fpos->SetUParameter( uv.X() );
+ fpos->SetVParameter( uv.Y() );
}
}
node->setXYZ( pos.X(), pos.Y(), pos.Z() );
dumpChangeNodes( f );
// Replace source nodes by target nodes in mesh faces to shrink
+ dumpFunction(SMESH_Comment("replNodesOnFace")<<f2sd->first); // debug
const SMDS_MeshNode* nodes[20];
for ( size_t i = 0; i < lEdges.size(); ++i )
{
nodes[iN] = ( n == srcNode ? tgtNode : n );
}
helper.GetMeshDS()->ChangeElementNodes( f, nodes, f->NbNodes() );
+ dumpChangeNodes( f );
}
}
// Create _SmoothNode's on face F
vector< _SmoothNode > nodesToSmooth( smoothNodes.size() );
{
+ dumpFunction(SMESH_Comment("fixUVOnFace")<<f2sd->first); // debug
const bool sortSimplices = isConcaveFace;
for ( size_t i = 0; i < smoothNodes.size(); ++i )
{
}
}
}
+ // TODO: check effect of this additional smooth
+ // additional laplacian smooth to increase allowed shrink step
+ // for ( int st = 1; st; --st )
+ // {
+ // dumpFunction(SMESH_Comment("shrinkFace")<<f2sd->first<<"_st"<<++smooStep); // debug
+ // for ( size_t i = 0; i < nodesToSmooth.size(); ++i )
+ // {
+ // nodesToSmooth[i].Smooth( badNb,surface,helper,refSign,
+ // _SmoothNode::LAPLACIAN,/*set3D=*/false);
+ // }
+ // }
} // while ( shrinked )
// No wrongly shaped faces remain; final smooth. Set node XYZ.
gp_Vec2d uvDir( srcUV, tgtUV );
double uvLen = uvDir.Magnitude();
uvDir /= uvLen;
- edge._normal.SetCoord( uvDir.X(),uvDir.Y(), 0);
+ edge._normal.SetCoord( uvDir.X(),uvDir.Y(), 0 );
edge._len = uvLen;
- // // IMPORTANT to have src nodes NOT yet REPLACED by tgt nodes in shrinked faces
- // vector<const SMDS_MeshElement*> faces;
- // multimap< double, const SMDS_MeshNode* > proj2node;
- // SMDS_ElemIteratorPtr fIt = srcNode->GetInverseElementIterator(SMDSAbs_Face);
- // while ( fIt->more() )
- // {
- // const SMDS_MeshElement* f = fIt->next();
- // if ( faceSubMesh->Contains( f ))
- // faces.push_back( f );
- // }
- // for ( size_t i = 0; i < faces.size(); ++i )
- // {
- // const int nbNodes = faces[i]->NbCornerNodes();
- // for ( int j = 0; j < nbNodes; ++j )
- // {
- // const SMDS_MeshNode* n = faces[i]->GetNode(j);
- // if ( n == srcNode ) continue;
- // if ( n->GetPosition()->GetTypeOfPosition() != SMDS_TOP_FACE &&
- // ( faces.size() > 1 || nbNodes > 3 ))
- // continue;
- // gp_Pnt2d uv = helper.GetNodeUV( F, n );
- // gp_Vec2d uvDirN( srcUV, uv );
- // double proj = uvDirN * uvDir;
- // proj2node.insert( make_pair( proj, n ));
- // }
- // }
-
- // multimap< double, const SMDS_MeshNode* >::iterator p2n = proj2node.begin(), p2nEnd;
- // const double minProj = p2n->first;
- // const double projThreshold = 1.1 * uvLen;
- // if ( minProj > projThreshold )
- // {
- // // tgtNode is located so that it does not make faces with wrong orientation
- // return true;
- // }
edge._pos.resize(1);
edge._pos[0].SetCoord( tgtUV.X(), tgtUV.Y(), 0 );
- // store most risky nodes in _simplices
- // p2nEnd = proj2node.lower_bound( projThreshold );
- // int nbSimpl = ( std::distance( p2n, p2nEnd ) + 1) / 2;
- // edge._simplices.resize( nbSimpl );
- // for ( int i = 0; i < nbSimpl; ++i )
- // {
- // edge._simplices[i]._nPrev = p2n->second;
- // if ( ++p2n != p2nEnd )
- // edge._simplices[i]._nNext = p2n->second;
- // }
// set UV of source node to target node
SMDS_FacePosition* pos = static_cast<SMDS_FacePosition*>( tgtNode->GetPosition() );
pos->SetUParameter( srcUV.X() );
pos->SetUParameter( uSrc );
}
return true;
-
- //================================================================================
- /*!
- * \brief Compute positions (UV) to set to a node on edge moved during shrinking
- */
- //================================================================================
-
- // Compute UV to follow during shrinking
-
-// const SMDS_MeshNode* srcNode = edge._nodes[0];
-// const SMDS_MeshNode* tgtNode = edge._nodes.back();
-
-// gp_XY srcUV = helper.GetNodeUV( F, srcNode );
-// gp_XY tgtUV = helper.GetNodeUV( F, tgtNode );
-// gp_Vec2d uvDir( srcUV, tgtUV );
-// double uvLen = uvDir.Magnitude();
-// uvDir /= uvLen;
-
-// // Select shrinking step such that not to make faces with wrong orientation.
-// // IMPORTANT to have src nodes NOT yet REPLACED by tgt nodes in shrinked faces
-// const double minStepSize = uvLen / 20;
-// double stepSize = uvLen;
-// SMDS_ElemIteratorPtr fIt = srcNode->GetInverseElementIterator(SMDSAbs_Face);
-// while ( fIt->more() )
-// {
-// const SMDS_MeshElement* f = fIt->next();
-// if ( !faceSubMesh->Contains( f )) continue;
-// const int nbNodes = f->NbCornerNodes();
-// for ( int i = 0; i < nbNodes; ++i )
-// {
-// const SMDS_MeshNode* n = f->GetNode(i);
-// if ( n->GetPosition()->GetTypeOfPosition() != SMDS_TOP_FACE || n == srcNode)
-// continue;
-// gp_XY uv = helper.GetNodeUV( F, n );
-// gp_Vec2d uvDirN( srcUV, uv );
-// double proj = uvDirN * uvDir;
-// if ( proj < stepSize && proj > minStepSize )
-// stepSize = proj;
-// }
-// }
-// stepSize *= 0.8;
-
-// const int nbSteps = ceil( uvLen / stepSize );
-// gp_XYZ srcUV0( srcUV.X(), srcUV.Y(), 0 );
-// gp_XYZ tgtUV0( tgtUV.X(), tgtUV.Y(), 0 );
-// edge._pos.resize( nbSteps );
-// edge._pos[0] = tgtUV0;
-// for ( int i = 1; i < nbSteps; ++i )
-// {
-// double r = i / double( nbSteps );
-// edge._pos[i] = (1-r) * tgtUV0 + r * srcUV0;
-// }
-// return true;
}
//================================================================================
SMESH::Controls::AspectRatio qualifier;
SMESH::Controls::TSequenceOfXYZ points(3), points1(3), points2(3);
const double maxAspectRatio = is2D ? 4. : 2;
- NodeCoordHelper xyz( F, helper, is2D );
+ _NodeCoordHelper xyz( F, helper, is2D );
// find bad triangles
const double kSafe = Max( 0.5, 1. - 0.1 * _simplices.size() );
// Select shrinking step such that not to make faces with wrong orientation.
- double stepSize = uvLen;
+ double stepSize = 1e100;
for ( size_t i = 0; i < _simplices.size(); ++i )
{
// find intersection of 2 lines: curUV-tgtUV and that connecting simplex nodes
stepSize = Min( step, stepSize );
}
gp_Pnt2d newUV;
- if ( uvLen - stepSize < _len / 200. )
+ if ( uvLen <= stepSize )
{
newUV = tgtUV;
_pos.clear();