e2D 1.0.6__py3-none-any.whl → 1.1.1__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
e2D/__init__.py CHANGED
@@ -7,26 +7,77 @@ HALF_PI = PI/2
7
7
  QUARTER_PI = PI/4
8
8
  DOUBLE_PI = PI*2
9
9
 
10
+ # regular expression to remove comments:
11
+ # """([\s\S]*?)"""
12
+
13
+ #
10
14
 
11
15
  class Vector2D:
12
- def __init__(self, x:int|float=0, y:int|float=0) -> None:
16
+ def __init__(self:"V2|Vector2D", x:int|float=0, y:int|float=0) -> None:
17
+ """
18
+ # Initialize a 2D vector with the specified x and y components.
19
+
20
+ ## Parameters:
21
+ x (int | float, optional): The x-component of the vector. Default is 0.
22
+ y (int | float, optional): The y-component of the vector. Default is 0.
23
+
24
+ ## Example:
25
+ vector1 = Vector2D() # Creates a vector with x=0 and y=0
26
+ vector2 = Vector2D(3, -2.5) # Creates a vector with x=3 and y=-2.5
27
+
28
+ ## Explanation:
29
+ This constructor initializes a 2D vector with the specified x and y components.
30
+
31
+ If no arguments are provided, the default values for x and y are both set to 0.
32
+
33
+ The x and y components can be integers or floating-point numbers.
34
+
35
+ Example usage is shown in the "Example" section above.
36
+ """
13
37
  self.x = x
14
38
  self.y = y
39
+
40
+ def set(self:"V2|Vector2D", x:int|float=0, y:int|float=0) -> None:
41
+ """
42
+ # Change the components of the Vector2D other without creating a new one.
43
+
44
+ ## Parameters:
45
+ x (int | float, optional): The new x-component to set. Default is 0.
46
+ y (int | float, optional): The new y-component to set. Default is 0.
47
+
48
+ ## Example:
49
+ vector = Vector2D(1, 2)
50
+ vector.set(3, -4)
51
+ print(vector.x, vector.y) # Output: 3, -4
52
+
53
+ ## Explanation:
54
+ The method updates the x and y components of the Vector2D other to the specified values.
55
+
56
+ If no arguments are provided, the default values for x and y are both set to 0.
57
+
58
+ The x and y components can be integers or floating-point numbers.
15
59
 
16
- def distance_to(self, object:"float|int|Vector2D|V2|list|tuple", squared:bool=True) -> int|float:
60
+ The method does not return any value, but it modifies the Vector2D other in place.
61
+
62
+ Example usage is shown in the "Example" section above.
63
+ """
64
+ self.x = x
65
+ self.y = y
66
+
67
+ def distance_to(self:"V2|Vector2D", other:"float|int|Vector2D|V2|list|tuple", squared:bool=True) -> int|float:
17
68
  """
18
- # Calculate the distance between the current Vector2D object and another object.
69
+ # Calculate the distance between the current Vector2D other and another other.
19
70
 
20
- # Parameters:
21
- object (float or int or Vector2D or list|tuple): The other object to which the distance is calculated.
71
+ ## Parameters:
72
+ other (float or int or Vector2D or list|tuple): The other other to which the distance is calculated.
22
73
  squared (bool, optional): If True, return the squared distance. If False, return the actual distance.
23
74
  Default is True.
24
75
 
25
- # Returns:
26
- int|float: The squared distance between the current Vector2D object and the other object if `squared` is True,
76
+ ## Returns:
77
+ int|float: The squared distance between the current Vector2D other and the other other if `squared` is True,
27
78
  otherwise the actual distance.
28
79
 
29
- # Example:
80
+ ## Example:
30
81
  point1 = Vector2D(0, 0)
31
82
 
32
83
  point2 = Vector2D(3, 4)
@@ -41,27 +92,27 @@ class Vector2D:
41
92
 
42
93
  This will calculate the squared and actual distances between the two points.
43
94
 
44
- # Explanation:
45
- The function calculates the squared distance between the current Vector2D object (self) and another object
46
- (object) using the formula: (self.x - object.x)**2 + (self.y - object.y)**2.
95
+ ## Explanation:
96
+ The function calculates the squared distance between the current Vector2D other (self) and another other
97
+ (other) using the formula: (self.x - other.x)**2 + (self.y - other.y)**2.
47
98
 
48
99
  The result is returned as the squared distance if `squared` is True, or as the actual distance if `squared` is False.
49
100
  """
50
- object = self.__normalize__(object)
51
- d = (self.x - object.x)**2 + (self.y - object.y)**2
101
+ other = self.__normalize__(other)
102
+ d = (self.x - other.x)**2 + (self.y - other.y)**2
52
103
  return (d**(1/2) if squared else d)
53
104
 
54
- def angle_to(self, object:"float|int|Vector2D|V2|list|tuple") -> int|float:
105
+ def angle_to(self:"V2|Vector2D", other:"float|int|Vector2D|V2|list|tuple") -> int|float:
55
106
  """
56
- # Calculate the angle between the current Vector2D object and another object.
107
+ # Calculate the angle between the current Vector2D other and another other.
57
108
 
58
- # Parameters:
59
- object (float or int or Vector2D or list|tuple): The other object to which the angle is calculated.
109
+ ## Parameters:
110
+ other (float or int or Vector2D or list|tuple): The other other to which the angle is calculated.
60
111
 
61
- # Returns:
62
- int|float: The angle in radians between the current Vector2D object and the other object.
112
+ ## Returns:
113
+ int|float: The angle in radians between the current Vector2D other and the other other.
63
114
 
64
- # Example:
115
+ ## Example:
65
116
  point1 = Vector2D(0, 0)
66
117
 
67
118
  point2 = Vector2D(1, 1)
@@ -72,27 +123,27 @@ class Vector2D:
72
123
 
73
124
  This will calculate the angle in radians between the two points.
74
125
 
75
- # Explanation:
76
- The function calculates the angle in radians between the current Vector2D object (self) and another object
77
- (object) using the `atan2` function from the `math` module.
126
+ ## Explanation:
127
+ The function calculates the angle in radians between the current Vector2D other (self) and another other
128
+ (other) using the `atan2` function from the `math` module.
78
129
 
79
130
  The result is returned as the angle in radians.
80
131
  """
81
- object = self.__normalize__(object)
82
- return _mt.atan2(object.y - self.y, object.x - self.x)
132
+ other = self.__normalize__(other)
133
+ return _mt.atan2(other.y - self.y, other.x - self.x)
83
134
 
84
- def point_from_degs(self, degs:int|float, radius:int|float) -> "Vector2D|V2":
135
+ def point_from_degs(self:"V2|Vector2D", degs:int|float, radius:int|float) -> "Vector2D|V2":
85
136
  """
86
137
  # Calculate a new Vector2D point from the current point based on an angle in degs and a radius.
87
138
 
88
- # Parameters:
139
+ ## Parameters:
89
140
  rad (int|float): The angle in degs.
90
141
  radius (int|float): The distance from the current point.
91
142
 
92
- # Returns:
143
+ ## Returns:
93
144
  Vector2D: A new Vector2D point calculated from the current point.
94
145
 
95
- # Example:
146
+ ## Example:
96
147
  point1 = Vector2D(0, 0)
97
148
 
98
149
  angle = 45
@@ -105,7 +156,7 @@ class Vector2D:
105
156
 
106
157
  This will calculate a new point 5 units away from point1 at a 45-degree angle.
107
158
 
108
- # Explanation:
159
+ ## Explanation:
109
160
  The function calculates a new Vector2D point based on an angle in degs (degs) and a distance (radius)
110
161
  from the current Vector2D point.
111
162
 
@@ -118,18 +169,18 @@ class Vector2D:
118
169
  y = radius * _mt.sin(_mt.radians(degs)) + self.y
119
170
  return Vector2D(x, y)
120
171
 
121
- def point_from_rads(self, rad:int|float, radius:int|float) -> "Vector2D|V2":
172
+ def point_from_rads(self:"V2|Vector2D", rad:int|float, radius:int|float) -> "Vector2D|V2":
122
173
  """
123
174
  # Calculate a new Vector2D point from the current point based on an angle in radians and a radius.
124
175
 
125
- # Parameters:
176
+ ## Parameters:
126
177
  rad (int|float): The angle in radians.
127
178
  radius (int|float): The distance from the current point.
128
179
 
129
- # Returns:
180
+ ## Returns:
130
181
  Vector2D: A new Vector2D point calculated from the current point.
131
182
 
132
- # Example:
183
+ ## Example:
133
184
  point1 = Vector2D(0, 0)
134
185
 
135
186
  angle = 45
@@ -142,7 +193,7 @@ class Vector2D:
142
193
 
143
194
  This will calculate a new point 5 units away from point1 at a 45-degree angle.
144
195
 
145
- # Explanation:
196
+ ## Explanation:
146
197
  The function calculates a new Vector2D point based on an angle in radians (rad) and a distance (radius)
147
198
  from the current Vector2D point.
148
199
 
@@ -155,40 +206,40 @@ class Vector2D:
155
206
  y = radius * _mt.sin(rad) + self.y
156
207
  return Vector2D(x, y)
157
208
 
158
- def copy(self) -> "Vector2D|V2":
209
+ def copy(self:"V2|Vector2D") -> "Vector2D|V2":
159
210
  """
160
- # Create a copy of the current Vector2D object.
211
+ # Create a copy of the current Vector2D other.
161
212
 
162
- # Returns:
163
- Vector2D: A new Vector2D object with the same x and y coordinates as the current object.
213
+ ## Returns:
214
+ Vector2D: A new Vector2D other with the same x and y coordinates as the current other.
164
215
 
165
- # Example:
216
+ ## Example:
166
217
  point1 = Vector2D(1, 2)
167
218
 
168
219
  point2 = point1.copy()
169
220
 
170
221
  print(point2.x, point2.y)
171
222
 
172
- This will print the x and y coordinates of the copied Vector2D object (1, 2).
223
+ This will print the x and y coordinates of the copied Vector2D other (1, 2).
173
224
 
174
- # Explanation:
175
- The function creates a new Vector2D object with the same x and y coordinates as the current object.
225
+ ## Explanation:
226
+ The function creates a new Vector2D other with the same x and y coordinates as the current other.
176
227
 
177
- The result is returned as a new Vector2D object, effectively making a copy of the original object.
228
+ The result is returned as a new Vector2D other, effectively making a copy of the original other.
178
229
  """
179
230
  return Vector2D(self.x, self.y)
180
231
 
181
- def absolute_round(self, n=1) -> "Vector2D|V2":
232
+ def absolute_round(self:"V2|Vector2D", n=1) -> "Vector2D|V2":
182
233
  """
183
- # Perform an "absolute round" operation on the Vector2D object.
234
+ # Perform an "absolute round" operation on the Vector2D other.
184
235
 
185
- # Parameters:
236
+ ## Parameters:
186
237
  n (int|float, optional): The numeric value to scale the "absolute rounded" vector. Default is 1.
187
238
 
188
- # Returns:
189
- Vector2D: The "absolute rounded" Vector2D object scaled by the provided numeric value.
239
+ ## Returns:
240
+ Vector2D: The "absolute rounded" Vector2D other scaled by the provided numeric value.
190
241
 
191
- # Example:
242
+ ## Example:
192
243
  vector1 = Vector2D(3.3, -4.7)
193
244
 
194
245
  result1 = vector1.absolute_round(0.5)
@@ -201,15 +252,15 @@ class Vector2D:
201
252
 
202
253
  print(result2.x, result2.y)
203
254
 
204
- # Explanation:
205
- The function performs an "absolute round" operation on the Vector2D object.
255
+ ## Explanation:
256
+ The function performs an "absolute round" operation on the Vector2D other.
206
257
 
207
- The "absolute round" operation involves taking the absolute values of both the x and y components of the Vector2D object,
258
+ The "absolute round" operation involves taking the absolute values of both the x and y components of the Vector2D other,
208
259
  and then scaling the resulting vector by the provided numeric value (n).
209
260
 
210
261
  The default value of n is 1, which means the "absolute rounded" vector will have the same magnitude as the original vector.
211
262
 
212
- If the provided numeric value (n) is 0, the function returns a Vector2D object with zeros for both components.
263
+ If the provided numeric value (n) is 0, the function returns a Vector2D other with zeros for both components.
213
264
 
214
265
  If the provided numeric value (n) is negative, the resulting "absolute rounded" vector will point in the opposite direction
215
266
  as the original vector but will have the same magnitude.
@@ -220,17 +271,17 @@ class Vector2D:
220
271
  s_abs = abs(self)
221
272
  return self.no_zero_div_error(s_abs, "zero") * n
222
273
 
223
- def floor(self, n:int|float=1) -> "Vector2D|V2":
274
+ def floor(self:"V2|Vector2D", n:int|float=1) -> "Vector2D|V2":
224
275
  """
225
- # Round down the components of the Vector2D object to the nearest integer or the specified numeric value.
276
+ # Round down the components of the Vector2D other to the nearest integer or the specified numeric value.
226
277
 
227
- # Parameters:
278
+ ## Parameters:
228
279
  n (int|float, optional): The numeric value to round down the components. Default is 1.
229
280
 
230
- # Returns:
231
- Vector2D: A new Vector2D object with the components rounded down to the nearest integer or the specified numeric value.
281
+ ## Returns:
282
+ Vector2D: A new Vector2D other with the components rounded down to the nearest integer or the specified numeric value.
232
283
 
233
- # Example:
284
+ ## Example:
234
285
  vector1 = Vector2D(3.3, 4.7)
235
286
 
236
287
  result1 = vector1.floor()
@@ -243,15 +294,15 @@ class Vector2D:
243
294
 
244
295
  print(result2.x, result2.y)
245
296
 
246
- # Explanation:
247
- The function rounds down the components of the Vector2D object to the nearest integer or the specified numeric value.
297
+ ## Explanation:
298
+ The function rounds down the components of the Vector2D other to the nearest integer or the specified numeric value.
248
299
 
249
- If the provided numeric value (n) is positive, the components of the resulting Vector2D object will be rounded down to
300
+ If the provided numeric value (n) is positive, the components of the resulting Vector2D other will be rounded down to
250
301
  the nearest multiple of the provided numeric value.
251
302
 
252
303
  If the provided numeric value (n) is negative, the function behaves the same as when n is positive.
253
304
 
254
- If the provided numeric value (n) is 0, the function returns a Vector2D object with zeros for both components.
305
+ If the provided numeric value (n) is 0, the function returns a Vector2D other with zeros for both components.
255
306
 
256
307
  If the provided numeric value (n) is not an integer, it will be converted to an integer before performing the rounding.
257
308
 
@@ -260,17 +311,17 @@ class Vector2D:
260
311
  """
261
312
  return self.__floor__(n)
262
313
 
263
- def ceil(self, n:int|float=1) -> "Vector2D|V2":
314
+ def ceil(self:"V2|Vector2D", n:int|float=1) -> "Vector2D|V2":
264
315
  """
265
- # Round up the components of the Vector2D object to the nearest integer or the specified numeric value.
316
+ # Round up the components of the Vector2D other to the nearest integer or the specified numeric value.
266
317
 
267
- # Parameters:
318
+ ## Parameters:
268
319
  n (int|float, optional): The numeric value to round up the components. Default is 1.
269
320
 
270
- # Returns:
271
- Vector2D: A new Vector2D object with the components rounded up to the nearest integer or the specified numeric value.
321
+ ## Returns:
322
+ Vector2D: A new Vector2D other with the components rounded up to the nearest integer or the specified numeric value.
272
323
 
273
- # Example:
324
+ ## Example:
274
325
  vector1 = Vector2D(3.3, 4.7)
275
326
 
276
327
  result1 = vector1.ceil()
@@ -283,15 +334,15 @@ class Vector2D:
283
334
 
284
335
  print(result2.x, result2.y)
285
336
 
286
- # Explanation:
287
- The function rounds up the components of the Vector2D object to the nearest integer or the specified numeric value.
337
+ ## Explanation:
338
+ The function rounds up the components of the Vector2D other to the nearest integer or the specified numeric value.
288
339
 
289
- If the provided numeric value (n) is positive, the components of the resulting Vector2D object will be rounded up to
340
+ If the provided numeric value (n) is positive, the components of the resulting Vector2D other will be rounded up to
290
341
  the nearest multiple of the provided numeric value.
291
342
 
292
343
  If the provided numeric value (n) is negative, the function behaves the same as when n is positive.
293
344
 
294
- If the provided numeric value (n) is 0, the function returns a Vector2D object with zeros for both components.
345
+ If the provided numeric value (n) is 0, the function returns a Vector2D other with zeros for both components.
295
346
 
296
347
  If the provided numeric value (n) is not an integer, it will be converted to an integer before performing the rounding.
297
348
 
@@ -304,7 +355,7 @@ class Vector2D:
304
355
  """
305
356
  # Generate a random Vector2D point within the specified range.
306
357
 
307
- # Parameters:
358
+ ## Parameters:
308
359
  start (int|float or Vector2D or None, optional): The starting point of the range.
309
360
  Default is None, which corresponds to (0, 0).
310
361
  If numeric, both x and y will have the same value.
@@ -312,24 +363,24 @@ class Vector2D:
312
363
  Default is None, which corresponds to (1, 1).
313
364
  If numeric, both x and y will have the same value.
314
365
 
315
- # Returns:
366
+ ## Returns:
316
367
  Vector2D: A new random Vector2D point within the specified range.
317
368
 
318
- # Example:
369
+ ## Example:
319
370
  random_point = randomize(Vector2D(10, 20), Vector2D(50, 70))
320
371
 
321
372
  print(random_point.x, random_point.y)
322
373
 
323
374
  This will print a random point between (10, 20) and (50, 70).
324
375
 
325
- # Explanation:
376
+ ## Explanation:
326
377
  The function generates a random Vector2D point within the specified range defined by `start` and `end`.
327
378
 
328
379
  If `start` and `end` are numeric values (int or float), both x and y coordinates will have the same value.
329
380
 
330
381
  If `start` and `end` are None, the default range is assumed to be (0, 0) to (1, 1).
331
382
 
332
- The function first checks if `start` and `end` are Vector2D objects. If not, it creates new Vector2D objects
383
+ The function first checks if `start` and `end` are Vector2D others. If not, it creates new Vector2D others
333
384
  based on the numeric values provided or the default values.
334
385
 
335
386
  It then generates random x and y coordinates in the range [0, 1) using the `random()` function from the `random` module.
@@ -345,17 +396,17 @@ class Vector2D:
345
396
  else: raise Exception(f"\nArg end must be in [Vector2D, int, float, tuple, list] not a [{type(end)}]\n")
346
397
  return start + Vector2D(_rnd.random(), _rnd.random()) * (end - start)
347
398
 
348
- def mid_point_to(self, *objects) -> float:
399
+ def mid_point_to(self:"V2|Vector2D", *others) -> float:
349
400
  """
350
- # Calculate the midpoint between the current Vector2D object and one or more other Vector2D objects.
401
+ # Calculate the midpoint between the current Vector2D other and one or more other Vector2D others.
351
402
 
352
- # Parameters:
353
- *objects (Vector2D): Variable number of Vector2D objects representing other points.
403
+ ## Parameters:
404
+ *others (Vector2D): Variable number of Vector2D others representing other points.
354
405
 
355
- # Returns:
356
- Vector2D: A new Vector2D object representing the midpoint.
406
+ ## Returns:
407
+ Vector2D: A new Vector2D other representing the midpoint.
357
408
 
358
- # Example:
409
+ ## Example:
359
410
  point1 = Vector2D(1, 2)
360
411
 
361
412
  point2 = Vector2D(3, 4)
@@ -366,122 +417,326 @@ class Vector2D:
366
417
 
367
418
  This will print the midpoint between point1 and point2.
368
419
 
369
- # Explanation:
370
- The function calculates the midpoint between the current Vector2D object (self)
371
- and one or more other Vector2D objects (provided as *objects).
420
+ ## Explanation:
421
+ The function calculates the midpoint between the current Vector2D other (self)
422
+ and one or more other Vector2D others (provided as *others).
372
423
 
373
- It first sums up all the Vector2D objects (including self) and then divides the sum by
374
- the total number of points (len(objects) + 1) to find the average point, which represents the midpoint.
424
+ It first sums up all the Vector2D others (including self) and then divides the sum by
425
+ the total number of points (len(others) + 1) to find the average point, which represents the midpoint.
375
426
 
376
- The result is returned as a new Vector2D object.
427
+ The result is returned as a new Vector2D other.
428
+ """
429
+ return sum(list(others) + [self]) / (len(others)+1)
430
+
431
+ def dot_product(self, other:"float|int|Vector2D|V2|list|tuple") -> float:
432
+ other = self.__normalize__(other)
377
433
  """
378
- return sum(list(objects) + [self]) / (len(objects)+1)
434
+ # Calculate the dot product of the current vector with another vector.
435
+
436
+ ## Parameters:
437
+ other (Vector2D): The other vector for the dot product calculation.
379
438
 
380
- # Vector2D(x,y) | [(Vector2D(x1,y1), Vector2D(x2,y2)), (Vector2D(x3,y3), Vector2D(x4,y4))]
381
- def inter_points(self:"Vector2D|V2", self_final_point:"Vector2D|V2", lines:list[tuple["Vector2D|V2", "Vector2D|V2"]], sort:bool=False, return_empty:bool=False) -> list["Vector2D|V2|None"]:
439
+ ## Returns:
440
+ float: The dot product value.
441
+
442
+ ## Example:
443
+ v1 = Vector2D(2, 3)
444
+ v2 = Vector2D(4, -1)
445
+ result = v1.dot_product(v2)
446
+ print(result) # Output: 5
447
+
448
+ ## Explanation:
449
+ The dot product of two vectors (A and B) is given by the formula: dot_product = A.x * B.x + A.y * B.y
450
+
451
+ The method takes another vector (other) as input and returns the dot product value.
452
+
453
+ Example usage is shown in the "Example" section above.
382
454
  """
383
- # Calculate the intersection points between a ray and a list of line segments.
455
+ return self.x * other.x + self.y * other.y
456
+
457
+ def magnitude(self) -> float:
458
+ """
459
+ # Vector Magnitude (Length)
384
460
 
385
- # Parameters:
386
- self (Vector2D): The starting point of the ray.
387
- self_final_point (Vector2D): The ending point of the ray.
388
- lines (list[tuple[Vector2D, Vector2D]]): A list of line segments represented by tuples of two Vector2D points.
389
- sort (bool, optional): If True, sort the intersection points by their distance to the starting point (self).
390
- Default is False.
391
- return_empty (bool, optional): If True, include None in the result for lines with no intersection points.
392
- Default is False.
461
+ ## Returns:
462
+ float: The magnitude (length) of the vector.
393
463
 
394
- # Returns:
395
- list[Vector2D|None]: A list of intersection points as Vector2D objects.
396
- If return_empty is True, the list may also include None for lines without intersections.
464
+ ## Example:
465
+ v = Vector2D(3, 4)
466
+ magnitude_v = v.magnitude() # Calculate the magnitude of the vector (3, 4)
467
+ print(magnitude_v) # Output: 5.0
397
468
 
398
- # Example:
399
- point1 = Vector2D(1, 2)
469
+ ## Explanation:
470
+ This method calculates the magnitude (length) of the vector.
471
+ The magnitude of a 2D vector (x, y) is the square root of the sum of the squares of its components.
400
472
 
401
- point2 = Vector2D(3, 4)
473
+ The method uses the formula: magnitude = sqrt(x^2 + y^2).
474
+
475
+ The resulting magnitude is returned as a floating-point value.
476
+
477
+ Example usage is shown in the "Example" section above.
478
+ """
479
+ return (self.x ** 2 + self.y ** 2) ** .5
402
480
 
403
- lines = [(Vector2D(2, 1), Vector2D(2, 5)), (Vector2D(0, 3), Vector2D(5, 3))]
481
+ def normalize(self) -> "Vector2D":
482
+ """
483
+ # Vector Normalization
484
+
485
+ ## Returns:
486
+ Vector2D: A new vector with the same direction as the current vector but with a magnitude of 1.
404
487
 
405
- intersections = point1.inter_points(point2, lines)
488
+ ## Raises:
489
+ ValueError: If the magnitude of the current vector is zero (zero vector).
406
490
 
407
- print(intersections)
491
+ ## Example:
492
+ v = Vector2D(3, 4)
493
+ normalized_v = v.normalize() # Normalize the vector (3, 4)
494
+ print(normalized_v) # Output: (0.6, 0.8)
408
495
 
409
- # Explanation:
410
- The function calculates the intersection points between the ray defined by the starting point (self)
411
- and the ending point (self_final_point) and a list of line segments (lines).
496
+ ## Explanation:
497
+ This method calculates the normalized version of the current vector, which means a new vector with the same direction as the original but with a magnitude of 1.
412
498
 
413
- It uses the lineLineIntersect function to check for intersection between the ray and each line segment.
499
+ The method first calculates the magnitude of the current vector using the 'magnitude' method.
414
500
 
415
- If sort is True, the intersection points are sorted by their distance to the starting point (self).
501
+ If the magnitude is zero (zero vector), a ValueError is raised, as normalization is not defined for zero vectors.
416
502
 
417
- If return_empty is True, the function includes None in the result for lines without intersection points.
503
+ The normalized vector is obtained by dividing each component of the current vector by its magnitude.
418
504
 
419
- The function returns a list of intersection points as Vector2D objects.
505
+ The resulting normalized vector is returned.
506
+
507
+ Example usage is shown in the "Example" section above.
420
508
  """
421
- ray = self() + self_final_point() #type: ignore
422
- def lineLineIntersect(P0, P1, Q0, Q1) -> tuple[int|float, int|float] | None:
423
- d = (P1[0]-P0[0]) * (Q1[1]-Q0[1]) + (P1[1]-P0[1]) * (Q0[0]-Q1[0])
424
- if d == 0:
425
- return None
426
- t = ((Q0[0]-P0[0]) * (Q1[1]-Q0[1]) +
427
- (Q0[1]-P0[1]) * (Q0[0]-Q1[0])) / d
428
- u = ((Q0[0]-P0[0]) * (P1[1]-P0[1]) +
429
- (Q0[1]-P0[1]) * (P0[0]-P1[0])) / d
430
- if 0 <= t <= 1 and 0 <= u <= 1:
431
- return P1[0] * t + P0[0] * (1-t), P1[1] * t + P0[1] * (1-t)
432
- return None
433
- collisions = [Vector2D(*line) if line else None for line in [lineLineIntersect(line1[1](), line1[0](), ray[:2], ray[2:]) for line1 in lines] if line or return_empty]
434
- if sort:
435
- collisions.sort(key=lambda x: self.distance_to(x, False)) #type: ignore
436
- return collisions
509
+ mag = self.magnitude()
510
+ if mag == 0:
511
+ raise ValueError("Cannot normalize zero vector.")
512
+ return Vector2D(self.x / mag, self.y / mag)
513
+
514
+ def projection(self, other:"float|int|Vector2D|V2|list|tuple") -> "Vector2D|V2":
515
+ """
516
+ # Vector Projection
517
+
518
+ ## Parameters:
519
+ other (float, int, Vector2D, V2, list, tuple): The vector onto which to project.
520
+
521
+ ## Returns:
522
+ Vector2D or V2: The projection of the current vector onto the 'other' vector.
523
+
524
+ ## Raises:
525
+ ValueError: If 'other' is a zero vector.
526
+
527
+ ## Example:
528
+ v1 = Vector2D(3, 4)
529
+ v2 = Vector2D(1, 0)
530
+ projection_v = v1.projection(v2) # Calculate the projection of v1 onto v2
531
+ print(projection_v) # Output: (3.0, 0.0)
532
+
533
+ ## Explanation:
534
+ This method calculates the projection of the current vector onto the 'other' vector.
535
+ The projection is a vector that represents the component of the current vector in the direction of the 'other' vector.
437
536
 
438
- def normalize(self, max:int|float=1, min:int|float=0) -> "Vector2D|V2":
537
+ If 'other' is not a Vector2D instance, it will be converted to one using the '__normalize__' method.
538
+ The method first normalizes the 'other' vector using the '__normalize__' method of the vector.
539
+
540
+ Next, it calculates the dot product of the current vector and the normalized 'other' vector using the 'dot_product' method.
541
+ It also calculates the squared magnitude of the 'other' vector using the 'magnitude' method.
542
+
543
+ If the magnitude of 'other' is zero (a zero vector), a ValueError is raised, as projection is not defined for zero vectors.
544
+
545
+ The projection is then obtained by scaling the 'other' vector by the dot product divided by the squared magnitude.
546
+
547
+ The resulting projection vector is returned.
548
+
549
+ Example usage is shown in the "Example" section above.
550
+ """
551
+ other = self.__normalize__(other)
552
+ dot_product = self.dot_product(other)
553
+ magnitude_product = other.magnitude() ** 2
554
+ if magnitude_product == 0:
555
+ raise ValueError("Cannot calculate projection for zero vectors.")
556
+ return other * (dot_product / magnitude_product)
557
+
558
+ def reflection(self, normal:"float|int|Vector2D|V2|list|tuple") -> "Vector2D|V2":
439
559
  """
440
- # Normalize the Vector2D object to a new magnitude defined by max while preserving its direction.
560
+ # Vector Reflection
441
561
 
442
- # Parameters:
443
- max (int|float, optional): The new magnitude to which the Vector2D object will be scaled.
444
- Default is 1.
445
- min (int|float, optional): The minimum magnitude. If provided, the Vector2D object will not be scaled
446
- below this value. Default is 0.
562
+ ## Parameters:
563
+ normal (float, int, Vector2D, V2, list, tuple): The normal vector representing the surface of reflection.
447
564
 
448
- # Returns:
449
- Vector2D: A new Vector2D object with the scaled magnitude.
565
+ ## Returns:
566
+ Vector2D or V2: The reflected vector.
450
567
 
451
- # Example:
452
- vector = Vector2D(3, 4)
568
+ ## Example:
569
+ incident_vector = Vector2D(3, 4)
570
+ normal_vector = Vector2D(1, 0)
571
+ reflected_vector = incident_vector.reflection(normal_vector) # Calculate the reflection of the incident vector over the given normal
572
+ print(reflected_vector) # Output: (-3.0, 4.0)
453
573
 
454
- normalized_vector = vector.normalize(5, 2)
574
+ ## Explanation:
575
+ This method calculates the reflection of the current vector over the given normal vector.
576
+ The normal vector represents the surface of reflection, and it should be normalized (unit vector).
455
577
 
456
- print(normalized_vector.x, normalized_vector.y)
578
+ The method first normalizes the 'normal' vector using the '__normalize__' method of the vector.
579
+ Next, it calculates the projection of the current vector onto the 'normal' vector using the 'projection' method.
580
+ The reflected vector is obtained by subtracting twice the projection from the current vector.
457
581
 
458
- # Explanation:
459
- The function scales the Vector2D object to a new magnitude defined by max while preserving its direction.
582
+ The resulting reflected vector is returned.
460
583
 
461
- It first calculates the current magnitude of the Vector2D object using distance_to method.
584
+ Example usage is shown in the "Example" section above.
585
+ """
586
+ normal = self.__normalize__(normal)
587
+ projection = self.projection(normal)
588
+ return self - projection * 2
462
589
 
463
- If the current magnitude is not zero, it creates a new Vector2D object with magnitude max using
464
- point_from_degs method and the angle_to method to preserve the direction.
590
+ def cartesian_to_polar(self) -> tuple:
591
+ """
592
+ # Convert Cartesian Coordinates to Polar Coordinates
593
+
594
+ ## Returns:
595
+ tuple: A tuple containing the radial distance (magnitude) 'r' and the angle 'theta' in radians.
596
+
597
+ ## Example:
598
+ v = Vector2D(3, 4)
599
+ r, theta = v.cartesian_to_polar() # Convert Cartesian coordinates (3, 4) to polar
600
+ print(r, theta) # Output: (5.0, 0.9272952180016122)
601
+
602
+ ## Explanation:
603
+ This method converts Cartesian coordinates (x, y) to polar coordinates (r, theta).
604
+ 'r' is the radial distance (magnitude) from the origin to the point, and 'theta' is the angle
605
+ (in radians) measured from the positive x-axis to the point.
606
+
607
+ The method calculates the radial distance 'r' using the 'magnitude' method of the vector.
608
+ The angle 'theta' is calculated using the arctan2 function, which takes the y and x components of the vector.
609
+
610
+ The resulting 'r' and 'theta' are returned as a tuple.
611
+
612
+ Example usage is shown in the "Example" section above.
613
+ """
614
+ r = self.magnitude()
615
+ theta = _mt.atan2(self.y, self.x)
616
+ return r, theta
465
617
 
466
- If the current magnitude is zero, it returns a new zero vector (VectorZero.copy()).
618
+ @classmethod
619
+ def polar_to_cartesian(cls, r: float|int, theta: float|int) -> "Vector2D|V2":
467
620
  """
468
- return Vector2D(min, min).point_from_degs(Vector2D(min, min).angle_to(self), max) if Vector2D(min, min).distance_to(self) != 0 else VectorZero.copy()
621
+ # Convert Polar Coordinates to Cartesian Coordinates
622
+
623
+ ## Parameters:
624
+ r (float or int): The radial distance (magnitude) from the origin to the point.
625
+ theta (float or int): The angle (in radians or degrees) measured from the positive x-axis to the point.
626
+
627
+ ## Returns:
628
+ Vector2D or V2: A new vector representing the Cartesian coordinates (x, y) of the point.
629
+
630
+ ## Example:
631
+ cartesian_point = Vector2D.polar_to_cartesian(5, math.pi/4) # Convert polar coordinates (r=5, theta=45 degrees) to Cartesian
632
+ print(cartesian_point) # Output: (3.5355339059327378, 3.5355339059327373)
633
+
634
+ ## Explanation:
635
+ This class method converts polar coordinates (r, theta) to Cartesian coordinates (x, y).
636
+ 'r' is the radial distance (magnitude) from the origin to the point, and 'theta' is the angle
637
+ (in radians or degrees) measured from the positive x-axis to the point.
638
+
639
+ The method calculates the x and y components using trigonometric functions (cosine and sine) based on 'r' and 'theta'.
640
+
641
+ Example usage is shown in the "Example" section above.
642
+ """
643
+ x = r * _mt.cos(theta)
644
+ y = r * _mt.sin(theta)
645
+ return cls(x, y)
646
+
647
+ def lerp(self, other:"float|int|Vector2D|V2|list|tuple", t: float) -> "Vector2D|V2":
648
+ """
649
+ # Linear Interpolation (LERP)
650
+
651
+ ## Parameters:
652
+ other (float, int, Vector2D, V2, list, tuple): The vector to interpolate towards.
653
+ t (float): The interpolation parameter. Must be between 0 and 1.
654
+
655
+ ## Returns:
656
+ Vector2D or V2: The result of the linear interpolation.
657
+
658
+ ## Raises:
659
+ ValueError: If t is not within the range [0, 1].
660
+
661
+ ## Example:
662
+ v1 = Vector2D(1, 2)
663
+ v2 = Vector2D(5, 7)
664
+ interpolated_v = v1.lerp(v2, 0.5) # Linearly interpolate between v1 and v2 with t = 0.5
665
+ print(interpolated_v) # Output: (3.0, 4.5)
666
+
667
+ ## Explanation:
668
+ This method performs linear interpolation between the current vector and the 'other' vector.
669
+ The 't' parameter represents the interpolation parameter, which controls how much the interpolation
670
+ leans towards the 'other' vector. When 't' is 0, the result will be equal to the current vector (self).
671
+ When 't' is 1, the result will be equal to the 'other' vector. For intermediate values of 't', the
672
+ result will be a linear combination of the two vectors, smoothly transitioning between them.
673
+
674
+ If 'other' is not a Vector2D instance, it will be converted to one using the '__normalize__' method.
675
+ If 't' is not within the range [0, 1], a ValueError is raised.
676
+
677
+ Example usage is shown in the "Example" section above.
678
+ """
679
+ other = self.__normalize__(other)
680
+ if not 0 <= t <= 1:
681
+ raise ValueError("t must be between 0 and 1 for linear interpolation.")
682
+ return Vector2D(self.x + (other.x - self.x) * t, self.y + (other.y - self.y) * t)
683
+
684
+ def rotate(self, angle: int|float, center:"float|int|Vector2D|V2|list|tuple|None"=None) -> "Vector2D|V2":
685
+ """
686
+ # Rotate the vector by a given angle around the origin or a specified center.
687
+
688
+ ## Parameters:
689
+ angle (int or float): The angle of rotation in radians or degrees, depending on the trigonometric functions used.
690
+ center (float, int, Vector2D, V2, list, tuple, or None): The center of rotation.
691
+ If None, the vector is rotated around the origin (0, 0).
692
+
693
+ ## Returns:
694
+ Vector2D or V2: The rotated vector.
695
+
696
+ ## Example:
697
+ v = Vector2D(3, 4)
698
+ rotated_v = v.rotate(math.pi / 4) # Rotate 45 degrees around the origin
699
+ print(rotated_v) # Output: (0.7071067811865476, 5.656854249492381)
700
+
701
+ center = Vector2D(1, 1)
702
+ rotated_v = v.rotate(math.pi / 4, center) # Rotate 45 degrees around the center (1, 1)
703
+ print(rotated_v) # Output: (1.7071067811865475, 2.656854249492381)
704
+
705
+ ## Explanation:
706
+ This method rotates the vector by the specified angle around the given center.
707
+ If no center is provided, the vector is rotated around the origin (0, 0).
708
+
709
+ The method calculates the trigonometric functions (cosine and sine) of the angle to perform the rotation.
710
+ The translated vector is obtained by subtracting the center from the current vector.
711
+ The rotated vector is then obtained by applying the rotation transformation to the translated vector.
712
+ The center is added back to the rotated vector to obtain the final result.
713
+
714
+ Example usage is shown in the "Example" section above.
715
+ """
716
+ if center is None:
717
+ center = V2z
718
+ else:
719
+ center = self.__normalize__(center)
720
+ translated = self - center
721
+ cos_angle = _mt.cos(angle)
722
+ sin_angle = _mt.sin(angle)
723
+ return Vector2D(translated.x * cos_angle - translated.y * sin_angle, translated.x * sin_angle + translated.y * cos_angle) + center
469
724
 
470
725
  def no_zero_div_error(self:"Vector2D|V2", n:"int|float|Vector2D|V2", error_mode:str="zero") -> "Vector2D|V2":
471
726
  """
472
- # Handle division between the Vector2D object and a numeric value or another Vector2D object.
727
+ # Handle division between the Vector2D other and a numeric value or another Vector2D other.
473
728
 
474
- # Parameters:
475
- n (int|float or Vector2D): The numeric value or Vector2D object for division.
729
+ ## Parameters:
730
+ n (int|float or Vector2D): The numeric value or Vector2D other for division.
476
731
  error_mode (str, optional): The mode to handle division by zero scenarios.
477
- - "zero" (default): Return a Vector2D object with zeros for both components.
478
- - "null": Return a Vector2D object with the original x or y component if available,
732
+ - "zero" (default): Return a Vector2D other with zeros for both components.
733
+ - "null": Return a Vector2D other with the original x or y component if available,
479
734
  otherwise, return NaN (Not a Number) for the component.
480
735
 
481
- # Returns:
482
- Vector2D: A new Vector2D object after division or handling division by zero scenarios.
736
+ ## Returns:
737
+ Vector2D: A new Vector2D other after division or handling division by zero scenarios.
483
738
 
484
- # Example:
739
+ ## Example:
485
740
  vector1 = Vector2D(3, 4)
486
741
 
487
742
  result1 = vector1.no_zero_div_error(2)
@@ -494,21 +749,21 @@ class Vector2D:
494
749
 
495
750
  print(result2.x, result2.y)
496
751
 
497
- # Explanation:
498
- The function handles division between the Vector2D object and a numeric value or another Vector2D object.
752
+ ## Explanation:
753
+ The function handles division between the Vector2D other and a numeric value or another Vector2D other.
499
754
 
500
755
  If n is a numeric value (int or float):
501
- - If n is zero, the function returns a Vector2D object with zeros for both components if error_mode is "zero".
502
- - If error_mode is "null", the function returns a Vector2D object with the original x or y component if available,
756
+ - If n is zero, the function returns a Vector2D other with zeros for both components if error_mode is "zero".
757
+ - If error_mode is "null", the function returns a Vector2D other with the original x or y component if available,
503
758
  otherwise, return NaN (Not a Number) for the component.
504
759
 
505
- If n is a Vector2D object:
506
- - If n's x or y component is zero, the function returns a Vector2D object with zeros for the corresponding component
760
+ If n is a Vector2D other:
761
+ - If n's x or y component is zero, the function returns a Vector2D other with zeros for the corresponding component
507
762
  if error_mode is "zero".
508
- - If error_mode is "null", the function returns a Vector2D object with the original x or y component if available,
763
+ - If error_mode is "null", the function returns a Vector2D other with the original x or y component if available,
509
764
  otherwise, return NaN (Not a Number) for the component.
510
765
 
511
- If n is neither a numeric value nor a Vector2D object, the function raises an exception.
766
+ If n is neither a numeric value nor a Vector2D other, the function raises an exception.
512
767
  """
513
768
  if isinstance(n, int|float):
514
769
  if n == 0:
@@ -520,62 +775,95 @@ class Vector2D:
520
775
  else:
521
776
  raise Exception(f"\nArg n must be in [Vector2D, int, float, tuple, list] not a [{type(n)}]\n")
522
777
 
523
- def __str__(self) -> str:
778
+ def __str__(self:"V2|Vector2D") -> str:
524
779
  return f"{self.x}, {self.y}"
525
780
 
526
- def __sub__(self, object:"float|int|Vector2D|V2|list|tuple") -> "Vector2D|V2":
527
- object = self.__normalize__(object)
528
- return Vector2D(self.x - object.x, self.y - object.y)
781
+ def __sub__(self:"V2|Vector2D", other:"float|int|Vector2D|V2|list|tuple") -> "Vector2D|V2":
782
+ other = self.__normalize__(other)
783
+ return Vector2D(self.x - other.x, self.y - other.y)
529
784
 
530
- def __add__(self, object:"float|int|Vector2D|V2|list|tuple") -> "Vector2D|V2":
531
- object = self.__normalize__(object)
532
- return Vector2D(self.x + object.x, self.y + object.y)
785
+ def __add__(self:"V2|Vector2D", other:"float|int|Vector2D|V2|list|tuple") -> "Vector2D|V2":
786
+ other = self.__normalize__(other)
787
+ return Vector2D(self.x + other.x, self.y + other.y)
533
788
 
534
- def __mod__(self, object:"float|int|Vector2D|V2|list|tuple") -> "Vector2D|V2":
535
- object = self.__normalize__(object)
536
- return Vector2D(self.x % object.x, self.y % object.y)
789
+ def __mod__(self:"V2|Vector2D", other:"float|int|Vector2D|V2|list|tuple") -> "Vector2D|V2":
790
+ other = self.__normalize__(other)
791
+ return Vector2D(self.x % other.x, self.y % other.y)
537
792
 
538
- def __radd__(self, object:"float|int|Vector2D|V2|list|tuple") -> "Vector2D|V2":
539
- return self.__add__(object)
793
+ def __radd__(self:"V2|Vector2D", other:"float|int|Vector2D|V2|list|tuple") -> "Vector2D|V2":
794
+ return self.__add__(other)
540
795
 
541
- def __repr__(self) -> str:
796
+ def __repr__(self:"V2|Vector2D") -> str:
542
797
  return f"x:{self.x}\ty:{self.y}"
543
798
 
544
- def __call__(self, return_tuple=False) -> list|tuple:
799
+ def __call__(self:"V2|Vector2D", return_tuple=False) -> list|tuple:
545
800
  return (self.x, self.y) if return_tuple else [self.x, self.y]
546
801
 
547
- def __truediv__(self, object:"float|int|Vector2D|V2|list|tuple") -> "Vector2D|V2":
548
- object = self.__normalize__(object)
549
- return Vector2D(self.x / object.x, self.y / object.y)
802
+ def __truediv__(self:"V2|Vector2D", other:"float|int|Vector2D|V2|list|tuple") -> "Vector2D|V2":
803
+ other = self.__normalize__(other)
804
+ return Vector2D(self.x / other.x, self.y / other.y)
550
805
 
551
- def __floordiv__(self, object:"float|int|Vector2D|V2|list|tuple") -> "Vector2D|V2":
552
- object = self.__normalize__(object)
553
- return Vector2D(self.x // object.x, self.y // object.y)
806
+ def __floordiv__(self:"V2|Vector2D", other:"float|int|Vector2D|V2|list|tuple") -> "Vector2D|V2":
807
+ other = self.__normalize__(other)
808
+ return Vector2D(self.x // other.x, self.y // other.y)
809
+
810
+ def __iadd__(self:"V2|Vector2D", other:"float|int|Vector2D|V2|list|tuple") -> "Vector2D":
811
+ other = self.__normalize__(other)
812
+ self.x += other.x
813
+ self.y += other.y
814
+ return self
815
+
816
+ def __isub__(self:"V2|Vector2D", other:"float|int|Vector2D|V2|list|tuple") -> "Vector2D":
817
+ other = self.__normalize__(other)
818
+ self.x -= other.x
819
+ self.y -= other.y
820
+ return self
821
+
822
+ def __imul__(self:"V2|Vector2D", other:"float|int|Vector2D|V2|list|tuple") -> "Vector2D":
823
+ other = self.__normalize__(other)
824
+ self.x *= other.x
825
+ self.y *= other.y
826
+ return self
554
827
 
555
- def __abs__(self) -> "Vector2D|V2":
828
+ def __itruediv__(self:"V2|Vector2D", other:"float|int|Vector2D|V2|list|tuple") -> "Vector2D":
829
+ other = self.__normalize__(other)
830
+ self.x /= other.x
831
+ self.y /= other.y
832
+ return self
833
+
834
+ def __eq__(self, other) -> bool:
835
+ if not isinstance(other, Vector2D|V2|list|tuple):
836
+ return False
837
+ other = self.__normalize__(other)
838
+ return self.x == other.x and self.y == other.y
839
+
840
+ def __ne__(self, other) -> bool:
841
+ return not self.__eq__(other)
842
+
843
+ def __abs__(self:"V2|Vector2D") -> "Vector2D|V2":
556
844
  return Vector2D(abs(self.x), abs(self.y))
557
845
 
558
- def __round__(self, n:int|float=1) -> "Vector2D|V2":
846
+ def __round__(self:"V2|Vector2D", n:int|float=1) -> "Vector2D|V2":
559
847
  return Vector2D(round(self.x / n) * n, round(self.y / n) * n)
560
848
 
561
- def __floor__(self, n:int|float=1) -> "Vector2D|V2":
849
+ def __floor__(self:"V2|Vector2D", n:int|float=1) -> "Vector2D|V2":
562
850
  return Vector2D(_mt.floor(self.x / n) * n, _mt.floor(self.y / n) * n)
563
851
 
564
- def __ceil__(self, n:int|float=1) -> "Vector2D|V2":
852
+ def __ceil__(self:"V2|Vector2D", n:int|float=1) -> "Vector2D|V2":
565
853
  return Vector2D(_mt.ceil(self.x / n) * n, _mt.ceil(self.y / n) * n)
566
854
 
567
- def __mul__(self, object:"float|int|Vector2D|V2|list|tuple") -> "Vector2D|V2":
568
- object = self.__normalize__(object)
569
- return Vector2D(self.x * object.x, self.y * object.y)
855
+ def __mul__(self:"V2|Vector2D", other:"float|int|Vector2D|V2|list|tuple") -> "Vector2D|V2":
856
+ other = self.__normalize__(other)
857
+ return Vector2D(self.x * other.x, self.y * other.y)
570
858
 
571
- def __pow__(self, object:"float|int|Vector2D|V2|list|tuple") -> "Vector2D|V2":
572
- object = self.__normalize__(object)
573
- return Vector2D(self.x ** object.x, self.y ** object.y)
859
+ def __pow__(self:"V2|Vector2D", other:"float|int|Vector2D|V2|list|tuple") -> "Vector2D|V2":
860
+ other = self.__normalize__(other)
861
+ return Vector2D(self.x ** other.x, self.y ** other.y)
574
862
 
575
- def __float__(self) -> "Vector2D|V2":
863
+ def __float__(self:"V2|Vector2D") -> "Vector2D|V2":
576
864
  return Vector2D(float(self.x), float(self.y))
577
865
 
578
- def __getitem__(self, n) -> int|float:
866
+ def __getitem__(self:"V2|Vector2D", n) -> int|float:
579
867
  if n in [0, "x"]:
580
868
  return self.x
581
869
  elif n in [1, "y"]:
@@ -583,18 +871,40 @@ class Vector2D:
583
871
  else:
584
872
  raise IndexError("V2 has only x,y...")
585
873
 
586
- def __normalize__(self, object) -> "Vector2D|V2":
587
- if not isinstance(object, Vector2D):
588
- if isinstance(object, int|float):
589
- return Vector2D(object, object)
590
- elif isinstance(object, list|tuple):
591
- return Vector2D(*object[:2])
874
+ def __normalize__(self:"V2|Vector2D", other) -> "Vector2D|V2":
875
+ if not isinstance(other, Vector2D):
876
+ if isinstance(other, int|float):
877
+ return Vector2D(other, other)
878
+ elif isinstance(other, list|tuple):
879
+ return Vector2D(*other[:2])
592
880
  else:
593
- raise TypeError(f"The value {object} is not a num type: [{int|float}] nor an array type: [{list|tuple}]")
594
- return object
881
+ raise TypeError(f"The value {other} is not a num type: [{int|float}] nor an array type: [{list|tuple}]")
882
+ return other
595
883
 
596
884
  class V2(Vector2D):
597
- def __init__(self, x: int|float = 0, y: int|float = 0) -> None:
885
+ def __init__(self:"V2|Vector2D", x: int|float = 0, y: int|float = 0) -> None:
886
+ """
887
+ # Initialize a 2D vector (V2) with the specified x and y components.
888
+
889
+ ## Parameters:
890
+ x (int | float, optional): The x-component of the vector. Default is 0.
891
+ y (int | float, optional): The y-component of the vector. Default is 0.
892
+
893
+ ## Example:
894
+ vector1 = V2() # Creates a V2 other with x=0 and y=0
895
+ vector2 = V2(3, -2.5) # Creates a V2 other with x=3 and y=-2.5
896
+
897
+ ## Explanation:
898
+ This class is an alias for the Vector2D class, with the benefit of using a shorter name (V2).
899
+
900
+ The constructor initializes a V2 other with the specified x and y components.
901
+
902
+ If no arguments are provided, the default values for x and y are both set to 0.
903
+
904
+ The x and y components can be integers or floating-point numbers.
905
+
906
+ Example usage is shown in the "Example" section above.
907
+ """
598
908
  super().__init__(x, y)
599
909
 
600
910
  V2inf = Vector2D(float('inf'), float('inf'))
@@ -608,7 +918,7 @@ def color_fade(starting_c:list|tuple, final_c:list|tuple, index:int|float, max_i
608
918
  """
609
919
  # Calculate the color at a specific index of a color fade between two given colors.
610
920
 
611
- # Parameters:
921
+ ## Parameters:
612
922
  starting_c (tuple or list): The RGB values of the starting color as a tuple or list.
613
923
  final_c (tuple or list): The RGB values of the final color as a tuple or list.
614
924
  index (int or float): The current index of the color fade, representing a position
@@ -616,10 +926,10 @@ def color_fade(starting_c:list|tuple, final_c:list|tuple, index:int|float, max_i
616
926
  max_index (int or float): The maximum index of the color fade, indicating the endpoint
617
927
  position between the starting and final colors.
618
928
 
619
- # Returns:
929
+ ## Returns:
620
930
  tuple: The RGB values of the color at the specified index as a tuple.
621
931
 
622
- # Example:
932
+ ## Example:
623
933
  starting_c = (255, 0, 0)
624
934
 
625
935
  final_c = (0, 0, 255)
@@ -640,14 +950,14 @@ def weighted_color_fade(colors_dict:dict) -> tuple:
640
950
  """
641
951
  # Calculate the weighted color based on a dictionary of colors and their corresponding weights.
642
952
 
643
- # Parameters:
953
+ ## Parameters:
644
954
  colors_dict (dict): A dictionary where keys represent RGB color values as tuples,
645
955
  and values represent the weights (floats) for each color.
646
956
 
647
- # Returns:
957
+ ## Returns:
648
958
  tuple: The RGB values of the calculated weighted color as a tuple.
649
959
 
650
- # Example:
960
+ ## Example:
651
961
  colors_dict = {
652
962
 
653
963
  (255, 255, 255): 0.1,
@@ -672,15 +982,15 @@ def angular_interpolation(starting_angle:int|float, final_angle:int|float, step:
672
982
  """
673
983
  # Perform angular interpolation between two angles using the shortest distance.
674
984
 
675
- # Parameters:
985
+ ## Parameters:
676
986
  starting_angle (int or float): The initial angle in radians.
677
987
  final_angle (int or float): The target angle in radians to interpolate towards.
678
988
  step (int or float, optional): The step size for interpolation in radians. Default is 0.1.
679
989
 
680
- # Returns:
990
+ ## Returns:
681
991
  float: The interpolated angle as a result of angular interpolation.
682
992
 
683
- # Example:
993
+ ## Example:
684
994
  starting_angle = 1.0
685
995
 
686
996
  final_angle = 5.0
@@ -691,7 +1001,7 @@ def angular_interpolation(starting_angle:int|float, final_angle:int|float, step:
691
1001
 
692
1002
  This will print the interpolated angle using angular interpolation.
693
1003
 
694
- # Explanation:
1004
+ ## Explanation:
695
1005
  The function calculates three distances between the `starting_angle` and the
696
1006
  `final_angle`. These distances represent possible angular interpolations:
697
1007
  1. The direct interpolation from `starting_angle` to `final_angle`.
@@ -714,17 +1024,17 @@ def color_distance(starting_c:list|tuple, final_c:list|tuple, sqrd:bool=True) ->
714
1024
  """
715
1025
  # Calculate the distance between two colors in RGB space.
716
1026
 
717
- # Parameters:
1027
+ ## Parameters:
718
1028
  starting_c (list or tuple): The RGB values of the starting color.
719
1029
  final_c (list or tuple): The RGB values of the final color.
720
1030
  sqrd (bool, optional): If True, return the squared distance. If False, return
721
1031
  the actual distance. Default is True.
722
1032
 
723
- # Returns:
1033
+ ## Returns:
724
1034
  float: The squared distance between the two colors if `sqrd` is True, otherwise
725
1035
  the actual distance.
726
1036
 
727
- # Example:
1037
+ ## Example:
728
1038
  starting_c = [255, 0, 0]
729
1039
 
730
1040
  final_c = [0, 255, 0]
@@ -739,7 +1049,7 @@ def color_distance(starting_c:list|tuple, final_c:list|tuple, sqrd:bool=True) ->
739
1049
 
740
1050
  This will calculate the squared and actual distances between the colors.
741
1051
 
742
- # Explanation:
1052
+ ## Explanation:
743
1053
  The function first calculates the squared distance between the two colors in RGB
744
1054
  space. It does this by computing the sum of the squared differences of the RGB
745
1055
  components for each color. The squared distance is obtained by taking the square
@@ -752,17 +1062,17 @@ def color_distance(starting_c:list|tuple, final_c:list|tuple, sqrd:bool=True) ->
752
1062
  distance = sum([(starting_c[i]-final_c[i])**2 for i in range(3)])
753
1063
  return (distance ** .5) if sqrd else distance
754
1064
 
755
- def avg_position(*objects:"Vector2D|V2") -> Vector2D|V2:
1065
+ def avg_position(*others:"Vector2D|V2") -> Vector2D|V2:
756
1066
  """
757
- # Calculate the average position for a variable number of Vector2D objects.
1067
+ # Calculate the average position for a variable number of Vector2D others.
758
1068
 
759
- # Parameters:
760
- *objects (Vector2D): Variable number of Vector2D objects representing positions.
1069
+ ## Parameters:
1070
+ *others (Vector2D): Variable number of Vector2D others representing positions.
761
1071
 
762
- # Returns:
763
- Vector2D: The average position as a new Vector2D object.
1072
+ ## Returns:
1073
+ Vector2D: The average position as a new Vector2D other.
764
1074
 
765
- # Example:
1075
+ ## Example:
766
1076
  position1 = Vector2D(10, 20)
767
1077
 
768
1078
  position2 = Vector2D(30, 40)
@@ -773,38 +1083,98 @@ def avg_position(*objects:"Vector2D|V2") -> Vector2D|V2:
773
1083
 
774
1084
  print(average_pos)
775
1085
 
776
- This will print the average position of the three Vector2D objects.
1086
+ This will print the average position of the three Vector2D others.
1087
+
1088
+ ## Explanation:
1089
+ The function takes a variable number of Vector2D others as input, representing positions.
1090
+ It calculates the sum of all the Vector2D others using the `sum` function and then divides
1091
+ it by the total number of others (length of `others`) to find the average position.
777
1092
 
778
- # Explanation:
779
- The function takes a variable number of Vector2D objects as input, representing positions.
780
- It calculates the sum of all the Vector2D objects using the `sum` function and then divides
781
- it by the total number of objects (length of `objects`) to find the average position.
1093
+ The result is returned as a new Vector2D other representing the average position.
1094
+ """
1095
+ return sum(others) / len(others) #type: ignore
782
1096
 
783
- The result is returned as a new Vector2D object representing the average position.
1097
+ def inter_points(ray:list["Vector2D|V2"]|tuple["Vector2D|V2", "Vector2D|V2"], lines:list[tuple["Vector2D|V2", "Vector2D|V2"]], return_inter_lines:bool=False, sort:bool=False, return_empty:bool=False) -> list[tuple[Vector2D | None, tuple[Vector2D | V2, Vector2D | V2]]] | list[Vector2D | None]:
784
1098
  """
785
- return sum(list(objects)) / (len(objects)) # type: ignore
1099
+ # Find intersection points between a ray or line segment and multiple line segments.
1100
+
1101
+ ## Parameters:
1102
+ ray (list[Vector2D|V2] | tuple[Vector2D|V2, Vector2D|V2]): The ray or line segment represented by two endpoints
1103
+ (start and end points).
1104
+ lines (list[tuple[Vector2D|V2, Vector2D|V2]]): A list of line segments represented by tuples of their endpoints.
1105
+ return_inter_lines (bool, optional): If True, return a list of tuples containing the intersection points and the
1106
+ corresponding intersecting line segment. Default is False.
1107
+ sort (bool, optional): If True, sort the intersection points by their distance from the ray's start point.
1108
+ Default is False.
1109
+ return_empty (bool, optional): If True, include None for line segments with no intersection. Default is False.
1110
+
1111
+ ## Returns:
1112
+ list[tuple[Vector2D | None, tuple[Vector2D | V2, Vector2D | V2]]] | list[Vector2D | None]:
1113
+ - If return_inter_lines is True, returns a list of tuples, each containing:
1114
+ - The intersection point (Vector2D) if it exists, or None otherwise.
1115
+ - The corresponding intersecting line segment (tuple[Vector2D | V2, Vector2D | V2]).
1116
+ - If return_inter_lines is False, returns a list of intersection points (Vector2D) if they exist, or None otherwise.
1117
+
1118
+ # Example:
1119
+ ray = [Vector2D(1, 2), Vector2D(5, 3)]
1120
+ lines = [(Vector2D(2, 2), Vector2D(4, 4)), (Vector2D(3, 3), Vector2D(6, 2))]
1121
+ result = inter_points(ray, lines, return_inter_lines=True, sort=True)
1122
+ print(result)
1123
+
1124
+ ## Explanation:
1125
+ The function finds the intersection points (if any) between the given ray (or line segment) and the provided list
1126
+ of line segments. The intersection points are returned in a list.
1127
+
1128
+ If return_inter_lines is True, the function returns a list of tuples, where each tuple contains the intersection point
1129
+ (Vector2D) and the corresponding intersecting line segment (tuple[Vector2D | V2, Vector2D | V2]). If return_inter_lines
1130
+ is False, the function returns only a list of intersection points (Vector2D) without the corresponding line segments.
1131
+
1132
+ If sort is True, the intersection points are sorted by their distance from the ray's start point. If sort is False,
1133
+ the intersection points are returned in the order they were found.
1134
+
1135
+ If return_empty is True, the function includes None for line segments with no intersection. If return_empty is False,
1136
+ line segments with no intersection are omitted from the result.
1137
+
1138
+ Example usage is shown in the "Example" section above.
1139
+ """
1140
+ def lineLineIntersect(P0:"V2|Vector2D", P1:"V2|Vector2D", Q0:"V2|Vector2D", Q1:"V2|Vector2D") -> "Vector2D | None":
1141
+ d = (P1.x-P0.x) * (Q1.y-Q0.y) + (P1.y-P0.y) * (Q0.x-Q1.x)
1142
+ if d == 0:
1143
+ return None
1144
+ t = ((Q0.x-P0.x) * (Q1.y-Q0.y) + (Q0.y-P0.y) * (Q0.x-Q1.x)) / d
1145
+ u = ((Q0.x-P0.x) * (P1.y-P0.y) + (Q0.y-P0.y) * (P0.x-P1.x)) / d
1146
+ if 0 <= t <= 1 and 0 <= u <= 1:
1147
+ return Vector2D(P1.x * t + P0.x * (1-t), P1.y * t + P0.y * (1-t))
1148
+ return None
1149
+
1150
+ if return_inter_lines:
1151
+ collisions = [(lineLineIntersect(line[1], line[0], ray[1], ray[0]), line) for line in lines if (line!=None or return_empty)]
1152
+ return sorted(collisions, key=lambda x: ray[0].distance_to(x[0], False) if x[0] != None else _mt.inf) if sort else collisions
1153
+ else:
1154
+ collisions = [lineLineIntersect(line[1], line[0], ray[1], ray[0]) for line in lines if (line!=None or return_empty)]
1155
+ return sorted(collisions, key=lambda x: ray[0].distance_to(x, False) if x != None else _mt.inf) if sort else collisions
786
1156
 
787
1157
  def get_points(position:Vector2D|V2, size:Vector2D|V2, rotation:int|float=0, pos_in_middle:bool=True, return_list:bool=False, clockwise_return:bool=False) -> tuple["Vector2D|V2", "Vector2D|V2", "Vector2D|V2", "Vector2D|V2"] | tuple[list[int|float]|tuple[int|float], list[int|float]|tuple[int|float], list[int|float]|tuple[int|float], list[int|float]|tuple[int|float]]:
788
1158
  """
789
1159
  # Generate points for a rectangle based on the given parameters.
790
1160
 
791
- # Parameters:
1161
+ ## Parameters:
792
1162
  position (Vector2D): The center position of the rectangle.
793
1163
  size (Vector2D): The size of the rectangle (width and height).
794
1164
  rotation (int|float, optional): The rotation angle in degrees. Default is 0.
795
1165
  pos_in_middle (bool, optional): If True, the points represent corners of the rectangle.
796
1166
  If False, the points represent the rectangle's edges.
797
1167
  Default is True.
798
- return_list (bool, optional): If True, return the points as lists instead of Vector2D objects.
1168
+ return_list (bool, optional): If True, return the points as lists instead of Vector2D others.
799
1169
  Default is False.
800
1170
  clockwise_return (bool, optional): If True, return the points in clockwise order (A, B, D, C).
801
1171
  If False, return the points in counterclockwise order (A, B, C, D).
802
1172
  Default is False.
803
1173
 
804
- # Returns:
1174
+ ## Returns:
805
1175
  tuple: A tuple containing the four points of the rectangle.
806
1176
 
807
- # Example:
1177
+ ## Example:
808
1178
  position = Vector2D(100, 100)
809
1179
 
810
1180
  size = Vector2D(50, 30)
@@ -817,12 +1187,12 @@ def get_points(position:Vector2D|V2, size:Vector2D|V2, rotation:int|float=0, pos
817
1187
 
818
1188
  This will print the four points of the rotated rectangle.
819
1189
 
820
- # Explanation:
1190
+ ## Explanation:
821
1191
  The function calculates the four points (A, B, C, D) of the rectangle based on the center position,
822
1192
  size, rotation, and pos_in_middle parameters. The points represent the rectangle's corners if pos_in_middle
823
1193
  is True, and the edges if pos_in_middle is False.
824
1194
 
825
- The points are returned as Vector2D objects unless the return_list parameter is set to True. In that case,
1195
+ The points are returned as Vector2D others unless the return_list parameter is set to True. In that case,
826
1196
  the points will be returned as lists.
827
1197
 
828
1198
  The clockwise_return parameter determines the order of the points. If True, the points will be returned in
@@ -845,7 +1215,7 @@ def get_lines(position:Vector2D|V2, size:Vector2D|V2, rotation:int|float=0, pos_
845
1215
  """
846
1216
  # Generate lines representing the sides of a rectangle based on the given parameters.
847
1217
 
848
- # Parameters:
1218
+ ## Parameters:
849
1219
  position (Vector2D): The center position of the rectangle.
850
1220
  size (Vector2D): The size of the rectangle (width and height).
851
1221
  rotation (int|float, optional): The rotation angle in degrees. Default is 0.
@@ -853,11 +1223,11 @@ def get_lines(position:Vector2D|V2, size:Vector2D|V2, rotation:int|float=0, pos_
853
1223
  If False, the points represent the rectangle's edges.
854
1224
  Default is True.
855
1225
 
856
- # Returns:
857
- list[list[Vector2D]]: A list of lists, where each sublist contains two Vector2D objects
1226
+ ## Returns:
1227
+ list[list[Vector2D]]: A list of lists, where each sublist contains two Vector2D others
858
1228
  representing the start and end points of a line segment.
859
1229
 
860
- # Example:
1230
+ ## Example:
861
1231
  position = Vector2D(100, 100)
862
1232
 
863
1233
  size = Vector2D(50, 30)
@@ -870,11 +1240,11 @@ def get_lines(position:Vector2D|V2, size:Vector2D|V2, rotation:int|float=0, pos_
870
1240
 
871
1241
  This will print the four line segments representing the sides of the rotated rectangle.
872
1242
 
873
- # Explanation:
1243
+ ## Explanation:
874
1244
  The function calculates the four points (A, B, C, D) of the rectangle using the `get_points` function
875
1245
  based on the center position, size, rotation, and pos_in_middle parameters.
876
1246
 
877
- The function then returns a list of lists, where each sublist contains two Vector2D objects representing
1247
+ The function then returns a list of lists, where each sublist contains two Vector2D others representing
878
1248
  the start and end points of a line segment forming the sides of the rectangle.
879
1249
  """
880
1250
  A, B, C, D = get_points(position, size, rotation, pos_in_middle)
@@ -884,15 +1254,15 @@ def distance_line_point(line_point_a:Vector2D|V2, line_point_b:Vector2D|V2, poin
884
1254
  """
885
1255
  # Calculate the distance between a line segment and a point.
886
1256
 
887
- # Parameters:
1257
+ ## Parameters:
888
1258
  line_point_a (Vector2D): The starting point of the line segment.
889
1259
  line_point_b (Vector2D): The ending point of the line segment.
890
1260
  point_c (Vector2D): The point to which the distance is calculated.
891
1261
 
892
- # Returns:
1262
+ ## Returns:
893
1263
  float: The distance between the line segment and the point.
894
1264
 
895
- # Example:
1265
+ ## Example:
896
1266
  line_point_a = Vector2D(0, 0)
897
1267
 
898
1268
  line_point_b = Vector2D(10, 0)
@@ -905,7 +1275,7 @@ def distance_line_point(line_point_a:Vector2D|V2, line_point_b:Vector2D|V2, poin
905
1275
 
906
1276
  This will print the distance between the line segment and the point.
907
1277
 
908
- # Explanation:
1278
+ ## Explanation:
909
1279
  The function calculates the distance between a line segment defined by two points (line_point_a and line_point_b)
910
1280
  and a third point (point_c).
911
1281