shp文件转换为CAD文件 (改进版)

上个月写了一个工具是关于shp文件转换为CAD文件,

后面被吐槽说这个工具的大小为390M。

1725542574779

我承认,这个是“小工具”一点也不小!

那是什么原因造成的呢?

其实这个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) 文件。

代码逐行解释

下面是对代码每一部分的逐行解释:

  1. import os: 导入os模块,用于处理文件路径和其他操作系统交互功能。
  2. import ezdxf: 导入ezdxf库,用于创建和读取DXF文件。
  3. from osgeo import ogr: 导入GDAL库中的ogr模块,用于读取GIS数据,如Shapefile。
  4. class Shp2Dxf:: 定义一个名为Shp2Dxf的类。
  5. def __init__(self, in_file):: 初始化方法,接收一个参数in_file表示输入的Shapefile路径。
  6. self.in_file = in_file: 将输入文件路径存储为类实例的一个属性。
  7. self.out_file = os.path.splitext(in_file)[0] + '.dxf': 根据输入文件路径创建输出文件名,扩展名改为.dxf
  8. def read_shp_by_ogr(self):: 定义一个方法来通过ogr读取Shapefile。
  9. ds = ogr.Open(self.in_file): 打开输入的Shapefile文件。
  10. shape = ds.GetLayer(): 获取文件的第一个图层。
  11. attribute_names = []: 初始化一个空列表,用于存储属性名称。
  12. ldefn = shape.GetLayerDefn(): 获取图层定义。
  13. geom_list = []: 初始化一个空列表,用于存储几何对象。
  14. for i in range(shape.GetFeatureCount()):: 遍历图层中的所有要素。
  15. feature = shape.GetFeature(i): 获取当前索引i的要素。
  16. geom = feature.GetGeometryRef(): 获取要素的几何对象。
  17. geom_list.append(geom.ExportToWkt()): 将几何对象以WKT格式添加到列表中。
  18. return geom_list: 返回包含所有要素几何信息的列表。
  19. def shp2dxf(self) -> None:: 定义一个方法将Shapefile转换为DXF文件。
  20. geom_list = self.read_shp_by_ogr(): 调用方法获取Shapefile的几何信息。
  21. doc = ezdxf.new(dxfversion='R2010'): 创建一个新的DXF文档,版本为R2010。
  22. msp = doc.modelspace(): 获取文档的模型空间。
  23. for geom_wkt in geom_list:: 遍历从Shapefile获取的所有几何信息。
  24. geom = ogr.CreateGeometryFromWkt(geom_wkt): 从WKT字符串创建几何对象。
  25. geom_type = geom.GetGeometryType(): 获取几何对象的类型。
  26. if geom_type == ogr.wkbPoint:: 如果几何对象是点类型。
  27. x, y = geom.GetX(), geom.GetY(): 获取点的坐标。
  28. msp.add_point((x, y)): 在模型空间中添加一个点。
  29. elif geom_type == ogr.wkbLineString:: 如果几何对象是线类型。
  30. points = geom.GetPoints(): 获取线的坐标点集合。
  31. msp.add_lwpolyline(points): 在模型空间中添加一个轻量级多段线。
  32. elif geom_type == ogr.wkbPolygon:: 如果几何对象是多边形类型。
  33. ring = geom.GetGeometryRef(0): 获取多边形的外环。
  34. points = ring.GetPoints(): 获取多边形外环的坐标点集合。
  35. hatch = msp.add_hatch(color=7): 在模型空间中添加带有填充的边界。
  36. path = hatch.paths.add_polyline_path(points, is_closed=True): 为边界添加闭合的多段线路径。
  37. doc.saveas(self.out_file): 保存DXF文件。
  38. print(f"Successfully converted {self.in_file} to {self.out_file}"): 输出转换成功的信息。
  39. def readdxf(self, file):: 定义一个方法用于读取DXF文件。
  40. doc = ezdxf.readfile(file): 读取DXF文件。
  41. msp = doc.modelspace(): 获取模型空间。
  42. for entity in msp:: 遍历模型空间中的所有实体。
  43. print(entity): 输出实体信息。
  44. for layer in doc.layers:: 遍历文档中的所有图层。
  45. print(layer.dxf.name): 输出图层名称。
  46. print(): 输出一个换行。
  47. if __name__ == '__main__':: 当脚本作为主程序运行时执行以下代码。
  48. in_file = input("输入shp文件路径:"): 请求用户输入Shapefile路径。
  49. try:: 尝试执行以下代码块。
  50. converter = Shp2Dxf(in_file): 创建Shp2Dxf类的实例。
  51. converter.shp2dxf(): 转换Shapefile为DXF。
  52. # converter.readdxf(converter.out_file): 注释掉的代码,用于读取生成的DXF文件。
  53. except Exception as e:: 捕获异常。
  54. print(e): 输出异常信息。
  55. input("已完成"): 输出“已完成”并等待用户按键继续。

打包程序

至此,我们完成了shp文件转换为CAD文件。

猫和老鼠00063-你能点个赞吗.jpg