Autor Beitrag
catweasel
ontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic starofftopic star
Beiträge: 487
Erhaltene Danke: 1

Win 7 64bit
Delphi 7 Second Sedition V7.2
BeitragVerfasst: Do 10.01.13 21:04 
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:
ausblenden Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
var
x,y : integer;    // MaxX und MaxY (grösse des DisplayArrays) sind uns bekannt
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:
ausblenden Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
var
x,y : integer;    // MaxX und MaxY (grösse des DisplayArrays) sind uns bekannt
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:
ausblenden Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
var
CenterCell : TPoint;
SelectedCell : TPoint;  // Die Position der ausgewählten Zelle im DisplayArray ist bekannt
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.

ausblenden Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
var
x,y : integer;    // MaxX und MaxY (grösse des DisplayArrays) sind uns bekannt
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

_________________
Pommes werden schneller fertig wenn man sie vor dem Frittieren einige Minuten in siedendes Fett legt.


Zuletzt bearbeitet von catweasel am Do 10.01.13 23:19, insgesamt 2-mal bearbeitet
jfheins
ontopic starontopic starontopic starontopic starontopic starontopic starofftopic starofftopic star
Beiträge: 918
Erhaltene Danke: 158

Win 10
VS 2013, VS2015
BeitragVerfasst: Do 10.01.13 21:27 
So ungefähr?
ausblenden 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 Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic starofftopic star
Beiträge: 487
Erhaltene Danke: 1

Win 7 64bit
Delphi 7 Second Sedition V7.2
BeitragVerfasst: Do 10.01.13 22:17 
user profile iconjfheins hat folgendes geschrieben Zum zitierten Posting springen:
So ungefähr?
ausblenden 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

_________________
Pommes werden schneller fertig wenn man sie vor dem Frittieren einige Minuten in siedendes Fett legt.
catweasel Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic starofftopic star
Beiträge: 487
Erhaltene Danke: 1

Win 7 64bit
Delphi 7 Second Sedition V7.2
BeitragVerfasst: 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:

ausblenden 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
Einloggen, um Attachments anzusehen!
_________________
Pommes werden schneller fertig wenn man sie vor dem Frittieren einige Minuten in siedendes Fett legt.
jfheins
ontopic starontopic starontopic starontopic starontopic starontopic starofftopic starofftopic star
Beiträge: 918
Erhaltene Danke: 158

Win 10
VS 2013, VS2015
BeitragVerfasst: 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 Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic starofftopic star
Beiträge: 487
Erhaltene Danke: 1

Win 7 64bit
Delphi 7 Second Sedition V7.2
BeitragVerfasst: Fr 11.01.13 15:12 
user profile iconjfheins hat folgendes geschrieben Zum zitierten Posting springen:
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

_________________
Pommes werden schneller fertig wenn man sie vor dem Frittieren einige Minuten in siedendes Fett legt.
catweasel Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic starofftopic star
Beiträge: 487
Erhaltene Danke: 1

Win 7 64bit
Delphi 7 Second Sedition V7.2
BeitragVerfasst: Sa 12.01.13 18:43 
Moderiert von user profile iconMartok: 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
Einloggen, um Attachments anzusehen!
_________________
Pommes werden schneller fertig wenn man sie vor dem Frittieren einige Minuten in siedendes Fett legt.
Mathematiker
ontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic starofftopic star
Beiträge: 2622
Erhaltene Danke: 1448

Win 7, 8.1, 10
Delphi 5, 7, 10.1
BeitragVerfasst: 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

_________________
Töten im Krieg ist nach meiner Auffassung um nichts besser als gewöhnlicher Mord. Albert Einstein
catweasel Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic starofftopic star
Beiträge: 487
Erhaltene Danke: 1

Win 7 64bit
Delphi 7 Second Sedition V7.2
BeitragVerfasst: Di 15.01.13 00:29 
Moderiert von user profile iconNarses: 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

_________________
Pommes werden schneller fertig wenn man sie vor dem Frittieren einige Minuten in siedendes Fett legt.