使用Python处理Shapefile文件
一、Shape文件介绍
ESRI Shapefile(shp),或简称shapefile,是美国环境系统研究所公司(ESRI)开发的一种空间数据开放格式。该文件格式已经成为了地理信息软件界的一个开放标准,这表明ESRI公司在全球的地理信息系统市场的重要性。Shapefile也是一种重要的交换格式,它能够在ESRI与其他公司的产品之间进行数据互操作。
Shapefile文件用于描述几何体对象:点,折线与多边形。例如,Shapefile文件可以存储井、河流、湖泊等空间对象的几何位置。除了几何位置,shp文件也可以存储这些空间对象的属性,例如一条河流的名字,一个城市的温度等等。
二、Shape文件组成
Shapefile文件指的是一种文件存储的方法,实际上该种文件格式是由多个文件组成的。其中,要组成一个Shapefile,有三个文件是必不可少的,它们分别是".shp", ".shx"与 ".dbf"文件。表示同一数据的一组文件其文件名前缀应该相同。例如,存储一个关于湖的几何与属性数据,就必须有lake.shp,lake.shx与lake.dbf三个文件。而其中“真正”的Shapefile的后缀为shp,然而仅有这个文件数据是不完整的,必须要把其他两个附带上才能构成一组完整的地理数据。除了这三个必须的文件以外,还有八个可选的文件,使用它们可以增强空间数据的表达能力。所有的文件名都必须遵循MS DOS的8.3文件名标准(文件前缀名8个字符,后缀名3个字符,如shapefil.shp),以方便与一些老的应用程序保持兼容性,尽管现在许多新的程序都能够支持长文件名。此外,所有的文件都必须位于同一个目录之中。
必须的文件:
- .shp— 图形格式,用于保存元素的几何实体。
- .shx— 图形索引格式。几何体位置索引,记录每一个几何体在shp文件之中的位置,能够加快向前或向后搜索一个几何体的效率。
- .dbf— 属性数据格式,以dBase IV的数据表格式存储每个几何形状的属性数据。
其他可选的文件:
- .prj— 投帧式,用于保存地理坐标系统与投影信息,是一个存储well-known text投影描述符的文本文件。
- .sbnand.sbx— 几何体的空间索引
- .fbnand.fbx— 只读的Shapefiles的几何体的空间索引
- .ainand.aih— 列表中活动字段的属性索引。
- .ixs— 可读写Shapefile文件的地理编码索引
- .mxs— 可读写Shapefile文件的地理编码索引(ODB格式)
- .atx—.dbf文件的属性索引,其文件名格式为_shapefile_.columnname.atx(ArcGIS 8及之后的版本)
- .shp.xml— 以XML格式保存元数据。
- .cpg— 用于描述.dbf文件的代码页,指明其使用的字符编码。
在每个.shp,.shx与.dbf文件之中,图形在每个文件的排序是一致的。也就是说,.shp的第一条记录与.shx及.dbf之中的第一条记录相对应,如此类推。此外,在.shp与.shx之中,有许多字段的字节序是不一样的。因此用户在编写读取这些文件格式的程序时,必须十分小心地处理不同文件的不同字节序。
Shapefile通常以X与Y的方式来处理地理坐标,一般X对应经度,Y对应纬度,用户必须注意X,Y的顺序。
Shapefile图形格式 (.shp)
Shapefile格式的主文件包含了地理参照数据。该文件由一个定长的文件头和一个或若干个变长的记录数据组成。每一条变长数据记录包含一个记录头和一些记录内容。详细的数据存储格式由_Esri Shapefile技术描述_.提供。注意,虽然Shapefile文件的后缀名与AutoCAD的图形字体源格式它们的文件后缀名相同的,都是.shp,请不要把它们混淆。
主文件头包含17个字段,共100个字节,其中包含九个4字节(32位有符号整数,int32)整数字段,紧接着是八个8字节(双精度浮点数)有符号浮点数字段。
三、MySQL对地理空间数据的支持
1.Geometry介绍
MySQL中支持的几何数据类型包括Geometry(几何)、Point(点)、LineString(线)、Polygon(面)
以及集合类型的MultiPoint(多点)、MultiLineString(多线)、MultiPolygon(多面)、GeometryCollection(混合数据类型)
其中,Geometry可以表示其他任意类型的值,剩下的只能表示单个类型的值
2.Geometry类型
注意:数据中间不能有多余的空格
| 名称 | 类型 | 例如 |
|---|---|---|
| Point | 点坐标 | POINT(103 35) |
| LineString | 线坐标 | LINESTRING(103 35,103 36,104 36,105 37) |
| Polygon | 面坐标 | POLYGON(103 35,104 35,104 36,103 36,103 35) |
| MultiPoint | 多点 | MULTIPOINT(103 35, 104 34,105 35) |
| MultiLineString | 多线 | MULTILINESTRING((103 35, 104 35), (105 36, 105 37)) |
| MultiPolygon | 多面 | MULTIPOLYGON(((103 35,104 35,104 36,103 36,103 35)),((103 36,104 36,104 37,103 36))) |
| GeometryCollection | 混合类型 | GEOMETRYCOLLECTION(POINT(103 35), LINESTRING(103 35, 103 37)) |
3、Geometry数据格式
MySQ L支持WKB,WKT数据生成空间数据类型,提供如下函数:
- WKT(文本格式:在代码中的格式)
GeomFromText(wtk [,srid)PointFromText LINESTRINGFROMTEXT ......
- WKB(二进制格式:存储在Geometry类型的表字段中)
GeomFromWKB(wtk [,srid)GeomFromWKB GeomFromWKB ......
4、Geometry的常用函数
1.构造函数
构造函数会获取一种几何类型或几何的文本说明,然后创建一个几何
- ST_Point:文本格式转Point格式(例如存表的时候)
- ST_PointFromText:Point格式转文本格式(例如查询的时候)
- ST_Polygon:文本格式转Polygon格式
- ST_PolygonFromText:Polygon格式转文本格式
- ST_PointFromWKB:以熟知二进制 (WKB) 表示和空间参考 ID 作为输入参数返回 ST_Point 类型的对象
2.存取器函数
函数都采用一个或多个几何作为输入,并返回关于几何的特定信息
- 获取线/面对象四至:st_xmin(geometry)、st_ymin(geometry)、st_xmax(geometry)、st_ymax(geometry)
- ST_AsText:获取一个几何类型,然后返回其可识别的文本表示
- ST_AsGeoJSON:将Geometry格式转为JSON格式
- ST_Centroid:以面或多面为参数输入,然后返回位于几何的包络矩形中心的点
- ST_Length:用于返回线串或多线串的长度
- ST_MaxX:以几何为参数,返回最大的 X 坐标
- ST_SRID:以几何对象作为输入参数,并返回其空间参考 ID
- ST_X:返回点坐标的 X 坐标
- ST_Y:返回点坐标的 Y 坐标
3.关系函数
关系函数将几何作为输入并确定各几何之间是否存在特定关系
- ST_Contains:判断第一个几何对象是否完全包含第二个几何对象
- ST_Disjoint:判断两个几何对象无交集
- ST_Equals:判断两个几何对象是否完全相同
4.几何函数
函数利用空间数据并对其执行分析,然后返回新的空间数据
- ST_Buffer:获取几何对象和距离,然后返回表示围绕源对象的缓冲区的几何对象(例如可以使用线坐标,构造一个线坐标50米之内的面)
- ST_Distance:用于返回两个几何之间的距离。这一距离是两个几何的最近折点之间的距离
- ST_Difference:获取两个几何对象,然后返回表示两个源对象之差的几何对象(例如,计算两个面积差)
更多相关函数可参考:ArcMap
四、Shape文件解析
shape文件解析使用geopandas进行解析和坐标的转换。
核心解析逻辑如下:
python
# 引入geopandas
from geopandas.io.file import read_file
# 读取prj文件
crs = read_crs_from_prj_file(self.prj)
# 读取shp文件信息,变成GeoDataFrame
data = read_file(shp, encoding="gbk")
# 设置数据原始坐标系数据
data.to_crs(crs=crs)
# 转换成WGS84投影坐标系
df = data.to_crs(crs="+proj=longlat +ellps=WGS84 +datum=WGS84 +no_defs")
# 转换成GEOJSON
outpoint_f = 'geometry.json'
df2.to_file(outpoint_f, driver='GeoJSON', encoding='utf-8')
# 生成可视化图片
df2.plot(color='red')
pyplot.savefig('geometry.svg', dpi=1000)
# 导出excel
columnname = list(df)
df.to_excel(self.save_folder + '/' + 'geometry.xlsx', index=None, header=columnname)
def read_crs_from_prj_file(self, prjfile: str):
"""
读取prj文件,获取坐标
:param prjfile: prj文件地址
:return: prj文件内容
"""
f = open(prjfile, "r")
result = f.read().encode("utf-8")
f.close()
return str(result, encoding='utf-8')
五、两种解析方式
1.命令行解析
本方式解析方式灵活。可随意修改代码进行解析,但是必须要懂得python,能够配置相应的python开发环境以及修改python代码。
代码如下:
python
import geopandas
import json
import geodaisy.converters as convert
import matplotlib.pyplot as pyplot
def read_crs_from_prj_file(prjfile: str):
"""
读取prj文件,获取坐标
:param prjfile: prj文件地址
:return: prj文件内容
"""
f = open(prjfile, "r")
result = f.read().encode("utf-8")
f.close()
print("prj文件读取成功")
return str(result, encoding='utf-8')
def convert_geometry(file: str, crs: str):
"""
转换shape文件的坐标系,进行列名转换,生成数据的可视化图片
:param file: shape文件
:param crs: prj文件内容
:param column_name_map: 要进行转换列名的列的字典
{
"原列名1":"新列名1",
"原列名2":"新列名2",
. .
. .
. .
"原列名n":"新列名n"
}
:return: 新生成的文件
"""
data = geopandas.read_file(file, encoding="gbk")
data.to_crs(crs=crs)
reprojected_data = data.to_crs(crs="+proj=longlat +ellps=WGS84 +datum=WGS84 +no_defs")
reprojected_data.to_file("result.shp", encoding="gbk")
print("转换格式后的文件生成成功,名称为:result.shp")
reprojected_data.plot(color='red')
pyplot.savefig('geometry.svg', dpi=1000)
print("数据可视化图片生成成功,名称为: geometry.svg")
return "result.shp"
def read_shape(file: str, column_name_map=None):
"""
将shape文件转换为GEOJson文件
:param file: shape文件地址
:return: GeoJson文件名称
"""
df2 = geopandas.read_file(file, encoding="gbk")
if column_name_map is not None:
df2 = df2.rename(columns=column_name_map)
outpoint_f = 'geometry.json'
df2.to_file(outpoint_f, driver='GeoJSON', encoding='utf-8')
print("GeoJson文件生成成功,名称为: geometry.json")
return outpoint_f
def parse_geo_json_file(file: str):
"""
将GEOJson文件转换为列表对象
:param file: GeoJOSN文件地址
:return: 对象列表
"""
with open(file, 'r', encoding='utf8')as fp:
json_data = json.load(fp)
datass = json_data['features']
values_list = []
for a in datass:
b = a
value = b['properties']
columns_list = []
for x in value:
columns_list.append(x)
values = {}
for key in columns_list:
vv = value.get(key)
if vv is None:
vv = ''
values[key] = vv
value2 = b['geometry']
corrd = str(value2['coordinates'][0])
values['coordinate'] = corrd
values_list.append(values)
return values_list
def parse_geo_json_file_by_wkt(file: str):
"""
将GEOJson文件转换为列表对象,同时将GEOJson转换为wkt
:param file: GEOJson文件地址
:return: 对象列表
"""
with open(file, 'r', encoding='utf8')as fp:
json_data = json.load(fp)
datass = json_data['features']
values_list = []
for a in datass:
b = a
value = b['properties']
columns_list = []
for x in value:
columns_list.append(x)
values = {}
for key in columns_list:
vv = value.get(key)
if vv is None:
vv = ''
values[key] = vv
value2 = b['geometry']
wkt = convert.geojson_to_wkt(value2)
values['coordinate'] = wkt
values_list.append(values)
return values_list
def parse_geo_json_file_by_wkt_and_text(file: str, need_muiliti: bool):
"""
将GEOJson文件转换为列表对象,同时将GEOJson转换为wkt
:param file: GEOJson文件地址
:return: 对象列表
"""
with open(file, 'r', encoding='utf8')as fp:
json_data = json.load(fp)
datass = json_data['features']
values_list = []
for a in datass:
b = a
value = b['properties']
columns_list = []
for x in value:
columns_list.append(x)
values = {}
values['unique_id'] = str(uuid.uuid4()).replace("-", '')
for key in columns_list:
vv = value.get(key)
if vv is None:
vv = ''
values[key] = vv
value2 = b['geometry']
corrd = str(value2['coordinates'][0])
values['geometry'] = corrd
wkt = convert.geojson_to_wkt(value2)
if need_muiliti and wkt.startswith("POLYGON"):
wkt = wkt.replace("POLYGON", "MULTIPOLYGON (")
wkt = wkt + ")"
values['coordinate'] = wkt
values_list.append(values)
values['shape_type'] = 'Polygon'
return values_list
def general_sql(table_name: str, values_list: list):
"""
生成sql文件
:param table_name: 表名
:param values_list: 数据对象列表
:return: sql语句文件地址
"""
sql_list = []
for data in values_list:
keys = []
values = []
for dd in data:
keys.append(dd)
if dd == 'coordinate':
values.append("ST_GeomFromText('" + str(data[dd]) + "')")
else:
values.append("'" + str(data[dd]) + "'")
sql_list.append("insert into {}({}) values ({})".format(table_name, ','.join(keys), ','.join(values)))
with open("geometry.sql", "w+", encoding='utf-8') as f:
f.write(";\n".join(sql_list))
print("SQL文件生成成功,名称为: geometry.sql")
return "geometry.sql"
if __name__ == '__main__':
"""
示例代码解析
"""
columns_name_map = {
"投影面积": "projectionArea",
"序号": "xh",
"西至": "west",
"shape_leng": "shapeLeng",
"南至": "south",
"北至": "north",
"shape_area": "shapeArea"
}
crs = read_crs_from_prj_file("/opt/datafile.prj")
result = convert_geometry("/opt/datafile.shp", crs, columns_name_map)
json_file = read_shape(result)
data = parse_geo_json_file_by_wkt(json_file)
sql_list = general_sql('tabless', data)
2.Python可视化处理小工具
本方式使用简单,只要使用软件输入相关shape文件地址信息,即可查看shape结构、生成示意图、生成geojson、生成sql、生成excel等,但也相对限制了灵活度。
代码如下:
python
# -*- coding: utf-8 -*-
# Form implementation generated from reading ui file 'windows.ui'
#
# Created by: PyQt5 UI code generator 5.15.4
#
# 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.
import sys
import cv2
from PyQt5.QtWidgets import QApplication, QMainWindow, QMessageBox, QTableWidgetItem, QAbstractItemView, \
QWidget, QHBoxLayout, QLabel, QGraphicsScene, QGraphicsPixmapItem
from PyQt5 import QtCore, QtWidgets
from PyQt5.Qt import QThread, QMutex, pyqtSignal
from PyQt5.QtWidgets import QFileDialog
from PyQt5.QtCore import QSize, Qt
from PyQt5.QtGui import QFontMetrics, QFont, QMovie, \
QMoveEvent, QImage, QPixmap
import os
from geopandas.io.file import read_file
import json
import geodaisy.converters as convert
from geopandas.geodataframe import GeoDataFrame
from matplotlib import pyplot
from matplotlib.backends.backend_qt5agg import FigureCanvasQTAgg
from fiona import _shim, schema
curr_tab_index = 0
qmut_1 = QMutex() # 创建线程锁
class Ui_MainWindow(object):
def setupUi(self, MainWindow):
MainWindow.setObjectName("MainWindow")
MainWindow.resize(800, 600)
self.centralwidget = QtWidgets.QWidget(MainWindow)
self.centralwidget.setObjectName("centralwidget")
self.lookStructs = QtWidgets.QTabWidget(self.centralwidget)
self.lookStructs.setGeometry(QtCore.QRect(0, 0, 801, 601))
self.lookStructs.setObjectName("lookStructs")
self.tab = QtWidgets.QWidget()
self.tab.setObjectName("tab")
self.label = QtWidgets.QLabel(self.tab)
self.label.setGeometry(QtCore.QRect(20, 40, 101, 16))
self.label.setObjectName("label")
self.label_2 = QtWidgets.QLabel(self.tab)
self.label_2.setGeometry(QtCore.QRect(20, 110, 101, 16))
self.label_2.setObjectName("label_2")
self.label_3 = QtWidgets.QLabel(self.tab)
self.label_3.setGeometry(QtCore.QRect(20, 90, 101, 16))
self.label_3.setText("")
self.label_3.setObjectName("label_3")
self.shapeFile = QtWidgets.QLineEdit(self.tab)
self.shapeFile.setGeometry(QtCore.QRect(90, 30, 531, 41))
self.shapeFile.setObjectName("shapeFile")
self.prjShape = QtWidgets.QLineEdit(self.tab)
self.prjShape.setGeometry(QtCore.QRect(90, 100, 531, 41))
self.prjShape.setObjectName("prjShape")
self.chooseShapeFile = QtWidgets.QPushButton(self.tab)
self.chooseShapeFile.setGeometry(QtCore.QRect(670, 30, 101, 41))
self.chooseShapeFile.setObjectName("chooseShapeFile")
self.choosePrjFile = QtWidgets.QPushButton(self.tab)
self.choosePrjFile.setGeometry(QtCore.QRect(670, 100, 101, 41))
self.choosePrjFile.setObjectName("choosePrjFile")
self.label_4 = QtWidgets.QLabel(self.tab)
self.label_4.setGeometry(QtCore.QRect(20, 180, 54, 12))
self.label_4.setObjectName("label_4")
self.dataStructsTable = QtWidgets.QTableWidget(self.tab)
self.dataStructsTable.setGeometry(QtCore.QRect(90, 170, 681, 321))
self.dataStructsTable.setObjectName("dataStructsTable")
self.dataStructsTable.setColumnCount(0)
self.dataStructsTable.setRowCount(0)
self.parseDataButton = QtWidgets.QPushButton(self.tab)
self.parseDataButton.setGeometry(QtCore.QRect(90, 500, 141, 41))
self.parseDataButton.setObjectName("parseDataButton")
self.lookStructs.addTab(self.tab, "")
self.tab_6 = QtWidgets.QWidget()
self.tab_6.setObjectName("tab_6")
self.chooseShapeFile_2 = QtWidgets.QPushButton(self.tab_6)
self.chooseShapeFile_2.setGeometry(QtCore.QRect(670, 30, 101, 41))
self.chooseShapeFile_2.setObjectName("chooseShapeFile_2")
self.choosePrjFile_2 = QtWidgets.QPushButton(self.tab_6)
self.choosePrjFile_2.setGeometry(QtCore.QRect(670, 100, 101, 41))
self.choosePrjFile_2.setObjectName("choosePrjFile_2")
self.shapeFile_2 = QtWidgets.QLineEdit(self.tab_6)
self.shapeFile_2.setGeometry(QtCore.QRect(90, 30, 531, 41))
self.shapeFile_2.setObjectName("shapeFile_2")
self.label_20 = QtWidgets.QLabel(self.tab_6)
self.label_20.setGeometry(QtCore.QRect(20, 110, 101, 16))
self.label_20.setObjectName("label_20")
self.parseDataButton_2 = QtWidgets.QPushButton(self.tab_6)
self.parseDataButton_2.setGeometry(QtCore.QRect(90, 500, 141, 41))
self.parseDataButton_2.setObjectName("parseDataButton_2")
self.label_21 = QtWidgets.QLabel(self.tab_6)
self.label_21.setGeometry(QtCore.QRect(20, 40, 101, 16))
self.label_21.setObjectName("label_21")
self.prjShape_2 = QtWidgets.QLineEdit(self.tab_6)
self.prjShape_2.setGeometry(QtCore.QRect(90, 100, 531, 41))
self.prjShape_2.setObjectName("prjShape_2")
self.zoomout = QtWidgets.QPushButton(self.tab_6)
self.zoomout.setGeometry(QtCore.QRect(20, 160, 40, 20))
self.zoomout.setObjectName("zoomout")
self.zoomin = QtWidgets.QPushButton(self.tab_6)
self.zoomin.setGeometry(QtCore.QRect(20, 180, 40, 20))
self.zoomin.setObjectName("zoomin")
self.graphicsView = QtWidgets.QGraphicsView(self.tab_6)
self.graphicsView.setGeometry(QtCore.QRect(90, 150, 681, 341))
self.graphicsView.setObjectName("graphicsView")
self.lookStructs.addTab(self.tab_6, "")
self.tab_2 = QtWidgets.QWidget()
self.tab_2.setObjectName("tab_2")
self.convertJSButton = QtWidgets.QPushButton(self.tab_2)
self.convertJSButton.setGeometry(QtCore.QRect(90, 500, 141, 41))
self.convertJSButton.setObjectName("convertJSButton")
self.js_shapeFile = QtWidgets.QLineEdit(self.tab_2)
self.js_shapeFile.setGeometry(QtCore.QRect(90, 30, 531, 41))
self.js_shapeFile.setObjectName("js_shapeFile")
self.chooseJSShapeFile = QtWidgets.QPushButton(self.tab_2)
self.chooseJSShapeFile.setGeometry(QtCore.QRect(670, 30, 101, 41))
self.chooseJSShapeFile.setObjectName("chooseJSShapeFile")
self.label_5 = QtWidgets.QLabel(self.tab_2)
self.label_5.setGeometry(QtCore.QRect(20, 40, 101, 16))
self.label_5.setObjectName("label_5")
self.label_6 = QtWidgets.QLabel(self.tab_2)
self.label_6.setGeometry(QtCore.QRect(20, 110, 101, 16))
self.label_6.setObjectName("label_6")
self.js_prjShape = QtWidgets.QLineEdit(self.tab_2)
self.js_prjShape.setGeometry(QtCore.QRect(90, 100, 531, 41))
self.js_prjShape.setObjectName("js_prjShape")
self.chooseJSPrjFile = QtWidgets.QPushButton(self.tab_2)
self.chooseJSPrjFile.setGeometry(QtCore.QRect(670, 100, 101, 41))
self.chooseJSPrjFile.setObjectName("chooseJSPrjFile")
self.label_11 = QtWidgets.QLabel(self.tab_2)
self.label_11.setGeometry(QtCore.QRect(10, 180, 81, 16))
self.label_11.setObjectName("label_11")
self.geojsonSaveFile = QtWidgets.QLineEdit(self.tab_2)
self.geojsonSaveFile.setGeometry(QtCore.QRect(90, 170, 531, 41))
self.geojsonSaveFile.setObjectName("geojsonSaveFile")
self.chooseGeoJsonSaveFile = QtWidgets.QPushButton(self.tab_2)
self.chooseGeoJsonSaveFile.setGeometry(QtCore.QRect(670, 170, 101, 41))
self.chooseGeoJsonSaveFile.setObjectName("chooseGeoJsonSaveFile")
self.label_12 = QtWidgets.QLabel(self.tab_2)
self.label_12.setGeometry(QtCore.QRect(10, 260, 54, 12))
self.label_12.setObjectName("label_12")
self.label_13 = QtWidgets.QLabel(self.tab_2)
self.label_13.setGeometry(QtCore.QRect(20, 330, 54, 12))
self.label_13.setObjectName("label_13")
self.columnConvertMap = QtWidgets.QTextEdit(self.tab_2)
self.columnConvertMap.setGeometry(QtCore.QRect(90, 310, 531, 181))
self.columnConvertMap.setObjectName("columnConvertMap")
self.checkBox = QtWidgets.QCheckBox(self.tab_2)
self.checkBox.setGeometry(QtCore.QRect(90, 260, 211, 21))
self.checkBox.setObjectName("checkBox")
self.lookStructs.addTab(self.tab_2, "")
self.tab_3 = QtWidgets.QWidget()
self.tab_3.setObjectName("tab_3")
self.convertSQLButton = QtWidgets.QPushButton(self.tab_3)
self.convertSQLButton.setGeometry(QtCore.QRect(90, 500, 141, 41))
self.convertSQLButton.setObjectName("convertSQLButton")
self.label_14 = QtWidgets.QLabel(self.tab_3)
self.label_14.setGeometry(QtCore.QRect(10, 180, 81, 16))
self.label_14.setObjectName("label_14")
self.sql_columnConvertMap = QtWidgets.QTextEdit(self.tab_3)
self.sql_columnConvertMap.setGeometry(QtCore.QRect(90, 310, 531, 181))
self.sql_columnConvertMap.setObjectName("sql_columnConvertMap")
self.sql_shapeFile = QtWidgets.QLineEdit(self.tab_3)
self.sql_shapeFile.setGeometry(QtCore.QRect(90, 30, 531, 41))
self.sql_shapeFile.setObjectName("sql_shapeFile")
self.sql_chooseShapeFile = QtWidgets.QPushButton(self.tab_3)
self.sql_chooseShapeFile.setGeometry(QtCore.QRect(670, 30, 101, 41))
self.sql_chooseShapeFile.setObjectName("sql_chooseShapeFile")
self.label_15 = QtWidgets.QLabel(self.tab_3)
self.label_15.setGeometry(QtCore.QRect(10, 240, 54, 12))
self.label_15.setObjectName("label_15")
self.sqlchooseGeoJsonSaveFile = QtWidgets.QPushButton(self.tab_3)
self.sqlchooseGeoJsonSaveFile.setGeometry(QtCore.QRect(670, 170, 101, 41))
self.sqlchooseGeoJsonSaveFile.setObjectName("sqlchooseGeoJsonSaveFile")
self.sql_choosePrjFile = QtWidgets.QPushButton(self.tab_3)
self.sql_choosePrjFile.setGeometry(QtCore.QRect(670, 100, 101, 41))
self.sql_choosePrjFile.setObjectName("sql_choosePrjFile")
self.label_16 = QtWidgets.QLabel(self.tab_3)
self.label_16.setGeometry(QtCore.QRect(20, 330, 54, 12))
self.label_16.setObjectName("label_16")
self.label_7 = QtWidgets.QLabel(self.tab_3)
self.label_7.setGeometry(QtCore.QRect(20, 110, 101, 16))
self.label_7.setObjectName("label_7")
self.sql_prjShape = QtWidgets.QLineEdit(self.tab_3)
self.sql_prjShape.setGeometry(QtCore.QRect(90, 100, 531, 41))
self.sql_prjShape.setObjectName("sql_prjShape")
self.label_8 = QtWidgets.QLabel(self.tab_3)
self.label_8.setGeometry(QtCore.QRect(20, 40, 101, 16))
self.label_8.setObjectName("label_8")
self.sqlSaveFile = QtWidgets.QLineEdit(self.tab_3)
self.sqlSaveFile.setGeometry(QtCore.QRect(90, 170, 531, 41))
self.sqlSaveFile.setObjectName("sqlSaveFile")
self.checkBox_3 = QtWidgets.QCheckBox(self.tab_3)
self.checkBox_3.setGeometry(QtCore.QRect(90, 240, 201, 21))
self.checkBox_3.setObjectName("checkBox_3")
self.checkBox_4 = QtWidgets.QCheckBox(self.tab_3)
self.checkBox_4.setGeometry(QtCore.QRect(310, 240, 161, 21))
self.checkBox_4.setObjectName("checkBox_4")
self.lookStructs.addTab(self.tab_3, "")
self.label_111 = QtWidgets.QLabel(self.tab_3)
self.label_111.setGeometry(QtCore.QRect(10, 280, 101, 16))
self.label_111.setObjectName("label_111")
self.label_222 = QtWidgets.QLabel(self.tab_3)
self.label_222.setGeometry(QtCore.QRect(90, 280, 101, 16))
self.label_222.setObjectName("label_222")
self.sql_coord_name = QtWidgets.QLineEdit(self.tab_3)
self.sql_coord_name.setGeometry(QtCore.QRect(170, 280, 100, 21))
self.sql_coord_name.setObjectName("sql_coord_name")
self.label_333 = QtWidgets.QLabel(self.tab_3)
self.label_333.setGeometry(QtCore.QRect(280, 280, 161, 16))
self.label_333.setObjectName("label_333")
self.sql_coord_text_name = QtWidgets.QLineEdit(self.tab_3)
self.sql_coord_text_name.setGeometry(QtCore.QRect(400, 280, 100, 21))
self.sql_coord_text_name.setObjectName("sql_coord_text_name")
self.label_444 = QtWidgets.QLabel(self.tab_3)
self.label_444.setGeometry(QtCore.QRect(500, 280, 161, 16))
self.label_444.setObjectName("label_444")
self.sql_table_name = QtWidgets.QLineEdit(self.tab_3)
self.sql_table_name.setGeometry(QtCore.QRect(530, 280, 100, 21))
self.sql_table_name.setObjectName("sql_table_name")
self.tab_4 = QtWidgets.QWidget()
self.tab_4.setObjectName("tab_4")
self.convertExcelButton = QtWidgets.QPushButton(self.tab_4)
self.convertExcelButton.setGeometry(QtCore.QRect(90, 500, 141, 41))
self.convertExcelButton.setObjectName("convertExcelButton")
self.label_17 = QtWidgets.QLabel(self.tab_4)
self.label_17.setGeometry(QtCore.QRect(10, 180, 81, 16))
self.label_17.setObjectName("label_17")
self.ex_columnConvertMap = QtWidgets.QTextEdit(self.tab_4)
self.ex_columnConvertMap.setGeometry(QtCore.QRect(90, 310, 531, 181))
self.ex_columnConvertMap.setObjectName("ex_columnConvertMap")
self.ex_shapeFile = QtWidgets.QLineEdit(self.tab_4)
self.ex_shapeFile.setGeometry(QtCore.QRect(90, 30, 531, 41))
self.ex_shapeFile.setObjectName("ex_shapeFile")
self.ex_chooseShapeFile = QtWidgets.QPushButton(self.tab_4)
self.ex_chooseShapeFile.setGeometry(QtCore.QRect(670, 30, 101, 41))
self.ex_chooseShapeFile.setObjectName("ex_chooseShapeFile")
self.label_18 = QtWidgets.QLabel(self.tab_4)
self.label_18.setGeometry(QtCore.QRect(10, 260, 54, 12))
self.label_18.setObjectName("label_18")
self.ex_chooseGeoJsonSaveFile = QtWidgets.QPushButton(self.tab_4)
self.ex_chooseGeoJsonSaveFile.setGeometry(QtCore.QRect(670, 170, 101, 41))
self.ex_chooseGeoJsonSaveFile.setObjectName("ex_chooseGeoJsonSaveFile")
self.ex_choosePrjFile = QtWidgets.QPushButton(self.tab_4)
self.ex_choosePrjFile.setGeometry(QtCore.QRect(670, 100, 101, 41))
self.ex_choosePrjFile.setObjectName("ex_choosePrjFile")
self.label_19 = QtWidgets.QLabel(self.tab_4)
self.label_19.setGeometry(QtCore.QRect(20, 330, 54, 12))
self.label_19.setObjectName("label_19")
self.label_9 = QtWidgets.QLabel(self.tab_4)
self.label_9.setGeometry(QtCore.QRect(20, 110, 101, 16))
self.label_9.setObjectName("label_9")
self.ex_prjShape = QtWidgets.QLineEdit(self.tab_4)
self.ex_prjShape.setGeometry(QtCore.QRect(90, 100, 531, 41))
self.ex_prjShape.setObjectName("ex_prjShape")
self.label_10 = QtWidgets.QLabel(self.tab_4)
self.label_10.setGeometry(QtCore.QRect(20, 40, 101, 16))
self.label_10.setObjectName("label_10")
self.ex_geojsonSaveFile = QtWidgets.QLineEdit(self.tab_4)
self.ex_geojsonSaveFile.setGeometry(QtCore.QRect(90, 170, 531, 41))
self.ex_geojsonSaveFile.setObjectName("ex_geojsonSaveFile")
self.checkBox_6 = QtWidgets.QCheckBox(self.tab_4)
self.checkBox_6.setGeometry(QtCore.QRect(90, 260, 221, 21))
self.checkBox_6.setObjectName("checkBox_6")
self.lookStructs.addTab(self.tab_4, "")
self.tab_5 = QtWidgets.QWidget()
self.tab_5.setObjectName("tab_5")
self.textBrowser = QtWidgets.QTextEdit(self.tab_5)
self.textBrowser.setGeometry(QtCore.QRect(0, 0, 801, 551))
self.textBrowser.setObjectName("textBrowser")
self.lookStructs.addTab(self.tab_5, "")
MainWindow.setCentralWidget(self.centralwidget)
self.statusbar = QtWidgets.QStatusBar(MainWindow)
self.statusbar.setObjectName("statusbar")
MainWindow.setStatusBar(self.statusbar)
self.retranslateUi(MainWindow)
self.lookStructs.setCurrentIndex(1)
QtCore.QMetaObject.connectSlotsByName(MainWindow)
self.lookStructs.setCurrentIndex(0)
self.lookStructs.currentChanged.connect(self.tab_change)
self.choosePrjFile.clicked.connect(self.choose_prj_file)
self.choosePrjFile_2.clicked.connect(self.choose_prj_file)
self.chooseJSPrjFile.clicked.connect(self.choose_prj_file)
self.sql_choosePrjFile.clicked.connect(self.choose_prj_file)
self.ex_choosePrjFile.clicked.connect(self.choose_prj_file)
self.chooseShapeFile.clicked.connect(self.choose_shp_file)
self.chooseShapeFile_2.clicked.connect(self.choose_shp_file)
self.chooseJSShapeFile.clicked.connect(self.choose_shp_file)
self.sql_chooseShapeFile.clicked.connect(self.choose_shp_file)
self.ex_chooseShapeFile.clicked.connect(self.choose_shp_file)
self.chooseGeoJsonSaveFile.clicked.connect(self.choose_save_folder)
self.sqlchooseGeoJsonSaveFile.clicked.connect(self.choose_save_folder)
self.ex_chooseGeoJsonSaveFile.clicked.connect(self.choose_save_folder)
self.parseDataButton.clicked.connect(self.get_data_structs)
self.parseDataButton_2.clicked.connect(self.get_data_image)
self.convertJSButton.clicked.connect(self.get_data_geoJSON)
self.convertSQLButton.clicked.connect(self.get_data_sql)
self.convertExcelButton.clicked.connect(self.get_data_excel)
self.zoomout.clicked.connect(self.on_zoomout_clicked)
self.zoomin.clicked.connect(self.on_zoomin_clicked)
def retranslateUi(self, MainWindow):
_translate = QtCore.QCoreApplication.translate
MainWindow.setWindowTitle(_translate("MainWindow", "Shape工具"))
self.label.setText(_translate("MainWindow", "Shape文件:"))
self.label_2.setText(_translate("MainWindow", "Prj文件:"))
self.chooseShapeFile.setText(_translate("MainWindow", "选择文件"))
self.choosePrjFile.setText(_translate("MainWindow", "选择文件"))
self.label_4.setText(_translate("MainWindow", "数据结构"))
self.parseDataButton.setText(_translate("MainWindow", "开始解析"))
self.lookStructs.setTabText(self.lookStructs.indexOf(self.tab), _translate("MainWindow", "查看数据结构"))
self.chooseShapeFile_2.setText(_translate("MainWindow", "选择文件"))
self.choosePrjFile_2.setText(_translate("MainWindow", "选择文件"))
self.label_20.setText(_translate("MainWindow", "Prj文件:"))
self.parseDataButton_2.setText(_translate("MainWindow", "开始解析"))
self.label_21.setText(_translate("MainWindow", "Shape文件:"))
self.lookStructs.setTabText(self.lookStructs.indexOf(self.tab_6), _translate("MainWindow", "查看图形分布"))
self.convertJSButton.setText(_translate("MainWindow", "开始转换"))
self.chooseJSShapeFile.setText(_translate("MainWindow", "选择文件"))
self.label_5.setText(_translate("MainWindow", "Shape文件:"))
self.label_6.setText(_translate("MainWindow", "Prj文件:"))
self.chooseJSPrjFile.setText(_translate("MainWindow", "选择文件"))
self.label_11.setText(_translate("MainWindow", "文件保存位置"))
self.chooseGeoJsonSaveFile.setText(_translate("MainWindow", "选择文件夹"))
self.label_12.setText(_translate("MainWindow", "转换选项"))
self.label_13.setText(_translate("MainWindow", "字段映射"))
self.label_111.setText(_translate("MainWindow", "地理信息"))
self.label_222.setText(_translate("MainWindow", "地理信息字段:"))
self.label_333.setText(_translate("MainWindow", "文本格式地理信息字段:"))
self.label_444.setText(_translate("MainWindow", "表名:"))
self.checkBox.setText(_translate("MainWindow", "是否根据Prj文件进行经纬度转换"))
self.lookStructs.setTabText(self.lookStructs.indexOf(self.tab_2), _translate("MainWindow", "转GEOJSON"))
self.convertSQLButton.setText(_translate("MainWindow", "开始转换"))
self.label_14.setText(_translate("MainWindow", "文件保存位置"))
self.sql_chooseShapeFile.setText(_translate("MainWindow", "选择文件"))
self.label_15.setText(_translate("MainWindow", "转换选项"))
self.sqlchooseGeoJsonSaveFile.setText(_translate("MainWindow", "选择文件夹"))
self.sql_choosePrjFile.setText(_translate("MainWindow", "选择文件"))
self.label_16.setText(_translate("MainWindow", "字段映射"))
self.label_7.setText(_translate("MainWindow", "Prj文件:"))
self.label_8.setText(_translate("MainWindow", "Shape文件:"))
self.checkBox_3.setText(_translate("MainWindow", "是否根据Prj文件进行经纬度转换"))
self.checkBox_4.setText(_translate("MainWindow", "是否转为Muiliti数据集"))
self.lookStructs.setTabText(self.lookStructs.indexOf(self.tab_3), _translate("MainWindow", "转SQL"))
self.convertExcelButton.setText(_translate("MainWindow", "开始转换"))
self.label_17.setText(_translate("MainWindow", "文件保存位置"))
self.ex_chooseShapeFile.setText(_translate("MainWindow", "选择文件"))
self.label_18.setText(_translate("MainWindow", "转换选项"))
self.ex_chooseGeoJsonSaveFile.setText(_translate("MainWindow", "选择文件夹"))
self.ex_choosePrjFile.setText(_translate("MainWindow", "选择文件"))
self.label_19.setText(_translate("MainWindow", "字段映射"))
self.label_9.setText(_translate("MainWindow", "Prj文件:"))
self.label_10.setText(_translate("MainWindow", "Shape文件:"))
self.checkBox_6.setText(_translate("MainWindow", "是否根据Prj文件进行经纬度转换"))
self.lookStructs.setTabText(self.lookStructs.indexOf(self.tab_4), _translate("MainWindow", "转EXCEL"))
self.lookStructs.setTabText(self.lookStructs.indexOf(self.tab_5), _translate("MainWindow", "使用说明"))
self.zoomout.setText(_translate("MainWindow", "放大"))
self.zoomin.setText(_translate("MainWindow", "缩小"))
self.sql_coord_name.setText("coordinate")
cc = """
使用说明手册
一、查看数据结构:
选择后缀名为.shp的文件。
选择后缀名为.prj的文件。
点击转换,等待转换结束,即可查看到前10条数据。
二、查看图形分布
选择后缀名为.shp的文件。
选择后缀名为.prj的文件。
点击转换,等待转换结束,即可看见图形分布。
点击 放大,可以放大图形。
点击 缩小,可以缩小图形。
三、转GEOJSON
选择后缀名为.shp的文件。
选择后缀名为.prj的文件。
选择保存生成的GEOJSON的文件夹。
转换选项:如果勾选,则将会根据prj文件中的信息将坐标转为WGS84,如不选则保存原数据。
字段映射:如果原始shape文件中字段名称为 汉字等,可以再次提供一个字段映射的map。在生成sql文件的时候会进行字段的相应转换。
{
"原始字段名1":"目标字段名1",
"原始字段名2":"目标字段名2"
}
点击转换,等待转换结束,即可在选择的保存文件夹下生成geometry.json文件。
四、转SQL
选择后缀名为.shp的文件。
选择后缀名为.prj的文件。
选择保存生成的GEOJSON的文件夹。
转换选项:
1.如果勾选,则将会根据prj文件中的信息将坐标转为WGS84,如不选则保存原数据。
2.如果勾选,则会将POLYGON格式转换为MULTIPOLYGON格式。
地理信息:
地理信息字段:数据库存储地理信息的字段,类型应该为Point、Polygon、multipolygon等类型,必填, MULTIPOLYGON(((120.15168627949 30.2256835231913)))
文本格式地理信息字段:数据库存储地理信息文本格式的字段,[[120.1516862794896, 30.22568352319127]]
字段映射:如果原始shape文件中字段名称为 汉字等,可以再次提供一个字段映射的map。在生成sql文件的时候会进行字段的相应转换。
{
"原始字段名1":"目标字段名1",
"原始字段名2":"目标字段名2"
}
点击转换,等待转换结束,即可在选择的保存文件夹下生成geometry.sql文件。
五、转EXCEL
选择后缀名为.shp的文件。
选择后缀名为.prj的文件。
选择保存生成的EXCEL的文件夹。
转换选项:如果勾选,则将会根据prj文件中的信息将坐标转为WGS84,如不选则保存原数据。
字段映射:如果原始shape文件中字段名称为 汉字等,可以再次提供一个字段映射的map。在生成EXCEL文件的时候会进行字段的相应转换。
{
"原始字段名1":"目标字段名1",
"原始字段名2":"目标字段名2"
}
点击转换,等待转换结束,即可在选择的保存文件夹下生成geometry.excel文件。
"""
self.textBrowser.setMarkdown(cc)
def tab_change(self, x):
global curr_tab_index
curr_tab_index = x
def messageDialog(self, msg):
# 核心功能代码就两行,可以加到需要的地方
if hasattr(self, "loading_mask"):
self.loading_mask.deleteLater()
msg_box = QMessageBox.about(self.centralwidget, '提示', msg)
def choose_prj_file(self):
# 打开文件路径
file_name, file_type = QFileDialog.getOpenFileName(self.centralwidget, "选取.prj文件", os.getcwd(), "*.prj")
global curr_tab_index
if curr_tab_index == 0:
self.prjShape.setText(file_name)
elif curr_tab_index == 1:
self.prjShape_2.setText(file_name)
elif curr_tab_index == 2:
self.js_prjShape.setText(file_name)
elif curr_tab_index == 3:
self.sql_prjShape.setText(file_name)
else:
self.ex_prjShape.setText(file_name)
def choose_shp_file(self):
# 打开文件路径
file_name, file_type = QFileDialog.getOpenFileName(self.centralwidget, "选取.shp文件", os.getcwd(), "*.shp")
global curr_tab_index
if curr_tab_index == 0:
self.shapeFile.setText(file_name)
elif curr_tab_index == 1:
self.shapeFile_2.setText(file_name)
elif curr_tab_index == 2:
self.js_shapeFile.setText(file_name)
elif curr_tab_index == 3:
self.sql_shapeFile.setText(file_name)
else:
self.ex_shapeFile.setText(file_name)
def choose_save_folder(self):
# 打开文件路径
folder_name = QFileDialog.getExistingDirectory(self.centralwidget, "选取输出文件夹", os.getcwd())
global curr_tab_index
if curr_tab_index == 2:
self.geojsonSaveFile.setText(folder_name)
elif curr_tab_index == 3:
self.sqlSaveFile.setText(folder_name)
else:
self.ex_geojsonSaveFile.setText(folder_name)
def get_data_structs(self):
try:
shp_file = self.shapeFile.text()
if shp_file is None or shp_file == '':
self.messageDialog("shape文件没有选择")
return
self.loading_mask = LoadingMask(MainWindow, tip='正在解析...', gif=get_resource_path('./loading.gif'))
MainWindow.installEventFilter(self.loading_mask)
self.loading_mask.show()
self.loading_mask.moveWithParent()
# 创建线程
self.thread = ReadShapeStructs(shp_file, {})
# 连接信号
self.thread._signal.connect(self.draw_structs) # 进程连接回传到GUI的事件
# 开始线程
self.thread.start()
except:
self.messageDialog("转换失败")
def get_data_image(self):
try:
shp_file = self.shapeFile_2.text()
if shp_file is None or shp_file == '':
self.messageDialog("shape文件没有选择")
return
self.loading_mask = LoadingMask(MainWindow, tip='正在解析...', gif=get_resource_path('./loading.gif'))
MainWindow.installEventFilter(self.loading_mask)
self.loading_mask.show()
self.loading_mask.moveWithParent()
# 创建线程
self.thread = ReadShapeImage(shp_file, {})
# 连接信号
self.thread._signal.connect(self.draw_image) # 进程连接回传到GUI的事件
# 开始线程
self.thread.start()
except:
self.messageDialog("转换失败")
def get_data_geoJSON(self):
try:
shp_file = self.js_shapeFile.text()
prj_file = self.js_prjShape.text()
save_folder = self.geojsonSaveFile.text()
column_map = self.columnConvertMap.toPlainText()
cov_ll = self.checkBox.checkState()
if shp_file is None or shp_file == '':
self.messageDialog("shape文件没有选择")
return
if cov_ll == 2 and (prj_file is None or prj_file == ''):
self.messageDialog("prj文件没有选择")
return
if save_folder is None or save_folder == '':
self.messageDialog("文件保存地址没有选择")
return
self.loading_mask = LoadingMask(MainWindow, tip='正在转换...', gif=get_resource_path('./loading.gif'))
MainWindow.installEventFilter(self.loading_mask)
self.loading_mask.show()
self.loading_mask.moveWithParent()
if column_map is None or len(column_map) <= 0:
column_map = '1222'
# 创建线程
self.thread = ConvertGeojson(shp_file, prj_file, save_folder, json.loads(column_map), cov_ll)
# 连接信号
self.thread._signal.connect(self.messageDialog) # 进程连接回传到GUI的事件
# 开始线程
self.thread.start()
except:
self.messageDialog("转换失败")
def get_data_sql(self):
try:
sql_table_name = self.sql_table_name.text()
sql_coord_name = self.sql_coord_name.text()
sql_coord_text_name = self.sql_coord_text_name.text()
shp_file = self.sql_shapeFile.text()
prj_file = self.sql_prjShape.text()
save_folder = self.sqlSaveFile.text()
column_map = self.sql_columnConvertMap.toPlainText()
cov_ll = self.checkBox_3.checkState()
cov_muiliti = self.checkBox_4.checkState()
if shp_file is None or shp_file == '':
self.messageDialog("shape文件没有选择")
return
if cov_ll == 2 and (prj_file is None or prj_file == ''):
self.messageDialog("prj文件没有选择")
return
if save_folder is None or save_folder == '':
self.messageDialog("文件保存地址没有选择")
return
if sql_coord_name is None or sql_coord_name == '':
self.messageDialog("地理信息字段不能为空")
return
self.loading_mask = LoadingMask(MainWindow, tip='正在转换...', gif=get_resource_path('./loading.gif'))
MainWindow.installEventFilter(self.loading_mask)
self.loading_mask.show()
self.loading_mask.moveWithParent()
# 创建线程
if column_map is None or len(column_map) <= 0:
column_map = '1222'
self.thread = ConvertSQL(shp_file, prj_file, save_folder, json.loads(column_map), cov_ll, cov_muiliti,sql_coord_name,sql_coord_text_name,sql_table_name)
# 连接信号
self.thread._signal.connect(self.messageDialog) # 进程连接回传到GUI的事件
# 开始线程
self.thread.start()
except:
self.messageDialog("转换失败")
def draw_structs(self, df):
try:
columnname = list(df)[0:-2]
self.dataStructsTable.setColumnCount(len(columnname))
self.dataStructsTable.setRowCount(min(10, len(df)))
self.dataStructsTable.setEditTriggers(QAbstractItemView.NoEditTriggers)
self.dataStructsTable.setHorizontalHeaderLabels(columnname)
for i in range(min(10, len(df))):
data = list(df.loc[i].values)
for j in range(len(columnname)):
self.dataStructsTable.setItem(i, j, QTableWidgetItem(str(data[j] if data[j] is not None else '')))
self.dataStructsTable.show()
self.loading_mask.deleteLater()
except:
self.messageDialog("转换失败")
def draw_image(self):
try:
self.loading_mask.deleteLater()
img = cv2.imread("geometry.png") # 读取图像
#img = cv2.cvtColor(img, cv2.COLOR_BGR2RGB) # 转换图像通道
x = img.shape[1] # 获取图像大小
y = img.shape[0]
self.zoomscale = 1 # 图片放缩尺度
frame = QImage(img, x, y, QImage.Format_RGB888)
pix = QPixmap.fromImage(frame)
self.item = QGraphicsPixmapItem(pix) # 创建像素图元
self.scene = QGraphicsScene() # 创建场景
self.scene.addItem(self.item)
self.graphicsView.setScene(self.scene)
except:
self.messageDialog("转换失败")
def on_zoomin_clicked(self):
"""
点击缩小图像
"""
# TODO: not implemented yet
try:
if hasattr(self, 'zoomscale'):
self.zoomscale = self.zoomscale - 0.05
if self.zoomscale <= 0:
self.zoomscale = 0.2
self.item.setScale(self.zoomscale) # 缩小图像
except:
self.messageDialog("缩放失败")
def on_zoomout_clicked(self):
"""
点击方法图像
"""
# TODO: not implemented yet
try:
if hasattr(self, 'zoomscale'):
self.zoomscale = self.zoomscale + 0.05
if self.zoomscale >= 1.2:
self.zoomscale = 1.2
self.item.setScale(self.zoomscale) # 放大图像
except:
self.messageDialog("缩放失败")
def get_data_excel(self):
try:
shp_file = self.ex_shapeFile.text()
prj_file = self.ex_prjShape.text()
save_folder = self.ex_geojsonSaveFile.text()
column_map = self.ex_columnConvertMap.toPlainText()
cov_ll = self.checkBox_6.checkState()
# cov_muiliti = self.checkBox_7.checkState()
if shp_file is None or shp_file == '':
self.messageDialog("shape文件没有选择")
return
if cov_ll == 2 and (prj_file is None or prj_file == ''):
self.messageDialog("prj文件没有选择")
return
if save_folder is None or save_folder == '':
self.messageDialog("文件保存地址没有选择")
return
self.loading_mask = LoadingMask(MainWindow, tip='正在转换...', gif=get_resource_path('./loading.gif'))
MainWindow.installEventFilter(self.loading_mask)
self.loading_mask.show()
self.loading_mask.moveWithParent()
# 创建线程
if column_map is None or len(column_map) <= 0:
column_map = '1233'
self.thread = ConvertExcel(shp_file, prj_file, save_folder, json.loads(column_map), cov_ll)
# 连接信号
self.thread._signal.connect(self.messageDialog) # 进程连接回传到GUI的事件
# 开始线程
self.thread.start()
except:
self.messageDialog("转换失败")
def draw_structs(self, df):
try:
columnname = list(df)[0:-2]
self.dataStructsTable.setColumnCount(len(columnname))
self.dataStructsTable.setRowCount(min(10, len(df)))
self.dataStructsTable.setEditTriggers(QAbstractItemView.NoEditTriggers)
self.dataStructsTable.setHorizontalHeaderLabels(columnname)
for i in range(min(10, len(df))):
data = list(df.loc[i].values)
for j in range(len(columnname)):
self.dataStructsTable.setItem(i, j, QTableWidgetItem(str(data[j] if data[j] is not None else '')))
self.dataStructsTable.show()
self.loading_mask.deleteLater()
except:
self.messageDialog("转换失败")
def get_resource_path(relative_path):
if getattr(sys, 'frozen', False) and hasattr(sys, '_MEIPASS'):
return os.path.join(sys._MEIPASS, relative_path)
return os.path.join(os.path.abspath("."), relative_path)
# 继承QThread
class ReadShapeStructs(QThread): # 线程1
# 通过类成员对象定义信号对象
_signal = pyqtSignal(GeoDataFrame)
def __init__(self, file: str, column_name_map: dict):
super().__init__()
self.file = file
self.column_name_map = column_name_map
def run(self):
qmut_1.lock() # 加锁
df2 = read_file(self.file, encoding="gbk")
if self.column_name_map is not None:
df2 = df2.rename(columns=self.column_name_map)
self._signal.emit(df2)
qmut_1.unlock() # 解锁#
# 继承QThread
class ReadShapeImage(QThread): # 线程1
# 通过类成员对象定义信号对象
_signal = pyqtSignal(GeoDataFrame)
def __init__(self, file: str, column_name_map: dict):
super().__init__()
self.file = file
self.column_name_map = column_name_map
def run(self):
qmut_1.lock() # 加锁
df2 = read_file(self.file, encoding="gbk")
df2.plot(color='red')
pyplot.savefig('geometry.png', dpi=1000)
self._signal.emit(df2)
qmut_1.unlock() # 解锁
# 继承QThread
class ConvertGeojson(QThread): # 线程1
# 通过类成员对象定义信号对象
_signal = pyqtSignal(str)
def __init__(self, shp: str, prj: str, save_folder: str, column_name_map: dict, cov_ll: int):
super().__init__()
self.shp = shp
self.prj = prj
self.save_folder = save_folder
self.cov_ll = cov_ll
self.column_name_map = column_name_map
def run(self):
qmut_1.lock() # 加锁
if self.cov_ll == 2:
crs = self.read_crs_from_prj_file(self.prj)
data = read_file(self.shp, encoding="gbk")
data.to_crs(crs=crs)
df = data.to_crs(crs="+proj=longlat +ellps=WGS84 +datum=WGS84 +no_defs")
else:
df = read_file(self.shp, encoding="gbk")
if self.column_name_map is not None and type(self.column_name_map) == dict:
df = df.rename(columns=self.column_name_map)
outpoint_f = 'geometry.json'
df.to_file(self.save_folder + '/' + outpoint_f, driver='GeoJSON', encoding='utf-8')
self._signal.emit('GeoJson文件生成成功,文件地址:' + self.save_folder + '/' + outpoint_f)
qmut_1.unlock() # 解锁
def read_crs_from_prj_file(self, prjfile: str):
"""
读取prj文件,获取坐标
:param prjfile: prj文件地址
:return: prj文件内容
"""
f = open(prjfile, "r")
result = f.read().encode("utf-8")
f.close()
return str(result, encoding='utf-8')
class Figure_Bar(FigureCanvasQTAgg):
def __init__(self, width, height, parent=None):
self.fig = pyplot.figure(figsize=(width, height), facecolor='#666666', dpi=100, edgecolor='#0000FF')
FigureCanvasQTAgg.__init__(self, self.fig)
self.setParent(parent)
self.myAxes = self.fig.add_subplot(111)
self.x = [0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9]
def ShowImage(self, axisX, axisY):
# 由于图片需要反复绘制,所以每次绘制前清空,然后绘图,最后刷新显示。
self.myAxes.clear()
self.myAxes.bar(self.x, axisY, width=0.02, color='blue', align='center', tick_label=axisX)
# 刷新画布,否则不刷新显示
self.fig.canvas.draw()
def ShowImage1(self, df):
# 由于图片需要反复绘制,所以每次绘制前清空,然后绘图,最后刷新显示。
self.myAxes.clear()
self.myAxes.plot(df)
df.plot(color='red')
# 刷新画布,否则不刷新显示
self.fig.canvas.draw(pyplot.show())
# 继承QThread
class ConvertExcel(QThread): # 线程1
# 通过类成员对象定义信号对象
_signal = pyqtSignal(str)
def __init__(self, shp: str, prj: str, save_folder: str, column_name_map: dict, cov_ll: int):
super().__init__()
self.shp = shp
self.prj = prj
self.save_folder = save_folder
self.cov_ll = cov_ll
self.column_name_map = column_name_map
def run(self):
qmut_1.lock() # 加锁
if self.cov_ll == 2:
crs = self.read_crs_from_prj_file(self.prj)
data = read_file(self.shp, encoding="gbk")
data.to_crs(crs=crs)
df = data.to_crs(crs="+proj=longlat +ellps=WGS84 +datum=WGS84 +no_defs")
else:
df = read_file(self.shp, encoding="gbk")
if self.column_name_map is not None and type(self.column_name_map) == dict:
df = df.rename(columns=self.column_name_map)
columnname = list(df)
df.to_excel(self.save_folder + '/' + 'geometry.xlsx', index=None, header=columnname)
self._signal.emit('excel文件生成成功,文件地址:' + self.save_folder + '/' + 'geometry.xlsx')
qmut_1.unlock() # 解锁
def read_crs_from_prj_file(self, prjfile: str):
"""
读取prj文件,获取坐标
:param prjfile: prj文件地址
:return: prj文件内容
"""
f = open(prjfile, "r")
result = f.read().encode("utf-8")
f.close()
return str(result, encoding='utf-8')
# 继承QThread
class ConvertSQL(QThread): # 线程1
# 通过类成员对象定义信号对象
_signal = pyqtSignal(str)
def __init__(self, shp: str, prj: str, save_folder: str, column_name_map: dict, cov_ll: int, cov_muiliti: int, sql_coord_name: str, sql_coord_text_name: str,sql_table_name:str):
super().__init__()
self.shp = shp
self.prj = prj
self.save_folder = save_folder
self.cov_ll = cov_ll
self.cov_muiliti = cov_muiliti
self.column_name_map = column_name_map
self.sql_coord_name = sql_coord_name
self.sql_coord_text_name = sql_coord_text_name
self.sql_table_name = sql_table_name
def run(self):
qmut_1.lock() # 加锁
if self.cov_ll == 2:
crs = self.read_crs_from_prj_file(self.prj)
data = read_file(self.shp, encoding="gbk")
data.to_crs(crs=crs)
df = data.to_crs(crs="+proj=longlat +ellps=WGS84 +datum=WGS84 +no_defs")
else:
df = read_file(self.shp, encoding="gbk")
if self.column_name_map is not None and type(self.column_name_map) == dict:
df = df.rename(columns=self.column_name_map)
outpoint_f = 'geometry.json'
df.to_file(self.save_folder + '/' + outpoint_f, driver='GeoJSON', encoding='utf-8')
with open(self.save_folder + '/' + outpoint_f, 'r', encoding='utf8')as fp:
json_data = json.load(fp)
datass = json_data['features']
values_list = []
for a in datass:
b = a
value = b['properties']
columns_list = []
for x in value:
columns_list.append(x)
values = {}
for key in columns_list:
vv = value.get(key)
if vv is None:
vv = ''
values[key] = vv
value2 = b['geometry']
corrd = str(value2['coordinates'][0])
if self.sql_coord_text_name is not None and self.sql_coord_text_name != '':
values[self.sql_coord_text_name] = corrd
if self.sql_coord_name is not None and self.sql_coord_name != '':
wkt = convert.geojson_to_wkt(value2)
if self.cov_muiliti == 2 and wkt.startswith("POLYGON"):
wkt = wkt.replace("POLYGON", "MULTIPOLYGON (")
wkt = wkt + ")"
values[self.sql_coord_name] = wkt
values_list.append(values)
sql_list = []
for data in values_list:
keys = []
values = []
for dd in data:
keys.append('`' + dd + '`')
if dd == self.sql_coord_name:
values.append("ST_GeomFromText('" + str(data[dd]) + "')")
else:
values.append("'" + str(data[dd]) + "'")
sql_list.append("insert into {}({}) values ({})".format(self.sql_table_name, ','.join(keys), ','.join(values)))
with open(self.save_folder + '/geometry.sql', "w+", encoding='utf-8') as f:
f.write(";\n".join(sql_list))
self._signal.emit('sql文件生成成功,文件地址:' + self.save_folder + '/geometry.sql')
qmut_1.unlock() # 解锁
def read_crs_from_prj_file(self, prjfile: str):
"""
读取prj文件,获取坐标
:param prjfile: prj文件地址
:return: prj文件内容
"""
f = open(prjfile, "r")
result = f.read().encode("utf-8")
f.close()
return str(result, encoding='utf-8')
class LoadingMask(QMainWindow):
def __init__(self, parent, gif=None, tip=None):
super(LoadingMask, self).__init__(parent)
parent.installEventFilter(self)
self.label = QLabel()
if not tip is None:
self.label.setText(tip)
font = QFont('Microsoft YaHei', 10, QFont.Normal)
font_metrics = QFontMetrics(font)
self.label.setFont(font)
self.label.setFixedSize(font_metrics.width(tip, len(tip)) + 10, font_metrics.height() + 5)
self.label.setAlignment(Qt.AlignCenter)
self.label.setStyleSheet(
'QLabel{background-color: rgba(0,0,0,70%);border-radius: 4px; color: white; padding: 5px;}')
if not gif is None:
self.movie = QMovie(gif)
self.label.setMovie(self.movie)
self.label.setFixedSize(QSize(160, 160))
self.label.setScaledContents(True)
self.movie.start()
layout = QHBoxLayout()
widget = QWidget()
widget.setFixedSize(800, 600)
widget.setLayout(layout)
layout.addWidget(self.label)
self.setCentralWidget(widget)
self.setWindowOpacity(0.8)
self.setWindowFlags(Qt.FramelessWindowHint | Qt.Dialog)
self.hide()
def eventFilter(self, widget, event):
if widget == self.parent() and type(event) == QMoveEvent:
self.moveWithParent()
return True
return super(LoadingMask, self).eventFilter(widget, event)
def moveWithParent(self):
if self.isVisible():
self.move(self.parent().geometry().x(), self.parent().geometry().y())
self.setFixedSize(QSize(self.parent().geometry().width(), self.parent().geometry().height()))
if __name__ == '__main__':
app = QApplication(sys.argv)
MainWindow = QMainWindow()
ui = Ui_MainWindow()
ui.setupUi(MainWindow)
MainWindow.show()
sys.exit(app.exec_())
