TXT / Excel(CSV) / SHP 三种格式任意互转
支持 WGS84 / CGCS2000 / Xian80 / Beijing54 / Web Mercator 坐标系转换
由 Mapo 🗺️ 自动生成
58 lines
1.9 KiB
Python
58 lines
1.9 KiB
Python
"""
|
|
Data model — unified internal representation for all coordinate data.
|
|
"""
|
|
from dataclasses import dataclass, field
|
|
from typing import Any
|
|
|
|
|
|
@dataclass
|
|
class CoordPoint:
|
|
x: float
|
|
y: float
|
|
z: float | None = None
|
|
attrs: dict[str, Any] = field(default_factory=dict)
|
|
|
|
|
|
@dataclass
|
|
class CoordData:
|
|
"""Unified container for all coordinate data regardless of source format."""
|
|
points: list[CoordPoint] = field(default_factory=list)
|
|
crs: str | None = None # e.g. "EPSG:4326"
|
|
columns: list[str] = field(default_factory=list) # all column names
|
|
geometry_type: str = "Point" # Point / LineString / Polygon
|
|
extra_meta: dict[str, Any] = field(default_factory=dict)
|
|
|
|
@property
|
|
def count(self) -> int:
|
|
return len(self.points)
|
|
|
|
def to_records(self) -> list[dict[str, Any]]:
|
|
"""Convert to list of flat dicts for DataFrame/Excel export."""
|
|
records = []
|
|
for pt in self.points:
|
|
row = dict(pt.attrs)
|
|
# Always put X, Y (and Z) at front
|
|
row["X"] = pt.x
|
|
row["Y"] = pt.y
|
|
if pt.z is not None:
|
|
row["Z"] = pt.z
|
|
records.append(row)
|
|
return records
|
|
|
|
@classmethod
|
|
def from_records(cls, records: list[dict], crs: str | None = None,
|
|
x_col: str = "X", y_col: str = "Y", z_col: str | None = "Z",
|
|
geometry_type: str = "Point") -> "CoordData":
|
|
points = []
|
|
for rec in records:
|
|
pt = CoordPoint(
|
|
x=float(rec[x_col]),
|
|
y=float(rec[y_col]),
|
|
z=float(rec[z_col]) if z_col and z_col in rec else None,
|
|
attrs={k: v for k, v in rec.items()
|
|
if k not in (x_col, y_col, z_col)},
|
|
)
|
|
points.append(pt)
|
|
cols = list(records[0].keys()) if records else []
|
|
return cls(points=points, crs=crs, columns=cols, geometry_type=geometry_type)
|