Salome HOME
PR: distributed geom and smesh scripts: first step
[modules/geom.git] / src / GEOMAlgo / BlockFix.cxx
1 // Copyright (C) 2007-2012  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.
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 // File:        BlockFix.cxx
23 // Created:     Tue Dec  7 11:59:05 2004
24 // Author:      Pavel DURANDIN
25
26 #include <BlockFix.hxx>
27
28 #include <BlockFix_SphereSpaceModifier.hxx>
29 #include <BlockFix_PeriodicSurfaceModifier.hxx>
30
31 #include <TopExp.hxx>
32 #include <TopExp_Explorer.hxx>
33
34 #include <TopLoc_Location.hxx>
35
36 #include <TopoDS.hxx>
37 #include <TopoDS_Edge.hxx>
38 #include <TopoDS_Face.hxx>
39 #include <TopoDS_Wire.hxx>
40 #include <TopoDS_Shape.hxx>
41 #include <TopoDS_Solid.hxx>
42 #include <TopoDS_Vertex.hxx>
43
44 #include <TopTools_ListOfShape.hxx>
45 #include <TopTools_ListIteratorOfListOfShape.hxx>
46 #include <TopTools_MapOfShape.hxx>
47 #include <TopTools_DataMapOfShapeShape.hxx>
48 #include <TopTools_DataMapIteratorOfDataMapOfShapeShape.hxx>
49
50 #include <BRep_Tool.hxx>
51 #include <BRep_Builder.hxx>
52
53 #include <BRepAdaptor_Surface.hxx>
54
55 #include <BRepTools.hxx>
56 #include <BRepTools_Modifier.hxx>
57 #include <BRepTools_Substitution.hxx>
58
59 #include <BRepOffsetAPI_MakeFilling.hxx>
60
61 #include <ShapeFix.hxx>
62 #include <ShapeFix_Edge.hxx>
63 #include <ShapeFix_Face.hxx>
64
65 #include <ShapeAnalysis.hxx>
66 #include <ShapeAnalysis_Edge.hxx>
67 #include <ShapeAnalysis_Curve.hxx>
68 #include <ShapeAnalysis_Surface.hxx>
69
70 #include <ShapeCustom.hxx>
71
72 #include <ShapeBuild_Edge.hxx>
73 #include <ShapeBuild_ReShape.hxx>
74
75 #include <ShapeFix_Wire.hxx>
76
77 #include <Geom_Surface.hxx>
78 #include <Geom_CylindricalSurface.hxx>
79 #include <Geom_ConicalSurface.hxx>
80 #include <Geom_SphericalSurface.hxx>
81 #include <Geom_ToroidalSurface.hxx>
82
83 #include <Geom2d_Curve.hxx>
84
85 #include <TColgp_SequenceOfPnt2d.hxx>
86
87 //=======================================================================
88 //function : FixResult
89 //purpose  : auxilary
90 //=======================================================================
91 static void FixResult(const TopoDS_Shape& result,
92                       Handle(ShapeBuild_ReShape)& Context,
93                       const Standard_Real Tol)
94 {
95   for (TopExp_Explorer ex_f(result,TopAbs_FACE); ex_f.More(); ex_f.Next()) {
96     TopoDS_Shape aShape = Context->Apply(ex_f.Current().Oriented(TopAbs_FORWARD));
97     // face coud not be dropped or splitted on this step
98     TopoDS_Face aFace = TopoDS::Face(aShape);
99     TopLoc_Location L;
100     Handle(Geom_Surface) Surf = BRep_Tool::Surface(aFace,L);
101
102     if( Surf->IsKind(STANDARD_TYPE(Geom_SphericalSurface)) ||
103         Surf->IsKind(STANDARD_TYPE(Geom_CylindricalSurface)) ) {
104
105       Standard_Integer nbWires = 0;
106       for (TopExp_Explorer ex_w(aFace,TopAbs_WIRE); ex_w.More(); ex_w.Next()) {
107         nbWires++;
108         Handle(ShapeFix_Wire) sfw = new ShapeFix_Wire(TopoDS::Wire(ex_w.Current()),
109                                                       aFace,
110                                                       Precision::Confusion());
111         sfw->FixReorder();
112         if(sfw->StatusReorder ( ShapeExtend_FAIL ))
113           continue;
114
115         sfw->SetPrecision(2.*Tol);
116         sfw->FixShifted();
117
118         Standard_Boolean isDone = sfw->LastFixStatus ( ShapeExtend_DONE );
119         isDone |= sfw->FixDegenerated();
120
121         // remove degenerated edges from not degenerated points
122         ShapeAnalysis_Edge sae;
123         Handle(ShapeExtend_WireData) sewd = sfw->WireData();
124         Standard_Integer i;
125         for( i = 1; i<=sewd->NbEdges();i++) {
126           TopoDS_Edge E = sewd->Edge(i);
127           if(BRep_Tool::Degenerated(E)&&!sae.HasPCurve(E,aFace)) {
128             sewd->Remove(i);
129             isDone = Standard_True;
130             i--;
131           }
132         }
133
134         //isDone |= sfw->FixLacking(); // commented by skl 22.03.2005 (PAL8395)
135
136         // remove neighbour seam edges
137         if(isDone) {
138           for( i = 1; i<sewd->NbEdges();i++) {
139             if(sewd->IsSeam(i) && sewd->IsSeam(i+1)) {
140               isDone = Standard_True;
141               sewd->Remove(i);
142               sewd->Remove(i);
143               i--;
144             }
145           }
146           if(sewd->IsSeam(1) && sewd->IsSeam(sewd->NbEdges())) {
147             sewd->Remove(1);
148             sewd->Remove(sewd->NbEdges());
149           }
150         }
151
152         if(isDone) {
153           TopoDS_Wire ResWire = sfw->Wire();
154           Context->Replace(ex_w.Current(), ResWire);
155         };
156       }
157       // Implement fix orientation in case of several wires
158       if(nbWires > 1) {
159         TopoDS_Face aFixedFace = TopoDS::Face(Context->Apply(aFace));
160         Handle(ShapeFix_Face) sff = new ShapeFix_Face(aFixedFace);
161         if(sff->FixOrientation())
162           Context->Replace(aFixedFace,sff->Face());
163       }
164     }
165   }
166 }
167
168 //=======================================================================
169 //function : RotateSphereSpace
170 //purpose  :
171 //=======================================================================
172 TopoDS_Shape BlockFix::RotateSphereSpace (const TopoDS_Shape& S,
173                                           const Standard_Real Tol)
174 {
175   // Create a modification description
176   Handle(BlockFix_SphereSpaceModifier) SR = new BlockFix_SphereSpaceModifier;
177   SR->SetTolerance(Tol);
178
179   TopTools_DataMapOfShapeShape context;
180   BRepTools_Modifier MD;
181   TopoDS_Shape result = ShapeCustom::ApplyModifier ( S, SR, context,MD );
182
183   Handle(ShapeBuild_ReShape) RS = new ShapeBuild_ReShape;
184   FixResult(result,RS,Tol);
185   result = RS->Apply(result);
186
187   ShapeFix_Edge sfe;
188   for(TopExp_Explorer exp(result,TopAbs_EDGE); exp.More(); exp.Next()) {
189     TopoDS_Edge E = TopoDS::Edge(exp.Current());
190     sfe.FixVertexTolerance (E);
191   }
192
193   ShapeFix::SameParameter(result,Standard_False);
194   return result;
195 }
196
197 //=======================================================================
198 //function : RefillProblemFaces
199 //purpose  :
200 //=======================================================================
201 TopoDS_Shape BlockFix::RefillProblemFaces (const TopoDS_Shape& aShape)
202 {
203   Standard_Integer NbSamples = 10;
204
205   TopTools_ListOfShape theFaces;
206
207   TopExp_Explorer Explo(aShape, TopAbs_FACE);
208   for (; Explo.More(); Explo.Next())
209   {
210     TopoDS_Face aFace = TopoDS::Face(Explo.Current());
211     BRepAdaptor_Surface BAsurf(aFace);
212     GeomAbs_SurfaceType SurfType = BAsurf.GetType();
213     if (SurfType >= GeomAbs_BezierSurface)
214     {
215       TopExp_Explorer fexp(aFace, TopAbs_EDGE);
216       for (; fexp.More(); fexp.Next())
217       {
218         const TopoDS_Edge& anEdge = TopoDS::Edge(fexp.Current());
219         if (BRep_Tool::Degenerated(anEdge))
220         {
221           TopoDS_Vertex V1, V2;
222           TopExp::Vertices(anEdge, V1, V2);
223           if (V1.IsSame(V2))
224           {
225             gp_Pnt aPnt = BRep_Tool::Pnt(V1);
226             Standard_Real TolV = BRep_Tool::Tolerance(V1);
227             Handle(Geom_Surface) aSurf = BRep_Tool::Surface(aFace);
228             Handle(ShapeAnalysis_Surface) Analyser = new ShapeAnalysis_Surface(aSurf);
229             if (Analyser->IsDegenerated(aPnt, TolV))
230             {
231               theFaces.Append(aFace);
232               break;
233             }
234           }
235         }
236       }
237     }
238   }
239
240   //Now all problem faces are collected in the list "theFaces"
241   BRepTools_Substitution aSubst;
242   TopTools_ListIteratorOfListOfShape itl(theFaces);
243   for (; itl.More(); itl.Next())
244   {
245     const TopoDS_Face& aFace = TopoDS::Face(itl.Value());
246     BRepOffsetAPI_MakeFilling Filler;
247     for (Explo.Init(aFace, TopAbs_EDGE); Explo.More(); Explo.Next())
248     {
249       const TopoDS_Edge& anEdge = TopoDS::Edge(Explo.Current());
250       if (!BRep_Tool::Degenerated(anEdge))
251         Filler.Add(anEdge, GeomAbs_C0);
252     }
253     Standard_Real Umin, Umax, Vmin, Vmax;
254     BRepTools::UVBounds(aFace, Umin, Umax, Vmin, Vmax);
255     //Handle(Geom_Surface) aSurf = BRep_Tool::Surface(aFace);
256     Standard_Integer i, j;
257     for (i = 1; i < NbSamples; i++)
258       for (j = 1; j < NbSamples; j++) {
259         /*
260         gp_Pnt aPoint = aSurf->Value(Umin + i*(Umax-Umin)/NbSamples,
261                                      Vmin + j*(Vmax-Vmin)/NbSamples);
262         Filler.Add(aPoint);
263         */
264         Filler.Add(Umin + i*(Umax-Umin)/NbSamples,
265                    Vmin + j*(Vmax-Vmin)/NbSamples,
266                    aFace, GeomAbs_G1);
267       }
268
269     Filler.Build();
270     if (Filler.IsDone())
271     {
272       for (Explo.Init(aFace, TopAbs_EDGE); Explo.More(); Explo.Next())
273       {
274         const TopoDS_Edge& anEdge = TopoDS::Edge(Explo.Current());
275         TopTools_ListOfShape Ledge;
276         if (!BRep_Tool::Degenerated(anEdge))
277         {
278           const TopTools_ListOfShape& Ledges = Filler.Generated(anEdge);
279           if (!Ledges.IsEmpty()) {
280             TopoDS_Shape NewEdge = Ledges.First();
281             Ledge.Append(NewEdge.Oriented(TopAbs_FORWARD));
282           }
283         }
284         aSubst.Substitute(anEdge, Ledge);
285       }
286       TopTools_ListOfShape Lface;
287       TopoDS_Face NewFace = TopoDS::Face(Filler.Shape());
288       NewFace.Orientation(TopAbs_FORWARD);
289       BRepAdaptor_Surface NewBAsurf(NewFace);
290       gp_Pnt MidPnt;
291       gp_Vec D1U, D1V, Normal, NewNormal;
292       Handle(Geom_Surface) aSurf = BRep_Tool::Surface(aFace);
293       aSurf->D1((Umin+Umax)*0.5, (Vmin+Vmax)*0.5, MidPnt, D1U, D1V);
294       Normal = D1U ^ D1V;
295       NewBAsurf.D1((NewBAsurf.FirstUParameter() + NewBAsurf.LastUParameter())*0.5,
296                    (NewBAsurf.FirstVParameter() + NewBAsurf.LastVParameter())*0.5,
297                    MidPnt, D1U, D1V);
298       NewNormal = D1U ^ D1V;
299       if (Normal * NewNormal < 0.)
300         NewFace.Reverse();
301       Lface.Append(NewFace);
302       aSubst.Substitute(aFace, Lface);
303     }
304   }
305   aSubst.Build(aShape);
306
307   TopoDS_Shape Result = aShape;
308   if (aSubst.IsCopied(aShape))
309     Result = aSubst.Copy(aShape).First();
310
311   BRepTools::RemoveUnusedPCurves(Result);
312
313   return Result;
314 }
315
316 //=======================================================================
317 //function : FixRanges
318 //purpose  :
319 //=======================================================================
320 TopoDS_Shape BlockFix::FixRanges (const TopoDS_Shape& S,
321                                   const Standard_Real Tol)
322 {
323   // Create a modification description
324   Handle(BlockFix_PeriodicSurfaceModifier) SR = new BlockFix_PeriodicSurfaceModifier;
325   SR->SetTolerance(Tol);
326
327   TopTools_DataMapOfShapeShape context;
328   BRepTools_Modifier MD;
329   TopoDS_Shape result = ShapeCustom::ApplyModifier ( S, SR, context,MD );
330
331   Handle(ShapeBuild_ReShape) RS = new ShapeBuild_ReShape;
332   FixResult(result,RS,Tol);
333   result = RS->Apply(result);
334
335   ShapeFix_Edge sfe;
336   for(TopExp_Explorer exp(result,TopAbs_EDGE); exp.More(); exp.Next()) {
337     TopoDS_Edge E = TopoDS::Edge(exp.Current());
338     sfe.FixVertexTolerance (E);
339   }
340
341   ShapeFix::SameParameter(result,Standard_False);
342
343   return result;
344 }