Пользователь вводит n-е пункты. Мне нужно проверить, существует ли многоугольник, а затем определить тип — вогнутый или выпуклый многоугольник. Я знаю, что многоугольник является выпуклым, если каждый из его углов меньше 180 градусов. Таким образом, проблема сводится к поиску каждого внутреннего угла многоугольника. Я искал формулу или алгоритм, но безуспешно.
Пример:
Вход: n = 4;
Точка 1: (5; 6)
Точка 2: (4; -5)
Точка 3: (-5; 4)
Точка 4: (-5; 5)
Ожидаемый результат: полигон выпуклый
Пока это код: прямо сейчас он находит только максимальное и минимальное расстояние между точками на плоскости.
#include "stdafx.h"#include <iostream>
using namespace std;
int main()
{
double a[15][2];
int n;
cin >> n;
if (n <= 0 && n > 15)
return 1;
for (int i = 0; i < n; i++)
{
cout << "x" << i << " = , y" << i << " = ";
cin >> a[i][0] >> a[i][1];
}
double maxDistance = 0.0;
double minDistance = 0.0;
double maxpoint1[2];
double maxpoint2[2];
double minpoint1[2];
double minpoint2[2];
for (int i = 0; i < n; i++)
{
for (int j = 0; j < n; j++)
{
if (j != i)
{
double x1 = a[i][0];
double x2 = a[j][0];
double y1 = a[i][1];
double y2 = a[j][1];
double currentDistance = sqrt(pow(x2 - x1, 2) + pow(y2 - y1, 2));
if (currentDistance > maxDistance)
{
maxDistance = currentDistance;
maxpoint1[0] = x1;
maxpoint1[1] = y1;
maxpoint2[0] = x2;
maxpoint2[1] = y2;
}
if (minDistance > currentDistance)
{
currentDistance = minDistance;
minpoint1[0] = x1;
minpoint1[1] = y1;
minpoint2[0] = x2;
minpoint2[1] = y2;
}
cout << "x1 = " << x1 << " y1 = " << y1 << " x2 = " << x2 << " y2 = " << y2;
cout << endl << "Distance is " << currentDistance;
cout << endl;
}
}
}
cout << "The max distance is: " << maxDistance << " between x1 = " << maxpoint1[0] << " y1 = " << maxpoint1[1] << " and x2 = " << maxpoint2[0] << " y2 = " << maxpoint2[1];
cout << "The min distance is: " << minDistance << " between x1 = " << minpoint1[0] << " y1 = " << minpoint1[1] << " and x2 = " << minpoint2[0] << " y2 = " << minpoint2[1];return 0;
}
Чтобы определить, является ли многоугольник выпуклым или вогнутым, просто проверьте признаки перекрестных произведений для всех последовательных точечных триплетов. CrossProduct(P[0], P[1], P[2]) etc
, Как пример
CrossProductSign(A, B, C) =
SignOf((B.X - A.X) * (C.Y - B.Y) - (B.Y - A.Y) * (C.X - B.X))
Для выпуклой формы все перекрестные произведения должны иметь одинаковый знак (+ или -).
Как это работает: для выпуклого многоугольника каждый триплет поворачивается в одну сторону (или CW, или CCW в зависимости от направления ходьбы). Для вогнутых некоторые знаки будут отличаться (где внутренний угол превышает 180 градусов). Обратите внимание, что вам не нужно рассчитывать значения углов.
Если вы хотите найти угол между двумя сторонами, используйте перекрестное или точечное произведение векторов.
точка b = | a || b | cos (angle_between_vectors) = a [0] * b [0] + a [1] * b [1] + a [2] * b [2]
внутренний угол будет (pi — angle_between_vectors)
О, кстати, многоугольник может пересекаться сам по себе, что также вредно во многих случаях. Ваше определение не сможет обнаружить это … например сложный квад будет иметь все углы менее 90 градусов.
Это не единственный способ определить, является ли многоугольник выпуклым, и, возможно, один из наиболее сложных для вычисления?
Проблема с точечным произведением состоит в том, что его знак будет отображаться, если угол меньше или больше, чем pi / 2. Правильный способ определить, является ли ваш многоугольник сложным или невыпуклым, состоит в том, чтобы проверить, изменяется ли направление поворота. Для этого вам понадобится перекрестный продукт. Для 2d векторов результат их перекрестного произведения получил только z компонент (перпендикулярно плоскости), его знак определяет, в каком направлении произошло вращение.
Вопрос уже был здесь.
Как определить, является ли многоугольник сложным / выпуклым / невыпуклым?