├── .gitignore ├── setup.py ├── coordtrans.h ├── main.cpp ├── README.md ├── _coordtrans.cpp ├── LICENSE └── coordtrans.cpp /.gitignore: -------------------------------------------------------------------------------- 1 | build 2 | *.o 3 | *.so 4 | coordtrans 5 | -------------------------------------------------------------------------------- /setup.py: -------------------------------------------------------------------------------- 1 | from distutils.core import setup, Extension 2 | 3 | setup( 4 | ext_modules=[Extension("_coordtrans", ["_coordtrans.cpp", "coordtrans.cpp"])] 5 | ) 6 | -------------------------------------------------------------------------------- /coordtrans.h: -------------------------------------------------------------------------------- 1 | #ifndef _COORDTRANS 2 | #define _COORDTRANS 3 | 4 | #include 5 | #include 6 | 7 | 8 | int coordtrans(const char *from, const char *to, double oldx, double oldy, double &newx, double &newy); 9 | 10 | #endif 11 | -------------------------------------------------------------------------------- /main.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include "coordtrans.h" 4 | 5 | int main(int argc, char* argv[]) { 6 | if (argc != 5) { 7 | printf("Usage: %s from to lng lat\n", argv[0]); 8 | return 1; 9 | } 10 | 11 | double lng = atof(argv[3]); 12 | double lat = atof(argv[4]); 13 | double newlng = 0; 14 | double newlat = 0; 15 | int ret = coordtrans(argv[1], argv[2], lng, lat, newlng, newlat); 16 | 17 | if (ret == 0) { 18 | printf("%lf\t%lf\t%lf,%lf\n", newlng, newlat, newlng, newlat); 19 | return 0; 20 | } else { 21 | printf("failed to convert from %s to %s\n", argv[1], argv[2]); 22 | return 1; 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | pycoordtrans 2 | ============ 3 | 4 | A python2 binding to coordtrans, which is written in C++ and provides coordinate conversion between bd09ll, gcj02 and wgs84. 5 | 6 | Build 7 | -------- 8 | Clone the repository and just run the following scripts. You will get a python module. 9 | 10 | ```Shell 11 | git clone https://github.com/zxteloiv/pycoordtrans.git 12 | cd pycoordtrans 13 | python2 setup.py build_ext --inplace 14 | ``` 15 | Usage 16 | --------- 17 | After you build this extension, you will have a python module named _coordtrans. 18 | The module is the same as other python modules except that it is written in C++. 19 | The compiled module is a linux shared library. All you get is a _coordtrans.so file residing at the current directory. 20 | 21 | Run it as the following: 22 | ```Python 23 | from _coordtrans import coordtrans 24 | y, x = 39.981839,116.306411 # x, y are longitude and latitude respectively by convention 25 | (x, y) = coordtrans('gcj02', 'bd09ll', x, y) # yielding a tuple (116.31290580529193, 39.98791010079803) 26 | ``` 27 | Handful tool 28 | --------- 29 | To check the coordinates in commandline, you can also compile the main.cpp as a traditional C++ program. 30 | 31 | ```Shell 32 | g++ main.cpp coordtrans.cpp -o coordtrans 33 | ./coordtrans gcj02 bd09ll 116.306411 39.981839 34 | ``` 35 | 36 | -------------------------------------------------------------------------------- /_coordtrans.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include "coordtrans.h" 3 | 4 | static char module_docstring[] = 5 | "This module provides an interface for coordtrans in C."; 6 | 7 | static char coordtrans_docstring[] = 8 | "Convert coordinates among bd09ll, wgs84, gcj02"; 9 | 10 | static PyObject *_coordtrans_coordtrans(PyObject *self, PyObject *args); 11 | 12 | static PyMethodDef module_methods[] = { 13 | {"coordtrans", _coordtrans_coordtrans, METH_VARARGS, coordtrans_docstring}, 14 | {NULL, NULL, 0, NULL} 15 | }; 16 | 17 | PyMODINIT_FUNC init_coordtrans(void) { 18 | PyObject *m = Py_InitModule3("_coordtrans", module_methods, module_docstring); 19 | if (m == NULL) 20 | return; 21 | }; 22 | 23 | static PyObject *_coordtrans_coordtrans(PyObject *self, PyObject *args) { 24 | char *from = NULL; 25 | char *to = NULL; 26 | double lng = 0; 27 | double lat = 0; 28 | double newlng = 0; 29 | double newlat = 0; 30 | int ret = -1; // return value 31 | if (!PyArg_ParseTuple(args, "ssdd", &from, &to, &lng, &lat)) { 32 | return NULL; 33 | } 34 | 35 | ret = coordtrans(from, to, lng, lat, newlng, newlat); 36 | 37 | if (0 != ret) { 38 | PyErr_SetString(PyExc_RuntimeError, "impossible string"); 39 | return NULL; 40 | } 41 | 42 | PyObject *val = Py_BuildValue("dd", newlng, newlat); 43 | return val; 44 | } 45 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2014, Shiina Haruki 2 | All rights reserved. 3 | 4 | Redistribution and use in source and binary forms, with or without 5 | modification, are permitted provided that the following conditions are met: 6 | 7 | * Redistributions of source code must retain the above copyright notice, this 8 | list of conditions and the following disclaimer. 9 | 10 | * Redistributions in binary form must reproduce the above copyright notice, 11 | this list of conditions and the following disclaimer in the documentation 12 | and/or other materials provided with the distribution. 13 | 14 | * Neither the name of pycoordtrans nor the names of its 15 | contributors may be used to endorse or promote products derived from 16 | this software without specific prior written permission. 17 | 18 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 19 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 20 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 21 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE 22 | FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 23 | DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 24 | SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 25 | CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 26 | OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 27 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 28 | 29 | -------------------------------------------------------------------------------- /coordtrans.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | 5 | int coordtrans(const char *from, const char *to, double oldx, double oldy, double &newx, double &newy); 6 | 7 | /////////////////////////////////////////////////////////////////// 8 | /** 9 | * @class dpoint_t 10 | * @brief double point type. 11 | */ 12 | struct dpoint_t { 13 | double x; 14 | double y; 15 | dpoint_t() : 16 | x(0), y(0) { 17 | } 18 | dpoint_t(double xx, double yy) : 19 | x(xx), y(yy) { 20 | } 21 | dpoint_t(const dpoint_t& rh) : 22 | x(rh.x), y(rh.y) { 23 | } 24 | }; 25 | 26 | 27 | dpoint_t _conv_(const dpoint_t& fromPoint, double factor[]) ; 28 | 29 | 30 | dpoint_t ll2mc(const dpoint_t& point) ; 31 | 32 | 33 | int ll2mc(const dpoint_t& pt, dpoint_t* res) ; 34 | 35 | class GcjEncryptor { 36 | private: 37 | double casm_rr; 38 | unsigned int casm_t1; 39 | unsigned int casm_t2; 40 | double casm_x1; 41 | double casm_y1; 42 | double casm_x2; 43 | double casm_y2; 44 | double casm_f; 45 | 46 | double yj_sin2(double x); 47 | double Transform_yj5(double x, double y) ; 48 | double Transform_yjy5(double x, double y); 49 | double Transform_jy5(double x, double xx) ; 50 | double Transform_jyj5(double x, double yy) ; 51 | double r_yj(); 52 | double random_yj() ; 53 | void IniCasm(unsigned int w_time, unsigned int w_lng, unsigned int w_lat); 54 | unsigned int wgtochina_lb(int wg_flag, unsigned int wg_lng, 55 | unsigned int wg_lat, int wg_heit, int wg_week, unsigned int wg_time, 56 | unsigned int *china_lng, unsigned int *china_lat); 57 | 58 | private: 59 | unsigned int _iix_, _iiy_; 60 | unsigned int _iox_, _ioy_; 61 | static const int _COFF_ = 3686400; 62 | 63 | public: 64 | GcjEncryptor() { 65 | casm_rr = 0; 66 | casm_t1 = 0; 67 | casm_t2 = 0; 68 | casm_x1 = 0; 69 | casm_y1 = 0; 70 | casm_x2 = 0; 71 | casm_y2 = 0; 72 | casm_f = 0; 73 | } 74 | ~GcjEncryptor() {} 75 | 76 | int encrypt(const dpoint_t& pt, dpoint_t* res) { 77 | if( !res ) { 78 | return -1; 79 | } 80 | _iix_ = static_cast(pt.x * _COFF_); 81 | _iiy_ = static_cast(pt.y * _COFF_); 82 | if(this->wgtochina_lb(1, _iix_, _iiy_, 1, 0, 0, &_iox_, &_ioy_)) { 83 | return -2; 84 | } 85 | res->x = static_cast(_iox_) / static_cast(_COFF_); 86 | res->y = static_cast(_ioy_) / static_cast(_COFF_); 87 | return 0; 88 | } 89 | 90 | int encrypt(double oldx, double oldy, double &newx, double &newy) { 91 | _iix_ = static_cast(oldx * _COFF_); 92 | _iiy_ = static_cast(oldy * _COFF_); 93 | if(this->wgtochina_lb(1, _iix_, _iiy_, 1, 0, 0, &_iox_, &_ioy_)) { 94 | return -2; 95 | } 96 | newx = static_cast(_iox_) / static_cast(_COFF_); 97 | newy = static_cast(_ioy_) / static_cast(_COFF_); 98 | return 0; 99 | } 100 | }; 101 | 102 | //geometric 103 | const long double _GRID_RADIX_ = 3E3; 104 | const long double _MAX_dR_ = 2E-5; 105 | const long double _MAX_dT_ = 3E-6; 106 | const double _LL2RAD_ = 0.0174532925194; 107 | const long double _OFFSET_X_ = 0.0065; 108 | const long double _OFFSET_Y_ = 0.0060; 109 | 110 | const double EARTHRADIUS = 6370996.81; 111 | const double MCBAND[6] = { 12890594.86, 8362377.87, 5591021, 3481989.83, 112 | 1678043.12, 0 }; 113 | const double LLBAND[6] = { 75, 60, 45, 30, 15, 0 }; 114 | 115 | const double MC2LL[][10] = { { 1.410526172116255e-008, 8.983055096488720e-006, 116 | -1.99398338163310, 2.009824383106796e+002, -1.872403703815547e+002, 117 | 91.60875166698430, -23.38765649603339, 2.57121317296198, 118 | -0.03801003308653, 1.733798120000000e+007 }, { -7.435856389565537e-009, 119 | 8.983055097726239e-006, -0.78625201886289, 96.32687599759846, 120 | -1.85204757529826, -59.36935905485877, 47.40033549296737, 121 | -16.50741931063887, 2.28786674699375, 1.026014486000000e+007 }, { 122 | -3.030883460898826e-008, 8.983055099835780e-006, 0.30071316287616, 123 | 59.74293618442277, 7.35798407487100, -25.38371002664745, 124 | 13.45380521110908, -3.29883767235584, 0.32710905363475, 125 | 6.856817370000000e+006 }, { -1.981981304930552e-008, 126 | 8.983055099779535e-006, 0.03278182852591, 40.31678527705744, 127 | 0.65659298677277, -4.44255534477492, 0.85341911805263, 128 | 0.12923347998204, -0.04625736007561, 4.482777060000000e+006 }, { 129 | 3.091913710684370e-009, 8.983055096812155e-006, 0.00006995724062, 130 | 23.10934304144901, -0.00023663490511, -0.63218178102420, 131 | -0.00663494467273, 0.03430082397953, -0.00466043876332, 132 | 2.555164400000000e+006 }, { 2.890871144776878e-009, 133 | 8.983055095805407e-006, -0.00000003068298, 7.47137025468032, 134 | -0.00000353937994, -0.02145144861037, -0.00001234426596, 135 | 0.00010322952773, -0.00000323890364, 8.260885000000000e+005 } }; 136 | 137 | const double LL2MC[][10] = { { -0.00157021024440, 1.113207020616939e+005, 138 | 1.704480524535203e+015, -1.033898737604234e+016, 139 | 2.611266785660388e+016, -3.514966917665370e+016, 140 | 2.659570071840392e+016, -1.072501245418824e+016, 141 | 1.800819912950474e+015, 82.50000000000000 }, { 8.277824516172526e-004, 142 | 1.113207020463578e+005, 6.477955746671608e+008, 143 | -4.082003173641316e+009, 1.077490566351142e+010, 144 | -1.517187553151559e+010, 1.205306533862167e+010, 145 | -5.124939663577472e+009, 9.133119359512032e+008, 67.50000000000000 }, { 146 | 0.00337398766765, 1.113207020202162e+005, 4.481351045890365e+006, 147 | -2.339375119931662e+007, 7.968221547186455e+007, 148 | -1.159649932797253e+008, 9.723671115602145e+007, 149 | -4.366194633752821e+007, 8.477230501135234e+006, 52.50000000000000 }, { 150 | 0.00220636496208, 1.113207020209128e+005, 5.175186112841131e+004, 151 | 3.796837749470245e+006, 9.920137397791013e+005, 152 | -1.221952217112870e+006, 1.340652697009075e+006, 153 | -6.209436990984312e+005, 1.444169293806241e+005, 37.50000000000000 }, { 154 | -3.441963504368392e-004, 1.113207020576856e+005, 155 | 2.782353980772752e+002, 2.485758690035394e+006, 6.070750963243378e+003, 156 | 5.482118345352118e+004, 9.540606633304236e+003, 157 | -2.710553267466450e+003, 1.405483844121726e+003, 22.50000000000000 }, 158 | {-3.218135878613132e-004, 1.113207020701615e+005, 0.00369383431289, 159 | 8.237256402795718e+005, 0.46104986909093, 160 | 2.351343141331292e+003, 1.58060784298199, 8.77738589078284, 161 | 0.37238884252424, 7.45000000000000 } }; 162 | 163 | 164 | /** 165 | * @brief 166 | */ 167 | dpoint_t _conv_(const dpoint_t& fromPoint, double factor[]) { 168 | dpoint_t toPoint; 169 | toPoint.x = factor[0] + factor[1] * fabs(fromPoint.x); 170 | double temp = fabs(fromPoint.y) / factor[9]; 171 | toPoint.y = factor[2] + factor[3] * temp + factor[4] * temp * temp 172 | + factor[5] * temp * temp * temp + factor[6] * temp * temp * temp 173 | * temp + factor[7] * temp * temp * temp * temp * temp + factor[8] 174 | * temp * temp * temp * temp * temp * temp; 175 | toPoint.x *= (fromPoint.x < 0 ? -1 : 1); 176 | toPoint.y *= (fromPoint.y < 0 ? -1 : 1); 177 | return toPoint; 178 | } 179 | 180 | /** 181 | * @brief 182 | */ 183 | inline long double _get_delta_r_(long double y0) { 184 | return sin(y0 * _GRID_RADIX_ * _LL2RAD_) * _MAX_dR_; 185 | } 186 | /** 187 | * @brief 188 | */ 189 | inline long double _get_delta_t_(long double x0) { 190 | return cos(x0 * _GRID_RADIX_ * _LL2RAD_) * _MAX_dT_; 191 | } 192 | 193 | int bd_encrypt(const dpoint_t& pt, dpoint_t* res) { 194 | if (!res) { 195 | return -1; 196 | } 197 | 198 | long double x0 = static_cast (pt.x); 199 | long double y0 = static_cast (pt.y); 200 | long double r0 = sqrt(x0 * x0 + y0 * y0); 201 | long double theta0 = atan2(y0, x0); 202 | long double r1 = r0 + _get_delta_r_(y0); 203 | long double theta1 = theta0 + _get_delta_t_(x0); 204 | long double x1(r1 * cos(theta1)), y1(r1 * sin(theta1)); 205 | 206 | res->x = static_cast (x1 + _OFFSET_X_); 207 | res->y = static_cast (y1 + _OFFSET_Y_); 208 | 209 | return 0; 210 | } 211 | 212 | /** 213 | * @brief transform from lat-lon to mercator. 214 | * @param pt point. 215 | * @return result point. 216 | */ 217 | dpoint_t ll2mc(const dpoint_t& point) { 218 | dpoint_t temp; 219 | temp.x = point.x; 220 | if(temp.x > 180.0) { 221 | temp.x = 180.0; 222 | } else if(temp.x < -180.0) { 223 | temp.x = -180.0; 224 | } 225 | 226 | temp.y = point.y; 227 | if (temp.y < 1E-7 && temp.y >= 0.0) { 228 | temp.y = 1E-7; 229 | } else if(temp.y < 0 && temp.y > -1.0E-7) { 230 | temp.y = -1E-7; 231 | } else if(temp.y > 74) { 232 | temp.y = 74; 233 | } else if(temp.y < -74) { 234 | temp.y = -74; 235 | } 236 | 237 | double factor[10] = { 0 }; 238 | unsigned int i = 0; 239 | for (i = 0; i < sizeof(LLBAND) / sizeof(double); i++) { 240 | if (fabs(temp.y) > LLBAND[i]) { 241 | memcpy(factor, LL2MC[i], sizeof(factor)); 242 | break; 243 | } 244 | } 245 | return _conv_(temp, factor); 246 | } 247 | 248 | /** 249 | * @brief transform from lat-lon to mercator. 250 | * @param pt point. 251 | * @param res return point ptr. 252 | * @return 253 | * - 0 - ok. 254 | * - <0 - failed. 255 | */ 256 | int ll2mc(const dpoint_t& pt, dpoint_t* res) { 257 | if (!res) { 258 | return -1; 259 | } 260 | (*res) = ll2mc(pt); 261 | return 0; 262 | } 263 | 264 | /** 265 | * @brief transform from mercator to lat-lon. 266 | * @param pt point. 267 | * @return result point. 268 | */ 269 | dpoint_t mc2ll(const dpoint_t& point) { 270 | dpoint_t temp; 271 | temp.x = point.x; 272 | if(temp.x > 20037508.342) { 273 | temp.x = 20037508.342; 274 | } else if(temp.x < -20037508.342) { 275 | temp.x = -20037508.342; 276 | } 277 | temp.y = point.y; 278 | if (temp.y < 1E-6 && temp.y >= 0) { 279 | temp.y = 1E-6; 280 | } else if(temp.y < 0 && temp.y > -1.0E-6) { 281 | temp.y = -1E-6; 282 | } else if(temp.y > 20037508.342) { 283 | temp.y = 20037508.342; 284 | } else if(temp.y < -20037508.342) { 285 | temp.y = -20037508.342; 286 | } 287 | 288 | double factor[10] = { 0 }; 289 | unsigned int i = 0; 290 | for (i = 0; i < sizeof(MCBAND) / sizeof(double); i++) { 291 | if (fabs(temp.y) > MCBAND[i]) { 292 | memcpy(factor, MC2LL[i], sizeof(factor)); 293 | break; 294 | } 295 | } 296 | return _conv_(temp, factor); 297 | } 298 | 299 | /** 300 | * @brief transform from mercator to lat-lon. 301 | * @param pt point. 302 | * @param res return point ptr. 303 | * @return 304 | * - 0 - ok. 305 | * - <0 - failed. 306 | */ 307 | int mc2ll(const dpoint_t& pt, dpoint_t* res) { 308 | if (!res) { 309 | return -1; 310 | } 311 | (*res) = mc2ll(pt); 312 | return 0; 313 | } 314 | 315 | /** 316 | * @brief baidu decrypt. 317 | * @param pt point. 318 | * @param res return point ptr. 319 | * @return 320 | * - 0 - ok. 321 | * - <0 - failed. 322 | */ 323 | int bd_decrypt(const dpoint_t& pt, dpoint_t* res) { 324 | if (!res) { 325 | return -1; 326 | } 327 | 328 | long double x0 = static_cast (pt.x) - _OFFSET_X_; 329 | long double y0 = static_cast (pt.y) - _OFFSET_Y_; 330 | long double r0 = sqrt(x0 * x0 + y0 * y0); 331 | long double theta0 = atan2(y0, x0); 332 | long double r1 = r0 - _get_delta_r_(y0); 333 | long double theta1 = theta0 - _get_delta_t_(x0); 334 | long double x1(r1 * cos(theta1)), y1(r1 * sin(theta1)); 335 | 336 | res->x = static_cast (x1); 337 | res->y = static_cast (y1); 338 | 339 | return 0; 340 | } 341 | 342 | /** 343 | * @brief transform coordinates from baidu09 system to wgs84 system; 344 | * @param pt point. 345 | * @param res return point ptr. 346 | * @return 347 | * - 0 - ok. 348 | * - <0 - failed. 349 | */ 350 | int bd09_to_wgs84(const dpoint_t& pt, dpoint_t* res) 351 | { 352 | dpoint_t bd_pt; 353 | if(mc2ll(pt, &bd_pt) < 0) { 354 | return -1; 355 | } 356 | if(bd_decrypt(bd_pt, res) < 0) { 357 | return -2; 358 | } 359 | 360 | return 0; 361 | } 362 | 363 | double GcjEncryptor::yj_sin2(double x) { 364 | double tt; 365 | double ss; 366 | int ff; 367 | double s2; 368 | int cc; 369 | ff = 0; 370 | if (x < 0) { 371 | x = -x; 372 | ff = 1; 373 | } 374 | cc = static_cast(x / 6.28318530717959); 375 | tt = x - cc * 6.28318530717959; 376 | if (tt > 3.1415926535897932) { 377 | tt = tt - 3.1415926535897932; 378 | if (ff == 1) 379 | ff = 0; 380 | else if (ff == 0) 381 | ff = 1; 382 | } 383 | x = tt; 384 | ss = x; 385 | s2 = x; 386 | tt = tt * tt; 387 | s2 = s2 * tt; 388 | ss = ss - s2 * 0.166666666666667; 389 | s2 = s2 * tt; 390 | ss = ss + s2 * 8.33333333333333E-03; 391 | s2 = s2 * tt; 392 | ss = ss - s2 * 1.98412698412698E-04; 393 | s2 = s2 * tt; 394 | ss = ss + s2 * 2.75573192239859E-06; 395 | s2 = s2 * tt; 396 | ss = ss - s2 * 2.50521083854417E-08; 397 | if (ff == 1) 398 | ss = -ss; 399 | return ss; 400 | } 401 | double GcjEncryptor::Transform_yj5(double x, double y) { 402 | double tt; 403 | tt = 300 + 1 * x + 2 * y + 0.1 * x * x + 0.1 * x * y + 0.1 * sqrt(sqrt(x 404 | * x)); 405 | tt = tt + (20 * yj_sin2(18.849555921538764 * x) + 20 * yj_sin2( 406 | 6.283185307179588 * x)) * 0.6667; 407 | tt = tt + (20 * yj_sin2(3.141592653589794 * x) + 40 * yj_sin2( 408 | 1.047197551196598 * x)) * 0.6667; 409 | tt = tt + (150 * yj_sin2(0.2617993877991495 * x) + 300 * yj_sin2( 410 | 0.1047197551196598 * x)) * 0.6667; 411 | return tt; 412 | } 413 | double GcjEncryptor::Transform_yjy5(double x, double y) { 414 | double tt; 415 | tt = -100 + 2 * x + 3 * y + 0.2 * y * y + 0.1 * x * y + 0.2 * sqrt(sqrt(x 416 | * x)); 417 | tt = tt + (20 * yj_sin2(18.849555921538764 * x) + 20 * yj_sin2( 418 | 6.283185307179588 * x)) * 0.6667; 419 | tt = tt + (20 * yj_sin2(3.141592653589794 * y) + 40 * yj_sin2( 420 | 1.047197551196598 * y)) * 0.6667; 421 | tt = tt + (160 * yj_sin2(0.2617993877991495 * y) + 320 * yj_sin2( 422 | 0.1047197551196598 * y)) * 0.6667; 423 | return tt; 424 | } 425 | double GcjEncryptor::Transform_jy5(double x, double xx) { 426 | double n; 427 | double a; 428 | double e; 429 | a = 6378245; 430 | e = 0.00669342; 431 | n = sqrt(1 - e * yj_sin2(x * 0.0174532925199433) * yj_sin2(x 432 | * 0.0174532925199433)); 433 | n = (xx * 180) / (a / n * cos(x * 0.0174532925199433) * 3.1415926); 434 | return n; 435 | } 436 | double GcjEncryptor::Transform_jyj5(double x, double yy) { 437 | double m; 438 | double a; 439 | double e; 440 | double mm; 441 | a = 6378245; 442 | e = 0.00669342; 443 | mm = 1 - e * yj_sin2(x * 0.0174532925199433) * yj_sin2(x 444 | * 0.0174532925199433); 445 | m = (a * (1 - e)) / (mm * sqrt(mm)); 446 | return (yy * 180) / (m * 3.1415926); 447 | } 448 | double GcjEncryptor::r_yj() { 449 | int casm_a; 450 | int casm_c; 451 | casm_a = 314159269; 452 | casm_c = 453806245; 453 | return 0; 454 | } 455 | double GcjEncryptor::random_yj() { 456 | int t; 457 | int casm_a; 458 | int casm_c; 459 | casm_a = 314159269; 460 | casm_c = 453806245; 461 | casm_rr = casm_a * casm_rr + casm_c; 462 | t = static_cast(casm_rr / 2); 463 | casm_rr = casm_rr - t * 2; 464 | casm_rr = casm_rr / 2; 465 | return (casm_rr); 466 | } 467 | void GcjEncryptor::IniCasm(unsigned int w_time, unsigned int w_lng, unsigned int w_lat) { 468 | int tt; 469 | casm_t1 = w_time; 470 | casm_t2 = w_time; 471 | tt = static_cast(w_time / 0.357); 472 | casm_rr = w_time - tt * 0.357; 473 | if (w_time == 0) 474 | casm_rr = 0.3; 475 | casm_x1 = w_lng; 476 | casm_y1 = w_lat; 477 | casm_x2 = w_lng; 478 | casm_y2 = w_lat; 479 | casm_f = 3; 480 | } 481 | unsigned int GcjEncryptor::wgtochina_lb(int wg_flag, unsigned int wg_lng, 482 | unsigned int wg_lat, int wg_heit, int wg_week, unsigned int wg_time, 483 | unsigned int *china_lng, unsigned int *china_lat) { 484 | double x_add; 485 | double y_add; 486 | double h_add; 487 | double x_l; 488 | double y_l; 489 | double casm_v; 490 | double t1_t2; 491 | double x1_x2; 492 | double y1_y2; 493 | 494 | if (wg_heit > 5000) { 495 | *china_lng = 0; 496 | *china_lat = 0; 497 | return 0xFFFF95FF; 498 | } 499 | x_l = wg_lng; 500 | x_l = x_l / 3686400.0; 501 | y_l = wg_lat; 502 | y_l = y_l / 3686400.0; 503 | if (x_l < 72.004) { 504 | *china_lng = 0; 505 | *china_lat = 0; 506 | return 0xFFFF95FF; 507 | } 508 | if (x_l > 137.8347) { 509 | *china_lng = 0; 510 | *china_lat = 0; 511 | return 0xFFFF95FF; 512 | } 513 | if (y_l < 0.8293) { 514 | *china_lng = 0; 515 | *china_lat = 0; 516 | return 0xFFFF95FF; 517 | } 518 | if (y_l > 55.8271) { 519 | *china_lng = 0; 520 | *china_lat = 0; 521 | return 0xFFFF95FF; 522 | } 523 | //if (wg_flag == 0) 524 | IniCasm(wg_time, wg_lng, wg_lat); 525 | if(0) 526 | { 527 | IniCasm(wg_time, wg_lng, wg_lat); 528 | *china_lng = wg_lng; 529 | *china_lat = wg_lat; 530 | return 0x00000000; 531 | } 532 | 533 | casm_t2 = wg_time; 534 | t1_t2 = (double) (casm_t2 - casm_t1) / 1000.0; 535 | if (t1_t2 <= 0) { 536 | casm_t1 = casm_t2; 537 | casm_f = casm_f + 1; 538 | casm_x1 = casm_x2; 539 | casm_f = casm_f + 1; 540 | casm_y1 = casm_y2; 541 | casm_f = casm_f + 1; 542 | } else { 543 | if (t1_t2 > 120) { 544 | if (casm_f == 3) { 545 | casm_f = 0; 546 | casm_x2 = wg_lng; 547 | casm_y2 = wg_lat; 548 | x1_x2 = casm_x2 - casm_x1; 549 | y1_y2 = casm_y2 - casm_y1; 550 | casm_v = sqrt(x1_x2 * x1_x2 + y1_y2 * y1_y2) / t1_t2; 551 | if (casm_v > 3185) { 552 | *china_lng = 0; 553 | *china_lat = 0; 554 | return (0xFFFF95FF); 555 | } 556 | 557 | } 558 | casm_t1 = casm_t2; 559 | casm_f = casm_f + 1; 560 | casm_x1 = casm_x2; 561 | casm_f = casm_f + 1; 562 | casm_y1 = casm_y2; 563 | casm_f = casm_f + 1; 564 | } 565 | } 566 | x_add = Transform_yj5(x_l - 105, y_l - 35); 567 | y_add = Transform_yjy5(x_l - 105, y_l - 35); 568 | h_add = wg_heit; 569 | 570 | x_add = x_add + h_add * 0.001 + yj_sin2(wg_time * 0.0174532925199433) 571 | + random_yj(); 572 | y_add = y_add + h_add * 0.001 + yj_sin2(wg_time * 0.0174532925199433) 573 | + random_yj(); 574 | *china_lng = static_cast((x_l + Transform_jy5(y_l, x_add)) * 3686400); 575 | *china_lat = static_cast((y_l + Transform_jyj5(y_l, y_add)) * 3686400); 576 | return (0x00000000); 577 | } 578 | 579 | double dis(double x1,double y1,double x2,double y2) 580 | { 581 | return sqrt((x1-x2)*(x1-x2) + (y1-y2)*(y1-y2)); 582 | } 583 | GcjEncryptor g_gcj_encryptor; 584 | 585 | int gcj_decrypt(dpoint_t oldxy, dpoint_t *newxy) { 586 | if (newxy == NULL) { 587 | return -1; 588 | } 589 | double xmid = oldxy.x, ymid = oldxy.y; 590 | double cellsize = 1; 591 | double realgcjx = oldxy.x, realgcjy = oldxy.y; 592 | double x1 = xmid - cellsize,x1new = 0; 593 | double y1 = ymid + cellsize,y1new = 0; 594 | double x2 = xmid - cellsize,x2new = 0; 595 | double y2 = ymid - cellsize,y2new = 0; 596 | double x3 = xmid + cellsize,x3new = 0; 597 | double y3 = ymid - cellsize,y3new = 0; 598 | double x4 = xmid + cellsize,x4new = 0; 599 | double y4 = ymid + cellsize,y4new = 0; 600 | double xmidnew,ymidnew; 601 | double gpsx,gpsy; 602 | int res = -1; 603 | g_gcj_encryptor.encrypt(xmid,ymid,xmidnew,ymidnew); 604 | if (dis(xmidnew,ymidnew,realgcjx,realgcjy) <= 1e-6) 605 | { 606 | gpsx = xmid; 607 | gpsy = ymid; 608 | res = 0; 609 | } 610 | else 611 | { 612 | while(1) 613 | {//Óеü´úµÄ±ØÒª 614 | double x1 = xmid - cellsize,x1new = 0; 615 | double y1 = ymid + cellsize,y1new = 0; 616 | double x2 = xmid - cellsize,x2new = 0; 617 | double y2 = ymid - cellsize,y2new = 0; 618 | double x3 = xmid + cellsize,x3new = 0; 619 | double y3 = ymid - cellsize,y3new = 0; 620 | double x4 = xmid + cellsize,x4new = 0; 621 | double y4 = ymid + cellsize,y4new = 0; 622 | g_gcj_encryptor.encrypt(x1,y1,x1new,y1new); 623 | g_gcj_encryptor.encrypt(x2,y2,x2new,y2new); 624 | g_gcj_encryptor.encrypt(x3,y3,x3new,y3new); 625 | g_gcj_encryptor.encrypt(x4,y4,x4new,y4new); 626 | double dis1 = dis(x1new,y1new,realgcjx,realgcjy); 627 | double dis2 = dis(x2new,y2new,realgcjx,realgcjy); 628 | double dis3 = dis(x3new,y3new,realgcjx,realgcjy); 629 | double dis4 = dis(x4new,y4new,realgcjx,realgcjy); 630 | if (dis1 < 1e-6) 631 | { 632 | gpsx = x1; 633 | gpsy = y1; 634 | res = 0; 635 | break; 636 | } 637 | if (dis2 < 1e-6) 638 | { 639 | gpsx = x2; 640 | gpsy = y2; 641 | res = 0; 642 | break; 643 | } 644 | if (dis3 < 1e-6) 645 | { 646 | gpsx = x3; 647 | gpsy = y3; 648 | res = 0; 649 | break; 650 | } 651 | if (dis4 < 1e-6) 652 | { 653 | gpsx = x4; 654 | gpsy = y4; 655 | res = 0; 656 | break; 657 | } 658 | //Ëĸö¶¼²»Îª0 659 | double w1 = 1/dis1, w2 = 1/dis2, w3 = 1/dis3, w4 = 1/dis4; 660 | xmid = ( x1 * w1 + x2 * w2 + x3 * w3 + x4 * w4 )/(w1 + w2 + w3 + w4); 661 | ymid = ( y1 * w1 + y2 * w2 + y3 * w3 + y4 * w4 )/(w1 + w2 + w3 + w4); 662 | g_gcj_encryptor.encrypt(xmid,ymid,xmidnew,ymidnew); 663 | double dismid = dis(xmidnew,ymidnew,realgcjx,realgcjy); 664 | if ( dismid <= 1e-6) 665 | { 666 | gpsx = xmid; 667 | gpsy = ymid; 668 | res = 0; 669 | break; 670 | } 671 | cellsize *= 0.6; 672 | if (cellsize < 1e-6) 673 | { 674 | gpsx = gpsy = -1; 675 | res = -1; 676 | break; 677 | } 678 | } 679 | } 680 | 681 | if (res == 0) 682 | { 683 | newxy->x = gpsx; 684 | newxy->y = gpsy; 685 | } 686 | return res; 687 | } 688 | 689 | int valid(const char * str) { 690 | if(strncmp(str, "wgs84", 5) == 0 || strncmp(str, "gcj02", 5) == 0) 691 | { 692 | return 1; 693 | } 694 | 695 | if (strncmp(str, "bd09", 4) == 0) { 696 | int len = strlen(str); 697 | if (strcmp(str + len - 2, "ll") == 0 || strcmp(str + len - 2, "mc") == 0) { 698 | return 1; 699 | } 700 | else 701 | { 702 | return 0; 703 | } 704 | } 705 | 706 | return 0; 707 | } 708 | 709 | int coordtrans(const char *from, const char *to, double oldx, double oldy, double &newx, double &newy) 710 | { 711 | if (!valid(from) || !valid(to)) { 712 | return -1; 713 | } 714 | 715 | if (strcmp(from, to) == 0) { 716 | newx = oldx; 717 | newy = oldy; 718 | return 0; 719 | } 720 | 721 | int from_len = strlen(from), to_len = strlen(to); 722 | dpoint_t oldxy(oldx, oldy), newxy; 723 | 724 | if (strcmp(from + from_len - 2, "mc") == 0) { 725 | /* ħ¿¨ÍÐת¾­Î³¶È */ 726 | oldxy = mc2ll(oldxy); 727 | } 728 | 729 | if (strncmp(from, to, (from_len < to_len ? from_len : to_len) - 2) != 0) { 730 | 731 | /* µÚÒ»²½ÏȰѴ«ÈëµÄ×ø±êת³É¹ú²â¾Ö×ø±ê */ 732 | if (strncmp(from, "wgs84", 5) == 0) { 733 | /* ¹ú¼Ê×ø±êÏȾ­¹ý¹ú²â¾ÖÒ»´Î¼ÓÃÜ */ 734 | if (g_gcj_encryptor.encrypt(oldxy, &oldxy) != 0) { 735 | return -1; 736 | } 737 | } else if (strncmp(from, "bd09", 4) == 0) { 738 | /* °Ù¶È×ø±êÏȽâÃܳɹú²â¾Ö×ø±ê */ 739 | if (bd_decrypt(oldxy, &oldxy) != 0) { 740 | return -1; 741 | } 742 | } 743 | 744 | /* µÚ¶þ²½°Ñ¹ú²â¾Ö×ø±êת³ÉÄ¿±ê×ø±ê */ 745 | if (strncmp(to, "wgs84", 5) == 0) { 746 | /* ¹ú²â¾Ö½âÃܺó¾ÍÊǹú¼Ê×ø±ê */ 747 | if (gcj_decrypt(oldxy, &oldxy) != 0) { 748 | return -1; 749 | } 750 | } else if (strncmp(to, "bd09", 4) == 0) { 751 | /* ¹ú²â¾Ö¼ÓÃܳɰٶÈ×ø±ê */ 752 | if (bd_encrypt(oldxy, &oldxy) != 0) { 753 | return -1; 754 | } 755 | } 756 | } 757 | 758 | /* Èç¹ûÐèÒªÔٴӰٶȾ­Î³¶Èת³É°Ù¶Èħ¿¨ÍÐ */ 759 | if (strcmp(to + to_len - 2, "mc") == 0) { 760 | newxy = ll2mc(oldxy); 761 | } else { 762 | newxy = oldxy; 763 | } 764 | 765 | newx = newxy.x; 766 | newy = newxy.y; 767 | return 0; 768 | } 769 | 770 | --------------------------------------------------------------------------------