-
Notifications
You must be signed in to change notification settings - Fork 5
/
poly_match_v1.py
101 lines (72 loc) · 2.41 KB
/
poly_match_v1.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
from functools import cached_property
from typing import List, Tuple
import numpy as np
from dataclasses import dataclass
Point = np.array
@dataclass
class Polygon:
x: np.array
y: np.array
_area: float = None
@cached_property
def center(self) -> np.array:
centroid = np.array([self.x, self.y]).mean(axis=1)
return centroid
def area(self) -> float:
if self._area is None:
self._area = 0.5 * np.abs(
np.dot(self.x, np.roll(self.y, 1)) - np.dot(self.y, np.roll(self.x, 1))
)
return self._area
def generate_one_polygon() -> Polygon:
x = np.arange(0.0, 1.0, 0.1)
y = np.sqrt(1.0 - x**2)
return Polygon(x=x, y=y)
def generate_example() -> Tuple[List[Polygon], List[np.array]]:
rng = np.random.RandomState(6)
xs = np.arange(0.0, 100.0, 1.0)
rng.shuffle(xs)
ys = np.arange(0.0, 100.0, 1.0)
rng.shuffle(ys)
points = [np.array([x, y]) for x, y in zip(xs, ys)]
ex_poly = generate_one_polygon()
polygons = [
Polygon(
x=ex_poly.x + rng.randint(0.0, 100.0),
y=ex_poly.y + rng.randint(0.0, 100.0),
)
for _ in range(1000)
]
return polygons, points
def find_close_polygons(
polygon_subset: List[Polygon], point: np.array, max_dist: float
) -> List[Polygon]:
close_polygons = []
for poly in polygon_subset:
if np.linalg.norm(poly.center - point) < max_dist:
close_polygons.append(poly)
return close_polygons
def select_best_polygon(
polygon_sets: List[Tuple[Point, List[Polygon]]]
) -> List[Tuple[Point, Polygon]]:
best_polygons = []
for point, polygons in polygon_sets:
best_polygon = polygons[0]
for poly in polygons:
if poly.area() < best_polygon.area():
best_polygon = poly
best_polygons.append((point, best_polygon))
return best_polygons
def main(polygons: List[Polygon], points: np.ndarray) -> List[Tuple[Point, Polygon]]:
max_dist = 10.0
polygon_sets = []
for point in points:
close_polygons = find_close_polygons(polygons, point, max_dist)
if len(close_polygons) == 0:
continue
polygon_sets.append((point, close_polygons))
best_polygons = select_best_polygon(polygon_sets)
return best_polygons
if __name__ == "__main__":
polygons, points = generate_example()
main(polygons, points)