Files
AI-Writie-Assistant/server/parsers/gis_parser.py
T
2026-04-16 10:01:11 +08:00

77 lines
2.9 KiB
Python

"""GIS parser — Shapefile, GeoJSON, KML via geopandas."""
import os
import json
import geopandas as gpd
def parse_gis(file_path: str) -> dict:
ext = os.path.splitext(file_path)[1].lower()
try:
if ext == ".geojson" or ext == ".json":
gdf = gpd.read_file(file_path, driver="GeoJSON")
elif ext == ".shp":
gdf = gpd.read_file(file_path)
elif ext == ".kml":
gpd.io.file.fiona.drvsupport.supported_drivers["KML"] = "r"
gdf = gpd.read_file(file_path, driver="KML")
elif ext == ".gpkg":
gdf = gpd.read_file(file_path)
else:
return {"markdown": "", "error": f"不支持的 GIS 格式: {ext}"}
except Exception as e:
return {"markdown": "", "error": f"GIS 文件解析失败: {e}"}
parts = ["## GIS 数据解析结果\n"]
parts.append(f"**文件**: {os.path.basename(file_path)}")
parts.append(f"**要素数量**: {len(gdf)}")
parts.append(f"**坐标系**: {gdf.crs or '未定义'}\n")
# Geometry types
geom_types = gdf.geometry.geom_type.value_counts()
if not geom_types.empty:
parts.append("### 几何类型\n\n| 类型 | 数量 |\n| --- | --- |")
for gt, cnt in geom_types.items():
parts.append(f"| {gt} | {cnt} |")
parts.append("")
# Bounds
bounds = gdf.total_bounds # [minx, miny, maxx, maxy]
parts.append(f"### 范围\n\n- 最小经度: {bounds[0]:.6f}\n- 最小纬度: {bounds[1]:.6f}\n- 最大经度: {bounds[2]:.6f}\n- 最大纬度: {bounds[3]:.6f}\n")
# Attributes
non_geom_cols = [c for c in gdf.columns if c != "geometry"]
if non_geom_cols:
parts.append("### 属性字段\n\n| 字段名 | 类型 | 示例值 |\n| --- | --- | --- |")
for col in non_geom_cols:
dtype = str(gdf[col].dtype)
sample = str(gdf[col].iloc[0]) if len(gdf) > 0 else ""
if len(sample) > 80:
sample = sample[:80] + "..."
parts.append(f"| {col} | {dtype} | {sample} |")
parts.append("")
# First N features as table
n_preview = min(20, len(gdf))
if n_preview > 0 and non_geom_cols:
parts.append(f"### 前 {n_preview} 条要素属性\n")
header = "| " + " | ".join(non_geom_cols) + " |"
sep = "| " + " | ".join("---" for _ in non_geom_cols) + " |"
parts.append(header)
parts.append(sep)
for _, row in gdf.head(n_preview).iterrows():
vals = []
for c in non_geom_cols:
v = str(row[c]) if row[c] is not None else ""
if len(v) > 60:
v = v[:60] + "..."
vals.append(v)
parts.append("| " + " | ".join(vals) + " |")
if len(gdf) > n_preview:
parts.append(f"\n> 共 {len(gdf)} 条要素,仅显示前 {n_preview} 条。")
parts.append("")
return {"markdown": "\n".join(parts)}