Salome HOME
updated copyright message
[modules/geom.git] / src / BlockFix / BlockFix.cxx
index 30f2505d97193e16bc7d80e2d1fac2bb9f6b9d8b..489506357da0f7ef00d0dd636a3c79fb6b93222a 100644 (file)
@@ -1,4 +1,4 @@
-// Copyright (C) 2007-2016  CEA/DEN, EDF R&D, OPEN CASCADE
+// Copyright (C) 2007-2023  CEA, EDF, OPEN CASCADE
 //
 // Copyright (C) 2003-2007  OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN,
 // CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS
@@ -52,6 +52,7 @@
 #include <BRep_Builder.hxx>
 
 #include <BRepAdaptor_Surface.hxx>
+#include <BRepBndLib.hxx>
 
 #include <BRepTools.hxx>
 #include <BRepTools_Modifier.hxx>
 
 #include <TColgp_SequenceOfPnt2d.hxx>
 
+#include <Basics_OCCTVersion.hxx>
+
+static Standard_Real ComputeMaxTolOfFace(const TopoDS_Face& theFace)
+{
+  Standard_Real MaxTol = BRep_Tool::Tolerance(theFace);
+
+  TopTools_IndexedMapOfShape aMap;
+  TopExp::MapShapes(theFace, TopAbs_EDGE, aMap);
+  for (Standard_Integer i = 1; i <= aMap.Extent(); i++)
+  {
+    const TopoDS_Edge& anEdge = TopoDS::Edge(aMap(i));
+    Standard_Real aTol = BRep_Tool::Tolerance(anEdge);
+    if (aTol > MaxTol)
+      MaxTol = aTol;
+  }
+
+  aMap.Clear();
+  TopExp::MapShapes(theFace, TopAbs_VERTEX, aMap);
+  for (Standard_Integer i = 1; i <= aMap.Extent(); i++)
+  {
+    const TopoDS_Vertex& aVertex = TopoDS::Vertex(aMap(i));
+    Standard_Real aTol = BRep_Tool::Tolerance(aVertex);
+    if (aTol > MaxTol)
+      MaxTol = aTol;
+  }
+
+  return MaxTol;
+}
+
 //=======================================================================
 //function : FixResult
 //purpose  : auxiliary
@@ -203,6 +233,11 @@ TopoDS_Shape BlockFix::RefillProblemFaces (const TopoDS_Shape& aShape)
 {
   Standard_Integer NbSamples = 10;
 
+#if OCC_VERSION_LARGE > 0x07040000
+  TopTools_IndexedDataMapOfShapeListOfShape VFmap;
+  TopExp::MapShapesAndUniqueAncestors(aShape, TopAbs_VERTEX, TopAbs_FACE, VFmap);
+#endif
+
   TopTools_ListOfShape theFaces;
 
   TopExp_Explorer Explo(aShape, TopAbs_FACE);
@@ -243,64 +278,147 @@ TopoDS_Shape BlockFix::RefillProblemFaces (const TopoDS_Shape& aShape)
   TopTools_ListIteratorOfListOfShape itl(theFaces);
   for (; itl.More(); itl.Next())
   {
-    const TopoDS_Face& aFace = TopoDS::Face(itl.Value());
-    BRepOffsetAPI_MakeFilling Filler;
-    for (Explo.Init(aFace, TopAbs_EDGE); Explo.More(); Explo.Next())
+    TopoDS_Face aFace = TopoDS::Face(itl.Value());
+    aFace.Orientation(TopAbs_FORWARD);
+
+    //Compute proper tolerance
+    Standard_Real MaxTolOfFace = ComputeMaxTolOfFace(aFace);
+#if OCC_VERSION_LARGE > 0x07040000
+    Bnd_Box aBndBox;
+    BRepBndLib::Add(aFace, aBndBox);
+    Standard_Real Xmin, Ymin, Zmin, Xmax, Ymax, Zmax;
+    aBndBox.Get(Xmin, Ymin, Zmin, Xmax, Ymax, Zmax);
+    Standard_Real LinSize = Min(Xmax - Xmin, Min(Ymax - Ymin, Zmax - Zmin));
+    Standard_Real LinTol = Max(0.001*LinSize, 1.5*MaxTolOfFace);
+#endif
+    
+    BRepAdaptor_Surface BAsurf(aFace, Standard_False);
+    BRepOffsetAPI_MakeFilling Filler(3, 10);
+    TopExp_Explorer Explo(aFace, TopAbs_EDGE);
+    for (; Explo.More(); Explo.Next())
     {
       const TopoDS_Edge& anEdge = TopoDS::Edge(Explo.Current());
-      if (!BRep_Tool::Degenerated(anEdge))
-        Filler.Add(anEdge, GeomAbs_C0);
+      if (BRep_Tool::Degenerated(anEdge) ||
+          BRepTools::IsReallyClosed(anEdge, aFace))
+        continue;
+      
+      Filler.Add(anEdge, GeomAbs_C0);
+      //Filler.Add(anEdge, aFace, GeomAbs_G1);
     }
     Standard_Real Umin, Umax, Vmin, Vmax;
     BRepTools::UVBounds(aFace, Umin, Umax, Vmin, Vmax);
-    //Handle(Geom_Surface) aSurf = BRep_Tool::Surface(aFace);
-    Standard_Integer i, j;
-    for (i = 1; i < NbSamples; i++)
-      for (j = 1; j < NbSamples; j++) {
-        /*
-        gp_Pnt aPoint = aSurf->Value(Umin + i*(Umax-Umin)/NbSamples,
-                                     Vmin + j*(Vmax-Vmin)/NbSamples);
-        Filler.Add(aPoint);
-        */
-        Filler.Add(Umin + i*(Umax-Umin)/NbSamples,
-                   Vmin + j*(Vmax-Vmin)/NbSamples,
-                   aFace, GeomAbs_G1);
+    Standard_Real DeltaU = (Umax - Umin)/NbSamples,
+      DeltaV = (Vmax - Vmin)/NbSamples;
+    for (Standard_Integer i = 1; i < NbSamples; i++)
+      for (Standard_Integer j = 1; j < NbSamples; j++) {
+        Filler.Add(Umin + i*DeltaU, Vmin + j*DeltaV, aFace, GeomAbs_G1);
       }
 
     Filler.Build();
     if (Filler.IsDone())
     {
-      for (Explo.Init(aFace, TopAbs_EDGE); Explo.More(); Explo.Next())
+      TopoDS_Face aNewFace = TopoDS::Face(Filler.Shape());
+      aNewFace.Orientation(TopAbs_FORWARD);
+      Handle(Geom_Surface) aNewSurf = BRep_Tool::Surface(aNewFace);
+      GeomAdaptor_Surface GAnewsurf(aNewSurf);
+      Extrema_ExtPS Projector;
+      Projector.Initialize(GAnewsurf, GAnewsurf.FirstUParameter(), GAnewsurf.LastUParameter(),
+                           GAnewsurf.FirstVParameter(), GAnewsurf.LastVParameter(),
+                           Precision::Confusion(), Precision::Confusion());
+      Standard_Real MaxSqDist = 0.;
+      for (Standard_Integer i = 0; i < NbSamples; i++)
+        for (Standard_Integer j = 0; j < NbSamples; j++)
+        {
+          gp_Pnt aPoint = BAsurf.Value(Umin + DeltaU/2 + i*DeltaU,
+                                       Vmin + DeltaV/2 + j*DeltaV);
+          Projector.Perform(aPoint);
+          if (Projector.IsDone())
+          {
+            Standard_Real LocalMinSqDist = RealLast();
+            for (Standard_Integer ind = 1; ind <= Projector.NbExt(); ind++)
+            {
+              Standard_Real aSqDist = Projector.SquareDistance(ind);
+              if (aSqDist < LocalMinSqDist)
+                LocalMinSqDist = aSqDist;
+            }
+            if (!Precision::IsInfinite(LocalMinSqDist) &&
+                LocalMinSqDist > MaxSqDist)
+              MaxSqDist = LocalMinSqDist;
+          }
+        }
+      Standard_Real MaxDist = Sqrt(MaxSqDist);
+#if OCC_VERSION_LARGE > 0x07040000
+      if (MaxDist < LinTol)
+#else
+      if (MaxDist < Max(1.e-4, 1.5*MaxTolOfFace))
+#endif
       {
-        const TopoDS_Edge& anEdge = TopoDS::Edge(Explo.Current());
-        TopTools_ListOfShape Ledge;
-        if (!BRep_Tool::Degenerated(anEdge))
+        TopTools_IndexedMapOfShape Emap;
+#if OCC_VERSION_LARGE > 0x07040000
+        TopTools_MapOfShape Vmap;
+#endif
+        TopExp::MapShapes(aFace, TopAbs_EDGE, Emap);
+        for (Standard_Integer i = 1; i <= Emap.Extent(); i++)
         {
-          const TopTools_ListOfShape& Ledges = Filler.Generated(anEdge);
-          if (!Ledges.IsEmpty()) {
-            TopoDS_Shape NewEdge = Ledges.First();
-            Ledge.Append(NewEdge.Oriented(TopAbs_FORWARD));
+          TopoDS_Edge anEdge = TopoDS::Edge(Emap(i));
+          anEdge.Orientation(TopAbs_FORWARD);
+#if OCC_VERSION_LARGE > 0x07040000
+          TopoDS_Vertex V1, V2;
+          TopExp::Vertices(anEdge, V1, V2);
+          TopTools_ListOfShape ListV1, ListV2;
+#endif
+          TopTools_ListOfShape Ledge;
+          if (!BRep_Tool::Degenerated(anEdge) &&
+              !BRepTools::IsReallyClosed(anEdge, aFace))
+          {
+            const TopTools_ListOfShape& Ledges = Filler.Generated(anEdge);
+            if (!Ledges.IsEmpty()) {
+              TopoDS_Edge NewEdge = TopoDS::Edge(Ledges.First());
+              Ledge.Append(NewEdge.Oriented(TopAbs_FORWARD));
+            }
+
+#if OCC_VERSION_LARGE > 0x07040000
+            TopoDS_Vertex NewV1 = TopoDS::Vertex(Filler.Generated(V1).First());
+            ListV1.Append(NewV1.Oriented(TopAbs_FORWARD));
+
+            if (!V1.IsSame(V2)) {
+              TopoDS_Vertex NewV2 = TopoDS::Vertex(Filler.Generated(V2).First());
+              ListV2.Append(NewV2.Oriented(TopAbs_FORWARD));
+            }
+#endif
+          }
+          aSubst.Substitute(anEdge, Ledge);
+#if OCC_VERSION_LARGE > 0x07040000
+          if (!Vmap.Contains(V1) &&
+              (!ListV1.IsEmpty() || VFmap.FindFromKey(V1).Extent() == 1))
+          {
+            aSubst.Substitute(V1, ListV1);
+            Vmap.Add(V1);
+          }
+          if (!Vmap.Contains(V2) &&
+              (!ListV2.IsEmpty() || VFmap.FindFromKey(V2).Extent() == 1))
+          {
+            aSubst.Substitute(V2.Oriented(TopAbs_FORWARD), ListV2);
+            Vmap.Add(V2);
           }
+#endif
         }
-        aSubst.Substitute(anEdge, Ledge);
+        TopTools_ListOfShape Lface;
+        BRepAdaptor_Surface NewBAsurf(aNewFace);
+        gp_Pnt MidPnt;
+        gp_Vec D1U, D1V, Normal, NewNormal;
+        Handle(Geom_Surface) aSurf = BRep_Tool::Surface(aFace);
+        aSurf->D1((Umin+Umax)*0.5, (Vmin+Vmax)*0.5, MidPnt, D1U, D1V);
+        Normal = D1U ^ D1V;
+        NewBAsurf.D1((NewBAsurf.FirstUParameter() + NewBAsurf.LastUParameter())*0.5,
+                     (NewBAsurf.FirstVParameter() + NewBAsurf.LastVParameter())*0.5,
+                     MidPnt, D1U, D1V);
+        NewNormal = D1U ^ D1V;
+        if (Normal * NewNormal < 0.)
+          aNewFace.Reverse();
+        Lface.Append(aNewFace);
+        aSubst.Substitute(aFace, Lface);
       }
-      TopTools_ListOfShape Lface;
-      TopoDS_Face NewFace = TopoDS::Face(Filler.Shape());
-      NewFace.Orientation(TopAbs_FORWARD);
-      BRepAdaptor_Surface NewBAsurf(NewFace);
-      gp_Pnt MidPnt;
-      gp_Vec D1U, D1V, Normal, NewNormal;
-      Handle(Geom_Surface) aSurf = BRep_Tool::Surface(aFace);
-      aSurf->D1((Umin+Umax)*0.5, (Vmin+Vmax)*0.5, MidPnt, D1U, D1V);
-      Normal = D1U ^ D1V;
-      NewBAsurf.D1((NewBAsurf.FirstUParameter() + NewBAsurf.LastUParameter())*0.5,
-                   (NewBAsurf.FirstVParameter() + NewBAsurf.LastVParameter())*0.5,
-                   MidPnt, D1U, D1V);
-      NewNormal = D1U ^ D1V;
-      if (Normal * NewNormal < 0.)
-        NewFace.Reverse();
-      Lface.Append(NewFace);
-      aSubst.Substitute(aFace, Lface);
     }
   }
   aSubst.Build(aShape);