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