diff --git a/geomdl/NURBS.py b/geomdl/NURBS.py index 0509a465..8b3ce8c0 100644 --- a/geomdl/NURBS.py +++ b/geomdl/NURBS.py @@ -91,9 +91,11 @@ def __deepcopy__(self, memo): result.init_cache() return result - def init_cache(self): - self._cache['ctrlpts'] = self._init_array() - self._cache['weights'] = self._init_array() + def init_cache(self, ctrlpts=[], weights=[]): + self._cache['ctrlpts'] = self._array_type(iter(ctrlpts)) + self._cache['weights'] = self._array_type(iter(weights)) + self._cache['ctrlpts'].register_callback(lambda: setattr(self, '_control_points_valid', False)) + self._cache['weights'].register_callback(lambda: setattr(self, '_control_points_valid', False)) @property def ctrlptsw(self): @@ -107,6 +109,9 @@ def ctrlptsw(self): :getter: Gets the weighted control points :setter: Sets the weighted control points """ + if not self._control_points_valid: + ctrlptsw = compatibility.combine_ctrlpts_weights(self.ctrlpts, self.weights) + self.set_ctrlpts(ctrlptsw) return self._control_points @ctrlptsw.setter @@ -127,22 +132,17 @@ def ctrlpts(self): # Populate the cache, if necessary if not self._cache['ctrlpts']: c, w = compatibility.separate_ctrlpts_weights(self._control_points) - self._cache['ctrlpts'] = self._array_type(iter(c)) - self._cache['weights'] = self._array_type(iter(w)) + self.init_cache(c, w) return self._cache['ctrlpts'] @ctrlpts.setter def ctrlpts(self, value): # Check if we can retrieve the existing weights. If not, generate a weights vector of 1.0s. if not self.weights: - weights = [1.0 for _ in range(len(value))] - else: - weights = self.weights + self.weights[:] = [1.0 for _ in range(len(value))] # Generate weighted control points using the new control points - ctrlptsw = compatibility.combine_ctrlpts_weights(value, weights) - - # Set new weighted control points + ctrlptsw = compatibility.combine_ctrlpts_weights(value, self.weights) self.set_ctrlpts(ctrlptsw) @property @@ -159,8 +159,7 @@ def weights(self): # Populate the cache, if necessary if not self._cache['weights']: c, w = compatibility.separate_ctrlpts_weights(self._control_points) - self._cache['ctrlpts'] = self._array_type(iter(c)) - self._cache['weights'] = self._array_type(iter(w)) + self.init_cache(c, w) return self._cache['weights'] @weights.setter @@ -174,6 +173,12 @@ def weights(self, value): # Set new weighted control points self.set_ctrlpts(ctrlptsw) + def _check_variables(self): + super(Curve, self)._check_variables() + if not self._control_points_valid: + ctrlptsw = compatibility.combine_ctrlpts_weights(self.ctrlpts, self.weights) + self.set_ctrlpts(ctrlptsw) + def reset(self, **kwargs): """ Resets control points and/or evaluated points. @@ -189,11 +194,9 @@ def reset(self, **kwargs): # Call parent function super(Curve, self).reset(ctrlpts=reset_ctrlpts, evalpts=reset_evalpts) + # Delete the caches if reset_ctrlpts: - # Delete the caches - self._cache['ctrlpts'] = self._init_array() - # TODO: why is this reset differently from the initialisation? - self._cache['weights'][:] = self._init_array() + self.init_cache() @export diff --git a/geomdl/abstract.py b/geomdl/abstract.py index 8ee0f171..ebb0c9cc 100644 --- a/geomdl/abstract.py +++ b/geomdl/abstract.py @@ -135,6 +135,7 @@ def __init__(self, **kwargs): self._knot_vector = [self._init_array() for _ in range(self._pdim)] # knot vector self._control_points = self._init_array() # control points self._control_points_size = [0 for _ in range(self._pdim)] # control points length + self._control_points_valid = False self._delta = [self._dinit for _ in range(self._pdim)] # evaluation delta self._bounding_box = self._init_array() # bounding box self._evaluator = None # evaluator instance @@ -466,7 +467,7 @@ def validate_and_clean(pts_in, check_for, dimension, pts_out, **kws): raise ValueError("Number of arguments after ctrlpts must be " + str(self._pdim)) # Keyword arguments - array_init = kwargs.get('array_init', [[] for _ in range(len(ctrlpts))]) + array_init = kwargs.get('array_init', self._array_type([] for _ in range(len(ctrlpts)))) array_check_for = kwargs.get('array_check_for', (list, tuple)) callback_func = kwargs.get('callback', validate_and_clean) self._dimension = kwargs.get('dimension', len(ctrlpts[0])) @@ -480,6 +481,7 @@ def validate_and_clean(pts_in, check_for, dimension, pts_out, **kws): # Set control points and sizes self._control_points = callback_func(ctrlpts, array_check_for, self._dimension, array_init, **kwargs) self._control_points_size = [int(arg) for arg in args] + self._control_points_valid = True @abc.abstractmethod def render(self, **kwargs): @@ -891,6 +893,7 @@ def reset(self, **kwargs): if reset_ctrlpts: self._control_points = self._init_array() self._bounding_box = self._init_array() + self._control_points_valid = False if reset_evalpts: self._eval_points = self._init_array()