0,0 → 1,547 |
|
namespace GMap.NET.MapProviders |
{ |
using System; |
using System.Collections.Generic; |
using System.Diagnostics; |
using System.Globalization; |
using System.Xml; |
using GMap.NET.Internals; |
using GMap.NET.Projections; |
|
public abstract class OpenStreetMapProviderBase : GMapProvider, RoutingProvider, GeocodingProvider |
{ |
public OpenStreetMapProviderBase() |
{ |
MaxZoom = null; |
RefererUrl = "http://www.openstreetmap.org/"; |
Copyright = string.Format("© OpenStreetMap - Map data ©{0} OpenStreetMap", DateTime.Today.Year); |
} |
|
public readonly string ServerLetters = "abc"; |
public int MinExpectedRank = 0; |
|
#region GMapProvider Members |
|
public override Guid Id |
{ |
get |
{ |
throw new NotImplementedException(); |
} |
} |
|
public override string Name |
{ |
get |
{ |
throw new NotImplementedException(); |
} |
} |
|
public override PureProjection Projection |
{ |
get |
{ |
return MercatorProjection.Instance; |
} |
} |
|
public override GMapProvider[] Overlays |
{ |
get |
{ |
throw new NotImplementedException(); |
} |
} |
|
public override PureImage GetTileImage(GPoint pos, int zoom) |
{ |
throw new NotImplementedException(); |
} |
|
#endregion |
|
#region GMapRoutingProvider Members |
|
public MapRoute GetRoute(PointLatLng start, PointLatLng end, bool avoidHighways, bool walkingMode, int Zoom) |
{ |
List<PointLatLng> points = GetRoutePoints(MakeRoutingUrl(start, end, walkingMode ? TravelTypeFoot : TravelTypeMotorCar)); |
MapRoute route = points != null ? new MapRoute(points, walkingMode ? WalkingStr : DrivingStr) : null; |
return route; |
} |
|
/// <summary> |
/// NotImplemented |
/// </summary> |
/// <param name="start"></param> |
/// <param name="end"></param> |
/// <param name="avoidHighways"></param> |
/// <param name="walkingMode"></param> |
/// <param name="Zoom"></param> |
/// <returns></returns> |
public MapRoute GetRoute(string start, string end, bool avoidHighways, bool walkingMode, int Zoom) |
{ |
throw new NotImplementedException("use GetRoute(PointLatLng start, PointLatLng end..."); |
} |
|
#region -- internals -- |
string MakeRoutingUrl(PointLatLng start, PointLatLng end, string travelType) |
{ |
return string.Format(CultureInfo.InvariantCulture, RoutingUrlFormat, start.Lat, start.Lng, end.Lat, end.Lng, travelType); |
} |
|
List<PointLatLng> GetRoutePoints(string url) |
{ |
List<PointLatLng> points = null; |
try |
{ |
string route = GMaps.Instance.UseRouteCache ? Cache.Instance.GetContent(url, CacheType.RouteCache) : string.Empty; |
if(string.IsNullOrEmpty(route)) |
{ |
route = GetContentUsingHttp(url); |
if(!string.IsNullOrEmpty(route)) |
{ |
if(GMaps.Instance.UseRouteCache) |
{ |
Cache.Instance.SaveContent(url, CacheType.RouteCache, route); |
} |
} |
} |
|
if(!string.IsNullOrEmpty(route)) |
{ |
XmlDocument xmldoc = new XmlDocument(); |
xmldoc.LoadXml(route); |
System.Xml.XmlNamespaceManager xmlnsManager = new System.Xml.XmlNamespaceManager(xmldoc.NameTable); |
xmlnsManager.AddNamespace("sm", "http://earth.google.com/kml/2.0"); |
|
///Folder/Placemark/LineString/coordinates |
var coordNode = xmldoc.SelectSingleNode("/sm:kml/sm:Document/sm:Folder/sm:Placemark/sm:LineString/sm:coordinates", xmlnsManager); |
|
string[] coordinates = coordNode.InnerText.Split('\n'); |
|
if(coordinates.Length > 0) |
{ |
points = new List<PointLatLng>(); |
|
foreach(string coordinate in coordinates) |
{ |
if(coordinate != string.Empty) |
{ |
string[] XY = coordinate.Split(','); |
if(XY.Length == 2) |
{ |
double lat = double.Parse(XY[1], CultureInfo.InvariantCulture); |
double lng = double.Parse(XY[0], CultureInfo.InvariantCulture); |
points.Add(new PointLatLng(lat, lng)); |
} |
} |
} |
} |
} |
} |
catch(Exception ex) |
{ |
Debug.WriteLine("GetRoutePoints: " + ex); |
} |
|
return points; |
} |
|
static readonly string RoutingUrlFormat = "http://www.yournavigation.org/api/1.0/gosmore.php?format=kml&flat={0}&flon={1}&tlat={2}&tlon={3}&v={4}&fast=1&layer=mapnik"; |
static readonly string TravelTypeFoot = "foot"; |
static readonly string TravelTypeMotorCar = "motorcar"; |
|
static readonly string WalkingStr = "Walking"; |
static readonly string DrivingStr = "Driving"; |
#endregion |
|
#endregion |
|
#region GeocodingProvider Members |
|
public GeoCoderStatusCode GetPoints(string keywords, out List<PointLatLng> pointList) |
{ |
// http://nominatim.openstreetmap.org/search?q=lithuania,vilnius&format=xml |
|
#region -- response -- |
//<searchresults timestamp="Wed, 01 Feb 12 09:46:00 -0500" attribution="Data Copyright OpenStreetMap Contributors, Some Rights Reserved. CC-BY-SA 2.0." querystring="lithuania,vilnius" polygon="false" exclude_place_ids="29446018,53849547,8831058,29614806" more_url="http://open.mapquestapi.com/nominatim/v1/search?format=xml&exclude_place_ids=29446018,53849547,8831058,29614806&accept-language=en&q=lithuania%2Cvilnius"> |
//<place place_id="29446018" osm_type="way" osm_id="24598347" place_rank="30" boundingbox="54.6868133544922,54.6879043579102,25.2885360717773,25.2898139953613" lat="54.6873633486028" lon="25.289199818878" display_name="National Museum of Lithuania, 1, Arsenalo g., Senamiesčio seniūnija, YAHOO-HIRES-20080313, Vilnius County, Šalčininkų rajonas, Vilniaus apskritis, 01513, Lithuania" class="tourism" type="museum" icon="http://open.mapquestapi.com/nominatim/v1/images/mapicons/tourist_museum.p.20.png"/> |
//<place place_id="53849547" osm_type="way" osm_id="55469274" place_rank="30" boundingbox="54.6896553039551,54.690486907959,25.2675743103027,25.2692089080811" lat="54.6900227236882" lon="25.2683589759401" display_name="Ministry of Foreign Affairs of the Republic of Lithuania, 2, J. Tumo Vaižganto g., Naujamiesčio seniūnija, Vilnius, Vilnius County, Vilniaus m. savivaldybė, Vilniaus apskritis, LT-01104, Lithuania" class="amenity" type="public_building"/> |
//<place place_id="8831058" osm_type="node" osm_id="836234960" place_rank="30" boundingbox="54.6670935059,54.6870973206,25.2638857269,25.2838876343" lat="54.677095" lon="25.2738876" display_name="Railway Museum of Lithuania, 15, Mindaugo g., Senamiesčio seniūnija, Vilnius, Vilnius County, Vilniaus m. savivaldybė, Vilniaus apskritis, 03215, Lithuania" class="tourism" type="museum" icon="http://open.mapquestapi.com/nominatim/v1/images/mapicons/tourist_museum.p.20.png"/> |
//<place place_id="29614806" osm_type="way" osm_id="24845629" place_rank="30" boundingbox="54.6904983520508,54.6920852661133,25.2606296539307,25.2628803253174" lat="54.6913385159005" lon="25.2617684209873" display_name="Seimas (Parliament) of the Republic of Lithuania, 53, Gedimino pr., Naujamiesčio seniūnija, Vilnius, Vilnius County, Vilniaus m. savivaldybė, Vilniaus apskritis, LT-01111, Lithuania" class="amenity" type="public_building"/> |
//</searchresults> |
#endregion |
|
return GetLatLngFromGeocoderUrl(MakeGeocoderUrl(keywords), out pointList); |
} |
|
public PointLatLng? GetPoint(string keywords, out GeoCoderStatusCode status) |
{ |
List<PointLatLng> pointList; |
status = GetPoints(keywords, out pointList); |
return pointList != null && pointList.Count > 0 ? pointList[0] : (PointLatLng?) null; |
} |
|
public GeoCoderStatusCode GetPoints(Placemark placemark, out List<PointLatLng> pointList) |
{ |
// http://nominatim.openstreetmap.org/search?street=&city=vilnius&county=&state=&country=lithuania&postalcode=&format=xml |
|
#region -- response -- |
//<searchresults timestamp="Thu, 29 Nov 12 08:38:23 +0000" attribution="Data © OpenStreetMap contributors, ODbL 1.0. http://www.openstreetmap.org/copyright" querystring="vilnius, lithuania" polygon="false" exclude_place_ids="98093941" more_url="http://nominatim.openstreetmap.org/search?format=xml&exclude_place_ids=98093941&accept-language=de-de,de;q=0.8,en-us;q=0.5,en;q=0.3&q=vilnius%2C+lithuania"> |
//<place place_id="98093941" osm_type="relation" osm_id="1529146" place_rank="16" boundingbox="54.5693359375,54.8323097229004,25.0250644683838,25.4815216064453" lat="54.6843135" lon="25.2853984" display_name="Vilnius, Vilniaus m. savivaldybė, Distrikt Vilnius, Litauen" class="boundary" type="administrative" icon="http://nominatim.openstreetmap.org/images/mapicons/poi_boundary_administrative.p.20.png"/> |
//</searchresults> |
#endregion |
|
return GetLatLngFromGeocoderUrl(MakeDetailedGeocoderUrl(placemark), out pointList); |
} |
|
public PointLatLng? GetPoint(Placemark placemark, out GeoCoderStatusCode status) |
{ |
List<PointLatLng> pointList; |
status = GetPoints(placemark, out pointList); |
return pointList != null && pointList.Count > 0 ? pointList[0] : (PointLatLng?) null; |
} |
|
public GeoCoderStatusCode GetPlacemarks(PointLatLng location, out List<Placemark> placemarkList) |
{ |
throw new NotImplementedException("use GetPlacemark"); |
} |
|
public Placemark? GetPlacemark(PointLatLng location, out GeoCoderStatusCode status) |
{ |
//http://nominatim.openstreetmap.org/reverse?format=xml&lat=52.5487429714954&lon=-1.81602098644987&zoom=18&addressdetails=1 |
|
#region -- response -- |
/* |
<reversegeocode timestamp="Wed, 01 Feb 12 09:51:11 -0500" attribution="Data Copyright OpenStreetMap Contributors, Some Rights Reserved. CC-BY-SA 2.0." querystring="format=xml&lat=52.5487429714954&lon=-1.81602098644987&zoom=18&addressdetails=1"> |
<result place_id="2061235282" osm_type="way" osm_id="90394420" lat="52.5487800131654" lon="-1.81626922291265"> |
137, Pilkington Avenue, Castle Vale, City of Birmingham, West Midlands, England, B72 1LH, United Kingdom |
</result> |
<addressparts> |
<house_number> |
137 |
</house_number> |
<road> |
Pilkington Avenue |
</road> |
<suburb> |
Castle Vale |
</suburb> |
<city> |
City of Birmingham |
</city> |
<county> |
West Midlands |
</county> |
<state_district> |
West Midlands |
</state_district> |
<state> |
England |
</state> |
<postcode> |
B72 1LH |
</postcode> |
<country> |
United Kingdom |
</country> |
<country_code> |
gb |
</country_code> |
</addressparts> |
</reversegeocode> |
*/ |
|
#endregion |
|
return GetPlacemarkFromReverseGeocoderUrl(MakeReverseGeocoderUrl(location), out status); |
} |
|
#region -- internals -- |
|
string MakeGeocoderUrl(string keywords) |
{ |
return string.Format(GeocoderUrlFormat, keywords.Replace(' ', '+')); |
} |
|
string MakeDetailedGeocoderUrl(Placemark placemark) |
{ |
var street = String.Join(" ", new[] { placemark.HouseNo, placemark.ThoroughfareName }).Trim(); |
return string.Format(GeocoderDetailedUrlFormat, |
street.Replace(' ', '+'), |
placemark.LocalityName.Replace(' ', '+'), |
placemark.SubAdministrativeAreaName.Replace(' ', '+'), |
placemark.AdministrativeAreaName.Replace(' ', '+'), |
placemark.CountryName.Replace(' ', '+'), |
placemark.PostalCodeNumber.Replace(' ', '+')); |
} |
|
string MakeReverseGeocoderUrl(PointLatLng pt) |
{ |
return string.Format(CultureInfo.InvariantCulture, ReverseGeocoderUrlFormat, pt.Lat, pt.Lng); |
} |
|
GeoCoderStatusCode GetLatLngFromGeocoderUrl(string url, out List<PointLatLng> pointList) |
{ |
var status = GeoCoderStatusCode.Unknow; |
pointList = null; |
|
try |
{ |
string geo = GMaps.Instance.UseGeocoderCache ? Cache.Instance.GetContent(url, CacheType.GeocoderCache) : string.Empty; |
|
bool cache = false; |
|
if(string.IsNullOrEmpty(geo)) |
{ |
geo = GetContentUsingHttp(url); |
|
if(!string.IsNullOrEmpty(geo)) |
{ |
cache = true; |
} |
} |
|
if(!string.IsNullOrEmpty(geo)) |
{ |
if(geo.StartsWith("<?xml") && geo.Contains("<place")) |
{ |
if(cache && GMaps.Instance.UseGeocoderCache) |
{ |
Cache.Instance.SaveContent(url, CacheType.GeocoderCache, geo); |
} |
|
XmlDocument doc = new XmlDocument(); |
doc.LoadXml(geo); |
{ |
XmlNodeList l = doc.SelectNodes("/searchresults/place"); |
if(l != null) |
{ |
pointList = new List<PointLatLng>(); |
|
foreach(XmlNode n in l) |
{ |
var nn = n.Attributes["place_rank"]; |
|
int rank = 0; |
#if !PocketPC |
if (nn != null && Int32.TryParse(nn.Value, out rank)) |
{ |
#else |
if(nn != null && !string.IsNullOrEmpty(nn.Value)) |
{ |
rank = int.Parse(nn.Value, NumberStyles.Integer, CultureInfo.InvariantCulture); |
#endif |
if(rank < MinExpectedRank) |
continue; |
} |
|
nn = n.Attributes["lat"]; |
if(nn != null) |
{ |
double lat = double.Parse(nn.Value, CultureInfo.InvariantCulture); |
|
nn = n.Attributes["lon"]; |
if(nn != null) |
{ |
double lng = double.Parse(nn.Value, CultureInfo.InvariantCulture); |
pointList.Add(new PointLatLng(lat, lng)); |
} |
} |
} |
|
status = GeoCoderStatusCode.G_GEO_SUCCESS; |
} |
} |
} |
} |
} |
catch(Exception ex) |
{ |
status = GeoCoderStatusCode.ExceptionInCode; |
Debug.WriteLine("GetLatLngFromGeocoderUrl: " + ex); |
} |
|
return status; |
} |
|
Placemark? GetPlacemarkFromReverseGeocoderUrl(string url, out GeoCoderStatusCode status) |
{ |
status = GeoCoderStatusCode.Unknow; |
Placemark? ret = null; |
|
try |
{ |
string geo = GMaps.Instance.UsePlacemarkCache ? Cache.Instance.GetContent(url, CacheType.PlacemarkCache) : string.Empty; |
|
bool cache = false; |
|
if(string.IsNullOrEmpty(geo)) |
{ |
geo = GetContentUsingHttp(url); |
|
if(!string.IsNullOrEmpty(geo)) |
{ |
cache = true; |
} |
} |
|
if(!string.IsNullOrEmpty(geo)) |
{ |
if(geo.StartsWith("<?xml") && geo.Contains("<result")) |
{ |
if(cache && GMaps.Instance.UsePlacemarkCache) |
{ |
Cache.Instance.SaveContent(url, CacheType.PlacemarkCache, geo); |
} |
|
XmlDocument doc = new XmlDocument(); |
doc.LoadXml(geo); |
{ |
XmlNode r = doc.SelectSingleNode("/reversegeocode/result"); |
if(r != null) |
{ |
var p = new Placemark(r.InnerText); |
|
XmlNode ad = doc.SelectSingleNode("/reversegeocode/addressparts"); |
if(ad != null) |
{ |
var vl = ad.SelectSingleNode("country"); |
if(vl != null) |
{ |
p.CountryName = vl.InnerText; |
} |
|
vl = ad.SelectSingleNode("country_code"); |
if(vl != null) |
{ |
p.CountryNameCode = vl.InnerText; |
} |
|
vl = ad.SelectSingleNode("postcode"); |
if(vl != null) |
{ |
p.PostalCodeNumber = vl.InnerText; |
} |
|
vl = ad.SelectSingleNode("state"); |
if(vl != null) |
{ |
p.AdministrativeAreaName = vl.InnerText; |
} |
|
vl = ad.SelectSingleNode("region"); |
if(vl != null) |
{ |
p.SubAdministrativeAreaName = vl.InnerText; |
} |
|
vl = ad.SelectSingleNode("suburb"); |
if(vl != null) |
{ |
p.LocalityName = vl.InnerText; |
} |
|
vl = ad.SelectSingleNode("road"); |
if(vl != null) |
{ |
p.ThoroughfareName = vl.InnerText; |
} |
} |
|
ret = p; |
|
status = GeoCoderStatusCode.G_GEO_SUCCESS; |
} |
} |
} |
} |
} |
catch(Exception ex) |
{ |
ret = null; |
status = GeoCoderStatusCode.ExceptionInCode; |
Debug.WriteLine("GetPlacemarkFromReverseGeocoderUrl: " + ex); |
} |
|
return ret; |
} |
|
static readonly string ReverseGeocoderUrlFormat = "http://nominatim.openstreetmap.org/reverse?format=xml&lat={0}&lon={1}&zoom=18&addressdetails=1"; |
static readonly string GeocoderUrlFormat = "http://nominatim.openstreetmap.org/search?q={0}&format=xml"; |
static readonly string GeocoderDetailedUrlFormat = "http://nominatim.openstreetmap.org/search?street={0}&city={1}&county={2}&state={3}&country={4}&postalcode={5}&format=xml"; |
|
#endregion |
|
#endregion |
} |
|
/// <summary> |
/// OpenStreetMap provider - http://www.openstreetmap.org/ |
/// </summary> |
public class OpenStreetMapProvider : OpenStreetMapProviderBase |
{ |
public static readonly OpenStreetMapProvider Instance; |
|
OpenStreetMapProvider() |
{ |
} |
|
static OpenStreetMapProvider() |
{ |
Instance = new OpenStreetMapProvider(); |
} |
|
#region GMapProvider Members |
|
readonly Guid id = new Guid("0521335C-92EC-47A8-98A5-6FD333DDA9C0"); |
public override Guid Id |
{ |
get |
{ |
return id; |
} |
} |
|
readonly string name = "OpenStreetMap"; |
public override string Name |
{ |
get |
{ |
return name; |
} |
} |
|
GMapProvider[] overlays; |
public override GMapProvider[] Overlays |
{ |
get |
{ |
if(overlays == null) |
{ |
overlays = new GMapProvider[] { this }; |
} |
return overlays; |
} |
} |
|
public override PureImage GetTileImage(GPoint pos, int zoom) |
{ |
string url = MakeTileImageUrl(pos, zoom, string.Empty); |
|
return GetTileImageUsingHttp(url); |
} |
|
#endregion |
|
string MakeTileImageUrl(GPoint pos, int zoom, string language) |
{ |
char letter = ServerLetters[GetServerNum(pos, 3)]; |
return string.Format(UrlFormat, letter, zoom, pos.X, pos.Y); |
} |
|
static readonly string UrlFormat = "http://{0}.tile.openstreetmap.org/{1}/{2}/{3}.png"; |
} |
} |