Pers.narod.ru. Алгоритмы. Ромб или квадрат? |
Выпуклый четырёхугольник задан координатами своих вершин A, B, C, D в порядке их обхода. Проверить, является ли четырёхугольник ромбом или квадратом, выдать соответствующее сообщение.
Здесь мы расположим X- и Y-координаты вершин в массивах X и Y соответственно, а затем посчитаем стороны и диагонали четырёхугольника, записывая эту информацию в массив R.
Следует помнить о возможной погрешности при сравнении вещественных чисел, так что в профессиональной программе условие r[i]<>r[4] следовало бы заменить чем-то вроде abs(r[i]-r[4])<eps, где eps - допустимая погрешность.
function dist (x1,y1,x2,y2:real):real;
{Расстояние между точками (x1,y1), (x2,y2)}
begin
dist:=sqrt(sqr(x1-x2)+sqr(y1-y2));
end;
var x,y:array [1..4] of real;
r:array [1..6] of real;
i,k:integer;
begin
for i:=1 to 4 do begin
write ('Введите координаты ',i,' точки:');
read (x[i],y[i]);
end;
r[4]:=dist(x[1],y[1],x[4],y[4]);
k:=0;
for i:=1 to 3 do begin
r[i]:=dist(x[i],y[i],x[i+1],y[i+1]);
if r[i]<>r[4] then k:=1;
end;
if k=0 then begin
r[5]:=dist(x[1],y[1],x[3],y[3]);
r[6]:=dist(x[2],y[2],x[4],y[4]);
if r[5]=r[6] then writeln ('Квадрат')
else writeln ('Ромб');
end
else writeln ('Не ромб и не квадрат');
reset (input); readln;
end.
Что изменится, если точки перечислены не в порядке обхода? Как минимум, нужно отсортировать их так, чтоб стали в порядке :) Также следует предварительно избавиться от возможных повторяющихся значений точек.
Из набора координат точек на плоскости выбрать те, которые образуют квадраты... |
Разовьём задачу. Что делать, если нужно проверить, какие из набора точек образуют квадраты на плоскости? Приходит в голову такой алгоритм. Предположим, что точки никак не упорядочены, но различны между собой и количество их - не менее четырёх. Переберём все возможные разбиения точек по 4 элемента. Для того чтобы проверить, лежат ли 4 точки в вершинах прямоугольника, переберём все перестановки последних трёх точек и проверим, что каждые 2 последовательных отрезка, соединяющих последовательные точки, образуют прямой угол. Это можно сделать используя то, что скалярное произведение двух векторов равно нулю тогда и только тогда, когда угол между ними - прямой.
В нашем случае скалярное произведение можно найти также по формуле x1*x2+y1*y2, где
вектора (x1,y1), (x2,y2) получены переносом в точку (x0,y0) начала координат (см. рис. и функцию angle)

Для проверки того, лежат ли 4 точки в вершинах квадрата, а не просто прямоугольника, дополнительно нужно проверить, что 2 соседние стороны равны. Приведём листинг на Паскале:
{Предполагается что задано не менее 4 точек и все они различны}
uses crt;
type point = array [1..2] of real;
const n=11;
p:array [1..n] of point = (
(8,8), (0,8), (8,0), (1,2),
(0,0), (4,4), (4,0), (0,4),
(2,3), (3,2), (2,1)
);
function dist (i,j:integer):real;
begin
dist:=sqrt(sqr(p[i,1]-p[j,1])+sqr(p[i,2]-p[j,2]));
end;
function angle (i,j,k:integer):boolean;
var p0,p1,p2:point; s:real;
begin
p0:=p[i]; p1:=p[j]; p2:=p[k];
p1[1]:=p1[1]-p0[1]; p1[2]:=p1[2]-p0[2];
p2[1]:=p2[1]-p0[1]; p2[2]:=p2[2]-p0[2];
s:=p1[1]*p2[1]+p1[2]*p2[2];
if s=0 then angle:=true
else angle:=false;
end;
function square0 (i,j,k,l:integer):boolean;
begin
if (angle(i,l,j)=true) and
(angle(k,j,l)=true) and
(dist(i,l)=dist(i,j)) and
(dist(i,j)=dist(j,k)) then square0:=true
else square0:=false;
end;
function square (i,j,k,l:integer):boolean;
begin
if (square0(i,j,k,l)=true) or
(square0(i,j,l,k)=true) or
(square0(i,k,j,l)=true) or
(square0(i,k,l,j)=true) or
(square0(i,l,j,k)=true) or
(square0(i,l,k,j)=true) then square:=true
else square:=false;
end;
var i,j,k,l:integer;
begin
clrscr;
for i:=1 to n-3 do
for j:=i+1 to n-2 do
for k:=i+2 to n-1 do
for l:=i+3 to n do
if square(i,j,k,l)=true then writeln (
'(',p[i,1]:2:0,',',p[i,2]:2:0,'), ',
'(',p[j,1]:2:0,',',p[j,2]:2:0,'), ',
'(',p[k,1]:2:0,',',p[k,2]:2:0,'), ',
'(',p[l,1]:2:0,',',p[l,2]:2:0,')');
end.
"Лишние" вызовы функции dist из square0
нужны здесь затем, чтобы не выводить несколько раз квадраты,
отличающиеся лишь порядком образующих их точек - ведь последние 3 точки
переставляются (за счёт перестановок индексов j, k, l в коде).
Есть ещё такой вариант решения - если окружность вписана в квадрат то она касается всех его сторон посредине, а её радиус равен половине стороны. То есть, мы могли бы искать середины всех сторон и рассчитывать предполагаемое место для центра окружности. Если все 4 отрезка от центра до каждой из середин сторон равны, то наш четырехугольник - квадрат.
|
|