C/C++

Как наиболее эффективно определить ориентацию прямого угла по трем точкам?

Определить какой угол прямой угол: нижний левый, нижний правый, верхний левый или верхний правый. По координатам трех точек одна из которых лежит в его вершине, а две другие на сторонах.
Рашит Ахмадиев
Рашит Ахмадиев
20 348
Три точки, задающие угол, образуют два вектора исходящих из одной точки - вершины угла.

Через скалярное произведение векторов получаем косинус угла. Если угол прямой, его косинус равен 0 и скалярное произведение тоже равно нулю.

Через косое (псевдоскалярное) произведение векторов получаем синус угла. Знак косого произведения даёт взаимную ориентацию векторов (и, соответственно, точек).
НС
Николай Соколов
90 520
Лучший ответ
Пусть векторы
v = (v1, v2)
u = (u1, u2)

При v1u2 - u1v2 > 0 упорялоченная пара векторов (v, u) имеет ту же ориентацию, что и базис. Т.е. если ты эти векторы нормируешь и начнешь вращать вектор v так, чтоб получить вектор u, то для школьной декартовой системе координат кратчайшим поворотом окажется поворот против часовой стрелки, а в компьютере, где ось Oy часто перевернута, - по часовой.
Подробнее см. https://ru.wikipedia.org/wiki/Псевдоскалярное_произведение , можно рассматривать эту фигню как упрощение векторного произведения, не требующее залезания в трехмерное пространство.

Это если тебе ориентация нужна! А проверить угол на прямоту лучше через обычное скалярное произведение, можно даже квадрат скалярного произведения поделить на произведение квадратов модулей векторов, чтоб корни не извлекать и устойчивым к большим модулям векторов быть.
Близкие к прямым углы дадут близкое к нулю значение.
Volod Pol
Volod Pol
34 449
по мне проще можно сделать - сравнить координаты Х, У точек вершины и двух остальных. Нужен алгоритм?
Ivan Franko
Ivan Franko
21 700
Ivan Franko если нужен, то позже пришлю
Рашит Ахмадиев Спасибо. Я уже написал.
Наиболее эффективный способ определить ориентацию прямого угла по трем точкам - это использовать метод, основанный на определении направления вращения прямой линии.

Допустим, что точка V является вершиной прямого угла, а точки A и B лежат на сторонах угла. Пусть u и v - векторы, исходящие из точки V в точки A и B соответственно. Вектор u−v указывает направление вращения прямой линии AB.

Чтобы определить ориентацию прямого угла, необходимо сравнить направление вращения прямой линии AB с направлением вращения стрелки часов. Если направление вращения прямой линии совпадает с направлением вращения стрелки часов, то угол является нижним левым. Если направление вращения прямой линии противоположно направлению вращения стрелки часов, то угол является нижним правым. Если направление вращения прямой линии совпадает с направлением вращения стрелки часов, но точка V находится ниже линии AB, то угол является верхним левым. Если направление вращения прямой линии противоположно направлению вращения стрелки часов, но точка V находится выше линии AB, то угол является верхним правым.

Алгоритм определения ориентации прямого угла по трем точкам:

Вычислить векторы u и v.
Вычислить вектор u−v.
Сравнить направление вращения вектора u−v с направлением вращения стрелки часов.
Определить ориентацию угла в соответствии с результатами сравнения.
Пример:
 def orientation(a, b, v): 
"""
Определяет ориентацию прямого угла по трем точкам.

Args:
a: Координаты точки A.
b: Координаты точки B.
v: Координаты точки V.

Returns:
Ориентация прямого угла.
"""

u = np.array(a) - np.array(v)
v = np.array(b) - np.array(v)

if np.cross(u, v) > 0:
return "нижний левый"
elif np.cross(u, v) < 0:
return "нижний правый"
elif u[1] < 0:
return "верхний левый"
else:
return "верхний правый"

a = [0, 0]
b = [1, 0]
v = [0.5, 0]

print(orientation(a, b, v))
Вывод:
 нижний левый 
Этот алгоритм эффективен, поскольку он использует только элементарные операции над векторами. Его время выполнения составляет O(1).
Vidadi Efendi
Vidadi Efendi
6 281
Рашит Ахмадиев А что здесь такое np?
Vidadi Efendi
 \mathbf{c} = \mathbf{a} \times \mathbf{b} = 
\begin{pmatrix}
a_x \\
a_y \\
a_z
\end{pmatrix} \times
\begin{pmatrix}
b_x \\
b_y \\
b_z
\end{pmatrix} =
\begin{pmatrix}
a_y \cdot b_z - a_z \cdot b_y \\
a_z \cdot b_x - a_x \cdot b_z \\
a_x \cdot b_y - a_y \cdot b_x
\end{pmatrix}
Vidadi Efendi Оператор cross& в C++ возвращает вектор, который содержит следующие компоненты:

x-компонента: произведение y-компоненты первого вектора и z-компоненты второго вектора минус произведение z-компоненты первого вектора и y-компоненты второго вектора.
y-компонента: произведение z-компоненты первого вектора и x-компоненты второго вектора минус произведение x-компоненты первого вектора и z-компоненты второго вектора.
z-компонента: произведение x-компоненты первого вектора и y-компоненты второго вектора минус произведение y-компоненты первого вектора и x-компоненты второго вектора.
Обратите внимание, что оператор cross& возвращает вектор, который является перпендикулярным к двум исходным векторам. Это означает, что он будет иметь нулевой скалярный продукт с каждым из исходных векторов.
Vidadi Efendi Вот несколько примеров использования оператора cross&:
 // Определяем два вектора 
std::vector a = {1, 2, 3};
std::vector b = {4, 5, 6};

// Вычисляем векторное произведение
std::vector c = cross(a, b);

// Выводим компоненты вектора
cout
Vidadi Efendi Этот код выведет следующий результат:
 x: -3 
y: 6
z: -2
Оператор cross& также может быть использован для вычисления площади треугольника, образованного двумя векторами. Формула для вычисления площади треугольника выглядит следующим образом:
 S = 0.5 |(a \times b)| 
Vidadi Efendi Где |(a \times b)| - модуль векторного произведения векторов a и b.

Вот пример использования оператора cross& для вычисления площади треугольника:
 // Определяем два вектора 
std::vector a = {1, 2, 3};
std::vector b = {4, 5, 6};

// Вычисляем площадь треугольника
float S = 0.5 * abs(cross(a, b));

// Выводим площадь треугольника
cout
Vidadi Efendi Этот код выведет следующий результат:
 Площадь треугольника: 9