Алгоритм целочисленного числа витков с граничными случаями

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

  • 0, если точка находится за пределами многоугольника
  • 1, если точка находится на краю или вершине многоугольника
  • 2, если точка находится внутри многоугольника

И аналогично в других случаях. (РЕДАКТИРОВАТЬ: изображение нескольких примеров )

Каждый алгоритм, который я обнаружил, не работает, когда точка находится на ребре или вершине.

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

Мне не нужно обрабатывать вырожденные пути, которые имеют две последовательные совпадающие точки или поворот на 180 градусов.

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

def orient((x,y), (a0,b0), (a1,b1)):
    return cmp((a1-a0)*y + (b0-b1)*x + a0*b1-a1*b0, 0)
def windingnumber(p0, ps):
    w, h = 0, [cmp(p, p0) for p in ps]
    for j in range(len(ps)):
        i, k = (j-1)%len(ps), (j+1)%len(ps)
        if h[j] * h[k] == -1:
            w += orient(p0, ps[j], ps[k])
        elif h[j] == 0 and h[i] == h[k]:
            w += orient(ps[k], ps[i], ps[j])
    return w

Ссылка на версию с комментариями и модульными тестами.

Мне нужна ссылка на правильный алгоритм, или подтверждение правильности моего алгоритма, или тестовый пример, когда мой алгоритм не работает. Спасибо!

5
задан Cosmologicon 10 December 2011 в 04:45
поделиться