0024255: Regressions in test cases on OCCT vc9 win64 Release
[occt.git] / src / BRepOffsetAPI / BRepOffsetAPI_MakeOffset.cxx
1 // Created on: 1995-09-18
2 // Created by: Bruno DUMORTIER
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 #include <BRepOffsetAPI_MakeOffset.ixx>
18 #include <BRepBuilderAPI_MakeFace.hxx>
19 #include <BRep_Builder.hxx>
20 #include <BRep_Tool.hxx>
21 #include <BRepAlgo_FaceRestrictor.hxx>
22 #include <Extrema_ExtPS.hxx>
23 #include <BRepAdaptor_Surface.hxx>
24 #include <BRepFill_OffsetWire.hxx>
25 #include <BRepFill_ListIteratorOfListOfOffsetWire.hxx>
26 #include <BRepTopAdaptor_FClass2d.hxx>
27 #include <gp_Pnt2d.hxx>
28 #include <gp_Pnt.hxx>
29 #include <Precision.hxx>
30 #include <TopTools_ListIteratorOfListOfShape.hxx> 
31 #include <TopExp_Explorer.hxx>
32 #include <TopExp.hxx>
33 #include <TopoDS.hxx>
34 #include <TopoDS_Vertex.hxx>
35 #include <TopoDS_Compound.hxx>
36 #include <TopoDS_Wire.hxx>
37
38 #include <StdFail_NotDone.hxx>
39 #ifdef OCCT_DEBUG
40 #include <BRepTools.hxx>
41 static Standard_Boolean AffichSpine = Standard_False;
42 #endif
43
44 //=======================================================================
45 //function : BRepOffsetAPI_MakeOffset
46 //purpose  : 
47 //=======================================================================
48
49 BRepOffsetAPI_MakeOffset::BRepOffsetAPI_MakeOffset()
50 :myIsInitialized( Standard_False)
51 {
52 }
53
54
55 //=======================================================================
56 //function : BRepOffsetAPI_MakeOffset
57 //purpose  : 
58 //=======================================================================
59
60 BRepOffsetAPI_MakeOffset::BRepOffsetAPI_MakeOffset(const TopoDS_Face& Spine, 
61                                                    const GeomAbs_JoinType Join,
62                                                    const Standard_Boolean IsOpenResult)
63 {
64   Init(Spine, Join, IsOpenResult);
65 }
66
67
68 //=======================================================================
69 //function : Init
70 //purpose  : 
71 //=======================================================================
72
73 void BRepOffsetAPI_MakeOffset::Init(const TopoDS_Face&     Spine,
74                                     const GeomAbs_JoinType Join,
75                                     const Standard_Boolean IsOpenResult)
76 {
77   myFace          = Spine;
78   myIsInitialized = Standard_True;
79   myJoin          = Join;
80   myIsOpenResult  = IsOpenResult;
81   TopExp_Explorer exp;
82   for (exp.Init(myFace,TopAbs_WIRE); exp.More();exp.Next()) {
83     myWires.Append(exp.Current());
84   }
85 }
86
87 //=======================================================================
88 //function : BRepOffsetAPI_MakeOffset
89 //purpose  : 
90 //=======================================================================
91
92 BRepOffsetAPI_MakeOffset::BRepOffsetAPI_MakeOffset(const TopoDS_Wire& Spine, 
93                                                    const GeomAbs_JoinType Join,
94                                                    const Standard_Boolean IsOpenResult)
95 {
96   myWires.Append(Spine);
97   myIsInitialized = Standard_True;
98   myJoin = Join;
99   myIsOpenResult  = IsOpenResult;
100 }
101
102 //=======================================================================
103 //function : Init
104 //purpose  : 
105 //=======================================================================
106
107 void BRepOffsetAPI_MakeOffset::Init(const GeomAbs_JoinType Join,
108                                     const Standard_Boolean IsOpenResult)
109 {
110   myJoin = Join;
111   myIsOpenResult  = IsOpenResult;
112 }
113
114 //=======================================================================
115 //function : BRepOffsetAPI_MakeOffset
116 //purpose  : 
117 //=======================================================================
118
119 void BRepOffsetAPI_MakeOffset::AddWire(const TopoDS_Wire& Spine)
120
121 {
122   myIsInitialized = Standard_True;
123   myWires.Append(Spine);
124 }
125
126 //=======================================================================
127 //function : BuildDomain
128 //purpose  : 
129 //=======================================================================
130
131 static void BuildDomains(TopoDS_Face&               myFace,
132                          TopTools_ListOfShape&      WorkWires,
133                          BRepFill_ListOfOffsetWire& myAlgos,
134                          GeomAbs_JoinType           myJoin,
135                          Standard_Boolean           myIsOpenResult,
136                          Standard_Boolean           isPositive)
137 {
138   BRepAlgo_FaceRestrictor  FR;
139   TopoDS_Vertex            VF,VL;
140   TopTools_ListOfShape     LOW;
141   BRep_Builder             B;
142
143   if (myFace.IsNull()) {
144     myFace   = BRepBuilderAPI_MakeFace(TopoDS::Wire(WorkWires.First()),Standard_True);
145     if (myFace.IsNull())
146       StdFail_NotDone::Raise ("BRepOffsetAPI_MakeOffset : the wire is not planar");
147   }
148 //  Modified by Sergey KHROMOV - Thu Apr 26 16:04:43 2001 Begin
149   TopExp_Explorer anExp(myFace, TopAbs_WIRE);
150   TopoDS_Shape    aWire1 = WorkWires.First();
151   TopoDS_Shape    aWire2;
152   if (anExp.More()) {
153     aWire2 = anExp.Current();
154     if ((aWire1.Orientation() == aWire2.Orientation() && isPositive) ||
155       (aWire1.Orientation() == TopAbs::Complement(aWire2.Orientation()) && !isPositive)) {
156         TopTools_ListOfShape LWires;
157         TopTools_ListIteratorOfListOfShape itl;
158         for (itl.Initialize(WorkWires); itl.More(); itl.Next()) {
159           const TopoDS_Shape& W = itl.Value();
160           LWires.Append(W.Reversed());
161         }
162         WorkWires = LWires;
163     }
164   }
165 //  Modified by Sergey KHROMOV - Thu Apr 26 16:04:44 2001 End
166   FR.Init(myFace,Standard_True);
167   //====================================================
168   // Construction of faces limited by closed wires.
169   //====================================================
170   TopTools_ListIteratorOfListOfShape itl(WorkWires);
171   for (; itl.More(); itl.Next()) {
172     TopoDS_Wire& W = TopoDS::Wire(itl.Value());
173     if (W.Closed()){
174       FR.Add(W);
175       continue;
176     }
177     TopExp::Vertices (W,VF,VL);
178     if (VF.IsSame(VL)) {
179       FR.Add(W);
180     }
181     else {
182       LOW.Append(W);
183     }
184   }
185   FR.Perform();
186   if (!FR.IsDone()) {
187     StdFail_NotDone::Raise ("BRepOffsetAPI_MakeOffset : Build Domains");
188   }
189   TopTools_ListOfShape Faces;
190 #ifdef OCCT_DEBUG
191   Standard_Integer ns = 0;
192 #endif
193   for (; FR.More(); FR.Next()) {
194     Faces.Append(FR.Current());
195 #ifdef OCCT_DEBUG
196     if(AffichSpine)
197     {
198       char name[32];
199       ns++;
200       sprintf(name, "FR%d",ns);
201       BRepTools::Write(FR.Current(), name);
202     }
203 #endif
204   }
205
206   //===========================================
207   // No closed wire => only one domain
208   //===========================================
209   if (Faces.IsEmpty()) {
210     TopoDS_Shape aLocalShape = myFace.EmptyCopied();
211     TopoDS_Face F = TopoDS::Face(aLocalShape);
212 //    TopoDS_Face F = TopoDS::Face(myFace.EmptyCopied());
213     TopTools_ListIteratorOfListOfShape itW(LOW);
214     for ( ; itW.More(); itW.Next()) {
215       B.Add(F,itW.Value());
216     }
217     BRepFill_OffsetWire Algo(F, myJoin, myIsOpenResult);
218     myAlgos.Append(Algo);
219     return;
220   }
221
222   //====================================================
223   // Classification of open wires.
224   //====================================================  
225 //  for (TopTools_ListIteratorOfListOfShape itF(Faces); itF.More(); itF.Next()) {
226   TopTools_ListIteratorOfListOfShape itF;
227   for (itF.Initialize(Faces) ; itF.More(); itF.Next()) {
228     TopoDS_Face&          F = TopoDS::Face(itF.Value());
229     BRepAdaptor_Surface   S(F,0);
230     Standard_Real         Tol = BRep_Tool::Tolerance(F); 
231
232     BRepTopAdaptor_FClass2d CL(F,Precision::Confusion());
233
234     TopTools_ListIteratorOfListOfShape itW(LOW);
235     while (itW.More()) {
236       TopoDS_Wire& W = TopoDS::Wire(itW.Value());
237       //=======================================================
238       // Choice of a point on the wire. + projection on the face.
239       //=======================================================
240       TopExp_Explorer exp(W,TopAbs_VERTEX);
241       TopoDS_Vertex   V  = TopoDS::Vertex(exp.Current());
242       gp_Pnt2d        PV;
243       gp_Pnt          P3d = BRep_Tool::Pnt(V);
244       Extrema_ExtPS ExtPS (P3d,S,Tol,Tol);
245       Standard_Real     Dist2Min = Precision::Infinite();
246       Standard_Real     Found   = Standard_False;
247       for (Standard_Integer ie = 1; ie <= ExtPS.NbExt(); ie++) {
248         Standard_Real X,Y;
249         if (ExtPS.SquareDistance(ie) < Dist2Min) {
250           Dist2Min = ExtPS.SquareDistance(ie);
251           Found   = Standard_True;
252           ExtPS.Point(ie).Parameter(X,Y);
253           PV.SetCoord(X,Y);
254         }
255       }
256       if ( Found && (CL.Perform(PV) == TopAbs_IN)) {
257         // The face that contains a wire is found and it is removed from the list
258         B.Add(F,W);
259         LOW.Remove(itW);
260       }
261       else {
262         itW.Next();
263       }
264     }
265   }
266   //========================================
267   // Creation of algorithms on each domain.
268   //========================================
269   for (itF.Initialize(Faces); itF.More(); itF.Next()) {
270     BRepFill_OffsetWire Algo(TopoDS::Face(itF.Value()), myJoin, myIsOpenResult);
271     myAlgos.Append(Algo);
272   }
273 }
274
275 //=======================================================================
276 //function : Perform
277 //purpose  : 
278 //=======================================================================
279
280 void BRepOffsetAPI_MakeOffset::Perform(const Standard_Real Offset,
281                                        const Standard_Real Alt)
282 {
283   StdFail_NotDone_Raise_if ( !myIsInitialized,
284     "BRepOffsetAPI_MakeOffset : Perform without Init");
285
286   try
287   {
288     Standard_Integer i = 1;
289     BRepFill_ListIteratorOfListOfOffsetWire itOW;
290     TopoDS_Compound Res;
291     BRep_Builder    B;
292     B.MakeCompound (Res);
293     myLastIsLeft = (Offset <= 0);
294
295     if( Offset <= 0. )
296     {
297       if( myLeft.IsEmpty() )
298       {
299         //  Modified by Sergey KHROMOV - Fri Apr 27 14:35:26 2001 Begin
300         BuildDomains(myFace,myWires,myLeft,myJoin,myIsOpenResult, Standard_False);
301         //  Modified by Sergey KHROMOV - Fri Apr 27 14:35:26 2001 End
302       }
303
304       for (itOW.Initialize(myLeft); itOW.More(); itOW.Next())
305       {
306         BRepFill_OffsetWire& Algo = itOW.Value();
307         Algo.Perform(Abs(Offset),Alt);
308         if (Algo.IsDone() && !Algo.Shape().IsNull())
309         {
310           B.Add(Res,Algo.Shape());
311           if (i == 1)
312             myShape = Algo.Shape();
313
314           i++;
315         }
316       }
317     }
318     else
319     {
320       if (myRight.IsEmpty())
321       {
322         //  Modified by Sergey KHROMOV - Fri Apr 27 14:35:28 2001 Begin
323         BuildDomains(myFace,myWires,myRight,myJoin,myIsOpenResult, Standard_True);
324         //  Modified by Sergey KHROMOV - Fri Apr 27 14:35:35 2001 End
325       }
326
327       for(itOW.Initialize(myRight); itOW.More(); itOW.Next())
328       {
329         BRepFill_OffsetWire& Algo = itOW.Value();
330         Algo.Perform(Offset,Alt);
331
332         if (Algo.IsDone() && !Algo.Shape().IsNull())
333         {
334           B.Add(Res,Algo.Shape());
335
336           if (i == 1)
337             myShape = Algo.Shape();
338
339           i++;
340         }
341       }
342     }
343
344     if( i > 2 )
345       myShape = Res;
346
347     if(myShape.IsNull())
348       NotDone();
349     else
350       Done();
351   }
352   catch(Standard_Failure) //Every exception was caught.
353   {
354 #ifdef OCCT_DEBUG
355     cout<<"An exception was caught in BRepOffsetAPI_MakeOffset::Perform : ";
356     Standard_ConstructionError::Caught()->Print(cout); 
357     cout<<endl;
358 #endif
359     NotDone();
360     myShape.Nullify();
361   }
362 }
363
364 //=======================================================================
365 //function : Build
366 //purpose  : 
367 //=======================================================================
368
369 void BRepOffsetAPI_MakeOffset::Build()
370 {
371   Done();
372 }
373
374
375 //=======================================================================
376 //function : ShapesFromShape
377 //purpose  : 
378 //=======================================================================
379
380 const TopTools_ListOfShape& BRepOffsetAPI_MakeOffset::Generated
381   (const TopoDS_Shape& S)
382 {
383   myGenerated.Clear();
384   BRepFill_ListIteratorOfListOfOffsetWire itOW;
385   BRepFill_ListOfOffsetWire* Algos;
386   Algos= &myLeft;
387   if (!myLastIsLeft) {
388     Algos = &myRight;
389   }
390   for (itOW.Initialize(*Algos); itOW.More(); itOW.Next()) {
391     BRepFill_OffsetWire& OW = itOW.Value();
392     TopTools_ListOfShape L;
393     L =  OW.GeneratedShapes(S.Oriented(TopAbs_FORWARD));
394     myGenerated.Append(L);
395     L =  OW.GeneratedShapes(S.Oriented(TopAbs_REVERSED));
396     myGenerated.Append(L);
397   }
398   return myGenerated;
399 }