1.搜索地址功能实现
1.1功能描述
在输入框中输入一个地址(要稍微知名度高一点的地标类,比如达到POI点这个级别,太小的地址可能找不到),OpenCycleMap没有搜索地址的接口,于是调用高德的搜索API(不需要用高德的底图),因为高德返回的是gcj02坐标,OpenCycleMap使用的是wgs84坐标,所以要将gcj02坐标转wgs84坐标,再定位到底图上。
1.2实现效果演示
功能菜单:
输入POI地址,点击确定,通过高德API获得gcj02坐标,换算为wgs84坐标,在底图上定位到该坐标,并增加一个marker标记,下图是搜索的示例,大家看还算准吧。
2.搜索地址的核心方法代码
核心动作:调取高德API,送地址参数,拿回火星坐标,转换成wgs84坐标,在地图上定位。
/// <summary>
/// 由地址获得经纬度,再显示地图位置。
/// </summary>
/// <param name="place"></param>
private void AddLocation(string place)
{
String addressStr = "http://restapi.amap.com/v3/geocode/geo?key=这里是用户的key大家自己申请&s=rsv3&city=027&address=";
String getAddress = addressStr + place;
//url 你的WebApi 地址重要!!!
Uri uri = new Uri(getAddress);
//WebClient:获取webaapi中的数据。
using (WebClient c = new WebClient())
{
//c.Headers["Type"]:获取数据的方式
c.Headers["Type"] = "GET";
//c.Headers["Accept"]:获取数据的格式
c.Headers["Accept"] = "application/json";
//c.Encoding:数据的编码格式。
c.Encoding = Encoding.UTF8;
//DownloadDataCompleted:在多线程情况下,能进行webApi数据传输。
c.DownloadStringCompleted += (senderobj, es) =>
{
if (es.Result != null)
{
//把webApi之中获取的json数据 序列化成dataTable
AddressSearchResult ad = JsonConvert.DeserializeObject<AddressSearchResult>(es.Result);
if (ad.geocodes != null)
{
if (ad.geocodes.Length > 0)
{
string[] s = ad.geocodes[0].location.Split(',');
//增加一个转换(gcj02坐标转wgs84坐标)
Cor hx = new Cor();
hx.lat = double.Parse(s[1]);
hx.lng = double.Parse(s[0]);
Cor x = Transformer.gcj02towgs84(hx); //火星标转换为84
PointLatLng cp = new PointLatLng(x.lat,x.lng); //lng是经度,lat是纬度 武汉
MainMap.Zoom = 16;
MainMap.Position = cp;
this.lbZoomStatus.Text = MainMap.Zoom.ToString();
#region 标记点
//创建标记,并设置位置及样式
GMapMarker marker = new GMarkerGoogle(new PointLatLng(cp.Lat, cp.Lng), GMarkerGoogleType.blue_pushpin);
marker.ToolTipMode = MarkerTooltipMode.OnMouseOver;
marker.ToolTipText = ad.geocodes[0].formatted_address;
marker.Tag = JsonConvert.SerializeObject(ad, Formatting.Indented);
//将标记添加到图层
overlay.Markers.Add(marker);
#endregion
}
else
{
System.Windows.MessageBox.Show("没有找到该地址,geo数组长度为0");
}
}
else
{
System.Windows.MessageBox.Show("没有找到该地址,geo对象为空");
}
}
};
//把当前webApi地址释放掉。
c.DownloadStringAsync(uri);
}
}
火星标转换为84方法代码:
/// <summary>
/// 火星转84
/// 该方法经过实战测试计算比较准确 naki 2022.4.19
/// </summary>
/// <param name="hx"></param>
/// <returns></returns>
public static Cor gcj02towgs84(Cor hx)
{
if (OutOfChina(hx))
{
return hx;
}
double dlat = transformlat(hx.lng - 105.0, hx.lat - 35.0);
double dlng = transformlng(hx.lng - 105.0, hx.lat - 35.0);
double radlat = hx.lat / 180.0 * pi;
double magic = Math.Sin(radlat);
magic = 1 - ee * magic * magic;
double sqrtmagic = Math.Sqrt(magic);
dlat = (dlat * 180.0) / ((a * (1 - ee)) / (magic * sqrtmagic) * pi);
dlng = (dlng * 180.0) / (a / sqrtmagic * Math.Cos(radlat) * pi);
Cor wgs84;
double mglat = hx.lat + dlat;
double mglng = hx.lng + dlng;
wgs84.lat = hx.lat * 2 - mglat;
wgs84.lng = hx.lng * 2 - mglng;
return wgs84;
}
/*辅助函数*/
//转换lat
private static double transformlat(double lng, double lat)
{
double ret = -100.0 + 2.0 * lng + 3.0 * lat + 0.2 * lat * lat +
0.1 * lng * lat + 0.2 * Math.Sqrt(Math.Abs(lng));
ret += (20.0 * Math.Sin(6.0 * lng * pi) + 20.0 *
Math.Sin(2.0 * lng * pi)) * 2.0 / 3.0;
ret += (20.0 * Math.Sin(lat * pi) + 40.0 *
Math.Sin(lat / 3.0 * pi)) * 2.0 / 3.0;
ret += (160.0 * Math.Sin(lat / 12.0 * pi) + 320 *
Math.Sin(lat * pi / 30.0)) * 2.0 / 3.0;
return ret;
}
/*辅助函数*/
//转换lng
private static double transformlng(double lng, double lat)
{
double ret = 300.0 + lng + 2.0 * lat + 0.1 * lng * lng +
0.1 * lng * lat + 0.1 * Math.Sqrt(Math.Abs(lng));
ret += (20.0 * Math.Sin(6.0 * lng * pi) + 20.0 *
Math.Sin(2.0 * lng * pi)) * 2.0 / 3.0;
ret += (20.0 * Math.Sin(lng * pi) + 40.0 *
Math.Sin(lng / 3.0 * pi)) * 2.0 / 3.0;
ret += (150.0 * Math.Sin(lng / 12.0 * pi) + 300.0 *
Math.Sin(lng / 30.0 * pi)) * 2.0 / 3.0;
return ret;
}