0026106: BRepMesh - revision of data model
[occt.git] / src / BRepMesh / BRepMesh_ModelHealer.hxx
diff --git a/src/BRepMesh/BRepMesh_ModelHealer.hxx b/src/BRepMesh/BRepMesh_ModelHealer.hxx
new file mode 100644 (file)
index 0000000..5fab250
--- /dev/null
@@ -0,0 +1,183 @@
+// Created on: 2016-06-23
+// Copyright (c) 2016 OPEN CASCADE SAS
+// Created by: Oleg AGASHIN
+//
+// This file is part of Open CASCADE Technology software library.
+//
+// This library is free software; you can redistribute it and/or modify it under
+// the terms of the GNU Lesser General Public License version 2.1 as published
+// by the Free Software Foundation, with special exception defined in the file
+// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
+// distribution for complete text of the license and disclaimer of any warranty.
+//
+// Alternatively, this file may be used under the terms of Open CASCADE
+// commercial license or contractual agreement.
+
+#ifndef _BRepMesh_ModelHealer_HeaderFile
+#define _BRepMesh_ModelHealer_HeaderFile
+
+#include <IMeshTools_ModelAlgo.hxx>
+#include <IMeshTools_Parameters.hxx>
+#include <IMeshData_Types.hxx>
+#include <IMeshData_Model.hxx>
+#include <TopoDS_Vertex.hxx>
+
+//! Class implements functionality of model healer tool.
+//! Iterates over model's faces and checks consistency of their wires, 
+//! i.e.whether wires are closed and do not contain self - intersections.
+//! In case if wire contains disconnected parts, ends of adjacent edges 
+//! forming the gaps are connected in parametric space forcibly. The notion 
+//! of this operation is to create correct discrete model defined relatively 
+//! parametric space of target face taking into account connectivity and 
+//! tolerances of 3D space only. This means that there are no specific 
+//! computations are made for the sake of determination of U and V tolerance.
+//! Registers intersections on edges forming the face¬ís shape and tries to 
+//! amplify discrete represenation by decreasing of deflection for the target edge. 
+//! Checks can be performed in parallel mode.
+class BRepMesh_ModelHealer : public IMeshTools_ModelAlgo
+{
+public:
+
+  //! Constructor.
+  Standard_EXPORT BRepMesh_ModelHealer();
+
+  //! Destructor.
+  Standard_EXPORT virtual ~BRepMesh_ModelHealer();
+
+  //! Performs processing of edges of the given model.
+  Standard_EXPORT virtual Standard_Boolean Perform(
+    const Handle(IMeshData_Model)& theModel,
+    const IMeshTools_Parameters&   theParameters) Standard_OVERRIDE;
+
+  //! Functor API to discretize the given edge.
+  inline void operator() (const Standard_Integer theEdgeIndex) const {
+    process(theEdgeIndex);
+  }
+
+  //! Functor API to discretize the given edge.
+  inline void operator() (const IMeshData::IFaceHandle& theDFace) const {
+    process(theDFace);
+  }
+
+  DEFINE_STANDARD_RTTI_INLINE(BRepMesh_ModelHealer, IMeshTools_ModelAlgo)
+
+private:
+
+  //! Checks existing discretization of the face and updates data model.
+  inline void process(const Standard_Integer theFaceIndex) const
+  {
+    const IMeshData::IFaceHandle& aDFace = myModel->GetFace(theFaceIndex);
+    process(aDFace);
+  }
+
+  //! Checks existing discretization of the face and updates data model.
+  void process(const IMeshData::IFaceHandle& theDFace) const;
+
+  //! Amplifies discretization of edges in case if self-intersection problem has been found.
+  void amplifyEdges();
+
+  //! Returns common vertex of two edges or null ptr in case if there is no such vertex.
+  TopoDS_Vertex getCommonVertex(
+    const IMeshData::IEdgeHandle& theEdge1,
+    const IMeshData::IEdgeHandle& theEdge2) const;
+
+  //! Connects pcurves of previous and current edge on the specified face 
+  //! according to topological connectivity. Uses next edge in order to
+  //! identify closest point in case of signle vertex shared between both
+  //! ends of edge (degenerative edge)
+  Standard_Boolean connectClosestPoints(
+    const IMeshData::IPCurveHandle& thePrevDEdge,
+    const IMeshData::IPCurveHandle& theCurrDEdge,
+    const IMeshData::IPCurveHandle& theNextDEdge) const;
+
+  //! Chooses the most closest point to reference one from the given pair.
+  //! Returns square distance between reference point and closest one as 
+  //! well as pointer to closest point.
+  inline Standard_Real closestPoint(
+    gp_Pnt2d&  theRefPnt,
+    gp_Pnt2d&  theFristPnt,
+    gp_Pnt2d&  theSecondPnt,
+    gp_Pnt2d*& theClosestPnt) const
+  {
+    // Find the most closest end-points.
+    const Standard_Real aSqDist1 = theRefPnt.SquareDistance(theFristPnt);
+    const Standard_Real aSqDist2 = theRefPnt.SquareDistance(theSecondPnt);
+    if (aSqDist1 < aSqDist2)
+    {
+      theClosestPnt = &theFristPnt;
+      return aSqDist1;
+    }
+
+    theClosestPnt = &theSecondPnt;
+    return aSqDist2;
+  }
+
+  //! Chooses the most closest points among the given to reference one from the given pair.
+  //! Returns square distance between reference point and closest one as 
+  //! well as pointer to closest point.
+  inline Standard_Real closestPoints(
+    gp_Pnt2d&  theFirstPnt1,
+    gp_Pnt2d&  theSecondPnt1,
+    gp_Pnt2d&  theFirstPnt2,
+    gp_Pnt2d&  theSecondPnt2,
+    gp_Pnt2d*& theClosestPnt1,
+    gp_Pnt2d*& theClosestPnt2) const
+  {
+    gp_Pnt2d *aCurrPrevUV1 = NULL, *aCurrPrevUV2 = NULL;
+    const Standard_Real aSqDist1 = closestPoint(theFirstPnt1,  theFirstPnt2, theSecondPnt2, aCurrPrevUV1);
+    const Standard_Real aSqDist2 = closestPoint(theSecondPnt1, theFirstPnt2, theSecondPnt2, aCurrPrevUV2);
+    if (aSqDist1 - aSqDist2 < gp::Resolution())
+    {
+      theClosestPnt1 = &theFirstPnt1;
+      theClosestPnt2 = aCurrPrevUV1;
+      return aSqDist1;
+    }
+
+    theClosestPnt1 = &theSecondPnt1;
+    theClosestPnt2 = aCurrPrevUV2;
+    return aSqDist2;
+  }
+
+  //! Adjusts the given pair of points supposed to be the same.
+  //! In addition, adjusts another end-point of an edge in order
+  //! to perform correct matching in case of gap.
+  inline void adjustSamePoints(
+    gp_Pnt2d*& theMajorSamePnt1,
+    gp_Pnt2d*& theMinorSamePnt1,
+    gp_Pnt2d*& theMajorSamePnt2,
+    gp_Pnt2d*& theMinorSamePnt2,
+    gp_Pnt2d&  theMajorFirstPnt,
+    gp_Pnt2d&  theMajorLastPnt,
+    gp_Pnt2d&  theMinorFirstPnt,
+    gp_Pnt2d&  theMinorLastPnt) const
+  {
+    if (theMajorSamePnt2 == theMajorSamePnt1)
+    {
+      theMajorSamePnt2 = (theMajorSamePnt2 == &theMajorFirstPnt) ? &theMajorLastPnt : &theMajorFirstPnt;
+      closestPoint(*theMajorSamePnt2, theMinorFirstPnt, theMinorLastPnt, theMinorSamePnt2);
+    }
+
+    *theMajorSamePnt1 = *theMinorSamePnt1;
+    *theMajorSamePnt2 = *theMinorSamePnt2;
+  }
+
+  //! Connects ends of pcurves of face's wires according to topological coherency.
+  void fixFaceBoundaries(const IMeshData::IFaceHandle& theDFace) const;
+
+  //! Returns True if check can be done in parallel.
+  inline Standard_Boolean isParallel() const
+  {
+    return (myParameters.InParallel && myModel->FacesNb() > 1);
+  }
+
+  //! Collects unique edges to be updated from face map. Clears data stored in face map.
+  Standard_Boolean popEdgesToUpdate(IMeshData::MapOfIEdgePtr& theEdgesToUpdate);
+
+private:
+
+  Handle(IMeshData_Model)                           myModel;
+  IMeshTools_Parameters                             myParameters;
+  Handle(IMeshData::DMapOfIFacePtrsMapOfIEdgePtrs)  myFaceIntersectingEdges;
+};
+
+#endif
\ No newline at end of file