Выпуклый многоугольник - C (СИ)
Формулировка задачи:
Очень нужно решить одну задачку, половину вроде бы сделал, но что-то не то, помогите, если сможете, пожалуйста. Фишка в том, что её нужно решить с подпрограммой
Сейчас объясню задумку. Например, мы задали 5-ти угольник. Вершины обзовём, соответсвенно 1, 2, 3, 4 и 5. Я провожу линию через точки 1 и 3 и проверяю формулой выше, находятся ли точки 2 и 4 по одну сторону относительно этой линии, или же по разные. И так проверяю кажду точку, потом строю другую прямую через 2 и 4 вершину и проверяю точки снова. Если они находятся по разные стороны, то это выпуклый многоугольник, если же нет, то вогнутый. Посоветуйте пожалуйста что-нибудь, а то я вообще без понятия что дальше делать... И ещё эта подпрограмма..
Заранее спасибо!
Выпуклый многоугольник
Многоугольник задан координатами своих вершин при их
последовательном
обходе. Составить подпрограмму, определяющую, является ли многоугольник выпуклым. Вот то, что я надумал:#include <stdio.h>
#include <math.h>
#include <conio.h>
void main ()
{
int n,i,s,k,t;
int x[100], y[100];
float l,r;
clrscr ();
printf("Введите кол-во вершин многоугольника* - ");
scanf("%i",&n);
for(i=0; i<n; i++)
{
printf("Введите координаты вершины: ");
scanf("%i %i", &x[i], &y[i]);
for(s=1; s<=l; s++)
for(k=1; k<=r; k++)
{
l=x[i]*(y[i+1]-y[i-1])+y[i]*(x[i-1]-x[i+1])+(x[i+1]*y[i-1]-x[i-1]*y[i+1]);
r=x[i+2]*(y[i+1]-y[i-1])+y[i+2]*(x[i-1]-x[i+1])+(x[i+1]*y[i-1]-x[i-1]*y[i+1]);
if(l*r<0)
printf("Выпуклый ");
else
printf("Вогнутый ");
}Решение задачи: «Выпуклый многоугольник»
textual
Листинг программы
///////////////////////////////////////////////////////////////////////////////////////
//Многоугольник задан координатами своих вершин при их последовательном обходе.
//Составить подпрограмму, определяющую, является ли многоугольник выпуклым.
///////////////////////////////////////////////////////////////////////////////////////
#include <algorithm>
#include <complex>
#include <functional>
#include <iostream>
#include <limits>
#include <vector>
///////////////////////////////////////////////////////////////////////////////////////
typedef double T_coord;
typedef std::complex<T_coord> T_vertice;
typedef std::vector<T_vertice> T_polygon;
typedef std::vector<T_coord> T_dets;
///////////////////////////////////////////////////////////////////////////////////////
template<class T>
bool equal_to_for_real(T a, T b)
{
const T coef = 10;
return abs(a - b) < std::numeric_limits<T>::epsilon() * coef;
}
///////////////////////////////////////////////////////////////////////////////////////
template<class T>
bool greater_for_real(T a, T b)
{
return a > b
&& !equal_to_for_real(a, b);
}
///////////////////////////////////////////////////////////////////////////////////////
template<class T>
bool less_for_real(T a, T b)
{
return a < b
&& !equal_to_for_real(a, b);
}
///////////////////////////////////////////////////////////////////////////////////////
template<class T>
bool greater_equal_for_real(T a, T b)
{
return !less_for_real(a, b);
}
///////////////////////////////////////////////////////////////////////////////////////
template<class T>
bool less_equal_for_real(T a, T b)
{
return !greater_for_real(a, b);
}
//////////////////////////////////////////////////////////////////////////////////////
bool operator< (T_vertice vert_A, T_vertice vert_B)
{
return equal_to_for_real(vert_A.real(), vert_B.real())
? less_for_real(vert_A.imag(), vert_B.imag())
: less_for_real(vert_A.real(), vert_B.real());
}
///////////////////////////////////////////////////////////////////////////////////////
T_coord det(T_vertice A, T_vertice B)
{
return A.real() * B.imag() - B.real() * A.imag();
}
///////////////////////////////////////////////////////////////////////////////////////
bool polygon_is_convex(const T_polygon& polygon)
{
//Сдвигаем циклически вершины.
T_polygon turned_polygon(polygon);
std::rotate(turned_polygon.begin(), turned_polygon.begin() + 1, turned_polygon.end());
//Находим векторы сторон многоугольника. Для этого вычитаем из элемнтов turned_polygon
//элементы polygon.
T_polygon edges;//Первый элемент - сторона 1-2.
std::transform(turned_polygon.begin(), turned_polygon.end(), polygon.begin(),
std::back_inserter(edges), std::minus<T_vertice>());
//Сдвигаем циклически стороны многоугольника.
T_polygon turned_edges(edges);
std::rotate(turned_edges.begin(), turned_edges.begin() + 1, turned_edges.end());
//Находим определители между соседними сторонами многоугольника.
T_dets dets;
std::transform(edges.begin(), edges.end(), turned_edges.begin(),
std::back_inserter(dets), det);
//Проверяем, что все определители ненулевые и одного знака.
//---------------------------------------------------------
//Ищем нулевой элемент.
T_dets::const_iterator zero_it
= std::find_if(dets.begin(), dets.end(),
std::bind2nd(std::ptr_fun(equal_to_for_real<T_coord>), 0.0));
if(zero_it != dets.end()) return false;
//Ищем положительный определитель.
T_dets::const_iterator positive_it
= std::find_if(dets.begin(), dets.end(),
std::bind2nd(std::ptr_fun(greater_for_real<T_coord>), 0.0));
//Ищем отрицательный определитель.
T_dets::const_iterator negative_it
= std::find_if(dets.begin(), dets.end(),
std::bind2nd(std::ptr_fun(less_for_real<T_coord>), 0.0));
return positive_it == dets.end()
|| negative_it == dets.end();
}
///////////////////////////////////////////////////////////////////////////////////////
int main()
{
std::locale::global(std::locale(""));
int n = 0;
do
{
std::cout << "Введите число вершин многоугольника >= 1: ";
std::cin >> n;
}while(n < 1);
std::cout << "Введите "
<< n
<< " вершин многоугольника последовательно "
<< std::endl
<<"в порядке обхода границы в любом направлении:"
<< std::endl;
T_polygon polygon;
while(polygon.size() < static_cast<size_t>(n))
{
std::cout << std::endl
<< "X["
<< polygon.size() + 1
<< "] = ";
T_coord x = 0;
std::cin >> x;
std::cout << "Y["
<< polygon.size() + 1
<< "] = ";
T_coord y = 0;
std::cin >> y;
T_vertice vertice_cur(x, y);
polygon.push_back(vertice_cur);
}
std::cout << "Заданный "
<< n
<< "-угольник "
<< (polygon_is_convex(polygon) ? "" : "НЕ ")
<<"является выпуклым."
<< std::endl;
}
Объяснение кода листинга программы
В данном коде реализована функция, определяющая выпуклость заданного многоугольника.
- В начале кода подключаются необходимые библиотеки: iostream, limits, algorithm, complex, vector.
- Далее, с помощью директивы #define, определяется тип вершин многоугольника - T_coord, который представляет собой числа с плавающей точкой.
- Затем, с помощью директивы #define, определяется тип вектора вершин многоугольника - T_polygon.
- Далее, определяются функции equal_to_for_real, greater_for_real, less_for_real, greater_equal_for_real, less_equal_for_real, которые сравнивают числа с плавающей точкой, используя функцию std::numeric_limits
::epsilon() для определения допустимой погрешности. - Затем, определяется оператор < для вершин многоугольника, который сравнивает координаты вершин.
- Далее, определяется функция det, которая вычисляет определитель векторов.
- В функции main() пользователю предлагается ввести количество вершин многоугольника, после чего запрашиваются координаты вершин и сохраняются в векторе polygon.
- Затем, вызывается функция polygon_is_convex, которая проверяет выпуклость многоугольника. Результат проверки выводится на экран. Таким образом, данный код решает задачу определения выпуклости выпуклого многоугольника, заданного координатами своих вершин при их последовательном обходе.