0023024: Update headers of OCCT files
[occt.git] / src / IntTools / IntTools_ShrunkRange.cxx
1 // Created on: 2001-03-11
2 // Created by: Peter KURNEV
3 // Copyright (c) 2001-2012 OPEN CASCADE SAS
4 //
5 // The content of this file is subject to the Open CASCADE Technology Public
6 // License Version 6.5 (the "License"). You may not use the content of this file
7 // except in compliance with the License. Please obtain a copy of the License
8 // at http://www.opencascade.org and read it completely before using this file.
9 //
10 // The Initial Developer of the Original Code is Open CASCADE S.A.S., having its
11 // main offices at: 1, place des Freres Montgolfier, 78280 Guyancourt, France.
12 //
13 // The Original Code and all software distributed under the License is
14 // distributed on an "AS IS" basis, without warranty of any kind, and the
15 // Initial Developer hereby disclaims all such warranties, including without
16 // limitation, any warranties of merchantability, fitness for a particular
17 // purpose or non-infringement. Please see the License for the specific terms
18 // and conditions governing the rights and limitations under the License.
19
20
21 #include <IntTools_ShrunkRange.ixx>
22
23 #include <Precision.hxx>
24
25 #include <gp_Lin.hxx>
26 #include <gp.hxx>
27 #include <gp_Circ.hxx>
28
29 #include <ElCLib.hxx>
30
31 #include <Geom_Curve.hxx>
32
33 #include <BRep_Tool.hxx>
34 #include <BRepBuilderAPI_MakeVertex.hxx>
35 #include <BRepAdaptor_Curve.hxx>
36 #include <BndLib_Add3dCurve.hxx>
37
38 #include <IntTools_Tools.hxx>
39
40 //=======================================================================
41 //function : IntTools_ShrunkRange
42 //purpose  : 
43 //=======================================================================
44 IntTools_ShrunkRange::IntTools_ShrunkRange ()
45 {
46 }
47
48 //=======================================================================
49 //function : IntTools_ShrunkRange
50 //purpose  : 
51 //=======================================================================
52 IntTools_ShrunkRange::IntTools_ShrunkRange (const TopoDS_Edge& aE,
53                                               const TopoDS_Vertex& aV1,
54                                               const TopoDS_Vertex& aV2,
55                                               const IntTools_Range& aR,
56                                               const Handle(IntTools_Context)& aCtx)
57 {
58   myEdge=aE;
59   myV1=aV1;
60   myV2=aV2;
61   myRange=aR;
62   myContext=aCtx;
63   myIsDone=Standard_False;
64   myErrorStatus=1;
65   Perform();
66 }
67 //=======================================================================
68 //function : SetContext
69 //purpose  : 
70 //======================================================================= 
71 void IntTools_ShrunkRange::SetContext(const Handle(IntTools_Context)& aContext)
72 {
73   myContext=aContext;
74 }
75 //=======================================================================
76 //function : Context
77 //purpose  : 
78 //======================================================================= 
79 const Handle(IntTools_Context)& IntTools_ShrunkRange::Context()const
80 {
81   return myContext;
82 }
83 //=======================================================================
84 //function : Edge
85 //purpose  : 
86 //=======================================================================
87 const TopoDS_Edge& IntTools_ShrunkRange::Edge() const
88 {
89   return myEdge;
90 }
91 //=======================================================================
92 //function : ShrunkRange
93 //purpose  : 
94 //=======================================================================
95 const IntTools_Range& IntTools_ShrunkRange::ShrunkRange() const
96 {
97   return myShrunkRange;
98 }
99 //=======================================================================
100 //function : BndBox
101 //purpose  : 
102 //=======================================================================
103 const Bnd_Box& IntTools_ShrunkRange::BndBox() const
104 {
105   return myBndBox;
106 }
107 //=======================================================================
108 //function : IsDone
109 //purpose  : 
110 //=======================================================================
111 Standard_Boolean IntTools_ShrunkRange::IsDone() const
112 {
113   return myIsDone;
114 }
115 //=======================================================================
116 //function : ErrorStatus
117 //purpose  : 
118 //=======================================================================
119 Standard_Integer IntTools_ShrunkRange::ErrorStatus() const
120 {
121   return myErrorStatus;
122 }
123 //=======================================================================
124 //function : Perform
125 //purpose  : 
126 //=======================================================================
127 void IntTools_ShrunkRange::Perform()
128 {
129   Standard_Real aCF, aCL, aTolE, aTolV1, aTolV2, t1, t11, t1C, t2, t12, t2C;
130   Standard_Real aCoeff, dt1, dt2, aR;
131   Standard_Integer pri;
132   Standard_Boolean bInf1, bInf2;
133   GeomAbs_CurveType aCurveType;
134   Handle(Geom_Curve) aC;
135   //
136   if (myContext.IsNull()) {
137     myContext=new IntTools_Context;
138   }
139   //
140   aTolE =BRep_Tool::Tolerance(myEdge);
141   aTolV1=BRep_Tool::Tolerance(myV1);
142   aTolV2=BRep_Tool::Tolerance(myV2);
143   //
144   myRange.Range (t1, t2);
145   //
146   BRepAdaptor_Curve aBAC(myEdge);
147   aCurveType=aBAC.GetType();
148   //
149   aC=BRep_Tool::Curve(myEdge, aCF, aCL);
150   BRep_Tool::Range(myEdge, aCF, aCL);
151   //
152   if (t1 < aCF || t2 > aCL) {
153     myErrorStatus=2;
154     return;
155   }
156   //
157   if (t1 > t2 ) {
158     myErrorStatus=3;
159     return;
160   }
161   //
162   aCoeff=2.;
163   // xf
164   if (aCurveType==GeomAbs_Line) {
165     Standard_Real aTV1, aTV2, aEps;
166     gp_Pnt aPV1, aPV2, aPC1, aPC2;
167     gp_Lin aL;
168     //
169     aEps=Precision::Confusion();
170     aEps=aEps*aEps;//1.e-14;
171     aL=aBAC.Line();
172     //
173     aPV1=BRep_Tool::Pnt(myV1);
174     aTV1=ElCLib::Parameter(aL, aPV1);
175     //
176     aPV2=BRep_Tool::Pnt(myV2);
177     aTV2=ElCLib::Parameter(aL, aPV2);
178     //
179     if (fabs(aTV1-aCF)<aEps && fabs(aTV2-aCL)<aEps) {
180       aCoeff=1.;
181     }
182   }
183   //
184   dt1=aCoeff*(aTolV1+aTolE);
185   dt2=aCoeff*(aTolV2+aTolE);
186   // xt
187   //
188   if (aCurveType==GeomAbs_Line) {
189     Standard_Real dt1x, dt2x;
190
191     dt1x = aBAC.Resolution(dt1);
192     t11=t1+dt1x;
193     
194     dt2x = aBAC.Resolution(dt2);
195     t12=t2-dt2x;
196
197     if (t11>t2 || t12<t1) {
198       t1C=t1;
199       t2C=t2;
200       myShrunkRange.SetFirst(t1C);
201       myShrunkRange.SetLast (t2C);
202       //
203       // BndBox
204       Standard_Real ddx=aTolE;//1.e-12;
205       BndLib_Add3dCurve::Add (aBAC, t1C, t2C, ddx, myBndBox);
206       
207       myErrorStatus=6;
208       myIsDone=Standard_True;
209       return;
210     }
211   }
212   //
213   if (aCurveType==GeomAbs_Circle) {
214     gp_Circ aCrc=aBAC.Circle();
215     aR=aCrc.Radius();
216     t1C=t1+dt1/aR;
217     t2C=t2-dt2/aR;
218   }
219
220   else {
221     //
222     // Vertex1 => t1C
223     gp_Pnt aP1,aP11;
224     aC->D0 (t1, aP1);
225     //
226     bInf1=Precision::IsNegativeInfinite(t1);
227     if (bInf1) {
228       t1C=t1;
229     }
230     //
231     else {
232       Standard_Real d1 = aCoeff*(aTolV1+aTolE);
233       //       dt1 = aBAC.Resolution(d1);
234       //
235       gp_Vec aD1vec1;
236       gp_Pnt aPoint;
237       aBAC.D1(t1, aPoint, aD1vec1);
238       Standard_Real ad1length1 = aD1vec1.Magnitude();
239       Standard_Boolean bTryOtherPoints = Standard_False;
240       dt1 = (t2 - t1) * 0.5;
241
242       if(ad1length1 > 1.e-12) {
243         dt1 = d1 / ad1length1;
244
245         if(dt1  > (t2 - t1)) {
246           // bad parametrization, big tolerance or too small range
247           bTryOtherPoints = Standard_True;
248         }
249       }
250       else {
251         bTryOtherPoints = Standard_True;
252       }
253
254       if(bTryOtherPoints) {
255         Standard_Integer nbsamples = 5;
256         Standard_Integer ii = 0;
257         Standard_Real adelta = (t2 - t1) / (nbsamples + 1);
258         Standard_Boolean bFound = Standard_False;
259
260         for(ii = 1; ii <= nbsamples; ii++) {
261           Standard_Real aparameter = t1 + (adelta * ii);
262           gp_Pnt aPoint2;
263           aBAC.D1(aparameter, aPoint2, aD1vec1);
264
265           if(aPoint.Distance(aPoint2) < d1)
266             dt1 = adelta * ii;
267           ad1length1 = aD1vec1.Magnitude();
268
269           if(ad1length1 > 1.e-12) {
270             dt1 = d1 / ad1length1;
271
272             if(dt1 < (t2 - t1)) {
273               bFound = Standard_True;
274               break;
275             }
276           }
277         }
278
279         if(!bFound) {
280           if(dt1 > (t2 - t1)) {
281             dt1 = aBAC.Resolution(d1);
282           }
283         }
284       }
285       //
286
287       t11=t1+dt1;
288       aC->D0 (t11, aP11);
289       
290       gp_Vec aV11(aP1, aP11);
291       // avoid exception if aP1 == aP11
292       if (aV11.SquareMagnitude() < gp::Resolution())
293         t1C = t1;
294       else {
295         gp_Dir aD11(aV11);
296
297         gp_Pnt aP1L;
298         //
299         aP1L.SetCoord (aP1.X()+d1*aD11.X(),
300                        aP1.Y()+d1*aD11.Y(),
301                        aP1.Z()+d1*aD11.Z());
302
303         BRepBuilderAPI_MakeVertex aMV1(aP1L);
304         const TopoDS_Vertex& aV1L=aMV1.Vertex();
305         //
306         pri=myContext->ComputeVE (aV1L, myEdge, t1C);
307         //
308         if (pri==-3) {
309           t1C = t1;
310         }
311       }
312     }
313     //
314     // Vertex2 => t2C
315     gp_Pnt aP2, aP12;
316     aC->D0 (t2, aP2);
317     //
318     bInf2=Precision::IsPositiveInfinite(t2);
319     if (bInf2) {
320       t2C=t2;
321     }
322     //
323     else {
324       Standard_Real d2 = aCoeff*(aTolV2+aTolE);
325       //       dt2 = aBAC.Resolution(d2);
326
327       //
328       gp_Vec aD1vec2;
329       gp_Pnt aPoint;
330       aBAC.D1(t2, aPoint, aD1vec2);
331       Standard_Real ad1length2 = aD1vec2.Magnitude();
332       Standard_Boolean bTryOtherPoints = Standard_False;
333       dt2 = (t2 - t1) * 0.5;
334
335       if(ad1length2 > 1.e-12) {
336         dt2 = d2 / ad1length2;
337
338         if(dt2 > (t2 - t1)) {
339           bTryOtherPoints = Standard_True;
340         }
341       }
342       else {
343         bTryOtherPoints = Standard_True;
344       }
345
346       if(bTryOtherPoints) {
347         Standard_Integer nbsamples = 5;
348         Standard_Integer ii = 0;
349         Standard_Real adelta = (t2 - t1) / (nbsamples + 1);
350         Standard_Boolean bFound = Standard_False;
351
352         for(ii = 1; ii <= nbsamples; ii++) {
353           Standard_Real aparameter = t2 - (adelta * ii);
354           gp_Pnt aPoint2;
355           aBAC.D1(aparameter, aPoint2, aD1vec2);
356
357           if(aPoint.Distance(aPoint2) < d2)
358             dt2 = adelta * ii;
359           ad1length2 = aD1vec2.Magnitude();
360
361           if(ad1length2 > 1.e-12) {
362             dt2 = d2 / ad1length2;
363
364             if(dt2 < (t2 - t1)) {
365               bFound = Standard_True;
366               break;
367             }
368           }
369         }
370
371         if(!bFound) {
372           if(dt2 > (t2 - t1)) {
373             dt2 = aBAC.Resolution(d2);
374           }
375         }
376       }
377       //
378       
379       t12=t2-dt2;
380       aC->D0 (t12, aP12);
381       
382       gp_Vec aV12(aP2, aP12);
383       // avoid exception if aP1 == aP11
384       if (aV12.SquareMagnitude() < gp::Resolution())
385         t2C = t2;
386       else {
387         gp_Dir aD12(aV12);
388
389         gp_Pnt aP2L;
390         //
391         aP2L.SetCoord (aP2.X()+d2*aD12.X(),
392                        aP2.Y()+d2*aD12.Y(),
393                        aP2.Z()+d2*aD12.Z());
394
395         BRepBuilderAPI_MakeVertex aMV2(aP2L);
396         const TopoDS_Vertex& aV2L=aMV2.Vertex();
397         //
398         pri=myContext->ComputeVE (aV2L, myEdge, t2C);
399         //
400         if (pri==-3) {
401           t2C = t2;
402         }
403       }
404     }
405   } // else {
406
407
408   if (t1C>t2){
409     t1C=0.5*(t2+t1);
410     t2C=t1C+0.1*(t2-t1C);
411   }
412   
413   if (t1C>t2C) {
414     t2C=t1C+0.1*(t2-t1C);
415   }
416
417   myShrunkRange.SetFirst(t1C);
418   myShrunkRange.SetLast (t2C);
419   //
420   // BndBox
421   Standard_Real ddx=aTolE;//1.e-12;
422   BndLib_Add3dCurve::Add (aBAC, t1C, t2C, ddx, myBndBox);
423   // 
424   // Ok
425   myErrorStatus=0;
426   myIsDone=Standard_True;
427 }
428
429 //=======================================================================
430 //function : SetShrunkRange
431 //purpose  : 
432 //=======================================================================
433   void IntTools_ShrunkRange::SetShrunkRange(const IntTools_Range& aR) 
434 {
435   Standard_Real f, l;
436   aR.Range(f, l);
437   
438   myShrunkRange.SetFirst(f);
439   myShrunkRange.SetLast (l);
440   
441   BRepAdaptor_Curve aBAC(myEdge);
442   BndLib_Add3dCurve::Add (aBAC, f, l, 0., myBndBox);
443 }
444
445 /////////////////////////////////////////////////////////////////////////
446 //
447 //            myErrorStatus :
448 //
449 // 1- Nothing has been done
450 // 2- The source range is out of the edge's range
451 // 3- t1 < t2 for source range
452 // 4- Can not project V1L  to the Edge;
453 // 5- Can not project V2L  to the Edge;
454 // 6- for obtained shrunk range [t11, t12] ->  t11>t2 || t12<t1;