unit AIObj
Создаем искусственный интеллект. Урок 8. Рисуем дуги вершин графа пространства
состояний.
Исходники у уроку можно скачать
здесь.
Прежде чем продолжить урок,
скажу, что открылся новый
цикл уроков по созданию искусственного
интеллекта, он будет идти параллельно с настоящим курсом и будет
называться "Создаем экспертную систему".
Перед тем как приступить к рисованиям дуг, сделаем
кругляшки вершин немного потолще:
procedure
TIIProblemSpace.DrawTop(AImage:TImage; index:integer);
var x,y,dx,dy:integer;
begin
x:=FLeft;
y:=FTop+index*FDistance;
dx:=10;
dy:=10;
AImage.Canvas.Pen.Width:=3;
AImage.Canvas.Ellipse(x,y,x+dx,y+dy);
end; |
Далее, хорошо было бы задать высоту и ширину кругляшка не
цифрами, а полями класса, так как эти данные у нас будут использоваться в
нескольких местах, и если мы захотим поменять размеры, то нам достаточно будет
просто напросто изменить значение этих полей:
procedure
TIIProblemSpace.DrawTop(AImage:TImage; index:integer);
var x,y,dx,dy:integer;
begin
x:=FLeft;
y:=FTop+index*FDistance;
dx:=FTopWidth;
dy:=FTopHeight;
AImage.Canvas.Pen.Width:=3;
AImage.Canvas.Ellipse(x,y,x+dx,y+dy);
end; |
соответственно, не забудьте объявить поля FTopWidth
и FTopHeight в секции protected и
инициализировать в конструкторе:
constructor
TIIProblemSpace.Create;
begin
inherited Create;
FItems:=TList.Create;
FCurrentItem:=nil;
FEnter:=nil;
FDistance:=30;
FLeft:=50;
FTop:=30;
FTopWidth:=10;
FTopHeight:=10;
end; |
Теперь напишем процедуру рисования дуги по двум точкам:
procedure DDraw(Canvas : TCanvas;
X, Y, X2, Y2 : integer; D : integer);
var
phi : double;
cX : Array[0..3] of
double;
cY : Array[0..3] of
double;
bc : array[0..3] of
TPoint;
i:integer; cosp, sinp,xx,yy:double;
begin
phi := arctan2((Y-Y2),(X-X2));
cX[3] := X2-X;
cY[3] := Y2-Y;
cosp := cos(-phi +3.14159);
sinp := sin(-phi+3.14159);
xx := cX[3];
yy := cY[3];
cX[3] := xx * cosp - yy*sinp;
cY[3] := xx*sinp + yy*cosp;
cX[0] := 0;
cX[1] := cX[3]/3;
cX[2] := cX[3]/3*2;
cY[0] := 0;
cY[1] := D;
cY[2] := D;
cosp := cos(phi+3.14159);
sinp := sin(phi +3.14159);
for i :=0 to 3 do
begin
xx :=
cX[i];
yy :=
cY[i];
cX[i] :=
xx * cosp - yy*sinp;
cY[i] :=
xx*sinp + yy*cosp;
end;
cX[0] := cX[0] + X;
cX[1] := cX[1] + X;
cX[2] := cX[2] + X;
cX[3] := cX[3] + X;
cY[0] := cY[0] + Y;
cY[1] := cY[1] + Y;
cY[2] := cY[2] + Y;
cY[3] := cY[3] + Y;
bc[0]:= Point(Trunc(cX[0]),
Trunc(cY[0]));
bc[1]:= Point(Trunc(cX[1]),
Trunc(cY[1]));
bc[2]:= Point(Trunc(cX[2]),
Trunc(cY[2]));
bc[3]:= Point(Trunc(cX[3]),
Trunc(cY[3]));
Canvas.PolyBezier(bc);
end; |
Напишем метод у класса TIIProblemSpace,
который рисует дугу между двумя вершинами графа:
procedure
TIIProblemSpace.DrawArc(AImage:TImage;index1,index2:integer);
var xr,yr,dx,dy,x,y:integer; ar:double; ari:integer;
y2:integer;
begin
x:=FLeft;
y:=FTop+index1*FDistance;
y2:=FTop+index2*FDistance;
dx:=FTopWidth;
dy:=FTopHeight;
xr:=x+dx*5;
yr:=FTop+index2*FDistance;
DDraw(AImage.Canvas, x, y+dy
div 2, x, y2+dy div 2,20);
end;
|
И, наконец, тестовый пример:
procedure
TfrmII.FormCreate(Sender: TObject);
var PS:TIIProblemSpace;
begin
PS:=TIIProblemSpace.Create;
PS.DrawTop(Image,0);
PS.DrawTop(Image,1);
PS.DrawTop(Image,2);
PS.DrawTop(Image,3);
PS.DrawTop(Image,4);
PS.DrawTop(Image,5);
PS.DrawArc(Image,0,1);
PS.DrawArc(Image,0,2);
PS.DrawArc(Image,2,3);
PS.DrawArc(Image,2,4);
PS.DrawArc(Image,1,5);
end; |
Вот результат его работы:

На следующем уроке мы улучим внешний вид дуг и нарисуем
стрелочки.
Исходники у уроку можно скачать
здесь. |