Авторизация



Счетчики

Обмен ссылками

Блог программиста
Электрик сделает электромонтажные работы дома в Новокузнецке и пригороде. Русский электрик.
Главная Borland C++ Builder Площадь семиугольника
Площадь семиугольника PDF Печать E-mail
Автор: Андрей   
31.03.2009 17:01

Описание программы
Расположение компонентов на форме
Свойства компонент
Код программы
Код с подробными комментариями
Советы по улучшению и расширению программы

Описание программы
В этой программе пользователь строит семиугольник, отмечая его вершины в компоненте PaintBox, после чего программа вычисляет его площадь (в пикселах). При этом предполагается, что семиугольник выпуклый. В противном случае для корректного расчета программу необходимо будет расширить. Вычисление площади происходит по следующему принципу: семиугольник разбивается на 5 треугольников (из первой вершины проводятся отрезки в 3ю, 4ю, 5ю и 6ю), а затем считается площадь каждого треугольника, исходя из того, что площадь треугольника, построенного на двух векторах, равна половине длины их векторного произведения. S = 0.5*(Xa*Yb - Ya*Xb), где Xa, Ya, Xb, Yb - проекции векторов на оси X и Y. После чего все площади суммируются.
Определение координат производится при перемещении курсора над PaintBox - событие OnMouseMove, а при щелчке внутри PaintBox сохраняется как координата очередного угла - при событии OnClick.

Используются следующие компоненты: Button, Edit, PaintBox, StaticText.

Расположение компонентов на форме

Размещение компонентов на форме программы

Свойства компонент, измененные по сравнению со стандартными
Button1:
Caption: "Выход"
Edit1:
Text: "0"
Edit2:
Text: "0"
Edit3:
Text: "0"
PaintBox1:
Height: 401
Width: 641
StaticText1:
Caption: "Площадь"
StaticText2:
Caption: "X"
StaticText3:
Caption: "Y"

Код программы

struct SomeAngle
 {
 int X, Y;
 };
SomeAngle SevenAngle[6];
double xx, yy;
int n = 0;
double S = 0;

void CalculateSquare()
{
double Si[5];
double Vector_a_X, Vector_a_Y;
double Vector_b_X, Vector_b_Y;
for (int i = 2; i <= 6; i++)
 {
 Vector_a_X = SevenAngle[i].X - SevenAngle[1].X;
 Vector_a_Y = SevenAngle[i].Y - SevenAngle[1].Y;
 Vector_b_X = SevenAngle[i - 1].X - SevenAngle[1].X;
 Vector_b_Y = SevenAngle[i - 1].Y - SevenAngle[1].Y;
 Si[i - 2] = abs(Vector_a_X * Vector_b_Y - Vector_a_Y * Vector_b_X)/2;
 }
S = 0;
for (int i = 0; i <= 4; i++) S += Si[i];
Form1 -> Edit1 -> Text = S;
}
//--------------------------------------------------------------------
void __fastcall TForm1::PaintBox1MouseMove(TObject *Sender,
 TShiftState Shift, int X, int Y)
{
xx = X;
yy = Y;
}
//--------------------------------------------------------------------
void __fastcall TForm1::PaintBox1Click(TObject *Sender)
{
if (n < 7)
 {
 SevenAngle[n].X = xx;
 SevenAngle[n].Y = yy;
 if (n == 0)
  PaintBox1 -> Canvas -> MoveTo(xx, yy);
 else PaintBox1 -> Canvas -> LineTo(SevenAngle[n].X, SevenAngle[n].Y);
 if (n == 6)
  PaintBox1 -> Canvas -> LineTo(SevenAngle[0].X, SevenAngle[0].Y);
 Edit2 -> Text = SevenAngle[n].X;
 Edit3 -> Text = SevenAngle[n].Y;
 n++;
 }
if (n == 7) CalculateSquare();
}
//--------------------------------------------------------------------
void __fastcall TForm1::Button1Click(TObject *Sender)
{
exit(0);
}

Код программы с комментариями

struct SomeAngle //Вершина треугольника
 {
 int X, Y; //Координаты вершины
 };
SomeAngle SevenAngle[6]; //Массив из семи вершин - от 0 до 6
double xx, yy; //Глобальные переменные, в которые записывается
  //положение курсора
int n = 0; //Количество отмеченных вершин
double S = 0; //Площадь семиугольника

void CalculateSquare() //Функция, вычисляющая площадь
{
double Si[5]; //Массив площадей пяти треугольников,
  //на которые разбивается семиугольник
double Vector_a_X, Vector_a_Y; //Координаты первого вектора,
  //на котором строится треугольник
double Vector_b_X, Vector_b_Y; //Координаты второго вектора
for (int i = 2; i <= 6; i++) //Для всех пяти треугольников
 {
 Vector_a_X = SevenAngle[i].X - SevenAngle[1].X; //Определяем
  //координаты векторов
 Vector_a_Y = SevenAngle[i].Y - SevenAngle[1].Y;
 Vector_b_X = SevenAngle[i - 1].X - SevenAngle[1].X;
 Vector_b_Y = SevenAngle[i - 1].Y - SevenAngle[1].Y;
 Si[i - 2] = abs(Vector_a_X * Vector_b_Y - Vector_a_Y * Vector_b_X)/2; //Считаем площадь треугольника
 }
S = 0;
for (int i = 0; i <= 4; i++) S += Si[i]; //Суммируем эти площади
Form1 -> Edit1 -> Text = S; //И выводим их в поле Edit1
}
//--------------------------------------------------------------------
void __fastcall TForm1::PaintBox1MouseMove(TObject *Sender,
 TShiftState Shift, int X, int Y)
{
xx = X; //При перемещении курсора по PaintBox его координаты
yy = Y; //записываются в глобальные переменные
}
//--------------------------------------------------------------------
void __fastcall TForm1::PaintBox1Click(TObject *Sender)
{
if (n < 7) //Если отмечены еще не все 7 вершин
 {
 SevenAngle[n].X = xx; //При щелчке в PaintBox координатам вершины
 SevenAngle[n].Y = yy; //присваивается значение из
  //глобальных переменных
 if (n == 0) //Если отмечаемая вершина - первая...
  PaintBox1 -> Canvas -> MoveTo(xx, yy); //Перемещаем курсор
  //в нужную точку
 else PaintBox1 -> Canvas -> LineTo(SevenAngle[n].X, SevenAngle[n].Y); //В противном случае проводим отрезок
  //от предыдущей вершины до этой
 if (n == 6) //Если до этого уже было отмечено 6 вершин...
  PaintBox1 -> Canvas -> LineTo(SevenAngle[0].X, SevenAngle[0].Y); //...замыкаем семиугольник
 Edit2 -> Text = SevenAngle[n].X; //Выводим координаты последней
 Edit3 -> Text = SevenAngle[n].Y; //отмеченной вершины
 n++; //Увеличиваем счетчик вершин на единицу
 }
if (n == 7) CalculateSquare(); //Отметив все 7 вершин, считаем площадь
}
//--------------------------------------------------------------------
void __fastcall TForm1::Button1Click(TObject *Sender)
{
exit(0); //При нажатии на кнопку выходим из программы
}

Советы по улучшению и расширению программы
Было объявлено, что в этой программе по умолчанию считается, что пользователь строит выпуклый семиугольник - только в этом случае отрезки, проводимые из произвольной (например, первой) вершины во все остальные, будут делить фигуру на треугольники, вершины которых совпадают с вершинами фигуры. Снять это ограничение можно двумя способами - либо разбивать невыпуклый семиугольник на выпуклые фигуры, и уже их разбивать на треугольники, либо принудить пользователя строить обязательно выпуклый семиугольник. Первый способ гораздо более универсальный, однако гораздо более нетривиальный. Поэтому рассмотрим только второй.
Чтобы фигура была выпуклой, все ее вершины должны лежать по одну сторону от прямой, проведенных через сторону фигуры - и это должно выполняться для каждой стороны - и каждой прямой. Таким образом, необходимо контролировать, чтобы каждая новая (i-ая) вершина лежала по определенную сторону относительно трех прямых - проходящей через первую и вторую вершины, проходящей через (i-1)-ю и (i-2)-ю вершины, проходящей через первую и (i+1)-ю (проверка этого факта оставляется читателю в качестве несложного домашнего упражнения (c)).
Чтобы проверить, лежат ли точки C и D по одну сторону от прямой, проходящей через точки A и B, нужно знать уравнение прямой {x=d} или же {y=a*x+b}. Если Xa=Xb, то уравнение {x=Xa}. В противном случае {y=a*x+b, где a=(Ya-Yb)/(Xa-Xb) b=Ya-a*Xa}. В первом случае C и D лежат по одну сторону от прямой, если (Xc-d)*(Xd-d)>0, во втором случае - если (Yc-a*Xc-b)*(Yd-a*Xd-b)>0.

Обновлено 13.01.2010 13:05