0030940: BRepFilletAPI_MakeFillet algorithm fails on closed shell
[occt.git] / src / BRepOffset / BRepOffset_Analyse.cxx
1 // Created on: 1995-10-20
2 // Created by: Yves FRICAUD
3 // Copyright (c) 1995-1999 Matra Datavision
4 // Copyright (c) 1999-2014 OPEN CASCADE SAS
5 //
6 // This file is part of Open CASCADE Technology software library.
7 //
8 // This library is free software; you can redistribute it and/or modify it under
9 // the terms of the GNU Lesser General Public License version 2.1 as published
10 // by the Free Software Foundation, with special exception defined in the file
11 // OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
12 // distribution for complete text of the license and disclaimer of any warranty.
13 //
14 // Alternatively, this file may be used under the terms of Open CASCADE
15 // commercial license or contractual agreement.
16
17
18 #include <Adaptor3d_Surface.hxx>
19 #include <BRep_Builder.hxx>
20 #include <BRep_Tool.hxx>
21 #include <BRepAdaptor_Curve.hxx>
22 #include <BRepAdaptor_Surface.hxx>
23 #include <BRepOffset_Analyse.hxx>
24 #include <BRepOffset_Interval.hxx>
25 #include <BRepOffset_ListIteratorOfListOfInterval.hxx>
26 #include <BRepOffset_Tool.hxx>
27 #include <BRepTools.hxx>
28 #include <Geom2d_Curve.hxx>
29 #include <Geom_Curve.hxx>
30 #include <Geom_Surface.hxx>
31 #include <gp.hxx>
32 #include <gp_Dir.hxx>
33 #include <gp_Pnt.hxx>
34 #include <gp_Pnt2d.hxx>
35 #include <gp_Vec.hxx>
36 #include <Precision.hxx>
37 #include <TopExp.hxx>
38 #include <TopExp_Explorer.hxx>
39 #include <TopoDS.hxx>
40 #include <TopoDS_Compound.hxx>
41 #include <TopoDS_Edge.hxx>
42 #include <TopoDS_Face.hxx>
43 #include <TopoDS_Shape.hxx>
44 #include <TopoDS_Vertex.hxx>
45 #include <TopTools_ListIteratorOfListOfShape.hxx>
46 #include <TopTools_MapOfShape.hxx>
47 #include <ChFi3d.hxx>
48
49 static void CorrectOrientationOfTangent(gp_Vec& TangVec,
50                                         const TopoDS_Vertex& aVertex,
51                                         const TopoDS_Edge& anEdge)
52 {
53   TopoDS_Vertex Vlast = TopExp::LastVertex(anEdge);
54   if (aVertex.IsSame(Vlast))
55     TangVec.Reverse();
56 }
57 //=======================================================================
58 //function : BRepOffset_Analyse
59 //purpose  : 
60 //=======================================================================
61
62 BRepOffset_Analyse::BRepOffset_Analyse()
63 :myDone(Standard_False)
64 {
65 }
66
67
68 //=======================================================================
69 //function : BRepOffset_Analyse
70 //purpose  : 
71 //=======================================================================
72
73 BRepOffset_Analyse::BRepOffset_Analyse(const TopoDS_Shape& S, 
74                                        const Standard_Real Angle)
75 :myDone(Standard_False)
76 {
77   Perform( S, Angle);
78 }
79
80 //=======================================================================
81 //function : EdgeAnlyse
82 //purpose  : 
83 //=======================================================================
84
85 static void EdgeAnalyse(const TopoDS_Edge&         E,
86                                           const TopoDS_Face&         F1,
87                                           const TopoDS_Face&         F2,
88                                           const Standard_Real        SinTol,
89                                                 BRepOffset_ListOfInterval& LI)
90 {
91   
92   Standard_Real   f,l;
93   BRep_Tool::Range(E, F1, f, l);
94   BRepOffset_Interval I;
95   I.First(f); I.Last(l);
96   //
97   // Tangent if the regularity is at least G1.
98   if (BRep_Tool::HasContinuity(E,F1,F2)) {
99     if (BRep_Tool::Continuity(E,F1,F2) > GeomAbs_C0) {
100       I.Type(ChFiDS_Tangential);
101       LI.Append(I);
102       return;
103     }
104   }
105   //
106   ChFiDS_TypeOfConcavity aType = ChFi3d::DefineConnectType(E, F1, F2,
107                                                            SinTol, Standard_False);
108   if(aType != ChFiDS_Tangential)
109   {
110     aType = ChFi3d::DefineConnectType(E, F1, F2, SinTol, Standard_True);
111   }
112   I.Type(aType);
113   LI.Append(I);
114 }
115
116 //=======================================================================
117 //function : BuildAncestors
118 //purpose  : 
119 //=======================================================================
120
121 static void BuildAncestors (const TopoDS_Shape&                        S,
122                             TopTools_IndexedDataMapOfShapeListOfShape& MA)
123 {  
124   MA.Clear();
125   TopExp::MapShapesAndUniqueAncestors(S,TopAbs_VERTEX,TopAbs_EDGE,MA);
126   TopExp::MapShapesAndUniqueAncestors(S,TopAbs_EDGE  ,TopAbs_FACE,MA);
127 }
128
129 //=======================================================================
130 //function : IsDone
131 //purpose  : 
132 //=======================================================================
133
134 Standard_Boolean BRepOffset_Analyse::IsDone() const 
135 {
136   return myDone;
137 }
138
139
140 //=======================================================================
141 //function : Perform
142 //purpose  : 
143 //=======================================================================
144
145 void BRepOffset_Analyse::Perform (const TopoDS_Shape& S, 
146                                   const Standard_Real Angle)
147 {
148   myShape = S;
149
150   angle                = Angle;
151   Standard_Real SinTol = Sin(Angle);
152
153   // Build ancestors.
154   BuildAncestors (S,ancestors);
155
156   
157   TopExp_Explorer Exp(S.Oriented(TopAbs_FORWARD),TopAbs_EDGE);
158   for ( ; Exp.More(); Exp.Next()) {
159     const TopoDS_Edge& E = TopoDS::Edge(Exp.Current());
160     if (!mapEdgeType.IsBound(E)) {
161       BRepOffset_ListOfInterval LI;
162       mapEdgeType.Bind(E,LI);
163       
164       const TopTools_ListOfShape& L = Ancestors(E);
165       if ( L.IsEmpty()) 
166         continue;
167
168       if (L.Extent() == 2) {
169         const TopoDS_Face& F1 = TopoDS::Face(L.First());
170         const TopoDS_Face& F2 = TopoDS::Face(L.Last ());
171         EdgeAnalyse(E,F1,F2,SinTol,mapEdgeType(E));
172       }
173       else if (L.Extent() == 1) {
174         Standard_Real U1,U2;
175         const TopoDS_Face& F = TopoDS::Face(L.First());
176         BRep_Tool::Range(E,F,U1,U2);
177         BRepOffset_Interval Inter(U1,U2,ChFiDS_Other);
178         
179         if (! BRepTools::IsReallyClosed(E,F)) {
180           Inter.Type(ChFiDS_FreeBound);
181         }
182         mapEdgeType(E).Append(Inter);
183       }
184       else {  
185 #ifdef OCCT_DEBUG
186         std::cout <<"edge shared by more than two faces"<<std::endl;
187 #endif  
188       }
189     }
190   }
191   myDone = Standard_True;
192 }
193
194 //=======================================================================
195 //function : Clear
196 //purpose  : 
197 //=======================================================================
198
199 void BRepOffset_Analyse::Clear()
200 {
201   myDone = Standard_False;
202   myShape     .Nullify();
203   mapEdgeType.Clear();
204   ancestors  .Clear();
205 }
206
207
208
209
210
211 //=======================================================================
212 //function : BRepOffset_ListOfInterval&
213 //purpose  : 
214 //=======================================================================
215
216 const BRepOffset_ListOfInterval& BRepOffset_Analyse::Type(const TopoDS_Edge& E)
217 const 
218 {
219   return mapEdgeType (E);
220 }
221
222
223 //=======================================================================
224 //function : Edges
225 //purpose  : 
226 //=======================================================================
227
228 void BRepOffset_Analyse::Edges(const TopoDS_Vertex&  V, 
229                                const ChFiDS_TypeOfConcavity T,
230                                TopTools_ListOfShape& LE) 
231 const 
232 {
233   LE.Clear();
234   const TopTools_ListOfShape& L = Ancestors (V);
235   TopTools_ListIteratorOfListOfShape it(L);
236   
237   for ( ;it.More(); it.Next()) {
238     const TopoDS_Edge& E = TopoDS::Edge(it.Value());
239     TopoDS_Vertex V1,V2;
240     BRepOffset_Tool::EdgeVertices (E,V1,V2);
241     if (V1.IsSame(V)) {
242       if (mapEdgeType(E).Last().Type() == T)
243         LE.Append(E);
244     }
245     if (V2.IsSame(V)) {
246       if (mapEdgeType(E).First().Type() == T)
247         LE.Append(E);
248     }
249   }
250 }
251
252
253 //=======================================================================
254 //function : Edges
255 //purpose  : 
256 //=======================================================================
257
258 void BRepOffset_Analyse::Edges(const TopoDS_Face&    F, 
259                                const ChFiDS_TypeOfConcavity T,
260                                TopTools_ListOfShape& LE) 
261 const 
262 {
263   LE.Clear();
264   TopExp_Explorer exp(F, TopAbs_EDGE);
265   
266   for ( ;exp.More(); exp.Next()) {
267     const TopoDS_Edge& E = TopoDS::Edge(exp.Current());
268
269     const BRepOffset_ListOfInterval& Lint = Type(E);
270     BRepOffset_ListIteratorOfListOfInterval it(Lint);
271     for ( ;it.More(); it.Next()) {
272       if (it.Value().Type() == T) LE.Append(E);
273     }
274   }
275 }
276
277 //=======================================================================
278 //function : TangentEdges
279 //purpose  : 
280 //=======================================================================
281
282 void BRepOffset_Analyse::TangentEdges(const TopoDS_Edge&    Edge  ,
283                                       const TopoDS_Vertex&  Vertex,
284                                       TopTools_ListOfShape& Edges  ) const 
285 {
286   gp_Vec V,VRef;
287
288
289   Standard_Real U,URef;
290   BRepAdaptor_Curve C3d, C3dRef;
291
292   URef   = BRep_Tool::Parameter(Vertex,Edge);
293   C3dRef = BRepAdaptor_Curve(Edge);
294   VRef   = C3dRef.DN(URef,1);
295   CorrectOrientationOfTangent(VRef, Vertex, Edge);
296   if (VRef.SquareMagnitude() < gp::Resolution()) return;
297
298   Edges.Clear();
299
300   const TopTools_ListOfShape& Anc = Ancestors(Vertex);
301   TopTools_ListIteratorOfListOfShape it(Anc);
302   for ( ; it.More(); it.Next()) {
303     const TopoDS_Edge& CurE = TopoDS::Edge(it.Value());
304     if ( CurE.IsSame(Edge)) continue;
305     U   = BRep_Tool::Parameter(Vertex,CurE);
306     C3d = BRepAdaptor_Curve(CurE);
307     V   = C3d.DN(U,1);
308     CorrectOrientationOfTangent(V, Vertex, CurE);
309     if (V.SquareMagnitude() < gp::Resolution()) continue;
310     if (V.IsOpposite(VRef,angle)) {
311       Edges.Append(CurE);
312     }
313   }
314 }
315
316
317
318 //=======================================================================
319 //function : HasAncestor
320 //purpose  : 
321 //=======================================================================
322
323 Standard_Boolean  BRepOffset_Analyse::HasAncestor (const TopoDS_Shape& S) const 
324 {
325   return ancestors.Contains(S);
326 }
327
328
329 //=======================================================================
330 //function : Ancestors
331 //purpose  : 
332 //=======================================================================
333
334 const TopTools_ListOfShape& BRepOffset_Analyse::Ancestors 
335 (const TopoDS_Shape& S) const 
336 {
337   return ancestors.FindFromKey(S);
338 }
339
340
341 //=======================================================================
342 //function : Explode
343 //purpose  : 
344 //=======================================================================
345
346 void BRepOffset_Analyse::Explode(      TopTools_ListOfShape&        List,
347                                  const ChFiDS_TypeOfConcavity       T   ) const 
348 {
349   List.Clear();
350   BRep_Builder B;
351   TopTools_MapOfShape Map;
352   
353   TopExp_Explorer Fexp;
354   for (Fexp.Init(myShape,TopAbs_FACE); Fexp.More(); Fexp.Next()) {
355     if ( Map.Add(Fexp.Current())) {
356       TopoDS_Face Face = TopoDS::Face(Fexp.Current());
357       TopoDS_Compound Co;
358       B.MakeCompound(Co);
359       B.Add(Co,Face);
360       // add to Co all faces from the cloud of faces
361       // G1 created from <Face>
362       AddFaces(Face,Co,Map,T);
363       List.Append(Co);
364     }
365   }
366 }
367
368 //=======================================================================
369 //function : Explode
370 //purpose  : 
371 //=======================================================================
372
373 void BRepOffset_Analyse::Explode(      TopTools_ListOfShape&  List,
374                                  const ChFiDS_TypeOfConcavity T1,
375                                  const ChFiDS_TypeOfConcavity T2) const 
376 {
377   List.Clear();
378   BRep_Builder B;
379   TopTools_MapOfShape Map;
380   
381   TopExp_Explorer Fexp;
382   for (Fexp.Init(myShape,TopAbs_FACE); Fexp.More(); Fexp.Next()) {
383     if ( Map.Add(Fexp.Current())) {
384       TopoDS_Face Face = TopoDS::Face(Fexp.Current());
385       TopoDS_Compound Co;
386       B.MakeCompound(Co);
387       B.Add(Co,Face);
388       // add to Co all faces from the cloud of faces
389       // G1 created from  <Face>
390       AddFaces(Face,Co,Map,T1,T2);
391       List.Append(Co);
392     }
393   }
394 }
395
396
397 //=======================================================================
398 //function : AddFaces
399 //purpose  : 
400 //=======================================================================
401
402 void BRepOffset_Analyse::AddFaces (const TopoDS_Face&    Face,
403                                    TopoDS_Compound&      Co,
404                                    TopTools_MapOfShape&  Map,
405                                    const ChFiDS_TypeOfConcavity T) const 
406 {
407   BRep_Builder B;
408   TopExp_Explorer exp(Face,TopAbs_EDGE);
409   for ( ; exp.More(); exp.Next()) {
410     const TopoDS_Edge& E = TopoDS::Edge(exp.Current());
411     const BRepOffset_ListOfInterval& LI = Type(E);
412     if (!LI.IsEmpty() && LI.First().Type() == T) {
413       // so <NewFace> is attached to G1 by <Face>
414       const TopTools_ListOfShape& L = Ancestors(E);
415       if (L.Extent() == 2) {
416         TopoDS_Face F1 = TopoDS::Face(L.First());
417         if ( F1.IsSame(Face)) 
418           F1 = TopoDS::Face(L.Last ());
419         if ( Map.Add(F1)) {
420           B.Add(Co,F1);
421           AddFaces(F1,Co,Map,T);
422         }
423       }
424     }
425   }
426 }
427 //=======================================================================
428 //function : AddFaces
429 //purpose  : 
430 //=======================================================================
431
432 void BRepOffset_Analyse::AddFaces (const TopoDS_Face&    Face,
433                                    TopoDS_Compound&      Co,
434                                    TopTools_MapOfShape&  Map,
435                                    const ChFiDS_TypeOfConcavity T1,
436                                    const ChFiDS_TypeOfConcavity T2) const 
437 {
438   BRep_Builder B;
439   TopExp_Explorer exp(Face,TopAbs_EDGE);
440   for ( ; exp.More(); exp.Next()) {
441     const TopoDS_Edge& E = TopoDS::Edge(exp.Current());
442     const BRepOffset_ListOfInterval& LI = Type(E);
443     if (!LI.IsEmpty() && 
444         (LI.First().Type() == T1 || LI.First().Type() == T2)) {
445       // so <NewFace> is attached to G1 by <Face>
446       const TopTools_ListOfShape& L = Ancestors(E);
447       if (L.Extent() == 2) {
448         TopoDS_Face F1 = TopoDS::Face(L.First());
449         if ( F1.IsSame(Face)) 
450           F1 = TopoDS::Face(L.Last ());
451         if ( Map.Add(F1)) {
452           B.Add(Co,F1);
453           AddFaces(F1,Co,Map,T1,T2);
454         }
455       }
456     }
457   }
458 }
459