@@ -34,7 +34,7 @@ def __init__(
3434 self , R : Number , r : Number , d : Number , thetas : List [Number ] = None ,
3535 theta_start : Number = None , theta_stop : Number = None ,
3636 theta_step : Number = None , origin : Tuple [Number , Number ] = (0 , 0 ),
37- orientation : Number = 0
37+ orientation : Number = 0 , noise : List [ "np.array" ] = None
3838 ) -> None :
3939 """Model of a trochoid curve from given input parameters. A trochoid is
4040 a curve drawn by tracing a point from a circle as it rolls around the
@@ -76,6 +76,7 @@ def __init__(
7676 self .thetas = _validate_theta (thetas , theta_start , theta_stop , theta_step )
7777 self .origin = origin
7878 self .orientation = orientation
79+ self .noise = noise
7980
8081 self ._validate_inputs ()
8182 self ._calculate_path ()
@@ -109,15 +110,17 @@ def translate(self, x: Number = 0, y: Number = 0) -> "_Trochoid":
109110 d = self .d ,
110111 thetas = self .thetas ,
111112 origin = (self .origin [0 ]+ x , self .origin [1 ]+ y ),
112- orientation = self .orientation
113+ orientation = self .orientation ,
114+ noise = self .noise
113115 )
114116 except TypeError :
115117 translated_shape = self .__class__ (
116118 R = self .R ,
117119 r = self .r ,
118120 thetas = self .thetas ,
119121 origin = (self .origin [0 ]+ x , self .origin [1 ]+ y ),
120- orientation = self .orientation
122+ orientation = self .orientation ,
123+ noise = self .noise
121124 )
122125 return translated_shape
123126
@@ -157,15 +160,18 @@ def scale(self, factor: Number) -> Union["_Trochoid", "_Cycloid"]:
157160 d = self .d * factor ,
158161 thetas = self .thetas ,
159162 origin = self .origin ,
160- orientation = self .orientation
163+ orientation = self .orientation ,
164+ noise = [self .noise [0 ]* factor , self .noise [1 ]* factor ]
161165 )
162166 except TypeError :
163167 scaled_shape = self .__class__ (
164168 R = self .R * factor ,
165169 r = self .r * factor ,
166170 thetas = self .thetas ,
167171 origin = self .origin ,
168- orientation = self .orientation
172+ orientation = self .orientation ,
173+ noise = [self .noise [0 ]* factor , self .noise [1 ]* factor ]
174+
169175 )
170176 return scaled_shape
171177
@@ -205,18 +211,45 @@ def rotate(self, angle: float, degrees: bool = False):
205211 d = self .d ,
206212 thetas = self .thetas ,
207213 origin = self .origin ,
208- orientation = self .orientation + angle
214+ orientation = self .orientation + angle ,
215+ noise = self .noise
209216 )
210217 except TypeError :
211218 rotated_shape = self .__class__ (
212219 R = self .R ,
213220 r = self .r ,
214221 thetas = self .thetas ,
215222 origin = self .origin ,
216- orientation = self .orientation + angle
223+ orientation = self .orientation + angle ,
224+ noise = self .noise
217225 )
218226 return rotated_shape
219227
228+ def add_noise (self , x_scale : Number = 0 , y_scale : Number = 0 ) -> Union ["_Trochoid" , "_Cycloid" ]:
229+ x_noise = np .random .normal (0 , x_scale , size = len (self .x ))
230+ y_noise = np .random .normal (0 , y_scale , size = len (self .y ))
231+ noise = [x_noise , y_noise ]
232+ try :
233+ noisy_shape = self .__class__ (
234+ R = self .R ,
235+ r = self .r ,
236+ d = self .d ,
237+ thetas = self .thetas ,
238+ origin = self .origin ,
239+ orientation = self .orientation ,
240+ noise = noise
241+ )
242+ except TypeError :
243+ noisy_shape = self .__class__ (
244+ R = self .R ,
245+ r = self .r ,
246+ thetas = self .thetas ,
247+ origin = self .origin ,
248+ orientation = self .orientation ,
249+ noise = noise
250+ )
251+ return noisy_shape
252+
220253 def plot (self , ** kwargs ) -> Tuple ["matplotlib.matplotlib.Figure" , "matplotlib.axes._axes.Axes" ]:
221254 """
222255 Plot the shape and return the associated matplotlib Figure and Axes objects.
@@ -642,12 +675,19 @@ def _calculate_path(self) -> None:
642675 self .x , self .y = _apply_rotation (self .x , self .y , self .orientation )
643676 self .x += self .origin [0 ]
644677 self .y += self .origin [1 ]
678+ if self .noise is None :
679+ self .noise = [
680+ np .zeros (len (self .x )),
681+ np .zeros (len (self .y ))
682+ ]
683+ # self.noise = _apply_rotation(self.noise[0], self.noise[1], self.orientation)
684+ self .x += self .noise [0 ]
685+ self .y += self .noise [1 ]
645686 self .min_x = min (self .x )
646687 self .max_x = max (self .x )
647688 self .min_y = min (self .y )
648689 self .max_y = max (self .y )
649-
650- self .coords = list (zip (self .x , self .y , self .thetas ))
690+ self .coords = list (zip (self .x + self .noise [0 ], self .y + self .noise [1 ], self .thetas ))
651691
652692 def _validate_inputs (self ) -> None :
653693 """Validate input parameters"""
@@ -796,7 +836,7 @@ def _draw_circle(
796836 y: The y-coordinate of the center of the circle.
797837 radius: The radius of the circle to be drawn.
798838
799- The circle drawn, uses steps = 200 that defines the smoothness of the circle.
839+ The circle drawn, uses steps = 200 that defines the smoothness of the circle.
800840 """
801841 t .up ()
802842 t .seth (0 )
0 commit comments