Вот в общих чертах. Выбор точек для окружности -- прямым перебором. Не стал пока додумывать каких-то оптимальных алгоритмов. Не уверен, что они есть. Если устраивает -- сделаю комментарии и занесу в ответы.
Программа[code h=200]
unit Unit1;
interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, Grids, StdCtrls, ExtCtrls, TeEngine, Series, TeeProcs, Chart;
type
TForm1 = class(TForm)
xy: TStringGrid;
LabelXc: TLabel;
LabelYc: TLabel;
LabelR: TLabel;
NewX: TLabeledEdit;
NewY: TLabeledEdit;
Button1: TButton;
Chart1: TChart;
Series1: TLineSeries;
Series2: TLineSeries;
Series3: TLineSeries;
procedure FormCreate(Sender: TObject);
procedure Button1Click(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
end;
var
Form1: TForm1;
implementation
{$R *.dfm}
var x:array[1..3] of real;
y:array[1..3] of real;
xc,yc,R:real;
procedure GetCenter;
var a:real;
begin
a:=x[3]*2*y[1] - x[3]*2*y[2] - x[2]*2*y[1] + x[2]*2*y[2]
- x[2]*2*y[2] + x[2]*2*y[3] + x[1]*2*y[2] - x[1]*2*y[3];
if abs(a)<1e-10
then begin
xc:=0;
yc:=0;
R:=0;
end
else begin
yc:=(
x[2]*sqr(x[3]) + x[2]*sqr(y[3]) - x[2]*sqr(x[2]) - x[2]*sqr(y[2])
- x[1]*sqr(x[3]) - x[1]*sqr(y[3]) + x[1]*sqr(x[2]) + x[1]*sqr(y[2])
- x[3]*sqr(x[2]) - x[3]*sqr(y[2]) + x[3]*sqr(x[1]) + x[3]*sqr(y[1])
+ x[2]*sqr(x[2]) + x[2]*sqr(y[2]) - x[2]*sqr(x[1]) - x[2]*sqr(y[1])
)/a;
if x[2]-x[1]<>0
then
xc:=(sqr(x[2]) + sqr(y[2]) - sqr(x[1]) - sqr(y[1])
+ 2*yc*y[1] - 2*yc*y[2]
)/2/(x[2]-x[1])
else
xc:=(sqr(x[3]) + sqr(y[3]) - sqr(x[2]) - sqr(y[2])
+ 2*yc*y[2] - 2*yc*y[3]
)/2/(x[3]-x[2]);
R:=sqrt(sqr(y[1]-yc)+sqr(x[1]-xc));
end;
end;
type point= record
x,y:real;
end;
var p:array of point;
procedure TForm1.FormCreate(Sender: TObject);
begin
xy.ColCount:=2;
xy.RowCount:=2;
xy.FixedCols:=0;
xy.FixedRows:=1;
xy.Cells[0,0]:='X';
xy.Cells[1,0]:='Y';
randomize;
end;
procedure TForm1.Button1Click(Sender: TObject);
var i,j,k,l,n,ibest,jbest,kbest,nbest:integer;
xxx,yyy:real;
begin
xy.Cells[0,xy.RowCount-1]:=NewX.Text;
xy.Cells[1,xy.RowCount-1]:=NewY.Text;
xy.RowCount:=xy.RowCount+1;
SetLength(p,length(p)+1);
p[High(p)].x:=StrToFloat(NewX.Text);
p[High(p)].y:=StrToFloat(NewY.Text);
if length(p)>=3
then begin
nbest:=-1;
for i:=0 to High(p) do
for j:=i+1 to High(p) do
for k:=j+1 to High(p) do
begin
x[1]:=p[i].x;
x[2]:=p[j].x;
x[3]:=p[k].x;
y[1]:=p[i].y;
y[2]:=p[j].y;
y[3]:=p[k].y;
GetCenter;
n:=0;
for l:=0 to High(p) do
if (l<>i) and (l<>j) and (l<>k)
and (sqr(p[l].x-xc)+sqr(p[l].y-yc)<sqr(R))
then inc(n);
if n>nbest
then begin
nbest:=n;
ibest:=i;
jbest:=j;
kbest:=k;
end;
end;
x[1]:=p[ibest].x;
x[2]:=p[jbest].x;
x[3]:=p[kbest].x;
y[1]:=p[ibest].y;
y[2]:=p[jbest].y;
y[3]:=p[kbest].y;
GetCenter;
LabelXc.Caption:='Xc = ' + FloatToStrF(xc,ffFixed,0,3);
LabelYc.Caption:='Yc = ' + FloatToStrF(yc,ffFixed,0,3);
LabelR.Caption:='R = ' + FloatToStrF(R,ffFixed,0,3);
Chart1.Series[2].Clear;
Chart1.Series[2].AddXY(p[ibest].x,p[ibest].y);
Chart1.Series[2].AddXY(p[jbest].x,p[jbest].y);
Chart1.Series[2].AddXY(p[kbest].x,p[kbest].y);
Chart1.Series[0].Clear;
for i:=0 to 2000 do
begin
xxx:=xc+R*cos(i/2000*2*pi);
yyy:=yc+R*sin(i/2000*2*pi);
Chart1.Series[0].AddXY(xxx,yyy);
end;
end;
Chart1.Series[1].Clear;
for i:=0 to High(p) do
if (i<>ibest) and (i<>jbest) and (i<>kbest)
then Chart1.Series[1].AddXY(p[i].x,p[i].y);
NewX.Text:=FloatToStrF(random,ffFixed,0,5);
NewY.Text:=FloatToStrF(random,ffFixed,0,5);
end;
end.
[/code]