Главная страница
    Top.Mail.Ru    Яндекс.Метрика
Форум: "Прочее";
Текущий архив: 2014.05.25;
Скачать: [xml.tar.bz2];

Вниз

Нумерация точек в системе координат.   Найти похожие ветки 

 
Дмитрий СС   (2013-11-17 20:15) [0]

Предположим есть двухмерная система координат, где координаты - целые числа.
Всевозможные точки необходимо пронумеровать. Должно быть некое соответствие:
n = f(x,y), где
x, y - координаты точки (целые).
n - номер этой точки.

Каждой точке соответствует один номер, каждому номеру - одна точка.
Должна быть возможность получить координаты по номеру точки (расчетом, а не перебором).
А также, важно, чтобы номер возрастал по мере отдаления точки от центра координат (поэтому, упаковка n=x*k+y, (где k - некое большое число) не подойдет).
Желательно, чтобы подсчет был математически простым.
Я помню мы это проходили в институте, знаю, что великие математики уже решили эту задачу, но не помню даже по каким словам искать.
Буду благодарен за направления для поиска! Спасибо.


 
Kerk ©   (2013-11-17 20:39) [1]

Отрицательные координаты могут быть?


 
Дмитрий СС   (2013-11-17 20:42) [2]


> Отрицательные координаты могут быть?

да


 
Павиа   (2013-11-17 21:25) [3]

По-спирали из центра пронумеруй.


 
Styx   (2013-11-17 21:26) [4]

Ну дык по спирали намотать... вроде очевидно. Или хочется готовую формулу?


 
Дмитрий СС   (2013-11-17 21:37) [5]


> Или хочется готовую формулу?

Конечно хочется, зачем велосипед изобретать. К тому же может быть есть что-то оптимальнее чем "по-спирали"


 
картман ©   (2013-11-17 21:46) [6]

x,y: smallint;
n: int64;
n = ( ( (x^2 * y^2) shl 32)  ) or (y shl 16) or x;


 
картман ©   (2013-11-17 21:50) [7]


> (x^2 * y^2) shl 32)  

(x^2 + y^2) shl 32)


 
Дмитрий СС   (2013-11-17 22:02) [8]


> картман

Так это ж тоже самое что и
n=x*k+y

Вот в упрощенном виде:
n = x shl 32 + y

Хотя изучая материал в интернете я уже не думаю, что это такая уж плохая идея.


 
Styx   (2013-11-17 22:44) [9]


> n=x*k+y

Это же не удовлетворяет требовантю

> чтобы номер возрастал по мере отдаления точки от центра
> координат

Или оно уже не важно, коли никто за Вас формулу для спирпли придумывать не стал? ;-)


 
[ВладОшин] ©   (2013-11-17 22:45) [10]


> Так это ж тоже самое что и
> n=x*k+y
>
> Вот в упрощенном виде:
> n = x shl 32 + y


а где тут


> А также, важно, чтобы номер возрастал по мере отдаления
> точки от центра координа


 
Дмитрий СС   (2013-11-17 22:50) [11]

Последним двух авторам:
Это плата за простоту.

Те способы, которые я нашел - они в лоб и слишком сложны.

А n = x shl 32 + y проста, но не все условия выполняются. придется выбирать, если не найду чего то более простого


 
Dimka Maslov ©   (2013-11-17 22:52) [12]

1. Номер должен быть уникальным
2. Номер должен возрастать по мере удаления от центра
3. Из номера можно получить координаты
4. Возможны отрицательные координаты

По моему это взаимоисключающие параграфы


 
Дмитрий СС   (2013-11-17 22:54) [13]

не вижу противоречий, что именно?


 
[ВладОшин] ©   (2013-11-17 22:54) [14]

Ну, задача твоя, тебе видней :)

А может сменить систему отсчета?
Пусть Х - расстояние до центра, а Y - угол с осью.
В Х уже заложено расстяние до центра :)
а У всегда выражается целочисленной дробью.


 
Sha ©   (2013-11-17 23:03) [15]

> важно, чтобы номер возрастал по мере отдаления точки от центра координат

как будем нумеровать равноудаленные точки?


 
картман ©   (2013-11-17 23:08) [16]


> Должна быть возможность получить координаты по номеру точки
> (расчетом, а не перебором).

а откуда такое ограничение? Ну, что мешает завести ассоциативный массив?


 
Dimka Maslov ©   (2013-11-17 23:13) [17]


> Дмитрий СС   (17.11.13 22:54) [13]


Как должны соотноситься друг с другом номера точек (-99, 99) и (99, -100), которые почти равноудалены от центра? Так что, либо возрастание по мере удаления от центра, либо возможность восстановления, либо простота. Теорему вон Ферма сколько лет доказывали по принципу "должно быть просто и понятно"?


 
Дмитрий СС   (2013-11-18 02:02) [18]


> как будем нумеровать равноудаленные точки?

недалеко отстоящими значениями. Это не принципиально.

Идея в том, что если расширить тип N до, скажем Int64 мы должны увеличить площадь охватываемого поля.


> а откуда такое ограничение? Ну, что мешает завести ассоциативный
> массив?

Есть же разница: массив с таскать или по формуле считать )


 
wicked ©   (2013-11-18 02:22) [19]

вот ссамое близкое решение твоей задачи

> [ВладОшин] ©   (17.11.13 22:54) [14]
> Ну, задача твоя, тебе видней :)
>
> А может сменить систему отсчета?
> Пусть Х - расстояние до центра, а Y - угол с осью.
> В Х уже заложено расстяние до центра :)
> а У всегда выражается целочисленной дробью.


на n условия целочисленности нет?
тогда выражать n = int(r) + phi/360 (r - радиус, phi - в градусах)

либо, если будет много точек возле начала координат, то заменить int(r) на int(r * 1000), чтобы близколежащие точки не путались


 
jumping jack   (2013-11-18 08:05) [20]

упаковка n=расстояние*n+x*k+y  (n>k)
пересчет в полярную с. к. не обеспечит абсолютной точности обратного пересчета


 
jumping jack   (2013-11-18 08:10) [21]

если не будет влезать - от y можно оставить только знак и пару младших бит (или от х)


 
Sha ©   (2013-11-18 09:41) [22]

> Нумерация точек в системе координат.

Все стесняются спросить, тогда придется мне: а зачем это надо?


 
Дмитрий СС   (2013-11-18 12:33) [23]


> Sha ©   (18.11.13 09:41) [22]

Есть таблица с объектами с их координатами (планируемый разброс координат +/-10E8). Необходимо построить такой индекс, с помощью которого можно извлечь все объекты из любой небольшой прямоугольной области (к примеру 1000х500). Поскольку от индекса по координатам толку не будет я решил сделать следующее:
разбить плоскость на квадраты (или секторы, для удобства размером 1024х1024) и каждый квадрат пронумеровать. По этому номеру проиндексировать все объекты.
Когда потребуется поиск по области, я вычисляю в каких квадратах она лежит и делаю запрос с условием sector in (...) and x between .... and y between. Тем самым очень сильно сужаю область поиска.

Сейчас я понимаю что нумерация по спирали неэффективная, т.к. расчеты будут очень сложными. Поэтому сектора я буду нумеровать парами чисел M и N: порядковые номера по горизонтали и по вертикали соответственно), а базе это будет bigint, рассчитанный по формуле Sector=(M shl 32) or N. Формула указана на вскидку.

Всем спасибо!


 
[ВладОшин] ©   (2013-11-18 13:38) [24]


> Поскольку от индекса по координатам толку не будет

Сомневаюсь..

пробовал?
если четыре индекса: [х], [у], [x][y], [y][x]  и если целочисленные - думаю, поможет хорошо.


 
Дмитрий СС   (2013-11-18 13:42) [25]


> [ВладОшин] ©   (18.11.13 13:38) [24]

Запрос к примеру:
SELEC * FROM objects WHERE (x BETWEEN 10000 AND 11000) AND (y BETWEEN -6000 AND -5000)

И какой индекс использовать?


 
[ВладОшин] ©   (2013-11-18 13:48) [26]


> 10E8

ух ты, не обратил внимания
тогда не надо [x][y], [y][x] :)


> И какой индекс использовать?

а СУБД какая?


 
MBo ©   (2013-11-18 14:02) [27]

см. kd-tree, r-tree
Как с базами данных это сочетается, не знаю


 
Дмитрий СС   (2013-11-18 14:06) [28]


> [ВладОшин] ©   (18.11.13 13:48) [26]
>

Не важно какая СУБД, принцип индексирования все-равно один и тот же.
Но если для примера: mysql. Можете взять и mssql.


> ух ты, не обратил внимания

Это не значит что объектов столько, просто разброс координат такой:)


 
Дмитрий СС   (2013-11-18 14:07) [29]


> MBo ©   (18.11.13 14:02) [27]

Спасибо, прочту!


 
Павиа   (2013-11-18 14:12) [30]

Тогда за одно советую ещё прочитать "в ведение в вычислительную геометрию".


 
[ВладОшин] ©   (2013-11-18 14:36) [31]


> Дмитрий СС   (18.11.13 14:06) [28]

Ok, mssql.
Проверю дома одну мыслю.


 
Кщд   (2013-11-18 14:59) [32]

>Дмитрий СС   (18.11.13 14:06) [28]
1. СУБД - важна, ибо в некоторых есть поддержка гео-данных и, соответственно, возможность индексирования с массой полезнах ф-ция(расстояние между объектами, вхождение одного объекта в другой и пр.);
2. В случае "плоских" данных поможет индекс по [x, y];
3. Идея с разбиением на бОльшие области и подразбиением каждой из них на меньшие - не нова и правильна при большом кол-ве объектов.
Не ясно, зачем нужна ф-ция нумерации, когда это решается след. алгоритмом:
1. Найти большУю область, в которой лежит точка;
2. Найти её подобласть, к которой точка принадлежит;
3. Повторить (2), если имеются меньшие подобласти.

Создаёте либо обычный индекс, либо индекс по ф-ции вхождения точки в область.


 
Кщд   (2013-11-18 14:59) [33]

полезнах))


 
jumping jack   (2013-11-18 20:39) [34]

http://technet.microsoft.com/ru-ru/library/bb964712(v=sql.105).aspx


 
[ВладОшин] ©   (2013-11-18 21:14) [35]

а каковы реальные объемы?
сколько объектов?


 
Дмитрий СС   (2013-11-18 22:20) [36]


> [ВладОшин] ©   (18.11.13 21:14) [35]

10-100 млн. такой порядок.


> jumping jack   (18.11.13 20:39) [34]

Очень круто.


 
jumping jack   (2013-11-19 05:44) [37]

если вдруг захочется свой велосипед делать - можно генерировать число для индексации по типу quad-tree: допустим, карта квадратная; старшие 2 бита числа определяют квадрант (квадрат в 1/4 от большего) на этой карте - Юго-Западный, СЗ, СВ или ЮВ; следующие 2 бита помладше - субквадрант внутри предыдущего и так далее

тогда 1 запрос c WHERE ... BETWEEN выдаст точки внутри любого из иерархических субквадрантов (но не любого произвольного прямоугольника - тут нужны либо несколько запросов, либо (наверное, быстрее) самому отфильтровать лишние точки из наименьшего полностью включающего нужную область субквадранта)


 
jumping jack   (2013-11-19 05:54) [38]

иными словами, этот quad-tree-index легко получить так: биты координат X и Y должны в индексном числе чередоваться: старший от X, старший от Y, следующие от X и Y и т. д. (самые младшие наверное не нужны, да и не войдут)
получается, все довольно легко и просто!


 
jumping jack   (2013-11-19 08:41) [39]

p.s. видимо, стоит закладываться на 4 запроса: например, область в самом центре карты не попадает полностью вообще ни в какой 1 субквадрант, но покроется 4-мя достаточно маленькими субквадрантами

ну и от минуса в координатах при рассчете индекса придется избавиться (добавить константу)


 
Кщд   (2013-11-19 10:11) [40]

>jumping jack   (19.11.13 08:41) [39]
структуру таблицы и предполагаемые индексы можно увидеть?
или сферический конь в вакууме?)


 
jumping jack   (2013-11-19 12:31) [41]

Кщд, поясните что именно вы не поняли?
структуру определит автор, но в ней явно будут X, Y, и индексное поле
индекс, конечно, один-единственный (а зачем их могло бы понадобиться несколько???)


 
Кщд   (2013-11-19 14:24) [42]

>jumping jack   (19.11.13 12:31) [41]
структуру таблицы, в которой, конечно, будут X и Y(пусть, например, это будут X, Y и некое поле VAL), ф-лу  для заполнения "индексного" поля и тип индекса - можно увидеть?
а также хотелось бы посмотреть типовой(ые?) запрос(ы)
пока есть мнение, что Вы не представляете, о чем говорите


 
jumping jack   (2013-11-19 14:59) [43]

Кщд, подожду мнения ТС
троллей много, а жизнь коротка
(извините)


 
Кщд   (2013-11-19 15:20) [44]

>jumping jack   (19.11.13 14:59) [43]
согласен
пустая демагогия имеет свойство разбиваться о суровую конкретную техническую реальность


 
jumping jack   (2013-11-19 15:30) [45]

:)


 
Кщд   (2013-11-19 22:58) [46]

>jumping jack   (19.11.13 15:30) [45]
автор потерялся, жаль
мне, как человеку, работающему с нелепыми ГИС-системами, которые отчего-то решили построить на реляционной базе, очень интересна конкретная реализация Вашего подхода

буквально четыре строки: создание таблицы, ф-ла для вычисляемого поля, тип индекса(достаточно команды на создание) и типовой select(точнее - два: получение координат объекта(напр., по имени) и получение объектов по диапазону координат).

PS про нелепые системы - это не сарказм. ГИС-системы не нужно создавать на основе реляционных баз, ибо они дурно ложатся на плоские таблицы
PPS можно в синтаксисе любой СУБД, с которой Вы знакомы достаточно свободно


 
Кщд   (2013-11-19 23:01) [47]

*создание таблицы - либо нескольких, если надобно, конечно
если таблица одна, то вопрос про "select" координат по имени снимается


 
jumping jack   (2013-11-20 02:41) [48]

Кщд, ок!
сама формула для индексного поля (вычисляемого, но хранимого в таблице) получится большая и некрасивая, но принцип должен быть ясен: биты от беззнаковых целых координат Х и  У чередуются по одному с сохранением порядка старшие-младшие: старший от Х, старший от У, следующий от Х и т.д.
т. е. индексное поле - целочисленного типа, беззнакового либо без использования знакового бита, я бы взял BIGINT (int64), но это на усмотрение автора
возможно, БД не поддерживает побитовые сдвиги и логику - тогда вычислять это нужно в своём приложении

тип индекса - самый простой, неуникальный, ASC[ending] (хотя и DESC скорее всего будет так же работать), по одному этому полю

получение точечных объектов по диапазону координат будет простым для любого из иерархических (суб)квадрантов -
select * from table where index_field between m and n
объяснение, что такое m и n заняло бы еще абзац-другой, так что просто ознакомьтесь с концепцией "quad-tree"
вкратце, это min и max значения индексных чисел, адресующих малейшие субквадранты в заданном квадранте
т.е. 0 или несколько последних _пар_ бит в m будут нулями, а в n - единичками

получение точечных объектов для любой прямоугольной области сложнее и может потребовать в запросе четырех разных диапазонов - (between m1 and n1) or (between m2 and n2) or (between m3 and n3)  or (between m4 and n4) - по описанным в [39] причинам - и последующей фильтрацией лишних объектов (предположительно не на сервере)
все детали описывать не берусь
sapienti sat

впрочем, автор/ТС наверняка уже ушел прорубаться в дебрях встроенных гео-средств mssql, и наверное, правильно сделал - удачи ему там


 
jumping jack   (2013-11-20 02:47) [49]

*) под "пара бит будет единичками" имел в виду "оба бита в паре установлены"


 
jumping jack   (2013-11-20 03:41) [50]

на всякий случай, для тех, кто в танке, еще одно пояснение:
что собственно означают отдельные биты беззнакового целого числа?
а вот что: самый старший бит показывает, в какой половине области значений данного типа чисел данное число располагается - в "большой" половине или в "малой" - т.е. больше число, чем MaxVal div 2 или меньше/равно?
следующий бит показывает, в какой из четвертей (половин предыдущих половин) области значений находится число и так далее
по такому же принципу построены вышеописанные "quad-tree index numbers", только там вместо единичных битов, указывающих на половину, половину половины и т.д. - пары битов, указывающих на квадрант, субквадрант в предыдущем квадранте и т.д.

в случае, когда области значений координат Х и У одинаковы, пары битов, определяющих субквадранты, можно брать прямиком из битов одинакового старшинства значений координат - получится их чередование

сходным образом для трехмерных данных можно построить "octo-tree index", уже с тройками бит

а это примечание не для тех, кто "в танке":
если координаты - это широта и долгота, то есть смысл биты широты ставить по старшинству впереди соотв. битов долготы - если формировать запросы по половинкам субквадрантов, то такая разбивка будет оптимальнее (с удалением от экватора километраж одного градуса долготы уменьшается, а у градуса широты он всегда постоянный) - на половинки лучше разбивать именно широту


 
jumping jack   (2013-11-20 05:35) [51]

"у градуса широты он (километраж) всегда постоянный"
- не совсем, он немного увеличивается с удалением от экватора


 
jumping jack   (2013-11-20 13:32) [52]

а вот и пресловутая "формула":
unsigned long long expand_bits(unsigned long long n)
{
n = n & 0x0000ffff0000ffff | (n & 0xffff0000ffff0000) << 16;
n = n & 0x00ff00ff00ff00ff | (n & 0xff00ff00ff00ff00) << 8;
n = n & 0x0f0f0f0f0f0f0f0f | (n & 0xf0f0f0f0f0f0f0f0) << 4;
n = n & 0x3333333333333333 | (n & 0xcccccccccccccccc) << 2;
n = n & 0x5555555555555555 | (n & 0xaaaaaaaaaaaaaaaa) << 1;
return n;
}

unsigned long long index_val = expand_bits(x) << 1 | expand_bits(y);


 
Кщд   (2013-11-20 14:43) [53]

>jumping jack   (20.11.13 02:41) [48]
всего лишь просил четыре строки кода
увидел одну

понял, что при мелком разбиение крупных областей может не хватить и int64
а самое главное - такой подход неэффективен на порядке записей ~10^8
даже при использовании индекса по битовой маске

использование такого подхода снизит скорость модификации данных(перестройка индекса) и выборки данных - по причине выше


 
jumping jack   (2013-11-20 16:22) [54]

> может не хватить и int64
если меридиан длиной 20000 км разбить на 2^32 частей, получим ~ 5 мм - или вы антаресодезией там у себя занимаетесь?
> такой подход неэффективен
очень радует, что есть более эффективные - значит РСУБД все-таки на что-то еще годятся



Страницы: 1 2 вся ветка

Форум: "Прочее";
Текущий архив: 2014.05.25;
Скачать: [xml.tar.bz2];

Наверх





Память: 0.6 MB
Время: 0.003 c
15-1385095642
atruhin
2013-11-22 08:47
2014.05.25
Алгоритмы. Обход списка с удалением произвольных элементов


2-1375798951
mfender
2013-08-06 18:22
2014.05.25
Появляются лишние символы при отправке TIdMultiPartFormDataStream


2-1375632164
NewOne
2013-08-04 20:02
2014.05.25
Проверка на существование


15-1384939416
Nil
2013-11-20 13:23
2014.05.25
Работа с SQLite


15-1385107572
Сергей
2013-11-22 12:06
2014.05.25
Решение задачи





Afrikaans Albanian Arabic Armenian Azerbaijani Basque Belarusian Bulgarian Catalan Chinese (Simplified) Chinese (Traditional) Croatian Czech Danish Dutch English Estonian Filipino Finnish French
Galician Georgian German Greek Haitian Creole Hebrew Hindi Hungarian Icelandic Indonesian Irish Italian Japanese Korean Latvian Lithuanian Macedonian Malay Maltese Norwegian
Persian Polish Portuguese Romanian Russian Serbian Slovak Slovenian Spanish Swahili Swedish Thai Turkish Ukrainian Urdu Vietnamese Welsh Yiddish Bengali Bosnian
Cebuano Esperanto Gujarati Hausa Hmong Igbo Javanese Kannada Khmer Lao Latin Maori Marathi Mongolian Nepali Punjabi Somali Tamil Telugu Yoruba
Zulu
Английский Французский Немецкий Итальянский Португальский Русский Испанский