pfc-geometry 0.2.20__tar.gz → 0.2.21__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.
- {pfc_geometry-0.2.20 → pfc_geometry-0.2.21}/PKG-INFO +1 -2
- {pfc_geometry-0.2.20 → pfc_geometry-0.2.21}/pyproject.toml +1 -2
- {pfc_geometry-0.2.20 → pfc_geometry-0.2.21}/src/geometry/__init__.py +2 -1
- pfc_geometry-0.2.21/src/geometry/air.py +20 -0
- {pfc_geometry-0.2.20 → pfc_geometry-0.2.21}/src/geometry/angles.py +6 -1
- {pfc_geometry-0.2.20 → pfc_geometry-0.2.21}/src/geometry/coordinate_frame.py +4 -2
- {pfc_geometry-0.2.20 → pfc_geometry-0.2.21}/src/geometry/point.py +13 -6
- {pfc_geometry-0.2.20 → pfc_geometry-0.2.21}/src/geometry/time.py +2 -2
- {pfc_geometry-0.2.20 → pfc_geometry-0.2.21}/src/geometry/transformation.py +2 -1
- {pfc_geometry-0.2.20 → pfc_geometry-0.2.21}/tests/test_quaternion.py +0 -2
- {pfc_geometry-0.2.20 → pfc_geometry-0.2.21}/.dockerignore +0 -0
- {pfc_geometry-0.2.20 → pfc_geometry-0.2.21}/.github/workflows/publish_pypi.yml +0 -0
- {pfc_geometry-0.2.20 → pfc_geometry-0.2.21}/.gitignore +0 -0
- {pfc_geometry-0.2.20 → pfc_geometry-0.2.21}/LICENSE +0 -0
- {pfc_geometry-0.2.20 → pfc_geometry-0.2.21}/README.md +0 -0
- {pfc_geometry-0.2.20 → pfc_geometry-0.2.21}/src/geometry/base.py +0 -0
- {pfc_geometry-0.2.20 → pfc_geometry-0.2.21}/src/geometry/checks.py +0 -0
- {pfc_geometry-0.2.20 → pfc_geometry-0.2.21}/src/geometry/gps.py +0 -0
- {pfc_geometry-0.2.20 → pfc_geometry-0.2.21}/src/geometry/mass.py +0 -0
- {pfc_geometry-0.2.20 → pfc_geometry-0.2.21}/src/geometry/py.typed +0 -0
- {pfc_geometry-0.2.20 → pfc_geometry-0.2.21}/src/geometry/quaternion.py +0 -0
- {pfc_geometry-0.2.20 → pfc_geometry-0.2.21}/src/geometry/utils.py +0 -0
- {pfc_geometry-0.2.20 → pfc_geometry-0.2.21}/tests/__init__.py +0 -0
- {pfc_geometry-0.2.20 → pfc_geometry-0.2.21}/tests/test_angles.py +0 -0
- {pfc_geometry-0.2.20 → pfc_geometry-0.2.21}/tests/test_base.py +0 -0
- {pfc_geometry-0.2.20 → pfc_geometry-0.2.21}/tests/test_coord.py +0 -0
- {pfc_geometry-0.2.20 → pfc_geometry-0.2.21}/tests/test_gps.py +0 -0
- {pfc_geometry-0.2.20 → pfc_geometry-0.2.21}/tests/test_mass.py +0 -0
- {pfc_geometry-0.2.20 → pfc_geometry-0.2.21}/tests/test_point.py +0 -0
- {pfc_geometry-0.2.20 → pfc_geometry-0.2.21}/tests/test_remove_outliers.csv +0 -0
- {pfc_geometry-0.2.20 → pfc_geometry-0.2.21}/tests/test_time.py +0 -0
- {pfc_geometry-0.2.20 → pfc_geometry-0.2.21}/tests/test_transform.py +0 -0
- {pfc_geometry-0.2.20 → pfc_geometry-0.2.21}/tests/test_utils.py +0 -0
- {pfc_geometry-0.2.20 → pfc_geometry-0.2.21}/uv.lock +0 -0
|
@@ -1,10 +1,9 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: pfc-geometry
|
|
3
|
-
Version: 0.2.
|
|
3
|
+
Version: 0.2.21
|
|
4
4
|
Summary: A library for working with 3D geometry.
|
|
5
5
|
License-File: LICENSE
|
|
6
6
|
Requires-Python: >=3.12
|
|
7
|
-
Requires-Dist: numpy-quaternion>=2024.0.7
|
|
8
7
|
Requires-Dist: numpy>=2.1.3
|
|
9
8
|
Requires-Dist: pandas>=2.2.3
|
|
10
9
|
Requires-Dist: rowan>=1.3.2
|
|
@@ -1,11 +1,10 @@
|
|
|
1
1
|
[project]
|
|
2
2
|
name = "pfc-geometry"
|
|
3
|
-
version="0.2.
|
|
3
|
+
version="0.2.21"
|
|
4
4
|
description = "A library for working with 3D geometry."
|
|
5
5
|
readme = "README.md"
|
|
6
6
|
requires-python = ">=3.12"
|
|
7
7
|
dependencies = [
|
|
8
|
-
"numpy-quaternion>=2024.0.7",
|
|
9
8
|
"numpy>=2.1.3",
|
|
10
9
|
"pandas>=2.2.3",
|
|
11
10
|
"rowan>=1.3.2",
|
|
@@ -18,7 +18,8 @@ from .gps import GPS
|
|
|
18
18
|
from .coordinate_frame import Coord
|
|
19
19
|
from .transformation import Transformation
|
|
20
20
|
from .mass import Mass
|
|
21
|
-
|
|
21
|
+
from .air import Air
|
|
22
|
+
from .angles import wrap_to_pi
|
|
22
23
|
|
|
23
24
|
def Euler(*args, **kwargs) -> Quaternion:
|
|
24
25
|
return Quaternion.from_euler(Point(*args, **kwargs))
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
from geometry.base import Base
|
|
2
|
+
|
|
3
|
+
R = 287.058
|
|
4
|
+
GAMMA = 1.4
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
def get_rho(pressure, temperature):
|
|
8
|
+
return pressure / (R * temperature)
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
class Air(Base):
|
|
12
|
+
cols = ["P", "T", "rho"]
|
|
13
|
+
|
|
14
|
+
@staticmethod
|
|
15
|
+
def iso_sea_level(length: int):
|
|
16
|
+
return Air(101325, 288.15, get_rho(101325, 288.15)).tile(length)
|
|
17
|
+
|
|
18
|
+
@staticmethod
|
|
19
|
+
def from_pt(pressure, temperature):
|
|
20
|
+
return Air(pressure, temperature, get_rho(pressure, temperature))
|
|
@@ -88,7 +88,7 @@ class Coord(Base):
|
|
|
88
88
|
def axes(self):
|
|
89
89
|
return Point.concatenate([self.x_axis, self.y_axis, self.z_axis])
|
|
90
90
|
|
|
91
|
-
def plot(self, fig=None, scale=1, label: str = None):
|
|
91
|
+
def plot(self, fig=None, scale=1, width=2, label: str = None):
|
|
92
92
|
import plotly.graph_objects as go
|
|
93
93
|
if fig is None:
|
|
94
94
|
fig = go.Figure(layout=dict(scene=dict(aspectmode="data")))
|
|
@@ -105,6 +105,7 @@ class Coord(Base):
|
|
|
105
105
|
mode="markers",
|
|
106
106
|
name="Origin",
|
|
107
107
|
marker=dict(size=5, color="black"),
|
|
108
|
+
showlegend=False
|
|
108
109
|
)
|
|
109
110
|
)
|
|
110
111
|
colors = ["red", "green", "blue"]
|
|
@@ -116,7 +117,8 @@ class Coord(Base):
|
|
|
116
117
|
z=[self.origin.z[0], (self.origin.z + axis.z * scale)[0]],
|
|
117
118
|
mode="lines",
|
|
118
119
|
name=f"{label or 'Axis'} {Point.cols[i]}",
|
|
119
|
-
line=dict(width=
|
|
120
|
+
line=dict(width=width, color=colors.pop(0)),
|
|
121
|
+
showlegend=False
|
|
120
122
|
)
|
|
121
123
|
)
|
|
122
124
|
return fig
|
|
@@ -272,7 +272,7 @@ def angle_between(a: Point, b: Point) -> np.ndarray:
|
|
|
272
272
|
|
|
273
273
|
@ppmeth
|
|
274
274
|
def scalar_projection(a: Point, b: Point) -> Point:
|
|
275
|
-
return
|
|
275
|
+
return cos_angle_between(a, b) * abs(a)
|
|
276
276
|
|
|
277
277
|
|
|
278
278
|
@ppmeth
|
|
@@ -284,21 +284,28 @@ def vector_projection(a: Point, b: Point) -> Point:
|
|
|
284
284
|
def vector_rejection(a: Point, b: Point) -> Point:
|
|
285
285
|
return a - ((Point.dot(a, b)) / Point.dot(b, b)) * b
|
|
286
286
|
|
|
287
|
+
@ppmeth
|
|
288
|
+
def min_angle_between(p1: Point, p2: Point):
|
|
289
|
+
angle = angle_between(p1, p2) % np.pi
|
|
290
|
+
return np.minimum(angle, np.pi - angle)
|
|
287
291
|
|
|
288
292
|
@ppmeth
|
|
289
293
|
def is_parallel(a: Point, b: Point, tolerance=1e-6):
|
|
290
294
|
return abs(a.cos_angle_between(b) - 1) < tolerance
|
|
291
295
|
|
|
296
|
+
@ppmeth
|
|
297
|
+
def is_anti_parallel(a: Point, b: Point, tolerance=1e-6):
|
|
298
|
+
return abs(a.cos_angle_between(-b) - 1) < tolerance
|
|
299
|
+
|
|
292
300
|
|
|
293
301
|
@ppmeth
|
|
294
|
-
def
|
|
295
|
-
return
|
|
302
|
+
def is_either_parallel(a: Point, b: Point, tolerance=1e-6):
|
|
303
|
+
return min_angle_between(a, b) < tolerance
|
|
296
304
|
|
|
297
305
|
|
|
298
306
|
@ppmeth
|
|
299
|
-
def
|
|
300
|
-
|
|
301
|
-
return np.minimum(angle, np.pi - angle)
|
|
307
|
+
def is_perpendicular(a: Point, b: Point, tolerance=1e-6):
|
|
308
|
+
return abs(a.dot(b)) < tolerance
|
|
302
309
|
|
|
303
310
|
|
|
304
311
|
def vector_norm(point: Point):
|
|
@@ -25,12 +25,12 @@ class Time(Base):
|
|
|
25
25
|
return Time(t, dt)
|
|
26
26
|
|
|
27
27
|
@staticmethod
|
|
28
|
-
def uniform(duration: float, npoints: int | None, minpoints: int = 1) -> Time:
|
|
28
|
+
def uniform(duration: float, npoints: int | None, minpoints: int = 1, freq=25) -> Time:
|
|
29
29
|
return Time.from_t(
|
|
30
30
|
np.linspace(
|
|
31
31
|
0,
|
|
32
32
|
duration,
|
|
33
|
-
npoints if npoints else max(int(np.ceil(duration *
|
|
33
|
+
npoints if npoints else max(int(np.ceil(duration * freq)), minpoints),
|
|
34
34
|
)
|
|
35
35
|
)
|
|
36
36
|
|
|
@@ -9,6 +9,7 @@ FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
|
|
|
9
9
|
You should have received a copy of the GNU General Public License along with
|
|
10
10
|
this program. If not, see <http://www.gnu.org/licenses/>.
|
|
11
11
|
"""
|
|
12
|
+
from __future__ import annotations
|
|
12
13
|
from geometry import Base, Point, Quaternion, P0, Q0, Coord
|
|
13
14
|
|
|
14
15
|
import numpy as np
|
|
@@ -54,7 +55,7 @@ class Transformation(Base):
|
|
|
54
55
|
raise AttributeError(name)
|
|
55
56
|
|
|
56
57
|
@staticmethod
|
|
57
|
-
def build(p:Point, q:Quaternion):
|
|
58
|
+
def build(p:Point, q:Quaternion) -> Transformation:
|
|
58
59
|
if len(p) == len(q):
|
|
59
60
|
return Transformation(np.concatenate([
|
|
60
61
|
p.data,
|
|
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
|
|
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
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|