Алгоритм поиска многоугольника, окружающего точку — определены только линии

У меня есть 2D-рисунок с множеством прямых линий. Все эти линии математически известны. И они независимы от других.

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

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


Подробности:

У меня нет заявленных полигонов. Просто линии. Любое количество строк, любой размер, любое положение. И заданная точка.

Эти линии могут образовывать один многоугольник, много или ни одного. Таким образом, нет никаких правил относительно того, как выглядят полигоны. Любое количество сторон, никакой регулярности. (Точки, образующие многоугольники, находятся путем пересечения линий. А линии конечны, если они не пересекаются, они не образуют многоугольник.)

Мой ответ — наименьший возможный многоугольник, содержащий заданную точку.


person Daniel Möller    schedule 10.05.2013    source источник
comment
Что определяет полигон? Гарантируется ли вам, что данные линии соединяются в полный многоугольник? Вы предполагаете, что многоугольник является четырехугольником? Или решение будет больше похоже на выпуклую оболочку?   -  person Sildoreth    schedule 10.05.2013
comment
Любое количество строк, любой размер, любое положение. Дана точка. Многоугольник — это наименьший полигон, который можно составить из линий, содержащих точку внутри. Есть только два возможных результата: многоугольник или ничего (в случае, если линии не охватывают точку)   -  person Daniel Möller    schedule 11.05.2013
comment
Не могли бы вы включить изображение или набор изображений, показывающих, какие решения являются допустимыми, а какие нет? Например... Могут ли стороны многоугольника решения пересекать любую из заданных прямых? Если одна из заданных линий является частью решения, должна ли она БЫТЬ ребром многоугольника решения или только одна из ее концов может использоваться в качестве вершины решения?   -  person Sildoreth    schedule 11.05.2013
comment
Подождите минутку. Я, возможно, смотрел на это неправильно. Дело в том, что все ребра многоугольника решения должны быть коллинеарны заданным отрезкам? Но ребра могут быть длиннее или короче заданных отрезков?   -  person Sildoreth    schedule 11.05.2013
comment
да. Представьте себе крестики-нолики, для очень простого примера. Эти 4 линии образуют один многоугольник, который является центральным квадратом. Если моя заданная точка находится внутри этого квадрата, я хочу этот квадрат. Если заданная точка находится в другом месте, полигона, содержащего ее, нет. Вот почему я сказал, что могу найти все пересечения линий, если это необходимо (поскольку пересечения — это точки, образующие многоугольник).   -  person Daniel Möller    schedule 11.05.2013


Ответы (2)


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

Алгоритм:

  1. Sort the line segments in order of how close they are to the target point.
    • Henceforth whenever you need to loop over the lines, loop over them in this sorted order
    • Рассматривайте сегменты линий как бесконечные линии при расчете их расстояния от целевой точки. расстояние точки/линии
  2. Perform Step 3 with the closest line segment, using the 2nd intersection point along the line in the "counter-clockwise" direction
    • Take "counter-clockwise" to mean the direction that puts the target point on the left side of the line.
    • ПРИМЕЧАНИЕ: мы надеемся, что 1-я точка пересечения — это место, где мы закончим, как только обойдем целевую точку.
  3. На новообретенной линии...

    A. Переберите все остальные линии, которые еще не являются частью фигуры, которую вы строите, и найдите их точки пересечения с этой линией
    B. Отсортируйте точки пересечения против часовой стрелки относительно целевой точки.
    сортировка против часовой стрелки

  4. Найдите следующую точку пересечения против часовой стрелки на текущей линии. Если это первая точка, которую мы проверяем на этой линии, то «следующая» точка — это точка после точки пересечения, которая привела нас к этой линии.

    О. Если такой точки нет (это может означать, что мы уже проверили все точки на текущей строке), то текущее решение-кандидат недопустимо...

    • Backtrack to the previous line and repeat Step 4 with the next point on that line.
    • Если предыдущей строки нет (т. е. вы находитесь на линии, с которой вы начали рисовать фигуру), Назад и выполните Шаг 2 со следующей ближайшей строкой, начиная новая форма.

    B. Если линия, образующая точку пересечения, не имеет целевой точки с левой стороны (против часовой стрелки), то многоугольник, который она образует, не охватывает целевую точку. Повторите шаг 4 для текущей линии со следующей точкой.
    C. Если линия, образующая точку пересечения, — это линия, с которой вы начали, то мы нашли решение
    Г. Если ничего из вышеперечисленного не верно, выполните Шаг 3 для линии, образующей точку пересечения.

Оптимизация:

  1. Если строк меньше 3, решения нет. Не делай никакой работы.
  2. You may want to cache the intersection points when you find them so that you don't have to recalculate them
    • If you choose to do this, I recommend using a 2D array
  3. I recommend throwing out lines when you know that they aren't part of the solution.
    • Example: if you already tried the line closest to the target point, but it didn't lead to a solution, it doesn't make sense to include that line when finding intersection points on other lines.

Примечания:

  • Этот алгоритм проще всего реализовать рекурсивно.
  • Вам придется решить, что делать, если целевая точка находится на одной из линий.
person Community    schedule 22.05.2013
comment
Это кажется отличным подходом! Я бы просто проявил особую осторожность в B, потому что, если у многоугольника есть вогнутость, эта линия может иметь точку на другой стороне. Затем мне нужно будет пройти до конца, чтобы закрыть многоугольник, а затем проверить, находится ли точка внутри него. (Представьте себе звезду, если точка находится внутри нее на одном из концов, линии от обоих соседних концов будут иметь эту точку с правой стороны). - person Daniel Möller; 01.10.2014
comment
Невероятно, но ближайшая линия может образовывать окружающий многоугольник, но этот многоугольник может быть не самым маленьким. Представьте себе большой неправильный многоугольник (конечные линии), внутри которого находится маленький квадрат, линии которого не касаются большего многоугольника. Внутри квадрата находится наша точка. Ничто не мешает точке находиться точно на бесконечном продолжении одной линии от большего многоугольника, что делает эту линию ближайшей. Поэтому всякий раз, когда я нахожу многоугольник, я все равно должен проверять все, что находится внутри этого многоугольника. - person Daniel Möller; 01.10.2014
comment
Из-за вогнутостей я должен также проверить точки пересечения, которые не находятся в последовательности против часовой стрелки. (Многоугольник может сделать поворот на другую сторону, а затем вернуться в направлении по часовой стрелке, пока не закроется). Но это не проблема, если я всегда проверяю точки пересечения в порядке удаления от той, которая заставила меня попасть в эту линию. - person Daniel Möller; 01.10.2014
comment
Но ведь это было достойно! Большое спасибо! - person Daniel Möller; 01.10.2014

Я считаю, что следующий алгоритм будет работать:

  1. Если строк меньше 3, выйти. Нет решения.
  2. Определите линию, ближайшую к целевой точке. Эта строка гарантированно будет частью решения.
  3. Пусть P1 будет перпендикулярной проекцией целевой точки на L1.
  4. Find the two intersection points of the other lines with L1 that are nearest to P1 and on opposite sides of it. These two points are guaranteed to be part of the solution.
    • Lets call these points P2 & P3, and call the lines L2 and L3
    • Если таких точек нет, решения нет.
  5. Найдите ближайшую точку на каждой из L2 и L3, которые находятся ближе всего к P2 и P3 соответственно и находятся на той же стороне L1, что и целевая точка.
  6. Repeat steps 4 and 5 until:
    • The line found coming from both directions is the same line
    • Найденная точка пересечения, идущая с обоих направлений, является одной и той же точкой
    • Точки, соответствующие критериям, не найдены. Это означает, что решения нет.
person Sildoreth    schedule 10.05.2013
comment
Это хорошее начало. Но на шаге 5 точка может быть и с другой стороны, так как линии не бесконечны. Могут даже пересекаться с другими на той же стороне целевой точки, но эти другие могут заканчиваться до закрытия полигона. (Поэтому обе стороны должны рассматриваться с приоритетом к точечной стороне) - person Daniel Möller; 11.05.2013
comment
А также ближайшая линия может быть одна (ничего не пересекая) внутри полигона. - person Daniel Möller; 11.05.2013
comment
Выглядит как проход через дорожки с развилками. Могу ли я после этого отобразить ВСЕ полигоны? За исключением полигонов, образованных двумя соседними полигонами. - person Daniel Möller; 11.05.2013
comment
Ах. Да, если вы не можете предположить бесконечные строки, то этот алгоритм не будет работать для вашего сценария. Я еще немного обдумаю это и опубликую отдельный ответ, если смогу его придумать. Я думаю, что для этого можно реализовать алгоритм «разделяй и властвуй», но он ускользает от меня. Возможно, вам придется реализовать алгоритм обратного отслеживания. - person Sildoreth; 13.05.2013