Find adressen ud fra en GPS-position

Slå den nærmeste adresse op fra længde- og breddegrad med reverse-geokodning, og håndtér GPS-unøjagtighed med en radius-søgning.

4 min Niveau: Øvet ✓ Kode testet

En håndværker-app skal udfylde adressen ud fra telefonens position. En skadesanmeldelse har kun et punkt på et kort. En flådestyring skal vise, hvilken adresse en bil holder ved. Alle tre er reverse-geokodning: fra koordinat til adresse.

API'et har to endpoints til det, og en radius-søgning, der giver dig mere kontrol, når positionen er unøjagtig.

Det enkle kald

GET /adgangsadresser/reverse returnerer den nærmeste aktive adgangsadresse (bygningens indgang) til punktet:

Shell#reverse-curl
curl -s "https://api.danadresse.dk/adgangsadresser/reverse?x=12.5757&y=55.7326" \
  -H "X-Api-Key: $DANADRESSE_API_KEY"

x er længdegraden og y er breddegraden. Det er den hyppigste fejl at bytte om på dem: Danmark ligger omkring 8-15° øst og 54-58° nord, så et x over 50 er næsten altid en ombytning.

Svaret har samme form som GET /adgangsadresser/{id}, og struktur=mini eller struktur=flad virker også her. De vigtigste felter:

FeltIndhold
idAdgangsadressens UUID
adressebetegnelseF.eks. Strandvejen 100, 2900 Hellerup
vejstykke.navn, husnr, postnummer.nr, postnummer.navnAdressens dele
kommune, sogn, politikreds …Administrative områder
adgangspunkt.koordinaterAdressens eget punkt, [x, y]

Har du koordinater i UTM32 (meter), så tilføj srid=25832. Så er både input og koordinaterne i svaret i meter:

Shell#reverse-utm
curl -s "https://api.danadresse.dk/adgangsadresser/reverse?x=724434.93&y=6175755.61&srid=25832" \
  -H "X-Api-Key: $DANADRESSE_API_KEY"

GET /adresser/reverse virker på samme måde, men returnerer en fuld adresse med etage og dør. Den vælger én af enhederne i bygningen. I en etageejendom ved API'et ikke, hvilken lejlighed brugeren står i, så lad brugeren vælge etage og dør bagefter. Hent listen med GET /adresser?adgangsadresseid={id}&struktur=mini.

Hvad reverse ikke fortæller dig

  • Ingen afstand. Svaret siger ikke, hvor langt punktet er fra adressen. Udregn den selv fra adgangspunkt.koordinater (se Afstand mellem to adresser).
  • Ingen maksimal afstand. Endpointet leder op til cirka 60 km væk. Står brugeren midt på en mark, får du stadig en adresse, måske et par kilometer væk. Kun hvis der ikke er nogen adresse inden for den afstand, svarer API'et 404 med koden not_found.
  • Kun aktive adresser. Gældende og foreløbige adresser indgår. Nedlagte adresser indgår ikke.
  • Altid den nærmeste. Reverse søger i stadig større felter, til den nærmeste indgang er fundet, også i tætte byområder. Den giver samme adresse, som radius-søgningen nedenfor har øverst.

GPS er ikke præcis: brug en radius

En telefon angiver sin position med en usikkerhed (coords.accuracy i browseren, i meter). Udendørs er den typisk 5-20 meter, indendørs og mellem høje huse ofte 50 meter eller mere. Med en usikkerhed på 40 meter kan brugeren lige så godt stå ved nabohuset.

Brug derfor cirkel=lon,lat,radius på /adgangsadresser med radius sat efter usikkerheden. Resultaterne kommer sorteret med den nærmeste først. Er der flere kandidater, så vis dem som en kort liste:

JavaScript#gps-node
const API = "https://api.danadresse.dk";
const headers = { "X-Api-Key": process.env.DANADRESSE_API_KEY };

function afstandMeter(lat1, lon1, lat2, lon2) {
  const R = 6371008.8, rad = Math.PI / 180;
  const dLat = (lat2 - lat1) * rad, dLon = (lon2 - lon1) * rad;
  const a = Math.sin(dLat / 2) ** 2 +
    Math.cos(lat1 * rad) * Math.cos(lat2 * rad) * Math.sin(dLon / 2) ** 2;
  return 2 * R * Math.asin(Math.sqrt(a));
}

async function adresserVed(lat, lon, noejagtighed) {
  const radius = Math.min(Math.max(Math.round(noejagtighed), 25), 250);
  const url = new URL(`${API}/adgangsadresser`);
  url.searchParams.set("cirkel", `${lon},${lat},${radius}`);
  url.searchParams.set("struktur", "mini");
  url.searchParams.set("per_side", "5");
  const res = await fetch(url, { headers });
  if (!res.ok) throw new Error(`HTTP ${res.status}`);
  const kandidater = await res.json();
  if (kandidater.length > 0) return kandidater;
  // Intet inden for radius: fald tilbage til den nærmeste adresse overhovedet
  const rev = await fetch(`${API}/adgangsadresser/reverse?x=${lon}&y=${lat}`, { headers });
  if (rev.status === 404) return [];
  const a = await rev.json();
  const [x, y] = a.adgangspunkt.koordinater;
  return [{ id: a.id, betegnelse: a.adressebetegnelse, x, y }];
}

const lat = 55.67565, lon = 12.56935, noejagtighed = 30;
for (const a of await adresserVed(lat, lon, noejagtighed)) {
  console.log(`${a.betegnelse} (afstand ${Math.round(afstandMeter(lat, lon, a.y, a.x))} m)`);
}

Radius skal være mellem 1 og 50 000 meter, ellers svarer API'et 400 med koden invalid_cirkel. Med srid=25832 er centrum i meter.

I browseren

navigator.geolocation giver position og usikkerhed. Kald API'et med en browsernøgle, der er låst til dit domæne (se Browsernøgler og tilladte domæner):

JavaScript#gps-browser
const API_KEY = "dawa_live_din_browsernøgle"; // låst til dit domæne

navigator.geolocation.getCurrentPosition(async ({ coords }) => {
  const radius = Math.min(Math.max(Math.round(coords.accuracy), 25), 250);
  const url = `https://api.danadresse.dk/adgangsadresser?cirkel=${coords.longitude},${coords.latitude},${radius}&struktur=mini&per_side=5`;
  const res = await fetch(url, { headers: { "X-Api-Key": API_KEY } });
  const forslag = await res.json();
  visForslag(forslag.map((a) => ({ id: a.id, tekst: a.betegnelse })));
}, (fejl) => console.warn(fejl.message), { enableHighAccuracy: true, timeout: 10000 });

Browseren spørger brugeren om lov. Siger brugeren nej, eller tager det for lang tid, så fald tilbage til et almindeligt adressefelt med autocomplete.

Kanttilfælde

  • Til søs eller i udlandet. Ligger punktet langt fra en dansk adresse, giver reverse 404, og cirklen giver en tom liste.
  • Store grunde. Adressepunktet ligger ved indgangen eller vejen. På en gård eller et industriområde kan brugeren stå flere hundrede meter fra punktet og stadig være på den rigtige adresse.
  • Manglende parametre. Både x og y er påkrævet. Mangler en, svarer API'et 400 med invalid_query_parameter.
  • Præcision i svaret. Koordinater i svaret har otte decimaler, som i DAWA. Vil du regne afstande i meter uden omregning, så brug srid=25832. Andre srid-værdier end 4326 og 25832 giver 400.

Næste skridt

Relaterede guides

Markdown-kilde Fejl i guiden? Skriv til os API-reference (Swagger)

Prøv det med en gratis nøgle

2 000 kald/måned på gratisplanen. Intet kreditkort.

Opret konto →