如何用RGeo在墨卡托投影上绘制可定义步长的大圆路径?
在Ruby中用RGeo生成带自定义步长的大圆路径
核心解决方案
要生成带可定义步长的大圆路径,关键是利用RGeo球面点的原生插值方法生成中间点,再转换为墨卡托投影线串。直接转换抽象的球面线串会丢失中间点,因此必须先显式生成所有插值点。
完整代码实现
# 初始化WGS84球面工厂(SRID 4326) spherical_factory = RGeo::Geographic.spherical_factory(srid: 4326) # 定义起始点与终点(RGeo点格式:经度在前,纬度在后) point1 = spherical_factory.point(-122.4194, 37.7749) # 旧金山坐标 point2 = spherical_factory.point(139.6917, 35.6895) # 东京坐标 # 定义步长:每100公里生成一个点(单位:米) step_distance = 100 * 1000 # 计算两点间的大圆总距离(单位:米) total_distance = spherical_factory.distance(point1, point2) # 计算插值步数(至少保留起点和终点) num_steps = [total_distance / step_distance, 1].max.floor points = [point1] # 插值生成所有中间点 (1...num_steps).each do |i| fraction = i.to_f / num_steps # 利用球面点的interpolate方法生成大圆上的点 interpolated_point = point1.interpolate(point2, fraction) points << interpolated_point end points << point2 # 初始化墨卡托投影工厂(适配Google Maps,SRID 3857) mercator_factory = RGeo::ProjectedFactory.new( srid: 3857, projection_proj4: '+proj=merc +a=6378137 +b=6378137 +lat_ts=0.0 +lon_0=0.0 +x_0=0.0 +y_0=0 +k=1.0 +units=m +nadgrids=@null +wktext +no_defs', geographic_factory: spherical_factory ) # 生成墨卡托投影的线串 mercator_line = mercator_factory.line_string(points) # 输出GeoJSON用于Google Maps渲染 puts RGeo::GeoJSON.encode(mercator_line) # 存储到PostGIS:直接将球面线串或墨卡托线串赋值给模型的geometry字段即可 # 例如:Model.create(geometry: spherical_factory.line_string(points))
关键细节说明
- 原生插值方法:
point.interpolate(other_point, fraction)是RGeo球面点的原生方法,基于球面三角学计算,能准确生成大圆路径上的点,避免手动移植代码的误差。 - 步长控制:通过总距离除以步长计算步数,确保点的密度符合需求。若需要按角度步长(如每1度一个点),可替换为基于夹角的计算逻辑:
# 按角度步长(每1度生成一个点) angle_step = 1.0 # 度 # 计算两点间的大圆夹角(弧度转角度) delta_rad = Math.acos( Math.sin(point1.lat * Math::PI / 180) * Math.sin(point2.lat * Math::PI / 180) + Math.cos(point1.lat * Math::PI / 180) * Math.cos(point2.lat * Math::PI / 180) * Math.cos((point1.lon - point2.lon) * Math::PI / 180) ) delta_deg = delta_rad * 180 / Math::PI num_steps = [delta_deg / angle_step, 1].max.floor - 投影转换:必须先生成所有插值点,再用
ProjectedFactory转换为墨卡托线串。直接转换抽象的球面线串只会保留起点和终点,丢失中间插值点。
解决你遇到的问题
- 之前移植OGR代码出现的重叠/间隙问题:原生插值方法基于标准球面三角学,精度更高,能避免手动实现的逻辑误差。
- 球面线串转墨卡托只有两点:因为RGeo的球面线串是抽象几何对象,未存储中间点,必须显式生成所有插值点后再转换。
内容的提问来源于stack exchange,提问作者Ben M
相关产品推荐
相关产品推荐

