compute_regions.py

Fri, 05 Feb 2021 12:16:29 +0200

author
Teemu Piippo <teemu@hecknology.net>
date
Fri, 05 Feb 2021 12:16:29 +0200
changeset 4
ac067a42b00f
parent 2
7378b802ddf8
permissions
-rwxr-xr-x

update

1
f9788970fa46 begin work on bus compiler
Teemu Piippo <teemu@hecknology.net>
parents:
diff changeset
1 #!/usr/bin/env python3
f9788970fa46 begin work on bus compiler
Teemu Piippo <teemu@hecknology.net>
parents:
diff changeset
2 import sys, json
f9788970fa46 begin work on bus compiler
Teemu Piippo <teemu@hecknology.net>
parents:
diff changeset
3 from misc import *
f9788970fa46 begin work on bus compiler
Teemu Piippo <teemu@hecknology.net>
parents:
diff changeset
4 from geometry import *
f9788970fa46 begin work on bus compiler
Teemu Piippo <teemu@hecknology.net>
parents:
diff changeset
5 from configparser import ConfigParser
f9788970fa46 begin work on bus compiler
Teemu Piippo <teemu@hecknology.net>
parents:
diff changeset
6
f9788970fa46 begin work on bus compiler
Teemu Piippo <teemu@hecknology.net>
parents:
diff changeset
7 class Blockmap:
f9788970fa46 begin work on bus compiler
Teemu Piippo <teemu@hecknology.net>
parents:
diff changeset
8 '''
f9788970fa46 begin work on bus compiler
Teemu Piippo <teemu@hecknology.net>
parents:
diff changeset
9 The blockmap is a grid of latitude and longitude lines and models
f9788970fa46 begin work on bus compiler
Teemu Piippo <teemu@hecknology.net>
parents:
diff changeset
10 a block -> set relation. A block is a latitude and longitude square.
f9788970fa46 begin work on bus compiler
Teemu Piippo <teemu@hecknology.net>
parents:
diff changeset
11 '''
f9788970fa46 begin work on bus compiler
Teemu Piippo <teemu@hecknology.net>
parents:
diff changeset
12 block_size = 200.0 # How big are blocks?
f9788970fa46 begin work on bus compiler
Teemu Piippo <teemu@hecknology.net>
parents:
diff changeset
13 def __init__(self, blocks = None):
f9788970fa46 begin work on bus compiler
Teemu Piippo <teemu@hecknology.net>
parents:
diff changeset
14 from collections import defaultdict
f9788970fa46 begin work on bus compiler
Teemu Piippo <teemu@hecknology.net>
parents:
diff changeset
15 self.blocks = blocks or defaultdict(set)
f9788970fa46 begin work on bus compiler
Teemu Piippo <teemu@hecknology.net>
parents:
diff changeset
16 def __getitem__(self, blockid):
f9788970fa46 begin work on bus compiler
Teemu Piippo <teemu@hecknology.net>
parents:
diff changeset
17 '''
f9788970fa46 begin work on bus compiler
Teemu Piippo <teemu@hecknology.net>
parents:
diff changeset
18 Returns a block for block coordinates. The block is a set that can
f9788970fa46 begin work on bus compiler
Teemu Piippo <teemu@hecknology.net>
parents:
diff changeset
19 contain anything.
f9788970fa46 begin work on bus compiler
Teemu Piippo <teemu@hecknology.net>
parents:
diff changeset
20 '''
f9788970fa46 begin work on bus compiler
Teemu Piippo <teemu@hecknology.net>
parents:
diff changeset
21 return self.blocks[blockid]
f9788970fa46 begin work on bus compiler
Teemu Piippo <teemu@hecknology.net>
parents:
diff changeset
22 def blockpoint(self, point):
f9788970fa46 begin work on bus compiler
Teemu Piippo <teemu@hecknology.net>
parents:
diff changeset
23 '''
f9788970fa46 begin work on bus compiler
Teemu Piippo <teemu@hecknology.net>
parents:
diff changeset
24 Returns blockmap coordinates for geographical coordinates.
f9788970fa46 begin work on bus compiler
Teemu Piippo <teemu@hecknology.net>
parents:
diff changeset
25 The blockmap coordinates refer to a block in the blockmap.
f9788970fa46 begin work on bus compiler
Teemu Piippo <teemu@hecknology.net>
parents:
diff changeset
26 '''
f9788970fa46 begin work on bus compiler
Teemu Piippo <teemu@hecknology.net>
parents:
diff changeset
27 block_coordinate = lambda x: int(x * self.block_size)
f9788970fa46 begin work on bus compiler
Teemu Piippo <teemu@hecknology.net>
parents:
diff changeset
28 return block_coordinate(point.x), block_coordinate(point.y)
f9788970fa46 begin work on bus compiler
Teemu Piippo <teemu@hecknology.net>
parents:
diff changeset
29
f9788970fa46 begin work on bus compiler
Teemu Piippo <teemu@hecknology.net>
parents:
diff changeset
30 def blocks_in_shape(blockmap, shape):
f9788970fa46 begin work on bus compiler
Teemu Piippo <teemu@hecknology.net>
parents:
diff changeset
31 '''
f9788970fa46 begin work on bus compiler
Teemu Piippo <teemu@hecknology.net>
parents:
diff changeset
32 Finds all blocks inside the bounding box of a shape.
f9788970fa46 begin work on bus compiler
Teemu Piippo <teemu@hecknology.net>
parents:
diff changeset
33 '''
f9788970fa46 begin work on bus compiler
Teemu Piippo <teemu@hecknology.net>
parents:
diff changeset
34 from itertools import product
f9788970fa46 begin work on bus compiler
Teemu Piippo <teemu@hecknology.net>
parents:
diff changeset
35 min_x, max_x = minmax(point.x for point in shape.points)
f9788970fa46 begin work on bus compiler
Teemu Piippo <teemu@hecknology.net>
parents:
diff changeset
36 min_y, max_y = minmax(point.y for point in shape.points)
f9788970fa46 begin work on bus compiler
Teemu Piippo <teemu@hecknology.net>
parents:
diff changeset
37 min_blockpoint = blockmap.blockpoint(Location(min_x, min_y))
f9788970fa46 begin work on bus compiler
Teemu Piippo <teemu@hecknology.net>
parents:
diff changeset
38 max_blockpoint = blockmap.blockpoint(Location(max_x, max_y))
f9788970fa46 begin work on bus compiler
Teemu Piippo <teemu@hecknology.net>
parents:
diff changeset
39 range_x = range(min_blockpoint[0], max_blockpoint[0] + 1)
f9788970fa46 begin work on bus compiler
Teemu Piippo <teemu@hecknology.net>
parents:
diff changeset
40 range_y = range(min_blockpoint[1], max_blockpoint[1] + 1)
f9788970fa46 begin work on bus compiler
Teemu Piippo <teemu@hecknology.net>
parents:
diff changeset
41 yield from (blockmap[x, y] for x, y in product(range_x, range_y))
f9788970fa46 begin work on bus compiler
Teemu Piippo <teemu@hecknology.net>
parents:
diff changeset
42
f9788970fa46 begin work on bus compiler
Teemu Piippo <teemu@hecknology.net>
parents:
diff changeset
43 def create_blockmap(regions):
f9788970fa46 begin work on bus compiler
Teemu Piippo <teemu@hecknology.net>
parents:
diff changeset
44 '''
f9788970fa46 begin work on bus compiler
Teemu Piippo <teemu@hecknology.net>
parents:
diff changeset
45 Creates a blockmap of regions
f9788970fa46 begin work on bus compiler
Teemu Piippo <teemu@hecknology.net>
parents:
diff changeset
46 '''
f9788970fa46 begin work on bus compiler
Teemu Piippo <teemu@hecknology.net>
parents:
diff changeset
47 blockmap = Blockmap()
f9788970fa46 begin work on bus compiler
Teemu Piippo <teemu@hecknology.net>
parents:
diff changeset
48 for region in regions.values():
f9788970fa46 begin work on bus compiler
Teemu Piippo <teemu@hecknology.net>
parents:
diff changeset
49 # Minor shapes contain major shapes, so just use those
f9788970fa46 begin work on bus compiler
Teemu Piippo <teemu@hecknology.net>
parents:
diff changeset
50 for shape in (region['minor_shapes'] or region['major_shapes']):
f9788970fa46 begin work on bus compiler
Teemu Piippo <teemu@hecknology.net>
parents:
diff changeset
51 for block in blocks_in_shape(blockmap, shape):
2
7378b802ddf8 destination processing
Teemu Piippo <teemu@hecknology.net>
parents: 1
diff changeset
52 set.add(block, region['ref'])
1
f9788970fa46 begin work on bus compiler
Teemu Piippo <teemu@hecknology.net>
parents:
diff changeset
53 return blockmap
f9788970fa46 begin work on bus compiler
Teemu Piippo <teemu@hecknology.net>
parents:
diff changeset
54
f9788970fa46 begin work on bus compiler
Teemu Piippo <teemu@hecknology.net>
parents:
diff changeset
55 def get_args():
f9788970fa46 begin work on bus compiler
Teemu Piippo <teemu@hecknology.net>
parents:
diff changeset
56 from argparse import ArgumentParser
f9788970fa46 begin work on bus compiler
Teemu Piippo <teemu@hecknology.net>
parents:
diff changeset
57 parser = ArgumentParser()
f9788970fa46 begin work on bus compiler
Teemu Piippo <teemu@hecknology.net>
parents:
diff changeset
58 parser.add_argument('gtfs_zip')
f9788970fa46 begin work on bus compiler
Teemu Piippo <teemu@hecknology.net>
parents:
diff changeset
59 parser.add_argument('profile')
f9788970fa46 begin work on bus compiler
Teemu Piippo <teemu@hecknology.net>
parents:
diff changeset
60 return parser.parse_args()
f9788970fa46 begin work on bus compiler
Teemu Piippo <teemu@hecknology.net>
parents:
diff changeset
61
f9788970fa46 begin work on bus compiler
Teemu Piippo <teemu@hecknology.net>
parents:
diff changeset
62 def test_shapes(shapes, point):
f9788970fa46 begin work on bus compiler
Teemu Piippo <teemu@hecknology.net>
parents:
diff changeset
63 return any(shape.contains_point(point) for shape in shapes)
f9788970fa46 begin work on bus compiler
Teemu Piippo <teemu@hecknology.net>
parents:
diff changeset
64
f9788970fa46 begin work on bus compiler
Teemu Piippo <teemu@hecknology.net>
parents:
diff changeset
65 class RegionalLocation:
f9788970fa46 begin work on bus compiler
Teemu Piippo <teemu@hecknology.net>
parents:
diff changeset
66 def __init__(self, *, region, region_class):
f9788970fa46 begin work on bus compiler
Teemu Piippo <teemu@hecknology.net>
parents:
diff changeset
67 self.region, self.region_class = region, region_class
f9788970fa46 begin work on bus compiler
Teemu Piippo <teemu@hecknology.net>
parents:
diff changeset
68 def __repr__(self):
f9788970fa46 begin work on bus compiler
Teemu Piippo <teemu@hecknology.net>
parents:
diff changeset
69 return str.format(
f9788970fa46 begin work on bus compiler
Teemu Piippo <teemu@hecknology.net>
parents:
diff changeset
70 'RegionalLocation(region = {region}, region_class = {region_class})',
f9788970fa46 begin work on bus compiler
Teemu Piippo <teemu@hecknology.net>
parents:
diff changeset
71 region = repr(self.region),
f9788970fa46 begin work on bus compiler
Teemu Piippo <teemu@hecknology.net>
parents:
diff changeset
72 region_class = repr(self.region_class),
f9788970fa46 begin work on bus compiler
Teemu Piippo <teemu@hecknology.net>
parents:
diff changeset
73 )
f9788970fa46 begin work on bus compiler
Teemu Piippo <teemu@hecknology.net>
parents:
diff changeset
74
f9788970fa46 begin work on bus compiler
Teemu Piippo <teemu@hecknology.net>
parents:
diff changeset
75 def locate_regionally(position, region):
f9788970fa46 begin work on bus compiler
Teemu Piippo <teemu@hecknology.net>
parents:
diff changeset
76 if test_shapes(region['major_shapes'], position):
2
7378b802ddf8 destination processing
Teemu Piippo <teemu@hecknology.net>
parents: 1
diff changeset
77 return RegionalLocation(region = region['ref'], region_class = 'major')
1
f9788970fa46 begin work on bus compiler
Teemu Piippo <teemu@hecknology.net>
parents:
diff changeset
78 elif test_shapes(region['minor_shapes'], position):
2
7378b802ddf8 destination processing
Teemu Piippo <teemu@hecknology.net>
parents: 1
diff changeset
79 return RegionalLocation(region = region['ref'], region_class = 'minor')
1
f9788970fa46 begin work on bus compiler
Teemu Piippo <teemu@hecknology.net>
parents:
diff changeset
80 else:
f9788970fa46 begin work on bus compiler
Teemu Piippo <teemu@hecknology.net>
parents:
diff changeset
81 return None
f9788970fa46 begin work on bus compiler
Teemu Piippo <teemu@hecknology.net>
parents:
diff changeset
82
f9788970fa46 begin work on bus compiler
Teemu Piippo <teemu@hecknology.net>
parents:
diff changeset
83 def find_region_for_point(position, regions, blockmap):
f9788970fa46 begin work on bus compiler
Teemu Piippo <teemu@hecknology.net>
parents:
diff changeset
84 for region_name in blockmap[blockmap.blockpoint(position)]:
f9788970fa46 begin work on bus compiler
Teemu Piippo <teemu@hecknology.net>
parents:
diff changeset
85 region = regions[region_name]
f9788970fa46 begin work on bus compiler
Teemu Piippo <teemu@hecknology.net>
parents:
diff changeset
86 classification = locate_regionally(position, region)
f9788970fa46 begin work on bus compiler
Teemu Piippo <teemu@hecknology.net>
parents:
diff changeset
87 if classification:
f9788970fa46 begin work on bus compiler
Teemu Piippo <teemu@hecknology.net>
parents:
diff changeset
88 return classification
f9788970fa46 begin work on bus compiler
Teemu Piippo <teemu@hecknology.net>
parents:
diff changeset
89
f9788970fa46 begin work on bus compiler
Teemu Piippo <teemu@hecknology.net>
parents:
diff changeset
90 class RegionTester:
f9788970fa46 begin work on bus compiler
Teemu Piippo <teemu@hecknology.net>
parents:
diff changeset
91 def __init__(self, regions):
f9788970fa46 begin work on bus compiler
Teemu Piippo <teemu@hecknology.net>
parents:
diff changeset
92 self.regions = regions
f9788970fa46 begin work on bus compiler
Teemu Piippo <teemu@hecknology.net>
parents:
diff changeset
93 self.blockmap = create_blockmap(regions)
f9788970fa46 begin work on bus compiler
Teemu Piippo <teemu@hecknology.net>
parents:
diff changeset
94 def __call__(self, latitude, longitude):
f9788970fa46 begin work on bus compiler
Teemu Piippo <teemu@hecknology.net>
parents:
diff changeset
95 return find_region_for_point(
f9788970fa46 begin work on bus compiler
Teemu Piippo <teemu@hecknology.net>
parents:
diff changeset
96 position = Location(float(latitude), float(longitude)),
f9788970fa46 begin work on bus compiler
Teemu Piippo <teemu@hecknology.net>
parents:
diff changeset
97 regions = self.regions,
f9788970fa46 begin work on bus compiler
Teemu Piippo <teemu@hecknology.net>
parents:
diff changeset
98 blockmap = self.blockmap,
f9788970fa46 begin work on bus compiler
Teemu Piippo <teemu@hecknology.net>
parents:
diff changeset
99 )

mercurial