def calc_scale(bbox, map_renderer):
    coord_transform = QgsCoordinateTransform(
        QgsCoordinateReferenceSystem(4326),
        QgsCoordinateReferenceSystem(27700)
    )
    # As we are using the QgsScaleCalculator to determine the scale we need to
    # create a standard bounding box to calculate the scale for the width and a
    # bounding box on it's side to calculate the scale to fit the height
    width_bbox = coord_transform.transform(QgsRectangle(bbox[0], bbox[1], bbox[2], bbox[3]))
    height_bbox = coord_transform.transform(QgsRectangle(bbox[1], bbox[0], bbox[3], bbox[2]))
    scale_calc = QgsScaleCalculator(map_renderer.outputDpi())
    scale = max(
        scale_calc.calculate(width_bbox, map_renderer.width()),
        scale_calc.calculate(height_bbox, map_renderer.height())
    )
    return scale * 1.1
Пример #2
0
    def identify(self, params):
        self.check_required_params(params)

        feature_collections = []

        with change_directory(self.project_root):

            crs = QgsCoordinateReferenceSystem()
            crs.createFromSrid(params.get('srs'))

            search_box = self._calcSearchBox(
                params.get('bbox'), params.get('image_size')[0],
                params.get('image_size')[1],
                params.get('click_point')[0], params.get('click_point')[1]
            )

            # initialize mapRenderer and a rendering context in order to be
            # to check if a feature will actually be rendered
            # we don't want to return features that are not visible
            img = QImage(QSize(
                settings.SUNLUMO_GFI_BUFFER*2, settings.SUNLUMO_GFI_BUFFER*2),
                QImage.Format_ARGB32_Premultiplied
            )
            dpm = 1 / 0.00028
            img.setDotsPerMeterX(dpm)
            img.setDotsPerMeterY(dpm)

            mapRenderer = QgsMapRenderer()
            mapRenderer.clearLayerCoordinateTransforms()
            mapRenderer.setOutputSize(QSize(
                settings.SUNLUMO_GFI_BUFFER*2, settings.SUNLUMO_GFI_BUFFER*2),
                img.logicalDpiX()
            )

            mapRenderer.setDestinationCrs(crs)
            mapRenderer.setProjectionsEnabled(True)
            mapUnits = crs.mapUnits()
            mapRenderer.setMapUnits(mapUnits)

            mapExtent = QgsRectangle(*search_box)
            mapRenderer.setExtent(mapExtent)

            renderContext = QgsRenderContext()
            renderContext.setExtent(mapRenderer.extent())
            renderContext.setRasterScaleFactor(1.0)
            renderContext.setMapToPixel(mapRenderer.coordinateTransform())
            renderContext.setRendererScale(mapRenderer.scale())
            renderContext.setScaleFactor(mapRenderer.outputDpi() / 25.4)
            renderContext.setPainter(None)

            qfr = QgsFeatureRequest()
            search_rectangle = QgsRectangle(*search_box)
            qfr.setFilterRect(search_rectangle)

            for q_layer in params.get('query_layers'):
                layer = self.layerRegistry.mapLayer(q_layer)

                if layer.type() == QgsMapLayer.RasterLayer:
                    # skip raster layer processing
                    continue

                # update layer fields (expressions, calculated, joined)
                layer.updateFields()

                scaleCalc = QgsScaleCalculator(
                    (img.logicalDpiX() + img.logicalDpiY()) / 2,
                    mapRenderer.destinationCrs().mapUnits()
                )
                scaleDenom = scaleCalc.calculate(mapExtent, img.width())

                # skip the layer if it's not visible at the current map scale
                if layer.hasScaleBasedVisibility():
                    if not(layer.minimumScale()
                            < scaleDenom < layer.maximumScale()):
                        continue

                # check if features actually intersect search rectangle
                intersected_features = self._intersectedFeatures(
                    layer.getFeatures(qfr), search_rectangle
                )
                # visible features generator
                visible_features = self._visibleFeatures(
                    layer, renderContext, intersected_features
                )
                layer_features = [featureToGeoJSON(
                    feature.id(), feature.geometry(),
                    self._collectAttributes(layer, feature)
                ) for feature in visible_features
                ]

                feature_collections.append(layer_features)

            return writeGeoJSON(chain(*feature_collections))