0026619: Tolerances of operands are modified using bop
[occt.git] / src / IntTools / IntTools_ShrunkRange.cxx
1 // Created by: Peter KURNEV
2 // Copyright (c) 1999-2014 OPEN CASCADE SAS
3 //
4 // This file is part of Open CASCADE Technology software library.
5 //
6 // This library is free software; you can redistribute it and/or modify it under
7 // the terms of the GNU Lesser General Public License version 2.1 as published
8 // by the Free Software Foundation, with special exception defined in the file
9 // OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
10 // distribution for complete text of the license and disclaimer of any warranty.
11 //
12 // Alternatively, this file may be used under the terms of Open CASCADE
13 // commercial license or contractual agreement.
14
15
16 #include <Bnd_Box.hxx>
17 #include <BndLib_Add3dCurve.hxx>
18 #include <BRep_Tool.hxx>
19 #include <BRepAdaptor_Curve.hxx>
20 #include <BRepBuilderAPI_MakeVertex.hxx>
21 #include <ElCLib.hxx>
22 #include <Geom_Curve.hxx>
23 #include <gp.hxx>
24 #include <gp_Circ.hxx>
25 #include <gp_Lin.hxx>
26 #include <IntTools_Context.hxx>
27 #include <IntTools_ShrunkRange.hxx>
28 #include <Precision.hxx>
29 #include <TopoDS_Edge.hxx>
30 #include <TopoDS_Vertex.hxx>
31
32 //=======================================================================
33 //function : 
34 //purpose  : 
35 //=======================================================================
36   IntTools_ShrunkRange::IntTools_ShrunkRange ()
37 {
38   myT1=-99;
39   myT2=myT1;
40   myTS1=myT1;
41   myTS2=myT1;
42   myErrorStatus=1;
43 }
44 //=======================================================================
45 //function : ~
46 //purpose  : 
47 //=======================================================================
48 IntTools_ShrunkRange::~IntTools_ShrunkRange () 
49 {
50 }
51 //=======================================================================
52 //function : SetData
53 //purpose  : 
54 //=======================================================================
55 void IntTools_ShrunkRange::SetData(const TopoDS_Edge& aE,
56                                    const Standard_Real aT1,
57                                    const Standard_Real aT2,
58                                    const TopoDS_Vertex& aV1,
59                                    const TopoDS_Vertex& aV2)
60 {
61   myEdge=aE;
62   myV1=aV1;
63   myV2=aV2;
64   myT1=aT1;
65   myT2=aT2;
66   myErrorStatus=1;
67 }
68 //=======================================================================
69 //function : SetContext
70 //purpose  : 
71 //=======================================================================
72 void IntTools_ShrunkRange::SetContext(const Handle(IntTools_Context)& aCtx)
73 {
74   myCtx=aCtx;
75 }
76 //=======================================================================
77 //function : Context
78 //purpose  : 
79 //=======================================================================
80 const Handle(IntTools_Context)& IntTools_ShrunkRange::Context()const
81 {
82   return myCtx;
83 }
84 //=======================================================================
85 //function : Edge
86 //purpose  : 
87 //=======================================================================
88 const TopoDS_Edge& IntTools_ShrunkRange::Edge() const
89 {
90   return myEdge;
91 }
92 //=======================================================================
93 //function : ShrunkRange
94 //purpose  : 
95 //=======================================================================
96 void IntTools_ShrunkRange::ShrunkRange(Standard_Real& aT1,
97                                        Standard_Real& aT2) const
98 {
99   aT1=myTS1;
100   aT2=myTS2;
101 }
102 //=======================================================================
103 //function : BndBox
104 //purpose  : 
105 //=======================================================================
106 const Bnd_Box& IntTools_ShrunkRange::BndBox() const
107 {
108   return myBndBox;
109 }
110 //=======================================================================
111 //function : ErrorStatus
112 //purpose  : 
113 //=======================================================================
114 Standard_Integer IntTools_ShrunkRange::ErrorStatus() const
115 {
116   return myErrorStatus;
117 }
118
119 //=======================================================================
120 //function : SetShrunkRange
121 //purpose  : 
122 //=======================================================================
123 void IntTools_ShrunkRange::SetShrunkRange(const Standard_Real aT1,
124                                           const Standard_Real aT2) 
125 {
126   myTS1=aT1;
127   myTS2=aT2;
128   //
129   BRepAdaptor_Curve aBAC(myEdge);
130   BndLib_Add3dCurve::Add (aBAC, aT1, aT2, 0., myBndBox);
131 }
132
133 //=======================================================================
134 //function : Perform
135 //purpose  : 
136 //=======================================================================
137 void IntTools_ShrunkRange::Perform()
138 {
139   Standard_Real aCF, aCL, aTolE, aTolV1;
140   Standard_Real aTolV2, t1, t11, t1C, t2, t12, t2C, dummy;
141   Standard_Real aCoeff1, aCoeff2, aTol1, aTol2, dt1, dt2, aR, anEps;
142   Standard_Integer pri;
143   Standard_Boolean bInf1, bInf2, bAppr;
144   GeomAbs_CurveType aCurveType;
145   Handle(Geom_Curve) aC;
146   //
147   myErrorStatus=0;
148   myTS1=-99;
149   myTS2=myTS1;
150   anEps = 1.e-8;
151   //
152   aTolE =BRep_Tool::Tolerance(myEdge);
153   aTolV1=BRep_Tool::Tolerance(myV1);
154   aTolV2=BRep_Tool::Tolerance(myV2);
155   //for edges with the tolerance value 
156   //more than the tolerance value of vertices
157   if (aTolV1 < aTolE) {
158     aTolV1 = aTolE;
159   }
160   //
161   if (aTolV2 < aTolE) {
162     aTolV2 = aTolE;
163   }
164   //
165   t1=myT1;
166   t2=myT2;
167   //
168   BRepAdaptor_Curve aBAC(myEdge);
169   aCurveType=aBAC.GetType();
170   //
171   aC=BRep_Tool::Curve(myEdge, aCF, aCL);
172   BRep_Tool::Range(myEdge, aCF, aCL);
173   //
174   if (t1 < aCF || t2 > aCL) {
175     myErrorStatus=2;
176     return;
177   }
178   //
179   bAppr = !(fabs(t2 - t1) > 100);
180   if (fabs(t2 - t1) < anEps) {
181     myErrorStatus=7;
182     return;
183   }
184   //
185   if (t1 > t2) {
186     myErrorStatus=3;
187     return;
188   }
189   //
190   aTol1 = Max(aTolV1, aTolE);
191   aTol2 = Max(aTolV2, aTolE);
192   //
193   aCoeff1 = (aTolE>0.05) ? 1. : 2.;
194   aCoeff2 = aCoeff1;
195   if (aCoeff1 == 2.) {
196     aCoeff1=(aTol1>0.05) ? 1.5 : 2.;
197     aCoeff2=(aTol2>0.05) ? 1.5 : 2.;
198   }
199   // xf
200   if (aCurveType==GeomAbs_Line && (aCoeff1 != 1 || aCoeff2 != 1)) {
201     Standard_Real aTV1, aTV2, aEps;
202     gp_Pnt aPV1, aPV2, aPC1, aPC2;
203     gp_Lin aL;
204     //
205     aEps=Precision::Confusion();
206     aEps=aEps*aEps;//1.e-14;
207     aL=aBAC.Line();
208     //
209     aPV1=BRep_Tool::Pnt(myV1);
210     aTV1=ElCLib::Parameter(aL, aPV1);
211     //
212     aPV2=BRep_Tool::Pnt(myV2);
213     aTV2=ElCLib::Parameter(aL, aPV2);
214     //
215     if (fabs(aTV1-aCF)<aEps) {
216       aCoeff1=1.;
217       aTol1 += Precision::Confusion();
218     }
219     if (fabs(aTV2-aCL)<aEps) {
220       aCoeff2=1.;
221       aTol2 += Precision::Confusion();
222     }
223   }
224   //
225   dt1=aCoeff1*aTol1;
226   dt2=aCoeff2*aTol2;
227   // xt
228   //
229   if (aCurveType==GeomAbs_Line) {
230     Standard_Real dt1x, dt2x;
231
232     dt1x = aBAC.Resolution(dt1);
233     t11=t1+dt1x;
234     
235     dt2x = aBAC.Resolution(dt2);
236     t12=t2-dt2x;
237
238     if (t11>t2 || t12<t1) {
239       t1C=t1;
240       t2C=t2;
241       myTS1=t1C;
242       myTS2=t2C;
243       //
244       // BndBox
245       Standard_Real ddx=aTolE;//1.e-12;
246       BndLib_Add3dCurve::Add (aBAC, t1C, t2C, ddx, myBndBox);
247       
248       myErrorStatus=6;//0
249       return;
250     }
251   }
252   //
253   if (aCurveType==GeomAbs_Circle) {
254     gp_Circ aCrc=aBAC.Circle();
255     aR=aCrc.Radius();
256     t1C=t1+dt1/aR;
257     t2C=t2-dt2/aR;
258   }
259   else {
260     //
261     // Vertex1 => t1C
262     gp_Pnt aP1,aP11;
263     aC->D0 (t1, aP1);
264     //
265     bInf1=Precision::IsNegativeInfinite(t1);
266     if (bInf1) {
267       t1C=t1;
268     }
269     //
270     else {
271       Standard_Real d1 = aCoeff1*aTol1;
272       //       dt1 = aBAC.Resolution(d1);
273       //
274       gp_Vec aD1vec1;
275       gp_Pnt aPoint;
276       aBAC.D1(t1, aPoint, aD1vec1);
277       Standard_Real ad1length1 = aD1vec1.Magnitude();
278       Standard_Boolean bTryOtherPoints = Standard_False;
279       dt1 = (t2 - t1) * 0.5;
280
281       if(ad1length1 > 1.e-12) {
282         dt1 = d1 / ad1length1;
283         
284         if(dt1  > (t2 - t1)) {
285           // bad parametrization, big tolerance or too small range
286           bTryOtherPoints = Standard_True;
287         }
288       }
289       else {
290         bTryOtherPoints = Standard_True;
291       }
292       
293       if(bTryOtherPoints) {
294         Standard_Integer nbsamples = 5;
295         Standard_Integer ii = 0;
296         Standard_Real adelta = (t2 - t1) / (nbsamples + 1);
297         Standard_Boolean bFound = Standard_False;
298         
299         for(ii = 1; ii <= nbsamples; ii++) {
300           Standard_Real aparameter = t1 + (adelta * ii);
301           gp_Pnt aPoint2;
302           aBAC.D1(aparameter, aPoint2, aD1vec1);
303           
304           if(aPoint.Distance(aPoint2) < d1)
305             dt1 = adelta * ii;
306           ad1length1 = aD1vec1.Magnitude();
307           
308           if(ad1length1 > 1.e-12) {
309             dt1 = d1 / ad1length1;
310             
311             if(dt1 < (t2 - t1)) {
312               bFound = Standard_True;
313               break;
314             }
315           }
316         }
317         
318         if(!bFound) {
319           if(dt1 > (t2 - t1)) {
320             dt1 = aBAC.Resolution(d1);
321             if (dt1 > (t2 - t1)) {
322               myErrorStatus = 7;
323               return;
324             }
325           }
326         }
327       }
328       //
329       if (!bAppr) {
330         dt1 *= 10;
331       }
332       t11=t1+dt1;
333       aC->D0 (t11, aP11);
334       
335       gp_Vec aV11(aP1, aP11);
336       // avoid exception if aP1 == aP11
337       if (aV11.SquareMagnitude() < gp::Resolution())
338         t1C = t1;
339       else {
340         gp_Dir aD11(aV11);
341
342         gp_Pnt aP1L;
343         //
344         aP1L.SetCoord (aP1.X()+d1*aD11.X(),
345                        aP1.Y()+d1*aD11.Y(),
346                        aP1.Z()+d1*aD11.Z());
347
348         BRepBuilderAPI_MakeVertex aMV1(aP1L);
349         const TopoDS_Vertex& aV1L=aMV1.Vertex();
350         //
351         pri = myCtx->ComputeVE(aV1L, myEdge, t1C, dummy);
352         //
353         if (pri==-3) {
354           myErrorStatus=4;
355           return;
356         }
357       }
358     }
359     //
360     // Vertex2 => t2C
361     gp_Pnt aP2, aP12;
362     aC->D0 (t2, aP2);
363     //
364     bInf2=Precision::IsPositiveInfinite(t2);
365     if (bInf2) {
366       t2C=t2;
367     }
368     //
369     else {
370       Standard_Real d2 = aCoeff2*aTol2;
371       //       dt2 = aBAC.Resolution(d2);
372
373       //
374       gp_Vec aD1vec2;
375       gp_Pnt aPoint;
376       aBAC.D1(t2, aPoint, aD1vec2);
377       Standard_Real ad1length2 = aD1vec2.Magnitude();
378       Standard_Boolean bTryOtherPoints = Standard_False;
379       dt2 = (t2 - t1) * 0.5;
380
381       if(ad1length2 > 1.e-12) {
382         dt2 = d2 / ad1length2;
383         
384         if(dt2 > (t2 - t1)) {
385           bTryOtherPoints = Standard_True;
386         }
387       }
388       else {
389         bTryOtherPoints = Standard_True;
390       }
391
392       if(bTryOtherPoints) {
393         Standard_Integer nbsamples = 5;
394         Standard_Integer ii = 0;
395         Standard_Real adelta = (t2 - t1) / (nbsamples + 1);
396         Standard_Boolean bFound = Standard_False;
397         
398         for(ii = 1; ii <= nbsamples; ii++) {
399           Standard_Real aparameter = t2 - (adelta * ii);
400           gp_Pnt aPoint2;
401           aBAC.D1(aparameter, aPoint2, aD1vec2);
402           
403           if(aPoint.Distance(aPoint2) < d2)
404             dt2 = adelta * ii;
405           ad1length2 = aD1vec2.Magnitude();
406           
407           if(ad1length2 > 1.e-12) {
408             dt2 = d2 / ad1length2;
409             
410             if(dt2 < (t2 - t1)) {
411               bFound = Standard_True;
412               break;
413             }
414           }
415         }
416         
417         if(!bFound) {
418           if(dt2 > (t2 - t1)) {
419             dt2 = aBAC.Resolution(d2);
420             if(dt2 > (t2 - t1)) {
421               myErrorStatus = 7;
422               return;
423             }
424           }
425         }
426       }
427       //
428       if (!bAppr) {
429         dt2 *= 10;
430       }
431
432       t12=t2-dt2;
433       aC->D0 (t12, aP12);
434       
435       gp_Vec aV12(aP2, aP12);
436       // avoid exception if aP1 == aP11
437       if (aV12.SquareMagnitude() < gp::Resolution())
438         t2C = t2;
439       else {
440         gp_Dir aD12(aV12);
441
442         gp_Pnt aP2L;
443         //
444         aP2L.SetCoord (aP2.X()+d2*aD12.X(),
445                        aP2.Y()+d2*aD12.Y(),
446                        aP2.Z()+d2*aD12.Z());
447
448         BRepBuilderAPI_MakeVertex aMV2(aP2L);
449         const TopoDS_Vertex& aV2L=aMV2.Vertex();
450         //
451         pri = myCtx->ComputeVE(aV2L, myEdge, t2C, dummy);
452         //
453         if (pri==-3) {
454           myErrorStatus=5;
455           return;
456         }
457       }
458     }
459   } // else {
460   //
461   if (t1C>t2){
462     t1C=0.5*(t2+t1);
463     t2C=t1C+0.1*(t2-t1C);
464   }
465   
466   if (t1C>t2C) {
467     t2C=t1C+0.1*(t2-t1C);
468   }
469   //
470   if (t2C-t1C < anEps) {
471     myErrorStatus = 7;
472     return;
473   }
474   //
475   myTS1=t1C;
476   myTS2=t2C;
477   //
478   // BndBox
479   Standard_Real ddx = aTolE + Precision::Confusion();
480   BndLib_Add3dCurve::Add (aBAC, t1C, t2C, ddx, myBndBox);
481 }
482 /////////////////////////////////////////////////////////////////////////
483 //
484 //            myErrorStatus :
485 //
486 // 1- Nothing has been done
487 // 2- The source range is out of the edge's range
488 // 3- t1 < t2 for source range
489 // 4- Can not project V1L  to the Edge;
490 // 5- Can not project V2L  to the Edge;
491 // 6- for obtained shrunk range [t11, t12] ->  t11>t2 || t12<t1;
492 // 7- too small range.