b311480e |
1 | // Created on: 1993-10-14 |
2 | // Created by: Remi LEQUETTE |
3 | // Copyright (c) 1993-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 | // Modified by skv - Fri Mar 4 15:50:09 2005 |
18 | // Add methods for supporting history. |
19 | |
42cf5bc1 |
20 | #include <BRep_TEdge.hxx> |
7fd59977 |
21 | #include <BRepLib.hxx> |
42cf5bc1 |
22 | #include <BRepPrimAPI_MakeRevol.hxx> |
23 | #include <BRepSweep_Revol.hxx> |
24 | #include <gp_Ax1.hxx> |
7fd59977 |
25 | #include <TopExp_Explorer.hxx> |
42cf5bc1 |
26 | #include <TopoDS_Shape.hxx> |
7e4ff648 |
27 | #include <TopTools_DataMapOfShapeListOfShape.hxx> |
28 | #include <BRepTools_ReShape.hxx> |
6f241137 |
29 | #include <Geom_TrimmedCurve.hxx> |
30 | #include <GeomAdaptor_SurfaceOfRevolution.hxx> |
31 | #include <GeomAdaptor_HCurve.hxx> |
32 | #include <Extrema_ExtCC.hxx> |
33 | #include <Extrema_POnCurv.hxx> |
34 | #include <Geom_Line.hxx> |
35 | |
7fd59977 |
36 | // perform checks on the argument |
7fd59977 |
37 | static const TopoDS_Shape& check(const TopoDS_Shape& S) |
38 | { |
39 | BRepLib::BuildCurves3d(S); |
40 | return S; |
41 | } |
42 | |
43 | //======================================================================= |
44 | //function : BRepPrimAPI_MakeRevol |
45 | //purpose : |
46 | //======================================================================= |
47 | |
48 | BRepPrimAPI_MakeRevol::BRepPrimAPI_MakeRevol(const TopoDS_Shape& S, |
49 | const gp_Ax1& A, |
50 | const Standard_Real D, |
6f241137 |
51 | const Standard_Boolean Copy) : |
52 | myRevol(check(S), A, D, Copy), |
53 | myIsBuild(Standard_False) |
54 | |
7fd59977 |
55 | { |
6f241137 |
56 | if (!CheckValidity(check(S), A)) |
57 | { |
58 | myShape.Nullify(); |
59 | myIsBuild = Standard_True; |
60 | } |
61 | else |
62 | { |
63 | Build(); |
64 | } |
7fd59977 |
65 | } |
66 | |
67 | |
68 | //======================================================================= |
69 | //function : BRepPrimAPI_MakeRevol |
70 | //purpose : |
71 | //======================================================================= |
72 | |
73 | BRepPrimAPI_MakeRevol::BRepPrimAPI_MakeRevol(const TopoDS_Shape& S, |
74 | const gp_Ax1& A, |
6f241137 |
75 | const Standard_Boolean Copy) : |
76 | |
77 | myRevol(check(S), A, 2. * M_PI, Copy), |
78 | myIsBuild(Standard_False) |
7fd59977 |
79 | { |
6f241137 |
80 | |
81 | if (!CheckValidity(check(S), A)) |
82 | { |
83 | myShape.Nullify(); |
84 | myIsBuild = Standard_True; |
85 | } |
86 | else |
87 | { |
88 | Build(); |
89 | } |
7fd59977 |
90 | } |
91 | |
92 | |
93 | //======================================================================= |
94 | //function : Revol |
95 | //purpose : |
96 | //======================================================================= |
97 | |
98 | const BRepSweep_Revol& BRepPrimAPI_MakeRevol::Revol() const |
99 | { |
100 | return myRevol; |
101 | } |
102 | |
103 | |
104 | //======================================================================= |
105 | //function : Build |
106 | //purpose : |
107 | //======================================================================= |
108 | |
109 | void BRepPrimAPI_MakeRevol::Build() |
110 | { |
6f241137 |
111 | if (myIsBuild) |
112 | { |
113 | return; |
114 | } |
7fd59977 |
115 | myShape = myRevol.Shape(); |
420f79f8 |
116 | BRepLib::UpdateInnerTolerances(myShape); |
117 | |
7fd59977 |
118 | Done(); |
6f241137 |
119 | myIsBuild = Standard_True; |
120 | |
7e4ff648 |
121 | myHist.Nullify(); |
7fd59977 |
122 | myDegenerated.Clear(); |
7e4ff648 |
123 | TopTools_DataMapOfShapeListOfShape aDegE; |
124 | BRep_Builder aBB; |
7fd59977 |
125 | |
126 | TopExp_Explorer anExp(myShape, TopAbs_EDGE); |
7e4ff648 |
127 | //Problem is that some degenerated edges can be shared by different faces. |
128 | //It is not valid for correct shape. |
129 | //To solve problem it is possible to copy shared degenerated edge for each face, which has it, and |
130 | //replace shared edge by its copy |
7fd59977 |
131 | for (; anExp.More(); anExp.Next()) { |
132 | const TopoDS_Shape &anEdge = anExp.Current(); |
133 | Handle(BRep_TEdge) aTEdge = Handle(BRep_TEdge)::DownCast(anEdge.TShape()); |
134 | |
135 | if (aTEdge->Degenerated()) |
7e4ff648 |
136 | { |
137 | TopTools_ListOfShape* anL = aDegE.ChangeSeek(anEdge); |
138 | if (anL) |
139 | { |
140 | //Make the copy if degenerated edge occurs more then once |
141 | TopoDS_Shape aCopyE = anEdge.EmptyCopied(); |
142 | aCopyE.Orientation(TopAbs_FORWARD); |
143 | TopoDS_Iterator aVIter(anEdge.Oriented(TopAbs_FORWARD), Standard_False); |
144 | for (; aVIter.More(); aVIter.Next()) |
145 | { |
146 | aBB.Add(aCopyE, aVIter.Value()); |
147 | } |
148 | aCopyE.Orientation(anEdge.Orientation()); |
149 | anL->Append(aCopyE); |
150 | myDegenerated.Append(aCopyE); |
151 | } |
152 | else |
153 | { |
154 | anL = aDegE.Bound(anEdge, TopTools_ListOfShape()); |
155 | anL->Append(anEdge); |
156 | myDegenerated.Append(anEdge); |
157 | } |
158 | } |
159 | } |
160 | if (!myDegenerated.IsEmpty()) |
161 | { |
162 | BRepTools_ReShape aSubs; |
163 | TopTools_DataMapOfShapeListOfShape aDegF; |
164 | Standard_Boolean isReplaced = Standard_False; |
165 | anExp.Init(myShape, TopAbs_FACE); |
166 | //Replace degenerated edge by its copies for different faces |
167 | //First, for each face list of d.e. is created |
168 | for (; anExp.More(); anExp.Next()) |
169 | { |
170 | const TopoDS_Shape& aF = anExp.Current(); |
171 | TopExp_Explorer anExpE(aF, TopAbs_EDGE); |
172 | for (; anExpE.More(); anExpE.Next()) |
173 | { |
174 | const TopoDS_Shape &anE = anExpE.Current(); |
175 | if (BRep_Tool::Degenerated(TopoDS::Edge(anE))) |
176 | { |
177 | TopTools_ListOfShape* anL = aDegF.ChangeSeek(aF); |
178 | if (!anL) |
179 | { |
180 | anL = aDegF.Bound(aF, TopTools_ListOfShape()); |
181 | } |
182 | anL->Append(anE); |
183 | } |
184 | } |
185 | } |
186 | // |
187 | //Second, replace edges by copies using ReShape |
188 | BRepTools_ReShape aSubsF; |
189 | TopTools_DataMapIteratorOfDataMapOfShapeListOfShape aFIter(aDegF); |
190 | for (; aFIter.More(); aFIter.Next()) |
191 | { |
192 | aSubs.Clear(); |
193 | isReplaced = Standard_False; |
194 | const TopoDS_Shape& aF = aFIter.Key(); |
195 | const TopTools_ListOfShape& aDEL = aFIter.ChangeValue(); |
196 | TopTools_ListIteratorOfListOfShape anEIter(aDEL); |
197 | for (; anEIter.More(); anEIter.Next()) |
198 | { |
199 | const TopoDS_Shape& anE = anEIter.Value(); |
200 | if (aDegE.IsBound(anE)) |
201 | { |
202 | TopTools_ListOfShape& aCEL = aDegE.ChangeFind(anE); |
203 | TopTools_ListIteratorOfListOfShape anIt(aCEL); |
204 | for (; anIt.More(); anIt.Next()) |
205 | { |
206 | if (anIt.Value().IsEqual(anE)) |
207 | { |
208 | //First occurence of initial deg. edge is not replaced |
209 | aCEL.Remove(anIt); |
210 | break; |
211 | } |
212 | if (anIt.Value().Orientation() == anE.Orientation()) |
213 | { |
214 | //All other occurences of anE are replaced by any copy |
215 | //with suitable orientation |
216 | isReplaced = Standard_True; |
217 | aSubs.Replace(anE, anIt.Value()); |
218 | aCEL.Remove(anIt); |
219 | break; |
220 | } |
221 | } |
222 | } |
223 | } |
224 | if (isReplaced) |
225 | { |
226 | TopoDS_Shape aNF = aSubs.Apply(aF); |
227 | aSubsF.Replace(aF, aNF); |
228 | if (myHist.IsNull()) |
229 | { |
230 | myHist = aSubs.History(); |
231 | } |
232 | else |
233 | { |
234 | myHist->Merge(aSubs.History()); |
235 | } |
236 | myShape = aSubsF.Apply(myShape); |
237 | myHist->Merge(aSubsF.History()); |
238 | //Pair aF->aNF is in history after first replacing of edge by aNF = aSubs.Apply(aF) |
239 | //After merging history for replacing faces, modified list for aF contains two exemplar of aNF |
240 | //So, using ReplaceModified clears modified list for aF and leaves only one exemplar of aNF |
241 | myHist->ReplaceModified(aF, aNF); |
242 | aSubsF.Clear(); |
243 | } |
244 | } |
7fd59977 |
245 | } |
7fd59977 |
246 | } |
6f241137 |
247 | //======================================================================= |
248 | //function : IsIntersect |
249 | //purpose : used in CheckValidity to find out is there |
250 | // intersection between curve and axe of revolution |
251 | //======================================================================= |
252 | static Standard_Boolean IsIntersect(const Handle(Adaptor3d_HCurve)& theC, |
253 | const gp_Ax1& theAxe) |
254 | { |
517ba7aa |
255 | const gp_Lin anAxis(theAxe); |
256 | //Quick test for circle |
257 | if (theC->GetType() == GeomAbs_Circle) |
258 | { |
259 | gp_Circ aCirc = theC->Circle(); |
260 | const gp_Pnt& aCentr = aCirc.Location(); |
261 | Standard_Real anR2 = aCirc.Radius(); |
262 | anR2 -= Precision::Confusion(); |
263 | anR2 *= anR2; |
264 | if (anAxis.SquareDistance(aCentr) > anR2) |
265 | { |
266 | return Standard_False; |
267 | } |
268 | } |
269 | const Handle(Geom_Line) aL = new Geom_Line(anAxis); |
6f241137 |
270 | const GeomAdaptor_Curve aLin(aL); |
271 | const Standard_Real aParTol = theC->Resolution(Precision::Confusion()); |
272 | const Standard_Real aParF = theC->FirstParameter() + aParTol, |
273 | aParL = theC->LastParameter() - aParTol; |
274 | |
275 | Extrema_ExtCC anExtr(theC->Curve(), aLin); |
276 | anExtr.Perform(); |
277 | if (anExtr.IsDone() && anExtr.NbExt() > 0) |
278 | { |
279 | Extrema_POnCurv aP1, aP2; |
280 | for (Standard_Integer i = 1; i <= anExtr.NbExt(); i++) |
281 | { |
282 | if (anExtr.SquareDistance(i) > Precision::SquareConfusion()) |
283 | { |
284 | continue; |
285 | } |
286 | anExtr.Points(i, aP1, aP2); |
287 | if ((aParF < aP1.Parameter()) && (aP1.Parameter() < aParL)) |
288 | { |
289 | return Standard_True; |
290 | } |
291 | } |
292 | } |
293 | return Standard_False; |
294 | } |
295 | |
296 | //======================================================================= |
297 | //function : CheckValidity |
298 | //purpose : |
299 | //======================================================================= |
300 | |
301 | Standard_Boolean BRepPrimAPI_MakeRevol::CheckValidity(const TopoDS_Shape& theShape, |
302 | const gp_Ax1& theA) |
303 | { |
304 | TopExp_Explorer anExp(theShape, TopAbs_EDGE); |
305 | Standard_Boolean IsValid = Standard_True; |
306 | for (; anExp.More(); anExp.Next()) |
307 | { |
308 | const TopoDS_Edge& anE = TopoDS::Edge(anExp.Current()); |
309 | |
310 | if (BRep_Tool::Degenerated(anE)) |
311 | { |
312 | continue; |
313 | } |
314 | |
315 | TopLoc_Location L; |
316 | Standard_Real First, Last; |
317 | Handle(Geom_Curve) C = BRep_Tool::Curve(anE, L, First, Last); |
318 | gp_Trsf Tr = L.Transformation(); |
319 | C = Handle(Geom_Curve)::DownCast(C->Copy()); |
320 | C = new Geom_TrimmedCurve(C, First, Last); |
321 | C->Transform(Tr); |
322 | |
323 | Handle(GeomAdaptor_HCurve) HC = new GeomAdaptor_HCurve(); |
324 | HC->ChangeCurve().Load(C, First, Last); |
325 | //Checking coinsidence axe of revolution and basis curve |
326 | //This code is taken directly from GeomAdaptor_SurfaceOfRevolution |
327 | Standard_Integer Ratio = 1; |
328 | Standard_Real Dist; |
329 | gp_Pnt PP; |
330 | do { |
331 | PP = HC->Value(First + (Last - First) / Ratio); |
332 | Dist = gp_Lin(theA).Distance(PP); |
333 | Ratio++; |
334 | } while (Dist < Precision::Confusion() && Ratio < 100); |
335 | // |
336 | if (Ratio >= 100) // edge coinsides with axes |
337 | { |
338 | IsValid = Standard_True; //Such edges are allowed by revol algo and treated |
339 | //by special way, so they must be concidered as valid |
340 | } |
341 | else |
342 | { |
343 | IsValid = !IsIntersect(HC, theA); |
344 | } |
345 | if (!IsValid) |
346 | { |
347 | break; |
348 | } |
349 | } |
350 | // |
351 | return IsValid; |
352 | } |
7fd59977 |
353 | |
354 | |
355 | //======================================================================= |
356 | //function : FirstShape |
357 | //purpose : |
358 | //======================================================================= |
359 | |
360 | TopoDS_Shape BRepPrimAPI_MakeRevol::FirstShape() |
361 | { |
362 | return myRevol.FirstShape(); |
363 | } |
364 | |
365 | |
366 | //======================================================================= |
367 | //function : LastShape |
368 | //purpose : |
369 | //======================================================================= |
370 | |
371 | TopoDS_Shape BRepPrimAPI_MakeRevol::LastShape() |
372 | { |
373 | return myRevol.LastShape(); |
374 | } |
375 | |
7fd59977 |
376 | //======================================================================= |
377 | //function : Generated |
378 | //purpose : |
379 | //======================================================================= |
7fd59977 |
380 | const TopTools_ListOfShape& BRepPrimAPI_MakeRevol::Generated (const TopoDS_Shape& S) |
381 | { |
382 | myGenerated.Clear(); |
80eeb3ce |
383 | |
384 | if (!myRevol.IsUsed(S)) |
385 | { |
386 | return myGenerated; |
387 | } |
388 | |
7e4ff648 |
389 | TopoDS_Shape aGS = myRevol.Shape(S); |
390 | if (!aGS.IsNull()) |
391 | { |
392 | if (BRepTools_History::IsSupportedType(aGS)) |
393 | { |
80eeb3ce |
394 | if (aGS.ShapeType() == TopAbs_EDGE) |
395 | { |
396 | Standard_Boolean isDeg = BRep_Tool::Degenerated(TopoDS::Edge(aGS)); |
397 | if (isDeg) |
398 | { |
399 | TopTools_ListIteratorOfListOfShape anIt(myDegenerated); |
400 | for (; anIt.More(); anIt.Next()) |
401 | { |
402 | if (aGS.IsSame(anIt.Value())) |
403 | { |
404 | myGenerated.Append(aGS); |
405 | if (!myHist.IsNull()) |
406 | { |
407 | TopTools_ListIteratorOfListOfShape anIt1(myHist->Modified(aGS)); |
408 | for (; anIt1.More(); anIt1.Next()) |
409 | { |
410 | myGenerated.Append(anIt1.Value()); |
411 | } |
412 | return myGenerated; |
413 | } |
414 | } |
415 | } |
416 | return myGenerated; |
417 | } |
418 | } |
419 | // |
7e4ff648 |
420 | if (myHist.IsNull()) |
421 | { |
422 | myGenerated.Append(aGS); |
423 | return myGenerated; |
424 | } |
80eeb3ce |
425 | // |
7e4ff648 |
426 | if (myHist->Modified(aGS).IsEmpty()) |
427 | { |
428 | myGenerated.Append(aGS); |
429 | return myGenerated; |
430 | } |
431 | // |
432 | TopTools_ListIteratorOfListOfShape anIt(myHist->Modified(aGS)); |
433 | for (; anIt.More(); anIt.Next()) |
434 | { |
435 | myGenerated.Append(anIt.Value()); |
436 | } |
7e4ff648 |
437 | } |
438 | } |
7fd59977 |
439 | return myGenerated; |
440 | } |
80eeb3ce |
441 | //======================================================================= |
442 | //function : IsDeleted |
443 | //purpose : |
444 | //======================================================================= |
445 | Standard_Boolean BRepPrimAPI_MakeRevol::IsDeleted(const TopoDS_Shape& S) |
446 | { |
447 | return !myRevol.IsUsed(S); |
448 | } |
449 | |
7fd59977 |
450 | |
7fd59977 |
451 | //======================================================================= |
452 | //function : FirstShape |
453 | //purpose : This method returns the shape of the beginning of the revolution, |
454 | // generated with theShape (subShape of the generating shape). |
455 | //======================================================================= |
456 | |
457 | TopoDS_Shape BRepPrimAPI_MakeRevol::FirstShape(const TopoDS_Shape &theShape) |
458 | { |
459 | return myRevol.FirstShape(theShape); |
460 | } |
461 | |
462 | |
463 | //======================================================================= |
464 | //function : LastShape |
465 | //purpose : This method returns the shape of the end of the revolution, |
466 | // generated with theShape (subShape of the generating shape). |
467 | //======================================================================= |
468 | |
469 | TopoDS_Shape BRepPrimAPI_MakeRevol::LastShape(const TopoDS_Shape &theShape) |
470 | { |
471 | return myRevol.LastShape(theShape); |
472 | } |
473 | |
474 | //======================================================================= |
475 | //function : HasDegenerated |
476 | //purpose : |
477 | //======================================================================= |
478 | |
479 | Standard_Boolean BRepPrimAPI_MakeRevol::HasDegenerated () const |
480 | { |
481 | return (!myDegenerated.IsEmpty()); |
482 | } |
483 | |
484 | |
485 | //======================================================================= |
486 | //function : Degenerated |
487 | //purpose : |
488 | //======================================================================= |
489 | |
490 | const TopTools_ListOfShape& BRepPrimAPI_MakeRevol::Degenerated () const |
491 | { |
492 | return myDegenerated; |
493 | } |