unit nets;
// (с) 2004 Rinas Alexandr

interface

uses Classes;

type

    TJoint=class;
    TVC=class;

    // класс соединения между ВЦ
    TJoint=class
        vc1,vc2: TVC;
        // соединяет ли данное соединение 2 ВЦ
        function Connecting(avc1,avc2: TVC): boolean;
        // возвращает длину соединения
        function Length: double;
        constructor Create(Avc1,Avc2: TVC);
    end;

    // класс ВЦ
    TVC=class
        index: integer;
        x,y: double;
        // рассчет растоятния до заданного ВЦ
        function PathTo(vc: TVC): double;
        // соединен ли ВЦ с другим ?
        function ConnectedTo(vc: TVC): boolean;
        constructor Create(ax,ay: Double);
    end;

    // класс - менеджер ВЦ и соединений
    // содержит набор ВЦ и соединений
    TONet=class
        joints: TList;
        vcs: TList;

        function GetJoint(i: integer): TJoint;
        function GetVC(i: integer): TVC;
        function GetJCount: integer;
        function GetVCount: integer;

        function JIndex(vc1,vc2: TVC): integer;
        procedure DeleteVC(i: integer);
        procedure DeleteJoint(i: integer);
        procedure ClearJoints;

        function AddVC(x,y: double): TVC;
        function AddJoint(avc1,avc2: TVC): TJoint;
        constructor Create;
        destructor Destroy; override;

        // массив соединений
        property Joint[i: integer]: TJoint read GetJoint;
        // массив ВЦ
        property Vc[i: integer]: TVC read GetVC;
        // число соединений
        property JCount: integer read GetJCount;
        // число ВЦ
        property VCount: integer read GetVCount;
    end;

var
// глобальный менеджер ВЦ и соединений
    Net: TOnet;

// создать глобальный менеджер сети
procedure CreateNet(No: integer);
// уничтожить глобальный менеджер сети
procedure DestroyNet;

implementation

procedure CreateNet(No: integer);
var i: integer;
begin
    if Net<>nil then DestroyNet;
    Net:=TONet.Create;
    for i:=1 to No do
        Net.AddVC(0,0);
end;

procedure DestroyNet;
begin
    if Net=nil then exit;
    Net.Free;
    Net:=nil;
end;

{ TJoint }

function TJoint.Connecting(avc1, avc2: TVC): boolean;
begin
    Result:=((vc1=avc1) and (vc2=avc2))
    or ((vc2=avc1) and (vc1=avc2)); 
end;

constructor TJoint.Create(Avc1, Avc2: TVC);
begin
    vc1:=Avc1; vc2:=Avc2;
end;

function TJoint.Length: double;
begin
    Result:=vc1.PathTo(vc2);
end;

{ TVC }

function TVC.ConnectedTo(vc: TVC): boolean;
begin
    Result:=Net.JIndex(self,vc)>=0;
end;

constructor TVC.Create(ax, ay: Double);
begin
    x:=ax;
    y:=ay;
end;

function TVC.PathTo(vc: TVC): double;
begin
    Result:=Sqrt(Sqr(vc.x-x)+Sqr(vc.y-y));
end;

{ TONet }

function TONet.AddJoint(avc1, avc2: TVC): TJoint;
var i: integer;
begin
    i:=JIndex(avc1,avc2);
    if i>=0 then
    begin
        Result:=Joint[i];
        exit;
    end;
    if avc1=avc2 then
    begin
        Result:=nil;
        exit;
    end;
    Result:=TJoint.Create(avc1,avc2);
    joints.Add(Result);
end;

function TONet.AddVC(x, y: double): TVC;
var i: integer;
begin
    Result:=TVC.Create(x,y);
    i:=vcs.Add(Result);
    Vc[i].index:=i+1;
end;

procedure TONet.ClearJoints;
var i: integer;
begin
    for i:=0 to JCount-1 do
        Joint[i].Free;
    joints.Clear;
end;

constructor TONet.Create;
begin
    joints:=TList.Create;
    vcs:=TList.Create;
end;

procedure TONet.DeleteJoint(i: integer);
begin
    Joint[i].Free;
    joints.Delete(i);
end;

procedure TONet.DeleteVC(i: integer);
begin
    Vc[i].Free;
    vcs.Delete(i);
end;

destructor TONet.Destroy;
var i: integer;
begin
    for i:=0 to JCount-1 do
        Joint[i].Free;
    for i:=0 to VCount-1 do
        VC[i].Free;
    joints.Free;
    vcs.Free;
end;

function TONet.GetJCount: integer;
begin
    Result:=joints.Count;
end;

function TONet.GetJoint(i: integer): TJoint;
begin
    Result:=TJoint(joints.Items[i]);
end;

function TONet.GetVC(i: integer): TVC;
begin
    Result:=TVC(vcs.Items[i]);
end;

function TONet.GetVCount: integer;
begin
    Result:=vcs.Count;
end;

function TONet.JIndex(vc1, vc2: TVC): integer;
var i: integer;
begin
    Result:=-1;
    for i:=0 to JCount-1 do
        if Joint[i].Connecting(vc1,vc2) then
        begin
            Result:=i;
            exit;
        end;    
end;

initialization
    Net:=nil;
end.

