0027448: BOPTools_AlgoTools::IsMicroEdge does not correspond to shape validity criteria
[occt.git] / src / IntTools / IntTools_ShrunkRange.cxx
1 // Created by: Peter KURNEV
2 // Copyright (c) 1999-2014 OPEN CASCADE SAS
3 //
4 // This file is part of Open CASCADE Technology software library.
5 //
6 // This library is free software; you can redistribute it and/or modify it under
7 // the terms of the GNU Lesser General Public License version 2.1 as published
8 // by the Free Software Foundation, with special exception defined in the file
9 // OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
10 // distribution for complete text of the license and disclaimer of any warranty.
11 //
12 // Alternatively, this file may be used under the terms of Open CASCADE
13 // commercial license or contractual agreement.
14
15
16 #include <Bnd_Box.hxx>
17 #include <BndLib_Add3dCurve.hxx>
18 #include <BRep_Tool.hxx>
19 #include <BRepAdaptor_Curve.hxx>
20 #include <GCPnts_AbscissaPoint.hxx>
21 #include <IntTools_ShrunkRange.hxx>
22 #include <Precision.hxx>
23
24 //=======================================================================
25 //function : 
26 //purpose  : 
27 //=======================================================================
28   IntTools_ShrunkRange::IntTools_ShrunkRange ()
29 {
30   myT1=-99;
31   myT2=myT1;
32   myTS1=myT1;
33   myTS2=myT1;
34   myIsDone=Standard_False;
35   myIsSplittable=Standard_False;
36 }
37 //=======================================================================
38 //function : ~
39 //purpose  : 
40 //=======================================================================
41 IntTools_ShrunkRange::~IntTools_ShrunkRange () 
42 {
43 }
44 //=======================================================================
45 //function : SetData
46 //purpose  : 
47 //=======================================================================
48 void IntTools_ShrunkRange::SetData(const TopoDS_Edge& aE,
49                                    const Standard_Real aT1,
50                                    const Standard_Real aT2,
51                                    const TopoDS_Vertex& aV1,
52                                    const TopoDS_Vertex& aV2)
53 {
54   myEdge=aE;
55   myV1=aV1;
56   myV2=aV2;
57   myT1=aT1;
58   myT2=aT2;
59   myIsDone=Standard_False;
60   myIsSplittable=Standard_False;
61 }
62 //=======================================================================
63 //function : SetContext
64 //purpose  : 
65 //=======================================================================
66 void IntTools_ShrunkRange::SetContext(const Handle(IntTools_Context)& aCtx)
67 {
68   myCtx=aCtx;
69 }
70 //=======================================================================
71 //function : Context
72 //purpose  : 
73 //=======================================================================
74 const Handle(IntTools_Context)& IntTools_ShrunkRange::Context()const
75 {
76   return myCtx;
77 }
78 //=======================================================================
79 //function : Edge
80 //purpose  : 
81 //=======================================================================
82 const TopoDS_Edge& IntTools_ShrunkRange::Edge() const
83 {
84   return myEdge;
85 }
86 //=======================================================================
87 //function : ShrunkRange
88 //purpose  : 
89 //=======================================================================
90 void IntTools_ShrunkRange::ShrunkRange(Standard_Real& aT1,
91                                        Standard_Real& aT2) const
92 {
93   aT1=myTS1;
94   aT2=myTS2;
95 }
96 //=======================================================================
97 //function : BndBox
98 //purpose  : 
99 //=======================================================================
100 const Bnd_Box& IntTools_ShrunkRange::BndBox() const
101 {
102   return myBndBox;
103 }
104 //=======================================================================
105 //function : SetShrunkRange
106 //purpose  : 
107 //=======================================================================
108 void IntTools_ShrunkRange::SetShrunkRange(const Standard_Real aT1,
109                                           const Standard_Real aT2) 
110 {
111   myTS1=aT1;
112   myTS2=aT2;
113   //
114   BRepAdaptor_Curve aBAC(myEdge);
115   BndLib_Add3dCurve::Add(aBAC, aT1, aT2, 0., myBndBox);
116 }
117
118 //=======================================================================
119 //function : Perform
120 //purpose  : 
121 //=======================================================================
122 void IntTools_ShrunkRange::Perform()
123 {
124   myIsDone = Standard_False;
125   myIsSplittable = Standard_False;
126   //
127   // default tolerance - Precision::Confusion()
128   Standard_Real aDTol = Precision::Confusion();
129   // default parametric tolerance - Precision::PConfusion()
130   Standard_Real aPDTol = Precision::PConfusion();
131   //
132   if (myT2 - myT1 < aPDTol) {
133     return;
134   }
135   //
136   Standard_Real aTolE, aTolV1, aTolV2;
137   aTolE = BRep_Tool::Tolerance(myEdge);
138   aTolV1 = BRep_Tool::Tolerance(myV1);
139   aTolV2 = BRep_Tool::Tolerance(myV2);
140   //
141   if (aTolV1 < aTolE) {
142     aTolV1 = aTolE;
143   }
144   //
145   if (aTolV2 < aTolE) {
146     aTolV2 = aTolE;
147   }
148   //
149   // to have correspondence with intersection precision
150   // the tolerances of vertices are increased on Precision::Confusion()
151   aTolV1 += aDTol;
152   aTolV2 += aDTol;
153   //
154   BRepAdaptor_Curve aBAC(myEdge);
155   // parametric tolerance for the edge
156   // to be used in AbscissaPoint computations
157   Standard_Real aPTolE = aBAC.Resolution(aTolE);
158   // for the edges with big tolerance use 
159   // min parametric tolerance - 1% of its range
160   Standard_Real aPTolEMin = (myT2 - myT1) / 100.;
161   if (aPTolE > aPTolEMin) {
162     aPTolE = aPTolEMin;
163   }
164   //
165   // compute the shrunk range - part of the edge not covered
166   // by the tolerance spheres of its vertices
167   GCPnts_AbscissaPoint aPC1(aBAC, aTolV1, myT1, aPTolE);
168   // if Abscissa is unable to compute the parameter
169   // use the resolution of the curve
170   myTS1 = aPC1.IsDone() ? aPC1.Parameter() : (myT1 + aBAC.Resolution(aTolV1));
171   if (myT2 - myTS1 < aPDTol) {
172     // micro edge
173     return;
174   }
175   //
176   GCPnts_AbscissaPoint aPC2(aBAC, -aTolV2, myT2, aPTolE);
177   myTS2 = aPC2.IsDone() ? aPC2.Parameter() : (myT2 - aBAC.Resolution(aTolV2));
178   if (myTS2 - myT1 < aPDTol) {
179     // micro edge
180     return;
181   }
182   //
183   if ((myTS2 - myTS1) < aPDTol) {
184     // micro edge
185     return;
186   }
187   //
188   // compute the length of the edge on the shrunk range
189   Standard_Real anEdgeLength =
190     GCPnts_AbscissaPoint::Length(aBAC, myTS1, myTS2, aPTolE);
191   if (anEdgeLength < aDTol) {
192     // micro edge
193     return;
194   }
195   //
196   myIsDone = Standard_True;
197   //
198   // check the shrunk range to have the length not less than
199   // 2*aTolE+2*Precision::Confusion()
200   // for the edge to have possibility to be split at least once:
201   // 2*TolE - minimal diameter of tolerance sphere of splitting vertex
202   // 2*Precision::Confusion() - minimal length of the new edges
203   if (anEdgeLength > (2 * aTolE + 2 * aDTol)) {
204     myIsSplittable = Standard_True;
205   }
206   //
207   // build bounding box for the edge on the shrunk range
208   BndLib_Add3dCurve::Add(aBAC, myTS1, myTS2,
209       aTolE + aDTol, myBndBox);
210 }