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