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