Files
2026-08-07 18:03:39 +00:00

441 lines
10 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 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 的电脑上做一次实测
- 若后续进一步提高稳定性,建议把距离匹配逐步切换到米制投影坐标系下处理