Es gab mal Zeiten, da habe ich auch EXTREM viel Zeit investiert um eine Line zu zeichnen.
Das Clipping hat mich ne Weile beschäftigt....
Übrigens habe ich später festgestellt, dass der Bresenham Algorithus erstaunlich ähnlich aussieht,
den habe ich aber nicht abgeguckt, sondern tatsächlich selbst was entwickelt, anhand von Zeichnungen diverser Linien auf Karopapier.
Das war noch zu Zeiten der Hercules Grafikkarte
Eigentlich sollte man froh sein, dass man sich darum nicht mehr kümmern muss......
Das sah dann so aus:
Code: Alles auswählen
procedure Line(x1,y1,x2,y2:Integer);
var xdiff,ydiff,direction,nn:Integer;
begin
xdiff := x2 - x1;
if xdiff < 0 then begin
xdiff:=-xdiff;
nn:=x1; x1:=x2; x2:=nn; { Swap X1 mit x2 }
nn:=y1; y1:=y2; y2:=nn; { Swap Y1 mit Y2 }
end;
direction := +1;
ydiff := y2 - y1;
if ydiff < 0 then begin
ydiff := -ydiff;
direction := -direction { identical to -1 }
end;
if xdiff >= ydiff then begin
nn := (xdiff+1) DIV 2;
repeat
{ PutPixel(x1,y1); }
nn := nn - ydiff;
if nn < 0 then begin
nn := nn + xdiff;
y1 := y1 + direction;
end;
x1 := x1 + 1;
until x1 > x2;
end else begin
nn := (ydiff+1) DIV 2;
repeat
{ PutPixel(x1,y1); }
nn := nn - xdiff;
if nn < 0 then begin
nn := nn + ydiff;
x1 := x1 + 1;
end;
y1 := y1 + direction;
until y1 > y2;
end;
end;
{--------------------------------------------------------------------------}
Function ClipLineOnWindow(Var x1,y1,x2,y2:Integer;
WinX1,WinY1,WinX2,WinY2:Integer):Boolean;
VAR xdiff,ydiff,n,rest:Word; nn:LongInt; { muss ein unsigned Longint sein }
temp:integer;
Begin { CLIPPING-ROUTINE }
ClipLineOnWindow:=False; { Voreinstellung Linie ausserhalb }
if y1=y2 then Begin { Sonderfall 1 HORIZONTALE LINIE }
if y1 < WinY1 then Exit; { liegt komplett ueber dem Fenster }
if y1 > WinY2 then Exit; { liegt komplett unter dem Fenster }
if x1 > x2 then Begin { wenn x1 groesser ist als x2 dann }
temp:=x1; x1:=x2; x2:=temp; { x1 mit x2 tauschen }
end;
if x2 < WinX1 then Exit; { liegt komplett links vom Fenster }
if x1 > WinX2 then Exit; { liegt komplett rechts vom Fenster }
if x1 < WinX1 then x1:=WinX1; { Start am linken Fensterrand }
if x2 > WinX2 then x2:=WinX2; { Ende am rechten Fenterrand }
ClipLineOnWindow:=True;
Exit; { und Ende }
end;
if x1=x2 then Begin { Sonderfall 2 VERTIKALE LINIE }
if x1 < WinX1 then Exit; { liegt komplett links vom Fenster }
if x1 > WinX2 then Exit; { liegt komplett rechts vom Fenster }
if y1 > y2 then Begin { wenn y1 groesser ist als y2 dann }
temp:=y1; y1:=y2; y2:=temp; { y1 mit y2 tauschen }
end;
if y2 < WinY1 then Exit; { liegt komplett ueber dem Fenster }
if y1 > WinY2 then Exit; { liegt komplett unter dem Fenster }
if y1 < WinY1 then y1:=WinY1; { Start am oberen Fensterrand }
if y2 > WinY2 then y2:=WinY2; { Ende am unteren Fensterrand }
ClipLineOnWindow:=True;
Exit; { und Ende }
end;
if x1 > x2 then Begin { wenn xdiff negativ waere Linie nach links }
temp:=x1; x1:=x2; x2:=temp; { tausche x1 mit x2 }
temp:=y1; y1:=y2; y2:=temp; { tausche y1 mit y2 }
end; { nun laufen alle Linien nach rechts }
if x1 > WinX2 then Exit; { Linie liegt komplett rechts }
if x2 < WinX1 then Exit; { Linie liegt komplett links }
{$R-}
xdiff:=x2; { X-Differenz }
xdiff:=xdiff-x1;
{$R+}
if y1 > y2 then Begin { wenn Linie nach oben geht ydiff negativ }
if y1 < WinY1 then Exit; { liegt komplett oben }
if y2 > WinY2 then Exit; { liegt komplett unten }
ydiff:=y1;
ydiff:=ydiff-y2; { ydiff nun positiv }
{ Linie nach rechts oben }
if xdiff >= ydiff then Begin { wobei xdiff >=ydiff }
n:=xdiff SHR 1;
if x1 < WinX1 then Begin { clip links }
nn:=WinX1;
nn:=nn-x1;
nn:=nn*ydiff;
nn:=nn+n;
n :=nn MOD xdiff;
nn:=nn DIV xdiff;
y1:=y1-nn;
if y1 < WinY1 then Exit; { liegt oben }
x1:=WinX1;
end;
if x2 > WinX2 then Begin { clip rechts }
nn:=WinX2;
nn:=nn-x1;
inc(nn);
nn:=nn*ydiff;
nn:=nn+n;
nn:=nn DIV xdiff;
y2:=y1-nn;
if y2 > WinY2 then Exit; { liegt unten }
x2:=WinX2;
end;
if y1 > WinY2 then Begin { clip unten }
nn:=y1;
nn:=nn-WinY2;
nn:=nn*xdiff;
nn:=nn-n;
rest:=nn MOD ydiff;
nn:=nn DIV ydiff;
if rest=0 then n:=0;
if rest > 0 then begin
inc(nn);
n:=ydiff-rest;
end;
x1:=x1+nn;
if x1 > WinX2 then Exit; { liegt rechts }
y1:=WinY2;
end;
if y2 < WinY1 then Begin { clip oben }
nn:=y1;
nn:=nn-WinY1;
inc(nn);
nn:=nn*xdiff;
nn:=nn-n;
rest:=nn MOD ydiff;
nn:=nn DIV ydiff;
if rest=0 then dec(nn);
x2:=x1+nn;
if x2 < WinX1 then Exit; { liegt links }
y2:=WinY1;
end;
ClipLineOnWindow:=True;
Exit;
end; { xdiff > ydiff }
{ Linie nach rechts oben }
n:=ydiff SHR 1; { wobei ydiff > xdiff }
if y2 < WinY1 then Begin { clip oben }
nn:=y1;
nn:=nn-WinY1;
inc(nn);
nn:=nn*xdiff;
nn:=nn+n;
nn:=nn DIV ydiff;
x2:=x1+nn;
if x2 < WinX1 then Exit; { liegt links }
y2:=WinY1;
end;
if y1 > WinY2 then Begin { clip unten }
nn:=y1;
nn:=nn-WinY2;
nn:=nn*xdiff;
nn:=nn+n;
n :=nn MOD ydiff;
nn:=nn DIV ydiff;
x1:=x1+nn;
if x1 > WinX2 then Exit; { liegt links }
y1:=WinY2;
end;
if x2 > WinX2 then Begin { clip rechts }
nn:=WinX2;
nn:=nn-x1;
inc(nn);
nn:=nn*ydiff;
nn:=nn-n;
rest:=nn MOD xdiff;
nn:=nn DIV xdiff;
if rest=0 then dec(nn);
y2:=y1-nn;
if y2 > WinY2 then Exit; { liegt unten }
x2:=WinX2;
end;
if x1 < WinX1 then Begin { clip links }
nn:=WinX1;
nn:=nn-x1;
nn:=nn*ydiff;
nn:=nn-n;
rest:=nn MOD xdiff;
nn:=nn DIV xdiff;
if rest=0 then n:=0;
if rest > 0 then begin
inc(nn);
n:=xdiff-rest;
end;
y1:=y1-nn;
if y1 < WinY1 then Exit; { liegt oben }
x1:=WinX1;
end;
ClipLineOnWindow:=True;
Exit; { und Ende }
end;
if y2 < WinY1 then Exit; { liegt komplett oben }
if y1 > WinY2 then Exit; { liegt komplett unten }
{$R-}
ydiff:=y2;
ydiff:=ydiff-y1; { Differenz positiv }
{$R+} { sonst Linie nach rechts unten ydiff positiv }
if xdiff >= ydiff then Begin
n:=xdiff SHR 1;
if x1 < WinX1 then Begin { CLIP links }
nn:=WinX1;
nn:=nn-x1;
nn:=nn*ydiff; { ab jetzt long }
nn:=nn+n;
n :=nn mod xdiff; { n ist der Rest der nachfolgenden Division }
nn:=nn div xdiff; { hier hinter also MOV n,DX (Rest) }
y1:=y1+nn;
if y1 > WinY2 then Exit; { liegt komplett rechts }
x1:=WinX1;
end;
if x2 > WinX2 then Begin { CLIP rechts }
nn:=WinX2;
nn:=nn-x1;
inc(nn);
nn:=nn*ydiff; { ab jetzt long }
nn:=nn+n;
nn:=nn DIV xdiff;
y2:=nn;
y2:=y2+y1;
if y2 < WinY1 then Exit; { liegt oben }
x2:=WinX2;
end;
if y2 > WinY2 then Begin { CLIP unten }
nn:=Winy2;
nn:=nn-y1;
inc(nn);
nn:=nn*xdiff; { ab jetzt long }
nn:=nn-n;
rest:=nn mod ydiff;
nn:=nn div ydiff;
if rest=0 then dec(nn);
x2:=nn;
x2:=x2+x1;
if x2 < WinX1 then exit; { liegt links }
y2:=WinY2;
end;
if y1 < WinY1 then Begin { CLIP oben }
nn:=WinY1;
nn:=nn-y1;
nn:=nn*xdiff; { ab jetzt long }
nn:=nn-n;
rest:=nn MOD ydiff;
nn:=nn div ydiff;
if rest = 0 then n:=0;
if rest > 0 then begin
inc(nn);
n:=ydiff-rest;
end;
x1:=x1+nn;
if x1 > WinX2 then Exit; { liegt komplett rechts }
y1:=WinY1;
end;
ClipLineOnWindow:=True;
Exit; { xdiff >= ydiff }
end;
n:=ydiff SHR 1; { ab hier ydiff > xdiff--------------------- }
if y1 < WinY1 then Begin { clip oben }
nn:=WinY1;
nn:=nn-y1;
nn:=nn*xdiff;
nn:=nn+n;
n :=nn MOD ydiff;
nn:=nn DIV ydiff;
x1:=x1+nn;
if x1 > WinX2 then exit; { liegt links }
y1:=WinY1;
end;
if y2 > WinY2 then Begin { clip unten }
nn:=Winy2;
nn:=nn-y1;
inc(nn);
nn:=nn*xdiff; { ab jetzt long }
nn:=nn+n;
nn:=nn DIV ydiff;
x2:=nn;
x2:=x2+x1;
if x2< WinX1 then exit; { liegt links }
y2:=WinY2;
end;
if x2 > WinX2 then Begin { clip rechts }
nn:=WinX2;
nn:=nn-x1;
inc(nn);
nn:=nn*ydiff;
nn:=nn-n;
rest:=nn mod xdiff;
nn:=nn DIV xdiff;
if rest = 0 then dec(nn);
y2:=nn;
y2:=y2+y1;
if y2 < WinY1 then Exit; { liegt oben }
x2:=WinX2;
end;
if x1 < WinX1 then Begin { clip links }
nn:=WinX1;
nn:=nn-x1;
nn:=nn*ydiff;
nn:=nn-n;
rest:=nn MOD xdiff;
nn:=nn DIV xdiff;
if rest=0 then n:=0;
if rest > 0 then begin
inc(nn);
n:=xdiff-rest;
end;
y1:=y1+nn;
if y1>WinY2 then Exit; { liegt unten }
x1:=WinX1;
end;
ClipLineOnWindow:=True;
end;{LINE}
{============================================================================}
{ liefert TRUE wenn sich Px und Py auf der uebergebenen Linie befindet }
Function PointInLine(Px,Py,Lx1,Ly1,Lx2,Ly2:Integer):Boolean;
Begin
PointInLine:=ClipLineOnWindow(Lx1,Ly1,Lx2,Ly2,Px,Py,Px,Py);
end;
{============================================================================}