Алгоритм для расширения/выкачивания (возмещение, буферизуя) полигоны

Хорошее правило ползунка (не всегда идеал, ну, в общем, просто правило ползунка) состоит в том, чтобы перефразировать, если хеш-таблица заполнена до 80%. Это означает, есть ли у Вас 100 блоков и 80 объектов внутри, независимо сколько коллизии Вы имели прежде, это заставляет время увеличивать способность.

, Насколько необходимо увеличить его? Ну, нет также никакого идеального значения. Простое решение должно удвоить способность на каждом увеличении. Таким образом, это переходит в 200, 400, 800, и так далее. Если Вы будете думать, что это слишком много (в конце концов, то это спрыгнет с памяти на 8 МБ к 16 МБ, когда хеш-таблица станет действительно большой, и Вы никогда не можете заполнять 16 МБ), выберите, меньшее выращивают фактор. По крайней мере, 1/3, рекомендуют (рост его от 100 до 133), я сказал бы, возможно, позволить ему вырасти на 50% каждый раз как компромисс.

Примечание, что все это также зависит, как обрабатываются коллизии. Простой способ обработать их (мой любимый) состоит в том, чтобы сохранить объекты в связанном списке, когда существует коллизия. Если 3 объекта помещаются в тот же ключ, существуют все еще, до только 3 выдерживают сравнение для нахождения его. Начиная со связанного списка очень неэффективны для поиска, можно хотеть увеличить способность ранее, например, если 60%-я способность используется для хранения хеш-таблицы быстро. OTOH, можно сделать что-то более сложное и сохранить статистику о количестве коллизий. Пока у Вас едва есть любые коллизии (если у Вас есть очень хорошая хеш-функция) нет никакой потребности перефразировать вообще, даже если 99% ее способности используются. Также, если Вы обрабатываете коллизии сложным способом (например, каждый узел является снова отсортированной таблицей, и можно выполнить двоичный поиск в них) поиск мог бы все еще быть достаточно быстрым, если таблица загружается в 200% (таким образом, у Вас есть вдвое больше объектов как способность). В этом случае Вы могли сохранить статистику, насколько большой самая большая отсортированная таблица и когда это становится больше, чем, скажем, 8 записей, Вы думаете, что это становится слишком медленным, и затем Вы перефразируете.

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

187
задан Dukeling 24 June 2017 в 06:02
поделиться

4 ответа

Вот альтернативное решение, посмотрите, понравится ли оно вам больше.

  1. Проведите триангуляцию , это не должно быть медленным - подойдет любая триангуляция. .

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

  3. Объедините их, используя модифицированный алгоритм отсечения Вейлера-Атертона

5
ответ дан 23 November 2019 в 05:47
поделиться

Sounds to me like what you want is:

  • Starting at a vertex, face anti-clockwise along an adjacent edge.
  • Replace the edge with a new, parallel edge placed at distance d to the "left" of the old one.
  • Repeat for all edges.
  • Find the intersections of the new edges to get the new vertices.
  • Detect if you've become a crossed polygon and decide what to do about it. Probably add a new vertex at the crossing-point and get rid of some old ones. I'm not sure whether there's a better way to detect this than just to compare every pair of non-adjacent edges to see if their intersection lies between both pairs of vertices.

The resulting polygon lies at the required distance from the old polygon "far enough" from the vertices. Near a vertex, the set of points at distance d from the old polygon is, as you say, not a polygon, so the requirement as stated cannot be fulfilled.

I don't know if this algorithm has a name, example code on the web, or a fiendish optimisation, but I think it describes what you want.

9
ответ дан 23 November 2019 в 05:47
поделиться

Многоугольник, который вы ищете, в вычислительной геометрии называется многоугольником смещения вовнутрь / наружу и тесно связан с прямым каркасом .

Это несколько полигонов смещения для сложного многоугольника:

А это прямой скелет для другого многоугольника:

Как указано в других комментариях, в зависимости от того, насколько далеко вы планируете «раздувать / deflate »ваш многоугольник, вы можете получить различные возможности подключения для вывода.

С точки зрения вычислений: как только у вас есть прямой скелет, можно будет относительно легко построить смещенные многоугольники. Библиотека с открытым исходным кодом и (бесплатная для некоммерческих) CGAL имеет пакет, реализующий эти структуры. См. этот пример кода для вычисления полигонов смещения с использованием CGAL. ​​

Руководство по пакету должно дать вам хорошую отправную точку для создания этих структур, даже если вы не собираетесь использовать CGAL, и содержит ссылки на документы с математическими определениями и свойствами:

Руководство CGAL: 2D прямой каркас и смещение многоугольника

38
ответ дан 23 November 2019 в 05:47
поделиться

Each line should split the plane to "inside" and "outline"; you can find this out using the usual inner-product method.

Move all lines outward by some distance.

Consider all pair of neighbor lines (lines, not line segment), find the intersection. These are the new vertex.

Cleanup the new vertex by removing any intersecting parts. -- we have a few case here

(a) Case 1:

 0--7  4--3
 |  |  |  |
 |  6--5  |
 |        |
 1--------2

if you expend it by one, you got this:

0----a----3
|    |    |
|    |    |
|    b    |
|         |
|         |
1---------2

7 and 4 overlap.. if you see this, you remove this point and all points in between.

(b) case 2

 0--7  4--3
 |  |  |  |
 |  6--5  |
 |        |
 1--------2

if you expend it by two, you got this:

0----47----3
|    ||    |
|    ||    |
|    ||    |
|    56    |
|          |
|          |
|          |
1----------2

to resolve this, for each segment of line, you have to check if it overlap with latter segments.

(c) case 3

       4--3
 0--X9 |  |
 |  78 |  |
 |  6--5  |
 |        |
 1--------2

expend by 1. this is a more general case for case 1.

(d) case 4

same as case3, but expend by two.

Actually, if you can handle case 4. All other cases are just special case of it with some line or vertex overlapping.

To do case 4, you keep a stack of vertex.. you push when you find lines overlapping with latter line, pop it when you get the latter line. -- just like what you do in convex-hull.

5
ответ дан 23 November 2019 в 05:47
поделиться
Другие вопросы по тегам:

Похожие вопросы: