def clear(): with block_signals_to(self.QCBox_ThematicFile): self.QCBox_ThematicFile.setCurrentIndex(-1) self.render_widget.canvas.setLayers([]) self.render_widget.refresh() self.PixelTable.clear() self.PixelTable.setRowCount(0) self.PixelTable.setColumnCount(0) with block_signals_to(self.QCBox_band_ThematicFile): self.QCBox_band_ThematicFile.clear()
def disable(self): with block_signals_to(self.render_widget): # deactivate some parts of this view self.layerStyleEditor.setDisabled(True) self.layerOpacity.setDisabled(True) # set status for view widget self.is_active = False self.parent_view.update()
def select_thematic_file_classes(self, layer): def clear(): with block_signals_to(self.QCBox_ThematicFile): self.QCBox_ThematicFile.setCurrentIndex(-1) self.render_widget.canvas.setLayers([]) self.render_widget.refresh() self.PixelTable.clear() self.PixelTable.setRowCount(0) self.PixelTable.setColumnCount(0) with block_signals_to(self.QCBox_band_ThematicFile): self.QCBox_band_ThematicFile.clear() if not layer: clear() return if layer.crs() != LayerToEdit.current.qgs_layer.crs(): self.MsgBar.pushMessage( "The selected file \"{}\" doesn't have the same coordinate system with respect to " "the thematic layer to edit \"{}\"".format( layer.name(), LayerToEdit.current.qgs_layer.name()), level=Qgis.Critical, duration=20) clear() return if (round(layer.rasterUnitsPerPixelX(), 3) != round( LayerToEdit.current.qgs_layer.rasterUnitsPerPixelX(), 3) or round(layer.rasterUnitsPerPixelY(), 3) != round( LayerToEdit.current.qgs_layer.rasterUnitsPerPixelY(), 3)): self.MsgBar.pushMessage( "The selected file \"{}\" doesn't have the same pixel size with respect to " "the thematic layer to edit \"{}\"".format( layer.name(), LayerToEdit.current.qgs_layer.name()), level=Qgis.Critical, duration=20) clear() return self.render_widget.canvas.setDestinationCrs(layer.crs()) self.render_widget.canvas.setLayers([layer]) self.render_widget.canvas.setExtent(layer.extent()) self.render_widget.refresh() self.thematic_file_classes = layer # set band count with block_signals_to(self.QCBox_band_ThematicFile): self.QCBox_band_ThematicFile.clear() self.QCBox_band_ThematicFile.addItems([ str(x) for x in range(1, self.thematic_file_classes.bandCount() + 1) ]) self.setup_thematic_file_classes()
def highlight_value_in_recode_pixel_table(self, value_to_select): """Highlight the current pixel value from mouse pointer on canvas""" from ThRasE.thrase import ThRasE if value_to_select is None: ThRasE.dialog.recodePixelTable.clearSelection() with block_signals_to(ThRasE.dialog.recodePixelTable): [ThRasE.dialog.recodePixelTable.item(idx, 2).setBackground(Qt.white) for idx in range(len(self.pixels))] return row_idx = next((idx for idx, i in enumerate(self.pixels) if i["value"] == value_to_select), None) if row_idx is not None: # select ThRasE.dialog.recodePixelTable.setCurrentCell(row_idx, 2) # set background with block_signals_to(ThRasE.dialog.recodePixelTable): [ThRasE.dialog.recodePixelTable.item(idx, 2).setBackground(Qt.white) for idx in range(len(self.pixels))] ThRasE.dialog.recodePixelTable.item(row_idx, 2).setBackground(Qt.yellow) else: ThRasE.dialog.recodePixelTable.clearSelection() with block_signals_to(ThRasE.dialog.recodePixelTable): [ThRasE.dialog.recodePixelTable.item(idx, 2).setBackground(Qt.white) for idx in range(len(self.pixels))]
def update_render_layers(self): with block_signals_to(self): # set the CRS of the canvas view if self.crs: # use the crs of thematic raster to edit self.canvas.setDestinationCrs(self.crs) else: # use the crs set in Qgis self.canvas.setDestinationCrs( iface.mapCanvas().mapSettings().destinationCrs()) # get all valid activated layers valid_layers = [ active_layer.layer for active_layer in self.active_layers if active_layer.is_active ] if len(valid_layers) == 0: self.canvas.setLayers([]) self.refresh() return # set to canvas self.canvas.setLayers(valid_layers) # set init extent from other view if any is activated else set layer extent from ThRasE.gui.main_dialog import ThRasEDialog others_extents = [ view_widget.render_widget.canvas.extent() for view_widget in ThRasEDialog.view_widgets if view_widget.is_active and view_widget.render_widget != self and not view_widget.render_widget.canvas.extent().isEmpty() ] if others_extents: # set extent using the extent of the other valid view (or self) with at least one layer extent = others_extents[0] self.update_canvas_to(extent) elif self.canvas.extent().isEmpty(): # first layer to render # set the extent using the extent of the Qgis project but first transform the crs if it is different new_layer = valid_layers[0] transform = QgsCoordinateTransform( new_layer.crs(), self.canvas.mapSettings().destinationCrs(), QgsProject.instance()) new_extent = transform.transformBoundingBox(new_layer.extent()) self.canvas.setExtent(new_extent) self.refresh()
def highlight(self, idx_tile=None): if idx_tile: # from slider with block_signals_to(self.currentTile): self.currentTile.setValue(idx_tile) if idx_tile: tile = next((tile for tile in self.layer_to_edit.navigation.tiles if tile.idx == idx_tile), None) else: tile = self.layer_to_edit.navigation.current_tile # unhighlight the before tile (rubber band) if self.highlight_tile: self.highlight_tile.reset(QgsWkbTypes.PolygonGeometry) self.highlight_tile = tile.create(self.render_widget.canvas, line_width=6, rbs_in="highlight")
def update_layer_opacity(self, opacity=None): if opacity is None: opacity = self.layerOpacity.value() if self.layer: if self.layer.type() == QgsMapLayer.VectorLayer: self.layer.setOpacity(opacity/100.0) else: self.layer.renderer().setOpacity(opacity/100.0) if hasattr(self.layer, "setCacheImage"): self.layer.setCacheImage(None) self.layer.triggerRepaint() from ThRasE.gui.main_dialog import ThRasEDialog same_layer_in_others_active_layer = \ [active_layer for active_layer in [al for als in [view_widget.active_layers for view_widget in ThRasEDialog.view_widgets] for al in als] if active_layer != self and active_layer.layer == self.layer] for active_layer in same_layer_in_others_active_layer: with block_signals_to(active_layer.layerOpacity): active_layer.layerOpacity.setValue(opacity) self.opacity = opacity
def apply(self): pixel_table = self.PixelTable classes_selected = [ int(pixel_table.item(row_idx, 1).text()) for row_idx in range(len(self.pixel_classes)) if pixel_table.item(row_idx, 2).checkState() == 2 ] if not classes_selected: self.MsgBar.pushMessage( "Error, none of the class was selected to apply", level=Qgis.Warning) return extent_intercepted = LayerToEdit.current.qgs_layer.extent().intersect( self.thematic_file_classes.extent()) ps_x = self.thematic_file_classes.rasterUnitsPerPixelX( ) # pixel size in x ps_y = self.thematic_file_classes.rasterUnitsPerPixelY( ) # pixel size in y # locate the pixel centroid in x and y for the pixel in min/max in the extent y_min = extent_intercepted.yMinimum() + (ps_y / 2.0) y_max = extent_intercepted.yMaximum() - (ps_y / 2.0) x_min = extent_intercepted.xMinimum() + (ps_x / 2.0) x_max = extent_intercepted.xMaximum() - (ps_x / 2.0) # index for extent intercepted start in the corner left-top respect to thematic file classes idx_x = int( (x_min - self.thematic_file_classes.extent().xMinimum()) / ps_x) idx_y = int( (self.thematic_file_classes.extent().yMaximum() - y_max) / ps_y) thematic_classes_band = int(self.QCBox_band_ThematicFile.currentText()) # data array for the extent intercepted using the thematic file classes values ds_in = gdal.Open(get_file_path_of_layer(self.thematic_file_classes)) da_intercepted = ds_in.GetRasterBand( thematic_classes_band).ReadAsArray( idx_x, idx_y, int(round((x_max - x_min) / ps_x + 1)), int(round((y_max - y_min) / ps_y + 1))).astype(np.int) del ds_in pixels_to_process = \ [QgsPointXY(x, y) for n_y, y in enumerate(np.arange(y_min, y_max + ps_y/2.0, ps_y)[::-1]) for n_x, x in enumerate(np.arange(x_min, x_max + ps_x/2.0, ps_x)) if da_intercepted[n_y][n_x] in classes_selected] del da_intercepted # edit all pixels inside the classes selected based on the recode pixel table edit_status = [ LayerToEdit.current.edit_pixel(pixel) for pixel in pixels_to_process ] if edit_status: if hasattr(LayerToEdit.current.qgs_layer, 'setCacheImage'): LayerToEdit.current.qgs_layer.setCacheImage(None) LayerToEdit.current.qgs_layer.reload() LayerToEdit.current.qgs_layer.triggerRepaint() else: self.MsgBar.pushMessage( "None of the pixel was edited with the classes selected", level=Qgis.Info) return # return to origin symbology symbology = \ [(str(pixel["value"]), pixel["value"], (pixel["color"]["R"], pixel["color"]["G"], pixel["color"]["B"], pixel["color"]["A"])) for pixel in self.pixel_classes_backup] apply_symbology(self.thematic_file_classes, thematic_classes_band, symbology) # clear self.PixelTable.clear() self.PixelTable.setRowCount(0) self.PixelTable.setColumnCount(0) self.render_widget.canvas.setLayers([]) self.render_widget.canvas.clearCache() self.render_widget.refresh() self.QCBox_ThematicFile.setCurrentIndex(-1) with block_signals_to(self.QCBox_band_ThematicFile): self.QCBox_band_ThematicFile.clear() self.accept()
def set_pixel_table(self): # clear table self.PixelTable.clear() self.PixelTable.setRowCount(0) self.PixelTable.setColumnCount(0) if not self.thematic_file_classes: return with block_signals_to(self.PixelTable): header = ["", "class value", "select"] row_length = len(self.pixel_classes) # init table self.PixelTable.setRowCount(row_length) self.PixelTable.setColumnCount(3) self.PixelTable.horizontalHeader().setMinimumSectionSize(45) # hidden row labels self.PixelTable.verticalHeader().setVisible(False) # add Header self.PixelTable.setHorizontalHeaderLabels(header) # insert items for col_idx, header in enumerate(header): if header == "": for row_idx, pixel in enumerate(self.pixel_classes): item_table = QTableWidgetItem() item_table.setFlags(item_table.flags() & ~Qt.ItemIsSelectable) item_table.setBackground( QColor(pixel["color"]["R"], pixel["color"]["G"], pixel["color"]["B"], pixel["color"]["A"])) self.PixelTable.setItem(row_idx, col_idx, item_table) if header == "class value": for row_idx, pixel in enumerate(self.pixel_classes): item_table = QTableWidgetItem(str(pixel["value"])) item_table.setFlags(item_table.flags() & ~Qt.ItemIsSelectable) item_table.setFlags(item_table.flags() & ~Qt.ItemIsEditable) item_table.setTextAlignment(Qt.AlignCenter | Qt.AlignVCenter) self.PixelTable.setItem(row_idx, col_idx, item_table) if header == "select": for row_idx, pixel in enumerate(self.pixel_classes): item_table = QTableWidgetItem() item_table.setFlags(item_table.flags() | Qt.ItemIsUserCheckable) item_table.setFlags(item_table.flags() | Qt.ItemIsEnabled) item_table.setFlags(item_table.flags() & ~Qt.ItemIsSelectable) item_table.setTextAlignment(Qt.AlignCenter | Qt.AlignVCenter) if pixel["select"]: item_table.setCheckState(Qt.Checked) else: item_table.setCheckState(Qt.Unchecked) self.PixelTable.setItem(row_idx, col_idx, item_table) # adjust size of Table self.PixelTable.resizeColumnsToContents() self.PixelTable.resizeRowsToContents() # adjust the editor block based on table content table_width = self.PixelTable.horizontalHeader().length() + 40 self.TableBlock.setMaximumWidth(table_width) self.TableBlock.setMinimumWidth(table_width)
def change_tile_from_spinbox(self, idx_tile): with block_signals_to(self.SliderNavigation): self.SliderNavigation.setValue(idx_tile) self.go_to_tile(idx_tile)
def change_tile_from_slider(self, idx_tile): with block_signals_to(self.currentTile): self.currentTile.setValue(idx_tile) self.go_to_tile(idx_tile)
def update_canvas_to(self, new_extent): with block_signals_to(self.canvas): self.canvas.setExtent(new_extent) self.refresh()