Поиск:

Ответ в темуСоздание новой темы Создание опроса
> Расстояния... 
:(
    Опции темы
Vit
Дата 6.6.2006, 20:39 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Vitaly Nevzorov
****


Профиль
Группа: Экс. модератор
Сообщений: 10964
Регистрация: 25.3.2002
Где: Chicago

Репутация: нет
Всего: 207



Задача достаточно тривиальная, но удобного решения я не нашёл.

Итого есть таблица например магазинов вида:

Имя магазина ---- Широта --- Долгота

Задача: если я живу в координатах X,Y то как мне найти 10 ближайших ко мне магазинов?

Задача в принципе решена, т.е. формулы для рассчёта расстояния между координатами есть, но... таблица очень большая - десятки миллионов записей, подставлять в формулу 10 миллионов значений - очень долго... Наверное, надо перевести координаты в полярные (сферические) взять какую-то условную длину от точки и проиндексировать её, или несколько таких длин... Может как-то можно и по другому... 


--------------------
With the best wishes, Vit
I have done so much with so little for so long that I am now qualified to do anything with nothing
Самый большой Delphi FAQ на русском языке здесь: www.drkb.ru
PM MAIL WWW ICQ   Вверх
Mal Hack
Дата 6.6.2006, 21:16 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Мудрый...
****


Профиль
Группа: Участник Клуба
Сообщений: 9926
Регистрация: 15.2.2004

Репутация: 1
Всего: 261



Цитата(Vit @  6.6.2006,  20:39 Найти цитируемый пост)
Наверное, надо перевести координаты в полярные (сферические) взять какую-то условную длину от точки и проиндексировать её, или несколько таких длин...

Я так понимаю, что в таком случае, придется все равно каждый раз вычислять радиус от заданной точки.

Вот первое что приходит в голову, а почему бы не ввести еще временную координату, я про часовой пояс. Сначала делать выборку по часовому поясу во временную таблицу, а потом уже в ней искать по координатам. 
PM ICQ   Вверх
Fin
Дата 6.6.2006, 21:41 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Дракон->Спать();
**


Профиль
Группа: Участник
Сообщений: 687
Регистрация: 4.1.2006

Репутация: 1
Всего: 10



Есть другой выход. Отсортировать список сначало по координате X, затем по координате Y.  Твои Координаты известны. 
Составляеш множество магазинов которые близки по координате X. Затем множество магазинов близких по координате Y. Делаеш "логическое И" двух множеств и получаеш список магазинов близких к твоим координатам.   


--------------------
Пролетал мимо.
PM MAIL   Вверх
skyboy
Дата 6.6.2006, 21:41 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


неОпытный
****


Профиль
Группа: Модератор
Сообщений: 9820
Регистрация: 18.5.2006
Где: Днепропетровск

Репутация: нет
Всего: 260



Vit, работа идёт при помощи базы данных? или обработка "вручную"?
Цитата(Mal Hack @  6.6.2006,  21:16 Найти цитируемый пост)
Вот первое что приходит в голову, а почему бы не ввести еще временную координату, я про часовой пояс.

Раз карта - плоскость, то может разбить на квадраты? 
 
PM MAIL   Вверх
Void
Дата 6.6.2006, 21:48 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


λcat.lolcat
****


Профиль
Группа: Участник Клуба
Сообщений: 2206
Регистрация: 16.11.2004
Где: Zürich

Репутация: 3
Всего: 173



После непродолжительного гугления обнаружил следующую статью:
Nearest Neighbour Queries.
К сожалению, там описывается только алгоритм, но не реализация с помощью РСУБД.
Также выяснилось, что некоторые базы данных имеют расширения для задач GIS и spatial search, например Oracle и PostgreSQL. 


--------------------
“Coming back to where you started is not the same as never leaving.” — Terry Pratchett
PM MAIL WWW GTalk   Вверх
Vit
Дата 6.6.2006, 22:55 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Vitaly Nevzorov
****


Профиль
Группа: Экс. модератор
Сообщений: 10964
Регистрация: 25.3.2002
Где: Chicago

Репутация: нет
Всего: 207



Цитата(skyboy @  6.6.2006,  12:41 Найти цитируемый пост)
Vit, работа идёт при помощи базы данных? или обработка "вручную"?


MS SQL Server

Цитата(skyboy @  6.6.2006,  12:41 Найти цитируемый пост)
Раз карта - плоскость, то может разбить на квадраты? 


Карта шар... Земной шар...

Цитата(Fin @  6.6.2006,  12:41 Найти цитируемый пост)
Есть другой выход. Отсортировать список сначало по координате X, затем по координате Y.  Твои Координаты известны. 
Составляеш множество магазинов которые близки по координате X. Затем множество магазинов близких по координате Y. Делаеш "логическое И" двух множеств и получаеш список магазинов близких к твоим координатам.   


Это интересная идея надо подумать...
 


--------------------
With the best wishes, Vit
I have done so much with so little for so long that I am now qualified to do anything with nothing
Самый большой Delphi FAQ на русском языке здесь: www.drkb.ru
PM MAIL WWW ICQ   Вверх
Akina
Дата 6.6.2006, 23:19 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Советчик
****


Профиль
Группа: Модератор
Сообщений: 20581
Регистрация: 8.4.2004
Где: Зеленоград

Репутация: 20
Всего: 454



Ничего хорошего не получится в общем случае - квадраты на шаре так себе квадраты. Впрочем  если надо выбрать 10 из 10 миллионов на глобусе (Антарктида и Арктика, надо понимать, не в счет) - сойдет.

Навскидку - я бы пошел таким путем: разбиение на перекрывающиеся области, форма их - в первом приближении квадраты. Причем перекрытие соседних областей составляет порядка 2/3 стороны (т.е. каждая область как бы состоит из 9 малых "суб-областей"), а количество точек (магазинов) в области порядка 400, причем в каждой "суб-области" не менее 20 (это фактически параметры деления на области, которые могут быть квадратами или прямоугольниками, не обязательно одинакового размера). Тогда можно сразу проводить поиск только в той области, где заданная точка в центральной "суб-области". 


--------------------
 О(б)суждение моих действий - в соответствующей теме, пожалуйста. Или в РМ. И высшая инстанция - Администрация форума.

PM MAIL WWW ICQ Jabber   Вверх
ILAgent
Дата 6.6.2006, 23:49 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 51
Регистрация: 1.3.2006

Репутация: нет
Всего: нет



Раз используешь СУБД, посмотри, как там реализована работа с пространственными объектами.
Что касается сортировки и быстрого поиска, см. R-tree, Quad-tree, k-D-tree. 
А начсчёт формы земли (а это кстати совсем не сфера) и вычисления расстояний см. инфу о проекции Гаусса-Крюгера и др. 
PM MAIL   Вверх
sergejzr
Дата 7.6.2006, 00:28 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Un salsero
Group Icon


Профиль
Группа: Админ
Сообщений: 13285
Регистрация: 10.2.2004
Где: Германия г .Ганновер

Репутация: 4
Всего: 360



Здесь однозначно делить на прямоугольники и субпрямоугольники  величина прямоугольника может вариировать в зависимости от густонаселённости.
Оптимальное количество ступеней найти экспериментальным путём (думаю 50 будет более чем достаточно). При выборке искать в квадратах-соседях.

 


--------------------
PM WWW IM ICQ Skype GTalk Jabber AOL YIM MSN   Вверх
sergejzr
Дата 7.6.2006, 00:57 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Un salsero
Group Icon


Профиль
Группа: Админ
Сообщений: 13285
Регистрация: 10.2.2004
Где: Германия г .Ганновер

Репутация: 4
Всего: 360



Вот, набросал алгоритмик. Совсем без вычислений smile
Аж интересно стало smile С удовольствием бы с базой поиграл smile)))


таблица "rectangles"
-------------------------------------
| id_rectangle | parent_id_rectangle | level | x1 | x2 | y1 | y2 |


таблица neighbours
-----------------------------------
| id_rectangle | id_neigbour |


таблица shops
--------------------------------
| id_shop | id_rectangle (самый низкий уровень)|


Код

$rect=(SELECT id_rectangle FROM shops WHERE id_shop); /*получили самый маленький квадрат*/

$neighbours=(SELECT id_neigbour FROM neighbours WHERE id_rectangle=$rect);/*нашли всех маленьких соседей маленького квадрата*/

$shops=SELECT * from shops where id_rectangle=$rect or $id_rectangle IN ($neighbours);/*нашли все магазы в этом квадрате и соседях*/

if(count($shops)>=max) return shops /*Смотрим, нашли ли достаточное кол-во магазинов*/





do{
 //выбираем квадрат побольше (след. уровень)

$neighbours=(SELECT id_neigbour FROM neighbours WHERE id_rectangle=$rect.parent_id); /*Соседей нашли*/

do{
$small_rects=(SELECT  id_rectangle FROM rectangles WHERE parent_id_rectangle=$neighbours.id_rectangle); /*выбираем квадраты поменьше, которые в наших находятся*/
}while $small_rects.level>0


$shops=SELECT * from shops where id_rectangle=$rect.id_rectangle or $id_rectangle IN ($neighbours);/*нашли все магазы в этом квадрате и соседях*/


}while(count($shops)>=max || $rect.parent_id_rectangle>0) /*или достаточное кол-во магазинов нашли, или наш квадрат - уже весь мир :)*/
return shops;


Теперьмы нашли достаточное количество самых близких магазинов и можем мерить расстояния уже только между ними. Количество сокращается с нескольких миллионов до нескольких десятков. Океаны можно на квадраты не делить, только континтнты и вообще только места, где магазы есть. Просто надо правильно расставить соседей в таблице.
          

Присоединённый файл ( Кол-во скачиваний: 5 )
Присоединённый файл  neigbourhood.gif 14,33 Kb


--------------------
PM WWW IM ICQ Skype GTalk Jabber AOL YIM MSN   Вверх
sergejzr
Дата 7.6.2006, 12:43 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Un salsero
Group Icon


Профиль
Группа: Админ
Сообщений: 13285
Регистрация: 10.2.2004
Где: Германия г .Ганновер

Репутация: 4
Всего: 360



Вообще, лучше на тре/шестиугольники делить. Так соседи всегда будут точно определены.. 


--------------------
PM WWW IM ICQ Skype GTalk Jabber AOL YIM MSN   Вверх
nostromo
Дата 7.6.2006, 19:18 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Бывалый
*


Профиль
Группа: Участник
Сообщений: 194
Регистрация: 23.3.2006

Репутация: 5
Всего: 10



Для нахождения ближайшей точки из заданного множества обычно используются диагораммы Вороного (триангуляция Делоне --- двойственная операция). В сети можно найти кучу готовых реализаций и описаний (в том числе на русском). Для поиска 10 ближайших точек алгоритм нужно немного доработать. 
--------------------
На пыльных тропинках далеких планет останутся наши следы.
PM MAIL   Вверх
Earnest
Дата 7.6.2006, 19:38 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Экс. модератор
Сообщений: 5962
Регистрация: 17.6.2005
Где: Рязань

Репутация: 7
Всего: 183



Задача оптимизации поиска на карте решается только пространственным индексированием. Индексы можно придумать самые разные. Самый простой способ, действительно, разбиение на одинаковые прямоугольники (неважно что на шаре они не очень прямоугольные, главное просто определяется попадание). Этот способ самый простой по реализации и скромный по занимаемой памяти. Но не очень эффективный, ессли речь идет о миллионах объектов, да еще очень неравномерно распределенных. 
Чуть более сложный способ - дерево - двоичное или тернарное, это уже как не в лом писать. Принцип - те же квази-квадраты, но не одинаковые, а уменьшаемые в 2\4 раза по мере углубления в дерево. Т.е. как только объектов в большом квадрате становится больше чем некоторое N, разбиваем его.
Я бы начала с четвертушек шарика.

Вариант с сортировкой по x, потом по y, ничего не даст...

Есть вероятность что в СУБД уже есть встроенное расширение для работы с пространственными данными, тогда там должно быть реализовано индексирование.

Добавлено @ 19:40 
sergej.z, уже примерно это написал, сразу не заметила. Только не согласна насчет тре\шестиугольников, градусные квадраты эффективнее. 


--------------------
...
PM   Вверх
  
Ответ в темуСоздание новой темы Создание опроса
Правила форума "Алгоритмы"

maxim1000

Форум "Алгоритмы" предназначен для обсуждения вопросов, связанных только с алгоритмами и структурами данных, без привязки к конкретному языку программирования и/или программному продукту.


Если Вам понравилась атмосфера форума, заходите к нам чаще! С уважением, maxim1000.

 
0 Пользователей читают эту тему (0 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | Алгоритмы | Следующая тема »


 




[ Время генерации скрипта: 0.1270 ]   [ Использовано запросов: 21 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.