diff --git a/src/Mod/Draft/DraftVecUtils.py b/src/Mod/Draft/DraftVecUtils.py index ac69a2365b..415e7e2c80 100644 --- a/src/Mod/Draft/DraftVecUtils.py +++ b/src/Mod/Draft/DraftVecUtils.py @@ -35,11 +35,13 @@ but which can also be used in other workbenches and in macros. # flake8 --ignore=E226,E266,E401,W503 import math +import warnings import FreeCAD from FreeCAD import Vector from draftutils import params from draftutils import messages +from draftutils.utils import precision as draft_precision __title__ = "FreeCAD Draft Workbench - Vector library" __author__ = "Yorik van Havre, Werner Mayer, Martin Burbaum, Ken Cline" @@ -48,17 +50,28 @@ __url__ = "https://www.freecad.org" ## \addtogroup DRAFTVECUTILS # @{ - +# @deprecated("use Draft.precision() instead.") def precision(): - """Get the number of decimal numbers used for precision. + """ + Get the number of fractional decimal digits as configured + in Draft preferences. + This function is deprecated since it is a doublette of + Draft.precision() + Returns ------- int - Return the number of decimal places set up in the preferences, - or a standard value (6), if the parameter is missing. + Return the number of fractional decimal digits as configured + in Draft preferences. """ - return params.get_param("precision") + warnings.warn("Call to deprecated function 'DraftVecUtils.precision()'." + + " Please consider using Draft.precision().", + DeprecationWarning, stacklevel=2) + messages._wrn("DraftVecUtils.precision() called, which is deprecated." + + " Please consider using Draft.precision(). ") + + return draft_precision() def typecheck(args_and_types, name="?"): @@ -177,7 +190,7 @@ def neg(u): return Vector(-u.x, -u.y, -u.z) -def equals(u, v): +def equals(u, v, precision=None): """Check for equality between two vectors. Due to rounding errors, two vectors will rarely be `equal`. @@ -191,10 +204,13 @@ def equals(u, v): Parameters ---------- - u : Base::Vector3 - The first vector. - v : Base::Vector3 - The second vector. + u : Base::Vector3 + The first vector. + v : Base::Vector3 + The second vector. + precision : int | None + mathematical precision - if None use configured draft + precision Returns ------- @@ -202,7 +218,7 @@ def equals(u, v): `True` if the vectors are within the precision, `False` otherwise. """ typecheck([(u, Vector), (v, Vector)], "equals") - return isNull(u.sub(v)) + return isNull(u.sub(v), precision) def scale(u, scalar): @@ -525,19 +541,22 @@ def getRotation(vector, reference=Vector(1, 0, 0)): return (c.x, c.y, c.z, Q) -def isNull(vector): +def isNull(vector, precision=None): """Return False if each of the components of the vector is zero. Due to rounding errors, an element is probably never going to be exactly zero. Therefore, it rounds the element by the number - of decimals specified in the `precision` parameter - in the parameter database, accessed through `FreeCAD.ParamGet()`. - It then compares the rounded numbers against zero. + of decimals specified in the `precision` parameter - if `precision` + is not set or set to None configured Draft precision is used. + It then compares the rounded coordinates against zero. Parameters ---------- vector : Base::Vector3 The tested vector. + precision : int | None + mathematical precision - if None use configured draft + precision Returns ------- @@ -545,14 +564,15 @@ def isNull(vector): `True` if each of the elements is zero within the precision. `False` otherwise. """ - p = precision() - x = round(vector.x, p) - y = round(vector.y, p) - z = round(vector.z, p) + if precision is None: + precision = params.get_param("precision") + x = round(vector.x, precision) + y = round(vector.y, precision) + z = round(vector.z, precision) return (x == 0 and y == 0 and z == 0) -def find(vector, vlist): +def find(vector, vlist, precision=None): """Find a vector in a list of vectors, and return the index. Finding a vector tests for `equality` which depends on the `precision` @@ -564,10 +584,13 @@ def find(vector, vlist): The tested vector. vlist : list A list of Base::Vector3 vectors. + precision : int | None + mathematical precision - if None use configured draft + precision Returns ------- - int + int | None The index of the list where the vector is found, or `None` if the vector is not found. @@ -577,7 +600,7 @@ def find(vector, vlist): """ typecheck([(vector, Vector), (vlist, list)], "find") for i, v in enumerate(vlist): - if equals(vector, v): + if equals(vector, v, precision): return i return None @@ -628,7 +651,7 @@ def closest(vector, vlist, return_length=False): return index -def isColinear(vlist): +def isColinear(vlist, precision=None): """Check if the vectors in the list are colinear. Colinear vectors are those whose angle between them is zero. @@ -655,6 +678,9 @@ def isColinear(vlist): vlist : list List of Base::Vector3 vectors. At least three elements must be present. + precision : int | None + mathematical precision - if None use configured draft + precision Returns ------- @@ -676,8 +702,8 @@ def isColinear(vlist): # This doesn't test for colinearity between the first two vectors. if len(vlist) < 3: return True - - p = precision() + if precision is None: + precision = params.get_param("precision") # Difference between the second vector and the first one first = vlist[1].sub(vlist[0]) @@ -691,12 +717,12 @@ def isColinear(vlist): # The angle between the difference and the first difference. _angle = angle(diff, first) - if round(_angle, p) != 0: + if round(_angle, precision) != 0: return False return True -def rounded(v,d=None): +def rounded(v,precision=None): """Return a vector rounded to the `precision` in the parameter database or to the given decimals value @@ -705,9 +731,12 @@ def rounded(v,d=None): Parameters ---------- - v : Base::Vector3 - The input vector. - d : (Optional) the number of decimals to round to + v : Base::Vector3 + The input vector. + precision : int | None + mathematical precision - if None use configured draft + precision + Returns ------- @@ -716,10 +745,9 @@ def rounded(v,d=None): to the number of decimals specified in the `precision` parameter in the parameter database. """ - p = precision() - if d: - p = d - return Vector(round(v.x, p), round(v.y, p), round(v.z, p)) + if precision is None: + precision = params.get_param("precision") + return Vector(round(v.x, precision), round(v.y, precision), round(v.z, precision)) def getPlaneRotation(u, v, _ = None): @@ -766,7 +794,7 @@ def getPlaneRotation(u, v, _ = None): return m -def removeDoubles(vlist): +def removeDoubles(vlist, precision=None): """Remove duplicated vectors from a list of vectors. It removes only the duplicates that are next to each other in the list. @@ -784,9 +812,12 @@ def removeDoubles(vlist): Parameters ---------- - vlist : list of Base::Vector3 - List with vectors. - + vlist : list of Base::Vector3 + List with vectors. + precision : int | None + mathematical precision - if None use configured draft + precision + Returns ------- list of Base::Vector3 @@ -805,20 +836,23 @@ def removeDoubles(vlist): # Iterate until the penultimate element, and test for equality # with the element in front for i in range(len(vlist) - 1): - if not equals(vlist[i], vlist[i+1]): + if not equals(vlist[i], vlist[i+1], precision): nlist.append(vlist[i]) # Add the last element nlist.append(vlist[-1]) return nlist -def get_spherical_coords(x, y, z): +def get_spherical_coords(x, y, z, precision=None): """Get the Spherical coordinates of the vector represented by Cartesian coordinates (x, y, z). Parameters ---------- - vector : Base::Vector3 - The input vector. + vector : Base::Vector3 + The input vector. + precision : int | None + mathematical precision - if None use configured draft + precision Returns ------- @@ -836,13 +870,16 @@ def get_spherical_coords(x, y, z): (0, 0, z) -> (radius, theta, 0) """ + if precision is None: + precision = params.get_param("precision") + v = Vector(x,y,z) x_axis = Vector(1,0,0) z_axis = Vector(0,0,1) y_axis = Vector(0,1,0) rad = v.Length - if not bool(round(rad, precision())): + if not bool(round(rad, precision)): return (0, math.pi/2, 0) theta = v.getAngle(z_axis)