TurnArray2d() - 2D-Array um 90, 180 und 270 Grad drehen

Hier könnt Ihr gute, von Euch geschriebene Codes posten. Sie müssen auf jeden Fall funktionieren und sollten möglichst effizient, elegant und beispielhaft oder einfach nur cool sein.
Kekskiller
Beiträge: 752
Registriert: 14.09.2004 21:39
Kontaktdaten:

TurnArray2d() - 2D-Array um 90, 180 und 270 Grad drehen

Beitrag von Kekskiller »

Mit freundlicher Unterstützung von Kaeru Gaman ist es mir gelungen, meinen Code zu korrigieren. Mit dieser Funktion kann man ein 2dimensionales Array drehen. Funktioniert bei mir auch prima mit Strukturen


Grundvoraussetzungen:
Breite = Höhe
2 Dimensionen


Benutzung:
TurnArray2D(Array-Adresse, Größe der Array-Struktur, Breite des Arrays, Rotationstyp)
TurnArray2D_90(Array-Adresse, Größe der Array-Struktur, Breite des Arrays)
TurnArray2D_180(Array-Adresse, Größe der Array-Struktur, Breite des Arrays)
TurnArray2D_270(Array-Adresse, Größe der Array-Struktur, Breite des Arrays)

Code: Alles auswählen

Enumeration
  #TA2D_DEGREE_0
  #TA2D_DEGREE_90
  #TA2D_DEGREE_180
  #TA2D_DEGREE_270
EndEnumeration

CompilerIf Defined(__TA2D_XY, #PB_Structure) = 0
  Structure __TA2D_XY
    X.l
    Y.l
  EndStructure
CompilerEndIf

CompilerIf Defined(__TA2D_last_strucsize, #PB_Variable) = 0
  Global __TA2D_last_strucsize.l
CompilerEndIf

CompilerIf Defined(*__TA2D_buffer, #PB_Variable) = 0
  Global *__TA2D_buffer
CompilerEndIf

Procedure TurnArray2D(*array, strucsize.l, width.l, flag.b)
  Protected Ring.l
  Protected Cell.l
  Protected linesize.l
  Protected *A1
  Protected *A2
  Protected *A3
  Protected *A4
  Protected P.__TA2D_XY
  Protected RingRange.l
  Protected LineWidth.l
  
  linesize = strucsize * width
  
  If strucsize <> __TA2D_last_strucsize
    ;Debug "changed __TA2D_last_strucsize from " + Str(__TA2D_last_strucsize) + " to " + Str(strucsize)
    *__TA2D_buffer = AllocateMemory(strucsize)
    __TA2D_last_strucsize = strucsize
  EndIf
  
  RingRange = width / 2 - 1
  LineWidth = width - 1
  
  For Ring = 0 To RingRange;nur bis zur Hälfte durchgehen
    
    ;ring-ecken vorberechnen
    P\X = Ring
    P\Y = Ring + LineWidth
    
    *A1 = *array + P\X * linesize + P\X * strucsize
    *A2 = *array + P\X * linesize + P\Y * strucsize
    *A3 = *array +  P\Y * linesize + P\Y * strucsize
    *A4 = *array +  P\Y * linesize + P\X * strucsize
    
    ;{Ursprüngliche Vorberechnung (zum Verständnis) <- falls eigene änderung, diesen code als vorlage nehmen!
    ; P1\X = Ring
    ; P1\Y = Ring
    ; P1\Z = *array +  P1\Y * linesize + P1\X * strucsize
    ; 
    ; P2\X = Ring + LineWidth
    ; P2\Y = Ring
    ; P2\Z = *array +  P2\Y * linesize + P2\X * strucsize
    ; 
    ; P3\X = Ring + LineWidth
    ; P3\Y = Ring + LineWidth
    ; P3\Z = *array +  P3\Y * linesize + P3\X * strucsize
    ; 
    ; P4\X = Ring
    ; P4\Y = Ring + LineWidth
    ; P4\Z = *array +  P4\Y * linesize + P4\X * strucsize
    ;}
    
    For Cell = 0 To LineWidth-1
      
      ;im gegensatz zu vorheriger version wird hier jede zelle einfach nur + "dazugerechnet"
      *A1 + strucsize
      *A2 + linesize
      *A3 - strucsize
      *A4 - linesize
      
      ;neubeschreiben
      Select flag
        Case #TA2D_DEGREE_90
          CopyMemory(*A1, *__TA2D_buffer, strucsize);PUFFER
          CopyMemory(*A2, *A1, strucsize)
          CopyMemory(*A3, *A2, strucsize)
          CopyMemory(*A4, *A3, strucsize)
          CopyMemory(*__TA2D_buffer, *A4, strucsize)
        Case #TA2D_DEGREE_180
          CopyMemory(*A1, *__TA2D_buffer, strucsize);PUFFER
          CopyMemory(*A3, *A1, strucsize)
          CopyMemory(*__TA2D_buffer, *A3, strucsize)
          CopyMemory(*A4, *__TA2D_buffer, strucsize);PUFFER
          CopyMemory(*A2, *A4, strucsize)
          CopyMemory(*__TA2D_buffer, *A2, strucsize)
        Case #TA2D_DEGREE_270
          CopyMemory(*A1, *__TA2D_buffer, strucsize);PUFFER
          CopyMemory(*A4, *A1, strucsize)
          CopyMemory(*A3, *A4, strucsize)
          CopyMemory(*A2, *A3, strucsize)
          CopyMemory(*__TA2D_buffer, *A2, strucsize)
      EndSelect
      
    Next
    LineWidth - 2 ;pro Ring zwei weniger vom Ursprung
  Next
EndProcedure

Procedure TurnArray2D_90(*array, strucsize.l, width.l)
  Protected Ring.l
  Protected Cell.l
  Protected linesize.l
  Protected *A1
  Protected *A2
  Protected *A3
  Protected *A4
  Protected P.__TA2D_XY
  Protected RingRange.l
  Protected LineWidth.l
  
  linesize = strucsize * width
  
  If strucsize <> __TA2D_last_strucsize
    *__TA2D_buffer = AllocateMemory(strucsize)
    __TA2D_last_strucsize = strucsize
  EndIf
  
  RingRange = width / 2 - 1
  LineWidth = width - 1
  
  For Ring = 0 To RingRange
    
    P\X = Ring
    P\Y = Ring + LineWidth
    
    *A1 = *array + P\X * linesize + P\X * strucsize
    *A2 = *array + P\X * linesize + P\Y * strucsize
    *A3 = *array +  P\Y * linesize + P\Y * strucsize
    *A4 = *array +  P\Y * linesize + P\X * strucsize
    
    For Cell = 0 To LineWidth-1
      
      *A1 + strucsize
      *A2 + linesize
      *A3 - strucsize
      *A4 - linesize
      
      CopyMemory(*A1, *__TA2D_buffer, strucsize)
      CopyMemory(*A2, *A1, strucsize)
      CopyMemory(*A3, *A2, strucsize)
      CopyMemory(*A4, *A3, strucsize)
      CopyMemory(*__TA2D_buffer, *A4, strucsize)
      
    Next
    LineWidth - 2
  Next
EndProcedure

Procedure TurnArray2D_180(*array, strucsize.l, width.l)
  Protected Ring.l
  Protected Cell.l
  Protected linesize.l
  Protected *A1
  Protected *A2
  Protected *A3
  Protected *A4
  Protected P.__TA2D_XY
  Protected RingRange.l
  Protected LineWidth.l
  
  linesize = strucsize * width
  
  If strucsize <> __TA2D_last_strucsize
    *__TA2D_buffer = AllocateMemory(strucsize)
    __TA2D_last_strucsize = strucsize
  EndIf
  
  RingRange = width / 2 - 1
  LineWidth = width - 1
  
  For Ring = 0 To RingRange
    
    P\X = Ring
    P\Y = Ring + LineWidth
    
    *A1 = *array + P\X * linesize + P\X * strucsize
    *A2 = *array + P\X * linesize + P\Y * strucsize
    *A3 = *array +  P\Y * linesize + P\Y * strucsize
    *A4 = *array +  P\Y * linesize + P\X * strucsize
    
    For Cell = 0 To LineWidth-1
      
      *A1 + strucsize
      *A2 + linesize
      *A3 - strucsize
      *A4 - linesize
      
      CopyMemory(*A1, *__TA2D_buffer, strucsize)
      CopyMemory(*A3, *A1, strucsize)
      CopyMemory(*__TA2D_buffer, *A3, strucsize)
      CopyMemory(*A4, *__TA2D_buffer, strucsize)
      CopyMemory(*A2, *A4, strucsize)
      CopyMemory(*__TA2D_buffer, *A2, strucsize)
      
    Next
    LineWidth - 2 
  Next
EndProcedure

Procedure TurnArray2D_270(*array, strucsize.l, width.l)
  Protected Ring.l
  Protected Cell.l
  Protected linesize.l
  Protected *A1
  Protected *A2
  Protected *A3
  Protected *A4
  Protected P.__TA2D_XY
  Protected RingRange.l
  Protected LineWidth.l
  
  linesize = strucsize * width
  
  If strucsize <> __TA2D_last_strucsize
    *__TA2D_buffer = AllocateMemory(strucsize)
    __TA2D_last_strucsize = strucsize
  EndIf
  
  RingRange = width / 2 - 1
  LineWidth = width - 1
  
  For Ring = 0 To RingRange
    
    P\X = Ring
    P\Y = Ring + LineWidth
    
    *A1 = *array + P\X * linesize + P\X * strucsize
    *A2 = *array + P\X * linesize + P\Y * strucsize
    *A3 = *array +  P\Y * linesize + P\Y * strucsize
    *A4 = *array +  P\Y * linesize + P\X * strucsize
    
    For Cell = 0 To LineWidth-1
      
      *A1 + strucsize
      *A2 + linesize
      *A3 - strucsize
      *A4 - linesize
      
      CopyMemory(*A1, *__TA2D_buffer, strucsize)
      CopyMemory(*A4, *A1, strucsize)
      CopyMemory(*A3, *A4, strucsize)
      CopyMemory(*A2, *A3, strucsize)
      CopyMemory(*__TA2D_buffer, *A2, strucsize)
      
    Next
    LineWidth - 2
  Next
EndProcedure


;#############################
;# HIER BEGINNT DAS BEISPIEL #
;#############################

;initialisieren
OpenConsole()
ConsoleTitle("TurnArray2D example!")
ConsoleCursor(0)
EnableGraphicalConsole(#True)

Global Dim feld.b(4,4)
Restore fielddat

Macro printit(ymul)
  For zy = 0 To 4
    For zx = 0 To 4
      ConsoleLocate(zx, zy + ymul * 6)
      Print(Chr(feld(zx,zy)))
    Next
  Next
EndMacro

;einlesen
For zy = 0 To 4
  For zx = 0 To 4
    Read feld(zx,zy)
  Next
Next

;ausgeben
printit(0)
TurnArray2D_90(@feld(0,0), SizeOf(Byte), 5)
printit(1)
TurnArray2D_180(@feld(0,0), SizeOf(Byte), 5)
printit(2)
TurnArray2D_270(@feld(0,0), SizeOf(Byte), 5)
printit(3)
Input()

DataSection
  fielddat:
    Data.b 3,     3, 178,   4,   4
    Data.b 3,     3, 178,   4,   4
    Data.b 178, 178, 178, 178, 178
    Data.b 6,     6, 178,   5,   5
    Data.b 6,     6, 178,   5,   5
EndDataSection
ACHTUNG: DREHUNG ERFOLGT IM UHRZEIGERSINN
Zuletzt geändert von Kekskiller am 30.10.2006 19:27, insgesamt 2-mal geändert.
Benutzeravatar
AndyX
Beiträge: 1272
Registriert: 17.12.2004 20:10
Wohnort: Niederösterreich
Kontaktdaten:

Beitrag von AndyX »

Cool!

Damit könnte man z.B. Bilder drehen :)
Kannst du das auch mit den zwischenliegenden Winkeln machen? also z.b. 62°, 160°, etc... ?
Benutzeravatar
Deeem2031
Beiträge: 1232
Registriert: 29.08.2004 00:16
Wohnort: Vorm Computer
Kontaktdaten:

Beitrag von Deeem2031 »

Bei "schiefen" Winkeln könnte man doch keine eindeutige Zuorndung mehr machen. Bei Bilder mag das ja noch sinnvoll sein, aber bei Arrays die andere Daten enthalten..?
Bild
[url=irc://irc.freenode.org/##purebasic.de]irc://irc.freenode.org/##purebasic.de[/url]
Kekskiller
Beiträge: 752
Registriert: 14.09.2004 21:39
Kontaktdaten:

Beitrag von Kekskiller »

Hm... Das wäre ein vollkommen anderer Algho ;) . Ich vertausche hier ja nur jeweils 4 "Ecken" des Arrays, also es ist speziell auf diese 90° Rotation ausgelegt. Aber cool wäre es schon, wenn man das auch mit "unkonformen" Gradwerten machen könnte. Nur eine einfache Rotation würde zu einem Stack Overflow führen. In abgeänderter Fassung würde z.b. das Array dann so aussehen:

VOR Rotation:

Code: Alles auswählen

1122
1122
4433
4433
NACH 45°-Rotation

Code: Alles auswählen

2113
1122
4331
3344
Also etwas verschoben, so dass ein "unbegrenztes Array" rotiert wird. Schlecht zu beschreiben, aber an den durch unkonforme Rotation entstandenen "Freiflächen" würde dann dass Array wiederholt werden, so könnte man z.b. innerhalb des rechteckigen Bereiches eines Bildes rotieren, ohne die Grundform zu ändern.

Interessanter Gedanke, aber erscheint mir etwas zu viel Arbeit, nur für ne Spielerei :) .
Kekskiller
Beiträge: 752
Registriert: 14.09.2004 21:39
Kontaktdaten:

Beitrag von Kekskiller »

Update: Berechnung jetzt noch fixer!

Code: Alles auswählen

Enumeration
  #TA2D_DEGREE_0
  #TA2D_DEGREE_90
  #TA2D_DEGREE_180
  #TA2D_DEGREE_270
EndEnumeration

CompilerIf Defined(TA2D_XYZ, #PB_Structure) = 0
  Structure TA2D_XYZ
    X.l
    Y.l
    Z.l
  EndStructure
CompilerEndIf

Procedure TurnArray2D(*array, strucsize, width.l, flag.b)
  Protected Ring.l
  Protected Cell.l
  Protected linesize.l
  Protected P1.TA2D_XYZ
  Protected P2.TA2D_XYZ
  Protected P3.TA2D_XYZ
  Protected P4.TA2D_XYZ
  Protected *buffer1
  Protected *buffer2
  Protected *buffer3
  Protected *buffer4
  Protected RingRange.l
  Protected LineWidth.l
  
  linesize = strucsize * width
  
  *buffer1 = AllocateMemory(strucsize)
  *buffer2 = AllocateMemory(strucsize)
  *buffer3 = AllocateMemory(strucsize)
  *buffer4 = AllocateMemory(strucsize)
  
  RingRange = width / 2 - 1
  LineWidth = width - 1
  
  For Ring = 0 To RingRange;nur bis zur Hälfte durchgehen
    
    ;ring-ecken vorberechnen
    P1\X = Ring
    P1\Y = Ring
    P1\Z = *array +  P1\Y * linesize + P1\X * strucsize
    
    P2\X = Ring + LineWidth
    P2\Y = Ring
    P2\Z = *array +  P2\Y * linesize + P2\X * strucsize
    
    P3\X = Ring + LineWidth
    P3\Y = Ring + LineWidth
    P3\Z = *array +  P3\Y * linesize + P3\X * strucsize
    
    P4\X = Ring
    P4\Y = Ring + LineWidth
    P4\Z = *array +  P4\Y * linesize + P4\X * strucsize
    
    For Cell = 0 To LineWidth-1
      
      ;im gegensatz zu vorheriger version wird hier jede zelle einfach nur + "dazugerechnet"
      P1\Z + strucsize
      P2\Z + linesize
      P3\Z - strucsize
      P4\Z - linesize
      
      ;zwischenpuffern
      CopyMemory(P1\Z, *buffer1, strucsize)
      CopyMemory(P2\Z, *buffer2, strucsize)
      CopyMemory(P3\Z, *buffer3, strucsize)
      CopyMemory(P4\Z, *buffer4, strucsize)
      
      ;neubeschreiben
      Select flag
        Case #TA2D_DEGREE_90
          CopyMemory(*buffer2, P1\Z, strucsize)
          CopyMemory(*buffer3, P2\Z, strucsize)
          CopyMemory(*buffer4, P3\Z, strucsize)
          CopyMemory(*buffer1, P4\Z, strucsize)
        Case #TA2D_DEGREE_180
          CopyMemory(*buffer3, P1\Z, strucsize)
          CopyMemory(*buffer4, P2\Z, strucsize)
          CopyMemory(*buffer1, P3\Z, strucsize)
          CopyMemory(*buffer2, P4\Z, strucsize)
        Case #TA2D_DEGREE_270
          CopyMemory(*buffer4, P1\Z, strucsize)
          CopyMemory(*buffer1, P2\Z, strucsize)
          CopyMemory(*buffer2, P3\Z, strucsize)
          CopyMemory(*buffer3, P4\Z, strucsize)
      EndSelect
      
    Next
    LineWidth - 2 ;pro Ring zwei weniger vom Ursprung
  Next
EndProcedure

;#############################
;# HIER BEGINNT DAS BEISPIEL #
;#############################


;initialisieren
OpenConsole()
ConsoleTitle("TurnArray2D example!")
ConsoleCursor(0)
EnableGraphicalConsole(#True)

Global Dim feld.b(4,4)
Restore fielddat


Procedure turn_it_all(degree.l)
  If degree > 0
    TurnArray2D(@feld(0,0), SizeOf(Byte), 5, degree)
  EndIf
  
  For zy = 0 To 4
    For zx = 0 To 4
      ConsoleLocate(zx * 2, zy + degree * 6)
      Print(Chr(feld(zx,zy)))
    Next
  Next
EndProcedure


;einlesen
For zy = 0 To 4
  For zx = 0 To 4
    Read feld(zx,zy)
  Next
Next

;ausgeben
turn_it_all(#TA2D_DEGREE_0)
turn_it_all(#TA2D_DEGREE_90)
turn_it_all(#TA2D_DEGREE_180)
turn_it_all(#TA2D_DEGREE_270)
Input()

DataSection
  fielddat:
    Data.b 't', 'h', 'i', 's', ' '
    Data.b 's', 'u', 'c', 'k', 's'
    Data.b ' ', 't', 'o', 't', 'a'
    Data.b 'l', 'l', 'y', '!', 'y'
    Data.b 'e', 'a', 'h', '.', '.'
EndDataSection
Hab die Multiplikationen rausgelassen und schon vorher eingefügt, die "Hauptschleife" rechnet jetzt nur noch Addition.
Hellhound66
Beiträge: 476
Registriert: 23.03.2005 23:19

Beitrag von Hellhound66 »

Code: Alles auswählen

  *buffer1 = AllocateMemory(strucsize)
  *buffer2 = AllocateMemory(strucsize)
  *buffer3 = AllocateMemory(strucsize)
  *buffer4 = AllocateMemory(strucsize) 
Reserviere nur einen Speicherblock von strucsize*4 Größe, da das erstens schneller geht und zweitens den speicher nicht unnötig fragmentiert. Ich denke dabei an intensive Nutzung deiner Methode innerhalb verschiedener Threads zum Beispiel.

Code: Alles auswählen

  *__BUF = AllocateMemory(strucsize*4)
  *buffer1 = *__BUF
  *buffer2 = *__BUF+strucsize
  *buffer3 = *__BUF+strucsize*2
  *buffer4 = *__BUF+strucsize*3 

2.
Du kannst dir die Select-Case-Abfrage in der Schleife sparen, wenn du die entweder rauslegst, oder 3 Prozeduren daraus machst, die von einer "Mutterprozedur" aus aufgerufen werden.

Dann sollte der Algo noch schneller sein.
Zu guter Letzt kannst du dir noch einen eigenes Copymemory()-Macro schreiben, dass abhängig von strucsize den optimalen Kopieralgo nutzt.
Optimismus ist ein Mangel an Information.
Kekskiller
Beiträge: 752
Registriert: 14.09.2004 21:39
Kontaktdaten:

Beitrag von Kekskiller »

@Hellhound:
Wollte ich ursprünglich auch so machen, hatte mich aber erstmal so wegen der Fehleranfälligkeit entschieden (wegen Kontrolle der Elemente). Aber ich werds später noch ändern.
Zu guter Letzt kannst du dir noch einen eigenes Copymemory()-Macro schreiben, dass abhängig von strucsize den optimalen Kopieralgo nutzt.
Wie meinst du das? Steht das in Verbindung mit dem Entfernen des Select-Case'...?
Kekskiller
Beiträge: 752
Registriert: 14.09.2004 21:39
Kontaktdaten:

Beitrag von Kekskiller »

Update!

Änderungen:

- nur noch ein Buffer für alle Prozeduren
- Speicher wird nur neualloziert, wenn Strukturgröße anders als vorher
- Variablenanzahl verringert (nur noch 4 Adressepointer, 1 XY-Variable
- Eine universelle Prozedur und für Speedfreaks noch mal getrennte ohne Select-Case

Code:

Code: Alles auswählen

Enumeration
  #TA2D_DEGREE_0
  #TA2D_DEGREE_90
  #TA2D_DEGREE_180
  #TA2D_DEGREE_270
EndEnumeration

CompilerIf Defined(__TA2D_XY, #PB_Structure) = 0
  Structure __TA2D_XY
    X.l
    Y.l
  EndStructure
CompilerEndIf

CompilerIf Defined(__TA2D_last_strucsize, #PB_Variable) = 0
  Global __TA2D_last_strucsize.l
CompilerEndIf

CompilerIf Defined(*__TA2D_buffer, #PB_Variable) = 0
  Global *__TA2D_buffer
CompilerEndIf

Procedure TurnArray2D(*array, strucsize.l, width.l, flag.b)
  Protected Ring.l
  Protected Cell.l
  Protected linesize.l
  Protected *A1
  Protected *A2
  Protected *A3
  Protected *A4
  Protected P.__TA2D_XY
  Protected RingRange.l
  Protected LineWidth.l
  
  linesize = strucsize * width
  
  If strucsize <> __TA2D_last_strucsize
    ;Debug "changed __TA2D_last_strucsize from " + Str(__TA2D_last_strucsize) + " to " + Str(strucsize)
    *__TA2D_buffer = AllocateMemory(strucsize)
    __TA2D_last_strucsize = strucsize
  EndIf
  
  RingRange = width / 2 - 1
  LineWidth = width - 1
  
  For Ring = 0 To RingRange;nur bis zur Hälfte durchgehen
    
    ;ring-ecken vorberechnen
    P\X = Ring
    P\Y = Ring + LineWidth
    
    *A1 = *array + P\X * linesize + P\X * strucsize
    *A2 = *array + P\X * linesize + P\Y * strucsize
    *A3 = *array +  P\Y * linesize + P\Y * strucsize
    *A4 = *array +  P\Y * linesize + P\X * strucsize
    
    ;{Ursprüngliche Vorberechnung (zum Verständnis) <- falls eigene änderung, diesen code als vorlage nehmen!
    ; P1\X = Ring
    ; P1\Y = Ring
    ; P1\Z = *array +  P1\Y * linesize + P1\X * strucsize
    ; 
    ; P2\X = Ring + LineWidth
    ; P2\Y = Ring
    ; P2\Z = *array +  P2\Y * linesize + P2\X * strucsize
    ; 
    ; P3\X = Ring + LineWidth
    ; P3\Y = Ring + LineWidth
    ; P3\Z = *array +  P3\Y * linesize + P3\X * strucsize
    ; 
    ; P4\X = Ring
    ; P4\Y = Ring + LineWidth
    ; P4\Z = *array +  P4\Y * linesize + P4\X * strucsize
    ;}
    
    For Cell = 0 To LineWidth-1
      
      ;im gegensatz zu vorheriger version wird hier jede zelle einfach nur + "dazugerechnet"
      *A1 + strucsize
      *A2 + linesize
      *A3 - strucsize
      *A4 - linesize
      
      ;neubeschreiben
      Select flag
        Case #TA2D_DEGREE_90
          CopyMemory(*A1, *__TA2D_buffer, strucsize);PUFFER
          CopyMemory(*A2, *A1, strucsize)
          CopyMemory(*A3, *A2, strucsize)
          CopyMemory(*A4, *A3, strucsize)
          CopyMemory(*__TA2D_buffer, *A4, strucsize)
        Case #TA2D_DEGREE_180
          CopyMemory(*A1, *__TA2D_buffer, strucsize);PUFFER
          CopyMemory(*A3, *A1, strucsize)
          CopyMemory(*__TA2D_buffer, *A3, strucsize)
          CopyMemory(*A4, *__TA2D_buffer, strucsize);PUFFER
          CopyMemory(*A2, *A4, strucsize)
          CopyMemory(*__TA2D_buffer, *A2, strucsize)
        Case #TA2D_DEGREE_270
          CopyMemory(*A1, *__TA2D_buffer, strucsize);PUFFER
          CopyMemory(*A4, *A1, strucsize)
          CopyMemory(*A3, *A4, strucsize)
          CopyMemory(*A2, *A3, strucsize)
          CopyMemory(*__TA2D_buffer, *A2, strucsize)
      EndSelect
      
    Next
    LineWidth - 2 ;pro Ring zwei weniger vom Ursprung
  Next
EndProcedure

Procedure TurnArray2D_90(*array, strucsize.l, width.l)
  Protected Ring.l
  Protected Cell.l
  Protected linesize.l
  Protected *A1
  Protected *A2
  Protected *A3
  Protected *A4
  Protected P.__TA2D_XY
  Protected RingRange.l
  Protected LineWidth.l
  
  linesize = strucsize * width
  
  If strucsize <> __TA2D_last_strucsize
    *__TA2D_buffer = AllocateMemory(strucsize)
    __TA2D_last_strucsize = strucsize
  EndIf
  
  RingRange = width / 2 - 1
  LineWidth = width - 1
  
  For Ring = 0 To RingRange
    
    P\X = Ring
    P\Y = Ring + LineWidth
    
    *A1 = *array + P\X * linesize + P\X * strucsize
    *A2 = *array + P\X * linesize + P\Y * strucsize
    *A3 = *array +  P\Y * linesize + P\Y * strucsize
    *A4 = *array +  P\Y * linesize + P\X * strucsize
    
    For Cell = 0 To LineWidth-1
      
      *A1 + strucsize
      *A2 + linesize
      *A3 - strucsize
      *A4 - linesize
      
      CopyMemory(*A1, *__TA2D_buffer, strucsize)
      CopyMemory(*A2, *A1, strucsize)
      CopyMemory(*A3, *A2, strucsize)
      CopyMemory(*A4, *A3, strucsize)
      CopyMemory(*__TA2D_buffer, *A4, strucsize)
      
    Next
    LineWidth - 2
  Next
EndProcedure

Procedure TurnArray2D_180(*array, strucsize.l, width.l)
  Protected Ring.l
  Protected Cell.l
  Protected linesize.l
  Protected *A1
  Protected *A2
  Protected *A3
  Protected *A4
  Protected P.__TA2D_XY
  Protected RingRange.l
  Protected LineWidth.l
  
  linesize = strucsize * width
  
  If strucsize <> __TA2D_last_strucsize
    *__TA2D_buffer = AllocateMemory(strucsize)
    __TA2D_last_strucsize = strucsize
  EndIf
  
  RingRange = width / 2 - 1
  LineWidth = width - 1
  
  For Ring = 0 To RingRange
    
    P\X = Ring
    P\Y = Ring + LineWidth
    
    *A1 = *array + P\X * linesize + P\X * strucsize
    *A2 = *array + P\X * linesize + P\Y * strucsize
    *A3 = *array +  P\Y * linesize + P\Y * strucsize
    *A4 = *array +  P\Y * linesize + P\X * strucsize
    
    For Cell = 0 To LineWidth-1
      
      *A1 + strucsize
      *A2 + linesize
      *A3 - strucsize
      *A4 - linesize
      
      CopyMemory(*A1, *__TA2D_buffer, strucsize)
      CopyMemory(*A3, *A1, strucsize)
      CopyMemory(*__TA2D_buffer, *A3, strucsize)
      CopyMemory(*A4, *__TA2D_buffer, strucsize)
      CopyMemory(*A2, *A4, strucsize)
      CopyMemory(*__TA2D_buffer, *A2, strucsize)
      
    Next
    LineWidth - 2 
  Next
EndProcedure

Procedure TurnArray2D_270(*array, strucsize.l, width.l)
  Protected Ring.l
  Protected Cell.l
  Protected linesize.l
  Protected *A1
  Protected *A2
  Protected *A3
  Protected *A4
  Protected P.__TA2D_XY
  Protected RingRange.l
  Protected LineWidth.l
  
  linesize = strucsize * width
  
  If strucsize <> __TA2D_last_strucsize
    *__TA2D_buffer = AllocateMemory(strucsize)
    __TA2D_last_strucsize = strucsize
  EndIf
  
  RingRange = width / 2 - 1
  LineWidth = width - 1
  
  For Ring = 0 To RingRange
    
    P\X = Ring
    P\Y = Ring + LineWidth
    
    *A1 = *array + P\X * linesize + P\X * strucsize
    *A2 = *array + P\X * linesize + P\Y * strucsize
    *A3 = *array +  P\Y * linesize + P\Y * strucsize
    *A4 = *array +  P\Y * linesize + P\X * strucsize
    
    For Cell = 0 To LineWidth-1
      
      *A1 + strucsize
      *A2 + linesize
      *A3 - strucsize
      *A4 - linesize
      
      CopyMemory(*A1, *__TA2D_buffer, strucsize)
      CopyMemory(*A4, *A1, strucsize)
      CopyMemory(*A3, *A4, strucsize)
      CopyMemory(*A2, *A3, strucsize)
      CopyMemory(*__TA2D_buffer, *A2, strucsize)
      
    Next
    LineWidth - 2
  Next
EndProcedure


;#############################
;# HIER BEGINNT DAS BEISPIEL #
;#############################

;initialisieren
OpenConsole()
ConsoleTitle("TurnArray2D example!")
ConsoleCursor(0)
EnableGraphicalConsole(#True)

Global Dim feld.b(4,4)
Restore fielddat

Macro printit(ymul)
  For zy = 0 To 4
    For zx = 0 To 4
      ConsoleLocate(zx, zy + ymul * 6)
      Print(Chr(feld(zx,zy)))
    Next
  Next
EndMacro

;einlesen
For zy = 0 To 4
  For zx = 0 To 4
    Read feld(zx,zy)
  Next
Next

;ausgeben
printit(0)
TurnArray2D_90(@feld(0,0), SizeOf(Byte), 5)
printit(1)
TurnArray2D_180(@feld(0,0), SizeOf(Byte), 5)
printit(2)
TurnArray2D_270(@feld(0,0), SizeOf(Byte), 5)
printit(3)
Input()

DataSection
  fielddat:
    Data.b 3,     3, 178,   4,   4
    Data.b 3,     3, 178,   4,   4
    Data.b 178, 178, 178, 178, 178
    Data.b 6,     6, 178,   5,   5
    Data.b 6,     6, 178,   5,   5
EndDataSection
Ich hoffe, ich hab alle Vorschläge zur Zufriedenheit eingebaut... Zumindest im Moment fällt mir keine Optimierung außer einer Funktion zur eigenen Bufferangabe (damit für sehr große Strukturen im Voraus Buffer anlegen kann).
Antworten