0024157: Parallelization of assembly part of BO
[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-2012 OPEN CASCADE SAS
5 //
6 // The content of this file is subject to the Open CASCADE Technology Public
7 // License Version 6.5 (the "License"). You may not use the content of this file
8 // except in compliance with the License. Please obtain a copy of the License
9 // at http://www.opencascade.org and read it completely before using this file.
10 //
11 // The Initial Developer of the Original Code is Open CASCADE S.A.S., having its
12 // main offices at: 1, place des Freres Montgolfier, 78280 Guyancourt, France.
13 //
14 // The Original Code and all software distributed under the License is
15 // distributed on an "AS IS" basis, without warranty of any kind, and the
16 // Initial Developer hereby disclaims all such warranties, including without
17 // limitation, any warranties of merchantability, fitness for a particular
18 // purpose or non-infringement. Please see the License for the specific terms
19 // and conditions governing the rights and limitations under the License.
20
21
22
23 #include <BRepOffset_Analyse.ixx>
24 #include <BRepOffset_Interval.hxx>
25 #include <BRepOffset_Tool.hxx>
26 #include <BRepOffset_ListIteratorOfListOfInterval.hxx>
27 #include <BRep_Tool.hxx>
28 #include <BRepTools.hxx>
29 #include <BRep_Builder.hxx>
30
31 #include <BRepAdaptor_Curve.hxx>
32
33 #include <gp.hxx>
34 #include <gp_Vec.hxx>
35 #include <gp_Dir.hxx>
36 #include <gp_Pnt.hxx>
37 #include <gp_Pnt2d.hxx>
38
39 #include <Geom_Surface.hxx>
40 #include <Geom_Curve.hxx>
41 #include <Geom2d_Curve.hxx>
42
43 #include <TopExp.hxx>
44 #include <TopExp_Explorer.hxx>
45
46 #include <TopoDS.hxx>
47 #include <TopoDS_Face.hxx>
48 #include <TopoDS_Edge.hxx>
49 #include <TopTools_ListIteratorOfListOfShape.hxx>
50 #include <TopTools_MapOfShape.hxx>
51
52 #include <Precision.hxx>
53 #include <gp.hxx>
54
55
56 //=======================================================================
57 //function : BRepOffset_Analyse
58 //purpose  : 
59 //=======================================================================
60
61 BRepOffset_Analyse::BRepOffset_Analyse()
62 :myDone(Standard_False)
63 {
64 }
65
66
67 //=======================================================================
68 //function : BRepOffset_Analyse
69 //purpose  : 
70 //=======================================================================
71
72 BRepOffset_Analyse::BRepOffset_Analyse(const TopoDS_Shape& S, 
73                                        const Standard_Real Angle)
74 :myDone(Standard_False)
75 {
76   Perform( S, Angle);
77 }
78
79 //=======================================================================
80 //function : EdgeAnlyse
81 //purpose  : 
82 //=======================================================================
83
84 static void EdgeAnalyse(const TopoDS_Edge&         E,
85                         const TopoDS_Face&         F1,
86                         const TopoDS_Face&         F2,
87                         const Standard_Real        SinTol,
88                         BRepOffset_ListOfInterval& LI)
89 {
90
91   
92   TopLoc_Location L;
93   Standard_Real   f,l;
94   
95   Handle (Geom_Surface) S1 = BRep_Tool::Surface(F1);
96   Handle (Geom_Surface) S2 = BRep_Tool::Surface(F2);
97   Handle (Geom2d_Curve) C1 = BRep_Tool::CurveOnSurface(E,F1,f,l);
98   Handle (Geom2d_Curve) C2 = BRep_Tool::CurveOnSurface(E,F2,f,l);
99
100   BRepAdaptor_Curve C(E);
101   f = C.FirstParameter();
102   l = C.LastParameter();
103   
104   // Tangent if the regularity is at least G1.
105   if (BRep_Tool::HasContinuity(E,F1,F2)) {
106     if (BRep_Tool::Continuity(E,F1,F2) > GeomAbs_C0) {
107       BRepOffset_Interval I;
108         I.First(f); I.Last(l);
109       I.Type(BRepOffset_Tangent);
110       LI.Append(I);
111       return;
112     }
113   }
114   // First stage : Type determined by one of ends.
115   // Calculate normals and tangents on the curves and surface.
116   // normals are oriented outwards.
117   
118   Standard_Real ParOnC = 0.5*(f+l);
119   gp_Vec T1 = C.DN(ParOnC,1).Transformed(L.Transformation());
120   if (T1.SquareMagnitude() > gp::Resolution()) {
121     T1.Normalize();
122   }
123   
124   if (BRepOffset_Tool::OriEdgeInFace(E,F1) == TopAbs_REVERSED) {
125     T1.Reverse();
126   }
127   if (F1.Orientation() == TopAbs_REVERSED) T1.Reverse();
128
129   gp_Pnt2d P  = C1->Value(ParOnC);
130   gp_Pnt   P3;
131   gp_Vec   D1U,D1V;
132   
133   S1->D1(P.X(),P.Y(),P3,D1U,D1V);
134   gp_Vec DN1(D1U^D1V);
135   if (F1.Orientation() == TopAbs_REVERSED) DN1.Reverse();
136   
137   P = C2->Value(ParOnC);
138   S2->D1(P.X(),P.Y(),P3,D1U,D1V);
139   gp_Vec DN2(D1U^D1V);
140   if (F2.Orientation() == TopAbs_REVERSED) DN2.Reverse();
141
142   DN1.Normalize();
143   DN2.Normalize();
144
145   gp_Vec        ProVec     = DN1^DN2;
146   Standard_Real NormProVec = ProVec.Magnitude(); 
147
148   BRepOffset_Interval I;
149   I.First(f); I.Last(l);
150
151   if (Abs(NormProVec) < SinTol) {
152     // plane
153     if (DN1.Dot(DN2) > 0) {   
154       //Tangent
155       I.Type(BRepOffset_Tangent);
156     }
157     else  {                   
158       //Mixed not finished!
159 #ifdef DEB
160       cout <<" faces locally mixed"<<endl;
161 #endif
162       I.Type(BRepOffset_Convex);
163     }
164   }
165   else {  
166     if (NormProVec > gp::Resolution())
167       ProVec.Normalize();
168     Standard_Real Prod  = T1.Dot(DN1^DN2);
169     if (Prod > 0.) {       
170       //
171       I.Type(BRepOffset_Convex);
172     }
173     else {                       
174       //reenters
175       I.Type(BRepOffset_Concave);
176     }
177   }
178   LI.Append(I);
179 }
180
181 //=======================================================================
182 //function : BuildAncestors
183 //purpose  : 
184 //=======================================================================
185
186 static void BuildAncestors (const TopoDS_Shape&                        S,
187                             TopTools_IndexedDataMapOfShapeListOfShape& MA)
188 {  
189   MA.Clear();
190   TopExp::MapShapesAndAncestors(S,TopAbs_VERTEX,TopAbs_EDGE,MA);
191   TopExp::MapShapesAndAncestors(S,TopAbs_EDGE  ,TopAbs_FACE,MA);
192
193   // Purge ancestors.
194   TopTools_MapOfShape Map;
195   for (Standard_Integer i = 1; i <= MA.Extent(); i++) {
196     Map.Clear();
197     TopTools_ListOfShape&              L = MA(i);
198     TopTools_ListIteratorOfListOfShape it(L);
199     while (it.More()) {
200       if (!Map.Add(it.Value())) {
201         L.Remove(it);
202       }
203       else {
204         it.Next();
205       }
206     }
207   }
208 }
209
210 //=======================================================================
211 //function : IsDone
212 //purpose  : 
213 //=======================================================================
214
215 Standard_Boolean BRepOffset_Analyse::IsDone() const 
216 {
217   return myDone;
218 }
219
220
221 //=======================================================================
222 //function : Perform
223 //purpose  : 
224 //=======================================================================
225
226 void BRepOffset_Analyse::Perform (const TopoDS_Shape& S, 
227                                   const Standard_Real Angle)
228 {
229   myShape = S;
230
231   angle                = Angle;
232   Standard_Real SinTol = sin(Angle);
233
234   // Build ancestors.
235   BuildAncestors (S,ancestors);
236
237   
238   TopExp_Explorer Exp(S.Oriented(TopAbs_FORWARD),TopAbs_EDGE);
239   for ( ; Exp.More(); Exp.Next()) {
240     const TopoDS_Edge& E = TopoDS::Edge(Exp.Current());
241     if (!mapEdgeType.IsBound(E)) {
242       BRepOffset_ListOfInterval LI;
243       mapEdgeType.Bind(E,LI);
244       
245       const TopTools_ListOfShape& L = Ancestors(E);
246       if ( L.IsEmpty()) 
247         continue;
248
249       if (L.Extent() == 2) {
250         const TopoDS_Face& F1 = TopoDS::Face(L.First());
251         const TopoDS_Face& F2 = TopoDS::Face(L.Last ());
252         EdgeAnalyse(E,F1,F2,SinTol,mapEdgeType(E));
253       }
254       else if (L.Extent() == 1) {
255         Standard_Real U1,U2;
256         const TopoDS_Face& F = TopoDS::Face(L.First());
257         BRep_Tool::Range(E,F,U1,U2);
258         BRepOffset_Interval Inter(U1,U2,BRepOffset_Other);
259         
260         if (! BRepTools::IsReallyClosed(E,F)) {
261           Inter.Type(BRepOffset_FreeBoundary);
262         }
263         mapEdgeType(E).Append(Inter);
264       }
265       else {  
266 #ifdef DEB                   
267         cout <<"edge shared by more than two faces"<<endl;
268 #endif  
269       }
270     }
271   }
272   myDone = Standard_True;
273 }
274
275 //=======================================================================
276 //function : Clear
277 //purpose  : 
278 //=======================================================================
279
280 void BRepOffset_Analyse::Clear()
281 {
282   myDone = Standard_False;
283   myShape     .Nullify();
284   mapEdgeType.Clear();
285   ancestors  .Clear();
286 }
287
288
289
290
291
292 //=======================================================================
293 //function : BRepOffset_ListOfInterval&
294 //purpose  : 
295 //=======================================================================
296
297 const BRepOffset_ListOfInterval& BRepOffset_Analyse::Type(const TopoDS_Edge& E)
298 const 
299 {
300   return mapEdgeType (E);
301 }
302
303
304 //=======================================================================
305 //function : Edges
306 //purpose  : 
307 //=======================================================================
308
309 void BRepOffset_Analyse::Edges(const TopoDS_Vertex&  V, 
310                                const BRepOffset_Type T,
311                                TopTools_ListOfShape& LE) 
312 const 
313 {
314   LE.Clear();
315   const TopTools_ListOfShape& L = Ancestors (V);
316   TopTools_ListIteratorOfListOfShape it(L);
317   
318   for ( ;it.More(); it.Next()) {
319     const TopoDS_Edge& E = TopoDS::Edge(it.Value());
320     TopoDS_Vertex V1,V2;
321     BRepOffset_Tool::EdgeVertices (E,V1,V2);
322     if (V1.IsSame(V)) {
323       if (mapEdgeType(E).Last().Type() == T)
324         LE.Append(E);
325     }
326     if (V2.IsSame(V)) {
327       if (mapEdgeType(E).First().Type() == T)
328         LE.Append(E);
329     }
330   }
331 }
332
333
334 //=======================================================================
335 //function : Edges
336 //purpose  : 
337 //=======================================================================
338
339 void BRepOffset_Analyse::Edges(const TopoDS_Face&    F, 
340                                const BRepOffset_Type T,
341                                TopTools_ListOfShape& LE) 
342 const 
343 {
344   LE.Clear();
345   TopExp_Explorer exp(F, TopAbs_EDGE);
346   
347   for ( ;exp.More(); exp.Next()) {
348     const TopoDS_Edge& E = TopoDS::Edge(exp.Current());
349
350     const BRepOffset_ListOfInterval& Lint = Type(E);
351     BRepOffset_ListIteratorOfListOfInterval it(Lint);
352     for ( ;it.More(); it.Next()) {
353       if (it.Value().Type() == T) LE.Append(E);
354     }
355   }
356 }
357
358 //=======================================================================
359 //function : TangentEdges
360 //purpose  : 
361 //=======================================================================
362
363 void BRepOffset_Analyse::TangentEdges(const TopoDS_Edge&    Edge  ,
364                                       const TopoDS_Vertex&  Vertex,
365                                       TopTools_ListOfShape& Edges  ) const 
366 {
367   gp_Vec V,VRef;
368
369
370   Standard_Real U,URef;
371   BRepAdaptor_Curve C3d, C3dRef;
372
373   URef   = BRep_Tool::Parameter(Vertex,Edge);
374   C3dRef = BRepAdaptor_Curve(Edge);
375   VRef   = C3dRef.DN(URef,1);
376   if (VRef.SquareMagnitude() < gp::Resolution()) return;
377
378   Edges.Clear();
379
380   const TopTools_ListOfShape& Anc = Ancestors(Vertex);
381   TopTools_ListIteratorOfListOfShape it(Anc);
382   for ( ; it.More(); it.Next()) {
383     const TopoDS_Edge& CurE = TopoDS::Edge(it.Value());
384     if ( CurE.IsSame(Edge)) continue;
385     U   = BRep_Tool::Parameter(Vertex,CurE);
386     C3d = BRepAdaptor_Curve(CurE);
387     V   = C3d.DN(U,1);
388     if (V.SquareMagnitude() < gp::Resolution()) continue;
389     if (V.IsParallel(VRef,angle)) {
390       Edges.Append(CurE);
391     }
392   }
393 }
394
395
396
397 //=======================================================================
398 //function : HasAncestor
399 //purpose  : 
400 //=======================================================================
401
402 Standard_Boolean  BRepOffset_Analyse::HasAncestor (const TopoDS_Shape& S) const 
403 {
404   return ancestors.Contains(S);
405 }
406
407
408 //=======================================================================
409 //function : Ancestors
410 //purpose  : 
411 //=======================================================================
412
413 const TopTools_ListOfShape& BRepOffset_Analyse::Ancestors 
414 (const TopoDS_Shape& S) const 
415 {
416   return ancestors.FindFromKey(S);
417 }
418
419
420 //=======================================================================
421 //function : Explode
422 //purpose  : 
423 //=======================================================================
424
425 void BRepOffset_Analyse::Explode(      TopTools_ListOfShape& List,
426                                  const BRepOffset_Type       T   ) const 
427 {
428   List.Clear();
429   BRep_Builder B;
430   TopTools_MapOfShape Map;
431   
432   TopExp_Explorer Fexp;
433   for (Fexp.Init(myShape,TopAbs_FACE); Fexp.More(); Fexp.Next()) {
434     if ( Map.Add(Fexp.Current())) {
435       TopoDS_Face Face = TopoDS::Face(Fexp.Current());
436       TopoDS_Compound Co;
437       B.MakeCompound(Co);
438       B.Add(Co,Face);
439       // add to Co all faces from the cloud of faces
440       // G1 created from <Face>
441       AddFaces(Face,Co,Map,T);
442       List.Append(Co);
443     }
444   }
445 }
446
447 //=======================================================================
448 //function : Explode
449 //purpose  : 
450 //=======================================================================
451
452 void BRepOffset_Analyse::Explode(      TopTools_ListOfShape& List,
453                                  const BRepOffset_Type       T1,
454                                  const BRepOffset_Type       T2) const 
455 {
456   List.Clear();
457   BRep_Builder B;
458   TopTools_MapOfShape Map;
459   
460   TopExp_Explorer Fexp;
461   for (Fexp.Init(myShape,TopAbs_FACE); Fexp.More(); Fexp.Next()) {
462     if ( Map.Add(Fexp.Current())) {
463       TopoDS_Face Face = TopoDS::Face(Fexp.Current());
464       TopoDS_Compound Co;
465       B.MakeCompound(Co);
466       B.Add(Co,Face);
467       // add to Co all faces from the cloud of faces
468       // G1 created from  <Face>
469       AddFaces(Face,Co,Map,T1,T2);
470       List.Append(Co);
471     }
472   }
473 }
474
475
476 //=======================================================================
477 //function : AddFaces
478 //purpose  : 
479 //=======================================================================
480
481 void BRepOffset_Analyse::AddFaces (const TopoDS_Face&    Face,
482                                    TopoDS_Compound&      Co,
483                                    TopTools_MapOfShape&  Map,
484                                    const BRepOffset_Type T) const 
485 {
486   BRep_Builder B;
487   TopExp_Explorer exp(Face,TopAbs_EDGE);
488   for ( ; exp.More(); exp.Next()) {
489     const TopoDS_Edge& E = TopoDS::Edge(exp.Current());
490     const BRepOffset_ListOfInterval& LI = Type(E);
491     if (!LI.IsEmpty() && LI.First().Type() == T) {
492       // so <NewFace> is attached to G1 by <Face>
493       const TopTools_ListOfShape& L = Ancestors(E);
494       if (L.Extent() == 2) {
495         TopoDS_Face F1 = TopoDS::Face(L.First());
496         if ( F1.IsSame(Face)) 
497           F1 = TopoDS::Face(L.Last ());
498         if ( Map.Add(F1)) {
499           B.Add(Co,F1);
500           AddFaces(F1,Co,Map,T);
501         }
502       }
503     }
504   }
505 }
506 //=======================================================================
507 //function : AddFaces
508 //purpose  : 
509 //=======================================================================
510
511 void BRepOffset_Analyse::AddFaces (const TopoDS_Face&    Face,
512                                    TopoDS_Compound&      Co,
513                                    TopTools_MapOfShape&  Map,
514                                    const BRepOffset_Type T1,
515                                    const BRepOffset_Type T2) const 
516 {
517   BRep_Builder B;
518   TopExp_Explorer exp(Face,TopAbs_EDGE);
519   for ( ; exp.More(); exp.Next()) {
520     const TopoDS_Edge& E = TopoDS::Edge(exp.Current());
521     const BRepOffset_ListOfInterval& LI = Type(E);
522     if (!LI.IsEmpty() && 
523         (LI.First().Type() == T1 || LI.First().Type() == T2)) {
524       // so <NewFace> is attached to G1 by <Face>
525       const TopTools_ListOfShape& L = Ancestors(E);
526       if (L.Extent() == 2) {
527         TopoDS_Face F1 = TopoDS::Face(L.First());
528         if ( F1.IsSame(Face)) 
529           F1 = TopoDS::Face(L.Last ());
530         if ( Map.Add(F1)) {
531           B.Add(Co,F1);
532           AddFaces(F1,Co,Map,T1,T2);
533         }
534       }
535     }
536   }
537 }