1 8.69 617 0 1/19/202121:05:11 4616337 40.74047,-74.00925140.74137,-74.0089340.7431706,-74.00859140.7462304,-74.0079740.74812,-74.00765140.748701,-74.00769140.74971,-74.0081940.75048,-74.00832140.751611,-74.0078940.7537504,-74.0070440.75721,-74.0046340.76003,-74.00263140.7607405,-7 }btwFx|ubMsD_AgJcAcR{ByJ_AsBFiEbByCXaFuAkLiDsTaNsPoKmCmB BBBBBBBBBBBBB NYC_DOT_LIC 4616337 Manhattan 11thavenganservoort-12thave@40thst
如上所示,这是一行的纽约市的某一时间段一条道路的连接信息,其中在这行信息之中对我们有用的有第一个数据----链路标识,第二个数据-----该路段上车辆经过的平均速度,第三个数据-----该路段上车辆行驶的平均时间,第四个数据-----路径状态标识,该标识有两个状态0和-101,其中0状态标识该链路可以通行,-101状态标识该链路不可通行,以及第七个数据----谷歌折现编码后的路径坐标值,其中最后一个数据对于我们来说更加的重要,因为官方给出的数据之中,路线图所经过的坐标并没有完整的表示出来,如果想要得到完整的路线坐标就必须要通过对折线编码后的字符串进行解码。接下来我们首先来说一下什么是谷歌折线编码(EncodedPolyLine)
多段线编码是一种有损压缩算法,利用这种算法,您可以将一系列坐标存储为单个字符串。点坐标使用有符号的值编码。下面指定了编码此类已签名值的步骤。
下面指定了编码此类已签名值的步骤。
1. 以初始签名值:
-179.9832104
2. 以十进制值乘以 1e5,舍入结果:
-17998321
3. 将十进制值转换为二进制值。请注意,使用负值必须使用其二个的补数计算,方法是反转二进制值并添加一个到结果
00000001 00010010 1010001 11110001
111111111111 1110 11101 010111110 0000011110
11111110 111010101010101011110 0000011111
4. 左移二进制值一位:
11111101 110110 10111100 0001111100
5. 如果原始十进制值为负数,则反转此编码
00000010 001001 0100001 1100001 1100001
6. 将二进制值分解为 5 位块(从右侧开始):
00001 00010 01010 10000 1111 00001
7. 将 5 位区块按相反顺序排列
00001 11111 10000 01010 00010 00001
8. 或每个值与 0x20, 如果另一
个位块如下: 100001 11111 110000 101010 100010 000001
将每个值转换为十进制
33 63 48 42 34 1
9.每个值添加 63:
96 126 111 105 97 64
9. 将每个值转换为其 ASCII
等效值:'=oia@
根据以上步骤,我们可以进行对编码过程的解码,将其转化为java算法可以表示为以下的代码形式:
package main.Operator;
import java.io.*;
import java.util.ArrayList;
public class TestDecode {
public static void main(String args[]) {
//for (int poi)
// for (int point : Decode("}btwFx|ubMsD_AgJcAcR{ByJ_AsBFiEbByCXaFuAkLiDsTaNsPoKmCmB")) {
// System.out.println(point); // Be aware that point is in E5
// }
String path = "D:\\newyork.txt";
File file = new File(path);
FileReader fr = null;
ArrayList<String[]> strs = new ArrayList<>();
ArrayList<ArrayList<Double>> start_end_points = new ArrayList<>();
try {
fr = new FileReader(file);
BufferedReader br = new BufferedReader(fr);
String str;
while ((str = br.readLine()) != null) {
//System.out.println(str);
String[] strings = str.split("\\s+");
//System.out.println(strings[0] + " " + strings[1] + " " + strings[2] + " " + strings[3] + " " + strings[4] + " " + strings[5] + " " + strings[7]);
strs.add(strings);
}
br.close();
fr.close();
} catch (Exception e) {
e.printStackTrace();
}
File file_write = new File("D:\\newyork_start_finish.txt");
FileWriter fw = null;
//ArrayList<String[]> strs=new ArrayList<>();
try {
fw = new FileWriter(file_write);
BufferedWriter bw = new BufferedWriter(fw);
for (int i = 0; i < strs.size(); i++) {
ArrayList<Integer> points = (ArrayList<Integer>) Decode(strs.get(i)[7]);
ArrayList<Double> _points = new ArrayList<>();
String[] str_strs = strs.get(i);
String write = str_strs[0] + " " + str_strs[1] + " " + str_strs[2] + " " + str_strs[3] + " " + str_strs[4] + " " + str_strs[5] + " ";
for (int j = 0; j < points.size(); j++) {
if (j < 2) {
} else {
points.set(j, points.get(j) + points.get(j - 2));
}
double h = ((double) points.get(j)) / 100000;
if (j == 0 || j == 1 || j == points.size() - 2 || j == points.size() - 1)
if (j % 2 == 0) {
write = write + String.valueOf(h) + " ";
_points.add(h);
} else {
_points.add(h);
write = write + String.valueOf(h) + ", ";
start_end_points.add(_points);
}
}
System.out.println(write);
bw.write(write);
bw.newLine();
}
bw.close();
fw.close();
} catch (Exception e) {
e.printStackTrace();
}
}
private static java.util.List<java.lang.Integer> Decode(String encoded_polylines) {
java.util.List<java.lang.Integer> trucks = new java.util.ArrayList<java.lang.Integer>();
int truck = 0;
int carriage_q = 0;
for (int x = 0, xx = encoded_polylines.length(); x < xx; ++x) {
int i = encoded_polylines.charAt(x);
i -= 63;
int _5_bits = i << (32 - 5) >>> (32 - 5);
truck |= _5_bits << carriage_q;
carriage_q += 5;
boolean is_last = (i & (1 << 5)) == 0;
if (is_last) {
boolean is_negative = (truck & 1) == 1;
truck >>>= 1;
if (is_negative) {
truck = ~truck;
}
trucks.add(truck);
carriage_q = 0;
truck = 0;
}
}
return trucks;
}
}
经过上述代码处理之后我们可以得到如下得数据
1 8.69 617 0 1/19/202121:05:11 4616337 40.74047 -74.00925, 40.76074 -74.00208,
如图我们可以得到始末点的数据,当我们得到这些数据之后,根据论文中所说步骤进行筛选,需要注意的是,这里文章中并没有边距误差很小,这个很小的误差的正确的取值范围应该是多少,所以还应该进行进一步的自己估算误差的处理。
由于信息以链接形式而不是节点的形式提供,因此
对数据进行了预处理,以获得可行的 TSP。要加入路由,
我们比较了GPS坐标。两个节点之间的通信
当路由的最后一个点和另一个起点在
同一位置(边距误差很小)。之后,我们迭代通过所有
节点删除具有度< 2。GPS 坐标列表已解码
从每个链接的编码聚合物线字段。
当我们根据上面的叙述完成对应操作之后就可以建立相应的具有时间指标的路网信息,在接下来只需要进一步调动相应的谷歌api返回两点之间的距离,就可以建立新的可应用于实际得TSP路网。