田块处方图可视化(PyQt5)
田块处方图可视化
- txt 文本说明
- 程序功能说明
- 完整代码(PyQt5)
- 可视化图1
- 可视化图2
txt 文本说明
%分割经纬度和施肥量,|分割经纬度,","分割经度和纬度
程序功能说明
文件加载:
- 通过"加载文件"按钮选择文本文件
- 支持标准文本文件格式(.txt)
数据解析:
- 解析格式为"经度,纬度|经度,纬度|经度,纬度|经度,纬度%百分比"的数据行
- 自动跳过空行和注释行(以#开头)
- 验证经纬度范围(纬度:-90到90,经度:-180到180)
数据可视化:
- 在Matplotlib画布上绘制所有多边形
- 根据百分比值着色(绿色到红色渐变)
- 在多边形中心显示百分比值
- 自动调整视图以显示所有多边形
- 添加颜色条图例显示百分比范围
用户界面:
- 显示文件加载状态
- 显示原始数据内容
- 提供"清除"按钮重置所有数据
- 状态栏显示操作信息
使用说明
- 运行程序后,点击加载文件按钮选择包含多边形数据的文本文件
- 程序会自动解析文件并在右侧画布上绘制多边形
- 原始数据会显示在中间的文本框中
- 点击"清除"按钮可以重置所有数据
完整代码(PyQt5)
import sys
import re
import numpy as np
import matplotlib.pyplot as plt
from PyQt5.QtWidgets import (QApplication, QMainWindow, QWidget, QVBoxLayout, QHBoxLayout, QLabel, QPushButton, QFileDialog, QTextEdit, QMessageBox)
from matplotlib.backends.backend_qt5agg import FigureCanvasQTAgg as FigureCanvas
from matplotlib.figure import Figure
import matplotlib.colors as mcolors
import matplotlib.patches as patches
import colorsysclass PolygonData:def __init__(self, points, percentage):self.points = pointsself.percentage = percentagedef get_points(self):return self.pointsdef get_percentage(self):return self.percentageclass PolygonVisualizer(QMainWindow):def __init__(self):super().__init__()self.setWindowTitle("多边形数据可视化工具")self.setGeometry(100, 100, 1000, 700)self.all_points = []self.polygons = []self.line_blocks = ""self.init_ui()def init_ui(self):# 创建主窗口部件main_widget = QWidget()self.setCentralWidget(main_widget)# 主布局main_layout = QVBoxLayout()main_widget.setLayout(main_layout)# 标题标签title_label = QLabel("多边形数据可视化工具")title_label.setStyleSheet("font-size: 20px; font-weight: bold; margin: 10px;")main_layout.addWidget(title_label)# 创建水平布局用于文件信息和按钮file_layout = QHBoxLayout()# 文件信息标签self.file_info_label = QLabel("未加载文件")self.file_info_label.setStyleSheet("font-size: 20px;")file_layout.addWidget(self.file_info_label)# 加载文件按钮load_button = QPushButton("加载文件")load_button.clicked.connect(self.load_file)load_button.setStyleSheet("padding: 5px 15px;")file_layout.addWidget(load_button)# 清除按钮clear_button = QPushButton("清除")clear_button.clicked.connect(self.clear_all)clear_button.setStyleSheet("padding: 5px 15px;")file_layout.addWidget(clear_button)main_layout.addLayout(file_layout)# 创建文本编辑框用于显示原始数据self.text_edit = QTextEdit()self.text_edit.setReadOnly(True)self.text_edit.setStyleSheet("font-family: Consolas, monospace; font-size: 15px;")main_layout.addWidget(self.text_edit)# 创建Matplotlib图形self.figure = Figure(figsize=(15, 10), dpi=100)self.canvas = FigureCanvas(self.figure)main_layout.addWidget(self.canvas)# 状态栏self.statusBar().showMessage("就绪")def load_file(self):# 打开文件对话框file_path, _ = QFileDialog.getOpenFileName(self, "选择多边形数据文件", "", "文本文件 (*.txt);;所有文件 (*)")if file_path:try:# 读取文件with open(file_path, 'r') as file:content = file.read()# 解析文件内容self.parse_file_content(content)# 更新UIself.file_info_label.setText(f"已加载文件: {file_path}")self.text_edit.setText(self.line_blocks)# 绘制多边形self.plot_polygons()self.statusBar().showMessage(f"成功加载文件: {file_path}")except Exception as e:QMessageBox.critical(self, "错误", f"读取文件失败: {str(e)}")self.statusBar().showMessage(f"读取文件失败: {str(e)}")def parse_file_content(self, content):# 重置数据self.all_points = []self.polygons = []self.line_blocks = ""lines = content.split('\n')line_count = 0valid_count = 0for line in lines:line_count += 1line = line.strip()# 跳过空行和注释行if not line or line.startswith('#'):continueself.line_blocks += line + '\n'# 解析多边形数据polygon = self.parse_polygon_line(line)if polygon:self.polygons.append(polygon)self.all_points.extend(polygon.get_points())valid_count += 1# 更新状态self.statusBar().showMessage(f"解析完成: {valid_count}个有效多边形/{line_count}行")def parse_polygon_line(self, line):try:# 分割百分比部分parts = line.split('%')if len(parts) < 2:return Nonepercentage = float(parts[1])# 分割点数据point_strings = parts[0].split('|')if len(point_strings) != 4: # 必须是4个点return Nonepoints = []# 解析每个点for point_str in point_strings:coords = point_str.split(',')if len(coords) != 2:return Nonelongitude = float(coords[0])latitude = float(coords[1])# 验证经纬度范围if -90 <= latitude <= 90 and -180 <= longitude <= 180:points.append((longitude, latitude))else:return Nonereturn PolygonData(points, percentage)except ValueError:return Nonedef get_color_for_percentage(self, percentage):# 从绿色(0%)到红色(100%)hue = (100 - percentage * 100) / 100.0 * 120.0 / 360.0 # 转换为0-1范围r, g, b = colorsys.hsv_to_rgb(hue, 1.0, 1.0)return (r, g, b, 0.7) # 添加透明度def plot_polygons(self):# 清除图形self.figure.clear()# 如果没有多边形数据,显示提示if not self.polygons:ax = self.figure.add_subplot(111)ax.text(0.5, 0.5, 'No polygon data', horizontalalignment='center', verticalalignment='center',transform=ax.transAxes, fontsize=14)self.canvas.draw()return# 创建坐标轴ax = self.figure.add_subplot(111)# 计算所有点的范围all_lons = [point[0] for polygon in self.polygons for point in polygon.get_points()]all_lats = [point[1] for polygon in self.polygons for point in polygon.get_points()]# 设置坐标轴范围lon_min, lon_max = min(all_lons), max(all_lons)lat_min, lat_max = min(all_lats), max(all_lats)# 添加一些边距lon_margin = (lon_max - lon_min) * 0.1lat_margin = (lat_max - lat_min) * 0.1ax.set_xlim(lon_min - lon_margin, lon_max + lon_margin)ax.set_ylim(lat_min - lat_margin, lat_max + lat_margin)# 设置标题和标签ax.set_title("Polygon Data Visualization", fontsize=14)ax.set_xlabel("Longitude", fontsize=12)ax.set_ylabel("Latitude", fontsize=12)# 绘制每个多边形for polygon in self.polygons:points = polygon.get_points()percentage = polygon.get_percentage()# 创建多边形poly = patches.Polygon(points, closed=True,edgecolor='black',facecolor=self.get_color_for_percentage(percentage),linewidth=1.5)ax.add_patch(poly)# 添加百分比标签centroid = self.calculate_centroid(points)ax.text(centroid[0], centroid[1], f"{percentage*100:.1f}%", fontsize=10, ha='center', va='center',bbox=dict(facecolor='white', alpha=0.7, edgecolor='none', pad=2))# 添加图例self.add_colorbar(ax)# 添加网格ax.grid(True, linestyle='--', alpha=0.7)# 重绘画布self.canvas.draw()def calculate_centroid(self, points):"""计算多边形的质心"""x = [p[0] for p in points]y = [p[1] for p in points]centroid_x = sum(x) / len(points)centroid_y = sum(y) / len(points)return (centroid_x, centroid_y)def add_colorbar(self, ax):"""添加颜色条图例"""# 创建颜色映射cmap = mcolors.LinearSegmentedColormap.from_list("custom", [(0, "green"), (0.5, "yellow"), (1, "red")])# 添加颜色条norm = mcolors.Normalize(vmin=0, vmax=100)sm = plt.cm.ScalarMappable(cmap=cmap, norm=norm)sm.set_array([])# 添加颜色条cbar = self.figure.colorbar(sm, ax=ax, orientation='vertical', fraction=0.046, pad=0.04)cbar.set_label("Percentage (%)", fontsize=10)def clear_all(self):"""清除所有数据"""self.all_points = []self.polygons = []self.line_blocks = ""# 更新UIself.file_info_label.setText("未加载文件")self.text_edit.clear()# 清除图形self.figure.clear()ax = self.figure.add_subplot(111)ax.text(0.5, 0.5, '等待加载数据...', horizontalalignment='center', verticalalignment='center',transform=ax.transAxes, fontsize=14)self.canvas.draw()self.statusBar().showMessage("已清除所有数据")if __name__ == "__main__":app = QApplication(sys.argv)# 设置应用样式app.setStyle("Fusion")# 创建并显示主窗口window = PolygonVisualizer()window.show()# 初始化图形window.clear_all()sys.exit(app.exec_())