Skip to content

Commit 4092a5f

Browse files
committed
refactor: define Point as NamedTuple class to adhere to naming conventions
1 parent fbce887 commit 4092a5f

1 file changed

Lines changed: 60 additions & 31 deletions

File tree

geometry/rotating_calipers.py

Lines changed: 60 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -15,8 +15,21 @@
1515
from __future__ import annotations
1616

1717
import math
18+
from typing import NamedTuple
1819

19-
Point = tuple[float, float]
20+
21+
class Point(NamedTuple):
22+
"""
23+
A 2D point with real-valued coordinates.
24+
25+
>>> Point(0.0, 0.0)
26+
Point(x=0.0, y=0.0)
27+
>>> Point(1.5, -2.0)
28+
Point(x=1.5, y=-2.0)
29+
"""
30+
31+
x: float
32+
y: float
2033

2134

2235
def cross_product(origin: Point, point_a: Point, point_b: Point) -> float:
@@ -29,30 +42,30 @@ def cross_product(origin: Point, point_a: Point, point_b: Point) -> float:
2942
< 0 : Clockwise turn (right turn)
3043
= 0 : Collinear points
3144
32-
>>> cross_product((0.0, 0.0), (1.0, 0.0), (1.0, 1.0))
45+
>>> cross_product(Point(0.0, 0.0), Point(1.0, 0.0), Point(1.0, 1.0))
3346
1.0
34-
>>> cross_product((0.0, 0.0), (1.0, 1.0), (1.0, 0.0))
47+
>>> cross_product(Point(0.0, 0.0), Point(1.0, 1.0), Point(1.0, 0.0))
3548
-1.0
36-
>>> cross_product((0.0, 0.0), (1.0, 1.0), (2.0, 2.0))
49+
>>> cross_product(Point(0.0, 0.0), Point(1.0, 1.0), Point(2.0, 2.0))
3750
0.0
3851
"""
39-
return (point_a[0] - origin[0]) * (point_b[1] - origin[1]) - (
40-
point_a[1] - origin[1]
41-
) * (point_b[0] - origin[0])
52+
return (point_a.x - origin.x) * (point_b.y - origin.y) - (point_a.y - origin.y) * (
53+
point_b.x - origin.x
54+
)
4255

4356

4457
def distance_squared(point_a: Point, point_b: Point) -> float:
4558
"""
4659
Compute the squared Euclidean distance between point_a and point_b.
4760
48-
>>> distance_squared((0.0, 0.0), (3.0, 4.0))
61+
>>> distance_squared(Point(0.0, 0.0), Point(3.0, 4.0))
4962
25.0
50-
>>> distance_squared((1.0, 1.0), (1.0, 1.0))
63+
>>> distance_squared(Point(1.0, 1.0), Point(1.0, 1.0))
5164
0.0
52-
>>> distance_squared((-1.0, -1.0), (2.0, 3.0))
65+
>>> distance_squared(Point(-1.0, -1.0), Point(2.0, 3.0))
5366
25.0
5467
"""
55-
return (point_a[0] - point_b[0]) ** 2 + (point_a[1] - point_b[1]) ** 2
68+
return (point_a.x - point_b.x) ** 2 + (point_a.y - point_b.y) ** 2
5669

5770

5871
def convex_hull(points: list[Point]) -> list[Point]:
@@ -63,14 +76,20 @@ def convex_hull(points: list[Point]) -> list[Point]:
6376
Time Complexity: O(n log n) where n is the number of points.
6477
Space Complexity: O(n)
6578
66-
>>> convex_hull([(0.0, 0.0), (1.0, 1.0)])
67-
[(0.0, 0.0), (1.0, 1.0)]
68-
>>> convex_hull([(0.0, 0.0), (3.0, 0.0), (3.0, 3.0), (0.0, 3.0), (1.0, 1.0)])
69-
[(0.0, 0.0), (3.0, 0.0), (3.0, 3.0), (0.0, 3.0)]
70-
>>> convex_hull([(0.0, 0.0), (1.0, 1.0), (2.0, 2.0)])
71-
[(0.0, 0.0), (2.0, 2.0)]
72-
>>> convex_hull([(1.0, 1.0)])
73-
[(1.0, 1.0)]
79+
>>> convex_hull([Point(0.0, 0.0), Point(1.0, 1.0)])
80+
[Point(x=0.0, y=0.0), Point(x=1.0, y=1.0)]
81+
>>> convex_hull([
82+
... Point(0.0, 0.0),
83+
... Point(3.0, 0.0),
84+
... Point(3.0, 3.0),
85+
... Point(0.0, 3.0),
86+
... Point(1.0, 1.0),
87+
... ])
88+
[Point(x=0.0, y=0.0), Point(x=3.0, y=0.0), Point(x=3.0, y=3.0), Point(x=0.0, y=3.0)]
89+
>>> convex_hull([Point(0.0, 0.0), Point(1.0, 1.0), Point(2.0, 2.0)])
90+
[Point(x=0.0, y=0.0), Point(x=2.0, y=2.0)]
91+
>>> convex_hull([Point(1.0, 1.0)])
92+
[Point(x=1.0, y=1.0)]
7493
"""
7594
unique_points = sorted(set(points))
7695
if len(unique_points) <= 1:
@@ -109,24 +128,34 @@ def rotating_calipers(points: list[Point]) -> tuple[float, tuple[Point, Point]]:
109128
Raises:
110129
ValueError: If fewer than 2 points are provided.
111130
112-
>>> points = [(0.0, 0.0), (3.0, 0.0), (3.0, 4.0), (0.0, 4.0)]
131+
>>> points = [
132+
... Point(0.0, 0.0),
133+
... Point(3.0, 0.0),
134+
... Point(3.0, 4.0),
135+
... Point(0.0, 4.0),
136+
... ]
113137
>>> max_dist, pair = rotating_calipers(points)
114138
>>> max_dist
115139
5.0
116140
>>> pair in [
117-
... ((0.0, 0.0), (3.0, 4.0)),
118-
... ((3.0, 4.0), (0.0, 0.0)),
119-
... ((3.0, 0.0), (0.0, 4.0)),
120-
... ((0.0, 4.0), (3.0, 0.0)),
141+
... (Point(0.0, 0.0), Point(3.0, 4.0)),
142+
... (Point(3.0, 4.0), Point(0.0, 0.0)),
143+
... (Point(3.0, 0.0), Point(0.0, 4.0)),
144+
... (Point(0.0, 4.0), Point(3.0, 0.0)),
121145
... ]
122146
True
123-
>>> rotating_calipers([(0.0, 0.0), (0.0, 5.0)])
124-
(5.0, ((0.0, 0.0), (0.0, 5.0)))
125-
>>> rotating_calipers([(1.0, 1.0), (1.0, 1.0)])
126-
(0.0, ((1.0, 1.0), (1.0, 1.0)))
127-
>>> rotating_calipers([(0.0, 0.0), (1.0, 1.0), (2.0, 2.0), (3.0, 3.0)])[0]
147+
>>> rotating_calipers([Point(0.0, 0.0), Point(0.0, 5.0)])
148+
(5.0, (Point(x=0.0, y=0.0), Point(x=0.0, y=5.0)))
149+
>>> rotating_calipers([Point(1.0, 1.0), Point(1.0, 1.0)])
150+
(0.0, (Point(x=1.0, y=1.0), Point(x=1.0, y=1.0)))
151+
>>> rotating_calipers([
152+
... Point(0.0, 0.0),
153+
... Point(1.0, 1.0),
154+
... Point(2.0, 2.0),
155+
... Point(3.0, 3.0),
156+
... ])[0]
128157
4.242640687119285
129-
>>> rotating_calipers([(1.0, 1.0)])
158+
>>> rotating_calipers([Point(1.0, 1.0)])
130159
Traceback (most recent call last):
131160
...
132161
ValueError: At least 2 points are required to compute polygon diameter.
@@ -140,7 +169,7 @@ def rotating_calipers(points: list[Point]) -> tuple[float, tuple[Point, Point]]:
140169
if hull_size == 1:
141170
return 0.0, (hull[0], hull[0])
142171
if hull_size == 2:
143-
return math.hypot(hull[0][0] - hull[1][0], hull[0][1] - hull[1][1]), (
172+
return math.hypot(hull[0].x - hull[1].x, hull[0].y - hull[1].y), (
144173
hull[0],
145174
hull[1],
146175
)

0 commit comments

Comments
 (0)