Linia po swojemu w trybie graficznym

0

Witam wszystkich !

Czy zna ktoś sposób na narysowanie linni prostej tylko za pomocą funkcji PutPixel ???
Chodzi mi o to, aby nie korzystać z gotowych funkcji w Pascalu, ale aby samemu pixel po pixelu (mając dane współrzędne początku i końca linni ) narysować ja sobie ???

Pozdrawiam i błagam o pomoc...

0

na jakimś servisie o grach to było, idea polega na zamalowywaniu tego pixela na drodze do końca który leży bliżej środka "pisaka"

0

x := (1-t) * p1.x + t * p2.x;
y := (1-t) * p1.y + t * p2.y;

gdzie :
t : wartość ograniczona zakresem [0 - 1] (np dla srodka prostej t := 0.5, wiesz o co chodzi)..
p1, p2 : punkty krańcowe prostej
x, y : wynik (dla procki putPixel)

oczywiście wszystko należy zloopować, skok t ustawić na : 1 / odl;
gdzie odl to odległość p1 od p2.

pozdrawiam.. w razie pytań.... pytaj :)

[dop]
Ciekawostka : jak w podobny sposób narysować krzwą Bezier'a 3-go stopnia ?

x:=(1-t)(1-t)(1-t)P1.x + 3(1-t)(1-t)tP2.x + 3(1-t)ttP3.x + tttP4.x;
y:=(1-t)(1-t)(1-t)P1.y + 3(1-t)(1-t)tP2.y + 3(1-t)ttP3.y + tttP4.y;

/* Nie wiedziałem, że są krzywe Bezier'a nie 3-go stopnia :-/ m.D. */

Tak właśnie.., poprawka : Krzywa Bezier'a to krzywa WIELOMIANOWA 3go stopnia.. Ale na upartego, złorzenie trzech takich krzywych można by nazwać właśnie krzywą Beziera 3go stopnia.. ale to już nie była by krzywa Beziera tylk krzywa Tomickiego.. ale to szczegół..
za dużo tych filmów Spilberga się naoglądałem..

0

Cześć !

Dzięki za odpowiedź - o to mi właśnie chodziło.

Ale skoro natrafiłem już na kogoś, kto się na tym zna, to postanowiłem dopytać co nie co.

A więc potrzebne były mi 2 procki, oto i one :

function OdlegloscPunktow(x1,y1,x2,y2:integer):integer;
begin
OdlegloscPunktow:=round(sqrt(sqr(abs(x2-x1))+sqr(abs(y2-y1))));
end;

procedure Line(x1,y1,x2,y2:integer);
var t:real;
l,odl:integer;
begin
odl:=odlegloscpunktow(x1,y1,x2,y2);
for l:= 0 to odl do
begin
t:=l/odl;
PutPixel(round((1-t)x1+tx2),round((1-t)y1+ty2),255);
end;
end;

Rysują prostą tak jak chciałem, aczkolwiek nie jest to chyba najlepsza metoda.

Uzyj procedury Line(0,0,319,199), aby się przekonać co jest nie tak.

Procedura nie rysuje ciągłej linii, ale zaznacza (akurat w tym wypadku) chyba co trzeci pixel.
Z tej procki raczej nic już lepszego się nie da wyciągnąć, więc czy znasz może jakiś lepszy sposób (lub
może ulepszenie tego) ???

0

Troszkę twoją procedurkę zmodyfikowałem :

function OdlegloscPunktow(x1,y1,x2,y2:integer):integer;
var a, b : real;
begin
a := abs(x1-x2);
b := abs(y1-y2);
OdlegloscPunktow := round(sqrt(aa + bb));
end;

procedure Line(x1,y1,x2,y2:integer);
var t, skok:real;

begin
skok:=1/OdlegloscPunktow(x1,y1,x2,y2);
repeat
t := t + skok;
PutPixel(round((1-t)x1+tx2), round((1-t)y1+ty2), 255);
until t >= 1;
end;

u mnie działa jak należy!

0

Dzięki
OK, zaraz przetestuję i postaram sie odpisać...

0

Skoro tak optymalizujemy (a ja to bardzo lubię, choć przesadnie to tylko dla zabawy) to pobawię się jeszcze.
Nie potrzeba abs, ponieważ potem podnosimy do kwadratu, więc znak jest nieistotny. Wystarczy więc tak:
a := x1-x2;
b := y1-y2;

Jeżeli naszej funcji OdlegloscPuntkow wykorzystujemy tylko w naszej procedurze to możemy ją umieścić jako lokalną funkcję. To zaoszczędzi nam przekazywania współrzędnych jako parametrów. Dodatkowo możemy zamienić Real na Single, gdyż nie jest tutaj wymagana ogromna dokładność a typ Single (4 bajty) jest szybciej obliczany niż Real (6 bajtów w Pascalu i Delphi = 1 + Skok;
end;

Możnaby spróbować pobawić się jeszcze troszkę i spróbować zastąpić standardową metrykę jakąś bez pierwiastków (to najbardziej obciążająca operacja tutaj).

0

Witam !
Dzięki za zainteresowanie tym problemem.
Poprzednia procka działa OK.
Znalazłem jeszcze jedną ( trochę długą procedurekę ) asseblerową rysującą linię (jeszcze nie testowałem ).

Zaczerpnięte żywcem z biblioteki KAJGL :
[code]
Procedure Line(X1, Y1, X2, Y2 : Word; Color : Byte); Assembler;
Var
DeX,
DeY,
IncF : Integer;

Asm { Line }
mov ax, [X2] { Move X2 into AX }
sub ax, [X1] { Get the horiz length of the line - X2 - X1 }
jnc @Dont1 { Did X2 - X1 yield a negative result? }
neg ax { Yes, so make the horiz length positive }

@Dont1:
inc ax
mov [DeX], ax { Now, move the horiz length of line into DeX }
mov ax, [Y2] { Move Y2 into AX }
sub ax, [Y1] { Subtract Y1 from Y2, giving the vert length }
jnc @Dont2 { Was it negative? }
neg ax { Yes, so make it positive }

@Dont2:
inc ax
mov [DeY], ax { Move the vert length into DeY }
cmp ax, [DeX] { Compare the vert length to horiz length }
jbe @OtherLine { If vert was !!

0

Polecam książkę wydawnictwa Microsoft Press & Read Me: "Komputerowe karty graficzne" - Richard Wilton.
Prawie 500 stron z tego typu algorytmami (ASM + C++).

I nie proś, abym je przepisywał :-D.

1 użytkowników online, w tym zalogowanych: 0, gości: 1