MApView: eigener MapProvider

Rund um die LCL und andere Komponenten
willie68
Beiträge: 15
Registriert: Di 9. Sep 2025, 11:03

MApView: eigener MapProvider

Beitrag von willie68 »

Hi,

ich suche nach einer einfachen Möglichkeit einen eigenen MapProvider als Overlay in den MapView einzubinden.

Code: Alles auswählen

    MapView1.Engine.AddMapProvider('OpenSeaMap Seamarks', ptEPSG3857, 'https://%serv%.openseamap.org/seamark/%z%/%x%/%y%.png', 0, 19, 3, @GetSvrLetter);
  layer := TGPSTilelayer.Create;
  layer.MapProvider := 'OpenSeaMap Seamarks';
funktioniert schon mal nicht, weil beim layer.MapProvider der hinzugefügte MapProvider nicht bekannt.

Ich hab den Provider jetzt erst mal in die mveingine_mapreg.inc eingetragen.

Gibt es da nicht auch einen anderen programatischen Weg, einen neuen Provider hinzuzufügen?

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

Re: MApView: eigener MapProvider

Beitrag von wp_xyz »

Da hast du einen Bug in LazMapViewer gefunden: Sowohl MapView als auch jeder Layer hatten eine eigene Provider-Liste, die noch dazu nicht aufeinander abgestimmt waren, so dass der der MapView manuell hinzugefügte OpenSeaMap-Provider dem Layer nicht bekannt war. Ich habe die Provider nun in eine globale Liste verlagert und einiges umgebaut. Nun funktioniert es (hoffentlich ohne zuviel Schaden in User-Code angerichtet zu haben, denn einige Änderungen liegen im public-Teil der MapViewerEngine).

In der URL für den OpenSeaMap-Provider steckte noch ein Fehler. Du hattest "'https://%serv%.openseamap.org, ..., @GetSvrLetter)" geschrieben. Hier ersetzt die Funktion GetSvrLetter den Parameter %serv% durch Buchstaben 'a', 'b', ... Auf https://community.ifs.com/assets-asset- ... -map-34004 habe ich aber gesehen, dass zumindest der erste Server die Kennung 't1' hat, und wenn das mit den von dir angegebenen 3 Servern stimmt, wird es wahrscheinlich auch Kennungen 't2' und 't3' geben. Daher habe ich eine neue Funktion GetSvrIndex gemacht, die die Servernummer einfach direkt als String einsetzt. Die URL heißt nun "'https://t%serv%.openseamap.org, ..., @GetSvrIndex)", und wie du an dem beigefügten Projekt siehst, funktioniert das (WICHTIG: aber nur mit dem aktuellen LazMapViewer im SVN-Repositorium).
Dateianhänge
openseamap.png
openseamap.png (299.96 KiB) 224 mal betrachtet
mapproviders_at_runtime.zip
(2.43 KiB) 125-mal heruntergeladen

willie68
Beiträge: 15
Registriert: Di 9. Sep 2025, 11:03

Re: MApView: eigener MapProvider

Beitrag von willie68 »

Sehr gut. Kann ich morgen direkt mal probieren.

willie68
Beiträge: 15
Registriert: Di 9. Sep 2025, 11:03

Re: MApView: eigener MapProvider

Beitrag von willie68 »

BTW.: T1 t2 und t3 sind leider keine gleichberechtigten Server. T2 ist für die Basiskarten, t1 für die Overlays Sport und Seamarks, t3 ist ein WMS Server für die Wassertiefen.

BTW.: gehen auch WMS Server als MapProvider?

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

Re: MApView: eigener MapProvider

Beitrag von wp_xyz »

willie68 hat geschrieben: Di 16. Sep 2025, 22:20 BTW.: T1 t2 und t3 sind leider keine gleichberechtigten Server. T2 ist für die Basiskarten, t1 für die Overlays Sport und Seamarks, t3 ist ein WMS Server für die Wassertiefen.
OK, dann ist es besser, t1, t2, und t3 in getrennten Providern jeweils fest einzutragen:

Code: Alles auswählen

  MapView1.Engine.AddMapProvider('OpenSeaMap Seamarks', ptEPSG3857,
    'https://t1.openseamap.org/seamark/%z%/%x%/%y%.png', 0, 19, 1); 
  MapView1.Engine.AddMapProvider('OpenSeaMap Base', ptEPSG3857,
    'https://t2.openseamap.org/seamark/%z%/%x%/%y%.png', 0, 19, 1); 
  MapView1.Engine.AddMapProvider('OpenSeaMap WaterDepths', ptEPSG3857,
    'https://t3.openseamap.org/seamark/%z%/%x%/%y%.png', 0, 19, 1); 
willie68 hat geschrieben: Di 16. Sep 2025, 22:20 BTW.: gehen auch WMS Server als MapProvider?
LazMapViewer unterstützt nur Tile-Server, die die in der URL mit den Indizes %x%, %y%, %z% identifizierten Kartenkacheln als Bitmaps zurückliefern. WMS (Web Map Service) scheint mir etwas allgemeiner zu sein (bin hier aber kein Fachmann).

willie68
Beiträge: 15
Registriert: Di 9. Sep 2025, 11:03

Re: MApView: eigener MapProvider

Beitrag von willie68 »

Ok,
Ja, ich hab da gestern mal einen eigenen Proxy (in Golang) geschrieben, der die TMS Anfragen dann auf WMS umsetzt.
Der Phyton Mapproxy Dienst, der dafür eigentlich eingesetzt wird, war mir für meine Desktop-App zu Schwergewichtig.
Meinen Miniproxy starte ich dann mit einem TProcess, wenn jemand das Overlay aktiviert und beende das dann, entweder beim Deaktivieren oder beim Verlassen der App.
Falls Interesse besteht, den Dienst findet man hier:
www.github.com/willie68/go_mapproxy

willie68
Beiträge: 15
Registriert: Di 9. Sep 2025, 11:03

Re: MApView: eigener MapProvider

Beitrag von willie68 »

So probiert und für gut befunden.
Ich musste nur die

Code: Alles auswählen

MapView1.GetMapProviders(provider);
auf

Code: Alles auswählen

MapView1.Engine.GetMapProviders(provider);
ändern.

willie68
Beiträge: 15
Registriert: Di 9. Sep 2025, 11:03

Re: MApView: eigener MapProvider

Beitrag von willie68 »

Argh, einen hab ich doch noch.
Ab und zu bekomme ich jetzt eine Exception, wenn ich den Tiefenlayer auf visible stelle
Screenshot 2025-09-17 11.47.38.png
Screenshot 2025-09-17 11.47.38.png (158.45 KiB) 104 mal betrachtet
und zwar hier:

Code: Alles auswählen

procedure TMapViewerEngine.SetUseThreads(AValue: Boolean);
begin
  if Queue.UseThreads = AValue then Exit;
  Queue.UseThreads := AValue;
  Cache.UseThreads := AValue;
end;
Queue ist dann nil.

Das passiert immer dann, wenn ich mit

Code: Alles auswählen

MapView1.GPSItems.Add(track, MLTracks);
meinen GPS Track hinzugefügt habe.
Die bis dahin aktivierten Layer werden auch nicht angezeigt.

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

Re: MApView: eigener MapProvider

Beitrag von wp_xyz »

Das könnte noch ein Relikt aus der Thread-Orgie der ersten Version sein. Stelle mal eine nil-Prüfung voran:

Code: Alles auswählen

if (Queue = nil) or (Queue.UseThreads = AValue) then Exit;
Falls das nicht hilft, könntest du auf TMapLayer umstellen? Tritt das Problem dann immer noch auf? Es schwebt mir vor, GPS-Layer als deprecated zu markieren und langfristig zu entfernen.

willie68
Beiträge: 15
Registriert: Di 9. Sep 2025, 11:03

Re: MApView: eigener MapProvider

Beitrag von willie68 »

Die Exception ist zwar weg, aber gerendert wird trotzdem nix...

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

Re: MApView: eigener MapProvider

Beitrag von wp_xyz »

OK. Kannst du mir vielleicht eine kleines Test-Projekt zusammenklicken, bei dem ich den Fehler sehen kann?

willie68
Beiträge: 15
Registriert: Di 9. Sep 2025, 11:03

Re: MApView: eigener MapProvider

Beitrag von willie68 »

WIe füge ich denn einzelne TrackPunkte hinzu?
PS.: erledigt.
Zuletzt geändert von willie68 am Mi 17. Sep 2025, 14:46, insgesamt 1-mal geändert.

willie68
Beiträge: 15
Registriert: Di 9. Sep 2025, 11:03

Re: MApView: eigener MapProvider

Beitrag von willie68 »

Ah, ich glaub, jetzt hab ich es:

Code: Alles auswählen

  if length(ltrack.Waypoints) > 0 then
  begin
    track := FTrackLayer.Tracks.Add as TMapTrack;
    for i := 0 to length(ltrack.Waypoints) - 1 do
    begin
      way := ltrack.Waypoints[i];
      if way.Active then
      begin
        p := track.Points.Add as TMapTrackPoint;
        p.DateTime := way.TIme;
        p.Elevation := way.Elevation;
        p.Longitude := way.Longitude;
        p.Latitude :=  way.Latitude;
        Depth.AddXY(way.Time, -way.Depth);
      end;
    end;
    track.LineWidth := 0.5;
  end;
Ne init Methode für das p wäre nett.
Bei dem GPSTRack gab es eine MEthode um die betroffene Area zu ermitteln.
Wie ist das bei Maptracks? Muss ich das selber berechnen?

BTW.: Der Fehler ist jetzt weg.

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

Re: MApView: eigener MapProvider

Beitrag von wp_xyz »

willie68 hat geschrieben: Mi 17. Sep 2025, 14:23 PS.: erledigt.
Trotzdem: dazu habe ich gerade einen Abschnitt in die wiki-Seite des MapViewers geschrieben.

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

Re: MApView: eigener MapProvider

Beitrag von wp_xyz »

willie68 hat geschrieben: Mi 17. Sep 2025, 14:46 Bei dem GPSTRack gab es eine MEthode um die betroffene Area zu ermitteln.
Wie ist das bei Maptracks? Muss ich das selber berechnen?
Im MapViewer gibt es ja the TMapXXX und dazu korrespondierende TGPSxxx-Klassen. TMapTrack entspricht dem TGPSTrack, und du kannst vom TMapTrack aus mit Hilfe der GPSObj-Property auf den zugehörigen TGPSTrack zugreifen. Allerdings ist GPSObj ein allgemeiner Typ, und du musst erst nach TGPSTrack casten, um die Methoden des GPSTrack aufrufen zu können. Also (ungetestet):

Code: Alles auswählen

var
  area: TRealArea;
..
  TGPSTrack(mapTrack.GPSObj).GetArea(area);
 
willie68 hat geschrieben: Mi 17. Sep 2025, 14:46 Ne init Methode für das p wäre nett.
OK. In der SVN-Version gibt es nun AddPoint-Methoden für TMapTrack und TMapArea:

Code: Alles auswählen

var
  tp: TMapTrackPoint;
  ap: TMapAreaPoint;
 ...
  tp := MapTrack.AddPoint(APoint, AElevation, ADateTime); 
  ap := MapArea.AddPoint(APoint, AElevation, ADateTime);
  // wobei APoint: TRealPoint, und AElevation und ADateTime optional sind

Antworten