gpt4 book ai didi

java - 如何正确缩放给定坐标以适应 View 的边界而不失真?

转载 作者:行者123 更新时间:2023-11-30 06:08:55 25 4
gpt4 key购买 nike

我有一个[纬度/经度]对的列表,并且想要将它们描述为连接线的路径绘制到我的自定义 View 中,但具有正确的比例。

到目前为止我的解决方案如下所示:查找纬度和经度的最小值和最大值,将每个值描述为 0 到 1 之间的数字,然后将它们乘以我的 View 的高度/宽度。结果,我的道路总是延伸到我的视野的边界。

例如,如果我从北向南步行 10000m,当时只向西 1m,然后向东 2m,我的路径看起来像这样(向四面八方延伸):

---------------
| * |
| **** |
|** |
| * |
| *** |
| **** |
| ** |
| **|
---------------

但我希望它看起来像这样:

---------------
| * |
| * |
| * |
| ** |
| * |
| * |
| * |
| * |
---------------

因此,当我主要从北向南行走时,路线应填满我的 View 的整个高度,并且应相应地显示 x 位置。当我主要从西向东行走时,它应该占据它的整个宽度。

我不知何故无法弄清楚如何正确缩放我的值,以便我可以在我的 View 中绘制它们。我希望您理解我的问题并能帮助我解决它。提前致谢! :)

最佳答案

假设您有以下具有明确含义的变量:screenWidthscreenHeightminLonmaxLonminLatmaxLat。您想要的是 lonlat 到屏幕坐标 xy 的映射,这样要么宽度或者高度被填充,但圆仍然是圆(距离的水平和垂直比例相同)。

经度和纬度差异的距离之比几乎恰好是纬度的余弦。 “几乎”只是因为地球不是一个完美的球体。余弦在纬度 0° 处为 1,因此,例如,在赤道处,相同的经度和纬度差对应于相同的距离。对于“足够”小区域的 map ,可以使用平均纬度来计算比例。

如果只有水平约束,则必须使 x==0 对应于 minLonx==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.0deltaLat == 0.0,您不想除以 0,而只想应用有意义的映射到你正在处理的直线。如果两者都是 != 0.0,您需要选择 latScalelonScale 之间较小的一个,记住它们的比率是平均纬度的余弦:

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;
}
}

其中,x0y0 已通过求解将 (maxL* - minL*)/2.0 置于屏幕(* 位于 onat)。

<小时/>

编辑

根据您的评论,您没有使用真实经度和纬度值,而只是使用东西和南北方向的距离。这有点像在赤道处,余弦因子变为1。我将继续将输入坐标称为lonlat,但它们可以用任何形式表示长度单位,只要两者的单位相同即可。

因此计算结果为:

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;

关于java - 如何正确缩放给定坐标以适应 View 的边界而不失真?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/50659975/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com