Commit | Line | Data |
---|---|---|

42cf5bc1 | 1 | // Created on: 1993-02-17 |

2 | // Created by: Remi LEQUETTE | |

3 | // Copyright (c) 1993-1999 Matra Datavision | |

4 | // Copyright (c) 1999-2014 OPEN CASCADE SAS | |

5 | // | |

6 | // This file is part of Open CASCADE Technology software library. | |

7 | // | |

8 | // This library is free software; you can redistribute it and/or modify it under | |

9 | // the terms of the GNU Lesser General Public License version 2.1 as published | |

10 | // by the Free Software Foundation, with special exception defined in the file | |

11 | // OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT | |

12 | // distribution for complete text of the license and disclaimer of any warranty. | |

13 | // | |

14 | // Alternatively, this file may be used under the terms of Open CASCADE | |

15 | // commercial license or contractual agreement. | |

16 | ||

17 | #ifndef _Precision_HeaderFile | |

18 | #define _Precision_HeaderFile | |

19 | ||

20 | #include <Standard.hxx> | |

21 | #include <Standard_DefineAlloc.hxx> | |

22 | #include <Standard_Handle.hxx> | |

42cf5bc1 | 23 | #include <Standard_Real.hxx> |

24 | #include <Standard_Boolean.hxx> | |

25 | ||

42cf5bc1 | 26 | //! The Precision package offers a set of functions defining precision criteria |

27 | //! for use in conventional situations when comparing two numbers. | |

28 | //! Generalities | |

29 | //! It is not advisable to use floating number equality. Instead, the difference | |

30 | //! between numbers must be compared with a given precision, i.e. : | |

31 | //! Standard_Real x1, x2 ; | |

32 | //! x1 = ... | |

33 | //! x2 = ... | |

34 | //! If ( x1 == x2 ) ... | |

35 | //! should not be used and must be written as indicated below: | |

36 | //! Standard_Real x1, x2 ; | |

37 | //! Standard_Real Precision = ... | |

38 | //! x1 = ... | |

39 | //! x2 = ... | |

40 | //! If ( Abs ( x1 - x2 ) < Precision ) ... | |

41 | //! Likewise, when ordering floating numbers, you must take the following into account : | |

42 | //! Standard_Real x1, x2 ; | |

43 | //! Standard_Real Precision = ... | |

44 | //! x1 = ... ! a large number | |

45 | //! x2 = ... ! another large number | |

46 | //! If ( x1 < x2 - Precision ) ... | |

47 | //! is incorrect when x1 and x2 are large numbers ; it is better to write : | |

48 | //! Standard_Real x1, x2 ; | |

49 | //! Standard_Real Precision = ... | |

50 | //! x1 = ... ! a large number | |

51 | //! x2 = ... ! another large number | |

52 | //! If ( x2 - x1 > Precision ) ... | |

53 | //! Precision in Cas.Cade | |

54 | //! Generally speaking, the precision criterion is not implicit in Cas.Cade. Low-level geometric algorithms accept | |

55 | //! precision criteria as arguments. As a rule, they should not refer directly to the precision criteria provided by the | |

56 | //! Precision package. | |

57 | //! On the other hand, high-level modeling algorithms have to provide the low-level geometric algorithms that they | |

58 | //! call, with a precision criteria. One way of doing this is to use the above precision criteria. | |

59 | //! Alternatively, the high-level algorithms can have their own system for precision management. For example, the | |

60 | //! Topology Data Structure stores precision criteria for each elementary shape (as a vertex, an edge or a face). When | |

61 | //! a new topological object is constructed, the precision criteria are taken from those provided by the Precision | |

62 | //! package, and stored in the related data structure. Later, a topological algorithm which analyses these objects will | |

63 | //! work with the values stored in the data structure. Also, if this algorithm is to build a new topological object, from | |

64 | //! these precision criteria, it will compute a new precision criterion for the new topological object, and write it into the | |

65 | //! data structure of the new topological object. | |

66 | //! The different precision criteria offered by the Precision package, cover the most common requirements of | |

67 | //! geometric algorithms, such as intersections, approximations, and so on. | |

68 | //! The choice of precision depends on the algorithm and on the geometric space. The geometric space may be : | |

69 | //! - a "real" 2D or 3D space, where the lengths are measured in meters, millimeters, microns, inches, etc ..., or | |

70 | //! - a "parametric" space, 1D on a curve or 2D on a surface, where lengths have no dimension. | |

71 | //! The choice of precision criteria for real space depends on the choice of the product, as it is based on the accuracy | |

72 | //! of the machine and the unit of measurement. | |

73 | //! The choice of precision criteria for parametric space depends on both the accuracy of the machine and the | |

74 | //! dimensions of the curve or the surface, since the parametric precision criterion and the real precision criterion are | |

75 | //! linked : if the curve is defined by the equation P(t), the inequation : | |

76 | //! Abs ( t2 - t1 ) < ParametricPrecision | |

77 | //! means that the parameters t1 and t2 are considered to be equal, and the inequation : | |

78 | //! Distance ( P(t2) , P(t1) ) < RealPrecision | |

79 | //! means that the points P(t1) and P(t2) are considered to be coincident. It seems to be the same idea, and it | |

80 | //! would be wonderful if these two inequations were equivalent. Note that this is rarely the case ! | |

81 | //! What is provided in this package? | |

82 | //! The Precision package provides : | |

83 | //! - a set of real space precision criteria for the algorithms, in view of checking distances and angles, | |

84 | //! - a set of parametric space precision criteria for the algorithms, in view of checking both : | |

85 | //! - the equality of parameters in a parametric space, | |

86 | //! - or the coincidence of points in the real space, by using parameter values, | |

87 | //! - the notion of infinite value, composed of a value assumed to be infinite, and checking tests designed to verify | |

88 | //! if any value could be considered as infinite. | |

89 | //! All the provided functions are very simple. The returned values result from the adaptation of the applications | |

90 | //! developed by the Open CASCADE company to Open CASCADE algorithms. The main interest of these functions | |

91 | //! lies in that it incites engineers developing applications to ask questions on precision factors. Which one is to be | |

92 | //! used in such or such case ? Tolerance criteria are context dependent. They must first choose : | |

93 | //! - either to work in real space, | |

94 | //! - or to work in parametric space, | |

95 | //! - or to work in a combined real and parametric space. | |

96 | //! They must next decide which precision factor will give the best answer to the current problem. Within an application | |

97 | //! environment, it is crucial to master precision even though this process may take a great deal of time. | |

98 | class Precision | |

99 | { | |

100 | public: | |

101 | ||

102 | DEFINE_STANDARD_ALLOC | |

103 | ||

42cf5bc1 | 104 | //! Returns the recommended precision value |

105 | //! when checking the equality of two angles (given in radians). | |

106 | //! Standard_Real Angle1 = ... , Angle2 = ... ; | |

107 | //! If ( Abs( Angle2 - Angle1 ) < Precision::Angular() ) ... | |

108 | //! The tolerance of angular equality may be used to check the parallelism of two vectors : | |

109 | //! gp_Vec V1, V2 ; | |

110 | //! V1 = ... | |

111 | //! V2 = ... | |

112 | //! If ( V1.IsParallel (V2, Precision::Angular() ) ) ... | |

113 | //! The tolerance of angular equality is equal to 1.e-12. | |

114 | //! Note : The tolerance of angular equality can be used when working with scalar products or | |

115 | //! cross products since sines and angles are equivalent for small angles. Therefore, in order to | |

116 | //! check whether two unit vectors are perpendicular : | |

117 | //! gp_Dir D1, D2 ; | |

118 | //! D1 = ... | |

119 | //! D2 = ... | |

120 | //! you can use : | |

121 | //! If ( Abs( D1.D2 ) < Precision::Angular() ) ... | |

122 | //! (although the function IsNormal does exist). | |

922da0a8 | 123 | static Standard_Real Angular() { return 1.e-12; } |

42cf5bc1 | 124 | |

125 | //! Returns the recommended precision value when | |

126 | //! checking coincidence of two points in real space. | |

127 | //! The tolerance of confusion is used for testing a 3D | |

128 | //! distance : | |

129 | //! - Two points are considered to be coincident if their | |

130 | //! distance is smaller than the tolerance of confusion. | |

131 | //! gp_Pnt P1, P2 ; | |

132 | //! P1 = ... | |

133 | //! P2 = ... | |

134 | //! if ( P1.IsEqual ( P2 , Precision::Confusion() ) ) | |

135 | //! then ... | |

136 | //! - A vector is considered to be null if it has a null length : | |

137 | //! gp_Vec V ; | |

138 | //! V = ... | |

139 | //! if ( V.Magnitude() < Precision::Confusion() ) then ... | |

140 | //! The tolerance of confusion is equal to 1.e-7. | |

141 | //! The value of the tolerance of confusion is also used to | |

142 | //! define : | |

143 | //! - the tolerance of intersection, and | |

144 | //! - the tolerance of approximation. | |

145 | //! Note : As a rule, coordinate values in Cas.Cade are not | |

146 | //! dimensioned, so 1. represents one user unit, whatever | |

147 | //! value the unit may have : the millimeter, the meter, the | |

148 | //! inch, or any other unit. Let's say that Cas.Cade | |

149 | //! algorithms are written to be tuned essentially with | |

150 | //! mechanical design applications, on the basis of the | |

151 | //! millimeter. However, these algorithms may be used with | |

152 | //! any other unit but the tolerance criterion does no longer | |

153 | //! have the same signification. | |

154 | //! So pay particular attention to the type of your application, | |

155 | //! in relation with the impact of your unit on the precision criterion. | |

156 | //! - For example in mechanical design, if the unit is the | |

157 | //! millimeter, the tolerance of confusion corresponds to a | |

158 | //! distance of 1 / 10000 micron, which is rather difficult to measure. | |

159 | //! - However in other types of applications, such as | |

160 | //! cartography, where the kilometer is frequently used, | |

161 | //! the tolerance of confusion corresponds to a greater | |

162 | //! distance (1 / 10 millimeter). This distance | |

163 | //! becomes easily measurable, but only within a restricted | |

164 | //! space which contains some small objects of the complete scene. | |

922da0a8 | 165 | static Standard_Real Confusion() { return 1.e-7; } |

42cf5bc1 | 166 | |

167 | //! Returns square of Confusion. | |

168 | //! Created for speed and convenience. | |

922da0a8 | 169 | static Standard_Real SquareConfusion() { return Confusion() * Confusion(); } |

170 | ||

42cf5bc1 | 171 | //! Returns the precision value in real space, frequently |

172 | //! used by intersection algorithms to decide that a solution is reached. | |

173 | //! This function provides an acceptable level of precision | |

174 | //! for an intersection process to define the adjustment limits. | |

175 | //! The tolerance of intersection is designed to ensure | |

176 | //! that a point computed by an iterative algorithm as the | |

177 | //! intersection between two curves is indeed on the | |

178 | //! intersection. It is obvious that two tangent curves are | |

179 | //! close to each other, on a large distance. An iterative | |

180 | //! algorithm of intersection may find points on these | |

181 | //! curves within the scope of the confusion tolerance, but | |

182 | //! still far from the true intersection point. In order to force | |

183 | //! the intersection algorithm to continue the iteration | |

184 | //! process until a correct point is found on the tangent | |

185 | //! objects, the tolerance of intersection must be smaller | |

186 | //! than the tolerance of confusion. | |

187 | //! On the other hand, the tolerance of intersection must | |

188 | //! be large enough to minimize the time required by the | |

189 | //! process to converge to a solution. | |

190 | //! The tolerance of intersection is equal to : | |

191 | //! Precision::Confusion() / 100. | |

192 | //! (that is, 1.e-9). | |

922da0a8 | 193 | static Standard_Real Intersection() { return Confusion() * 0.01; } |

194 | ||

42cf5bc1 | 195 | //! Returns the precision value in real space, frequently used |

196 | //! by approximation algorithms. | |

197 | //! This function provides an acceptable level of precision for | |

198 | //! an approximation process to define adjustment limits. | |

199 | //! The tolerance of approximation is designed to ensure | |

200 | //! an acceptable computation time when performing an | |

201 | //! approximation process. That is why the tolerance of | |

202 | //! approximation is greater than the tolerance of confusion. | |

203 | //! The tolerance of approximation is equal to : | |

204 | //! Precision::Confusion() * 10. | |

205 | //! (that is, 1.e-6). | |

206 | //! You may use a smaller tolerance in an approximation | |

207 | //! algorithm, but this option might be costly. | |

922da0a8 | 208 | static Standard_Real Approximation() { return Confusion() * 10.0; } |

209 | ||

42cf5bc1 | 210 | //! Convert a real space precision to a parametric |

211 | //! space precision. <T> is the mean value of the | |

212 | //! length of the tangent of the curve or the surface. | |

213 | //! | |

214 | //! Value is P / T | |

922da0a8 | 215 | static Standard_Real Parametric (const Standard_Real P, const Standard_Real T) { return P / T; } |

42cf5bc1 | 216 | |

217 | //! Returns a precision value in parametric space, which may be used : | |

218 | //! - to test the coincidence of two points in the real space, | |

219 | //! by using parameter values, or | |

220 | //! - to test the equality of two parameter values in a parametric space. | |

221 | //! The parametric tolerance of confusion is designed to | |

222 | //! give a mean value in relation with the dimension of | |

223 | //! the curve or the surface. It considers that a variation of | |

224 | //! parameter equal to 1. along a curve (or an | |

225 | //! isoparametric curve of a surface) generates a segment | |

226 | //! whose length is equal to 100. (default value), or T. | |

227 | //! The parametric tolerance of confusion is equal to : | |

228 | //! - Precision::Confusion() / 100., or Precision::Confusion() / T. | |

229 | //! The value of the parametric tolerance of confusion is also used to define : | |

230 | //! - the parametric tolerance of intersection, and | |

231 | //! - the parametric tolerance of approximation. | |

232 | //! Warning | |

233 | //! It is rather difficult to define a unique precision value in parametric space. | |

234 | //! - First consider a curve (c) ; if M is the point of | |

235 | //! parameter u and M' the point of parameter u+du on | |

236 | //! the curve, call 'parametric tangent' at point M, for the | |

237 | //! variation du of the parameter, the quantity : | |

238 | //! T(u,du)=MM'/du (where MM' represents the | |

239 | //! distance between the two points M and M', in the real space). | |

240 | //! - Consider the other curve resulting from a scaling | |

241 | //! transformation of (c) with a scale factor equal to | |

242 | //! 10. The 'parametric tangent' at the point of | |

243 | //! parameter u of this curve is ten times greater than the | |

244 | //! previous one. This shows that for two different curves, | |

245 | //! the distance between two points on the curve, resulting | |

246 | //! from the same variation of parameter du, may vary considerably. | |

247 | //! - Moreover, the variation of the parameter along the | |

248 | //! curve is generally not proportional to the curvilinear | |

249 | //! abscissa along the curve. So the distance between two | |

250 | //! points resulting from the same variation of parameter | |

251 | //! du, at two different points of a curve, may completely differ. | |

252 | //! - Moreover, the parameterization of a surface may | |

253 | //! generate two quite different 'parametric tangent' values | |

254 | //! in the u or in the v parametric direction. | |

255 | //! - Last, close to the poles of a sphere (the points which | |

256 | //! correspond to the values -Pi/2. and Pi/2. of the | |

257 | //! v parameter) the u parameter may change from 0 to | |

258 | //! 2.Pi without impacting on the resulting point. | |

259 | //! Therefore, take great care when adjusting a parametric | |

260 | //! tolerance to your own algorithm. | |

922da0a8 | 261 | static Standard_Real PConfusion (const Standard_Real T) { return Parametric (Confusion(), T); } |

42cf5bc1 | 262 | |

dbe54d10 | 263 | //! Returns square of PConfusion. |

264 | //! Created for speed and convenience. | |

265 | static Standard_Real SquarePConfusion() { return PConfusion() * PConfusion(); } | |

266 | ||

42cf5bc1 | 267 | //! Returns a precision value in parametric space, which |

268 | //! may be used by intersection algorithms, to decide that | |

269 | //! a solution is reached. The purpose of this function is to | |

270 | //! provide an acceptable level of precision in parametric | |

271 | //! space, for an intersection process to define the adjustment limits. | |

272 | //! The parametric tolerance of intersection is | |

273 | //! designed to give a mean value in relation with the | |

274 | //! dimension of the curve or the surface. It considers | |

275 | //! that a variation of parameter equal to 1. along a curve | |

276 | //! (or an isoparametric curve of a surface) generates a | |

277 | //! segment whose length is equal to 100. (default value), or T. | |

278 | //! The parametric tolerance of intersection is equal to : | |

279 | //! - Precision::Intersection() / 100., or Precision::Intersection() / T. | |

922da0a8 | 280 | static Standard_Real PIntersection (const Standard_Real T) { return Parametric(Intersection(),T); } |

281 | ||

42cf5bc1 | 282 | //! Returns a precision value in parametric space, which may |

283 | //! be used by approximation algorithms. The purpose of this | |

284 | //! function is to provide an acceptable level of precision in | |

285 | //! parametric space, for an approximation process to define | |

286 | //! the adjustment limits. | |

287 | //! The parametric tolerance of approximation is | |

288 | //! designed to give a mean value in relation with the | |

289 | //! dimension of the curve or the surface. It considers | |

290 | //! that a variation of parameter equal to 1. along a curve | |

291 | //! (or an isoparametric curve of a surface) generates a | |

292 | //! segment whose length is equal to 100. (default value), or T. | |

293 | //! The parametric tolerance of intersection is equal to : | |

294 | //! - Precision::Approximation() / 100., or Precision::Approximation() / T. | |

922da0a8 | 295 | static Standard_Real PApproximation (const Standard_Real T) { return Parametric(Approximation(),T); } |

296 | ||

42cf5bc1 | 297 | //! Convert a real space precision to a parametric |

298 | //! space precision on a default curve. | |

299 | //! | |

300 | //! Value is Parametric(P,1.e+2) | |

922da0a8 | 301 | static Standard_Real Parametric (const Standard_Real P) { return Parametric (P, 100.0); } |

302 | ||

42cf5bc1 | 303 | //! Used to test distances in parametric space on a |

304 | //! default curve. | |

305 | //! | |

306 | //! This is Precision::Parametric(Precision::Confusion()) | |

922da0a8 | 307 | static Standard_Real PConfusion() { return Parametric (Confusion()); } |

308 | ||

42cf5bc1 | 309 | //! Used for Intersections in parametric space on a |

310 | //! default curve. | |

311 | //! | |

312 | //! This is Precision::Parametric(Precision::Intersection()) | |

922da0a8 | 313 | static Standard_Real PIntersection() { return Parametric (Intersection()); } |

314 | ||

42cf5bc1 | 315 | //! Used for Approximations in parametric space on a |

316 | //! default curve. | |

317 | //! | |

318 | //! This is Precision::Parametric(Precision::Approximation()) | |

922da0a8 | 319 | static Standard_Real PApproximation() { return Parametric (Approximation()); } |

320 | ||

42cf5bc1 | 321 | //! Returns True if R may be considered as an infinite |

322 | //! number. Currently Abs(R) > 1e100 | |

922da0a8 | 323 | static Standard_Boolean IsInfinite (const Standard_Real R) { return Abs (R) >= (0.5 * Precision::Infinite()); } |

324 | ||

42cf5bc1 | 325 | //! Returns True if R may be considered as a positive |

326 | //! infinite number. Currently R > 1e100 | |

922da0a8 | 327 | static Standard_Boolean IsPositiveInfinite (const Standard_Real R) { return R >= (0.5 * Precision::Infinite()); } |

328 | ||

42cf5bc1 | 329 | //! Returns True if R may be considered as a negative |

330 | //! infinite number. Currently R < -1e100 | |

922da0a8 | 331 | static Standard_Boolean IsNegativeInfinite (const Standard_Real R) { return R <= -(0.5 * Precision::Infinite()); } |

332 | ||

42cf5bc1 | 333 | //! Returns a big number that can be considered as |

334 | //! infinite. Use -Infinite() for a negative big number. | |

922da0a8 | 335 | static Standard_Real Infinite() { return 2.e+100; } |

42cf5bc1 | 336 | |

337 | }; | |

338 | ||

42cf5bc1 | 339 | #endif // _Precision_HeaderFile |