Find closest location with longitude and latitude

前端 未结 6 1086
不知归路
不知归路 2020-12-12 17:20

I am working on a application where I need to get nearby location, my web service will receive 2 parameters (decimal longitude, decimal latitude )

I have a table wh

相关标签:
6条回答
  • 2020-12-12 17:52

    Do you have a valid range, outside of which the "hit" is not really relevant? If so, use

    from l in locations where ((l.lat - point.lat) * (l.lat - point.lat)) + ((l.lng - point.lng) * (l.lng - point.lng)) < (range * range) select l
    

    then find the hit with the smallest squared distance value within a loop of those results.

    0 讨论(0)
  • 2020-12-12 17:53

    A netcore friendly solution. Refactor as needed.

    public static System.Drawing.PointF getClosestPoint(System.Drawing.PointF[] points, System.Drawing.PointF query) {
        return points.OrderBy(x => distance(query, x)).First();
    }
    
    public static double distance(System.Drawing.PointF pt1, System.Drawing.PointF pt2) {
        return Math.Sqrt((pt2.Y - pt1.Y) * (pt2.Y - pt1.Y) + (pt2.X - pt1.X) * (pt2.X - pt1.X));
    }
    
    0 讨论(0)
  • 2020-12-12 18:06

    You could first convert the location data in database to System.Device.Location.GeoCoordinate, then use LINQ to find the nearest one.

    var coord = new GeoCoordinate(latitude, longitude);
    var nearest = locations.Select(x => new GeoCoordinate(x.Latitude, x.Longitude))
                           .OrderBy(x => x.GetDistanceTo(coord))
                           .First();
    
    0 讨论(0)
  • 2020-12-12 18:06
    var objAllListing = (from listing in _listingWithLanguageRepository.GetAll().Where(z => z.IsActive == true)
                                         let distance = 12742 * SqlFunctions.Asin(SqlFunctions.SquareRoot(SqlFunctions.Sin(((SqlFunctions.Pi() / 180) * (listing.Listings.Latitude - sourceLatitude)) / 2) * SqlFunctions.Sin(((SqlFunctions.Pi() / 180) * (listing.Listings.Latitude - sourceLatitude)) / 2) +
                                                            SqlFunctions.Cos((SqlFunctions.Pi() / 180) * sourceLatitude) * SqlFunctions.Cos((SqlFunctions.Pi() / 180) * (listing.Listings.Latitude)) *
                                                            SqlFunctions.Sin(((SqlFunctions.Pi() / 180) * (listing.Listings.Longitude - sourceLongitude)) / 2) * SqlFunctions.Sin(((SqlFunctions.Pi() / 180) * (listing.Listings.Longitude - sourceLongitude)) / 2)))
                                         where distance <= input.Distance
    
                                         select new ListingFinalResult { ListingDetail = listing, Distance = distance }).ToList();//.Take(5).OrderBy(x => x.distance).ToList();
    
    0 讨论(0)
  • 2020-12-12 18:07

    To elaborate on the comment by @Fung, if you are using Entity Framework / LINQ to Entities, if you try to use the GeoCoordinate.GetDistanceTo method in a LINQ query, you'll get a runtime NotSupportedException with the message:

    LINQ to Entities does not recognize the method 'Double GetDistanceTo(System.Device.Location.GeoCoordinate)' method, and this method cannot be translated into a store expression.

    With Entity Framework version 5 or 6, an alternative is to use the System.Data.Spatial.DbGeography class. For example:

    DbGeography searchLocation = DbGeography.FromText(String.Format("POINT({0} {1})", longitude, latitude));
    
    var nearbyLocations = 
        (from location in _context.Locations
         where  // (Additional filtering criteria here...)
         select new 
         {
             LocationID = location.ID,
             Address1 = location.Address1,
             City = location.City,
             State = location.State,
             Zip = location.Zip,
             Latitude = location.Latitude,
             Longitude = location.Longitude,
             Distance = searchLocation.Distance(
                 DbGeography.FromText("POINT(" + location.Longitude + " " + location.Latitude + ")"))
         })
        .OrderBy(location => location.Distance)
        .ToList();
    

    _context in this example is your previously-instantiated DbContext instance.

    Although it's currently undocumented in MSDN, the units returned by the DbGeography.Distance method appear to be meters. See: System.Data.Spatial DbGeography.Distance units?

    0 讨论(0)
  • 2020-12-12 18:08

    Here is Solution

    var constValue = 57.2957795130823D
    
    var constValue2 = 3958.75586574D;
    
    var searchWithin = 20;
    
    double latitude = ConversionHelper.SafeConvertToDoubleCultureInd(Latitude, 0),
                        longitude = ConversionHelper.SafeConvertToDoubleCultureInd(Longitude, 0);
    var loc = (from l in DB.locations
    let temp = Math.Sin(Convert.ToDouble(l.Latitude) / constValue) *  Math.Sin(Convert.ToDouble(latitude) / constValue) +
                                     Math.Cos(Convert.ToDouble(l.Latitude) / constValue) *
                                     Math.Cos(Convert.ToDouble(latitude) / constValue) *
                                     Math.Cos((Convert.ToDouble(longitude) / constValue) - (Convert.ToDouble(l.Longitude) / constValue))
                                 let calMiles = (constValue2 * Math.Acos(temp > 1 ? 1 : (temp < -1 ? -1 : temp)))
                                 where (l.Latitude > 0 && l.Longitude > 0)
                                 orderby calMiles
    
    select new location
      {
         Name = l.name
      });
      return loc .ToList();
    
    0 讨论(0)
提交回复
热议问题