0026396: Taper API result differs run-to-run for identical inputs
[occt.git] / src / Draft / Draft_Modification.cxx
1 // Created on: 1994-08-30
2 // Created by: Jacques GOUSSARD
3 // Copyright (c) 1994-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
18 #include <BRep_Builder.hxx>
19 #include <BRep_Tool.hxx>
20 #include <BRepTools.hxx>
21 #include <Draft_EdgeInfo.hxx>
22 #include <Draft_FaceInfo.hxx>
23 #include <Draft_Modification.hxx>
24 #include <Draft_VertexInfo.hxx>
25 #include <Geom2d_Curve.hxx>
26 #include <Geom_Circle.hxx>
27 #include <Geom_ConicalSurface.hxx>
28 #include <Geom_Curve.hxx>
29 #include <Geom_CylindricalSurface.hxx>
30 #include <Geom_Ellipse.hxx>
31 #include <Geom_RectangularTrimmedSurface.hxx>
32 #include <Geom_SphericalSurface.hxx>
33 #include <Geom_Surface.hxx>
34 #include <Geom_SurfaceOfLinearExtrusion.hxx>
35 #include <Geom_TrimmedCurve.hxx>
36 #include <GeomProjLib.hxx>
37 #include <gp_Dir.hxx>
38 #include <gp_Pln.hxx>
39 #include <gp_Pnt.hxx>
40 #include <gp_Pnt2d.hxx>
41 #include <gp_Vec2d.hxx>
42 #include <Precision.hxx>
43 #include <Standard_ConstructionError.hxx>
44 #include <Standard_DomainError.hxx>
45 #include <Standard_NoSuchObject.hxx>
46 #include <Standard_Type.hxx>
47 #include <StdFail_NotDone.hxx>
48 #include <TopExp.hxx>
49 #include <TopExp_Explorer.hxx>
50 #include <TopLoc_Location.hxx>
51 #include <TopoDS.hxx>
52 #include <TopoDS_Edge.hxx>
53 #include <TopoDS_Face.hxx>
54 #include <TopoDS_Shape.hxx>
55 #include <TopoDS_Vertex.hxx>
56 #include <TopTools_ListIteratorOfListOfShape.hxx>
57
58 //=======================================================================
59 //function : Draft_Modification
60 //purpose  : 
61 //=======================================================================
62 Draft_Modification::Draft_Modification (const TopoDS_Shape& S) :
63        myComp(Standard_False),myShape(S)
64 {
65   TopExp::MapShapesAndAncestors(myShape,TopAbs_EDGE,TopAbs_FACE,myEFMap);
66 }
67
68
69
70 //=======================================================================
71 //function : Clear
72 //purpose  : 
73 //=======================================================================
74
75 void Draft_Modification::Clear ()
76 {
77   myComp = Standard_False;
78   myFMap.Clear();
79   myEMap.Clear();
80   myVMap.Clear();
81   myEFMap.Clear();
82   badShape.Nullify();
83   errStat = Draft_NoError;
84 }
85
86
87
88 //=======================================================================
89 //function : Init
90 //purpose  : 
91 //=======================================================================
92
93 void Draft_Modification::Init(const TopoDS_Shape& S)
94 {
95   myShape = S;
96   Clear();
97   TopExp::MapShapesAndAncestors(myShape,TopAbs_EDGE,TopAbs_FACE,myEFMap);
98 }
99
100 //=======================================================================
101 //function : Add
102 //purpose  : 
103 //=======================================================================
104
105 Standard_Boolean Draft_Modification::Add(const TopoDS_Face& F,
106                                          const gp_Dir& Direction,
107                                          const Standard_Real Angle,
108                                          const gp_Pln& NeutralPlane,
109                                          const Standard_Boolean Flag)
110 {
111   if (!badShape.IsNull()) {
112     Standard_ConstructionError::Raise();
113   }
114
115   if (myComp) {
116     Clear();
117   }
118   curFace = F;
119   return InternalAdd(F,Direction,Angle,NeutralPlane, Flag);
120 }
121
122
123 //=======================================================================
124 //function : Remove
125 //purpose  : 
126 //=======================================================================
127
128 void Draft_Modification::Remove(const TopoDS_Face& F)
129 {
130   if (!myFMap.Contains(F) || myComp) {
131     Standard_NoSuchObject::Raise();
132   }
133
134   conneF.Clear();
135   TopTools_ListIteratorOfListOfShape ltod;
136
137   curFace = myFMap.FindFromKey(F).RootFace();
138   for (Standard_Integer i = 1; i <= myFMap.Extent(); i++)
139   {
140     const TopoDS_Face& theF = myFMap.FindKey(i);
141     if (myFMap.FindFromKey(theF).RootFace().IsSame(curFace)) {
142       conneF.Append(theF);
143       if (theF.IsSame(badShape)) {
144         badShape.Nullify();
145       }
146     }
147   }
148
149   ltod.Initialize(conneF);
150   Standard_Integer IndToReplace = 0;
151   while (ltod.More()) {
152     IndToReplace = myFMap.FindIndex(TopoDS::Face(ltod.Value()));
153     if (IndToReplace)
154     {
155       Standard_Integer LInd = myFMap.Extent();
156       TopoDS_Face LF = myFMap.FindKey(LInd);
157       Draft_FaceInfo LFInfo = myFMap.FindFromIndex(LInd);
158       myFMap.RemoveLast();
159       if (IndToReplace != LInd)
160         myFMap.Substitute(IndToReplace, LF, LFInfo);
161     }
162     ltod.Next();
163   }
164
165   conneF.Clear();
166   for (Standard_Integer i = 1; i <= myEMap.Extent(); i++)
167   {
168     const TopoDS_Edge& theE = myEMap.FindKey(i);
169     if (myEMap.FindFromKey(theE).RootFace().IsSame(curFace))
170        conneF.Append(theE);
171   }
172   ltod.Initialize(conneF);
173   while (ltod.More()) {
174     IndToReplace = myFMap.FindIndex(TopoDS::Face(ltod.Value()));
175     if (IndToReplace)
176     {
177       Standard_Integer LInd = myEMap.Extent();
178       TopoDS_Edge LF = myEMap.FindKey(LInd);
179       Draft_EdgeInfo LFInfo = myEMap.FindFromIndex(LInd);
180       myEMap.RemoveLast();
181       if (IndToReplace != LInd)
182         myEMap.Substitute(IndToReplace, LF, LFInfo);
183     }
184     ltod.Next();
185   }
186 }
187
188
189 //=======================================================================
190 //function : IsDone
191 //purpose  : 
192 //=======================================================================
193
194 Standard_Boolean Draft_Modification::IsDone() const
195 {
196   return myComp && badShape.IsNull();
197
198
199
200 //=======================================================================
201 //function : Error
202 //purpose  : 
203 //=======================================================================
204
205 Draft_ErrorStatus Draft_Modification::Error() const
206 {
207   return errStat;
208
209
210
211 //=======================================================================
212 //function : ProblematicShape
213 //purpose  : 
214 //=======================================================================
215
216 const TopoDS_Shape& Draft_Modification::ProblematicShape() const
217 {
218   return badShape;
219
220
221
222 //=======================================================================
223 //function : ConnectedFaces
224 //purpose  : 
225 //=======================================================================
226
227 const TopTools_ListOfShape & Draft_Modification::ConnectedFaces(const TopoDS_Face& F)
228 {
229   if (!myFMap.Contains(F)) {
230     Standard_NoSuchObject::Raise();
231   }
232   if (!IsDone()) {
233     StdFail_NotDone::Raise();
234   }
235   conneF.Clear();
236   curFace = myFMap.FindFromKey(F).RootFace();
237
238   for (Standard_Integer i = 1; i <= myFMap.Extent(); i++)
239   {
240     const TopoDS_Face& theF = myFMap.FindKey(i);
241     if (myFMap.FindFromKey(theF).RootFace().IsSame(curFace)) {
242       conneF.Append(theF);
243     }
244   }
245
246   return conneF;
247   
248
249 }
250
251
252 //=======================================================================
253 //function : ModifiedFaces
254 //purpose  : 
255 //=======================================================================
256
257 const TopTools_ListOfShape & Draft_Modification::ModifiedFaces()
258 {
259   if (!badShape.IsNull()) {
260     StdFail_NotDone::Raise();
261   }
262   conneF.Clear();
263
264   for (Standard_Integer i = 1; i <= myFMap.Extent(); i++)
265   {
266     const TopoDS_Face& theF = myFMap.FindKey(i);
267     if (!myFMap.FindFromKey(theF).RootFace().IsNull()) {
268       conneF.Append(theF);
269     }
270   }
271
272   return conneF;
273   
274
275 }
276
277
278 //=======================================================================
279 //function : NewSurface
280 //purpose  : 
281 //=======================================================================
282
283 Standard_Boolean Draft_Modification::NewSurface(const TopoDS_Face& F,
284                                                 Handle(Geom_Surface)& S,
285                                                 TopLoc_Location& L,
286                                                 Standard_Real& Tol,
287                                                 Standard_Boolean& RevWires,
288                                                 Standard_Boolean& RevFace)
289 {
290   if (!IsDone()) {Standard_DomainError::Raise();}
291
292   if (!myFMap.Contains(F) || !myFMap.FindFromKey(F).NewGeometry()) {
293     return Standard_False;
294   }
295
296   RevWires = Standard_False;
297   RevFace = Standard_False;
298   Tol = BRep_Tool::Tolerance(F);
299
300   S = BRep_Tool::Surface(F,L);
301
302   L.Identity();
303
304   S = myFMap.FindFromKey(F).Geometry();
305
306   return Standard_True;
307 }
308                                                 
309
310 //=======================================================================
311 //function : NewCurve
312 //purpose  : 
313 //=======================================================================
314
315 Standard_Boolean Draft_Modification::NewCurve(const TopoDS_Edge& E,
316                                               Handle(Geom_Curve)& C,
317                                               TopLoc_Location& L, 
318                                               Standard_Real& Tol)
319 {
320   if (!IsDone()) {Standard_DomainError::Raise();}
321
322   if (!myEMap.Contains(E)) 
323     return Standard_False;
324   
325   const Draft_EdgeInfo& Einf= myEMap.FindFromKey(E);
326   if (!myEMap.FindFromKey(E).NewGeometry())
327     return Standard_False;
328   
329   Tol = Einf.Tolerance();
330   Tol = Max(Tol, BRep_Tool::Tolerance(E));
331   L.Identity();
332   C = myEMap.FindFromKey(E).Geometry();
333
334   return Standard_True;
335
336 }
337
338
339 //=======================================================================
340 //function : NewPoint
341 //purpose  : 
342 //=======================================================================
343
344 Standard_Boolean Draft_Modification::NewPoint(const TopoDS_Vertex& V,
345                                               gp_Pnt& P, 
346                                               Standard_Real& Tol)
347 {
348   if (!IsDone()) {Standard_DomainError::Raise();};
349
350   if (!myVMap.Contains(V)) {
351     return Standard_False;
352   }
353
354   Tol = BRep_Tool::Tolerance(V);
355   P = myVMap.FindFromKey(V).Geometry();
356   return Standard_True;
357 }
358
359
360 //=======================================================================
361 //function : NewCurve2d
362 //purpose  : 
363 //=======================================================================
364
365 Standard_Boolean Draft_Modification::NewCurve2d(const TopoDS_Edge& E, 
366                                                 const TopoDS_Face& F, 
367                                                 const TopoDS_Edge& NewE, 
368                                                 const TopoDS_Face&, 
369                                                 Handle(Geom2d_Curve)& C,
370                                                 Standard_Real& Tol)
371 {
372   
373   if (!IsDone()) {Standard_DomainError::Raise();};
374
375   if (!myEMap.Contains(E)) {
376     return Standard_False;
377   }
378   
379   Standard_Real Fp,Lp;
380   BRep_Tool::Range(NewE,Fp,Lp);
381   
382   Handle(Geom_Surface) SB = myFMap.FindFromKey(F).Geometry();
383
384   const Draft_EdgeInfo& Einf = myEMap.FindFromKey(E);
385   if ( Einf.FirstFace().IsSame(F) && !Einf.FirstPC().IsNull()) {
386     C = Einf.FirstPC();
387   }
388   else if ( Einf.SecondFace().IsSame(F) && !Einf.SecondPC().IsNull()) {
389     C = Einf.SecondPC();
390   }
391   else {
392     
393     if (!myEMap.FindFromKey(E).NewGeometry()) {
394       Standard_Real Fpi,Lpi;
395       BRep_Tool::Range(E,Fpi,Lpi);
396       if (Fpi <= Fp && Fp <= Lpi && Fpi <= Lp && Lp <= Lpi) {
397         return Standard_False;
398       }
399     }
400     
401     Tol = BRep_Tool::Tolerance(E);
402     
403     //  if (!BRep_Tool::IsClosed(E,F)) {
404     BRep_Tool::Range(NewE,Fp,Lp);
405     Handle(Geom_TrimmedCurve) TC = new Geom_TrimmedCurve(myEMap.FindFromKey(E).Geometry(),
406                                                          Fp,Lp);
407     Fp = TC->FirstParameter();
408     Lp = TC->LastParameter();
409     BRep_Builder B;
410     B.Range( NewE, Fp, Lp );
411     C = GeomProjLib::Curve2d(TC,Fp, Lp, SB, Tol);
412   }
413
414   Handle(Standard_Type) typs = SB->DynamicType();
415   if (typs == STANDARD_TYPE(Geom_RectangularTrimmedSurface) ) {
416     SB = Handle(Geom_RectangularTrimmedSurface)::DownCast(SB)->BasisSurface();
417     typs = SB->DynamicType();
418   }
419
420   Standard_Boolean JeRecadre = Standard_False;
421   if (typs == STANDARD_TYPE(Geom_SurfaceOfLinearExtrusion)) {
422     Handle(Geom_Curve) aC = 
423       Handle(Geom_SurfaceOfLinearExtrusion)::DownCast(SB)->BasisCurve();
424     Handle(Standard_Type) typc = aC->DynamicType();
425     if (typc == STANDARD_TYPE(Geom_Circle)) JeRecadre = Standard_True;
426   }
427
428   JeRecadre = JeRecadre || 
429               (typs == STANDARD_TYPE(Geom_CylindricalSurface)) || 
430               (typs == STANDARD_TYPE(Geom_SphericalSurface)) || 
431               (typs == STANDARD_TYPE(Geom_ConicalSurface));
432
433   if ( JeRecadre) {
434     Standard_Boolean bTranslate;
435     Standard_Real aD2, aT1, aT2;
436     gp_Pnt2d  PF, NewPF, aP2DT;
437     gp_Vec2d aV2DT, vectra(2.*M_PI,0.);
438     Handle(Geom2d_Curve) aC2DE;
439     //
440     aC2DE=BRep_Tool::CurveOnSurface(E, F, aT1, aT2);
441     //
442     PF=aC2DE->Value(0.5*(aT1+aT2));
443     //
444     NewPF=C->Value(0.5*(Fp+Lp));
445     //
446     aD2=NewPF.SquareDistance(PF);
447     //
448     bTranslate=Standard_False;
449     if (NewPF.Translated(vectra).SquareDistance(PF) < aD2) {
450       aV2DT=vectra;
451       bTranslate=!bTranslate; //True
452     }
453     else if (NewPF.Translated(-vectra).SquareDistance(PF) < aD2) {
454       aV2DT=-vectra;
455       bTranslate=!bTranslate; //True
456     }
457     //
458     if (bTranslate) {
459       C->Translate(aV2DT);
460     }
461   }
462   return Standard_True;
463 }
464
465
466 //=======================================================================
467 //function : NewParameter
468 //purpose  : 
469 //=======================================================================
470
471 Standard_Boolean Draft_Modification::NewParameter(const TopoDS_Vertex& V,
472                                                   const TopoDS_Edge& E,
473                                                   Standard_Real& P,
474                                                   Standard_Real& Tol)
475 {
476
477   if (!IsDone()) {Standard_DomainError::Raise();};
478
479   if (!myVMap.Contains(V)) {
480     return Standard_False;
481   }
482
483   P = myVMap.ChangeFromKey(V).Parameter(E);
484   Handle(Geom_Curve) GC = myEMap.FindFromKey(E).Geometry();
485   Handle(Standard_Type) typc = GC->DynamicType();
486   if (typc == STANDARD_TYPE(Geom_TrimmedCurve)) {
487     GC = Handle(Geom_TrimmedCurve)::DownCast(GC);
488     typc = GC->DynamicType();
489   }
490
491   if (GC->IsClosed()) {
492     TopoDS_Vertex FV = TopExp::FirstVertex(E);
493     Standard_Real paramf;
494     if (myVMap.Contains(FV)) {
495       paramf = myVMap.ChangeFromKey(FV).Parameter(E);
496     }
497     else {
498       paramf = BRep_Tool::Parameter(FV,E);
499     }
500
501     //Patch
502     Standard_Real FirstPar = GC->FirstParameter(), LastPar = GC->LastParameter();
503     Standard_Real pconf = Precision::PConfusion();
504     if (Abs( paramf - LastPar ) <= pconf)
505       {
506         paramf = FirstPar;
507         FV.Orientation(E.Orientation());
508         if (V.IsEqual( FV ))
509           P = paramf;
510       }
511
512     FV.Orientation(E.Orientation());
513     if (!V.IsEqual(FV) && P <= paramf) {
514       if (GC->IsPeriodic()) {
515         P += GC->Period();
516       }
517       else {
518         P = GC->LastParameter();
519       }
520     }
521   }
522   
523   Tol = Max (BRep_Tool::Tolerance(V), BRep_Tool::Tolerance(E));
524   return Standard_True;
525 }
526
527
528
529 //=======================================================================
530 //function : Continuity
531 //purpose  : 
532 //=======================================================================
533
534 GeomAbs_Shape Draft_Modification::Continuity(const TopoDS_Edge& E,
535                                              const TopoDS_Face& F1,
536                                              const TopoDS_Face& F2,
537                                              const TopoDS_Edge&,
538                                              const TopoDS_Face&,
539                                              const TopoDS_Face&)
540 {
541   return BRep_Tool::Continuity(E,F1,F2);
542 }
543                                              
544