我有一个[纬度/经度]对的列表,并希望将他们描述的路径描绘为我的自定义视图中的连接线,但是具有正确的比率。
到目前为止我的解决方案如下: 找到纬度和经度的最小值和最大值,将每个值描述为0到1之间的数字,然后将它们乘以我视图的高度/宽度。 结果,我的路径总是被拉伸到我视角的边界。
所以,例如,如果我从北向南行走10000米,在那个时间只有1米向西,然后向东2米,我的路径看起来像这样(向四面伸展):
---------------
| * |
| **** |
|** |
| * |
| *** |
| **** |
| ** |
| **|
---------------
但我希望它看起来像这样:
---------------
| * |
| * |
| * |
| ** |
| * |
| * |
| * |
| * |
---------------
因此,当我大部分时间从北向南行走时,路线应该填满我视线的整个高度,并且应该相应地显示x位置。当我主要从西向东走时,它应该占据整个宽度。
我无法弄清楚如何正确缩放我的值,以便我可以在我看来绘制它们。我希望你理解我的问题并帮助我解决它。提前致谢! :)
答案 0 :(得分:1)
假设您有以下变量,希望有明确的含义:
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
或{{ 1}})。
修改强>
根据您的评论,您不使用真实的经度和纬度值,而只是使用东西向和南北向的距离。这有点像在赤道,余弦因子变为1.我将继续调用输入坐标at
和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;
}
答案 1 :(得分:0)
我会定义最大宽高比。例如:
min_aspect_ratio = 5; // Minimum aspect ratio of 5:1
x_scale = screen_width/max_x_diff;
y_scale = screen_height/max_y_diff;
if(x_scale>y_scale)
if (x_scale/y_scale < min_aspect_ratio)
y_scale = x_scale/min_aspect_ratio;
else
if (y_scale/x_scale < min_aspect_ratio)
x_scale = y_scale/min_aspect_ratio;
免责声明:我没有测试此代码。