def renderTile(self, x, y): """ Render one tile :param x: The x index of the current tile :param y: The y index of the current tile """ painter = QPainter(self.image) self.settings.setExtent( QgsRectangle( self.extent.xMinimum() + x * self.mupp * self.tile_size, self.extent.yMaximum() - (y + 1) * self.mupp * self.tile_size, self.extent.xMinimum() + (x + 1) * self.mupp * self.tile_size, self.extent.yMaximum() - y * self.mupp * self.tile_size)) job = QgsMapRendererCustomPainterJob(self.settings, painter) job.renderSynchronously() painter.end() # Needs not to be deleted or Windows will kill it too early... tmpfile = tempfile.NamedTemporaryFile(suffix='.png', delete=False) try: self.image.save(tmpfile.name) src_ds = osgeo.gdal.Open(tmpfile.name) self.dataset.WriteRaster( x * self.tile_size, y * self.tile_size, self.tile_size, self.tile_size, src_ds.ReadRaster(0, 0, self.tile_size, self.tile_size)) finally: del src_ds tmpfile.close() os.unlink(tmpfile.name)
def renderedImage(self, width, height, extent, transp_background=False, layerids=None): # render layers with QgsMapRendererCustomPainterJob from qgis.core import QgsMapRendererCustomPainterJob antialias = True settings = self.exportSettings.mapSettings # store old map settings old_outputSize = settings.outputSize() old_extent = settings.extent() old_rotation = settings.rotation() old_layers = settings.layers() old_backgroundColor = settings.backgroundColor() # map settings settings.setOutputSize(QSize(width, height)) settings.setExtent(extent.unrotatedRect()) settings.setRotation(extent.rotation()) if layerids: settings.setLayers(tools.getLayersByLayerIds(layerids)) if transp_background: settings.setBackgroundColor(QColor(Qt.transparent)) has_pluginlayer = False for layer in settings.layers(): if layer and layer.type() == QgsMapLayer.PluginLayer: has_pluginlayer = True break # create an image image = QImage(width, height, QImage.Format_ARGB32_Premultiplied) painter = QPainter() painter.begin(image) if antialias: painter.setRenderHint(QPainter.Antialiasing) # rendering job = QgsMapRendererCustomPainterJob(settings, painter) if has_pluginlayer: job.renderSynchronously( ) # use this method so that TileLayerPlugin layer is rendered correctly else: job.start() job.waitForFinished() painter.end() # restore map settings settings.setOutputSize(old_outputSize) settings.setExtent(old_extent) settings.setRotation(old_rotation) settings.setLayers(old_layers) settings.setBackgroundColor(old_backgroundColor) return image
def renderedImage(self, width, height, extent, transp_background=False, layerids=None): if QGis.QGIS_VERSION_INT < 20700: return self._renderedImage2(width, height, extent, transp_background, layerids) # render layers with QgsMapRendererCustomPainterJob from qgis.core import QgsMapRendererCustomPainterJob antialias = True settings = self.exportSettings.mapSettings # store old map settings old_outputSize = settings.outputSize() old_extent = settings.extent() old_rotation = settings.rotation() old_layerids = settings.layers() old_backgroundColor = settings.backgroundColor() # map settings settings.setOutputSize(QSize(width, height)) settings.setExtent(extent.unrotatedRect()) settings.setRotation(extent.rotation()) if layerids is not None: settings.setLayers(layerids) if transp_background: settings.setBackgroundColor(QColor(Qt.transparent)) #else: #TODO: remove #settings.setBackgroundColor(self.exportSettings.canvas.canvasColor()) has_pluginlayer = False for layerId in settings.layers(): layer = QgsMapLayerRegistry.instance().mapLayer(layerId) if layer and layer.type() == QgsMapLayer.PluginLayer: has_pluginlayer = True break # create an image image = QImage(width, height, QImage.Format_ARGB32_Premultiplied) painter = QPainter() painter.begin(image) if antialias: painter.setRenderHint(QPainter.Antialiasing) # rendering job = QgsMapRendererCustomPainterJob(settings, painter) if has_pluginlayer: job.renderSynchronously() # use this method so that TileLayerPlugin layer is rendered correctly else: job.start() job.waitForFinished() painter.end() # restore map settings settings.setOutputSize(old_outputSize) settings.setExtent(old_extent) settings.setRotation(old_rotation) settings.setLayers(old_layerids) settings.setBackgroundColor(old_backgroundColor) return tools.base64image(image)
def renderSingleMetatile(self, metatile): if self.feedback.isCanceled(): return # Haven't found a better way to break than to make all the new threads return instantly if "Dummy" in threading.current_thread().name or len( self.settingsDictionary) == 1: # single thread testing threadSpecificSettings = list(self.settingsDictionary.values())[0] else: thread_nr = self.thread_nr_re.search( threading.current_thread().name)[0] # terminating number only threadSpecificSettings = self.settingsDictionary[thread_nr] size = QSize(self.tile_width * metatile.rows(), self.tile_height * metatile.columns()) extent = QgsRectangle(*metatile.extent()) threadSpecificSettings.setExtent( self.wgs_to_dest.transformBoundingBox(extent)) threadSpecificSettings.setOutputSize(size) #Append MapSettings scope in order to update map variables (e.g @map_scale) with new extent data exp_context = threadSpecificSettings.expressionContext() exp_context.appendScope( QgsExpressionContextUtils.mapSettingsScope(threadSpecificSettings)) threadSpecificSettings.setExpressionContext(exp_context) image = QImage(size, QImage.Format_ARGB32_Premultiplied) image.fill(self.color) dpm = threadSpecificSettings.outputDpi() / 25.4 * 1000 image.setDotsPerMeterX(dpm) image.setDotsPerMeterY(dpm) painter = QPainter(image) job = QgsMapRendererCustomPainterJob(threadSpecificSettings, painter) job.renderSynchronously() painter.end() ## For analysing metatiles (labels, etc.) ## metatile_dir = os.path.join(output_dir, str(zoom)) ## os.makedirs(metatile_dir, exist_ok=True) ## image.save(os.path.join(metatile_dir, 'metatile_%s.png' % i)) for r, c, tile in metatile.tiles: tileImage = image.copy(self.tile_width * r, self.tile_height * c, self.tile_width, self.tile_height) self.writer.write_tile(tile, tileImage) # to stop thread sync issues with self.progressThreadLock: self.progress += 1 self.feedback.setProgress(100 * (self.progress / self.totalMetatiles))
def renderTile(self, x, y, feedback, make_trans): """ Render one tile :param x: The x index of the current tile :param y: The y index of the current tile """ if make_trans: background_color = QColor(255, 255, 255, 0) self.image.fill(background_color.rgba()) else: background_color = QColor(255, 255, 255) self.image.fill(background_color.rgb()) painter = QPainter(self.image) self.settings.setExtent( QgsRectangle( self.extent.xMinimum() + x * self.mupp * self.tile_size, self.extent.yMaximum() - (y + 1) * self.mupp * self.tile_size, self.extent.xMinimum() + (x + 1) * self.mupp * self.tile_size, self.extent.yMaximum() - y * self.mupp * self.tile_size)) job = QgsMapRendererCustomPainterJob(self.settings, painter) job.renderSynchronously() painter.end() # Needs not to be deleted or Windows will kill it too early... tmpfile = tempfile.NamedTemporaryFile(suffix='.png', delete=False) try: self.image.save(tmpfile.name) src_ds = osgeo.gdal.Open(tmpfile.name) self.dataset.WriteRaster( x * self.tile_size, y * self.tile_size, self.tile_size, self.tile_size, src_ds.ReadRaster(0, 0, self.tile_size, self.tile_size)) except Exception as e: feedback.reportError(str(e)) finally: del src_ds tmpfile.close() os.unlink(tmpfile.name)
def renderMetatile(self, metatile, dest_crs, outputFormat, renderSettings, transformContext, sourceCrs): wgs_to_dest = QgsCoordinateTransform(sourceCrs, dest_crs, transformContext) renderSettings.setExtent( wgs_to_dest.transformBoundingBox(QgsRectangle(*metatile.extent()))) size = QSize(self.WIDTH * metatile.rows(), self.HEIGHT * metatile.columns()) renderSettings.setOutputSize(size) image = QImage(size, outputFormat) image.fill(Qt.transparent) dpm = renderSettings.outputDpi() / 25.4 * 1000 image.setDotsPerMeterX(dpm) image.setDotsPerMeterY(dpm) painter = QPainter(image) job = QgsMapRendererCustomPainterJob(renderSettings, painter) job.renderSynchronously() painter.end() return image
def renderTile(self, x, y, feedback, make_trans): """ Render one tile :param x: The x index of the current tile :param y: The y index of the current tile """ if make_trans: background_color = QColor(255, 255, 255, 0) self.image.fill(background_color.rgba()) else: background_color = QColor(255, 255, 255) self.image.fill(background_color.rgb()) painter = QPainter(self.image) self.settings.setExtent(QgsRectangle( self.extent.xMinimum() + x * self.mupp * self.tile_size, self.extent.yMaximum() - (y + 1) * self.mupp * self.tile_size, self.extent.xMinimum() + (x + 1) * self.mupp * self.tile_size, self.extent.yMaximum() - y * self.mupp * self.tile_size)) job = QgsMapRendererCustomPainterJob(self.settings, painter) job.renderSynchronously() painter.end() # Needs not to be deleted or Windows will kill it too early... tmpfile = tempfile.NamedTemporaryFile(suffix='.png', delete=False) try: self.image.save(tmpfile.name) src_ds = osgeo.gdal.Open(tmpfile.name) self.dataset.WriteRaster(x * self.tile_size, y * self.tile_size, self.tile_size, self.tile_size, src_ds.ReadRaster(0, 0, self.tile_size, self.tile_size)) except Exception as e: feedback.reportError(str(e)) finally: del src_ds tmpfile.close() os.unlink(tmpfile.name)
def writeThumbnail(self, mapDestExtent, mapTitle, mapAttr, operation, renderSettings): mapTitle = UTILS.normalizeName(mapTitle) mapAttr = UTILS.normalizeName(mapAttr) renderSettings.setExtent(mapDestExtent) size = QSize(180, 180) renderSettings.setOutputSize(size) image = QImage(size, QImage.Format_ARGB32_Premultiplied) image.fill(Qt.transparent) dpm = renderSettings.outputDpi() / 25.4 * 1000 image.setDotsPerMeterX(dpm) image.setDotsPerMeterY(dpm) painter = QPainter(image) job = QgsMapRendererCustomPainterJob(renderSettings, painter) job.renderSynchronously() painter.end() legendFolder = self.getPathForMap(mapTitle, mapAttr, operation) os.makedirs(legendFolder, exist_ok=True) image.save(os.path.join(legendFolder, 'thumbnail.png'), self.format, self.quality)
def renderMetatile(metatile, dest_crs, renderSettings, transformContext, sourceCrs, width, height): wgs_to_dest = QgsCoordinateTransform(sourceCrs, dest_crs, transformContext) renderSettings.setExtent( wgs_to_dest.transformBoundingBox(QgsRectangle(*metatile.extent()))) size = QSize(width * metatile.rows(), height * metatile.columns()) renderSettings.setOutputSize(size) image = QImage(size, renderSettings.outputImageFormat()) image.fill(Qt.transparent) dpm = renderSettings.outputDpi() / 25.4 * 1000 image.setDotsPerMeterX(dpm) image.setDotsPerMeterY(dpm) painter = QPainter(image) #painter.setRenderHints(QPainter.RenderHint.NonCosmeticDefaultPen, on=True) #painter.setCompositionMode(QPainter.CompositionMode_Source) job = QgsMapRendererCustomPainterJob(renderSettings, painter) job.renderSynchronously() painter.end() return image
def renderer(self): if 'QGIS_AUTH_DB_DIR_PATH' not in os.environ: os.environ['QGIS_AUTH_DB_DIR_PATH'] = '/tmp' qgis = None while True: options, result = self.queue.get() # Don't start QGIS until first request if qgis is None: qgis = QgsApplication([], False) qgis.setPrefixPath(self.settings.get('path'), True) qgis.setDefaultSvgPaths(qgis.svgPaths() + self.settings.get('svgpaths')) qgis.setMaxThreads(1) qgis.initQgis() try: if isinstance(options, LegendOptions): style, = options layer = self._qgs_memory_layer(style) layer.setName(style.parent.display_name) QgsMapLayerRegistry.instance().addMapLayer(layer) root = QgsLayerTreeGroup() root.addLayer(layer) # 'Cannot create a QPixmap when no GUI is being used' # warning occurs here model = QgsLayerTreeModel(root) settings = QgsLegendSettings() settings.setTitle('') settings.setBoxSpace(1) settings.setSymbolSize(QSizeF(5, 3)) settings.setDpi(96) renderer = QgsLegendRenderer(model, settings) # Dots per mm dpmm = settings.dpi() / 25.4 min_size = renderer.minimumSize() size = QSize(dpmm * min_size.width(), dpmm * min_size.height()) img = QImage(size, QImage.Format_ARGB32) img.fill(QColor(0, 0, 0, 0)) painter = QPainter() painter.begin(img) painter.scale(dpmm, dpmm) renderer.drawLegend(painter) painter.end() QgsMapLayerRegistry.instance().removeAllMapLayers() ba = QByteArray() bf = QBuffer(ba) bf.open(QIODevice.WriteOnly) img.save(bf, 'PNG') bf.close() buf = StringIO() buf.write(bf.data()) buf.seek(0) result.put(buf) else: path = features = None if isinstance(options, VectorRenderOptions): style, features, render_size, \ extended, target_box = options layer = self._qgs_memory_layer(style, features=features) elif isinstance(options, RasterRenderOptions): style, path, render_size, \ extended, target_box = options layer = QgsRasterLayer(path) layer.loadNamedStyle( self.env.file_storage.filename(style.qml_fileobj)) settings = QgsMapSettings() settings.setLayers([layer.id()]) settings.setFlag(QgsMapSettings.DrawLabeling) settings.setFlag(QgsMapSettings.Antialiasing) settings.setCrsTransformEnabled(True) settings.setDestinationCrs(layer.crs()) settings.setMapUnits(layer.crs().mapUnits()) settings.setOutputSize(QSize(*render_size)) settings.setExtent(QgsRectangle(*extended)) settings.setOutputImageFormat(QImage.Format_ARGB32) bgcolor = QColor.fromRgba(qRgba(255, 255, 255, 0)) settings.setBackgroundColor(bgcolor) settings.setOutputDpi(96) QgsMapLayerRegistry.instance().addMapLayer(layer) settings.setLayers([layer.id()]) # Create QImage by hand to be able to use # QgsMapRendererCustomPainterJob. Others will not # allow to workaround a bug with overlay rendering. img = QImage(settings.outputSize(), QImage.Format_ARGB32) # These cludges are needed for rendering # on transparent background, otherwise it's a mess. img.fill(QColor.fromRgba(qRgba(255, 255, 255, 255))) img.fill(QColor.fromRgba(qRgba(255, 255, 255, 0))) # DPI should be equal to settings, otherwise an error. # In QImage the resolution is set in dots per meter # for each axis. dpm = settings.outputDpi() / 25.4 * 1000 img.setDotsPerMeterX(dpm) img.setDotsPerMeterY(dpm) painter = QPainter(img) job = QgsMapRendererCustomPainterJob(settings, painter) job.renderSynchronously() painter.end() QgsMapLayerRegistry.instance().removeAllMapLayers() img = self._qimage_to_pil(img) # Clip needed part result.put(img.crop(target_box)) # Cleanup if path is not None: gdal.Unlink(path) except Exception as exc: self.logger.error(exc.message) result.put(exc) qgis.exitQgis()
def processAlgorithm(self, parameters, context, feedback): feedback.setProgress(1) extent = self.parameterAsExtent(parameters, self.EXTENT, context) min_zoom = self.parameterAsInt(parameters, self.ZOOM_MIN, context) max_zoom = self.parameterAsInt(parameters, self.ZOOM_MAX, context) dpi = self.parameterAsInt(parameters, self.DPI, context) tile_format = self.formats[self.parameterAsEnum(parameters, self.TILE_FORMAT, context)] output_format = self.outputs[self.parameterAsEnum(parameters, self.OUTPUT_FORMAT, context)] if output_format == 'Directory': output_dir = self.parameterAsString(parameters, self.OUTPUT_DIRECTORY, context) if not output_dir: raise QgsProcessingException(self.tr('You need to specify output directory.')) else: # MBTiles output_file = self.parameterAsString(parameters, self.OUTPUT_FILE, context) if not output_file: raise QgsProcessingException(self.tr('You need to specify output filename.')) tile_width = 256 tile_height = 256 wgs_crs = QgsCoordinateReferenceSystem('EPSG:4326') dest_crs = QgsCoordinateReferenceSystem('EPSG:3857') project = context.project() src_to_wgs = QgsCoordinateTransform(project.crs(), wgs_crs, context.transformContext()) wgs_to_dest = QgsCoordinateTransform(wgs_crs, dest_crs, context.transformContext()) settings = QgsMapSettings() settings.setOutputImageFormat(QImage.Format_ARGB32_Premultiplied) settings.setDestinationCrs(dest_crs) settings.setLayers(self.layers) settings.setOutputDpi(dpi) if tile_format == 'PNG': settings.setBackgroundColor(QColor(Qt.transparent)) wgs_extent = src_to_wgs.transformBoundingBox(extent) wgs_extent = [wgs_extent.xMinimum(), wgs_extent.yMinimum(), wgs_extent.xMaximum(), wgs_extent.yMaximum()] metatiles_by_zoom = {} metatiles_count = 0 for zoom in range(min_zoom, max_zoom + 1): metatiles = get_metatiles(wgs_extent, zoom, 4) metatiles_by_zoom[zoom] = metatiles metatiles_count += len(metatiles) lab_buffer_px = 100 progress = 0 tile_params = { 'format': tile_format, 'quality': 75, 'width': tile_width, 'height': tile_height } if output_format == 'Directory': writer = DirectoryWriter(output_dir, tile_params) else: writer = MBTilesWriter(output_file, tile_params, wgs_extent, min_zoom, max_zoom) for zoom in range(min_zoom, max_zoom + 1): feedback.pushConsoleInfo('Generating tiles for zoom level: %s' % zoom) for i, metatile in enumerate(metatiles_by_zoom[zoom]): size = QSize(tile_width * metatile.rows(), tile_height * metatile.columns()) extent = QgsRectangle(*metatile.extent()) settings.setExtent(wgs_to_dest.transformBoundingBox(extent)) settings.setOutputSize(size) label_area = QgsRectangle(settings.extent()) lab_buffer = label_area.width() * (lab_buffer_px / size.width()) label_area.set( label_area.xMinimum() + lab_buffer, label_area.yMinimum() + lab_buffer, label_area.xMaximum() - lab_buffer, label_area.yMaximum() - lab_buffer ) settings.setLabelBoundaryGeometry(QgsGeometry.fromRect(label_area)) image = QImage(size, QImage.Format_ARGB32_Premultiplied) image.fill(Qt.transparent) dpm = settings.outputDpi() / 25.4 * 1000 image.setDotsPerMeterX(dpm) image.setDotsPerMeterY(dpm) painter = QPainter(image) job = QgsMapRendererCustomPainterJob(settings, painter) job.renderSynchronously() painter.end() # For analysing metatiles (labels, etc.) # metatile_dir = os.path.join(output_dir, str(zoom)) # os.makedirs(metatile_dir, exist_ok=True) # image.save(os.path.join(metatile_dir, 'metatile_%s.png' % i)) for r, c, tile in metatile.tiles: tile_img = image.copy(tile_width * r, tile_height * c, tile_width, tile_height) writer.writeTile(tile, tile_img) progress += 1 feedback.setProgress(100 * (progress / metatiles_count)) writer.close() results = {} if output_format == 'Directory': results['OUTPUT_DIRECTORY'] = output_dir else: # MBTiles results['OUTPUT_FILE'] = output_file return results
def processAlgorithm(self, parameters, context, feedback): feedback.setProgress(1) extent = self.parameterAsExtent(parameters, self.EXTENT, context) min_zoom = self.parameterAsInt(parameters, self.ZOOM_MIN, context) max_zoom = self.parameterAsInt(parameters, self.ZOOM_MAX, context) dpi = self.parameterAsInt(parameters, self.DPI, context) tile_format = self.formats[self.parameterAsEnum(parameters, self.TILE_FORMAT, context)] output_format = self.outputs[self.parameterAsEnum(parameters, self.OUTPUT_FORMAT, context)] if output_format == 'Directory': output_dir = self.parameterAsString(parameters, self.OUTPUT_DIRECTORY, context) if not output_dir: raise QgsProcessingException(self.tr('You need to specify output directory.')) else: # MBTiles output_file = self.parameterAsString(parameters, self.OUTPUT_FILE, context) if not output_file: raise QgsProcessingException(self.tr('You need to specify output filename.')) tile_width = 256 tile_height = 256 wgs_crs = QgsCoordinateReferenceSystem('EPSG:4326') dest_crs = QgsCoordinateReferenceSystem('EPSG:3857') project = context.project() src_to_wgs = QgsCoordinateTransform(project.crs(), wgs_crs, context.transformContext()) wgs_to_dest = QgsCoordinateTransform(wgs_crs, dest_crs, context.transformContext()) settings = QgsMapSettings() settings.setOutputImageFormat(QImage.Format_ARGB32_Premultiplied) settings.setDestinationCrs(dest_crs) settings.setLayers(self.layers) settings.setOutputDpi(dpi) wgs_extent = src_to_wgs.transformBoundingBox(extent) wgs_extent = [wgs_extent.xMinimum(), wgs_extent.yMinimum(), wgs_extent.xMaximum(), wgs_extent.yMaximum()] metatiles_by_zoom = {} metatiles_count = 0 for zoom in range(min_zoom, max_zoom + 1): metatiles = get_metatiles(wgs_extent, zoom, 4) metatiles_by_zoom[zoom] = metatiles metatiles_count += len(metatiles) lab_buffer_px = 100 progress = 0 tile_params = { 'format': tile_format, 'quality': 75, 'width': tile_width, 'height': tile_height } if output_format == 'Directory': writer = DirectoryWriter(output_dir, tile_params) else: writer = MBTilesWriter(output_file, tile_params, wgs_extent, min_zoom, max_zoom) for zoom in range(min_zoom, max_zoom + 1): feedback.pushConsoleInfo('Generating tiles for zoom level: %s' % zoom) for i, metatile in enumerate(metatiles_by_zoom[zoom]): size = QSize(tile_width * metatile.rows(), tile_height * metatile.columns()) extent = QgsRectangle(*metatile.extent()) settings.setExtent(wgs_to_dest.transformBoundingBox(extent)) settings.setOutputSize(size) label_area = QgsRectangle(settings.extent()) lab_buffer = label_area.width() * (lab_buffer_px / size.width()) label_area.set( label_area.xMinimum() + lab_buffer, label_area.yMinimum() + lab_buffer, label_area.xMaximum() - lab_buffer, label_area.yMaximum() - lab_buffer ) settings.setLabelBoundaryGeometry(QgsGeometry.fromRect(label_area)) image = QImage(size, QImage.Format_ARGB32_Premultiplied) image.fill(Qt.transparent) dpm = settings.outputDpi() / 25.4 * 1000 image.setDotsPerMeterX(dpm) image.setDotsPerMeterY(dpm) painter = QPainter(image) job = QgsMapRendererCustomPainterJob(settings, painter) job.renderSynchronously() painter.end() # For analysing metatiles (labels, etc.) # metatile_dir = os.path.join(output_dir, str(zoom)) # os.makedirs(metatile_dir, exist_ok=True) # image.save(os.path.join(metatile_dir, 'metatile_%s.png' % i)) for r, c, tile in metatile.tiles: tile_img = image.copy(tile_width * r, tile_height * c, tile_width, tile_height) writer.writeTile(tile, tile_img) progress += 1 feedback.setProgress(100 * (progress / metatiles_count)) writer.close() results = {} if output_format == 'Directory': results['OUTPUT_DIRECTORY'] = output_dir else: # MBTiles results['OUTPUT_FILE'] = output_file return results
def generate(self, writer, parameters, context, feedback): feedback.setProgress(1) extent = self.parameterAsExtent(parameters, self.EXTENT, context) self.min_zoom = self.parameterAsInt(parameters, self.ZOOM_MIN, context) self.max_zoom = self.parameterAsInt(parameters, self.ZOOM_MAX, context) dpi = self.parameterAsInt(parameters, self.DPI, context) self.tile_format = self.formats[self.parameterAsEnum(parameters, self.TILE_FORMAT, context)] tile_width = 256 tile_height = 256 wgs_crs = QgsCoordinateReferenceSystem('EPSG:4326') dest_crs = QgsCoordinateReferenceSystem('EPSG:3857') project = context.project() src_to_wgs = QgsCoordinateTransform(project.crs(), wgs_crs, context.transformContext()) wgs_to_dest = QgsCoordinateTransform(wgs_crs, dest_crs, context.transformContext()) settings = QgsMapSettings() settings.setOutputImageFormat(QImage.Format_ARGB32_Premultiplied) settings.setDestinationCrs(dest_crs) settings.setLayers(self.layers) settings.setOutputDpi(dpi) if self.tile_format == 'PNG': settings.setBackgroundColor(QColor(Qt.transparent)) self.wgs_extent = src_to_wgs.transformBoundingBox(extent) self.wgs_extent = [self.wgs_extent.xMinimum(), self.wgs_extent.yMinimum(), self.wgs_extent.xMaximum(), self.wgs_extent.yMaximum()] metatiles_by_zoom = {} metatiles_count = 0 for zoom in range(self.min_zoom, self.max_zoom + 1): metatiles = get_metatiles(self.wgs_extent, zoom, 4) metatiles_by_zoom[zoom] = metatiles metatiles_count += len(metatiles) lab_buffer_px = 100 progress = 0 tile_params = { 'format': self.tile_format, 'quality': 75, 'width': tile_width, 'height': tile_height, 'min_zoom': self.min_zoom, 'max_zoom': self.max_zoom, 'extent': self.wgs_extent, } writer.set_parameters(tile_params) for zoom in range(self.min_zoom, self.max_zoom + 1): feedback.pushConsoleInfo('Generating tiles for zoom level: %s' % zoom) for i, metatile in enumerate(metatiles_by_zoom[zoom]): if feedback.isCanceled(): break size = QSize(tile_width * metatile.rows(), tile_height * metatile.columns()) extent = QgsRectangle(*metatile.extent()) settings.setExtent(wgs_to_dest.transformBoundingBox(extent)) settings.setOutputSize(size) if hasattr(settings, 'setLabelBoundaryGeometry'): label_area = QgsRectangle(settings.extent()) lab_buffer = label_area.width() * (lab_buffer_px / size.width()) label_area.set( label_area.xMinimum() + lab_buffer, label_area.yMinimum() + lab_buffer, label_area.xMaximum() - lab_buffer, label_area.yMaximum() - lab_buffer ) settings.setLabelBoundaryGeometry(QgsGeometry.fromRect(label_area)) image = QImage(size, QImage.Format_ARGB32_Premultiplied) image.fill(Qt.transparent) dpm = settings.outputDpi() / 25.4 * 1000 image.setDotsPerMeterX(dpm) image.setDotsPerMeterY(dpm) painter = QPainter(image) job = QgsMapRendererCustomPainterJob(settings, painter) job.renderSynchronously() painter.end() # For analysing metatiles (labels, etc.) # metatile_dir = os.path.join(output_dir, str(zoom)) # os.makedirs(metatile_dir, exist_ok=True) # image.save(os.path.join(metatile_dir, 'metatile_%s.png' % i)) for r, c, tile in metatile.tiles: tile_img = image.copy(tile_width * r, tile_height * c, tile_width, tile_height) writer.write_tile(tile, tile_img) progress += 1 feedback.setProgress(100 * (progress / metatiles_count)) writer.close()
print('crs authid: %s' % layer.crs().authid()) print('extent: %s' % layer.sourceExtent().toString()) QgsProject.instance().addMapLayer(layer) image = QImage(QSize(600, 400), QImage.Format_ARGB32_Premultiplied) image.fill(QColor(255, 255, 128).rgb()) painter = QPainter(image) settings = QgsMapSettings() settings.setOutputDpi(image.logicalDpiX()) settings.setOutputImageFormat(QImage.Format_ARGB32) settings.setDestinationCrs(layer.crs()) settings.setOutputSize(image.size()) settings.setFlag(QgsMapSettings.Antialiasing, True) settings.setFlag(QgsMapSettings.RenderMapTile, True) settings.setFlag(QgsMapSettings.UseAdvancedEffects, True) settings.setBackgroundColor(QColor(255, 255, 255, 0)) settings.setLayers([layer]) settings.setExtent(layer.extent()) job = QgsMapRendererCustomPainterJob(settings, painter) job.renderSynchronously() painter.end() output_path = os.environ.get('QGIS_DJANGO_PROVIDER_TEST_OUTPUT', '/tmp/qgis-django-provider-test.png') image.save(output_path, 'png')
def GDX_Publisher(self): # print ("GDX_Publisher -------------------------------\n") tumpdir = unicode( QFileInfo(QgsApplication.qgisUserDatabaseFilePath()).path() ) + "/python/plugins/gearthview3/_WebServer" # print (tumpdir) adesso = str(datetime.datetime.now()) adesso = adesso.replace(" ", "_") adesso = adesso.replace(":", "_") adesso = adesso.replace(".", "_") # print ("adesso: <%s>\n" %(adesso)) # HERE IT DELETES THE OLD IMAGE ------------------------------------ # (if you comment these, images still remain ... :) for filename in glob.glob(str(tumpdir + '/*.png')): os.remove(str(filename)) for filename in glob.glob(str(tumpdir + '/*.pngw')): os.remove(str(filename)) # ------------------------------------------------------------------ mapCanvas = self.iface.mapCanvas() text = mapCanvas.extent().toString() text1 = text.replace(",", " ") text2 = text1.replace(" : ", ",") # print ("extent: <%s>\n" %(text2)) layer = mapCanvas.currentLayer() # print ("Layer: <%s>\n" %(layer.name() )) extent = mapCanvas.extent() crsSrc = mapCanvas.mapSettings().destinationCrs() crsDest = QgsCoordinateReferenceSystem(4326) try: transform = QgsCoordinateTransform(crsSrc, crsDest, QgsProject.instance()) except: transform = QgsCoordinateTransform(crsSrc, crsDest) projectedExtent = transform.transformBoundingBox(extent) x1 = projectedExtent.xMinimum() y1 = projectedExtent.yMinimum() x2 = projectedExtent.xMaximum() y2 = projectedExtent.yMinimum() x3 = projectedExtent.xMaximum() y3 = projectedExtent.yMaximum() x4 = projectedExtent.xMinimum() y4 = projectedExtent.yMaximum() xc = (x1 + x3) / 2. yc = (y1 + y3) / 2. out_folder = tumpdir # create output image and initialize it mapRect = mapCanvas.extent() width = mapCanvas.width() height = mapCanvas.height() srs = mapCanvas.mapSettings().destinationCrs() # print (width, height) # MINORU # canvas = mapCanvas ## image = QImage(size.width(), size.height(), QImage.Format_ARGB32_Premultiplied) # image = QImage(QSize(math.ceil(width), math.ceil(height)), QImage.Format_ARGB32) # image.fill(Qt.transparent) ## image.fill(QColor(0)) # painter = QPainter() # painter.setRenderHint(QPainter.Antialiasing, True) # painter.setRenderHint(QPainter.TextAntialiasing, True) # painter.setRenderHint(QPainter.SmoothPixmapTransform, True) ## painter.setRenderHint(QPainter.transparent, True) # ## brush = QtGui.QBrush() ## brush.setColor(QtGui.QColor(0)) ## painter.setBackground(self, 0) # # painter.begin(image) # canvas.render(painter) # painter.end() # MINORU # MINORU2 # settings = self.exportSettings.mapSettings settings = QgsMapSettings() # extent = settings.extent() extent = mapCanvas.extent() # store old map settings # old_outputSize = settings.outputSize() # old_extent = settings.extent() # old_rotation = settings.rotation() # old_layers = settings.layers() # old_backgroundColor = settings.backgroundColor() # map settings settings.setOutputSize(QSize(width, height)) # settings.setExtent(extent.unrotatedRect()) # settings.setRotation(extent.rotation()) # if layerids: # settings.setLayers(tools.getLayersByLayerIds(layerids)) # if transp_background: settings.setBackgroundColor(QColor(Qt.transparent)) has_pluginlayer = False for layer in settings.layers(): if layer and layer.type() == QgsMapLayer.PluginLayer: has_pluginlayer = True break # create an image image = QImage(width, height, QImage.Format_ARGB32_Premultiplied) painter = QPainter() painter.begin(image) # if antialias: # painter.setRenderHint(QPainter.Antialiasing) # rendering job = QgsMapRendererCustomPainterJob(settings, painter) if has_pluginlayer: job.renderSynchronously( ) # use this method so that TileLayerPlugin layer is rendered correctly else: job.start() job.waitForFinished() painter.end() # restore map settings # settings.setOutputSize(old_outputSize) # settings.setExtent(old_extent) # settings.setRotation(old_rotation) # settings.setLayers(old_layers) # settings.setBackgroundColor(old_backgroundColor) # MINORU2 kml = codecs.open(out_folder + '/doc.kml', 'w', encoding='utf-8') kml.write('<?xml version="1.0" encoding="UTF-8"?>\n') kml.write( '<kml xmlns="http://www.opengis.net/kml/2.2" xmlns:gx="http://www.google.com/kml/ext/2.2" xmlns:kml="http://www.opengis.net/kml/2.2" xmlns:atom="http://www.w3.org/2005/Atom">\n' ) kml.write(' <Document>\n') kml.write(' <name>QGisView</name>\n') kml.write(' <Snippet maxLines="0"></Snippet>\n') # loc = (" <description><![CDATA[https://map.what3words.com/%.7lf,%.7lf]]></description>\n") %(yc, xc) # kml.write(loc) kml.write(' <open>1</open>\n') kml.write(' <Style id="sh_style">\n') kml.write(' <PolyStyle>\n') kml.write(' <color>7fff8080</color>\n') kml.write(' </PolyStyle>\n') kml.write(' </Style>\n') kml.write(' <StyleMap id="msn_style">\n') kml.write(' <Pair>\n') kml.write(' <key>normal</key>\n') kml.write(' <styleUrl>#sn_style</styleUrl>\n') kml.write(' </Pair>\n') kml.write(' <Pair>\n') kml.write(' <key>highlight</key>\n') kml.write(' <styleUrl>#sh_style</styleUrl>\n') kml.write(' </Pair>\n') kml.write(' </StyleMap>\n') kml.write(' <Style id="sn_style">\n') kml.write(' <PolyStyle>\n') kml.write(' <color>00ff8080</color>\n') kml.write(' <fill>0</fill>\n') kml.write(' </PolyStyle>\n') kml.write(' </Style>\n') kml.write(' <Style id="sh_ylw-pushpin">\n') kml.write(' <IconStyle>\n') kml.write(' <scale>1.2</scale>\n') kml.write(' </IconStyle>\n') kml.write(' <PolyStyle>\n') kml.write(' <fill>0</fill>\n') kml.write(' </PolyStyle>\n') kml.write(' </Style>\n') kml.write(' <Style id="sn_ylw-pushpin">\n') kml.write(' <PolyStyle>\n') kml.write(' <fill>0</fill>\n') kml.write(' </PolyStyle>\n') kml.write(' </Style>\n') kml.write(' <StyleMap id="msn_ylw-pushpin">\n') kml.write(' <Pair>\n') kml.write(' <key>normal</key>\n') kml.write(' <styleUrl>#sn_ylw-pushpin</styleUrl>\n') kml.write(' </Pair>\n') kml.write(' <Pair>\n') kml.write(' <key>highlight</key>\n') kml.write(' <styleUrl>#sh_ylw-pushpin</styleUrl>\n') kml.write(' </Pair>\n') kml.write(' </StyleMap>\n') kml.write(' <StyleMap id="msn_style">\n') kml.write(' <Pair>\n') kml.write(' <key>normal</key>\n') kml.write(' <styleUrl>#sn_style</styleUrl>\n') kml.write(' </Pair>\n') kml.write(' <Pair>\n') kml.write(' <key>highlight</key>\n') kml.write(' <styleUrl>#sh_style</styleUrl>\n') kml.write(' </Pair>\n') kml.write(' </StyleMap>\n') kml.write(' <Style id="hl">\n') kml.write(' <IconStyle>\n') kml.write(' <scale>0.7</scale>\n') kml.write(' <Icon>\n') kml.write( ' <href>http://maps.google.com/mapfiles/kml/shapes/placemark_circle_highlight.png</href>\n' ) kml.write(' </Icon>\n') kml.write(' </IconStyle>\n') kml.write(' <LabelStyle>\n') kml.write(' <scale>0.7</scale>\n') kml.write(' </LabelStyle>\n') kml.write(' <ListStyle>\n') kml.write(' </ListStyle>\n') kml.write(' </Style>\n') kml.write(' <Style id="default">\n') kml.write(' <IconStyle>\n') kml.write(' <scale>0.7</scale>\n') kml.write(' <Icon>\n') kml.write( ' <href>http://maps.google.com/mapfiles/kml/shapes/placemark_circle.png</href>\n' ) kml.write(' </Icon>\n') kml.write(' </IconStyle>\n') kml.write(' <LabelStyle>\n') kml.write(' <scale>0.7</scale>\n') kml.write(' </LabelStyle>\n') kml.write(' <ListStyle>\n') kml.write(' </ListStyle>\n') kml.write(' </Style>\n') kml.write(' <StyleMap id="default0">\n') kml.write(' <Pair>\n') kml.write(' <key>normal</key>\n') kml.write(' <styleUrl>#default</styleUrl>\n') kml.write(' </Pair>\n') kml.write(' <Pair>\n') kml.write(' <key>highlight</key>\n') kml.write(' <styleUrl>#hl</styleUrl>\n') kml.write(' </Pair>\n') kml.write(' </StyleMap>\n') rotazio = 0.0 rotazio = -(mapCanvas.rotation()) kml.write(' <Folder>\n') xc = (x1 + x3) / 2. yc = (y1 + y3) / 2. dx = (x3 - x1) * 75000. #100000. kml.write(' <open>1</open>\n') kml.write(' <NetworkLink>\n') kml.write(' <name>QGIS_link</name>\n') kml.write(' <visibility>1</visibility>\n') kml.write(' <open>1</open>\n') kml.write(' <Link>\n') kml.write(' <href>QGIS_link.kmz</href>\n') kml.write(' </Link>\n') kml.write(' </NetworkLink>\n') kml.write(' <LookAt>\n') stringazza = (" <longitude>%lf</longitude>\n") % (xc) kml.write(stringazza) stringazza = (" <latitude>%lf</latitude>\n") % (yc) kml.write(stringazza) kml.write(' <altitude>0</altitude>\n') stringazza = (" <heading>%lf</heading>\n") % (rotazio) kml.write(stringazza) kml.write(' <tilt>0</tilt>\n') stringazza = (" <range>%lf</range>\n") % (dx) kml.write(stringazza) kml.write(' <gx:altitudeMode>relativeToGround</gx:altitudeMode>\n') kml.write(' </LookAt>\n') kml.write(' <GroundOverlay>\n') kml.write(' <name>QGisView</name>\n') kml.write(' <Icon>\n') xN = projectedExtent.xMinimum() yN = projectedExtent.yMinimum() nomePNG = ("QGisView_%lf_%lf_%s") % (xN, yN, adesso) stringazza = (" <href>%s.png</href>\n") % (nomePNG) kml.write(stringazza) kml.write(' <viewBoundScale>1.0</viewBoundScale>\n') kml.write(' </Icon>\n') kml.write(' <gx:LatLonQuad>\n') kml.write(' <coordinates>\n') stringazza = ("%.7lf,%.7lf,0 %.7lf,%.7lf,0 %.7lf,%.7lf,0 %.7lf,%.7lf,0\n" ) % (x1, y1, x2, y2, x3, y3, x4, y4) kml.write(stringazza) kml.write(' </coordinates>\n') kml.write(' </gx:LatLonQuad>\n') kml.write(' </GroundOverlay>\n') #Export tfw-file xScale = (projectedExtent.xMaximum() - projectedExtent.xMinimum()) / image.width() yScale = (projectedExtent.yMaximum() - projectedExtent.yMinimum()) / image.height() f = open(out_folder + "/" + nomePNG + ".pngw", 'w') f.write(str(xScale) + '\n') f.write(str(0) + '\n') f.write(str(0) + '\n') f.write('-' + str(yScale) + '\n') f.write(str(projectedExtent.xMinimum()) + '\n') f.write(str(projectedExtent.yMaximum()) + '\n') f.write(str(projectedExtent.xMaximum()) + '\n') f.write(str(projectedExtent.yMinimum())) f.close() input_file = out_folder + "/" + nomePNG + ".png" #Save the image image.save(input_file, "png") nomeLay = "gearthview" # foo default name # Adesso scrivo il vettoriale # Prendo il sistema di riferimento del Layer selezionato ------------------ curLayer = mapCanvas.currentLayer() iface = qgis.utils.iface selectedLayers = iface.layerTreeView().selectedLayers() if (not selectedLayers): # print ("selectedLayers is Empty") selectedLayers = [] selectedLayers.append(curLayer) for layer in selectedLayers: if layer: if layer.type() == layer.VectorLayer: name = layer.source() nomeLayer = layer.name() nomeLay = nomeLayer.replace(" ", "_") # print(layer.name()) kml.write(' <Folder>\n') stringazza = (' <name>%s</name>\n') % (nomeLay) kml.write(stringazza) crsSrc = layer.crs() crsDest = QgsCoordinateReferenceSystem(4326) # Wgs84LLH xform = QgsCoordinateTransform(crsSrc, crsDest, QgsProject.instance()) #---------------------------------------------------------------------------- # Trasformo la finestra video in coordinate layer, # per estrarre solo gli elementi visibili #---------------------------------------------------------------------------- # mapCanvas = iface.mapCanvas() boundBox = mapCanvas.extent() xMin = float(boundBox.xMinimum()) yMin = float(boundBox.yMinimum()) xMax = float(boundBox.xMaximum()) yMax = float(boundBox.yMaximum()) crs2 = mapCanvas.mapSettings().destinationCrs() crsSrc2 = QgsCoordinateReferenceSystem(crs2.authid()) crsDest2 = QgsCoordinateReferenceSystem(layer.crs()) xform2 = QgsCoordinateTransform(crsSrc2, crsDest2, QgsProject.instance()) pt0 = xform2.transform(QgsPointXY(xMin, yMin)) pt1 = xform2.transform(QgsPointXY(xMax, yMax)) rect = QgsRectangle(pt0, pt1) # print ("pt0x: <%s>" %(str(pt0.x())) ) # print ("pt0y: <%s>" %(str(pt0.y())) ) # print ("pt1x: <%s>" %(str(pt1.x())) ) # print ("pt1y: <%s>" %(str(pt1.y())) ) rq = QgsFeatureRequest(rect) iter = layer.getFeatures(rq) for feat in iter: nele = feat.id() # fetch geometry geom = feat.geometry() # show some information about the feature # print (("GeomType: %d") %(geom.type())) if geom.type() == 0: elem = geom.asPoint() x1 = elem.x() y1 = elem.y() # pt1 = xform.transform(QgsPoint(x1, y1)) kml.write(' <Placemark>\n') stringazza = (' <name>%s</name>\n') % (nele) kml.write(stringazza) kml.write(' <styleUrl>#default0</styleUrl>\n') # DESCRIPTION DATA----------- kml.write(' <Snippet maxLines="0"></Snippet>\n') kml.write(' <description><![CDATA[\n') kml.write('<html><body><table border="1">\n') kml.write( '<tr><th>Field Name</th><th>Field Value</th></tr>\n' ) # Prendo il contenuto dei campi ------------- fff = feat.fields() num = fff.count() iii = -1 for f in layer.fields(): iii = iii + 1 stringazza = ('<tr><td>%s</td><td>%s</td></tr>\n' ) % (f.name(), feat[iii]) kml.write(stringazza) kml.write('</table></body></html>\n') kml.write(']]></description>\n') # EXTENDED DATA ------------- stringazza = ( ' <ExtendedData><SchemaData schemaUrl="#%s">\n' ) % (nomeLay) kml.write(stringazza) ## Prendo il contenuto dei campi ------------- fff = feat.fields() num = fff.count() iii = -1 for f in layer.fields(): iii = iii + 1 stringazza = ( ' <SimpleData name="%s">%s</SimpleData>\n' ) % (f.name(), feat[iii]) if (stringazza.find('<SimpleData name="descrip') == -1): kml.write(stringazza) kml.write(' </SchemaData></ExtendedData>\n') # EXTENDED DATA ------------- wkt = layer.crs().toWkt() source = osr.SpatialReference() source.ImportFromWkt(wkt) target = osr.SpatialReference() target.ImportFromEPSG(4326) transform = osr.CoordinateTransformation( source, target) testo = geom.asWkt() # print (testo) testo = testo.replace("PointZ (", "Point (") testo = testo.replace("PointZM (", "Point (") testo = testo.replace(" 0,", ",") testo = testo.replace(" 0)", ")") geometra = ogr.CreateGeometryFromWkt(testo) geometra.Transform(transform) testoKML = geometra.ExportToKML() kml.write(testoKML) kml.write(' </Placemark>\n') elif geom.type() == 1: elem = geom.asPolyline() kml.write(' <Placemark>\n') stringazza = (' <name>%s</name>\n') % (nele) kml.write(stringazza) kml.write(' <styleUrl>#default0</styleUrl>\n') # DESCRIPTION DATA----------- kml.write(' <Snippet maxLines="0"></Snippet>\n') kml.write(' <description><![CDATA[\n') kml.write('<html><body><table border="1">\n') kml.write( '<tr><th>Field Name</th><th>Field Value</th></tr>\n' ) # Prendo il contenuto dei campi ------------- fff = feat.fields() num = fff.count() iii = -1 for f in layer.fields(): iii = iii + 1 stringazza = ('<tr><td>%s</td><td>%s</td></tr>\n' ) % (f.name(), feat[iii]) kml.write(stringazza) kml.write('</table></body></html>\n') kml.write(']]></description>\n') # EXTENDED DATA ------------- stringazza = ( ' <ExtendedData><SchemaData schemaUrl="#%s">\n' ) % (nomeLay) kml.write(stringazza) ## Prendo il contenuto dei campi ------------- fff = feat.fields() num = fff.count() iii = -1 for f in layer.fields(): iii = iii + 1 stringazza = ( ' <SimpleData name="%s">%s</SimpleData>\n' ) % (f.name(), feat[iii]) if (stringazza.find('<SimpleData name="descrip') == -1): kml.write(stringazza) kml.write(' </SchemaData></ExtendedData>\n') # EXTENDED DATA ------------- wkt = layer.crs().toWkt() source = osr.SpatialReference() source.ImportFromWkt(wkt) target = osr.SpatialReference() target.ImportFromEPSG(4326) transform = osr.CoordinateTransformation( source, target) testo = geom.asWkt() # print (testo) testo = testo.replace("LineStringZ (", "LineString (") testo = testo.replace("LineStringZM (", "LineString (") testo = testo.replace(" 0,", ",") testo = testo.replace(" 0)", ")") geometra = ogr.CreateGeometryFromWkt(testo) geometra.Transform(transform) testoKML = geometra.ExportToKML() kml.write(testoKML) kml.write(' </Placemark>\n') elif geom.type() == 2: kml.write(' <Placemark>\n') stringazza = (' <name>%s</name>\n') % (nele) kml.write(stringazza) kml.write(' <styleUrl>#msn_style</styleUrl>\n') # DESCRIPTION DATA----------- kml.write(' <Snippet maxLines="0"></Snippet>\n') kml.write(' <description><![CDATA[\n') kml.write('<html><body><table border="1">\n') kml.write( '<tr><th>Field Name</th><th>Field Value</th></tr>\n' ) # Prendo il contenuto dei campi ------------- fff = feat.fields() num = fff.count() iii = -1 for f in layer.fields(): iii = iii + 1 stringazza = ('<tr><td>%s</td><td>%s</td></tr>\n' ) % (f.name(), feat[iii]) kml.write(stringazza) kml.write('</table></body></html>\n') kml.write(']]></description>\n') # EXTENDED DATA ------------- stringazza = ( ' <ExtendedData><SchemaData schemaUrl="#%s">\n' ) % (nomeLay) kml.write(stringazza) ## Prendo il contenuto dei campi ------------- fff = feat.fields() num = fff.count() iii = -1 for f in layer.fields(): iii = iii + 1 stringazza = ( ' <SimpleData name="%s">%s</SimpleData>\n' ) % (f.name(), feat[iii]) if (stringazza.find('<SimpleData name="descrip') == -1): kml.write(stringazza) kml.write(' </SchemaData></ExtendedData>\n') # EXTENDED DATA ------------- testo = geom.asWkt() # print (testo) wkt = layer.crs().toWkt() source = osr.SpatialReference() source.ImportFromWkt(wkt) target = osr.SpatialReference() target.ImportFromEPSG(4326) transform = osr.CoordinateTransformation( source, target) testo = testo.replace("PolygonZ (", "Polygon (") testo = testo.replace("PolygonZM (", "Polygon (") testo = testo.replace(" 0,", ",") testo = testo.replace(" 0)", ")") geometra = ogr.CreateGeometryFromWkt(testo) geometra.Transform(transform) testoKML = geometra.ExportToKML() testoKML = testoKML.replace( "<Polygon>", "<Polygon><altitudeMode>relativeToGround</altitudeMode>" ) kml.write(testoKML) kml.write(' </Placemark>\n') kml.write(' </Folder>\n') kml.write('</Folder>\n') kml.write('</Document>\n') kml.write('</kml>\n') kml.close() if platform.system() == "Windows": os.startfile(out_folder + '/doc.kml') if platform.system() == "Darwin": os.system("open " + str(out_folder + '/doc.kml')) if platform.system() == "Linux": os.system("xdg-open " + str(out_folder + '/doc.kml'))
def renderer(self): qgis = QgsApplication([], False) qgis.setPrefixPath(self.settings.get('path'), True) qgis.setMaxThreads(1) qgis.initQgis() while True: try: fndata, srs, render_size, extended, \ target_box, result = self.queue.get() layer = QgsVectorLayer(fndata, 'layer', 'ogr') crs = QgsCoordinateReferenceSystem(srs.id) layer.setCrs(crs) settings = QgsMapSettings() settings.setLayers([layer.id()]) settings.setFlag(QgsMapSettings.DrawLabeling) settings.setFlag(QgsMapSettings.Antialiasing) settings.setCrsTransformEnabled(True) settings.setDestinationCrs(crs) settings.setMapUnits(crs.mapUnits()) settings.setOutputSize(QSize(*render_size)) settings.setExtent(QgsRectangle(*extended)) settings.setOutputImageFormat(QImage.Format_ARGB32) bgcolor = QColor.fromRgba(qRgba(255, 255, 255, 0)) settings.setBackgroundColor(bgcolor) settings.setOutputDpi(96) QgsMapLayerRegistry.instance().addMapLayer(layer) settings.setLayers([layer.id()]) # Создаем QImage руками чтобы можно было использовать # QgsMapRendererCustomPainterJob. Остальные не позволяют # обойти баг с рисованием поверх старого. img = QImage(settings.outputSize(), QImage.Format_ARGB32) # Эти костыли нужны для того, чтобы корректно рисовались # слои на прозрачном фоне, без этого получается каша. img.fill(QColor.fromRgba(qRgba(255, 255, 255, 255))) img.fill(QColor.fromRgba(qRgba(255, 255, 255, 0))) # DPI должно быть таким же как в settings, иначе ошибка. В QImage # разрешение указывается в точках на метр по каждой оси. dpm = settings.outputDpi() / 25.4 * 1000 img.setDotsPerMeterX(dpm) img.setDotsPerMeterY(dpm) painter = QPainter(img) job = QgsMapRendererCustomPainterJob(settings, painter) job.renderSynchronously() painter.end() QgsMapLayerRegistry.instance().removeAllMapLayers() # Преобразование QImage в PIL ba = QByteArray() bf = QBuffer(ba) bf.open(QIODevice.WriteOnly) img.save(bf, 'PNG') bf.close() buf = StringIO() buf.write(bf.data()) buf.seek(0) img = PIL.Image.open(buf) # Вырезаем нужный нам кусок изображения result.put(img.crop(target_box)) except Exception as e: self.logger.error(e.message) qgis.exitQgis()
def generate(self, writer, parameters, context, feedback): feedback.setProgress(1) extent = self.parameterAsExtent(parameters, self.EXTENT, context) self.min_zoom = self.parameterAsInt(parameters, self.ZOOM_MIN, context) self.max_zoom = self.parameterAsInt(parameters, self.ZOOM_MAX, context) dpi = self.parameterAsInt(parameters, self.DPI, context) color = self.parameterAsColor(parameters, self.BACKGROUND_COLOR, context) self.tile_format = self.formats[self.parameterAsEnum( parameters, self.TILE_FORMAT, context)] quality = self.parameterAsInt(parameters, self.QUALITY, context) self.metatilesize = self.parameterAsInt(parameters, self.METATILESIZE, context) try: tile_width = self.parameterAsInt(parameters, self.TILE_WIDTH, context) tile_height = self.parameterAsInt(parameters, self.TILE_HEIGHT, context) except AttributeError: tile_width = 256 tile_height = 256 wgs_crs = QgsCoordinateReferenceSystem('EPSG:4326') dest_crs = QgsCoordinateReferenceSystem('EPSG:3857') project = context.project() src_to_wgs = QgsCoordinateTransform(project.crs(), wgs_crs, context.transformContext()) wgs_to_dest = QgsCoordinateTransform(wgs_crs, dest_crs, context.transformContext()) settings = QgsMapSettings() settings.setOutputImageFormat(QImage.Format_ARGB32_Premultiplied) settings.setDestinationCrs(dest_crs) settings.setLayers(self.layers) settings.setOutputDpi(dpi) if self.tile_format == 'PNG': settings.setBackgroundColor(color) # disable partial labels (they would be cut at the edge of tiles) labeling_engine_settings = settings.labelingEngineSettings() labeling_engine_settings.setFlag( QgsLabelingEngineSettings.UsePartialCandidates, False) settings.setLabelingEngineSettings(labeling_engine_settings) self.wgs_extent = src_to_wgs.transformBoundingBox(extent) self.wgs_extent = [ self.wgs_extent.xMinimum(), self.wgs_extent.yMinimum(), self.wgs_extent.xMaximum(), self.wgs_extent.yMaximum() ] metatiles_by_zoom = {} metatiles_count = 0 for zoom in range(self.min_zoom, self.max_zoom + 1): metatiles = get_metatiles(self.wgs_extent, zoom, self.metatilesize) metatiles_by_zoom[zoom] = metatiles metatiles_count += len(metatiles) lab_buffer_px = 100 progress = 0 tile_params = { 'format': self.tile_format, 'quality': quality, 'width': tile_width, 'height': tile_height, 'min_zoom': self.min_zoom, 'max_zoom': self.max_zoom, 'extent': self.wgs_extent, } writer.set_parameters(tile_params) for zoom in range(self.min_zoom, self.max_zoom + 1): feedback.pushConsoleInfo('Generating tiles for zoom level: %s' % zoom) for i, metatile in enumerate(metatiles_by_zoom[zoom]): if feedback.isCanceled(): break size = QSize(tile_width * metatile.rows(), tile_height * metatile.columns()) extent = QgsRectangle(*metatile.extent()) settings.setExtent(wgs_to_dest.transformBoundingBox(extent)) settings.setOutputSize(size) image = QImage(size, QImage.Format_ARGB32_Premultiplied) image.fill(color) dpm = settings.outputDpi() / 25.4 * 1000 image.setDotsPerMeterX(dpm) image.setDotsPerMeterY(dpm) painter = QPainter(image) job = QgsMapRendererCustomPainterJob(settings, painter) job.renderSynchronously() painter.end() # For analysing metatiles (labels, etc.) # metatile_dir = os.path.join(output_dir, str(zoom)) # os.makedirs(metatile_dir, exist_ok=True) # image.save(os.path.join(metatile_dir, 'metatile_%s.png' % i)) for r, c, tile in metatile.tiles: tile_img = image.copy(tile_width * r, tile_height * c, tile_width, tile_height) writer.write_tile(tile, tile_img) progress += 1 feedback.setProgress(100 * (progress / metatiles_count)) writer.close()