Skip to main content

ymgis

面向桌面 GIS 小工具的轻量组件库:画布 + 图层管理 + 图层树 + 基础绘制 + 在线地图服务预览 + 动态重投影。

不依赖 QGIS。基于 PyQt6 + rasterio + Shapely + pyproj,可发布到 PyPI,供 QuickAnno、下载器、质检工具等复用。

能力概览

能力 说明
地图画布 平移、滚轮锚定缩放(鼠标下点不动)、可配置背景色(默认白色)
动态重投影 可叠加不同坐标系数据;视图 CRS 由第一个带 CRS 的图层决定
本地栅格 GeoTIFF(rasterio)按视口窗口读取;跨 CRS 时 WarpedVRT 重投影
图片预览 PNG / JPG / BMP / WebP / GIF(ImageLayer,像素坐标,无地理参考)
矢量标注 内存 Shapely 点/线/面 + 简单样式;渲染时按需重投影
图层树 勾选显隐;展开图例(矢量样式;栅格为 ArcMap 拉伸高/中/低或 RGB 波段;底图符号)
添加数据 ArcGIS / YMDesktop 风格浏览对话框;可选「数据源」或「图层」,图层支持单选/多选;GDB/MDB/PostGIS
绘制工具 平移 / 点 / 线 / 矩形 / 多边形(线、面双击结束,双击点为终点/顶点)
切片底图 通用 XYZ/TMS;预设天地图、高德、百度、谷歌
OGC WMS GetMap 视口图像预览
ArcGIS REST MapServer / ImageServer export;亦可 XYZ tile/{z}/{y}/{x}
超图 iServer 地图 image.png 视口预览;亦可 zxyTileImage 瓦片

在线服务图层自身为 EPSG:3857,叠到其它视图 CRS 时会动态重投影(AABB 近似)。高德/百度存在国内加密坐标偏移,适合底图预览,不宜与精密测绘数据直接叠合量测。

安装

# 开发态(本仓库)
pip install -e .

# 发布后
pip install ymgis

快速开始

from PyQt6.QtWidgets import QApplication, QMainWindow, QSplitter
from ymgis import MapCanvas, RasterLayer, VectorLayer, LayerTreeWidget, PanTool, DrawPolygonTool

app = QApplication([])
win = QMainWindow()
canvas = MapCanvas()
tree = LayerTreeWidget(canvas.layer_manager)

# 第一个带 CRS 的图层决定视图坐标系(无需手动 set_crs)
raster = RasterLayer(r"D:\data\demo.tif")
canvas.layer_manager.add_layer(raster)
canvas.zoom_to_full_extent()

# 普通图片预览(无地理参考,像素坐标):
# from ymgis import ImageLayer
# canvas.layer_manager.add_layer(ImageLayer(r"D:\data\photo.jpg"))
# canvas.zoom_to_full_extent()

# 标注层自动继承视图 CRS;绘制坐标为画布 CRS
annos = VectorLayer("标注")
canvas.layer_manager.add_layer(annos)

tool = DrawPolygonTool()
tool.polygon_drawn.connect(
    lambda g: annos.add_feature(g, {"class": "demo"}, source_crs=canvas.crs)
)
canvas.set_map_tool(tool)

split = QSplitter()
split.addWidget(tree)
split.addWidget(canvas)
win.setCentralWidget(split)
win.resize(1200, 800)
win.show()
app.exec()

多坐标系叠加

from ymgis import MapCanvas, RasterLayer, VectorLayer, create_amap
from shapely.geometry import Point

canvas = MapCanvas()

# 先加载 CGCS2000 / 任意投影影像 → 视图 CRS = 该影像 CRS
canvas.layer_manager.add_layer(RasterLayer(r"D:\data\cgcs2000.tif"))

# 再叠加 WGS84 矢量 → 渲染时自动重投影到视图 CRS
pts = VectorLayer("点", crs="EPSG:4326")
pts.add_feature(Point(116.4, 39.9))
canvas.layer_manager.add_layer(pts)

# 在线底图(EPSG:3857)也会重投影到当前视图
canvas.layer_manager.add_layer(create_amap(), to_top=False)

canvas.zoom_to_full_extent()

添加数据(数据源 / 图层)

from ymgis import AddDataMode, browse_add_data

# 只选数据源(文件夹 / GDB / MDB / PostGIS),不进入图层
src = browse_add_data(mode=AddDataMode.SOURCE, multiselect=False)

# 选图层:可双击进入 GDB/MDB,支持多选
layers = browse_add_data(mode=AddDataMode.LAYER, multiselect=True)
if layers:
    for item in layers.items:
        print(item.kind, item.path, item.layer_name)

在线底图 / 地图服务预览

from ymgis import (
    MapCanvas,
    create_amap,
    create_baidu,
    create_google,
    create_tianditu,
    WmsLayer,
    ArcGisRestLayer,
    SuperMapRestLayer,
)

canvas = MapCanvas()

canvas.layer_manager.add_layer(create_amap(), to_top=False)
# canvas.layer_manager.add_layer(create_baidu(), to_top=False)
# canvas.layer_manager.add_layer(create_google(), to_top=False)
# canvas.layer_manager.add_layer(create_tianditu("你的天地图tk"), to_top=False)

# WMS / ArcGIS / 超图
# canvas.layer_manager.add_layer(WmsLayer("https://host/wms", "workspace:layer"))
# canvas.layer_manager.add_layer(
#     ArcGisRestLayer("https://host/arcgis/rest/services/Demo/MapServer")
# )
# canvas.layer_manager.add_layer(
#     SuperMapRestLayer("http://host:8090/iserver/services/map-demo/rest/maps/Demo")
# )

canvas.zoom_to_full_extent()

自定义 XYZ:

from ymgis import XyzTileLayer

layer = XyzTileLayer(
    "https://tile.example.com/{z}/{x}/{y}.png",
    name="自定义瓦片",
    subdomains=["a", "b", "c"],  # 对应模板 {s}
)

运行示例:

pip install -e .
python examples/basic_viewer.py
# 可选传入 GeoTIFF:
python examples/basic_viewer.py D:\data\demo.tif

# 在线底图 / WMS / ArcGIS / 超图预览:
python examples/online_basemap.py
# 天地图也可:set TIANDITU_TOKEN=你的tk

模块

模块 说明
MapCanvas 地图画布;首层定 CRS、动态重投影渲染
LayerManager 图层栈;combined_extent(target_crs)
RasterLayer GeoTIFF 窗口读取 + WarpedVRT 重投影
ImageLayer 本地图片预览(PNG/JPG/BMP/WebP/GIF)
VectorLayer 内存 Shapely 要素;可指定 crs=
ymgis.crs transform_xy / transform_extent / transform_geometry
XyzTileLayer 通用 XYZ/TMS 异步瓦片底图
BaiduTileLayer / create_* 百度及天地图/高德/谷歌预设
WmsLayer OGC WMS GetMap 视口预览
ArcGisRestLayer ArcGIS REST export 预览
SuperMapRestLayer 超图 iServer 地图预览
LayerTreeWidget 图层树 + 图例(show_legend=True)
AddDataDialog / browse_add_data 添加数据;AddDataMode.SOURCE / LAYER + 单选/多选
ymgis.data GisDataItem / list_layers 等数据源类型与枚举
LegendItem / LegendSymbol 图例条目与符号类型
PanTool / DrawPointTool / DrawLineTool / DrawRectTool / DrawPolygonTool 交互工具

设计约定

  • 视图 CRS:由第一个加载且带有 CRS 的图层自动设定;canvas.set_crs(...) 可显式指定并锁定。
  • 动态重投影:后续图层 CRS 不同时,在渲染/combined_extent 时转换到视图 CRS(依赖 pyproj;栅格用 WarpedVRT)。
  • 无 CRS 的图层(如空标注层)加入后自动继承当前视图 CRS;绘制工具产出的几何为画布 CRS。
  • 图层树默认展开图例:矢量按点/线/面样式,栅格显示缩略图,在线底图/服务显示通用符号;LayerTreeWidget(show_legend=False) 可关闭。
  • 在线切片/WMS 图层原生多为 EPSG:3857;瓦片异步加载并带内存缓存。
  • 栅格按视口读取并缩放到控件尺寸,避免整图进内存。

与 QGIS / GeoD 的关系

  • 不是 QGIS 替代品:无工程文件、无复杂符号、无拓扑规则。
  • 可预览常见在线底图与 OGC/REST 地图服务,但不是 GeoD 那种批量网图下载器。
  • 目标:多个内部小工具共用同一套画布/图层树,安装包体积远小于捆绑 qgis_runtime。

发布到 PyPI

包名:ymgis(见 PyPI)。版本号只改一处:src/ymgis/__about__.py 中的 __version__(pyproject.toml 通过 hatch 动态读取,无需再改)。

1. 准备 API Token

  1. 登录 PyPI → Account settings → API tokens
  2. 新建 token(建议 scope 限定到项目 ymgis)
  3. 复制以 pypi- 开头的完整 token(不是 Recovery Codes)

本地保存(勿提交仓库):

copy scripts\publish.local.ps1.example scripts\publish.local.ps1
# 编辑 publish.local.ps1:
#   $PyPiToken = 'pypi-你的完整token'

scripts/publish.local.ps1 已在 .gitignore 中。

2. 升高版本并发布(推荐)

# 1) 编辑版本,例如:
#    src/ymgis/__about__.py  →  __version__ = "0.1.13"

# 2) 一键构建 + 上传
.\scripts\publish.ps1

# 其它用法:
# .\scripts\publish.ps1 -Token "pypi-你的完整token"   # 不写本地文件时临时传入
# .\scripts\publish.ps1 -SkipBuild                    # 仅上传已有 dist/
# .\scripts\publish.ps1 -TestPyPI                     # 上传到 TestPyPI

脚本会设置 TWINE_USERNAME=__token__、TWINE_PASSWORD=...,执行 python -m build 与 twine upload,结束后清理进程内的敏感环境变量。

3. 手动发布(可选)

pip install -e ".[dev]"
# 先改 __about__.py 版本
python -m build
# 交互上传时:Username 填 __token__ ,Password 填 pypi-...
twine upload dist/*

或使用环境变量:

$env:TWINE_USERNAME = "__token__"
$env:TWINE_PASSWORD = "pypi-你的完整token"
twine upload dist/*

4. 安装验证

# 官方源(发布后立即可用)
pip install -U ymgis==0.1.13 -i https://pypi.org/simple

# 国内镜像(如清华)可能延迟同步,找不到新版本时改用官方源,或稍后再试
pip install -U ymgis -i https://pypi.tuna.tsinghua.edu.cn/simple

5. 常见问题

现象 原因 / 处理
400 Bad Request(邮箱) 作者邮箱须合法;勿使用 .local 等无效域名
400 Bad Request(版本) 该版本已上传过,升高 __version__ 后重发
403 Forbidden token 无效、过期或无该项目上传权限
镜像找不到新版本 镜像未同步;用 -i https://pypi.org/simple 安装
终端粘贴 token「没反应」 密码输入不回显,粘贴后直接回车即可

注意: 不要把 API token、Recovery Codes 提交进 git;同一版本号在 PyPI 上不可覆盖,只能发新版本。

目录

ymgis/
├── pyproject.toml
├── README.md
├── LICENSE
├── examples/
│   ├── basic_viewer.py
│   └── online_basemap.py
├── src/ymgis/
│   ├── crs.py          # 动态重投影
│   ├── canvas/
│   ├── layers/
│   │   └── services/   # XYZ / WMS / ArcGIS / 超图 / 厂商预设
│   ├── tools/
│   └── widgets/
└── tests/

License

MIT

Metadata

Release files for ymgis 0.1.12

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for ymgis 0.1.12
File Size Uploaded
ymgis-0.1.12.tar.gz 50.2 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for ymgis 0.1.12
File Interpreter ABI Platform
ymgis-0.1.12-py3-none-any.whl Python 3 none any Details

Total release size: 114.4 kB

Release files / ymgis-0.1.12.tar.gz

Download URL ymgis-0.1.12.tar.gz
Size 50.2 kB
Tags Source
SHA-256 checksum
How to use checksums
88630fc53ce5a297ca2dce67ff9da15ae73dcba8cd6dbed1f728ed2da233126d
BLAKE2b-256 checksum
How to use checksums
764fa506c230193dea374dd84bbac89f890480c4940a657f61ce363ede9d1437
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/7.0.0 CPython/3.14.0

Release files / ymgis-0.1.12-py3-none-any.whl

Download URL ymgis-0.1.12-py3-none-any.whl
Size 64.3 kB
Tags Python 3
SHA-256 checksum
How to use checksums
69fe9c1111f4d3d528254b8e9887a3b09fa69474e8e0597bfea24d4e030920b5
BLAKE2b-256 checksum
How to use checksums
5b439a821757a67617ef16b3baf3f6cc0757253b3e74eb3bd61cfbb37bc6d886
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/7.0.0 CPython/3.14.0

Release history Release notifications | RSS feed

This release

0.1.12 This release

2 release files

0.1.11

2 release files

0.1.10

2 release files

0.1.8

2 release files

0.1.7

2 release files

0.1.6

2 release files

0.1.5

2 release files

0.1.4

2 release files

0.1.3

2 release files

0.1.2

2 release files

0.1.1

2 release files

0.1.0

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page