请查看我的另一个问题:这是错误的here。
我有一张我国家地图的图片,我从Google地图中获取了地图,这意味着我知道了经度和纬度的所有角落坐标。我的程序需要显示地图,并在其上绘制目标,其中每个目标都有唯一的经度和纬度,类似于雷达显示目标的方式。
我的解决方案的问题在于它并没有真正使用真正的数学公式来获得X,Y位置。它使用简单除法和倍数比率,最小值和最大值,如我在其他问题中所见。
这是方法:
protected Location getCoordinatesByGlobe(float latitude, float longitude) {
/**
* Work out minimum and maximums, clamp inside map bounds
*/
latitude = Math.max(mapLatitudeMin, Math.min(mapLatitudeMax, latitude));
longitude = Math.max(mapLongitudeMin, Math.min(mapLongitudeMax, longitude));
/**
* We need the distance from 0 or minimum long/lat
*/
float adjLon = longitude - mapLongitudeMin;
float adjLat = latitude - mapLatitudeMin;
float mapLongWidth = mapLongitudeMax - mapLongitudeMin;
float mapLatHeight = mapLatitudeMax - mapLatitudeMin;
float mapWidth = mapImage.getWidth();
float mapHeight = mapImage.getHeight();
float longPixelRatio = mapWidth / mapLongWidth;
float latPixelRatio = mapHeight / mapLatHeight;
int x = Math.round(adjLon * longPixelRatio) - 3;// these are offsets for the target icon that shows.. eedit laterrr @oz
int y = Math.round(adjLat * latPixelRatio) + 3; //
// turn it up
y = (int) (mapHeight - y);
return new Location(x, y);
}
所以我对自己有点试图想一些符合逻辑的东西,我怎么能这样做呢。我想出了一些并不完全正常工作的东西:
如果我们有左上角例如坐标(经度和纬度),并且我们有我们想要显示的目标的坐标,这意味着我们可以distanceToPoint
知道距离多少公里从一开始就是。
在那之后,我们需要知道到那一点的标题,所以我们calculateHeading
给出了目标点的角度。
所以我们称A为起点(左上角)
float aLat = 33.49f;
float aLong = 33.69f;
我们的目标点我们称之为b:
float bLat = 32f;
float bLong = 35f;
然后我们可以用千米来计算从 A 到 B 的距离:
double km = distanceTopPoint(aLat, aLong, bLat, bLong);
然后我们计算到该点的角度:
double angle = calculateHeading(aLat, aLong, bLat, bLong);
如果我们有km距离和角度,我们可以知道经度和纬度的公里距离:
int latDistance = (int) Math.round(km * Math.cos(angle));
int lonDistance = (int) Math.round(km * Math.sin(angle));
所以现在我可能有经度到目标经度的距离,纬度相同。但是我能用这些信息做些什么呢?
我再次尝试思考,并且我发现我可以知道从左上角到右上角距离的距离(以km为单位),左上角到左上角的距离相同。然后我可以width / km
来获得每像素的公里数。
但我真的不确定,我确定我做错了什么。 有什么想法吗?
答案 0 :(得分:1)
墨卡托投影是圆柱投影,即广义坐标可以计算为:
a = longitude
b = tan(latitude)
这些是未缩放的坐标,即它们与像素位置不对应。
假设您有w
x h
像素的图像,表示(min_long, min_lat) - (max_long, max_lat)
之间的区域。可以使用上述公式将这些坐标转换为广义投影坐标,从而得到(min_a, min_b) - (max_a, max_b)
。
现在您需要将广义坐标线性映射到像素位置。该线性映射可以用四个参数(两个缩放参数和两个偏移参数)表示:
x = s_a * a + o_a
y = s_b * b = o_a
因此,您需要找到四个参数。您知道左上角有像素坐标(0, 0)
和广义坐标(min_a, max_b)
。同样适用于右下角。这为您提供了四个约束和一个线性方程组:
0 = s_a * min_a + o_a
0 = s_b * max_b + o_b
w = s_a * max_a + o_a
h = s_b * min_b + o_b
该系统的解决方案是:
s_a = w / (max_a - min_a)
o_a = -w * min_a / (max_a - min_a)
s_b = -h / (max_b - min_b)
o_b = h * max_b / (max_b - min_b)
就是这样。如果你想要某个任意点`(long,lat)的像素坐标,那么执行以下操作:
a
和b
(计算tangens时要小心使用弧度)。a
和b
转换为带有预先计算参数的像素坐标x
和y
。要从像素坐标获取纬度和经度,请执行以下操作:
计算广义坐标:
a = (x - o_a) / s_a
b = (x - o_b) / s_b
计算地理坐标:
longitude = a
latitude = arc tan (b)
再次注意弧度/度数。