def element_to_lines(element: Element, osm_helper: OsmHelper): if element.tag == 'relation' and tag_dict(element).get( 'type') == 'multipolygon': return osm_helper.multipolygon_to_polygons(element) elif element.tag == 'way': return [osm_helper.way_coordinates(element)] return []
def draw(self, elements: Element, osm_helper: OsmHelper, camera: Camera, image_draw: ImageDraw): layers = defaultdict(lambda: defaultdict(list)) for element in elements: tags = tag_dict(element) try: layer = int(tags['layer']) except (KeyError, ValueError): layer = 1 if tags.get('bridge') == 'yes'\ else -1 if tags.get('tunnel') == 'yes'\ else 0 road_type: MappedFeature = self.types[element] layers[layer][road_type] += transform_shapes( element_to_lines(element, osm_helper), camera) def draw_roads(color, width, roads): if color is not None: for road in roads: image_draw.line(road, fill=color, width=width, joint='curve') for layer in range(-5, 7): # draw bridge outline if layer > 0: for road_type in sorted(layers[layer]): width = road_type.style.width * (camera.px_per_meter()** road_type.style.exp) draw_roads(road_type.style.outline_bridge, int(width) + 2, layers[layer][road_type]) # draw surface outline if layer == 0: for road_type in sorted(layers[layer]): width = road_type.style.width * (camera.px_per_meter()** road_type.style.exp) draw_roads(road_type.style.outline, int(width) + 2, layers[layer][road_type]) # draw tunnel line if layer < 0: for road_type in sorted(layers[layer]): width = road_type.style.width * (camera.px_per_meter()** road_type.style.exp) draw_roads(road_type.style.fill + '8', int(width), layers[layer][road_type]) # draw line if layer >= 0: for road_type in sorted(layers[layer]): width = road_type.style.width * (camera.px_per_meter()** road_type.style.exp) draw_roads(road_type.style.fill, int(width), layers[layer][road_type])
def _select(self, element, name=None): self.highlight, self.selection = None, None self.dirty = True if element is None: return if not name: name = osm_helper.tag_dict(element).get('name') if element.tag == 'node': self.highlight = (float(element.attrib['lat']), float(element.attrib['lon'])) self.camera.center_at(*self.highlight) self.selection = name else: points = [] tp = element.tag if element.tag == 'way': points = self.osm_helper.way_coordinates(element) elif element.tag == 'relation': tags = osm_helper.tag_dict(element) tp = '{}:{}'.format(element.tag, tags.get('type')) if tags.get('type') == 'multipolygon': points = [ point for polygon in self.osm_helper.multipolygon_to_polygons(element) for point in polygon ] if len(points) == 0: log('Don\'t know how to select element {} of type {}'.format( name, tp), level=1) else: rect = Rectangle( min(points, key=itemgetter(0))[0], min(points, key=itemgetter(1))[1], max(points, key=itemgetter(0))[0], max(points, key=itemgetter(1))[1]) self.highlight = rect self.camera.center_at((rect.min_lat + rect.max_lat) / 2, (rect.min_lon + rect.max_lon) / 2) self.selection = name log('Selected {} at {}'.format(self.highlight, self.selection))
def wants_element(self, element: Element, osm_helper: OsmHelper): tags = tag_dict(element) if tags.get('area') == 'yes' and \ not tags.get('railway') == 'turntable': return False for tag, types in _road_types.items(): try: self.types[element] = types[tags[tag]] return True except KeyError: pass return False
def element_to_polygons(element: Element, osm_helper: OsmHelper): if element.tag == 'relation' and tag_dict(element).get( 'type') == 'multipolygon': return [ polygon[:-1] for polygon in osm_helper.multipolygon_to_wsps(element) ] elif element.tag == 'way': way = osm_helper.way_coordinates(element) if len(way) >= 4 and way[0] == way[-1]: return [way[:-1]] return []
def element_to_points(element: Element, osm_helper: OsmHelper): if element.tag == 'relation' and tag_dict(element).get( 'type') == 'multipolygon': return [ point for polygon in osm_helper.multipolygon_to_polygons(element) for point in polygon ] elif element.tag == 'way': way = osm_helper.way_coordinates(element) if len(way) >= 2 and way[0] == way[-1]: return way[:-1] return way elif element.tag == 'node': return [(float(element.attrib['lat']), float(element.attrib['lon']))] return []
def wants_element(self, element: Element, osm_helper: OsmHelper): tags = tag_dict(element) for key, features in self.styles.items(): try: feature: MappedFeature = features[tags[key]] if feature.style.wants_element(element, tags, osm_helper): self.map[element] = feature self.data[element] = feature.style.convert( element, tags, osm_helper), element_to_bbox(element, osm_helper) return self.data[element][0] is not None return False except KeyError: pass return False
def task_search_address(self, street: str, number: str): street, number = street.lower(), number.lower() self._status( status='Searching for address: {}, {}'.format(street, number)) self._select(None) for element in self.element_tree.getroot(): tags = osm_helper.tag_dict(element) addr_street, addr_number = tags.get('addr:street', ''), tags.get( 'addr:housenumber', '') address = ' '.join(filter(lambda x: x, [addr_street, addr_number])) if street in addr_street.lower() and number in addr_number.lower( ).split('/'): log('Found {}'.format(address)) self._select(element, address) return log('Search unsuccessful')
def task_search_name(self, target: str): target = target.lower() self._status(status='Searching for name: {}'.format(target)) self._select(None) best, best_len = None, 1000 for element in self.element_tree.getroot(): tags = osm_helper.tag_dict(element) names = filter(lambda i: 'name' in i[0], tags.items()) for key, name in names: if target in name.lower(): match = len(name) if element.tag == 'node': match += 0.5 if element.tag == 'relation': match -= 0.5 if match < best_len: best, best_len = element, match if best is None: log('Search unsuccessful') self._select(best)
return False return True print('testing osm_helper.multipolygon_to_wsps') test_count = 0 correct_tests = 0 failure = None element_tree = ET.parse('testdata/map.osm') root = element_tree.getroot() helper = osm_helper.OsmHelper(element_tree) for element in root: if element.tag == 'relation': td = osm_helper.tag_dict(element) if td['type'] == 'multipolygon' and 'test' in td: fail = None result = helper.multipolygon_to_wsps(element) im1 = PIL.Image.new('RGB', (500, 800)) draw = PIL.ImageDraw.Draw(im1) draw.rectangle((0, 0, 499, 799), fill='white', outline='black') xs = [p[0] for polygon in result for p in polygon] ys = [p[1] for polygon in result for p in polygon] scale_x = 300 / (max(xs) - min(xs)) delta_x = -min(xs) * scale_x + 100 scale_y = 300 / (max(ys) - min(ys)) delta_y = -min(ys) * scale_y + 250 for polygon in result:
if len(dict1) != len(dict2): return False return True print('testing osm_helper.tag_dict') test_count = 0 correct_tests = 0 failure = None element_tree = ET.parse('testdata/map.osm') root = element_tree.getroot() with open('testdata/tag_dict.out', 'r', encoding="utf8") as f: for element in root: fail = None result = osm_helper.tag_dict(element) expected = {} expected_count = int(f.readline()) for i in range(expected_count): key = f.readline().rstrip() value = f.readline().rstrip() expected[key] = value if not isinstance(result, dict): fail = 'expected dictionary, got {}'.format(type(result)) elif not dicts_equal(result, expected): fail = 'expected \n{},\n got \n{}\n'.format(expected, result) else: correct_tests += 1 test_count += 1