0022972: Eliminate macro definitions that has compiler-provided analogs (WNT and...
[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;
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 = aTolV1+aTolE;
191   aTol2 = 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     }
218     if (fabs(aTV2-aCL)<aEps) {
219       aCoeff2=1.;
220     }
221   }
222   //
223   dt1=aCoeff1*aTol1;
224   dt2=aCoeff2*aTol2;
225   // xt
226   //
227   if (aCurveType==GeomAbs_Line) {
228     Standard_Real dt1x, dt2x;
229
230     dt1x = aBAC.Resolution(dt1);
231     t11=t1+dt1x;
232     
233     dt2x = aBAC.Resolution(dt2);
234     t12=t2-dt2x;
235
236     if (t11>t2 || t12<t1) {
237       t1C=t1;
238       t2C=t2;
239       myTS1=t1C;
240       myTS2=t2C;
241       //
242       // BndBox
243       Standard_Real ddx=aTolE;//1.e-12;
244       BndLib_Add3dCurve::Add (aBAC, t1C, t2C, ddx, myBndBox);
245       
246       myErrorStatus=6;//0
247       return;
248     }
249   }
250   //
251   if (aCurveType==GeomAbs_Circle) {
252     gp_Circ aCrc=aBAC.Circle();
253     aR=aCrc.Radius();
254     t1C=t1+dt1/aR;
255     t2C=t2-dt2/aR;
256   }
257   else {
258     //
259     // Vertex1 => t1C
260     gp_Pnt aP1,aP11;
261     aC->D0 (t1, aP1);
262     //
263     bInf1=Precision::IsNegativeInfinite(t1);
264     if (bInf1) {
265       t1C=t1;
266     }
267     //
268     else {
269       Standard_Real d1 = aCoeff1*aTol1;
270       //       dt1 = aBAC.Resolution(d1);
271       //
272       gp_Vec aD1vec1;
273       gp_Pnt aPoint;
274       aBAC.D1(t1, aPoint, aD1vec1);
275       Standard_Real ad1length1 = aD1vec1.Magnitude();
276       Standard_Boolean bTryOtherPoints = Standard_False;
277       dt1 = (t2 - t1) * 0.5;
278
279       if(ad1length1 > 1.e-12) {
280         dt1 = d1 / ad1length1;
281         
282         if(dt1  > (t2 - t1)) {
283           // bad parametrization, big tolerance or too small range
284           bTryOtherPoints = Standard_True;
285         }
286       }
287       else {
288         bTryOtherPoints = Standard_True;
289       }
290       
291       if(bTryOtherPoints) {
292         Standard_Integer nbsamples = 5;
293         Standard_Integer ii = 0;
294         Standard_Real adelta = (t2 - t1) / (nbsamples + 1);
295         Standard_Boolean bFound = Standard_False;
296         
297         for(ii = 1; ii <= nbsamples; ii++) {
298           Standard_Real aparameter = t1 + (adelta * ii);
299           gp_Pnt aPoint2;
300           aBAC.D1(aparameter, aPoint2, aD1vec1);
301           
302           if(aPoint.Distance(aPoint2) < d1)
303             dt1 = adelta * ii;
304           ad1length1 = aD1vec1.Magnitude();
305           
306           if(ad1length1 > 1.e-12) {
307             dt1 = d1 / ad1length1;
308             
309             if(dt1 < (t2 - t1)) {
310               bFound = Standard_True;
311               break;
312             }
313           }
314         }
315         
316         if(!bFound) {
317           if(dt1 > (t2 - t1)) {
318             dt1 = aBAC.Resolution(d1);
319             if (dt1 > (t2 - t1)) {
320               myErrorStatus = 7;
321               return;
322             }
323           }
324         }
325       }
326       //
327       if (!bAppr) {
328         dt1 *= 10;
329       }
330       t11=t1+dt1;
331       aC->D0 (t11, aP11);
332       
333       gp_Vec aV11(aP1, aP11);
334       // avoid exception if aP1 == aP11
335       if (aV11.SquareMagnitude() < gp::Resolution())
336         t1C = t1;
337       else {
338         gp_Dir aD11(aV11);
339
340         gp_Pnt aP1L;
341         //
342         aP1L.SetCoord (aP1.X()+d1*aD11.X(),
343                        aP1.Y()+d1*aD11.Y(),
344                        aP1.Z()+d1*aD11.Z());
345
346         BRepBuilderAPI_MakeVertex aMV1(aP1L);
347         const TopoDS_Vertex& aV1L=aMV1.Vertex();
348         //
349         pri=myCtx->ComputeVE (aV1L, myEdge, t1C);
350         //
351         if (pri==-3) {
352           myErrorStatus=4;
353           return;
354         }
355       }
356     }
357     //
358     // Vertex2 => t2C
359     gp_Pnt aP2, aP12;
360     aC->D0 (t2, aP2);
361     //
362     bInf2=Precision::IsPositiveInfinite(t2);
363     if (bInf2) {
364       t2C=t2;
365     }
366     //
367     else {
368       Standard_Real d2 = aCoeff2*aTol2;
369       //       dt2 = aBAC.Resolution(d2);
370
371       //
372       gp_Vec aD1vec2;
373       gp_Pnt aPoint;
374       aBAC.D1(t2, aPoint, aD1vec2);
375       Standard_Real ad1length2 = aD1vec2.Magnitude();
376       Standard_Boolean bTryOtherPoints = Standard_False;
377       dt2 = (t2 - t1) * 0.5;
378
379       if(ad1length2 > 1.e-12) {
380         dt2 = d2 / ad1length2;
381         
382         if(dt2 > (t2 - t1)) {
383           bTryOtherPoints = Standard_True;
384         }
385       }
386       else {
387         bTryOtherPoints = Standard_True;
388       }
389
390       if(bTryOtherPoints) {
391         Standard_Integer nbsamples = 5;
392         Standard_Integer ii = 0;
393         Standard_Real adelta = (t2 - t1) / (nbsamples + 1);
394         Standard_Boolean bFound = Standard_False;
395         
396         for(ii = 1; ii <= nbsamples; ii++) {
397           Standard_Real aparameter = t2 - (adelta * ii);
398           gp_Pnt aPoint2;
399           aBAC.D1(aparameter, aPoint2, aD1vec2);
400           
401           if(aPoint.Distance(aPoint2) < d2)
402             dt2 = adelta * ii;
403           ad1length2 = aD1vec2.Magnitude();
404           
405           if(ad1length2 > 1.e-12) {
406             dt2 = d2 / ad1length2;
407             
408             if(dt2 < (t2 - t1)) {
409               bFound = Standard_True;
410               break;
411             }
412           }
413         }
414         
415         if(!bFound) {
416           if(dt2 > (t2 - t1)) {
417             dt2 = aBAC.Resolution(d2);
418             if(dt2 > (t2 - t1)) {
419               myErrorStatus = 7;
420               return;
421             }
422           }
423         }
424       }
425       //
426       if (!bAppr) {
427         dt2 *= 10;
428       }
429
430       t12=t2-dt2;
431       aC->D0 (t12, aP12);
432       
433       gp_Vec aV12(aP2, aP12);
434       // avoid exception if aP1 == aP11
435       if (aV12.SquareMagnitude() < gp::Resolution())
436         t2C = t2;
437       else {
438         gp_Dir aD12(aV12);
439
440         gp_Pnt aP2L;
441         //
442         aP2L.SetCoord (aP2.X()+d2*aD12.X(),
443                        aP2.Y()+d2*aD12.Y(),
444                        aP2.Z()+d2*aD12.Z());
445
446         BRepBuilderAPI_MakeVertex aMV2(aP2L);
447         const TopoDS_Vertex& aV2L=aMV2.Vertex();
448         //
449         pri=myCtx->ComputeVE (aV2L, myEdge, t2C);
450         //
451         if (pri==-3) {
452           myErrorStatus=5;
453           return;
454         }
455       }
456     }
457   } // else {
458   //
459   if (t1C>t2){
460     t1C=0.5*(t2+t1);
461     t2C=t1C+0.1*(t2-t1C);
462   }
463   
464   if (t1C>t2C) {
465     t2C=t1C+0.1*(t2-t1C);
466   }
467   //
468   if (t2C-t1C < anEps) {
469     myErrorStatus = 7;
470     return;
471   }
472   //
473   myTS1=t1C;
474   myTS2=t2C;
475   //
476   // BndBox
477   Standard_Real ddx=aTolE;//1.e-12;
478   BndLib_Add3dCurve::Add (aBAC, t1C, t2C, ddx, myBndBox);
479 }
480 /////////////////////////////////////////////////////////////////////////
481 //
482 //            myErrorStatus :
483 //
484 // 1- Nothing has been done
485 // 2- The source range is out of the edge's range
486 // 3- t1 < t2 for source range
487 // 4- Can not project V1L  to the Edge;
488 // 5- Can not project V2L  to the Edge;
489 // 6- for obtained shrunk range [t11, t12] ->  t11>t2 || t12<t1;
490 // 7- too small range.