def add_to_layout(self, layout, background_color=QColor(255, 255, 255, 0), size=80): """ Inspired by https://opensourceoptions.com/blog/pyqgis-create-and-print-a-map-layout-with-python/ """ layers = [layer.layer() for layer in self.group.findLayers()] # create map item in the layout map = QgsLayoutItemMap(layout) map.setRect(20, 20, 20, 20) # set the map extent ms = QgsMapSettings() ms.setLayers(layers) # set layers to be mapped crs = QgsCoordinateReferenceSystem() crs.createFromProj(self.projection.value.proj_str(self.origin)) map.setCrs(crs) map.setFollowVisibilityPreset(True) map.setFollowVisibilityPresetName(Globe.THEME_NAME) rect = QgsRectangle(ms.fullExtent()) ms.setExtent(rect) map.setExtent(rect) map.setBackgroundColor(background_color) layout.addLayoutItem(map) map.attemptMove(QgsLayoutPoint(5, 20, QgsUnitTypes.LayoutMillimeters)) map.attemptResize( QgsLayoutSize(size, size, QgsUnitTypes.LayoutMillimeters))
def cvt_vtr(self): QSWATMOD_path_dict = self.dirs_and_paths() selectedVector = self.dlg.comboBox_vector_lyrs.currentText() layer = QgsProject.instance().mapLayersByName(str(selectedVector))[0] # Find .dis file and read number of rows, cols, x spacing, and y spacing (not allowed to change) for filename in glob.glob(str(QSWATMOD_path_dict['SMfolder']) + "/*.dis"): with open(filename, "r") as f: data = [] for line in f.readlines(): if not line.startswith("#"): data.append(line.replace('\n', '').split()) nrow = int(data[0][1]) ncol = int(data[0][2]) delr = float(data[2][1]) # is the cell width along rows (y spacing) delc = float( data[3][1]) # is the cell width along columns (x spacing). # get extent ext = layer.extent() xmin = ext.xMinimum() xmax = ext.xMaximum() ymin = ext.yMinimum() ymax = ext.yMaximum() extent = "{a},{b},{c},{d}".format(a=xmin, b=xmax, c=ymin, d=ymax) fdnames = [ field.name() for field in layer.dataProvider().fields() if not (field.name() == 'fid' or field.name() == 'id' or field.name() == 'xmin' or field.name() == 'xmax' or field.name() == 'ymin' or field.name() == 'ymax' or field.name() == 'grid_id' or field.name() == 'row' or field.name() == 'col' or field.name() == 'elev_mf') ] # Create swatmf_results tree inside root = QgsProject.instance().layerTreeRoot() if root.findGroup("swatmf_results"): swatmf_results = root.findGroup("swatmf_results") else: swatmf_results = root.insertGroup(0, "swatmf_results") if root.findGroup(selectedVector): rastergroup = root.findGroup(selectedVector) else: rastergroup = swatmf_results.insertGroup(0, selectedVector) per = 0 self.dlg.progressBar_cvt_vtr.setValue(0) for fdnam in fdnames: QCoreApplication.processEvents() nodata = float(self.dlg.lineEdit_nodata.text()) mincolor = self.dlg.mColorButton_min_rmap.color().name() maxcolor = self.dlg.mColorButton_max_rmap.color().name() name = fdnam name_ext = "{}.tif".format(name) output_dir = QSWATMOD_path_dict['SMshps'] # create folder for each layer output rasterpath = os.path.join(output_dir, selectedVector) if not os.path.exists(rasterpath): os.makedirs(rasterpath) output_raster = os.path.join(rasterpath, name_ext) params = { 'INPUT': layer, 'FIELD': fdnam, 'UNITS': 1, 'WIDTH': delc, 'HEIGHT': delr, 'EXTENT': extent, 'NODATA': nodata, 'DATA_TYPE': 5, #Float32 'OUTPUT': output_raster } processing.run("gdal:rasterize", params) rasterlayer = QgsRasterLayer(output_raster, '{0} ({1})'.format(fdnam, selectedVector)) QgsProject.instance().addMapLayer(rasterlayer, False) rastergroup.insertChildNode(0, QgsLayerTreeLayer(rasterlayer)) stats = rasterlayer.dataProvider().bandStatistics( 1, QgsRasterBandStats.All) rmin = stats.minimumValue rmax = stats.maximumValue fnc = QgsColorRampShader() lst = [ QgsColorRampShader.ColorRampItem(rmin, QColor(mincolor)), QgsColorRampShader.ColorRampItem(rmax, QColor(maxcolor)) ] fnc.setColorRampItemList(lst) fnc.setColorRampType(QgsColorRampShader.Interpolated) shader = QgsRasterShader() shader.setRasterShaderFunction(fnc) renderer = QgsSingleBandPseudoColorRenderer(rasterlayer.dataProvider(), 1, shader) rasterlayer.setRenderer(renderer) rasterlayer.triggerRepaint() # create image img = QImage(QSize(800, 800), QImage.Format_ARGB32_Premultiplied) # set background color # bcolor = QColor(255, 255, 255, 255) bcolor = QColor(255, 255, 255, 0) img.fill(bcolor.rgba()) # create painter p = QPainter() p.begin(img) p.setRenderHint(QPainter.Antialiasing) # create map settings ms = QgsMapSettings() ms.setBackgroundColor(bcolor) # set layers to render flayer = QgsProject.instance().mapLayersByName(rasterlayer.name()) ms.setLayers([flayer[0]]) # set extent rect = QgsRectangle(ms.fullExtent()) rect.scale(1.1) ms.setExtent(rect) # set ouptut size ms.setOutputSize(img.size()) # setup qgis map renderer render = QgsMapRendererCustomPainterJob(ms, p) render.start() render.waitForFinished() # get timestamp p.drawImage(QPoint(), img) pen = QPen(Qt.red) pen.setWidth(2) p.setPen(pen) font = QFont() font.setFamily('Times') # font.setBold(True) font.setPointSize(18) p.setFont(font) # p.setBackground(QColor('sea green')) doesn't work p.drawText(QRect(0, 0, 800, 800), Qt.AlignRight | Qt.AlignBottom, fdnam) p.end() # save the image img.save(os.path.join(rasterpath, '{:03d}_{}.jpg'.format(per, fdnam))) # Update progress bar per += 1 progress = round((per / len(fdnames)) * 100) self.dlg.progressBar_cvt_vtr.setValue(progress) QCoreApplication.processEvents() self.dlg.raise_() duration = self.dlg.doubleSpinBox_ani_r_time.value() # filepaths fp_in = os.path.join(rasterpath, '*.jpg') fp_out = os.path.join(rasterpath, '{}.gif'.format(selectedVector)) # https://pillow.readthedocs.io/en/stable/handbook/image-file-formats.html#gif fimg, *fimgs = [Image.open(f) for f in sorted(glob.glob(fp_in))] fimg.save(fp=fp_out, format='GIF', append_images=fimgs, save_all=True, duration=duration * 1000, loop=0, transparency=0) msgBox = QMessageBox() msgBox.setWindowIcon(QtGui.QIcon(':/QSWATMOD2/pics/sm_icon.png')) msgBox.setWindowTitle("Coverted!") msgBox.setText( "Fields from {} were converted successfully!".format(selectedVector)) msgBox.exec_() questionBox = QMessageBox() questionBox.setWindowIcon(QtGui.QIcon(':/QSWATMOD2/pics/sm_icon.png')) reply = QMessageBox.question(questionBox, 'Open?', 'Do you want to open the animated gif file?', QMessageBox.Yes, QMessageBox.No) if reply == QMessageBox.Yes: os.startfile(os.path.join(rasterpath, '{}.gif'.format(selectedVector)))