0031460: Modeling Algorithms - Regression: Revolution not done.
[occt.git] / src / BRepPrimAPI / BRepPrimAPI_MakeRevol.cxx
CommitLineData
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 37static 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
48BRepPrimAPI_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
73BRepPrimAPI_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
98const BRepSweep_Revol& BRepPrimAPI_MakeRevol::Revol() const
99{
100 return myRevol;
101}
102
103
104//=======================================================================
105//function : Build
106//purpose :
107//=======================================================================
108
109void 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//=======================================================================
252static 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
301Standard_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
360TopoDS_Shape BRepPrimAPI_MakeRevol::FirstShape()
361{
362 return myRevol.FirstShape();
363}
364
365
366//=======================================================================
367//function : LastShape
368//purpose :
369//=======================================================================
370
371TopoDS_Shape BRepPrimAPI_MakeRevol::LastShape()
372{
373 return myRevol.LastShape();
374}
375
7fd59977 376//=======================================================================
377//function : Generated
378//purpose :
379//=======================================================================
7fd59977 380const 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//=======================================================================
445Standard_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
457TopoDS_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
469TopoDS_Shape BRepPrimAPI_MakeRevol::LastShape(const TopoDS_Shape &theShape)
470{
471 return myRevol.LastShape(theShape);
472}
473
474//=======================================================================
475//function : HasDegenerated
476//purpose :
477//=======================================================================
478
479Standard_Boolean BRepPrimAPI_MakeRevol::HasDegenerated () const
480{
481 return (!myDegenerated.IsEmpty());
482}
483
484
485//=======================================================================
486//function : Degenerated
487//purpose :
488//=======================================================================
489
490const TopTools_ListOfShape& BRepPrimAPI_MakeRevol::Degenerated () const
491{
492 return myDegenerated;
493}