需求
测绘时候经常用到rtk,可以测量一点的经纬度和高程,做控制点测量的时候,每个点需要测量多次,然后取平均值作为该点的最终值。
现在公司里有两套仪器,导出的格式略有不同,我们需要提取 点的编号、经度、纬度、高程 这4个数据,然后把同一个点的多次测量结果求平均值;另外需要GUI界面,降低操作难度;其次,有时候需要同时使用多台仪器测量,所以要能一次输入导出的多个文件,输出一个最终处理结果;最后,处理结果要求可以选择csv、xlsx、dat三种格式,有时候要xlsx格式上报,有时候需要dat格式导入cass,有时候需要csv格式便于查看。
思路
- 判断输入的数据是哪套仪器导出的
- 提取 点编号、经度、纬度、高程
- 间距小于0.1的点视为同一位置的多次测量结果,要对这些点求均值,测量的次数不固定,可能有任意多个
- 输出结果到一个文件
- 写个界面包装下
结果
处理完毕
处理结果
01
数据实例
rtk仪器1导出的结果
rtk仪器2导出的结果
02
开始写代码
import sysimport ctlsui import timeimport osimport xlwtfrom PyQt5.QtWidgets import (QMainWindow, QTextEdit, QAction, QFileDialog, QApplication,QMessageBox,QWidget)#dat:6,7 y,x,hclass ctl(QWidget): def __init__(self,ui): super(ctl,self).__init__() self.ui = ui self.xt = '' self.zjg = '' def warn(self,str_): QMessageBox.information(self, #使用infomation信息框 "警告", str_, QMessageBox.Yes) def showDialog(self): #self.ui.setWindowFlags(QtCore.Qt.WindowStaysOnTopHint) # 弹出文件选择框。第一个字符串参数是getOpenFileName()方法的标题。第二个字符串参数指定了对话框的工作目录。 # 默认的,文件过滤器设置成All files (*)。 fname = QFileDialog.getOpenFileNames(None, '打开文件', '','*.csv;;*') # 选中文件后,读出文件的内容,并设置成文本编辑框组件的显示文本 if fname[0]: paths = fname[0] if isinstance(paths, list): paths = '\n'.join(paths) if self.ui.text.toPlainText(): self.ui.text.setPlainText(self.ui.text.toPlainText()+'\n'+paths) else: self.ui.text.setPlainText(paths) #C:\Users\Administrator\Documents\Fiddler2 def write_excel(self,result,path=time.strftime("%Y%m%d_像控点.xls", time.localtime())): path = path +'/'+time.strftime("%Y%m%d_像控点.xls", time.localtime()) workbook = xlwt.Workbook(encoding = 'ascii') worksheet = workbook.add_sheet('像控点') for i in range(len(result)): for k in range(len(result[i])): worksheet.write(i, k, result[i][k]) workbook.save(path) return path def write_csv(self,type_,result,path=time.strftime("%Y%m%d_像控点.csv", time.localtime())): path = path +'/'+time.strftime("%Y%m%d_像控点.csv", time.localtime()) if type_ == 'dat': path =path.replace('csv','dat') result = result[1:] with open(path,'w+',encoding='ascii')as f: for item in result: #print(item) f.write("{},,{},{},{}\n".format(item[0],item[1],item[2],item[3])) return path def read_fle(self,path): try: #输入文件path,全部整理成一个样子 #-->#点号,x,y,h with open(path, 'r',encoding='ansi') as f: datas = f.readlines() result = [] if 'Version : 1' in datas[0]: #大黄 for item in [k.split(',') for k in datas[2:]]: result.append((item[0],float(item[2]),float(item[1]),float(item[3]))) else: #小蓝 for item in [k.split(',') for k in datas[1:]]: result.append((item[0],float(item[13]),float(item[12]),float(item[14]))) return result except: self.warn('文件打开失败') def join_data(self,data): #数据聚类、求平均 #输出结果数据[点,x,y,h] #同一点要求:a-b<1 result = [] for item in data: tmp = [] for k in data:#遍历其他 if abs(item[1]-k[1])<=1 and abs(item[2]-k[2])<=1: #xy的差值小于1 if str(k) not in tmp: tmp.append(str(k)) if str(tmp) not in result: result.append(str(tmp)) #average new_result =[] for items in list(result): items = list(eval(items)) tmp = [items[0][0]] x = 0 y = 0 h = 0 # print(items) for item in items: item = eval(item) x +=item[1] y +=item[2] h += item[3] x = x/len(items) y /=len(items) h /= len(items) new_result.append([eval(items[0])[0],x,y,h]) #print(new_result) return new_result def cal(self): try: if self.ui.text.toPlainText(): #read files self.result = [['点名','东坐标','北坐标','高程']] for path in self.ui.text.toPlainText().split('\n'): if path: data=self.read_fle(path) self.result +=self.join_data(data) print('done') #print(self.result) path ='C:/Users/Administrator/Documents/像控点处理' if not os.path.exists(path): os.makedirs(path) #write excel_path = '' csv_path = '' dat_path = '' if self.ui.excel.isChecked(): excel_path = self.write_excel(self.result,path) if self.ui.csv.isChecked(): csv_path = self.write_csv('csv',self.result,path) if self.ui.dat.isChecked(): dat_path = self.write_csv('dat',self.result,path) if excel_path or csv_path or dat_path: QMessageBox.information(self, #使用infomation信息框 "处理完毕", '处理完毕,已保存到'+path, QMessageBox.Yes) if csv_path: os.startfile(csv_path) elif excel_path: os.startfile(excel_path) else: os.startfile(path) else: QMessageBox.information(self, #使用infomation信息框 "处理完毕", '未选择保存文件类型', QMessageBox.Yes) else: self.warn('请输入数据') except Exception as e: print(e) with open('log.txt','a+',encoding = 'utf-8')as f: f.write(e) QMessageBox.information(self, #使用infomation信息框 "未知错误", '错误已保存到log.txt', QMessageBox.Yes)if __name__ == '__main__': app = QApplication(sys.argv) MainWindow = QMainWindow() ui = ctlsui.Ui_mainWindow() ui.setupUi(MainWindow) MainWindow.show() ctl = ctl(ui) ui.open.clicked.connect(lambda :ctl.showDialog()) ui.start.clicked.connect(lambda :ctl.cal()) sys.exit(app.exec_())
ui代码 ctlsui.py
# -*- coding: utf-8 -*-# Form implementation generated from reading ui file 'ctls.ui'## Created by: PyQt5 UI code generator 5.15.0## WARNING: Any manual changes made to this file will be lost when pyuic5 is# run again. Do not edit this file unless you know what you are doing.from re import findallfrom PyQt5 import QtCore, QtGui, QtWidgetsclass textEdit(QtWidgets.QPlainTextEdit): def __int__(self): super().__init__() self.setAcceptDrops(True) #允许接收拖曳过来的内容 def dragEnterEvent(self, e): if e.mimeData().hasText(): e.accept() else: e.ignore() def dropEvent(self, e): if self.toPlainText(): self.setPlainText(self.toPlainText()+'\n'+e.mimeData().text().replace('file:///', '')) else: self.setPlainText(e.mimeData().text().replace('file:///', ''))class Ui_mainWindow(object): def setupUi(self, mainWindow): mainWindow.setObjectName("mainWindow") mainWindow.resize(425, 265) self.centralwidget = QtWidgets.QWidget(mainWindow) self.centralwidget.setObjectName("centralwidget") self.gridLayout = QtWidgets.QGridLayout(self.centralwidget) self.gridLayout.setObjectName("gridLayout") self.text = textEdit() sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Minimum, QtWidgets.QSizePolicy.Expanding) sizePolicy.setHorizontalStretch(0) sizePolicy.setVerticalStretch(0) sizePolicy.setHeightForWidth(self.text.sizePolicy().hasHeightForWidth()) self.text.setSizePolicy(sizePolicy) self.text.setObjectName("text") self.gridLayout.addWidget(self.text, 0, 0, 1, 1) self.verticalLayout = QtWidgets.QVBoxLayout() self.verticalLayout.setObjectName("verticalLayout") self.open = QtWidgets.QPushButton(self.centralwidget) font = QtGui.QFont() font.setBold(True) font.setWeight(75) self.open.setFont(font) self.open.setObjectName("open") self.verticalLayout.addWidget(self.open) self.excel = QtWidgets.QCheckBox(self.centralwidget) self.excel.setObjectName("excel") self.verticalLayout.addWidget(self.excel) self.csv = QtWidgets.QCheckBox(self.centralwidget) self.csv.setChecked(True) self.csv.setObjectName("csv") self.verticalLayout.addWidget(self.csv) self.dat = QtWidgets.QCheckBox(self.centralwidget) self.dat.setObjectName("dat") self.dat.setChecked(True) self.verticalLayout.addWidget(self.dat) self.gridLayout.addLayout(self.verticalLayout, 0, 1, 1, 1) self.start = QtWidgets.QPushButton(self.centralwidget) self.start.setLayoutDirection(QtCore.Qt.LeftToRight) self.start.setObjectName("start") self.gridLayout.addWidget(self.start, 1, 0, 1, 2) mainWindow.setCentralWidget(self.centralwidget) self.menubar = QtWidgets.QMenuBar(mainWindow) self.menubar.setGeometry(QtCore.QRect(0, 0, 425, 22)) self.menubar.setObjectName("menubar") mainWindow.setMenuBar(self.menubar) self.statusbar = QtWidgets.QStatusBar(mainWindow) self.statusbar.setObjectName("statusbar") mainWindow.setStatusBar(self.statusbar) self.retranslateUi(mainWindow) QtCore.QMetaObject.connectSlotsByName(mainWindow) def retranslateUi(self, mainWindow): _translate = QtCore.QCoreApplication.translate mainWindow.setWindowTitle(_translate("mainWindow", "控制点数据批量处理")) self.text.setPlaceholderText(_translate("mainWindow", "请拖入或右侧打开文件")) self.open.setText(_translate("mainWindow", "...")) self.excel.setText(_translate("mainWindow", "导出至excel")) self.csv.setText(_translate("mainWindow", "导出至csv")) self.dat.setText(_translate("mainWindow", "导出至dat")) self.start.setText(_translate("mainWindow", "开始处理"))
03
运行
只要将仪器导出的文件拖入或者点击右侧按钮打开文件,就可以开始处理任意数量的文件,右侧还可以选择处理结果的格式,默认为csv和dat格式,点击开始处理,处理完毕后会自动打开文件便于查看。一般按下开始处理按钮,数据就处理完了,比以往要快很多。