 |
Das deutsche QBasic- und FreeBASIC-Forum Für euch erreichbar unter qb-forum.de, fb-forum.de und freebasic-forum.de!
|
Vorheriges Thema anzeigen :: Nächstes Thema anzeigen |
Autor |
Nachricht |
Muttonhead

Anmeldungsdatum: 26.08.2008 Beiträge: 565 Wohnort: Jüterbog
|
Verfasst am: 26.05.2013, 11:24 Titel: Grafik drehen, Klappe die x. .... |
|
|
Ich will mir meine eigene Bitmaprotation schreiben und hab dabei mal versucht Multiput zu zerlegen...
naja... nicht so einfach
Letztendlich hab ich mich für diese Vorgehensweise entschieden.
Dafür hab ich mal eine kleine Visualisierung geschrieben:
(Frage kommt hinterher)
Code: |
'******************************************************************************
type vector
x as double
y as double
end type
'******************************************************************************
'Koordinatenursprung
const as integer Xo=400
const as integer Yo=300
'Pi
const as double pi =atn (1) * 4
const as double doublepi=pi*2
'Globaler Punkte/Vektor Speicher
dim shared as vector Points(63)' so! das sollten genug Punkte sein
'Zeichenroutinen, sollen nur den Code lesbarer machen
sub DrawCartesian
line (0,Yo)-(799,Yo),&H007F00
line (Xo,0)-(Xo,599),&H7F0000
end sub
sub DrawPolygon(fi as integer, li as integer,col as uinteger=&H000000)
pset(Xo+Points(li).x,Yo-Points(li).y),col
for i as integer=fi to li
line -(Xo+Points(i).x,Yo-Points(i).y),col
next i
end sub
sub DrawPoint(i as integer,col as uinteger=&H000000)
line (Xo+Points(i).x-5,Yo-Points(i).y)-(Xo+Points(i).x+5,Yo-Points(i).y),col
line (Xo+Points(i).x,Yo-Points(i).y-5)-(Xo+Points(i).x,Yo-Points(i).y+5),col
circle(Xo+Points(i).x,Yo-Points(i).y),5,&H000000
end sub
sub DrawVector(l as integer,i as integer,col as uinteger=&H000000)
line (Xo+Points(l).x,Yo-Points(l).y)-(Xo+Points(l).x + Points(i).x*15,Yo-Points(l).y - Points(i).y*15),col
circle(Xo+Points(l).x,Yo-Points(l).y),2,&H000000
end sub
'******************************************************************************
'******************************************************************************
'******************************************************************************
'Hier gehts los....
screen 19,32
color &H000000,&HFFFFFF
dim as integer boxw,boxh
dim as double pivotx,pivoty
dim as double arcus,degree
dim as double x,y,xmin,xmax,ymin,ymax'Berechnungshilfen
dim as string junk
dim as uinteger gray,green
gray=&H7F7F7F
green=&H00DD22
'Boxgröße definieren
boxw=150 'diese stellt das ungedrehte Originalimage dar
boxh=200
'Drehwinkel in Grad festlegen
degree=100
arcus=doublepi/360 * degree 'Grad --> Bogenmaß
'Drehpunkt festlegen
pivotx=30
pivoty=-30
'Zeichnen
cls
DrawCartesian 'Zeichne Koordinatensystem
print "1.) Koordinatensystem"
sleep 15000 'Pause
'Berechnungen
Points(0).x=0 'linke obere Ecke im Koordinatenursprung positionieren
Points(0).y=0
Points(1).x=Points(0).x 'basierend auf ersten Punkt die drei anderen positionieren
Points(1).y=Points(0).y - boxh
Points(2).x=Points(0).x + boxw
Points(2).y=Points(0).y - boxh
Points(3).x=Points(0).x + boxw
Points(3).y=Points(0).y 'Box befindet sich nun im IV. Quadranten
Points(4).x=pivotx 'Drehpunkt in das Pointsarray übertragen
Points(4).y=pivoty
'Zeichnen
cls
DrawCartesian 'Zeichne Koordinatensystem
DrawPolygon(0,3,green) 'ungedrehte Box
DrawPoint(0,green) 'ungedrehte Box, linker oberer Punkt ( Pixel(0,0) )
DrawPoint(4,gray) 'ungedrehter Drehpunkt
print "2.) Originalgrafik linke obere Ecke ( Pixel(0,0) ) im Koordinatenursprung mit"
print " gewuenschtem Drehpunkt"
sleep 15000 'Pause
'Berechnungen
xmin=0 'mit Hilfe dieser vier Variablen wird die Größe und Lage(!) des temporären
xmax=0 'Images bestimmt, welches die gedrehte Grafik aufnimmt
ymin=0
ymax=0
Points(5)=Points(0) 'da im Ursprung kann dieser einfach übernommen werden
for i as integer=1 to 4 'nur 3 Punkte müssen gedreht werden
x= Points(i).x * cos(arcus) - Points(i).y * sin(arcus)
y= Points(i).x * sin(arcus) + Points(i).y * cos(arcus)
Points(i+5).x=x
Points(i+5).y=y
if i<4 then 'Drehpunkt bei min/max ausschließen
if x<xmin then xmin=x 'nach Berechnung auf max/min prüfen und "merken"
if x>xmax then xmax=x
if y<ymin then ymin=y
if y>ymax then ymax=y
end if
next i
'Zeichnen
cls
DrawCartesian 'Zeichne Koordinatensystem
DrawPolygon(0,3,gray) 'ungedrehte Box
DrawPoint(0,gray) 'ungedrehte Box, linker oberer Punkt ( Pixel(0,0) )
DrawPoint(4,gray) 'ungedrehter Drehpunkt
DrawPolygon(5,8,green) 'gedrehte Box
DrawPoint(5,green) 'gedrehte Box, linker oberer Punkt ( Pixel(0,0) )
DrawPoint(9,green) 'gedrehter Drehpunkt
print "3.) gedrehte Grafik mit gedrehten Drehpunkt *hust*"
sleep 15000 'Pause
'Berechnung
dim as integer box2w,box2h
box2w=xmax-xmin
box2h=ymax-ymin
Points(10).x=xmin
Points(10).y=ymax
Points(11).x=Points(10).x
Points(11).y=Points(10).y - box2h
Points(12).x=Points(10).x + box2w
Points(12).y=Points(10).y - box2h
Points(13).x=Points(10).x + box2w
Points(13).y=Points(10).y
Points(14).x=Points(10).x'2 Hilfspunkte für die Darstellung der Vektoren
Points(14).y=Points(10).y+15
Points(15).x=Points(10).x-15
Points(15).y=Points(10).y
Points(16).x=+1'Vektor
Points(16).y=0
Points(17).x=0
Points(17).y=-1
'Zeichnen
cls
DrawCartesian
DrawPolygon(0,3,gray) 'ungedrehte Box
DrawPoint(0,gray) 'ungedrehte Box, linker oberer Punkt ( Pixel(0,0) )
DrawPoint(4,gray) 'ungedrehter Drehpunkt
DrawPolygon(5,8,gray) 'gedrehte Box
DrawPoint(5,gray) 'gedrehte Box, linker oberer Punkt ( Pixel(0,0) )
DrawPoint(9,gray) 'gedrehter Drehpunkt
DrawPolygon(10,13,green) 'ungedrehte Box temporäres Image,
DrawPoint(10,green) 'ungedrehte Box temporäres Image, linker oberer Punkt ( Pixel(0,0) )
DrawVector(14,16,green) 'Vektor
DrawVector(15,17,green) 'Vektor
print "4.) Lage und Groesse des temporaeren Images welches die gedrehte Grafik enthalten wird"
print "der linke obere Punkt des temp. Images ist gleichzeitig der noch"
print "ungedrehte Startpunkt des Scanvorgangs"
sleep 15000 'Pause
'Berechnung
'Drehung der Scanbox entgegengesetzt
for i as integer=10 to 17
x= Points(i).x * cos(-arcus) - Points(i).y * sin(-arcus)
y= Points(i).x * sin(-arcus) + Points(i).y * cos(-arcus)
Points(i+8).x=x
Points(i+8).y=y
next i
'Zeichnen
cls
DrawCartesian
DrawPolygon(0,3,gray) 'ungedrehte Box
DrawPoint(0,gray) 'ungedrehte Box, linker oberer Punkt ( Pixel(0,0) )
DrawPoint(4,gray) 'ungedrehter Drehpunkt
DrawPolygon(5,8,gray) 'gedrehte Box
DrawPoint(5,gray) 'gedrehte Box, linker oberer Punkt ( Pixel(0,0) )
DrawPoint(9,gray) 'gedrehter Drehpunkt
DrawPolygon(10,13,gray) 'ungedrehte Box temporäres Image,
DrawPoint(10,gray) 'ungedrehte Box temporäres Image, linker oberer Punkt ( Pixel(0,0) )
DrawVector(14,16,gray) 'Vektor
DrawVector(15,17,gray) 'Vektor
DrawPolygon(18,21,green) 'gedrehte Box temporäres Image,
DrawPoint(18,green) 'gedrehte Box temporäres Image, linker oberer Punkt ( Pixel(0,0) )
DrawVector(22,24,green) 'gedrehter Vektor
DrawVector(23,25,green) 'gedrehter Vektor
print "5.) entgegengesetzt gedrehte Box des temp. Images. Scanstartpunkt ist"
print "nun an richtiger Position. Die beiden Richtungsvektoren sind ebenfalls"
print "gedreht."
print "Dies stellt nun die ScanBox dar, von der die Farbwerte ins temp. Image"
print "uebertragen werden."
sleep
end |
um einen anderen Drehpunkt zu realisieren, habe ich einfach einen Punkt definiert und diesen virtuell mitgedreht.
Reicht es einfach aus, (nach Rotation und Scan) das temoräre Image so zu verschieben, daß sich der "gedrehte RotationsPunkt"
wieder über den "ungedrehten" befindet?
Ich weiß, das Ganze ist jetzt sehr unglückich formuliert, hoffe aber jemand steigt hinter mein Anliegen.
Ich bin auch schon reichlich loose deswegen
Mutton |
|
Nach oben |
|
 |
Eternal_pain

Anmeldungsdatum: 08.08.2006 Beiträge: 1783 Wohnort: BW/KA
|
Verfasst am: 26.05.2013, 12:55 Titel: |
|
|
Ich hab vor ewigen Zeiten (auch mithilfe von multiput) mal eine eigene Rotations-Routine gebastelt gehabt (auch wenn ich sie (vermutlich) nicht mehr habe)
Aber um ehrlich zu sein, ich hab die Frage nicht wirklich verstanden...
Was genau ist nun das Problem? _________________
 |
|
Nach oben |
|
 |
Muttonhead

Anmeldungsdatum: 26.08.2008 Beiträge: 565 Wohnort: Jüterbog
|
Verfasst am: 26.05.2013, 14:35 Titel: |
|
|
Also mal kurz eine (Er-)Klärung:
Da wie beim "normalen" PUT Pixel(0,0) der Originalgrafik als Referenz für die Verortung gilt, soll
dies auch bei meine Routine so bleiben.Deswegen liegt die linke obere Ecke im Koordinatenursprung.
Dann werden die restlichen 3 Eckpunkte gedreht. Dies dient eigentlich nur dazu, Die Größe und(!) die Lage eines
temporären Images festzustellen. Dieses temporäre Image enthält später (nach einem Scan) die gedrehte Grafik und kann
genau an der grade ermittelten Position "gePUTet" werden, WENN der Drehpunkt im Koordinatenursprung bzw Pixel(0,0) bleibt.
Was wenn der Drehpunkt wo anders sein soll? Grundsätzlich ist es natürlich möglich die Originalgrafik nicht in den Urprung zu setzen.
Für den Scanvorgang ist es meiner Meinung nach günstiger, die Originalgrafik mit Pixel(0,0) im Ursprung zu belassen.
Statt dessen hab ich mir etwas anderes ausgedacht.
Ich definiere ein Drehpunkt, nennen wir ihn "P". Diesen drehe ich genauso wie ich es mit der OriginalBox getan habe. dadurch entsteht
punkt "P'".
Oben ist Punkt PT. Dies ist der Punkt wo ich das temporäre Image PUTen würde, wenn der Drehpunkt im Koordinatenursprung ist.
Wenn ich diesen aber so verschiebe, das "P" und "P'" wieder übereinander liegen...
Entspricht das Ergebnis dann einer Drehung um den Punkt "P" ????
naja es wird wohl auch nicht deutlicher *lach*
Mutton |
|
Nach oben |
|
 |
Eternal_pain

Anmeldungsdatum: 08.08.2006 Beiträge: 1783 Wohnort: BW/KA
|
Verfasst am: 26.05.2013, 15:50 Titel: |
|
|
Kann sein das ich heute auf der Leitung steh' aber wirklich verstanden habe ich es eigentlich immer noch nicht
Deine Rotationsfunktion ansich ist ok, einen drehpunkt zu definieren ist glaube auch kein problem, das man ein image das man original zB nach 100,100 geputtet hat rotiert dann aber nicht mehr bei 100,100 putten kann sollte klar sein (wo ich wieder die Frage habe was genau das Problem ist )
Code: |
tX = (X-rotationspunktX) * cos(winkel) - (Y-rotationspunktY) * sin(winkel)
tY = (X-rotationspunktX) * sin(winkel) + (Y-rotationspunktY) * cos(winkel)
|
Das sollte eigentlich den 'schwerpunkt' der rotation lösen?!
wenn das dein Problem war??? _________________
 |
|
Nach oben |
|
 |
Muttonhead

Anmeldungsdatum: 26.08.2008 Beiträge: 565 Wohnort: Jüterbog
|
Verfasst am: 26.05.2013, 18:09 Titel: |
|
|
Zitat: | Deine Rotationsfunktion ansich ist ok, einen drehpunkt zu definieren ist glaube auch kein problem, das man ein image das man original zB nach 100,100 geputtet hat rotiert dann aber nicht mehr bei 100,100 putten kann sollte klar sein (wo ich wieder die Frage habe was genau das Problem ist ) |
Genau darum geht es ja! Die eigentliche Drehung erfolgt bei mir immer um Pixel(0,0) des Originals, der auch im Koordinatenursprung liegt.
Wohin in diesem Fall gePUTet wird, ist bekannt. Diesen Punkt (PT siehe vorherigen Post) berechne ich ja korrekt.
Ich will aber anschließend, durch PUTn mit einen bestimmten Offset von diesem Punkt das Rotationszentrum verlagern.
Und da war meine Idee halt diese: man nehme einen Punkt(P) der das neue Rotationszentrum sein soll, drehe diesen(P') und verschiebe dann das zu PUTende von TP soweit, das Punkte P und P' wieder übereinanderliegen.
Meine Frage ist halt: ob das Ergebnis dann mathematisch,trigonometrisch oder sonstwie einer korrekten Drehung um P entspricht...
Naja... davon geht die Welt nicht unter  |
|
Nach oben |
|
 |
ThePuppetMaster

Anmeldungsdatum: 18.02.2007 Beiträge: 1839 Wohnort: [JN58JR]
|
Verfasst am: 26.05.2013, 23:59 Titel: |
|
|
Ich habs zwar auch nicht kappiert, aber ich versuche jetzt einfach mal auf irgend etwas zu antworten:
Um etwas zu drehen benötigst du grundlegend erstmal einen Rotationspunkt. Ohne diesen funktioniert das drehen generell nicht.
Anhand dieses Punktes kannst du dann berechnen, wo ein Sourcepixel nach der drehung platziert werden muss.
Du hast angenommen ein Bild mit 200x300. Legst auf 100x150 den drehpunkt fest und willst um 90° drehen. Dann landet der pixel von 1x1 bei 250x-50.
änderst du den drehpunkt entsprechend auf 1x1 dann landet pixel 1x1 bei 1x1.
die berechnung dieses ist, wie von @Eternal_pain schon beschrieben.
wenn du jetzt noch einen offset hinzufügen willst, sprich ... du drehst, udn willst das ergebniss dann nochmal linear verschieben, dann musst du natürlich diesen offset beim ergebniss setzen, da beim source du sonst outofboundary kommst.
sprich: tx = offsetX + (x-rotationspunktX) ....
MfG
TPM _________________ [ WebFBC ][ OPS ][ ToOFlo ][ Wiemann.TV ] |
|
Nach oben |
|
 |
Eukalyptus
Anmeldungsdatum: 17.05.2013 Beiträge: 11
|
Verfasst am: 27.05.2013, 22:49 Titel: |
|
|
Verwende doch eine Matrix.
Damit kannst du dann gleichzeitig auch noch kippen und skalieren.
Genauso, wie man es in GDIPlus machen kann!
Ich hab mal versucht diese Beispiel zusammenzubasteln:
Code: | Type t_MATRIX2D
Private:
MX(9) As Double
Declare Sub Mul(pMX1 As Double Ptr, pMX2 As Double Ptr)
Public:
Declare Sub GetElements(pMX As Double Ptr)
Declare Sub Invert
Declare Sub MulVector(fX As Double, fY As Double, ByRef fTX As Double, ByRef fTY As Double)
Declare Sub Reset(pMX As Double Ptr)
Declare Sub Rotate(fAngle As Double, iOrder As Integer = 0)
Declare Sub Scale(fScaleX As Double, fScaleY As Double, iOrder As Integer = 0)
Declare Sub Skew(fSkewX As Double, fSkewY As Double, iOrder As Integer = 0)
Declare Sub Translate(fTransX As Double, fTransY As Double, iOrder As Integer = 0)
Declare Constructor
End Type
Sub t_MATRIX2D.GetElements(pMX As Double Ptr)
For i As Integer = 0 To 8
pMX[i] = MX(i)
Next
End Sub
Sub t_MATRIX2D.Mul(pMX1 As Double Ptr, pMX2 As Double Ptr)
Dim As Double fS
For x As Integer = 0 To 2
For y As Integer = 0 To 2
fS = 0
For z As Integer = 0 To 2
fS += pMX1[x*3+z] * pMX2[z*3+y]
Next
MX(x*3+y) = fS
Next
Next
End Sub
Sub t_MATRIX2D.MulVector(fX As Double, fY As Double, ByRef fTX As Double, ByRef fTY As Double)
fTX = fX * MX(0) + fY * MX(3) + MX(6)
fTY = fX * MX(1) + fY * MX(4) + MX(7)
End Sub
Sub t_MATRIX2D.Invert
'[ a b 0 ]
'[ c d 0 ]
'[ x y 1 ]
't = a*d-b*c
'[ d/t -b/t 0 ]
'[ -c/t a/t 0 ]
'[(c*y-d*x)/t -(a*y-b*x)/t 1 ]
Dim As Double fM(9), fT
GetElements(@fM(0))
fT = fM(0)*fM(4)-fM(1)*fM(3)
MX(0) = fM(4)/fT
MX(1) = -fM(1)/fT
MX(3) = -fM(3)/fT
MX(4) = fM(0)/fT
MX(6) = (fM(3)*fM(7)-fM(4)*fM(6)) / fT
MX(7) = -(fM(0)*fM(7)-fM(1)*fM(6)) / fT
End Sub
Sub t_MATRIX2D.Translate(fTransX As Double, fTransY As Double, iOrder As Integer = 0)
'[ 1 0 0 ]
'[ 0 1 0 ]
'[TX TY 1 ]
Dim As Double MX1(9), MX2(9)
GetElements(@MX2(0))
Reset(@MX1(0))
MX1(6) = fTransX
MX1(7) = fTransY
Select Case iOrder
Case 0
Mul(@MX1(0), @MX2(0))
Case Else
Mul(@MX2(0), @MX1(0))
End Select
End Sub
Sub t_MATRIX2D.Skew(fSkewX As Double, fSkewY As Double, iOrder As Integer = 0)
'[ 1 SY 0 ]
'[SX 1 0 ]
'[ 0 0 1 ]
Dim As Double MX1(9), MX2(9)
GetElements(@MX2(0))
Reset(@MX1(0))
MX1(1) = fSkewY * 0.0174532925199433
MX1(3) = fSkewX * 0.0174532925199433
Select Case iOrder
Case 0
Mul(@MX1(0), @MX2(0))
Case Else
Mul(@MX2(0), @MX1(0))
End Select
End Sub
Sub t_MATRIX2D.Scale(fScaleX As Double, fScaleY As Double, iOrder As Integer = 0)
'[SX 0 0 ]
'[ 0 SY 0 ]
'[ 0 0 1 ]
Dim As Double MX1(9), MX2(9)
GetElements(@MX2(0))
Reset(@MX1(0))
MX1(0) = fScaleX
MX1(4) = fScaleY
Select Case iOrder
Case 0
Mul(@MX1(0), @MX2(0))
Case Else
Mul(@MX2(0), @MX1(0))
End Select
End Sub
Sub t_MATRIX2D.Rotate(fAngle As Double, iOrder As Integer = 0)
'[ C S 0 ]
'[-S C 0 ]
'[ 0 0 1 ]
If fAngle = 0 Then Return
Dim As Double fR, fS, fC
fR = fAngle * 0.0174532925199433
fC = Cos(fR)
fS = Sin(fR)
Dim As Double MX1(9), MX2(9)
GetElements(@MX2(0))
Reset(@MX1(0))
MX1(0) = fC
MX1(1) = fS
MX1(3) = -fS
MX1(4) = fC
Select Case iOrder
Case 0
Mul(@MX1(0), @MX2(0))
Case Else
Mul(@MX2(0), @MX1(0))
End Select
End Sub
Sub t_MATRIX2D.Reset(pMX As Double Ptr)
'[ 1 0 0 ]
'[ 0 1 0 ]
'[ 0 0 1 ]
For i As Integer = 0 To 8
pMX[i] = 0
Next
pMX[0] = 1
pMX[4] = 1
pMX[8] = 1
End Sub
Constructor t_MATRIX2D
Reset(@MX(0))
End Constructor
Screen 19,32
Dim As String sFileName = "Bild.bmp"
Dim As Integer iBmpW, iBmpH, iScreenW, iScreenH
ScreenInfo iScreenW, iScreenH, , , , ,
Dim As Integer iFile = FreeFile
Open sFileName For Input As #iFile
Get #iFile, 19, iBmpW
Get #iFile, 23, iBmpH
Close #iFile
Dim pPixel As UInteger Ptr
pPixel = ImageCreate(iBmpW, iBmpH)
Bload sFileName, pPixel
Dim As t_MATRIX2D tMX
tMX.Translate(-iBmpW/2, -iBmpH/2)'RotationsAchse in Bildmitte verschieben
tMX.Scale(0.5, 0.8, 1)'Skalieren
tMX.Rotate(30, 1)'Rotieren
'tMX.Skew(-45, 0)'Skew
tMX.Translate(iScreenW/2, iScreenH/2, 1)'BildMitte zu ScreenMitte verschieben
'Neue Bildeckpunkte berechnen
Dim As Double aPnt(4, 2)
tMX.MulVector(0, 0, aPnt(0,0), aPnt(0,1))
tMX.MulVector(iBmpW, 0, aPnt(1,0), aPnt(1,1))
tMX.MulVector(0, iBmpH, aPnt(2,0), aPnt(2,1))
tMX.MulVector(iBmpW, iBmpH, aPnt(3,0), aPnt(3,1))
Dim As Integer iX1, iY1, iX2, iY2
iX1 = 2147483647
iY1 = 2147483647
iX2 = -2147483648
iY2 = -2147483648
For i As Integer = 0 To 3
If aPnt(i, 0) < iX1 Then iX1 = aPnt(i, 0)
If aPnt(i, 0) > iX2 Then iX2 = aPnt(i, 0)
If aPnt(i, 1) < iY1 Then iY1 = aPnt(i, 1)
If aPnt(i, 1) > iY2 Then iY2 = aPnt(i, 1)
Next
tMX.Invert 'Matrix invertieren -> Reverse mapping
'Man könnte auch forward-mappen, jedoch bekommt man dann bei einer Vergrößerung Löcher und eine Interpolation lässt sich auch nicht realisieren
Dim As Double fX, fY
For x As Integer = iX1 To iX2
For y As Integer = iY1 To iY2
tMX.MulVector(x, y, fX, fY)'Src - Pixelpos berechnen
If (fX >= 0) And (fY >= 0) And (fX < iBmpW) And (fY < iBmpH) Then
PSet (x, y), Point(fX, fY, pPixel)
EndIf
Next
Next
Circle(aPnt(0,0), aPnt(0,1)),4,&HFF00FF00,,,,F
Circle(aPnt(1,0), aPnt(1,1)),4,&HFF00FF00,,,,F
Circle(aPnt(2,0), aPnt(2,1)),4,&HFF00FF00,,,,F
Circle(aPnt(3,0), aPnt(3,1)),4,&HFF00FF00,,,,F
Sleep
If pPixel <> 0 Then ImageDestroy(pPixel)
End |
|
|
Nach oben |
|
 |
Eternal_pain

Anmeldungsdatum: 08.08.2006 Beiträge: 1783 Wohnort: BW/KA
|
Verfasst am: 28.05.2013, 09:20 Titel: |
|
|
Matrix, ein 'Zauberwort' auf das ich wohl so schnell nicht gekommen wäre obwohl es doch eigentlich so nahe liegt... wenn mich mein Verständnis nicht trübt so müsste das ganze sogar schneller sein als die ursprüngliche Berechnung und zudem auch noch recht flexibel. (OpenGL Berechnungen sehr ähnlich)
Wenn es Dir vielleicht nicht zu viel Mühe bereiten würde, könntest Du dem Code ein paar zusätzliche als Hilfestellung dienende Kommentare hinzufügen um ein besseres Verständnis der Mathematik dahinter zu bekommen?
Mit etwas Googlen und dem Code könnte sich vielleicht meine Matrixphobie legen  _________________
 |
|
Nach oben |
|
 |
Muttonhead

Anmeldungsdatum: 26.08.2008 Beiträge: 565 Wohnort: Jüterbog
|
Verfasst am: 28.05.2013, 09:49 Titel: |
|
|
meine schulbildung, und die ist auch schon nen weilchen her, reicht leider nicht für matrizen aus... Und wiki ist bei fehlendem hintergrundwissen nicht wirklich hilfreich
EDIT:
Trotzdem versuch ichs nochmal
Also dies hier ist eine Drehung um den Punkt P
Da anderenfalls Weltfrieden ausbrechen würde und der Sack Reis in China nicht umkippt
muß die Drehung in der oberen linken Ecke vonstatten gehen. Meinen gewünschten Drehpunkt A
habe ich mal mitgedreht. Und der bekommt als gedreht den Namen A'
Wenn ich jetzt mein gedrehtes Etwas so verschiebe, das A' wieder über A liegt...
Sind dann alle Bedingungen erfüllt das man behaupten kann:
Das Objekt wurde um A gedreht???
Ein einfaches Ja würde mir genügen  |
|
Nach oben |
|
 |
Eternal_pain

Anmeldungsdatum: 08.08.2006 Beiträge: 1783 Wohnort: BW/KA
|
Verfasst am: 28.05.2013, 23:03 Titel: |
|
|
Ja
Im Grunde hat es TPM ja schon genannt...
Code: |
tX = offsetx + (X-rotationspunktX) * cos(winkel) - (Y-rotationspunktY) * sin(winkel)
tY = offsety + (X-rotationspunktX) * sin(winkel) + (Y-rotationspunktY) * cos(winkel)
|
den offset bekommst du durch die x und y verschiebung...
sowas wie
Code: |
'pseudocode
offsetx = originalpunktx - gedrehterpunktx
offsety = originalpunkty - gedrehterpunkty
|
_________________
 |
|
Nach oben |
|
 |
Eukalyptus
Anmeldungsdatum: 17.05.2013 Beiträge: 11
|
Verfasst am: 29.05.2013, 11:38 Titel: |
|
|
Wie eine Matrix genau funktioniert, kann ich auch nicht genau erklären.
Aber ich hab etwas Erfahrung, wie man sie benutzt.
Hier mal ein Bleipiel:
Vor dem ersten Sleep wird nur rotiert.
Der Drehpunkt befindet sich oben links.
Soll sich der Drehpunkt in der Objektmitte befinden, muss man die Matrix zuerst verschieben (Sleep 2)
Code: | tMX.Translate(-70, -40)
tMX.Rotate(i) |
Dann kann man die Gewünschte Endposition bestimmen, indem man die Matrix nach dem rotieren nochmals verschiebt:
Code: | tMX.Translate(-70, -40)
tMX.Rotate(i)
tMX.Translate(iScreenW / 2, iScreenH / 2) |
Nun wird das Objekt im Objektmittelpunkt gedreht und in der Mitte des Fensters platziert.
Hier der Code: Code: | Type t_MATRIX2D
Private:
MX(9) As Double
Declare Sub Mul(pMX1 As Double Ptr, pMX2 As Double Ptr)
Declare Sub ResetP(pMX As Double Ptr)
Public:
Declare Sub GetElements(pMX As Double Ptr)
Declare Sub Invert
Declare Sub MulVector(fX As Double, fY As Double, ByRef fTX As Double, ByRef fTY As Double)
Declare Sub Reset
Declare Sub Rotate(fAngle As Double, iOrder As Integer = 0)
Declare Sub Scale(fScaleX As Double, fScaleY As Double, iOrder As Integer = 0)
Declare Sub Skew(fSkewX As Double, fSkewY As Double, iOrder As Integer = 0)
Declare Sub Translate(fTransX As Double, fTransY As Double, iOrder As Integer = 0)
Declare Constructor
End Type
Sub t_MATRIX2D.GetElements(pMX As Double Ptr)
For i As Integer = 0 To 8
pMX[i] = MX(i)
Next
End Sub
Sub t_MATRIX2D.Mul(pMX1 As Double Ptr, pMX2 As Double Ptr)
Dim As Double fS
For x As Integer = 0 To 2
For y As Integer = 0 To 2
fS = 0
For z As Integer = 0 To 2
fS += pMX1[x*3+z] * pMX2[z*3+y]
Next
MX(x*3+y) = fS
Next
Next
End Sub
Sub t_MATRIX2D.MulVector(fX As Double, fY As Double, ByRef fTX As Double, ByRef fTY As Double)
fTX = fX * MX(0) + fY * MX(3) + MX(6)
fTY = fX * MX(1) + fY * MX(4) + MX(7)
End Sub
Sub t_MATRIX2D.Invert
'[ a b 0 ]
'[ c d 0 ]
'[ x y 1 ]
't = a*d-b*c
'[ d/t -b/t 0 ]
'[ -c/t a/t 0 ]
'[(c*y-d*x)/t -(a*y-b*x)/t 1 ]
Dim As Double fM(9), fT
GetElements(@fM(0))
fT = fM(0)*fM(4)-fM(1)*fM(3)
MX(0) = fM(4)/fT
MX(1) = -fM(1)/fT
MX(3) = -fM(3)/fT
MX(4) = fM(0)/fT
MX(6) = (fM(3)*fM(7)-fM(4)*fM(6)) / fT
MX(7) = -(fM(0)*fM(7)-fM(1)*fM(6)) / fT
End Sub
Sub t_MATRIX2D.Translate(fTransX As Double, fTransY As Double, iOrder As Integer = 0)
'[ 1 0 0 ]
'[ 0 1 0 ]
'[TX TY 1 ]
Dim As Double MX1(9), MX2(9)
GetElements(@MX2(0))
ResetP(@MX1(0))
MX1(6) = fTransX
MX1(7) = fTransY
Select Case iOrder
Case 0
Mul(@MX2(0), @MX1(0))
Case Else
Mul(@MX1(0), @MX2(0))
End Select
End Sub
Sub t_MATRIX2D.Skew(fSkewX As Double, fSkewY As Double, iOrder As Integer = 0)
'[ 1 SY 0 ]
'[SX 1 0 ]
'[ 0 0 1 ]
Dim As Double MX1(9), MX2(9)
GetElements(@MX2(0))
ResetP(@MX1(0))
MX1(1) = fSkewY * 0.0174532925199433
MX1(3) = fSkewX * 0.0174532925199433
Select Case iOrder
Case 0
Mul(@MX2(0), @MX1(0))
Case Else
Mul(@MX1(0), @MX2(0))
End Select
End Sub
Sub t_MATRIX2D.Scale(fScaleX As Double, fScaleY As Double, iOrder As Integer = 0)
'[SX 0 0 ]
'[ 0 SY 0 ]
'[ 0 0 1 ]
Dim As Double MX1(9), MX2(9)
GetElements(@MX2(0))
ResetP(@MX1(0))
MX1(0) = fScaleX
MX1(4) = fScaleY
Select Case iOrder
Case 0
Mul(@MX2(0), @MX1(0))
Case Else
Mul(@MX1(0), @MX2(0))
End Select
End Sub
Sub t_MATRIX2D.Rotate(fAngle As Double, iOrder As Integer = 0)
'[ C S 0 ]
'[-S C 0 ]
'[ 0 0 1 ]
If fAngle = 0 Then Return
Dim As Double fR, fS, fC
fR = fAngle * 0.0174532925199433
fC = Cos(fR)
fS = Sin(fR)
Dim As Double MX1(9), MX2(9)
GetElements(@MX2(0))
ResetP(@MX1(0))
MX1(0) = fC
MX1(1) = fS
MX1(3) = -fS
MX1(4) = fC
Select Case iOrder
Case 0
Mul(@MX2(0), @MX1(0))
Case Else
Mul(@MX1(0), @MX2(0))
End Select
End Sub
Sub t_MATRIX2D.ResetP(pMX As Double Ptr)
'[ 1 0 0 ]
'[ 0 1 0 ]
'[ 0 0 1 ]
For i As Integer = 0 To 8
pMX[i] = 0
Next
pMX[0] = 1
pMX[4] = 1
pMX[8] = 1
End Sub
Sub t_MATRIX2D.Reset
ResetP(@MX(0))
End Sub
Constructor t_MATRIX2D
ResetP(@MX(0))
End Constructor
Sub _Clear(iColor As UInteger, iX As Integer, iY As Integer, iW As Integer, iH As Integer, iP As Integer)
Dim As Any Ptr pScreen = ScreenPtr
If pScreen = 0 Then Return
Dim As UInteger Ptr pPixel
ScreenLock()
For y As Integer = iY To iY + iH - 1
pPixel = pScreen + (y * iP) + iX * 4
For x As Integer = iX To iX + iW - 1
*pPixel = iColor
pPixel += 1
Next
Next
ScreenUnlock()
End Sub
Sub _Draw(tMX As t_MATRIX2D, pPnt As Single Ptr, iCnt As Integer)
Dim As Double fX, fY
ScreenLock()
For i As Integer = 0 To iCnt-1
tMX.MulVector(pPnt[i*2], pPnt[i*2+1], fX, fY)
Circle(fX, fY),4,&HFF00FF00,,,,F
Next
ScreenUnlock()
End Sub
Screen 14,32
Dim As Integer iScreenW, iScreenH, iPitch
ScreenInfo iScreenW, iScreenH, , , iPitch
Dim As Single aPnt(39, 1)
For y As Integer = 0 To 4
For x As Integer = 0 To 7
aPnt(y * 8 + x, 0) = x * 20
aPnt(y * 8 + x, 1) = y * 20
Next
Next
Dim As t_MATRIX2D tMX
For i As Integer = 0 To 360
tMX.Reset
tMX.Rotate(i)
_Clear(&hFF000000, 0, 0, iScreenW, iScreenH, iPitch)
_Draw(tMX, @aPnt(0, 0), 40)
Sleep(10)
Next
Sleep
For i As Integer = 0 To 360
tMX.Reset
tMX.Translate(-70, -40)
tMX.Rotate(i)
_Clear(&hFF000000, 0, 0, iScreenW, iScreenH, iPitch)
_Draw(tMX, @aPnt(0, 0), 40)
Sleep(10)
Next
Sleep
For i As Integer = 0 To 360
tMX.Reset
tMX.Translate(-70, -40)
tMX.Rotate(i)
tMX.Translate(iScreenW / 2, iScreenH / 2)
_Clear(&hFF000000, 0, 0, iScreenW, iScreenH, iPitch)
_Draw(tMX, @aPnt(0, 0), 40)
Sleep(10)
Next
Sleep
End |
Bei den einzelnen Matrixberechnungen kann man noch den Parameter "Order" angeben - Damit legt man fest, ob die ursprüngliche Matrix bei der Matrixmultiplikation auf der linken, oder rechten Seite steht.
Was das genau bewirkt, muss man einfach ausprobieren.
Das obige Programm zeigt eine Forward-Transformation - d.h.: Aus den original Koordinaten werden ganz einfach die Zielkoordinaten berechnet.
Wenn man mit dieser Methode ein Bitmap dreht, dann bekommt man ein Moiré. Einfach deswegen, weil die Zielkoordinaten nie GENAU auf einen Pixel fallen.
Wenn man dann noch skaliert entstehen zusätzlich noch Löcher im Zielbild.
Deshalb muss man ein Bitmap reversemappen - d.h.: Die Matrix wird invertiert und aus einer Zielkoordinate wird die Position im Originalbid berechnet.
Man geht also alle Zielkoordinaten durch und berechnet, welchem Pixel im Originalbild diese entsprechen.
Damit vermeidet man dann das Moiré und die Löcher.
Vielleicht zeigt dieses Programm, was ich meine:
(Evtl. etwas umständlich programmiert, aber mit der FreeBasic-Grafik kenn ich mich noch nicht gut aus. Normalerweise verwende ich immer GDI+)
Als Beispielbild verwende ich ein Bitmap aus dem Example-Ordner und liegt bei mir hier: "C:\Programme\FreeBASIC\examples\libraries\GL\NeHe\data\BG.bmp"
Diesen Pfad vorher anpassen!
Zuerst wird das Bild nur gedreht - es entsteht ein leichtes Moiré
Dann wird das Bild dedreht und vergrößert = Löcher + Moiré
Dann die Reversemapping Methode = sieht schon ganz gut aus
Zuletzt Reverse + Interpolation
Code: | Type t_MATRIX2D
Private:
MX(9) As Double
Declare Sub Mul(pMX1 As Double Ptr, pMX2 As Double Ptr)
Declare Sub ResetP(pMX As Double Ptr)
Public:
Declare Sub GetElements(pMX As Double Ptr)
Declare Sub Invert
Declare Sub MulVector(fX As Double, fY As Double, ByRef fTX As Double, ByRef fTY As Double)
Declare Sub Reset
Declare Sub Rotate(fAngle As Double, iOrder As Integer = 0)
Declare Sub Scale(fScaleX As Double, fScaleY As Double, iOrder As Integer = 0)
Declare Sub Skew(fSkewX As Double, fSkewY As Double, iOrder As Integer = 0)
Declare Sub Translate(fTransX As Double, fTransY As Double, iOrder As Integer = 0)
Declare Constructor
End Type
Sub t_MATRIX2D.GetElements(pMX As Double Ptr)
For i As Integer = 0 To 8
pMX[i] = MX(i)
Next
End Sub
Sub t_MATRIX2D.Mul(pMX1 As Double Ptr, pMX2 As Double Ptr)
Dim As Double fS
For x As Integer = 0 To 2
For y As Integer = 0 To 2
fS = 0
For z As Integer = 0 To 2
fS += pMX1[x*3+z] * pMX2[z*3+y]
Next
MX(x*3+y) = fS
Next
Next
End Sub
Sub t_MATRIX2D.MulVector(fX As Double, fY As Double, ByRef fTX As Double, ByRef fTY As Double)
fTX = fX * MX(0) + fY * MX(3) + MX(6)
fTY = fX * MX(1) + fY * MX(4) + MX(7)
End Sub
Sub t_MATRIX2D.Invert
'[ a b 0 ]
'[ c d 0 ]
'[ x y 1 ]
't = a*d-b*c
'[ d/t -b/t 0 ]
'[ -c/t a/t 0 ]
'[(c*y-d*x)/t -(a*y-b*x)/t 1 ]
Dim As Double fM(9), fT
GetElements(@fM(0))
fT = fM(0)*fM(4)-fM(1)*fM(3)
MX(0) = fM(4)/fT
MX(1) = -fM(1)/fT
MX(3) = -fM(3)/fT
MX(4) = fM(0)/fT
MX(6) = (fM(3)*fM(7)-fM(4)*fM(6)) / fT
MX(7) = -(fM(0)*fM(7)-fM(1)*fM(6)) / fT
End Sub
Sub t_MATRIX2D.Translate(fTransX As Double, fTransY As Double, iOrder As Integer = 0)
'[ 1 0 0 ]
'[ 0 1 0 ]
'[TX TY 1 ]
Dim As Double MX1(9), MX2(9)
GetElements(@MX2(0))
ResetP(@MX1(0))
MX1(6) = fTransX
MX1(7) = fTransY
Select Case iOrder
Case 0
Mul(@MX2(0), @MX1(0))
Case Else
Mul(@MX1(0), @MX2(0))
End Select
End Sub
Sub t_MATRIX2D.Skew(fSkewX As Double, fSkewY As Double, iOrder As Integer = 0)
'[ 1 SY 0 ]
'[SX 1 0 ]
'[ 0 0 1 ]
Dim As Double MX1(9), MX2(9)
GetElements(@MX2(0))
ResetP(@MX1(0))
MX1(1) = fSkewY * 0.0174532925199433
MX1(3) = fSkewX * 0.0174532925199433
Select Case iOrder
Case 0
Mul(@MX2(0), @MX1(0))
Case Else
Mul(@MX1(0), @MX2(0))
End Select
End Sub
Sub t_MATRIX2D.Scale(fScaleX As Double, fScaleY As Double, iOrder As Integer = 0)
'[SX 0 0 ]
'[ 0 SY 0 ]
'[ 0 0 1 ]
Dim As Double MX1(9), MX2(9)
GetElements(@MX2(0))
ResetP(@MX1(0))
MX1(0) = fScaleX
MX1(4) = fScaleY
Select Case iOrder
Case 0
Mul(@MX2(0), @MX1(0))
Case Else
Mul(@MX1(0), @MX2(0))
End Select
End Sub
Sub t_MATRIX2D.Rotate(fAngle As Double, iOrder As Integer = 0)
'[ C S 0 ]
'[-S C 0 ]
'[ 0 0 1 ]
If fAngle = 0 Then Return
Dim As Double fR, fS, fC
fR = fAngle * 0.0174532925199433
fC = Cos(fR)
fS = Sin(fR)
Dim As Double MX1(9), MX2(9)
GetElements(@MX2(0))
ResetP(@MX1(0))
MX1(0) = fC
MX1(1) = fS
MX1(3) = -fS
MX1(4) = fC
Select Case iOrder
Case 0
Mul(@MX2(0), @MX1(0))
Case Else
Mul(@MX1(0), @MX2(0))
End Select
End Sub
Sub t_MATRIX2D.ResetP(pMX As Double Ptr)
'[ 1 0 0 ]
'[ 0 1 0 ]
'[ 0 0 1 ]
For i As Integer = 0 To 8
pMX[i] = 0
Next
pMX[0] = 1
pMX[4] = 1
pMX[8] = 1
End Sub
Sub t_MATRIX2D.Reset
ResetP(@MX(0))
End Sub
Constructor t_MATRIX2D
ResetP(@MX(0))
End Constructor
Sub _Clear(iColor As UInteger, iX As Integer, iY As Integer, iW As Integer, iH As Integer, iP As Integer)
Dim As Any Ptr pScreen = ScreenPtr
If pScreen = 0 Then Return
Dim As UInteger Ptr pPixel
ScreenLock()
For y As Integer = iY To iY + iH - 1
pPixel = pScreen + (y * iP) + iX * 4
For x As Integer = iX To iX + iW - 1
*pPixel = iColor
pPixel += 1
Next
Next
ScreenUnlock()
End Sub
Type t_IMAGE
iHeader As UInteger
iBPP As UInteger
iWidth As UInteger
iHeight As UInteger
iPitch As UInteger
aUnused(2) As UInteger
pPixel As UInteger Ptr
End Type
Sub _ForwardMapping(tMX As t_MATRIX2D, pImage As t_IMAGE Ptr, iScreenW As Integer, iScreenH As Integer, iPitch As Integer)
Dim As UInteger Ptr pScreen = ScreenPtr
If pScreen = 0 Then Return
Dim As UInteger Ptr pPixel = @pImage->pPixel
Dim As Integer iBmpW = pImage->iWidth, iBmpH = pImage->iHeight, iBmpP = pImage->iPitch / 4
iPitch /= 4
Dim As Double fX, fY
Dim As Integer iX, iY
ScreenLock()
For y As Integer = 0 To iBmpH-1
For x As Integer = 0 To iBmpW-1
tMX.MulVector(x, y, fX, fY)
iX = fX
iY = fY
If (iX >= 0) And (iY >= 0) And (iX < iScreenW) And (iY < iScreenH) Then
pScreen[iY * iPitch + iX] = pPixel[y * iBmpP + x]
EndIf
Next
Next
ScreenUnlock()
End Sub
Sub _ReverseMapping(tMX As t_MATRIX2D, pImage As t_IMAGE Ptr, iScreenW As Integer, iScreenH As Integer, iPitch As Integer)
Dim As UInteger Ptr pScreen = ScreenPtr
If pScreen = 0 Then Return
Dim As UInteger Ptr pPixel = @pImage->pPixel
Dim As Integer iBmpW = pImage->iWidth, iBmpH = pImage->iHeight, iBmpP = pImage->iPitch / 4
iPitch /= 4
Dim As Double aPnt(4, 2)
tMX.MulVector(0, 0, aPnt(0,0), aPnt(0,1))
tMX.MulVector(iBmpW, 0, aPnt(1,0), aPnt(1,1))
tMX.MulVector(0, iBmpH, aPnt(2,0), aPnt(2,1))
tMX.MulVector(iBmpW, iBmpH, aPnt(3,0), aPnt(3,1))
Dim As Integer iX1, iY1, iX2, iY2
iX1 = iScreenW
iY1 = iScreenH
iX2 = 0
iY2 = 0
For i As Integer = 0 To 3
If aPnt(i, 0) < iX1 Then iX1 = aPnt(i, 0)
If aPnt(i, 0) > iX2 Then iX2 = aPnt(i, 0)
If aPnt(i, 1) < iY1 Then iY1 = aPnt(i, 1)
If aPnt(i, 1) > iY2 Then iY2 = aPnt(i, 1)
Next
If iX1 < 0 Then
iX1 = 0
ElseIf iX1 >= iScreenW Then
iX1 = iScreenW-1
EndIf
If iX2 < 0 Then
iX2 = 0
ElseIf iX2 >= iScreenW Then
iX2 = iScreenW-1
EndIf
If iY1 < 0 Then
iY1 = 0
ElseIf iY1 >= iScreenH Then
iY1 = iScreenH-1
EndIf
If iY2 < 0 Then
iY2 = 0
ElseIf iY2 >= iScreenH Then
iY2 = iScreenH-1
EndIf
tMX.Invert
Dim As Double fX, fY
Dim As Integer iX, iY
ScreenLock()
For x As Integer = iX1 To iX2
For y As Integer = iY1 To iY2
tMX.MulVector(x, y, fX, fY)
iX = fX
iY = fY
If (iX >= 0) And (iY >= 0) And (iX < iBmpW) And (iY < iBmpH) Then
pScreen[y * iPitch + x] = pPixel[iY * iBmpP + iX]
EndIf
Next
Next
ScreenUnlock()
End Sub
Type t_ARGB
B As UByte
G As UByte
R As UByte
A As UByte
End Type
Sub _ReverseMapping_Interpolate(tMX As t_MATRIX2D, pImage As t_IMAGE Ptr, iScreenW As Integer, iScreenH As Integer, iPitch As Integer)
Dim As UInteger Ptr pScreen = ScreenPtr
If pScreen = 0 Then Return
Dim As UInteger Ptr pPixel = @pImage->pPixel
Dim As Integer iBmpW = pImage->iWidth, iBmpH = pImage->iHeight, iBmpP = pImage->iPitch / 4
iPitch /= 4
Dim As Double aPnt(4, 2)
tMX.MulVector(0, 0, aPnt(0,0), aPnt(0,1))
tMX.MulVector(iBmpW, 0, aPnt(1,0), aPnt(1,1))
tMX.MulVector(0, iBmpH, aPnt(2,0), aPnt(2,1))
tMX.MulVector(iBmpW, iBmpH, aPnt(3,0), aPnt(3,1))
Dim As Integer iX1, iY1, iX2, iY2
iX1 = iScreenW
iY1 = iScreenH
iX2 = 0
iY2 = 0
For i As Integer = 0 To 3
If aPnt(i, 0) < iX1 Then iX1 = aPnt(i, 0)
If aPnt(i, 0) > iX2 Then iX2 = aPnt(i, 0)
If aPnt(i, 1) < iY1 Then iY1 = aPnt(i, 1)
If aPnt(i, 1) > iY2 Then iY2 = aPnt(i, 1)
Next
If iX1 < 0 Then
iX1 = 0
ElseIf iX1 >= iScreenW Then
iX1 = iScreenW-1
EndIf
If iX2 < 0 Then
iX2 = 0
ElseIf iX2 >= iScreenW Then
iX2 = iScreenW-1
EndIf
If iY1 < 0 Then
iY1 = 0
ElseIf iY1 >= iScreenH Then
iY1 = iScreenH-1
EndIf
If iY2 < 0 Then
iY2 = 0
ElseIf iY2 >= iScreenH Then
iY2 = iScreenH-1
EndIf
tMX.Invert
Dim As Double fX, fY
Dim As Integer iSX, iSY
Dim As Single fFX, fFY, fFX1, fFY1
Dim As UInteger aColor(2, 2)
Dim As t_ARGB Ptr aARGB(2, 2)
For iX As Integer = 0 To 1
For iY As Integer = 0 To 1
aARGB(iX, iY) = @aColor(iX, iY)
Next
Next
ScreenLock()
For x As Integer = iX1 To iX2
For y As Integer = iY1 To iY2
tMX.MulVector(x, y, fX, fY)
If (fX >= 0) And (fY >= 0) And (fX < iBmpW) And (fY < iBmpH) Then
iSX = Int(fX)
iSY = Int(fY)
fFX = Frac(fX)
fFY = Frac(fY)
For iLX As Integer = iSX To iSX + 1
For iLY As Integer = iSY To iSY + 1
If (iLX < 0) Or (iLY < 0) Or (iLX >= iBmpW) Or (iLY >= iBmpH) Then
aColor(iLX - iSX, iLY - iSY) = 0
Else
aColor(iLX - iSX, iLY - iSY) = pPixel[iLY * iBmpP + iLX]
EndIf
Next
Next
fFX1 = 1 - fFX
fFY1 = 1 - fFY
'Interpolate X aColor(0, 0) <-> aColor(1, 0)
aARGB(0, 0)->A = aARGB(0, 0)->A * fFX1 + aARGB(1, 0)->A * fFX
aARGB(0, 0)->R = aARGB(0, 0)->R * fFX1 + aARGB(1, 0)->R * fFX
aARGB(0, 0)->G = aARGB(0, 0)->G * fFX1 + aARGB(1, 0)->G * fFX
aARGB(0, 0)->B = aARGB(0, 0)->B * fFX1 + aARGB(1, 0)->B * fFX
'Interpolate X aColor(0, 1) <-> aColor(1, 1)
aARGB(0, 1)->A = aARGB(0, 1)->A * fFX1 + aARGB(1, 1)->A * fFX
aARGB(0, 1)->R = aARGB(0, 1)->R * fFX1 + aARGB(1, 1)->R * fFX
aARGB(0, 1)->G = aARGB(0, 1)->G * fFX1 + aARGB(1, 1)->G * fFX
aARGB(0, 1)->B = aARGB(0, 1)->B * fFX1 + aARGB(1, 1)->B * fFX
'Interpolate Y aColor(0, 0) <-> aColor(0, 1)
aARGB(0, 0)->A = aARGB(0, 0)->A * fFY1 + aARGB(0, 1)->A * fFY
aARGB(0, 0)->R = aARGB(0, 0)->R * fFY1 + aARGB(0, 1)->R * fFY
aARGB(0, 0)->G = aARGB(0, 0)->G * fFY1 + aARGB(0, 1)->G * fFY
aARGB(0, 0)->B = aARGB(0, 0)->B * fFY1 + aARGB(0, 1)->B * fFY
pScreen[y * iPitch + x] = aColor(0, 0)
EndIf
Next
Next
ScreenUnlock()
End Sub
Screen 19,32
Dim As String sFileName = "C:\Programme\FreeBASIC\examples\libraries\GL\NeHe\data\BG.bmp"
Dim As Integer iBmpW, iBmpH, iScreenW, iScreenH, iPitch
ScreenInfo iScreenW, iScreenH, , , iPitch
Dim As Integer iFile = FreeFile
Open sFileName For Input As #iFile
Get #iFile, 19, iBmpW
Get #iFile, 23, iBmpH
Close #iFile
Dim pImg As Any Ptr
pImg = ImageCreate(iBmpW, iBmpH)
Bload sFileName, pImg
Dim As t_MATRIX2D tMX
tMX.Translate(-iBmpW/2, -iBmpH/2)
tMX.Rotate(45)
tMX.Translate(iScreenW/2, iScreenH/2)
_Clear(&hFF000000, 0, 0, iScreenW, iScreenH, iPitch)
_ForwardMapping(tMX, pImg, iScreenW, iScreenH, iPitch)
Sleep
tMX.Reset
tMX.Translate(-iBmpW/2, -iBmpH/2)
tMX.Scale(5, 5)
tMX.Rotate(10)
tMX.Translate(iScreenW/2, iScreenH/2)
_Clear(&hFF000000, 0, 0, iScreenW, iScreenH, iPitch)
_ForwardMapping(tMX, pImg, iScreenW, iScreenH, iPitch)
Sleep
tMX.Reset
tMX.Translate(-iBmpW/2, -iBmpH/2)
tMX.Scale(5, 5)
tMX.Rotate(10)
tMX.Translate(iScreenW/2, iScreenH/2)
_Clear(&hFF000000, 0, 0, iScreenW, iScreenH, iPitch)
_ReverseMapping(tMX, pImg, iScreenW, iScreenH, iPitch)
Sleep
tMX.Reset
tMX.Translate(-iBmpW/2, -iBmpH/2)
tMX.Scale(5, 5)
tMX.Rotate(10)
tMX.Translate(iScreenW/2, iScreenH/2)
_Clear(&hFF000000, 0, 0, iScreenW, iScreenH, iPitch)
_ReverseMapping_Interpolate(tMX, pImg, iScreenW, iScreenH, iPitch)
Sleep
If pImg <> 0 Then ImageDestroy(pImg)
End |
|
|
Nach oben |
|
 |
Muttonhead

Anmeldungsdatum: 26.08.2008 Beiträge: 565 Wohnort: Jüterbog
|
Verfasst am: 30.05.2013, 19:32 Titel: |
|
|
@Eukalyptus: UI.... das ist ein Brett...
Also ich bedank mich mal artig bei allen und betrachte mein Problem als
gelöst
Da mein Ergebnis sehr fragwürdig ist werd ich mich wohl doch auf Fremdcode verlassen, was in meinem Fall das beste ist
Code: |
'definitely inspired by D.J.Peters'>>Multiput<<
'original code at: http://www.freebasic.net/forum/viewtopic.php?f=8&t=19303
#include "fbgfx.bi"
using FB
'******************************************************************************
type vector
x as double
y as double
end type
'******************************************************************************
declare sub RotPut(img as any ptr,posx as integer,posy as integer, pivotx as integer=0, pivoty as integer=0, arcus as double)
sub RotPut(img as any ptr,posx as integer,posy as integer, pivotx as integer=0, pivoty as integer=0, arcus as double)
'posx,posy Position,es gilt Koordinatensystem Screen
'pivotx,pivoty Drehpunkt als Offset von Pixel(0,0) links oben, es gilt Koordinatensystem Screen
dim as integer imgw,imgh 'Größe Originalimage
dim as integer xmin,xmax,ymin,ymax 'Größenermittlung temporäres Image
dim as any ptr imgtmp 'temporäres Image
dim as integer imgtmpw,imgtmph 'Größe temp. Image
dim as double x,y 'Hilfsvariablen
dim as integer ii,kk
dim as vector Points(6) 'Punkte und Vektoren
dim as uinteger pixelcolor 'Farbwert
dim as uinteger ptr pixaddr,pixaddrtmp 'Adressen der Pixel
dim as Image ptr header,headertmp 'um an die Daten im Imageheader zu kommen
header=img
imgw=header->width
imgh=header->height
'Verortung Originalimage, Pixel (0,0) ist im Koordinatenursprung und braucht nicht berechnet zu werden
Points(1).x=0
Points(1).y=-imgh
Points(2).x=imgw
Points(2).y=-imgh
Points(3).x=imgw
Points(3).y=0
Points(4).x=pivotx 'gewünschter Drehpunkt
Points(4).y=-pivoty 'Anpassung an kartesisches Koordinatensystem
'Origalimage Eckpunkte drehen um Größe und Lage des temp Images zu ermitteln
for i as integer=1 to 4
if i<4 then
x= Points(i).x * cos(arcus) - Points(i).y * sin(arcus)
y= Points(i).x * sin(arcus) + Points(i).y * cos(arcus)
Points(i).x= x
Points(i).y= y
if x<xmin then xmin=x
if x>xmax then xmax=x
if y<ymin then ymin=y
if y>ymax then ymax=y
else
Points(5).x= Points(i).x * cos(arcus) - Points(i).y * sin(arcus)
Points(5).y= Points(i).x * sin(arcus) + Points(i).y * cos(arcus)
end if
next i
'Verschiebung berechnen
Points(6).x= Points(4).x - Points(5).x
Points(6).y= Points(4).y - Points(5).y
Points(0).x=xmin 'Position linke obere Ecke des temp. Images
Points(0).y=ymax
Points(1).x=1 'Zeilenvektor
Points(1).y=0
Points(2).x=0 'Spaltenvektor
Points(2).y=-1
for i as integer=0 to 2
if i>0 then
x= Points(i).x * cos(-arcus) - Points(i).y * sin(-arcus)
y= Points(i).x * sin(-arcus) + Points(i).y * cos(-arcus)
Points(i).x= x
Points(i).y= y
else
Points(3).x= Points(i).x * cos(-arcus) - Points(i).y * sin(-arcus)
Points(3).y= Points(i).x * sin(-arcus) + Points(i).y * cos(-arcus)
end if
next i
'temp. Image erzeugen
imgtmpw=xmax-xmin
imgtmph=ymax-ymin
imgtmp=imagecreate(imgtmpw,imgtmph,&HFF00FF)
if imgtmp then
headertmp=imgtmp
'Scan
dim as integer switch=0
for k as integer=0 to imgtmph-1
for i as integer=0 to imgtmpw-1
ii=int(Points(3).x + Points(1).x*i + Points(2).x*k)
kk=int(Points(3).y + Points(1).y*i + Points(2).y*k)
if (ii>=0) and (ii<imgw-1) and (kk<=0) and (kk>-imgh+1) then
'pset imgtmp,(i,k),point(ii,-kk,img)'<---- Flaschenhals!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
'dies ist schneller.....
pixaddr=img + 32 + (-kk * header->pitch) + (ii * header->bpp)
pixaddrtmp=imgtmp + 32 + (k * headertmp->pitch) + (i * headertmp->bpp)
*pixaddrtmp=*pixaddr
end if
next i
next k
put (posx + Points(0).x + Points(6).x,posy - Points(0).y - Points(6).y),imgtmp,trans
imagedestroy imgtmp
end if
end sub
'******************************************************************************
'******************************************************************************
'******************************************************************************
screen 19,32
'Originalimage
dim img as any ptr'Image
img=imagecreate(400,300)
if img then
bload "pattern.bmp",img
for arcus as double=0 to 6.28 step .01
screenlock
cls
RotPut(img,300,200,200,150,arcus)
screenunlock
sleep 2
next arcus
imagedestroy img
end if
sleep
end
|
edit: Code korrigiert
edit2: Flaschenhals entfernt, Farbwert wird direkt von einem Image ins andere kopiert... bedeutend schneller
Mutton |
|
Nach oben |
|
 |
|
|
Du kannst keine Beiträge in dieses Forum schreiben. Du kannst auf Beiträge in diesem Forum nicht antworten. Du kannst deine Beiträge in diesem Forum nicht bearbeiten. Du kannst deine Beiträge in diesem Forum nicht löschen. Du kannst an Umfragen in diesem Forum nicht mitmachen.
|
|