74e45cbccea99977e29584ab64e899554b0948a7
[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;
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   //
134   aTolE =BRep_Tool::Tolerance(myEdge);
135   aTolV1=BRep_Tool::Tolerance(myV1);
136   aTolV2=BRep_Tool::Tolerance(myV2);
137   //for edges with the tolerance value 
138   //more than the tolerance value of vertices
139   if (aTolV1 < aTolE) {
140     aTolV1 = aTolE;
141   }
142   //
143   if (aTolV2 < aTolE) {
144     aTolV2 = aTolE;
145   }
146   //
147   t1=myT1;
148   t2=myT2;
149   //
150   BRepAdaptor_Curve aBAC(myEdge);
151   aCurveType=aBAC.GetType();
152   //
153   aC=BRep_Tool::Curve(myEdge, aCF, aCL);
154   BRep_Tool::Range(myEdge, aCF, aCL);
155   //
156   if (t1 < aCF || t2 > aCL) {
157     myErrorStatus=2;
158     return;
159   }
160   //
161   bAppr = (fabs(t2 - t1) > 100) ? Standard_False : Standard_True;
162   if (fabs(t2 - t1) < Precision::PConfusion()) {
163     myErrorStatus=7;
164     return;
165   }
166   //
167   if (t1 > t2) {
168     myErrorStatus=3;
169     return;
170   }
171   //
172   aCoeff=2.;
173   // xf
174   if (aCurveType==GeomAbs_Line) {
175     Standard_Real aTV1, aTV2, aEps;
176     gp_Pnt aPV1, aPV2, aPC1, aPC2;
177     gp_Lin aL;
178     //
179     aEps=Precision::Confusion();
180     aEps=aEps*aEps;//1.e-14;
181     aL=aBAC.Line();
182     //
183     aPV1=BRep_Tool::Pnt(myV1);
184     aTV1=ElCLib::Parameter(aL, aPV1);
185     //
186     aPV2=BRep_Tool::Pnt(myV2);
187     aTV2=ElCLib::Parameter(aL, aPV2);
188     //
189     if (fabs(aTV1-aCF)<aEps && fabs(aTV2-aCL)<aEps) {
190       aCoeff=1.;
191     }
192   }
193   //
194   dt1=aCoeff*(aTolV1+aTolE);
195   dt2=aCoeff*(aTolV2+aTolE);
196   // xt
197   //
198   if (aCurveType==GeomAbs_Line) {
199     Standard_Real dt1x, dt2x;
200
201     dt1x = aBAC.Resolution(dt1);
202     t11=t1+dt1x;
203     
204     dt2x = aBAC.Resolution(dt2);
205     t12=t2-dt2x;
206
207     if (t11>t2 || t12<t1) {
208       t1C=t1;
209       t2C=t2;
210       myTS1=t1C;
211       myTS2=t2C;
212       //
213       // BndBox
214       Standard_Real ddx=aTolE;//1.e-12;
215       BndLib_Add3dCurve::Add (aBAC, t1C, t2C, ddx, myBndBox);
216       
217       myErrorStatus=6;//0
218       return;
219     }
220   }
221   //
222   if (aCurveType==GeomAbs_Circle) {
223     gp_Circ aCrc=aBAC.Circle();
224     aR=aCrc.Radius();
225     t1C=t1+dt1/aR;
226     t2C=t2-dt2/aR;
227   }
228   else {
229     //
230     // Vertex1 => t1C
231     gp_Pnt aP1,aP11;
232     aC->D0 (t1, aP1);
233     //
234     bInf1=Precision::IsNegativeInfinite(t1);
235     if (bInf1) {
236       t1C=t1;
237     }
238     //
239     else {
240       Standard_Real d1 = aCoeff*(aTolV1+aTolE);
241       //       dt1 = aBAC.Resolution(d1);
242       //
243       gp_Vec aD1vec1;
244       gp_Pnt aPoint;
245       aBAC.D1(t1, aPoint, aD1vec1);
246       Standard_Real ad1length1 = aD1vec1.Magnitude();
247       Standard_Boolean bTryOtherPoints = Standard_False;
248       dt1 = (t2 - t1) * 0.5;
249
250       if(ad1length1 > 1.e-12) {
251         dt1 = d1 / ad1length1;
252         
253         if(dt1  > (t2 - t1)) {
254           // bad parametrization, big tolerance or too small range
255           bTryOtherPoints = Standard_True;
256         }
257       }
258       else {
259         bTryOtherPoints = Standard_True;
260       }
261       
262       if(bTryOtherPoints) {
263         Standard_Integer nbsamples = 5;
264         Standard_Integer ii = 0;
265         Standard_Real adelta = (t2 - t1) / (nbsamples + 1);
266         Standard_Boolean bFound = Standard_False;
267         
268         for(ii = 1; ii <= nbsamples; ii++) {
269           Standard_Real aparameter = t1 + (adelta * ii);
270           gp_Pnt aPoint2;
271           aBAC.D1(aparameter, aPoint2, aD1vec1);
272           
273           if(aPoint.Distance(aPoint2) < d1)
274             dt1 = adelta * ii;
275           ad1length1 = aD1vec1.Magnitude();
276           
277           if(ad1length1 > 1.e-12) {
278             dt1 = d1 / ad1length1;
279             
280             if(dt1 < (t2 - t1)) {
281               bFound = Standard_True;
282               break;
283             }
284           }
285         }
286         
287         if(!bFound) {
288           if(dt1 > (t2 - t1)) {
289             dt1 = aBAC.Resolution(d1);
290           }
291         }
292       }
293       //
294       if (!bAppr) {
295         dt1 *= 10;
296       }
297       t11=t1+dt1;
298       aC->D0 (t11, aP11);
299       
300       gp_Vec aV11(aP1, aP11);
301       // avoid exception if aP1 == aP11
302       if (aV11.SquareMagnitude() < gp::Resolution())
303         t1C = t1;
304       else {
305         gp_Dir aD11(aV11);
306
307         gp_Pnt aP1L;
308         //
309         aP1L.SetCoord (aP1.X()+d1*aD11.X(),
310                        aP1.Y()+d1*aD11.Y(),
311                        aP1.Z()+d1*aD11.Z());
312
313         BRepBuilderAPI_MakeVertex aMV1(aP1L);
314         const TopoDS_Vertex& aV1L=aMV1.Vertex();
315         //
316         pri=myCtx->ComputeVE (aV1L, myEdge, t1C);
317         //
318         if (pri==-3) {
319           myErrorStatus=4;
320           return;
321         }
322       }
323     }
324     //
325     // Vertex2 => t2C
326     gp_Pnt aP2, aP12;
327     aC->D0 (t2, aP2);
328     //
329     bInf2=Precision::IsPositiveInfinite(t2);
330     if (bInf2) {
331       t2C=t2;
332     }
333     //
334     else {
335       Standard_Real d2 = aCoeff*(aTolV2+aTolE);
336       //       dt2 = aBAC.Resolution(d2);
337
338       //
339       gp_Vec aD1vec2;
340       gp_Pnt aPoint;
341       aBAC.D1(t2, aPoint, aD1vec2);
342       Standard_Real ad1length2 = aD1vec2.Magnitude();
343       Standard_Boolean bTryOtherPoints = Standard_False;
344       dt2 = (t2 - t1) * 0.5;
345
346       if(ad1length2 > 1.e-12) {
347         dt2 = d2 / ad1length2;
348         
349         if(dt2 > (t2 - t1)) {
350           bTryOtherPoints = Standard_True;
351         }
352       }
353       else {
354         bTryOtherPoints = Standard_True;
355       }
356
357       if(bTryOtherPoints) {
358         Standard_Integer nbsamples = 5;
359         Standard_Integer ii = 0;
360         Standard_Real adelta = (t2 - t1) / (nbsamples + 1);
361         Standard_Boolean bFound = Standard_False;
362         
363         for(ii = 1; ii <= nbsamples; ii++) {
364           Standard_Real aparameter = t2 - (adelta * ii);
365           gp_Pnt aPoint2;
366           aBAC.D1(aparameter, aPoint2, aD1vec2);
367           
368           if(aPoint.Distance(aPoint2) < d2)
369             dt2 = adelta * ii;
370           ad1length2 = aD1vec2.Magnitude();
371           
372           if(ad1length2 > 1.e-12) {
373             dt2 = d2 / ad1length2;
374             
375             if(dt2 < (t2 - t1)) {
376               bFound = Standard_True;
377               break;
378             }
379           }
380         }
381         
382         if(!bFound) {
383           if(dt2 > (t2 - t1)) {
384             dt2 = aBAC.Resolution(d2);
385           }
386         }
387       }
388       //
389       if (!bAppr) {
390         dt2 *= 10;
391       }
392
393       t12=t2-dt2;
394       aC->D0 (t12, aP12);
395       
396       gp_Vec aV12(aP2, aP12);
397       // avoid exception if aP1 == aP11
398       if (aV12.SquareMagnitude() < gp::Resolution())
399         t2C = t2;
400       else {
401         gp_Dir aD12(aV12);
402
403         gp_Pnt aP2L;
404         //
405         aP2L.SetCoord (aP2.X()+d2*aD12.X(),
406                        aP2.Y()+d2*aD12.Y(),
407                        aP2.Z()+d2*aD12.Z());
408
409         BRepBuilderAPI_MakeVertex aMV2(aP2L);
410         const TopoDS_Vertex& aV2L=aMV2.Vertex();
411         //
412         pri=myCtx->ComputeVE (aV2L, myEdge, t2C);
413         //
414         if (pri==-3) {
415           myErrorStatus=5;
416           return;
417         }
418       }
419     }
420   } // else {
421
422
423   if (t1C>t2){
424     t1C=0.5*(t2+t1);
425     t2C=t1C+0.1*(t2-t1C);
426   }
427   
428   if (t1C>t2C) {
429     t2C=t1C+0.1*(t2-t1C);
430   }
431   //
432   if (t2C-t1C < Precision::PConfusion()) {
433     myErrorStatus = 7;
434     return;
435   }
436   //
437   myTS1=t1C;
438   myTS2=t2C;
439   //
440   // BndBox
441   Standard_Real ddx=aTolE;//1.e-12;
442   BndLib_Add3dCurve::Add (aBAC, t1C, t2C, ddx, myBndBox);
443 }
444 /////////////////////////////////////////////////////////////////////////
445 //
446 //            myErrorStatus :
447 //
448 // 1- Nothing has been done
449 // 2- The source range is out of the edge's range
450 // 3- t1 < t2 for source range
451 // 4- Can not project V1L  to the Edge;
452 // 5- Can not project V2L  to the Edge;
453 // 6- for obtained shrunk range [t11, t12] ->  t11>t2 || t12<t1;
454 // 7- too small range.