Skip to content

Commit 627c59f

Browse files
committed
Merge branch 'main' of https://github.com/flet-dev/flet
2 parents ad8a0e7 + 81d7dab commit 627c59f

File tree

1 file changed

+125
-0
lines changed

1 file changed

+125
-0
lines changed

sdk/python/flet/utils.py

Lines changed: 125 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
import math
12
import os
23
import platform
34
import sys
@@ -111,3 +112,127 @@ def slugify(original: str) -> str:
111112
slugified = slugified.replace(" ", "-")
112113

113114
return slugified
115+
116+
117+
class Vector(complex):
118+
"""
119+
Simple immutable 2D vector class based on the Python complex number type
120+
121+
Create and access - coordinates
122+
123+
>>> v = Vector(1, 2)
124+
>>> v.x, v.y
125+
(1.0, 2.0)
126+
127+
Create and access - angle and magnitude (length)
128+
129+
>>> v = Vector.polar(math.pi, 2)
130+
>>> v
131+
Vector(-2.0, 0.0)
132+
>>> v.magnitude # Length of the vector, alias for abs(v)
133+
2.0
134+
>>> v.radians
135+
3.141592653589793
136+
>>> v.degrees
137+
180.0
138+
139+
Arithmetic operations
140+
141+
>>> Vector(1, 1) + 2
142+
Vector(3.0, 1.0)
143+
>>> Vector(0.1, 0.1) + Vector(0.2, 0.2) == Vector(0.3, 0.3) # Float tolerance 10 decimals
144+
True
145+
>>> Vector(2, 3) - Vector(1, 1)
146+
Vector(1.0, 2.0)
147+
>>> Vector(1, 1) * 2
148+
Vector(2.0, 2.0)
149+
>>> round(Vector.polar(math.pi / 4, 1), 1)
150+
Vector(0.7, 0.7)
151+
152+
Get a new vector by adjusting one of the coordinates
153+
>>> v = Vector()
154+
>>> v.with_x(1)
155+
Vector(1.0, 0.0)
156+
>>> v.with_y(2)
157+
Vector(0.0, 2.0)
158+
159+
Get a new vector by adjusting angle or magnitude
160+
161+
>>> v = Vector(1, 2)
162+
>>> v = v.with_magnitude(4.47213595499958) # Twice as long
163+
>>> v.x, v.y
164+
(2.0, 4.0)
165+
166+
>>> v = Vector.polar(math.pi, 2)
167+
>>> v
168+
Vector(-2.0, 0.0)
169+
>>> v.with_radians(0)
170+
Vector(2.0, 0.0)
171+
>>> v.with_degrees(90)
172+
Vector(0.0, 2.0)
173+
"""
174+
abs_tol = 1e-10
175+
176+
x = complex.real
177+
y = complex.imag
178+
__add__ = lambda self, other: type(self)(complex.__add__(self, other))
179+
__sub__ = lambda self, other: type(self)(complex.__sub__(self, other))
180+
__mul__ = lambda self, other: type(self)(complex.__mul__(self, other))
181+
__truediv__ = lambda self, other: type(self)(complex.__truediv__(self, other))
182+
__len__ = lambda self: 2
183+
__round__ = lambda self, ndigits=None: type(self)(round(self.x, ndigits), round(self.y, ndigits))
184+
185+
def __eq__(self, other):
186+
return (
187+
math.isclose(self.x, other.x, abs_tol=self.abs_tol) and
188+
math.isclose(self.y, other.y, abs_tol=self.abs_tol)
189+
)
190+
191+
def __ne__(self, other):
192+
return not self.__eq__(other)
193+
194+
def __iter__(self):
195+
return iter([self.x, self.y])
196+
197+
def __str__(self):
198+
return str(tuple(self))
199+
200+
def __repr__(self):
201+
return f"{type(self).__name__}{str(self)}"
202+
203+
@classmethod
204+
def polar(cls, radians, magnitude):
205+
return cls(
206+
round(math.cos(radians) * magnitude, 10),
207+
round(math.sin(radians) * magnitude, 10),
208+
)
209+
210+
@property
211+
def magnitude(self):
212+
return abs(self)
213+
214+
@property
215+
def degrees(self):
216+
return math.degrees(self.radians)
217+
218+
@property
219+
def radians(self):
220+
return math.atan2(self.y, self.x)
221+
222+
def with_x(self, value):
223+
return type(self)(value, self.y)
224+
225+
def with_y(self, value):
226+
return type(self)(self.x, value)
227+
228+
def with_magnitude(self, value):
229+
return self * value / abs(self)
230+
231+
def with_radians(self, value):
232+
magnitude = abs(self)
233+
return type(self).polar(value, magnitude)
234+
235+
def with_degrees(self, value):
236+
radians = math.radians(value)
237+
magnitude = abs(self)
238+
return type(self).polar(radians, magnitude)

0 commit comments

Comments
 (0)