Adresse in LazMapViewer suchen?

Rund um die LCL und andere Komponenten
Antworten
Benutzeravatar
fliegermichl
Lazarusforum e. V.
Beiträge: 1812
Registriert: Do 9. Jun 2011, 09:42
OS, Lazarus, FPC: Lazarus Fixes FPC Stable
CPU-Target: 32/64Bit
Wohnort: Echzell

Adresse in LazMapViewer suchen?

Beitrag von fliegermichl »

In dem Beispielprogramm fulldemo kann man nach einem Ort suchen.
Gibt es auch eine Möglichkeit, eine bestimmte Adresse einzugeben?

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

Re: Adresse in LazMapViewer suchen?

Beitrag von wp_xyz »

Dazu müsstest du dir einen Map-Service suchen und dort die Koordinaten abfragen, z.B. https://geocode.maps.co/. Es scheint einen kostenlosen Zugang zu geben, aber API-Key erforderlich. Um die Adresse "555, 5th Ave, New York, NY 10017, US" abzufragen, musst du folgende URL abschicken:

Code: Alles auswählen

https://geocode.maps.co/search?q=555+5th+Ave+New+York+NY+10017+US&api_key=YOUR_SECRET_API_KEY
(dabei "YOUR_SECRET_API_KEY" durch deinen persönlichen API-Key ersetzen). Damit erhältst du ein json, in dem u.a. die Longitude and Latitude stehen.

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

Re: Adresse in LazMapViewer suchen?

Beitrag von wp_xyz »

Ich habe mal ein kleines Demo-Programm basierend auf dem GeoCode.Maps-Servce geschrieben - siehe Anhang. Als erstes musst du dich bei GeoCode registrieren und dir einen API-Code schicken lassen (kostenlos, 25.000 Anfragen pro Monat bei max 5 Anfragen pro Sekunde): https://geocode.maps.co/join/. Der API-Code wird beim Start des Demo-Programms abgefragt und für künftige Programmstarts in einer ini-Datei gespeichert. Anschließend kannst du in der Zeile "Adresse" die gewünschte Such-Adresse eingeben. Ich habe mich nicht tief in das API eingelesen (https://geocode.maps.co/docs/endpoints/#search), daher hat die Abfrage bei mir nur englische Ortsnamen akzeptiert (Munich statt München) - aber das kann man sicher ändern.
Dateianhänge
AddressToMap.zip
(8.37 KiB) 8-mal heruntergeladen

Benutzeravatar
fliegermichl
Lazarusforum e. V.
Beiträge: 1812
Registriert: Do 9. Jun 2011, 09:42
OS, Lazarus, FPC: Lazarus Fixes FPC Stable
CPU-Target: 32/64Bit
Wohnort: Echzell

Re: Adresse in LazMapViewer suchen?

Beitrag von fliegermichl »

Danke für die schnelle Antwort,
In der Zip Datei hat die AddressToMap.lpr gefehlt.
Ich habe die schnell selbst erstellt.

Code: Alles auswählen

Program AddressToMap;
uses interfaces, forms, main;

begin
  Application.Initialize;
  Application.CreateForm(TMainform, Mainform);
  Application.Run;
end.
Ich konnte erfolgreich eine deutsche Adresse (allerdings ohne Umlaute im Namen) finden.

Edit: Wenn man Umlaute mit ae, ue usw. eingibt, funktioniert es auch. Beispiel "Praelat-Zistl-Str. 1 Muenchen"

paweld
Beiträge: 114
Registriert: So 11. Jun 2023, 16:01
OS, Lazarus, FPC: Lazarus trunk, FPC fixes

Re: Adresse in LazMapViewer suchen?

Beitrag von paweld »

allerdings ohne Umlaute im Namen
Du musst die URL verschlüsseln:

Code: Alles auswählen

uses
  fphttpclient, opensslsockets, fpjson;

type
  TCoordinate = record
    name: String;
    displayname: String;
    &type: String;
    addresstype: String;
    lat: Double;
    lon: Double;
    village: String;
    town: String;
    city: String;
    county: String;
    state: String;
    postcode: String;
    country: String;
  end;
  TCoordinates = array of TCoordinate;

var
  GEOCODE_APIKEY: String = 'xxxxxx';

function GetCoords(const Aquery, Aapikey: String; var Acoords: TCoordinates): Boolean;
var
  hc: TFpHttpClient;
  json: String;
  jarr: TJsonArray;
  jo: TJsonObject;
  fs: TFormatSettings;
  i, c: Integer;
  lat, lon: Double;
begin
  fs.DecimalSeparator := '.';
  Result := False;
  Acoords := nil;
  hc := TFpHttpClient.Create(nil);
  hc.AllowRedirect := True;
  try
    json := hc.Get(Format('https://geocode.maps.co/search?q=%s&api_key=%s', [EncodeUrlElement(Aquery), EncodeUrlElement(Aapikey)]));  //encode url
    Result := True;
  except
  end;
  hc.Free;
  if Result then
  begin
    c := 0;
    jarr := TJsonArray(GetJson(json));
    SetLength(Acoords, jarr.Count);
    for i := 0 to jarr.Count - 1 do
    begin
      jo := TJsonObject(jarr.Items[i]);
      if (jo.FindPath('.lat') <> nil) and (jo.FindPath('.lon') <> nil) and
        TryStrToFloat(jo.GetPath('.lat').AsString, lat, fs) and TryStrToFloat(jo.GetPath('.lon').AsString, lon, fs) then
      begin
        Acoords[c].lat := lat;
        Acoords[c].lon := lon;
        //Weitere Informationen zu den gefundenen Adressen
        if jo.FindPath('.name') <> nil then
          Acoords[c].name := jo.GetPath('.name').AsString;
        if jo.FindPath('.display_name') <> nil then
          Acoords[c].displayname := jo.GetPath('.display_name').AsString;
        if jo.FindPath('.type') <> nil then
          Acoords[c].&type := jo.GetPath('.type').AsString;
        if jo.FindPath('.addresstype') <> nil then
          Acoords[c].addresstype := jo.GetPath('.addresstype').AsString;
        if jo.FindPath('.address.city') <> nil then
          Acoords[c].city := jo.GetPath('.address.city').AsString;
        if jo.FindPath('.address.town') <> nil then
          Acoords[c].town := jo.GetPath('.address.town').AsString;
        if jo.FindPath('.address.village') <> nil then
          Acoords[c].village := jo.GetPath('.address.village').AsString;
        if jo.FindPath('.address.county') <> nil then
          Acoords[c].county := jo.GetPath('.address.county').AsString;
        if jo.FindPath('.address.state') <> nil then
          Acoords[c].state := jo.GetPath('.address.state').AsString;
        if jo.FindPath('.address.country') <> nil then
          Acoords[c].country := jo.GetPath('.address.country').AsString;
        if jo.FindPath('.address.postcode') <> nil then
          Acoords[c].postcode := jo.GetPath('.address.postcode').AsString;
        //
        Inc(c);
      end;
    end;
    jarr.Free;
    SetLength(Acoords, c);
    Result := Length(Acoords) > 0;
  end;
end;

procedure TForm1.Button1Click(Sender: TObject);
var
  coords: TCoordinates;
  s: String;
  i: Integer;
begin
  if GetCoords(Edit1.Text, GEOCODE_APIKEY, coords) then
  begin
    s := '';
    for i := 0 to High(coords) do
      s := s + Format('lat: %g; lon: %g; address type: %s; name: %s; state: %s; country: %s',
        [coords[i].lat, coords[i].lon, coords[i].addresstype, coords[i].displayname, coords[i].state, coords[i].country]) + #13#10;
    ShowMessage(Format('Coordinates for: %s'#13#10'%s', [Edit1.Text, s]))
  end
  else
    ShowMessage('Unable to retrieve coordinates');
end; 
Grüße / Pozdrawiam
paweld

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

Re: Adresse in LazMapViewer suchen?

Beitrag von wp_xyz »

Ich habe noch einen Provider gefunden, der nicht einmal einen API-Key verlangt: https://nominatim.org/release-docs/develop/api/Search/. Die URL für die Abfrage wäre hier

Code: Alles auswählen

var
  url, searchParam: String;
  fs: TFormatSettings;
...
  searchParam := EncodeURLElement(Edit1.Text);
  url := Format(
    'https://nominatim.openstreetmap.org/search?addressdetails=1&q=%s&format=json&limit=1',
    [searchParam]); 
Der Rest des Programms kann unverändert bleiben (bis auf alles was zum API-Key gehört und entfallen kann). Die Zusatzinformationen in paweld's Code habe ich nicht geprüft, können ggfs sicher leicht angepasst werden.

paweld, danke für den Tipp mit EncodeURLElement...

Benutzeravatar
fliegermichl
Lazarusforum e. V.
Beiträge: 1812
Registriert: Do 9. Jun 2011, 09:42
OS, Lazarus, FPC: Lazarus Fixes FPC Stable
CPU-Target: 32/64Bit
Wohnort: Echzell

Re: Adresse in LazMapViewer suchen?

Beitrag von fliegermichl »

wp_xyz hat geschrieben: Sa 8. Aug 2026, 23:29 Ich habe noch einen Provider gefunden, der nicht einmal einen API-Key verlangt:
...
Hier bekomme ich nur einen 403 (Forbidden)!?

Edit: Der 403 kommt nur in dem Lazarusprogramm. Gebe ich die URL im Browser ein, bekomme ich ein korrektes Ergebnis!?!

paweld
Beiträge: 114
Registriert: So 11. Jun 2023, 16:01
OS, Lazarus, FPC: Lazarus trunk, FPC fixes

Re: Adresse in LazMapViewer suchen?

Beitrag von paweld »

fliegermichl hat geschrieben: Hier bekomme ich nur einen 403 (Forbidden)!?

Edit: Der 403 kommt nur in dem Lazarusprogramm. Gebe ich die URL im Browser ein, bekomme ich ein korrektes Ergebnis!?!
Es reicht aus, den Header „User-Agent“ hinzuzufügen:

Code: Alles auswählen

var
  hc: TFpHttpClient;
  json: String;
begin
  hc := TFpHttpClient.Create(nil);
  hc.AddHeader('User-Agent', 'Mozilla/5.0 (Windows NT 10.0; rv:130.0) Gecko/20240101 Firefox/130.0'); //add this line
  hc.AllowRedirect := True;
  try
    json := hc.Get(Format('https://nominatim.openstreetmap.org/search?addressdetails=1&q=%s&format=json&limit=1', [EncodeUrlElement('Löcknitz')]));
    ShowMessage(json);
  except
    on E: Exception do
      ShowMessage(E.Message + #13#10 + IntToStr(hc.ResponseStatusCode) + ' - ' + hc.ResponseStatusText);
  end;
  hc.Free;
end; 
Grüße / Pozdrawiam
paweld

Benutzeravatar
fliegermichl
Lazarusforum e. V.
Beiträge: 1812
Registriert: Do 9. Jun 2011, 09:42
OS, Lazarus, FPC: Lazarus Fixes FPC Stable
CPU-Target: 32/64Bit
Wohnort: Echzell

Re: Adresse in LazMapViewer suchen?

Beitrag von fliegermichl »

paweld hat geschrieben: So 9. Aug 2026, 07:14
fliegermichl hat geschrieben: Hier bekomme ich nur einen 403 (Forbidden)!?

Edit: Der 403 kommt nur in dem Lazarusprogramm. Gebe ich die URL im Browser ein, bekomme ich ein korrektes Ergebnis!?!
Es reicht aus, den Header „User-Agent“ hinzuzufügen:
Danke, das war's.

Antworten