shp文件转换为CAD文件 (改进版)
shp文件转换为CAD文件 (改进版)
ytkz上个月写了一个工具是关于shp文件转换为CAD文件,
后面被吐槽说这个工具的大小为390M。
我承认,这个是“小工具”一点也不小!
那是什么原因造成的呢?
其实这个python打包的通病问题,python作为胶水语言,可以快速开发。想要打包成二进制文件交给其他人使用,这个二进制文件一般是巨大无比的。
更底层的原因是,在代码中,我们导入了geopandas这个库,geopandas很好用,是因为它引用了非常多的第三方库,所以使用pyinstaller打包的时候,往往会把这些“无用”的第三方库也打包进去我们的项目里面。
同样是这个程序,我曾打包后的文件大小是3G多,我看了一下 ,好家伙啊,它把torch-cuda依赖也打包进去了!
针对这个shp文件转换为CAD文件小工具,我们可以改进它,主要做法是,不导入geopandas,即不使用geopandas!
经过网上冲浪查资料,我发现有个纯python包叫做ezdxf,这ezdxf可以对dxf文件读写,很符合这个小工具的要求。
我有了个大体的思路,使用ogr读取矢量文件的数据。ogr是啥?ogr就是osgeo里面的子库,ogr和gdal同一个级别,区别在于gdal读写栅格数据,ogr读写矢量数据。
好了,现在的程序处理步骤如下:
1.使用ogr读取矢量文件,获取点位数据。
2.使用ezdxf将点位数据保存为dxf文件。
好了好了,现在就差代码还需要写了。
import os
import ezdxf
from osgeo import ogr
class Shp2Dxf:
def __init__(self, in_file):
self.in_file = in_file
self.out_file = os.path.splitext(in_file)[0] + '.dxf'
def read_shp_by_ogr(self):
ds = ogr.Open(self.in_file)
shape = ds.GetLayer()
attribute_names = []
ldefn = shape.GetLayerDefn()
geom_list = []
for i in range(shape.GetFeatureCount()):
feature = shape.GetFeature(i)
geom = feature.GetGeometryRef()
geom_list.append(geom.ExportToWkt()) # 将几何信息保存为WKT格式
return geom_list
def shp2dxf(self) -> None:
# 读取Shapefile中的几何信息
geom_list = self.read_shp_by_ogr()
# 创建一个新的DXF文件
doc = ezdxf.new(dxfversion='R2010')
msp = doc.modelspace() # 获取模型空间
# 将几何信息转换为DXF实体并添加到DXF文件中
for geom_wkt in geom_list:
geom = ogr.CreateGeometryFromWkt(geom_wkt)
geom_type = geom.GetGeometryType()
if geom_type == ogr.wkbPoint: # 点类型
x, y = geom.GetX(), geom.GetY()
msp.add_point((x, y))
elif geom_type == ogr.wkbLineString: # 线类型
points = geom.GetPoints()
msp.add_lwpolyline(points)
elif geom_type == ogr.wkbPolygon: # 多边形类型
ring = geom.GetGeometryRef(0) # 获取多边形的外环
points = ring.GetPoints()
# 创建Hatch对象
hatch = msp.add_hatch(color=7) # 设置填充颜色,默认颜色为7(白色或黑色,取决于背景)
# 添加路径
path = hatch.paths.add_polyline_path(points, is_closed=True)
# 保存DXF文件
doc.saveas(self.out_file)
print(f"Successfully converted {self.in_file} to {self.out_file}")
def readdxf(self, file):
doc = ezdxf.readfile(file)
msp = doc.modelspace()
for entity in msp:
print(entity)
for layer in doc.layers:
print(layer.dxf.name)
print()
if __name__ == '__main__':
# in_file = r'd://temp/create_shp_by_fiona.shp'
in_file = input("输入shp文件路径:")
try:
converter = Shp2Dxf(in_file)
converter.shp2dxf()
# converter.readdxf(converter.out_file)
# converter.shp2dxf()
except Exception as e:
print(e)
input("已完成")
这段代码定义了一个名为Shp2Dxf
的类,该类用于将Shapefile (.shp) 文件转换为AutoCAD的Drawing Interchange Format (.dxf) 文件。
代码逐行解释
下面是对代码每一部分的逐行解释:
import os
: 导入os模块,用于处理文件路径和其他操作系统交互功能。import ezdxf
: 导入ezdxf库,用于创建和读取DXF文件。from osgeo import ogr
: 导入GDAL库中的ogr模块,用于读取GIS数据,如Shapefile。class Shp2Dxf:
: 定义一个名为Shp2Dxf的类。def __init__(self, in_file):
: 初始化方法,接收一个参数in_file
表示输入的Shapefile路径。self.in_file = in_file
: 将输入文件路径存储为类实例的一个属性。self.out_file = os.path.splitext(in_file)[0] + '.dxf'
: 根据输入文件路径创建输出文件名,扩展名改为.dxf
。def read_shp_by_ogr(self):
: 定义一个方法来通过ogr读取Shapefile。ds = ogr.Open(self.in_file)
: 打开输入的Shapefile文件。shape = ds.GetLayer()
: 获取文件的第一个图层。attribute_names = []
: 初始化一个空列表,用于存储属性名称。ldefn = shape.GetLayerDefn()
: 获取图层定义。geom_list = []
: 初始化一个空列表,用于存储几何对象。for i in range(shape.GetFeatureCount()):
: 遍历图层中的所有要素。feature = shape.GetFeature(i)
: 获取当前索引i的要素。geom = feature.GetGeometryRef()
: 获取要素的几何对象。geom_list.append(geom.ExportToWkt())
: 将几何对象以WKT格式添加到列表中。return geom_list
: 返回包含所有要素几何信息的列表。def shp2dxf(self) -> None:
: 定义一个方法将Shapefile转换为DXF文件。geom_list = self.read_shp_by_ogr()
: 调用方法获取Shapefile的几何信息。doc = ezdxf.new(dxfversion='R2010')
: 创建一个新的DXF文档,版本为R2010。msp = doc.modelspace()
: 获取文档的模型空间。for geom_wkt in geom_list:
: 遍历从Shapefile获取的所有几何信息。geom = ogr.CreateGeometryFromWkt(geom_wkt)
: 从WKT字符串创建几何对象。geom_type = geom.GetGeometryType()
: 获取几何对象的类型。if geom_type == ogr.wkbPoint:
: 如果几何对象是点类型。x, y = geom.GetX(), geom.GetY()
: 获取点的坐标。msp.add_point((x, y))
: 在模型空间中添加一个点。elif geom_type == ogr.wkbLineString:
: 如果几何对象是线类型。points = geom.GetPoints()
: 获取线的坐标点集合。msp.add_lwpolyline(points)
: 在模型空间中添加一个轻量级多段线。elif geom_type == ogr.wkbPolygon:
: 如果几何对象是多边形类型。ring = geom.GetGeometryRef(0)
: 获取多边形的外环。points = ring.GetPoints()
: 获取多边形外环的坐标点集合。hatch = msp.add_hatch(color=7)
: 在模型空间中添加带有填充的边界。path = hatch.paths.add_polyline_path(points, is_closed=True)
: 为边界添加闭合的多段线路径。doc.saveas(self.out_file)
: 保存DXF文件。print(f"Successfully converted {self.in_file} to {self.out_file}")
: 输出转换成功的信息。def readdxf(self, file):
: 定义一个方法用于读取DXF文件。doc = ezdxf.readfile(file)
: 读取DXF文件。msp = doc.modelspace()
: 获取模型空间。for entity in msp:
: 遍历模型空间中的所有实体。print(entity)
: 输出实体信息。for layer in doc.layers:
: 遍历文档中的所有图层。print(layer.dxf.name)
: 输出图层名称。print()
: 输出一个换行。if __name__ == '__main__':
: 当脚本作为主程序运行时执行以下代码。in_file = input("输入shp文件路径:")
: 请求用户输入Shapefile路径。try:
: 尝试执行以下代码块。converter = Shp2Dxf(in_file)
: 创建Shp2Dxf类的实例。converter.shp2dxf()
: 转换Shapefile为DXF。# converter.readdxf(converter.out_file)
: 注释掉的代码,用于读取生成的DXF文件。except Exception as e:
: 捕获异常。print(e)
: 输出异常信息。input("已完成")
: 输出“已完成”并等待用户按键继续。
打包程序
至此,我们完成了shp文件转换为CAD文件。