Subversion Repositories Projects

Compare Revisions

Ignore whitespace Rev 2286 → Rev 2287

/MKLiveView/v1.0/GMap.NET.Core/GMap.NET.MapProviders/OpenStreetMap/OpenStreetMapProvider.cs
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";
}
}