77 lines
2.9 KiB
Python
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)}
|