Если вы ищете скорость, вот процедура, которая может вам помочь.
Сортировка вершин треугольника по их ординатам. Это займет в худшем случае три сравнения. Пусть Y0, Y1, Y2 - три отсортированных значения. Проводя через них три горизонтали, вы делите плоскость на две полуплоскости и две плиты. Пусть Y будет ординатой точки запроса.
if Y < Y1
if Y <= Y0 -> the point lies in the upper half plane, outside the triangle; you are done
else Y > Y0 -> the point lies in the upper slab
else
if Y >= Y2 -> the point lies in the lower half plane, outside the triangle; you are done
else Y < Y2 -> the point lies in the lower slab
Стоит еще два сравнения. Как видите, быстрое отклонение достигается для точек за пределами «ограничительной плиты».
При желании вы можете поставить тест на абсциссу для быстрого отклонения слева и справа (X <= X0' or X >= X2'
). При этом будет реализован быстрый ограничивающий прямоугольный тест, но вам также придется сортировать по абсциссам.
В конце концов вам нужно будет вычислить знак данной точки относительно двух сторон треугольника, которые разграничивают соответствующую плиту (верхнюю или нижнюю). Тест имеет вид:
((X - Xi) * (Y - Yj) > (X - Xi) * (Y - Yj)) == ((X - Xi) * (Y - Yk) > (X - Xi) * (Y - Yk))
Полное обсуждение комбинаций i, j, k
(их шесть на основе результатов такого рода) выходит за рамки этого ответа и «оставлено читателю как упражнение»; для эффективности они должны быть жестко закодированы.
Если вы считаете, что это решение сложное, обратите внимание, что оно в основном включает в себя простые сравнения (некоторые из которых могут быть предварительно вычислены), плюс 6 вычитаний и 4 умножения в случае неудачи теста ограничивающего прямоугольника. Последнюю стоимость трудно превзойти, поскольку в худшем случае вы не можете избежать сравнения контрольной точки с двумя сторонами (ни один метод в других ответах не имеет более низкой стоимости, некоторые ухудшают ее, например, 15 вычитаний и 6 умножений, иногда делений). 1017 *
UPDATE:
Быстрее с преобразованием сдвига
Как объяснено выше, вы можете быстро найти точку внутри одной из четырех горизонтальных полос, разделенных тремя ординатами вершин, используя два сравнения.
При желании можно выполнить один или два дополнительных теста X, чтобы проверить внутреннюю границу ограничительной рамки (пунктирные линии).
Затем рассмотрим преобразование "сдвиг", определяемое как X'= X - m Y, Y' = Y
, где m
- наклон DX/DY
для самого высокого края. Это преобразование сделает эту сторону треугольника вертикальной. И поскольку вы знаете, на какой стороне средней горизонтали вы находитесь, достаточно проверить знак относительно одной стороны треугольника.
Предполагая, что вы предварительно вычислили наклон m
, а также X'
для вершин срезаемого треугольника и коэффициенты уравнений сторон как X = m Y + p
, вам понадобится в худшем случае
- сравнение двух ординат для вертикальной классификации;
- опционально одно или два сравнения абсцисс для отклонения ограничительной рамки;
- вычисление
X' = X - m Y
;
- одно или два сравнения с абсциссами срезанного треугольника;
- один знак теста
X >< m' Y + p'
против соответствующей стороны срезанного треугольника.