[mobilesafe] 17_火星坐标系统

Android 4.0

火星坐标系统 

     国家保密插件,也叫做加密插件或者加偏或者SM模组,其实就是对真实坐标系统进行人为的加偏处理,按照几行代码的算法,将真实的坐标加密成虚假的坐标,而这个加偏并不是线性的加偏,所以各地的偏移情况都会有所不同。而加密后的坐标也常被人称为火星坐标系统。

       所有的电子地图所有的导航设备,都需要加入国家保密插件。第一步,地图公司测绘地图,测绘完成后,送 到国家测绘局,将真实坐标的电子地图,加密成“火星坐标”,这样的地图才是可以出版和发布的,然后才可以让GPS公司处理。第二步,所有的GPS公司,只要需要汽车导航的,需要用到导航电子地图的,统统需要在软件中加入国家保密算法,将COM口读出来的真实的坐标信号,加密转换成国家要求的保密的坐标,这样,GPS导航仪和导航电子地图就可以完全匹配,GPS也就可以正常工作。

转换工具和数据库
1、Demo.java
package cn.zengfansheng.mark;
/**
 * 坐标转换
 * @author hacket
 *
 */
public class Demo {
    public static void main(String[] args) throws Exception {
        ModifyOffset modifyOffset = ModifyOffset.getInstance(Demo.class
                .getClassLoader().getResourceAsStream("axisoffset.dat"));
        // 111.599,26.21 经度,纬度
        double longtitude = 111.59928293; // 经度
        double latitude = 26.2100881;// 纬度
        PointDouble pt = new PointDouble(longtitude, latitude);
        // 转成真实坐标
        PointDouble realPoint = modifyOffset.s2c(pt);//
        System.out.println(realPoint);
        // x=111.60451544453608, y=26.206613768669037
    }
}
2、ModifyOffset.java
package cn.zengfansheng.mark;
 
import java.io.InputStream;
import java.io.ObjectInputStream;
 
/**
* 火星地球坐标转化.地图坐标修偏
*
*/

public class ModifyOffset {
    private static ModifyOffset modifyOffset;
    static double[] X = new double[660 * 450];
    static double[] Y = new double[660 * 450];
 
 
    private ModifyOffset(InputStream inputStream) throws Exception {
        init(inputStream);
    }
 
    public synchronized static ModifyOffset getInstance(InputStream is) throws Exception {
        if (modifyOffset == null) {
            modifyOffset = new ModifyOffset(is);
        }
        return modifyOffset;
    }
 
    public void init(InputStream inputStream) throws Exception {
        ObjectInputStream in = new ObjectInputStream(inputStream);
        try {
            int i = 0;
            while (in.available() > 0) {
                if ((i & 1) == 1) {
                    Y[(i - 1) >> 1] = in.readInt() / 100000.0d;
                    ;
                } else {
                    X[i >> 1] = in.readInt() / 100000.0d;
                    ;
                }
                i++;
            }
        } finally {
            if (in != null)
                in.close();
        }
    }
 
    // standard -> china
    /**
     * 国际标准的坐标→中国的坐标
     * @param pt  PointDouble点
     * @return
     */

    public PointDouble s2c(PointDouble pt) {
        int cnt = 10;
        double x = pt.x, y = pt.y;
        while (cnt-- > 0) {
            if (x < 71.9989d || x > 137.8998d || y < 9.9997d || y > 54.8996d)
                return pt;
            int ix = (int) (10.0d * (x - 72.0d));
            int iy = (int) (10.0d * (y - 10.0d));
            double dx = (x - 72.0d - 0.1d * ix) * 10.0d;
            double dy = (y - 10.0d - 0.1d * iy) * 10.0d;
            x = (x + pt.x + (1.0d - dx) * (1.0d - dy) * X[ix + 660 * iy] + dx
                    * (1.0d - dy) * X[ix + 660 * iy + 1] + dx * dy
                    * X[ix + 660 * iy + 661] + (1.0d - dx) * dy
                    * X[ix + 660 * iy + 660] - x) / 2.0d;
            y = (y + pt.y + (1.0d - dx) * (1.0d - dy) * Y[ix + 660 * iy] + dx
                    * (1.0d - dy) * Y[ix + 660 * iy + 1] + dx * dy
                    * Y[ix + 660 * iy + 661] + (1.0d - dx) * dy
                    * Y[ix + 660 * iy + 660] - y) / 2.0d;
        }
        return new PointDouble(x, y);
    }
 
    // china -> standard
    /**
     * 中国坐标点→国家坐标点
     * @param pt
     * @return
     */

    public PointDouble c2s(PointDouble pt) {
        int cnt = 10;
        double x = pt.x, y = pt.y;
        while (cnt-- > 0) {
            if (x < 71.9989d || x > 137.8998d || y < 9.9997d || y > 54.8996d)
                return pt;
            int ix = (int) (10.0d * (x - 72.0d));
            int iy = (int) (10.0d * (y - 10.0d));
            double dx = (x - 72.0d - 0.1d * ix) * 10.0d;
            double dy = (y - 10.0d - 0.1d * iy) * 10.0d;
            x = (x + pt.x - (1.0d - dx) * (1.0d - dy) * X[ix + 660 * iy] - dx
                    * (1.0d - dy) * X[ix + 660 * iy + 1] - dx * dy
                    * X[ix + 660 * iy + 661] - (1.0d - dx) * dy
                    * X[ix + 660 * iy + 660] + x) / 2.0d;
            y = (y + pt.y - (1.0d - dx) * (1.0d - dy) * Y[ix + 660 * iy] - dx
                    * (1.0d - dy) * Y[ix + 660 * iy + 1] - dx * dy
                    * Y[ix + 660 * iy + 661] - (1.0d - dx) * dy
                    * Y[ix + 660 * iy + 660] + y) / 2.0d;
        }
        return new PointDouble(x, y);
    }
 
}
 
class PointDouble {
    double x, y;
 
    PointDouble(double x, double y) {
        this.x = x;
        this.y = y;
    }
 
    public String toString() {
        return "x=" + x + ", y=" + y;
    }
}
使用前: 26.2100881,111.59928293  (纬度,经度)

使用后:26.206613768669037,111.60451544453608