一、问题
上篇博客传送门实现了求OLC邻域编码部分代码,最后多次进位时出现问题,本篇博客旨在解决这一问题。
递归的思想:
-
首先计算出编码长度为2时,每个编码的邻域;
-
求编码为4的时候,就是前两位的邻域+后面两位的邻域(如果最后一位(经度的最后一位或者纬度的最后一位)不是边界的话,直接计算后两位的邻域,否则计算后两位和前两位的邻域);
-
求编码长度为6的时候,前4位的邻域+后两位;
-
同样,求编码长度为8、10一样的思路;
-
求编码长度为11时,由于OLC编码方式发生了改变,因此是求前10位+最后一位(不分经纬);
-
求编码长度位12时,是求前11位+最后一位。
二、代码
/*
* OLC 8邻域的第二个版本,解决多次进位的问题
*
* 2019-12-03
* 来桂兵
* */
public class OpenLocationCodeNearCodeV2 {
public static String BASE20 = "23456789CFGHJMPQRVWX"; //2位以上编码
public static String BASE18 = "23456789CFGHJMPQRV"; //2位编码
/*
*从Code中获取纬度的编码值(code的奇数位)
*/
public static String getLatCode(String code){
code = code.replace("+","");
String latCode = new String();
for(int i = 0; i < code.length(); i += 2){
latCode += code.charAt(i);
}
return latCode;
}
/*
*从code中获取经度的编码值(code的偶数位)
*/
public static String getLonCode(String code){
code = code.replace("+","");
String lonCode = new String();
for(int i = 1; i < code.length(); i += 2){
lonCode += code.charAt(i);
}
return lonCode;
}
/*
* 组合经纬度为Code(交叉合并经纬度的Code值)
*/
public static String getMerge(String a, String b) {
// 将字符串转换为字符数组
char[] aArray = a.toCharArray();
char[] bArray = b.toCharArray();
// 定义一个字符缓冲流
StringBuffer stringBuffer = new StringBuffer();
// 循环字符数组将两个字符数组中的元素进行交换位置
for (int i = 0; i < aArray.length; i++) {
// 将第一个字符数组添加的字符缓冲区
stringBuffer.append(aArray[i]);
// 如果i<bArray.length将bArray添加到字符串缓冲区
if (i < bArray.length) {
stringBuffer.append(bArray[i]);
}
}
// 返回交叉后的结果
return stringBuffer.toString();
}
/*
*计算 上邻域 (纬度 + 1 )
*/
public static String getTop(String code) {
String latCode = getLatCode(code); //纬度code
String lonCode = getLonCode(code); //经度code
String newCode = new String();
//编码长度为2时
if (code.length() == 2) {
String newlatCode = new String(); //初始化一个新字符串用来保存新纬度值
if (latCode.equals("C")) { //边界是 “C”, 就变成 ”2“
newlatCode = "2";
} else { //最后一位不是“C”
newlatCode = BASE18.charAt(BASE18.indexOf(latCode) + 1) + ""; // 否则 取 下一位索引对应的字符(为了保证它是String,而不是char)
}
//重新组合
newCode = getMerge(newlatCode, lonCode);
}
//编码长度为4时
else if (code.length() == 4) {
String FirstTwoChr = code.substring(0, 2); //前两位
String lastlatChr = latCode.substring(1); //最后一位纬度Code
String lastlonChr = lonCode.substring(1); //最后一位经度Code
if (lastlatChr.equals("X")) { //最后一位是X
FirstTwoChr = getTop(FirstTwoChr);
lastlatChr = "2" + "";
lastlonChr = lastlonChr;
newCode = FirstTwoChr + lastlatChr + lastlonChr;
} else { //最后一位不是X
FirstTwoChr = FirstTwoChr;
lastlatChr = BASE20.charAt(BASE20.indexOf(lastlatChr) + 1) + "";
lastlonChr = lastlonChr;
newCode = FirstTwoChr + lastlatChr + lastlonChr;
}
}
//编码 6位
else if(code.length() == 6){
String FirstFourChr = code.substring(0, 4); //前四位
String lastlatChr = latCode.substring(2); //最后一位纬度Code
String lastlonChr = lonCode.substring(2); //最后一位经度Code
if (lastlatChr.equals("X")) { //最后一位是X
FirstFourChr = getTop(FirstFourChr);
lastlatChr = "2" + "";
lastlonChr = lastlonChr;
newCode = FirstFourChr + lastlatChr + lastlonChr;
} else { //最后一位不是X
FirstFourChr = FirstFourChr;
lastlatChr = BASE20.charAt(BASE20.indexOf(lastlatChr) + 1) + "";
lastlonChr = lastlonChr;
newCode = FirstFourChr + lastlatChr + lastlonChr;
}
}
//编码 8位
else if(code.length() == 8){
String FirstSixChr = code.substring(0, 6); //前六位
String lastlatChr = latCode.substring(3); //最后一位纬度Code
String lastlonChr = lonCode.substring(3); //最后一位经度Code
if (lastlatChr.equals("X")) { //最后一位是X
FirstSixChr = getTop(FirstSixChr);
lastlatChr = "2" + "";
lastlonChr = lastlonChr;
newCode = FirstSixChr + "+" + lastlatChr + lastlonChr;
} else { //最后一位不是X
FirstSixChr = FirstSixChr;
lastlatChr = BAS