e2D 1.4.8__py3-none-any.whl → 1.4.10__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
@@ -16,49 +16,310 @@ DOUBLE_PI = PI*2
16
16
 
17
17
  class Vector2D:
18
18
  round_values_on_print :int|float= 2
19
- def __init__(self:"V2|Vector2D", x:int|float=0.0, y:int|float=0.0) -> None:
19
+ def __init__(self:"Vector2D", x:int|float=0.0, y:int|float=0.0) -> None:
20
+ """
21
+ # Initialize a 2D vector with the specified x and y components.
22
+
23
+ ## Parameters:
24
+ x (int | float, optional): The x-component of the vector. Default is 0.
25
+ y (int | float, optional): The y-component of the vector. Default is 0.
26
+
27
+ ## Example:
28
+ vector1 = Vector2D() # Creates a vector with x=0 and y=0
29
+ vector2 = Vector2D(3, -2.5) # Creates a vector with x=3 and y=-2.5
30
+
31
+ ## Explanation:
32
+ This constructor initializes a 2D vector with the specified x and y components.
33
+
34
+ If no arguments are provided, the default values for x and y are both set to 0.
35
+
36
+ The x and y components can be integers or floating-point numbers.
37
+
38
+ Example usage is shown in the "Example" section above.
39
+ """
20
40
  self.x = x
21
41
  self.y = y
22
42
 
23
- def set(self:"V2|Vector2D", x:int|float=0, y:int|float=0) -> None:
43
+ def set(self:"Vector2D", x:int|float=0, y:int|float=0) -> None:
44
+ """
45
+ # Change the components of the Vector2D other without creating a new one.
46
+
47
+ ## Parameters:
48
+ x (int | float, optional): The new x-component to set. Default is 0.
49
+ y (int | float, optional): The new y-component to set. Default is 0.
50
+
51
+ ## Example:
52
+ vector = Vector2D(1, 2)
53
+ vector.set(3, -4)
54
+ print(vector.x, vector.y) # Output: 3, -4
55
+
56
+ ## Explanation:
57
+ The method updates the x and y components of the Vector2D other to the specified values.
58
+
59
+ If no arguments are provided, the default values for x and y are both set to 0.
60
+
61
+ The x and y components can be integers or floating-point numbers.
62
+
63
+ The method does not return any value, but it modifies the Vector2D other in place.
64
+
65
+ Example usage is shown in the "Example" section above.
66
+ """
24
67
  self.x = x
25
68
  self.y = y
26
69
 
27
- def distance_to(self:"V2|Vector2D", other:"float|int|Vector2D|V2|list|tuple", sqrd:bool=True) -> int|float:
70
+ def distance_to(self:"Vector2D", other:"float|int|Vector2D|list|tuple", sqrd:bool=True) -> int|float:
71
+ """
72
+ # Calculate the distance between the current Vector2D other and another other.
73
+
74
+ ## Parameters:
75
+ other (float or int or Vector2D or list|tuple): The other other to which the distance is calculated.
76
+ squared (bool, optional): If True, return the squared distance. If False, return the actual distance.
77
+ Default is True.
78
+
79
+ ## Returns:
80
+ int|float: The squared distance between the current Vector2D other and the other other if `squared` is True,
81
+ otherwise the actual distance.
82
+
83
+ ## Example:
84
+ point1 = Vector2D(0, 0)
85
+
86
+ point2 = Vector2D(3, 4)
87
+
88
+ squared_distance = point1.distance_to(point2)
89
+
90
+ print(f"Squared Distance: {squared_distance}")
91
+
92
+ distance = point1.distance_to(point2, squared=False)
93
+
94
+ print(f"Actual Distance: {distance}")
95
+
96
+ This will calculate the squared and actual distances between the two points.
97
+
98
+ ## Explanation:
99
+ The function calculates the squared distance between the current Vector2D other (self) and another other
100
+ (other) using the formula: (self.x - other.x)**2 + (self.y - other.y)**2.
101
+
102
+ The result is returned as the squared distance if `squared` is True, or as the actual distance if `squared` is False.
103
+ """
28
104
  other = self.__normalize__(other)
29
105
  d = (self.x - other.x)**2 + (self.y - other.y)**2
30
106
  return (d**(1/2) if sqrd else d)
31
107
 
32
- def angle_to(self:"V2|Vector2D", other:"float|int|Vector2D|V2|list|tuple") -> int|float:
108
+ def angle(self:"Vector2D") -> int|float:
109
+ return _mt.atan2(self.y, self.x)
110
+
111
+ def angle_to(self:"Vector2D", other:"float|int|Vector2D|list|tuple") -> int|float:
112
+ """
113
+ # Calculate the angle between the current Vector2D other and another other.
114
+
115
+ ## Parameters:
116
+ other (float or int or Vector2D or list|tuple): The other other to which the angle is calculated.
117
+
118
+ ## Returns:
119
+ int|float: The angle in radians between the current Vector2D other and the other other.
120
+
121
+ ## Example:
122
+ point1 = Vector2D(0, 0)
123
+
124
+ point2 = Vector2D(1, 1)
125
+
126
+ angle = point1.angle_to(point2)
127
+
128
+ print(f"Angle in radians: {angle}")
129
+
130
+ This will calculate the angle in radians between the two points.
131
+
132
+ ## Explanation:
133
+ The function calculates the angle in radians between the current Vector2D other (self) and another other
134
+ (other) using the `atan2` function from the `math` module.
135
+
136
+ The result is returned as the angle in radians.
137
+ """
33
138
  other = self.__normalize__(other)
34
139
  return _mt.atan2(other.y - self.y, other.x - self.x)
35
140
 
36
- def point_from_degs(self:"V2|Vector2D", degs:int|float, radius:int|float) -> "Vector2D|V2":
141
+ def point_from_degs(self:"Vector2D", degs:int|float, radius:int|float) -> "Vector2D":
142
+ """
143
+ # Calculate a new Vector2D point from the current point based on an angle in degs and a radius.
144
+
145
+ ## Parameters:
146
+ rad (int|float): The angle in degs.
147
+ radius (int|float): The distance from the current point.
148
+
149
+ ## Returns:
150
+ Vector2D: A new Vector2D point calculated from the current point.
151
+
152
+ ## Example:
153
+ point1 = Vector2D(0, 0)
154
+
155
+ angle = 45
156
+
157
+ distance = 5
158
+
159
+ new_point = point1.point_from_degs(angle, distance)
160
+
161
+ print(new_point.x, new_point.y)
162
+
163
+ This will calculate a new point 5 units away from point1 at a 45-degree angle.
164
+
165
+ ## Explanation:
166
+ The function calculates a new Vector2D point based on an angle in degs (degs) and a distance (radius)
167
+ from the current Vector2D point.
168
+
169
+ It computes the new x and y coordinates of the point using the trigonometric functions `cos` and `sin`
170
+ to determine the horizontal and vertical components of the new point.
171
+
172
+ The result is returned as a new Vector2D point with the calculated coordinates.
173
+ """
37
174
  x = radius * _mt.cos(_mt.radians(degs)) + self.x
38
175
  y = radius * _mt.sin(_mt.radians(degs)) + self.y
39
176
  return Vector2D(x, y)
40
177
 
41
- def point_from_rads(self:"V2|Vector2D", rad:int|float, radius:int|float) -> "Vector2D|V2":
178
+ def point_from_rads(self:"Vector2D", rad:int|float, radius:int|float) -> "Vector2D":
179
+ """
180
+ # Calculate a new Vector2D point from the current point based on an angle in radians and a radius.
181
+
182
+ ## Parameters:
183
+ rad (int|float): The angle in radians.
184
+ radius (int|float): The distance from the current point.
185
+
186
+ ## Returns:
187
+ Vector2D: A new Vector2D point calculated from the current point.
188
+
189
+ ## Example:
190
+ point1 = Vector2D(0, 0)
191
+
192
+ angle = 45
193
+
194
+ distance = 5
195
+
196
+ new_point = point1.point_from_degs(_mt.radians(angle), distance)
197
+
198
+ print(new_point.x, new_point.y)
199
+
200
+ This will calculate a new point 5 units away from point1 at a 45-degree angle.
201
+
202
+ ## Explanation:
203
+ The function calculates a new Vector2D point based on an angle in radians (rad) and a distance (radius)
204
+ from the current Vector2D point.
205
+
206
+ It computes the new x and y coordinates of the point using the trigonometric functions `cos` and `sin`
207
+ to determine the horizontal and vertical components of the new point.
208
+
209
+ The result is returned as a new Vector2D point with the calculated coordinates.
210
+ """
42
211
  x = radius * _mt.cos(rad) + self.x
43
212
  y = radius * _mt.sin(rad) + self.y
44
213
  return Vector2D(x, y)
45
214
 
46
- def copy(self:"V2|Vector2D") -> "Vector2D|V2":
215
+ def copy(self:"Vector2D") -> "Vector2D":
216
+ """
217
+ # Create a copy of the current Vector2D other.
218
+
219
+ ## Returns:
220
+ Vector2D: A new Vector2D other with the same x and y coordinates as the current other.
221
+
222
+ ## Example:
223
+ point1 = Vector2D(1, 2)
224
+
225
+ point2 = point1.copy()
226
+
227
+ print(point2.x, point2.y)
228
+
229
+ This will print the x and y coordinates of the copied Vector2D other (1, 2).
230
+
231
+ ## Explanation:
232
+ The function creates a new Vector2D other with the same x and y coordinates as the current other.
233
+
234
+ The result is returned as a new Vector2D other, effectively making a copy of the original other.
235
+ """
47
236
  return Vector2D(self.x, self.y)
48
237
 
49
- def sign(self:"V2|Vector2D") -> "Vector2D|V2":
238
+ def sign(self:"Vector2D") -> "Vector2D":
239
+ """
240
+ # Perform an "absolute round" operation on the Vector2D other.
241
+
242
+ ## Parameters:
243
+ n (int|float, optional): The numeric value to scale the "absolute rounded" vector. Default is 1.
244
+
245
+ ## Returns:
246
+ Vector2D: The "absolute rounded" Vector2D other scaled by the provided numeric value.
247
+
248
+ ## Example:
249
+ vector1 = Vector2D(3.3, -4.7)
250
+
251
+ result1 = vector1.absolute_round(0.5)
252
+
253
+ print(result1.x, result1.y)
254
+
255
+ vector2 = Vector2D(-2.8, 1.1)
256
+
257
+ result2 = vector2.absolute_round()
258
+
259
+ print(result2.x, result2.y)
260
+
261
+ ## Explanation:
262
+ The function performs an "absolute round" operation on the Vector2D other.
263
+
264
+ The "absolute round" operation involves taking the absolute values of both the x and y components of the Vector2D other,
265
+ and then scaling the resulting vector by the provided numeric value (n).
266
+
267
+ The default value of n is 1, which means the "absolute rounded" vector will have the same magnitude as the original vector.
268
+
269
+ If the provided numeric value (n) is 0, the function returns a Vector2D other with zeros for both components.
270
+
271
+ If the provided numeric value (n) is negative, the resulting "absolute rounded" vector will point in the opposite direction
272
+ as the original vector but will have the same magnitude.
273
+
274
+ Note: The "absolute round" operation does not perform standard mathematical rounding; instead, it ensures the resulting
275
+ vector points in the same direction as the original vector but has non-negative components.
276
+ """
50
277
  return self.no_zero_div_error(abs(self), "zero")
51
278
 
52
- def floor(self:"V2|Vector2D", n:"int|float|Vector2D|V2"=1) -> "Vector2D|V2":
279
+ def floor(self:"Vector2D", n:"int|float|Vector2D"=1) -> "Vector2D":
53
280
  return self.__floor__(n)
54
281
 
55
- def ceil(self:"V2|Vector2D", n:"int|float|Vector2D|V2"=1) -> "Vector2D|V2":
282
+ def ceil(self:"Vector2D", n:"int|float|Vector2D"=1) -> "Vector2D":
56
283
  return self.__ceil__(n)
57
284
 
58
- def round(self:"V2|Vector2D", n:"int|float|Vector2D|V2"=1) -> "Vector2D|V2":
285
+ def round(self:"Vector2D", n:"int|float|Vector2D"=1) -> "Vector2D":
59
286
  return self.__round__(n)
60
287
 
61
- def randomize(start:"int|float|Vector2D|V2|None"=None, end:"int|float|Vector2D|V2|None"=None) -> "Vector2D|V2": #type: ignore
288
+ def randomize(start:"int|float|Vector2D|None"=None, end:"int|float|Vector2D|None"=None) -> "Vector2D": #type: ignore
289
+ """
290
+ # Generate a random Vector2D point within the specified range.
291
+
292
+ ## Parameters:
293
+ start (int|float or Vector2D or None, optional): The starting point of the range.
294
+ Default is None, which corresponds to (0, 0).
295
+ If numeric, both x and y will have the same value.
296
+ end (int|float or Vector2D or None, optional): The ending point of the range.
297
+ Default is None, which corresponds to (1, 1).
298
+ If numeric, both x and y will have the same value.
299
+
300
+ ## Returns:
301
+ Vector2D: A new random Vector2D point within the specified range.
302
+
303
+ ## Example:
304
+ random_point = randomize(Vector2D(10, 20), Vector2D(50, 70))
305
+
306
+ print(random_point.x, random_point.y)
307
+
308
+ This will print a random point between (10, 20) and (50, 70).
309
+
310
+ ## Explanation:
311
+ The function generates a random Vector2D point within the specified range defined by `start` and `end`.
312
+
313
+ If `start` and `end` are numeric values (int or float), both x and y coordinates will have the same value.
314
+
315
+ If `start` and `end` are None, the default range is assumed to be (0, 0) to (1, 1).
316
+
317
+ The function first checks if `start` and `end` are Vector2D others. If not, it creates new Vector2D others
318
+ based on the numeric values provided or the default values.
319
+
320
+ It then generates random x and y coordinates in the range [0, 1) using the `random()` function from the `random` module.
321
+ These random values are then scaled by (end - start) and added to the start point to obtain the final random Vector2D point.
322
+ """
62
323
  if not any(isinstance(start, cls) for cls in {Vector2D, V2}):
63
324
  if type(start) in int|float: start = Vector2D(start, start) #type: ignore
64
325
  elif type(start) == None: start = Vector2D(0,0)
@@ -69,17 +330,102 @@ class Vector2D:
69
330
  else: raise Exception(f"\nArg end must be in [Vector2D, int, float, tuple, list] not a [{type(end)}]\n")
70
331
  return start + Vector2D(_rnd.random(), _rnd.random()) * (end - start) #type: ignore
71
332
 
72
- def dot_product(self, other:"float|int|Vector2D|V2|list|tuple") -> float:
333
+ def dot_product(self, other:"float|int|Vector2D|list|tuple") -> float:
73
334
  other = self.__normalize__(other)
335
+ """
336
+ # Calculate the dot product of the current vector with another vector.
337
+
338
+ ## Parameters:
339
+ other (Vector2D): The other vector for the dot product calculation.
340
+
341
+ ## Returns:
342
+ float: The dot product value.
343
+
344
+ ## Example:
345
+ v1 = Vector2D(2, 3)
346
+ v2 = Vector2D(4, -1)
347
+ result = v1.dot_product(v2)
348
+ print(result) # Output: 5
349
+
350
+ ## Explanation:
351
+ The dot product of two vectors (A and B) is given by the formula: dot_product = A.x * B.x + A.y * B.y
352
+
353
+ The method takes another vector (other) as input and returns the dot product value.
354
+
355
+ Example usage is shown in the "Example" section above.
356
+ """
74
357
  return self.x * other.x + self.y * other.y
75
358
 
76
359
  def normalize(self) -> "Vector2D":
360
+ """
361
+ # Vector Normalization
362
+
363
+ ## Returns:
364
+ Vector2D: A new vector with the same direction as the current vector but with a magnitude of 1.
365
+
366
+ ## Raises:
367
+ ValueError: If the magnitude of the current vector is zero (zero vector).
368
+
369
+ ## Example:
370
+ v = Vector2D(3, 4)
371
+ normalized_v = v.normalize() # Normalize the vector (3, 4)
372
+ print(normalized_v) # Output: (0.6, 0.8)
373
+
374
+ ## Explanation:
375
+ 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.
376
+
377
+ The method first calculates the magnitude of the current vector using the 'magnitude' method.
378
+
379
+ If the magnitude is zero (zero vector), a ValueError is raised, as normalization is not defined for zero vectors.
380
+
381
+ The normalized vector is obtained by dividing each component of the current vector by its magnitude.
382
+
383
+ The resulting normalized vector is returned.
384
+
385
+ Example usage is shown in the "Example" section above.
386
+ """
77
387
  mag = self.length()
78
388
  if mag == 0:
79
389
  return self
80
390
  return Vector2D(self.x / mag, self.y / mag)
81
391
 
82
- def projection(self, other:"float|int|Vector2D|V2|list|tuple") -> "Vector2D|V2":
392
+ def projection(self, other:"float|int|Vector2D|list|tuple") -> "Vector2D":
393
+ """
394
+ # Vector Projection
395
+
396
+ ## Parameters:
397
+ other (float, int, Vector2D, V2, list, tuple): The vector onto which to project.
398
+
399
+ ## Returns:
400
+ Vector2D or V2: The projection of the current vector onto the 'other' vector.
401
+
402
+ ## Raises:
403
+ ValueError: If 'other' is a zero vector.
404
+
405
+ ## Example:
406
+ v1 = Vector2D(3, 4)
407
+ v2 = Vector2D(1, 0)
408
+ projection_v = v1.projection(v2) # Calculate the projection of v1 onto v2
409
+ print(projection_v) # Output: (3.0, 0.0)
410
+
411
+ ## Explanation:
412
+ This method calculates the projection of the current vector onto the 'other' vector.
413
+ The projection is a vector that represents the component of the current vector in the direction of the 'other' vector.
414
+
415
+ If 'other' is not a Vector2D instance, it will be converted to one using the '__normalize__' method.
416
+ The method first normalizes the 'other' vector using the '__normalize__' method of the vector.
417
+
418
+ Next, it calculates the dot product of the current vector and the normalized 'other' vector using the 'dot_product' method.
419
+ It also calculates the squared magnitude of the 'other' vector using the 'magnitude' method.
420
+
421
+ If the magnitude of 'other' is zero (a zero vector), a ValueError is raised, as projection is not defined for zero vectors.
422
+
423
+ The projection is then obtained by scaling the 'other' vector by the dot product divided by the squared magnitude.
424
+
425
+ The resulting projection vector is returned.
426
+
427
+ Example usage is shown in the "Example" section above.
428
+ """
83
429
  other = self.__normalize__(other)
84
430
  dot_product = self.dot_product(other)
85
431
  magnitude_product = other.length() ** 2
@@ -87,18 +433,91 @@ class Vector2D:
87
433
  raise ValueError("Cannot calculate projection for zero vectors.")
88
434
  return other * (dot_product / magnitude_product)
89
435
 
90
- def reflection(self, normal:"float|int|Vector2D|V2|list|tuple") -> "Vector2D|V2":
436
+ def reflection(self, normal:"float|int|Vector2D|list|tuple") -> "Vector2D":
437
+ """
438
+ # Vector Reflection
439
+
440
+ ## Parameters:
441
+ normal (float, int, Vector2D, V2, list, tuple): The normal vector representing the surface of reflection.
442
+
443
+ ## Returns:
444
+ Vector2D or V2: The reflected vector.
445
+
446
+ ## Example:
447
+ incident_vector = Vector2D(3, 4)
448
+ normal_vector = Vector2D(1, 0)
449
+ reflected_vector = incident_vector.reflection(normal_vector) # Calculate the reflection of the incident vector over the given normal
450
+ print(reflected_vector) # Output: (-3.0, 4.0)
451
+
452
+ ## Explanation:
453
+ This method calculates the reflection of the current vector over the given normal vector.
454
+ The normal vector represents the surface of reflection, and it should be normalized (unit vector).
455
+
456
+ The method first normalizes the 'normal' vector using the '__normalize__' method of the vector.
457
+ Next, it calculates the projection of the current vector onto the 'normal' vector using the 'projection' method.
458
+ The reflected vector is obtained by subtracting twice the projection from the current vector.
459
+
460
+ The resulting reflected vector is returned.
461
+
462
+ Example usage is shown in the "Example" section above.
463
+ """
91
464
  normal = self.__normalize__(normal)
92
465
  projection = self.projection(normal)
93
466
  return self - projection * 2
94
467
 
95
468
  def cartesian_to_polar(self) -> tuple:
469
+ """
470
+ # Convert Cartesian Coordinates to Polar Coordinates
471
+
472
+ ## Returns:
473
+ tuple: A tuple containing the radial distance (magnitude) 'r' and the angle 'theta' in radians.
474
+
475
+ ## Example:
476
+ v = Vector2D(3, 4)
477
+ r, theta = v.cartesian_to_polar() # Convert Cartesian coordinates (3, 4) to polar
478
+ print(r, theta) # Output: (5.0, 0.9272952180016122)
479
+
480
+ ## Explanation:
481
+ This method converts Cartesian coordinates (x, y) to polar coordinates (r, theta).
482
+ 'r' is the radial distance (magnitude) from the origin to the point, and 'theta' is the angle
483
+ (in radians) measured from the positive x-axis to the point.
484
+
485
+ The method calculates the radial distance 'r' using the 'magnitude' method of the vector.
486
+ The angle 'theta' is calculated using the arctan2 function, which takes the y and x components of the vector.
487
+
488
+ The resulting 'r' and 'theta' are returned as a tuple.
489
+
490
+ Example usage is shown in the "Example" section above.
491
+ """
96
492
  r = self.length()
97
493
  theta = _mt.atan2(self.y, self.x)
98
494
  return r, theta
99
495
 
100
496
  @classmethod
101
- def polar_to_cartesian(cls, r: float|int, theta: float|int) -> "Vector2D|V2":
497
+ def polar_to_cartesian(cls, r: float|int, theta: float|int) -> "Vector2D":
498
+ """
499
+ # Convert Polar Coordinates to Cartesian Coordinates
500
+
501
+ ## Parameters:
502
+ r (float or int): The radial distance (magnitude) from the origin to the point.
503
+ theta (float or int): The angle (in radians or degrees) measured from the positive x-axis to the point.
504
+
505
+ ## Returns:
506
+ Vector2D or V2: A new vector representing the Cartesian coordinates (x, y) of the point.
507
+
508
+ ## Example:
509
+ cartesian_point = Vector2D.polar_to_cartesian(5, math.pi/4) # Convert polar coordinates (r=5, theta=45 degrees) to Cartesian
510
+ print(cartesian_point) # Output: (3.5355339059327378, 3.5355339059327373)
511
+
512
+ ## Explanation:
513
+ This class method converts polar coordinates (r, theta) to Cartesian coordinates (x, y).
514
+ 'r' is the radial distance (magnitude) from the origin to the point, and 'theta' is the angle
515
+ (in radians or degrees) measured from the positive x-axis to the point.
516
+
517
+ The method calculates the x and y components using trigonometric functions (cosine and sine) based on 'r' and 'theta'.
518
+
519
+ Example usage is shown in the "Example" section above.
520
+ """
102
521
  x = r * _mt.cos(theta)
103
522
  y = r * _mt.sin(theta)
104
523
  return cls(x, y)
@@ -107,19 +526,81 @@ class Vector2D:
107
526
  return self.x + self.y * 1j
108
527
 
109
528
  @classmethod
110
- def complex_to_cartesian(cls, complex_n: complex) -> "Vector2D|V2":
529
+ def complex_to_cartesian(cls, complex_n: complex) -> "Vector2D":
111
530
  return cls(complex_n.real, complex_n.imag)
112
531
 
113
532
  def length(self) -> float:
114
533
  return (self.x ** 2 + self.y ** 2) ** .5
115
534
 
116
- def lerp(self, other:"float|int|Vector2D|V2|list|tuple", t: float) -> "Vector2D|V2":
535
+ def lerp(self, other:"float|int|Vector2D|list|tuple", t: float) -> "Vector2D":
536
+ """
537
+ # Linear Interpolation (LERP)
538
+
539
+ ## Parameters:
540
+ other (float, int, Vector2D, V2, list, tuple): The vector to interpolate towards.
541
+ t (float): The interpolation parameter. Must be between 0 and 1.
542
+
543
+ ## Returns:
544
+ Vector2D or V2: The result of the linear interpolation.
545
+
546
+ ## Raises:
547
+ ValueError: If t is not within the range [0, 1].
548
+
549
+ ## Example:
550
+ v1 = Vector2D(1, 2)
551
+ v2 = Vector2D(5, 7)
552
+ interpolated_v = v1.lerp(v2, 0.5) # Linearly interpolate between v1 and v2 with t = 0.5
553
+ print(interpolated_v) # Output: (3.0, 4.5)
554
+
555
+ ## Explanation:
556
+ This method performs linear interpolation between the current vector and the 'other' vector.
557
+ The 't' parameter represents the interpolation parameter, which controls how much the interpolation
558
+ leans towards the 'other' vector. When 't' is 0, the result will be equal to the current vector (self).
559
+ When 't' is 1, the result will be equal to the 'other' vector. For intermediate values of 't', the
560
+ result will be a linear combination of the two vectors, smoothly transitioning between them.
561
+
562
+ If 'other' is not a Vector2D instance, it will be converted to one using the '__normalize__' method.
563
+ If 't' is not within the range [0, 1], a ValueError is raised.
564
+
565
+ Example usage is shown in the "Example" section above.
566
+ """
117
567
  other = self.__normalize__(other)
118
568
  if not 0 <= t <= 1:
119
569
  raise ValueError("t must be between 0 and 1 for linear interpolation.")
120
570
  return Vector2D(self.x + (other.x - self.x) * t, self.y + (other.y - self.y) * t)
121
571
 
122
- def rotate(self, angle: int|float, center:"float|int|Vector2D|V2|list|tuple|None"=None) -> "Vector2D|V2":
572
+ def rotate(self, angle: int|float, center:"float|int|Vector2D|list|tuple|None"=None) -> "Vector2D":
573
+ """
574
+ # Rotate the vector by a given angle around the origin or a specified center.
575
+
576
+ ## Parameters:
577
+ angle (int or float): The angle of rotation in radians or degrees, depending on the trigonometric functions used.
578
+ center (float, int, Vector2D, V2, list, tuple, or None): The center of rotation.
579
+ If None, the vector is rotated around the origin (0, 0).
580
+
581
+ ## Returns:
582
+ Vector2D or V2: The rotated vector.
583
+
584
+ ## Example:
585
+ v = Vector2D(3, 4)
586
+ rotated_v = v.rotate(math.pi / 4) # Rotate 45 degrees around the origin
587
+ print(rotated_v) # Output: (0.7071067811865476, 5.656854249492381)
588
+
589
+ center = Vector2D(1, 1)
590
+ rotated_v = v.rotate(math.pi / 4, center) # Rotate 45 degrees around the center (1, 1)
591
+ print(rotated_v) # Output: (1.7071067811865475, 2.656854249492381)
592
+
593
+ ## Explanation:
594
+ This method rotates the vector by the specified angle around the given center.
595
+ If no center is provided, the vector is rotated around the origin (0, 0).
596
+
597
+ The method calculates the trigonometric functions (cosine and sine) of the angle to perform the rotation.
598
+ The translated vector is obtained by subtracting the center from the current vector.
599
+ The rotated vector is then obtained by applying the rotation transformation to the translated vector.
600
+ The center is added back to the rotated vector to obtain the final result.
601
+
602
+ Example usage is shown in the "Example" section above.
603
+ """
123
604
  if center is None: center = V2z
124
605
  else: center = self.__normalize__(center)
125
606
  translated = self - center
@@ -127,7 +608,49 @@ class Vector2D:
127
608
  sin_angle = _mt.sin(angle)
128
609
  return Vector2D(translated.x * cos_angle - translated.y * sin_angle, translated.x * sin_angle + translated.y * cos_angle) + center
129
610
 
130
- def no_zero_div_error(self:"Vector2D|V2", n:"int|float|Vector2D|V2", error_mode:str="zero") -> "Vector2D|V2":
611
+ def no_zero_div_error(self:"Vector2D", n:"int|float|Vector2D", error_mode:str="zero") -> "Vector2D":
612
+ """
613
+ # Handle division between the Vector2D other and a numeric value or another Vector2D other.
614
+
615
+ ## Parameters:
616
+ n (int|float or Vector2D): The numeric value or Vector2D other for division.
617
+ error_mode (str, optional): The mode to handle division by zero scenarios.
618
+ - "zero" (default): Return a Vector2D other with zeros for both components.
619
+ - "null": Return a Vector2D other with the original x or y component if available,
620
+ otherwise, return NaN (Not a Number) for the component.
621
+
622
+ ## Returns:
623
+ Vector2D: A new Vector2D other after division or handling division by zero scenarios.
624
+
625
+ ## Example:
626
+ vector1 = Vector2D(3, 4)
627
+
628
+ result1 = vector1.no_zero_div_error(2)
629
+
630
+ print(result1.x, result1.y)
631
+
632
+ vector2 = Vector2D(5, 0)
633
+
634
+ result2 = vector1.no_zero_div_error(vector2, error_mode="null")
635
+
636
+ print(result2.x, result2.y)
637
+
638
+ ## Explanation:
639
+ The function handles division between the Vector2D other and a numeric value or another Vector2D other.
640
+
641
+ If n is a numeric value (int or float):
642
+ - If n is zero, the function returns a Vector2D other with zeros for both components if error_mode is "zero".
643
+ - If error_mode is "null", the function returns a Vector2D other with the original x or y component if available,
644
+ otherwise, return NaN (Not a Number) for the component.
645
+
646
+ If n is a Vector2D other:
647
+ - If n's x or y component is zero, the function returns a Vector2D other with zeros for the corresponding component
648
+ if error_mode is "zero".
649
+ - If error_mode is "null", the function returns a Vector2D other with the original x or y component if available,
650
+ otherwise, return NaN (Not a Number) for the component.
651
+
652
+ If n is neither a numeric value nor a Vector2D other, the function raises an exception.
653
+ """
131
654
  if any(isinstance(n, cls) for cls in {int, float}):
132
655
  if n == 0:
133
656
  return Vector2D(0 if error_mode == "zero" else (self.x if error_mode == "null" else _mt.nan), 0 if error_mode == "zero" else (self.y if error_mode == "null" else _mt.nan))
@@ -138,15 +661,15 @@ class Vector2D:
138
661
  else:
139
662
  raise Exception(f"\nArg n must be in [Vector2D, int, float, tuple, list] not a [{type(n)}]\n")
140
663
 
141
- def min(self:"V2|Vector2D", other:"float|int|Vector2D|V2|list|tuple") -> "Vector2D|V2":
664
+ def min(self:"Vector2D", other:"float|int|Vector2D|list|tuple") -> "Vector2D":
142
665
  other = self.__normalize__(other)
143
666
  return Vector2D(min(self.x, other.x), min(self.y, other.y))
144
667
 
145
- def max(self:"V2|Vector2D", other:"float|int|Vector2D|V2|list|tuple") -> "Vector2D|V2":
668
+ def max(self:"Vector2D", other:"float|int|Vector2D|list|tuple") -> "Vector2D":
146
669
  other = self.__normalize__(other)
147
670
  return Vector2D(max(self.x, other.x), max(self.y, other.y))
148
671
 
149
- def advanced_stringify(self:"V2|Vector2D", precision:float|None=None, use_scientific_notation:bool=False, return_as_list=False) -> str:
672
+ def advanced_stringify(self:"Vector2D", precision:float|None=None, use_scientific_notation:bool=False, return_as_list=False) -> str:
150
673
  precision = self.round_values_on_print if precision == None else precision
151
674
  def optimize(value) -> str:
152
675
  abs_value = abs(value)
@@ -157,112 +680,112 @@ class Vector2D:
157
680
  else:
158
681
  return f"{value:.{precision}e}"
159
682
  if return_as_list:
160
- return [optimize(self.x), optimize(self.y)] if use_scientific_notation else [f"{self.x:.{precision}f}", f"{self.y:.{precision}f}"]
683
+ return [optimize(self.x), optimize(self.y)] if use_scientific_notation else [f"{self.x:.{precision}f}", f"{self.y:.{precision}f}"] #type: ignore
161
684
  return f"{optimize(self.x)}, {optimize(self.y)}" if use_scientific_notation else f"{self.x:.{precision}f}, {self.y:.{precision}f}"
162
685
 
163
- def __str__(self:"V2|Vector2D") -> str:
686
+ def __str__(self:"Vector2D") -> str:
164
687
  return f"{self.x:.{self.round_values_on_print}f}, {self.y:.{self.round_values_on_print}f}"
165
688
 
166
- def __repr__(self:"V2|Vector2D") -> str:
689
+ def __repr__(self:"Vector2D") -> str:
167
690
  return f"x:{self.x:.{self.round_values_on_print}f}\ty:{self.y:.{self.round_values_on_print}f}"
168
691
 
169
- def __call__(self:"V2|Vector2D", return_tuple=False) -> list|tuple:
692
+ def __call__(self:"Vector2D", return_tuple=False) -> list|tuple:
170
693
  return (self.x, self.y) if return_tuple else [self.x, self.y]
171
694
 
172
695
  # normal operations Vector2D + a
173
- def __add__(self:"V2|Vector2D", other:"float|int|Vector2D|V2|list|tuple") -> "Vector2D|V2":
696
+ def __add__(self:"Vector2D", other:"float|int|Vector2D|list|tuple") -> "Vector2D":
174
697
  other = self.__normalize__(other)
175
698
  return Vector2D(self.x + other.x, self.y + other.y)
176
699
 
177
- def __sub__(self:"V2|Vector2D", other:"float|int|Vector2D|V2|list|tuple") -> "Vector2D|V2":
700
+ def __sub__(self:"Vector2D", other:"float|int|Vector2D|list|tuple") -> "Vector2D":
178
701
  other = self.__normalize__(other)
179
702
  return Vector2D(self.x - other.x, self.y - other.y)
180
703
 
181
- def __mul__(self:"V2|Vector2D", other:"float|int|Vector2D|V2|list|tuple") -> "Vector2D|V2":
704
+ def __mul__(self:"Vector2D", other:"float|int|Vector2D|list|tuple") -> "Vector2D":
182
705
  other = self.__normalize__(other)
183
706
  return Vector2D(self.x * other.x, self.y * other.y)
184
707
 
185
- def __mod__(self:"V2|Vector2D", other:"float|int|Vector2D|V2|list|tuple") -> "Vector2D|V2":
708
+ def __mod__(self:"Vector2D", other:"float|int|Vector2D|list|tuple") -> "Vector2D":
186
709
  other = self.__normalize__(other)
187
710
  return Vector2D(self.x % other.x, self.y % other.y)
188
711
 
189
- def __pow__(self:"V2|Vector2D", other:"float|int|Vector2D|V2|list|tuple") -> "Vector2D|V2":
712
+ def __pow__(self:"Vector2D", other:"float|int|Vector2D|list|tuple") -> "Vector2D":
190
713
  other = self.__normalize__(other)
191
714
  return Vector2D(self.x ** other.x, self.y ** other.y)
192
715
 
193
- def __truediv__(self:"V2|Vector2D", other:"float|int|Vector2D|V2|list|tuple") -> "Vector2D|V2":
716
+ def __truediv__(self:"Vector2D", other:"float|int|Vector2D|list|tuple") -> "Vector2D":
194
717
  other = self.__normalize__(other)
195
718
  return Vector2D(self.x / other.x, self.y / other.y)
196
719
 
197
- def __floordiv__(self:"V2|Vector2D", other:"float|int|Vector2D|V2|list|tuple") -> "Vector2D|V2":
720
+ def __floordiv__(self:"Vector2D", other:"float|int|Vector2D|list|tuple") -> "Vector2D":
198
721
  other = self.__normalize__(other)
199
722
  return Vector2D(self.x // other.x, self.y // other.y)
200
723
 
201
724
  # right operations a + Vector2D
202
- def __radd__(self:"V2|Vector2D", other:"float|int|Vector2D|V2|list|tuple") -> "Vector2D|V2":
725
+ def __radd__(self:"Vector2D", other:"float|int|Vector2D|list|tuple") -> "Vector2D":
203
726
  return self.__add__(other)
204
727
 
205
- def __rsub__(self:"V2|Vector2D", other:"float|int|Vector2D|V2|list|tuple") -> "Vector2D|V2":
728
+ def __rsub__(self:"Vector2D", other:"float|int|Vector2D|list|tuple") -> "Vector2D":
206
729
  other = self.__normalize__(other)
207
730
  return Vector2D(other.x - self.x, other.y - self.y)
208
731
 
209
- def __rmul__(self:"V2|Vector2D", other:"float|int|Vector2D|V2|list|tuple") -> "Vector2D|V2":
732
+ def __rmul__(self:"Vector2D", other:"float|int|Vector2D|list|tuple") -> "Vector2D":
210
733
  return self.__mul__(other)
211
734
 
212
- def __rmod__(self:"V2|Vector2D", other:"float|int|Vector2D|V2|list|tuple") -> "Vector2D|V2":
735
+ def __rmod__(self:"Vector2D", other:"float|int|Vector2D|list|tuple") -> "Vector2D":
213
736
  other = self.__normalize__(other)
214
737
  return Vector2D(other.x % self.x, other.y % self.y)
215
738
 
216
- def __rpow__(self:"V2|Vector2D", other:"float|int|Vector2D|V2|list|tuple") -> "Vector2D|V2":
739
+ def __rpow__(self:"Vector2D", other:"float|int|Vector2D|list|tuple") -> "Vector2D":
217
740
  other = self.__normalize__(other)
218
741
  return Vector2D(other.x ** self.x, other.y ** self.y)
219
742
 
220
- def __rtruediv__(self:"V2|Vector2D", other:"float|int|Vector2D|V2|list|tuple") -> "Vector2D|V2":
743
+ def __rtruediv__(self:"Vector2D", other:"float|int|Vector2D|list|tuple") -> "Vector2D":
221
744
  other = self.__normalize__(other)
222
745
  return Vector2D(other.x / self.x, other.y / self.y)
223
746
 
224
- def __rfloordiv__(self:"V2|Vector2D", other:"float|int|Vector2D|V2|list|tuple") -> "Vector2D|V2":
747
+ def __rfloordiv__(self:"Vector2D", other:"float|int|Vector2D|list|tuple") -> "Vector2D":
225
748
  other = self.__normalize__(other)
226
749
  return Vector2D(other.x // self.x, other.y // self.y)
227
750
 
228
751
  # in-place operations Vector2D += a
229
- def __iadd__(self:"V2|Vector2D", other:"float|int|Vector2D|V2|list|tuple") -> "Vector2D":
752
+ def __iadd__(self:"Vector2D", other:"float|int|Vector2D|list|tuple") -> "Vector2D":
230
753
  other = self.__normalize__(other)
231
754
  self.x += other.x
232
755
  self.y += other.y
233
756
  return self
234
757
 
235
- def __isub__(self:"V2|Vector2D", other:"float|int|Vector2D|V2|list|tuple") -> "Vector2D":
758
+ def __isub__(self:"Vector2D", other:"float|int|Vector2D|list|tuple") -> "Vector2D":
236
759
  other = self.__normalize__(other)
237
760
  self.x -= other.x
238
761
  self.y -= other.y
239
762
  return self
240
763
 
241
- def __imul__(self:"V2|Vector2D", other:"float|int|Vector2D|V2|list|tuple") -> "Vector2D":
764
+ def __imul__(self:"Vector2D", other:"float|int|Vector2D|list|tuple") -> "Vector2D":
242
765
  other = self.__normalize__(other)
243
766
  self.x *= other.x
244
767
  self.y *= other.y
245
768
  return self
246
769
 
247
- def __itruediv__(self:"V2|Vector2D", other:"float|int|Vector2D|V2|list|tuple") -> "Vector2D":
770
+ def __itruediv__(self:"Vector2D", other:"float|int|Vector2D|list|tuple") -> "Vector2D":
248
771
  other = self.__normalize__(other)
249
772
  self.x /= other.x
250
773
  self.y /= other.y
251
774
  return self
252
775
 
253
- def __imod__(self:"V2|Vector2D", other:"float|int|Vector2D|V2|list|tuple") -> "Vector2D|V2":
776
+ def __imod__(self:"Vector2D", other:"float|int|Vector2D|list|tuple") -> "Vector2D":
254
777
  other = self.__normalize__(other)
255
778
  self.x %= other.x
256
779
  self.y %= other.y
257
780
  return self
258
781
 
259
- def __ipow__(self:"V2|Vector2D", other:"float|int|Vector2D|V2|list|tuple") -> "Vector2D|V2":
782
+ def __ipow__(self:"Vector2D", other:"float|int|Vector2D|list|tuple") -> "Vector2D":
260
783
  other = self.__normalize__(other)
261
784
  self.x **= other.x
262
785
  self.y **= other.y
263
786
  return self
264
787
 
265
- def __ifloordiv__(self:"V2|Vector2D", other:"float|int|Vector2D|V2|list|tuple") -> "Vector2D|V2":
788
+ def __ifloordiv__(self:"Vector2D", other:"float|int|Vector2D|list|tuple") -> "Vector2D":
266
789
  other = self.__normalize__(other)
267
790
  self.x //= other.x
268
791
  self.y //= other.y
@@ -277,25 +800,25 @@ class Vector2D:
277
800
  def __ne__(self, other) -> bool:
278
801
  return not self.__eq__(other)
279
802
 
280
- def __abs__(self:"V2|Vector2D") -> "Vector2D|V2":
803
+ def __abs__(self:"Vector2D") -> "Vector2D":
281
804
  return Vector2D(abs(self.x), abs(self.y))
282
805
 
283
- def __round__(self:"V2|Vector2D", n:"int|float|Vector2D|V2"=1) -> "Vector2D|V2":
806
+ def __round__(self:"Vector2D", n:"int|float|Vector2D"=1) -> "Vector2D":
284
807
  n = self.__normalize__(n)
285
808
  return Vector2D(round(self.x / n.x) * n.x, round(self.y / n.y) * n.y)
286
809
 
287
- def __floor__(self:"V2|Vector2D", n:"int|float|Vector2D|V2"=1) -> "Vector2D|V2":
810
+ def __floor__(self:"Vector2D", n:"int|float|Vector2D"=1) -> "Vector2D":
288
811
  n = self.__normalize__(n)
289
812
  return Vector2D(_mt.floor(self.x / n.x) * n.x, _mt.floor(self.y / n.y) * n.y)
290
813
 
291
- def __ceil__(self:"V2|Vector2D", n:"int|float|Vector2D|V2"=1) -> "Vector2D|V2":
814
+ def __ceil__(self:"Vector2D", n:"int|float|Vector2D"=1) -> "Vector2D":
292
815
  n = self.__normalize__(n)
293
816
  return Vector2D(_mt.ceil(self.x / n.x) * n.x, _mt.ceil(self.y / n.y) * n.y)
294
817
 
295
- def __float__(self:"V2|Vector2D") -> "Vector2D|V2":
818
+ def __float__(self:"Vector2D") -> "Vector2D":
296
819
  return Vector2D(float(self.x), float(self.y))
297
820
 
298
- def __getitem__(self:"V2|Vector2D", n) -> int|float:
821
+ def __getitem__(self:"Vector2D", n) -> int|float:
299
822
  if n in [0, "x"]:
300
823
  return self.x
301
824
  elif n in [1, "y"]:
@@ -303,27 +826,22 @@ class Vector2D:
303
826
  else:
304
827
  raise IndexError("V2 has only x,y...")
305
828
 
306
- def __normalize__(self:"V2|Vector2D", other) -> "Vector2D|V2":
829
+ def __normalize__(self:"Vector2D", other) -> "Vector2D":
307
830
  if not isinstance(other, Vector2D):
308
831
  if any(isinstance(other, cls) for cls in {int, float}):
309
832
  return Vector2D(other, other)
310
833
  elif any(isinstance(other, cls) for cls in {list, tuple}):
311
834
  return Vector2D(*other[:2])
312
835
  else:
313
- raise TypeError(f"The value {other} is not a num type: [{int|float}] nor an array type: [{list|tuple}]")
836
+ try:
837
+ return Vector2D(other.x, other.y)
838
+ except:
839
+ raise TypeError(f"pThe value {other} of type {type(other)} is not a num type: [{int|float}] nor an array type: [{list|tuple}]")
314
840
  return other
315
841
 
316
- # __pvector2d__ = Vector2D
317
- # try:
318
- # from .Cmain import * #type: ignore
319
- # __cvector2d__ = Vector2D
320
- # except Exception as err:
321
- # print(Warning(f"Unable to load the C-version on Vector2D: \n\t{err}"))
322
- # __cvector2d__ = None
842
+ from .cvb import *
323
843
 
324
- class V2(Vector2D):
325
- def __init__(self:"V2|Vector2D", x: int|float = 0, y: int|float = 0) -> None:
326
- super().__init__(x, y)
844
+ V2 = Vector2D
327
845
 
328
846
  V2inf = Vector2D(float('inf'), float('inf'))
329
847
  V2z = VectorZero = Vector2D()
@@ -507,13 +1025,13 @@ def angular_interpolation(starting_angle:int|float, final_angle:int|float, step:
507
1025
  distances = (final_angle - starting_angle, final_angle - DOUBLE_PI - starting_angle, final_angle + DOUBLE_PI - starting_angle)
508
1026
  return min(distances, key=abs) * step
509
1027
 
510
- def bezier_cubic_interpolation(t:float, p0:Vector2D|V2, p1:Vector2D|V2) -> float:
1028
+ def bezier_cubic_interpolation(t:float, p0:Vector2D, p1:Vector2D) -> float:
511
1029
  return t*p0.y*3*(1 - t)**2 + p1.y*3*(1 - t) * t**2 + t**3
512
1030
 
513
- def bezier_quadratic_interpolation(t:float, p0:Vector2D|V2) -> float:
1031
+ def bezier_quadratic_interpolation(t:float, p0:Vector2D) -> float:
514
1032
  return 2*(1-t)*t*p0.y+t**2
515
1033
 
516
- def avg_position(*others:"Vector2D|V2") -> Vector2D|V2:
1034
+ def avg_position(*others:"Vector2D") -> Vector2D:
517
1035
  """
518
1036
  # Calculate the average position for a variable number of Vector2D others.
519
1037
 
@@ -545,14 +1063,14 @@ def avg_position(*others:"Vector2D|V2") -> Vector2D|V2:
545
1063
  """
546
1064
  return sum(others) / len(others) #type: ignore
547
1065
 
548
- 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]:
1066
+ def inter_points(ray:list["Vector2D"]|tuple["Vector2D", "Vector2D"], lines:list[tuple["Vector2D", "Vector2D"]], return_inter_lines:bool=False, sort:bool=False, return_empty:bool=False) -> list[tuple[Vector2D | None, tuple[Vector2D | V2, Vector2D | V2]]] | list[Vector2D | None] | list[Vector2D]:
549
1067
  """
550
1068
  # Find intersection points between a ray or line segment and multiple line segments.
551
1069
 
552
1070
  ## Parameters:
553
- ray (list[Vector2D|V2] | tuple[Vector2D|V2, Vector2D|V2]): The ray or line segment represented by two endpoints
1071
+ ray (list[Vector2D] | tuple[Vector2D, Vector2D]): The ray or line segment represented by two endpoints
554
1072
  (start and end points).
555
- lines (list[tuple[Vector2D|V2, Vector2D|V2]]): A list of line segments represented by tuples of their endpoints.
1073
+ lines (list[tuple[Vector2D, Vector2D]]): A list of line segments represented by tuples of their endpoints.
556
1074
  return_inter_lines (bool, optional): If True, return a list of tuples containing the intersection points and the
557
1075
  corresponding intersecting line segment. Default is False.
558
1076
  sort (bool, optional): If True, sort the intersection points by their distance from the ray's start point.
@@ -588,7 +1106,7 @@ def inter_points(ray:list["Vector2D|V2"]|tuple["Vector2D|V2", "Vector2D|V2"], li
588
1106
 
589
1107
  Example usage is shown in the "Example" section above.
590
1108
  """
591
- def lineLineIntersect(P0:"V2|Vector2D", P1:"V2|Vector2D", Q0:"V2|Vector2D", Q1:"V2|Vector2D") -> "Vector2D | None":
1109
+ def lineLineIntersect(P0:"Vector2D", P1:"Vector2D", Q0:"Vector2D", Q1:"Vector2D") -> "Vector2D | None":
592
1110
  d = (P1.x-P0.x) * (Q1.y-Q0.y) + (P1.y-P0.y) * (Q0.x-Q1.x)
593
1111
  if d == 0:
594
1112
  return None
@@ -599,13 +1117,13 @@ def inter_points(ray:list["Vector2D|V2"]|tuple["Vector2D|V2", "Vector2D|V2"], li
599
1117
  return None
600
1118
 
601
1119
  if return_inter_lines:
602
- collisions = [(lineLineIntersect(line[1], line[0], ray[1], ray[0]), line) for line in lines if (line!=None or return_empty)]
1120
+ collisions = [(ip, line) for line in lines if ((ip:=lineLineIntersect(line[1], line[0], ray[1], ray[0]))!=None or return_empty)]
603
1121
  return sorted(collisions, key=lambda x: ray[0].distance_to(x[0], False) if x[0] != None else _mt.inf) if sort else collisions
604
1122
  else:
605
- collisions = [lineLineIntersect(line[1], line[0], ray[1], ray[0]) for line in lines if (line!=None or return_empty)]
1123
+ collisions = [ip for line in lines if ((ip:=lineLineIntersect(line[1], line[0], ray[1], ray[0]))!=None or return_empty)]
606
1124
  return sorted(collisions, key=lambda x: ray[0].distance_to(x, False) if x != None else _mt.inf) if sort else collisions
607
1125
 
608
- 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]]:
1126
+ def get_points(position:Vector2D, size:Vector2D, rotation:int|float=0, pos_in_middle:bool=True, return_list:bool=False, clockwise_return:bool=False) -> tuple["Vector2D", "Vector2D", "Vector2D", "Vector2D"] | 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]]:
609
1127
  """
610
1128
  # Generate points for a rectangle based on the given parameters.
611
1129
 
@@ -662,7 +1180,7 @@ def get_points(position:Vector2D|V2, size:Vector2D|V2, rotation:int|float=0, pos
662
1180
  points = (A, B, C, D) if not clockwise_return else (A, B, D, C)
663
1181
  return points if not return_list else tuple(x() for x in points)
664
1182
 
665
- def get_lines(position:Vector2D|V2, size:Vector2D|V2, rotation:int|float=0, pos_in_middle:bool=True) -> list[list]:
1183
+ def get_lines(position:Vector2D, size:Vector2D, rotation:int|float=0, pos_in_middle:bool=True) -> list[list]:
666
1184
  """
667
1185
  # Generate lines representing the sides of a rectangle based on the given parameters.
668
1186
 
@@ -701,7 +1219,7 @@ def get_lines(position:Vector2D|V2, size:Vector2D|V2, rotation:int|float=0, pos_
701
1219
  A, B, C, D = get_points(position, size, rotation, pos_in_middle)
702
1220
  return [[A, B], [A, C], [C, D], [D, B]]
703
1221
 
704
- def distance_line_point(line_point_a:Vector2D|V2, line_point_b:Vector2D|V2, point_c:Vector2D|V2) -> float:
1222
+ def distance_line_point(line_point_a:Vector2D, line_point_b:Vector2D, point_c:Vector2D) -> float:
705
1223
  """
706
1224
  # Calculate the distance between a line segment and a point.
707
1225
 
@@ -735,7 +1253,7 @@ def distance_line_point(line_point_a:Vector2D|V2, line_point_b:Vector2D|V2, poin
735
1253
 
736
1254
  The result is returned as a float representing the distance between the line segment and the point.
737
1255
  """
738
- return float(_np.linalg.norm(_np.cross((line_point_b-line_point_a)(), (line_point_a-point_c)()))/_np.linalg.norm((line_point_b-line_point_a)()))
1256
+ return float(_np.linalg.norm(_np.cross((line_point_b-line_point_a)(), (line_point_a-point_c)()))/_np.linalg.norm((line_point_b-line_point_a)())) #type: ignore
739
1257
 
740
1258
  def optimize_value_string(value:int|float, precision:int) -> str:
741
1259
  abs_value = abs(value)