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