def __init__(self, relation, ways_cache, coords_cache): self.relation = relation self.polygon_builder = PolygonBuilder() self.linestring_builder = LineStringBuilder() self.ways_cache = ways_cache self.coords_cache = coords_cache
class RelationBuilderBase(object): validate_rings = True def __init__(self, relation, ways_cache, coords_cache): self.relation = relation self.polygon_builder = PolygonBuilder() self.linestring_builder = LineStringBuilder() self.ways_cache = ways_cache self.coords_cache = coords_cache def fetch_ways(self): ways = [] for member in self.relation.members: # skip label nodes, relations of relations, etc if member[1] != 'way': continue way = self.ways_cache.get(member[0]) if way is None: log.debug('way not found %s:%s', self.relation.osm_id, member[0]) if imposm.config.import_partial_relations: continue else: raise IncompletePolygonError('way not found %s:%s' % (self.relation.osm_id, member[0])) if way.partial_refs: log.warn('multiple linestrings in way %s (relation %s)', member[0], self.relation.osm_id) raise IncompletePolygonError() way.coords = self.fetch_way_coords(way) if way.coords is None: if not imposm.config.import_partial_relations: raise IncompletePolygonError() else: ways.append(way) return ways def build_rings(self, ways): rings = [] incomplete_rings = [] for ring in (Ring(w) for w in ways): if ring.is_closed(): ring.geom = self.polygon_builder.build_checked_geom(ring, validate=self.validate_rings) rings.append(ring) else: incomplete_rings.append(ring) merged_rings = self.build_ring_from_incomplete(incomplete_rings) if len(rings) + len(merged_rings) == 0: raise IncompletePolygonError('linestrings from relation %s have no rings' % (self.relation.osm_id, )) return rings + merged_rings def build_ring_from_incomplete(self, incomplete_rings): rings = merge_rings(incomplete_rings) for ring in rings[:]: if not ring.is_closed(): if imposm.config.import_partial_relations: rings.remove(ring) continue else: raise InvalidGeometryError('linestrings from relation %s do not form a ring' % self.relation.osm_id) ring.geom = self.polygon_builder.build_checked_geom(ring, validate=self.validate_rings) return rings def fetch_way_coords(self, way): """ Fetch all coordinates of way.refs. """ coords = self.coords_cache.get_coords(way.refs) if coords is None: log.debug('missing coord from way %s in relation %s', way.osm_id, self.relation.osm_id) return None return coords def build_relation_geometry(self, rings): """ Build relation geometry from rings. """ raise NotImplementedError() def mark_inserted_ways(self, inserted_ways_queue): for w in self.relation.ways: if w.inserted: inserted_ways_queue.put(w.osm_id) def build(self): try: time_start = time.time() ways = self.fetch_ways() time_ways = time.time() - time_start if not ways: raise IncompletePolygonError('no ways found') time_start = time.time() rings = self.build_rings(ways) time_rings = time.time() - time_start if (imposm.config.imposm_multipolygon_max_ring and len(rings) > imposm.config.imposm_multipolygon_max_ring): log.warn('skipping relation %d with %d ways (%.1fms) and %d rings (%.1fms): too many rings', self.relation.osm_id, len(ways), time_ways*1000, len(rings), time_rings*1000) raise IncompletePolygonError('skipping too large multipolygon') time_start = time.time() self.build_relation_geometry(rings) time_relations = time.time() - time_start if time_ways + time_rings + time_relations > imposm.config.imposm_multipolygon_report: log.warn('building relation %d with %d ways (%.1fms) and %d rings (%.1fms) took %.1fms', self.relation.osm_id, len(ways), time_ways*1000, len(rings), time_rings*1000, time_relations*1000) except InvalidGeometryError, ex: log.debug(ex) raise IncompletePolygonError(ex) except IncompletePolygonError: raise
class RelationBuilderBase(object): validate_rings = True def __init__(self, relation, ways_cache, coords_cache): self.relation = relation self.polygon_builder = PolygonBuilder() self.linestring_builder = LineStringBuilder() self.ways_cache = ways_cache self.coords_cache = coords_cache def fetch_ways(self): ways = [] for member in self.relation.members: # skip label nodes, relations of relations, etc if member[1] != 'way': continue way = self.ways_cache.get(member[0]) if way is None: log.debug('way not found %s:%s', self.relation.osm_id, member[0]) if imposm.config.import_partial_relations: continue else: raise IncompletePolygonError('way not found %s:%s' % (self.relation.osm_id, member[0])) if way.partial_refs: log.warn('multiple linestrings in way %s (relation %s)', member[0], self.relation.osm_id) raise IncompletePolygonError() way.coords = self.fetch_way_coords(way) if way.coords is None: if not imposm.config.import_partial_relations: raise IncompletePolygonError() else: ways.append(way) return ways def build_rings(self, ways): rings = [] incomplete_rings = [] for ring in (Ring(w) for w in ways): if ring.is_closed(): ring.geom = self.polygon_builder.build_checked_geom(ring, validate=self.validate_rings) rings.append(ring) else: incomplete_rings.append(ring) merged_rings = self.build_ring_from_incomplete(incomplete_rings) if len(rings) + len(merged_rings) == 0: raise IncompletePolygonError('linestrings from relation %s have no rings' % (self.relation.osm_id, )) return rings + merged_rings def build_ring_from_incomplete(self, incomplete_rings): rings = merge_rings(incomplete_rings) for ring in rings[:]: if not ring.is_closed(): if imposm.config.import_partial_relations: rings.remove(ring) continue else: raise InvalidGeometryError('linestrings from relation %s do not form a ring' % self.relation.osm_id) ring.geom = self.polygon_builder.build_checked_geom(ring, validate=self.validate_rings) return rings def fetch_way_coords(self, way): """ Fetch all coordinates of way.refs. """ coords = self.coords_cache.get_coords(way.refs) if coords is None: log.debug('missing coord from way %s in relation %s', way.osm_id, self.relation.osm_id) return None return coords def build_relation_geometry(self, rings): """ Build relation geometry from rings. """ raise NotImplementedError() def build(self): try: time_start = time.time() ways = self.fetch_ways() time_ways = time.time() - time_start if not ways: raise IncompletePolygonError('no ways found') time_start = time.time() rings = self.build_rings(ways) time_rings = time.time() - time_start if (imposm.config.imposm_multipolygon_max_ring and len(rings) > imposm.config.imposm_multipolygon_max_ring): log.warn('skipping relation %d with %d ways (%.1fms) and %d rings (%.1fms): too many rings', self.relation.osm_id, len(ways), time_ways*1000, len(rings), time_rings*1000) raise IncompletePolygonError('skipping too large multipolygon') time_start = time.time() self.build_relation_geometry(rings) time_relations = time.time() - time_start if time_ways + time_rings + time_relations > imposm.config.imposm_multipolygon_report: log.warn('building relation %d with %d ways (%.1fms) and %d rings (%.1fms) took %.1fms', self.relation.osm_id, len(ways), time_ways*1000, len(rings), time_rings*1000, time_relations*1000) except InvalidGeometryError, ex: log.debug(ex) raise IncompletePolygonError(ex) except IncompletePolygonError: raise