# Irrigation Coding Tool 基于 `GeoPandas + Shapely` 的灌区空间编码工具,用于对农场数据中的水路、闸门、田块进行批量编号,并输出新的 `shp` 与 `geojson` 结果。 当前主程序入口为 [src/main.py](/d:/Desktop/yuelu0402/src/main.py)。 ## 1. 功能概述 本工具主要处理三类空间数据: - 点文件:设备点,包含泵、闸门、排水口等。 - 线文件:水路,包含主渠、支渠,以及排水渠。 - 面文件:田块。 处理完成后,工具会输出: - 编码后的水路结果 - 编码后的闸门/泵/排水口点结果 - 编码后的田块结果 - 对应的 `GeoJSON` 结果 - 运行日志 ## 2. 当前代码结构 ### 2.1 主入口 - [src/main.py](/d:/Desktop/yuelu0402/src/main.py) 主要职责: - 批量扫描农场目录 - 调用水路编码 - 调用闸门编码 - 调用田块编码 - 合并点位结果 - 输出 `shp` / `geojson` - 提供 `tkinter` 运行窗口与日志输出 ### 2.2 水路编码 - [src/segment_code.py](/d:/Desktop/yuelu0402/src/segment_code.py) 主要职责: - 识别泵点 - 保留已有合法泵编码,缺失时自动补码 - 对非排水渠进行主渠/支渠编号 - 对排水渠单独续编 - 输出 `code`、`type`、`feed_by` ### 2.3 闸门编码 - [src/gate_code.py](/d:/Desktop/yuelu0402/src/gate_code.py) 主要职责: - 从点文件中筛选闸门 - 匹配闸门所属水路 - 按 DFS 规则生成闸门编号 - 自动补全闸门 `类型/type` - 输出详细匹配与排序日志 ## 3. 输入数据要求 ### 3.1 文件组织方式 程序按“批处理”方式运行。默认会扫描工具同级目录下的多个农场文件夹。 每个农场文件夹中需要至少有以下三类 `shp`: - 点文件:文件名包含 `节制闸` - 面文件:文件名包含 `田块` - 线文件:文件名包含 `水路` 示意结构: ```text 某个总目录/ ├─ 农场A/ │ ├─ xxx节制闸.shp │ ├─ xxx田块.shp │ └─ xxx水路.shp ├─ 农场B/ │ ├─ xxx节制闸.shp │ ├─ xxx田块.shp │ └─ xxx水路.shp └─ src/ ├─ main.py ├─ segment_code.py └─ gate_code.py ``` ### 3.2 坐标系 当前代码直接在经纬度坐标下处理,默认你的数据为 `WGS84` 或与之兼容的度单位坐标系。 当前阈值: - 水路父子关系判定容差:`0.00005` - 闸门匹配渠道容差:`0.00010` 近似理解: - `0.00005` 度约等于 5 米 - `0.00010` 度约等于 10 米 这只是近似值,东西方向实际距离会受纬度影响。 ### 3.3 点文件字段要求 点文件建议至少包含以下字段之一: - `类型` - `type` 当前点位识别规则: - 泵:由水路编码模块筛选 - 闸门:`类型` 为 `进水闸 / 进排水闸 / 节制闸`,或 `type` 为 `inlet-G / inout-G / main-G / branch-G` - 排水口:`类型` 为 `排水口`,或 `type` 为 `drain-G` ### 3.4 水路文件字段要求 水路文件建议至少具备能区分排水渠的字段: - `ch_type` - 或 `渠型` 当前排水渠判定规则: - `ch_type == "drain-S"` - 或 `渠型 == "排水渠"` ### 3.5 田块文件字段要求 田块需具备有效面几何。字段没有强制固定要求,但输出时会新增 `code`、`dis_rank`。 ## 4. 编码规则说明 ### 4.1 泵编码规则 泵点编码由 [src/segment_code.py](/d:/Desktop/yuelu0402/src/segment_code.py) 处理。 规则如下: - 如果泵已有 `code`,且文本中包含 `P`,则认为该编码有效,直接保留。 - 如果没有合法 `code`,则自动编号为 `P1`、`P2`、`P3`... - 泵排序优先按 `P` 后的数字排序。 - 如果去掉 `P` 后无法转成数字,则回退到整体文本排序。 示例: - `P1` - `P2` - `P10` 如果存在非标准值,例如: - `P-A` - `Pump3` 则会按兜底文本排序。 ### 4.2 水路编码规则 #### 非排水渠 非排水渠先进行主渠/支渠编号。 规则如下: - 先依据泵点识别主渠 - 主渠编码为 `S1`、`S2`、`S3`... - 支渠编码也使用 `Sx` - `type` 字段写入: - `main-S` - `branch-S` - `feed_by` 表示该水路由哪条上级水路供给 当前逻辑不是“父渠先抢子渠”,而是先为候选子渠构建更合理的父子关系,再生成编码,可减少相邻水路误匹配。 #### 排水渠 排水渠单独处理,编号接续在非排水渠之后。 规则如下: - `code` 继续沿用 `Sx` - 编号从非排水渠最后一个 `S` 号往后接 - 排序按起点坐标: - 先纬度从大到小,即北到南 - 再经度从大到小,即东到西 - 排水渠不参与主支关系计算 - 排水渠的: - `type = ""` - `feed_by = ""` - `dis_rank = 空` ### 4.3 闸门编码规则 闸门编码由 [src/gate_code.py](/d:/Desktop/yuelu0402/src/gate_code.py) 处理。 规则如下: 1. 从点文件中筛出闸门。 2. 将闸门匹配到最近的非排水渠,即 `main-S / branch-S`。 3. 计算闸门在所属水路上的投影位置 `along_dist`。 4. 按 DFS 规则排序: - 当前渠上的闸门与下级支渠入口一起比较 - 按沿渠位置从后往前排序 - 遇到支渠入口时递归进入支渠 5. 按全局顺序赋编号: - `S1-G1` - `S1-G2` - `S2-G3` 当前版本已修正一个关键问题: - 闸门在线上的顺序计算改为精确投影 `line.project(point)` - 不再使用分段 `buffer` 推断所在段 - 这能避免闸门靠近分叉点时顺序被算反 #### 闸门类型补全 闸门最终会补全中英文类型: - `进水闸` -> `inlet-G` - `进排水闸` -> `inout-G` - `节制闸` -> 根据所属水路补成: - `main-G` - `branch-G` ### 4.4 田块编码规则 田块编码由 [src/main.py](/d:/Desktop/yuelu0402/src/main.py) 中的 `assign_field_code()` 处理。 规则如下: - 田块优先与非节制闸关联 - 从闸门编码中继承前缀 - 再追加田块序号 示例: - `S1-G3-F1` - `S2-G8-F12` 田块结果还会生成 `dis_rank`。 ## 5. 输出结果说明 ### 5.1 输出目录 批处理运行后,会在基础目录下生成: - `result_时间戳/` - `result_时间戳_geojson/` - `log_时间戳.txt` ### 5.2 输出文件 每个农场会生成: - 编码后的水路 `shp` - 编码后的点位 `shp` - 编码后的田块 `shp` - 对应 `geojson` ### 5.3 字段保留规则 #### 水路结果 - 原始字段大部分保留 - 会写入或覆盖: - `code` - `type` - `feed_by` - `dis_rank` #### 点位结果 点位结果不是原点文件直接复制,而是重新合并得到: - 闸门 - 泵 - 排水口 当前版本已尽量保留各类点位的非核心原始字段,合并时按字段并集输出,缺失字段填空。 #### 田块结果 - 原始字段大部分保留 - 会写入或覆盖: - `code` - `dis_rank` ## 6. 运行方式 ### 6.1 直接运行源码 进入 `src` 目录后运行: ```powershell python main.py ``` 程序会弹出黑底日志窗口,并在运行目录附近生成结果目录和日志文件。 ### 6.2 运行窗口说明 当前窗口会输出: - 输入路径信息 - 水路处理统计 - 闸门匹配明细 - 闸门 DFS 排序明细 - 闸门编号生成过程 - 单个农场汇总 - 批处理最终汇总 最终汇总至少包含: - 成功数量 - 失败数量 - 泵站检测/完成数 - 水路检测/完成数 - 闸门检测/完成数 - 总耗时 ## 7. 打包说明 ### 7.1 最简单的打包方式 如果你只想从 `src` 目录直接把 `main.py` 打包: ```powershell cd D:\Desktop\yuelu0402\src python -m PyInstaller --noconfirm --clean --onedir --windowed --name IrrigationTool_v1.4 main.py ``` 输出目录: - `src\dist\IrrigationTool_v1.4\` 可执行文件: - `src\dist\IrrigationTool_v1.4\IrrigationTool_v1.4.exe` ### 7.2 给没有 Python 的用户使用 如果采用 `--onedir` 打包: - 不能只发单独一个 `.exe` - 必须把整个 `IrrigationTool_v1.4` 文件夹一起发给对方 对方使用方式: 1. 解压整个目录 2. 双击 `IrrigationTool_v1.4.exe` 3. 将待处理农场文件夹与工具目录按要求摆放 ### 7.3 关于 `--onefile` 本项目依赖: - `geopandas` - `pyogrio` - `pyproj` - `GDAL` 这类 GIS 依赖在 `--onefile` 模式下较容易出现动态库、数据文件或运行时定位问题。除非有充分测试,否则更建议使用 `--onedir`。 ## 8. 环境依赖 建议环境: - Python 3.9 - geopandas - shapely - pandas - pyogrio - pyproj - tkinter - pyinstaller ## 9. GDAL / PROJ 说明 当前环境如果出现以下警告: ```text GDAL_DATA is not defined Cannot find header.dxf ``` 这通常不是业务代码错误,而是 `GDAL` 没找到自己的数据目录。 典型需要设置的环境变量: - `GDAL_DATA` - `PROJ_LIB` 示例: ```powershell $env:GDAL_DATA="F:\miniforge3\envs\geo_python\Library\share\gdal" $env:PROJ_LIB="F:\miniforge3\envs\geo_python\Library\share\proj" python main.py ``` 如果不涉及复杂坐标转换或特殊格式,当前很多情况下只是警告,不一定影响 `shp/geojson` 主流程。 ## 10. 已完成的关键修正 当前版本已完成以下修正: - 保留已有合法泵编码,不再强制重排 - 泵排序优先按 `P` 后数字排序,失败后回退文本排序 - 支持排水渠识别与单独续编 - 排水渠不参与 `type/feed_by/dis_rank` 主逻辑 - 水路判定容差收紧到约 5 米 - 闸门匹配水路容差收紧到约 10 米 - 闸门排序位置改为精确投影,修复分叉点附近顺序反转问题 - 点位结果保留更多原始非核心字段 - 运行窗口补回闸门详细信息 - 运行窗口补回最终汇总信息 ## 11. 已知限制 - 当前主要按经纬度坐标直接计算距离,属于近似处理 - 不同纬度下,东西方向距离换算并不完全一致 - 输入文件命名依赖关键字匹配 - 输入字段命名若与当前约定差异较大,需要额外适配 - `GDAL_DATA / PROJ_LIB` 未正确设置时,可能出现警告 ## 12. 建议 - 正式批量生产前,先用 1 个农场做完整验证 - 打包后,最好在一台未安装 Python 的电脑上做一次实测 - 若后续进一步提高稳定性,建议把距离匹配逐步切换到米制投影坐标系下处理