0026106: BRepMesh - revision of data model
[occt.git] / src / BRepMesh / BRepMesh_MeshTool.hxx
diff --git a/src/BRepMesh/BRepMesh_MeshTool.hxx b/src/BRepMesh/BRepMesh_MeshTool.hxx
new file mode 100644 (file)
index 0000000..7ca0294
--- /dev/null
@@ -0,0 +1,235 @@
+// Created on: 2016-08-22
+// 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_MeshTool_HeaderFile
+#define _BRepMesh_MeshTool_HeaderFile
+
+#include <Standard_Transient.hxx>
+#include <Standard_DefineHandle.hxx>
+#include <BRepMesh_DataStructureOfDelaun.hxx>
+#include <BRepMesh_CircleTool.hxx>
+#include <gp_Lin2d.hxx>
+#include <IMeshData_Types.hxx>
+#include <BRepMesh_Edge.hxx>
+
+#include <stack>
+
+//! Auxiliary tool providing API for manipulation with BRepMesh_DataStructureOfDelaun.
+class BRepMesh_MeshTool : public Standard_Transient
+{
+public:
+
+  //! Helper functor intended to separate points to left and right from the constraint.
+  class NodeClassifier
+  {
+  public:
+
+    NodeClassifier(
+      const BRepMesh_Edge&                          theConstraint,
+      const Handle(BRepMesh_DataStructureOfDelaun)& theStructure)
+      : myStructure(theStructure)
+    {
+      const BRepMesh_Vertex& aVertex1 = myStructure->GetNode(theConstraint.FirstNode());
+      const BRepMesh_Vertex& aVertex2 = myStructure->GetNode(theConstraint.LastNode());
+
+      myConstraint.SetLocation(aVertex1.Coord());
+      myConstraint.SetDirection(gp_Vec2d(aVertex1.Coord(), aVertex2.Coord()));
+      mySign = myConstraint.Direction().X() > 0;
+    }
+
+    inline Standard_Boolean IsAbove(const Standard_Integer theNodeIndex) const
+    {
+      const BRepMesh_Vertex& aVertex = myStructure->GetNode(theNodeIndex);
+      const gp_Vec2d aNodeVec(myConstraint.Location(), aVertex.Coord());
+      if (aNodeVec.SquareMagnitude() > gp::Resolution())
+      {
+        const Standard_Real aCross = aNodeVec.Crossed(myConstraint.Direction());
+        if (Abs(aCross) > gp::Resolution())
+        {
+          return mySign ? 
+            aCross < 0. :
+            aCross > 0.;
+        }
+      }
+
+      return Standard_False;
+    }
+
+  private:
+
+    NodeClassifier (const NodeClassifier& theOther);
+
+    void operator=(const NodeClassifier& theOther);
+
+  private:
+
+    const Handle(BRepMesh_DataStructureOfDelaun)& myStructure;
+    gp_Lin2d                                      myConstraint;
+    Standard_Boolean                              mySign;
+  };
+
+  //! Constructor.
+  //! Initializes tool by the given data structure.
+  Standard_EXPORT BRepMesh_MeshTool(const Handle(BRepMesh_DataStructureOfDelaun)& theStructure);
+
+  //! Destructor.
+  Standard_EXPORT virtual ~BRepMesh_MeshTool();
+
+  //! Returns data structure manipulated by this tool.
+  inline const Handle(BRepMesh_DataStructureOfDelaun)& GetStructure() const
+  {
+    return myStructure;
+  }
+
+  //! Dumps triangles to specified file.
+  void DumpTriangles(const Standard_CString theFileName, IMeshData::MapOfInteger* theTriangles);
+
+  //! Adds new triangle with specified nodes to mesh.
+  //! Legalizes triangle in case if it violates circle criteria.
+  inline void AddAndLegalizeTriangle(
+    const Standard_Integer thePoint1,
+    const Standard_Integer thePoint2,
+    const Standard_Integer thePoint3)
+  {
+    Standard_Integer aEdges[3];
+    AddTriangle(thePoint1, thePoint2, thePoint3, aEdges);
+
+    Legalize(aEdges[0]);
+    Legalize(aEdges[1]);
+    Legalize(aEdges[2]);
+  }
+
+  //! Adds new triangle with specified nodes to mesh.
+  inline void AddTriangle(
+    const Standard_Integer thePoint1,
+    const Standard_Integer thePoint2,
+    const Standard_Integer thePoint3,
+    Standard_Integer     (&theEdges)[3])
+  {
+    Standard_Boolean aOri[3];
+    AddLink(thePoint1, thePoint2, theEdges[0], aOri[0]);
+    AddLink(thePoint2, thePoint3, theEdges[1], aOri[1]);
+    AddLink(thePoint3, thePoint1, theEdges[2], aOri[2]);
+
+    myStructure->AddElement(BRepMesh_Triangle(theEdges, aOri, BRepMesh_Free));
+  }
+
+  //! Adds new link to mesh.
+  //! Updates link index and link orientaion parameters.
+  inline void AddLink(const Standard_Integer theFirstNode,
+                      const Standard_Integer theLastNode,
+                      Standard_Integer&      theLinkIndex,
+                      Standard_Boolean&      theLinkOri)
+  {
+    const Standard_Integer aLinkIt = myStructure->AddLink(
+      BRepMesh_Edge(theFirstNode, theLastNode, BRepMesh_Free));
+
+    theLinkIndex = Abs(aLinkIt);
+    theLinkOri = (aLinkIt > 0);
+  }
+
+  //! Performs legalization of triangles connected to the specified link.
+  Standard_EXPORT void Legalize(const Standard_Integer theLinkIndex);
+
+  //! Erases all elements connected to the specified artificial node.
+  //! In addition, erases the artificial node itself.
+  Standard_EXPORT void EraseItemsConnectedTo(const Standard_Integer theNodeIndex);
+
+  //! Cleans frontier links from triangles to the right.
+  Standard_EXPORT void CleanFrontierLinks();
+
+  //! Erases the given set of triangles.
+  //! Fills map of loop edges forming the countour surrounding the erased triangles.
+  void EraseTriangles(const IMeshData::MapOfInteger&  theTriangles,
+                      IMeshData::MapOfIntegerInteger& theLoopEdges);
+
+  //! Erases triangle with the given index and adds the free edges into the map.
+  //! When an edge is suppressed more than one time it is destroyed.
+  Standard_EXPORT void EraseTriangle(const Standard_Integer          theTriangleIndex,
+                                     IMeshData::MapOfIntegerInteger& theLoopEdges);
+
+  //! Erases all links that have no elements connected to them.
+  Standard_EXPORT void EraseFreeLinks();
+
+  //! Erases links from the specified map that have no elements connected to them.
+  Standard_EXPORT void EraseFreeLinks(const IMeshData::MapOfIntegerInteger& theLinks);
+
+  //! Gives the list of edges with type defined by input parameter.
+  Standard_EXPORT Handle(IMeshData::MapOfInteger) GetEdgesByType(const BRepMesh_DegreeOfFreedom theEdgeType) const;
+
+  DEFINE_STANDARD_RTTI_INLINE(BRepMesh_MeshTool, Standard_Transient)
+
+private:
+
+  //! Returns True if the given point lies within circumcircle of the given triangle.
+  inline Standard_Boolean checkCircle(
+    const Standard_Integer(&aNodes)[3],
+    const Standard_Integer thePoint)
+  {
+    const BRepMesh_Vertex& aVertex0 = myStructure->GetNode(aNodes[0]);
+    const BRepMesh_Vertex& aVertex1 = myStructure->GetNode(aNodes[1]);
+    const BRepMesh_Vertex& aVertex2 = myStructure->GetNode(aNodes[2]);
+
+    gp_XY aLocation;
+    Standard_Real aRadius;
+    const Standard_Boolean isOk = BRepMesh_CircleTool::MakeCircle(
+      aVertex0.Coord(), aVertex1.Coord(), aVertex2.Coord(),
+      aLocation, aRadius);
+
+    if (isOk)
+    {
+      const BRepMesh_Vertex& aVertex = myStructure->GetNode(thePoint);
+      const Standard_Real aDist = (aVertex.Coord() - aLocation).SquareModulus() - (aRadius * aRadius);
+      return (aDist < Precision::SquareConfusion());
+    }
+
+    return Standard_False;
+  }
+
+  //! Adds new triangle with the given nodes and updates
+  //! links stack by ones are not in used map.
+  inline void addTriangleAndUpdateStack(
+    const Standard_Integer         theNode0,
+    const Standard_Integer         theNode1,
+    const Standard_Integer         theNode2,
+    const IMeshData::MapOfInteger& theUsedLinks,
+    std::stack<Standard_Integer>&  theStack)
+  {
+    Standard_Integer aEdges[3];
+    AddTriangle(theNode0, theNode1, theNode2, aEdges);
+
+    for (Standard_Integer i = 0; i < 3; ++i)
+    {
+      if (!theUsedLinks.Contains(aEdges[i]))
+      {
+        theStack.push(aEdges[i]);
+      }
+    }
+  }
+
+  //! Iteratively erases triangles and their neighbours consisting
+  //! of free links using the given link as starting front.
+  //! Only triangles around the constraint's saddle nodes will be removed.
+  void collectTrianglesOnFreeLinksAroundNodesOf(
+    const BRepMesh_Edge&     theConstraint,
+    const Standard_Integer   theStartLink,
+    IMeshData::MapOfInteger& theTriangles);
+
+private:
+
+  Handle(BRepMesh_DataStructureOfDelaun) myStructure;
+};
+
+#endif