Entwickler-Ecke
Sonstiges (Delphi) - Koordinaten umrechnen zwischen Arrays
catweasel - Do 10.01.13 21:04
Titel: Koordinaten umrechnen zwischen Arrays
Hi,
Ich hab folgendes Problem:
Es gibt zwei Arrays,zweidimensional, nennen wir sie einmal "DatenArray" und "DisplayArray".
Ich möchte nun Inhalte des datenarrays im Displayarray abbilden.
Wären nun beide Arrays gleich gross, wäre die Sache einfach:
Delphi-Quelltext
1: 2: 3: 4: 5: 6: 7:
| var x,y : integer; begin for y := 0 to MaxY-1 do for x := 0 to MaxX-1 do DisplayArray[x,y] := DatenArray[x,y]; end; |
Aber leider kann das DatenArray sowohl kleiner oder grösser als das DisplayArray sein.
In dem Fall das das DatenArray kleiner als das DisplayArray ist sollen die Daten wiederholt angezeigt werden.
Ungefähr so:
Delphi-Quelltext
1: 2: 3: 4: 5: 6: 7:
| var x,y : integer; begin for y := 0 to MaxY-1 do for x := 0 to MaxX-1 do DisplayArray[x,y] := DatenArray[x mod MaxX,y mod MaxY]; end; |
Wenn das DatenArray grösser als das DisplayArray ist soll gescrollt werden können.
Dazu brauch ich einen Offset der anstelle eine Zuweisung
DisplayArray[x,y] := DatenArray[x,y]; das ganze entsprechend verschiebt. Auch hier sollen, falls man mit dem DisplayArray über die Grenze des DatenArrays hinausgescrollt die Daten wiederholt werden.
Zusammengefasst:
Man soll also "endlos" in alle Richtungen scrollen können, ohne jemals an einen Rand zu stossen. Die Daten wiederholen sich dann eben nur ab einem bestimmten Punkt. Ist das DatenArray kleiner als das DisplayArray sieht man sich wiederholende Daten auch ohne Scrollen.
Das Scrollen soll folgendermassen geschehen:
Nicht per Buttons oder Scrollbars, sondern dadurch das eine bestimmte Zelle zum "Mittlepunkt" wird.
Da die Grösse das DisplayArrays bekannt ist, lässt sich auch ausrechnen welche Zelle ungefähr in der Mittes ist und deren relative Position zur ausgewählten Zelle, etwa:
Delphi-Quelltext
1: 2: 3: 4: 5: 6: 7: 8: 9: 10:
| var CenterCell : TPoint; SelectedCell : TPoint; DeltaPos : TPoint; begin CenterCell.X := MaxX div2; CenterCell.Y := MaxY div2; DeltaPos.X := SelectedCell.X - CenterCell.X; DeltaPos.Y := SelectedCell.Y - CenterCell.Y; end; |
ist also der Mittelpunkt des DisplayArray bei (5,7) und wird die Zelle (6,12) in DisplayArray ausgewählt, so soll nun soweit gescrollt werden (in diesem Fall also "eins nach rechts und fünf nach unten"). Damit ist die ausgewählte Zelle im Mittelpunkt. (Den Wert für SelectedCell muss man natürlich danach noch updaten).
Hmpf :?!?:
Trotz all dieser Vorüberlegungen bekomme ich das einfachg nicht hin.
Wie geht die Umwandlung von Display Koordinaten in Datenkoordinaten.
Delphi-Quelltext
1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16:
| var x,y : integer; Pos : TPoint begin for y := 0 to MaxY-1 do for x := 0 to MaxX-1 do begin Pos := DisplayPosToDataPos(x,y); DisplayArray[x,y] := DatenArray[Pos.X,Pos.Y]; end; end;
function DisplayPosToDataPos(ACol,ARow:integer):TPoint; begin Result := ??? end; |
Ich bekomme es einfach nicht hin. Entweder gibts AccessViolations weil ich über die Arraygrenzen hinausschiesse, oder es wird nur Müll angezeigt.
Irgendwie habe ich da ein Brett vor dem Kopf bei dieser Indirektion. :autsch:
Kann mir mal jemand auf die Sprünge helfen. Das wäre Super :roll:
Besten Dank.
Cheers,
Catweasel
jfheins - Do 10.01.13 21:27
So ungefähr?
Delphi-Quelltext
1: 2: 3: 4: 5: 6: 7:
| for y := 0 to MaxY-1 do for x := 0 to MaxX-1 do begin Pos.X = (x + OffsetX) mod Length(DatenArray); Pos.Y = (y + OffsetY) mod Length(DatenArray[0]) DisplayArray[x,y] := DatenArray[Pos.X,Pos.Y]; end; |
Wenn die MaxxY Werte vom DisplayArray sind, musst du bei der modulo-Operation natürlich die
richtigen Werte hernehmen ;-)
Das mit dem Scrollen ist dann auch einfach erledigt: Das errechnete Delta wird einfach zum aktuellen Offset hinzuaddiert (oder subtrahiert) und dann alle Zellen neu ausrechnen.
catweasel - Do 10.01.13 22:17
jfheins hat folgendes geschrieben : |
So ungefähr?
Delphi-Quelltext 1: 2: 3: 4: 5: 6: 7:
| for y := 0 to MaxY-1 do for x := 0 to MaxX-1 do begin Pos.X = (x + OffsetX) mod Length(DatenArray); Pos.Y = (y + OffsetY) mod Length(DatenArray[0]) DisplayArray[x,y] := DatenArray[Pos.X,Pos.Y]; end; |
Wenn die MaxxY Werte vom DisplayArray sind, musst du bei der modulo-Operation natürlich die richtigen Werte hernehmen ;-)
Das mit dem Scrollen ist dann auch einfach erledigt: Das errechnete Delta wird einfach zum aktuellen Offset hinzuaddiert (oder subtrahiert) und dann alle Zellen neu ausrechnen. |
Danke für die schnelle Antwort. Ich kann das aber erst morgen ausprobieren.
Bin aber schon mal gespannt. Falls es nicht klappt bastel ich mal ne kleine Testanwendung und lade es hier hoch.
Schönen Abend noch :)
Catweasel
catweasel - Do 10.01.13 23:46
Hi,
Hab doch noch etwas Zeit gefunden :)
Es klappt soweit ganz wunderbar.
Es muss(te) nur noch eine Abfrage für den GesamtOffset, der kann negativ werden.
Abgefangen sieht das so aus:
Delphi-Quelltext
1: 2: 3: 4: 5: 6: 7:
| function Tmainform.DisplayPosToDataPos(Pos: TPoint): TPoint; begin Result.X := (Pos.X+ScrollOffset.X) mod DataDim.X; Result.Y := (Pos.Y+ScrollOffset.Y) mod DataDim.Y; if Result.X<0 then Result.X := DataDim.X+Result.X; if Result.Y<0 then Result.Y := DataDim.Y+Result.Y; end; |
Ich hab mal die Demo Anwendung mit der ich das getestet habe beigefügt :)
Das blaue Quadrat zeigt das "Zentrum" an, das rote Quadrat markiert die Fokuszelle.
Klick zum Markieren, Doppelklick für Scrollen.
Cheers,
Catweasel
jfheins - Fr 11.01.13 11:18
Wenn du jetzt noch eine schöne Animation für den Scrollvorgang einbaust, bekommst du einen virtuellen Keks :mrgreen:
(Natürlich schön flüssig, während der Animation müssten also auch Bruchteile von Zellen angezeigt werden...)
catweasel - Fr 11.01.13 15:12
jfheins hat folgendes geschrieben : |
Wenn du jetzt noch eine schöne Animation für den Scrollvorgang einbaust, bekommst du einen virtuellen Keks :mrgreen:
(Natürlich schön flüssig, während der Animation müssten also auch Bruchteile von Zellen angezeigt werden...) |
Ich mag Kekse :)
Ich werd mal das GridControl das ich entwickelt habe (von einer PaintBox aus) hier reinstellen. Das macht da dann sogar durhaus Sinn das Scrollen zu animieren. Ich will hier aber nicht gleich das ganze Projekt reinballern. Ich werd mal meine Demo App auf mein eigenes Grid umrüsten :)
Vielleicht hat auch der eine oder andere noch Tips wie man Sachen verbessern könnte....
Aber dazu komme ich wohle erst heute Abend...
Cheers,
Catweasel
catweasel - Sa 12.01.13 18:43
Moderiert von
Martok: Vollzitat des vorigen Beitrags entfernt.
So :)
Nun hab ich mal eine Demo Anwendung mit meinem eigenen Grid anstelle eines TDrawGrids verwendet.
Ein paar kleinere Änderungen waren notwendig da das Display in meinem Projekt mit mehreren anderen Klassen zusammenarbeitet.
Ich habe das aber nur minimalst zerpflückt.
Schaut es euch mal an. Ein paar kleinere Sachen fehlen noch....
Cheers,
Catweasel
Mathematiker - Di 15.01.13 00:17
Hallo,
Du bekommst jetzt (fast) einen virtuellen Keks. :mrgreen:
Ich habe Dein Programm ausprobiert und es funktioniert soweit ohne Probleme. Etwa ab 200 Zeilen und Spalten gibt es eine kurze Verzögerung bis das Bild erscheint. Verstehe ich, da eine Menge gerechnet wird.
"Fast" einen virtuellen Keks gibt's aber nur, da ich absolut nicht weiß, welchen Zweck das Programm eigentlich hat.
Und klicke ich eine Hexagon-Zelle an, ändert sich irgendetwas, aber warum? :nixweiss:
Beste Grüße
Mathematiker
catweasel - Di 15.01.13 00:29
Moderiert von
Narses: Komplett-Zitat des letzten Beitrags entfernt.
Hey fast geschafft :)
Also wenn sich der Zellenwert ändert dann liegt das daran das du durch die Daten scrollst (Doppelklick).
Bei normalem Einzelklick sollte sich nur der Markierungsrahmen bewegen..
Das ganze wird so ein kleines Spiel im Stil von Civilization (Grafisch etwa auf dem Level von Civ2).
Das samplen der Thumbmap kann man auch per Scanline machen, das sollte etwas schneller gehen...
Wo ich nun noch einen Rat bräuchte:
Das
FOrigins array wird ja im Grunde nur gebraucht um Klick-Koordinaten zu Hexzellen-Koordinaten umzurechnen. Was inder
UpdateOrigins Prozedur gemacht wird kann ja uch in der
RenderCell Prozedur für jedes Hex in-situ erfolgen..
Aber irgendwie bekomm ich das anders nicht hin.
Von Col/Row zu Origin ist leicht, aber wie geht die Umkehrfunktion?
Cheers,
Catweasel
Entwickler-Ecke.de based on phpBB
Copyright 2002 - 2011 by Tino Teuber, Copyright 2011 - 2025 by Christian Stelzmann Alle Rechte vorbehalten.
Alle Beiträge stammen von dritten Personen und dürfen geltendes Recht nicht verletzen.
Entwickler-Ecke und die zugehörigen Webseiten distanzieren sich ausdrücklich von Fremdinhalten jeglicher Art!