geometry.py

Thu, 30 Jul 2020 21:52:31 +0300

author
Teemu Piippo <teemu@hecknology.net>
date
Thu, 30 Jul 2020 21:52:31 +0300
changeset 2
7378b802ddf8
parent 1
f9788970fa46
permissions
-rw-r--r--

destination processing

1
f9788970fa46 begin work on bus compiler
Teemu Piippo <teemu@hecknology.net>
parents:
diff changeset
1 from math import sqrt, hypot, radians, sin, cos, atan2
f9788970fa46 begin work on bus compiler
Teemu Piippo <teemu@hecknology.net>
parents:
diff changeset
2
f9788970fa46 begin work on bus compiler
Teemu Piippo <teemu@hecknology.net>
parents:
diff changeset
3 class Location:
f9788970fa46 begin work on bus compiler
Teemu Piippo <teemu@hecknology.net>
parents:
diff changeset
4 def __init__(self, latitude, longitude):
f9788970fa46 begin work on bus compiler
Teemu Piippo <teemu@hecknology.net>
parents:
diff changeset
5 self.latitude, self.longitude = latitude, longitude
f9788970fa46 begin work on bus compiler
Teemu Piippo <teemu@hecknology.net>
parents:
diff changeset
6 def distance(self, other):
f9788970fa46 begin work on bus compiler
Teemu Piippo <teemu@hecknology.net>
parents:
diff changeset
7 # https://stackoverflow.com/a/365853
f9788970fa46 begin work on bus compiler
Teemu Piippo <teemu@hecknology.net>
parents:
diff changeset
8 a = sin(radians(self.latitude - other.latitude) / 2) ** 2
f9788970fa46 begin work on bus compiler
Teemu Piippo <teemu@hecknology.net>
parents:
diff changeset
9 a += sin(radians(self.longitude - other.longitude) / 2) ** 2 * cos(radians(self.latitude)) * cos(radians(other.latitude))
f9788970fa46 begin work on bus compiler
Teemu Piippo <teemu@hecknology.net>
parents:
diff changeset
10 return 6371 * 2 * atan2(sqrt(a), sqrt(1 - a))
f9788970fa46 begin work on bus compiler
Teemu Piippo <teemu@hecknology.net>
parents:
diff changeset
11 def __repr__(self):
f9788970fa46 begin work on bus compiler
Teemu Piippo <teemu@hecknology.net>
parents:
diff changeset
12 return '%s(%r, %r)' % (type(self).__name__, self.latitude, self.longitude)
f9788970fa46 begin work on bus compiler
Teemu Piippo <teemu@hecknology.net>
parents:
diff changeset
13 def __str__(self):
f9788970fa46 begin work on bus compiler
Teemu Piippo <teemu@hecknology.net>
parents:
diff changeset
14 return '%.5f, %.5f' % (self.latitude, self.longitude)
f9788970fa46 begin work on bus compiler
Teemu Piippo <teemu@hecknology.net>
parents:
diff changeset
15 @property
f9788970fa46 begin work on bus compiler
Teemu Piippo <teemu@hecknology.net>
parents:
diff changeset
16 def x(self):
f9788970fa46 begin work on bus compiler
Teemu Piippo <teemu@hecknology.net>
parents:
diff changeset
17 return self.latitude
f9788970fa46 begin work on bus compiler
Teemu Piippo <teemu@hecknology.net>
parents:
diff changeset
18 @property
f9788970fa46 begin work on bus compiler
Teemu Piippo <teemu@hecknology.net>
parents:
diff changeset
19 def y(self):
f9788970fa46 begin work on bus compiler
Teemu Piippo <teemu@hecknology.net>
parents:
diff changeset
20 return self.longitude
f9788970fa46 begin work on bus compiler
Teemu Piippo <teemu@hecknology.net>
parents:
diff changeset
21 @property
f9788970fa46 begin work on bus compiler
Teemu Piippo <teemu@hecknology.net>
parents:
diff changeset
22 def link_to_map(self):
f9788970fa46 begin work on bus compiler
Teemu Piippo <teemu@hecknology.net>
parents:
diff changeset
23 return 'http://www.openstreetmap.org/#map=19/%f/%f' % (self.latitude, self.longitude)
f9788970fa46 begin work on bus compiler
Teemu Piippo <teemu@hecknology.net>
parents:
diff changeset
24
f9788970fa46 begin work on bus compiler
Teemu Piippo <teemu@hecknology.net>
parents:
diff changeset
25 class Ring:
f9788970fa46 begin work on bus compiler
Teemu Piippo <teemu@hecknology.net>
parents:
diff changeset
26 def __init__(self, container):
f9788970fa46 begin work on bus compiler
Teemu Piippo <teemu@hecknology.net>
parents:
diff changeset
27 self.container = container
f9788970fa46 begin work on bus compiler
Teemu Piippo <teemu@hecknology.net>
parents:
diff changeset
28 def __getitem__(self, i):
f9788970fa46 begin work on bus compiler
Teemu Piippo <teemu@hecknology.net>
parents:
diff changeset
29 while i < 0:
f9788970fa46 begin work on bus compiler
Teemu Piippo <teemu@hecknology.net>
parents:
diff changeset
30 i += len(self.container)
f9788970fa46 begin work on bus compiler
Teemu Piippo <teemu@hecknology.net>
parents:
diff changeset
31 while i >= len(self.container):
f9788970fa46 begin work on bus compiler
Teemu Piippo <teemu@hecknology.net>
parents:
diff changeset
32 i -= len(self.container)
f9788970fa46 begin work on bus compiler
Teemu Piippo <teemu@hecknology.net>
parents:
diff changeset
33 return self.container[i]
f9788970fa46 begin work on bus compiler
Teemu Piippo <teemu@hecknology.net>
parents:
diff changeset
34 def __iter__(self):
f9788970fa46 begin work on bus compiler
Teemu Piippo <teemu@hecknology.net>
parents:
diff changeset
35 return iter(self.container)
f9788970fa46 begin work on bus compiler
Teemu Piippo <teemu@hecknology.net>
parents:
diff changeset
36 def __len__(self):
f9788970fa46 begin work on bus compiler
Teemu Piippo <teemu@hecknology.net>
parents:
diff changeset
37 return len(self.container)
f9788970fa46 begin work on bus compiler
Teemu Piippo <teemu@hecknology.net>
parents:
diff changeset
38
f9788970fa46 begin work on bus compiler
Teemu Piippo <teemu@hecknology.net>
parents:
diff changeset
39 class Polygon:
f9788970fa46 begin work on bus compiler
Teemu Piippo <teemu@hecknology.net>
parents:
diff changeset
40 def __init__(self, *points):
f9788970fa46 begin work on bus compiler
Teemu Piippo <teemu@hecknology.net>
parents:
diff changeset
41 self.points = points
f9788970fa46 begin work on bus compiler
Teemu Piippo <teemu@hecknology.net>
parents:
diff changeset
42 def __repr__(self):
f9788970fa46 begin work on bus compiler
Teemu Piippo <teemu@hecknology.net>
parents:
diff changeset
43 return '%s(%s)' % (type(self).__name__, ', '.join(map(repr, self.points)))
f9788970fa46 begin work on bus compiler
Teemu Piippo <teemu@hecknology.net>
parents:
diff changeset
44 def area(self):
f9788970fa46 begin work on bus compiler
Teemu Piippo <teemu@hecknology.net>
parents:
diff changeset
45 ring = Ring(self.points)
f9788970fa46 begin work on bus compiler
Teemu Piippo <teemu@hecknology.net>
parents:
diff changeset
46 return sum(
f9788970fa46 begin work on bus compiler
Teemu Piippo <teemu@hecknology.net>
parents:
diff changeset
47 ring[i].x * ring[i + 1].y - ring[i + 1].x * ring[i].y
f9788970fa46 begin work on bus compiler
Teemu Piippo <teemu@hecknology.net>
parents:
diff changeset
48 for i in range(len(ring))
f9788970fa46 begin work on bus compiler
Teemu Piippo <teemu@hecknology.net>
parents:
diff changeset
49 ) / 2
f9788970fa46 begin work on bus compiler
Teemu Piippo <teemu@hecknology.net>
parents:
diff changeset
50 def circumference(self):
f9788970fa46 begin work on bus compiler
Teemu Piippo <teemu@hecknology.net>
parents:
diff changeset
51 ring = Ring(self.points)
f9788970fa46 begin work on bus compiler
Teemu Piippo <teemu@hecknology.net>
parents:
diff changeset
52 return sum(
f9788970fa46 begin work on bus compiler
Teemu Piippo <teemu@hecknology.net>
parents:
diff changeset
53 sqrt((ring[i + 1].x - ring[i].x)**2 + (ring[i + 1].y - ring[i].y)**2)
f9788970fa46 begin work on bus compiler
Teemu Piippo <teemu@hecknology.net>
parents:
diff changeset
54 for i in range(len(ring))
f9788970fa46 begin work on bus compiler
Teemu Piippo <teemu@hecknology.net>
parents:
diff changeset
55 )
f9788970fa46 begin work on bus compiler
Teemu Piippo <teemu@hecknology.net>
parents:
diff changeset
56 def centroid(self):
f9788970fa46 begin work on bus compiler
Teemu Piippo <teemu@hecknology.net>
parents:
diff changeset
57 ring = Ring(self.points)
f9788970fa46 begin work on bus compiler
Teemu Piippo <teemu@hecknology.net>
parents:
diff changeset
58 x = sum(
f9788970fa46 begin work on bus compiler
Teemu Piippo <teemu@hecknology.net>
parents:
diff changeset
59 (ring[i].x + ring[i + 1].x) * (ring[i].x * ring[i + 1].y - ring[i + 1].x * ring[i].y)
f9788970fa46 begin work on bus compiler
Teemu Piippo <teemu@hecknology.net>
parents:
diff changeset
60 for i in range(len(ring))
f9788970fa46 begin work on bus compiler
Teemu Piippo <teemu@hecknology.net>
parents:
diff changeset
61 ) / 6 / self.area()
f9788970fa46 begin work on bus compiler
Teemu Piippo <teemu@hecknology.net>
parents:
diff changeset
62 y = sum(
f9788970fa46 begin work on bus compiler
Teemu Piippo <teemu@hecknology.net>
parents:
diff changeset
63 (ring[i].y + ring[i + 1].y) * (ring[i].x * ring[i + 1].y - ring[i + 1].x * ring[i].y)
f9788970fa46 begin work on bus compiler
Teemu Piippo <teemu@hecknology.net>
parents:
diff changeset
64 for i in range(len(ring))
f9788970fa46 begin work on bus compiler
Teemu Piippo <teemu@hecknology.net>
parents:
diff changeset
65 ) / 6 / self.area()
f9788970fa46 begin work on bus compiler
Teemu Piippo <teemu@hecknology.net>
parents:
diff changeset
66 return self.point_type()(x, y)
f9788970fa46 begin work on bus compiler
Teemu Piippo <teemu@hecknology.net>
parents:
diff changeset
67 def point_type(self):
f9788970fa46 begin work on bus compiler
Teemu Piippo <teemu@hecknology.net>
parents:
diff changeset
68 if len(self.points):
f9788970fa46 begin work on bus compiler
Teemu Piippo <teemu@hecknology.net>
parents:
diff changeset
69 return type(self.points[0])
f9788970fa46 begin work on bus compiler
Teemu Piippo <teemu@hecknology.net>
parents:
diff changeset
70 else:
f9788970fa46 begin work on bus compiler
Teemu Piippo <teemu@hecknology.net>
parents:
diff changeset
71 return Point
f9788970fa46 begin work on bus compiler
Teemu Piippo <teemu@hecknology.net>
parents:
diff changeset
72 def segments(self):
f9788970fa46 begin work on bus compiler
Teemu Piippo <teemu@hecknology.net>
parents:
diff changeset
73 ring = Ring(self.points)
f9788970fa46 begin work on bus compiler
Teemu Piippo <teemu@hecknology.net>
parents:
diff changeset
74 for i in range(len(ring)):
f9788970fa46 begin work on bus compiler
Teemu Piippo <teemu@hecknology.net>
parents:
diff changeset
75 yield LineSegment(ring[i], ring[i + 1])
f9788970fa46 begin work on bus compiler
Teemu Piippo <teemu@hecknology.net>
parents:
diff changeset
76 def contains_point(self, point):
f9788970fa46 begin work on bus compiler
Teemu Piippo <teemu@hecknology.net>
parents:
diff changeset
77 outer_point = self.point_type()(
f9788970fa46 begin work on bus compiler
Teemu Piippo <teemu@hecknology.net>
parents:
diff changeset
78 min(point.x for point in self.points) - 1,
f9788970fa46 begin work on bus compiler
Teemu Piippo <teemu@hecknology.net>
parents:
diff changeset
79 min(point.y for point in self.points) - 1
f9788970fa46 begin work on bus compiler
Teemu Piippo <teemu@hecknology.net>
parents:
diff changeset
80 )
f9788970fa46 begin work on bus compiler
Teemu Piippo <teemu@hecknology.net>
parents:
diff changeset
81 outer_segment = LineSegment(point, outer_point)
f9788970fa46 begin work on bus compiler
Teemu Piippo <teemu@hecknology.net>
parents:
diff changeset
82 intersections = 0
f9788970fa46 begin work on bus compiler
Teemu Piippo <teemu@hecknology.net>
parents:
diff changeset
83 for segment in self.segments():
f9788970fa46 begin work on bus compiler
Teemu Piippo <teemu@hecknology.net>
parents:
diff changeset
84 if segment.intersection(outer_segment) is not None:
f9788970fa46 begin work on bus compiler
Teemu Piippo <teemu@hecknology.net>
parents:
diff changeset
85 intersections += 1
f9788970fa46 begin work on bus compiler
Teemu Piippo <teemu@hecknology.net>
parents:
diff changeset
86 return bool(intersections & 1)
f9788970fa46 begin work on bus compiler
Teemu Piippo <teemu@hecknology.net>
parents:
diff changeset
87
f9788970fa46 begin work on bus compiler
Teemu Piippo <teemu@hecknology.net>
parents:
diff changeset
88 class LineSegment:
f9788970fa46 begin work on bus compiler
Teemu Piippo <teemu@hecknology.net>
parents:
diff changeset
89 def __init__(self, p1, p2):
f9788970fa46 begin work on bus compiler
Teemu Piippo <teemu@hecknology.net>
parents:
diff changeset
90 self.p1, self.p2 = p1, p2
f9788970fa46 begin work on bus compiler
Teemu Piippo <teemu@hecknology.net>
parents:
diff changeset
91 def __repr__(self):
f9788970fa46 begin work on bus compiler
Teemu Piippo <teemu@hecknology.net>
parents:
diff changeset
92 return 'LineSegment(%r, %r)' % (self.p1, self.p2)
f9788970fa46 begin work on bus compiler
Teemu Piippo <teemu@hecknology.net>
parents:
diff changeset
93 def length(self):
f9788970fa46 begin work on bus compiler
Teemu Piippo <teemu@hecknology.net>
parents:
diff changeset
94 return hypot(self.p1.x - self.p2.x, self.p1.y - self.p2.y)
f9788970fa46 begin work on bus compiler
Teemu Piippo <teemu@hecknology.net>
parents:
diff changeset
95 def intersection(self, other):
f9788970fa46 begin work on bus compiler
Teemu Piippo <teemu@hecknology.net>
parents:
diff changeset
96 point_type = type(self.p1)
f9788970fa46 begin work on bus compiler
Teemu Piippo <teemu@hecknology.net>
parents:
diff changeset
97 x = (self.p1.x, self.p2.x, other.p1.x, other.p2.x)
f9788970fa46 begin work on bus compiler
Teemu Piippo <teemu@hecknology.net>
parents:
diff changeset
98 y = (self.p1.y, self.p2.y, other.p1.y, other.p2.y)
f9788970fa46 begin work on bus compiler
Teemu Piippo <teemu@hecknology.net>
parents:
diff changeset
99 try:
f9788970fa46 begin work on bus compiler
Teemu Piippo <teemu@hecknology.net>
parents:
diff changeset
100 denominator = (x[0] - x[1]) * (y[2] - y[3]) - (y[0] - y[1]) * (x[2] - x[3])
f9788970fa46 begin work on bus compiler
Teemu Piippo <teemu@hecknology.net>
parents:
diff changeset
101 Px = ((x[0] * y[1] - y[0] * x[1]) * (x[2] - x[3]) - (x[0] - x[1]) * (x[2] * y[3] - y[2] * x[3])) / denominator
f9788970fa46 begin work on bus compiler
Teemu Piippo <teemu@hecknology.net>
parents:
diff changeset
102 Py = ((x[0] * y[1] - y[0] * x[1]) * (y[2] - y[3]) - (y[0] - y[1]) * (x[2] * y[3] - y[2] * x[3])) / denominator
f9788970fa46 begin work on bus compiler
Teemu Piippo <teemu@hecknology.net>
parents:
diff changeset
103 distance = lambda n: hypot(Px - x[n], Py - y[n])
f9788970fa46 begin work on bus compiler
Teemu Piippo <teemu@hecknology.net>
parents:
diff changeset
104 if max(distance(0), distance(1)) <= self.length() and max(distance(2), distance(3)) <= other.length():
f9788970fa46 begin work on bus compiler
Teemu Piippo <teemu@hecknology.net>
parents:
diff changeset
105 return point_type(Px, Py)
f9788970fa46 begin work on bus compiler
Teemu Piippo <teemu@hecknology.net>
parents:
diff changeset
106 else:
f9788970fa46 begin work on bus compiler
Teemu Piippo <teemu@hecknology.net>
parents:
diff changeset
107 return None
f9788970fa46 begin work on bus compiler
Teemu Piippo <teemu@hecknology.net>
parents:
diff changeset
108 except ZeroDivisionError:
f9788970fa46 begin work on bus compiler
Teemu Piippo <teemu@hecknology.net>
parents:
diff changeset
109 return None
f9788970fa46 begin work on bus compiler
Teemu Piippo <teemu@hecknology.net>
parents:
diff changeset
110
f9788970fa46 begin work on bus compiler
Teemu Piippo <teemu@hecknology.net>
parents:
diff changeset
111 class Point:
f9788970fa46 begin work on bus compiler
Teemu Piippo <teemu@hecknology.net>
parents:
diff changeset
112 def __init__(self, x, y):
f9788970fa46 begin work on bus compiler
Teemu Piippo <teemu@hecknology.net>
parents:
diff changeset
113 self.x, self.y = x, y
f9788970fa46 begin work on bus compiler
Teemu Piippo <teemu@hecknology.net>
parents:
diff changeset
114 def __repr__(self):
f9788970fa46 begin work on bus compiler
Teemu Piippo <teemu@hecknology.net>
parents:
diff changeset
115 return 'Point(%r, %r)' % (self.x, self.y)
f9788970fa46 begin work on bus compiler
Teemu Piippo <teemu@hecknology.net>
parents:
diff changeset
116
f9788970fa46 begin work on bus compiler
Teemu Piippo <teemu@hecknology.net>
parents:
diff changeset
117 A = Polygon(
f9788970fa46 begin work on bus compiler
Teemu Piippo <teemu@hecknology.net>
parents:
diff changeset
118 Point(2,3),
f9788970fa46 begin work on bus compiler
Teemu Piippo <teemu@hecknology.net>
parents:
diff changeset
119 Point(1,1),
f9788970fa46 begin work on bus compiler
Teemu Piippo <teemu@hecknology.net>
parents:
diff changeset
120 Point(4,0),
f9788970fa46 begin work on bus compiler
Teemu Piippo <teemu@hecknology.net>
parents:
diff changeset
121 Point(6,2),
f9788970fa46 begin work on bus compiler
Teemu Piippo <teemu@hecknology.net>
parents:
diff changeset
122 Point(4,4))
f9788970fa46 begin work on bus compiler
Teemu Piippo <teemu@hecknology.net>
parents:
diff changeset
123 L1 = LineSegment(Point(1, 1), Point(-1, 5))
f9788970fa46 begin work on bus compiler
Teemu Piippo <teemu@hecknology.net>
parents:
diff changeset
124 L2 = LineSegment(Point(1, 5), Point(5, 1))

mercurial