-
Notifications
You must be signed in to change notification settings - Fork 0
/
cell.py
88 lines (73 loc) · 2.38 KB
/
cell.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
from __future__ import division
import collections
import itertools
import math
class Cell(object):
"""
Representation of a 2D or 3D point in space.
"""
def __init__(self, x=0, y=0, z=0):
"""
Initialize with any of x, y or z coordinates.
"""
if isinstance(x, tuple):
self.x, self.y, self.z = 0, 0, 0 # init
if len(x) > 0:
self.x = x[0]
if len(x) > 1:
self.y = x[1]
if len(x) > 2:
self.z = x[2]
else:
self.x = x
self.y = y
self.z = z
def neighbours(self, ndims=2):
"""
Get 8 neighbouring cell coords to a start cell.
"""
offsets = list(itertools.product([0, 1, -1], repeat=2))
del offsets[offsets.index((0, 0))] # Don't include self
return [Cell(self.x + dx, self.y + dy, self.z) for dx, dy in offsets]
def distance(self, point, squared=False, ndims=2):
"""
Calculate distance between two points using Pythagorean theorem.
"""
d_squared = (point.x - self.x) ** 2 + (point.y - self.y) ** 2
if squared:
return d_squared
else:
return math.sqrt(d_squared)
def tuple(self, dimensions='3D'):
"""
Convert a cell to 2D or 3D tuple.
"""
if '2' in dimensions:
return (self.x, self.y)
else:
return tuple(self)
def __eq__(self, other):
return all([self.x == other.x, self.y == other.y, self.z == other.z])
def __iter__(self):
return iter([self.x, self.y, self.z])
def __hash__(self):
return hash(repr(self))
def __str__(self):
return '({}, {}, {})'.format(self.x, self.y, self.z)
def __repr__(self):
return 'cell.Cell({}, {}, {})'.format(self.x, self.y, self.z)
def restrict_quadrants(neighbours, start, end):
"""
Only return the quadrants of a set of neighbours that are
oriented in the direction of 'end' Cell.
"""
cells = neighbours[:]
if end.x > start.x:
cells = [x for x in cells if x.x >= start.x]
elif end.x < start.x:
cells = [x for x in cells if x.x <= start.x]
if end.y > start.y:
cells = [x for x in cells if x.y >= start.y]
elif end.y < start.y:
cells = [x for x in cells if x.y <= start.y]
return cells