Near is not on
When neither Dad nor Pippa knows a building's door, Pathfinder asks OpenStreetMap, through the Overpass API: a public service with no key. The obvious question is "which entrances are near this point?", and Atocha shows why it is the wrong one. Measured there while the feature was built: 31 entrances within 350 m, most of them other buildings'. A main door tagged a hundred metres away is as likely the museum across the road as the station. The strong evidence is not distance. It is a door that sits on the outline of the building the destination stands in.
One query, three sections
OSMEntrances.query(around:) asks three things in one round trip:
- The venue.
is_infinds the areas the point stands in, and the query keeps the buildings, railway stations and public-transport stations among them, plus any building within 40 m, so a point that falls just outside a footprint still finds its building. Each comes back with its tags and a centre. - The doors. Entrance nodes, and
railway=train_station_entrancenodes, that are members of those venue ways: points on the building's own outline. - The near. Station entrances within 250 m and any entrance node within 150 m.
Overpass answers with one flat list of elements and no labels, so the reader could not tell a door from the second section from one in the third. The query solves that with Overpass's make statement: make split section="doors"; out; emits a derived element of type split carrying a tag, between sections. OSMEntrances.read walks the list, switches section whenever it meets a split, and marks each door onVenue if it appeared in the doors section. A node listed in both sections (a door on the outline is also near the point) is kept once, and stays on the venue. The Santa Justa fixture in the kit's tests, read live from Overpass, is exactly that case: one door, listed twice, on the station itself.
The venue section does a second job. If any venue is a station (building=train_station, railway=station or public_transport=station) or has building:levels of three or more, the reading says isLargeVenue, which is how a place named "Madrid Puerta de Atocha" earns its last stretch.
Scoring a door
OSMEntrances.rank gives each door a score and sorts best first:
| Tags | Base |
|---|---|
railway=train_station_entrance | 45 at a station, else 30 |
entrance=main | 25 |
entrance=yes or home | 12 |
entrance=secondary | 8 |
any other entrance value | 4 |
railway=subway_entrance with no entrance tag | 2 |
access=no or private | dropped, checked before anything else |
entrance=service, emergency, exit, garage, staircase | dropped, unless the node is also a railway=train_station_entrance |
The order of the checks is the table's fine print. Access is read first, so a private door never scores. The station-entrance tag is read next, before the entrance value, so a node tagged both railway=train_station_entrance and entrance=exit still scores 45 at a station: the code trusts the railway tag over the entrance value.
Then: +25 if the door is on the venue, minus distance to the centre / 20, and, when Dad's starting point is known, minus distance from him / 60, so between two equally good doors the one on his side of the building wins. The subway entrance scores 2 for a reason written in the code: a metro entrance near a railway station leads into a different station.
The sketch below runs that arithmetic on the kit test's five synthetic doors around Atocha's centre. A main door 100 m off the building scores 25 − 5 = 20. A plain entrance=yes on the outline, 67 m away, scores 12 + 25 − 3.3 = 33.7, and beats it. A station entrance named "Salidas" 133 m away scores 45 − 6.7 = 38.3 and leads. The service door and the private main door never enter the list. That is the order the kit test asserts.
Levels, honestly
OpenStreetMap's level tag is the only floor information on a door, and Pathfinder takes it narrowly. Only a single non-zero whole number counts. 0 is the street and says nothing about climbing; 0;-1 (a lift between two levels) is ambiguous; neither becomes a level. Santa Justa's one door is tagged level 0, so it arrives with no level at all. And OSM's level is the building's own numbering, while Entrance.level means floors above the street the walk arrives on. Those agree only when the walk arrives at the building's level 0, which is one more reason a door Dad confirmed outranks this one.
Being a polite client of a free service
- Say who you are. The main server answers 406 to a request with no User-Agent. Pathfinder sends
cwkPathfinder/1.0 (personal navigation; iOS). The project notes record it as a gotcha, because a 406 looks like a server problem when it is a client one. - Have a second door.
overpass-api.deis often busy, soEntranceFinderfalls through to the mirroroverpass.kumi.systems. Anything but a 200 with readable JSON moves on to the next server. - Never make Dad wait. Each server gets a 6 s request timeout and 8 s in all. It is asked while the route preview shows, never during a walk, and only when the phone has no fresh answer for that building. The route is already planned from what the phone knows; a door learned in time re-plans the preview, a failed answer changes nothing, and a late one is only remembered for next time.
- Ask rarely. An answer is kept for 30 days, up to 12 doors per building.
- Credit the data. OpenStreetMap is the contributors', under the ODbL. When the approach card shows a door from it, the card says "입구 정보 © OpenStreetMap".
None of this runs in a simulation or under XCTest. The tests read the recorded Santa Justa fixture instead of the network.