题目是
代码用python实现
设计开发用于空间数据质量检查的应用软件工具,该工具运行于单PC机桌面环境,不需要网络连接;说明及评估所采用的软件架构风格。
(1)基本功能要求:
A、地图数据加载:从应用中打开指定的图形或文档类型地图数据文件,并显示在应用程序窗口中。
B、地图数据显示:针对不同类型数据采用不同方式:图形形式的可视化符号显示(主要有栅格及矢量格式类型,原型中至少实现其中一种类型的可视化进行示意);文本形式直接显示数值内容(原型中可用普通文本文件示意)。
C、错误记录:通过在图形中或文本中指定位置,标记各项错误的位置;指出错误位置后,输入错误类型、错误描述等信息并自动给错误编号;在文件中保存所记录的错误信息。
D、错误记录查询:地图数据加载后,在质检工具中打开已保存的错误信息文件,可通过输入关键字搜索并显示出错情况。
(2)成果提交:
A、软件架构说明。说明所采用的软件架构风格及主要优缺点。
B、软件源码及可执行代码包。实现基本功能要求。提示:可使用所学编程语言平台中FILE I/O API及GUI构件。
import json
import tkinter as tk
from tkinter import filedialog, messagebox, Text, Scrollbar
import geopandas as gpd
import rasterio
from rasterio.plot import show as rasterio_show
import matplotlib.pyplot as plt
from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg
class SpatialQualityCheckApp:
def init(self, root):
self.root = root
self.root.title("空间数据质量检查工具")
# 创建菜单
menu = tk.Menu(self.root)
self.root.config(menu=menu)
file_menu = tk.Menu(menu, tearoff=0)
file_menu.add_command(label="打开地图数据", command=self.load_map_data)
file_menu.add_command(label="保存错误记录", command=self.save_error_record)
file_menu.add_command(label="退出", command=root.quit)
menu.add_cascade(label="文件", menu=file_menu)
# 创建界面组件
self.figure = plt.figure(figsize=(6, 6))
self.canvas = FigureCanvasTkAgg(self.figure, master=self.root)
self.canvas_widget = self.canvas.get_tk_widget()
self.canvas_widget.pack(pady=20)
self.error_label = tk.Label(self.root, text="错误记录")
self.error_label.pack(pady=10)
self.error_text = Text(self.root, width=80, height=10)
self.error_text.pack(pady=10)
self.scrollbar = Scrollbar(self.root, command=self.error_text.yview)
self.scrollbar.pack(side=tk.RIGHT, fill=tk.Y)
self.error_text.config(yscrollcommand=self.scrollbar.set)
self.search_label = tk.Label(self.root, text="搜索关键字")
self.search_label.pack(pady=10)
self.search_entry = tk.Entry(self.root)
self.search_entry.pack(pady=10)
self.search_button = tk.Button(self.root, text="搜索", command=self.search_error_record)
self.search_button.pack(pady=10)
# 初始化变量
self.map_data = None
self.error_data = []
def load_map_data(self):
file_path = filedialog.askopenfilename(title="选择地图数据文件", filetypes=[("GeoJSON files", "*.geojson"), ("Shapefile", "*.shp"), ("Raster files", "*.tif"), ("Text files", "*.txt")])
if file_path:
self.plot_map_data(file_path)
def plot_map_data(self, file_path):
self.figure.clear()
self.error_data.clear()
self.error_text.delete(1.0, tk.END)
if file_path.endswith('.geojson') or file_path.endswith('.shp'):
# 读取地图数据
self.map_data = gpd.read_file(file_path)
# 矢量数据,使用 geopandas 进行可视化
ax = self.figure.add_subplot(111)
self.map_data.plot(ax=ax)
ax.set_aspect('equal')
self.canvas.draw()
elif file_path.endswith('.tif'):
# 栅格数据,使用 rasterio 进行可视化
with rasterio.open(file_path) as src:
ax = self.figure.add_subplot(111)
rasterio_show(src, ax=ax)
ax.set_aspect('equal')
self.canvas.draw()
elif file_path.endswith('.txt'):
# 文本文件,直接显示数值内容
with open(file_path, 'r') as f:
content = f.read()
self.error_text.insert(tk.END, content)
else:
messagebox.showinfo("提示", "不支持的文件格式")
def save_error_record(self):
error_info = {
'errors': self.error_data
}
file_path = filedialog.asksaveasfilename(title="保存错误记录", defaultextension=".json", filetypes=[("JSON files", "*.json")])
if file_path:
with open(file_path, 'w') as f:
json.dump(error_info, f)
def search_error_record(self):
keyword = self.search_entry.get()
results = [error for error in self.error_data if keyword in error['description']]
self.error_text.delete(1.0, tk.END)
for result in results:
self.error_text.insert(tk.END, f"错误编号:{result['id']}, 错误类型:{result['type']}, 错误描述:{result['description']}\n")
if name == "main":
root = tk.Tk()
app = SpatialQualityCheckApp(root)
root.mainloop()
结果是这样的
可要求要做成这样的
我的地图数据导入和交互都出现了问题不知道怎么解决
同学,你也是武大遥感空信的吧
import sys
from PyQt5.QtWidgets import QApplication, QMainWindow, QAction, QTextEdit, QFileDialog, QVBoxLayout, QWidget, QPushButton, QLineEdit, QLabel, QMessageBox
class MapDataChecker(QMainWindow):
def init(self):
super().init()
self.initUI()
def initUI(self):
self.setWindowTitle('Map Data Checker')
self.setGeometry(100, 100, 800, 600)
# Menu bar
menubar = self.menuBar()
fileMenu = menubar.addMenu('File')
openAction = QAction('Open', self)
openAction.triggered.connect(self.openFile)
fileMenu.addAction(openAction)
saveAction = QAction('Save', self)
saveAction.triggered.connect(self.saveFile)
fileMenu.addAction(saveAction)
quitAction = QAction('Quit', self)
quitAction.triggered.connect(self.close)
fileMenu.addAction(quitAction)
# Central widget
self.centralWidget = QWidget()
self.setCentralWidget(self.centralWidget)
self.layout = QVBoxLayout()
self.mapDisplay = QTextEdit()
self.layout.addWidget(self.mapDisplay)
self.errorLabel = QLabel("Errors:")
self.layout.addWidget(self.errorLabel)
self.errorDisplay = QTextEdit()
self.layout.addWidget(self.errorDisplay)
self.searchLabel = QLabel("Search Error:")
self.layout.addWidget(self.searchLabel)
self.searchInput = QLineEdit()
self.layout.addWidget(self.searchInput)
self.prevButton = QPushButton("Previous")
self.prevButton.clicked.connect(self.showPrevError)
self.layout.addWidget(self.prevButton)
self.nextButton = QPushButton("Next")
self.nextButton.clicked.connect(self.showNextError)
self.layout.addWidget(self.nextButton)
self.centralWidget.setLayout(self.layout)
self.errors = []
self.currentErrorIndex = 0
def openFile(self):
options = QFileDialog.Options()
fileName, _ = QFileDialog.getOpenFileName(self, "Open Map Data File", "", "All Files (*);;Text Files (*.txt)", options=options)
if fileName:
with open(fileName, 'r') as file:
data = file.read()
# Parse the data and extract errors
self.mapDisplay.setText(data)
self.errors = self.extractErrors(data)
self.currentErrorIndex = 0
self.showCurrentError()
def extractErrors(self, data):
# Dummy function to extract errors from data
# You can implement your own logic here
return [{"position": "Error 1", "type": "Type 1", "description": "Description 1"},
{"position": "Error 2", "type": "Type 2", "description": "Description 2"}]
def showCurrentError(self):
if self.errors:
currentError = self.errors[self.currentErrorIndex]
errorInfo = f"Position: {currentError['position']}\nType: {currentError['type']}\nDescription: {currentError['description']}"
self.errorDisplay.setText(errorInfo)
def showPrevError(self):
if self.errors:
self.currentErrorIndex = (self.currentErrorIndex - 1) % len(self.errors)
self.showCurrentError()
def showNextError(self):
if self.errors:
self.currentErrorIndex = (self.currentErrorIndex + 1) % len(self.errors)
self.showCurrentError()
def saveFile(self):
options = QFileDialog.Options()
fileName, _ = QFileDialog.getSaveFileName(self, "Save Errors", "", "All Files (*);;Text Files (*.txt)", options=options)
if fileName:
with open(fileName, 'w') as file:
errorInfo = self.errorDisplay.toPlainText()
file.write(errorInfo)
if name == 'main':
app = QApplication(sys.argv)
window = MapDataChecker()
window.show()
sys.exit(app.exec_())