unit U_FlatLandPianoMovers;
 {Copyright 2001, Gary Darby, Intellitech Systems Inc., www.DelphiForFun.org

 This program may be used or modified for any non-commercial purpose
 so long as this original notice remains in place.
 All other rights are reserved
 }


interface

uses
  Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
  StdCtrls, NumEdit, Buttons, ExtCtrls, ComCtrls;

type


  TForm1 = class(TForm)
    {...Generated code snipped...}
  private
    { Private declarations }
  public
    { Public declarations }
    procedure drawimage;
  end;

var
  Form1: TForm1;

implementation

{$R *.DFM}

uses math;
type
  tline=record
    p1,p2:TPoint;
  end;

function sameside(L:TLine; p1,p2:TPoint; var pointonborder:boolean):int64;
  {used by Intersect function}
  {same side =>result>0
   opposite sides => result <0
   a point on the line => result=0 }
  var
    dx,dy,dx1,dy1,dx2,dy2:int64;
  begin
    dx:=L.p2.x-L.P1.x;
    dy:=L.p2.y-L.P1.y;
    dx1:=p1.x-L.p1.x;
    dy1:=p1.y-L.p1.y;
    dx2:=p2.x-L.p2.x;
    dy2:=p2.y-L.p2.y;
    result:=(dx*dy1-dy*dx1)*(dx*dy2-dy*dx2);
    if ((dx<>0) or (dy<>0)) and (result=0) then pointonborder:=true
    else pointonborder:=false;
  end;

 {******************** INTERSECT *******************}
  function  intersect(L1,L2:TLine; var pointonborder:boolean):boolean;
  {test for 2 line segments intersecting }
  var
    a,b:int64;
    pb:boolean;
  begin
    pointonborder:=false;
    a:=sameside(L1,L2.p1,L2.p2, pb);
    if pb then pointonborder:=true;
    b:=sameside(L2,L1.p1,L1.p2,pb);
    if pb then pointonborder:=true;
    result:=(a<=0) and (b<=0);
  end;

procedure TForm1.TryMoveBtnClick(Sender: TObject);
var
  L,W,N,H,V:integer;
  PrevDrawAngle:integer;  {used to check when piano was last drawn}
  Angle:extended;
  line1,line2:Tline;
  pointonborder, fits:boolean;
begin
  with image1, canvas do
  begin
    brush.color:=clwhite;
    rectangle(clientrect);
    drawimage;
    L:=PlenUD.position;
    w:=PWidthUD.position;
    {define a line from outside to inside of corrider corner}
    line2.p1:=point(0,0);
    line2.p2:=point(c1ud.position,c2UD.position);
    h:=0;
    angle:=0;
    prevdrawangle:=-1;
    fits:=true;
    while (fits) and (angle<=Pi/2) do
    begin
      v:=trunc(sqrt(L*L-H*H));
      {line1 contains coordinates of lower corners of the piano.
     If it intersects a line fron the outside to inside corners
     of the hallway (line2), it clears the corner at this angle}
      line1.p1:=point(trunc(L*sin(angle)+w*cos(angle)),trunc(W*sin(angle)));
      line1.p2:=point(trunc(w*cos(angle)),trunc(L*cos(angle)+W*sin(angle)));
      if not intersect(line1,line2, pointonborder)
      then fits:=false;
      N:=trunc(radtodeg(angle));
      if not fits or (N-prevdrawangle>10) then
      begin {only draw piano if stuck or every 10 degrees}
        prevdrawangle:=N;
        Moveto(0,V);
        lineto(H,0);
        lineto(H+trunc(W*cos(angle)),trunc(W*sin(angle)));
        lineto(trunc(W*sin(pi/2-angle)),V+trunc(W*cos(pi/2-angle)));
        lineto(0,V);
      end;
      angle:=angle+pi/2/StepsUD.position;
      h:=trunc(l*sin(angle));
    end;
    if fits then
    begin
     rectangle(L,0,L+L, W);
     showmessage('Made it!');
    end
    else showmessage('Won''t fit!')
  end;
end;

procedure TForm1.drawimage;
{draw initial and final image of the piano}
var
  L,W:integer;
begin
  with image1, canvas do
  begin
    brush.color:=clWhite;
    rectangle(clientrect);
    pen.width:=2;
    moveto(c1UD.position,height);
    lineto(c1UD.position,c2ud.position);
    lineto(width,c2UD.position);
    pen.width:=1;
    brush.color:=clsilver;
    brush.style:= bsdiagcross;
    canvas.floodfill(3,3,clblack,fsborder);
    L:=PlenUD.position; {piano length}
    W:=PWidthUD.position; {piano width}
    brush.color:=clgreen;
    brush.style:=bssolid;
    rectangle(0,L ,W,L+L);
    moveto(c1UD.position,height);
    lineto(c1UD.position,c2ud.position);
    lineto(width,c2UD.position);
  end;
end;

procedure TForm1.FormActivate(Sender: TObject);
begin
  drawimage;
end;

procedure TForm1.PLengthEdtChange(Sender: TObject);
begin
  drawimage;
end;

end.