unit uttory;

interface

uses glmesh,vectortypes,GLScene, GLObjects,  SysUtils,
  vectorgeometry,GLtexture,glstate,glmisc,glgeomobjects;

type XYZ = record
        x,y,z:real;
        end;

type XY = record
        x,y:real;
        end;

type TP=record
        t:integer;
        p:real;
        end;

type ttory = class
        private


        public
        np,nt:integer;
        tra:array[1..512] of record a,b:integer; len:real; podloze:byte; vmax: real; end;
        pnt:array[1..512] of record x,y,kx,ky:real;
                a,b :array[1..3] of integer;
                lia,lib:byte;
                sa,sb:byte;
        end;
        starty:array[1..8] of TP;
        startil:byte;
        baza:tglbasesceneobject;
        siata,siatap:tglmesh;
        sta,stb:array[1..3] of tglarrowline;
        Constructor Create;
        procedure wczytaj(nazwa:string);
        procedure rysuj;
        procedure rysujpodloze;
        function bez(p1,p2,p3,p4:XY;mu:real):XY;
        function tbez(ntra:integer;mu:real):XY;
        procedure pokstrz(nr:integer);
        procedure crstr;
        function len(ntra:integer):real;
        function getpos(act:TP):XY;
        function dodajdl(act:TP;lg:real):TP;
        procedure slupki(t:integer);
        function dodajto(act:TP;ile:real):TP;
        function ujmijdl(act:TP;lg:real):TP;
        function switchf(nu:integer):integer;
        function switchb(nu:integer):integer;


end;

implementation

procedure zapisz(s:string);
var f:textfile;
begin
assignfile(f,'aaa.txt');
append(f);
write(f,S);
closefile(f);
end;

constructor ttory.create;

begin
end;

function ttory.switchf(nu:integer):integer;
begin

if (pnt[nu].sa<pnt[nu].lia) then
        inc(pnt[nu].sa)
        else
        pnt[nu].sa:=1;
        switchf:=pnt[nu].a[pnt[nu].sa];
end;

function ttory.switchb(nu:integer):integer;
begin
if (pnt[nu].sb<pnt[nu].lib) then
        inc(pnt[nu].sb)
        else
        pnt[nu].sb:=1;
        switchb:=pnt[nu].b[pnt[nu].sb];      
end;


function dist(a,b:XY):real;
begin
dist:=sqrt((a.x-b.x)*(a.x-b.x)+(a.y-b.y)*(a.y-b.y));
end;

function ttory.getpos(act:TP):XY;
begin
repeat

if act.p>=1 then  begin
        act.t:=pnt[tra[act.t].b].a[pnt[tra[act.t].a].sa];
        act.p:=act.p-1;
        end;

if act.p<0 then begin
        act.t:=pnt[tra[act.t].a].b[pnt[tra[act.t].b].sb];
        act.p:=act.p+1;
        end;
until ((act.p<1) and (act.p>=0));
    //    zapisz(format('%d %f',[act.t,act.p]));
  getpos:=tbez(act.t,act.p);
end;

function ttory.dodajto(act:TP;ile:real):TP;
var p:real;
t:integer;
tmp: TP;
begin
p:=act.p;
t:=act.t;
p:=p+ile;
//repeat

if p>=1 then begin
        t:=pnt[tra[t].b].a[pnt[tra[t].b].sa];
        p:=p-1;
        // zapisz('nastepna');
        end;

if p<0 then begin
        t:=pnt[tra[t].a].b[pnt[tra[t].a].sb];
        p:=p+1;
        // zapisz(format ('caofnieto %d ',[t]));
        end;
//until
tmp.t:=t;
tmp.p:=p;
dodajto:=tmp;
end;

function ttory.dodajdl(act:TP;lg:real):TP;
var nit:integer;
odeta,deta,skok:real;
okoncp,koncp:TP;
start,koniec:XY;
begin
//zapisz(format('========1: %d',[act.t]));
  dodajdl.t:=act.t;
  if (abs(lg)<0.001) then dodajdl.p:=act.p else
  begin
        nit:=0;
        koncp:=act;
//zapisz(format('1: %d',[act.t]));
        start:=tbez(act.t,act.p);
//zapisz('2:');
        koniec:=tbez(koncp.t,koncp.p);
//zapisz('3:');
//writeln(f,format('1: koncp: %f, ppos: %f, start: %f,%f ',[koncp,ppos,start.x,start.y]));{
        skok:=(1-act.p)/2.0;
//zapisz('4:');
        odeta:=dist(start,koniec);
//zapisz('5:');
        repeat
//        koncp:=koncp+skok;       //[0-1]
//zapisz('5a:');
                koncp:=dodajto(koncp,skok);
//zapisz(format('5b %d %f :',[koncp.t,koncp.p]));
                koniec:=getpos(koncp); //[xy] ([i][0-1])
//zapisz('5c:');
                deta:=dist(start,koniec); //[m]
//zapisz('5d:');
                if ((deta<lg) and (lg<odeta)) then skok:=-skok/2;
                if ((deta>lg) and (lg>odeta)) then skok:=-skok/2;
                odeta:=deta;
                inc(nit);

        until ((nit>1000) or ((deta-lg)*(deta-lg)<0.0001)) ;
//zapisz('6:'+#13+#10+' ');
//writeln(f,format('3: dist %f, lg: %f',[dist(start,koniec),lg]));
        dodajdl:=koncp;
   end;
end;

function ttory.ujmijdl(act:TP;lg:real):TP;
var nit:integer;
odeta,deta,skok:real;
koncp:TP;
start,koniec:XY;

begin
  ujmijdl.t:=act.t;
  if (abs(lg)<0.001) then ujmijdl.p:=act.p else
  begin
        nit:=0;

        koncp:=act;

        start:=tbez(act.t,act.p);

        koniec:=tbez(koncp.t,koncp.p);

        skok:=-(act.p)/2.0;

        odeta:=dist(start,koniec);

        repeat
                koncp:=dodajto(koncp,skok);

                koniec:=getpos(koncp); //[xy] ([i][0-1])

                deta:=dist(start,koniec); //[m]

                if ((deta<lg) and (lg<odeta)) then skok:=-skok/2;
                if ((deta>lg) and (lg>odeta)) then skok:=-skok/2;
                odeta:=deta;
                inc(nit);

        until ((nit>1000) or ((deta-lg)*(deta-lg)<0.0001)) ;

        ujmijdl:=koncp;
   end;
end;


procedure ttory.slupki(t:integer);
var i:integer;
a:real;
pd:XY;
slup:tglcylinder;
f:textfile;
tm:TP;
begin
  //      assignfile(f,'aaa.txt');
  //      rewrite(f);
  //      closefile(f);
  //      assignfile(f,'slupki.txt');
  //      rewrite(f);
        a:=0.0;
        tm.p:=a;
        tm.t:=t;
        for i:=1 to round(tra[t].len/2) do begin

        pd:=getpos(tm);
        slup:=tglcylinder.create(baza.addnewchild(tglcylinder));
        slup.parent:=baza;
        slup.position.x:=pd.x;
        slup.position.Y:=pd.y;
        slup.Up.x:=0; slup.Up.y:=0; slup.Up.Z:=1; slup.Up.x:=0; slup.Up.y:=0; slup.Up.Z:=1;

        slup.BottomRadius:=0.1;
        slup.topRadius:=0.1;

        slup.Height:=10;
        write(f,i,' | ',a, ' | ');

        tm:=dodajdl(tm,3);

     //   writeln(f,a);
        end;
    //    closefile(f);

end;

function ttory.len(ntra:integer):real;
var i:integer;
olp,nop:XY;
le:real;
begin
        len:=0;
        olp:=tbez(ntra,0);
        for i:=1 to 100 do begin
        nop:=tbez(ntra,i/100);
        le:=le+sqrt((nop.x-olp.x)*(nop.x-olp.x)+(nop.y-olp.y)*(nop.y-olp.y));
        olp:=nop;
        end;
        len:=le;
end;

procedure ttory.wczytaj(nazwa:string);

var i,j:integer;
f:textfile;

begin
assignfile(f,nazwa);
reset(f);
readln(f,nt);
for i:=1 to nt do begin
        readln(f,tra[i].a,tra[i].b,tra[i].vmax);
        tra[i].vmax:=tra[i].vmax/3.6;
        tra[i].len:=1;
        tra[i].podloze:=1;
        end;
readln(f,np);
for i:=1 to np do begin
        readln(f,pnt[i].y,pnt[i].x,pnt[i].ky,pnt[i].kx);
        end;
readln(f,startil);
for i:=1 to startil do begin
        readln(f,starty[i].t,starty[i].p);
        end;


closefile(f);

for i:=1 to np do begin
        pnt[i].lia:=0;
        pnt[i].lib:=0;
        pnt[i].sa:=1;
        pnt[i].sb:=1;
        for j:=1 to nt do begin
                if tra[j].a=i then begin inc(pnt[i].lia); pnt[i].a[pnt[i].lia]:=j; end;
                if tra[j].b=i then begin inc(pnt[i].lib); pnt[i].b[pnt[i].lib]:=j; end;
        end;
        end;

for i:=1 to nt do begin
        tra[i].len:=len(i);
        end;

end;

procedure ttory.crstr;
var i:integer;
begin
for i:=1 to 3 do begin
  sta[i]:=tglarrowline(baza.addnewchild(tglarrowline));
  sta[i].parent:=baza;
  sta[i].Material.FrontProperties.Diffuse.Color:=clryellow;
  sta[i].Material.MaterialOptions:=[ monolighting];
  sta[i].Height:=10;
  sta[i].BottomArrowHeadRadius:=1;
  sta[i].BottomRadius:=2;

  //sta[i].up.X:=0;  sta[i].up.y:=0;  sta[i].up.z:=1;  sta[i].up.X:=0;  sta[i].up.y:=0;  sta[i].up.z:=1;

  stb[i]:=tglarrowline(baza.addnewchild(tglarrowline));
  stb[i].parent:=baza;
  stb[i].Material.FrontProperties.Diffuse.Color:=clryellow;
  stb[i].Material.MaterialOptions:=[ monolighting];
  stb[i].Height:=10;
  stb[i].BottomArrowHeadRadius:=1;
  stb[i].BottomRadius:=2;
end;
end;

function ttory.bez(p1,p2,p3,p4:XY;mu:real):XY;
var re:XY;
mum1,mum13,mu3:real;
begin
   mum1 := 1 - mu;
   mum13 := mum1 * mum1 * mum1;
   mu3 := mu * mu * mu;
   re.x:=mum13*p1.x + 3*mu*mum1*mum1*p2.x + 3*mu*mu*mum1*p3.x + mu3*p4.x;
   re.y:= mum13*p1.y + 3*mu*mum1*mum1*p2.y + 3*mu*mu*mum1*p3.y + mu3*p4.y;
   bez:=re;

end;

function ttory.tbez(ntra:integer;mu:real):XY;
var te:XY;
pk1,pk2,pk3,pk4:XY;
begin
   pk1.x:=pnt[tra[ntra].a].x;
   pk1.y:=pnt[tra[ntra].a].y;

   pk2.x:=pnt[tra[ntra].a].x+pnt[tra[ntra].a].kx;
   pk2.y:=pnt[tra[ntra].a].y+pnt[tra[ntra].a].ky;;

   pk3.x:=pnt[tra[ntra].b].x-pnt[tra[ntra].b].kx;
   pk3.y:=pnt[tra[ntra].b].y-pnt[tra[ntra].b].ky;;


   pk4.x:=pnt[tra[ntra].b].x;
   pk4.y:=pnt[tra[ntra].b].y;
   te:=bez(pk1,pk2,pk3,pk4,mu);
   tbez:=te;
end;

procedure ttory.rysujpodloze;

  procedure  dodajv(pos:XYZ;s,t:single;col:tcolorvector);
        var t1:tvector3f;
             a:ttexpoint;
        begin
                t1[0]:=pos.x;t1[1]:=pos.y;t1[2]:=pos.z;
                a.S:=s;a.T:=t;
                siatap.Vertices.AddVertex(t1,NullVector,col,a);
        end;

        procedure  dodajf(a,b,c:XYZ);
        var co:tcolorvector;
        begin
                co[0]:=3; co[1]:=2; co[2]:=1; co[3]:=1;
                siatap.Mode:=mmTriangles;
                dodajv(a,0,0,co);
                dodajv(b,0,0,co);
                dodajv(c,0,0,co);
        end;

        procedure dodajprof(p1,d1,p2,d2:XY);
        var t1,t2,t3:XYZ;
        const z1 = 4.75;
         z2=1.7;
        begin
         {**top}
        t1.x:=p2.x+d2.x*z2; t1.y:=p2.y-d2.y*z2; t1.z:=0;
        t2.x:=p1.x+d1.x*z2; t2.y:=p1.y-d1.y*z2; t2.z:=0;
        t3.x:=p1.x-d1.x*z2; t3.y:=p1.y+d1.y*z2; t3.z:=0;
        dodajf(t1,t2,t3);

        t1.x:=p2.x+d2.x*z2; t1.y:=p2.y-d2.y*z2; t1.z:=0;
        t2.x:=p1.x-d1.x*z2; t2.y:=p1.y+d1.y*z2; t2.z:=0;
        t3.x:=p2.x-d2.x*z2; t3.y:=p2.y+d2.y*z2; t3.z:=0;
        dodajf(t1,t2,t3);

        {**lnasyp}
        t1.x:=p2.x+d2.x*z2; t1.y:=p2.y-d2.y*z2; t1.z:=0;
        t2.x:=p1.x+d1.x*z2; t2.y:=p1.y-d1.y*z2; t2.z:=0;
        t3.x:=p1.x+d1.x*z1; t3.y:=p1.y-d1.y*z1; t3.z:=-0.3;
         dodajf(t2,t1,t3);

        t1.x:=p2.x+d2.x*z2; t1.y:=p2.y-d2.y*z2; t1.z:=0;
        t2.x:=p1.x+d1.x*z1; t2.y:=p1.y-d1.y*z1; t2.z:=-0.3;
        t3.x:=p2.x+d2.x*z1; t3.y:=p2.y-d2.y*z1; t3.z:=-0.3;
        dodajf(t2,t1,t3);

        {**pnasyp}

         t1.x:=p2.x-d2.x*z2; t1.y:=p2.y+d2.y*z2; t1.z:=0;
        t2.x:=p1.x-d1.x*z2; t2.y:=p1.y+d1.y*z2; t2.z:=0;
        t3.x:=p1.x-d1.x*z1; t3.y:=p1.y+d1.y*z1; t3.z:=-0.3;
         dodajf(t1,t2,t3);

       t1.x:=p2.x-d2.x*z2; t1.y:=p2.y+d2.y*z2; t1.z:=0;
        t2.x:=p1.x-d1.x*z1; t2.y:=p1.y+d1.y*z1; t2.z:=-0.3;
        t3.x:=p2.x-d2.x*z1; t3.y:=p2.y+d2.y*z1; t3.z:=-0.3;
        dodajf(t1,t2,t3);


          
//        form1.memo1.lines.add(floattostr(t1.x)+' '+floattostr(t1.y));

        end;





        procedure rystr(ntra:integer);
        var i:integer;
        a: array[0..10] of record p,d:XY;  end;
        dl,dx,dy:real;

        begin
                for i:=0 to 10 do begin
                        a[i].p:=tbez(ntra,i/10);
                end;
                for i:=0 to 9 do begin
                        dx:=a[i].p.x-a[i+1].p.x;
                        dy:=a[i].p.y-a[i+1].p.y;
                        dl:=sqrt(dx*dx+dy*dy);
                        a[i].d.x:=dy/dl;
                        a[i].d.y:=dx/dl;
                end;

                for i:=0 to 9 do begin
                        dodajprof(a[i].p,a[i].d,a[i+1].p,a[i+1].d);
                end;

        end;

var i:integer;
begin
siatap:=tglmesh(baza.addnewchild(tglmesh));
siatap.Vertices.clear;
for i:=1 to nt do begin
        rystr(i);
end;
        siatap.CalcNormals(fwClockWise);
end;



procedure ttory.rysuj;

        procedure  dodajv(pos:XYZ;s,t:single;col:tcolorvector);
        var t1:tvector3f;
             a:ttexpoint;
        begin
                t1[0]:=pos.x;t1[1]:=pos.y;t1[2]:=pos.z;
                a.S:=s;a.T:=t;
                siata.Vertices.AddVertex(t1,NullVector,col,a);
        end;

        procedure  dodajf(a,b,c:XYZ);
        var co:tcolorvector;
        begin
                co[0]:=0.5; co[1]:=0.5; co[2]:=0.5; co[3]:=1;
                siata.Mode:=mmTriangles;
                dodajv(a,0,0,co);
                dodajv(b,0,0,co);
                dodajv(c,0,0,co);
        end;

        procedure dodajprof(p1,d1,p2,d2:XY);
        var t1,t2,t3:XYZ;
        const z1 = 0.6;
         z2=0.5;
        begin
        t1.x:=p2.x-d2.x*z2; t1.y:=p2.y+d2.y*z2; t1.z:=0.1;
        t2.x:=p1.x-d1.x*z2; t2.y:=p1.y+d1.y*z2; t2.z:=0.1;
        t3.x:=p1.x-d1.x*z1; t3.y:=p1.y+d1.y*z1; t3.z:=0.1;
        dodajf(t1,t2,t3);

        t1.x:=p2.x-d2.x*z2; t1.y:=p2.y+d2.y*z2; t1.z:=0.1;
        t2.x:=p1.x-d1.x*z1; t2.y:=p1.y+d1.y*z1; t2.z:=0.1;
        t3.x:=p2.x-d2.x*z1; t3.y:=p2.y+d2.y*z1; t3.z:=0.1;
        dodajf(t1,t2,t3);

        t1.x:=p2.x+d2.x*z2; t1.y:=p2.y-d2.y*z2; t1.z:=0.1;
        t2.x:=p1.x+d1.x*z2; t2.y:=p1.y-d1.y*z2; t2.z:=0.1;
        t3.x:=p1.x+d1.x*z1; t3.y:=p1.y-d1.y*z1; t3.z:=0.1;
        dodajf(t1,t3,t2);

        t1.x:=p2.x+d2.x*z2; t1.y:=p2.y-d2.y*z2; t1.z:=0.1;
        t2.x:=p1.x+d1.x*z1; t2.y:=p1.y-d1.y*z1; t2.z:=0.1;
        t3.x:=p2.x+d2.x*z1; t3.y:=p2.y-d2.y*z1; t3.z:=0.1;
        dodajf(t1,t3,t2);


//        form1.memo1.lines.add(floattostr(t1.x)+' '+floattostr(t1.y));

        end;





        procedure rystr(ntra:integer);
        var i:integer;
        a: array[0..100] of record p,d:XY;  end;
        dl,dx,dy:real;

        begin
                for i:=0 to 100 do begin
                        a[i].p:=tbez(ntra,i/100);
                end;
                for i:=0 to 99 do begin
                        dx:=a[i].p.x-a[i+1].p.x;
                        dy:=a[i].p.y-a[i+1].p.y;
                        dl:=sqrt(dx*dx+dy*dy);
                        a[i].d.x:=dy/dl;
                        a[i].d.y:=dx/dl;
                end;

                for i:=0 to 99 do begin
                        dodajprof(a[i].p,a[i].d,a[i+1].p,a[i+1].d);
                end;

        end;

var i:integer;
begin
siata:=tglmesh(baza.addnewchild(tglmesh));
siata.Vertices.clear;
for i:=1 to nt do begin
        rystr(i);
end;
        siata.CalcNormals(fwClockWise);
end;

procedure ttory.pokstrz(nr:integer);
var i:integer;
pok:xy;
begin;
  for i:=1 to 3 do begin
   if (i<=pnt[tra[nr].b].lia) then begin
   pok:=tbez(pnt[tra[nr].b].a[i],0.5);
   sta[i].Position.X:=pok.x;
   sta[i].Position.y:=pok.y;
   sta[i].Visible:=true;
   if i=pnt[tra[nr].b].sa then
        sta[i].Material.FrontProperties.Diffuse.Color:=clrgreen
        else
        sta[i].Material.FrontProperties.Diffuse.Color:=clryellow;

   end
   else
   sta[i].Visible:=false;

   if (i<=pnt[tra[nr].a].lib) then begin
   pok:=tbez(pnt[tra[nr].a].b[i],0.5);
   stb[i].Position.X:=pok.x;
   stb[i].Position.y:=pok.y;
   stb[i].Visible:=true;
   if i=pnt[tra[nr].a].sb then
        stb[i].Material.FrontProperties.Diffuse.Color:=clrgreen
        else
        stb[i].Material.FrontProperties.Diffuse.Color:=clryellow;

   end
   else
   stb[i].Visible:=false;

end;



end;

end.
