Имея список точек, как мне найти, если они расположены по часовой стрелке?
Например:
point[0] = (5,0)
point[1] = (6,4)
point[2] = (4,5)
point[3] = (1,5)
point[4] = (1,0)
сказал бы, что это против часовой стрелки (или против часовой стрелки, для некоторых людей).
Ответы:
Некоторые из предложенных методов потерпят неудачу в случае невыпуклого многоугольника, такого как полумесяц. Вот простой, который будет работать с невыпуклыми многоугольниками (он даже будет работать с самопересекающимся многоугольником, подобным восьмерке, сообщая, будет ли он в основном по часовой стрелке).
Суммируйте по краям, (x 2 - x 1 ) (y 2 + y 1 ). Если результат положительный, кривая идет по часовой стрелке, если она отрицательная, кривая против часовой стрелки. (Результат - удвоенная закрытая область с условием +/-.)
источник
Sum( (x[(i+1) mod N] - x[i]) * (y[i] + y[(i+1) mod N]) )
для i = от 0 до N-1. Т.е. должен брать индекс по модулю N (N ≡ 0
) Формула работает только для замкнутых многоугольников. Полигоны не имеют воображаемых ребер.Крест продукт измеряет степень перпендикулярной-ность двух векторов. Представьте, что каждое ребро вашего многоугольника является вектором в плоскости xy трехмерного (3-D) пространства xyz. Тогда перекрестным произведением двух последовательных ребер является вектор в направлении z (положительное направление z, если второй сегмент направлен по часовой стрелке, минус направление z, если против часовой стрелки). Величина этого вектора пропорциональна синусу угла между двумя исходными краями, поэтому он достигает максимума, когда они перпендикулярны, и сужается, чтобы исчезнуть, когда края коллинеарны (параллельны).
Итак, для каждой вершины (точки) многоугольника рассчитайте величину двойного произведения двух соседних ребер:
Так обозначьте края последовательно как
edgeA
сегмент отpoint0
кpoint1
иedgeB
междуpoint1
кpoint2
...
edgeE
междуpoint4
иpoint0
.Тогда вершина A (
point0
) находится междуedgeE
[Frompoint4
topoint0
]edgeA
[Frompoint0
to `point1 'Эти два ребра сами являются векторами, координаты x и y которых можно определить, вычитая координаты их начальной и конечной точек:
edgeE
=point0
-point4
=(1, 0) - (5, 0)
=(-4, 0)
иedgeA
=point1
-point0
=(6, 4) - (1, 0)
=(5, 4)
иИ крест произведение этих двух смежных ребер вычисляется с использованием определитель следующей матрицы, которая строится путем ввода координат двух векторов ниже символов , представляющих три оси координат (
i
,j
, &k
). Третья (нулевая) -значная координата существует потому, что концепция кросс-произведения является трехмерной конструкцией, и поэтому мы расширяем эти 2-D векторы в 3-D, чтобы применить кросс-произведение:Учитывая, что все перекрестные произведения дают вектор, перпендикулярный к плоскости умножаемых двух векторов, определитель матрицы выше имеет только
k
компонент (или ось Z).Формула для вычисления величины компонента
k
или оси z имеет видa1*b2 - a2*b1 = -4* 4 - 0* 1
=-16
Величина этого значения (
-16
) является мерой синуса угла между двумя исходными векторами, умноженного на произведение величин двух векторов.На самом деле, другая формула для его стоимости
A X B (Cross Product) = |A| * |B| * sin(AB)
.Итак, чтобы вернуться к показателю угла, вам нужно разделить это значение (
-16
) на произведение двух векторов.|A| * |B|
=4 * Sqrt(17)
=16.4924...
Таким образом, мера греха (AB) =
-16 / 16.4924
=-.97014...
Это мера того, изогнулся ли следующий сегмент после вершины влево или вправо, и насколько. Нет необходимости принимать арк-синус. Все, о чем мы будем заботиться, это его величина и, конечно, его знак (положительный или отрицательный)!
Сделайте это для каждой из 4 других точек по замкнутому пути и сложите значения из этого расчета в каждой вершине.
Если итоговая сумма положительна, вы пошли по часовой стрелке, отрицательно, против часовой стрелки.
источник
Я думаю, это довольно старый вопрос, но я все равно собираюсь выкинуть другое решение, потому что оно простое и не математически интенсивное - оно просто использует базовую алгебру. Вычислите подписанную площадь многоугольника. Если оно отрицательное, точки расположены по часовой стрелке, если оно положительное, они против часовой стрелки. (Это очень похоже на решение Беты.)
Вычислите область со знаком: A = 1/2 * (x 1 * y 2 - x 2 * y 1 + x 2 * y 3 - x 3 * y 2 + ... + x n * y 1 - x 1 * y н )
Или в псевдокоде:
Обратите внимание, что если вы проверяете только порядок, вам не нужно делить на 2.
Источники: http://mathworld.wolfram.com/PolygonArea.html
источник
previousPoint
для следующей итерации. Перед началом цикла установитеpreviousPoint
последнюю точку массива. Компромисс - дополнительная копия локальной переменной, но меньший доступ к массиву. И самое главное, не нужно трогать входной массив.Найдите вершину с наименьшим y (и наибольшим x, если есть связи). Пусть вершина будет,
A
а предыдущая вершина в списке будет,B
а следующая вершина в списке будетC
. Теперь вычислите знак перекрестного произведенияAB
иAC
.Ссылки:
Как мне найти ориентацию простого многоугольника? в часто задаваемых вопросах: comp.graphics.algorithms .
Кривая ориентации в Википедии.
источник
O(1)
решение. Все остальные ответы даютO(n)
решения дляn
числа точек многоугольника. Для еще более глубокой оптимизации, см. Подраздел « Практические соображения » фантастической статьи о ориентации кривой «Википедия» .O(1)
только в том случае, если либо (A) этот многоугольник является выпуклым (в этом случае любая произвольная вершина находится на выпуклой оболочке и, следовательно, достаточно), либо (B) вы уже знаете вершину с наименьшей координатой Y. Если это не так (т. Е. Этот многоугольник невыпуклый, и вы ничего о нем не знаете), требуетсяO(n)
поиск. Однако, поскольку суммирование не требуется, это все равно значительно быстрее, чем любое другое решение для простых многоугольников.Вот простая реализация алгоритма на C #, основанная на этом ответе .
Давайте предположим , что у нас есть
Vector
тип , имеющийX
иY
свойства типаdouble
.%
является оператором по модулю или остатку, выполняющим операцию по модулю, которая ( согласно Википедии ) находит остаток после деления одного числа на другое.источник
Начните с одной из вершин и вычислите угол, образованный каждой стороной.
Первый и последний будут равны нулю (так что пропустите); в остальном синус угла будет задан как произведение произведенных нормализаций на единицу длины (точка [n] -точка [0]) и (точка [n-1] -точка [0]).
Если сумма значений положительна, то ваш многоугольник нарисован против часовой стрелки.
источник
Для чего бы это ни стоило, я использовал этот миксин для расчета порядка намотки для приложений Google Maps API v3.
В коде используется побочный эффект областей многоугольника: порядок вершин по часовой стрелке дает положительную область, а порядок вращения тех же вершин против часовой стрелки создает ту же площадь, что и отрицательное значение. Код также использует своего рода частный API в библиотеке геометрии Карт Google. Я чувствовал себя комфортно, используя его - используйте на свой страх и риск.
Пример использования:
Полный пример с юнит-тестами @ http://jsfiddle.net/stevejansen/bq2ec/
источник
Реализация ответа Шона в JavaScript:
Уверен, что это правильно. Кажется, это работает :-)
Эти полигоны выглядят так, если вам интересно:
источник
Это реализованная функция для OpenLayers 2 . Условие наличия многоугольника по часовой стрелке
area < 0
подтверждается этой ссылкой .источник
Если вы используете Matlab, функция
ispolycw
возвращает true, если вершины многоугольника расположены по часовой стрелке.источник
Кроме того, как описано в этой статье Википедии ориентация кривой , давалось 3 очка
p
,q
иr
на самолете (т.е. с координатами х и у), можно вычислить знак следующего определителяЕсли определитель отрицателен (то есть
Orient(p, q, r) < 0
), то многоугольник ориентирован по часовой стрелке (CW). Если определитель является положительным (то естьOrient(p, q, r) > 0
), многоугольник ориентирован против часовой стрелки (против часовой стрелки). Определитель равен нулю (т.е.Orient(p, q, r) == 0
) , если точекp
,q
иr
являются коллинеарны .В приведенной выше формуле, мы предварять те , перед координатами
p
,q
иr
потому , что мы используем однородные координаты .источник
Код C # для реализации ответа LHF :
источник
Я думаю, что для того, чтобы некоторые точки давались по часовой стрелке, все ребра должны быть положительными, а не только сумма ребер. Если одно ребро отрицательно, то по крайней мере 3 очка даются против часовой стрелки.
источник
Мое решение C # / LINQ основано на совете по продуктам @charlesbretana ниже. Вы можете указать эталонную норму для обмотки. Он должен работать до тех пор, пока кривая в основном находится в плоскости, определенной вектором вверх.
с модульным тестом
источник
Это мое решение, используя объяснения в других ответах:
источник
Гораздо более простой в вычислительном отношении метод, если вы уже знаете точку внутри многоугольника :
Выберите любой отрезок из исходного многоугольника, точки и их координаты в указанном порядке.
Добавьте известную «внутреннюю» точку и сформируйте треугольник.
Рассчитайте CW или CCW, как предложено здесь, с этими тремя точками.
источник
После тестирования нескольких ненадежных реализаций алгоритм, который дал удовлетворительные результаты в отношении ориентации CW / CCW, был опубликован OP в этой теме (
shoelace_formula_3
).Как всегда, положительное число представляет ориентацию CW, а отрицательное число - CCW.
источник
Вот быстрое решение 3.0, основанное на ответах выше:
источник
Другое решение для этого;
Возьмите все вершины в виде такого массива;
источник
Решение для R, чтобы определить направление и повернуть, если по часовой стрелке (нашел это необходимым для объектов):
источник
Хотя эти ответы верны, они математически более интенсивны, чем необходимо. Предположим, координаты карты, где самая северная точка является самой высокой точкой на карте. Найдите самую северную точку, и если 2 точки связаны, это самый северный, а затем самый восточный (это точка, которую lhf использует в своем ответе). В ваших очках,
точка [0] = (5,0)
точка [1] = (6,4)
точка [2] = (4,5)
точка [3] = (1,5)
точка [4] = (1,0)
Если мы предположим, что P2 - самая северная точка, то восточная точка предыдущей или следующей точки определяет по часовой стрелке, CW или CCW. Так как самая северная точка находится на северной стороне, если P1 (предыдущий) к P2 перемещается на восток, направление - CW. В этом случае он движется на запад, поэтому в направлении принятого ответа указано CCW. Если предыдущая точка не имеет горизонтального перемещения, то та же система применяется к следующей точке, P3. Если P3 к западу от P2, это так, тогда движение - это против часовой стрелки. Если движение P2 к P3 - восток, в этом случае это запад, движение CW. Предположим, что nte, P2 в ваших данных, является самой северной, чем восточной точкой, а prv - предыдущей точкой, P1 в ваших данных, а nxt - следующей точкой, P3 в ваших данных, а [0] - горизонтальная или восточная / запад, где запад меньше, чем восток, а [1] вертикальный.
источник
.x
и.y
из структуры, вместо того ,[0]
и[1]
я не знаю , что ваш код говорил, первый раз , когда я взглянул на него.)Вот простая реализация Python 3, основанная на этом ответе (которая, в свою очередь, основана на решении, предложенном в принятом ответе )
источник
найти центр масс этих точек.
Предположим, есть линии от этой точки до ваших точек.
найти угол между двумя линиями для line0 line1
чем сделать это для line1 и line2
...
...
если этот угол монотонно увеличивается, чем против часовой стрелки,
иначе, если монотонно уменьшается, то по часовой стрелке
иначе (это не монотонно)
Вы не можете решить, так что это не мудро
источник