GPS纠偏0.01精度工具/算法案例

2016-09-28 14:57:22 root 231

 

精度工具下载 :http://map.yanue.net/gps.html
 
该校正适用于 Google map China, Microsoft map china ,MapABC 等,因为这些地图构成方法是一样的需要offset.dat文件,该文件为0.01精度校正数据, 有需要者请联系本网站人员, 非免费版本。
 
算法演示:
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
<?php
/*
   代码功能:利用0.01精度校正库文件修正中国地图经纬度偏移。
*/
header("Content-Type:text/html; charset=utf-8");
define('__dat_db__' 'offset.dat' );// DAT数据文件
define('datmax' , 9813675 );// 数据条数-结束记录
 
// # offset.php?lat=39.914914&lon=116.460633
$lon=$_GET['lon'];
$lat=$_GET['lat'];
$tmplon=intval($lon * 100);
$tmplat=intval($lat * 100);
//经度到像素X值
function lngToPixel($lng,$zoom) {
return ($lng+180)*(256<<$zoom)/360;
}
//像素X到经度
function pixelToLng($pixelX,$zoom){
return $pixelX*360/(256<<$zoom)-180;
}
//纬度到像素Y
function latToPixel($lat$zoom) {
$siny = sin($lat * pi() / 180);
$y=log((1+$siny)/(1-$siny));
return (128<<$zoom)*(1-$y/(2*pi()));
}
//像素Y到纬度
function pixelToLat($pixelY$zoom) {
$y = 2*pi()*(1-$pixelY /(128 << $zoom));
$z = pow(M_E, $y);
$siny = ($z -1)/($z +1);
return asin($siny) * 180/pi();
}
 
function xy_fk( $number ){
        $fp fopen(__dat_db__,"rb"); //■1■.将 r 改为 rb
        $myxy=$number;//#"112262582";
        $left = 0;//开始记录
        $right = datmax;//结束记录
 
        //采用用二分法来查找查数据
        while($left <= $right){
            $recordCount =(floor(($left+$right)/2))*8; //取半
            //echo "运算:left=".$left." right=".$right." midde=".$recordCount."<br />";
            @fseek $fp$recordCount , SEEK_SET ); //设置游标
            $c fread($fp,8); //读8字节
            $lon = unpack('s',substr($c,0,2));
            $lat = unpack('s',substr($c,2,2));
            $x = unpack('s',substr($c,4,2));
            $y = unpack('s',substr($c,6,2));
            $jwd=$lon[1].$lat[1];
            //echo "找到的经纬度:".$jwd;
            if ($jwd==$myxy){
               fclose($fp);
               return $x[1]."|".$y[1];
               break;
            }else if($jwd<$myxy){
               //echo " > ".$myxy."<br />";
               $left=($recordCount/8) +1;
            }else if($jwd>$myxy){
               //echo " < ".$myxy."<br />";
               $right=($recordCount/8) -1;
            }
 
        }
        fclose($fp);
}
 
$offset =xy_fk($tmplon.$tmplat);
$off=explode('|',$offset);
$lngPixel=lngToPixel($lon,18)+$off[0];
$latPixel=latToPixel($lat,18)+$off[1];
 
echo pixelToLat($latPixel,18).",".pixelToLng($lngPixel,18);
 
?>
c#算法
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;   
 
namespace MapDigit.GIS
{
    public class GeoLatLng
    {   
 
        public GeoLatLng(double latitude, double longitude)
        {
            this.latitude = latitude;
            this.longitude = longitude;
        }
        public double latitude;
        public double longitude;
    }   
 
    public class GeoPoint
    {
        public GeoPoint(int x, int y)
        {
            this.x = x;
            this.y = y;
        }
        public int x;
        public int y;
    }   
 
    public class OffsetInChina
    {
        //用于从GPS坐标转换为偏移后坐标
        public static GeoLatLng fromEarthToMars(GeoLatLng earth)
        {
            GeoPoint ptOffset = getOffset(earth.latitude, earth.longitude);
            if (ptOffset.x != 0 || ptOffset.y != 0)
            {
                int pixelX, pixelY;
                TileSystem.LatLongToPixelXY(earth.latitude, earth.longitude, 18, out pixelX, out pixelY);
                GeoPoint pt = new GeoPoint(pixelX, pixelY);
                pt.x += ptOffset.x;
                pt.y += ptOffset.y;
                double latitude, longitude;
                TileSystem.PixelXYToLatLong(pt.x, pt.y, 18, out latitude, out longitude);
                return new GeoLatLng(latitude, longitude);   
 
            }
            else
            {
                return new GeoLatLng(earth.latitude, earth.longitude);
            }   
 
        }   
 
        //用于将偏移后坐标转成真实的坐标
        public static GeoLatLng fromMarToEarth(GeoLatLng mars)
        {
            GeoPoint ptOffset = getOffset(mars.latitude, mars.longitude);
            if (ptOffset.x != 0 || ptOffset.y != 0)
            {
                int pixelX, pixelY;
                TileSystem.LatLongToPixelXY(mars.latitude, mars.longitude, 18, out pixelX, out pixelY);
                GeoPoint pt = new GeoPoint(pixelX, pixelY);
                pt.x -= ptOffset.x;
                pt.y -= ptOffset.y;
                double latitude, longitude;
                TileSystem.PixelXYToLatLong(pt.x, pt.y, 18, out latitude, out longitude);
                return new GeoLatLng(latitude, longitude);   
 
            }
            else
            {
                return new GeoLatLng(mars.latitude, mars.longitude);
            }
        }   
 
        //这个函数用于将需要查询的经纬度转成最近的0.01分度值,无插值
        //也可以自行实现插值
        private static GeoPoint getQueryLocation(double latitude, double longitude)
        {
            int lat = (int)(latitude * 100);
            int lng = (int)(longitude * 100);
            double lat1 = ((int)(latitude * 1000 + 0.499999)) / 10.0;
            double lng1 = ((int)(longitude * 1000 + 0.499999)) / 10.0;
            for (double x = longitude; x < longitude + 1; x += 0.5)
            {
                for (double y = latitude; x < latitude + 1; y += 0.5)
                {
                    if (x <= lng1 && lng1 < (x + 0.5) && lat1 >= y && lat1 < (y + 0.5))
                    {
                        return new GeoPoint((int)(x + 0.5), (int)(y + 0.5));
                    }
                }
            }
            return new GeoPoint(lng, lat);
        }   
 
        private static GeoPoint getOffset(double longitude, double latitude)
        {
            //这个函数用于返回查询结果,就是从校正数据中返回18级时x,y方偏移
            //可以自行实现
            return null;
        }   
 
    }
}