我正在使用 MapQuest Android API 并在两点之间绘制路线。我想要做的是沿路线找到多个点,例如沿路径每 100 米的纬度和经度值,并将其存储在一个数组中。有没有办法做到这一点。我希望我的问题足够清楚,可以理解。
2 回答
我在 Java 和 Actionscript 中做过类似的事情。
首先,如果您还没有意识到,您所拥有的路线中的每条腿都是一条直线。路线越直,你的腿就越少。
要识别沿路线等距离的点 - 或者在我的情况下,沿路线的旅行时间 - 只需循环通过一组 [lat,long] 坐标计算每条腿末端的累积距离。
使用此信息,您可以轻松地修改循环以检查距离点(或多个点)沿着一条腿出现的位置。记住每条腿都是一条直线。如果是这样,它很简单,可以识别沿着你正在寻找的腿的距离,并从中计算出沿着腿那么远的点。
为此,您需要 2 种算法:
- 2 [lat,lng] 坐标之间的距离
- 沿 2 [lat, lng] 坐标之间的直线距离为 x 的点
说起来容易做起来难,这些都是复杂的算法,网上有一些可疑的例子。在我看来,很少有人能很好地解释数学是如何工作的,而且我发现的 mot 是不完整的。
然后我找到了这个宝石:http ://www.movable-type.co.uk/scripts/latlong.html
基于 Chris Veness 的出色参考,我在 actionscript 和 java 中实现了我的算法。
该链接应提供您需要的一切。解释您需要做什么,在伪代码和 javascript 中使用简洁的算法,如果这还不够,可以使用一个工具来测试您的算法。
如果您试图减少路径中的点数,但仍保持路径的准确表示,则最好的选择是使用线简化算法。
一种常见的行简化算法是 Douglas-Peucker,您可以在 Google MyTracks 项目中使用 Douglas-Peucker 的实现,在 Apache v2.0 下获得许可: https ://code.google.com/p/mytracks /source/browse/MyTracks/src/com/google/android/apps/mytracks/util/LocationUtils.java#78
这是代码,以防链接中断:
/**
* Decimates the given locations for a given zoom level. This uses a
* Douglas-Peucker decimation algorithm.
*
* @param tolerance in meters
* @param locations input
* @param decimated output
*/
private static void decimate(double tolerance, ArrayList<Location> locations, ArrayList<Location> decimated) {
final int n = locations.size();
if (n < 1) {
return;
}
int idx;
int maxIdx = 0;
Stack<int[]> stack = new Stack<int[]>();
double[] dists = new double[n];
dists[0] = 1;
dists[n - 1] = 1;
double maxDist;
double dist = 0.0;
int[] current;
if (n > 2) {
int[] stackVal = new int[] { 0, (n - 1) };
stack.push(stackVal);
while (stack.size() > 0) {
current = stack.pop();
maxDist = 0;
for (idx = current[0] + 1; idx < current[1]; ++idx) {
dist = LocationUtils.distance(
locations.get(idx), locations.get(current[0]), locations.get(current[1]));
if (dist > maxDist) {
maxDist = dist;
maxIdx = idx;
}
}
if (maxDist > tolerance) {
dists[maxIdx] = maxDist;
int[] stackValCurMax = { current[0], maxIdx };
stack.push(stackValCurMax);
int[] stackValMaxCur = { maxIdx, current[1] };
stack.push(stackValMaxCur);
}
}
}
int i = 0;
idx = 0;
decimated.clear();
for (Location l : locations) {
if (dists[idx] != 0) {
decimated.add(l);
i++;
}
idx++;
}
Log.d(Constants.TAG, "Decimating " + n + " points to " + i + " w/ tolerance = " + tolerance);
}