Example #1
0
    def coastlines(self):
        '''
        Draws coastlines on the map.

        TODO: fill map with sea color if no coastline intersects the map but
            the area actually is no land mass
        '''

        coastlines = session.query(OSMLine).filter(and_(
            BBOX_QUERY_COND % ((OSMLine.__table__, ) + self.mapobj.bbox.bounds),
            OSMLine.natural=='coastline'
        )).all()
        coastpolygons = session.query(OSMPolygon).filter(and_(
            BBOX_QUERY_COND % ((OSMPolygon.__table__, ) + self.mapobj.bbox.bounds),
            OSMPolygon.natural=='coastline'
        )).all()
        # only fill map with sea color if there is a at least one coastline
        if coastlines or coastpolygons:
            lines = tuple(wkb.loads(str(cl.geom.geom_wkb))
                for cl in coastlines)
            merged = utils.merge_lines(lines)
            islands = []
            shorelines = []
            for line in merged:
                #: closed rings are islands and must be filled with map background
                if line.is_ring:
                    islands.append(line)
                else:
                    inter = line.intersection(self.mapobj.bbox)
                    points = line.intersection(self.mapobj.bbox.exterior)
                    #: only add line to closing process if number of intersections
                    #: with bbox is even. Otherwise we have a incomplete coastline
                    #: which ends in the visible map
                    if points.geom_type == 'MultiPoint' and len(points) % 2 == 0 \
                            and len(points) > 0:
                        if inter.geom_type == 'LineString':
                            shorelines.append(inter)
                        else:
                            shorelines.extend(inter)
            #: save all polygon coordinates as numpy arrays and add to islands
            for island in coastpolygons:
                islands.append(numpy.array(wkb.loads(str(island.geom.geom_wkb)).exterior))
            #: fill water with sea background
            shore = None
            for shore in utils.close_coastlines(shorelines, self.mapobj.bbox):
                self.mapobj.draw_polygon(
                    exterior=numpy.array(shore),
                    background_color=self.stylesheet.sea_background
                )
            #: fill map with sea background if there is no shoreline
            if shore is None and islands:
                self.mapobj.draw_background(self.stylesheet.sea_background)
            #: fill land filled area with map background
            for island in islands:
                self.mapobj.draw_polygon(
                    exterior=numpy.array(island),
                    background_color=self.stylesheet.map_background
                )
Example #2
0
    def query_objects(self, geom_type):
        '''
        Returns all objects for current scale/geom_type as a 2-dimensional
        sorted list (according to z-index specified in stylesheet) and sets
        style as attribute to db objects.

        :param geom_type: one of ``'point'``, ``'line'`` or ``'polygon'``

        :returns: 2-dimensional list containing sorted objects
        '''

        # create 2-dimensional list so objects can be sorted (may be too many
        # sublists as there probably won't be as many z-index's defined as
        # MAX_Z_INDEX)
        results = [list() for _ in xrange(self.stylesheet.MAX_Z_INDEX)]
        # determine database model class
        db_class = GEOM_TYPES[geom_type]
        counter = 0
        # iterate over all visible tags and names
        for tags, columns, conditions in self.iter_query_conditions(geom_type):
            # simple st_intersects() does not work because this operation
            # raises an InternalError exception because of invalid geometries
            # in the OSM database
            bbox_condition = BBOX_QUERY_COND % (
                (db_class.__table__, ) + self.bbox.bounds)
            objects = session.query(
                # only get necessary columns to increase performance
                db_class.geom,
                *[getattr(db_class, c) for c in tuple(tags) + tuple(columns)]
            ).filter(and_(bbox_condition, *conditions)).all()
            #: set style attr to obj and sort according to z-index
            for obj in objects:
                counter += 1
                tag_value = dict((tag, getattr(obj, tag)) for tag in tags)
                obj.style = self.stylesheet.get(self.mapobj.scale, geom_type,
                    tag_value)
                results[obj.style.get('z-index', 0)].append(obj)
        self.verbose_print('>  %s %ss' % (counter, geom_type))
        return results