folium地图坐标转换:WGS84、UTM与地方坐标系转换

folium地图坐标转换:WGS84、UTM与地方坐标系转换

【免费下载链接】folium Python Data. Leaflet.js Maps. 【免费下载链接】folium 项目地址: https://gitcode.com/gh_mirrors/fo/folium

在地理信息可视化工作中,你是否经常遇到这样的困扰:从不同渠道获取的坐标数据无法直接在地图上正确显示?GPS设备记录的经纬度导入后位置偏移,CAD图纸的地方坐标系数据与地图无法对齐?本文将通过folium结合Python生态工具,解决WGS84、UTM与地方坐标系之间的转换难题,让你的地理数据在地图上精准呈现。

坐标系基础:理解WGS84、UTM与地方坐标系

地理坐标系就像不同国家的语言,同一地点在不同坐标系中会有不同的"表达方式"。WGS84(World Geodetic System 1984,世界大地坐标系)是GPS设备的标准语言,以经纬度(度分秒)形式描述地球表面位置;UTM(Universal Transverse Mercator,通用横轴墨卡托投影)则是一种将地球表面分带投影为平面坐标的语言,以米为单位;而地方坐标系(如北京54、西安80)则是特定区域的"方言",通常基于局部基准面。

folium作为基于Leaflet.js的Python地图库,原生支持WGS84坐标系(EPSG:4326)。当我们创建地图时,所有坐标默认采用这种国际通用格式:

import folium
# 创建WGS84坐标系地图(EPSG:4326)
m = folium.Map(location=[39.9042, 116.4074], zoom_start=12)  # 北京WGS84坐标
m.save("wgs84_map.html")

要查看folium对坐标的基础处理逻辑,可以参考folium/utilities.py中的坐标验证函数,其中validate_location方法确保输入的经纬度符合WGS84规范,拒绝包含NaN值或非数值类型的坐标。

核心转换技术:从经纬度到平面坐标

当处理大比例尺地图或需要精确距离计算时,UTM坐标系比WGS84更具优势。folium虽然没有内置坐标转换功能,但可以通过Python生态中的专业库实现无缝衔接。下面是一个完整的WGS84与UTM坐标互转方案:

import folium
from pyproj import Transformer

def wgs84_to_utm(lat, lon):
    """将WGS84经纬度转换为UTM坐标"""
    # 自动检测UTM分带
    zone = int((lon + 180) / 6) + 1
    # 创建转换器 (WGS84 -> UTM)
    transformer = Transformer.from_crs(
        "EPSG:4326",  # WGS84
        f"EPSG:326{zone:02d}" if lat >= 0 else f"EPSG:327{zone:02d}"  # UTM北半球/南半球
    )
    utm_x, utm_y = transformer.transform(lat, lon)
    return utm_x, utm_y, zone

def utm_to_wgs84(utm_x, utm_y, zone, is_northern=True):
    """将UTM坐标转换为WGS84经纬度"""
    crs_code = f"EPSG:326{zone:02d}" if is_northern else f"EPSG:327{zone:02d}"
    transformer = Transformer.from_crs(crs_code, "EPSG:4326")
    lat, lon = transformer.transform(utm_x, utm_y)
    return lat, lon

# 示例转换
wgs84_lat, wgs84_lon = 39.9042, 116.4074  # 北京WGS84坐标
utm_x, utm_y, zone = wgs84_to_utm(wgs84_lat, wgs84_lon)
print(f"UTM坐标: X={utm_x:.2f}m, Y={utm_y:.2f}m, 分带={zone}")

# 转换回WGS84并在folium中显示
recovered_lat, recovered_lon = utm_to_wgs84(utm_x, utm_y, zone)
m = folium.Map(location=[recovered_lat, recovered_lon], zoom_start=15)
folium.Marker([recovered_lat, recovered_lon], 
              popup=f"UTM: {utm_x:.0f}, {utm_y:.0f}").add_to(m)
m.save("utm_conversion_demo.html")

folium的坐标验证机制确保转换后的WGS84坐标有效。在folium/utilities.pyvalidate_location函数中,会检查坐标是否为数值类型、是否包含NaN值,以及是否符合经纬度范围要求。这一步骤在数据可视化前至关重要,可以有效避免因坐标格式错误导致的地图显示异常。

实战案例:地方坐标系与WGS84的衔接

在实际工作中,我们经常会遇到基于地方基准面的坐标数据(如北京54、西安80、CGCS2000)。这些坐标系与WGS84之间的转换需要专业参数,通常通过七参数或四参数模型实现。以下是一个结合pyproj处理地方坐标系的完整工作流:

import folium
from pyproj import CRS, Transformer

def beijing54_to_wgs84(bj54_x, bj54_y, bj54_proj="EPSG:2431"):
    """北京54坐标系转WGS84
    
    注:不同区域的北京54坐标系可能需要不同的EPSG代码或自定义参数
    """
    # 定义北京54坐标系(以3度分带为例,EPSG:2431对应北京54 / 3度带 117E)
    bj54_crs = CRS.from_epsg(bj54_proj)
    wgs84_crs = CRS.from_epsg(4326)
    
    # 创建转换器,这里使用预设的EPSG转换参数
    # 对于无EPSG代码的地方坐标系,需使用proj字符串定义参数
    transformer = Transformer.from_crs(bj54_crs, wgs84_crs)
    lat, lon = transformer.transform(bj54_x, bj54_y)
    return lat, lon

# 示例:北京54坐标转WGS84并可视化
bj54_x, bj54_y = 394661.45, 4427865.32  # 假设的北京54坐标(3度带117E)
wgs84_lat, wgs84_lon = beijing54_to_wgs84(bj54_x, bj54_y)

m = folium.Map(location=[wgs84_lat, wgs84_lon], zoom_start=14)
folium.CircleMarker(
    location=[wgs84_lat, wgs84_lon],
    radius=10,
    color='red',
    fill=True,
    fill_color='red',
    popup=f"北京54坐标: {bj54_x:.2f}, {bj54_y:.2f}"
).add_to(m)
m.save("beijing54_to_wgs84.html")

对于没有标准EPSG代码的地方坐标系,我们需要使用proj字符串手动定义转换参数。例如,使用七参数转换模型:

# 自定义地方坐标系转换(示例参数,实际使用需替换为真实参数)
custom_crs = CRS.from_proj4("""+proj=tmerc +lat_0=39 +lon_0=116 +k=1 +x_0=500000 
                              +y_0=0 +datum=Beijing54 +units=m +no_defs""")
transformer = Transformer.from_crs(custom_crs, CRS.from_epsg(4326))

坐标转换在folium中的高级应用

结合folium的GeoJSON处理能力,我们可以实现批量坐标转换与可视化。以下示例展示如何将UTM坐标系的GIS数据转换为WGS84并在folium地图上显示:

import folium
import json
from pyproj import Transformer
from folium.utilities import validate_locations  # 导入folium坐标验证工具

def transform_geojson_coordinates(geojson_data, src_crs, dest_crs="EPSG:4326"):
    """转换GeoJSON数据中的所有坐标"""
    transformer = Transformer.from_crs(src_crs, dest_crs, always_xy=True)
    
    def transform_coords(coords):
        if isinstance(coords, (list, tuple)) and len(coords) >= 2:
            # 检查是否为坐标点
            if all(isinstance(c, (int, float)) for c in coords[:2]):
                x, y = coords[:2]
                lon, lat = transformer.transform(x, y)
                return [lat, lon] + list(coords[2:])
            # 递归处理嵌套坐标
            return [transform_coords(c) for c in coords]
        return coords
    
    # 深拷贝并转换坐标
    transformed = json.loads(json.dumps(geojson_data))
    for feature in transformed.get("features", []):
        feature["geometry"]["coordinates"] = transform_coords(
            feature["geometry"]["coordinates"]
        )
    return transformed

# 加载UTM坐标系的GeoJSON数据(示例)
with open("examples/data/utm_data.geojson") as f:
    utm_geojson = json.load(f)

# 转换为WGS84坐标系
wgs84_geojson = transform_geojson_coordinates(utm_geojson, "EPSG:32650")  # UTM 50N

# 在folium中显示转换后的数据
m = folium.Map(location=[39.9, 116.4], zoom_start=10)
folium.GeoJson(
    wgs84_geojson,
    name="转换后的GeoJSON数据",
    style_function=lambda x: {"color": "blue", "weight": 2}
).add_to(m)
folium.LayerControl().add_to(m)
m.save("transformed_geojson_demo.html")

在处理大量坐标数据时,folium的folium/utilities.py提供了validate_locationsvalidate_multi_locations函数,可批量验证坐标有效性,确保转换后的数据符合folium的要求。这些工具函数在folium/vector_layers.pyfolium/raster_layers.py中被广泛用于验证输入坐标。

常见问题与解决方案

坐标偏移问题

如果转换后的坐标在地图上出现系统性偏移,可能是以下原因导致:

  1. UTM分带错误:确保使用了正确的UTM分带号,中国区域大致位于UTM 43N至53N之间
  2. 基准面差异:北京54/西安80与WGS84存在基准面差异,需要七参数转换
  3. 投影参数错误:自定义坐标系时检查中央经线、缩放因子等参数

解决方案示例:使用七参数精确转换地方坐标系

# 使用七参数转换模型(需要实际测量的参数)
custom_crs = CRS.from_proj4("""+proj=tmerc +lat_0=0 +lon_0=117 +k=1 +x_0=500000 
                              +y_0=0 +datum=WGS84 +units=m +no_defs 
                              +towgs84=dx,dy,dz,ex,ey,ez,ppm""")  # 替换为实际七参数

批量数据处理

当处理大型数据集时,建议使用pandas结合pyproj进行矢量化转换:

import pandas as pd
import pyproj

def batch_convert_utm_to_wgs84(df, zone, is_northern=True):
    """批量转换DataFrame中的UTM坐标为WGS84"""
    crs_code = f"EPSG:326{zone:02d}" if is_northern else f"EPSG:327{zone:02d}"
    transformer = pyproj.Transformer.from_crs(crs_code, "EPSG:4326", always_xy=True)
    
    # 矢量化转换(比循环快10-100倍)
    lons, lats = transformer.transform(df['utm_x'].values, df['utm_y'].values)
    df['lat'] = lats
    df['lon'] = lons
    return df

# 示例:处理CSV数据
df = pd.read_csv("examples/data/large_utm_data.csv")
df = batch_convert_utm_to_wgs84(df, zone=50)  # UTM 50N

# 验证坐标并创建folium地图
valid_locations = folium.utilities.validate_locations(df[['lat', 'lon']].values.tolist())
m = folium.Map(location=[df['lat'].mean(), df['lon'].mean()], zoom_start=12)
for lat, lon in valid_locations:
    folium.CircleMarker([lat, lon], radius=3, fill=True).add_to(m)
m.save("batch_conversion_demo.html")

坐标可视化验证

为确保转换结果正确,可使用folium的标记功能同时显示原始坐标和转换后坐标:

m = folium.Map(location=[wgs84_lat, wgs84_lon], zoom_start=15)
# 原始坐标(假设为地方坐标系)
folium.Marker([original_lat, original_lon], 
              icon=folium.Icon(color='red'),
              popup="原始坐标").add_to(m)
# 转换后坐标
folium.Marker([converted_lat, converted_lon], 
              icon=folium.Icon(color='green'),
              popup="转换后坐标").add_to(m)
# 添加连接线
folium.PolyLine([[original_lat, original_lon], [converted_lat, converted_lon]],
               color='gray', dash_array='5, 5').add_to(m)
m.save("coordinate_validation.html")

通过对比两者位置,可以直观判断转换是否正确。更多folium标记功能可参考官方文档docs/user_guide/ui_elements/popups.md

总结与进阶学习

本文介绍了folium地图应用中三种常见坐标系(WGS84、UTM与地方坐标系)的转换方法,通过Python的pyproj库实现坐标转换,结合folium完成可视化。核心要点包括:

  1. 坐标系基础:理解WGS84经纬度与UTM平面坐标的区别及应用场景
  2. 转换实现:使用pyproj库进行不同坐标系间的精确转换
  3. 批量处理:结合pandas实现大规模坐标数据的转换与验证
  4. 可视化验证:利用folium的地图功能直观检查转换结果

进阶学习资源:

掌握坐标系转换技能后,你可以轻松整合不同来源的地理数据,创建更加精准的folium地图可视化作品。无论是处理GPS轨迹数据、分析GIS空间信息,还是整合CAD工程图纸,坐标系转换都是连接不同数据世界的关键桥梁。

【免费下载链接】folium Python Data. Leaflet.js Maps. 【免费下载链接】folium 项目地址: https://gitcode.com/gh_mirrors/fo/folium

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值