第13章:序列化与反序列化(WKT/WKB/GeoJSON)
几何体的序列化与反序列化是 GIS 数据交换的基础。无论是存储到数据库、通过网络传输,还是在不同系统间共享数据,都需要将内存中的几何对象转换为标准格式。Shapely 支持 WKT(Well-Known Text)、WKB(Well-Known Binary)、GeoJSON 以及 Pickle 等多种序列化格式,本章将全面介绍这些格式的使用方法、参数选项和性能特点。
WKT(Well-Known Text)
WKT 格式概述
WKT 是 OGC(开放地理空间联盟)定义的文本格式,可读性好,常用于调试和数据展示。
from shapely import Point, LineString, Polygon
# 各种几何类型的 WKT 表示
print(Point(1, 2).wkt)
# POINT (1 2)
print(Point(1, 2, 3).wkt)
# POINT Z (1 2 3)
print(LineString([(0, 0), (1, 1), (2, 0)]).wkt)
# LINESTRING (0 0, 1 1, 2 0)
print(Polygon([(0, 0), (1, 0), (1, 1), (0, 1)]).wkt)
# POLYGON ((0 0, 1 0, 1 1, 0 1, 0 0))
to_wkt 函数
from shapely import to_wkt, Point, LineString, Polygon
# 基本用法
point = Point(1.123456789, 2.987654321)
print(to_wkt(point))
# POINT (1.123456789 2.987654321)
# rounding_precision:控制小数位数
print(to_wkt(point, rounding_precision=3))
# POINT (1.123 2.988)
print(to_wkt(point, rounding_precision=0))
# POINT (1 3)
# trim:去除尾部多余的零
print(to_wkt(Point(1.0, 2.0), rounding_precision=6, trim=True))
# POINT (1 2)
print(to_wkt(Point(1.0, 2.0), rounding_precision=6, trim=False))
# POINT (1.000000 2.000000)
output_dimension 参数
from shapely import to_wkt, Point
# 3D 点
point_3d = Point(1, 2, 3)
# 输出 3D
print(to_wkt(point_3d, output_dimension=3))
# POINT Z (1 2 3)
# 强制输出 2D(丢弃 Z 坐标)
print(to_wkt(point_3d, output_dimension=2))
# POINT (1 2)
from_wkt 函数
from shapely import from_wkt
# 基本解析
point = from_wkt("POINT (1 2)")
print(f"类型: {point.geom_type}, 坐标: ({point.x}, {point.y})")
line = from_wkt("LINESTRING (0 0, 1 1, 2 0)")
print(f"类型: {line.geom_type}, 顶点数: {len(line.coords)}")
polygon = from_wkt("POLYGON ((0 0, 10 0, 10 10, 0 10, 0 0))")
print(f"类型: {polygon.geom_type}, 面积: {polygon.area}")
# 解析 3D 几何
point_3d = from_wkt("POINT Z (1 2 3)")
print(f"Z 坐标: {point_3d.z}")
on_invalid 参数
from shapely import from_wkt
import warnings
# 有效的 WKT
valid = from_wkt("POINT (1 2)")
print(f"有效: {valid}")
# 无效的 WKT 字符串
# on_invalid='raise'(默认)- 抛出异常
try:
from_wkt("INVALID WKT STRING", on_invalid='raise')
except Exception as e:
print(f"异常: {type(e).__name__}: {e}")
# on_invalid='warn' - 发出警告,返回 None
with warnings.catch_warnings(record=True) as w:
warnings.simplefilter("always")
result = from_wkt("INVALID WKT STRING", on_invalid='warn')
print(f"警告模式返回: {result}")
if w:
print(f"警告: {w[0].message}")
# on_invalid='ignore' - 静默返回 None
result = from_wkt("INVALID WKT STRING", on_invalid='ignore')
print(f"忽略模式返回: {result}")
.wkt 属性快捷方式
from shapely import (
Point, LineString, Polygon,
MultiPoint, MultiLineString, MultiPolygon,
GeometryCollection
)
# 所有几何类型的 WKT 表示
geometries = [
Point(0, 0),
LineString([(0, 0), (1, 1)]),
Polygon([(0, 0), (1, 0), (1, 1), (0, 1)]),
MultiPoint([(0, 0), (1, 1)]),
MultiLineString([[(0, 0), (1, 0)], [(1, 1), (2, 2)]]),
MultiPolygon([
([(0, 0), (1, 0), (1, 1), (0, 1)], []),
([(2, 2), (3, 2), (3, 3), (2, 3)], [])
]),
GeometryCollection([Point(0, 0), LineString([(1, 1), (2, 2)])]),
]
for geom in geometries:
print(f"{geom.geom_type:25s}: {geom.wkt}")
批量处理 WKT
from shapely import to_wkt, from_wkt
import numpy as np
# 批量序列化
from shapely import Point
points = np.array([Point(i, i*2) for i in range(5)])
wkt_array = to_wkt(points)
print(f"批量序列化结果类型: {type(wkt_array)}")
for w in wkt_array:
print(f" {w}")
# 批量反序列化
wkt_strings = np.array([
"POINT (0 0)",
"POINT (1 2)",
"POINT (3 4)",
])
geoms = from_wkt(wkt_strings)
print(f"\n批量反序列化:")
for g in geoms:
print(f" {g}")
WKB(Well-Known Binary)
WKB 格式概述
WKB 是几何体的二进制表示格式,体积小、解析快,适合存储和网络传输。
from shapely import Point
point = Point(1, 2)
# WKB 二进制
wkb_bytes = point.wkb
print(f"WKB 字节: {wkb_bytes}")
print(f"WKB 长度: {len(wkb_bytes)} 字节")
# WKB 十六进制
wkb_hex = point.wkb_hex
print(f"WKB Hex: {wkb_hex}")
to_wkb 函数
from shapely import to_wkb, Point, Polygon
point = Point(1.5, 2.5)
# 默认 WKB(小端序、二进制)
wkb = to_wkb(point)
print(f"默认 WKB: {wkb.hex()}")
# 十六进制输出
wkb_hex = to_wkb(point, hex=True)
print(f"Hex WKB: {wkb_hex}")
# 字节序控制
# byte_order=0: 大端序(Big-Endian / XDR)
# byte_order=1: 小端序(Little-Endian / NDR)
wkb_be = to_wkb(point, byte_order=0)
wkb_le = to_wkb(point, byte_order=1)
print(f"大端序第1字节: {wkb_be[0]:02x}") # 00
print(f"小端序第1字节: {wkb_le[0]:02x}") # 01
output_dimension 参数
from shapely import to_wkb, Point
point_3d = Point(1, 2, 3)
# 3D WKB
wkb_3d = to_wkb(point_3d, output_dimension=3, hex=True)
print(f"3D WKB: {wkb_3d}")
# 强制 2D
wkb_2d = to_wkb(point_3d, output_dimension=2, hex=True)
print(f"2D WKB: {wkb_2d}")
print(f"3D 长度: {len(wkb_3d)} 字符")
print(f"2D 长度: {len(wkb_2d)} 字符")
SRID 嵌入
from shapely import to_wkb, from_wkb, Point
from shapely import geos_version
point = Point(116.4, 39.9)
# 嵌入 SRID(Extended WKB / EWKB)
ewkb = to_wkb(point, include_srid=True, hex=True)
print(f"带 SRID 的 WKB: {ewkb}")
# 注意:Shapely 本身不跟踪 SRID
# 但可以通过 EWKB 与 PostGIS 等数据库交互
from_wkb 函数
from shapely import from_wkb, to_wkb, Point, Polygon
# 从二进制 WKB 还原
point = Point(3.14, 2.72)
wkb = to_wkb(point)
restored = from_wkb(wkb)
print(f"还原: {restored}")
print(f"坐标: ({restored.x}, {restored.y})")
# 从十六进制 WKB 还原
wkb_hex = to_wkb(point, hex=True)
restored_hex = from_wkb(wkb_hex)
print(f"从 Hex 还原: {restored_hex}")
# on_invalid 参数同样适用
result = from_wkb(b'\x00\x00', on_invalid='ignore')
print(f"无效 WKB: {result}") # None
.wkb_hex 属性
from shapely import Point, LineString, Polygon
# 各种类型的 WKB Hex
geoms = [
Point(1, 2),
LineString([(0, 0), (1, 1)]),
Polygon([(0, 0), (1, 0), (1, 1), (0, 0)]),
]
for geom in geoms:
hex_str = geom.wkb_hex
print(f"{geom.geom_type:15s}: {hex_str[:40]}... ({len(hex_str)} 字符)")
批量 WKB 操作
from shapely import to_wkb, from_wkb, Point
import numpy as np
# 批量序列化
points = np.array([Point(i, i*2) for i in range(5)])
wkb_array = to_wkb(points)
print(f"批量 WKB 类型: {type(wkb_array)}")
# 批量反序列化
restored = from_wkb(wkb_array)
for r in restored:
print(f" {r}")
# 十六进制批量
hex_array = to_wkb(points, hex=True)
for h in hex_array:
print(f" {h}")
GeoJSON
GeoJSON 格式概述
GeoJSON 是基于 JSON 的地理数据格式,广泛用于 Web GIS 应用。
from shapely import Point
from shapely.geometry import mapping, shape
import json
point = Point(116.4, 39.9)
# 使用 mapping() 转换为 dict
geojson_dict = mapping(point)
print(json.dumps(geojson_dict, indent=2))
# {
# "type": "Point",
# "coordinates": [116.4, 39.9]
# }
to_geojson 函数
from shapely import to_geojson, Point, LineString, Polygon
# 基本转换
point = Point(116.4, 39.9)
geojson_str = to_geojson(point)
print(f"GeoJSON: {geojson_str}")
# 带缩进的格式化输出
line = LineString([(0, 0), (1, 1), (2, 0)])
formatted = to_geojson(line, indent=2)
print(f"格式化 GeoJSON:\n{formatted}")
# 多边形
polygon = Polygon([(0, 0), (1, 0), (1, 1), (0, 1)])
print(to_geojson(polygon, indent=2))
mapping() 函数
from shapely.geometry import mapping
from shapely import (
Point, LineString, Polygon,
MultiPoint, MultiLineString, MultiPolygon
)
# mapping() 返回 Python 字典,符合 GeoJSON 规范
geoms = {
"点": Point(1, 2),
"线": LineString([(0, 0), (1, 1)]),
"面": Polygon([(0, 0), (1, 0), (1, 1), (0, 1)]),
"多点": MultiPoint([(0, 0), (1, 1)]),
"多线": MultiLineString([[(0, 0), (1, 0)], [(1, 1), (2, 2)]]),
}
for name, geom in geoms.items():
d = mapping(geom)
print(f"{name}: type={d['type']}, "
f"coordinates 类型={type(d['coordinates']).__name__}")
shape() 函数
from shapely.geometry import shape, mapping
# 从 GeoJSON dict 创建几何体
geojson_point = {
"type": "Point",
"coordinates": [116.4, 39.9]
}
point = shape(geojson_point)
print(f"Point: {point}")
geojson_polygon = {
"type": "Polygon",
"coordinates": [
[[0, 0], [10, 0], [10, 10], [0, 10], [0, 0]]
]
}
polygon = shape(geojson_polygon)
print(f"Polygon: {polygon}")
print(f"面积: {polygon.area}")
# 带孔洞的多边形
geojson_with_hole = {
"type": "Polygon",
"coordinates": [
[[0, 0], [10, 0], [10, 10], [0, 10], [0, 0]], # 外环
[[2, 2], [2, 8], [8, 8], [8, 2], [2, 2]] # 孔洞
]
}
poly_with_hole = shape(geojson_with_hole)
print(f"带孔洞面积: {poly_with_hole.area}")
geo_interface 协议
from shapely import Point, Polygon
from shapely.geometry import shape
# Shapely 几何体实现了 __geo_interface__ 协议
point = Point(1, 2)
print(f"__geo_interface__: {point.__geo_interface__}")
# {'type': 'Point', 'coordinates': (1.0, 2.0)}
# 任何实现了 __geo_interface__ 的对象都可以用 shape() 转换
class MyGeometry:
@property
def __geo_interface__(self):
return {
'type': 'Point',
'coordinates': (3.0, 4.0)
}
my_geom = MyGeometry()
shapely_geom = shape(my_geom)
print(f"自定义对象转换: {shapely_geom}")
GeoJSON 规范要求
from shapely import Point, Polygon
from shapely.geometry import mapping
import json
# GeoJSON 规范要求使用 WGS84 坐标系 (EPSG:4326)
# 经度在前,纬度在后
beijing = Point(116.4, 39.9) # (经度, 纬度)
geojson = mapping(beijing)
print(json.dumps(geojson))
# {"type": "Point", "coordinates": [116.4, 39.9]}
# 右手规则:外环逆时针,孔洞顺时针
# Shapely 的 Polygon 可能不遵循此规则
# 使用 orient() 可以规范化方向
from shapely.geometry import polygon as poly_module
from shapely import Polygon
exterior = [(0, 0), (0, 10), (10, 10), (10, 0), (0, 0)] # 顺时针
hole = [(2, 2), (8, 2), (8, 8), (2, 8), (2, 2)] # 逆时针
poly = Polygon(exterior, [hole])
oriented = poly_module.orient(poly, sign=1.0) # 确保右手规则
print(f"外环方向修正后: {oriented.wkt[:60]}...")
构造 FeatureCollection
from shapely import Point, Polygon
from shapely.geometry import mapping
import json
# 虽然 Shapely 不直接支持 Feature/FeatureCollection
# 但可以手动构造
features = []
# 添加点要素
for i in range(3):
feature = {
"type": "Feature",
"geometry": mapping(Point(i, i)),
"properties": {
"name": f"Point_{i}",
"value": i * 10
}
}
features.append(feature)
# 构造 FeatureCollection
feature_collection = {
"type": "FeatureCollection",
"features": features
}
print(json.dumps(feature_collection, indent=2))
Pickle 序列化
基本 Pickle 操作
import pickle
from shapely import Point, LineString, Polygon
# 序列化
point = Point(1, 2)
pickled = pickle.dumps(point)
print(f"Pickle 大小: {len(pickled)} 字节")
# 反序列化
restored = pickle.loads(pickled)
print(f"还原: {restored}")
print(f"相等: {point.equals(restored)}")
多种几何体的 Pickle
import pickle
from shapely import Point, LineString, Polygon, MultiPoint
geometries = [
Point(1, 2),
LineString([(0, 0), (1, 1), (2, 0)]),
Polygon([(0, 0), (10, 0), (10, 10), (0, 10)]),
MultiPoint([(0, 0), (1, 1), (2, 2)]),
]
# 序列化整个列表
data = pickle.dumps(geometries)
print(f"列表 Pickle 大小: {len(data)} 字节")
# 反序列化
restored = pickle.loads(data)
for orig, rest in zip(geometries, restored):
print(f"{orig.geom_type}: 相等={orig.equals(rest)}")
在多进程中传递几何体
from shapely import Point, Polygon
import pickle
# 模拟多进程数据传递
# 主进程:创建几何体并序列化
polygon = Polygon([(0, 0), (10, 0), (10, 10), (0, 10)])
serialized = pickle.dumps(polygon)
# 子进程:反序列化并处理
def worker_process(data):
"""模拟子进程的工作函数"""
geom = pickle.loads(data)
area = geom.area
centroid = geom.centroid
return {
'area': area,
'centroid': (centroid.x, centroid.y)
}
result = worker_process(serialized)
print(f"面积: {result['area']}")
print(f"质心: {result['centroid']}")
# 使用 concurrent.futures 的实际示例
from concurrent.futures import ProcessPoolExecutor
def compute_area(wkb):
"""在子进程中计算面积"""
from shapely import from_wkb
geom = from_wkb(wkb)
return geom.area
# 准备数据(使用 WKB 比 Pickle 更通用)
from shapely import to_wkb, box
polygons_wkb = [to_wkb(box(i, i, i+5, i+5)) for i in range(5)]
# 注意:在实际使用中取消下面的注释
# with ProcessPoolExecutor(max_workers=2) as executor:
# areas = list(executor.map(compute_area, polygons_wkb))
# print(f"面积列表: {areas}")
格式化输出
f-string 格式化
from shapely import Point, LineString
point = Point(1.123456789, 2.987654321)
# 控制小数位数(需要 Shapely 2.0+)
# 标准的 .wkt 属性
print(f"默认 WKT: {point.wkt}")
# 使用 to_wkt 控制精度
from shapely import to_wkt
print(f"3位精度: {to_wkt(point, rounding_precision=3)}")
print(f"6位精度: {to_wkt(point, rounding_precision=6)}")
# WKB 十六进制
from shapely import to_wkb
hex_wkb = to_wkb(point, hex=True)
print(f"WKB Hex: {hex_wkb}")
自定义格式化函数
from shapely import Point, LineString, to_wkt
def format_geometry(geom, precision=3, max_length=80):
"""自定义几何体格式化"""
wkt = to_wkt(geom, rounding_precision=precision, trim=True)
if len(wkt) > max_length:
return wkt[:max_length-3] + "..."
return wkt
# 使用
line = LineString([(i*0.1, i*0.2) for i in range(20)])
print(format_geometry(line, precision=2))
print(format_geometry(line, precision=2, max_length=50))
批量序列化与反序列化
处理几何数组
from shapely import (
to_wkt, from_wkt, to_wkb, from_wkb, to_geojson,
Point, LineString, box
)
import numpy as np
# 创建几何数组
geoms = np.array([Point(i, i*2) for i in range(5)])
# 批量转 WKT
wkt_array = to_wkt(geoms, rounding_precision=2)
print("WKT 数组:")
for w in wkt_array:
print(f" {w}")
# 批量转 WKB(十六进制)
wkb_array = to_wkb(geoms, hex=True)
print("\nWKB Hex 数组:")
for w in wkb_array:
print(f" {w}")
# 批量反序列化
restored_from_wkt = from_wkt(wkt_array)
restored_from_wkb = from_wkb(wkb_array)
print("\n从 WKT 还原:")
for g in restored_from_wkt:
print(f" {g}")
处理 None 和无效值
from shapely import to_wkt, from_wkt, Point
import numpy as np
# 包含 None 的数组
geoms = np.array([Point(1, 1), None, Point(3, 3)], dtype=object)
# to_wkt 处理 None
wkt_result = to_wkt(geoms)
print(f"含 None 的 WKT: {wkt_result}")
# from_wkt 处理无效字符串
wkt_strings = np.array([
"POINT (1 1)",
"INVALID",
"POINT (3 3)"
])
result = from_wkt(wkt_strings, on_invalid='ignore')
print(f"含无效值的结果: {result}")
性能比较
WKT vs WKB vs GeoJSON 速度对比
from shapely import (
to_wkt, from_wkt, to_wkb, from_wkb, to_geojson,
Point, Polygon, box
)
from shapely.geometry import mapping, shape
import time
import json
# 创建测试几何体
polygon = Polygon([
(i * 0.1, (i * 0.1) ** 2 % 10)
for i in range(100)
])
n_iterations = 1000
# WKT 序列化/反序列化
start = time.perf_counter()
for _ in range(n_iterations):
wkt = to_wkt(polygon)
wkt_ser_time = time.perf_counter() - start
start = time.perf_counter()
for _ in range(n_iterations):
from_wkt(wkt)
wkt_deser_time = time.perf_counter() - start
# WKB 序列化/反序列化
start = time.perf_counter()
for _ in range(n_iterations):
wkb = to_wkb(polygon)
wkb_ser_time = time.perf_counter() - start
start = time.perf_counter()
for _ in range(n_iterations):
from_wkb(wkb)
wkb_deser_time = time.perf_counter() - start
# GeoJSON 序列化/反序列化
start = time.perf_counter()
for _ in range(n_iterations):
gj = to_geojson(polygon)
gj_ser_time = time.perf_counter() - start
start = time.perf_counter()
for _ in range(n_iterations):
shape(json.loads(gj))
gj_deser_time = time.perf_counter() - start
print(f"{'格式':<12} {'序列化(ms)':<14} {'反序列化(ms)':<14} {'大小(bytes)'}")
print("-" * 55)
print(f"{'WKT':<12} {wkt_ser_time*1000:<14.2f} {wkt_deser_time*1000:<14.2f} {len(wkt)}")
print(f"{'WKB':<12} {wkb_ser_time*1000:<14.2f} {wkb_deser_time*1000:<14.2f} {len(wkb)}")
print(f"{'GeoJSON':<12} {gj_ser_time*1000:<14.2f} {gj_deser_time*1000:<14.2f} {len(gj)}")
大小对比
from shapely import to_wkt, to_wkb, to_geojson, Point, LineString, Polygon
test_cases = [
("简单点", Point(116.123456, 39.654321)),
("简单线", LineString([(i, i*2) for i in range(10)])),
("简单面", Polygon([(i*10, (i*10)**2 % 100) for i in range(20)])),
]
print(f"{'几何类型':<12} {'WKT(字节)':<14} {'WKB(字节)':<14} {'GeoJSON(字节)'}")
print("-" * 55)
for name, geom in test_cases:
wkt_size = len(to_wkt(geom).encode('utf-8'))
wkb_size = len(to_wkb(geom))
gj_size = len(to_geojson(geom).encode('utf-8'))
print(f"{name:<12} {wkt_size:<14} {wkb_size:<14} {gj_size}")
与数据库交互
PostGIS WKB 格式
from shapely import to_wkb, from_wkb, Point
# PostGIS 使用 EWKB(Extended WKB)格式
# 包含 SRID 信息
point = Point(116.4, 39.9)
# 生成 EWKB Hex(适合 PostGIS)
ewkb_hex = to_wkb(point, hex=True, include_srid=True)
print(f"EWKB Hex: {ewkb_hex}")
# 常规 WKB Hex
wkb_hex = to_wkb(point, hex=True)
print(f"WKB Hex: {wkb_hex}")
# 模拟从 PostGIS 读取
# 假设从数据库获得 WKB Hex 字符串
db_wkb_hex = wkb_hex
geom = from_wkb(db_wkb_hex)
print(f"从数据库还原: {geom}")
模拟数据库交互
from shapely import to_wkb, from_wkb, Point, Polygon
import json
# 模拟空间数据的存储与读取
class SpatialDatabase:
"""简单的空间数据存储模拟"""
def __init__(self):
self.records = []
def insert(self, name, geometry):
"""存储几何体(使用 WKB)"""
wkb = to_wkb(geometry, hex=True)
self.records.append({
'name': name,
'geom_wkb': wkb
})
def query_all(self):
"""读取所有记录"""
results = []
for record in self.records:
geom = from_wkb(record['geom_wkb'])
results.append({
'name': record['name'],
'geometry': geom
})
return results
# 使用
db = SpatialDatabase()
db.insert("北京", Point(116.4, 39.9))
db.insert("上海", Point(121.5, 31.2))
db.insert("广州", Point(113.3, 23.1))
# 查询
records = db.query_all()
for r in records:
print(f"{r['name']}: {r['geometry']}")
与 SQLAlchemy/GeoAlchemy2 配合
# 示例:使用 WKB 与 GeoAlchemy2 交互的模式
from shapely import to_wkb, from_wkb, Point
# 写入数据库前
point = Point(116.4, 39.9)
wkb_for_db = to_wkb(point, hex=True)
# SQL 示例(伪代码)
sql_insert = f"""
INSERT INTO locations (name, geom)
VALUES ('北京', ST_GeomFromWKB(decode('{wkb_for_db}', 'hex'), 4326))
"""
print(f"插入 SQL 示例:\n{sql_insert}")
# 从数据库读取后
# 假设 row['geom'] 返回 WKB hex 字符串
mock_db_result = wkb_for_db
restored_point = from_wkb(mock_db_result)
print(f"从 DB 还原: {restored_point}")
格式选择指南
何时使用哪种格式
# 格式选择参考表
format_guide = """
┌──────────┬────────────────┬──────────────┬──────────────┐
│ 格式 │ 适用场景 │ 优点 │ 缺点 │
├──────────┼────────────────┼──────────────┼──────────────┤
│ WKT │ 调试、日志 │ 人类可读 │ 体积大 │
│ │ SQL 查询 │ 易于检查 │ 解析较慢 │
├──────────┼────────────────┼──────────────┼──────────────┤
│ WKB │ 数据库存储 │ 体积小 │ 不可读 │
│ │ 高性能传输 │ 解析最快 │ 需要工具查看 │
├──────────┼────────────────┼──────────────┼──────────────┤
│ GeoJSON │ Web API │ JSON 生态 │ 体积最大 │
│ │ 前端展示 │ 广泛支持 │ 仅 WGS84 │
├──────────┼────────────────┼──────────────┼──────────────┤
│ Pickle │ Python 内部 │ 最快序列化 │ Python 专用 │
│ │ 缓存 │ 支持所有类型 │ 安全风险 │
└──────────┴────────────────┴──────────────┴──────────────┘
"""
print(format_guide)
小结
本章介绍了 Shapely 中几何体序列化与反序列化的完整方案:
- WKT:文本格式,可读性好,适合调试和 SQL 交互
- WKB:二进制格式,体积小速度快,适合存储和高性能场景
- GeoJSON:JSON 格式,Web 应用首选,广泛的生态支持
- Pickle:Python 原生格式,适合内部缓存和多进程
关键选择原则:
- 调试输出:使用 WKT,rounding_precision 控制精度
- 数据库存储:使用 WKB,体积小、解析快
- Web API:使用 GeoJSON,前端友好
- 内部缓存:使用 WKB 或 Pickle
- 批量处理:使用 NumPy 数组 + 向量化函数
掌握这些序列化技术,可以在不同系统和组件之间高效地传递空间数据。