/// <summary> /// <para>Decodes a polyline from string into points as GPS Position as latitude (X) longitude (Y)</para> /// <para>Source: https://github.com/mapbox/polyline/blob/master/src/polyline.js</para> /// </summary> /// <param name="encodedPolyline">Encoded polyline</param> /// <param name="precisionFactor">Precision factor of the encoded polyline. Same as the one you encoded with if you encoded yourself.</param> /// <returns>Points of the polyline as latitude, longitude</returns> private static List <ProjVector2> DecodePoints(string encodedPolyline, double precisionFactor) { List <ProjVector2> points = new List <ProjVector2>(); int latitude = 0; int longitude = 0; for (int i = 0; i < encodedPolyline.Length;) { int b; int shift = 0; int result = 0; do { b = encodedPolyline[i++] - 63; result |= (b & 31) << shift; shift += 5; }while (32 <= b); latitude += (result & 1) > 0 ? ~(result >> 1) : result >> 1; result = shift = 0; do { b = encodedPolyline[i++] - 63; result |= (b & 31) << shift; shift += 5; }while (32 <= b); longitude += (result & 1) > 0 ? ~(result >> 1) : result >> 1; ProjVector2 p = new ProjVector2(latitude / precisionFactor, longitude / precisionFactor, Projection.LatitudeLongitude); points.Add(p); } return(points); }
public double?ProjectedDistance(ProjVector2 point, double distanceLimit) { point = point.ToProjection(Points.First().Projection); int bestIndex = -1; double bestProj = 0; double bestDist = 0; for (int i = 1; i < Points.Count; i++) { ProjVector2 a = Points[i] - Points[i - 1]; ProjVector2 b = point - Points[i - 1]; double proj = a.Dot(b) / a.LengthSquared; if (proj < 0) { proj = 0; } else if (proj > 1) { proj = 1; } double dist = (point - (Points[i] + a * proj)).MeterLength / 1000; if ((bestIndex == -1 || dist < bestDist) && dist < distanceLimit) { bestIndex = i; bestProj = proj; bestDist = dist; } } // The point could not be projected if (bestIndex == -1) { return(null); } double km = 0; for (int i = 1; i <= bestIndex; i++) { km += (Points[i] - Points[i - 1]).MeterLength / 1000; } km += bestProj * (Points[bestIndex + 1] - Points[bestIndex]).MeterLength / 1000; return(km); }
private static List <PlacesAPIData> Scan(ProjVector2 position, double radius) { List <PlacesAPIData> ret = new List <PlacesAPIData>(); HttpWebRequest request = WebRequest.CreateHttp("https://maps.googleapis.com/maps/api/place/nearbysearch/json?location=" + position.Vec.ToString() + "&radius=" + radius + "&type=train_station&key=" + APIKey); request.Method = "GET"; try { using (WebResponse response = request.GetResponse()) { using (StreamReader reader = new StreamReader(response.GetResponseStream(), Encoding.UTF8)) { string json = reader.ReadToEnd(); JObject whole = JObject.Parse(json); string status = whole["status"].ToString(); if (status == "OK" || status == "ZERO_RESULTS") { if (whole["results"] is JArray results) { foreach (JObject place in results) { ret.Add(new PlacesAPIData( place["name"].ToString(), new ProjVector2(double.Parse(place["geometry"]["location"]["lat"].ToString()), double.Parse(place["geometry"]["location"]["lng"].ToString()), Projection.LatitudeLongitude))); } } } else { throw new PlacesAPIException("Places API is unavailable. Status code: " + status); } } } } catch (WebException) { // TODO: Log throw new PlacesAPIException("Places API is unavailable."); } return(ret); }
public static ProjVector2?Search(Station station, ProjVector2 position, double radius, int maxLevenshtein) { int minDist = 0; PlacesAPIData?minRes = null; var results = Scan(position.ToProjection(Projection.LatitudeLongitude), radius); foreach (var result in results) { int dist = LevenshteinDistance(station.NormalizedName, Station.NormalizeName(result.StationName)); if (dist == 0) { return(result.Position); } if (dist <= maxLevenshtein && (minRes == null || dist < minDist)) { minRes = result; minDist = dist; } } return(minRes?.Position); }
public PlacesAPIData(string stationName, ProjVector2 position) { StationName = stationName; Position = position; }