本工具调用高德地图逆地理编码api,根据高的地图逆地理编码api,实现根据经纬度获取位置描述。
总体设计逻辑,窗体采用WPF,通过属性的方式传递交互对象,核心处理逻辑写到button的执行逻辑中。

- <Window x:Class="DayDreamInGISTool.GeoCoding.InverseGCWPF"
- xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
- xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
- xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
- xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
- mc:Ignorable="d" Title="逆地理编码" ResizeMode="NoResize" WindowStartupLocation="CenterScreen"
- Width="500" Height="480">
- <Grid Margin="5">
- <Grid.RowDefinitions>
- <RowDefinition Height="40">RowDefinition>
- <RowDefinition Height="40">RowDefinition>
- <RowDefinition Height="40">RowDefinition>
- <RowDefinition Height="40">RowDefinition>
- <RowDefinition Height="40">RowDefinition>
- <RowDefinition>RowDefinition>
- <RowDefinition>RowDefinition>
- <RowDefinition Height="40">RowDefinition>
- Grid.RowDefinitions>
- <Grid>
- <Grid.ColumnDefinitions>
- <ColumnDefinition Width="100">ColumnDefinition>
- <ColumnDefinition>ColumnDefinition>
- Grid.ColumnDefinitions>
- <Label Content="高德地图Token" VerticalAlignment="Center">Label>
- <TextBox Grid.Column="1" VerticalAlignment="Center" Name="txtGDToken" Height="22" Text="b1670be70e419c2a112957742e55a756">TextBox>
- Grid>
-
- <Grid Grid.Row="1">
- <Grid.ColumnDefinitions>
- <ColumnDefinition Width="100">ColumnDefinition>
- <ColumnDefinition>ColumnDefinition>
- Grid.ColumnDefinitions>
- <Label Content="图层" VerticalAlignment="Center" HorizontalAlignment="Right">Label>
- <ComboBox Grid.Column="1" Name="cmbLayer" VerticalAlignment="Center" Height="23" SelectionChanged="cmbLayer_SelectionChanged">ComboBox>
- Grid>
-
- <Grid Grid.Row="2">
- <Grid.ColumnDefinitions>
- <ColumnDefinition Width="100">ColumnDefinition>
- <ColumnDefinition>ColumnDefinition>
- Grid.ColumnDefinitions>
- <Label Content="经度" VerticalAlignment="Center" HorizontalAlignment="Right">Label>
- <ComboBox Grid.Column="1" Name="cmbLongtitude" VerticalAlignment="Center" Height="23">ComboBox>
- Grid>
-
- <Grid Grid.Row="3">
- <Grid.ColumnDefinitions>
- <ColumnDefinition Width="100">ColumnDefinition>
- <ColumnDefinition>ColumnDefinition>
- Grid.ColumnDefinitions>
- <Label Content="纬度" VerticalAlignment="Center" HorizontalAlignment="Right">Label>
- <ComboBox Grid.Column="1" VerticalAlignment="Center" Name="cmbLatitude" Height="23">ComboBox>
- Grid>
-
- <Grid Grid.Row="4">
- <Grid.ColumnDefinitions>
- <ColumnDefinition Width="100">ColumnDefinition>
- <ColumnDefinition>ColumnDefinition>
- Grid.ColumnDefinitions>
- <Label Content="位置" VerticalAlignment="Center" HorizontalAlignment="Right">Label>
- <ComboBox Grid.Column="1" VerticalAlignment="Center" Name="cmbLocation" Height="23">ComboBox>
- Grid>
-
- <Grid Grid.Row="5">
- <GroupBox Header="地址结构">
- <Grid Margin="45 5">
- <Grid.RowDefinitions>
- <RowDefinition>RowDefinition>
- <RowDefinition>RowDefinition>
- Grid.RowDefinitions>
- <Grid>
- <Grid.ColumnDefinitions>
- <ColumnDefinition>ColumnDefinition>
- <ColumnDefinition>ColumnDefinition>
- <ColumnDefinition>ColumnDefinition>
- <ColumnDefinition>ColumnDefinition>
- Grid.ColumnDefinitions>
- <CheckBox Grid.Column="0" Name="chkPro" IsChecked="False" VerticalAlignment="Center" Checked="chkPro_Checked">省CheckBox>
- <CheckBox Grid.Column="1" Name="chkCity" IsChecked="False" VerticalAlignment="Center" Checked="chkCity_Checked">市CheckBox>
- <CheckBox Grid.Column="2" Name="chkCounty" IsChecked="False" VerticalAlignment="Center" Checked="chkCounty_Checked">县/区CheckBox>
- <CheckBox Grid.Column="3" Name="chkTown" IsChecked="False" VerticalAlignment="Center" Checked="chkTown_Checked">街道/乡镇CheckBox>
- Grid>
- <Grid Grid.Row="1">
- <Label>示例Label>
- <TextBox Name="txtExample" VerticalAlignment="Center" HorizontalAlignment="Right" IsReadOnly="True">
- 北京市朝阳区望京街道方恒国际中心B座方恒国际
- TextBox>
- Grid>
-
- Grid>
- GroupBox>
- Grid>
-
-
- <Grid Grid.Row="6">
- <GroupBox Header="说明">
- <Grid Margin="8">
- <TextBlock TextWrapping="Wrap" LineHeight="20">
- <Run>本插件使用高德地图逆地理编码服务获取位置描述,经纬度需为wgs84或者cgcs2000的经纬度,如果token不能使用,请去高德图管网申请tokenRun>
- <LineBreak>LineBreak>
- <Hyperlink Click="Hyperlink_Click" NavigateUri="https://console.amap.com/dev/key/app"> https://console.amap.com/dev/key/appHyperlink>
- TextBlock>
-
- Grid>
- GroupBox>
- Grid>
-
-
- <Grid Grid.Row="7">
- <Grid.ColumnDefinitions>
- <ColumnDefinition>ColumnDefinition>
- <ColumnDefinition>ColumnDefinition>
- Grid.ColumnDefinitions>
- <Button Content="确定" Name="btnOK" Width="80" Height="30" VerticalAlignment="Center" HorizontalAlignment="Center" Click="btnOK_Click">Button>
- <Button Content="取消" Name="btnCancel" Width="80" Height="30" Grid.Column="1" VerticalAlignment="Center" HorizontalAlignment="Center" Click="btnCancel_Click">Button>
- Grid>
- Grid>
- Window>
- using System;
- using System.Collections.Generic;
- using System.Linq;
- using System.Text;
- using System.Threading.Tasks;
- using System.Windows;
- using System.Windows.Controls;
- using System.Windows.Data;
- using System.Windows.Documents;
- using System.Windows.Input;
- using System.Windows.Media;
- using System.Windows.Media.Imaging;
- using System.Windows.Navigation;
- using System.Windows.Shapes;
- using ESRI.ArcGIS.Carto;
- using ESRI.ArcGIS.Geometry;
- using ESRI.ArcGIS.Geodatabase;
- using System.CodeDom;
- using System.Diagnostics;
-
- namespace DayDreamInGISTool.GeoCoding
- {
- ///
- /// InverseGCWPF.xaml 的交互逻辑
- ///
- public partial class InverseGCWPF : Window
- {
- private IFeatureLayer pftlyr = null;
-
- public IFeatureLayer Pftlyr
- {
- get { return pftlyr; }
- set { pftlyr = value; }
- }
- private string xfdnm;
-
- public string Xfdnm
- {
- get { return xfdnm; }
- set { xfdnm = value; }
- }
- private string yfdnm;
-
- public string Yfdnm
- {
- get { return yfdnm; }
- set { yfdnm = value; }
- }
- private string locationfdnm;
-
- public string Locationfdnm
- {
- get { return locationfdnm; }
- set { locationfdnm = value; }
- }
- private string gdtoken;
-
- public string Gdtoken
- {
- get { return gdtoken; }
- set { gdtoken = value; }
- }
-
- private IMap pMap = null;
-
- string toolname = "DDGInverGeocoding";
- string keyname = "gdtoken";
- string tokenInReg = "";
-
- public InverseGCWPF()
- {
- InitializeComponent();
- pMap = ArcMap.Document.FocusMap;
- GISCommonHelper.CartoLyrHelper.setFeatureLyrCombox(ref cmbLayer, pMap, esriGeometryType.esriGeometryAny);
-
- try
- {
- object tt = GISCommonHelper.esriSystemHelper.getValueFromReg2(toolname, keyname);
- if (tt == null)
- {
-
- }
- else
- {
- tokenInReg = tt.ToString();
- this.txtGDToken.Text = tt.ToString();
- }
- }
- catch (Exception)
- {
-
- throw;
- }
-
- setExample();
- }
-
- private bool isPro;
-
- public bool IsPro
- {
- get { return isPro; }
- set { isPro = value; }
- }
- private bool isCity;
-
- public bool IsCity
- {
- get { return isCity; }
- set { isCity = value; }
- }
- private bool isCounty;
-
- public bool IsCounty
- {
- get { return isCounty; }
- set { isCounty = value; }
- }
- private bool isTown;
-
- public bool IsTown
- {
- get { return isTown; }
- set { isTown = value; }
- }
-
- private void cmbLayer_SelectionChanged(object sender, SelectionChangedEventArgs e)
- {
- if (cmbLayer.SelectedIndex != -1)
- {
- pftlyr = cmbLayer.SelectedValue as IFeatureLayer;
-
- GISCommonHelper.CartoFieldHelper.setFieldCombox(ref cmbLongtitude, pftlyr.FeatureClass.Fields, false,
- esriFieldType.esriFieldTypeDouble, esriFieldType.esriFieldTypeSingle);
- GISCommonHelper.CartoFieldHelper.setFieldCombox(ref cmbLatitude, pftlyr.FeatureClass.Fields, false,
- esriFieldType.esriFieldTypeDouble, esriFieldType.esriFieldTypeSingle);
- GISCommonHelper.CartoFieldHelper.setFieldCombox(ref cmbLocation, pftlyr.FeatureClass.Fields,false,esriFieldType.esriFieldTypeString);
-
- GISCommonHelper.CartoFieldHelper.setDftField(ref cmbLongtitude, p =>
- {
- if (p.alias_name.Contains("经度") || p.name.Contains("经度") || p.alias_name.Contains("Lng")
- || p.name.Contains("Lng") || p.alias_name.Contains("Longtitude") || p.name.Contains("Longtitude")
- || p.name.ToLower()=="x" || p.alias_name.ToLower()=="x")
- {
- return true;
- }
-
- return false;
- });
-
- GISCommonHelper.CartoFieldHelper.setDftField(ref cmbLatitude, p =>
- {
- if (p.alias_name.Contains("纬度") || p.name.Contains("纬度") || p.alias_name.Contains("Lat")
- || p.name.Contains("Lat") || p.alias_name.Contains("Latitude") || p.name.Contains("Latitude")
- || p.name.ToLower()=="y" || p.alias_name.ToLower()=="y")
- {
- return true;
- }
-
- return false;
- });
-
- GISCommonHelper.CartoFieldHelper.setDftField(ref cmbLocation, p =>
- {
- if (p.alias_name.Contains("位置") || p.name=="位置" || p.name.ToLower().Contains("location"))
- {
- return true;
- }
- else
- {
- return false;
- }
- });
- }
- }
-
- private void btnCancel_Click(object sender, RoutedEventArgs e)
- {
- this.DialogResult = false;
- }
-
- // 北京市朝阳区望京街道方恒国际中心B座方恒国际
- string pro = "浙江省";
- string city = "杭州市";
- string county = "上城区";
- string town = "四季青街道";
- string building = "钱江新城";
-
- private void btnOK_Click(object sender, RoutedEventArgs e)
- {
- if (pftlyr == null)
- {
- MessageBox.Show("请选择图层");
- return;
- }
-
- if (cmbLatitude.SelectedIndex == -1)
- {
- MessageBox.Show("请配置纬度字段");
- return;
- }
- else
- {
- yfdnm = cmbLatitude.SelectedValue.ToString();
- }
-
- if (cmbLongtitude.SelectedIndex == -1)
- {
- MessageBox.Show("请配置经度字段");
- return;
- }
- else
- {
- xfdnm = cmbLongtitude.SelectedValue.ToString();
- }
-
- if (cmbLocation.SelectedIndex == -1)
- {
- MessageBox.Show("请配置位置字段");
- return;
- }
- else
- {
- locationfdnm = cmbLocation.SelectedValue.ToString();
- }
-
- if (string.IsNullOrEmpty(txtGDToken.Text))
- {
- MessageBox.Show("高德地图token不能为空");
- }
- else
- {
- gdtoken = txtGDToken.Text;
- if(gdtoken== tokenInReg)
- {
-
- }
- else
- {
- //写入注册表
- GISCommonHelper.esriSystemHelper.setValueToReg2(toolname, new KeyValuePair<string, object>(keyname, gdtoken));
- }
- }
-
- this.DialogResult = true;
- }
-
- private void Hyperlink_Click(object sender, RoutedEventArgs e)
- {
- System.Windows.Documents.Hyperlink link = sender as System.Windows.Documents.Hyperlink;
- Process.Start(new ProcessStartInfo(link.NavigateUri.AbsoluteUri));
- }
-
- private void setExample()
- {
- string res = "";
- if (isPro)
- {
- res += pro;
- }
-
- if (isCity)
- {
- res+= city;
- }
-
- if (isCounty)
- {
- res += county;
- }
-
- if(isTown)
- {
- res += town;
- }
-
- res += building;
- txtExample.Text = res;
- }
-
- private void chkPro_Checked(object sender, RoutedEventArgs e)
- {
- isPro = chkPro.IsChecked.Value;
- setExample();
- }
-
- private void chkCity_Checked(object sender, RoutedEventArgs e)
- {
- isCity= chkCity.IsChecked.Value;
- setExample();
- }
-
- private void chkCounty_Checked(object sender, RoutedEventArgs e)
- {
- isCounty= chkCounty.IsChecked.Value;
- setExample();
- }
-
- private void chkTown_Checked(object sender, RoutedEventArgs e)
- {
- isTown= chkTown.IsChecked.Value;
- setExample();
- }
- }
- }
- using System;
- using System.Collections.Generic;
- using System.Text;
- using System.IO;
- using ESRI.ArcGIS.Geodatabase;
- using ESRI.ArcGIS.Geometry;
- using ESRI.ArcGIS.Carto;
- using System.Windows;
- using GISCommonHelper;
- using DayDreamInGISTool.Assister;
- using Newtonsoft.Json.Linq;
-
- namespace DayDreamInGISTool.GeoCoding
- {
- ///
- /// 高德地图逆地理编码
- /// 地址结构点选 OO
- /// 处理消息/状态写入 OO
- /// 进度条 OO
- /// token限制 默认token限速
- ///
- public class btnInverseGeocoding : ESRI.ArcGIS.Desktop.AddIns.Button
- {
- public btnInverseGeocoding()
- {
- }
-
- ESRI.ArcGIS.esriSystem.ITrackCancel trackCancel = null;
- ESRI.ArcGIS.esriSystem.IStepProgressor stepProgressor = null;
- ESRI.ArcGIS.Framework.IProgressDialog2 progressDialog2 = null;
-
- InverseGCWPF iwp = null;
- string tsttoken = "";
- bool isTest = false;
-
- protected override void OnClick()
- {
- try
- {
- iwp = new InverseGCWPF();
- if (iwp.ShowDialog().Value)
- {
- if(iwp.Gdtoken== tsttoken)
- {
- MessageBox.Show("测试token,每次处理不超过30个要素");
- isTest = true;
- }
-
-
- trackCancel = new ESRI.ArcGIS.Display.CancelTrackerClass();
- ESRI.ArcGIS.Framework.IProgressDialogFactory progressDialogFactory = new ESRI.ArcGIS.Framework.ProgressDialogFactoryClass();
- stepProgressor = progressDialogFactory.Create(trackCancel, ArcMap.Application.hWnd);
- ESRI.ArcGIS.Framework.IProgressDialog2 progressDialog2 = (ESRI.ArcGIS.Framework.IProgressDialog2)stepProgressor; // Explict Cast
- progressDialog2.CancelEnabled = true;
- progressDialog2.Description = "逆地理编码中...";
- progressDialog2.Title = "逆地理编码";
- progressDialog2.Animation = ESRI.ArcGIS.Framework.esriProgressAnimationTypes.esriProgressGlobe;
- stepProgressor.Show();
- execute();
-
- //完成
- trackCancel = null;
- stepProgressor = null;
- progressDialog2.HideDialog();
- progressDialog2 = null;
- }
- }
- catch (Exception ex)
- {
- MessageBox.Show("发生未知异常:"+ex.Message);
- }
- }
-
- string statusFd = "status";
- string infoFd = "info";
-
- private void execute()
- {
- //创建可能的消息状态字段
- try
- {
- GISCommonHelper.FieldHelper.AddStringField(iwp.Pftlyr.FeatureClass, new KeyValuePair<string, int>(statusFd, 10),
- new KeyValuePair<string, int>(infoFd, 70));
- }
- catch (Exception)
- {
- MessageBox.Show("创建标识字段出错");
- }
-
- stepProgressor.MinRange = 0;
- int featurecount = iwp.Pftlyr.FeatureClass.FeatureCount(null);
- if (isTest)
- {
- stepProgressor.MaxRange = featurecount > 30 ? 30 : featurecount; //测试token,一次请求只能30
- }
- else
- {
- stepProgressor.MaxRange = featurecount;
- }
- stepProgressor.StepValue = 1;
- int n = 0;
- IFeatureCursor pftcursor = iwp.Pftlyr.FeatureClass.Search(null, false);
- IFeature pFeature= pftcursor.NextFeature();
- while(pFeature!=null )
- {
- if (isTest)
- {
- if (n > 30)
- {
- break;
- }
- }
-
- stepProgressor.Message = "正在处理要素,OId:" + pFeature.OID;
- System.Diagnostics.Debug.WriteLine("正在处理:"+pFeature.OID);
- double lng= (double)pFeature.getval(iwp.Xfdnm);
- double lat = (double)pFeature.getval(iwp.Yfdnm);
- RequestRes rr = getLocationStr(lng, lat);
- if(pFeature.Fields.FindField(statusFd)!=-1)
- pFeature.setval(statusFd, rr.status);
- if (rr.status == "0")
- {
- if(pFeature.Fields.FindField(infoFd)!=-1)
- pFeature.setval(infoFd, rr.info);
- }
- else if (rr.status == "1")
- {
- pFeature.setval(iwp.Locationfdnm, rr.address);
- }
-
- stepProgressor.Step();
-
- pFeature.Store();
- n++;
- pFeature = pftcursor.NextFeature();
- }
- }
-
- string bsurl = "https://restapi.amap.com/v3/geocode/regeo?parameters";
-
- private RequestRes getLocationStr(double lng,double lat)
- {
- RequestRes rr = new RequestRes();
- //https://restapi.amap.com/v3/geocode/regeo?output=xml&location=116.310003,39.991957&key=<用户的key>&radius=1000&extensions=all
- string location = "";
- string url = string.Format("https://restapi.amap.com/v3/geocode/regeo?location={0},{1}&key={2}&radius=1000&extensions=all",lng,lat,iwp.Gdtoken);
- string json = WebRequestAssist.GetRequestStr(url);
- var jRoot= JObject.Parse(json);
- int status= jRoot.Value<int>("status");
- rr.status = status.ToString();
- if (status == 1)
- {
- // 1 请求成功
- var regeocodeObj = jRoot.GetValue("regeocode") as JObject;
- string formatted_address = regeocodeObj.Value<string>("formatted_address");
- //北京市朝阳区望京街道方恒国际中心B座方恒国际
- //移除前缀
- var addressComponentObj = regeocodeObj.GetValue("addressComponent");
- string province = addressComponentObj.Value<string>("province");
- string district = addressComponentObj.Value<string>("district");
- string city = addressComponentObj.Value<string>("city");
- string township = addressComponentObj.Value<string>("township");
- rr.address = formatted_address;
- //return formatted_address;
-
- if (!iwp.IsPro)
- {
- formatted_address=formatted_address.Replace(province, "");
- }
-
- if(!iwp.IsCity)
- {
- if (!string.IsNullOrEmpty(city))
- {
- formatted_address = formatted_address.Replace(city, "");
- }
- }
-
- if (!iwp.IsCounty)
- {
- formatted_address = formatted_address.Replace(district,"");
- }
-
- if (!iwp.IsTown)
- {
- formatted_address = formatted_address.Replace(township, "");
- }
- rr.address = formatted_address;
- }
- else
- {
- //0 请求失败
- string info = jRoot.Value<string>("info"); //错误消息
- rr.info = info;
- }
-
- return rr;
- }
-
- protected override void OnUpdate()
- {
- }
-
- struct RequestRes
- {
- public string status { get; set; }
- public string info { get; set; }
- public string address { get; set; }
- }
- }
- }
大体解析:(1)获取要素的经度、纬度字段值
(2)调用高德地图逆地理编码API,获取位置描述
(3)通过Newtonsoft.JSON解析返回的json对象,并按照要求,剔除省、市等前缀
(4)将结果写入要素