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