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
def testCalculateImageSize(self): calculator = QgsScaleCalculator() calculator.setDpi(96) calculator.setMapUnits(QgsUnitTypes.DistanceMeters) extent = QgsRectangle(336609, 1162304, 354942, 1168151) image_size = calculator.calculateImageSize(extent, 65000) self.assertAlmostEqual(image_size.width(), 1066.001, 3) self.assertAlmostEqual(image_size.height(), 339.983, 3)
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))