예제 #1
0
    def render_image(self, extent, size, padding=0):
        res_x = (extent[2] - extent[0]) / size[0]
        res_y = (extent[3] - extent[1]) / size[1]

        # Экстент с учетом отступа
        extended = (
            extent[0] - res_x * padding,
            extent[1] - res_y * padding,
            extent[2] + res_x * padding,
            extent[3] + res_y * padding,
        )

        # Размер изображения с учетом отступа
        render_size = (
            size[0] + 2 * padding,
            size[1] + 2 * padding
        )

        # Фрагмент изображения размера size
        target_box = (
            padding,
            padding,
            size[0] + padding,
            size[1] + padding
        )

        # Выбираем объекты по экстенту
        feature_query = self.layer.feature_query()
        feature_query.intersects(box(*extended, srid=self.layer.srs_id))
        feature_query.geom()
        features = feature_query()

        mapobj = self._mapobj(features)

        # Получаем картинку эмулируя WMS запрос
        req = mapscript.OWSRequest()
        req.setParameter("bbox", ','.join(map(str, extended)))
        req.setParameter("width", str(render_size[0]))
        req.setParameter("height", str(render_size[1]))
        req.setParameter("srs", 'EPSG:%d' % self.layer.srs_id)
        req.setParameter("format", 'image/png')
        req.setParameter("layers", 'main')
        req.setParameter("request", "GetMap")
        req.setParameter('transparent', 'TRUE')

        mapobj.loadOWSParameters(req)
        gdimg = mapobj.draw()

        # Преобразуем изображение из PNG в объект PIL
        buf = StringIO()
        buf.write(gdimg.getBytes())
        buf.seek(0)

        img = Image.open(buf)

        # Вырезаем нужный нам кусок изображения
        return img.crop(target_box)
예제 #2
0
    def select(self, params):
        if self.query is None:
            self._setup_query()

        self.query.filter_by()

        # Startfeature+maxfeature
        if params.startfeature is None:
            params.startfeature = 0
        if params.maxfeatures:
            maxfeatures = params.maxfeatures
        else:
            maxfeatures = self.maxfeatures

        self.query.limit(maxfeatures, params.startfeature)

        # BBOX
        if params.bbox:
            coords = params.bbox['coords']
            srs_id = params.bbox[
                'srs_id'] if 'srs_id' in params.bbox else self.srid_out
            geom = box(*coords, srid=srs_id)
            self.query.intersects(geom)

        srid = params.srsname if params.srsname else self.srid_out
        self.query.srs(Bunch({'id': srid}))

        self.query.geom()
        result = self.query()

        features = []
        fields_checked = False
        for row in result:
            # Check if names contains characters that can't be used in XML tags
            if not fields_checked:
                for field_name in row.fields:
                    if '<' in field_name or '>' in field_name or '&' in field_name or '@' in field_name:
                        raise OperationProcessingFailedException(
                            message='Field name %s contains unsupported symbol'
                            % (field_name, ))
                fields_checked = True

            feature = Feature(id=row.id, props=row.fields, srs=srid)
            feature.geometry_attr = self.geom_col
            geom = geojson.dumps(row.geom)

            # featureserver.feature.geometry is a dict, so convert str->dict:
            feature.set_geo(geojson.loads(geom))
            features.append(feature)

        return features
예제 #3
0
    def render_image(self, extent, size, padding=0):
        res_x = (extent[2] - extent[0]) / size[0]
        res_y = (extent[3] - extent[1]) / size[1]

        # Экстент с учетом отступа
        extended = (
            extent[0] - res_x * padding,
            extent[1] - res_y * padding,
            extent[2] + res_x * padding,
            extent[3] + res_y * padding,
        )

        # Размер изображения с учетом отступа
        render_size = (size[0] + 2 * padding, size[1] + 2 * padding)

        # Фрагмент изображения размера size
        target_box = (padding, padding, size[0] + padding, size[1] + padding)

        # Выбираем объекты по экстенту
        feature_query = self.layer.feature_query()
        feature_query.intersects(box(*extended, srid=self.layer.srs_id))
        feature_query.geom()
        features = feature_query()

        mapobj = self._mapobj(features)

        # Получаем картинку эмулируя WMS запрос
        req = mapscript.OWSRequest()
        req.setParameter("bbox", ','.join(map(str, extended)))
        req.setParameter("width", str(render_size[0]))
        req.setParameter("height", str(render_size[1]))
        req.setParameter("srs", 'EPSG:%d' % self.layer.srs_id)
        req.setParameter("format", 'image/png')
        req.setParameter("layers", 'main')
        req.setParameter("request", "GetMap")
        req.setParameter('transparent', 'TRUE')

        mapobj.loadOWSParameters(req)
        gdimg = mapobj.draw()

        # Преобразуем изображение из PNG в объект PIL
        buf = StringIO()
        buf.write(gdimg.getBytes())
        buf.seek(0)

        img = Image.open(buf)

        # Вырезаем нужный нам кусок изображения
        return img.crop(target_box)
예제 #4
0
def geocollection(request):
    try:
        date = str(request.GET.get('datetime', datetime.now()))
        if 'layers' in request.GET:
            qlayers = map(int, request.GET['layers'].split(','))
            print qlayers
            layers = DBSession.query(VectorLayer)\
                .filter(VectorLayer.id.in_(qlayers))\
                .all()
        else:
            layers = DBSession.query(VectorLayer)\
                .all()
        layers = filter(lambda layer: layer.has_permission(PD_READ, request.user), layers)
        print layers
    except Exception as e:
        raise HTTPBadRequest(e.message)

    features = GeoJsonFeatureList()

    # Запрос коллекции GeoJSON объектов, попадающих в заданную область видимости
    if 'bbox' in request.GET:
        try:
            bbox = map(float, request.GET['bbox'].split(','))
            print bbox
            geometry = box(*bbox, srid=3857)
            for layer in layers:
                query = layer.feature_query()
                query.geom()
                query.intersects(geometry)
                for feature in query():
                    print feature
                    feature.fields['__layer__'] = feature.layer.id
                    features.append(feature)
        except Exception as e:
            print e
            raise HTTPBadRequest(e.message)
    else:
        raise HTTPBadRequest()
    print len(features)

    for f in features:
        f._geom = geometry_transform(f.geom, f.layer.srs_id, 4326)
    result = geojson.dumps(features, cls=ComplexEncoder)

    return Response(result, content_type='application/json')
예제 #5
0
        def render_image(self, extent, img_size, settings):
            # Выбираем объекты по экстенту
            feature_query = self.layer.feature_query()
            feature_query.intersects(box(*extent, srid=self.layer.srs_id))
            feature_query.geom()
            features = feature_query()

            ds = mapnik.MemoryDatasource()
            for (id, f) in enumerate(features):
                if mapnik.mapnik_version() < 200100:
                    feature = mapnik.Feature(id)
                else:
                    feature = mapnik.Feature(mapnik.Context(), id)
                feature.add_geometries_from_wkb(f.geom.wkb)
                ds.add_feature(feature)

            style_content = str(self.style_content)

            m = mapnik.Map(img_size[0], img_size[1])
            mapnik.load_map_from_string(m, style_content)
            m.zoom_to_box(mapnik.Box2d(*extent))

            layer = mapnik.Layer('main')
            layer.datasource = ds

            root = ET.fromstring(style_content)
            styles = [s.attrib.get('name') for s in root.iter('Style')]
            for s in styles:
                layer.styles.append(s)
            m.layers.append(layer)

            img = mapnik.Image(img_size[0], img_size[1])
            mapnik.render(m, img)
            data = img.tostring('png')

            # Преобразуем изображение из PNG в объект PIL
            buf = StringIO()
            buf.write(data)
            buf.seek(0)

            img = Image.open(buf)
            return img
예제 #6
0
        def render_image(self, extent, img_size, settings):
            # Выбираем объекты по экстенту
            feature_query = self.layer.feature_query()
            feature_query.intersects(box(*extent, srid=self.layer.srs_id))
            feature_query.geom()
            features = feature_query()

            ds = mapnik.MemoryDatasource()
            for (id, f) in enumerate(features):
                if mapnik.mapnik_version() < 200100:
                    feature = mapnik.Feature(id)
                else:
                    feature = mapnik.Feature(mapnik.Context(), id)
                feature.add_geometries_from_wkb(f.geom.wkb)
                ds.add_feature(feature)

            style_content = str(self.style_content)

            m = mapnik.Map(img_size[0], img_size[1])
            mapnik.load_map_from_string(m, style_content)
            m.zoom_to_box(mapnik.Box2d(*extent))

            layer = mapnik.Layer('main')
            layer.datasource = ds

            root = ET.fromstring(style_content)
            styles = [s.attrib.get('name') for s in root.iter('Style')]
            for s in styles:
                layer.styles.append(s)
            m.layers.append(layer)

            img = mapnik.Image(img_size[0], img_size[1])
            mapnik.render(m, img)
            data = img.tostring('png')

            # Преобразуем изображение из PNG в объект PIL
            buf = StringIO()
            buf.write(data)
            buf.seek(0)

            img = Image.open(buf)
            return img
예제 #7
0
    def _render_image(self, srs, extent, size, cond, padding=0):
        extended, render_size, target_box = _render_bounds(
            extent, size, padding)

        # Выбираем объекты по экстенту
        feature_query = self.parent.feature_query()

        # Отфильтровываем объекты по условию
        if cond is not None:
            feature_query.filter_by(**cond)

        # FIXME: Тоже самое, но через интерфейсы
        if hasattr(feature_query, 'srs'):
            feature_query.srs(srs)

        feature_query.intersects(box(*extended, srid=srs.id))
        feature_query.geom()
        features = feature_query()

        options = VectorRenderOptions(
            self, features, render_size,
            extended, target_box)
        return env.qgis.renderer_job(options)
예제 #8
0
    def _render_image(self, srs, extent, size, padding=0):
        res_x = (extent[2] - extent[0]) / size[0]
        res_y = (extent[3] - extent[1]) / size[1]

        # Экстент с учетом отступов
        extended = (
            max(srs.minx, extent[0] - res_x * padding),
            max(srs.miny, extent[1] - res_y * padding),
            min(srs.maxx, extent[2] + res_x * padding),
            min(srs.maxy, extent[3] + res_y * padding),
        )

        # Маска отступов
        pmask = (
            extended[0] != srs.minx,
            extended[1] != srs.miny,
            extended[2] != srs.maxx,
            extended[3] != srs.maxy
        )

        # Размер изображения с учетом отступов
        render_size = (
            size[0] + int(pmask[0] + pmask[2]) * padding,
            size[1] + int(pmask[1] + pmask[3]) * padding
        )

        # Фрагмент изображения размера size
        target_box = (
            pmask[0] * padding,
            pmask[3] * padding,
            size[0] + pmask[0] * padding,
            size[1] + pmask[3] * padding
        )

        # Выбираем объекты по экстенту
        feature_query = self.parent.feature_query()

        # FIXME: Тоже самое, но через интерфейсы
        if hasattr(feature_query, 'srs'):
            feature_query.srs(srs)

        feature_query.intersects(box(*extended, srid=srs.id))
        feature_query.geom()
        features = feature_query()

        res_img = None
        try:
            dirname, fndata, fnstyle = None, None, None

            dirname = mkdtemp()
            fndata = os.path.join(dirname, 'layer.geojson')

            with open(fndata, 'wb') as fd:
                fd.write(geojson.dumps(features))

            fnstyle = os.path.join(dirname, 'layer.qml')
            os.symlink(env.file_storage.filename(self.qml_fileobj), fnstyle)

            result = Queue()
            env.qgis.queue.put((fndata, self.srs, render_size,
                                extended, target_box, result))
            render_timeout = int(env.qgis.settings.get('render_timeout'))
            res_img = result.get(block=True, timeout=render_timeout)

        finally:
            if fndata and os.path.isfile(fndata):
                os.unlink(fndata)
            if fnstyle and os.path.isfile(fnstyle):
                os.unlink(fnstyle)
            if dirname and os.path.isdir(dirname):
                os.rmdir(dirname)

        return res_img
예제 #9
0
    def _render_image(self, srs, extent, size, padding=0):
        res_x = (extent[2] - extent[0]) / size[0]
        res_y = (extent[3] - extent[1]) / size[1]

        # Экстент с учетом отступов
        extended = (
            max(srs.minx, extent[0] - res_x * padding),
            max(srs.miny, extent[1] - res_y * padding),
            min(srs.maxx, extent[2] + res_x * padding),
            min(srs.maxy, extent[3] + res_y * padding),
        )

        # Маска отступов
        pmask = (extended[0] != srs.minx, extended[1] != srs.miny,
                 extended[2] != srs.maxx, extended[3] != srs.maxy)

        # Размер изображения с учетом отступов
        render_size = (size[0] + int(pmask[0] + pmask[2]) * padding,
                       size[1] + int(pmask[1] + pmask[3]) * padding)

        # Фрагмент изображения размера size
        target_box = (pmask[0] * padding, pmask[3] * padding,
                      size[0] + pmask[0] * padding,
                      size[1] + pmask[3] * padding)

        # Выбираем объекты по экстенту
        feature_query = self.parent.feature_query()

        # FIXME: Тоже самое, но через интерфейсы
        if hasattr(feature_query, 'srs'):
            feature_query.srs(srs)

        feature_query.intersects(box(*extended, srid=srs.id))
        feature_query.geom()
        features = feature_query()

        res_img = None
        try:
            dirname, fndata, fnstyle = None, None, None

            dirname = mkdtemp()
            fndata = os.path.join(dirname, 'layer.geojson')

            with open(fndata, 'wb') as fd:
                fd.write(geojson.dumps(features))

            fnstyle = os.path.join(dirname, 'layer.qml')
            os.symlink(env.file_storage.filename(self.qml_fileobj), fnstyle)

            result = Queue()
            env.qgis.queue.put(
                (fndata, self.srs, render_size, extended, target_box, result))
            render_timeout = int(env.qgis.settings.get('render_timeout'))
            res_img = result.get(block=True, timeout=render_timeout)

        finally:
            if fndata and os.path.isfile(fndata):
                os.unlink(fndata)
            if fnstyle and os.path.isfile(fnstyle):
                os.unlink(fnstyle)
            if dirname and os.path.isdir(dirname):
                os.rmdir(dirname)

        return res_img
예제 #10
0
    def _render_image(self, srs, extent, size, cond, padding=0):
        extended, render_size, target_box = _render_bounds(
            extent, size, padding)

        feature_query = self.parent.feature_query()

        # Apply filter condition
        if cond is not None:
            feature_query.filter_by(**cond)

        # TODO: Do this via interfaces
        if hasattr(feature_query, 'srs'):
            feature_query.srs(srs)

        feature_query.intersects(box(*extended, srid=srs.id))
        feature_query.geom()

        env.qgis.qgis_init()

        crs = CRS.from_epsg(srs.id)

        mreq = MapRequest()
        mreq.set_dpi(96)
        mreq.set_crs(crs)

        def path_resolver(name):
            for skip_path in SKIP_PATHS:
                if name.startswith(skip_path):
                    name = name.replace(skip_path, '', 1)
                    break

            if path.isabs(name):
                raise ValueError("Absolute paths are not allowed.")

            name = path.normpath(name)
            if name[-4:].lower() == '.svg':
                name = name[:-4]

            items = name.split(path.sep)
            for i in range(len(items)):
                candidate = path.sep.join(items[i:])
                filename = env.svg_marker_library.lookup(
                    candidate, self.svg_marker_library)
                if filename is not None:
                    return filename

            return name

        style = Style.from_string(
            _qml_cache(env.file_storage.filename(self.qml_fileobj)),
            path_resolver)

        style_attrs = style.used_attributes()

        qhl_fields = list()
        cnv_fields = list()
        qry_fields = list()

        for field in self.parent.fields:
            fkeyname = field.keyname
            if (style_attrs is not None) and (fkeyname not in style_attrs):
                continue
            field_to_qgis = _FIELD_TYPE_TO_QGIS[field.datatype]
            qhl_fields.append((fkeyname, field_to_qgis[0]))
            cnv_fields.append((fkeyname, field_to_qgis[1]))
            qry_fields.append(fkeyname)

        feature_query.fields(*qry_fields)

        features = list()
        for feat in feature_query():
            features.append((feat.id, feat.geom.wkb,
                             tuple([
                                 convert(feat.fields[field])
                                 for field, convert in cnv_fields
                             ])))

        if len(features) == 0:
            return None

        layer = Layer.from_data(_GEOM_TYPE_TO_QGIS[self.parent.geometry_type],
                                crs, tuple(qhl_fields), tuple(features))

        mreq.add_layer(layer, style)

        res = mreq.render_image(extent, size)
        return qgis_image_to_pil(res)