Пространственные структуры данных в C - PullRequest
9 голосов
/ 17 сентября 2008

Я работаю в области теоретической химии на высокопроизводительном кластере, часто включающем моделирование молекулярной динамики. Одна из проблем, к которой относится моя работа, связана со статическим полем из N-мерных (обычно N = 2-5) гиперсфер, с которыми может сталкиваться пробная частица. Я стремлюсь оптимизировать (читай: пересмотреть) структуру данных, которую я использую для представления поля сфер, чтобы я мог быстро обнаруживать столкновения. В настоящее время я использую простой мертвый массив указателей на N-членную структуру (удваивается для каждой координаты центра) и список ближайших соседей. Я слышал о восьмеричных и четырехугольных деревьях, но не нашел четкого объяснения того, как они работают, как эффективно реализовать одно или как затем быстро обнаружить столкновение с ним. Учитывая размер моих симуляций, память (почти) не объект, а циклы.

Ответы [ 5 ]

4 голосов
/ 17 сентября 2008

Как лучше всего подойти к этой проблеме, зависит от нескольких факторов, которые вы не описали: - Будет ли такое же расположение гиперсфер использоваться для многих расчетов столкновений частиц? - Гиперсферы одинакового размера? - Что такое движение частицы (например, прямая линия / кривая) и влияют ли на это движение сферы? - Считаете ли вы, что частица имеет нулевой объем?

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

Если ваши положения в гиперсфере фиксированы для большого количества столкновений частиц, тогда вычисление разложения вороной / тесселяции Дирихле даст вам быстрый способ позже найти точно, какая сфера ближе всего к вашей частице для любой данной точки в космосе.

Однако, чтобы ответить на ваш первоначальный вопрос о octrees / quadtrees / 2 ^ n-деревьях, в n измерениях вы начинаете с (гипер) -куба, который содержит интересующую вас область пространства. Он будет разделен на 2 ^ n гиперкубов, если вы считаете содержимое слишком сложным. Это продолжается рекурсивно до тех пор, пока в узлах листа не останутся только простые элементы (например, один гиперсферный центроид). Теперь, когда n-дерево построено, вы используете его для обнаружения столкновений, беря путь вашей частицы и пересекая его с внешним гиперкубом. Положение пересечения скажет вам, какой гиперкуб на следующем уровне вниз по дереву следует посетить следующим, и вы определите позицию пересечения со всеми 2 ^ n гиперкубами на этом уровне, следуя вниз, пока не достигнете листового узла. Как только вы достигнете листа, вы можете исследовать взаимодействие между вашим путем частиц и гиперсферой, хранящейся на этом листе. Если у вас есть столкновение, которое вы закончили, в противном случае вы должны найти точку выхода пути частицы из текущего листа гиперкуба и определить, к какому гиперкубу он перемещается в следующий. Продолжайте, пока не найдете столкновение или не покинете весь ограничивающий гиперкуб.

Эффективное нахождение соседнего гиперкуба при выходе из гиперкуба является одной из самых сложных частей этого подхода. Для 2 ^ n деревьев подходы Самета {1, 2} могут быть адаптированы. Для kd-деревьев (бинарных деревьев) подход предлагается в разделе {3} 4.3.3.

Эффективная реализация может быть такой же простой, как сохранение списка из 8 указателей от каждого гиперкуба на его дочерние гиперкубы и специальная маркировка гиперкуба, если это лист (например, сделать все указатели NULL).

Описание разделения пространства для создания дерева квадрантов (которое можно обобщить для n-дерева) можно найти в Klinger & Dyer {4}

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

{1} Маркировка подключенных компонентов, Ханан Самет, Использование журнала Quadtrees в журнале ACM, том 28, выпуск 3 (июль 1981 года)

{2} Обнаружение соседей в изображениях, представленных октреями, Ханан Самет, том компьютерного зрения, графики и обработки изображений, том 46, выпуск 3 (июнь 1989 года)

{3} Выпуклая генерация корпуса, маркировка подключенных компонентов и минимальное расстояние расчет для теоретически заданных моделей, Дэн Пидкок, 2000

{4} Эксперименты по представлению изображений с использованием регулярного разложения, Klinger, A. и Dyer, C.R. E, Comptr. Графика и обработка изображений 5 (1976), 68-105.

1 голос
/ 17 сентября 2008

Звучит так, будто вы хотите реализовать kd-дерево , которое позволит вам быстрее искать в N-мерном пространстве. Больше информации и ссылок на реализации в репозитории алгоритма Stony Brook.

1 голос
/ 17 сентября 2008

Поскольку ваше поле статично (я предполагаю, что вы имеете в виду, что гиперсферы не двигаются), то самое быстрое решение, которое я знаю, это Kdtree.
Вы можете сделать свой собственный, или использовать чужой, как этот: http://libkdtree.alioth.debian.org/

0 голосов
/ 17 сентября 2008

Октри будет работать до тех пор, пока вы можете указать сферы по их центрам - оно иерархически объединяет точки в кубические области с восемью дочерними элементами. Для разработки соседей в структуре данных октодерева вам потребуется выполнить вычисления куба, пересекающего сферу (в некоторой степени проще, чем они выглядят), чтобы определить, какие кубические области в октрее находятся внутри сферы.

Поиск ближайших соседей означает переход назад вверх по дереву, пока вы не получите узел с более чем одним заполненным дочерним элементом и включением всех окружающих узлов (это гарантирует, что запрос получает все стороны).

По памяти это (несколько наивный) базовый алгоритм пересечения сферы с кубом:

я. Является ли центр внутри куба (получается одноименная ситуация)

II. Находятся ли какие-либо углы куба в радиусе r от центра (углы внутри сферы)

III. Для каждой поверхности куба (вы можете устранить некоторые из поверхностей, определив, на какой стороне поверхности лежит центр), выполните следующие действия (это векторная арифметика первого года):

а. Нормаль поверхности, которая идет к центру сферы

б. Расстояние от центра сферы до пересечения нормали с плоскостью поверхности (хорда пересекает плоскость поверхности куба)

с. Пересечение плоскости лежит внутри стороны куба (одно условие пересечения хорды с кубом)

IV. Рассчитать размер хорды (Sin of Cos ^ -1 отношения нормальной длины к радиусу сферы)

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

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

0 голосов
/ 17 сентября 2008

Четырехъядерное дерево - это двумерное дерево, в котором на каждом уровне узел имеет 4 дочерних элемента, каждый из которых покрывает 1/4 площади родительского узла.

Октябрьское дерево - это трехмерное дерево, в котором на каждом уровне узел имеет 8 дочерних элементов, каждый из которых содержит 1/8 объема родительского узла. Вот изображение, чтобы помочь вам визуализировать его: http://en.wikipedia.org/wiki/Octree

Если вы выполняете N-мерные пересечения, вы можете обобщить это на N-дерево.

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

...