lazMapViewer, Ergänzung des Verhaltens

Rund um die LCL und andere Komponenten
Antworten
Ekkehard
Beiträge: 67
Registriert: So 12. Feb 2023, 12:42
OS, Lazarus, FPC: Windows Lazarus 3.6, FPC 3.2.2
CPU-Target: 64-Bit
Wohnort: Hildesheim

lazMapViewer, Ergänzung des Verhaltens

Beitrag von Ekkehard »

Hallo,
beim lazMapViewer finde ich das "Flat-Earth" Verhalten ungünstig.
Eigentlich möchte man doch eher einen umlaufenden Zylinder abbilden, d.h. wenn man rechts (östlich) über die 180 Grad läuft, solle es nahtlos bei -180 Grad (westlich) weitergehen.
So wie der laMapViewer implementiert ist, geht es halt einfach nicht weiter.

Zum Glück sind die nötigen Änderungen nicht groß, so dass man das recht einfach umbauen kann.
Es sind nur Änderungen in der Datei "mvengine.pas" nötig.

In der Methode TMapViewerEngine.CalculateVisibleTiles muss Result.Left eins weniger sein. Ich denke, dass ist eher ein genereller Fehler.

Code: Alles auswählen

function TMapViewerEngine.CalculateVisibleTiles(const aWin: TMapWindow): TArea;
(...)
  Result.Left := startX - 1; //EDo
In der Methode TMapViewerEngine.MapPixelsToDegrees muss die Limitierung der X-Achse verändert werden, sie muss module 180 sein und umlaufen.

Code: Alles auswählen

function TMapViewerEngine.MapPixelsToDegrees(const AWin: TMapWindow;
  APoint: TPoint): TRealPoint;
(...)
// Statt:  mPoint.X := EnsureRange(APoint.X - AWin.X, 0, iMapWidth);
// 
  mPoint.X := (APoint.X - AWin.X) mod iMapWidth;
  while mPoint.X < 0 do
    mPoint.X := mPoint.X + iMapWidth;
  while mPoint.X >= iMapWidth do
    mPoint.X := mPoint.X - iMapWidth;
In der Methode TMapViewerEngine.Redraw müssen die Kacheln ggf am anderen Ende verwendet werden. Hierzu muss die Anzahl der Kacheln bestimmt werden.

Code: Alles auswählen

procedure TMapViewerEngine.Redraw(const aWin: TmapWindow);
(...)
  numTiles : Integer; //EDo: Loop around
(...)
  numTiles := 1 shl aWin.Zoom;
  for y := TilesVis.Top to TilesVis.Bottom do
    for X := TilesVis.Left to TilesVis.Right do
    begin
      // Statt: Tiles[iTile].X := X;
      Tiles[iTile].X := X mod numTiles;
      if Tiles[iTile].X < 0 then
        Tiles[iTile].X := Tiles[iTile].X + numTiles; 

In der Methode TMapViewerEngine.TileDownloaded müssen ggf Kacheln mehrfach gezeichnet werden, bzw. der Umlauf ausgeführt werden.
Dazu gibt es drei neue Lokale Variablen und zwei Schleifen, die jeweils nach rechts und links nachsehen, ob und ggf wieviele Kacheln in das Sichtfenster passen.

Code: Alles auswählen

procedure TMapViewerEngine.TileDownloaded(Data: PtrInt);
var
(...)
  worldWidth : Integer;  
  numTiles : Integer; 
  baseX : Integer;
begin
(...)
       // Y bleibt, tauscht aber die Zeile mit X, die 
       Y := EnvTile.Win.Y + EnvTile.Tile.Y * TILE_SIZE; // begin of Y
       // Statt: X := EnvTile.Win.X + EnvTile.Tile.X * TILE_SIZE; // begin of X
       // und DrawTile(EnvTile.Tile, X, Y, img);
       
       baseX := EnvTile.Win.X + EnvTile.Tile.X * TILE_SIZE; // begin of X
       numTiles := 1 shl EnvTile.Win.Zoom;
       worldWidth := numTiles * TILE_SIZE;
       // From the center to the left (western) hemisphere
       X := baseX;
       while (X+TILE_SIZE >= 0) do
       begin
         DrawTile(EnvTile.Tile, X, Y, img);
         X := X - worldWidth;
       end;
       // From the center to the right (eastern) hemisphere
       X := baseX + worldWidth;
       while ((X-TILE_SIZE) <= EnvTile.Win.Width) do
       begin
         DrawTile(EnvTile.Tile, X, Y, img);
         X := X + worldWidth;
       end;
  
Das wars. Ab dann verhält sich der lazMapViewer wie die Website von OpenStreetMap. Deutlich sieht man in großen Fenstern die Erde mehrfach und in größeren Zoom-Bereichen kann man im Osten Russlands über die Ost/West Grenze schieben, ähnliches auch in den zu den USA gehörenden Aleuten.

Gruß Ekkehard

PS: Es gibt noch ein weiteres Problem, was bisher nicht so auffiel. Da der Kartenhintergrund nie aktualisiert wird, ergeben sich unangenehme Dopplungen und Artefakte, insbesondere, wenn bei geringem Zoom die Karte verschoben wird. Ein einfache Lösung habe ich dazu noch nicht gefunden.

wp_xyz
Beiträge: 5163
Registriert: Fr 8. Apr 2011, 09:01

Re: lazMapViewer, Ergänzung des Verhaltens

Beitrag von wp_xyz »

Danke. Eine schöne Erweiterung. Ins svn hochgeladen.

Bei der Ausgabe gibt es sowieso noch das Problem, dass wegen der vielen Threads jederzeit Teile der Anzeige überpinselt werden können. Daher muss man bei Overlays (Positionsmarkern, Tracks) ohne Thread-Support arbeiten, das Programm wird dementsprechend langsam - das kriegt man sicher besser hin. Und das ganze stürzt in Linux ab (https://gitlab.com/freepascal.org/lazar ... sues/39017). Da ich mich nicht auf dieses eine Projekt konzentrieren kann, wäre ich für jede Unterstützung dankbar.

Antworten