X-Git-Url: http://git.salome-platform.org/gitweb/?p=modules%2Fsmesh.git;a=blobdiff_plain;f=src%2FSMESH%2FSMESH_MesherHelper.hxx;h=9e8d82958744f6c1d7be562d407f50c0c6ef2eb7;hp=cf515dfba0566992d3684e5c80759bcdbf893238;hb=1dd2f82c6d43d470c088288248edea674d583eec;hpb=88b3dbe23b236bd1746405155ae33a76aaf59ecd diff --git a/src/SMESH/SMESH_MesherHelper.hxx b/src/SMESH/SMESH_MesherHelper.hxx index cf515dfba..9e8d82958 100644 --- a/src/SMESH/SMESH_MesherHelper.hxx +++ b/src/SMESH/SMESH_MesherHelper.hxx @@ -1,4 +1,4 @@ -// Copyright (C) 2007-2012 CEA/DEN, EDF R&D, OPEN CASCADE +// Copyright (C) 2007-2015 CEA/DEN, EDF R&D, OPEN CASCADE // // Copyright (C) 2003-2007 OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN, // CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS @@ -6,7 +6,7 @@ // This library is free software; you can redistribute it and/or // modify it under the terms of the GNU Lesser General Public // License as published by the Free Software Foundation; either -// version 2.1 of the License. +// version 2.1 of the License, or (at your option) any later version. // // This library is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of @@ -34,6 +34,7 @@ #include #include +#include #include #include #include @@ -72,7 +73,7 @@ typedef gp_XY (*xyFunPtr)(const gp_XY& uv1, const gp_XY& uv2); class SMESH_EXPORT SMESH_MesherHelper { -public: + public: // ---------- PUBLIC UTILITIES ---------- /*! @@ -97,7 +98,7 @@ public: * The key of the map is a normalized parameter of each * base node on theBaseSide. Edges in theBaseSide must be sequenced. * This method works in supposition that nodes on the face - * forms a rectangular grid and elements can be quardrangles or triangles + * forms a structured grid and elements can be quardrangles or triangles */ static bool LoadNodeColumns(TParam2ColumnMap & theParam2ColumnMap, const TopoDS_Face& theFace, @@ -117,6 +118,11 @@ public: */ static bool IsStructured( SMESH_subMesh* faceSM ); + /*! + * \brief Return true if 2D mesh on FACE is distored + */ + static bool IsDistorted2D( SMESH_subMesh* faceSM, bool checkUV=false ); + /*! * \brief Returns true if given node is medium * \param n - node to check @@ -130,6 +136,7 @@ public: * \param node - the node * \param meshDS - mesh DS * \retval TopoDS_Shape - found support shape + * \sa SMESH_Algo::VertexNode( const TopoDS_Vertex&, SMESHDS_Mesh* ) */ static TopoDS_Shape GetSubShapeByNode(const SMDS_MeshNode* node, const SMESHDS_Mesh* meshDS); @@ -140,12 +147,41 @@ public: * \param nbNodes - total nb of nodes * \retval int - valid node index */ - static int WrapIndex(const int ind, const int nbNodes) { - if ( ind < 0 ) return nbNodes + ind % nbNodes; - if ( ind >= nbNodes ) return ind % nbNodes; - return ind; + static inline int WrapIndex(int ind, const int nbNodes) { + return (( ind %= nbNodes ) < 0 ) ? ind + nbNodes : ind; } + /*! + * \brief Return UV of a point inside a quadrilateral FACE by it's + * normalized parameters within a unit quadrangle and the + * corresponding projections on sub-shapes of the real-world FACE. + * The used calculation method is called Trans-Finite Interpolation (TFI). + * \param x,y - normalized parameters that should be in range [0,1] + * \param a0,a1,a2,a3 - UV of VERTEXes of the FACE == projections on VERTEXes + * \param p0,p1,p2,p3 - UV of the point projections on EDGEs of the FACE + * \return gp_XY - UV of the point on the FACE + * + * Y ^ Order of those UV in the FACE is as follows. + * | + * a3 p2 a2 + * o---x-----o + * | : | + * | :UV | + * p3 x...O.....x p1 + * | : | + * o---x-----o ----> X + * a0 p0 a1 + */ + inline static gp_XY calcTFI(double x, double y, + const gp_XY& a0,const gp_XY& a1,const gp_XY& a2,const gp_XY& a3, + const gp_XY& p0,const gp_XY& p1,const gp_XY& p2,const gp_XY& p3); + + /*! + * \brief Same as "gp_XY calcTFI(...)" but in 3D + */ + inline static gp_XYZ calcTFI(double x, double y, + const gp_XYZ& a0,const gp_XYZ& a1,const gp_XYZ& a2,const gp_XYZ& a3, + const gp_XYZ& p0,const gp_XYZ& p1,const gp_XYZ& p2,const gp_XYZ& p3); /*! * \brief Count nb of sub-shapes * \param shape - the shape @@ -186,8 +222,14 @@ public: static bool IsSubShape( const TopoDS_Shape& shape, SMESH_Mesh* aMesh ); + static bool IsBlock( const TopoDS_Shape& shape ); + static double MaxTolerance( const TopoDS_Shape& shape ); + static double GetAngle( const TopoDS_Edge & E1, const TopoDS_Edge & E2, + const TopoDS_Face & F, const TopoDS_Vertex & V, + gp_Vec* faceNormal=0); + static bool IsClosedEdge( const TopoDS_Edge& anEdge ); static TopoDS_Vertex IthVertex( const bool is2nd, TopoDS_Edge anEdge, const bool CumOri=true ); @@ -195,6 +237,10 @@ public: static TopAbs_ShapeEnum GetGroupType(const TopoDS_Shape& group, const bool avoidCompound=false); + static TopoDS_Shape GetShapeOfHypothesis( const SMESHDS_Hypothesis * hyp, + const TopoDS_Shape& shape, + SMESH_Mesh* mesh); + public: // ---------- PUBLIC INSTANCE METHODS ---------- @@ -202,7 +248,9 @@ public: // constructor SMESH_MesherHelper(SMESH_Mesh& theMesh); - SMESH_Mesh* GetMesh() const { return myMesh; } + SMESH_Gen* GetGen() const { return GetMesh()->GetGen(); } + + SMESH_Mesh* GetMesh() const { return myMesh; } SMESHDS_Mesh* GetMeshDS() const { return GetMesh()->GetMeshDS(); } @@ -211,11 +259,19 @@ public: * quadratic elements will be created. Also fill myTLinkNodeMap */ bool IsQuadraticSubMesh(const TopoDS_Shape& theShape); + /*! * \brief Set order of elements to create without calling IsQuadraticSubMesh() */ void SetIsQuadratic(const bool theBuildQuadratic) { myCreateQuadratic = theBuildQuadratic; } + + /*! + * \brief Set myCreateBiQuadratic flag + */ + void SetIsBiQuadratic(const bool theBuildBiQuadratic) + { myCreateBiQuadratic = theBuildBiQuadratic; } + /*! * \brief Return myCreateQuadratic flag */ @@ -226,6 +282,11 @@ public: */ bool IsReversedSubMesh (const TopoDS_Face& theFace); + /*! + * \brief Return myCreateBiQuadratic flag + */ + bool GetIsBiQuadratic() const { return myCreateBiQuadratic; } + /*! * \brief Move medium nodes of faces and volumes to fix distorted elements * \param error - container of fixed distorted elements @@ -257,7 +318,7 @@ public: const TopoDS_Shape& GetSubShape() const { return myShape; } /*! - * Creates a node + * Creates a node (!Note ID before u=0.,v0.) */ SMDS_MeshNode* AddNode(double x, double y, double z, int ID = 0, double u=0., double v=0.); /*! @@ -276,7 +337,7 @@ public: const int id=0, const bool force3d = false); /*! - * Creates quadratic or linear quadrangle + * Creates bi-quadratic, quadratic or linear quadrangle */ SMDS_MeshFace* AddFace(const SMDS_MeshNode* n1, const SMDS_MeshNode* n2, @@ -284,7 +345,6 @@ public: const SMDS_MeshNode* n4, const int id = 0, const bool force3d = false); - /*! * Creates polygon, with additional nodes in quadratic mesh */ @@ -322,7 +382,7 @@ public: const int id = 0, const bool force3d = true); /*! - * Creates quadratic or linear hexahedron + * Creates bi-quadratic, quadratic or linear hexahedron */ SMDS_MeshVolume* AddVolume(const SMDS_MeshNode* n1, const SMDS_MeshNode* n2, @@ -374,7 +434,7 @@ public: double GetNodeU(const TopoDS_Edge& theEdge, const SMDS_MeshNode* theNode, const SMDS_MeshNode* inEdgeNode=0, - bool* check=0); + bool* check=0) const; /*! * \brief Return node UV on face * \param inFaceNode - a node of element being created located inside a face @@ -414,12 +474,22 @@ public: static gp_XY GetMiddleUV(const Handle(Geom_Surface)& surface, const gp_XY& uv1, const gp_XY& uv2); + /*! + * \brief Return UV for the central node of a biquadratic triangle + */ + static gp_XY GetCenterUV(const gp_XY& uv1, + const gp_XY& uv2, + const gp_XY& uv3, + const gp_XY& uv12, + const gp_XY& uv23, + const gp_XY& uv31, + bool * isBadTria=0); /*! * \brief Define a pointer to wrapper over a function of gp_XY class, - * suitable to pass as xyFunPtr to applyIn2D(). + * suitable to pass as xyFunPtr to ApplyIn2D(). * For exaple gp_XY_FunPtr(Added) defines pointer gp_XY_Added to function * calling gp_XY::Added(gp_XY), which is to be used like following - * applyIn2D(surf, uv1, uv2, gp_XY_Added) + * ApplyIn2D(surf, uv1, uv2, gp_XY_Added) */ #define gp_XY_FunPtr(meth) \ static gp_XY __gpXY_##meth (const gp_XY& uv1, const gp_XY& uv2) { return uv1.meth( uv2 ); } \ @@ -430,18 +500,26 @@ public: * It takes into account period of the surface. Use gp_XY_FunPtr macro * to easily define pointer to function of gp_XY class. */ - static gp_XY applyIn2D(const Handle(Geom_Surface)& surface, - const gp_XY& uv1, - const gp_XY& uv2, - xyFunPtr fun, - const bool resultInPeriod=true); - + static gp_XY ApplyIn2D(Handle(Geom_Surface) surface, + const gp_XY& uv1, + const gp_XY& uv2, + xyFunPtr fun, + const bool resultInPeriod=true); + + /*! + * \brief Move node positions on a FACE within surface period + * \param [in] face - the FACE + * \param [inout] uv - node positions to adjust + * \param [in] nbUV - nb of \a uv + */ + void AdjustByPeriod( const TopoDS_Face& face, gp_XY uv[], const int nbUV ); + /*! * \brief Check if inFaceNode argument is necessary for call GetNodeUV(F,..) - * \retval bool - return true if the face is periodic - * - * If F is Null, answer about subshape set through IsQuadraticSubMesh() or - * SetSubShape() + * \retval bool - return true if the face is periodic + * + * If F is Null, answer about subshape set through IsQuadraticSubMesh() or + * SetSubShape() */ bool GetNodeUVneedInFaceNode(const TopoDS_Face& F = TopoDS_Face()) const; @@ -451,6 +529,10 @@ public: GeomAPI_ProjectPointOnSurf& GetProjector(const TopoDS_Face& F, TopLoc_Location& loc, double tol=0 ) const; + /*! + * \brief Return a cached ShapeAnalysis_Surface of a FACE + */ + Handle(ShapeAnalysis_Surface) GetSurface(const TopoDS_Face& F ); /*! * \brief Check if shape is a degenerated edge or it's vertex @@ -502,13 +584,20 @@ public: { return IsRealSeam( GetMeshDS()->ShapeToIndex( subShape)); } /*! * \brief Check if the shape set through IsQuadraticSubMesh() or SetSubShape() - * has a seam edge - * \retval bool - true if it has + * has a seam edge, i.e. an edge that has two parametric representations + * on a surface + * \retval bool - true if it has */ bool HasSeam() const { return !mySeamShapeIds.empty(); } + /*! + * \brief Check if the shape set through IsQuadraticSubMesh() or SetSubShape() + * has a seam edge that encounters twice in a wire + * \retval bool - true if it has + */ + bool HasRealSeam() const { return HasSeam() && ( *mySeamShapeIds.begin() < 0 ); } /*! * \brief Return index of periodic parametric direction of a closed face - * \retval int - 1 for U, 2 for V direction + * \retval int - 1 for U, 2 for V direction */ int GetPeriodicIndex() const { return myParIndex; } /*! @@ -521,15 +610,49 @@ public: * \param force3d - true means node creation at the middle between the * two given nodes, else node position is found on its * supporting geometrical shape, if any. + * \param expectedSupport - shape type corresponding to element being created + * , e.g TopAbs_EDGE if SMDSAbs_Edge is created + * basing on \a n1 and \a n2 */ const SMDS_MeshNode* GetMediumNode(const SMDS_MeshNode* n1, const SMDS_MeshNode* n2, - const bool force3d); + const bool force3d, + TopAbs_ShapeEnum expectedSupport=TopAbs_SHAPE); + /*! + * \brief Return existing or create a new central node for a quardilateral + * quadratic face given its 8 nodes. + * \param force3d - true means node creation in between the given nodes, + * else node position is found on a geometrical face if any. + */ + const SMDS_MeshNode* GetCentralNode(const SMDS_MeshNode* n1, + const SMDS_MeshNode* n2, + const SMDS_MeshNode* n3, + const SMDS_MeshNode* n4, + const SMDS_MeshNode* n12, + const SMDS_MeshNode* n23, + const SMDS_MeshNode* n34, + const SMDS_MeshNode* n41, + bool force3d); + /*! + * \brief Return existing or create a new central node for a + * quadratic triangle given its 6 nodes. + * \param force3d - true means node creation in between the given nodes, + * else node position is found on a geometrical face if any. + */ + const SMDS_MeshNode* GetCentralNode(const SMDS_MeshNode* n1, + const SMDS_MeshNode* n2, + const SMDS_MeshNode* n3, + const SMDS_MeshNode* n12, + const SMDS_MeshNode* n23, + const SMDS_MeshNode* n31, + bool force3d); /*! * \brief Return index and type of the shape (EDGE or FACE only) to set a medium node on */ std::pair GetMediumPos(const SMDS_MeshNode* n1, - const SMDS_MeshNode* n2); + const SMDS_MeshNode* n2, + const bool useCurSubShape=false, + TopAbs_ShapeEnum expectedSupport=TopAbs_SHAPE); /*! * \brief Add a link in my data structure */ @@ -542,9 +665,9 @@ public: void AddTLinkNodeMap(const TLinkNodeMap& aMap) { myTLinkNodeMap.insert(aMap.begin(), aMap.end()); } - void AddTLinks(const SMDS_MeshEdge* edge); - void AddTLinks(const SMDS_MeshFace* face); - void AddTLinks(const SMDS_MeshVolume* vol); + bool AddTLinks(const SMDS_MeshEdge* edge); + bool AddTLinks(const SMDS_MeshFace* face); + bool AddTLinks(const SMDS_MeshVolume* vol); /** * Returns myTLinkNodeMap @@ -561,35 +684,63 @@ public: virtual ~SMESH_MesherHelper(); -protected: + protected: /*! * \brief Select UV on either of 2 pcurves of a seam edge, closest to the given UV - * \param uv1 - UV on the seam - * \param uv2 - UV within a face - * \retval gp_Pnt2d - selected UV + * \param uv1 - UV on the seam + * \param uv2 - UV within a face + * \retval gp_Pnt2d - selected UV */ - gp_Pnt2d GetUVOnSeam( const gp_Pnt2d& uv1, const gp_Pnt2d& uv2 ) const; + gp_Pnt2d getUVOnSeam( const gp_Pnt2d& uv1, const gp_Pnt2d& uv2 ) const; const SMDS_MeshNode* getMediumNodeOnComposedWire(const SMDS_MeshNode* n1, const SMDS_MeshNode* n2, bool force3d); + + double getFaceMaxTol( const TopoDS_Shape& face ) const; + private: // Forbiden copy constructor - SMESH_MesherHelper (const SMESH_MesherHelper& theOther) {}; - - // special map for using during creation of quadratic elements - TLinkNodeMap myTLinkNodeMap; + SMESH_MesherHelper (const SMESH_MesherHelper& theOther); + + // key of a map of bi-quadratic face to it's central node + struct TBiQuad: public std::pair > + { + TBiQuad(const SMDS_MeshNode* n1, + const SMDS_MeshNode* n2, + const SMDS_MeshNode* n3, + const SMDS_MeshNode* n4=0) + { + TIDSortedNodeSet s; + s.insert(n1); + s.insert(n2); + s.insert(n3); + if ( n4 ) s.insert(n4); + TIDSortedNodeSet::iterator n = s.begin(); + first = (*n++)->GetID(); + second.first = (*n++)->GetID(); + second.second = (*n++)->GetID(); + } + }; + + // maps used during creation of quadratic elements + TLinkNodeMap myTLinkNodeMap; // medium nodes on links + std::map< TBiQuad, const SMDS_MeshNode* > myMapWithCentralNode; // central nodes of faces std::set< int > myDegenShapeIds; std::set< int > mySeamShapeIds; double myPar1[2], myPar2[2]; // U and V bounds of a closed periodic surface int myParIndex; // bounds' index (1-U, 2-V, 3-both) - typedef std::map< int, GeomAPI_ProjectPointOnSurf* > TID2ProjectorOnSurf; - TID2ProjectorOnSurf myFace2Projector; + std::map< int, double > myFaceMaxTol; + + typedef std::map< int, Handle(ShapeAnalysis_Surface)> TID2Surface; + typedef std::map< int, GeomAPI_ProjectPointOnSurf* > TID2ProjectorOnSurf; typedef std::map< int, GeomAPI_ProjectPointOnCurve* > TID2ProjectorOnCurve; + TID2Surface myFace2Surface; + TID2ProjectorOnSurf myFace2Projector; TID2ProjectorOnCurve myEdge2Projector; TopoDS_Shape myShape; @@ -597,14 +748,35 @@ protected: int myShapeID; bool myCreateQuadratic; + bool myCreateBiQuadratic; bool mySetElemOnShape; bool myFixNodeParameters; std::map< int,bool > myNodePosShapesValidity; bool toCheckPosOnShape(int shapeID ) const; void setPosOnShapeValidity(int shapeID, bool ok ) const; - }; +//======================================================================= +inline gp_XY +SMESH_MesherHelper::calcTFI(double x, double y, + const gp_XY& a0,const gp_XY& a1,const gp_XY& a2,const gp_XY& a3, + const gp_XY& p0,const gp_XY& p1,const gp_XY& p2,const gp_XY& p3) +{ + return + ((1 - y) * p0 + x * p1 + y * p2 + (1 - x) * p3 ) - + ((1 - x) * (1 - y) * a0 + x * (1 - y) * a1 + x * y * a2 + (1 - x) * y * a3); +} +//======================================================================= +inline gp_XYZ +SMESH_MesherHelper::calcTFI(double x, double y, + const gp_XYZ& a0,const gp_XYZ& a1,const gp_XYZ& a2,const gp_XYZ& a3, + const gp_XYZ& p0,const gp_XYZ& p1,const gp_XYZ& p2,const gp_XYZ& p3) +{ + return + ((1 - y) * p0 + x * p1 + y * p2 + (1 - x) * p3 ) - + ((1 - x) * (1 - y) * a0 + x * (1 - y) * a1 + x * y * a2 + (1 - x) * y * a3); +} +//======================================================================= #endif