Так что это довольно неловко, но после сна над проблемой ответ кажется очевидным. Я пишу это, чтобы, надеюсь, помочь учащимся в будущем с тем же вопросом, что и я.
Край Вороного между двумя участками перпендикулярно делит (воображаемый) отрезок линии, соединяющий участки. Вы можете получить наклон края, взяв перпендикуляр угла наклона соединительного отрезка, а затем выполнив тест пересечения линии на двух краях, но есть еще более простой способ.
Если три узла не коллинеарны , то ребра, которые перпендикулярно делят пополам сегменты между участками, также касаются круга, ребро которого содержит все три узла. Следовательно, точки останова, определяемые тройкой узлов Вороного, сходятся, если центр круга, определяемого тремя участками, находится перед участком middle , где «впереди» и «сзади» зависят от системы координат и выравнивание линии поворота, которое вы выбрали.
В моем случае у меня есть горизонтальная линия поворота, по которой я двигаюсь от минимума y к максимуму y, поэтому точки останова сходятся, если координата y центра круга больше, чем координата y среднего участка, и расходятся в противном случае.
Редактировать: Кристиан Д'Амато справедливо указывает, что алгоритм выше пропускает некоторые случаи сходимости. Последний алгоритм, который я использовал, приведен ниже. Конечно, я не уверен, что это на 100% правильно, но, похоже, это работает для всех случаев, на которых я его опробовал.
Given left, middle, right sites
if they are collinear, return false
center = ComputeCircleCenterDefinedBy3Points(left, middle, right)
return IsRightOfLine(left, middle, center) && IsRightOfLine(middle, right, center)
IsRightOfLine(start, end, point)
((end.X - start.X) * (point.Y - start.Y) - (end.Y - start.Y) * (point.X - start.X)) <= 0