#ruby-on-rails #ruby-on-rails-3 #plugins #rubygems #geolocation
#ruby-on-rails #ruby-on-rails-3 #Плагины #rubygems #геолокация
Вопрос:
У меня есть модель пользователя, и у каждого пользователя широта и долгота хранятся в таблице. Я хочу получить всех пользователей в диапазоне 30 км с заданными широтой и долготой. Любой плагин для вычисления расстояния с использованием широты и долготы из таблицы.
id name latitude longitude
1 abc 43.56 56.34
2 xyz 46.34 57.87
3 mno 50.34 23.56
Предположим, что это мои табличные значения (это просто образец данных.). Я хочу получить всех пользователей в радиусе 30 км от заданной высоты, например (34.89, 56.45)
Ответ №1:
Существует прекрасный камень Geokit, который добавляет этот метод в ваши модели:
Store.find(:all, :origin =>[37.792,-122.393], :within=>10)
или даже
Store.find(:all, :origin=>'100 Spear st, San Francisco, CA', :within=>10)
Ответ №2:
В Thinking sphinx есть поиск, сортировка и фильтрация по расстоянию от широты и долготы: http://freelancing-god.github.com/ts/en/geosearching.html
Ответ №3:
Используя справку из скриптов с подвижным типом, опубликованную Wicked, я произвел это вычисление расстояния между двумя точками (используйте метод в активной записи, которая имеет атрибуты lat, lng):
def calc_distance(origin)
radius = 6371
lat1 = to_rad(origin[0])
lat2 = to_rad(self.lat)
lon1 = to_rad(origin[1])
lon2 = to_rad(self.lng)
dLat = lat2-lat1
dLon = lon2-lon1
a = Math::sin(dLat/2) * Math::sin(dLat/2)
Math::cos(lat1) * Math::cos(lat2) *
Math::sin(dLon/2) * Math::sin(dLon/2);
c = 2 * Math::atan2(Math::sqrt(a), Math::sqrt(1-a));
d = radius * c
end
def to_rad angle
angle * Math::PI / 180
end
Geokit очень надежный, но мне нужно было только рассчитать расстояние, плюс Geokit требует базы данных, отличной от sqlite
Комментарии:
1. Новейший Geokit совместим с sqlite.
Ответ №4:
Попробуйте эту ссылку. Существует подробное объяснение подхода.
http://www.movable-type.co.uk/scripts/latlong.html
Кроме того, я нашел этот алгоритм C # в Интернете. Я надеюсь, что это поможет.
class DistanceAlgorithm
{
const double PIx = 3.141592653589793;
const double RADIO = 6378.16;
/// <summary>
/// This class cannot be instantiated.
/// </summary>
private DistanceAlgorithm() { }
/// <summary>
/// Convert degrees to Radians
/// </summary>
/// <param name="x">Degrees</param>
/// <returns>The equivalent in radians</returns>
public static double Radians(double x)
{
return x * PIx / 180;
}
/// <summary>
/// Calculate the distance between two places.
/// </summary>
/// <param name="lon1"></param>
/// <param name="lat1"></param>
/// <param name="lon2"></param>
/// <param name="lat2"></param>
/// <returns></returns>
public static double DistanceBetweenPlaces(
double lon1,
double lat1,
double lon2,
double lat2)
{
double dlon = lon2 - lon1;
double dlat = lat2 - lat1;
double a = (Math.Sin(dlat / 2) * Math.Sin(dlat / 2)) Math.Cos(lat1) * Math.Cos(lat2) * (Math.Sin(dlon / 2) * Math.Sin(dlon / 2));
double angle = 2 * Math.Atan2(Math.Sqrt(a), Math.Sqrt(1 - a));
return angle * RADIO;
}