physpyx 3.2.0__tar.gz → 3.3.0__tar.gz

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.
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: physpyx
3
- Version: 3.2.0
3
+ Version: 3.3.0
4
4
  Summary: Provides a way to use python code in LaTeX
5
5
  Author: Jérôme Dufour
6
6
  Author-email: Jérôme Dufour <jerome.dufour@eduvaud.ch>
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "physpyx"
3
- version = "3.2.0"
3
+ version = "3.3.0"
4
4
  description = "Provides a way to use python code in LaTeX"
5
5
  readme = "README.md"
6
6
  requires-python = ">=3.13"
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "physpyx"
3
- version = "3.2.0"
3
+ version = "3.3.0"
4
4
  description = "Provides a way to use python code in LaTeX"
5
5
  readme = "README.md"
6
6
  requires-python = ">=3.13"
@@ -79,7 +79,7 @@ class Orbit:
79
79
  raise ValueError(f"{every} is not a divisor {steps} steps")
80
80
 
81
81
  dt = self.T / steps
82
- for i in range(steps + 1):
82
+ for i in range(steps):
83
83
  if i % every == 0:
84
84
  yield self.x
85
85
  self.step(dt)
@@ -108,7 +108,7 @@ class Orbit:
108
108
  vec_t = self.v / vt
109
109
  vec_p = np.array([-vec_t[1], vec_t[0]])
110
110
 
111
- # compute cetripetal acceleration
111
+ # compute centripetal acceleration
112
112
  a = self.get_acceleration()
113
113
  ac = a.dot(vec_p)
114
114
 
@@ -13,8 +13,13 @@ class Coordinate:
13
13
  def norm(self) -> float:
14
14
  return np.sqrt(self.x * self.x + self.y * self.y)
15
15
 
16
- def orientation(self) -> float:
17
- return np.atan2(self.y, self.x) * 180 / np.pi
16
+ def __str__(self) -> str:
17
+ return f"({self.x}, {self.y})"
18
+
19
+ def __eq__(self, other: object) -> bool:
20
+ if not isinstance(other, Coordinate):
21
+ return False
22
+ return bool(np.isclose(self.x, other.x) and np.isclose(self.y, other.y))
18
23
 
19
24
  def __isub__(self, other: "Coordinate") -> Self:
20
25
  self.x -= other.x
@@ -29,6 +34,9 @@ class Coordinate:
29
34
  self.y += other.y
30
35
  return self
31
36
 
37
+ def __add__(self, other: "Coordinate") -> "Coordinate":
38
+ return Coordinate(self.x + other.x, self.y + other.y)
39
+
32
40
  def __mul__(self, number: float) -> "Coordinate":
33
41
  return Coordinate(self.x * number, self.y * number)
34
42
 
@@ -37,14 +45,20 @@ class Coordinate:
37
45
  def __truediv__(self, number: float) -> "Coordinate":
38
46
  return Coordinate(self.x / number, self.y / number)
39
47
 
40
- def __add__(self, other: "Coordinate") -> "Coordinate":
41
- return Coordinate(self.x + other.x, self.y + other.y)
42
-
43
48
  def dot(self, other: "Coordinate") -> float:
44
49
  return self.x * other.x + self.y * other.y
45
50
 
46
- def __str__(self) -> str:
47
- return f"({self.x}, {self.y})"
51
+ def orientation(self) -> float:
52
+ a = np.atan2(self.y, self.x) * 180 / np.pi
53
+ return a + 360 if a < 0 else a
54
+
55
+ def rotate(self, angle: float, deg: bool = True) -> "Coordinate":
56
+ if deg:
57
+ angle *= np.pi / 180
58
+ return Coordinate(
59
+ self.x * np.cos(angle) + self.y * -np.sin(angle),
60
+ self.x * np.sin(angle) + self.y * np.cos(angle),
61
+ )
48
62
 
49
63
 
50
64
  class Rectangle:
@@ -113,6 +127,13 @@ class Circle:
113
127
  def __str__(self) -> str:
114
128
  return f"{self.center} circle ({self.radius})"
115
129
 
130
+ def get_point_on_circle(self, angle: float) -> Coordinate:
131
+ angle *= np.pi / 180
132
+ return self.center + Coordinate(
133
+ self.radius * np.cos(angle),
134
+ self.radius * np.sin(angle),
135
+ )
136
+
116
137
  def tangent_points_to_circle(
117
138
  self, circ: "Circle", lr: LR, io: IO
118
139
  ) -> tuple[Coordinate, Coordinate]:
@@ -194,3 +215,29 @@ class Rope:
194
215
  angle_i, angle_o = self._compute_angles(P1.center, t1, orientation)
195
216
  self._path += f" arc ({angle_i}:{angle_o}:{P1.radius}) -- {t2}"
196
217
  self.current = t2
218
+
219
+
220
+ class Angle:
221
+ def __init__(
222
+ self,
223
+ origin: Coordinate,
224
+ p1: Coordinate,
225
+ p2: Coordinate,
226
+ orient: Circle.ORIENT = Circle.ORIENT.COUNTER_CLOCKWISE,
227
+ ):
228
+ self.origin = origin
229
+ self.p1 = p1
230
+ self.p2 = p2
231
+ self.alpha1 = (self.p1 - self.origin).orientation()
232
+ self.alpha2 = (self.p2 - self.origin).orientation()
233
+ if orient == Circle.ORIENT.CLOCKWISE and self.alpha2 > self.alpha1:
234
+ self.alpha2 -= 360
235
+ elif orient == Circle.ORIENT.COUNTER_CLOCKWISE and self.alpha1 > self.alpha2:
236
+ self.alpha1 -= 360
237
+ self.alpha = self.alpha2 - self.alpha1
238
+
239
+ def angle(self) -> str:
240
+ return rf"{self.p1} -- {self.origin} -- {self.p2}"
241
+
242
+ def arc(self, radius: float) -> str:
243
+ return rf"([shift={{{self.origin}}}]{self.alpha1}:{radius}) arc ({self.alpha1}:{self.alpha2}:{radius})"
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes