// Try to get the general locality of a point from Google public static async Task <PlaceLocality> GetLocality(double lat, double lon) { PlaceLocality locality = null; using (HttpClient client = new HttpClient()) { string reqUrl = string.Format("https://maps.googleapis.com/maps/api/geocode/json?latlng={0},{1}&sensor=true&result_type=locality&key={2}", lat, lon, Common.ConfidentialData.mapsk); var response = await client.GetStringAsync(reqUrl); Common.Models.GMapsResultColl ret = JsonConvert.DeserializeObject <Common.Models.GMapsResultColl>(response); if (ret != null && ret.results.Count > 0) { Common.Models.GooglePlaceResult place = ret.results[0]; locality = new PlaceLocality { GooglePlaceId = place.place_id, Latitude = new decimal(place.geometry.location.lat), Longitude = new decimal(place.geometry.location.lng), Name = place.address_components[0].long_name, CreatedAt = DateTime.UtcNow }; } } return(locality); }
// http://stackoverflow.com/questions/32203770/linq-find-closest-coordinates private static IQueryable <Place> GetClosest(ApplicationDbContext db, double lat, double lon, int limit = 10) { decimal latitude = new decimal(lat); decimal longitude = new decimal(lon); // Try to get closest group, so we only compute over a subsection PlaceLocality closestLocality = db.PlaceLocalities.OrderBy(pl => (latitude - pl.Latitude) * (latitude - pl.Latitude) + (longitude - pl.Longitude) * (longitude - pl.Longitude)).FirstOrDefault(); if (closestLocality != null) { return(db.Places.Where(pl => pl.Locality.Id == closestLocality.Id)); } // Resort to looking at all items return(db.Places.OrderBy(pl => (latitude - pl.Latitude) * (latitude - pl.Latitude) + (longitude - pl.Longitude) * (longitude - pl.Longitude)) .Take(limit)); }
protected async Task<List<Place>> ProcessPlacesInNewContent(ICollection<Place> places, ApplicationUser currentUser, List<Place> finalPlaces = null) { // Go through the creation's Places, adding them to the database if necessary if (finalPlaces == null) { finalPlaces = new List<Place>(); } else { // avoiding creating new, which seems to cause conflicts finalPlaces.Clear(); } if (places == null) return finalPlaces; for (int i = 0; i < places.Count; i++) { Place thisPlace = places.ElementAt(i); Place existing = await db.Places.Where(p => p.GooglePlaceId == thisPlace.GooglePlaceId).FirstOrDefaultAsync(); if (existing != null) { finalPlaces.Add(existing); } else { Common.Models.GMapsResult result; using (HttpClient client = new HttpClient()) { string reqUrl = string.Format("https://maps.googleapis.com/maps/api/place/details/json?placeid={0}&key={1}", thisPlace.GooglePlaceId, Common.ConfidentialData.mapsk); var response = await client.GetStringAsync(reqUrl); result = JsonConvert.DeserializeObject<Common.Models.GMapsResult>(response); } if (result.status == "OK") { double lat = result.result.geometry.location.lat; double lon = result.result.geometry.location.lng; Place finalPlace = new Place { GooglePlaceId = result.result.place_id, Latitude = new decimal(lat), Longitude = new decimal(lon), Location = ServerUtils.CreatePoint(lat, lon), Name = result.result.name, CreatedAt = DateTime.UtcNow, AddedBy = currentUser }; // Check for parent locality PlaceLocality locality = await LocationLogic.GetLocality(lat, lon); if (locality != null) { PlaceLocality existingLocality = await db.PlaceLocalities .Where(p => p.GooglePlaceId == locality.GooglePlaceId).FirstOrDefaultAsync(); if (existingLocality == null) { finalPlace.Locality = db.PlaceLocalities.Add(locality); await db.SaveChangesAsync(); } else { finalPlace.Locality = existingLocality; } } finalPlaces.Add(db.Places.Add(finalPlace)); } } } return finalPlaces; }