]> SALOME platform Git repositories - modules/geom.git/blob - src/BlockFix/BlockFix.cxx
Salome HOME
ae10155d69b9183db737dccd7ff8a9d33ff23e87
[modules/geom.git] / src / BlockFix / BlockFix.cxx
1 // Copyright (C) 2007-2020  CEA/DEN, EDF R&D, OPEN CASCADE
2 //
3 // Copyright (C) 2003-2007  OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN,
4 // CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS
5 //
6 // This library is free software; you can redistribute it and/or
7 // modify it under the terms of the GNU Lesser General Public
8 // License as published by the Free Software Foundation; either
9 // version 2.1 of the License, or (at your option) any later version.
10 //
11 // This library is distributed in the hope that it will be useful,
12 // but WITHOUT ANY WARRANTY; without even the implied warranty of
13 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14 // Lesser General Public License for more details.
15 //
16 // You should have received a copy of the GNU Lesser General Public
17 // License along with this library; if not, write to the Free Software
18 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
19 //
20 // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
21 //
22
23 // File:        BlockFix.cxx
24 // Created:     Tue Dec  7 11:59:05 2004
25 // Author:      Pavel DURANDIN
26
27 #include <BlockFix.hxx>
28
29 #include <BlockFix_SphereSpaceModifier.hxx>
30 #include <BlockFix_PeriodicSurfaceModifier.hxx>
31
32 #include <TopExp.hxx>
33 #include <TopExp_Explorer.hxx>
34
35 #include <TopLoc_Location.hxx>
36
37 #include <TopoDS.hxx>
38 #include <TopoDS_Edge.hxx>
39 #include <TopoDS_Face.hxx>
40 #include <TopoDS_Wire.hxx>
41 #include <TopoDS_Shape.hxx>
42 #include <TopoDS_Solid.hxx>
43 #include <TopoDS_Vertex.hxx>
44
45 #include <TopTools_ListOfShape.hxx>
46 #include <TopTools_ListIteratorOfListOfShape.hxx>
47 #include <TopTools_MapOfShape.hxx>
48 #include <TopTools_DataMapOfShapeShape.hxx>
49 #include <TopTools_DataMapIteratorOfDataMapOfShapeShape.hxx>
50
51 #include <BRep_Tool.hxx>
52 #include <BRep_Builder.hxx>
53
54 #include <BRepAdaptor_Surface.hxx>
55
56 #include <BRepTools.hxx>
57 #include <BRepTools_Modifier.hxx>
58 #include <BRepTools_Substitution.hxx>
59
60 #include <BRepOffsetAPI_MakeFilling.hxx>
61
62 #include <ShapeFix.hxx>
63 #include <ShapeFix_Edge.hxx>
64 #include <ShapeFix_Face.hxx>
65
66 #include <ShapeAnalysis.hxx>
67 #include <ShapeAnalysis_Edge.hxx>
68 #include <ShapeAnalysis_Curve.hxx>
69 #include <ShapeAnalysis_Surface.hxx>
70
71 #include <ShapeCustom.hxx>
72
73 #include <ShapeBuild_Edge.hxx>
74 #include <ShapeBuild_ReShape.hxx>
75
76 #include <ShapeFix_Wire.hxx>
77
78 #include <Geom_Surface.hxx>
79 #include <Geom_CylindricalSurface.hxx>
80 #include <Geom_ConicalSurface.hxx>
81 #include <Geom_SphericalSurface.hxx>
82 #include <Geom_ToroidalSurface.hxx>
83
84 #include <Geom2d_Curve.hxx>
85
86 #include <TColgp_SequenceOfPnt2d.hxx>
87
88 static Standard_Real ComputeMaxTolOfFace(const TopoDS_Face& theFace)
89 {
90   Standard_Real MaxTol = BRep_Tool::Tolerance(theFace);
91
92   TopTools_IndexedMapOfShape aMap;
93   TopExp::MapShapes(theFace, TopAbs_EDGE, aMap);
94   for (Standard_Integer i = 1; i <= aMap.Extent(); i++)
95   {
96     const TopoDS_Edge& anEdge = TopoDS::Edge(aMap(i));
97     Standard_Real aTol = BRep_Tool::Tolerance(anEdge);
98     if (aTol > MaxTol)
99       MaxTol = aTol;
100   }
101
102   aMap.Clear();
103   TopExp::MapShapes(theFace, TopAbs_VERTEX, aMap);
104   for (Standard_Integer i = 1; i <= aMap.Extent(); i++)
105   {
106     const TopoDS_Vertex& aVertex = TopoDS::Vertex(aMap(i));
107     Standard_Real aTol = BRep_Tool::Tolerance(aVertex);
108     if (aTol > MaxTol)
109       MaxTol = aTol;
110   }
111
112   return MaxTol;
113 }
114
115 //=======================================================================
116 //function : FixResult
117 //purpose  : auxiliary
118 //=======================================================================
119 static void FixResult(const TopoDS_Shape& result,
120                       Handle(ShapeBuild_ReShape)& Context,
121                       const Standard_Real Tol)
122 {
123   for (TopExp_Explorer ex_f(result,TopAbs_FACE); ex_f.More(); ex_f.Next()) {
124     TopoDS_Shape aShape = Context->Apply(ex_f.Current().Oriented(TopAbs_FORWARD));
125     // face could not be dropped or split on this step
126     TopoDS_Face aFace = TopoDS::Face(aShape);
127     TopLoc_Location L;
128     Handle(Geom_Surface) Surf = BRep_Tool::Surface(aFace,L);
129
130     if( Surf->IsKind(STANDARD_TYPE(Geom_SphericalSurface)) ||
131         Surf->IsKind(STANDARD_TYPE(Geom_CylindricalSurface)) ) {
132
133       Standard_Integer nbWires = 0;
134       for (TopExp_Explorer ex_w(aFace,TopAbs_WIRE); ex_w.More(); ex_w.Next()) {
135         nbWires++;
136         Handle(ShapeFix_Wire) sfw = new ShapeFix_Wire(TopoDS::Wire(ex_w.Current()),
137                                                       aFace,
138                                                       Precision::Confusion());
139         sfw->FixReorder();
140         if(sfw->StatusReorder ( ShapeExtend_FAIL ))
141           continue;
142
143         sfw->SetPrecision(2.*Tol);
144         sfw->FixShifted();
145
146         Standard_Boolean isDone = sfw->LastFixStatus ( ShapeExtend_DONE );
147         isDone |= sfw->FixDegenerated();
148
149         // remove degenerated edges from not degenerated points
150         ShapeAnalysis_Edge sae;
151         Handle(ShapeExtend_WireData) sewd = sfw->WireData();
152         Standard_Integer i;
153         for( i = 1; i<=sewd->NbEdges();i++) {
154           TopoDS_Edge E = sewd->Edge(i);
155           if(BRep_Tool::Degenerated(E)&&!sae.HasPCurve(E,aFace)) {
156             sewd->Remove(i);
157             isDone = Standard_True;
158             i--;
159           }
160         }
161
162         //isDone |= sfw->FixLacking(); // commented by skl 22.03.2005 (PAL8395)
163
164         // remove neighbour seam edges
165         if(isDone) {
166           for( i = 1; i<sewd->NbEdges();i++) {
167             if(sewd->IsSeam(i) && sewd->IsSeam(i+1)) {
168               isDone = Standard_True;
169               sewd->Remove(i);
170               sewd->Remove(i);
171               i--;
172             }
173           }
174           if(sewd->IsSeam(1) && sewd->IsSeam(sewd->NbEdges())) {
175             sewd->Remove(1);
176             sewd->Remove(sewd->NbEdges());
177           }
178         }
179
180         if(isDone) {
181           TopoDS_Wire ResWire = sfw->Wire();
182           Context->Replace(ex_w.Current(), ResWire);
183         };
184       }
185       // Implement fix orientation in case of several wires
186       if(nbWires > 1) {
187         TopoDS_Face aFixedFace = TopoDS::Face(Context->Apply(aFace));
188         Handle(ShapeFix_Face) sff = new ShapeFix_Face(aFixedFace);
189         if(sff->FixOrientation())
190           Context->Replace(aFixedFace,sff->Face());
191       }
192     }
193   }
194 }
195
196 //=======================================================================
197 //function : RotateSphereSpace
198 //purpose  :
199 //=======================================================================
200 TopoDS_Shape BlockFix::RotateSphereSpace (const TopoDS_Shape& S,
201                                           const Standard_Real Tol)
202 {
203   // Create a modification description
204   Handle(BlockFix_SphereSpaceModifier) SR = new BlockFix_SphereSpaceModifier;
205   SR->SetTolerance(Tol);
206
207   TopTools_DataMapOfShapeShape context;
208   BRepTools_Modifier MD;
209   TopoDS_Shape result = ShapeCustom::ApplyModifier ( S, SR, context,MD );
210
211   Handle(ShapeBuild_ReShape) RS = new ShapeBuild_ReShape;
212   FixResult(result,RS,Tol);
213   result = RS->Apply(result);
214
215   ShapeFix_Edge sfe;
216   for(TopExp_Explorer exp(result,TopAbs_EDGE); exp.More(); exp.Next()) {
217     TopoDS_Edge E = TopoDS::Edge(exp.Current());
218     sfe.FixVertexTolerance (E);
219   }
220
221   ShapeFix::SameParameter(result,Standard_False);
222   return result;
223 }
224
225 //=======================================================================
226 //function : RefillProblemFaces
227 //purpose  :
228 //=======================================================================
229 TopoDS_Shape BlockFix::RefillProblemFaces (const TopoDS_Shape& aShape)
230 {
231   Standard_Integer NbSamples = 10;
232
233   TopTools_ListOfShape theFaces;
234
235   TopExp_Explorer Explo(aShape, TopAbs_FACE);
236   for (; Explo.More(); Explo.Next())
237   {
238     TopoDS_Face aFace = TopoDS::Face(Explo.Current());
239     BRepAdaptor_Surface BAsurf(aFace);
240     GeomAbs_SurfaceType SurfType = BAsurf.GetType();
241     if (SurfType >= GeomAbs_BezierSurface)
242     {
243       TopExp_Explorer fexp(aFace, TopAbs_EDGE);
244       for (; fexp.More(); fexp.Next())
245       {
246         const TopoDS_Edge& anEdge = TopoDS::Edge(fexp.Current());
247         if (BRep_Tool::Degenerated(anEdge))
248         {
249           TopoDS_Vertex V1, V2;
250           TopExp::Vertices(anEdge, V1, V2);
251           if (V1.IsSame(V2))
252           {
253             gp_Pnt aPnt = BRep_Tool::Pnt(V1);
254             Standard_Real TolV = BRep_Tool::Tolerance(V1);
255             Handle(Geom_Surface) aSurf = BRep_Tool::Surface(aFace);
256             Handle(ShapeAnalysis_Surface) Analyser = new ShapeAnalysis_Surface(aSurf);
257             if (Analyser->IsDegenerated(aPnt, TolV))
258             {
259               theFaces.Append(aFace);
260               break;
261             }
262           }
263         }
264       }
265     }
266   }
267
268   //Now all problem faces are collected in the list "theFaces"
269   BRepTools_Substitution aSubst;
270   TopTools_ListIteratorOfListOfShape itl(theFaces);
271   for (; itl.More(); itl.Next())
272   {
273     TopoDS_Face aFace = TopoDS::Face(itl.Value());
274     aFace.Orientation(TopAbs_FORWARD);
275     Standard_Real MaxTolOfFace = ComputeMaxTolOfFace(aFace);
276     BRepAdaptor_Surface BAsurf(aFace, Standard_False);
277     BRepOffsetAPI_MakeFilling Filler(3, 10);
278     TopExp_Explorer Explo(aFace, TopAbs_EDGE);
279     for (; Explo.More(); Explo.Next())
280     {
281       const TopoDS_Edge& anEdge = TopoDS::Edge(Explo.Current());
282       if (BRep_Tool::Degenerated(anEdge) ||
283           BRepTools::IsReallyClosed(anEdge, aFace))
284         continue;
285       
286       Filler.Add(anEdge, GeomAbs_C0);
287     }
288     Standard_Real Umin, Umax, Vmin, Vmax;
289     BRepTools::UVBounds(aFace, Umin, Umax, Vmin, Vmax);
290     Standard_Real DeltaU = (Umax - Umin)/NbSamples,
291       DeltaV = (Vmax - Vmin)/NbSamples;
292     for (Standard_Integer i = 1; i < NbSamples; i++)
293       for (Standard_Integer j = 1; j < NbSamples; j++) {
294         Filler.Add(Umin + i*DeltaU, Vmin + j*DeltaV, aFace, GeomAbs_G1);
295       }
296
297     Filler.Build();
298     if (Filler.IsDone())
299     {
300       TopoDS_Face aNewFace = TopoDS::Face(Filler.Shape());
301       aNewFace.Orientation(TopAbs_FORWARD);
302       Handle(Geom_Surface) aNewSurf = BRep_Tool::Surface(aNewFace);
303       GeomAdaptor_Surface GAnewsurf(aNewSurf);
304       Extrema_ExtPS Projector;
305       Projector.Initialize(GAnewsurf, GAnewsurf.FirstUParameter(), GAnewsurf.LastUParameter(),
306                            GAnewsurf.FirstVParameter(), GAnewsurf.LastVParameter(),
307                            Precision::Confusion(), Precision::Confusion());
308       Standard_Real MaxSqDist = 0.;
309       for (Standard_Integer i = 0; i < NbSamples; i++)
310         for (Standard_Integer j = 0; j < NbSamples; j++)
311         {
312           gp_Pnt aPoint = BAsurf.Value(Umin + DeltaU/2 + i*DeltaU,
313                                        Vmin + DeltaV/2 + j*DeltaV);
314           Projector.Perform(aPoint);
315           if (Projector.IsDone())
316           {
317             Standard_Real LocalMinSqDist = RealLast();
318             for (Standard_Integer ind = 1; ind <= Projector.NbExt(); ind++)
319             {
320               Standard_Real aSqDist = Projector.SquareDistance(ind);
321               if (aSqDist < LocalMinSqDist)
322                 LocalMinSqDist = aSqDist;
323             }
324             if (!Precision::IsInfinite(LocalMinSqDist) &&
325                 LocalMinSqDist > MaxSqDist)
326               MaxSqDist = LocalMinSqDist;
327           }
328         }
329       Standard_Real MaxDist = Sqrt(MaxSqDist);
330       if (MaxDist < Max(1.e-4, 1.5*MaxTolOfFace))
331       {
332         TopTools_IndexedMapOfShape Emap;
333         TopExp::MapShapes(aFace, TopAbs_EDGE, Emap);
334         for (Standard_Integer i = 1; i <= Emap.Extent(); i++)
335         {
336           TopoDS_Edge anEdge = TopoDS::Edge(Emap(i));
337           anEdge.Orientation(TopAbs_FORWARD);
338           TopTools_ListOfShape Ledge;
339           if (!BRep_Tool::Degenerated(anEdge) &&
340               !BRepTools::IsReallyClosed(anEdge, aFace))
341           {
342             const TopTools_ListOfShape& Ledges = Filler.Generated(anEdge);
343             if (!Ledges.IsEmpty()) {
344               TopoDS_Edge NewEdge = TopoDS::Edge(Ledges.First());
345               Ledge.Append(NewEdge.Oriented(TopAbs_FORWARD));
346             }
347           }
348           aSubst.Substitute(anEdge, Ledge);
349         }
350         TopTools_ListOfShape Lface;
351         BRepAdaptor_Surface NewBAsurf(aNewFace);
352         gp_Pnt MidPnt;
353         gp_Vec D1U, D1V, Normal, NewNormal;
354         Handle(Geom_Surface) aSurf = BRep_Tool::Surface(aFace);
355         aSurf->D1((Umin+Umax)*0.5, (Vmin+Vmax)*0.5, MidPnt, D1U, D1V);
356         Normal = D1U ^ D1V;
357         NewBAsurf.D1((NewBAsurf.FirstUParameter() + NewBAsurf.LastUParameter())*0.5,
358                      (NewBAsurf.FirstVParameter() + NewBAsurf.LastVParameter())*0.5,
359                      MidPnt, D1U, D1V);
360         NewNormal = D1U ^ D1V;
361         if (Normal * NewNormal < 0.)
362           aNewFace.Reverse();
363         Lface.Append(aNewFace);
364         aSubst.Substitute(aFace, Lface);
365       }
366     }
367   }
368   aSubst.Build(aShape);
369
370   TopoDS_Shape Result = aShape;
371   if (aSubst.IsCopied(aShape))
372     Result = aSubst.Copy(aShape).First();
373
374   BRepTools::RemoveUnusedPCurves(Result);
375
376   return Result;
377 }
378
379 //=======================================================================
380 //function : FixRanges
381 //purpose  :
382 //=======================================================================
383 TopoDS_Shape BlockFix::FixRanges (const TopoDS_Shape& S,
384                                   const Standard_Real Tol)
385 {
386   // Create a modification description
387   Handle(BlockFix_PeriodicSurfaceModifier) SR = new BlockFix_PeriodicSurfaceModifier;
388   SR->SetTolerance(Tol);
389
390   TopTools_DataMapOfShapeShape context;
391   BRepTools_Modifier MD;
392   TopoDS_Shape result = ShapeCustom::ApplyModifier ( S, SR, context,MD );
393
394   Handle(ShapeBuild_ReShape) RS = new ShapeBuild_ReShape;
395   FixResult(result,RS,Tol);
396   result = RS->Apply(result);
397
398   ShapeFix_Edge sfe;
399   for(TopExp_Explorer exp(result,TopAbs_EDGE); exp.More(); exp.Next()) {
400     TopoDS_Edge E = TopoDS::Edge(exp.Current());
401     sfe.FixVertexTolerance (E);
402   }
403
404   ShapeFix::SameParameter(result,Standard_False);
405
406   return result;
407 }