经纬度转凯立德 K 码
由于GPS信号位置均是经纬度球面坐标,国家从安全角度考虑不允许直接引用,因此凯立德为了方便导航者易于导航,就把经纬度坐标网格化,每一个网格单位代表纵横向0.1秒。
K码的具体格式如下:
1. K码是9位码;
2. K码将地图分成了四块进行编码,中心点在内蒙的阿拉善左旗境内;经纬度是东经105度0分0秒;北纬40度0分0秒
3. 以该点为中心分别在东西方向和南北方向画一条线当横纵(XY)坐标轴,那么第一象限(即东北方向的那块)的K码的第1位是5,第2、3、4象限的K码的第一位分别是6、7、8。
4. K码的第2-5位表示东西方向上的坐标,第6-9位代表南北方向上的坐标。
5. K码是一个凯立德特有的34进制数,(在KLD K码输入界面有说明:26个字母加10个阿拉伯数字,再去掉不用的L和O共34个字符),这个34进制数从左向右从低位向高位排列
6. 中心点的K码有4个,分别是500000000、6uy1y0000、7uy1yuy1y、80000uy1y。分别代表原点或中心点四个象限的K码。及X、Y轴正方向起始坐标0秒或代码为0000,X、Y轴负方向最大坐标为1260000秒或代码为uy1y
VC++的代码如下:
KCode.h
1 #ifndef _KLD_K_CODE_CALC_H_ 2 #define _KLD_K_CODE_CALC_H_ 3 4 typedef struct{ 5 int iIndex; 6 TCHAR cKCode; 7 }MyKCode_T; 8 9 #define KLD_KCODE_SYSTEM 34 10 #define KOCDE_MAX_LENGTH 4 11 #define KCODE_CENTER_LAT (40.0) 12 #define KCODE_CENTER_LON (105.0) 13 #define KCODE_X_Y_MAX_NAGATIVE 1260000 14 15 16 BOOL ConvertDuFenMiaoToDu(double dLatLonDu,double dLatLonFen,double dLatLonMiao,double &dLatLon); 17 BOOL ConvertTo34System(DWORD dwNumber,TCHAR *pKCode,BOOL bNegative); 18 BOOL ConvertTo34System2(DWORD dwNumber,TCHAR *pKCode,BOOL bNegative); // 与 ConvertTo34System 功能相同,采用对照表的方式实现 19 20 BOOL KCodeToZeroPoint(double dLat,double dLon,TCHAR *pKCode,int iKCodeSize); 21 22 /* 23 调用示例: 24 double dLon = 0.0; 25 double dLat = 0.0; 26 TCHAR cTmpBuffer[2 * KOCDE_MAX_LENGTH + 2]; 27 28 ZeroMemory(cTmpBuffer,sizeof(TCHAR) * (2 * KOCDE_MAX_LENGTH + 2)); 29 ConvertDuFenMiaoToDu(101.0,7.0,26.33,dLon); 30 ConvertDuFenMiaoToDu(29.0,39.0,51.76,dLat); 31 // ConvertDuFenMiaoToDu(40.0,0.0,0.0,dLat); // 坐标轴上的点测试 32 KCodeToZeroPoint(dLat,dLon,cTmpBuffer,2 * KOCDE_MAX_LENGTH + 2); 33 */ 34 35 #endif
源代码:
KCode.cpp
1 #include "stdafx.h" 2 #include "KCode.h" 3 4 MyKCode_T gMyKCode[KLD_KCODE_SYSTEM] = 5 { 6 {0, '0'}, 7 {1, '1'}, 8 {2, '2'}, 9 {3, '3'}, 10 {4, '4'}, 11 {5, '5'}, 12 {6, '6'}, 13 {7, '7'}, 14 {8, '8'}, 15 {9, '9'}, 16 {10,'a'}, 17 {11,'b'}, 18 {12,'c'}, 19 {13,'d'}, 20 {14,'e'}, 21 {15,'f'}, 22 {16,'g'}, 23 {17,'h'}, 24 {18,'i'}, 25 {19,'j'}, 26 {20,'k'}, // no L 27 {21,'m'}, 28 {22,'n'}, // no character O 29 {23,'p'}, 30 {24,'q'}, 31 {25,'r'}, 32 {26,'s'}, 33 {27,'t'}, 34 {28,'u'}, 35 {29,'v'}, 36 {30,'w'}, 37 {31,'x'}, 38 {32,'y'}, 39 {33,'z'}, 40 }; 41 42 BOOL ConvertDuFenMiaoToDu(double dLatLonDu,double dLatLonFen,double dLatLonMiao,double &dLatLon) 43 { 44 BOOL bRet = TRUE; 45 46 // 输入有效性判断 47 { 48 } 49 50 dLatLon = dLatLonDu + (dLatLonFen + (dLatLonMiao / 60.0)) / 60.0; 51 52 return bRet; 53 } 54 55 BOOL ConvertTo34System2(DWORD dwNumber,TCHAR *pKCode,BOOL bNegative) 56 { 57 BOOL bRet = TRUE; 58 DWORD dwDivideBy34 = dwNumber; 59 int iModeOf34 = 0; 60 int iCount = 0; 61 int i = 0; 62 63 // dwDivideBy34 = 1260000; 64 65 do 66 { 67 iModeOf34 = dwDivideBy34 % 34; 68 dwDivideBy34 = dwDivideBy34 / 34; 69 70 for(i = 0;i < KLD_KCODE_SYSTEM;i++) 71 { 72 if(iModeOf34 == gMyKCode[i].iIndex) 73 { 74 pKCode[iCount] = gMyKCode[i].cKCode; 75 iCount++; 76 if(1 == iCount && bNegative) 77 { 78 pKCode[0]--; 79 } 80 81 break; 82 } 83 } 84 85 }while(dwDivideBy34 > 0); 86 87 return bRet; 88 } 89 90 BOOL ConvertTo34System(DWORD dwNumber,TCHAR *pKCode,BOOL bNegative) 91 { 92 BOOL bRet = TRUE; 93 DWORD dwDivideBy34 = dwNumber; 94 int iModeOf34 = 0; 95 int iCount = 0; 96 97 do 98 { 99 iModeOf34 = dwDivideBy34 % 34; 100 dwDivideBy34 = dwDivideBy34 / 34; 101 102 if(iModeOf34 <= 9) 103 { 104 pKCode[iCount] = '0' + iModeOf34; 105 } 106 else if(iModeOf34 >= 10 && iModeOf34 <= 20) 107 { 108 pKCode[iCount] = 'a' + (iModeOf34 - 10); 109 } 110 else if(iModeOf34 >= 21 && iModeOf34 <= 22) 111 { 112 pKCode[iCount] = 'm' + (iModeOf34 - 21); 113 } 114 else if(iModeOf34 >= 23 && iModeOf34 <= 33) 115 { 116 pKCode[iCount] = 'p' + (iModeOf34 - 23); 117 } 118 iCount++; 119 if(1 == iCount && bNegative) 120 { 121 pKCode[0]--; 122 } 123 124 }while(dwDivideBy34 > 0); 125 126 return bRet; 127 } 128 129 /* 130 * 说明: iKCodeSize 的大小包含最后的 NULL 131 */ 132 BOOL KCodeToZeroPoint(double dLat,double dLon,TCHAR *pKCode,int iKCodeSize) 133 { 134 BOOL bRet = TRUE; 135 DWORD dwTmpLat = 0; 136 DWORD dwTmpLon = 0; 137 BOOL bIsNegative = FALSE; 138 TCHAR pKCodeLat[KOCDE_MAX_LENGTH + 1]; 139 TCHAR pKCodeLon[KOCDE_MAX_LENGTH + 1]; 140 141 // 输入有效性判断 142 { 143 if(iKCodeSize < (2 * KOCDE_MAX_LENGTH + 1)) 144 { 145 return bRet; 146 } 147 if(NULL == pKCode) 148 { 149 bRet = FALSE; 150 return bRet; 151 } 152 } 153 154 ZeroMemory(pKCodeLat,sizeof(TCHAR) * (KOCDE_MAX_LENGTH + 1)); 155 ZeroMemory(pKCodeLon,sizeof(TCHAR) * (KOCDE_MAX_LENGTH + 1)); 156 157 if(NULL != pKCodeLat) 158 { 159 double dDiff = (dLat - KCODE_CENTER_LAT); 160 161 if(dDiff < 0) 162 { 163 bIsNegative = TRUE; 164 dDiff = -dDiff; 165 dwTmpLat = (DWORD)((dDiff * 3600) * 10); // 以 0.1 秒为单位 166 dwTmpLat = KCODE_X_Y_MAX_NAGATIVE - dwTmpLat; 167 } 168 else 169 { 170 bIsNegative = FALSE; 171 dwTmpLat = (DWORD)((dDiff * 3600) * 10); // 以 0.1 秒为单位 172 } 173 ConvertTo34System(dwTmpLat,pKCodeLat,bIsNegative); 174 } 175 176 if(NULL != pKCodeLon) 177 { 178 double dDiff = (dLon - KCODE_CENTER_LON); 179 180 if(dDiff < 0) 181 { 182 bIsNegative = TRUE; 183 dDiff = -dDiff; 184 dwTmpLon = (DWORD)((dDiff * 3600) * 10); // 以 0.1 秒为单位 185 dwTmpLon = KCODE_X_Y_MAX_NAGATIVE - dwTmpLon; 186 } 187 else 188 { 189 bIsNegative = FALSE; 190 dwTmpLon = (DWORD)((dDiff * 3600) * 10); // 以 0.1 秒为单位 191 } 192 ConvertTo34System(dwTmpLon,pKCodeLon,bIsNegative); 193 } 194 195 if(KCODE_CENTER_LAT == dLat || KCODE_CENTER_LON == dLon) 196 { 197 if(KCODE_CENTER_LAT == dLat && KCODE_CENTER_LON == dLon) 198 { 199 pKCode[0] = '5'; 200 } 201 else if(KCODE_CENTER_LAT == dLat) 202 { 203 if(dLon > KCODE_CENTER_LON) 204 { 205 pKCode[0] = '6'; 206 } 207 else 208 { 209 pKCode[0] = '8'; 210 } 211 } 212 else if(KCODE_CENTER_LON == dLon) 213 { 214 if(dLat > KCODE_CENTER_LAT) 215 { 216 pKCode[0] = '5'; 217 } 218 else 219 { 220 pKCode[0] = '7'; 221 } 222 } 223 } 224 else 225 { 226 if(dLat > KCODE_CENTER_LAT) 227 { 228 if(dLon > KCODE_CENTER_LON) 229 { 230 pKCode[0] = '5'; 231 } 232 else 233 { 234 pKCode[0] = '6'; 235 } 236 } 237 else 238 { 239 if(dLon > KCODE_CENTER_LON) 240 { 241 pKCode[0] = '8'; 242 } 243 else 244 { 245 pKCode[0] = '7'; 246 } 247 } 248 } 249 wcscat_s(pKCode,iKCodeSize,pKCodeLon); 250 wcscat_s(pKCode,iKCodeSize,pKCodeLat); 251 printf("K Code is: %s\r\n",pKCode); 252 253 return bRet; 254 }
说明:以下是后补的:
1 // P76-P79行和P119-P122行存在边界值错误的问题。 2 // 修改为: 3 if(1 == iCount && bNegative) 4 { 5 if(0 == pKCode[0]) 6 { 7 pKCode[0] = 'z'; 8 } 9 else if('a' == pKCode[0]) 10 { 11 pKCode[0] = '9'; 12 } 13 else if('m' == pKCode[0]) 14 { 15 pKCode[0] = 'k'; 16 } 17 else if('p' == pKCode[0]) 18 { 19 pKCode[0] = 'n'; 20 } 21 else 22 { 23 pKCode[0]--; 24 } 25 } 26 // 但此算法只是猜的,不知真正的实现是否是样。 27 // 有待后继实际数值来验证。