Skip to content

Commit 3b885b5

Browse files
committed
Added polar conversions to Coordinate
1 parent 5333943 commit 3b885b5

File tree

2 files changed

+63
-1
lines changed

2 files changed

+63
-1
lines changed

src/geocompy/data.py

Lines changed: 48 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -913,4 +913,51 @@ class Coordinate(Vector):
913913
914914
"""
915915

916-
# SIM = 0x04000 # TPSSim
916+
@classmethod
917+
def from_polar(
918+
cls,
919+
hz: Angle,
920+
v: Angle,
921+
dist: float
922+
) -> Self:
923+
"""
924+
Constructs 3D cartesian coordinate from polar coordinate.
925+
926+
Parameters
927+
----------
928+
hz : Angle
929+
Horizontal angle.
930+
v : Angle
931+
Vertical angle.
932+
dist : float
933+
Slope distance.
934+
935+
Returns
936+
-------
937+
Coordinate
938+
"""
939+
dist2d = math.sin(v) * dist
940+
x = math.sin(hz) * dist2d
941+
y = math.cos(hz) * dist2d
942+
z = math.cos(v) * dist
943+
944+
return cls(x, y, z)
945+
946+
def to_polar(self) -> tuple[Angle, Angle, float]:
947+
"""
948+
Converts 3D cartesian coordinates to polar coordinates.
949+
950+
Returns
951+
-------
952+
tuple
953+
Horizontal and vertical angles and slope distance.
954+
"""
955+
dist2d = math.sqrt(self.x**2 + self.y**2)
956+
dist = math.sqrt(dist2d**2 + self.z**2)
957+
hz = math.atan2(self.x, self.y)
958+
v = math.atan2(dist2d, self.z)
959+
return (
960+
Angle(hz, normalize=True, positive=True),
961+
Angle(v, normalize=True, positive=True),
962+
dist
963+
)

tests/test_data.py

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
import math
12
from enum import Enum
23

34
import pytest
@@ -156,3 +157,17 @@ def test_arithmetic(self):
156157
assert type(+c1) is Coordinate
157158
c3 = +c1
158159
assert c3 is not c1
160+
161+
def test_polar(self):
162+
c1 = Coordinate(-1, -1, -1)
163+
p1 = c1.to_polar()
164+
165+
assert float(p1[0]) == approx(math.radians(225))
166+
assert float(p1[1]) == approx(math.radians(125.2643897))
167+
assert p1[2] == approx(math.sqrt(3))
168+
169+
c2 = Coordinate.from_polar(*p1)
170+
171+
assert c1.x == approx(c2.x)
172+
assert c1.y == approx(c2.y)
173+
assert c1.z == approx(c2.z)

0 commit comments

Comments
 (0)