Определите, можно ли рисовать 2d-многоугольник с помощью одного треугольника

Сначала я думал, что эта проблема будет эквивалентна определению того, является ли многоугольник выпуклым, однако кажется, что невыпуклый многоугольник все еще может быть нарисован одним веером треугольника. Рассмотрим эту фигуру, не выпуклый многоугольник. Легко представить себе некоторую область центральных точек, которая позволила бы нарисовать этот многоугольник с помощью треугольного веера (хотя бы были другие центральные точки, которые не были бы). Учитывая фиксированную центральную точку, я хочу иметь возможность определить, может ли набор точек 2d, определяющих многоугольник, рисовать его с помощью одного треугольного вентилятора.

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

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

Ответ 1

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

Он будет выглядеть примерно так:

vector lastCross = cross_product( vector(vertex[0] - center), vector(vertex[numVerts - 1] - center) );

canBeFan = true;
for (n = 1; canBeFan && n < numVerts; ++n) {
    vector testCross = cross_product( vector(vertex[n] - center), vector(vertex[n - 1] - center) );
    if (0.0 >= dot_product(testCross, lastCross) ) {
        canBeFan = false;
    }
}

Ответ 2

Свойство, которое вы ищете, это " star-shaped". Звездообразные многоугольники определяются наличием точки, из которой видна всего многоугольника.

Чтобы проверить, что многоугольник имеет звездную форму, вы можете построить область, из которой будет отображаться весь многоугольник. Эта область будет выпуклым множеством, поэтому вы можете пересечь ее с помощью полуплоскости в O(log(n)).

Это означает, что вы можете пересечь полуплоскости, образованные краями, и проверить, что результирующая область видимости не пуста в O(n log n).

Ответ 3

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

Как говорит @jpalecek, термин для этого имеет звездообразную форму. Если ваш многоугольник имеет звездную форму, будет выпуклый многоугольник (внутри оригинала), чьи точки могут видеть все ребра оригинала - и, наоборот, если такой субполигон существует, оригинал не является звездообразным, и вы не можете нарисовать его с помощью треугольного вентилятора.

Определение этого субполигона в основном представляет собой dual приложение выпуклый корпус; он может быть вычислен в O(n log n).