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> 23 #include <Standard_Real.hxx> 24 #include <Standard_Boolean.hxx> 25 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 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). Angular()123 static Standard_Real Angular() { return 1.e-12; } 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. Confusion()165 static Standard_Real Confusion() { return 1.e-7; } 166 167 //! Returns square of Confusion. 168 //! Created for speed and convenience. SquareConfusion()169 static Standard_Real SquareConfusion() { return Confusion() * Confusion(); } 170 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). Intersection()193 static Standard_Real Intersection() { return Confusion() * 0.01; } 194 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. Approximation()208 static Standard_Real Approximation() { return Confusion() * 10.0; } 209 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 Parametric(const Standard_Real P,const Standard_Real T)215 static Standard_Real Parametric (const Standard_Real P, const Standard_Real T) { return P / T; } 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. PConfusion(const Standard_Real T)261 static Standard_Real PConfusion (const Standard_Real T) { return Parametric (Confusion(), T); } 262 263 //! Returns square of PConfusion. 264 //! Created for speed and convenience. SquarePConfusion()265 static Standard_Real SquarePConfusion() { return PConfusion() * PConfusion(); } 266 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. PIntersection(const Standard_Real T)280 static Standard_Real PIntersection (const Standard_Real T) { return Parametric(Intersection(),T); } 281 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. PApproximation(const Standard_Real T)295 static Standard_Real PApproximation (const Standard_Real T) { return Parametric(Approximation(),T); } 296 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) Parametric(const Standard_Real P)301 static Standard_Real Parametric (const Standard_Real P) { return Parametric (P, 100.0); } 302 303 //! Used to test distances in parametric space on a 304 //! default curve. 305 //! 306 //! This is Precision::Parametric(Precision::Confusion()) PConfusion()307 static Standard_Real PConfusion() { return Parametric (Confusion()); } 308 309 //! Used for Intersections in parametric space on a 310 //! default curve. 311 //! 312 //! This is Precision::Parametric(Precision::Intersection()) PIntersection()313 static Standard_Real PIntersection() { return Parametric (Intersection()); } 314 315 //! Used for Approximations in parametric space on a 316 //! default curve. 317 //! 318 //! This is Precision::Parametric(Precision::Approximation()) PApproximation()319 static Standard_Real PApproximation() { return Parametric (Approximation()); } 320 321 //! Returns True if R may be considered as an infinite 322 //! number. Currently Abs(R) > 1e100 IsInfinite(const Standard_Real R)323 static Standard_Boolean IsInfinite (const Standard_Real R) { return Abs (R) >= (0.5 * Precision::Infinite()); } 324 325 //! Returns True if R may be considered as a positive 326 //! infinite number. Currently R > 1e100 IsPositiveInfinite(const Standard_Real R)327 static Standard_Boolean IsPositiveInfinite (const Standard_Real R) { return R >= (0.5 * Precision::Infinite()); } 328 329 //! Returns True if R may be considered as a negative 330 //! infinite number. Currently R < -1e100 IsNegativeInfinite(const Standard_Real R)331 static Standard_Boolean IsNegativeInfinite (const Standard_Real R) { return R <= -(0.5 * Precision::Infinite()); } 332 333 //! Returns a big number that can be considered as 334 //! infinite. Use -Infinite() for a negative big number. Infinite()335 static Standard_Real Infinite() { return 2.e+100; } 336 337 }; 338 339 #endif // _Precision_HeaderFile 340