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

10 KiB
Raw Permalink Blame History

Irrigation Coding Tool

基于 GeoPandas + Shapely 的灌区空间编码工具,用于对农场数据中的水路、闸门、田块进行批量编号,并输出新的 shpgeojson 结果。

当前主程序入口为 src/main.py

1. 功能概述

本工具主要处理三类空间数据:

  • 点文件:设备点,包含泵、闸门、排水口等。
  • 线文件:水路,包含主渠、支渠,以及排水渠。
  • 面文件:田块。

处理完成后,工具会输出:

  • 编码后的水路结果
  • 编码后的闸门/泵/排水口点结果
  • 编码后的田块结果
  • 对应的 GeoJSON 结果
  • 运行日志

2. 当前代码结构

2.1 主入口

主要职责:

  • 批量扫描农场目录
  • 调用水路编码
  • 调用闸门编码
  • 调用田块编码
  • 合并点位结果
  • 输出 shp / geojson
  • 提供 tkinter 运行窗口与日志输出

2.2 水路编码

主要职责:

  • 识别泵点
  • 保留已有合法泵编码,缺失时自动补码
  • 对非排水渠进行主渠/支渠编号
  • 对排水渠单独续编
  • 输出 codetypefeed_by

2.3 闸门编码

主要职责:

  • 从点文件中筛选闸门
  • 匹配闸门所属水路
  • 按 DFS 规则生成闸门编号
  • 自动补全闸门 类型/type
  • 输出详细匹配与排序日志

3. 输入数据要求

3.1 文件组织方式

程序按“批处理”方式运行。默认会扫描工具同级目录下的多个农场文件夹。

每个农场文件夹中需要至少有以下三类 shp

  • 点文件:文件名包含 节制闸
  • 面文件:文件名包含 田块
  • 线文件:文件名包含 水路

示意结构:

某个总目录/
├─ 农场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

当前点位识别规则:

  • 泵:由水路编码模块筛选
  • 闸门:类型进水闸 / 进排水闸 / 节制闸,或 typeinlet-G / inout-G / main-G / branch-G
  • 排水口:类型排水口,或 typedrain-G

3.4 水路文件字段要求

水路文件建议至少具备能区分排水渠的字段:

  • ch_type
  • 渠型

当前排水渠判定规则:

  • ch_type == "drain-S"
  • 渠型 == "排水渠"

3.5 田块文件字段要求

田块需具备有效面几何。字段没有强制固定要求,但输出时会新增 codedis_rank

4. 编码规则说明

4.1 泵编码规则

泵点编码由 src/segment_code.py 处理。

规则如下:

  • 如果泵已有 code,且文本中包含 P,则认为该编码有效,直接保留。
  • 如果没有合法 code,则自动编号为 P1P2P3...
  • 泵排序优先按 P 后的数字排序。
  • 如果去掉 P 后无法转成数字,则回退到整体文本排序。

示例:

  • P1
  • P2
  • P10

如果存在非标准值,例如:

  • P-A
  • Pump3

则会按兜底文本排序。

4.2 水路编码规则

非排水渠

非排水渠先进行主渠/支渠编号。

规则如下:

  • 先依据泵点识别主渠
  • 主渠编码为 S1S2S3...
  • 支渠编码也使用 Sx
  • type 字段写入:
    • main-S
    • branch-S
  • feed_by 表示该水路由哪条上级水路供给

当前逻辑不是“父渠先抢子渠”,而是先为候选子渠构建更合理的父子关系,再生成编码,可减少相邻水路误匹配。

排水渠

排水渠单独处理,编号接续在非排水渠之后。

规则如下:

  • code 继续沿用 Sx
  • 编号从非排水渠最后一个 S 号往后接
  • 排序按起点坐标:
    • 先纬度从大到小,即北到南
    • 再经度从大到小,即东到西
  • 排水渠不参与主支关系计算
  • 排水渠的:
    • type = ""
    • feed_by = ""
    • dis_rank = 空

4.3 闸门编码规则

闸门编码由 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 中的 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 目录后运行:

python main.py

程序会弹出黑底日志窗口,并在运行目录附近生成结果目录和日志文件。

6.2 运行窗口说明

当前窗口会输出:

  • 输入路径信息
  • 水路处理统计
  • 闸门匹配明细
  • 闸门 DFS 排序明细
  • 闸门编号生成过程
  • 单个农场汇总
  • 批处理最终汇总

最终汇总至少包含:

  • 成功数量
  • 失败数量
  • 泵站检测/完成数
  • 水路检测/完成数
  • 闸门检测/完成数
  • 总耗时

7. 打包说明

7.1 最简单的打包方式

如果你只想从 src 目录直接把 main.py 打包:

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 说明

当前环境如果出现以下警告:

GDAL_DATA is not defined
Cannot find header.dxf

这通常不是业务代码错误,而是 GDAL 没找到自己的数据目录。

典型需要设置的环境变量:

  • GDAL_DATA
  • PROJ_LIB

示例:

$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 的电脑上做一次实测
  • 若后续进一步提高稳定性,建议把距离匹配逐步切换到米制投影坐标系下处理