e2D 1.4.12__py3-none-any.whl → 1.4.14__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 +58 -55
- e2D/__init__.pyi +124 -123
- e2D/envs.py +7 -6
- e2D/plots.py +3 -3
- e2D/utils.py +7 -3
- e2D/winrec.py +1 -1
- {e2D-1.4.12.dist-info → e2D-1.4.14.dist-info}/METADATA +1 -1
- e2D-1.4.14.dist-info/RECORD +11 -0
- {e2D-1.4.12.dist-info → e2D-1.4.14.dist-info}/WHEEL +1 -1
- e2D/cvb.py +0 -831
- e2D-1.4.12.dist-info/RECORD +0 -12
- {e2D-1.4.12.dist-info → e2D-1.4.14.dist-info}/LICENSE +0 -0
- {e2D-1.4.12.dist-info → e2D-1.4.14.dist-info}/top_level.txt +0 -0
e2D/__init__.py
CHANGED
|
@@ -2,11 +2,12 @@ from __future__ import annotations
|
|
|
2
2
|
|
|
3
3
|
import math as _mt
|
|
4
4
|
import random as _rnd
|
|
5
|
+
from typing import Any, Generator, Literal
|
|
5
6
|
|
|
6
7
|
PI = _mt.pi
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
8
|
+
PI_HALF = PI/2
|
|
9
|
+
PI_QUARTER = PI/4
|
|
10
|
+
PI_DOUBLE = PI*2
|
|
10
11
|
|
|
11
12
|
sign = lambda val: -1 if val < 0 else (1 if val > 0 else 0)
|
|
12
13
|
|
|
@@ -16,9 +17,9 @@ class Vector2D:
|
|
|
16
17
|
self.x = x
|
|
17
18
|
self.y = y
|
|
18
19
|
|
|
19
|
-
def distance_to(self, other,
|
|
20
|
+
def distance_to(self, other, rooted=True) -> int|float:
|
|
20
21
|
d = (self.x - other.x)**2 + (self.y - other.y)**2
|
|
21
|
-
return
|
|
22
|
+
return d**(1/2) if rooted else d
|
|
22
23
|
|
|
23
24
|
def angle_to(self, other) -> int|float:
|
|
24
25
|
return _mt.atan2(other.y - self.y, other.x - self.x)
|
|
@@ -31,8 +32,8 @@ class Vector2D:
|
|
|
31
32
|
return _mt.atan2(self.y, self.x)
|
|
32
33
|
|
|
33
34
|
@angle.setter
|
|
34
|
-
def angle(self,
|
|
35
|
-
|
|
35
|
+
def angle(self, new_angle) -> None:
|
|
36
|
+
self.rotate(new_angle - self.angle)
|
|
36
37
|
|
|
37
38
|
@property
|
|
38
39
|
def copy(self) -> "Vector2D":
|
|
@@ -41,16 +42,20 @@ class Vector2D:
|
|
|
41
42
|
@property
|
|
42
43
|
def sign(self) -> "Vector2D":
|
|
43
44
|
return Vector2D(sign(self.x), sign(self.y))
|
|
44
|
-
|
|
45
|
+
|
|
45
46
|
@property
|
|
46
47
|
def normalize(self) -> "Vector2D":
|
|
47
48
|
if (mag:=self.length) == 0:
|
|
48
49
|
return self.copy
|
|
49
50
|
return Vector2D(self.x / mag, self.y / mag)
|
|
50
|
-
|
|
51
|
+
|
|
51
52
|
@property
|
|
52
53
|
def length(self) -> float:
|
|
53
54
|
return (self.x ** 2 + self.y ** 2) ** .5
|
|
55
|
+
|
|
56
|
+
@property
|
|
57
|
+
def length_sqrd(self) -> float:
|
|
58
|
+
return self.x ** 2 + self.y ** 2
|
|
54
59
|
|
|
55
60
|
def floor(self, n=1) -> "Vector2D":
|
|
56
61
|
return self.__floor__(n)
|
|
@@ -88,16 +93,12 @@ class Vector2D:
|
|
|
88
93
|
def reflection(self, normal) -> "Vector2D":
|
|
89
94
|
return self - self.projection(normal) * 2
|
|
90
95
|
|
|
91
|
-
def cartesian_to_polar(self) -> tuple:
|
|
92
|
-
|
|
93
|
-
theta = _mt.atan2(self.y, self.x)
|
|
94
|
-
return r, theta
|
|
96
|
+
def cartesian_to_polar(self) -> tuple[float, float]:
|
|
97
|
+
return self.length, _mt.atan2(self.y, self.x)
|
|
95
98
|
|
|
96
99
|
@classmethod
|
|
97
100
|
def polar_to_cartesian(cls, r, theta) -> "Vector2D":
|
|
98
|
-
|
|
99
|
-
y = r * _mt.sin(theta)
|
|
100
|
-
return cls(x, y)
|
|
101
|
+
return cls(r * _mt.cos(theta), r * _mt.sin(theta))
|
|
101
102
|
|
|
102
103
|
def cartesian_to_complex(self) -> complex:
|
|
103
104
|
return self.x + self.y * 1j
|
|
@@ -107,19 +108,17 @@ class Vector2D:
|
|
|
107
108
|
return cls(complex_n.real, complex_n.imag)
|
|
108
109
|
|
|
109
110
|
def lerp(self, other, t=.1) -> "Vector2D":
|
|
110
|
-
other = Vector2D.__normalize__(other)
|
|
111
|
-
if not 0 <= t <= 1:
|
|
112
|
-
raise ValueError("t must be between 0 and 1 for linear interpolation.")
|
|
113
111
|
return Vector2D(self.x + (other.x - self.x) * t, self.y + (other.y - self.y) * t)
|
|
114
112
|
|
|
115
|
-
def rotate(self, angle, center=None) ->
|
|
116
|
-
if center
|
|
113
|
+
def rotate(self, angle, center=None) -> None:
|
|
114
|
+
if center == None: center = Vector2D.zero()
|
|
117
115
|
translated = self - center
|
|
118
116
|
cos_angle = _mt.cos(angle)
|
|
119
117
|
sin_angle = _mt.sin(angle)
|
|
120
|
-
|
|
118
|
+
self.x = translated.x * cos_angle - translated.y * sin_angle + center.x
|
|
119
|
+
self.y = translated.x * sin_angle + translated.y * cos_angle + center.y
|
|
121
120
|
|
|
122
|
-
def no_zero_div_error(self, n, error_mode="zero") -> "Vector2D":
|
|
121
|
+
def no_zero_div_error(self, n, error_mode=Literal["zero", "null", "nan"]) -> "Vector2D":
|
|
123
122
|
if isinstance(n, (int, float)):
|
|
124
123
|
if n == 0:
|
|
125
124
|
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))
|
|
@@ -166,20 +165,20 @@ class Vector2D:
|
|
|
166
165
|
def sub(self, both=.0, x=.0, y=.0) -> Vector2D:
|
|
167
166
|
return Vector2D(self.x - (x + both), self.y - (y + both))
|
|
168
167
|
|
|
169
|
-
def mult(self, both
|
|
170
|
-
return Vector2D(self.x *
|
|
168
|
+
def mult(self, both=1.0, x=1.0, y=1.0) -> Vector2D:
|
|
169
|
+
return Vector2D(self.x * x * both, self.y * y * both)
|
|
171
170
|
|
|
172
|
-
def pow(self, both
|
|
171
|
+
def pow(self, both=1.0, x=1.0, y=1.0) -> Vector2D:
|
|
173
172
|
return Vector2D(self.x ** (x + both), self.y ** (y + both))
|
|
174
173
|
|
|
175
|
-
def mod(self, both
|
|
174
|
+
def mod(self, both=1.0, x=1.0, y=1.0) -> Vector2D:
|
|
176
175
|
return Vector2D(self.x % (x + both), self.y % (y + both))
|
|
177
176
|
|
|
178
|
-
def div(self, both
|
|
179
|
-
return Vector2D(self.x /
|
|
177
|
+
def div(self, both=1.0, x=1.0, y=1.0) -> Vector2D:
|
|
178
|
+
return Vector2D(self.x / x / both, self.y / y / both)
|
|
180
179
|
|
|
181
|
-
def fdiv(self, both
|
|
182
|
-
return Vector2D(self.x //
|
|
180
|
+
def fdiv(self, both=1.0, x=1.0, y=1.0) -> Vector2D:
|
|
181
|
+
return Vector2D(self.x // x // both, self.y // y // both)
|
|
183
182
|
|
|
184
183
|
# fast inplace operations Vector2D.ioperation(both,x,y)
|
|
185
184
|
def set(self, both=.0, x=.0, y=.0) -> Vector2D:
|
|
@@ -197,29 +196,29 @@ class Vector2D:
|
|
|
197
196
|
self.y -= y + both
|
|
198
197
|
return self
|
|
199
198
|
|
|
200
|
-
def imult(self, both
|
|
201
|
-
self.x *= x
|
|
202
|
-
self.y *= y
|
|
199
|
+
def imult(self, both=1.0, x=1.0, y=1.0) -> Vector2D:
|
|
200
|
+
self.x *= x * both
|
|
201
|
+
self.y *= y * both
|
|
203
202
|
return self
|
|
204
203
|
|
|
205
|
-
def ipow(self, both
|
|
204
|
+
def ipow(self, both=1.0, x=1.0, y=1.0) -> Vector2D:
|
|
206
205
|
self.x **= x + both
|
|
207
206
|
self.y **= y + both
|
|
208
207
|
return self
|
|
209
208
|
|
|
210
|
-
def imod(self, both
|
|
209
|
+
def imod(self, both=1.0, x=1.0, y=1.0) -> Vector2D:
|
|
211
210
|
self.x %= x + both
|
|
212
211
|
self.y %= y + both
|
|
213
212
|
return self
|
|
214
213
|
|
|
215
|
-
def idiv(self, both
|
|
216
|
-
self.x /= x
|
|
217
|
-
self.y /= y
|
|
214
|
+
def idiv(self, both=1.0, x=1.0, y=1.0) -> Vector2D:
|
|
215
|
+
self.x /= x * both
|
|
216
|
+
self.y /= y * both
|
|
218
217
|
return self
|
|
219
218
|
|
|
220
|
-
def ifdiv(self, both
|
|
221
|
-
self.x //= x
|
|
222
|
-
self.y //= y
|
|
219
|
+
def ifdiv(self, both=1.0, x=1.0, y=1.0) -> Vector2D:
|
|
220
|
+
self.x //= x * both
|
|
221
|
+
self.y //= y * both
|
|
223
222
|
return self
|
|
224
223
|
|
|
225
224
|
# normal operations Vector2D + a
|
|
@@ -356,6 +355,10 @@ class Vector2D:
|
|
|
356
355
|
else:
|
|
357
356
|
raise IndexError("V2 has only x,y...")
|
|
358
357
|
|
|
358
|
+
def __iter__(self) -> Generator[float, Any, None]:
|
|
359
|
+
yield self.x
|
|
360
|
+
yield self.y
|
|
361
|
+
|
|
359
362
|
@classmethod
|
|
360
363
|
def __normalize__(cls, other) -> "Vector2D":
|
|
361
364
|
if isinstance(other, Vector2D):
|
|
@@ -496,22 +499,22 @@ VECTORS_8_DIRECTIONS_NORM = (V2right, V2down_right_norm, V2down, V2down_left_nor
|
|
|
496
499
|
def rgb(r:float, g:float, b:float) -> tuple[float, float, float]:
|
|
497
500
|
return (r,g,b)
|
|
498
501
|
|
|
499
|
-
|
|
500
|
-
|
|
502
|
+
def color_lerp(current_c:list|tuple, final_c:list|tuple, step=.1) -> tuple[float, float, float]:
|
|
503
|
+
return tuple(c + (final_c[i] - c) * step for i,c in enumerate(current_c)) #type: ignore
|
|
501
504
|
|
|
502
|
-
|
|
503
|
-
|
|
505
|
+
def color_fade(starting_c:list|tuple, final_c:list|tuple, index, max_index) -> tuple[float, float, float]:
|
|
506
|
+
return tuple((starting_c[i] - final_c[i]) / max_index * (max_index - index) + final_c[i] for i in range(3)) #type: ignore
|
|
504
507
|
|
|
505
|
-
|
|
506
|
-
|
|
507
|
-
|
|
508
|
+
def weighted_color_fade(colors_dict:dict) -> tuple[float, float, float]:
|
|
509
|
+
colors = colors_dict.keys()
|
|
510
|
+
weights = colors_dict.values()
|
|
508
511
|
|
|
509
|
-
|
|
510
|
-
|
|
512
|
+
if float("inf") in weights: return list(colors)[list(weights).index(float("inf"))]
|
|
513
|
+
return tuple(sum(n[i]*w for n,w in zip(colors, weights)) / sum(weights) for i in range(3)) #type: ignore
|
|
511
514
|
|
|
512
|
-
|
|
513
|
-
|
|
514
|
-
|
|
515
|
+
def color_distance(starting_c:list|tuple, final_c:list|tuple, rooted) -> float:
|
|
516
|
+
distance = sum([(starting_c[i]-final_c[i])**2 for i in range(3)])
|
|
517
|
+
return (distance ** .5) if rooted else distance
|
|
515
518
|
|
|
516
519
|
def lerp(starting, ending, step=.1) -> float:
|
|
517
520
|
return starting + (ending - starting) * step
|
|
@@ -522,7 +525,7 @@ def angular_interpolation(starting_angle, final_angle, step=.1) -> float:
|
|
|
522
525
|
# return starting_angle + min((delta, delta - DOUBLE_PI, delta + DOUBLE_PI), key=abs) * step
|
|
523
526
|
|
|
524
527
|
# math way
|
|
525
|
-
shortest_angle = ((((final_angle - starting_angle) %
|
|
528
|
+
shortest_angle = ((((final_angle - starting_angle) % PI_DOUBLE) + PI_DOUBLE * 1.5) % PI_DOUBLE) - PI
|
|
526
529
|
return starting_angle + shortest_angle * step
|
|
527
530
|
|
|
528
531
|
def bezier_cubic_interpolation(t, p0, p1) -> float:
|
e2D/__init__.pyi
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
from __future__ import annotations
|
|
2
|
-
from typing import Callable, Literal
|
|
2
|
+
from typing import Any, Callable, Generator, Literal
|
|
3
3
|
|
|
4
4
|
PI : float
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
5
|
+
PI_HALF : float
|
|
6
|
+
PI_QUARTER : float
|
|
7
|
+
PI_DOUBLE : float
|
|
8
8
|
|
|
9
9
|
# regular expression to remove comments:
|
|
10
10
|
# """([\s\S]*?)"""
|
|
@@ -39,31 +39,31 @@ class Vector2D:
|
|
|
39
39
|
self.x : int|float
|
|
40
40
|
self.y : int|float
|
|
41
41
|
|
|
42
|
-
def distance_to(self:"Vector2D", other:"Vector2D",
|
|
42
|
+
def distance_to(self:"Vector2D", other:"Vector2D", rooted:bool=True) -> int|float:
|
|
43
43
|
"""
|
|
44
44
|
# Calculate the distance between the current Vector2D other and another other.
|
|
45
45
|
|
|
46
46
|
## Parameters:
|
|
47
47
|
other (float or int or Vector2D or list|tuple): The other other to which the distance is calculated.
|
|
48
|
-
|
|
48
|
+
rooted (bool, optional): If True, return the normal distance. If False, return the square distance.
|
|
49
49
|
Default is True.
|
|
50
50
|
|
|
51
51
|
## Returns:
|
|
52
|
-
int|float: The
|
|
53
|
-
otherwise the
|
|
52
|
+
int|float: The distance between the current Vector2D other and the other other if `rooted` is True,
|
|
53
|
+
otherwise the squared distance.
|
|
54
54
|
|
|
55
55
|
## Example:
|
|
56
56
|
point1 = Vector2D(0, 0)
|
|
57
57
|
|
|
58
58
|
point2 = Vector2D(3, 4)
|
|
59
59
|
|
|
60
|
-
|
|
60
|
+
normal_distance = point1.distance_to(point2)
|
|
61
61
|
|
|
62
|
-
print(f"
|
|
62
|
+
print(f"Normal Distance: {normal_distance}")
|
|
63
63
|
|
|
64
|
-
|
|
64
|
+
squared_distance = point1.distance_to(point2, rooted=False)
|
|
65
65
|
|
|
66
|
-
print(f"
|
|
66
|
+
print(f"Squared Distance: {distance}")
|
|
67
67
|
|
|
68
68
|
This will calculate the squared and actual distances between the two points.
|
|
69
69
|
|
|
@@ -71,7 +71,7 @@ class Vector2D:
|
|
|
71
71
|
The function calculates the squared distance between the current Vector2D other (self) and another other
|
|
72
72
|
(other) using the formula: (self.x - other.x)**2 + (self.y - other.y)**2.
|
|
73
73
|
|
|
74
|
-
The result is returned as the squared distance if `
|
|
74
|
+
The result is returned as the squared distance if `rooted` is False, or as the actual distance if `rooted` is True.
|
|
75
75
|
"""
|
|
76
76
|
...
|
|
77
77
|
|
|
@@ -246,6 +246,10 @@ class Vector2D:
|
|
|
246
246
|
def length(self:"Vector2D") -> float:
|
|
247
247
|
...
|
|
248
248
|
|
|
249
|
+
@property
|
|
250
|
+
def length_sqrd(self:"Vector2D") -> float:
|
|
251
|
+
...
|
|
252
|
+
|
|
249
253
|
def floor(self:"Vector2D", n:"int|float|Vector2D"=1) -> "Vector2D":
|
|
250
254
|
...
|
|
251
255
|
|
|
@@ -387,7 +391,7 @@ class Vector2D:
|
|
|
387
391
|
"""
|
|
388
392
|
...
|
|
389
393
|
|
|
390
|
-
def cartesian_to_polar(self:"Vector2D") -> tuple:
|
|
394
|
+
def cartesian_to_polar(self:"Vector2D") -> tuple[float, float]:
|
|
391
395
|
"""
|
|
392
396
|
# Convert Cartesian Coordinates to Polar Coordinates
|
|
393
397
|
|
|
@@ -479,7 +483,7 @@ class Vector2D:
|
|
|
479
483
|
"""
|
|
480
484
|
...
|
|
481
485
|
|
|
482
|
-
def rotate(self:"Vector2D", angle: int|float, center:"Vector2D|None"=None) ->
|
|
486
|
+
def rotate(self:"Vector2D", angle: int|float, center:"Vector2D|None"=None) -> None:
|
|
483
487
|
"""
|
|
484
488
|
# Rotate the vector by a given angle around the origin or a specified center.
|
|
485
489
|
|
|
@@ -489,7 +493,7 @@ class Vector2D:
|
|
|
489
493
|
If None, the vector is rotated around the origin (0, 0).
|
|
490
494
|
|
|
491
495
|
## Returns:
|
|
492
|
-
|
|
496
|
+
None
|
|
493
497
|
|
|
494
498
|
## Example:
|
|
495
499
|
v = Vector2D(3, 4)
|
|
@@ -577,32 +581,32 @@ class Vector2D:
|
|
|
577
581
|
|
|
578
582
|
def sub(self, both:int|float=.0, x:int|float=.0, y:int|float=.0) -> Vector2D: ...
|
|
579
583
|
|
|
580
|
-
def mult(self, both:int|float
|
|
584
|
+
def mult(self, both:int|float=1.0, x:int|float=1.0, y:int|float=1.0) -> Vector2D: ...
|
|
581
585
|
|
|
582
|
-
def pow(self, both:int|float
|
|
586
|
+
def pow(self, both:int|float=1.0, x:int|float=1.0, y:int|float=1.0) -> Vector2D: ...
|
|
583
587
|
|
|
584
|
-
def mod(self, both:int|float
|
|
588
|
+
def mod(self, both:int|float=1.0, x:int|float=1.0, y:int|float=1.0) -> Vector2D: ...
|
|
585
589
|
|
|
586
|
-
def div(self, both:int|float
|
|
590
|
+
def div(self, both:int|float=1.0, x:int|float=1.0, y:int|float=1.0) -> Vector2D: ...
|
|
587
591
|
|
|
588
|
-
def fdiv(self, both:int|float
|
|
592
|
+
def fdiv(self, both:int|float=1.0, x:int|float=1.0, y:int|float=1.0) -> Vector2D: ...
|
|
589
593
|
|
|
590
594
|
# fast inplace operations Vector2D.ioperation(both,x,y)
|
|
591
|
-
def set(self, both
|
|
595
|
+
def set(self, both:int|float=.0, x:int|float=.0, y:int|float=.0) -> Vector2D: ...
|
|
592
596
|
|
|
593
|
-
def iadd(self, both:int|float, x:int|float, y
|
|
597
|
+
def iadd(self, both:int|float=.0, x:int|float=.0, y:int|float=.0) -> Vector2D: ...
|
|
594
598
|
|
|
595
|
-
def isub(self, both:int|float, x:int|float, y
|
|
599
|
+
def isub(self, both:int|float=.0, x:int|float=.0, y:int|float=.0) -> Vector2D: ...
|
|
596
600
|
|
|
597
|
-
def imult(self, both:int|float, x:int|float, y
|
|
601
|
+
def imult(self, both:int|float=1.0, x:int|float=1.0, y:int|float=1.0) -> Vector2D: ...
|
|
598
602
|
|
|
599
|
-
def ipow(self, both:int|float, x:int|float, y
|
|
603
|
+
def ipow(self, both:int|float=1.0, x:int|float=1.0, y:int|float=1.0) -> Vector2D: ...
|
|
600
604
|
|
|
601
|
-
def imod(self, both:int|float, x:int|float, y
|
|
605
|
+
def imod(self, both:int|float=1.0, x:int|float=1.0, y:int|float=1.0) -> Vector2D: ...
|
|
602
606
|
|
|
603
|
-
def idiv(self, both:int|float, x:int|float, y
|
|
607
|
+
def idiv(self, both:int|float=1.0, x:int|float=1.0, y:int|float=1.0) -> Vector2D: ...
|
|
604
608
|
|
|
605
|
-
def ifdiv(self, both:int|float, x:int|float, y
|
|
609
|
+
def ifdiv(self, both:int|float=1.0, x:int|float=1.0, y:int|float=1.0) -> Vector2D: ...
|
|
606
610
|
|
|
607
611
|
# normal operations Vector2D + a
|
|
608
612
|
def __add__(self:"Vector2D", other:"int|float|Vector2D|list|tuple") -> "Vector2D": ...
|
|
@@ -664,7 +668,9 @@ class Vector2D:
|
|
|
664
668
|
|
|
665
669
|
def __float__(self:"Vector2D") -> "Vector2D": ...
|
|
666
670
|
|
|
667
|
-
def __getitem__(self:"Vector2D", n) -> int|float: ...
|
|
671
|
+
def __getitem__(self:"Vector2D", n:Literal[0,1,"x","y"]) -> int|float: ...
|
|
672
|
+
|
|
673
|
+
def __iter__(self:"Vector2D") -> Generator[float, Any, None]: ...
|
|
668
674
|
|
|
669
675
|
@classmethod
|
|
670
676
|
def __normalize__(cls, other:"Vector2D|int|float|tuple|list") -> "Vector2D": ...
|
|
@@ -796,138 +802,133 @@ def rgb(r:float, g:float, b:float) -> tuple[float, float, float]:
|
|
|
796
802
|
|
|
797
803
|
def lerp(starting: int|float, ending: int|float, step: int|float=.1) -> float: ...
|
|
798
804
|
|
|
799
|
-
|
|
800
|
-
|
|
801
|
-
#
|
|
805
|
+
def color_lerp(current_c: list|tuple, final_c: list|tuple, step: int|float=.1) -> tuple[float, float, float]:
|
|
806
|
+
"""
|
|
807
|
+
# Linearly interpolate between two colors.
|
|
802
808
|
|
|
803
|
-
|
|
804
|
-
|
|
805
|
-
|
|
806
|
-
|
|
809
|
+
## Parameters:
|
|
810
|
+
current_c (tuple or list): The RGB values of the current color as a tuple or list.
|
|
811
|
+
final_c (tuple or list): The RGB values of the target color as a tuple or list.
|
|
812
|
+
step (int or float): The interpolation step, ranging from 0.0 (current color) to 1.0 (target color).
|
|
807
813
|
|
|
808
|
-
|
|
809
|
-
|
|
814
|
+
## Returns:
|
|
815
|
+
tuple: The RGB values of the interpolated color as a tuple.
|
|
810
816
|
|
|
811
|
-
|
|
812
|
-
|
|
817
|
+
## Example:
|
|
818
|
+
current_c = (255, 0, 0)
|
|
813
819
|
|
|
814
|
-
|
|
820
|
+
final_c = (0, 0, 255)
|
|
815
821
|
|
|
816
|
-
|
|
822
|
+
step = 0.5
|
|
817
823
|
|
|
818
|
-
|
|
824
|
+
interpolated_color = color_lerp(current_c, final_c, step)
|
|
819
825
|
|
|
820
|
-
|
|
826
|
+
print(f"At step {step}: RGB {interpolated_color}")
|
|
821
827
|
|
|
822
|
-
|
|
823
|
-
|
|
824
|
-
|
|
828
|
+
This will calculate the color at an interpolation step of 0.5 between (255, 0, 0) and (0, 0, 255).
|
|
829
|
+
"""
|
|
830
|
+
...
|
|
825
831
|
|
|
826
|
-
|
|
827
|
-
|
|
828
|
-
#
|
|
832
|
+
def color_fade(starting_c: list|tuple, final_c: list|tuple, index: int|float, max_index: int|float) -> tuple[float, float, float]:
|
|
833
|
+
"""
|
|
834
|
+
# Calculate the color at a specific index of a color fade between two given colors.
|
|
829
835
|
|
|
830
|
-
|
|
831
|
-
|
|
832
|
-
|
|
833
|
-
|
|
834
|
-
|
|
835
|
-
|
|
836
|
-
|
|
836
|
+
## Parameters:
|
|
837
|
+
starting_c (tuple or list): The RGB values of the starting color as a tuple or list.
|
|
838
|
+
final_c (tuple or list): The RGB values of the final color as a tuple or list.
|
|
839
|
+
index (int or float): The current index of the color fade, representing a position
|
|
840
|
+
between the starting and final colors.
|
|
841
|
+
max_index (int or float): The maximum index of the color fade, indicating the endpoint
|
|
842
|
+
position between the starting and final colors.
|
|
837
843
|
|
|
838
|
-
|
|
839
|
-
|
|
844
|
+
## Returns:
|
|
845
|
+
tuple: The RGB values of the color at the specified index as a tuple.
|
|
840
846
|
|
|
841
|
-
|
|
842
|
-
|
|
847
|
+
## Example:
|
|
848
|
+
starting_c = (255, 0, 0)
|
|
843
849
|
|
|
844
|
-
|
|
850
|
+
final_c = (0, 0, 255)
|
|
845
851
|
|
|
846
|
-
|
|
852
|
+
max_index = 100
|
|
847
853
|
|
|
848
|
-
|
|
854
|
+
for i in range(max_index + 1):
|
|
849
855
|
|
|
850
|
-
|
|
856
|
+
color_at_index = color_fade(starting_c, final_c, i, max_index)
|
|
851
857
|
|
|
852
|
-
|
|
858
|
+
print(f"At index {i}: RGB {color_at_index}")
|
|
853
859
|
|
|
854
|
-
|
|
855
|
-
|
|
856
|
-
|
|
860
|
+
This will print the colors transitioning from (255, 0, 0) to (0, 0, 255).
|
|
861
|
+
"""
|
|
862
|
+
...
|
|
857
863
|
|
|
858
|
-
|
|
859
|
-
|
|
860
|
-
#
|
|
864
|
+
def weighted_color_fade(colors_dict:dict) -> tuple[float, float, float]:
|
|
865
|
+
"""
|
|
866
|
+
# Calculate the weighted color based on a dictionary of colors and their corresponding weights.
|
|
861
867
|
|
|
862
|
-
|
|
863
|
-
|
|
864
|
-
|
|
868
|
+
## Parameters:
|
|
869
|
+
colors_dict (dict): A dictionary where keys represent RGB color values as tuples,
|
|
870
|
+
and values represent the weights (floats) for each color.
|
|
865
871
|
|
|
866
|
-
|
|
867
|
-
|
|
872
|
+
## Returns:
|
|
873
|
+
tuple: The RGB values of the calculated weighted color as a tuple.
|
|
868
874
|
|
|
869
|
-
|
|
870
|
-
|
|
875
|
+
## Example:
|
|
876
|
+
colors_dict = {
|
|
871
877
|
|
|
872
|
-
|
|
878
|
+
(255, 255, 255): 0.1,
|
|
873
879
|
|
|
874
|
-
|
|
880
|
+
(0, 0, 0): 0.9,
|
|
875
881
|
|
|
876
|
-
|
|
882
|
+
}
|
|
877
883
|
|
|
878
|
-
|
|
884
|
+
weighted_color = weighted_color_fade(colors_dict)
|
|
879
885
|
|
|
880
|
-
|
|
886
|
+
print(f"Weighted color: RGB {weighted_color}")
|
|
881
887
|
|
|
882
|
-
|
|
883
|
-
|
|
884
|
-
|
|
885
|
-
# weights = colors_dict.values()
|
|
886
|
-
|
|
887
|
-
# if float("inf") in weights: return list(colors)[list(weights).index(float("inf"))]
|
|
888
|
-
# return tuple(sum(n[i]*w for n,w in zip(colors, weights)) / sum(weights) for i in range(3)) #type: ignore
|
|
889
|
-
|
|
890
|
-
# def color_distance(starting_c: list|tuple, final_c: list|tuple, sqrd:bool=True) -> float:
|
|
891
|
-
# """
|
|
892
|
-
# # Calculate the distance between two colors in RGB space.
|
|
888
|
+
This will print the weighted color based on the provided dictionary.
|
|
889
|
+
"""
|
|
890
|
+
...
|
|
893
891
|
|
|
894
|
-
|
|
895
|
-
|
|
896
|
-
#
|
|
897
|
-
# sqrd (bool, optional): If True, return the squared distance. If False, return
|
|
898
|
-
# the actual distance. Default is True.
|
|
892
|
+
def color_distance(starting_c: list|tuple, final_c: list|tuple, rooted:bool=True) -> float:
|
|
893
|
+
"""
|
|
894
|
+
# Calculate the distance between two colors in RGB space.
|
|
899
895
|
|
|
900
|
-
|
|
901
|
-
|
|
902
|
-
|
|
896
|
+
## Parameters:
|
|
897
|
+
starting_c (list or tuple): The RGB values of the starting color.
|
|
898
|
+
final_c (list or tuple): The RGB values of the final color.
|
|
899
|
+
rooted (bool, optional): If True, return the rooted distance. If False, return
|
|
900
|
+
the actual distance. Default is True.
|
|
903
901
|
|
|
904
|
-
|
|
905
|
-
|
|
902
|
+
## Returns:
|
|
903
|
+
float: The squared distance between the two colors if `rooted` is False, otherwise
|
|
904
|
+
the actual distance.
|
|
906
905
|
|
|
907
|
-
|
|
906
|
+
## Example:
|
|
907
|
+
starting_c = [255, 0, 0]
|
|
908
908
|
|
|
909
|
-
|
|
909
|
+
final_c = [0, 255, 0]
|
|
910
910
|
|
|
911
|
-
|
|
911
|
+
squared_distance = color_distance(starting_c, final_c)
|
|
912
912
|
|
|
913
|
-
|
|
913
|
+
print(f"Squared Distance: {squared_distance}")
|
|
914
914
|
|
|
915
|
-
|
|
915
|
+
distance = color_distance(starting_c, final_c, rooted=True)
|
|
916
916
|
|
|
917
|
-
|
|
917
|
+
print(f"Actual Distance: {distance}")
|
|
918
918
|
|
|
919
|
-
|
|
920
|
-
# The function first calculates the squared distance between the two colors in RGB
|
|
921
|
-
# space. It does this by computing the sum of the squared differences of the RGB
|
|
922
|
-
# components for each color. The squared distance is obtained by taking the square
|
|
923
|
-
# root of this sum.
|
|
919
|
+
This will calculate the squared and actual distances between the colors.
|
|
924
920
|
|
|
925
|
-
|
|
926
|
-
|
|
927
|
-
|
|
928
|
-
|
|
929
|
-
|
|
930
|
-
|
|
921
|
+
## Explanation:
|
|
922
|
+
The function first calculates the squared distance between the two colors in RGB
|
|
923
|
+
space. It does this by computing the sum of the squared differences of the RGB
|
|
924
|
+
components for each color. The squared distance is obtained by taking the square
|
|
925
|
+
root of this sum.
|
|
926
|
+
|
|
927
|
+
The `rooted` parameter allows the user to choose between returning the squared
|
|
928
|
+
distance or the actual distance. If `rooted` is True, the function returns the
|
|
929
|
+
actual distance, and if `rooted` is False, it returns the squared distance.
|
|
930
|
+
"""
|
|
931
|
+
...
|
|
931
932
|
|
|
932
933
|
def angular_interpolation(starting_angle: int|float, final_angle: int|float, step: int|float=.1) -> float:
|
|
933
934
|
"""
|