Pers.narod.ru. Алгоритмы. Площади выпуклого и невыпуклого многоугольников

Дано натуральное число N и действительные числа {Xi,Yi}, i=1,2,...,N, описывающие координаты вершин многоугольника на плоскости. Найти площадь выпуклого N-угольника, вершины которого при последовательном обходе имеют координаты {X1,Y1}, ..., {XN,YN}.

Алгоритм сводится к разбиению многоугольника на треугольники с общей вершиной в точке {X1,Y1} и последующим вычислением их площадей по форумле Герона.

Проверка того, действительно ли можно из введённых координат получить выпуклый многоугольник, не делается.

const nmax=10;
var x,y:array [1..nmax] of real;
 n,i:integer;
 s,r1,r2,r3,p,p2:real;
 
begin
 {Ввод данных}
 repeat
  write ('Число вершин (от 3 до ',nmax,'): ');
  {$I-}read (n);{$I+}
  if IoResult<>0 then continue;
 until (n>2) and (n<=nmax);
 for i:=1 to n do
 repeat
  write ('Координаты вершины ',i,': ');
  {$I-}read (x[i],y[i]);{$I+}
 until IoResult=0;
 {Реализация}
 s:=0;
 r1:=sqrt(sqr(x[1]-x[2])+sqr(y[1]-y[2]));
 for i:=3 to n do begin
  p:=r1;
  r2:=sqrt(sqr(x[i]-x[i-1])+sqr(y[i]-y[i-1]));
  p:=p+r2;
  r3:=sqrt(sqr(x[i]-x[1])+sqr(y[i]-y[1]));
  p:=p+r3;
  p2:=p/2;
  s:=s+sqrt(p2*(p2-r1)*(p2-r2)*(p2-r3));
  r1:=r3;
 end;
 {Вывод результата}
 writeln ('Площадь ',n,'-угольника=',s:8:2);
 write ('Нажмите Enter для выхода');
 reset (input); readln;
end.

Можно всё упростить, вычисляя площади треугольников через координаты их вершин.

const nmax=10;
var x,y:array [1..nmax] of real;
 n,i:integer;
 s:real;
 
begin
 {Ввод данных}
 repeat
  write ('Число вершин (от 3 до ',nmax,'): ');
  {$I-}read (n);{$I+}
  if IoResult<>0 then continue;
 until (n>2) and (n<=nmax);
 for i:=1 to n do
 repeat
  write ('Координаты вершины ',i,': ');
  {$I-}read (x[i],y[i]);{$I+}
 until IoResult=0;
 {Реализация}
 s:=0;
 for i:=1 to n-2 do
  s:=s+1/2*abs((x[i+1]-x[1])*(y[i+2]-y[1])-(x[i+2]-x[1])*(y[i+1]-y[1]));
 {Вывод результата}
 writeln ('Площадь ',n,'-угольника=',s:8:2);
 write ('Нажмите Enter для выхода');
 reset (input); readln;
end.

Теперь рассмотрим случай невыпуклого многоугольника, для которого столь простые алгоритмы неприменимы.

Пример невыпуклого многоугольника

Примем, что многоугольник находится в области Y>0. Если это не так, его всегда можно переместить в положительную зону оси Y путём вычитания из всех координат Yi значения min{Yi}=Ymin. Общая площадь многоугольника будет равна сумме площадей прямоугольных трапеций, боковыми сторонами которых являются ось X и отрезок прямой, проведённый через 2 соседние вершины в порядке обхода. При этом в общей сумме площадь очередной трапеции учитывается со знаком "+", если значение Xi в последующей точке больше предыдущего в порядке обхода (наклонная штриховка на рисунке) или со знаком "-" в противном случае (вертикальная штриховка).

На нашем рисунке площади трапеций abco, ocdm, mdei и iefk будут учтены со знаком "+", так как X1<X2<X3<X4<X5, а площади треугольников nfk, nab, вычисляемые также по формуле прямоугольных трапеций, со знаком "-", так как X5>X6>X1.

const nmax=10;
var x,y:array [1..nmax] of real;
 n,i:integer;
 s,min:real;
 
begin
 {Ввод данных}
 repeat
  write ('Число вершин (от 3 до ',nmax,'): ');
  {$I-}read (n);{$I+}
  if IoResult<>0 then continue;
 until (n>2) and (n<=nmax);
 for i:=1 to n do
 repeat
  write ('Координаты вершины ',i,': ');
  {$I-}read (x[i],y[i]);{$I+}
 until IoResult=0;
 {Реализация}
 min:=y[1];
 for i:=2 to n do if y[i]<min then min:=y[i];
 if min<0 then for i:=1 to n do y[i]:=y[i]-min;
 s:=abs((x[1]-x[n])*(y[1]+y[n]))/2;
 for i:=2 to n do s:=s+abs((x[i]-x[i-1])*(y[i]+y[i-1]))/2;
 {Вывод результата}
 writeln ('Площадь ',n,'-угольника=',s:8:2);
 write ('Нажмите Enter для выхода');
 reset (input); readln;
end.

Рейтинг@Mail.ru

вверх гостевая; E-mail
Hosted by uCoz