定位方法,以及纠偏的调用

// 开发调试环境: win8.1+Delphi XE8+TCL M3GS(android 5.0.2 X64)  
// 已实现功能  
// 1.获取手机GPS定位得到的坐标  
// 2.纠偏系统获取的坐标为腾讯地图坐标  
// 3.用纠偏后的坐标简单调用腾讯地图并定位  
// 4.判断开启系统是否打开定位,如未打开则弹出系统位置服务设置界面  

unit Unit1;  
  
interface  
  
uses  
  System.SysUtils, System.Types, System.UITypes, System.Classes,  
  System.Variants,  
  FMX.Types, FMX.Controls, FMX.Forms, FMX.Graphics, FMX.Dialogs, System.Sensors,  
  System.Sensors.Components, FMX.WebBrowser, FMX.StdCtrls, FMX.ListBox,  
  FMX.Controls.Presentation, FMX.Layouts, FMX.ScrollBox, FMX.Memo;  
  
type  
  TForm1 = class(TForm)  
    ListBox1: TListBox;  
    ListBoxHeader1: TListBoxHeader;  
    Label1: TLabel;  
    ListBoxItem1: TListBoxItem;  
    ListBoxItem2: TListBoxItem;  
    ListBoxItem3: TListBoxItem;  
    Switch1: TSwitch;  
    Label2: TLabel;  
    Label3: TLabel;  
    WebBrowser1: TWebBrowser;  
    LocationSensor1: TLocationSensor;  
    Memo1: TMemo;  
    procedure Switch1Switch(Sender: TObject);  
    procedure LocationSensor1LocationChanged(Sender: TObject;  
      const OldLocation, NewLocation: TLocationCoord2D);  
  private  
    { Private declarations }  
  public  
    { Public declarations }  
  end;  
  
var  
  Form1: TForm1;  
  
implementation  
  
{$R *.fmx}  
  
uses GLGSPCorrect, // GPS 纠偏及逆转单元文件  
  Androidapi.JNI.GraphicsContentViewText,  
  Androidapi.Helpers,  
  Androidapi.JNI.Provider;  
  
procedure TForm1.LocationSensor1LocationChanged(Sender: TObject;  
  const OldLocation, NewLocation: TLocationCoord2D);  
// 申明腾讯地图地址为常量  
const  
  sTencentMapURL: String = 'http://apis.map.qq.com/uri/v1/geocoder?coord=%s,%s';  
var  
  lat: Double;  
  lon: Double;  
begin  
  // 标签控件显示经度和纬度  
  Label2.Text := NewLocation.Latitude.ToString;  
  Label3.Text := NewLocation.Longitude.ToString;  
  // 赋值给经度变量和纬度变量  
  lat := NewLocation.Latitude;  
  lon := NewLocation.Longitude;  
  // 纠偏GPS坐标为腾讯坐标  
  GLGSPCorrect.TGLGPSCorrect.GPS_to_Google(lat, lon);  
  // web控件定位并显示纠偏后的地图  
  WebBrowser1.Navigate(Format(sTencentMapURL, [lat.ToString, lon.ToString]));  
end;  
  
procedure TForm1.Switch1Switch(Sender: TObject);  
var  
  Provider: string;  
  Settings_secure: TJSettings_Secure;  
  Intent: JIntent;  
begin  
  // 获取已开启的定位方式(gps,network)  
  Provider := JStringToString(Settings_secure.JavaClass.getString  
    (SharedActivityContext.getContentResolver,  
    TJSettings_system.JavaClass.LOCATION_PROVIDERS_ALLOWED));  
  // 输出获取到的定位方式  
  Memo1.Lines.Add(Provider);  
  // 判断返回的定位方式中是否有GPS或network定位  
  if pos('gps', Provider) or pos('network', Provider) = 0 then  
  begin  
    // 如无定位则弹出位置设置界面  
    Intent := TJIntent.Create;  
    Intent.setAction(TJSettings.JavaClass.ACTION_LOCATION_SOURCE_SETTINGS);  
    SharedActivity.startActivity(Intent);  
  end;  
  // 通过滑动按钮控制GPS控件  
  LocationSensor1.Active := Switch1.IsChecked;  
end;  
  
end.
===================================

/// <remarks>
/// 由网上算法翻译过来
/// 谷哥,高德,腾讯,百度地图纠偏与逆转算法
/// 翻译人: /tp机器猫(5909386)  如有不对,请发邮件
/// </remarks>


unit GLGSPCorrect;


interface


const
  PI = 3.14159265358979324;
  x_pi = 3.14159265358979324 * 3000.0 / 180.0;


type
  TGLGPSCorrect = class
  private
    class procedure delta(var lat, lng: Double);
    class function transformLon(lat, lng: Double): Double;
    class function transformlat(lat, lng: Double): Double;


    /// <remarks>
    /// GPS坐标转到 Google Map、高德、腾讯
    /// </remarks>
    class procedure WGS84_to_GCJ02(var lat, lng: Double);
    /// <remarks>
    /// 从Google Map、高德、腾讯转到GPS坐标
    /// </remarks>
    class procedure GCJ02_to_WGS84(var lat, lng: Double); // 粗略
    class procedure GCJ02_to_WGS84Ex(var lat, lng: Double); // 精确


    /// <remarks>
    /// 从Google Map、高德、腾讯转到百度坐标
    /// </remarks>
    class procedure GCJ02_to_BD09(var lat, lng: Double);
    /// <remarks>
    /// 从百度转到 Google Map、高德、腾讯坐标
    /// </remarks>
    class procedure BD09_to_GCJ02(var lat, lng: Double);
  public
    class function OutOfChina(lat, lng: Double): Boolean;
    class function Distance(latA, lngA, latB, lngB: Double): Double;
    class procedure GPS_to_Google(var lat, lng: Double);
    class procedure Google_to_GPS(var lat, lng: Double);
    class procedure Gps_to_Baidu(var lat, lng: Double);
    class procedure Baidu_to_Gps(var lat, lng: Double);
    class procedure Google_to_Baidu(var lat, lng: Double);
    class procedure Baidu_to_Google(var lat, lng: Double);
  end;


implementation


uses
  Math;


class procedure TGLGPSCorrect.Baidu_to_Google(var lat, lng: Double);
begin
  BD09_to_GCJ02(lat, lng);
end;


class procedure TGLGPSCorrect.Baidu_to_Gps(var lat, lng: Double);
begin
  BD09_to_GCJ02(lat, lng);
  GCJ02_to_WGS84Ex(lat, lng);
end;


class procedure TGLGPSCorrect.BD09_to_GCJ02(var lat, lng: Double);
var
  x, y, z, theta: Double;
begin
  x := lng - 0.0065;
  y := lat - 0.006;
  z := sqrt(x * x + y * y) - 0.00002 * sin(y * x_pi);
  theta := ArcTan2(y, x) - 0.000003 * cos(x * x_pi);
  lng := z * cos(theta);
  lat := z * sin(theta);
end;


class procedure TGLGPSCorrect.delta(var lat, lng: Double);
const
  a = 6378245.0; // a: 卫星椭球坐标投影到平面地图坐标系的投影因子。
  ee = 0.00669342162296594323; // ee: 椭球的偏心率。
var
  dLat, dLng, radLat, magic, sqrtMagic: Double;
begin
  dLat := transformlat(lng - 105.0, lat - 35.0);
  dLng := transformLon(lng - 105.0, lat - 35.0);
  radLat := lat / 180.0 * PI;
  magic := sin(radLat);
  magic := 1 - ee * magic * magic;
  sqrtMagic := sqrt(magic);
  dLat := (dLat * 180.0) / ((a * (1 - ee)) / (magic * sqrtMagic) * PI);
  dLng := (dLng * 180.0) / (a / sqrtMagic * cos(radLat) * PI);


  lat := dLat;
  lng := dLng;
end;


class function TGLGPSCorrect.Distance(latA, lngA, latB, lngB: Double): Double;
const
  earthR = 6371000.0;
var
  x, y, s, alpha: Double;
begin
  x := cos(latA * PI / 180.0) * cos(latB * PI / 180.0) *
    cos((lngA - lngB) * PI / 180);
  y := sin(latA * PI / 180.0) * sin(latB * PI / 180.0);
  s := x + y;
  if (s > 1) then
    s := 1;
  if (s < -1) then
    s := -1;
  alpha := ArcCos(s);
  result := alpha * earthR;
end;


class procedure TGLGPSCorrect.GCJ02_to_BD09(var lat, lng: Double);
var
  x, y, z, theta: Double;
begin
  x := lng;
  y := lat;
  z := sqrt(x * x + y * y) + 0.00002 * sin(y * x_pi);
  theta := ArcTan2(y, x) + 0.000003 * cos(x * x_pi);
  lng := z * cos(theta) + 0.0065;
  lat := z * sin(theta) + 0.006;
end;


class procedure TGLGPSCorrect.GCJ02_to_WGS84(var lat, lng: Double);
var
  deltalat, delatlng: Double;
begin
  if OutOfChina(lat, lng) then
    exit;


  deltalat := lat;
  delatlng := lng;
  delta(deltalat, delatlng);


  lat := lat - deltalat;
  lng := lng - delatlng;
end;


class procedure TGLGPSCorrect.GCJ02_to_WGS84Ex(var lat, lng: Double);
const
  initDelta = 0.01;
  threshold = 0.000000001;
var
  dLat, dLon, mLat, mLon, pLat, pLon, wgsLat, wgsLon: Double;
  i: integer;
begin
  dLat := initDelta;
  dLon := initDelta;
  mLat := lat - dLat;
  mLon := lng - dLon;
  pLat := lat + dLat;
  pLon := lng + dLon;
  i := 0;
  while true do
  begin
    wgsLat := (mLat + pLat) / 2;
    wgsLon := (mLon + pLon) / 2;
    WGS84_to_GCJ02(wgsLat, wgsLon);
    dLat := wgsLat - lat;
    dLon := wgsLon - lng;
    if ((abs(dLat) < threshold) and (abs(dLon) < threshold)) then
      break;


    if (dLat > 0) then
      pLat := wgsLat
    else
      mLat := wgsLat;
    if (dLon > 0) then
      pLon := wgsLon
    else
      mLon := wgsLon;
    Inc(i);
    if i > 10000 then
      break;
  end;
  lat := wgsLat;
  lng := wgsLon;
end;


class procedure TGLGPSCorrect.Google_to_Baidu(var lat, lng: Double);
begin
  GCJ02_to_BD09(lat, lng);
end;


class procedure TGLGPSCorrect.Google_to_GPS(var lat, lng: Double);
begin
  GCJ02_to_WGS84Ex(lat, lng);
end;


class procedure TGLGPSCorrect.Gps_to_Baidu(var lat, lng: Double);
begin
  WGS84_to_GCJ02(lat, lng);
  GCJ02_to_BD09(lat, lng);
end;


class procedure TGLGPSCorrect.GPS_to_Google(var lat, lng: Double);
begin
  WGS84_to_GCJ02(lat, lng);
end;


class function TGLGPSCorrect.OutOfChina(lat, lng: Double): Boolean;
begin
  result := False;
  if (lng < 72.004) or (lng > 137.8347) then
    result := true;
  if (lat < 0.8293) or (lat > 55.8271) then
    result := true;
end;


class function TGLGPSCorrect.transformlat(lat, lng: Double): Double;
begin
  result := -100.0 + 2.0 * lat + 3.0 * lng + 0.2 * lng * lng + 0.1 * lat * lng +
    0.2 * sqrt(abs(lat));
  result := result + (20.0 * sin(6.0 * lat * PI) + 20.0 * sin(2.0 * lat * PI)) *
    2.0 / 3.0;
  result := result + (20.0 * sin(lng * PI) + 40.0 * sin(lng / 3.0 * PI)) *
    2.0 / 3.0;
  result := result + (160.0 * sin(lng / 12.0 * PI) + 320 * sin(lng * PI / 30.0))
    * 2.0 / 3.0;
end;


class function TGLGPSCorrect.transformLon(lat, lng: Double): Double;
begin
  result := 300.0 + lat + 2.0 * lng + 0.1 * lat * lat + 0.1 * lat * lng + 0.1 *
    sqrt(abs(lat));
  result := result + (20.0 * sin(6.0 * lat * PI) + 20.0 * sin(2.0 * lat * PI)) *
    2.0 / 3.0;
  result := result + (20.0 * sin(lat * PI) + 40.0 * sin(lat / 3.0 * PI)) *
    2.0 / 3.0;
  result := result + (150.0 * sin(lat / 12.0 * PI) + 300.0 *
    sin(lat / 30.0 * PI)) * 2.0 / 3.0;
end;


class procedure TGLGPSCorrect.WGS84_to_GCJ02(var lat, lng: Double);
var
  deltalat, delatlng: Double;
begin
  if (OutOfChina(lat, lng)) then
    exit;


  deltalat := lat;
  delatlng := lng;
  delta(deltalat, delatlng);
  lat := lat + deltalat;
  lng := lng + delatlng;
end;


end.
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值