Задача: Три произвольно заданных точки лежат на окружности. Составить на Паскале программу опредения координат центра этой окружности.
На чем я застрял: раз три точки - ежику ясно: вершины треугольника с описанной вокруг него окружностью. Стороны, площадь, радиус - пожалуйста, не проблема вычислить, т.к. координаты точек есть. Но что дальше? ](*,)
В методичке даже близко подобного ничего нету, включив логику и остатки знаний по геометрии, вторую неделю бьюсь с идеей нахождения через серединные перпендикуляры к сторонам.
Т.е. если одну сторону получившегося треугольника представить, как часть графика функции Y=kX+b, то перпендикуляр, если не ошибаюсь, будет Yp=-X/k+b (так?). Если добавить поправочный коэф-т, чтоб при Хсреднем давал Yсреднее - формула серединного перпендикуляра готова. Но как найти точку пересечения этих самых перпендикуляров (aka центр окружности) - вообще идей нету, школьная математика успела вылететь напрочь за эти годы. Да и было ли оно такое в школе?
А может есть более простой алгоритм? Задачка-то считается обычной контрольной для заочников, всего лишь второе задание из 4, причем остальные три я расщелкал как орешки...
PS Еще раз спасибо всем принимавшим участие.
Хоть минус три мильярда! Если в процедуре CHECK получается три одинаковых радиуса, то значит все верно, таки и должно быть.
На картинке-то ? Ну не знаю, специально жирным выделил x0 :)
Хотя, теперь уже неважно, все равно мои формулы забраковали :lol:
Так что я сам где-то намудрил. Правда где - так и не понял. :oops: Наверное, зимний авитаминоз на мозги давит :lol:
при выводе везде надо 'ymax-' подставлять, и ёще вроде где-то индексы перепутал. вот попробуй, тока с делением на ноль сам уж доведи... :)
дебаг версия:
[code:1]
unit Unit2;
interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, StdCtrls;
type
TForm1 = class(TForm)
Button1: TButton;
Label1: TLabel;
Label2: TLabel;
Label3: TLabel;
procedure Button1Click(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
end;
var
Form1: TForm1;
a:array [1..6] of array [1..2] of integer; // координаты точек закинуты в массив a[1,1]=x1, a[1,2]=y1, a[2,1]=x2 и т.д.
MyMetafile: TMetafile;
b1,b2,k1,k2,xa,ya,xb,yb:real;
i:byte;
const
YMax: Integer = 400;
implementation
{$R *.dfm}
procedure TForm1.Button1Click(Sender: TObject);
begin
{т.к. ось OY идет сверху вниз, значение Y отнимаем от Ymax,
чтобы график рисовался как положено, а не вверх ногами}
a[1,1]:=119;
a[1,2]:=ymax-85;
a[2,1]:=257;
a[2,2]:=ymax-201;
a[3,1]:=166;
a[3,2]:=ymax-271;
//****************************************
k1:=(a[3,1]-a[2,1]) / (a[2,2]-a[3,2]);
k2:=(a[1,1]-a[3,1]) / (a[3,2]-a[1,2]);
xa:=( (a[2,1] + a[3,1]) / 2 );
ya:=( (a[2,2] + a[3,2]) / 2 );
xb:=( (a[3,1] + a[1,1]) / 2 );
yb:=( (a[3,2] + a[1,2]) / 2 );
b1:=ya - k1*xa;
b2:=yb - k2*xb;
{и, наконец, вычисляем координаты центра окружности}
a[5,1]:=round( (b2 - b1) / (k1 - k2) ); {это x0}
a[5,2]:=round( k1 * a[5,1] + b1 ); {а это y0}
//***********************************
if round( k1*a[5,1]+b1) = round( k2*a[5,1]+b2)
then Label2.Caption := 'True'
else Label2.Caption := 'False';
//**********************
k1:=(a[1,1]-a[3,1]) / (a[3,2]-a[1,2]);
k2:=(a[2,1]-a[1,1]) / (a[1,2]-a[2,2]);
xa:=( (a[3,1] + a[1,1]) / 2 );
ya:=( (a[3,2] + a[1,2]) / 2 );
xb:=( (a[1,1] + a[2,1]) / 2 );
yb:=( (a[1,2] + a[2,2]) / 2 );
b1:=ya-k1*xa;
b2:=yb-k2*xb;
{и, наконец, вычисляем координаты центра окружности}
a[6,1]:=round( (b2 - b1) / (k1 - k2) ); {это x0}
a[6,2]:=round( k1 * a[6,1] + b1 ); {а это y0}
//***********************************
if round( k1*a[6,1]+b1) = round( k2*a[6,1]+b2)
then Label3.Caption := 'True'
else Label3.Caption := 'False';
if a[1,2] <> a[2,2]
then k1:=(a[2,1]-a[1,1]) / (a[1,2]-a[2,2])
else k1:= 0;
if a[3,2] <> a[2,2]
then k2:=(a[3,1]-a[2,1]) / (a[2,2]-a[3,2])
else k2:= 0;
xa:=( (a[1,1] + a[2,1]) / 2 );
ya:=( (a[1,2] + a[2,2]) / 2 );
xb:=( (a[2,1] + a[3,1]) / 2 );
yb:=( (a[2,2] + a[3,2]) / 2 );
b1:=ya-k1*xa;
b2:=yb-k2*xb;
{и, наконец, вычисляем координаты центра окружности}
a[4,1]:= round( (b2 - b1) / (k1 - k2) ); {это x0}
a[4,2]:= round( k1 * a[4,1] + b1 ); {а это y0}
if round( k1*a[4,1]+b1) = round( k2*a[4,1]+b2)
then Label1.Caption := 'True'
else Label1.Caption := 'False';
//**********************
{и выводим результаты на экран}
MyMetafile := TMetafile.Create;
for i:=6 downto 1 do
begin
with TMetafileCanvas.Create(MyMetafile, 0) do
try
if i<4 then Brush.Color := clRed else Brush.Color := clYellow;
if i=5 then Brush.Color := clBlue;
if i=6 then Brush.Color := clGreen;
Ellipse(a[i,1]-i*4,ymax-a[i,2]-i*4,a[i,1]+i*4,ymax-a[i,2]+i*4);
if i<3
then
begin
MoveTo(a[i,1],ymax-a[i,2]);
LineTo(a[i+1,1], ymax-a[i+1,2]);
end;
if i=3
then
begin
MoveTo(a[i,1],ymax-a[i,2]);
LineTo(a[1,1], ymax-a[1,2]);
end;
if i=1
then
begin
MoveTo( round(xa),ymax-round(ya) );
LineTo( round(xa-50),ymax-round(k1*(xa-50)+b1) );
MoveTo( round(xb),ymax-round(yb) );
LineTo( round(xb-50),ymax-round(k2*(xb-50)+b2) );
end;
finally
Free;
end;
Form1.Canvas.Draw(0,0,MyMetafile);
end;
end;
end.
[/code:1]
[code:1]unit Unit1;
interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, StdCtrls, Menus;
type
TForm1 = class(TForm)
procedure FormCreate(Sender: TObject);
procedure Button1Click(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
end;
var
Form1: TForm1;
c:integer;
a:array [1..4] of array [1..2] of integer;
implementation
uses Unit2;
{$R *.dfm}
Function X0:extended;
Var
chisl,znam:longint;
Begin
chisl:=(a[3,2]-a[2,2])*(a[1,1]*a[1,1]+a[1,2]*a[1,2])+(a[1,2]-a[3,2])*(a[2,1]*a[2,1]+a[2,2]*a[2,2])+
(a[2,2]-a[1,2])*(a[3,1]*a[3,1]+a[3,2]*a[3,2]);
znam :=2*((a[1,2]-a[2,2])*(a[1,1]-a[3,1])-(a[1,2]-a[3,2])*(a[1,1]-a[2,1]));
X0:=chisl/znam;
End;
Function Y0(x0:extended):extended;
Var
chisl,znam:extended;
Begin
chisl:=a[1,1]*a[1,1]-a[2,1]*a[2,1]+a[1,2]*a[1,2]-a[2,2]*a[2,2]-2*(a[1,1]-a[2,1])*x0;
znam :=2*(a[1,2]-a[2,2]);
Y0:=chisl/znam;
End;
procedure PutCircle(X,Y,R:integer; Solid:Boolean);
const
YMax: Integer = 400;
var
MyMetafile: TMetafile;
begin
MyMetafile := TMetafile.Create;
with TMetafileCanvas.Create(MyMetafile, 0) do
try
if Solid then with Brush do
begin
Color := clRed;
Style := bsSolid;
end
else
Brush.Style := bsClear;
Ellipse(X-R,Ymax-(Y-R),X+R,Ymax-(Y+R));
finally
Free;
end;
Form1.Canvas.Draw(0,0,MyMetafile);
end;
procedure TForm1.FormCreate(Sender: TObject);
begin
a[1,1]:=257;
a[1,2]:=201;
a[2,1]:=166;
a[2,2]:=279;
a[3,1]:=119;
a[3,2]:=85;
end;
procedure TForm1.Form1Click(Sender: TObject);
var
i,r:byte;
begin
a[4,1]:=round(X0);
a[4,2]:=round(Y0(a[4,1]));
for i:=1 to 3 do
begin
PutCircle(a[i,1],a[i,2],5,True);
end;
r:=round(sqrt(sqr((a[1,1]-a[4,1]))+sqr((a[1,2]-a[4,2]))));
PutCircle(a[4,1],a[4,2],r,False);
end;
end.[/code:1]
Добавлено спустя 21 минуту 29 секунд:
Сдаётся мне, что проще через окружности считать, тем более радиус известен из площади. :?
Добавлено спустя 7 часов 21 минуту 36 секунд:
Вот!
[code:1]procedure FindCenter(X1,Y1,X2,Y2,X3,Y3:integer);
var
a1,a2,b1,b2,c1,c2,znam:extended;
X0,Y0:integer;
begin
a1:=x2-x1;
a2:=x3-x1;
b1:=y2-y1;
b2:=y3-y1;
c1:=(a1*(x2+x1)+b1*(y2+y1)) / 2;
c2:=(a2*(x3+x1)+b2*(y3+y1)) / 2;
znam:=a1*b2-a2*b1;
X0:= round((c1*b2 - c2*b1)/znam);
Y0:= round((a1*c2 - a2*c1)/znam);
end;[/code:1]
А если серьезно, эта проблема решается легче легкого: просто проверю, если znam=0 - перегенерю координаты.