POSGAR94多边形与WGS84 Leaflet地图错位问题排查求助
最近我在R里用Leaflet绘制城市多边形时踩了个坑:我的数据集是POSGAR94坐标系,但Leaflet基于OpenStreetMap(使用WGS84),所以必须转投影。但转完之后所有多边形都偏移了一个街区,城市边界处尤其明显,完全不对位。
先给大家看看我用的代码:
library(rgdal) library(magrittr) library(leaflet) # 读取数据并转换投影 complete_data <- readOGR("data_folder", GDAL1_integer64_policy = TRUE) complete_data <- spTransform(complete_data, CRS("+proj=longlat +datum=WGS84 +no_defs")) # 筛选目标多边形 int_data <- complete_data[grep("^0604219|^0604201|060421102|060421103", complete_data@data$link), ] # 绘制Leaflet地图 leaflet(int_data, options = leafletOptions(minZoom = 12, maxZoom = 18)) %>% setMaxBounds(lat1 = -37.1815, lng1 = -58.5581, lat2 = -37.1197, lng2 = -58.4297) %>% addTiles()%>% addPolygons(color = "#3498db", weight = 2, smoothFactor = 0.5, opacity = 0.5, fillOpacity = 0.1, highlightOptions = highlightOptions(color = "black", weight = 3, bringToFront = TRUE))
转换前后的坐标系信息我也查了:
转换前(POSGAR94):
User input: +proj=tmerc +lat_0=-90 +lon_0=-66 +k=1 +x_0=3500000 +y_0=0 +ellps=WGS84 +units=m +no_defs wkt: PROJCS["unnamed", GEOGCS["WGS 84", DATUM["unknown", SPHEROID["WGS84",6378137,298.257223563]], PRIMEM["Greenwich",0], UNIT["degree",0.0174532925199433]], PROJECTION["Transverse_Mercator"], PARAMETER["latitude_of_origin",-90], PARAMETER["central_meridian",-66], PARAMETER["scale_factor",1], PARAMETER["false_easting",3500000], PARAMETER["false_northing",0], UNIT["Meter",1]]
转换后(WGS84):
User input: +proj=longlat +datum=WGS84 +no_defs +ellps=WGS84 +towgs84=0,0,0 wkt: GEOGCS["WGS 84", DATUM["WGS_1984", SPHEROID["WGS 84",6378137,298.257223563, AUTHORITY["EPSG","7030"]], AUTHORITY["EPSG","6326"]], PRIMEM["Greenwich",0, AUTHORITY["EPSG","8901"]], UNIT["degree",0.0174532925199433, AUTHORITY["EPSG","9122"]], AUTHORITY["EPSG","4326"]]
我现在的疑问是:是投影转换的代码写错了?spTransform本身会带来误差?还是我的源数据本身就有问题?
可能的排查方向和解决方案
1. 先确认源CRS是否准确
你手动输入的POSGAR94参数可能有问题!POSGAR94对应的标准EPSG代码是32721(UTM Zone 21S),它的参数是+proj=utm +zone=21 +south +datum=WGS84 +units=m +no_defs,和你写的+proj=tmerc +lat_0=-90...有差异。手动写投影参数很容易出错,建议直接用EPSG代码来定义源坐标系试试:
# 替换原来的spTransform步骤 complete_data <- spTransform(complete_data, CRS("EPSG:32721")) # 先确保源CRS正确 complete_data <- spTransform(complete_data, CRS("EPSG:4326")) # 转WGS84
2. 换用sf包验证转换结果
rgdal和sp包相对老旧,推荐用更现代的sf包来处理空间数据,它的投影转换更稳定,也更直观:
library(sf) library(leaflet) # 读取数据并设置正确的源CRS complete_data_sf <- st_read("data_folder", GDAL1_integer64_policy = TRUE) st_crs(complete_data_sf) <- "EPSG:32721" # 强制设置正确的源坐标系 # 转换到WGS84 complete_data_sf_wgs84 <- st_transform(complete_data_sf, crs = "EPSG:4326") # 筛选数据并绘制 int_data_sf <- complete_data_sf_wgs84[grep("^0604219|^0604201|060421102|060421103", complete_data_sf_wgs84$link), ] leaflet(int_data_sf, options = leafletOptions(minZoom = 12, maxZoom = 18)) %>% setMaxBounds(lat1 = -37.1815, lng1 = -58.5581, lat2 = -37.1197, lng2 = -58.4297) %>% addTiles()%>% addPolygons(color = "#3498db", weight = 2, smoothFactor = 0.5, opacity = 0.5, fillOpacity = 0.1, highlightOptions = highlightOptions(color = "black", weight = 3, bringToFront = TRUE))
3. 检查源数据本身的准确性
找一个你知道准确WGS84坐标的地标(比如某个建筑、路口),在你的源数据里找到对应的多边形,提取它的中心坐标,手动转换后对比实际坐标,看是不是源数据本身就有偏移。如果是数据采集时的问题,那转换也救不了,得找数据源方核对。
4. 验证转换精度
spTransform本身的精度是很高的,只要源和目标CRS设置正确,不会出现“偏移一个街区”这么大的误差,所以核心问题大概率还是CRS参数设置错误。
内容的提问来源于stack exchange,提问作者Catriel Lopez

