1 // Copyright 2015 gRPC authors. 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // 7 // http://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 // See the License for the specific language governing permissions and 13 // limitations under the License. 14 15 using Newtonsoft.Json; 16 using Newtonsoft.Json.Linq; 17 using System; 18 using System.Collections.Generic; 19 using System.IO; 20 using System.Linq; 21 using System.Reflection; 22 using System.Text; 23 using System.Threading.Tasks; 24 25 namespace Routeguide 26 { 27 /// <summary> 28 /// Utility methods for the route guide example. 29 /// </summary> 30 public static class RouteGuideUtil 31 { 32 public const string DefaultFeaturesResourceName = "RouteGuide.route_guide_db.json"; 33 34 private const double CoordFactor = 1e7; 35 36 /// <summary> 37 /// Indicates whether the given feature exists (i.e. has a valid name). 38 /// </summary> Exists(this Feature feature)39 public static bool Exists(this Feature feature) 40 { 41 return feature != null && (feature.Name.Length != 0); 42 } 43 GetLatitude(this Point point)44 public static double GetLatitude(this Point point) 45 { 46 return point.Latitude / CoordFactor; 47 } 48 GetLongitude(this Point point)49 public static double GetLongitude(this Point point) 50 { 51 return point.Longitude / CoordFactor; 52 } 53 54 /// <summary> 55 /// Calculate the distance between two points using the "haversine" formula. 56 /// The formula is based on http://mathforum.org/library/drmath/view/51879.html 57 /// </summary> 58 /// <param name="start">the starting point</param> 59 /// <param name="end">the end point</param> 60 /// <returns>the distance between the points in meters</returns> GetDistance(this Point start, Point end)61 public static double GetDistance(this Point start, Point end) 62 { 63 int r = 6371000; // earth radius in metres 64 double lat1 = ToRadians(start.GetLatitude()); 65 double lat2 = ToRadians(end.GetLatitude()); 66 double lon1 = ToRadians(start.GetLongitude()); 67 double lon2 = ToRadians(end.GetLongitude()); 68 double deltalat = lat2 - lat1; 69 double deltalon = lon2 - lon1; 70 71 double a = Math.Sin(deltalat / 2) * Math.Sin(deltalat / 2) + Math.Cos(lat1) * Math.Cos(lat2) * Math.Sin(deltalon / 2) * Math.Sin(deltalon / 2); 72 double c = 2 * Math.Atan2(Math.Sqrt(a), Math.Sqrt(1 - a)); 73 return r * c; 74 } 75 76 /// <summary> 77 /// Returns <c>true</c> if rectangular area contains given point. 78 /// </summary> Contains(this Rectangle rectangle, Point point)79 public static bool Contains(this Rectangle rectangle, Point point) 80 { 81 int left = Math.Min(rectangle.Lo.Longitude, rectangle.Hi.Longitude); 82 int right = Math.Max(rectangle.Lo.Longitude, rectangle.Hi.Longitude); 83 int top = Math.Max(rectangle.Lo.Latitude, rectangle.Hi.Latitude); 84 int bottom = Math.Min(rectangle.Lo.Latitude, rectangle.Hi.Latitude); 85 return (point.Longitude >= left && point.Longitude <= right && point.Latitude >= bottom && point.Latitude <= top); 86 } 87 ToRadians(double val)88 private static double ToRadians(double val) 89 { 90 return (Math.PI / 180) * val; 91 } 92 93 /// <summary> 94 /// Parses features from an embedded resource. 95 /// </summary> LoadFeatures()96 public static List<Feature> LoadFeatures() 97 { 98 var features = new List<Feature>(); 99 var jsonFeatures = JsonConvert.DeserializeObject<List<JsonFeature>>(ReadFeaturesFromResource()); 100 101 foreach(var jsonFeature in jsonFeatures) 102 { 103 features.Add(new Feature 104 { 105 Name = jsonFeature.name, 106 Location = new Point { Longitude = jsonFeature.location.longitude, Latitude = jsonFeature.location.latitude} 107 }); 108 } 109 return features; 110 } 111 ReadFeaturesFromResource()112 private static string ReadFeaturesFromResource() 113 { 114 var stream = typeof(RouteGuideUtil).GetTypeInfo().Assembly.GetManifestResourceStream(DefaultFeaturesResourceName); 115 if (stream == null) 116 { 117 throw new IOException(string.Format("Error loading the embedded resource \"{0}\"", DefaultFeaturesResourceName)); 118 } 119 using (var streamReader = new StreamReader(stream)) 120 { 121 return streamReader.ReadToEnd(); 122 } 123 } 124 125 #pragma warning disable 0649 // Suppresses "Field 'x' is never assigned to". 126 private class JsonFeature 127 { 128 public string name; 129 public JsonLocation location; 130 } 131 132 private class JsonLocation 133 { 134 public int longitude; 135 public int latitude; 136 } 137 #pragma warning restore 0649 138 } 139 } 140