0022048: Visualization, AIS_InteractiveContext - single object selection should alway...
[occt.git] / src / Precision / Precision.hxx
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).
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.
165   static Standard_Real Confusion() { return 1.e-7; }
166
167   //! Returns square of Confusion.
168   //! Created for speed and convenience.
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).
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.
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
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.
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.
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.
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.
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)
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())
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())
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())
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
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
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
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.
335   static Standard_Real Infinite() { return 2.e+100; }
336
337 };
338
339 #endif // _Precision_HeaderFile