-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathcommon.py
110 lines (84 loc) · 3.04 KB
/
common.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
102
103
104
105
106
107
108
109
110
import bisect
from collections import namedtuple
from scipy.spatial.distance import euclidean
NO_QUADRANT = -1
NORTH_WEST = 1
NORTH_EAST = 2
SOUTH_EAST = 3
SOUTH_WEST = 4
# Constants for tuple access optimzation
CENTER = 0
DIMENSION = 1
X = 0
Y = 1
Point = namedtuple('Point', ['x', 'y'])
Boundary = namedtuple('Boundary', ['center', 'dimension'])
def belongs(boundary, point):
""" Check if the point belongs to the boundary """
if not point:
return False
d = boundary[DIMENSION]
cx, cy = boundary[CENTER]
px, py = point
return (py <= cy + d and py >= cy - d) and (px <= cx + d and px >= cx - d)
def quadrants(boundary, point):
""" Find in which quadrant the point belongs to """
if not isinstance(boundary, Boundary) or \
not isinstance(point, Point):
return False
d = boundary[DIMENSION]
cx, cy = boundary[CENTER]
px, py = point
if (py <= cy + d and py >= cy) and (px >= cx - d and px <= cx):
return NORTH_WEST
if (py <= cy + d and py >= cy) and (px <= cx + d and px >= cx):
return NORTH_EAST
if (py >= cy - d and py <= cy) and (px <= cx + d and px >= cx):
return SOUTH_EAST
if (py >= cy - d and py <= cy) and (px >= cx - d and px <= cx):
return SOUTH_WEST
return NO_QUADRANT
def intersects(boundary0, boundary1):
""" Check if the given boundary intersects this boundary """
if not boundary0 or not boundary1:
return False
ad = boundary0[DIMENSION]
aleft = boundary0[CENTER][X] - ad
aright = boundary0[CENTER][X] + ad
atop = boundary0[CENTER][Y] + ad
abottom = boundary0[CENTER][Y] - ad
bd = boundary1[DIMENSION]
bleft = boundary1[CENTER][X] - bd
bright = boundary1[CENTER][X] + bd
btop = boundary1[CENTER][Y] + bd
bbottom = boundary1[CENTER][Y] - bd
intersect_left = bright > aleft and bleft < aleft
intersect_right = bleft < aright and bright > aright
intersect_top = bbottom < atop and btop > atop
intersect_bottom= btop > abottom and bbottom < abottom
intersect_inside = (atop > btop and abottom < bbottom) or\
(aleft < bleft and aright > bright)
return intersect_top and intersect_left or\
intersect_top and intersect_right or\
intersect_bottom and intersect_left or\
intersect_bottom and intersect_right or\
intersect_inside
def compute_knn(points, point, k):
neighbors = []
distant_neighbor = None
for p in points:
if p == point: continue
dist = euclidean(point, p)
neighbor = (dist, p)
if len(neighbors) < k:
if not distant_neighbor:
distant_neighbor = neighbor
if neighbor[0] > distant_neighbor[0]:
distant_neighbor = neighbor
bisect.insort(neighbors, neighbor)
continue
if neighbor[0] < distant_neighbor[0]:
del neighbors[-1]
bisect.insort(neighbors, neighbor)
distant_neighbor = neighbors[-1]
return neighbors