Public Domain library for rectifying Chinese coordinates
Switch branches/tags
Nothing to show
Clone or download
Fetching latest commit…
Cannot retrieve the latest commit at this time.
Permalink
Failed to load latest commit information.
cpp
docs
haskell
js
lua
matlab
pgsql
py
racket
LICENSE.gplv3
README.md

README.md

PRCoords

People's Rectified Coordinates (PRCoords) is a cross-language implementation of "public secret" Chinese coordinate obfuscation methods including GCJ-02 and BD-09, along with general deobfuscation methods previously established in ChinaMapShift, eviltransform, and geoChina. (Referring to the process of replacing straight lines with wavy ones as a "transform" is euphemism overdone.)

Languages

  • JavaScript
  • Python
  • (Obj-)C/C++ (C structs)
    • Makefile with install
  • Ruby
  • Swift
  • C#
  • Haskell (GCJ only; data structure incomplete)
    • need to move googollee/eviltransform#54 here sometime.
  • Java
  • Matlab/Octave
    • too lazy to split the files. also expand "caijun"
  • PGSQL
  • Typed Racket
    • is it done?

(should I split them into submodules?)

For languages not yet supported, we recommend you to check for eviltransform (MIT) or geoChina (GPLv3, R) instead.

API

PRCoord's APIs operate on, and returns, dedicated structures for coordinates. In API names, we generally refer to WGS-84 as wgs, GCJ-02 as gcj, and BD-09 (lat-lon) as bd.

Inverse functions

The obfuscations generally have these properties to maintain basic usefulness:

  1. obfs(coord) is sort of close to coord.
  2. obfs(a) - obfs(b) is usually close to a - b. (The closer a and b are to each other, the better it works.)

In general two approaches of inverting the "forward" obfuscations, or working from obfs(coord) to coord, are implemented:

  • Run it backwards: obfs(coord) is never too far from coord, so just use  obfs(obfs(coord)) - obfs(coord) to estimate obfs(coord) - coord.
  • Iterate a bit: Get a rough guess somehow, and just use property 2 to estimate the remaining error as obfs(guess) - obfs(coord) and correct the guess.

You can read on the demo page about how well these methods work from the ΔRoundtrip entry. Unless you are doing archival work, you generally don't have to iterate.

The "in China" sanity check

Typically PRCoords is only supposed to be ran on obfuscated input data, which are primarily Chinese coordinates. For this reason, initial implementations include this very very rough sanity check that spans a rectangular region on a mercator-projected map. This check can be overridden by passing a boolean value, or may be not at all implemented in certain languages if I am not in the right mood for doing silly things.

There is an "insane" sanity check intended to approximate the range of Google and Baidu's distortion, intended for use by IITC: js/insane_is_in_china.js. It is basically a ray-casting polygon check with 70 vertices. You, as the caller, should still be responsible for telling whether a point is part of the gov-screwed Chinese data.

Why another wheel?

  • Public Domain
  • Clean API based on pairs of coordinates
  • Need to find a place for this sarcastic name

Physical PRCoords

You can print out a minimal copy of PRCoords with this PDF file. I am working on some better options in issue #2. A fairly simple tote bag with an older version of the PDF is available from Teespring.

Feel free to print and sell t-shirts with the PDF file! It is put in the Public Domain, so you don't have to pay me for that. You can always fund my subversive activities on Patreon though.

License

Unless otherwise mentioned, all files in this package, including this README file, are dual-licensed under:

GPL is only included for fun here.

Sources

  • Algorithm.Coords.Converter from EMQ (GitHub mirror) is probably the GCJ leak. It is a JSP project "for demonstrating GIS systems", probably done by some government contractor.
    • There is some randomness in the GCJ deltas on both axes: one sin invocation and one LCG. Each add a maximum of 1 meter of error.
  • on4wp7 (2013) is the earliest rationalized GCJ (forward) implementation. No randomness is attempted.
  • ChinaMapShift (2014) figured out the quick iterative inverse for GCJ. I learned about it via geoChina first and generalized it here.
  • BD-09 is not very well sourced, but pycoordtrans (2014) seems to have it.

See also

  • Restrictions on geographic data in China: this Wikipedia article outlines impacts and the "common secret" deobfuscation approach.
  • eviltransform is among the most popular cross-language soltions to the problem. It borrows its name directly from EvilTransform.cs, an early refactored version of a raw-flesh Java implementation.
    • Since June 2016, eviltransform contains numerous parameter errors that compromise its output, especially for BD-09. See googollee/eviltransform#43, #53 and #44 for corrections. As of April 2018 these problems are not fixed.
  • geoChina by caijun is a clear, concise implementation written in R. It features the iterative method from ChinaMapShift.
  • I am planning on moving some of the comments on the algorithm found in my initial JavaScript implementation to the GitHub Wiki. I don't think anyone is going to be interested in copying comments on these idiocy when translating my implementation to other languages.

Oh, and finally, here is an official news report on that particular [bleep] who came up with GCJ-02.