假设您有以下具有明确含义的变量:
screenWidth、screenHeight、minLon、maxLon、minLat、maxLat。
您想要的是 lon 和 lat 到屏幕坐标 x 和 y 的映射,这样宽度或高度都被填充,但圆圈仍然是圆圈(距离的水平和垂直比例相同)。
经纬度差的距离之比几乎是纬度的余弦值。 “几乎”只是因为地球不是一个完美的球体。余弦在纬度 0° 处为 1,因此,例如,在赤道,经度和纬度的相同差异对应于相同的距离。对于“足够”小区域的地图,可以使用平均纬度来计算比例。
如果您只有水平约束,则必须使x==0 对应于minLon 和x==screenWidth-1 对应于maxLon。其线性变换(即映射)将是:
x = lon * lonScale + x0;
与
deltaLon = maxLon - minLon;
lonScale = (screenWidth - 1) / deltaLon;
x0 = - minLon * lonScale;
同样,如果你只有一个垂直约束:
y = y0 - lat * latScale; // i.e.: lat * (-latScale) + y0
与
deltaLat = maxLat - minLat;
latScale = (screenHeight - 1) / deltaLat;
y0 = maxLat * latScale;
(减号是因为屏幕坐标的原点位于左上角。)
现在,如果deltaLon == 0.0 或deltaLat == 0.0,您不想除以0,而只想将有意义的映射应用于您正在处理的直线。如果两者都是!= 0.0,你想在latScale和lonScale之间选择较小的一个,记住它们的比率是平均纬度的余弦:
lonScale == latScale * Math.cos((maxLat + minLat) / 2.0)
所以:
avgLat = (maxLat + minLat) / 2.0;
cosFactor = Math.cos(avgLat);
if (deltaLon != 0.0 && deltaLat != 0.0) {
if (lonScale > latScale * cosFactor) {
lonScale = latScale * cosFactor;
x0 = ((screenWidth - 1) - (minLon + maxLon) * lonScale) / 2.0;
} else {
latScale = lonScale / cosFactor;
y0 = ((screenHeight - 1) + (minLat + maxLat) * latScale) / 2.0;
}
}
其中x0 和y0 已通过求解将(maxL* - minL*) / 2.0 置于屏幕中间的方程进行了调整(* 是on 或at)。
编辑
根据您的评论,您不使用真正的经度和纬度值,而只是使用东到西和南到北方向的距离。这有点像在赤道,余弦因子变为1。我将继续调用输入坐标lon和lat,但它们可以用任何长度单位表示,只要它是相同的单位两者兼得。
所以计算变成:
deltaLon = maxLon - minLon;
deltaLat = maxLat - minLat;
if (deltaLon != 0.0 && deltaLat != 0.0) {
lonScale = (screenWidth - 1) / deltaLon;
latScale = (screenHeight - 1) / deltaLat;
x0 = - minLon * lonScale;
y0 = maxLat * latScale;
if (lonScale > latScale) {
lonScale = latScale;
x0 = ((screenWidth - 1) - (minLon + maxLon) * lonScale) / 2.0;
} else {
latScale = lonScale;
y0 = ((screenHeight - 1) + (minLat + maxLat) * latScale) / 2.0;
}
} else if (deltaLon != 0.0) {
lonScale = (screenWidth - 1) / deltaLon;
latScale = 0;
x0 = - minLon * lonScale;
y0 = (screenHeight - 1) / 2.0;
} else if (deltaLat != 0.0) {
lonScale = 0;
latScale = (screenHeight - 1) / deltaLat;
x0 = (screenWidth - 1) / 2.0;
y0 = maxLat * latScale;
} else {
lonScale = 0;
latScale = 0;
x0 = (screenHeight - 1) / 2.0;
y0 = (screenWidth - 1) / 2.0;
}
屏幕值的计算与一般情况完全相同,即:
x = x0 + lon * lonScale;
y = y0 - lat * latScale;