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." "; @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." "; $left=($recordCount/8) +1; }else if($jwd>$myxy){ //echo " < ".$myxy." "; $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); ?> |
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; } } } |