|
|
|||
File indexing completed on 2026-10-02 09:13:36
0001 // Created on: 1993-02-17 0002 // Created by: Remi LEQUETTE 0003 // Copyright (c) 1993-1999 Matra Datavision 0004 // Copyright (c) 1999-2014 OPEN CASCADE SAS 0005 // 0006 // This file is part of Open CASCADE Technology software library. 0007 // 0008 // This library is free software; you can redistribute it and/or modify it under 0009 // the terms of the GNU Lesser General Public License version 2.1 as published 0010 // by the Free Software Foundation, with special exception defined in the file 0011 // OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT 0012 // distribution for complete text of the license and disclaimer of any warranty. 0013 // 0014 // Alternatively, this file may be used under the terms of Open CASCADE 0015 // commercial license or contractual agreement. 0016 0017 #ifndef _Precision_HeaderFile 0018 #define _Precision_HeaderFile 0019 0020 #include <Standard.hxx> 0021 #include <Standard_DefineAlloc.hxx> 0022 #include <Standard_Real.hxx> 0023 0024 //! The Precision package offers a set of functions defining precision criteria 0025 //! for use in conventional situations when comparing two numbers. 0026 //! Generalities 0027 //! It is not advisable to use floating number equality. Instead, the difference 0028 //! between numbers must be compared with a given precision, i.e. : 0029 //! double x1, x2 ; 0030 //! x1 = ... 0031 //! x2 = ... 0032 //! If ( x1 == x2 ) ... 0033 //! should not be used and must be written as indicated below: 0034 //! double x1, x2 ; 0035 //! double Precision = ... 0036 //! x1 = ... 0037 //! x2 = ... 0038 //! If ( Abs ( x1 - x2 ) < Precision ) ... 0039 //! Likewise, when ordering floating numbers, you must take the following into account : 0040 //! double x1, x2 ; 0041 //! double Precision = ... 0042 //! x1 = ... ! a large number 0043 //! x2 = ... ! another large number 0044 //! If ( x1 < x2 - Precision ) ... 0045 //! is incorrect when x1 and x2 are large numbers ; it is better to write : 0046 //! double x1, x2 ; 0047 //! double Precision = ... 0048 //! x1 = ... ! a large number 0049 //! x2 = ... ! another large number 0050 //! If ( x2 - x1 > Precision ) ... 0051 //! Precision in Cas.Cade 0052 //! Generally speaking, the precision criterion is not implicit in Cas.Cade. Low-level geometric 0053 //! algorithms accept precision criteria as arguments. As a rule, they should not refer directly to 0054 //! the precision criteria provided by the Precision package. On the other hand, high-level modeling 0055 //! algorithms have to provide the low-level geometric algorithms that they call, with a precision 0056 //! criteria. One way of doing this is to use the above precision criteria. Alternatively, the 0057 //! high-level algorithms can have their own system for precision management. For example, the 0058 //! Topology Data Structure stores precision criteria for each elementary shape (as a vertex, an 0059 //! edge or a face). When a new topological object is constructed, the precision criteria are taken 0060 //! from those provided by the Precision package, and stored in the related data structure. Later, a 0061 //! topological algorithm which analyses these objects will work with the values stored in the data 0062 //! structure. Also, if this algorithm is to build a new topological object, from these precision 0063 //! criteria, it will compute a new precision criterion for the new topological object, and write it 0064 //! into the data structure of the new topological object. The different precision criteria offered 0065 //! by the Precision package, cover the most common requirements of geometric algorithms, such as 0066 //! intersections, approximations, and so on. The choice of precision depends on the algorithm and 0067 //! on the geometric space. The geometric space may be : 0068 //! - a "real" 2D or 3D space, where the lengths are measured in meters, millimeters, microns, 0069 //! inches, etc ..., or 0070 //! - a "parametric" space, 1D on a curve or 2D on a surface, where lengths have no dimension. 0071 //! The choice of precision criteria for real space depends on the choice of the product, as it is 0072 //! based on the accuracy of the machine and the unit of measurement. The choice of precision 0073 //! criteria for parametric space depends on both the accuracy of the machine and the dimensions of 0074 //! the curve or the surface, since the parametric precision criterion and the real precision 0075 //! criterion are linked : if the curve is defined by the equation P(t), the inequation : Abs ( t2 - 0076 //! t1 ) < ParametricPrecision means that the parameters t1 and t2 are considered to be equal, and 0077 //! the inequation : Distance ( P(t2) , P(t1) ) < RealPrecision means that the points P(t1) and 0078 //! P(t2) are considered to be coincident. It seems to be the same idea, and it would be wonderful 0079 //! if these two inequations were equivalent. Note that this is rarely the case ! What is provided 0080 //! in this package? The Precision package provides : 0081 //! - a set of real space precision criteria for the algorithms, in view of checking distances and 0082 //! angles, 0083 //! - a set of parametric space precision criteria for the algorithms, in view of checking both : 0084 //! - the equality of parameters in a parametric space, 0085 //! - or the coincidence of points in the real space, by using parameter values, 0086 //! - the notion of infinite value, composed of a value assumed to be infinite, and checking tests 0087 //! designed to verify if any value could be considered as infinite. All the provided functions are 0088 //! very simple. The returned values result from the adaptation of the applications developed by the 0089 //! Open CASCADE company to Open CASCADE algorithms. The main interest of these functions lies in 0090 //! that it incites engineers developing applications to ask questions on precision factors. Which 0091 //! one is to be used in such or such case ? Tolerance criteria are context dependent. They must 0092 //! first choose : 0093 //! - either to work in real space, 0094 //! - or to work in parametric space, 0095 //! - or to work in a combined real and parametric space. 0096 //! They must next decide which precision factor will give the best answer to the current problem. 0097 //! Within an application environment, it is crucial to master precision even though this process 0098 //! may take a great deal of time. 0099 class Precision 0100 { 0101 public: 0102 DEFINE_STANDARD_ALLOC 0103 0104 //! Returns the recommended precision value 0105 //! when checking the equality of two angles (given in radians). 0106 //! double Angle1 = ... , Angle2 = ... ; 0107 //! If ( std::abs( Angle2 - Angle1 ) < Precision::Angular() ) ... 0108 //! The tolerance of angular equality may be used to check the parallelism of two vectors : 0109 //! gp_Vec V1, V2 ; 0110 //! V1 = ... 0111 //! V2 = ... 0112 //! If ( V1.IsParallel (V2, Precision::Angular() ) ) ... 0113 //! The tolerance of angular equality is equal to 1.e-12. 0114 //! Note : The tolerance of angular equality can be used when working with scalar products or 0115 //! cross products since sines and angles are equivalent for small angles. Therefore, in order to 0116 //! check whether two unit vectors are perpendicular : 0117 //! gp_Dir D1, D2 ; 0118 //! D1 = ... 0119 //! D2 = ... 0120 //! you can use : 0121 //! If ( std::abs( D1.D2 ) < Precision::Angular() ) ... 0122 //! (although the function IsNormal does exist). 0123 static constexpr double Angular() { return 1.e-12; } 0124 0125 //! Returns the recommended precision value when 0126 //! checking coincidence of two points in real space. 0127 //! The tolerance of confusion is used for testing a 3D 0128 //! distance : 0129 //! - Two points are considered to be coincident if their 0130 //! distance is smaller than the tolerance of confusion. 0131 //! gp_Pnt P1, P2 ; 0132 //! P1 = ... 0133 //! P2 = ... 0134 //! if ( P1.IsEqual ( P2 , Precision::Confusion() ) ) 0135 //! then ... 0136 //! - A vector is considered to be null if it has a null length : 0137 //! gp_Vec V ; 0138 //! V = ... 0139 //! if ( V.Magnitude() < Precision::Confusion() ) then ... 0140 //! The tolerance of confusion is equal to 1.e-7. 0141 //! The value of the tolerance of confusion is also used to 0142 //! define : 0143 //! - the tolerance of intersection, and 0144 //! - the tolerance of approximation. 0145 //! Note : As a rule, coordinate values in Cas.Cade are not 0146 //! dimensioned, so 1. represents one user unit, whatever 0147 //! value the unit may have : the millimeter, the meter, the 0148 //! inch, or any other unit. Let's say that Cas.Cade 0149 //! algorithms are written to be tuned essentially with 0150 //! mechanical design applications, on the basis of the 0151 //! millimeter. However, these algorithms may be used with 0152 //! any other unit but the tolerance criterion does no longer 0153 //! have the same signification. 0154 //! So pay particular attention to the type of your application, 0155 //! in relation with the impact of your unit on the precision criterion. 0156 //! - For example in mechanical design, if the unit is the 0157 //! millimeter, the tolerance of confusion corresponds to a 0158 //! distance of 1 / 10000 micron, which is rather difficult to measure. 0159 //! - However in other types of applications, such as 0160 //! cartography, where the kilometer is frequently used, 0161 //! the tolerance of confusion corresponds to a greater 0162 //! distance (1 / 10 millimeter). This distance 0163 //! becomes easily measurable, but only within a restricted 0164 //! space which contains some small objects of the complete scene. 0165 static constexpr double Confusion() { return 1.e-7; } 0166 0167 //! Returns square of Confusion. 0168 //! Created for speed and convenience. 0169 static constexpr double SquareConfusion() { return Confusion() * Confusion(); } 0170 0171 //! Returns a precision value at machine epsilon level, used for 0172 //! low-level numerical computations and floating-point comparisons. 0173 //! Unlike the geometric tolerances (Confusion, Intersection, Approximation) 0174 //! which are application-level values for modeling operations, this value 0175 //! represents the fundamental limit of floating-point arithmetic precision. 0176 //! 0177 //! Typical use cases include: 0178 //! - Checking if squared magnitudes are effectively zero (e.g., vector.SquareMagnitude() < 0179 //! SquareComputational()) 0180 //! - Division-by-zero protection in numerical algorithms 0181 //! - Convergence criteria in iterative solvers at machine precision level 0182 //! - Detecting numerical degeneracies in low-level computations 0183 //! 0184 //! The computational tolerance is equal to DBL_EPSILON (approximately 2.22e-16), 0185 //! which is the smallest positive value such that 1.0 + eps != 1.0 in double 0186 //! precision floating-point arithmetic. This is the fundamental machine epsilon 0187 //! for double (double) type. 0188 //! 0189 //! Note: This value should NOT be used for geometric comparisons. 0190 //! Use Precision::Confusion() for comparing geometric distances, 0191 //! Precision::Angular() for angles, etc. 0192 static constexpr double Computational() { return RealEpsilon(); } 0193 0194 //! Returns square of Computational. 0195 //! Created for speed and convenience when comparing squared values. 0196 static constexpr double SquareComputational() { return Computational() * Computational(); } 0197 0198 //! Returns the precision value in real space, frequently 0199 //! used by intersection algorithms to decide that a solution is reached. 0200 //! This function provides an acceptable level of precision 0201 //! for an intersection process to define the adjustment limits. 0202 //! The tolerance of intersection is designed to ensure 0203 //! that a point computed by an iterative algorithm as the 0204 //! intersection between two curves is indeed on the 0205 //! intersection. It is obvious that two tangent curves are 0206 //! close to each other, on a large distance. An iterative 0207 //! algorithm of intersection may find points on these 0208 //! curves within the scope of the confusion tolerance, but 0209 //! still far from the true intersection point. In order to force 0210 //! the intersection algorithm to continue the iteration 0211 //! process until a correct point is found on the tangent 0212 //! objects, the tolerance of intersection must be smaller 0213 //! than the tolerance of confusion. 0214 //! On the other hand, the tolerance of intersection must 0215 //! be large enough to minimize the time required by the 0216 //! process to converge to a solution. 0217 //! The tolerance of intersection is equal to : 0218 //! Precision::Confusion() / 100. 0219 //! (that is, 1.e-9). 0220 static constexpr double Intersection() { return Confusion() * 0.01; } 0221 0222 //! Returns the precision value in real space, frequently used 0223 //! by approximation algorithms. 0224 //! This function provides an acceptable level of precision for 0225 //! an approximation process to define adjustment limits. 0226 //! The tolerance of approximation is designed to ensure 0227 //! an acceptable computation time when performing an 0228 //! approximation process. That is why the tolerance of 0229 //! approximation is greater than the tolerance of confusion. 0230 //! The tolerance of approximation is equal to : 0231 //! Precision::Confusion() * 10. 0232 //! (that is, 1.e-6). 0233 //! You may use a smaller tolerance in an approximation 0234 //! algorithm, but this option might be costly. 0235 static constexpr double Approximation() { return Confusion() * 10.0; } 0236 0237 //! Convert a real space precision to a parametric 0238 //! space precision. <T> is the mean value of the 0239 //! length of the tangent of the curve or the surface. 0240 //! 0241 //! Value is P / T 0242 static constexpr double Parametric(const double P, const double T) { return P / T; } 0243 0244 //! Returns a precision value in parametric space, which may be used : 0245 //! - to test the coincidence of two points in the real space, 0246 //! by using parameter values, or 0247 //! - to test the equality of two parameter values in a parametric space. 0248 //! The parametric tolerance of confusion is designed to 0249 //! give a mean value in relation with the dimension of 0250 //! the curve or the surface. It considers that a variation of 0251 //! parameter equal to 1. along a curve (or an 0252 //! isoparametric curve of a surface) generates a segment 0253 //! whose length is equal to 100. (default value), or T. 0254 //! The parametric tolerance of confusion is equal to : 0255 //! - Precision::Confusion() / 100., or Precision::Confusion() / T. 0256 //! The value of the parametric tolerance of confusion is also used to define : 0257 //! - the parametric tolerance of intersection, and 0258 //! - the parametric tolerance of approximation. 0259 //! Warning 0260 //! It is rather difficult to define a unique precision value in parametric space. 0261 //! - First consider a curve (c) ; if M is the point of 0262 //! parameter u and M' the point of parameter u+du on 0263 //! the curve, call 'parametric tangent' at point M, for the 0264 //! variation du of the parameter, the quantity : 0265 //! T(u,du)=MM'/du (where MM' represents the 0266 //! distance between the two points M and M', in the real space). 0267 //! - Consider the other curve resulting from a scaling 0268 //! transformation of (c) with a scale factor equal to 0269 //! 10. The 'parametric tangent' at the point of 0270 //! parameter u of this curve is ten times greater than the 0271 //! previous one. This shows that for two different curves, 0272 //! the distance between two points on the curve, resulting 0273 //! from the same variation of parameter du, may vary considerably. 0274 //! - Moreover, the variation of the parameter along the 0275 //! curve is generally not proportional to the curvilinear 0276 //! abscissa along the curve. So the distance between two 0277 //! points resulting from the same variation of parameter 0278 //! du, at two different points of a curve, may completely differ. 0279 //! - Moreover, the parameterization of a surface may 0280 //! generate two quite different 'parametric tangent' values 0281 //! in the u or in the v parametric direction. 0282 //! - Last, close to the poles of a sphere (the points which 0283 //! correspond to the values -Pi/2. and Pi/2. of the 0284 //! v parameter) the u parameter may change from 0 to 0285 //! 2.Pi without impacting on the resulting point. 0286 //! Therefore, take great care when adjusting a parametric 0287 //! tolerance to your own algorithm. 0288 static constexpr double PConfusion(const double T) { return Parametric(Confusion(), T); } 0289 0290 //! Returns square of PConfusion. 0291 //! Created for speed and convenience. 0292 static constexpr double SquarePConfusion() { return PConfusion() * PConfusion(); } 0293 0294 //! Returns a precision value in parametric space, which 0295 //! may be used by intersection algorithms, to decide that 0296 //! a solution is reached. The purpose of this function is to 0297 //! provide an acceptable level of precision in parametric 0298 //! space, for an intersection process to define the adjustment limits. 0299 //! The parametric tolerance of intersection is 0300 //! designed to give a mean value in relation with the 0301 //! dimension of the curve or the surface. It considers 0302 //! that a variation of parameter equal to 1. along a curve 0303 //! (or an isoparametric curve of a surface) generates a 0304 //! segment whose length is equal to 100. (default value), or T. 0305 //! The parametric tolerance of intersection is equal to : 0306 //! - Precision::Intersection() / 100., or Precision::Intersection() / T. 0307 static constexpr double PIntersection(const double T) { return Parametric(Intersection(), T); } 0308 0309 //! Returns a precision value in parametric space, which may 0310 //! be used by approximation algorithms. The purpose of this 0311 //! function is to provide an acceptable level of precision in 0312 //! parametric space, for an approximation process to define 0313 //! the adjustment limits. 0314 //! The parametric tolerance of approximation is 0315 //! designed to give a mean value in relation with the 0316 //! dimension of the curve or the surface. It considers 0317 //! that a variation of parameter equal to 1. along a curve 0318 //! (or an isoparametric curve of a surface) generates a 0319 //! segment whose length is equal to 100. (default value), or T. 0320 //! The parametric tolerance of intersection is equal to : 0321 //! - Precision::Approximation() / 100., or Precision::Approximation() / T. 0322 static constexpr double PApproximation(const double T) { return Parametric(Approximation(), T); } 0323 0324 //! Convert a real space precision to a parametric 0325 //! space precision on a default curve. 0326 //! 0327 //! Value is Parametric(P,1.e+2) 0328 static constexpr double Parametric(const double P) { return P * 0.01; } 0329 0330 //! Used to test distances in parametric space on a 0331 //! default curve. 0332 //! 0333 //! This is Precision::Parametric(Precision::Confusion()) 0334 static constexpr double PConfusion() { return Confusion() * 0.01; } 0335 0336 //! Used for Intersections in parametric space on a 0337 //! default curve. 0338 //! 0339 //! This is Precision::Parametric(Precision::Intersection()) 0340 static constexpr double PIntersection() { return Intersection() * 0.01; } 0341 0342 //! Used for Approximations in parametric space on a 0343 //! default curve. 0344 //! 0345 //! This is Precision::Parametric(Precision::Approximation()) 0346 static constexpr double PApproximation() { return Approximation() * 0.01; } 0347 0348 //! Returns True if R may be considered as an infinite 0349 //! number. Currently std::abs(R) > 1e100 0350 static inline bool IsInfinite(const double R) 0351 { 0352 return std::abs(R) >= (0.5 * Precision::Infinite()); 0353 } 0354 0355 //! Returns True if R may be considered as a positive 0356 //! infinite number. Currently R > 1e100 0357 static constexpr bool IsPositiveInfinite(const double R) 0358 { 0359 return R >= (0.5 * Precision::Infinite()); 0360 } 0361 0362 //! Returns True if R may be considered as a negative 0363 //! infinite number. Currently R < -1e100 0364 static constexpr bool IsNegativeInfinite(const double R) 0365 { 0366 return R <= -(0.5 * Precision::Infinite()); 0367 } 0368 0369 //! Returns a big number that can be considered as 0370 //! infinite. Use -Infinite() for a negative big number. 0371 static constexpr double Infinite() { return 2.e+100; } 0372 }; 0373 0374 #endif // _Precision_HeaderFile
| [ Source navigation ] | [ Diff markup ] | [ Identifier search ] | [ general search ] |
|
This page was automatically generated by the 2.3.7 LXR engine. The LXR team |
|