@@ -53,6 +53,9 @@ class Tolerance(Data):
5353 This value is called the "true value".
5454 By convention, the second value is considered the "true value" by the comparison functions of this class.
5555
56+ The :class:`compas.tolerance.Tolerance` class is implemented using a "singleton" pattern and can therefore have only 1 (one) instance per context.
57+ Usage of :attr:`compas.tolerance.TOL` outside of :mod:`compas` internals is therefore deprecated.
58+
5659 Examples
5760 --------
5861 >>> tol = Tolerance()
@@ -67,6 +70,16 @@ class Tolerance(Data):
6770
6871 """
6972
73+ _instance = None
74+ _is_inited = False
75+
76+ SUPPORTED_UNITS = ["M" , "MM" ]
77+ """{"M", "MM"}: Default tolerances are defined in relation to length units.
78+
79+ Currently, only meters ("M") and millimeters ("MM") are supported.
80+
81+ """
82+
7083 ABSOLUTE = 1e-9
7184 """float: Determines when a number is small enough to be considered zero.
7285 """
@@ -108,8 +121,9 @@ class Tolerance(Data):
108121 """
109122
110123 def __new__ (cls , * args , ** kwargs ):
111- if not hasattr (cls , "_instance" ):
112- cls ._instance = super (Tolerance , cls ).__new__ (cls )
124+ if not cls ._instance :
125+ cls ._instance = object .__new__ (cls , * args , ** kwargs )
126+ cls ._is_inited = False
113127 return cls ._instance
114128
115129 @property
@@ -151,22 +165,34 @@ def __init__(
151165 name = None ,
152166 ):
153167 super (Tolerance , self ).__init__ (name = name )
154- self ._unit = None
155- self ._absolute = None
156- self ._relative = None
157- self ._angular = None
158- self ._approximation = None
159- self ._precision = None
160- self ._lineardeflection = None
161- self ._angulardeflection = None
162- self .unit = unit
163- self .absolute = absolute
164- self .relative = relative
165- self .angular = angular
166- self .approximation = approximation
167- self .precision = precision
168- self .lineardeflection = lineardflection
169- self .angulardeflection = angulardflection
168+ if not self ._is_inited :
169+ self ._unit = None
170+ self ._absolute = None
171+ self ._relative = None
172+ self ._angular = None
173+ self ._approximation = None
174+ self ._precision = None
175+ self ._lineardeflection = None
176+ self ._angulardeflection = None
177+
178+ self ._is_inited = True
179+
180+ if unit is not None :
181+ self .unit = unit
182+ if absolute is not None :
183+ self .absolute = absolute
184+ if relative is not None :
185+ self .relative = relative
186+ if angular is not None :
187+ self .angular = angular
188+ if approximation is not None :
189+ self .approximation = approximation
190+ if precision is not None :
191+ self .precision = precision
192+ if lineardflection is not None :
193+ self .lineardeflection = lineardflection
194+ if angulardflection is not None :
195+ self .angulardeflection = angulardflection
170196
171197 # this can be autogenerated if we use slots
172198 # __repr__: return f"{__class__.__name__}({', '.join(f'{k}={v!r}' for k, v in self.__dict__.items())})}"
@@ -193,6 +219,23 @@ def reset(self):
193219 self ._lineardeflection = None
194220 self ._angulardeflection = None
195221
222+ def update_from_dict (self , tolerance ):
223+ """Update the tolerance singleton from the key-value pairs found in a dict.
224+
225+ Parameters
226+ ----------
227+ tolerance : dict
228+ A dictionary containing named tolerance values.
229+
230+ Returns
231+ -------
232+ None
233+
234+ """
235+ for name in tolerance :
236+ if hasattr (self , name ):
237+ setattr (self , name , tolerance [name ])
238+
196239 @property
197240 def units (self ):
198241 return self ._unit
0 commit comments