X-Git-Url: http://git.salome-platform.org/gitweb/?p=modules%2Fsmesh.git;a=blobdiff_plain;f=src%2FSMESH%2FSMESH_MesherHelper.hxx;h=5950ec9315c33da59edd2eb53458f2459305ff8e;hp=d67e335b59ede60c1d8fc021f23671476645945d;hb=b09372829929f8f561495d6c16527134971a1909;hpb=b0a908c0d20341651771d0249fb10882f54b2aad diff --git a/src/SMESH/SMESH_MesherHelper.hxx b/src/SMESH/SMESH_MesherHelper.hxx index d67e335b5..5950ec931 100644 --- a/src/SMESH/SMESH_MesherHelper.hxx +++ b/src/SMESH/SMESH_MesherHelper.hxx @@ -1,4 +1,4 @@ -// Copyright (C) 2007-2014 CEA/DEN, EDF R&D, OPEN CASCADE +// Copyright (C) 2007-2021 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 @@ -29,11 +29,11 @@ #include "SMESH_SMESH.hxx" -#include "SMESH_MeshEditor.hxx" // needed for many meshers -#include -#include +#include "SMESH_ComputeError.hxx" +#include "SMESH_TypeDefs.hxx" #include +#include #include #include #include @@ -41,16 +41,26 @@ #include #include -class GeomAPI_ProjectPointOnSurf; class GeomAPI_ProjectPointOnCurve; +class GeomAPI_ProjectPointOnSurf; +class SMDS_MeshNode; +class SMESHDS_Hypothesis; +class SMESHDS_Mesh; +class SMESHDS_SubMesh; +class SMESH_Gen; +class SMESH_Mesh; class SMESH_ProxyMesh; +class SMESH_subMesh; +class TopoDS_Edge; +class TopoDS_Face; +class TopoDS_Vertex; typedef std::map TLinkNodeMap; typedef std::map::iterator ItTLinkNode; typedef SMDS_Iterator PShapeIterator; typedef boost::shared_ptr< PShapeIterator > PShapeIteratorPtr; - + typedef std::vector TNodeColumn; typedef std::map< double, TNodeColumn > TParam2ColumnMap; @@ -117,6 +127,13 @@ class SMESH_EXPORT SMESH_MesherHelper */ 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, + SMESH_MesherHelper* faceHelper = NULL); + /*! * \brief Returns true if given node is medium * \param n - node to check @@ -130,6 +147,7 @@ class SMESH_EXPORT SMESH_MesherHelper * \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); @@ -166,20 +184,20 @@ class SMESH_EXPORT SMESH_MesherHelper * 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); + 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); + 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 * \param type - the type of sub-shapes to count - * \param ignoreSame - if true, use map not to count same shapes, esle use explorer + * \param ignoreSame - if true, use map not to count same shapes, else use explorer * \retval int - the calculated number */ static int Count(const TopoDS_Shape& shape, @@ -193,11 +211,12 @@ class SMESH_EXPORT SMESH_MesherHelper const SMESH_Mesh& mesh, TopAbs_ShapeEnum ancestorType=TopAbs_SHAPE); /*! - * \brief Return iterator on ancestors of the given type + * \brief Return iterator on ancestors of the given type, included into a container shape */ static PShapeIteratorPtr GetAncestors(const TopoDS_Shape& shape, const SMESH_Mesh& mesh, - TopAbs_ShapeEnum ancestorType); + TopAbs_ShapeEnum ancestorType, + const TopoDS_Shape* container = 0); /*! * \brief Find a common ancestor, of the given type, of two shapes */ @@ -215,9 +234,13 @@ class SMESH_EXPORT SMESH_MesherHelper 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); + 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 ); @@ -226,6 +249,10 @@ class SMESH_EXPORT SMESH_MesherHelper 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 ---------- @@ -233,21 +260,20 @@ public: // constructor SMESH_MesherHelper(SMESH_Mesh& theMesh); - SMESH_Mesh* GetMesh() const { return myMesh; } + SMESH_Gen* GetGen() const; - SMESHDS_Mesh* GetMeshDS() const { return GetMesh()->GetMeshDS(); } + SMESH_Mesh* GetMesh() const { return myMesh; } + SMESHDS_Mesh* GetMeshDS() const; + /*! * Check submesh for given shape: if all elements on this shape are quadratic, * quadratic elements will be created. Also fill myTLinkNodeMap */ bool IsQuadraticSubMesh(const TopoDS_Shape& theShape); - /*! - * \brief Set order of elements to create without calling IsQuadraticSubMesh() - */ /*! - * \brief Set myCreateQuadratic flag + * \brief Set order of elements to create without calling IsQuadraticSubMesh() */ void SetIsQuadratic(const bool theBuildQuadratic) { myCreateQuadratic = theBuildQuadratic; } @@ -282,7 +308,7 @@ public: /*! * \brief To set created elements on the shape set by IsQuadraticSubMesh() - * or the next methods. By defaul elements are set on the shape if + * or the next methods. By default elements are set on the shape if * a mesh has no shape to be meshed */ bool SetElementsOnShape(bool toSet) @@ -302,17 +328,28 @@ public: * \brief Return the shape set by IsQuadraticSubMesh() or SetSubShape() */ const TopoDS_Shape& GetSubShape() const { return myShape; } + /*! + * \brief Copy shape information from another helper to improve performance + * since SetSubShape() can be time consuming if there are many edges + */ + void CopySubShapeInfo(const SMESH_MesherHelper& other); + + + /*! + * \brief Convert a shape to its index in the SMESHDS_Mesh + */ + int ShapeToIndex( const TopoDS_Shape& S ) const; /*! * 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.); + SMDS_MeshNode* AddNode(double x, double y, double z, smIdType ID = 0, double u=0., double v=0.); /*! * Creates quadratic or linear edge */ SMDS_MeshEdge* AddEdge(const SMDS_MeshNode* n1, const SMDS_MeshNode* n2, - const int id = 0, + const smIdType id = 0, const bool force3d = true); /*! * Creates quadratic or linear triangle @@ -320,7 +357,7 @@ public: SMDS_MeshFace* AddFace(const SMDS_MeshNode* n1, const SMDS_MeshNode* n2, const SMDS_MeshNode* n3, - const int id=0, + const smIdType id=0, const bool force3d = false); /*! * Creates bi-quadratic, quadratic or linear quadrangle @@ -329,13 +366,13 @@ public: const SMDS_MeshNode* n2, const SMDS_MeshNode* n3, const SMDS_MeshNode* n4, - const int id = 0, + const smIdType id = 0, const bool force3d = false); /*! * Creates polygon, with additional nodes in quadratic mesh */ SMDS_MeshFace* AddPolygonalFace (const std::vector& nodes, - const int id = 0, + const smIdType id = 0, const bool force3d = false); /*! * Creates quadratic or linear tetrahedron @@ -344,7 +381,7 @@ public: const SMDS_MeshNode* n2, const SMDS_MeshNode* n3, const SMDS_MeshNode* n4, - const int id = 0, + const smIdType id = 0, const bool force3d = true); /*! * Creates quadratic or linear pyramid @@ -354,7 +391,7 @@ public: const SMDS_MeshNode* n3, const SMDS_MeshNode* n4, const SMDS_MeshNode* n5, - const int id = 0, + const smIdType id = 0, const bool force3d = true); /*! * Creates quadratic or linear pentahedron @@ -365,7 +402,7 @@ public: const SMDS_MeshNode* n4, const SMDS_MeshNode* n5, const SMDS_MeshNode* n6, - const int id = 0, + const smIdType id = 0, const bool force3d = true); /*! * Creates bi-quadratic, quadratic or linear hexahedron @@ -378,7 +415,7 @@ public: const SMDS_MeshNode* n6, const SMDS_MeshNode* n7, const SMDS_MeshNode* n8, - const int id = 0, + const smIdType id = 0, bool force3d = true); /*! @@ -396,7 +433,7 @@ public: const SMDS_MeshNode* n10, const SMDS_MeshNode* n11, const SMDS_MeshNode* n12, - const int id = 0, + const smIdType id = 0, bool force3d = true); /*! @@ -404,7 +441,7 @@ public: */ SMDS_MeshVolume* AddPolyhedralVolume (const std::vector& nodes, const std::vector& quantities, - const int ID=0, + const smIdType ID=0, const bool force3d = true); /*! * \brief Enables fixing node parameters on EDGEs and FACEs by @@ -472,10 +509,10 @@ public: bool * isBadTria=0); /*! * \brief Define a pointer to wrapper over a function of gp_XY class, - * suitable to pass as xyFunPtr to applyIn2D(). - * For exaple gp_XY_FunPtr(Added) defines pointer gp_XY_Added to function + * suitable to pass as xyFunPtr to ApplyIn2D(). + * For example 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 ); } \ @@ -486,43 +523,61 @@ 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; /*! - * \brief Return projector intitialized by given face without location, which is returned + * \brief Return projector initialized by given face without location, which is returned */ 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 ) const; /*! * \brief Check if shape is a degenerated edge or it's vertex - * \param subShape - edge or vertex index in SMESHDS - * \retval bool - true if subShape is a degenerated shape - * - * It works only if IsQuadraticSubMesh() or SetSubShape() has been called + * \param subShape - edge or vertex index in SMESHDS + * \retval bool - true if subShape is a degenerated shape + * + * It works only if IsQuadraticSubMesh() or SetSubShape() has been called */ bool IsDegenShape(const int subShape) const { return myDegenShapeIds.find( subShape ) != myDegenShapeIds.end(); } /*! * \brief Check if the shape set through IsQuadraticSubMesh() or SetSubShape() * has a degenerated edges - * \retval bool - true if it has + * \retval bool - true if there are degenerated edges */ bool HasDegeneratedEdges() const { return !myDegenShapeIds.empty(); } + /*! + * \brief Return a number of degenerated edges in the shape set through + * IsQuadraticSubMesh() or SetSubShape() + * \retval size_t - nb edges + */ + size_t NbDegeneratedEdges() const { return myDegenShapeIds.size(); } /*! * \brief Check if shape is a seam edge or it's vertex @@ -530,7 +585,7 @@ public: * \retval bool - true if subShape is a seam shape * * It works only if IsQuadraticSubMesh() or SetSubShape() has been called. - * Seam shape has two 2D alternative represenations on the face + * Seam shape has two 2D alternative representations on the face */ bool IsSeamShape(const int subShape) const { return mySeamShapeIds.find( subShape ) != mySeamShapeIds.end(); } @@ -540,10 +595,10 @@ public: * \retval bool - true if subShape is a seam shape * * It works only if IsQuadraticSubMesh() or SetSubShape() has been called. - * Seam shape has two 2D alternative represenations on the face + * Seam shape has two 2D alternative representations on the face */ bool IsSeamShape(const TopoDS_Shape& subShape) const - { return IsSeamShape( GetMeshDS()->ShapeToIndex( subShape )); } + { return IsSeamShape( ShapeToIndex( subShape )); } /*! * \brief Return true if an edge or a vertex encounters twice in face wire * \param subShape - Id of edge or vertex @@ -555,32 +610,57 @@ public: * \param subShape - edge or vertex */ bool IsRealSeam(const TopoDS_Shape& subShape) const - { return IsRealSeam( GetMeshDS()->ShapeToIndex( subShape)); } + { return IsRealSeam( 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 a number of real seam edges in the shape set through + * IsQuadraticSubMesh() or SetSubShape(). A real seam edge encounters twice in a wire + * \retval size_t - nb of real seams + */ + size_t NbRealSeam() const; /*! * \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; } + /*! + * \brief Return period in given direction [1,2] + */ + double GetPeriod(int perioIndex) const { return myPar2[ perioIndex-1 ] - myPar1[ perioIndex-1 ]; } /*! * \brief Return an alternative parameter for a node on seam */ double GetOtherParam(const double param) const; + /*! + * \brief Check if UV is on seam. Return 0 if not, 1 for U seam, 2 for V seam + */ + int IsOnSeam(const gp_XY& uv) const; /*! * \brief Return existing or create new medium nodes between given ones * \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. @@ -614,7 +694,8 @@ public: */ std::pair GetMediumPos(const SMDS_MeshNode* n1, const SMDS_MeshNode* n2, - const bool useCurSubShape=false); + const bool useCurSubShape=false, + TopAbs_ShapeEnum expectedSupport=TopAbs_SHAPE); /*! * \brief Add a link in my data structure */ @@ -627,9 +708,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 @@ -646,6 +727,9 @@ public: virtual ~SMESH_MesherHelper(); + static void WriteShape(const TopoDS_Shape& s); + + protected: /*! @@ -654,18 +738,22 @@ public: * \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 + // forbidden copy constructor SMESH_MesherHelper (const SMESH_MesherHelper& theOther); // key of a map of bi-quadratic face to it's central node - struct TBiQuad: public std::pair > + struct TBiQuad: public std::pair > { TBiQuad(const SMDS_MeshNode* n1, const SMDS_MeshNode* n2, @@ -693,9 +781,13 @@ public: 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; + mutable TID2Surface myFace2Surface; + TID2ProjectorOnSurf myFace2Projector; TID2ProjectorOnCurve myEdge2Projector; TopoDS_Shape myShape; @@ -715,8 +807,8 @@ public: //======================================================================= 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) + 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 ) - @@ -725,8 +817,8 @@ SMESH_MesherHelper::calcTFI(double x, double y, //======================================================================= 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) + 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 ) -