Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Sonstige Fragen zu Delphi (https://www.delphipraxis.net/19-sonstige-fragen-zu-delphi/)
-   -   Delphi Merkwürdiger Effekt bei Drehung einer Grafik (https://www.delphipraxis.net/119385-merkwuerdiger-effekt-bei-drehung-einer-grafik.html)

Taunuskrieger 25. Aug 2008 18:53


Merkwürdiger Effekt bei Drehung einer Grafik
 
Liste der Anhänge anzeigen (Anzahl: 1)
Hallo zusammen,

ich habe mir eine kleine Routine geschrieben, mit der ich eine Grafik innerhalb eines TImage drehen kann:

Delphi-Quellcode:
procedure TTurtle.Linksdrehung(winkel: integer);
var i,j, xcoord, ycoord:integer;
    farbe:TColor;
    xneu,yneu,alpha:real;
begin
                laufwinkel:=(laufwinkel+winkel) mod 360;
                alpha:=-1*laufwinkel;
                for j:=0 to 20 do begin
                        for i:=0 to 19 do begin
                                xcoord:=i-10;
                                ycoord:=j-10;
                                if ((i>1) and (i<18) and (j>4) and (j<16)) then begin
                                        farbe:=TurtleBild[(j-5)*16+i-2];
                                end
                                else farbe:=clWhite;
                                xneu:=xcoord*cos(alpha*(Pi/180))-ycoord*sin(alpha*(Pi/180))+10;
                                yneu:=xcoord*sin(alpha*(Pi/180))+ycoord*cos(alpha*(Pi/180))+10;
                                xcoord:=Round(xneu);
                                ycoord:=Round(yneu);
                                if ((xcoord>0) and (xcoord<20) and (ycoord>0) and (ycoord<21))
                                        then TurtleFigur.Canvas.Pixels[xcoord, ycoord]:=farbe;
                        end;
                end;
end;
Das Image TurtleFigur selbst ist 20x21 Pixel groß, die Farben für die Grafik sind pixelweise im Array TurtleBild gespeichert. Die Grafik ist 16x11 Pixel groß.
Laufwinkel ist eine globale Variable vom Typ integer und kann, bedingt durch meine Programmierung, Werte im Bereich 0 bis 359 annehmen.

Nun zu meinem Problem:
Rufe ich die Methode nacheinander auf (z.B. durch Druck auf einen Button), und wähle den Winkel, um den sich das ganze drehen soll, sehr klein, sieht das Ergebnis ganz gut aus.
Wähle ich allerdings sofort einen Winkel von 45 Grad, ist das Ergebnis total verpixelt. Eigentlich bin ich der Meinung, dass das Ergebnis dasselbe sein müsste (weil alpha in jedem Fall -45 beträgt), aber dem ist nicht so.

Wenn ich noch eine Schleife um die Methode bastele (also den laufwinkel nicht gleich um winkel erhöhe, sondern in Einerschritten), dann ist das Ergebnis auch ok. Mich würde aber noch der Grund für den Effekt interessieren. Hat jemand eine Idee?

SirThornberry 25. Aug 2008 20:34

Re: Merkwürdiger Effekt bei Drehung einer Grafik
 
Versuch mal ob bei Verwendung von PlgBlt auch diese Effekte auftreten.

grizzly 26. Aug 2008 07:35

Re: Merkwürdiger Effekt bei Drehung einer Grafik
 
Wenn ich Deinen Code beim Überfliegen richtig verstanden habe, dann berechnest Du für jedes Pixel des ungedrehten Bildes die neuen Pixelkoordinaten im gedrehten Bild und bildest das Pixel dort ab. Dabei kann es passieren, daß Du manche Pixelpositionen im neuen (gedrehten) Bild gar nicht erreichst -> Das Bild wird fransig und löchrig.
Man sollte den umgekehrten Weg gehen: Für jedes Pixel im neuen (gedrehten) Bild sucht man das zugehörige Pixel aus dem Originalbild. Dann wird kein Pixel ausgelassen.

Gruß
Michael

Taunuskrieger 26. Aug 2008 12:41

Re: Merkwürdiger Effekt bei Drehung einer Grafik
 
Der Tipp mit dem inversen Operator (umgekehrte Rechnung) war super. Er erklärt zwar nicht das Phänomen, löst das Problem aber weit sauberer als die zusätzliche Schleife:

Delphi-Quellcode:
procedure TTurtle.Linksdrehung(winkel: integer);
var i,j, xcoord, ycoord:integer;
    farbe:TColor;
    xneu,yneu,alpha:real;
begin
        laufwinkel:=(laufwinkel+winkel) mod 360;
        alpha:=laufwinkel;
        RichtungBestimmen(laufwinkel);
        for j:=0 to 20 do begin
                for i:=0 to 19 do begin
                        xcoord:=i-10;
                        ycoord:=j-10;
                        xneu:=xcoord*cos(alpha*(Pi/180))-ycoord*sin(alpha*(Pi/180))+10;
                        yneu:=xcoord*sin(alpha*(Pi/180))+ycoord*cos(alpha*(Pi/180))+10;
                        xcoord:=Round(xneu);
                        ycoord:=Round(yneu);
                        if ((xcoord>1) and (xcoord<18) and (ycoord>4) and (ycoord<16)) then begin
                                farbe:=TurtleBild[(ycoord-5)*16+xcoord-2];
                        end
                        else farbe:=clWhite;
                        TurtleFigur.Canvas.Pixels[i, j]:=farbe;
                end;
        end;
end;
Eine weitere Unit zu verwenden geht leider nicht. Wir können bei uns an der Schule leider keine weiteren Komponenten hinzufügen. Die Unit, die ich gerade schreibe, braucht man nachher nur in dasselbe Verzeichnis kopieren wie das Hauptprojekt. Bei mehreren Projekte ist auch das schon unschön, und ich möchte vermeiden, noch mehr solcher Units zu verwenden.

So, das Problem ist jetzt zwar gelöst, aber noch nicht erklärt. alpha war doch in beiden Fällen 45. Wie kommt es zu unterschiedlichen Resultaten? Ich habe in beiden Fällen (alpha gleich 45, alpha 45 mal 1) auf das Originalarray zugegriffen, aber jedes mal war das Resultat ein anderes. Übrigens steigerte sich die Ungenauigkeit mit der Schrittweite.


Alle Zeitangaben in WEZ +1. Es ist jetzt 21:28 Uhr.

Powered by vBulletin® Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz