Exemplo n.º 1
0
 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
Exemplo n.º 2
0
 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
Exemplo n.º 3
0
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
Exemplo n.º 4
0
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