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