OpenStreetMap

Anton Khorev's Diary

Recent diary entries

iD on a phone

Posted by Anton Khorev on 20 April 2023 in English.

Normally the edit button on the osm website is hidden on phones. That’s because you probably don’t have any remote-control-capable editor installed and iD is unusable on small screens. What you’re supposed to do instead is open the Share tool and tap the Geo URI link. This will let you launch any app that understands Geo URIs such as Vespucci.

But to my surprise I was able to use iD on a phone. My note viewer has a tool to open iD on the current map location. It should work similarly to the Edit button except it won’t disappear if the screen is too small. Actually it is hidden by default because too many tools would clutter small screens. But you can always add it back by pressing the ⚙️ button.

When I opened the link, I noticed that iD looks differently compared to what you usually get on a phone. I expected to get that oversized sidebar covering most of the screen. Instead I got everything scaled down to fit on the screen. That happened not because of any changes in iD but because note-viewer opens iD differently.

iD with non-scalable UI

What you usually see after pressing the Edit button

Normally to launch iD you press the Edit button on the OSM website. It opens this link: https://www.openstreetmap.org/edit?editor=id . The button is hidden on small screens but you still can open this URL. Then you’ll see why it’s hidden: the editor is barely usable. However there’s another link you can open to make iD slightly more usable: https://www.openstreetmap.org/id .This link is used by note-viewer for different reasons, you can read about them in my remote control diary entry.

iD with scaled-down UI

What you see after opening the /id link

What’s the difference between these links? The /id link opens just the iD editor. The /edit link opens an OSM website page with iD embedded in it. This page has a tag preventing UI rescaling:

<meta name="viewport" content="width=device-width, minimum-scale=1.0, maximum-scale=1.0" />

You could tell the mobile browser to ignore it by turning on the “Desktop site” option, but scaling is not the only problem. Another problem is touch controls. After scrolling the map view they stop working properly. You can’t select an element by tapping it. But for some reason tapping keeps working as expected on the /id page.

Conclusions

If you’re using a phone, have no editors installed, don’t want to use unfamiliar services but have to do an edit right now, use this link: https://www.openstreetmap.org/id . Things will be small but you can pinch-zoom to make them larger. If you want a proper mobile UI, install an editor like Vespucci. To launch Vespucci from the OSM website, use the Geo URI in the Share panel on the right side of the map. There’s also a Geo URI tool in note-viewer.

In case you wanted to use my note viewer with another openstreetmap-website-based project - now you can. Although most likely you didn’t because there aren’t many of them and they don’t use notes actively. Additional projects that note-viewer is already configured to work with are:

It’s not a surprise that notes aren’t heavily used in these projects. Often you place a note where the map diverges from reality and you can’t edit the map at the moment. But neither OpenHistoricalMap nor OpenGeofiction represent something that is currently real. Right now OpenGeofiction has less than 100 notes, and it’s not obvious if that project even needs notes. Maybe they might use notes to coordinate editing of their collaborative territories?

Now you can also edit the loaded and selected notes by commenting, closing or reopening them. This might be useful to deal with several notes at once. Actually it was one of the original plans for note-viewer. The situations where it’s helpful include someone modifying a lot of notes without a good reason. For example, users sometimes close existing notes without making any map modifications or providing reasons why the notes are irrelevant. They may do this because open notes look wrong (red with x marks) and closed notes look right (green with ticks). Closing a note may look like confirming it. Probably that’s why users sometimes close even their own notes without making any edits. Now it’s possible to quickly deal with such note modifications by searching for a given username, followed by filtering for user’s close actions, selecting all filtered notes and reopening them.

Editing the notes most likely requires you to log in first. This is true for OpenStreetMap but I haven’t checked other servers. To log in or change a server, currently you have to open the About tab. Later I’ll replace it with a menu button. You can also configure note-viewer to use your own osm server there.

In my last diary entry I wrote about putting the requested note ids into url. I said that it’s likely not going to be a problem because ids are stored in the url part that’s not sent over HTTP therefore it doesn’t matter how long is this part, how many ids it contains. That was said about a typical output of neis-one.org note feeds for countries that contain updates dating back up to a week. For a busy country that’s usually a few hundred notes. Concatenated with single-character separators they result in a few thousand character string appended to a url.

Feeds are not the only way to get note ids from neis-one.org. In fact you may no even want to get notes from the feeds because of their one week age limit. There are regular html pages for each country too, one for all notes, another for open notes. They likely contain more notes than the feeds do. The open notes pages, which are of interest to someone who wants to resolve notes in a given country, can have up to ten thousand notes. I added options to open those with note-viewer, along with arbitrary html files. The last two options in the neis-one.org Get … notes for this country dropdown of the XML tab set up the selector (cells in second columns of tables from neis-one.org webpages) and open the webpage that you have to save to a file and then open that file with note-viewer. Unlike the xml feeds, even Firefox won’t start the download automatically.

Is note-viewer able to open ten thousand notes? Kind of. It won’t have to load all of them at once. There’s not even a way to load them at once. Like was said in my last diary entry, each note has to be downloaded with a separate request to the OSM API. That’s why the available batch sizes in note-viewer’s XML mode are so small. Even if there was an API call to fetch several notes at once, like the one for elements, it wouldn’t work for thousands of elements. In case of such hypothetical API call, the ids would have to be sent over HTTP, this is going to limit the request length. But let’s go back to urls generated by note-viewer that can supposedly be of any length. Will note-viewer generate a url with 10k note ids? Yes. We’re at seven-digit note ids now, plus one separator character between ids - that’ 80k characters! 80k characters in your browser’s location bar, will they fit there? Let’s find out:

Link example

Notes of countries

One of possible uses of note-viewer is browsing notes in some area. You can do this using the BBox dialog that lets you get notes in a rectangular area. This is similar to how the note layer on the OSM website work and how the editors like JOSM load notes. And it similarly won’t work if the area is too large or not rectangular. So if you want to get notes in a country, you won’t be able to get them easily. But you may know that there are services that show notes for a given country, like the one by Pascal Neis. There you can select a country and get a list of notes filtered by their status.

That’s how you can get a list of notes for a country. But what if you want to see notes on a map? The list doesn’t contain note coordinates so it can’t be done directly. The situation is similar to looking at a list of user’s notes on the OSM website, something that note-viewer was originally written to take care of. Can it handle country lists now? Actually it can handle any list with note ids. In addition to showing webpages with note lists, Pascal Neis’ site also has Atom feeds. It’s going to be easier for us to get note ids from these feeds. And no, unfortunately, they still don’t contain coordinates.

Any list in our case is an XML file, and note-viewer handling it means that it’s possible to come up with selectors for XML elements that contain note ids. If ids are inside some attributes, the names of the attributes also need to be specified. Click on the XML tab in note-viewer and look below the instructions for neis-one.org to see the inputs for selectors and attributes. You won’t have to use them if you only want to get note lists from neis-one.org, just follow the instructions above.

Getting the list

The instructions seem a bit long. What you’d expect to do is to pick a country, pick a note status such as open or closed, press a button and see the notes in note-viewer. In fact, this is what you do except note-viewer can’t read the feed directly so you won’t see any notes yet. What you’ll see is either the feed file downloading or a new browser tab showing you the feed contents. In the latter case you need to save it yourself. All of this is because of same-origin policy that stops scripts from accessing data across domains unless the server permits it. neis-one.org server doesn’t.

Hopefully it’s not a big problem, just an extra file save and load, like was discussed in my diary entry about getting iD to open notes exported by note-viewer. And the solution is similar: drag and drop, except note-viewer now is on the receiving side. Find the file in the download manager (toolbar button in Firefox, bar under the webpage in Chrome) and drag it to the Read XML file area below the form in note-viewer. This will get the notes into note-viewer, although they’ll load slower than usual because each one of them has to be requested from the OSM API separately.

URLs

Normally, after you press the Load button, note-viewer stores request parameters in the webpage url. This way the request can be repeated if outdated or if opened on another computer. But in case of country feed requests its impossible to do because they can’t be automated. If you want a note-viewer url corresponding to open notes in some country, you are not going to get it. What note-viewer does instead is it saves the exact set of note ids that were present in the feed file when you opened it. If you reload the page you’ll get the same set even if the feed has changed. If you want new notes you’ll have to reload the feed.

Saving every note id in the url makes it rather long. There are ways to reduce its size, something that I’ll maybe do later. First, doing it will make the url unreadable. Also, its length may not be a problem. The length spent on encoding note ids is not subject to HTTP protocol limitations because ids are contained inside the fragment part after #.

One of the things that note-viewer does is showing notes on a map. They are displayed as markers which we can click to find notes in the table. Map markers show us locations and statuses of notes, the rest of note details can be found in the table. But we can dig deeper into these details. From the last diary entry we know that note-viewer looks for links to osm elements inside note comments. When clicked these links display their linked element on the map. That shows us the element geometry, but now we may want to see more details about the element. The map is displayed using Leaflet library1 which supports adding popups to various items that are shown over the base layer. A popup seems like an appropriate place to show the element version, changeset, last editing user and tags.

What’s the best way for us to implement these popups? If we just bind the popup (layer.bindPopup()) to the element geometry on the map, the user would have to click the element for the popup to show up. Sometimes that’s not very convenient to do because of note markers covering the geometry. To make things easier we can open the popup right away (layer.openPopup()) when the element link is clicked. But that’s not the only thing that needs to happen at that moment, and we may find ourselves struggling a bit with Leaflet. Obviously the linked element may be outside the current map view and we need to pan and zoom to it (map.panTo(), map.flyTo() or others). Opening the popup could have done part of this job because by default the map pans to the opened popup. That still doesn’t take care of zooming. But you may think so what, just let the user zoom to the tip of the popup to find the element on the map.

Here comes up our next problem: when the popup is opened at a low zoom level, after zooming it may drift away from the intended place. Anyway we probably want to zoom first and then open the popup. It would have been nice if we could queue the popup opening after the zooming/panning is finished. We’ll have to do that by listening to animation end events. There are zoomend and moveend events, which ones do we need to listen to? Maybe the map is already at a correct zoom level or at max zoom and the element is small. Then the zooming is not going to happen. Will the zoomend event also not happen in which case waiting for it is useless? But maybe the panning is also not going to happen and waiting for moveend is useless too? Apparently the moveend event happens after every call like map.panTo() or map.flyTo(), so we’ll wait for this event and then open the popup.

We’re still not done because for some unclear reason Leaflet sometimes manages to open the popup at a wrong location even after the map finished moving and zooming. Normally we would attach the popup to the geometry with layer.bindPopup() where we can also set popup options. One of the options is autoPan which is on by default as mentioned above. When the popup is opened at a wrong place, the map view scrolls away from the element with this option on, not something we want. With this option off, the popup stays outside the view, not something we want either. Here’s what we can do to solve this problem and what note-viewer currently does:

  1. Add the geometry to the map.
  2. Tell the map to .panTo()/.flyTo() the element if it’s a node or fit the element’s bounding box (layer.getBounds()) into the map view (map.fitBounds()) and wait for moveend.
  3. In the moveend listener create new L.popup() not bound to any geometry.
  4. Set the popup coordinates (popup.setLatLng()) to the current map center (map.getCenter()).
  5. Open the popup (popup.openOn(map)).
  6. Only after the steps above bind the popup to the geometry (layer.bindPopup(popup)).

Now the popup is going to be shown at the center of the element’s bounding box. This is not ideal because this center may be outside the element itself, but at least it’s not at some random location. That’s true unless the user manages to interrupt the map movement by grabbing the map before the animation stops, but they’ll have to do that on purpose and be quick.

  1. Everything written here is concerned with Leaflet v1.7.1 and may not be exactly true for the recently released v1.8. 

One of my goals when developing note-viewer is to try various experimental features. Note-viewer started as a replacement for user’s notes pages. I could have tried changing it in the osm website code but then I’d be constrained by other things. And I want to do some things that are definitely not going to be on the osm website, maybe for a good reason because some of them will turn out to be useless and I’ll throw them away later. In fact, I’ve already thrown away some. If you were using note-viewer before did you notice that round note status icons in the table used to work as radio buttons? They don’t anymore, that was a way to select the date, now you just click the date. What does this date selection do is another topic which we won’t go into here.

What we are going to look into is getting links to various things mentioned in note comments. Actually when the API returns note information it sends note comments in two formats: plaintext and html. However we won’t rely on this html output because users commenting notes enter plaintext and don’t set any links themselves and in the html output everything that looks like a url gets a link, no matter how dubious the site is. We only want links to sites we trust. Obviously one of them is openstreetmap.org. Another one is StreetComplete’s image hosting. Currently that’s all what note-viewer handles, but other sites may get added in the future.

The goal is to get the relevant information without leaving note-viewer. Normal link with a solid underline works as any html link does: when we click it, another webpage is opened. Links with a dotted underline are treated specially. They can be used as normal links with middle-click to open a new page in a new browser tab. Left-clicking them does something inside note-viewer. Clicking StreetComplete’s westnordost.de image links replaces the map view with the linked image. Of osm links those that point to notes, changesets and elements are recognized. Note links do the same thing as if we click a note marker: scroll both the table and the map to show the note. The likely problem here is that the note is not loaded because it’s not among the note query results. I haven’t decided what to do in this case so now it just reports that the note is not loaded. The link itself can still be opened by a middle-click. Links to changesets show their bounding boxes on the map. Links to nodes, ways and relations show these elements. They also open popups with tags and other information.

How does note-viewer detect links inside note comments? When the link is spelled out fully starting with https:// that’s obviously a link. If it matches any of the recognized types, note-viewer replaces the plaintext url with a dotted hyperlink. Such links are found in comments when users copy-paste osm webpage urls. Some apps like StreetComplete also add such links in notes about osm elements (and some like MAPS.ME and its derivatives don’t). But when users write comments manually that’s too long to type. They may write something like “fixed in changeset 123456”. We may want to see this changeset but there’s no link. Could note-viewer have detected it as a link? Since references like this are written in a natural language that may not even be English, we can see that such detection efforts may fail. But we still want to open the implied link and we don’t want to type it ourselves.

Here’s the experimental feature: note-viewer will try to detect such implied links, but only if we tell it to do so. We can tell it by selecting the part of a comment that contains the necessary information. The information is the id represented by a number and the type represented by a keyword such as changeset. So in the example above we could have selected “changeset 123456” like we normally select text (press left mouse button, move mouse, release button) and note-viewer would have tried to detect a link there. In this case it’s obviously a reference to a changeset so that the detection would have succeeded. And it does.

The next step for note-viewer is to present the detected link to the user. One way to do that would have been inserting the link into the comment text. That’s not what note-viewer does. What if we made an incomplete selection that doesn’t have enough information to figure out the correct link? Maybe the word “changeset” wasn’t selected or, worse yet, we didn’t select all of the digits of the id. Then we’d have ended with a broken link inside the comment. We could have tried selecting the right thing again but the link may be in our way. Text selection works differently on links, pressing the mouse button and moving the pointer may result in dragging a link. Even if we succeed, note-viewer would have to clean up the old link intersecting with our selection. But what if it was a legit link put by note-viewer before we had made any selection? Should it be removed? That’s a messy process we don’t want to get into.

Instead of inserting a link, note-viewer shows a popup with it. Actually it’s a popup with several links, one for each possible osm item type plus the detected type. The detected type link is the largest and is displayed right under the mouse pointer. In the best case scenario we can click it right after selecting the text. If the detection went wrong we can select one of the other links below it that refer to other possible items with the same id. And we’ll have to do this if note-viewer failed to detect any type because there will be no default link.

There are some problems with this approach. The obvious one is that we don’t expect stuff popping up under our pointer when we select text, that could be annoying. The first thing note-viewer does to mitigate this problem is to not show a popup when no link is detected. When note-viewer fails to detect a type, the popup still shows up if there’s a number in the text selection. That number is treated as an id with the type manually selectable in the popup. However if there’s no number it’s impossible to come up with a link. Therefore text selections not containing a number don’t cause the appearance of a popup. Actually the current requirements for an id is stronger than that. The number is required to be the last thing in the selection, the only thing that can follow it is whitespace. This restriction makes sense for languages I know but maybe there are some where it’s customary to write a type after an id number, so maybe I’ll reconsider.

If our text selection doesn’t end with a number, the popup won’t bother us. What if there is a number and the unexpected popup shows up? The next problem is that it covers the selected text. And the easiest fix for that is to make the popup transparent. Not very transparent because we want to be able to read the popup itself. Currently it has an opacity of 90%. Another thing to do about the unwanted popup is to make it go away as soon as possible. The popup is opened right under the mouse pointer in order to let the user select the link faster. But there’s also another reason for this placement. The popup disappears as soon as the pointer leaves it. With the popup initially under the pointer it’s possible to close the popup by moving the pointer away in any direction. Had the popup appeared away from the pointer, it would have to be entered first, and without moving the pointer over the popup it could get stuck on the webpage.

Faster selection

With these steps to make the popup unobtrusive the text selection process looks like the following from a user’s perspective:

  • the user selects some text
  • if it wasn’t intended for note-viewer to find references, chances are that nothing pops up and the user can proceed as usual
  • if the unwanted popup appeared, the user can move the mouse pointer away
  • if the goal was to get links and the correct link is detected, the user can click it without moving the pointer
  • if only the id is detected correctly, the user has to select the links by moving the pointer, taking care not to leave the popup; that shouldn’t be difficult because the popup is large enough, although there’s an area for improvement here

All of this was predicated on the user making the correct selection. The selection action itself is more complicated compared to a click. A shaky hand and a button released too soon may result in an incomplete number selection. Then the popup is useless because the id is wrong. The selection has to be performed again with the user spending time again on aiming at the beginning and the end of the phrase. The more time is spent the less advantageous this process is compared to constructing the link by copy-pasting together the id and other parts of the osm website url. If we could get by with just clicking, everything would be easier and faster. But there’s no link to click, that’s why we have to select the text instead.

However there’s a possibility to select text by clicking or, to be exact, by double-clicking. The browser selects a double-clicked word. Our primary goal is to select the id so we double-click the number. But then we don’t select any keyword that may indicate a type. Isn’t that a problem? Maybe, but note-viewer tries to get around it. In case of a double-click the entire comment text preceding the selection is also treated as selected. Isn’t it too much irrelevant text to process? Again maybe, but note-viewer looks for a keyword that is located closest to the number. If there’s a keyword near the number, it doesn’t matter how much stuff precedes it in the selected text. The problems are going to arise only if there’s no recognized keyword related to the number, but the comment has an unrelated keyword far away that we wouldn’t have selected. In this case we’re going to have a false positive with a likely incorrect type of a default link. This is not the biggest problem, we can just select the correct type manually. We probably were ready to do it before our double-click because we knew that there’s no keyword near the clicked number, so we won’t blindly click the default link in the popup.

Now our fastest way to get the link to some osm item with an id is to double-click the id. Note-viewer then looks at the comment text from the beginning up to the clicked id and gives us a bunch of links, maybe gives us the default link right under the pointer, and maybe this link is correct. If that is supposed to work fine why doesn’t note-viewer always looks at the text starting from the beginning of the comment, even when we select text by moving the mouse? The answer is that the user is expected to mainly do double-clicks selections because that’s faster and use mouse-move selections when double-clicks fail to tell note-viewer exactly where to look.

Unwanted focusing on markers

So double-clicks are great, we almost always want to use them. Unfortunately there is one conflict between them and previously implemented note-viewer behavior. Note-viewer shows notes both in a table and on a map. We want to know which map marker corresponds to a given table row and vice versa. When a marker is clicked, its table row is scrolled into view and highlighted. A similar thing happens when the row is clicked. Now we can see the problem: the entire table row of a note reacts to clicks to focus on its map marker. But clicks are also used to select ids. When we select an id by clicking it, the table may pan and zoom to the note location. Maybe we don’t want this. There are ways to deal with this but I haven’t yet decided which one to use and if any one of them is worth using.

One way is to stop focusing on markers when the note row is clicked and introduce some other method of doing it. Maybe put a button there saying “show note on map”, but that would clutter the table with another input element repeated as many times as there are notes. Introducing such elements made little sense early during the development when the comment column had no links in it. The comment column is usually the largest one, therefore clicking the note is usually clicking one of its comments. Even now the comments are mostly free of links, so it still makes sense to focus on notes by clicking them anywhere in the table.

Another way to deal with unwanted map movements is to try to differentiate between clicks. Notes focus on a single click. Text selects on a double click. Aren’t these different clicks that can be distinguished? Yes and no. These are different click events, but double-click event doesn’t replace single-click events, it happens after them. When we do a double-click, a single-click event happens, then after some time another single-click event and after it a double-click. When the first click event arrives, that some time hasn’t passed yet as we haven’t made a second click yet. But that single-click event is enough to activate the map movement. Of course we wouldn’t want to move the map had we knew that the second click is coming. We don’t know that however, knowing about the next click would require a time machine.

Since we don’t have a time machine, we may instead wait for some time for the second click. If after some time it doesn’t happen we’ll focus on the map marker, otherwise we’ll do the popup. But how long is this some time? We don’t know exactly, the specifications say it depends on the environment. Basically, there’s an UI setting somewhere for the user to set how fast they double-click. If we don’t know its value we can guess that it is somewhere around 200 milliseconds. So we could wait after the first click event for, say 300 milliseconds, and if by then a second click event doesn’t arrive, we’d focus on the marker. The problem with this plan is that 300ms is a noticeable delay. The user is going to see this delay between the click and the map movement and it would be annoying.

There are some possible fixes for this delay. Maybe we don’t need to delay everything. Maybe there are different degrees of annoyance between unwanted delay, unwanted pan and unwanted zoom. For example, if unwanted zoom is the most annoying of them and unwanted pan is the least annoying, we can do the panning as soon as the first click happens but delay the zooming. We can also check if some modifier key is pressed during the click. Holding the key may signal to move the map right away or, conversely, to delay it. Of course it’s not obvious which way is better and what key to hold. It couldn’t be Shift though because Shift affects the text selection. But maybe we don’t need to do anything about these unwanted map movements, maybe its ok for them to happen.

Final considerations

Whether this popup feature is useful depends on how well it can detect the references inside the text. This is language-dependent and I still haven’t done any language support other than English. It’s impossible to support every language but mainly it’s the number that needs to be detected, hopefully there will be no surprises with that. You can post some links to notes that you think note-viewer should be able to parse but doesn’t. Or those that incorrectly detected when it’s cleat that they shouldn’t. I probably will add negative keywords like “phone” so that phone numbers often met in onosm.org notes don’t get picked up as possible ids.

Another possible complication is that the references are not necessarily coming in keyword-number pairs. One keyword may refer to multiple id in a phrase like “nodes 123 and 456”. Since note-viewer doesn’t try to get all references and is looking for just one, there shouldn’t be any problems in this case. The number that is the last in the selection, or the only one in case of a double-click, is going to be the one included in the link. Just double-click 123 to get a link to node 123 or double-click 456 to get another node.

Do you find this feature useful or annoying? Maybe you like it so much that you want it on regular osm website pages? It’s possible to make a browser extension for this with a possibility to add links to the context menu.

Remote control for iD

Posted by Anton Khorev on 24 April 2022 in English.

As you remember from my last diary entry, I tried to make note-viewer communicate with editors. It was relatively easy to do with JOSM because JOSM supports remote control. If I want to open a bunch of notes in JOSM, I can make a remote control call for each note to open its url which JOSM understands. But with iD I had to concede a defeat. The easiest way to open selected notes in iD seems to be exporting the notes to a GPX file and opening it as a custom data layer.

map parameter

But since then you may have noticed that iD has appeared in note-viewer’s toolbar. That means I had a rematch with iD and although I didn’t win it either I got at least something. That something is opening a given map location in iD without losing the edits. That doesn’t seems like much and last time we could open iD at the coordinates we wanted. The difference is that now we can tell the already running iD instance to go there. If we look at the location bar while panning the map in iD we’ll see that map in the hash part is being updated with current coordinates. That’s not surprising, map is one of the documented parameters, we can open iD with map set to the place we need and iD will zoom there. But can we update the location ourselves while iD is running? We may try to edit it right in the location bar. For example, the first number of map value is zoom. Let’s change it and press enter. Nothing seems to happen…

Is it possible for a web application to react to such location updates? Yes. For example, note-viewer also updates the location depending on values entered into forms. That allows to link its user notes queries with OSM Smart Menu. The username goes to the display_name parameter. It’s also possible to edit the location manually, replacing the username with another one. If we do this, note-viewer updates the notes. How does note-viewer know that we edited the location? By listening to the hashchange event. If iD also listened to this event, it could update the view in response to map changes. We’ll look at the source code and we’ll find that it does actually listen to this event. And it updates the view. Yet it doesn’t work.

We’ll make it work. Actually it’s easy. Remember my note in the last diary entry that we assume iD to be the selected editor in user’s settings. That’s because /edit urls on the osm website are not iD’s own urls. They open the preferred editor that can also be the one listening to remote control. But even if the preferences are set to iD, the page at /edit is not plain iD. It contains an osm site header after which iD is embedded. And we can see that it’s embedded with a url ending with /id before any hash parameters. That’s the url we need to open. We won’t get the site header but we will get iD listening to location updates.

Now we can have some remote control for iD. We’re not going to alter the location manually of course. We’ll have note-viewer do it for us. First we can replicate the Load map area button that works with JOSM. If we have JOSM running we may want to tell it to load the data at some place. That place might be related to our notes and we may have it in the note-viewer’s map view. We can press the Load map area button in note-viewer and JOSM will load that area. Other data including our unsaved edits are not going to be lost. What is the similar thing for iD? It doesn’t have the load area functionality and it doesn’t need to. Instead it just loads whatever in its view if the zoom is high enough. So we just need to zoom to the place of interest. We already know how to do it. I mean, note-viewer knows, and that’s what the iD: Load map center button is for. What it does is opening a named window with the map parameter set to note-viewer’s map zoom/lat/lon. When pressed for the first time it opens a new window with iD. All the subsequent presses change the location of that window by updating map. iD reacts by zooming to new coordinates and loading the data around the place.

gpx parameter

Another thing note-viewer does through remote control is loading selected notes. We already know that getting it to work by setting the url parameters is not easy. First of all, there are no parameters related to notes. Instead we can try to represent notes by gpx waypoints. There is a parameter for that but in order to convince iD to load our gpx data it must come from an acceptable source. Basically we can’t generate the data in note-viewer and feed it directly to iD, that’s why we had to go through save-file-load-file route which can’t be automated. And it can’t be automated on purpose, because security. What if some evil script passes some data taking advantage of some exploit? That evil script as well as note-viewer will need to convince the user to save and load the data file.

But even if we can’t make iD to load several note waypoints at once, we can still make it with one note. We can get gpx data for a single note from the osm api, which is an acceptable source for iD. Therefore we can alter the gpx parameter to point to that data like we do with map, right? Actually no, we can’t alter gpx this way. We can launch iD with gpx set to an osm api url and it will load. However we can’t alter gpx for an already running iD instance. Well, we can, but iD won’t react to it. If we look again at the hashchange listener, we’ll see that there’s no code to handle gpx updates. So no such remote control for us.

Note Viewer and editors

Posted by Anton Khorev on 13 April 2022 in English.

Looks like my diary here is going to turn into a development blog for my note viewer, which I’m going to call note-viewer in this post. I haven’t came up with a fancier name because I wasn’t sure what this thing was supposed to do other than being an alternative to user’s notes pages. Now I’m adding features that are not strictly for viewing notes. After all, you don’t want to just view notes, you want to do something about them.

Editing the notes along with the data

One of the things that you can’t currently do from my note viewer is to manipulate notes, that is you can’t comment or close them. You have to do those things either on osm note pages or in editors. What you can do is to go to a note page by clicking its id in the table, then you can do anything with the note that the osm website permits. It may not be very convenient though because you have to work with that note in isolation, without seeing related notes and other osm data. This lack of note editing functionality is there because I wanted first to implement a replacement for user’s notes pages. You can’t edit notes from those pages either.

But of course you want to edit the notes, usually along with related data. A note may tell about an error in the data, you edit the data, then you close the note. After that you move to another related note. Related notes are the ones you selected with note-viewer based on some criteria. That could be your own notes for some period of time made about some kind of objects. An example of such kind of use is described in my earlier diary entry. Another kind of note manipulation would be mass commenting/closing/reopening of selected notes, but the tool is not yet ready for that and we won’t look at this usage here.

So we want to edit selected notes alongside the data. For this we of course need an editor. We want to load a bunch of notes in our editor to make them visible and editable. Also we don’t want other unrelated notes to be shown in the editor because we don’t want to be distracted by them. It means that we can’t just download all notes in some area, if that is good enough we wouldn’t need note-viewer to select the notes. The editor has to be able to receive the notes from note-viewer. And the editor is better be able to edit the notes too because we want to close them after editing the data.

Luckily we have such editor. It’s JOSM of course. It has a remote control feature that can be used to receive data from other applications and note-viewer makes use of that. To do this kind of data-and-note editing first you need to enable remote control in JOSM’s options. Then you need to load notes in note-viewer and select the ones you want to edit by ticking their checkboxes. You can tick a range of checkboxes by clicking while holding Shift. Then in the tools panel below the table press RC > Load selected notes button. Now you can switch to JOSM, load the data around the notes (without loading along more notes), edit the data, close the notes and upload the results. Don’t forget to upload the note changes, in JOSM this is done separately, with a button in the notes window.

That was JOSM, the proper editor. But what if we’re using a computer without JOSM or any other editor installed? Note-viewer doesn’t require installation and works fully in a browser with a web server required only to serve static files. (Actually you can kind of install it by copying the files to your local filesystem and opening index.html with a browser) I’m talking about being able to use iD of course. Can we load selected notes in iD? Yes, to some extent. In the rest of this diary post I’ll go over my attempts to make it work.

Making notes visible

First of all, how do we make notes visible at all? On the OSM website there’s a note layer enabled by Layers > Map Notes checkbox. It adds &layers=N to the current url. So if we want to make an osm url for a map with notes visible, this one will do the job. We won’t have any control over the age of notes after being closed but let’s ignore that for now. Since iD is integrated into the website we can hope that iD also shows notes when launched from a map with notes. But it doesn’t work: iD launches without notes being visible. To make notes visible we have to enable Map Data > Data Layers > OpenStreetMap Notes in the right-side menu. That’s not a big deal, we can tick a checkbox once. But that of course is not our end goal.

Can we make one specific note visible? Under the hood, the remote control feature passes notes to JOSM one by one, so that might be our way to successful note loading implementation. On the website you can have a link and a webpage to a element like this: https://www.openstreetmap.org/node/id. When you’re on the webpage, the edit button contains a reference to the element like this: https://www.openstreetmap.org/edit?node=id. (All /edit links in this post assume that you have iD set as a default editor in your osm preferences.) Opening this link launches iD and selects the element for editing. Maybe there’s a similar link for notes? Unfortunately, as you can see, going to a note page (https://www.openstreetmap.org/note/id) doesn’t make the edit button to contain any reference to the note. But we’ll try anyway by constructing the link ourselves: https://www.openstreetmap.org/edit?note=id. And we’ll find out that the note is not going to get shown but the map inside iD pans to the note’s location. If we enable the notes layer after opening the link, we’ll see the note in the center of the screen. This works even if the link doesn’t contain the #map= part referencing the location. But none of this helps us much because the note is not highlighted in any way inside iD and we can’t add another note to a would-be highlight. We want to highlight several notes at once.

While we’re poking edit urls, it’s worth noting that there’s an API documentation for iD. It doesn’t mention notes though, so we made a discovery of an undocumented feature. It didn’t help us and now we need to look for something else. If there’s no way to tell iD from outside to display a selection of notes, maybe we can tell it to display something else at the locations of the notes? There’s a gpx parameter, how about we put gpx waypoints in place of notes and make iD show us the gpx data? We can put links to notes inside the waypoints or we can just display the note layer and pay attention only to the notes coinciding with the waypoints.

The gpx parameter

Let’s try to open some gpx data that already exists. There’s a link on the Notes/Advanced_use wiki page that lets us download notes inside some area as gpx. We’ll urlencode it and put it in the gpx parameter like this. What do we get? 500 Internal Server Error: Application error… Maybe the data is wrong? We can go to Map Data > Data Layers > Custom Map Data in iD, click ... to edit custom data settings and enter the url there. Now the waypoints-in-place-of-notes are loaded. We can load the gpx data from a file too, so if everything else fails, we’ll have to export the selected notes from note-viewer into a file and load this file in iD.

Can we pass anything to the gpx parameter without the site crashing? Empty value https://www.openstreetmap.org/edit?gpx= crashes, adding editor=id like in the documentation still crashes, not urlencoding the gpx url like in the documentation again crashes. If we can’t open iD with a gpx parameter, we may try to automate away the save-to-file-open-file bit in some other way. But we’re probably using the gpx parameter wrong. Remember the undocumented note parameter? It’s actually an an osm website feature, implemented here. And we see the gpx parameter nearby. Doesn’t it accept a track id like note accepts a note id? Yes, it does, it’s an id of a track uploaded to osm like the ones you can find on Public GPS Traces page. That’s not what we want, we’re not going to upload our fake track just to see it in iD. So gpx parameter won’t help us.

That was osm’s gpx parameter. However, standalone iD has its own gpx parameter. We found out that osm’s gpx is not doing what the iD’s API documentation says. Maybe we should use the iD’s one, if we can get to it. Standalone gpx parameter should be passed through the hash part of the url. Let’s try passing something simpler through the hash, for example let’s pre-fill the changeset comment like this. If you make an edit and press upload, you’ll see our “testing123123” comment. So passing parameters through hash works. Can we pass our original gpx link through the hash? Yes, we can.

Now that we figured out how to launch iD with gpx data displayed, we can try to avoid exporting notes to a file. We’d like to open gpx in iD like we open notes in JOSM with one click of a button. For this we need to generate an url with gpx data that iD will accept. We can construct a data url, data:text/xml;… url with gpx data encoded. That of course is not going to work because security. Same would happen if we paste the url into Custom Map Data dialog. Can we try a blob url constructed with URL.createObjectURL() that I use for gpx export to file? Same result.

Did we lose the fight with the gpx parameter? Do we have to import our note track from a file? If we examine iD’s code, we’ll see that any url we pass eventually goes to fetch(), and if fetch() rejects the url, there’s nothing we can do about it. The fetch call is buried inside npm-style ten-line import which is mostly there to throw an exception when the fetch response is not successful. (Excuse me, it’s actually an eight-line import. Ok, it’s part of a bigger library used for other things.) The exception is then ignored by iD. I actually skipped part of the story above where I passed a damaged link to #gpx and was wondering why nothing happened. You have to look at your browser console for error messages. There you’ll find that iD wants “only URLs with network schemes”. Note-viewer is not a web server, so that’s out of the question. Looks like the gpx parameter won’t help us unless we find a way around Content Security Policy.

Now let’s see what iD accepts as custom data. We tried gpx first because it was the name of the related url parameter. But iD accepts other formats too, and osm api can produce other formats. Let’s go over api formats following the example in the wiki for /api/0.6/notes. Which ones are supported?

We got gpx and json, and, as you can see, they are displayed slightly differently. When displaying json, iD doesn’t render any labels for points. This is likely because geojson feature’s properties object has no standard definition and iD doesn’t know what to render. If we generate our own json, we can put there something that iD likes better. But for now we’ll stick with gpx. Then of course you’ll notice that labels in gpx as produced by osm api are ugly, containing html tags. Again, if we generate our own gpx, we’ll put something nicer there. The difference is that we know where exacly that there is, because gpx waypoints have well-defined name and description tags. There’s also kml support in iD, but osm api doesn’t support it.

Why do we care about osm api support for these formats? If we’re generating our own file with notes, we don’t have to care about the api. These api urls are just for testing. However, if we could convince the api to output exactly the same set of notes that we selected in note-viewer, we could feed that output to iD through #gpx, because it comes from an acceptable protocol and source. We wouldn’t have to generate a file then. Can we do it? The examples above that output note data weren’t very selective. They output all notes that fit some criteria, like being inside a bounding box. But we need a set of notes selected by the user. Basically we need an api call that would accept a list of note ids and output their gpx waypoints. There are only two api calls that can output gpx for a set of notes: bounding box and search. There’s also a feed call, but it’s rss and has no advantages over a bounding box. Neither bounding box nor search accept note id parameters. Which calls do? The usual read one. But it only accepts one id. We’d need something like multi fetch for elements but there isn’t one for notes. We can open only one note like this. For it to be useful we’d need to convince iD to display multiple custom data layers, one for each note. I guess it can’t do that. Looks like yes, we lost our fight with #gpx. See also this question on help.openstreetmap.org.

Drag and drop

What else do we have besides going to Custom Data’s open file dialog? We have drag and drop. We can drag a gpx file and drop it into iD’s tab and iD will render the data. We still have to create a file and then find it in our filesystem with a file manager that supports drag and drop, then actually drag it into iD. That’s slower than one press of a button to transfer notes with remote control. Can we use drag and drop with less ui fiddling? Knowing that there’s HTML Drag and Drop API that lets us transfer various data types by dragging html elements, we may think that this is the way. We won’t need to create any file, we’ll just make some element draggable, put a dragstart event listener on it and set our notes data in the listener with whatever type iD wants to receive: text/xml or maybe application/gpx+xml. It’s implemented in note-viewer now on gpx export button. In addition to pressing it you can drag and drop it. Problem solved?

Nope. For this thing to work, iD needs to receive the data in its expected format. And setting the type won’t help us because iD expects files. If your drag and drop data doesn’t contain a file, it’s ignored. That makes the draggable button almost useless for now. Maybe later iD developers will change their mind and implement receiving draggable data without files, so I left this feature in. One thing you can do is select text/plain as a type, then note-viewer will pretend that it’s sending plaintext, although it’s still going to be xml. But this makes more apps being able to receive the data. For example, you can drag it into html text inputs like <textarea>. That a very limited use, often not even a text editor is able to receive such data. I guess we failed again?

Not quite. We still can drag stuff to iD without leaving our browser for a file manager. Dragging the export button may not help us, we’ll have to press it to create a file. But then usually some download manager pops up. If file is downloaded we can drag it from there. It will also go to our download folder which we’ll have to clean up later. Dragging is easier to do if we have iD opened in another browser window. If iD is in the same window as note-viewer, we have to switch to iD’s tab in the middle of the drag operation. In Firefox we can drag the data over to tab title of iD tab, but don’t drop it, hold it over the title until the browser switches to the tab, then drop it inside iD. This may work differently on other browsers and maybe its easier to go through the Custom Data file dialog. Let’s suppose that we can open our gpx file in some way.

Finally getting to see our notes in iD

Our workflow with iD starts like this: download notes with note-viewer, select some of them, export them to a gpx file, open the file in iD as Custom Map Data. We still don’t see the note pins in iD, but that’s hopefully easy to fix. We can actually do the same thing and load a file in JOSM instead of using its remote control. We won’t see the note pins either but we’ll see buttons next to waypoint markers that let us open associated links. Those links lead to osm note pages. However we won’t see similar links in iD. iD apparently doesn’t know what to do with <link> elements in gpx. Therefore we can’t see the actual notes yet. Instead, we can enable all notes, like we did earlier with Map Data > Data Layers > OpenStreetMap Notes. Now for each note of interest we can see a pink circle marker from gpx Custom Map Data and a note pin inside it from OpenStreetMap Notes. Pins that are not inside circles correspond to notes we didn’t select, which we can ignore. We can click a pin to select its note for commenting or closing. To make sure that a pin corresponds to a selected note we can compare the text label of the pink circle marker with the note comments. By default only the first comment is displayed next to the circle marker. That’s because only the first comment is saved as a gpx waypoint description. We can change that during the gpx export in note-viewer, picking all comments instead of first comment, but the labels may become too long.

What else can we change during the export? There’s a connections option. Since we’re exporting notes to gpx, we can take advantage of the format and pretend that this is some kind of a track. Then we’ll have a line connecting circle markers. Maybe it’s going to be easier for us to go to the next note by following this line. To get the line, change without connections to connected by route or connected by track. Route and track are different connections allowed by the gpx spec. Route actually makes more sense but may be less supported by applications or less convenient to work with. For example, JOSM keeps routes in separate layers, making three layers per file when saved as connected by route. Saving as connected by track will result in two layers. From iD we may not care about this.

What we do care about is seeing all of the note pins. Here lies another problem mentioned earlier: the age of the notes. You know that old closed notes disappear from the map. They don’t actually disappear but most of note viewing tools show resolved notes that were closed no earlier than a week ago. 7 days is the default value for the closed parameter in osm api calls. One exception to this is user’s notes pages https://www.openstreetmap.org/user/username/notes. There all notes are shown. Since note-viewer was developed to be an alternative to these page, it also defaults to showing all notes. You can of course choose not to fetch old notes or not select them for viewing in the editor, but what if you do? Well, you won’t see them, you’ll only see their gpx circle markers, not their note pins. Therefore, you won’t be able to comment or reopen them from iD. For JOSM this doesn’t matter. When JOSM is told to open a note with remote control, the note is going to be displayed no matter what it’s age. But JOSM also has an option to control the age limit when downloading all notes inside an area. You can find it in Edit > Preferences > OSM Server > Max age for closed notes. Is there a similar option in iD? There’s one deep inside iD’s code, but it seems to be unused. With this and with lack of support for waypoint links, its going to be difficult to use iD for reviewing closed notes. Hovewer, that’s likely not the most common use of notes, and when you need it, you can use JOSM instead.

This is an answer to our very first question of this post about iD: yes, we can use note-viewer with iD, but it’s going to be less convenient, especially when working with old notes.

Note Viewer update

Posted by Anton Khorev on 30 March 2022 in English.

I’ve fixed some of the limitations of my note viewer that were discussed at the end of this diary post.

  1. Now you can use this tool as a more general interface to /api/0.6/notes/search OSM API requests. Providing a username is no longer required, and it’s possible to do comment text searches and limit the results to date ranges.
  2. Search queries are encoded in URLs. That opens some additional possibilities.
  3. Earlier you could accidentally load too much data that would slow down your browser too much. There weren’t an obvious way out of this situation because the tool always tried to restore the results of the last request. Now it shouldn’t be a problem - just open the page without the query in the URL (without everything after #). Or press the (x) button on the top.
  4. You can open several different requests in different windows at the same time. There’s still one problem left: opening the same request in different windows is not guaranteed to work.
  5. Since queries are stored in URLs you can share links to them. Also you can generate links without typing stuff into the search form. For example, you can use OSM Smart Menu browser plugin to switch to user’s notes as shown by this tool from any webpage that the plugin associates with the user. You need to add this URL template in OSM Smart Menu settings: https://antonkhorev.github.io/osm-note-viewer/#mode=search&display_name={osm_user_name}

Раз уж мне пришлось в двух предыдущих записях обратиться к теме заметок, я выложу из черновиков ещё одну запись на эту тему. Она станет внеочередной записью из серии про OsmAnd и недвухэтапный ввод POI, и речь в ней пойдёт об одной из разновидностей заметок, которые я оставляю из OsmAnd при таком вводе.

Заметки из OsmAnd оставлять приходится, потому что не всё, что нужно проделать с осмовскими данными, возможно или целесообразно пытаться сделать из самого OsmAnd. Необходимые действия можно отложить, оставив в качестве напоминания заметку, в которой описаны либо сами действия, либо наблюдаемая ситуация на местности, если действия ещё не определены или их долго описывать. Именно из-за последнего варианта я и пишу эту запись, так как на заметки могут среагировать другие участники, не зная, что именно по моему мнению надо сделать.

Рассматриваемая здесь разновидность заметок ставится мной на месте отмеченной POI, и содержит следующее утверждение: POI на этом месте не видно, и непонятно, где бы она могла быть. То есть, тут не просто не наблюдается отмеченного на карте заведения, но и само место выглядит для него неподходящим. Если отмеченного заведения не видно, часто это означает, что оно закрылось и, возможно, на его месте открылось другое. Но там, где я ставлю рассматриваемую заметку, я подозреваю, что заведения никогда и не было.

Неподходящее место

Что такое неподходящее место для заведения? Чаще всего это отсутствие входа в здание со стороны улицы. Если в осме отмечен магазин или общепит, посетители должны туда как-то попасть. Обычно это делается посредством прохода через дверь. Если двери на местности не наблюдается, то и проходить, скорее всего, некуда, как сейчас, так и раньше. Тут, конечно, надо учитывать, что некоторые двери — это бывшие окна, и наоборот, так что нынешнее окно могло быть дверью в существовавшее раньше заведение. В первую очередь это касается, конечно же, окон первого этажа, на котором большинство заведений и расположено.

Но не с любым окном легко проделать операцию переделки в дверь. Если окно расположено достаточно высоко, то есть уровень первого этажа существенно выше уровня земли, к нему придётся пристроить лестницу. Явление это не такое и редкое, иногда лестницу пристраивают и до второго этажа. В нашем неподходящем месте, однако, ни лестницы, ни следов её былого присутствия не наблюдается.

Помимо первого и второго этажа некоторые заведения могут занимать также цокольный. Там они в моей местности встречаются даже чаще, чем на втором. Но обычно там, где я ставлю рассматриваемые заметки, подходящего места на цокольном этаже тоже нет, или нет самого этажа.

Иногда решить, что место неподходящее, можно заглянув в окно. Может стать ясно, что там, например, жилое помещение, и что такая картина наблюдается на протяжении всего этажа. Если при этом на карте там отмечен магазин, его наверняка в этом месте нет и не было, так как переделки торговых помещений внизу здания в жилые — явление не слишком часто встречающееся.

Действия

Почему в такой ситуации я просто не удаляю POI? Если POI была отмечена в том месте, где её быть не могло, весьма вероятно, что она была в другом месте. Данное же место было выбрано по ошибке, причин для чего бывает достаточно, например, выбор соседнего дома вместо нужного. А если POI была в другом месте, то, возможно, она и сейчас находится в другом месте, и тогда её нужно не удалить, а подвинуть. Подвинуть точку из OsmAnd я не могу, тем более что в данном случае я даже не знаю, куда её двигать. Чтобы это знать, реальное место надо сначала найти, а для этого неплохо бы знать, как оно выглядит. Если отмеченная POI не является каким-нибудь известным сетевым магазином типа «Пятёрочки», с этим тоже могут быть затруднения.

Что в итоге я собираюсь сделать, когда вспомню про свои заметки? Примерно то же, что описывается в недавней записи про телефоны. Я могу посмотреть на старые панорамы места, когда точка была добавлена, чтобы убедиться, было ли там тогда соответствующее заведение. Если я его увижу, то всё просто: точку можно удалить, также как и точку телефона в записи про телефоны. Разница с ситуацией из той записи, однако, есть. Там обнаружение телефона на старых снимках было ожидаемым результатом. Здесь же я ожидаю не увидеть заведение на снимках.

Что я собираюсь сделать, если заведения не видно ни в настоящий момент в реальности, ни на старых панорамах? Посмотреть на панорамах вокруг места точки, в первую очередь — на соседние здания. Один из вероятных вариантов — заведение было в соседнем здании, а добавлявший его в осм участник ошибся с выбором места для точки. В этом случае в настоящий момент заведение уже закрыто, так как иначе я бы увидел его в реальности — на соседние здания я бы тоже посмотрел, и при обнаружении заведения там добавил бы заметку «подвинуть». Но раз его там нет, хотя раньше оно там было, я бы всё равно подвинул точку на прежнее реальное место заведения, но убрал бы теги под префикс disused: или ему подобный. Если на том месте уже другое заведение — я бы точку с ним объединил.

Другой вероятный вариант — поблизости на панорамах заведение тоже не обнаружится. Это может означать, что заведение запрятано в глубине здания или с другой его стороны, а, значит, есть вероятность, что оно существует и сейчас. Тогда имеет смысл поискать его в интернете по названию и/или адресу. Может быть контактные данные даже указаны на точке, тогда я ими воспользуюсь, чтобы открыть, например сайт, убедиться, что он обновляется, и найти на нём хотя бы адрес. Если сайт сдох — заведения, вероятно, больше нет, хотя лучше проверить и контакты в соцсетях. Если адрес указан другой — заведение, вероятно, переехало. В этих случаях его точку можно удалить. О том же, что точку лучше не трогать, могут свидетельствовать указания типа «мы находимся на третьем этаже в офисе 32» или «нас трудно найти на месте, звоните нам по телефону».


Итак, написанное выше относилось к заметкам типа POI на этом месте не видно, и непонятно, где бы она могла быть, и написано выше про то, что такие заметки означают, и что собираюсь с ними делать я, когда до них доберусь. Если же до таких заметок раньше доберётесь вы — теперь и вы знаете, что с ними делать.

Note Viewer

Posted by Anton Khorev on 22 March 2022 in English.

Sometimes you add a bunch of notes and need to look at them later. Or someone adds notes and you need to look at their notes. Or someone does something with a lot of notes like closing without a good reason or leaving useless comments and you need to look at them. How do you do it? There is a link from the profile page to user’s notes. You go there and you’ll see a list of notes with their opening comments and current statuses. The problem is it’s cumbersome to use. You don’t get to see where the notes are located unless you click each one separately, then you’ll see only that one note.

What if we want to see all of the notes? Actually, how about we just see everything known about the notes on one page? That’s what I’ve done here. You can enter a username and load as many notes as you need. They are going to be displayed in a table with all their comments and status changes. Also their markers are going to be added to a map on the same page. You can find the marker corresponding to a table entry by clicking it and vice versa. There are also some commands available below the table, like loading selected notes into an editor with remote control.

Another problem with the notes page on the osm website is when we don’t want to see all of the user’s notes. What are the user’s notes anyway? Note records in the database don’t have direct references to users. The references are found in comment and action records. So the user’s notes are the ones opened, closed or commented by the user. But what if you only want to see only the notes that you’ve opened? On my notes page you still have to load all your notes because that’s how the OSM API works. After that you can use the filter to hide unwanted notes. To see only notes you created yourself, use this filter expression:

user = YourName, action = opened

It’s possible to do more elaborate filtering. Maybe you want to check if someone closed notes opened by you. Here’s a filter for that:

user = YourName, action = opened
*
user != YourName, action = closed

Now let’s talk about the limitations of this tool. Displaying everything on one page may slow down the browser if there’s too much information. Normally, the next batch of notes is downloaded when you scroll down to the end of the table. This feature is turned off after a large enough number of notes is fetched. You can also turn it off yourself using the checkbox in the download form. Also because the data is stored in the browser’s local storage, it’s possible to run out of available space there. Couple of thousand notes should be fine though. And it’s assumed that there’s only one instance is open, so only one set of notes is remembered by the browser. All of these limitations are fixable and probably soon will no longer exist.

Here’s the source code.

Here’s a post in Russian describing one of the applications of this tool.

Телефонное наследие

Как-то раз я вводил очередную порцию данных POI. При том способе, которым я обычно действую, я выясняю, где находятся их входы. Далее, при вводе, я добавляю или изменяю данные так, чтобы было понятно, где находятся соответствующие POI входы. В простейшем случае для этого достаточно поставить точку POI рядом с тем местом, где находится вход в здание, через который можно пройти в редактируемое заведение. Подробнее об этом и о более продвинутых способах ввода можно прочитать в записи про геометрию POI. Большая продвинутось обычно включает в себя также отмечание самого входа как точки entrance=yes, входящей в контур здания. Нередко есть смысл это сделать, так как некоторые входы в здание уже отмечены, и тогда лучше доотметить их все.

Так вот, в тот раз именно доотмечанием входов я и занимался. То есть, мне понадобилось добавить POI в здание, где часть входов уже была отмечена, вместе с чем было лучше добавить в контур здания и неотмеченные входы. Но точки entrance это не единственное, что бывает в линии контура. Помимо задающих геометрию углов здания, там бывают и точки прочих объектов, находящихся в или на стене. Ими могут быть, например, почтовые ящики или мемориальные доски. Ясно, что было бы неплохо, чтобы все обозначения этих объектов шли в том порядке, в котором идут и сами объекты в реальности.

То есть, если в реальности есть входная дверь, и слева от неё находится почтовый ящик, а справа — мемориальная доска, мы захотим, чтобы и в осме было так же. А именно, в линии контура слева направо должны присутствовать точка ящика, затем точка входа, затем точка доски. Если точки входа ещё нет, её надо добавить между ящиком и доской, чтобы она располагалась относительно правильно. Но также точку входа надо добавить на то место, где вход собственно и находится, чтобы она располагалась и абсолютно правильно. А это сделать не удастся, если точки ящика и доски сами в достаточной степени расположены абсолютно неправильно.

Короче, если нам надо воткнуть в стену здания входную дверь, а рядом с местом втыкания уже обозначено что-то ещё, нам придётся, во-первых, выяснить, с какой стороны от двери это что-то ещё находится, а, во-вторых, возможно, подвинуть это в сторону, чтобы дверь можно было поставить на место. И в тот раз мне пришлось подобным заниматься. В роли чего-то ещё, отмеченного рядом с местом входа, выступил телефонный аппарат amenity=telephone. Это такая штуковина, которой в далёкие времена до распространения мобильных телефонов находящиеся на улице люди пользовались для голосовой связи. Сейчас времена уже другие, и подобные штуковины не особо нужны, и их, соответственно, демонтируют. Я даже не уверен, остались ли они где-либо в Петербурге. Где-то я один, кажется, видел.

Так вот, тот раз. В осме на стенке был нарисован телефон, там, куда я хотел добавить дверь. Мне надо было решить, куда подвинуть телефон, в существовании которого я не был уверен. Конечно, до того я побывал на месте, и, значит, видел, есть ли там телефон или нет. Но когда мапишь одну разновидность объектов, привыкаешь не обращать внимания на другие, и я не запомнил, видел ли я рядом с дверью телефон. Сами POI я маплю, конечно, не по памяти, я делаю их фотографии, причём так, чтобы на них оказался вход в заведение. Но в тот раз на том месте мне не повезло: тот участок стены, где мог быть телефон, в кадр не попал. А что это за участок? Раз я не помнил, видел ли я телефон, я не знал и где он мог бы быть. Но узнать это легко, посмотрев, например, на Яндекс.Панорамы, что я и сделал. И на них я увидел телефон справа от двери. Панорамы того места, правда, датируются 2019-м годом, а сейчас 2022-й.

И вот мне пришлось заниматься довольно глупым делом: разглядывать на старых фотографиях то, что скорее всего уже не существует, и куда-то двигать это в осме, чтобы оно не мешало мапить другие вещи. А сколько реально таких телефонов осталось? Не пора ли пройтись конкретно по ним и выпилить лишние осмовские точки? Я решил, что пора.

Подготовительные рассуждения

Собственно, почему существуют такие места, где телефон отмечен, а в реальности его нет, иногда лет даже десять как нет? Видимо, потому что раз на месте его нет, то вроде как и мапить нечего, ну или, по крайней мере, реагировать не на что. Чтобы понять, что надо сделать правку, при обходе надо не только смотреть на объекты в реальности, но и сравнивать их с текущими данными. Так оно получается само собой при подробной отрисовке небольшого участка, например, в Vespucci. Но таким образом действовать долго, и до многих мест очередь дойдёт нескоро.

Если хочется собирать данные, проходя существенные расстояния, бывает легче действовать таким способом, который позволял бы не отвлекаться на сравнения с текущими данными. Например, при своих проверках POI, когда я ищу заведения, а не объекты инфраструктуры, я фотографирую также те места, где заведения могли бы быть, но их нет. Это непосредственно наблюдаемые помещения заведений, которые заброшены или на ремонте, а также закрытые двери, не являющиеся входами в жилые помещения. Потом я сравниваю эти фотографии со своими же старыми фотографиями тех же мест или с панорамами. Так, если в данных POI есть, на старой фотографии — тоже есть, а на новой — нет, я становлюсь уверен, что с POI надо разделаться. Без сравнения старого-нового снимков уверенности было бы меньше: вдруг я POI просто не заметил.

Если применять вышеописанный способ к телефонам-автоматам, на местности придётся обращать внимание на останки демонтированных телефонов. Задача эта не то чтобы невозможная, но более сложная по сравнению с тем, что приходится делать для заведений. В конце концов, демонтировали телефоны не для того, чтобы виднелись от них следы. Но следы иногда заметны, если знать, на что обращать внимание. Легче всего увидеть другую окраску стены в том месте, где была кабинка. Если стену с тех пор покрасили, искать придётся дырки или штырьки для крепления и оборванные провода для подключения. Шансы пройти мимо и не обратить на всё это внимания высоки.

след от ранее существовавшего телефона-автомата

Типичный след бывшего телефона.

В общем, целенаправленно искать места бывших телефонов, не ориентируясь на информацию о том, где телефоны были, довольно сложно да и незачем. Мы-то хотим убрать обозначенные телефоны, отмечать новые и обновлять существующие мы не собираемся. Так что наша задача непосредственно связана с текущими данными, и мы ими воспользуемся. Для упомянутого выше обхода заведений приходится действовать иначе из-за добавлений/обновлений и не только. Бывают места, где заведений много, в них пришлось бы потратить также много времени на сравнения. Сами сравнения при этом не ограничивались бы проверкой присутствия/отсутствия, нужно проверять тип, название и прочие атрибуты. При обходе смотреть на текущие данные заведений неудобно. В Vespucci большие участки обхода грузить неудобно, у него начнутся тормоза. В OsmAnd и подобных приложениях нет гарантий, что все POI будут видны.

В отличие от сказанного выше, для обхода обозначенных телефонов OsmAnd вполне подойдёт. На самом деле, подойдёт практически любое приложение, отображающее осмовские данные для конечного пользователя. Телефоны расположены не так плотно, как заведения, так что с их отображением OsmAnd справится. Никакие теги на них мы сверять и обновлять тоже не будем. Помимо OsmAnd’а и аналогов мы могли бы воспользваться StreetComplete. Для этого надо, чтобы StreetComplete был установлен на устройстве, а его может и не быть, потому что это приложение не для просмотра карты, а для определённого вида проверок и правок. Для проверок нам хватит и OsmAnd’а, а правки на месте мы делать не будем по причинам, о которых рассказывается далее.

Первая причина должна быть уже понятна: если мы видим в данных присутствие, а на месте отсутствие телефона, может быть мы смотрим не на то место? Телефон может существовать и сейчас, но не там, где мы его ищем. Например, когда его точка не вставлена в линию контура здания, она может находиться внутри. Так она могла быть поставлена изначально, или оказаться там в результате сдвига здания. Что если телефон на самом деле внутри здания? Если же мы посмотрим на старый снимок и увидим телефон всё-таки снаружи, там, где его сейчас нет, уверенности в необходимости его удаления у нас будет гораздо больше. Без этого нам придётся искать следы демонтирования, которые могут быть труднозаметны или вообще отсутствовать. В общем, нам может помешать либо недостаточная точность данных, либо недостаточные возможности проверки на местности. И если потом, за компом, нам будет легко свериться со снимками, да и правку будет сделать легче, то лучше так и поступить.

колонны у подземного перехода

Попадаются и такие места, где догадаться о (бывшем) расположении телефона сложно. Где он был: на стене первого этажа? на одной из колонн? с какой стороны одной из колонн? Придётся обойти каждую из них кругом.

То, что правку за компом будет сделать легче, — это ещё одна причина, теперь чисто техническая. Если точка телефона на карте есть, а в реальности телефона нет, какой должна быть правка? Вроде как удалением точки, но на самом деле не только. Точка, вероятно, входит в линию контура здания, и удалить её нельзя, не изменив эту линию. У редакторов POI с этим могут возникнуть проблемы, потому что такие редакторы ориентированы на правки тегов, а здесь нужно править также геометрию. OsmAnd, в частности, имел обыкновение вылетать с неизвестной ошибкой при закачке такого удаления. В MAPS.ME (и, вероятно, в Organic Maps) проблемы решаются просто невозможностью удаления и предложением создать вместо этого заметку.

Проблемы, описанные выше, заключаются в сложностях с редактированием геометрии, являющейся чисто формальной. Точка телефона обычно вставлена в прямой участок стены, потому что именно к прямому, а не, например, к закруглённому, в реальности легче этот телефон прикрутить. Удаление такой точки по сути форму стены не изменит, так что редактору надо лишь суметь исключить точку из линии, а настоящие средства работы с геометрией не нужны. Но это верно, когда точку надо удалить действительно из прямого участка, с упомянутым выше закруглением надо действовать иначе. Тут уже точка телефона не будет лишь формальной частью геометрии.

Хотя телефон в непрямой стене мне пока ни разу не попался, это не единственный способ для точки выступить реальной геометрией. Мне попалось кое-что другое. Точка ведь не обязана входить лишь в одну линию, а, значит, телефон не обязательно будет геометрией только здания. И один из отсутствующих телефонов являлся также углом обозначенного полигоном заведения внутри дома. Такую точку тоже нельзя удалять, но чтобы об этом узнать, надо увидеть её линию. Редактор, встроенный в приложение просмотра карт, отображает не все линии, в отличие от десктопных JOSM или iD. OsmAnd контуры POI рисует, но только если нажать на иконку POI, а она может находиться на расстоянии от нашей точки. Так что о линии контура POI мы можем не узнать.

Допустим, о реально-геометрической роли точки телефона мы знаем. Тогда вместо удаления самой точки нам надо удалить её теги. Реакторы POI обычно не любят и такую операцию. Они хотят, чтобы у точки POI был тип. Точка POI — телефон — в данных уже есть. Редактор может дать поменять тип, которым в данном случае является тег amenity, но не удалить его, или сделать удаление неудобным. OsmAnd тип удалить позволяет, но надо ещё догадаться, как именно. Отгадка: в диалоге тегов, в поле тип надо не выбирать что-то из выпадающего списка, а редактировать его значение как текст и полностью его удалить, стереть все буквы. OsmAnd потом спросит: «Как же так? Неужели вы хотите сохранить элемент без типа?» Да, хотим.

английская телефонная будка

Здесь телефона больше нет, но нельзя сказать, что не осталось ничего, достойного быть отмеченным на карте. Если так, то и удаление — не то, что следует делать.

Короче говоря, разбираться с редактированием лучше потом, в нормальном редакторе, а на месте просто поставить заметку, в которой написать, что телефон не обнаружился.

Переход к действиям

Действия на месте для каждого телефона такие:

  1. Найти в данных телефон, которого, вероятно, нет в реальности.
  2. Пойти туда и посмотреть, есть ли там на самом деле телефон.
  3. Если его нет, добавить соответствующую заметку.

И далее за компьютером:

  1. Загрузить в редактор заметку и данные вокруг неё.
  2. Открыть снимок соответствующего места, сделанный тогда, когда телефон предположительно существовал, и посмотреть, есть ли на нём телефон.
  3. Если телефон на старом снимке виден, удалить его точку и закрыть заметку.

Разбираться по этой схеме мы будем не с каждым телефоном в отдельности, а с пачками. Это несколько повлияет на последовательность шагов.

Действия на месте

Начнём с поиска телефона в данных. В моём случае телефон, которого, вероятно, нет — это любой отмеченный телефон. В другой местности ситуация с демонтажом телефонов может быть иная, и искать их может понадобиться по каким-то признакам. Здесь мы будем искать все телефоны подряд. Сделаем мы это с помощью OsmAnd. Нажмём на кнопку-бургер в левом нижнем углу, далее выберем Поиск. Далее воспользуемся строкой поиска, а не категориями — неочевидно, к какой категории телефоны относятся. В строке поиска наберём “телефон”, а в результатах выберем Телефон — Сервис. Далее должен появиться список ближайших телефонов, а над ним кнопка Показать телефон на карте, на неё и нажмём. Теперь на карте уже на любых масштабах будут выводиться иконки телефонов, и мы сможем узнать, куда нам идти как в общем — к скоплению иконок, — так и в частности — к отдельно взятой иконке места обозначенного в осме телефона.

скриншот OsmAnd с иконками телефонов на карте

Результаты поиска телефонов в OsmAnd, отображаемые на карте.

Так мы наметим себе маршрут обхода нескольких точек. Для каждой из этих точек нам надо найти соответствующее место в реальности. Поскольку самого телефона мы на месте не ожидаем увидеть, нам нужны другие ориентиры. Самый очевидный из них — номер дома. Правда, на него может быть неудобно смотреть: в OsmAnd номер рендерится по середине здания, которую надо ещё найти, или не рендерится вообще, это зависит от зума. Нажимать на здание при этом бесполезно, оно выберется только при нажатии на номер. Значит, если номера не видно, придётся зумиться или смотреть на номера соседних домов.

Гораздо более заметными на карте являются иконки POI, но в реальности сами POI могли измениться — мы и пришли засвидетельствовать одно из таких изменений. Но, может быть, POI на карте достаточно свежие, и тогда мы сможем искать телефон рядом с отмеченным и хорошо заметным на месте магазином. Есть ещё входы в здания, которые в реальности меняются реже, но, как мы знаем из начала этой записи, они не обязательно полностью отмечены. В таких условиях, чтобы использовать их как ориентиры, надо не перепутать один вход, неотмеченный, с другим, отмеченным.

Допустим, место мы нашли. Там мы можем увидеть: телефон, его останки, ничего или то, с чем телефон можно перепутать. Если мы видим телефон, то здесь ничего делать не надо, можно только отметить место как просмотренное для себя, создав закладку кнопкой со звёздочкой. Если видны останки телефона, можно было бы его сразу удалить, но, как мы знаем, нам могут помешать технические причины. Так что мы добавим заметку, в которой напишем, что телефона нет. Поскольку в данном случае его очевидно нет, особых подробностей можно не писать.

Для добавления заметки нужно, чтобы был включен плагин редактирования osm (меню > Плагины). Если он включен, то после нажатия на иконку телефона на карте и далее нажатия на кнопку Действия будет доступна кнопка OSM-заметка. Когда мы ей воспользуемся, введём комментарий и сохраним, заметка ещё не будет закачана на сервер. Закачивание мы выполним позже, так мы можем не пользоваться мобильным интернетом.

Теперь более сложные случаи, когда не видно ни телефона, ни следов от него. Если на месте вообще ничего нет, просто стена без чего-либо к ней прикреплённого, то это как раз тот случай, из-за которого мы и хотим смотреть архивные снимки. Вероятно, стену тут отремонтировали после того, как телефон был убран, но возможны и другие варианты. Здесь мы тоже добавим заметку, но в комментарии нам стоит как-то описать место, где именно мы не видим телефона. Или вместо телефона мы можем обнаружить что-то другое, что могло быть кем-то отмечено как телефон. Например, это может быть устройство для экстренной связи, которое тоже как-бы телефон, только не amenity, а emergency. Какой-нибудь участник мог отметить его таки как amenity. Тогда мы добавим заметку, в которой напишем, что телефона нет, и что вместо него есть то, что обнаружилось. Может даже попасться демонтированное устройство — то есть, то, и чего уже нет, и с чем можно было перепутать телефон.

Разобравшись с одним местом, мы пойдём к следующему, там тоже создадим закладку/заметку и так далее. Когда мы решим, что обошли достаточно, нужно будет закачать созданные заметки. В OsmAnd заметки закачиваются таким же образом, как и другие изменения данных. Пункт меню для этого действия не так давно поменялся, и теперь находится тут: Мои места > кнопка со стрелкой вверх в левом нижнем углу. Дальше надо выбрать, какие из изменений надо закачать. Поскольку скорее всего закачать нужно всё, достаточно отметить верхний чекбокс Ваши правки. Затем надо нажать на кнопку со стрелкой, переместившуюся в противоположный угол экрана, в правый верхний. Далее появится довольно бессмысленный диалог, в котором будет упоминаться одна заметка, и её комментарий можно отредактировать. Но мы закачиваем, вероятно, не одну заметку, а несколько, и диалог этот мы проигнорируем просто нажав на Отправить. Закачаться должны все выбранные заметки, а не только та, которая попала в диалог. Смысл диалога на самом деле в том, что если бы мы закачивали также правки данных, то есть добавления/изменения/удаления элементов, это был бы диалог создания пакета правок, и вместо комментария к одной из заметок был бы комментарий к пакету. А так как изменений элементов у нас нет, то и пакет не создаётся, но кнопку Отправить и прочие элементы управления разработчикам куда-то вставить было надо, поэтому диалог есть.

Действия за компьютером

Теперь приступим к редактированию в JOSM. Для начала надо загрузить сами заметки — несколько штук, которые мы собираемся рассмотреть. Прочие же заметки нам загружать не надо, чтобы они не мешали. Так что мы не будем грузить их стандартным способом — через диалог загрузки, вместе с или вместо основных осмовских данных. Мы загрузим нужные заметки каждую по отдельности, но не вручную, а через remote control. Если вы не знаете, что это, то он у вас не включен, и его, конечно, надо включить. Делается это в меню Правка > Настройки… > Удалённое управление. В результате запустится локальный веб-сервер, открытие определённых url’ов на котором приводит к выполнению определённых действий в JOSM. Нам нужно действие, работающее аналогично команде Файл > Открыть адрес…, загружающей данные из указанной ссылки. Можете убедиться, что она работает и для ссылок на заметки.

Итак, мы будем открывать ссылки на локальном сервере, внутри которых будут ссылки на заметки в осме. Детали этого для нас не важны, потому что это мы тоже будем делать не вручную. Мы воспользуемся инструментом osm-note-viewer, написанным в качестве альтернативы странице заметок пользователя на сайте osm. Там надо ввести имя пользователя или вставить его осмовскую ссылку, выбрать сортировку по дате создания в убывающем порядке и загрузить список заметок (интерфейс может измениться). Поскольку нужные заметки, вероятно, являются последними созданными, то мы их первыми и увидим. Дальше нужно отметить их чекбоксы. Если нужные заметки идут подряд, не перемежаясь с ненужными, для этого можно кликнуть на первый чекбокс, а затем с нажатым Shift кликнуть на последний. Теперь внизу окна надо нажать на кнопку RC: Load selected notes, и заметки загрузятся в JOSM.

Теперь будем разбираться с каждой заметкой отдельно. Если на странице osm-note-viewer в таблице сверху/слева (это настраивается в интерфейсе, но подробно писать про него я не буду, потому что по ходу разработки всё может поменяться) нажать на заметку не там, где какая-нибудь ссылка или элемент управления, а, например, на комментарии, вид на карте снизу/справа переместится так, что заметка окажется посередине. Повторные нажатия на заметку позволяют зазумиться поближе к ней. Так, кликая по заметке, сделаем, чтобы она была посередине карты, а на самой карте была область, которую имеет смысл загрузить в редактор. Это нам нужно для того, чтобы воспользоваться ещё парой кнопок внизу. Сначала нажмём на кнопку загрузки данных RC: Load map area, после чего данные места на карте попадут в JOSM.

Мы пока не уверены, как редактировать загруженные данные, и для уверенности мы посмотрим на яндекс-панорамы. Это мы сделаем нажатием на кнопку Y.Panoramas: Open map center, открывающую в браузере окно с панорамами. Тут важно, чтобы заметка действительно была посередине вида карты, потому что панорамы открываются с координатами середины. При этом обычно получается, что камера на панорамах направлена на нужное место, и её не надо поворачивать или перемещать вдоль улицы. Это позволяет разобраться с местом бывшего телефона весьма быстро, может хватить и пяти секунд на все манипуляции с отдельным телефоном. Значит, если мы зачем-то подвинули карту после клика по заметке, легче кликнуть на неё ещё раз для центрирования перед открытием панорам. Помешать панорамам открыться в нужном месте могут отснятые рядом интерьеры. Тогда камера попадёт внутрь здания, и её придётся вручную перетащить на улицу. Ещё её придётся двигать, если вид заслоняет какой-нибудь автобус. Ну и, конечно же, панорамы не откроются, если в данном месте их нет. В данный момент какие-либо другие снимки придётся открывать вручную.

Допустим, панорамы места успешно открылись. В самом простом случае на них будет виден телефон, которого на самом деле уже нет. Тогда мы можем сразу принять решение его удалить. Но может получиться так, что телефона на панорамах нет. Тогда нам придётся смотреть на даты снимков и данных. Первым делом можно посмотреть историю редактирования точки телефона. Нас интересует, когда она была создана, или когда на ней появился тег amenity=telephone. Возможно, это было очень давно, мне попадались точки, созданные более десяти лет назад. В этом случае и в реальности телефона может не быть давно. Тогда его не будет и на самом свежем снимке, который показывается по умолчанию. В Петербурге панорамы обновляются обычно раз в три года, и на начало 2022 года самые свежие из них в большинстве мест были сделаны в 2019.

Однако смотреть лишь на самый свежий снимок не обязательно, можно переключиться и на более старый, для чего в окне панорамы есть кнопка в правом верхнем углу. Там можно выбрать год снимка, а какой год нам нужен, мы можем оценить из истории точки. Можно перебрать и все снимки от нового к старому, только не будет смысла смотреть на те из них, которые намного старее точки. Если мы видим телефон на любом снимке после добавления точки или на самом позднем снимке до её добавления, мы тоже можем принять решение от точки отделаться.

Если телефона нет и на менее свежих снимках, с данным местом придётся разбираться отдельно. Возможно мы не туда смотрим, и телефон находится с другой стороны какой-то конструкции или внутри здания. Возможно он был добавлен в осм в данное место по ошибке, и на самом деле находится или находился в другом. Тут уже общего алгоритма действий не придумать. Наверное, можно сказать, что чем более старой является точка, тем более мы будем склоняться к её удалению, а для новых точек будет больше смысла разузнать про точное положение телефона у добавившего его участника. Если телефон реально всё-таки есть, в идеале следовало бы привести данные в такое состояние, чтобы всем было ясно, где он. Как именно — тут могут быть всякие варианты. Например, если он внутри здания — добавить тег indoor=*.

Допустим, что на снимке мы телефон увидели. Тогда мы уже приняли решение от него избавиться в данных, так как вероятность, что именно он соответствует отмеченному в осме, очень высока. Само удаление будет собственно удалением точки, если эта точка не входит в линии или входит только в прямые участки линий. Ожидаемый вариант это вхождение в прямой участок единственной линии — контура здания. Если же точка телефона задаёт геометрию чего-либо так, что при её удалении форма этого объекта существенно поменяется, с точки надо убрать теги телефона. Вероятно, других тегов, кроме телефонных, на точке нет, и тогда надо удалить все теги. Тут можно отметить, что Ctrl-A — выбрать всё — работает и для тегов; нужно сначала кликнуть по окну тегов сбоку.

Правка для точки сделана, значит можно закрыть заметку. В JOSM есть средство и для этого — окно заметок. По умолчанию оно может быть скрыто, тогда его надо включить через меню окон. Для закрытия заметки можно кликнуть на неё на карте, после чего заметка выберется и в списке окна. Затем достаточно просто нажать на кнопку закрытия заметки внизу окна — мы ведь не обидимся на себя за то, что не написали ещё один комментарий. Теперь мы полностью разобрались с точкой, хотя ни изменения данных, ни закрытия заметок ещё не закачаны на сервер. Закачать мы их можем, когда наберётся осмысленная порция изменений. Пока же перейдём от JOSM к браузеру, к osm-note-viewer. Там мы можем очистить чекбокс у отработанной заметки. Никакой функциональности в этом нет, сделать это имеет смысл, чтобы не запутаться, с какими заметками мы уже разобрались. Теперь можно переходить к следующей заметке и так далее.

Когда мы разберёмся со всеми заметками или с такой их частью, которую имеет смысл залить одним пакетом, мы собственно их и зальём. Думаю, не надо объяснять, как это делается в JOSM. Зато надо обратить внимание на отличие от OsmAnd: заметки вместе с изменениями данных не закачаются, эту операцию надо выполнить отдельно, кнопкой закачки в окне заметок. Собственно, её лучше выполнить после закачивания данных, чтобы не закрывать заметок до внесения изменений. Как-то раз я пересёкся с другим участником, который закрывал заметки до закачивания данных, и я заметки переоткрывал, так как соответствующих правок не видел, а он их перезакрывал.

Заключение

Вообще-то я собирался написать очень короткую запись про свой osm-note-viewer. Запись должна была быть типа такой: 1. Жмём сюда 2. Жмём туда 3. Повторяем. И в этом инструменте сейчас есть функции только для описанной задачи. Но дела могут пойти и по-другому: например, поскольку мы ставим общедоступные заметки, кто-то мог постараться закрыть их раньше нас, и при этом не соблюдать предосторожностей с проверкой старых снимков. Свои заметки, даже закрытые, мы по-прежнему сможем просмотреть и проверить по панорамам. Но средств анализа изменений и восстановления данных — на случай, если мы признаем правку необоснованной — в инструменте нет, их ещё предстоит реализовать.

Также отметим, что всё сказанное в этой записи применимо не только к телефонам, но и к какому угодно виду объектов, обширно отмеченному, но, возможно, уже отсутствующему в реальности. Я, например, попробовал применить всё это к велопарковкам. Однако не стоит слишком стараться тереть из данных те объекты, которые обычно убирают и ставят обратно. В Петербурге к таким относятся, например, скамейки, забираемые на покраску.

две велопарковки в снегу

Две велопарковки, одну из них можно не заметить зимой.

Интересно, откуда у Яндекса данные по подъездам? Некоторые тут говорят, какие у них замечательные данные. Действительно, часто их данные с реальностью совпадают, или в них можно найти лишь мелкие отличия. Но иногда их данные к реальности имеют отдалённое отношение.

Только что ввёл дом: из девяти входов у меня с Яндексом совпадают два (№1 и №7, ну можно засчитать ещё №2, если не смотреть на него относительно арки).

скриншот дома с подъездами из Яндекс-карт

скриншот дома с подъездами из JOSM

В ряде случаев у Яндекса есть номера подъездов, которые на месте не написаны, и судя по их же панорамам не были написаны дольше десяти лет. Следовательно, вариант расставить с улицы как на самом деле, а внутри квартала как получится использовался не всегда.

Вот продолжение моих попыток вводить POI сразу на месте из OsmAnd. В этот раз я обошёл вокруг квартала Московский-Смоленская-Заозёрная-Обводный. Этот заход оказался относительно успешным. Мне удалось ввести большую часть POI из тех, которые я бы ввёл обычным двухэтапным способом. Одна из причин успеха — в этом месте до меня было отмечено не слишком много POI. Соответственно, практически не возникало проблем сопоставления отмеченного с реальным. Одна из причин этой одной из причин — наличие свежепостроенных зданий, в которых очевидным образом не может быть обозначенных точек десятилетней давности.

Новые здания, как на Смоленской улице, также облегчают задачу сопоставления самих себя со своими образами на карте. Их обычно не строят в упор друг к другу, благодаря чему гадать об их границах не приходится. Зато там, где дома более-менее старые, что в моём случае наблюдается вдоль Московского проспекта, непонятные границы зданий возникают вновь. И, как обычно, далеко идти за ними не приходится. Начав обход с угла Московского проспекта и Обводного канала, прямо на этом углу я обнаружил дом № 62 со своим соседом № 64 или один дом № 62-64. Табличек с номерами там две,1 но это ещё не значит, что и дома два. Если таблички убрать, то, скорее, покажется, что дом один, если смотреть на него с улицы. Взгляд со стороны двора, возможно, произвёл бы другое впечатление, но я же не буду обходить каждый дом со всех сторон, когда ищу POI на улице. Но это ещё не самый сложный случай, потому что даже и с улицы ясно, какому месту соответствует видимая на карте граница между зданиями. Следующая же граница между домами № 64 и № 66 в том месте, где она нарисована, не видна совсем.

дом на углу Московского проспекта и Обводного канала

Дом или два дома № 62-64. Закруглённая часть это № 62, а прямая справа от неё — № 64.

дом справа от предыдущего дома

Следующий дом № 66. Можно подумать, что зелёный дом с видным на фотографии номером «66 А» — это он и есть. Но нет, это и дом № 66, и часть дома № 64. Значит, должна быть видна граница между этими двумя домами, только придётся сильно постараться, чтобы её увидеть. Искать её надо между входом «Asus» и табличкой с номером дома.

этот же дом в OsmAnd

Так дом № 66 выглядит в OsmAnd. Примерно то же самое можно увидеть и в РГИС, где, конечно же, всё всегда указано правильно.

Несколько точек в одном месте

Надо сказать, что в этот раз непонятные границы зданий мне не слишком помешали отмечать POI. К тому же, проблемы с границами зданий нам уже известны из предыдущей записи, так что не будем их дальше обсуждать и перейдём к чему-нибудь ещё. Что-нибудь ещё мы можем увидеть уже на только что приведённой фотографии непонятной границы, и называется оно «Дом быта».

«дом быта» в доме с предыдущей фотографии

«Дом быта» в доме № 66, то есть в № 64. Или в обоих домах.

Что такое «Дом быта» помимо того, что это вывеска-надпись, которую при желании мы могли бы поместить в тег inscription? 2 Это обычно несколько разных craft’ов и/или shop’ов в одном месте, из чего следуют дальнейшие вопросы:

  • обозначать ли дом быта как единое целое или как несколько отдельных точек или даже и так и так? (у всего дома быта может быть своя идентичность, свой сайт, он может походить на shop=mall, а может и нет)
  • какие именно там услуги? (обнаружим ли мы их список снаружи на вывеске или пойдём проверять внутрь)
  • каким осмовским тегам они соответствуют? (например, часто встречающийся ремонт кожгалантереи это craft=что?)
  • если мы ставим отдельные точки, то куда именно? (сойдёт ли набросать их в случайном порядке или лучше попробовать воспроизвести их реальное положение?)

На перечисленные вопросы неудобно давать ответы и при обычном двухэтапном вводе. Когда такой дом быта мне попадается в первый раз, я обычно не пытаюсь выяснять, что у него внутри, верю написанному на вывеске и обозначаю всё одной точкой со списками значений через точку с запятой. Потом, при повторной проверке я, может быть, зайду внутрь, если посчитаю, что это имеет смысл сделать, и что этому не встретится существенных помех. При вводе из OsmAnd неудобств, конечно, меньше не становится. Ставить несколько точек в осмысленных местах можно даже не пытаться: делать это пришлось бы пальцем на сенсорном экране без возможности подвинуть результат. Значит, обойдёмся одной точкой, которой нужно задать тип. OsmAnd любит, когда тип один, выбранный из его списка, а нам надо несколько. Значит придётся набирать список значений вручную, опять же, пальцем на сенсорном экране. Всё это натолкнёт нас на мысли об ещё одном варианте ввода: ну его нафиг. Именно этим вариантом я и воспользовался.

Помимо «дома быта» встречаются и более понятные случаи расположения нескольких точек за одним входом в здание — когда там два-три магазина. Понятные они в плане количества точек, так как обычно сразу понятно, что это отдельные магазины, которые надо обозначать отдельными точками. Также понятна и их идентификация: их обычно видно через окна и двери, а значит видно, закрыты они или работают, и что именно они продают, и тогда не обязательно верить одним лишь наружным вывескам. Даже если видно плохо, с заходом внутрь таких мест проблем не возникает. Значит, при обычном двухэтапном вводе на первом этапе можно выяснить всю необходимую информацию, а на втором — ввести.

Для таких мест я предпочитаю рисовать вход и проходы от него до отдельных заведений. Почему и как я это делаю подробнее написано в записи про геометрию POI. Понятно, что ни вход, ни проходы из OsmAnd мне не нарисовать, но в простых случаях это делать не так важно. Если бы за входом было два магазина — один слева, другой справа — я бы просто поставил рядом две точки. Запутаться с тем, где они находятся, было бы сложно. На самом деле, при моём первом проходе по Адмиралтейскому району я так и поступал, хотя действовал в два этапа.

скриншот из JOSM: несколько POI, соединённые коридорами со входом в здание

Так выглядел бы относительно простой случай с тремя точками, к которым нарисованы проходы. Но в этот раз мне попались более сложные конфигурации.

Это я описал простой случай, и это не то, что мне попалось при обходе квартала. Очевидно, что с возрастанием количества заведений, появлением мелких услуг, кофе-с-собой и т.п. ситуация приближается к описанной с домом быта. Актуальность и полнота наружных вывесок падает, вместе с чем возрастает необходимость внутренней проверки, результаты которой из OsmAnd толком не ввести. Пока мелкие услуги в таком месте не доминируют, более понятно, для чего нужны отдельные точки. Но, вообще-то, и в попавшемся мне доме быта был по крайней мере один магазин и один сервис-центр с собственным названием. Магазин там уже был отмечен, а про остальное я решил, что нафиг. Угадайте, что я решил насчёт продуктов-фотокопицентра-пункта выдачи, где «в продаже есть вяленая рыба» и «акция 5+1 на всё пиво». Продукты там тоже уже отмечены, а для добавления остального лучше воспользоваться более продвинутым редактором.

копицентр, пункт выдачи и прочее внутри магазина

Фрагмент внутренностей попавшихся мне продуктов-фотокопицентра-пункта выдачи. Собственно продукты находятся справа от сфотографированного места. А на этом месте заметьте стрелочки для навигации.

Проблемы визуализации

Только что описанные проблемы, в той степени, в которой они касались OsmAnd, были проблемами ввода. Помимо них есть и проблемы вывода, к которым мы сейчас перейдём. Ещё в первой части мы заметили, что у существующих в осме POI нет никаких гарантий отображения в OsmAnd. Самой очевидной причиной неотображения могло бы быть отсутствие POI в загруженных данных, но это легко поправить их обновлением. Другая очевидная причина — невозможность отобразить все POI, потому что они перекрываются друг с другом. Как происходит практически во всех рендерах осмовских данных, не предназначенных непосредственно для редактирования, POI, изображения которых перекрылись бы с другими, по-тихому опускаются. По-тихому — значит пользователя никто не предупреждает, что на этом месте есть что-то ещё, например, с помощью изображения кластера с указанием количества точек.

К таким непредназначенным рендерам относятся тайлы на сайте осма и юзерские приложения типа MAPS.ME и OsmAnd. Да, при редактировании из OsmAnd нам придётся смотреть на рендер, не предназначенный для редактирования. В отличие от этого JOSM и iD выведут POI, даже если они налезают друг на друга. И по крайней мере в JOSM есть средство для перебора элементов, находящихся на совсем одинаковом месте. В OsmAnd мы можем в лучшем случае догадываться о наличии неотображаемых POI, но даже правильная догадка не позволит нам их выбрать, а, следовательно, и редактировать.

Но всё-таки у нас не статическая картинка, и мы можем производить над ней манипуляции, пытаясь заставить POI вывестись. Самая очевидная из манипуляций — увеличение карты. При увеличении экранные расстояния между POI растут, а их шансы помешать друг другу падают. Так что мы можем подумать, что у POI становится больше шансов быть отрендеренной при увеличении карты. Но, оказывается, это не обязательно так, с чем мне пришлось столкнуться.

В одном месте я обнаружил банк, отсутствующий на карте. Это было отделение Сбербанка под их приватным брендом «Сбербанк Первый». Собственно этого названия я точно не помнил, а писать его так, чтобы можно было прочитать, Сбербанк не хочет. Вместо этого этого они пишут «Сбербан1к» со сросшимися «1» и «к».

табличка с логотипом «Сбербанк Первый»

«Сбербанодинк».

Тут можно было бы порассуждать о таком недостатке одноэтапного ввода, как невозможность ввести нечитаемое название, но нам он уже в принципе известен. Нет достаточной информации для ввода на месте — придётся оставить заметку, что я и сделал. Когда же я на неё позже посмотрел, я обнаружил, что банк уже отмечен, причём вовсе не потому, что кто-то уже на заметку среагировал. Отмечен он был давно, просто он не рендерился. Но спрашивается, как он мог не рендериться, если я зазумился так, чтобы близко никаких POI не было? А вот так: при умеренном увеличении рендерится, а при дальнейшем увеличении пропадает. Почему в данном случае это происходит, я точно не знаю. Можно предположить, что на больших зумах начинает выводиться что-то ещё, конкурирующее с POI за место на экране. В данном случае это, видимо, значок входной двери.

заметка и отсутствие иконки банка в OsmAnd

То, что я сначала увидел в OsmAnd + моя заметка. Заметка отображается в виде креста на красном фоне, что значит, что она ещё открыта, то есть, никто не делал правок на эту тему. Обратите внимание на то, что под заметкой нет иконки банка.

заметка и иконка банка в OsmAnd на другом масштабе

А теперь иконка под заметкой появилась.

Обнаружив банк, я закрыл заметку. Если бы Сбербанк проявлял меньше креатива, я бы создал дубль, который пришлось бы потом удалять. Причём делать это пришлось бы кому-нибудь другому, потому что я бы ещё не скоро посмотрел на это место так, чтобы заметить две точки одного банка. Из OsmAnd я увидел бы лишь одну точку по только что рассмотренным причинам, так что всё то время, что я изображал бы из себя одноэтапно-вводящего пользователя этого приложения, о дубле я бы не знал. Посмотрел же я туда то ли чтобы узнать, не обработал ли кто заметку, то ли чтобы проиллюстрировать скриншотом сбербанковский креатив, сейчас уже не помню.

Подобного рода дублями из-за того, что существующая в базе POI не выводится, известно приложение MAPS.ME. Я об этом уже писал три года назад, правда тогда я думал, что с обновлением данных там ситуация будет лучше, чем в OsmAnd, благодаря более экономной передаче изменений на карте. Теперь дело обстоит совсем по другому: в OsmAnd можно получить данные двухчасовой свежести,3 а в MAPS.ME, после продажи кому-то, об обновлениях вспоминают раз в несколько месяцев. Но зато с отображением уже скачанных POI в MAPS.ME дело обстоит получше. В обычном пользовательском режиме отображения у MAPS.ME преимуществ нет, и, может быть, наоборот есть недостатки. Например, приоритет отображения там определяется коммерческими интересами, когда у показываемых вместе с осмовскими POI съёмных квартир из Booking он выше, если, конечно, владельцы POI не заплатили за продвижение. Однако для добавления POI MAPS.ME переключается в другой режим — с прицелом для указания места, что тоже удобнее, но главное — с выводом всех POI, даже если они перекрываются. Сценарий, при котором это пригодится, такой:

  1. POI есть в реальности и есть в базе, значит, пользователю её надо отредактировать или просто не трогать;
  2. POI скачана, но не выводится, потому что ей что-то мешает, и пользователь либо не знает о её наличии в базе, либо знает, но не может выбрать для редактирования;
  3. в такой ситуации пользователь, скорее всего, выберет добавление POI, так как уверенности в её наличии в базе не будет;
  4. MAPS.ME перейдёт в режим добавления и выведет нужную POI;
  5. тут пользователю предстоит проявить свои способности во-первых, заметить нужное название и значок среди каши из перекрывающихся объектов, а во-вторых, удержаться от ввода новой точки, если заметить нужную удалось; с этим, как известно, справляются не все;
  6. если пользователь планировал зафиксировать только наличие POI, то ему ничего дальше делать не нужно, если же он хотел её отредактировать или узнать, нужно ли её редактировать, то ему предстоит её выбрать, для чего её надо всё-таки заставить вывестись в обычном режиме;4
  7. как именно пользователь заставит вывестись POI, мы не знаем, может быть, будет зумить и крутить карту, может быть, использует поиск — режим добавления тут уже не поможет, но зато от создания дубля он застраховать способен.

В том, что последует дальше — редактировании тегов новой или существующей точки — MAPS.ME уже хуже, в первую очередь потому что непосредственно теги он не показывает вообще. Конечно, и OsmAnd в этом плане не идеален, но вкладка показа всех тегов там есть. Точнее, показа только для чтения двух особенных тегов и полного показа прочих. Про редактор тегов OsmAnd мы скажем ещё кое-что ниже, а до его более подробного разбора мы доберёмся в одной из следующих записей. Эти особенности могут доставить неудобства, но не станут непреодолимыми препятствиями.

Более серьёзным препятствием будет невозможность попасть в редактор тегов. В этом разделе мы про такую невозможность и говорим по самой элементарной причине — неотображении POI. Из причин же самого неотображения в этом разделе мы уже упомянули две: незагруженность и столкновение с другими POI. Также, в первой записи мы упоминали неотображение, потому что OsmAnd просто не признает определённый набор тегов за POI, то есть их неизвестный тип. Но при обходе рассматриваемого квартала я с этой проблемой не столкнулся, так что отложим её до следующей записи. Там же мы выясним, что в редактор тегов дорога может быть закрыта даже для отображаемых POI, которые удалось ткнуть.

В общем-то по теме неотображения в рамках обхода квартала между Московским проспектом и Заозёрной улицей мне добавить нечего. Разве что если бы я решился вводить дом «быта» множеством точек, они оказались бы слишком близко друг к другу и стали бы не видны, так что у меня имелась ещё одна причина этим не заниматься. Если же воспользоваться этим местом для более глобальных рассуждений, можно заметить, что проблемам отображения и прочим проблемам вывода вовсе не обязательно быть проблемами одноэтапного редактирования. Дело лишь в доступных средствах такого редактирования.

Более глобальные рассуждения

Так получается, что доступными средствами часто являются дополнительные функции приложений для отображения карты конечному пользователю. Мы пытаемся ими пользоваться как неконечные пользователи, и получаем от них этакий WYSIWYG, предполагающий, что все данные видеть не нужно. Однако эти приложения не являются каким-то особым классом софта для чайников, от которого существенно отличаются редакторы для настоящих осмеров. Вместо этого можно обнаружить спектр чайниковости, основной характеристикой которой является количество скрываемых от пользователя данных. Уже iD пытается скрывать не только теги, задвигая их подальше, за селектор типа и форму основных характеристик, но и типы элементов точка-линия-отношение.

Конечно, не стоило бы реализовывать редактор внутри вида для пользователя, тем более, что нет какого-то одного правильного вида для пользователя. Даже если ограничиться представлением POI, ни одной его подходящей реализации без уже обозначенных проблем я не видел. Отчасти помочь могла бы возможность зумиться ещё больше, но, например для тайлов, это вызвало бы повышение требований к серверам. И, кстати, тайлы с осмовского сайта строго говоря не являются видом для конечного пользователя, так что все POI на них рендерить просто не пытаются. Вывод POI на осмовском сайте считается отдельной задачей, которую неплохо бы решить, но пока никто этого не сделал.

Зум бывает ограничен не только у тайлов на сервере, но и в клиентских приложениях, к которым относится и OsmAnd. При этом понятно, что для редактирования неплохо бы иметь больший возможный зум, чем для обычного пользования. Так что тут OsmAnd снова проявляет себя не с лучшей стороны как редактор. И зачем ограничивать зум даже для пользователя? Возможно, считается, что иначе пользователь заблудится: многие места при глубоких зумах будут пустыми а, значит, во-первых бесполезными, а во-вторых без ориентиров. Если в добавок к этому нет и мини-карты, а её обычно нет, пользователю будет вообще не ясно, куда он попал. На устройствах с сенсорными экранами такие соображения особенно актуальны из-за больших возможностей ошибок ввода. Держать устройства приходится за места рядом с экраном, из-за чего возможны случайные его срабатывания на якобы нажатия. Если вдруг начнётся дождь, любая капля воды тоже может устроить «нажатие» и перемещение карты в неизвестном направлении. Со мной такое случалось при использовании Vespucci, когда я понятия не имел, какое место открылось и почему. Единственным выходом было сбросить вид до всей планеты и оттуда увеличивать нужный фрагмент карты.

С достаточным зумом или без, даже на коммерческих картах, которые никак не относятся к осму, все подряд POI обычно не выводятся. Видимо, считается, что все без разбора они никому не нужны и что их на самом деле может быть слишком много при практических зумах, или что многие их координаты получены таким путём, что в них нельзя быть уверенным. Возможно, и в наличии уверенности нет, и тогда их отображение стало бы слишком лакомой приманкой для спама. Короче, всех POI на юзерских рендерах нам не видать, хотя сделать редактор с их выводом никто не мешает, так что и для одноэтапного редактирования эта проблема решаема, как, скорее всего, и прочие проблемы вывода. Проблемы ввода же будут существенными, каким бы софтом мы не пытались пользоваться на месте.

Проблемы редактора тегов

Что ещё можно сказать про мой обход, и что не относится ко вводу кучи POI в одном месте и их невыводу в OsmAnd? Про невозможность написать название, которое невозможно прочитать, мы уже сказали. Про невозможность передвинуть POI говорилось во второй части, но у этой проблемы обнаруживается родственная: POI невозможно и объединить. Мне попался дважды отмеченный магазин, одна из точек которого находилась дальше от нужного места так, что её стоило бы объединить с другой. Конечно, в таком случае лишнюю точку можно просто удалить, но на ней могут быть теги типа сайтов, телефонов, режимов работы, которые хотелось бы сохранить. Для сохранения их можно было бы скопировать на другую точку, только делать это неудобно. В OsmAnd в редакторе тегов нельзя отметить чекбокс над тегами и нажать кнопку «скопировать» как в Vespucci, потому что чекбокса и кнопки нет. Можно копировать значения тегов по одному, но заниматься этим лень, так что, как и в случае с перемещением, легче просто оставить заметку.

магазин «Всё для шитья»

Магазин «Auratessu», он же «Всё для шитья».

две точки магазина в OsmAnd

Он же в двух экземплярах на карте.

редактор тегов в Vespucci

Так выглядело бы редактирование тегов в Vespucci. Заметьте чекбоксы слева и кнопку копирования рядом с правым верхним углом. Хотите пересоздавать отдельно каждый из этих тегов на другой точке?

Иногда вместо одной POI обнаруживается совсем другая на том же месте. Точнее, что она на том же месте, мы до конца уверены быть не можем, и проверять это во время обхода не станем, но достаточная уверенность у нас может иметься. Мы, опять же, можем решить удалить старую точку и добавить новую, но у нас могут быть причины этого не делать, и мы предпочтём редактирование существующей точки. Иногда возможность удаления просто отсутствует, например, если POI обозначена не точкой или точка входит в линию. Так что делать замены нам, вероятно, придётся, как пришлось и мне в этот раз.

При замене POI на осмовском элементе надо отделаться от более неактуальных тегов. Сначала, конечно, можно ввести название и тип — изменить значения в верхних двух полях османдовского редактора тегов. В редакторе есть две вкладки для свойств: основные и расширенные, при этом имя и тип можно изменить на любой из них. Дальше, поскольку по умолчанию мы попадаем в основные свойства, может возникнуть желание начать эти свойства вводить, например, задать режим работы. Но если мы хотим отделаться от старых тегов, поступить лучше по-другому. Лучше сразу открыть вкладку расширенных свойств и по-быстрому их всех удалить, нажимая на крестики с справой стороны. В расширенные свойства нам всё равно придётся перейти, потому что на вкладке основных не видны все теги. Перейти же туда до ввода свойств лучше потому, что так легче и безопаснее удалять.

Возможность быстрого удаления тегов нажатиями на крестики способна доставить неприятности: можно снести только что введённые теги. Неприятности эти тем больше, чем дольше происходил ввод снесённых тегов. В следующей записи мы вспомним о крестиках в связи со вводом иногда довольно длинных значений тега inscription. Сейчас же в качестве примера подойдёт режим работы. Вот вы (как я во время обхода) отмечали чекбоксы дней, возили пальцем по циферблату, нажимали на кнопки, снова возили пальцем по циферблату, потом возможно ещё отмечали чекбоксы дней для другого режима в выходные и так далее. Потом вы перешли в расширенные свойства, снесли одно лишнее, второе и упс! дотронулись до крестика напротив opening_hours. Теперь придётся вводить режим по-новой.

Но можно же отменить редактирование, внизу же есть кнопка «отмена»? Эта кнопка для отмены редактирования всего элемента, после этой отмены придётся вводить по-новой не только режимы, но и всё остальное. К счастью она не такая опасная, потому что после нажатия на неё появится диалог подтверждения с кнопками «отмена» и «OK». Теперь «отмена» это отмена отмены, а «OK» — подтверждение отмены, так что вы можете отменить ненужную отмену, если не запутаетесь в отменах. Нужной же отмены, то есть отмены удаления одного тега, в редакторе, похоже, нет.

диалог отмены изменений тегов в OsmAnd

Я пытался заменить Альфа-Банк на БЖФ Банк, для чего сначала надо удалить многочисленные теги Альфа-Банка. На скриншоте можно увидеть диалог с «отменой» после нажатия на «отмену», что я, кажется, сделал после того как снёс только что введённый режим работы. Этот скриншот, конечно, сделан позже, во время написания данной записи. Тут я обнаружил, что теги Альфы я так и не убрал…

Итого безопаснее снести лишние теги сразу, до ввода нужных тегов. Алгоритм действий получается такой:

  1. вводим новые имя и тип;
  2. переходим в расширенные свойства и сносим всё лишнее, нажимая на крестики — после этого этапа на крестики уже не нажимаем и держим пальцы от них подальше;
  3. если нам известны ещё какие-либо основные свойства, переходим обратно на их вкладку и вводим их;
  4. если нужно ввести теги, не вписавшиеся в основные свойства, переходим снова в расширенные и вводим;
  5. сохраняем.

Прочее

Можно ещё сказать по одну возникшую при обходе квартала проблему другого рода — проблему проверки данных. О проблемах этого рода уже говорилось в обеих предыдущих записях, да и в начале этой записи тоже, только теперь она проявится в более чистом виде. Иногда мы не можем или не хотим выяснить всю информацию, необходимую для ввода POI, хотя и знаем, что её надо ввести. При двухэтапном редактировании мы откладываем часть выяснений на второй этап, надеясь раздобыть недостающие сведения в интернете. В случае с «домом быта» и несколькими магазинами в одном месте из начала данной записи перед нами вдобавок к этому встала бы проблема их ввода. Сейчас же мы посмотрим на одну POI, для которой ввести одну точку было бы легко, если бы было известно, что это надо сделать, и какие свойства для неё надо задать.

В известном нам доме № 64 рядом с «домом быта» обнаруживается лестница, ведущая к двум дверям. За одной из дверей находится видный с проспекта магазин одежды. Над второй дверью написано «Время красоты», и это, вероятно, салон красоты. Однако за дверью достаточно темно, так что непонятно, на самом ли деле это салон красоты, и работает ли он. Обычно у работающих заведений бывает табличка с режимом работы, а тут её нет, возможно её демонтировали в связи с закрытием, или ещё не поставили, потому что ещё не состоялось открытие. Что я сделал с этим предположительно салоном — нетрудно догадаться. Поскольку он отмечен не был, я его не стал вводить. Если бы он был отмечен — я бы его не стал удалять, точнее, отмечать как неработающий.5 А если бы я действовал двухэтапно, то перед внесением или невнесением изменений на втором этапе я бы посмотрел на фотографию данного места, чтобы узнать, какая там ранее существовала вывеска с названием и/или режимом. Также я поискал бы «Время красоты» или любой салон по адресу. После этого иногда приходится делать и третий с четвёртым этапы — идти на место уже зная, что именно надо проверить, и вводить результаты такой проверки.

входы в бутик «Malina» и «Время красоты»

Бутик и «Время красоты». Подниматься по лестнице и разглядывать, что находится в темноте за дверью «Времени» мне было лень. В отличие от этого, что находится за дверью бутика, видно достаточно хорошо.

На этом я, пожалуй, закончу запись про обход квартала у Московского проспекта. Про OsmAnd я могу сказать ещё много чего, но привязывать это к отдельной проверке POI не имеет смысла. Времени с тех пор прошло уже достаточно, а всех подробностей именно того обхода я могу уже не вспомнить, тем более, что после этого я сделал более десятка других. Так что в следующей записи я напишу про все мои обходы с одноэтапным вводом POI через OsmAnd вообще, а не про какой-то конкретный из них в отдельности.

Примечания

  1. Точнее, табличек как минимум три, но разных номеров на них как минимум два. 

  2. Или из OsmAnd не могли бы, если захотели бы поместить тег на вход. Входы OsmAnd хоть и показывает, но редактировать не даёт. 

  3. При использовании OsmAnd Live. В той версии, которая на F-Droid, оно включено для обновления осмовских данных. Правда, и без него у OsmAnd обновления данных теперь происходят чаще. 

  4. У MAPS.ME есть ещё одна особенность, позволяющая редактировать точки без их выбора. Для этого надо попытаться создать точку ровно в том месте, где находится другая точка, причём не важно, отображается она или нет. Тогда вместо создания новой точки будет выполнено изменение существующей. Пользователю об этом, правда, приложение не сообщит, и теги существующей точки показаны не будут (если вообще имеет смысл говорить о показе тегов из MAPS.ME). В общем ничего хорошего от такого редактирования ждать не следует. 

  5. Такое отмечание с помощью lifecycle prefix делать довольно неудобно. С ним и с его альтернативным вариантом мы встретимся в следующей записи. 

В прошлый раз, про что написано в предыдущей записи, я попытался немного повводить POI из OsmAnd. Тогда я сразу же наткнулся на место, где мне не удалось ввести ничего. Может быть, мне просто не повезло, поэтому я попробовал ещё раз в другом месте — на Большом проспекте Петроградской стороны.

Опять соответствие точек

Теперь кое-что мне ввести удалось, но, конечно, не всё, что я бы ввёл дома из JOSM. Далеко идти до места, где потенциально вводимые данные приходится пропускать, не понадобилось. Уже через три точки передо мной встала задача сопоставления нечта под названием «Музей сновидений Фрейда» на карте с нечтом под названием «Институт психоанализа» в реальности. Институт теперь вместо музея, или музей всё ещё есть в институте? Ответ можно было бы обнаружить на сайте института, найдя там что-нибудь про музей. Заниматься этим и ему подобными вопросами, стоя у каждой редактируемой точки, весьма неудобно.

На самом деле, при более внимательном рассмотрении места табличку музея обнаружить можно.1 Она находится на двери под гораздо более заметной вывеской института. Получается, что я её не заметил с первого раза, но это ведь не проблема османда? Проблема эта, тем не менее, связана с процессом сбора и ввода данных при его использовании. Мне нужно на месте идентифицировать все POI, иначе я не смогу их ввести. Пока я их идентифицирую и ввожу, я не могу идти дальше. В отличие от этого, при обычном сборе данных я фотографирую все таблички, все вывески и все двери, так, чтобы иметь возможность разобраться с ситуациями одно заведение внутри другого потом.

вход в музей и институт

Фотография двери, которую я бы сделал при обычной проверке POI. Точнее, эта фотография сделана, конечно, для этой записи, а при реальной проверке я бы постарался, чтобы в кадр попало больше потенциальных ориентиров, или сделал бы несколько фотографий, чтобы одну сопоставить с панорамами улицы, а другие — с той одной. Часто для одной POI я делаю две фотки.

О том, что вопрос соответствия реальных и обозначенных POI может нам помешать, мы уже знаем и из предыдущей записи. Однако, помимо этого нам может помешать и ответ на него. Уже в следующем здании2 я обнаруживаю магазин и кафе. Точнее, магазин и кафе я обнаруживаю на карте, а в реальности я вижу сначала кафе, а потом магазин — в таком порядке. Магазин обозначен явно не в той части здания, и его стоило бы передвинуть, только как? Из OsmAnd, конечно, никак, так что остаётся добавить вместо этого заметку.

скриншот рассматриваемого места в OsmAnd с открытой заметкой

Магазин «Вместе», кафе «Вояж» и заметка, где магазину стоило бы находиться.

Куда ставить точки

Как получается, что точки POI оказываются не на месте? Пока мы не будем рассматривать деятельность импортёров, сеошников и прочих категорий участников, расставляющих точки в неизвестных им местах. Допустим, что наши предшественники ставят точки примерно таким же образом, что и мы. То есть, если я вижу отмеченный не там магазин, я могу предположить, что его тоже отметили из OsmAnd, MAPS.ME или чего-нибудь подобного. Даже если это не так, то я-то, поставив точку из OsmAnd, сам стану таким предшественником относительно тех, кто будет редактировать карту позже. Короче, либо пользователи османда могли облажаться до меня, либо я могу таким же образом облажаться сейчас.

Куда же ставить точки пользователю мобильных приложений, чтобы не ошибиться? Ясно, что не ровно в то место, какое показывает GPS. Локация, показываемая прямо из OsmAnd, может быть весьма примерной, так как рядом со зданием сигнал искажается. Но в моём случае, казалось бы, ответ на вопрос о нужном месте уже готов: ведь я сказал, что магазин обозначен не в той части здания, значит, я знаю и ту, нужную часть, куда точку и следовало бы поставить. Только к этому выводу надо сначала прийти.3

Небольшой проблемой является то, что стоя в упор к зданию, не всегда удобно это здание обозревать. Соответственно, может быть неудобно и определять, в какой части здания относительно его протяжённости находится нужная нам точка: примерно посередине, примерно на четверти длины или ещё где. Без серьёзной точности мы можем обойтись, главное, чтобы оценки положений внутри здания хватило для того, чтобы поставить точки в правильном порядке. Для этого удобнее было бы отойти от здания так, чтобы его было видно целиком, но отойти помешает проезжая часть улицы. Получается, что здание лучше видно с противоположной стороны улицы, но мапить POI оттуда не выйдет: таблички как у упомянутого выше музея так точно заметить не удастся, и мелкие надписи режимов работы или даже названий будет не разобрать. Но тут же можно придумать и решение: ставить точки на одной стороне улицы относительно объектов на её противоположной стороне.

Для сравнения скажу, что при двухэтапном методе перед вводом из JOSM проблему определения положения точки я решаю поиском сфотографированного места на доступных фотографиях, например на панорамах. При этом даже не важно, какой свежести эти фотографии: магазина на старой фотке мы не найдём, но место мы опознать сможем.4 5 Это верно по крайней мере для центра Петербурга, где не так много достаточно длинных зданий с повторяющимися одинаковыми элементами. Например, во всём Адмиралтейском районе Петербурга только одно здание у меня вызвало затруднения с определением положения POI по их фотографиям — Московский проспект, дом 73. Там ещё к моменту моей проверки неправильное количество проездов/проходов под зданием было нарисовано, что приближает нас к следующей проблеме.

коллаж фрагментов дома Московский, 73

Повторяющиеся элементы Московского, 73 в 2016 году. Эти фотографии мне пришлось делать в определённом порядке независимо от наличия POI на местах, чтобы эти места опознать. Обычно этим заниматься не приходится.

Соответствие зданий

Итак, мы хотим поставить точку относительно протяжённости здания вдоль улицы. Возможно, это здание находится на противоположной стороне, сейчас нам это не важно. Важно, что нам надо увидеть протяженность здания в реальности и на карте, чтобы их сопоставить. То есть, надо увидеть, где здание начинается и где оно заканчивается. В моём случае с магазином и кафе магазин как раз обозначен у начала здания, что мне кажется сомнительным. Это здание — дом 18, на карте видно, что начинается оно на границе с домом 18А и заканчивается на углу квартала. В реальности я вижу дом с номером 18 литер А… Наверное это 18А… А дальше… А где следующий дом, который просто 18? Никакого номера после 18 литер А не обнаруживается, но граница между домами, видимо вот тут. Посмотрим заодно назад, на границу между домами 16 и 18А.

граница домов 16 и 18А

Граница домов 16 и 18А. Если бы не таблички с номерами, её можно и не заметить.

граница домов 18А и 18

Граница домов 18А и 18. А здесь и табличек нет. Может, и границы на самом деле нет?

Как видите, границы не очень заметные, потому что фасады домов похожи, да и высота одинаковая. Возможно, что участник, обозначивший ранее магазин, запутался именно из-за этого. Как было сказано выше, я это исправить на месте не мог, поэтому мне пришлось поставить заметку. Так что к этому месту мне придётся вернуться позже, или кто-нибудь ещё обработает заметку вместо меня. Я же пошёл дальше по проспекту отмечать следующие POI.

До следующего сюрприза, как обычно, далеко идти не понадобилось. Теперь это дом 22-24. Во всяком случае, такая табличка видна в реальности. А в осме обозначено два дома — 22 и 24. Границы между ними на месте не видно никакой. Рядом с предполагаемым местом границы есть арка, так что я зашёл во двор посмотреть на якобы границу с обратной стороны. Там она тоже оказалась не очень заметной.

скриншот рассматриваемых домов в OsmAnd

Дома 22 и 24, которые я увидел в OsmAnd с уже добавленными мной POI.

дом 22-24

Дом 22-24, который я увидел в реальности, или два дома. Если их два, то граница должна быть на фотографии, ещё до того места, где леса.

дом 22-24 сзади

Дом 22-24, вид со двора на предполагаемую границу. Тут при желании её можно увидеть, а можно и не увидеть, последнее более вероятно.

Похоже, что это всё-таки один дом с номером 22-24. Распилить на два его могли ради адресации. Некоторым участникам кажется, что между зданиями и номерами должно быть взаимно однозначное соответствие, а номера из нескольких чисел — это не настоящие номера. Значит номер надо распилить, и здание тоже надо распилить, и вот у нас на карте два здания, даже если на самом деле здание одно. Я не буду утверждать, что с домом 22-24 дело обстояло именно так. Возможно, когда-то на нём было два отдельных номера. Это, конечно, всё равно не было бы хорошей причиной делить здание на два, хотя желающим видеть взаимно однозначное соответствие так не кажется. Например, почти на каждом доме на углу квартала можно обнаружить две таблички с номерами по двум улицам. Не пилить же из-за этого такие дома надвое. Но желающие говорят, что да, и их тоже надо пилить. В моём случае предыдущий дом 20 на углу квартала как раз так и распилен от угла. Как видите, это я даже за сюрприз не посчитал, потому что протяжённость здания вдоль улицы это определить не помешает. Если же за сюрприз это считать, то сюрприз был в каждом просмотренном мной доме, с 16 по 24. К дому 16 мы ещё вернёмся. После необнаруженной мной границы между домами 22 и 24 я решил со вводом POI закончить и начать писать эту запись.

Следующий день

На следующий день мне пришло оповещение, что поставленная мной заметка про место магазина закрыта. Раз так, то я решил обновить данные в османде и сделать скриншоты для записи. Действительно, теперь точка магазина находится не у границы домов 18А и 18, а после кафе. Только и границы теперь нет, и дома 18А — тоже. Его место занимает увеличившийся дом 18. Значит, закрывший заметку участник перемещением точки магазина не ограничился.

старая и новая версии дома 18

Было-стало.

Действительно, наличие в реальности обозначенной ранее границы между домами 18А и 18 было небесспорно. Впрочем, если смотреть на фасады, то же самое можно сказать и про границу домов 16 и 18А (или просто 18, как теперь). Дом 16 при этом по-прежнему обозначен, объединять его с домом 18 пока никто не пытался. Почему тогда одна из границ есть, а другой нет? Ведь глядя с земли мы могли бы как увидеть обе границы — 16/18А и 18А/18 — так и не увидеть ни одной.

В таких случаях я начинаю подозревать, что кто-то заглянул в РГИС — региональную геоинформационную систему, где есть официальная информация о зданиях и адресах, один из популярных источников для местных мапперов.6 Действительно, в РГИС нет отдельного дома 18А. Отдельной таблички с номером 18А, как мы уже знаем, тоже нет. Значит, правка зданий может быть обоснована. Тогда, возможно, предыдущая конфигурация с отдельным домом 18А была вымышленная? Откуда вообще это «А» взялось? Не перепутал ли кто-то литеру А с «А» в номере? Оказывается, нет, не перепутал.

В осме дом 18А был нарисован в 2010 году. Если посмотреть на фотографии дома тех времён, можно увидеть две отдельные таблички с номерами: 18 и 18А. Правда, из этого ещё не следует, что это отдельные здания. С РГИС тогда свериться было нельзя.7 Возможно, что и на спутниковых снимках никакого определённого ответа, один это дом или два, разглядеть тоже было нельзя. А можно ли было увидеть границу 16/18? На современных снимках она более заметна, хотя при желании можно было бы решить, что нет и её. Мнение о том, что 16-18 это один дом существует, и его можно найти, например, в Википедии.

К чему это всё было сказано? Мы хотим обозначать POI из османда. Мы их ставим внутри зданий. Для этого нам надо распознавать здания. Выясняется, что границы зданий могут быть не совсем очевидны. Редактировать их мы из османда не можем. Сверяться с РГИС на месте мы не будем. Смотреть на спутник мы тоже, скорее всего, не будем. Всё это повышает наши шансы поставить точку не туда, или обнаружить её не туда поставленной. Передвинуть точку мы не можем.

Из выяснившегося на следующий день можно отметить ещё следующее. Выше было сказано, что мы пока не рассматриваем правки сеошников. Одна из точек в доме 18 оказалась результатом именно такой правки. Это был офис компании, занимающейся лицензированием музыки, отмеченный как музыкальный магазин. Если верить их сайту, то офис где-то в здании на самом деле есть, но с улицы его не видно. Отмеченного магазина, конечно же, тоже не видно, так что это очередная точка, которую при одноэтапном проходе с османдом пришлось пропустить. Неясно только, зачем отмечать офис как магазин. Может быть, для рендеринга? Офисы тоже рендерятся, но магазины рендерятся красивее.

Заключение

Предыдущая запись была написана про проверку трёх точек, эта — про проверку примерно десяти. На этот раз не каждая из точек оказалась нерешаемой на месте проблемой для пользователя OsmAnd, зато обнаружилась ещё одна разновидность таких проблем. Помимо разгадывания соответствия реальных и обозначенных POI, бывает нужно заниматься тем же и для зданий. Если нам и удастся выяснить необходимую информацию, внести изменения в существующую геометрию мы не сможем. Мы можем поставить заметку, что следует делать только если мы хотим привлечь внимание других участников — внимание может привлечься довольно быстро, и к этому моменту нам лучше незалитых правок не иметь. Если ничьё внимание помимо своего собственного мы привлекать не собираемся, лучше не пользоваться осмовскими заметками, а добавить место в избранные внутри приложения. Только это будет означать, что одноэтапность нам не удалась.

Примечания

  1. Значит, музей существует. Про него даже в Википедии написано, правда с шаблоном требует существенной переработки. Также, что нам далее окажется интересным, там указан его адрес — дом 18А. 

  2. Или не в следующем, см. далее. 

  3. Сейчас мы пойдём рассуждать про проблемы со зданиями. Но это всё относится к местам, где здания уже обозначены. Мест же, где здания пока не нарисованы всё ещё полно, и это не только мелкие населённые пункты. Каковы же шансы на правильный ввод у пользователей OsmAnd или MAPS.ME там? 

  4. Этот момент может оказаться важен с юридической точки зрения. Допустим, вы пользуетесь именно Яндекс-панорамами. Яндекс, вроде бы, дал разрешение на их использование. Только сначала его дал не совсем Яндекс, и непонятно, действительно ли оно и для текущих версий. Мне же текущие версии не нужны. 

  5. Если вам кажется, что с разрешением от Яндекса всё понятно, можете попробовать почитать подобное разрешение для Bing Streetside

  6. На самом деле, там информация об объектах адресной системы, которые не обязательно являются зданиями, но обычно всё же являются. 

  7. Неизвестно, была ли новая правка зданий на самом деле выполнена на основании РГИС — в пакетах источник данных не указан. Если да, то РГИС за десять лет смог существенно изменить здание, существенно не изменившееся в реальности. 

Некоторое время назад я начал описывать свой процесс сбора и ввода данных о POI. Само описание ещё далеко от завершения, хотя часть продолжения уже давно написана, но не опубликована. Там ещё много чего надо отредактировать, потом я решил написать другую запись покороче, но она получилась втрое длиннее последней записи про POI, и теперь я не знаю, когда доделаю и её. Сейчас я напишу кое-что на самом деле покороче.

Как и его описание, сам процесс обновления POI идёт с тормозами. Одна из очевидных причин этого — его двухэтапность.1 Сначала я иду на место и собираю там информацию о POI. Потом я иду за комп и ввожу собранную информацию. Это «потом» может наступить весьма потом или не наступить вовсе. Последнее происходит, когда данные достаточно устаревают из-за длительного срока с момента сбора или каких-либо существенных событий. Например, сейчас мне придётся выбросить данные, собранные осенью 2020 года. Летом того же года мне пришлось выбросить всё собранное до коронавируса.

Конечно, есть средства, позволяющие минимизировать количество возможных конфликтов от ввода старых данных, но сейчас я собираюсь написать не о них, так что вернёмся к двухэтапности. Двухэтапность это, вроде бы, плохо. Если бы я сразу вводил выясняемую на месте информацию, процесс шёл бы быстрее и с меньшим количеством потерь. И у нас же есть средства для ввода POI сразу, например, плагин редактирования в OsmAnd. Почему я им не пользуюсь?

Полунаписанная запись про особенности редактирования из OsmAnd у меня тоже есть в черновиках. Аналогичная ей про MAPS.ME уже давно написана. В ней в основном говорится о чужих правках, которые нам могут попасться, как они объясняются и что с ними делать. Сейчас же мы посмотрим на редактирование из OsmAnd с другой стороны — с сугубо практической для нас, на конкретном примере.

Конкретный пример

Пройдём по 9-й линии Васильевского острова с только что обновлённой через OsmAnd Live картой. В первом же доме, в котором есть типичные POI, мы обнаружим различия между картой и реальностью. Различия заключаются в трёх точках между южным краем дома 2/11 и аркой. Там есть три входа, за которыми находятся следующие заведения:

  • кафе «O’Yes»,
  • винный магазин «Vinissimo»,
  • ресторан «Panda», на данный момент закрытый.

кафе «O'Yes» винный магазин «Vinissimo» ресторан «Panda»

Наблюдаемое в реальности

На карте в OsmAnd в том же месте наблюдается следующее:

  • автошкола «Светофор»,
  • note=«выглядит запущенно»,
  • строительная компания «Петротрест».

скриншот рассматриваемого места в OsmAnd

Наблюдаемое на карте

Как бы вы стали с помощью OsmAnd обновлять POI в этом месте? Ситуация тут ещё относительно простая: три точки было, три точки есть. Значит, и решение, казалось бы простое: заменить автошколу на кафе, note на вино, строителей на закрытый ресторан. Последнюю замену допустят только те, кто признаёт возможность обозначения неработающих заведений. Предположим, что мы такую возможность признаём.

Самой очевидной выглядит замена note. Обратим внимание, что это именно тег note на осмовском элементе, а не отдельная заметка. Отображение тегов note нам надо было предварительно включить, иначе они никак не будут видны. Включается оно через меню Configure map > Map rendering > Details > OSM mapper assistant. Отображение мы включили, теперь отредактируем соответствующий элемент. Обычно это делается нажатием на значок элемента и выбором из меню Actions > Modify POI, доступным со включённым плагином редактирования. Тут мы обнаружим, что для note в Actions пункта Modify POI нет, так что наш исходный план по замене трёх точек уже не удался.

Хотя почему не удался? Мы не смогли заменить note редактированием элемента, а кто сказал, что мы собирались делать замены редактированием? Может быть, нам плевать на сохранение истории точек, или мы не признаём в таких случаях её преемственность. А может быть, мы всё это признаём, но считаем, что важнее иметь актуальные данные, и если инструмент редактирования не позволяет редактировать правильно, то лучше редактировать как возможно, чем не редактировать никак. То есть, мы можем решить просто удалить старые точки и создать новые. В случае с note это нам всё равно сделать не удастся, пункта «удалить» в меню мы тоже не найдём. Остальные две точки можно как редактировать, так и удалять, так что для них разницы в осуществимости правки не будет.

Тут нам стоило бы задуматься, на каком элементе поставлен тег note. Мы ничего про него не знаем, так как OsmAnd нам ничего кроме значения тега не показывает. Мы даже не знаем, что это точка, а не другой тип элемента, собственно поэтому мы иногда и называли его «элементом», а не «точкой». А ведь примечание написано про какой-то определённый объект, который «выглядит запущенно». Наверняка на элементе есть ещё теги, из которых стало бы ясно, о каком объекте идёт речь. Жаль, что OsmAnd нам их не покажет. Может быть это точка обнаруженного нами закрытого ресторана?2 Так мы можем начать сомневаться в соответствии обозначенных на карте и обнаруженных в реальности объектов.

С чего мы вообще взяли, что соответствие автошкола-кафе, note-вино, строители-ресторан правильное? Мы не увидели на месте автошколы и строительной компании. А вдруг они на самом деле есть? Мы посмотрели с улицы на помещения первого этажа, и не увидели там этих POI. Но такие POI могут быть в офисах, а офисы бывают в других помещениях. Может быть автошкола и строительная компания существуют и находятся где-нибудь на втором этаже или сзади. Получается, что безопаснее их оставить, отказавшись от замены точек? Нам лучше просто добавить новые точки, поставив их рядом со старыми?

Ясно, что каждый раз оставляя старые точки, мы будем делать ситуацию всё более запутанной. Сейчас мы не знаем, что делать с тремя точками. Потом мы тем более не будем знать, что делать с шестью. От неактуальных данных надо избавляться, но делать это с мобильника на ходу проблематично. Нам стоило бы посмотреть на старые фотографии места, чтобы возможно обнаружить там старые POI, проверить их контактные данные и так далее. В принципе мы могли бы этим заняться, но так вся операция обновления данных может занять у нас ещё больше времени, чем двухэтапный ввод со вторым этапом за компом с клавиатурой, мышью и нормальным интернетом. И уж конечно мы не сможем так идти вдоль улицы и фиксировать все POI подряд. Нам пришлось бы торчать рядом с каждым заведением неопределённое время, проверяя информацию о его предшественнике.

Некоторые выводы

Нам может попасться и более сложная ситуация, когда точек POI на определённом участке гораздо больше, когда нет уверенности, где именно они находятся, когда мы даже не знаем, все ли они отображаются в приложении. Получается, что воспользоваться OsmAnd’ом для ввода POI не так и просто, если POI в интересующем нас месте уже вводились. Не будь в нашем примере уже трёх поставленных точек, мы бы без проблем добавили три новые, ну или две, без закрытого ресторана. Но точки есть, и помимо добавления POI надо делать что-то и с уже имеющимися обозначениями.

Можно сделать и более общее наблюдение: часто подходы к редактированию осмовских данных описываются так, как будто бы на интересующем нас месте никаких данных ещё нет. Но часто они уже есть, и в общем случае помимо добавления новых данных надо что-то делать со старыми, и желательно их не ломать. На это «не ломать» используемые подходы к редактированию рассчитаны далеко не всегда.

Примечания

  1. В посте по ссылке, правда, автор отказывается не только от двухэтапного ввода данных, но и от их ввода в осм вообще. Одна из причин такого решения (добавлять просто, а поддерживать — нет) обнаружится и у нас. Но также там приводятся и не слишком убедительные причины. Например, споры про теги будут только по ряду заметных сетей заведений, которые подвернутся участникам, любящим массовые правки. 

  2. На самом деле это точка, но не ресторана. Является ли элемент точкой для OsmAnd имеет значение при попытке его удаления. 

Problems with level

Posted by Anton Khorev on 15 November 2018 in English.

There are problems with level=* tag stemming from the fact that not all mappers agree on what it means. This problem comes up more often in some geographic areas than in others where different floor numbering traditions exist. In this sense it is like name=* tag where certain parts of a name stop looking like parts of a name after being translated into a different language.

So what are exactly the problems with level=*? Some people think that the value of this tag should be whatever floor number that is used in place. You can usually but not always read it off some plaque, floor plan or elevator button. Other people think that the value should be a number such that the first floor at or above the ground level gets number 0, the floor above it gets 1 and so on. Those two different ways of assigning a value could be exactly the same, especially for English-speaking areas where they have a “ground floor” as level=0 and a “first floor” as level=1. If you are from those places, you may not even understand that there’s a problem. If you are from a place like Russia or the US, it’s evident for you that those ways are different. I’ll be using Russia as an example because it’s where I map.

But there should be no debate about the exact definition of level=* tag because we have a wiki where it’s perfectly documented, right? Not quite. First of all, we don’t have one wiki, we have multiple wikis in different languages. Those languages may correspond to areas with different floor numbering traditions, which in turn affects the wiki contents. Again, this is like name=*, where local wiki editors put their preferred spin on what should and what should not be part of a name.

Even if we stick to English wiki, we still won’t avoid the problems with its current contents. You may get different impression on what level=* actually means depending on where you start and where you end reading the page, and also whether you follow the links to certain other pages or not. In fact, since I mentioned other pages, how do you know which wiki page you have to read in the first place? You may think that it’s obviously Key:level, but that page disagrees with you, sending you elsewhere for further information. You may also remember building:min_level=* tag which also takes on level as a value. Or is it a different level? Is there a definition of level that exists independently of particular tags?

What can those disagreements lead to? We can look at this from the point of view of a data user and of a data editor. For a user, let’s say you want to get to a POI which is inside a building. You look it up in some app, for example OsmAnd, and the app would tell you which floor the POI is on. So you see among other things about the POI something like “Floor: 1”. Actually, OsmAnd will say “Level: 1”, but that’s going to happen if you have English interface. In Russian it’s going to be “Этаж” which is literally a floor. At this point we can remember what happens to the wikis in different languages and look at this as an attempt to bolster a particular interpretation of level=* through localization. I’m talking about level tag because the number you see in the app comes from this tag. As a user, you may not know anything about tags and possible differences in their interpretations. Your most likely interpretation of the number you see is going to be that it’s a floor number, a designation of a floor inside the building, which is either evident from local traditions or directly written somewhere. You are unlikely to attempt to determine level zero and then count the specified number of levels upwards. In fact, this counting operation may seem unnecessarily complicated and even nonsensical, which looks like a good argument to just use the self-evident floor number as a value of level tag. With this assumption you’ll only get the correct floor number if the last editor of level tag on the particular POI shares this opinion. If not, in Russia you’ll most likely end one level below the POI. Sometimes it’ll be two levels. It’s going to happen when “first floor” is slightly below the ground. In some cases the level will coincide with the floor number even under this “counting” interpretation, but you wouldn’t know that in advance.

What are the problems for editors? Obviously, different people may want different values for the same tag on the same object. This may lead to edit wars. You may then propose to keep whatever level numbering scheme already exists in a certain building and make everyone follow this scheme. Unfortunately this is not always possible. In order to know what scheme is in place you have to find stuff that is already mapped with level tag and figure out what scheme it corresponds to. There’s a chance that no single scheme would fit because different things were mapped by people with different opinions. This is likely to happen if there are many elements tagged with level. On the other hand there could be few and you wouldn’t notice them. All this scheme guessing has to be done because nobody indicates what scheme is to be followed at a particular place. Nobody indicates that because according to most mappers there’s only one right scheme and other schemes shouldn’t exist.

Even if you know the scheme, you can find yourself in a situation where you have to change already existing level values. For example, you may tag all of the POIs along a street in one manner and eventually you get to a place that was mapped differently. Do you stop and change your way starting with this place? Do you go back and retag everything you already have entered? If you have entered a lot and there’s only a few things mapped differently, it makes more sense to retag those few things.

Of course having two different interpretations of one tag is inconvenient. We are better off with just one that makes more sense and is easier to use. And we already know which one it is. Just write the local traditional floor number, you can always check it on place, you don’t need to figure out where’s level zero, you don’t need to count floors, you don’t need to follow the rules made up by foreigners who don’t know how things work in your country. That’s how people who prefer this particular scheme think, however there are reasons to think otherwise.

That other way of thinking goes as follows. We had the definition of level that has 0 assigned to the first level above the ground level for at least seven years. This definition is used in Simple 3D buildings (S3DB) for about as long. All of the software that uses S3DB data relies on this definition. It would be inconvenient to come up with another “indoor” level numbering scheme. It may not even be a numbering because floors can be designated by letters and then you wouldn’t know the vertical order of levels without extra data. Even some of software that mainly concerned with indoor visualizations like OpenLevelUp assumes 0-based numbering. So there is only one scheme that works, it’s been around for a long time, and it’s how it defined in the wiki. That last statement about the wiki is a bit of a wishful thinking done by the proponents of this scheme.

Those were the ideas behind the two major level numbering schemes: locally-defined labeling (it’s may not be strictly numbering) and 0-based numbering. As you can see, the proponents of these schemes can be pretty convinced that their scheme is the correct one and they want the level tag for themselves. In addition you can come up with many more schemes. For example, you may want 1-based numbering where you say that those who think that ground floor and first floor are two different floors got their traditions wrong and have to adapt to 1-based counting because all normal people count from one.

One noteworthy scheme lies between the two major ones. A scheme that we’ll call locally-based numbering attempts to fix some issues with locally-defined labeling. It uses only numbers that make the vertical level sequence well-defined. For this scheme you replace all non-numeric level labels with numbers. For example, if a building had level K below level 0, like described in this comment, you replace K with -1. Usually it’s the same as matching the number sequence …, -2, -1, 0, 1, 2, … as close as possible with all numeric labels. In this case the result is usually going to be the same as picking either 0-based or 1-based numbering, whatever fits best.

There’s one extra quirk that is skipped levels. Imagine a 100-storey building without 13th floor. The best match with the sequence would involve setting level=2 for 1st floor, level=3 for 2nd and so on until 12th floor. This is not what people typically want to do so it’s fixed by extra hack. This hack can be added to any of the numbering schemes mentioned above. It consists of declaring some of levels as non existent and their numbers are thrown out of the sequence before it’s matched with numeric labels. It also makes level numbers incompatible with S3DB levels, in case you use it with 0-based numbering.

For places like Russia, no matter what scheme you pick, you lose either compatibility with existing tools or traditional floor numbers, maybe both. Losing traditional numbers is particularly annoying because you have to use numbers that are almost always one off and it’s easy to make mistakes because of that. I think that compatibility with tools is the main divide here. Those who use S3DB want to see the visualizations with tools that assume 0-based numbering. After a while they get somewhat comfortable with that scheme and are more likely to stick with it for other things. Those who don’t use S3DB see 0-based numbering as something alien.

How prevalent are the problems described here, are they worth your attention? In the place I map, Saint Petersburg, Russia, both main schemes are in use. That means you can’t rely on levels displayed by apps like OsmAnd. I’ve seen levels changed from one scheme to another when next user comes to edit elements with existing level tags. I had to do it myself too, in the situations I described above. Now I mostly avoid the buildings such as malls that are mapped using the other scheme, but eventually I’ll have to do something about them. I haven’t yet seen full-blown edit wars over level values, however currently there’s nothing that would stop one from happening.

What’s to be done about it? You can do something about the editing apps, the end-user apps and the tagging conventions with their documentation. That last thing is going to be the subject of another post, but I can tell right away what can be done with the editors even if we don’t agree on the exact meaning of level tag. This is for editors with indoor mode such as Vespucci. In this mode you don’t have to enter the level values directly, the editor sets them for you. You only have to select the level to be displayed. The level selector can be modified to display some other number instead of the actual level value, or display both actual and altered values alongside each other. The simplest way to specify how to alter the value is to have the level offset option that takes numeric values. For example, with the +1 offset, level=0 would be displayed as 1. A more elaborate options would be required to skip (or insert) certain numbers and replace numbers with letters (or letters with numbers), but the simple offset would solve a lot of problems.

I tried to write this post from neutral point of view without preferring any particular scheme. You can read about my opinion on which scheme is better and which one do I use in my previous post (in Russian). It’s quite long, but you only need sections Вертикальная геометрия and Как я маплю. The next thing to be discussed about levels is what exactly the wiki says. I’m going to leave it for another post.

Теперь можно рассмотреть, какие осмовские данные я использую для записи информации о POI. Эти данные можно разделить на геометрию POI и их теги. Здесь будет рассмотрена геометрия, а теги будут в следующих записях. Как выяснится, геометрию можно задавать различными способами, так что прежде, чем рассказать, какими из них пользуюсь я, придётся их отдельно разобрать, на что уйдёт большая часть записи.

TL;DR

Основная задача: отметить POI так, чтобы её было как можно проще найти либо обнаружить её отсутствие или изменение при последующей проверке. В пределах проверяемых участков достигается заданием последовательности POI вдоль контуров зданий, которую удастся воспроизвести при проверке, либо в которой удастся заметить изменения. Последовательность создаётся заданием соответствия между POI как объектами, имеющими существенную площадь в масштабах зданий, и входами как точечными объектами на контурах зданий. Соответствие задаётся либо явно заданием entrance=* и его соединением с POI, либо неявно позиционированием POI рядом с местом расположения входа. В случае, если последовательность задать невозможно по причине отсутствия взаимно однозначного соответствия POI и входов, изображается структура проходов внутри здания, ведущих к POI. Также возможно использование дополнительных тегов для обозначения вертикального положения перечисленных объектов.

Куда ставить POI?

В осме все данные находятся в одном слое, из чего следует, что всё надо позиционировать относительно всего. В случае с POI, их приходится обозначать в первую очередь относительно зданий, которые, как правило, уже нарисованы. Есть, конечно, места, где за рисование зданий никто не брался, но при этом POI там пытаются обозначать. В тех местах POI приходится позиционировать относительно дорог, которые обычно рисуют перед тем, как берутся за здания. Но всё это является задачами первоначального наполнения данными, а то, чем занимаюсь я – это обновление уже существующих данных.

В Петербурге здания обычно уже нарисованы, и есть участники, которые оперативно дорисуют то, что будет построено. Иногда, правда, встречаются неточности у уже нарисованных зданий, которые могут помешать их использованию в качестве ориентиров для расположения POI. Одной из разновидностей неточностей является неправильное деление расположенных вплотную друг к другу зданий. Какое деление правильное – вопрос с не всегда однозначным ответом, но можно указать очевидно неправильные варианты, такие как диагональный разрез от угла, выходящего на перекрёсток. Также встречается различные смещения близко расположенных зданий и достаточно большие искажения их формы, которые имеет смысл устранить перед обозначением POI. Подобного рода неточности могут быть в данных изначально, например, в следствии обводки снимков с низким разрешением, или рисованием по принципу «лучше коряво, зато быстро нарисовать всё, чем качественно нарисовать часть, а остальное оставить пустым». Также эти неточности могут быть привнесены позже участниками, не вполне понимающими, что они делают, среди которых в данном случае преобладают пользователи iD.

Строительство нового здания на месте снесённого старого

Иногда здания меняются и в центре города

Если здания внутри квартала расположены более-менее правильно относительно друг друга, то их можно использовать в качестве ориентира для POI, даже не выясняя, смещён ли весь квартал. При уточнении положения квартала достаточно будет сдвинуть здания вместе с расположенными относительно них POI. Хотя POI я и обозначаю подобным образом, есть объекты, которые я рисую по-другому. Например, тротуары, проходящие вдоль зданий, я обозначаю относительно улицы с целью выравнивания вдоль оси, значит тротуары сдвигать вместе с кварталом не надо.

Допустим, что здания в приемлемом качестве уже есть, и при обозначении POI первоочередной задачей является выбор их расположения относительно зданий. Так как большинство POI, подходящих по моим критериям из прошлой записи, находятся внутри зданий, то и места для них надо выбрать внутри. Это даст точкам адреса, которые не понадобится задавать вручную, если только не понадобится адрес, не совпадающий с адресом здания. Кстати, существует мнение, которое я не разделяю, при котором (некоторые) POI обозначаются не внутри, а на границе здания. Про него будет написано ниже.

Геометрия точки

POI это «точка интереса», а какая геометрия и площадь могут быть у точки? Геометрическая точка, у которой нет площади, это абстракция, которая может подходить, а может и не подходить в различных ситуациях. Насколько POI уместно отмечать в виде геометрических точек, зависит от того, как плотно они расположены. Если в одном здании не больше одной POI, то точка вполне подойдёт для обозначения такой POI, причём не понадобится даже думать, куда именно внутри здания ставить точку. Но в тех местах, где я отмечаю POI, часто бывает не так, и если без обозначения площадными объектами обычно можно обойтись, то конкретное место внутри здания для точки выбирать уже приходится.

Если POI расположены достаточно близко, то понадобится отразить в данных их расположение друг относительно друга, а также относительно прочих деталей, отмеченных на здании. Этими деталями обычно являются въезды (barrier=gate, tunnel=building_passage), входы (entrance=*), части здания (building:part=*) и объекты расположенные на стенах типа почтовых ящиков, телефонов и часов. Делать это приходится как для упрощения проверок POI, чтобы не приходилось искать случайным образом разбросанные точки, так и для обозначения взаимодействий POI, таких как расположение одного заведения внутри другого или наличие общего входа в разные заведения.

POI в виде точек

Допустим пока, что POI обозначаются именно точками. Но обозначаемое заведение не является геометрической точкой, а значит придётся принимать решение, куда именно точку ставить. Можно посмотреть в вики, куда там советуют ставить точки всяких магазинов, amenity и прочего подобного. Иногда это рекомендация ставить точку внутри, иногда – по центру. По центру, конечно, звучит логично, это конкретное место в отличие от просто внутри, но на деле выясняется, что годится этот выбор опять же только для низкой плотности POI. Поскольку при низкой плотности выбор конкретного места практически не важен, то и толку от совета ставить по центру практически никакого нет.

Точки по центру заведений

Какие проблемы с установкой точки по центру заведения?

  • Несмотря на то, что центр – это, казалось бы, конкретное место, для его определения понадобятся конкретные границы заведения. Тут могут возникнуть различные мнения по поводу того, где они проходят. Например, будете ли вы включать в них служебные помещения или ограничитесь только местами, доступными клиентам? Я служебные помещения включаю, о чём будет написано ниже.

  • Даже если определиться с тем, что именно включать в границы заведения, сами эти границы могут быть неизвестны. Если включать служебные помещения, то точные границы сложно определить в связи с отсутствием к ним доступа, но даже если и не включать, то всё равно границы определить сложнее обычного. Помещения находятся внутри здания, значит их не видно на снимках, и gps в них не работает. Тут можно заметить, что в этих сложностях ничего страшного нет, для начала можно решить и примерно, а потом уточнить. Однако речь шла о преимуществах выбора центра как места для точки, и преимуществом было то, что это конкретное место. Теперь же выясняется, что конкретности заметно поубавилось.

  • Необходимость в принципе выяснять границы является недостатком в случае, если есть способ выбора точки, при котором их выяснять не надо. А он есть, и он как раз пригодится при том варианте проверок, который я обычно использую: идти вдоль улицы и отмечать все заведения подряд, не обязательно в них заходя, и, следовательно, не обязательно зная их границы.

  • Для геометрической фигуры можно дать несколько определений центра, так что даже с точно известными границами конкретности всё равно может не быть.

  • «Ставьте точку по центру» звучит как уточнение рекомендации «ставьте точку внутри». Так будет, если заведение имеет форму выпуклого многоугольника. В других случаях центр может оказаться и снаружи. Так получится, например, если форма заведения П-образная. Точка POI, поставленная за пределами POI, выглядит довольно странно.

  • Центр – это не обязательно самое важное место, и пользователи при просмотре карты ищут, скорее всего, не его. Те, кто прочитал выше TL;DR, уже поняли, на какое искомое место и какой метод простановки точки без выяснения границ я намекаю.

  • Ещё они помнят, что там было написано про последовательность POI, ведь если POI много, то удобно, когда они как-то упорядочены, а не набросаны на здание неопределённым образом. Несмотря на то, что центр – это не случайное место, хотя, как следует из написанного выше, и не столь определённое как может показаться, при достаточно плотно расположенных POI порядка в их точках уже не будет. Это произойдёт, если площади POI перекрываются. Перекрываться они могут как включением, когда одно заведение располагается внутри другого, так и вертикально, когда одно располагается над другим. Есть места, где этого полно, например дома, у которых и первый и цокольный этаж заняты магазинами.

Итого центр – не лучшее место точки как для пользователя, так и для редактирующего данные участника.

Точки рядом со входами

Другой вариант выбора места для точки это её установка рядом со входом в заведение. Если определиться с тем, насколько рядом, и почему не прямо на вход, то получится тоже вполне определённое место, у которого не будет перечисленных выше недостатков. Тут нетрудно заметить, что я слегка соврал, так как определённость и порядок будут только при взаимно однозначном соответствии POI и входов. Для POI, наблюдаемых с улицы, обычно так и есть, а про то, что делать, когда это не так, будет написано ниже. Пока будем делать вид, что однозначное соответствие есть.

Почему имеет смысл ставить точку внутрь здания рядом со входом, а не на стену, прямо на вход?

  • Это гораздо ближе к приведенным выше рекомендациям ставить точку внутри или по центру заведения. Точка на стене, то есть границе здания окажется и на границе заведения, а не внутри его. Точка рядом со входом в центре не окажется, зато будет ближе к нему, чем точка на входе. Впрочем, бывает, что «рядом со входом» и «внутри» – это весьма разные места, но об этом потом.

  • Традиционно так и делают, во всяком случае там, где я редактирую. Из активно редактирующих центр Петербурга есть только один несогласный с таким методом участник. Поскольку почти все точки так и отмечены, то понадобится меньше переделывать, если тоже ставить точки внутри.

  • Из редакторов типа MAPS.ME или OsmAnd по-другому и не выйдет. Точнее, промахнуться мимо здания, конечно же, выйдет, и нередко пользователям MAPS.ME это удаётся, но это не является желаемым результатом. А вот поставить точно на стену не получится, и не стоит даже и пытаться, особенно если вход уже отмечен. Можно сказать, что это проблемы пользователей этих не вполне пригодных редакторов, но какую-то часть данных они внесут, и если не настаивать на приклеивание точки к стене, то придётся опять же меньше переделывать.

  • Включение точки в контур здания приведёт к правке здания. Возможно, это не слишком серьёзный аргумент, потому что добавление самого входа тоже приведёт к правке, а, как будет написано ниже, добавить вход мы можем захотеть.

Определённое расстояние

Причин ставить точку внутрь добавится, когда мы вспомним, что однозначного соответствия между входами и POI может и не быть. Но пока что ещё нужно точнее определить, что значит «ставить точку рядом со входом». Можно было бы этого и не определять, но тогда точки оказались бы разбросанными на разные расстояния от своих входов и порядка бы не было. Чтобы порядок был, можно задать определённое расстояние от входа и от стены, на котором должна находиться точка.

Помимо явно видимого порядка точек, определённое расстояние нужно для того, чтобы принимать меньше решений, то есть чтобы не думать, на какое расстояние ставить точки. При добавлении точки приходится принимать ряд решений: какое указать название, направление деятельности, сайт и т.д. Все эти решения отнимают время, так что чем меньше их делаешь, тем быстрее идёт ввод данных.

Расстояние от входа и границы здания до точки POI в моём случае равно двум метрам. Откуда эти два метра взялись?

  • Снова можно сказать, что традиционно так и делают. Конечно, ровно два метра традиционно не отмеряли, и ставить могли и на четыре метра, но не сильно больше. Чтобы ставили, например, на десять метров, я не помню.

  • Практически при любой ширине зданий точка, отстоящая на два метра от стены, будет ближе к этой стене, чем к противоположной. Редко попадаются здания у́же четырёх метров с POI внутри, причём такие, какие нельзя целиком отождествить с POI. Какие можно, а это, например, ларьки, либо сами пригодны для обозначения точками, либо позволяют поставить теги POI на свой полигон. Последний случай – это уже не обозначение POI точкой, так что его мы пока не рассматриваем.

  • Слишком близко к стене точку ставить не стоит, потому что тогда при корректировке геометрии здания она рискует оказаться за его пределами. Это произойдёт, если корректирующий не заметит POI, что бывает не так и редко. Типичный случай – когда сразу несколько зданий выравниваются вдоль улицы, например, потому что рядом с ними хочется провести линию тротуара, или потому что они вместе попали на снимок с коптера. Пара метров – расстояние, которое обычно и называется погрешностью рисования по снимкам, что позволяет надеяться на то, что корректировка произойдёт на меньшее расстояние и POI останутся внутри.

POI за пределами здания

Надежды оправдываются не всегда

  • Точке надо быть достаточно близко ко входу, чтобы в случае, когда рядом находятся несколько входов, можно было бы невооружённым взглядом определить, какой из них принадлежит POI. Для этого расстоянию от входа желательно быть меньше расстояний между входами, которое обычно больше двух метров, но бывает что не намного больше. Вариант с вооружением взгляда посредством рисования линий от входа до POI позже тоже будет рассмотрен.

  • Можно привести ещё одну причину, которая верна только на определённых широтах, в частности на той, на которой находится Петербург. В JOSM при десятиметровом масштабе, то есть когда рядом с линейкой в верхнем левом углу написано 10 м., ширина обводки площадных объектов, которые полностью не закрашиваются, примерно равна двум метрам. Такими объектами на данном масштабе являются, как правило, здания. Получается видимая граница закраски, на которую можно ставить точки POI, чтобы они были на одинаковом расстоянии от стены. Правда, двум метрам это расстояние будет равно при соблюдении некоторых дополнительных условий. Во-первых, должен быть добавлен какой-нибудь слой снимков, и включено масштабирование под их разрешение. Когда оно включено, слева от названия слоя появляется иконка в виде чёрных и белых квадратов в шахматном порядке. Включиться оно должно само при добавлении слоя, но можно случайно его выключить. Если его выключить, то не будет какого-то одного десятиметрового масштаба, так как масштаб можно будет устанавливать более свободно, а не только по шагам, подогнанным под разрешение снимков. Причина эта довольно специфическая, но ставить точки на два метра от стены я начал именно благодаря ей.

Обводка здания и POI на ней

Выравнивание под обводку здания: 1 – масштаб; 2 – линия, вдоль которой можно расставить POI; 3 – индикатор ограничения масштаба под снимок, ограничение работает даже когда снимок не отображается

Не лень ли выравнивать точки на два метра? Лень, поэтому я это делаю не вручную. Для подобного рода задач я пишу скрипты к плагину CommandLine для JOSM. В данном случае это скрипт PoiAlign из моего форка скриптов.

Проблемы определённого расстояния

Можно возразить, что два метра это лично мои выдумки, и другие участники не обязаны ставить точки так же. Поскольку я могу подвинуть точку, поставленную другим участником, а ему ничто не мешает подвинуть её обратно, может начаться война правок. Причиной этой войны будет произвольно выбранное расстояние, значит настаивать на определённом расстоянии вредно? Разрешить это разногласие можно, отказавшись в данном случае от обозначения POI точкой и перейдя к обозначению полигоном. В большинстве случаев перемещением точек туда-обратно никто не занимается, чаще расстояние до границ зданий меняется из-за сдвига самих границ.

Если уже поставленные точки находятся на разном расстоянии от стен, не теряется ли информация при их установке на одинаковое? Скорее всего нет, потому что вряд ли эти расстояния были выбраны по какому-либо принципу, и никакой информационной нагрузки в их различиях нет. Тут, однако, есть важное исключение с точками, которые находятся в глубине здания, когда пройдя через вход вы не оказываетесь сразу в заведении. Такие точки выравнивать уже может не иметь смысла, особенно если неизвестно, где именно внутри здания находятся их заведения, и попадут ли внутрь этих заведений точки после выравнивания.

С точки зрения рендеринга можно привести аргументы как против определённого расстояния, так и против слишком маленького, и два метра в этом смысле можно посчитать слишком маленьким. Рендерить POI тем легче, чем больше между ними расстояния. Если не пытаться выстроить их в одну линию, то расстояния можно увеличить, расставив POI так, чтобы некоторые были ближе к стенам, некоторые – дальше. Подобные действия, правда, лучше оставить для самих рендереров, но пока что известные рендереры делать этого не умеют.

Если POI стоят слишком близко к линии улицы, то их рендеринг будет сталкиваться с рендерингом названия улицы. На многих рендерах, включая стандартные тайлы, название POI может выводиться только под её значком. В этом случае наиболее пострадают POI на северной стороне улицы. Это опять же является проблемой рендереров, которым никто не мешает начать выводить названия сверху или сбоку. Можно повторить и традиционную рекомендацию «не рисуйте под рендер», хотя тут описаны проблемы любого рендерера, а не конкретного.

Можно сравнить метод расстановки POI с тем, как это делается на других картах. По какому принципу расставлены точки на картах Гугла и Яндекса? В общем, никакого принципа там не наблюдается. Точки стоят как попало, не обязательно даже внутри зданий. Это может объясняться тем, что они находятся в отдельном слое, и относительно зданий их ставить никто не пытается. Этим слоем могут быть их «народные» карты, где контуры зданий могут отличаться от «профессиональных». Ещё Гугл и Яндекс выводят далеко не все известные им POI, что позволяет уменьшить количество столкновений при рендеринге, но какого-либо принципа в их выборе тоже не наблюдается. На их рендерах можно увидеть точки, которых уже не существует, включая те, про которые им самим известно, что они не существуют. Яндекс с недавнего времени также показывает и входы в заведения. Ещё раньше это стал делать 2гис. 2гис при этом, как правило, не пытается представлять координаты POI и ограничивается их адресами, а значки точек выводит в горизонтальной плоскости там, где их входы, почему-то сдвигая их по вертикали на крышу.

Фрагмент Яндекс.Карт с выбранной POI

Яндекс показывает, где находится вход в ресторан Тан-Жен, и почему-то он отдельно от самого ресторана

В отличие от осма, упомянутые выше сервисы могут и не претендовать на то, что данные о POI в них являются географическими. Осм, в свою очередь, не претендует на то, чтобы быть справочником организаций, с чем, конечно же, не согласятся сеошники.

Адаптация точек рядом со входами

Если отбросить рендер-проблемы и потенциальные войны правок из-за расстояний, то какие проблемы у метода обозначать POI точками, расположенными на расстоянии двух метров от входа останутся? Проблемы будут возникать в следующих ситуациях:

  1. POI значительно дальше двух метров. Тогда одной точкой не выразить информацию и о месте входа в здание, и о месте POI. По данному методу информация о месте POI выбрасывается, но это неправильно. Точка является обозначением именно POI, а не входа, значит лишней информацией у точки является место входа, и при необходимости что-то выбросить, следовало бы избавиться от него.
  2. За одним входом несколько POI. Если строго следовать методу, то несколько точек придётся ставить в одно и то же место. При этом внутри POI в лучшем случае окажется только одна из них, значит информации о месте POI опять нет.
  3. У одной POI может быть несколько входов. Одна точка не может передать информацию о двух входах, и по методу место для точки не определено.

Допустим, что несмотря на перечисленные выше проблемы мы всё равно хотим пользоваться описанным выше методом, то есть для обозначения POI ставить только одну точку, которая (как правило, от которого мы здесь отступим) ставится рядом со входом. Как можно его адаптировать к ситуациям 1, 2 и 3?

Ситуация 1: POI не рядом со входом. При внешней проверке, которую я обычно и делаю, когда иду смотреть участок первый раз, появляется дополнительная сложность: неизвестно, насколько далеко от входа находится POI, так как всё, что видно, это дверь с вывеской. Выше я писал, что не стоит стремиться выравнивать POI, находящиеся в глубине здания, но для этого нужно знать, что POI действительно в глубине. В итоге такие POI всё равно отмечаются рядом со входом. Если же их истинное расположение известно, то точки можно поставить куда-нибудь внутрь них. Дальше, поскольку при данном методе дополнительно ничего не рисуется, придётся добавить к ним примечание, например в теге note, как туда пройти. Понятно, что лучше было бы проход нарисовать, но, к сожалению, причины его не рисовать могут не ограничиваться незнанием его расположения. Рисованием проходов мы займёмся при последующих модификациях метода.

Ситуация 2: за одним входом несколько POI. Ровно в одно место их ставить, конечно же, никто не будет, значит их придётся каким-то способом раздвигать. Насколько результаты этого способа будут соответствовать настоящему расположению POI зависит от обстоятельств. Иногда можно хотя бы примерно оценить расположение POI, например, если за входной дверью сразу видны проходы в отдельные POI. Допустим, виден проход налево в один магазин, и направо в другой, тогда первый магазин можно отметить точкой чуть левее входа, другой – точкой чуть правее. Если оценить расположение POI нельзя, то вместе с ситуацией 2 может иметь место и ситуация 1. Собственно так и будет, если рассматриваемый вход – это вход в бизнес-центр или что-нибудь подобное. Тогда у самого входа будет написано про десяток организаций, но их расположение относительно здания и относительно друг друга останется неизвестным. В этом случае придётся городить скопление из точек рядом со входом, не имеющие никакого отношения к их истинному расположению.

Кое-какая информация о месте POI в случае с БЦ бывает. Обычно это номер этажа, но это расположить POI горизонтально не поможет. Если повезёт, то можно обнаружить окна каких-то из организаций. Всё это, казалось бы, повод не мапить подобные случаи без проведения внутренней разведки здания, после которой можно будет отметить POI другим способом, с рисованием внутренней геометрии. Однако куча POI может оказаться за любой дверью в любом здании, а не только в явно офисном, которое можно было бы заранее решить исключить из проверяемого участка.

Дверь с множеством табличек POI

За одним из входов в обычное жилое здание скрывается более десятка POI

Частный случай ситуации с несколькими POI – расположение одной POI внутри другой. Есть «большая» POI, а внутри неё – «маленькая», не имеющая собственного входа снаружи здания. Точку внутрь точки поставить не получится, поэтому если есть намерение по прежнему ставить только точки, то относительное расположение опять придётся передавать фиктивными координатами точек. В данном случае «большая» точка ставится как обычно, а «маленькая» – за ней вглубь здания, и её уже выравнивать на два метра от стены не надо.

Ситуация 3: у POI несколько входов. Ясно, что обычно не следует ставить по точке у каждого входа. Иногда бывают и менее ясные случаи, когда входы ведут в не соединённые между собой части заведения. Тут, строго говоря, одной точки не хватит не только для того, чтобы обозначить входы, но и для того, чтобы обозначить само заведение. Но если хочется обойтись одной точкой, придётся выбрать «главную часть», например, которая больше, и поставить точку у входа в неё. Подобным же образом можно поступить и в более простом случае, когда входы ведут в одно место, и заведение не состоит из нескольких частей. Тут можно выбрать «главный вход» и поставить точку рядом с ним. Главным может быть вход, который шире, который дольше открыт либо открыт в более доступное время, или который в более доступном месте, например на углу. Другой способ выбрать место для точки – поставить её посередине между входами, если входа два. Если входы расположены на разных сторонах здания, то точку можно опять же поставить на углу между ними.

Угол здания и два входа с разных сторон от него

Два входа в «Кондитерскую» с разных сторон относительно угла здания

Входы

Раз уж в большинстве случаев, описанных выше, точки ставились относительно входов в здания, почему бы не обозначить и сами входы? Тогда чаще всего для POI будет нужно поставить две точки: entrance=* на границу здания на место входа и точку POI в двух метрах от него. Если входов больше одного, то точек получится больше двух.

Недостатки

Первая причина этого не делать – лень ставить дополнительную точку. Для борьбы с ленью предназначен уже упомянутый скрипт PoiAlign, который вместе с выравниванием относительно границы здания может и поставить вход, и выровнять POI относительно существующего входа.

Также входы являются дополнительными данными, которые нужно поддерживать, при этом не настолько стабильные, насколько может показаться. Как уже было сказано в предыдущей записи, из окна на первом этаже могут сделать дверь, а из двери – окно. Двери, ведущие на лестницы жилых домов, гораздо более стабильны, поскольку саму лестницу переместить гораздо сложнее, но в связи с POI нас интересуют преимущественно не они.

Арка, в которой расположен вход в магазин

Помимо обычной переделки окна в дверь и обратно, упомянутой в прошлой записи, во вход может превратиться и арка, через которую ранее шёл проезд во двор

На выбор места для входа уходит больше времени, чем на выбор места для точки POI. Если промахнуться на несколько метров с POI, то велика вероятность, что точка всё равно окажется внутри заведения. Входные двери по сравнению с заведениями гораздо меньше, значит и ставить их надо точнее.

Возможны также сложности с определением наличия и количества входов, связанные с тем, что вход это не обязательно (одна) дверь. Вход может быть и без двери, хотя такое встречается редко. Если двери прямо на границе здания нет, то, скорее всего, она есть где-то дальше. Вход может состоять и из нескольких расположенных рядом и обычно одинаковых дверей. Почему их не обозначить отдельными входами? Они ведут в один и тот же коридор, фойе или что там за ними. Их могут открывать по очереди, например, сегодня открыта правая дверь, завтра левая, а послезавтра там важное мероприятие, и будет открыта центральная, а по окончании мероприятия на выход откроют все. Если отметить такие двери отдельными входами, то это усложнит данные и сразу даст одну из описанных выше ситуаций с несколькими входами для POI. Если отдельные входы в данном случае отмечать не хочется, то надо ещё определить, имеет ли место данный случай для каждой конкретной группы дверей. Если двери непрозрачные, то определить это может быть нереально без захода внутрь. Несмотря на только что сказанное, никто не мешает обозначить сами двери независимо от того, скольким входам они соответствуют. Для собственно двери есть отдельный тег door=*. Если принимать все эти решения и всё это делать, то можно потратить много времени, которое, возможно, лучше было бы потратить на ввод следующих POI.

Группа из двух дверей

Две двери, ведущие в одно место, открыта одна из них

Бывают и противоположные ситуации, когда дверь это не обязательно один вход. Перегородка, поставленная сразу за двустворчатой дверью превращает её в два входа, ведущие в разные места. Если входов у POI всё-таки несколько, то обозначить, какие из них соответствуют POI, только посредством расположения точки POI рядом со входом либо совсем не выйдет, либо выйдет только для одного из них. Но, строго говоря, само по себе расположение рядом не говорит о связи. Говорит оно лишь для участника, следующего данному методу обозначения POI, а другие участники могут методу и не следовать.

Ещё одна неприятность – два входа, расположенные один ровно над другим. Поскольку это разные входы, то им нужны разные точки, но точки эти должны находиться в одном и том же месте, что неудобно. Лучше их чуть-чуть раздвинуть. Их POI, скорее всего, мы тоже захотим раздвинуть.

Лестницы, ведущие наверх и вниз к дверям, расположенным друг над другом

Один вход ровно над другим, добраться до них позволяют лестницы, приделанные снаружи к зданию

Преимущества

У обозначения входов вместе с POI есть и преимущества. Если не отметить вход, то его может позже отметить другой участник. Этот участник может не знать, что POI была отмечена рядом с местом входа и не станет пытаться сделать так, чтобы вход и точка POI оказались рядом. Поскольку место для входа выбрать сложнее, а при криво нарисованном здании вообще нельзя выбрать однозначно, велика вероятность того, что точка входа окажется не там, где точка POI. После этого одну из точек придётся двигать.

Если потратить достаточно времени на выбор места для входа, то не очень захочется тратить его ещё раз. Если при этом место входа в осмовских данных представлено только точкой POI, то его сохранность зависит от сохранности этой точки. Сохранность же точки зависит от того, насколько хорошо функционирует соответствующее ей заведение. Есть участники, которые готовы по любому подходящему поводу эту точку удалить. До этого мы доберёмся в следующей записи, когда будем рассматривать lifecycle prefix. Сейчас же отметим, что закрытый магазин они потрут, потому что он для них не магазин, зато закрытый вход они не потрут, потому что… В общем, если хотите, чтобы место входа осталось в данных, отметьте на нём entrance.

Обозначение

Вход обозначается точкой с тегом entrance=*, в который записывается тип входа. Чаще всего типом является просто entrance=yes, встречаются также значения main, staircase и service. Когда стоит ставить main, а когда хватит и обычного yes, не всегда очевидно. Иногда main используется для основного входа в любое место. Тогда единственный вход в магазин будет main, и main-входов будет даже больше, чем обычных. Противоположным вариантом будет считать main’ом только единственный главный вход в здание, если он есть, и у большинства зданий его нет.

Некоторые участники предлагают считать вход в магазин отдельным типом входа, и обозначать его entrance=shop. Объясняют они это тем, что без данного значения из осмовских данных непонятно, куда ведёт вход. Ниже будет показано, что нарисовав проходы внутри здания, можно сделать так, чтобы, куда он ведёт, понятно было. Это несколько убавляет причин использовать entrance=shop, хотя сам принцип задавать значение entrance по месту за входом уже используется в entrance=staircase.

За entrance=shop можно привести и другие аргументы: это тип использования входа или это конструктивная особенность входа. Подойдут оба аргумента. С точки зрения типа использования это вход для неограниченного множества посетителей, которые надолго в данном месте не задержатся, которые могут стать, а могут и не стать клиентами заведения, и могут использовать этот вход для выноса приобретённого товара. Вход может использоваться достаточно часто для прохода и туда, и обратно, значит он должен легко открываться, и через него должно быть удобно ходить встречным потокам людей. Может быть, на счёт «удобно» я преувеличиваю, но обычно сделано хотя бы что-то, чтобы облегчить встречный проход, например, есть возможность увидеть сквозь дверь, что кто-либо идёт навстречу. То есть дверь часто бывает прозрачная – это мы перешли к конструктивным особенностям. Ещё к ним можно отнести достаточно большую ручку двери, или даже автоматическое открывание. У такого входа не будет кнопок, переговорных устройств и прочих хитростей – за дверями со всем этим магазины тоже бывают, но на сам вход при этом не обязательно ставить entrance=shop. В общем, этот тег – не такая странная идея.

Дверь на лестницу и дверь в заведение

Два входа: staircase и shop; перед вторым входом ступеньки, у первого входа ступеньки внутри, на то он и staircase

Ещё встречается entrance=exit. «Вход=выход» некоторым так не нравится, что они предлагают использовать другой тег, а именно exit=*. Но на самом деле почти любой вход является также и выходом. По идее тогда следовало бы ставить почти всегда пару тегов entrance и exit, а это не слишком хочется делать. Можно вообще задуматься, почему обычно пишется именно «вход», а не «выход». Видимо, потому что в осме рисуется преимущественно то, что находится вне зданий, глядя на это из мест опять же вне зданий.

Если мы ограничимся только тегом entrance, то entrance=exit следует ставить на выход в чистом виде, через который нельзя войти. У POI и даже у мест скоплений POI, типа ТК, такие выходы попадаются редко. Чаще они встречаются на объектах с ещё большими потоками людей, например, на транспортных объектах вроде метро. Входы и, возможно, выходы метро считаются такими важными, что они удостоились своего собственного тега railway=subway_entrance. «Возможно» – потому что на выходы этот тег ставят менее охотно, предпочитая вместо него entrance=exit. Впрочем, и на вход в добавок к railway=subway_entrance иногда ставят entrance=main. Проблем было бы меньше, если бы тег railway для входов не использовался, но он был введён в употребление ещё в те времена, когда вход в здание обозначался как «здание», то есть building=entrance. Есть попытки ввести подобный тег и для железнодорожных станций.

Дверь с надписью «Exit only»

Здесь только выход из магазина матрёшек

Поскольку вход обозначается точкой, можно рассмотреть, является ли точка подходящей абстракцией для него. Для POI, как мы знаем, она подходит не всегда. В большинстве случаев вход это одна дверь, а она мала в масштабах здания, так что обозначить её точкой приемлемо. Неприемлемо это станет в случае очень подробного indoor mapping’а с сантиметровой точностью. Сейчас это редкое явление, хотя вот французы говорят, что они так мапят железнодорожные станции. Также вход может быть группой дверей, то есть быть больше, но в этом случае, обычно, и само здание большое, так что вход всё равно мал относительно здания.

Выше мы подразумевали, что вход в здание находится на его границе, но это не всегда так. Вход может находиться и внутри площади здания. Распространённым вариантом входа внутри является вход, расположенный под аркой. JOSM выдаёт предупреждения, если entrance не стоит на какой-либо линии. В случае с аркой линии, на которую можно было бы поставить точку не существует, потому что стены арки как правило никто не рисует. Если хочется линию по этому поводу создать, то альтернативой рисованию стен арки может служить рисование прохода ко входу, о чём будет написано ниже.

Арка с двумя дверями под ней

Входы в здание под аркой

Ещё один вариант нахождения входа внутри площади здания – расположение входа под частью здания, не касающейся земли. Сам вход при этом будет на границе касающейся земли части, то есть на линии building:part, что вполне устраивает валидатор JOSM’а. В этих случаях, когда вход оказывается внутри площади здания, находящиеся за ним POI, конечно же, не нужно выравнивать относительно границы здания, хотя можно их выровнять относительно границы его части.

Входа, доступного для клиентов заведения, может и не существовать. Вместо него бывает окно для приёма и выдачи заказов. Тогда точку POI придётся ставить уже относительно окна. В другом случае окно присутствует не вместо входа, а дополнительно к нему. Тут уже POI лучше ставить относительно входа. И в том и в другом случае может возникнуть желание обозначить окно, и, следуя тому, что предлагается в ветке форума про МакАвто и МакЭкспресс, можно воспользоваться для этого тегом amenity=walk_up_window. Хотя по большей части в той ветке форума обсуждается, является ли подобное окно отдельной POI или нет, для нас это сейчас не важно, потому что само окно можно отметить в любом случае.

Три окна с шавермой и кофе

Окна обслуживания тоже могут идти плотно

Соответствие входов и POI без проходов

Как уже было сказано выше, само по себе расположение POI рядом со входом не говорит о том, что в POI ведёт именно этот вход. В следующем разделе будет показан наиболее логичный с точки зрения географических данных способ это соответствие задать. Тот способ будет подразумевать рисование дополнительных объектов, а в этом разделе мы разберём, что можно сделать, если дополнительно рисовать ничего не хочется.

Совмещение

В разделе Точка рядом со входом описывалось, почему точку POI лучше ставить внутрь здания, а не на стену. Но если мы взялись ставить и точку входа, которая окажется уже на стене, может быть можно ей и ограничиться, поставив на неё все теги заведения вдобавок к entrance=*? Помимо того, что это самый экономичный по отношению к рисованию способ, он ещё и наиболее явно задаёт соответствие входа и POI. К сожалению у этого способа есть серьёзные недостатки:

  • Все вышеописанные причины ставить точку POI внутрь никуда не исчезают от того, что на ней будет ещё и тег entrance. Допустим, мы считаем, что это хорошие причины и ожидаем, что они тем более являются хорошими для тех, кого не интересует обозначение входов, а это большинство мапящих POI. Тогда нас должно беспокоить, что метод объединения POI и входа в одной точке несовместим с методом обозначения POI внутри здания, по которому основная часть POI и обозначена, на что есть хорошие причины. Эти «объединённые» POI будут выделяться среди остальных.

  • Вход и POI это разные сущности, так что нежелательно представлять их одним осмовским элементом. Проблемы, которые могут возникнуть, связаны с использованием тегов, которые сами по себе не задают чего-то физически существующего, и ставятся в дополнение к тем тегам, которые задают. То есть это такие теги, которые уточняют тип сущности или описывают её свойства. А если на элементе два тега, которые задают две разные физические сущности, то к какой из них станет относиться добавленный на тот же элемент дополняющий тег? Самым распространённым дополняющим тегом является name. На POI, подобные рассматриваемым в этих записях, name стараются поставить всегда, когда название удаётся определить. Тогда name окажется и на «объединённой» точке, и его значение сможет считаться названием входа, а это не то, чего обычно хотят, хотя некоторые в ряде случаев предлагают делать исключения. Можно, конечно, возразить, что у входов редко бывают названия, следовательно ясно, что name относится не ко входу, однако name – не единственный подобный тег. Такая ситуация возникает не только со входами. Ниже будет рассмотрена ситуация, когда POI будет совмещена со зданием, и нужно будет задать и название здания, и название POI. Там же будет рассмотрен и другой взгляд на эту проблему, при котором мы утверждаем, что отмечаем мы в первую очередь не заведение, здание или вход в него, а географическое место. Если мы посмотрим таким образом на точку с тегами и входа, и POI, то name относится не ко входу и не к POI, а к месту, а, значит, неопределённости, к чему относится name, нет. Однако в данной ситуации нам это не поможет, потому что вход и POI это разные места, а то, что осмовских данных они представлены одной точкой – результат экономности при добавлении точек для рассматриваемого метода. Становится видно, что экономность эта проявлена зря.

  • Обозначить вход и POI одной точкой не выйдет, если нет взаимно однозначного соответствия вход-POI. У метода поставить POI рядом со входом в этом случае тоже возникнут проблемы, но их легче исправить. Здесь же, если входов у одной POI несколько, то придётся выбирать «главный» вход, к которому будут добавлены теги POI. Если же за одним входом несколько POI, то поставить их теги на одну точку не получится, и придётся выбирать уже «главную» POI, а остальные со входом не совмещать. При этом ни «главного» входа, ни «главной» POI может на самом деле не быть.

  • Раз уж все POI со входами совместить не получится, можно предложить это делать только в случае однозначного соответствия, а в других случаях ставить точки POI внутри зданий. Тогда пока за входом одно заведение, оно совмещается со входом. Если там открывается ещё одно, то, помимо его добавления, старое заведение отделяется от входа. Если какое-то из них закрывается, то оставшееся, видимо, снова приклеивается ко входу, хотя, скорее всего, этого уже делать никто не будет. Так что лучше просто всегда ставить POI внутри зданий.

Отношение

Допустим, что вход и POI обозначены разными элементами. Как обозначить то, что вход относится к POI? Может быть, осмовским отношением?

Отношения в осме – довольно неудобные элементы, например, потому что нет самого объекта отношения, который выводился бы редактором, и на который можно было бы ткнуть, чтобы его выбрать. Ткнуть можно только член отношения, и только через член можно выбрать само отношение. Без помощи членов до отношения можно добраться через список, существующий отдельно от карты, что менее наглядно. Сказанное про список относится к JOSM, в других редакторах чего-либо подобного может и не быть. Неудивительно, что использования отношений стараются избегать, и хотя для целей соответствия входа и POI было придумано несколько разновидностей отношений, ни один из них широко не используется.

  • Отношение building. Отношение позволяет задать здание и связать с ним его входы и POI. Непонятно, зачем это делать, ведь входы и POI и так находятся на контуре здания или внутри него. Ещё более непонятно, как это позволит нам задать соответствие между отдельными входами и POI. Предлагается же задать его таким довольно странным способом: создать отдельное отношение здания для каждой POI, про которую известна дополнительная информация типа отдельного входа. Вход при этом надо записать в него с ролью entrance, а саму POI – не совсем ясно, с какой, видимо с outline, что будет означать, что POI надо обозначить полигоном. Почему отдельная POI превращается в здание – непонятно. Короче, получается что-то страшное, что делать не стоит. Для того, чтобы сделать что-то менее страшное, были придуманы два следующих типа отношений.

  • Отношение site. Это отношение ещё неоднократно нам встретится, но, к сожалению, нам ни разу не удастся заключить, что оно-то и является решением очередной проблемы. Если посмотреть на текущую редакцию его описания, то вообще не понятно, как оно может нам помочь со входами. В этой редакции – действительно никак. Однако ранее это отношение, предназначенное для сбора нескольких элементов в единое целое, могло включать в себя и член с ролью entrance. Позже его, видимо, посчитали излишним, так как отношение позволяет задать периметр объекта, а на периметре можно искать уже сам вход, да и чем является периметр решили переопределить. Впрочем, возможно и в прежней интерпретации использовать его для задания соответствия входа и POI не получилось бы, потому что нужный нам вход является, строго говоря, входом в здание, и не всегда является входом непосредственно в заведение, и, следовательно, не всегда является частью заведения, которую можно было бы собрать в одно отношение с ним. Некоторым участникам могло казаться, что site подходит для решения данной задачи, другим могло казаться иначе. В данный момент вообще не наблюдается согласия, для чего это отношение предназначено. Например, в Петербурге его используют для коллекций типа «Сеть АЗС Лукойл», то есть для того, что текущая редакция вики делать не рекомендует. В итоге это отношение для решения нашей задачи не подходит.

  • Отношение associated_entrance. Популярностью это отношение не пользуется, зато оно наиболее близко по смыслу к поставленной задаче. Оно достаточно простое и логичное, так что если бы вы про него не знали, то придумали бы что-нибудь очень похожее. Если того, что описано в следующем разделе, сделать не удастся, а соответствие вход-POI как-то обозначить захочется, то лучше всего использовать именно этот тип отношения. Как нам объясняет страница-пропозал, все POI здания неявно связаны со всеми входами. Однако мы знаем, что в реальности чаще всего это не так, и связи между каждым входом и каждой POI нет. Зато всё множество входов и POI можно поделить на непересекающиеся подмножества, внутри которых связи уже есть. Тогда для каждого из таких подмножеств можно создать отношение associated_entrance. Каждое подмножество будет состоять из одного или нескольких входов и из одной или нескольких POI, при этом через любой из входов можно пройти в любую из этих POI. Все входы подмножества надо добавить в отношение с ролью entrance, а все POI подмножества – с пустой ролью.

Видно, что способы задания соответствия с использованием отношений имеют по крайней мере одно преимущество перед совмещением в одну точку – соответствие можно ими задать даже если оно не взаимно однозначное. Это значит, что мы справимся с таким случаем, как вход, за которым магазин, через который можно пройти в ещё один магазин. Способ из следующего раздела позволяет справиться с таким случаем ещё лучше.

Проходы к POI

Если не объединять вход и POI в один элемент, которым может быть точка или отношение, то соответствие между ними придётся задать геометрически, то есть что-то дополнительно нарисовать. Самый логичный способ это сделать – нарисовать проход, ведущий от входа к POI, а также, если нужно, от одной POI к другим. Нарисованный проход задаст соответствие как с точки зрения машиночитаемых данных, так и с точки зрения участников, и избавит от необходимости писать примечания типа «вход через арку/другой магазин». Также, поскольку проход может соединять несколько входов и POI, он избавит от проблем, связанных с отсутствием их взаимно однозначного соответствия. Проход этот в реальности может состоять из коридоров, лестниц, направлений движения через залы или как бы вообще не существовать, когда заходишь в дверь и сразу оказываешься в заведении.

Если принять этот способ, то отмечание POI превращается в разновидность indoor mapping, только в отличие от распространённого Simple Indoor Tagging, когда рисуются препятствия типа стен, здесь наоборот рисуются проходы. Препятствия, конечно, тоже можно отметить, но это не решит поставленной задачи соединить вход с POI. Вычисление соответствия входов и POI по данным о препятствиях будет заключаться в составлении поэтажных планов и дальнейшей маршрутизации по площадям этих планов, свободным от препятствий. Маршрутизацию по площадям пока никто не делает, и ещё непонятно, однозначно ли определены соединения между планами в виде лестниц и прочих не лежащих в плоскости проходов. Если же рисовать вместо этого линии проходов, то подойдут обычные средства маршрутизации. Точнее, поскольку маршрутизация нужна только в пределах одного здания, подойдут даже и тупые средства типа поиска в ширину и даже в глубину.

Также рисовать препятствия, как правило, сложнее, в частности это требует большего количества линий. Например, для изображения прямого прохода через коридор понадобится добавить один отрезок, зато ограничивающие его стены потребуют уже четыре. Проще препятствия становится рисовать, когда нужны целиком несколько этажей, так как есть средства задать повторяющиеся на разных этажах элементы. Это может пригодиться для торговых комплексов, но не для групп магазинов за одной дверью на одном-двух этажах, проходы к которым не вписываются в общий план здания. Эти проходы являются, как правило, результатом переделки жилых и хозяйственных помещений в торговые, чего полно в центре Петербурга.

Задача соединения входов с POI делится на две подзадачи: выяснение геометрии прохода и, заодно, более точного расположения POI, и собственно обозначение прохода осмовскими элементами. Поскольку разведка на местности будет рассматриваться в другой записи, время писать про первую подзадачу ещё не пришло. Здесь она упоминается только для того, чтобы обратить внимание на возможные дополнительные действия для данного метода обозначения POI, которые придётся выполнить на месте, по сравнению с более простым методом, когда проход не рисуется. Пока же можно отметить, что сложность первой подзадачи варьируется от тривиальной, когда за входной дверью в здание находится только один магазин, до нереальной, когда за дверь никак не попасть. В первом случае никаких дополнительных действий на месте предпринимать не понадобится, а в последнем, видимо, придётся от соединения входа с POI отказаться.

Перейдём ко второй подзадаче. Она заключается в том, чтобы соединить одной или несколькими линиями один или несколько входов с одной или несколькими точками POI. Какие осмовские элементы нам для этого подойдут? Подойдут в первую очередь линии с пешеходными тегами highway=*, а именно:

  • highway=footway – тег, используемый для пешеходного чего угодно, когда не подходит ничего другое; как следствие, используется слишком широко, зато у него есть уточняющий тег footway=*;
  • highway=steps – тег для обозначения лестниц; чаще всего используется для ступенек вне зданий, хотя большинство лестниц находятся внутри;
  • highway=corridor – гораздо менее поддерживаемый тег для коридоров, зато предназначенный для использования именно внутри зданий.

Насколько в принципе уместно соединять POI с highway? Например, валидатору JOSM’а не нравится, когда точки amenity, office, shop соединены с highway. Но тут валидатор проявляет непоследовательность, ведь если POI отмечена полигоном, то никаких возражений с его стороны не поступает.

Раз уж даже редактор возражает против рисования проходов внутри зданий, может быть без них можно обойтись? И обойтись на самом деле можно в большинстве случаев обозначения видимых с улицы POI. Эти POI мы выстраивали в последовательность, ставя их на определённое расстояние от границы здания, чтобы за ними было легче следить. При имеющихся данных о последовательности мы знаем, что, допустим, сначала идёт магазин А, потом Б, потом В. Если в реальности мы увидим магазин Г между А и В, то мы будем знать, что Б надо поменять на Г. Но бывают случаи, когда в последовательность магазины не выстроить, например, если между А и В идёт Б, но в глубине Б есть коридор налево с Б1 и направо с Б2. Если мы начнём подозревать, что Б2 закрылся, нам надо знать, куда идти внутри здания, чтобы найти место на котором он находился, и решить, что с ним делать. Типичными примерами таких Б1 и Б2 являются точки продажи кофе с собой и точки ремонта электроники, часто безымянные. Такие точки придётся ставить вглубь здания вне последовательности, и если они не соединены проходами с другими POI и/или входами, то будет сложно доказать, на месте ли они до сих пор. Дело осложняется ещё и тем, что они могут идти группами по несколько штук в одном здании с близко расположенными входами одновременно на нескольких этажах.

Место с несколькими POI, соединёнными пересекающимися проходами

Несколько дверей, за которыми по несколько POI на нескольких этажах; рядом ещё и метро

Новый вход в подвал

С того момента, как я в прошлом месяце сфотографировал это место, в подвале появилось ещё три POI – это под бывшим Макдоналдсом на Сенной, на месте которого теперь тоже три POI, и это я ещё не говорю, что на 2, 3, 4 и 5 этажах

Напоследок, перед рассмотрением отдельных составляющих проходов, заметим, что данный метод рисования проходов, а не препятствий в основном предназначен для небольших групп POI, находящихся за одним-двумя входами. Насколько он уместен для больших торговых комплексов я пока сказать не могу, так как не пробовал их мапить полностью. Возможно этот метод подойдёт и для бизнес-центров, так как там многие препятствия, в частности стены между офисами не видны. В отличие от ТК, там, скорее всего, нет прозрачных дверей и витрин, сквозь которые видны внутренности помещений, и гораздо меньше возможностей в эти помещения заходить.

Теперь рассмотрим составляющие проходов.

Лестницы

Для лестницы ничего лучше highway=steps не подходит. К лестнице внутри здания придётся добавить как минимум indoor=yes. Это пригодится для рендереров, делающих различие между тем, что внутри, и тем, что снаружи, таким как OsmAnd.

Хорошо, когда лестница на пути к POI специально сделана для этого пути, и ни в какое другое место не ведёт. Если же путь к POI проходит через такую лестницу, какие обычно находятся в лестничных клетках многоэтажных зданий, и сама точка находится на одном из верхних этажей, то придётся рисовать несколько витков лестницы со всеми сопутствующими неприятностями типа необходимости поставить две разные точки в одно и то же место так, чтобы они были в разных местах. Это точки, которые находятся одна ровно над другой, так как марши и площадки лестницы находятся один над другим. Они должны быть представлены разными осмовскими точками, чтобы не создавать связности там, где её нет. Если разные точки создать ровно на одном месте, то неудобно будет редактировать, да и валидатор JOSM’а по этому поводу выскажется. Отсюда следует одна из причин не рисовать проход, даже когда он известен: рисовать может оказаться слишком сложно.

Эскалатор – обозначается как лестница с дополнительным тегом conveying=*. Вместо этого довольно часто попадается тег escalator=*, но это хуже, потому что тогда для движущихся не-лестниц, то есть траволаторов, придётся изобретать ещё один тег, например travolator=*. Траволатор можно обозначить тем же conveying=*, добавленным уже к highway=footway.

Коридоры

Для коридоров имеется непосредственно подходящий тег highway=corridor. У этого тега меньшая поддержка среди рендереров, что и хорошо, и плохо. Хорошо это тем, что рендерер не будет пытаться выводить плотно расположенные проходы внутри зданий на бо́льших зумах, когда выводить их не нужно. Плохо это примерно тем же, только на меньших зумах. Хуже всего результат выглядит, когда вместе с коридорами надо нарисовать и лестницы – тогда будут видны ни с чем не связанные ступеньки. Во многих простых случаях, когда за входом либо сразу POI, либо сразу короткие проходы в разные стороны, результат с использованием тега highway=corridor получается вполне приемлемым. Тогда, возможно, конечному пользователю карты рендер коридоров и не нужен.

С точки зрения редактирующих данные участников, у тега highway=corridor тоже есть и преимущества, и недостатки. К преимуществам можно отнести то, что про него сразу ясно, что он внутри здания. Это значит, что дополнительно не надо ставить indoor=yes, а раз ставить не надо, то нельзя и забыть поставить. Лично мне удаётся забыть поставить какой-нибудь indoor-тег довольно часто, так как для них никаких предупреждений валидаторы, встроенные в редакторы, не дают. Зато для упомянутых выше простых случаев достаточно линии с одним тегом highway=corridor. Именно такой способ, как самый простой, и используется в скрипте PoiAlign, когда создаётся соединение входа и POI.

Недостатки highway=corridor заключаются в том, что ни JOSM ни Vespucci его не понимают, во всяком случае без дополнительной настройки. JOSM понимает только то, что это highway, чего ему достаточно, чтобы ругаться на соединения с POI. Зато чтобы рендерить как-либо отлично от линии без тегов, этого не достаточно. В итоге нельзя забыть поставить indoor=yes, зато можно забыть сам highway=corridor. Но JOSM теперь предупреждает и о линиях без тегов, значит забыть всё-таки не выйдет? Выйдет, если добавить ещё какой-нибудь тег, обычно level. Линия, на которой стоит только level, вполне устраивает валидатор JOSM’а. Лучше настроить JOSM, чтобы и highway=corridor, и indoor=yes как-либо отображались, что сделать довольно просто с помощью ​MapCSS. Добавить свой файл со стилем можно через меню View > Map Paint Styles > Map paint preferences, дальше в появившемся диалоге нажать на + рядом с правым верхним углом.

Если хочется, чтобы corridor выглядел как footway, можно добавить файл, содержащий такой стиль:

way[highway=corridor] {
	width: 1;
	color: foot#00ff00;
}

При желании можно отображать и indoor подобно тому, как рисуются тоннели:

way[highway=corridor],
way[highway=steps][indoor=yes],
way[highway=footway][indoor=yes] {
	casing-width: 1;
	casing-color: indoor#888888;
	casing-dashes: list(10, 2);
}

Из Vespucci использовать corridor ещё более неудобно. Помимо того, что он не рендерится как дорожка, он ещё и не попадает в автозаполнение значения тега, даже после того, как он был введён. А именно Vespucci приходится использовать на месте для отрисовки сложного indoor’а, когда нет желания ни бороться с редактором, ни смотреть правильные значения тегов в интернете. В этом случае легче использовать для обозначения коридоров highway=footway.

Почему бы тогда всегда не использовать footway? Сам проход мы по-прежнему можем обозначить, причём более распространённым тегом. Теряется информация о том, что это именно коридор? У нас есть уточняющий тег footway=*. Правда сейчас все его распространённые значения относятся к проходам вдоль и поперёк улиц, то есть к тротуарам и переходам, но возможно стоит добавить footway=corridor и прочие значения для того, что будет описано ниже.

Однозначно ответить, что лучше – corridor или footway – не получается. Теоретически есть выбор между: * меньше перегружать значениями highway=footway, использовав вместо него другое значение для тега highway, то есть highway=corridor, и * не вводить в употребление ещё одно значение более высокого уровня, то есть highway=corridor, когда можно использовать второстепенный уточняющий тег, в данном случае – footway=*.

Ну и все разновидности проходов, которые были и будут упомянуты, не являются «хайвеями», так что в идеале должен был бы использоваться какой-то другой тег.

Прочие проходы через помещения

Коридор – это проход, ограниченный по бокам стенами. Но не всякий проход ими ограничен. В качестве ограничителей могут выступать полки с товарами в магазинах, перила во многоэтажных залах или столики в фудкортах. Ограничителей может не быть вообще, если цель прохода находится на противоположной стороне зала. У зала, конечно, стены есть, но весь целиком он проходом не является. Линия прохода в этом случае займёт наиболее удобную траекторию движения по залу.

Как подобные проходы обозначать? steps не подходит, значит придётся использовать либо footway либо corridor. Выше мы уже начали рассматривать тег highway=corridor в принципе, а не только применительно к собственно коридорам. Если мы посчитаем его уместным для коридоров, то можем ли мы также посчитать его уместным и для прочих проходов? Наименее подходящим случаем для corridor выглядит проход без ограничителей. Но можно сказать, что он и для footway не подходит, ведь никакой выделенной дорожки нет. А раз не подходит и тот, и другой тег, то можно использовать более простой corridor… или более распространённый footway. Короче, опять однозначно не ответить, что лучше. В итоге обычно получается, что если начали в данном здании использовать один из тегов, то и продолжаем его использовать в случаях, подобных описанным здесь.

Проходы поперёк других проходов

Допустим, что есть коридор, и он уже нарисован одной линией. Её нам хватит, чтобы соединить начало и конец коридора. Но между началом и концом коридора может быть дверь, за которой нужная нам POI. Точка этой POI окажется сбоку от линии коридора, значит линию и точку придётся соединить ещё одной линией. Эта линия будет соответствовать проходу от линии коридора до двери. Следует ли её обозначать как коридор? Находится она в коридоре, но сам коридор уже обозначен. Или мы можем сказать, что линия соответствует проходу через дверной проём, просто её пришлось продлить до пересечения с линией коридора. Этот проход можно посчитать за отдельный короткий коридор.

Если представить себе длинный коридор через бизнес-центр с кучей офисов, то возникнет желание отметить подобные линии до каждого из офисов именно как highway=corridor для того, чтобы они не рендерились, иначе результат будет похож на бахрому. Может также возникнуть желание придумать свой тег, причём даже не footway=*, а highway=*. Стандартные маршрутизаторы его не поймут, но нам этого и не надо, так как линия с этим тегом будет короткая, значит маршрут и так подойдёт достаточно близко к цели, да и занимаемся мы рисованием проходов в первую очередь для организации процесса обновления POI, а не для маршрутизации.

Подобная же ситуация наблюдается и с самими входами в здания, когда вместо коридора имеется тротуар. Соединение входа с тротуаром и, соответственно, с глобальным графом дорог это уже другая задача, которая будет рассмотрена ниже. Однако один из случаев соединения с тротуаром придётся частично рассмотреть здесь. Это случай, когда POI находится сразу за входом. Как мы помним, есть достаточно причин обозначить её на определённом расстоянии от входа. Теперь сравним ситуацию с коридором и данную ситуацию.

  • Вместо коридора у нас тротуар.
  • Вместо двери в помещение с POI у нас входная дверь в здание. Сами двери мы в обязательном порядке не обозначаем в обеих ситуациях, но вход в здание, который обычно совпадает с дверью, мы обозначаем.
  • Вместо POI сбоку от коридора у нас POI сразу за входом в здание.
  • Коридор нужно было соединить с POI, на что хватало одной линии, которая целиком находилась внутри здания. Соединение же с тротуаром состоит из двух частей: от тротуара до входа вне здания и от входа до POI внутри здания. Мы пока ещё не решили, нужно ли нам рисовать первую часть, но вторую часть рисовать нужно. Далее в этом разделе мы будем рассматривать только вторую часть.
  • В случае с коридором мы рассматривали, стоит ли обозначать соединение как коридор, потому что оно находится в коридоре. В случае с тротуаром соединение входа с POI находится не на тротуаре, значит обозначать его как тротуар не имеет смысла.
  • В случае с коридором мы рассматривали соединение и по-другому – как дверной проём, продлённый до линии коридора. На самом деле продлевался он и в другую сторону, до точки POI, но это было незаметно, если мы не обозначали саму дверь. В случае с тротуаром точка, от которой продлевается проём, всегда обозначена как вход, и интересующая нас часть соединения является продлением от неё до точки POI.

Из всего этого следует, что footway=sidewalk на соединение входа с POI ставить не стоит. Значит набор подходящих тегов для этой линии такой же, как и в случае с коридором, ведь там sidewalk мы бы тоже не поставили, а всё остальное вроде как подходит.

Точечные объекты

Линия соединения может проходить через объекты, которые не являются линейными. Поскольку эти объекты для обозначения соединения не нужны, то их не обязательно вводить с точки зрения следования нашему методу обозначения POI. Некоторые из этих объектов, тем не менее, могут являться полезными ориентирами для нахождения POI, и их имеет смысл ввести. Сделать это можно, как правило, поставив точку с нужными тегами на линию пути.

Распространённым видом объектов является двери внутри здания. Если дверь открыта во время, доступное для посещения интересующего нас места, то на неё можно даже не обратить внимания. Если и входные двери обычно не обозначают как двери, то и без внутренних можно обойтись. Несколько больше толку от обозначения дверей, которые надо самостоятельно открывать, хотя и тут, если дверь сразу ведёт к цели, например, если это дверь офиса, можно полениться её вводить. Обозначить дверь можно тегом door=* со значением, соответствующим её типу. Например, обычная дверь на петлях это door=hinged.

Объектами на пути, которые сложно не заметить, являются турникеты. Встречаются они на станциях метро, железнодорожных станциях и местах с пропускным режимом. К последним из интересных в смысле POI мест относятся некоторые бизнес-центры. Обозначить его можно точкой с тегом barrier=turnstile. Турникет может пропускать только в одну сторону, тогда на часть пути можно поставить oneway=yes.

Входная дверь, за которой виден турникет

Хитрый вход в БЦ с переговорными устройствами и турникетом за дверью

Нелинейным объектом, который можно назвать обязательным для обозначения, является лифт. Обозначается он с помощью тега highway=elevator, что является примером растяжения тега highway дальше казалось бы предназначенного смысла. Впрочем, это растяжение не настолько бессмысленное, как обозначение фонарей с помощью highway=street_lamp, ведь точкой лифта можно соединить другие, уже линейные highway, то есть проходы на разных этажах.

Выше уже был упомянут тег level, который можно поставить на линию прохода для обозначения его вертикального уровня. Почему я не написал «для обозначения этажа» станет ясно из раздела про теги вертикального положения, где оно рассматривается преимущественно для точек POI. Здесь мы предположим, что level уже поставлен на части проходов, которые соединяются точкой лифта. В случае линейных объектов, level нужен на самой линии, а на точках, входящих в линию, этого тега может и не быть. Лифт является одной из таких точек, значит не обязательно ставить тег level и на него. Но, допустим, что поставить level всё-таки захотелось, например, чтобы показать, что лифт идёт и на этажи, которые пока не нарисованы. В этом случае на его точке в тег level надо записать через точку с запятой список значений уровней, как тех проходов, которые уже нарисованы и соединены с лифтом, так и тех, которых пока нет.

Чем соединить окно?

В разделе Входы было отмечено, что иногда с точки зрения посетителя их не существует, и в подобной роли выступают окна выдачи. Чем соединять с точками POI их? Не коридором и вообще не каким-либо проходом, ведь через окно не ходят. Пока, видимо, лучше не соединять ничем. Однако, допустим, что в этом месте много POI, и, даже если не удаётся указать, какая из них связана с окном, средствами, понятными всем, то можно сделать это чисто для себя. Для этого можно соединить POI с окном любой линией, даже без тегов, ну или с соответствующей note. Подобных нестандартных соединений можно избежать, если POI отмечена полигоном, что мы рассмотрим несколькими разделами ниже.

Проходы с улицы ко входам

Всё, что описывается в этом разделе делать не обязательно с точки зрения добавления и поддержки информации о POI. Проходы внутри зданий нам были нужны для построения последовательности POI вдоль контура здания. В сложных случаях они также были нужны для облегчения поиска POI на месте, то есть для того, чтобы было понятно, в какую сторону внутри здания надо идти. В этом разделе мы рассматриваем проходы снаружи зданий, которые ведут ко входам в них. Для выстраивания последовательности они не нужны. Также они, скорее всего, не нужны и для нахождения POI, так как то, что находится на улице, гораздо легче обозревается, чем то, что внутри, а, значит, дорогу до входа не составит проблем найти и без пририсованной к нему дорожки. Нужны такие проходы могут быть для каких-то других целей, здесь мы рассматриваем их обозначение для того, чтобы закрыть начатую в предыдущем разделе тему соединений точек с помощью highway.

Случаи с проходами ко входам в здания можно поделить на понятные и менее понятные. Понятные это когда есть дорожка, ведущая непосредственно ко входу. Тогда надо просто нарисовать эту дорожку до точки входа. Подобный случай получается, например, если перед зданием находится газон, подходящий вплотную к стене, а через газон проложена дорожка ко входу.

Дорожка ко входу

Дорожка, ведущая в заведение; если она будет нарисована, то наверняка дойдёт до входа

Менее понятные случаи – это когда рядом со входом дорожка есть, но ведёт она не ко входу. Соответственно через точку входа она не проходит и вставлять вход в линию как промежуточную точку нелогично. Типичным случаем такой дорожки является тротуар, который рисуется вдоль границы здания не глядя на то, есть ли на ней входы или их нет. Линия тротуара в этом случае проходит рядом со входами, то есть мимо них. При этом в сами входы можно пройти непосредственно с тротуара, то есть никакой выделенной дорожки к ним нет, и вроде как нечего к ним рисовать. Тогда откуда может возникнуть желание их чем-то соединить с тротуаром?

  • Можно захотеть соединить вход с тротуаром из соображений связности графа маршрутизации. Снаружи здания находится глобальный граф маршрутизации, если всё введено правильно и его никто не разорвал. Но при рисовании проходов внутри здания тоже образуется граф, который будет изолирован, если его не связать посредством соединения входа с тротуаром. После этого можно будет строить маршрут до POI, включающий указания, куда идти внутри здания.

  • Можно обнаружить, что на пути ко входу есть что-то существенное, что хотелось бы нарисовать. Например, при входной двери могут быть ступеньки, что важно с точки зрения accessibility. Если пририсовать ко входу ступеньки, то они вовсе не обязательно достанут до линии тротуара, и может захотеться чем-то соединить уже их, чтобы не образовывался тупиковый highway.

Идущие выше соображения про менее понятные случаи были изложены из расчёта, что тротуар уже нарисован. Если тротуар ещё не нарисован, но в реальности существует, то полезнее будет сначала нарисовать его. Если в реальности его нет, а есть какой-либо другой highway, идущий рядом со стеной здания, то далее в этом разделе, под «тротуаром» подразумевается именно этот highway. Подобную роль может играть, например, highway=pedestrian или highway=service, если вход находится во дворе.

В предыдущем разделе мы сравнивали рисование проходов от тротуара ко входу с рисованием проходов от коридора к расположенному сбоку от него помещению. Сам проход мы поделили на две части, и рассмотрение части вне здания мы отложили до этого раздела. В случае с коридором одним из вариантов интерпретации того, чем является соединяющаяся с ним линия, был продление прохода через дверной проём. С тротуаром уже такая интерпретация не подходит, так как проём находится внутри здания, а рассматриваемая здесь часть прохода – вне, и indoor-теги прохода через проём для неё не подойдут. Кроме того, если сразу при двери снаружи находятся ступеньки, и соединять надо уже их конец, то говорить, что через них продлевается проход через проём совсем нелогично.

Из аналогий с коридором осталась интерпретация «раз соединение проходит по тротуару, то отмечать его надо как тротуар». Но это корявый вариант, так как тротуар уже отмечен, и никакого дополнительного тротуара, ведущего ко входной двери, не существует. Из этого следует, что если мы хотим оставаться в рамках широко используемых тегов, то проход ко входу либо к тому, что к нему пририсовано типа лестницы, надо обозначать как highway=footway без footway=sidewalk.

На тротуаре помимо тегов highway=footway, который мы решили воспроизвести на рассматриваемом проходе, и footway=sidewalk, который мы решили не воспроизводить, могут быть и другие теги:

  • surface=* – материал поверхности тротуара. Поверхность рассматриваемого прохода от тротуара, а точнее по тротуару до входа, как правило, совпадает с поверхностью всего тротуара, значит можно её тег и не повторять на линии прохода. С другой стороны, поверхность эта объективно есть и на протяжении прохода, значит можно и повторить, особенно если для полноты мы захотим surface на всех highway. Похожий выбор приходится делать при рисовании пешеходных переходов, которые, как правило, тоже не имеют своей выделенной поверхности, и их тоже можно рассматривать как соединения с тротуаром. Есть и другие свойства поверхности, например, smoothness, про которые можно сказать то же самое.

  • lit=* – освещённость. Подобная ситуация и с этим тегом: если освещение есть на тротуаре, то есть и на проходе. Если постараться, то удастся найти или изобрести и другие теги, соответствующие свойствам, которые повторяются у тротуара и у прохода. Такие свойства можно назвать интенсивными, как в физике. Значит, можно найти и экстенсивные свойства, которые совпадать не будут.

  • width=* – ширина. У прохода она наверняка будет отличаться от ширины тротуара. Это как раз пример экстенсивного свойства, теги которого копировать точно не нужно. В случае именно с шириной, её вообще может не существовать, если у прохода нет ограничителей по бокам, тогда ставить этот тег даже с другим значением не следует.

В принципе, при нарисованном area:highway можно было бы наследовать значения таких тегов, как surface и lit от него. Если у нас есть highway, который полностью помещается в area:highway, то и интенсивные свойства у него те же. В подобном наследовании ничего принципиально нового не будет, например, оно уже широко используется для адресов. Конечно, сейчас никто не будет на основании этого убирать теги с линий тротуаров, но как причина не ставить теги со свойствами на второстепенные проходы это вполне подойдёт.

Что можно пририсовать ко входу с внешней стороны здания помимо прохода по тротуару? Мы уже называли лестницы, которые можно обозначить с помощью линии highway=steps. Ещё бывают пандусы, с которыми связаны всякие accessibility-теги типа ramp или wheelchair. Насколько агрессивно эти теги следует ставить, неясно. Например, массовая расстановка wheelchair=yes на все достаточно широкие и не слишком наклонные дорожки пока не наблюдается. Если же не обращать внимания на то, для каких целей пандусы установлены, то на них можно поставить тег incline=*. Некоторые предпочитают на подобные конструкции ставить ещё и bridge=yes, даже если под ними можно пробраться только ползком. Упомянутые средства подъёма не обязательно вплотную подходят к двери, например, если есть крыльцо. Тогда понадобится соединять их и с дверью тоже с помощью highway=footway.

Основная проблема с рисованием всего этого заключается в том, что в результате получается много второстепенных по сравнению с тротуаром линий. Лет семь назад так могли бы сказать и про сами тротуары – они второстепенные по сравнению с highway=primary, highway=secondary и прочим. Но у тротуаров есть свой набор тегов, и если, например, вы не хотите, чтобы они рендерились, вам надо игнорировать всё, на чём стоит footway=sidewalk. А у всех этих соединений со входами своих тегов нет, значит непонятно как их отфильтровать. Фильтровать же их захочется, потому что их может быть реально много. Есть места, магазины в которых попадаются через каждые пять шагов.

Итого получается следующие теоретические вопросы: 1. Можем ли мы определить, что значимость проходов ниже на основании какого-нибудь объективного критерия? 2. Как обозначить значимость в данных?

Критерий второстепенности

На первый вопрос можно дать положительный ответ. Как уже было сказано, проход от линии тротуара к точке входа имеет более низкую значимость по сравнению с тротуаром, так как полностью находится внутри площади тротуара. То есть, когда один highway находится внутри площади объекта, который обозначен другим highway, у первого highway значимость ниже. Но этого условия может быть недостаточно.

Рассмотрим пешеходные переходы. Без них тротуары рисовать бесполезно, так как тротуары не будут соединены друг с другом. Значит, переходы надо рисовать вместе с тротуарами, и в этом смысле у них значимость не ниже. Можно заметить, что при обычном способе их рисования они не полностью находятся внутри площади другого highway. Начало линии у них лежит в площади тротуара, середина – в площади проезжей части, конец – в площади противоположного тротуара. Но в принципе мы могли бы сделать и по-другому и провести переход только по проезжей части, а в пределах тротуаров соединить его опять же некими highway. Теперь и сам переход, и его соединители полностью находятся в площадях других highway и получаются менее значимыми. Нам же нужно, чтобы их значимость была такая же, как у тротуаров, для чего критерий придётся уточнить. Уточним мы его, руководствуясь тем, что, как было сказано выше, тротуары должны быть чем-то соединены: значимость highway не ниже, если он нужен для связности графа маршрутизации. Или так не выйдет, ведь мы соединяем менее значимым проходом компоненту графа внутри здания – все коридоры и прочее, которые мы вели до POI. Тут можно выкрутиться, сказав, что вся компонента менее значимая, и связность остального глобального графа не нарушится, если её вырезать, то есть для нашего критерия связность должна обеспечиваться для частей графа одинаковой значимости.

Ещё может быть непонятно, находится ли highway в площади другого highway. В основном, это касается лестниц. Лестницы при дверях относятся ко всей этой мишуре, которую хочется объявить второстепенной. Но находятся ли они в площади тротуара? Если они пристроены к дверям, то вроде как да, но они могут быть и более внушительными и входить в так сказать архитектурный облик здания, тогда, скорее, тротуар проложен так, чтобы их обойти. Можно было бы попробовать определить второстепенность по наличию поверхности тротуара под ступеньками, но тогда второстепенными не будут ведущие вниз лестницы при входах в подвалы. Да и при ведущих вверх ступеньках поверхности может быть не видно, а исключать непроходимые места из поверхности тоже странно, ведь тогда придётся вырезать и места занятые урнами, столбами и прочим.

Ступеньки на разных сторонах улицы

Вид с серьёзных ступенек на менее серьёзные

Поэтому уточним критерий нахождения в площади по-другому: площадью будем считать то место, которое мы бы посчитали за таковую, если бы не обратили внимания на тот highway (или последовательность highway), второстепенность которого определяем. Например, есть лестница, ведущая в подвал. Как бы мы нарисовали area:highway тротуара, если бы не заметили лестницу? Скорее всего, то место, где находится лестница, вошло бы в area:highway, значит лестница второстепенна. Оговорка про последовательность highway сделана на случай, если сама лестница подходит не в упор к двери и соединяется со входом с помощью ещё какого-то highway. Если мы не заметим лестницы, то мы не заметим и её соединения с дверью. Теперь у нас есть приемлемый критерий второстепенности.

Обозначение второстепенности

Как обозначить второстепенный проход в осмовских данных? Понятно, что линией с какими-то тегами. Варианта тут два – либо какое-то новое значение highway, либо highway=footway с новым значением тега footway, а в случае со ступеньками, видимо с тегом steps. С улицами целиком либо с их проезжими частями пошли по первому пути, и есть набор значений для highway: primary, secondary и т.д. Есть также значения специально для соединений: primary_link, secondary_link и т.д. Наша второстепенность подобна второстепенности соединений, и в этом случае нам нужны теги highway=footway_link и highway=steps_link без дополнительных тегов footway=*. Можно, правда, придраться к тому, что link’ами соединяют и highway одинаковой значимости, и если мы хотим действовать аналогично, то связность из критерия второстепенности надо убрать, а переходы надо тоже объявить линками. Я этого пока не предлагаю, потому что у переходов свой тег уже есть, а менять им значение highway можно начать и потом, когда и если это значение получит достаточную поддержку. Тогда же можно будет расширить критерий второстепенности, чтобы под него подходили и переходы.

Второй вариант выглядел бы так: highway=footway + footway=sidewalk_link и аналог для steps. Первый вариант лучше, если хочется, чтобы мишура перестала рендериться прямо сейчас, даже в ущерб маршрутизации. При втором варианте маршрутизация будет, но придётся дожидаться, пока рендереры научатся понимать новые теги, если они вообще согласятся их понимать. Правда и в первом случае, мы хотим мишуру видеть на больших зумах, так что лучше, чтобы рендереры научились понимать описываемые здесь теги, и, заодно и описанные ранее indoor-теги, и не рендерили на небольших зумах и их.

Наличие проблем выбора тегов отчасти объясняется тем, что в осме теги, соответствующие физическим дорогам, проездам и проходам совмещены с тегами логических рёбер графа маршрутизации. Так, видимо, получилось, потому что в первую очередь принято обозначать физические объекты, ведь именно они являются ground truth. Но маршрутизацию делать тоже хочется, а раз введены физические дороги, то делать её приходится именно по ним. Связь тротуара со входом мы бы могли обозначить абстрактным ребром графа без физической дорожки, но такого в осме нет.

Вертикальная геометрия

Вспомним, что мы пытаемся отмечать на данный момент. Мы ставим точку POI где-то внутри соответствующего заведения, скорее всего на расстоянии двух метров от входа, возможно обозначаем сам вход, возможно соединяем вход и точку POI. В этом разделе мы будем делать вид, что мы только ставим точку POI, так как именно это является нашей основной целью. Поскольку теги с информацией о POI мы пока не рассматриваем, то нашей задачей на данный момент является выбор места для точки. Место мы выбираем в пространстве, которое на самом деле трёхмерное, но точку мы ставим на плоскости, потому что поверхность земли плоская, по крайней мере, локально в центре Петербурга, где нет гор. POI, тем не менее, могут располагаться на разной высоте над этой поверхностью и даже под ней. Высоту можно было бы измерить непосредственно, и записать её в теге ele, но это, как правило, не делается. Интересна обычно не высота относительно уровня моря, а высота относительно того, что находится рядом, причём выраженная не в единицах измерения длины, а качественно, типа «это выше того» или «это на одной высоте с тем». Для этого имеются теги level, addr:floor, level:ref, location, layer. Теги POI в этой записи мы рассматривать не собирались, но упомянутые здесь теги относятся не к сути заведений, а к их месту, так что их мы рассмотрим.

Слегка наклонный тротуар

Если постараться, то в некоторых местах в центре Петербурга у улиц можно заметить наклон

level

Чаще всего приходится иметь дело с тегом level. Он обозначает уровень внутри здания. Высота уровня обычно равна высоте этажа. За точку отсчёта уровней, то есть за то место, где уровень равен нулю, принимается самый низкий уровень пола какого-либо этажа, находящийся над землёй. У здания получается вертикальная шкала уровней, значения которой идут от building:min_level на полу нижнего этажа, до building:levels на крыше, если крыша плоская, или на чердаке в случае типичной для центра Петербурга двускатной крыши. building:min_level обычно не ставят, потому что, глядя на здание снаружи, сложно определить, сколько у него этажей под землёй, но это не помешает использовать отрицательные значения на отмечаемых нами объектах.

POI имеет площадь, но мы пока что сжимали её до точки. Точно также POI имеет и протяжённость в высоту, которую мы тоже сожмём. Чаще всего заведение занимает только один этаж. В этом случае оно всё равно не плоское, и может занимать даже всё пространство от пола до потолка. Вместо диапазона уровней для разных точек внутри площади заведения мы получим одно или несколько значений уровня с помощью округления вниз до целого числа. Строго эта операция выглядит так: берём (несчётное) множество всех точек пространства внутри заведения, отображаем их все по функции точкаеё округлённый до целого вниз уровень, получаем (конечное) множество округлённых уровней. Элементы этого множества пишем через точку с запятой в тег level. У заведения на одном этаже в теге level будет одно целое число, у многоэтажных заведений будет список из нескольких целых чисел.

То, что было выше сказано про level является одной из интерпретаций, не противоречащих его общепринятому использованию, а возможны и другие:

  • Считать, что отметки на шкале уровней проходят не по полу, а по середине высоты этажа, и округлять уровень до ближайшего целого, а не вниз. Мне это меньше нравится, потому что именно пол используется для определения нулевого уровня.

  • Не использовать непрерывную шкалу уровней, использовать дискретную. Тогда всему этажу будет соответствовать какое-то одно значение уровня. Это выглядит проще, да и зачем нам непрерывная шкала, если мы используем только целые значения? Только целые значения мы используем для интересующих нас POI, а в общем случае нам могут пригодиться и дробные. Главная причина не использовать дробные значения на данный момент – это их интерпретация редакторами и приложениями. JOSM и Vespucci сейчас в своих автофильтрах их игнорируют, то есть не показывают их ни вместе с целым уровнем выше, ни вместе с целым уровнем ниже. В JOSM всё плохо и без этого, он не поддерживает даже перечисления уровней через точку с запятой.

  • Не требовать округления и разрешить, в частности, «полууровни». В типичном здании они могут соответствовать лестничным площадкам между этажами, на которых интересующие нас POI бывают редко, но, в принципе, ничто, кроме размера площадок им там быть не мешает. Тогда вместо округления уровня надо брать его нижнюю границу, но не совсем понятно, что делать с многоэтажными POI. Можно, например, считать, что перекрытия между этажами делят их на отдельные части, и в level пишется список нижних границ этих частей.

  • Разрешить дробные значения при дискретной шкале – комбинация двух предыдущих вариантов. Дискретная шкала это не обязательно целые значения. Дробное же значение теперь будет соответствовать промежуточному этажу, что обычно не нужно, или площадке между этажами.

Въезд на подземную парковку с указателем «уровень»

Термин «уровень» на местности; неизвестно, соответствуют ли эти уровни нашему определению

Есть также весьма распространённые противоречащие общепринятому использованию интерпретации тега level. Можно заметить, что по крайней мере при обозначении POI уровень соответствует, хотя и не обязательно равен, определённому этажу. Почему тогда не отказаться от термина уровень и использовать этаж, и именно этаж и писать в level? У этажа обычно есть обозначение или номер, являющийся чаще всего, но не всегда числом, которое даётся по принципу, соответствующему традициям для данной местности, данного типа зданий и назначению данного этажа. Однако, традиции эти бывают разные, и в общем случае, глядя на эти обозначения, нельзя сказать ни как расположены этажи относительно земли, ни как относительно друг друга. Вам может казаться, что первый этаж над уровнем земли в этой стране и её ближайших окрестностях всегда имеет номер 1. Чаще всего так и есть, но, например, в торговых центрах номер 1 иногда бывает у этажа над первым. В этом разделе термин уровень используется для того, чтобы не перепутать его значение с номером этажа.

Лестница перед выходом из ТК

Вид с лестницы соединяющий этаж 1 на уровне 0 и этаж опять же 1 на уровне 1

Из общепринятой интерпретации level следует, что уровни нам надо отсчитывать так, как считают все нормальные люди, то есть те, кто программируют на си-подобных языках: начиная от нуля с условием завершения по строгому неравенству (level < building:levels). Если серьёзно, то считать от нуля следует, скорее всего, потому что так решили те, кто придумал тег level, а в их местах этот метод подсчёта даст те же значения уровней, что и номера этажей, если ограничиться теми этажами, которые обозначаются числами и находятся ниже 13-го уровня. В общем случае значения уровней и номера этажей совпадать уже не будут, но зато из самих уровней всегда будет ясно их относительное положение, которое в общем случае неясно из номеров этажей.

В наших местах уровень и этаж будут обычно отличаться на единицу, что может быть неудобно, если надо ориентироваться именно по номерам этажей. Соответственно, у нас есть участники, которые либо хотят считать уровни от единицы, либо не хотят считать вообще. Нежелающие считать хотят использовать исключительно номера этажей. Несмотря на то, что номера или какие-либо другие обозначения этажей существуют не всегда, данные участники говорят, что номера «есть, видны прям на этаже и эффективно могут (быть) на месте проверены», уровни же верифицируемыми они не считают. Процесс вычисления значения level по их мнению является «игрой в считалочки», а сама схема значений level, построенная по этому принципу «неработоспособна». Всё это не было бы проблемой, если бы они не хотели при этом результат своего подсчёта либо неподсчёта писать в тот же тег level. Более подходящие теги для записи этого результата описываются в следующем подразделе, но их упомянутые участники предпочитают не замечать.

Конечно же, подобные интерпретации тега level являются несовместимыми с той, которая описана в английской вики и широко используется. (Тут придётся сделать примечание, что это утверждение верно, если не пытаться определить тег level через схемы, появившиеся позже самого тега.) Ту из интерпретаций, которая соответствует записи обозначений этажей, можно сравнить с разрезанием и слиянием зданий под адреса, чем не стоит заниматься, потому что здания существуют независимо от адресов. Также и этажи существуют независимо от своих обозначений и с ними можно сопоставить не связанную с их обозначениями шкалу уровней.

Несовместимости сторонники подсчёта с единицы либо обозначения этажа в level предлагают устранить, передокументировав level согласно своим желаниям. Недавно участники чата провели опрос, где у сторонников данного взгляда на level обнаружилось большинство, о чём нам теперь сообщает русская вики. Правда, из результатов опроса непонятно, кого больше: считающих с единицы или не считающих вообще, видят ли они разницу между этими вариантами, и, соответственно, каким из этих способов они хотят переопределить level.

Надпись «1-2 floor»

Обозначение этажей по-русски по-английски

Всё написанное выше в данном подразделе являлось теоретическими рассуждениями. Теперь вернёмся к тому, с чем приходится сталкиваться на практике. Допустим, что мы отмечаем POI, видимые с улицы – это по прежнему большая часть отмечаемых мной POI. Раз они видны с улицы, то ясно, что они не на десятом этаже. Собственно отмечаем мы их рядом с их входом, вход доступен с земли, а за входом идёт проход, в котором сложно заблудиться, значит по большому счёту не важно на каком уровне POI находится. Основная информация для обнаружения заведения уже есть в его координатах на плоскости и без тега level можно обойтись. Так оно и есть в большинстве мест. Но попадаются места, где POI идут плотно, располагаясь на разных этажах, обычно от подвального до второго. Входы в них расположены близко друг к другу, а иногда и совсем один над другим. В этом случае, чтобы не запутаться, можно поставить на POI тег level, у которого значением обычно будет −1, 0 или 1, где 0 это обычный первый этаж.

Лестницы вверх и вниз, ведущие от тротуара ко входам в магазины

Типичное расположение магазинов на двух этажах

Немного другая ситуация возникает, когда заведение надо обозначить не рядом со входом, и при этом мы захотим соединить вход и точку POI линией прохода. Но этого будет недостаточно, чтобы не запутаться, если проход ведёт в место под или над другой POI. Обычно это выглядит так: есть нормальный первый этаж, на котором входы в магазины на нормальном расстоянии. В добавок к нему есть подвальный этаж со своими входами, и за каждым входом расположен целый «куст» из мелких POI, иногда с довольно длинными проходами до них. «Нормальные» магазины получаются расположенными над сетью подвальных POI, и это «над» надо отразить в данных. В данном случае подвальные магазины получат level=-1, а нормальные – level=0.

Всё это время мы делали вид, что без проблем можем определить нулевой уровень у здания. Проблемы, конечно, могут возникнуть, и условно их можно поделить на питерские и непитерские.

Непитерские проблемы это когда поверхность, на которой находится здание, не является горизонтальной. Земля в некоторых местах всё-таки не плоская, и при движении по горизонтали можно попасть из места над поверхностью в место под. Местом над может быть точка на полу какого-то этажа, раз она над, то её уровень неотрицательный. Но в этой же горизонтальной плоскости можно оказаться и под, а это уже отрицательный уровень. Поскольку до этого землю мы считали плоской, не приходилось даже требовать того, чтобы горизонтальная плоскость соответствовала одному уровню, это получалось само собой. Теперь нам надо это потребовать. Требовать мы будем это в пределах того, на чём стоит building:levels, то есть либо на всём здании, либо на его части, обозначаемой с помощью building:part. Если внутри этих пределов наблюдается описанная ситуация с переходом из над в под, то level там однозначно не определён. Чтобы его определить, есть два варианта действий: 1. Отпилить часть здания, в которой перехода не будет, а, значит, не будет и проблем с определением level. Обозначить эту часть как building:part со своей этажностью, которая может отличаться от этажности остального здания. 2. Выбрать какую-то вертикальную линию, например, проходящую через главный вход, и присвоить горизонтальным плоскостям уровни точек на этой линии.

Тут у нас наблюдается свобода выбора, главное, чтобы значения уровней в результате выбора не противоречили тегам building:levels на здании или части.

Понижение уровня земли перед дворцом

Непитерские проблемы в Питере

К питерским проблемам относятся те проблемы определения уровня, которые возникнут несмотря на то, что земля плоская. Когда нужно обнаружить первый этаж над уровнем земли, вы, скорее всего, признаете за него и тот, который на пару сантиметров ниже. Эту пару сантиметров вы и не заметите. А если это пять сантиметров? Десять? Двадцать? Для какого-то значения вы решите, что это уже level=-1. Другой же участник может считать, что это всё ещё level=0. Чтобы устранить эту неоднозначность, можно предложить считать уровень отрицательным, если, чтобы на него попасть, надо пройти вниз по хотя бы одной ступеньке, то есть сделать вниз хотя бы два шага.

Дверь, за которой уровень пола чуть ниже

Один шаг вниз при входе в магазин, из-за которого не стоит считать его уровень отрицательным

Дверь, за которой несколько ступенек вниз

Более существенное количество ступенек вниз

Задача осложняется тем, что уровень пола мог быть изменён отдельно для рассматриваемого заведения. При входе в другое заведение на том же этаже может быть другое количество ступенек, в частности потому, что могут быть причины это количество уменьшить ради accessibility. level хотелось бы иметь одинаковый для всего этажа. Для этого можно попробовать использовать критерий для выбора между level=-1 и level=0, не связанный с тем, насколько глубоко приходится спускаться. Связать вместо этого его можно с размером окон на рассматриваемом этаже. Если на этаже, который расположен ниже уровня земли, окна по высоте меньше, чем окна на этажах, находящихся явно над землёй, то данный этаж достаточно низок, чтобы считать его уровень отрицательным.

Окна разной высоты на разных этажах

Снизу окна ниже, сверху – выше

По последнему критерию level=0 будет получаться чаще. Получается, что у нас есть некоторая свобода выбора, подобная свободе выбора нулевого уровня при наклонной поверхности. Конечно, в случае неопределённости можно было бы выяснить, как называется интересующий нас этаж, и если он «первый», то сделать выбор в пользу level=0. Однако выяснить это в случае с входами с улицы в заведения может и не получиться, потому что обозначения этажа у них нет.

Неопределённость несколько уменьшается за счёт того, что выбранное значение уровня должно сочетаться со значением building:levels. Например, если над интересующим нас этажом есть ещё три и building:levels равно четырём, то это level=0. Если же building:levels равно трём, то это level=-1. Это решило бы наши проблемы, если бы мы могли рассчитывать на то, что правильно определённое значение building:levels уже стоит или его легко определить самостоятельно, а также на то, что мы можем без проблем сосчитать этажи над POI. Рассчитывать на всё это можно было бы, если бы здания имели простую форму, однако проблемы я назвал питерскими потому что тут так не бывает.

Глядя на здание только с одной стороны, в частности с той, где находится POI, для которой надо определить level, вовсе не обязательно удастся определить этажность. Также не обязательно будет иметься возможность посмотреть на здание с другой стороны, с которой не обязательно будет видно то же самое количество этажей. Количество этажей может быть другим за счёт асимметрии крыши, пристроек, надстроек и просто того, что, находясь близко к зданию, может быть не видно того, что у него наверху, а при осмотре POI приходится находиться близко. Помимо того, что всё это может быть сложно определить, это может быть сложно и записать. Чтобы этажность была правильной в произвольном месте, которое может нас заинтересовать, может понадобиться делить здание на части с различными значениями building:levels. Велика вероятность того, что до нас деление сделано не было, и building:levels был поставлен целиком на всё здание по неизвестному принципу. Неизвестно даже, знал ли ставивший этот тег, что части с различной этажностью в данном случае существуют, ведь он мог ограничился просмотром здания только с одного ракурса, возможно даже с яндекс-панорам. В общем случае приходится предполагать, что любой объект в осме отмечен самым простым способом, потому что так быстрее, а значит у отмечавшего была возможность совершить больше подобных правок. В итоге часто легче определять уровень отдельно взятой точки не глядя на building:levels.

Другого рода неприятности связаны с взаимодействием с теми участниками, у которых альтернативный взгляд на значения тега level. Для них обычный первый этаж это level=1, а подвал это level=0. Если ранее в POI-плотном месте, где хотелось бы обозначить уровни, чтобы не запутаться, один из таких участников расставил теги level по-своему, то их придётся менять, иначе вместо достижения цели «не запутаться» будет достигнуто нечто противоположное. Не исключено и ведение войны правок, ведь мнение оппонента теперь как бы подкреплено текстом русской вики. В итоге может понадобиться сослаться на изложенные здесь соображения, не зря же я их писал. Если оппонент использует для редактирования OsmAnd, то у него есть дополнительные причины понимать level именно как обозначение этажа. OsmAnd при нажатии на точку показывает информацию о ней, куда входит и «этаж». «Этаж» на самом деле равен level’у, хотя пользователь наверняка хотел бы увидеть вместо этого номер этажа. В результате совместных усилий стандартно и альтернативно видящих level участников, а также того, что однозначного соответствия между уровнем и этажом в общем случае нет, османдовский «этаж» следует воспринимать как номер этажа с точностью ±1, а то и ±2.

Ещё я был уверен, что какое-то приложение называло layer «уровнем», но сейчас не могу обнаружить, какое именно. Интересно, что от одного из альтернативных участников поступило предложение layer именно как уровень и использовать. Почему для этого понадобится альтернативный взгляд ещё и на этот тег, станет ясно из подраздела, идущего за следующим. В следующем же подразделе мы рассмотрим, куда всё-таки писать номер этажа.

addr:floor, level:ref и им подобные

Многоэтажные здания, то есть ТК или БЦ, будут основным видом мест, где использования обозначения положения по вертикали не избежать. Вертикальное положение POI придётся задать как для пользователей, так и для самого процесса поддержки POI в актуальном состоянии. Чтобы проверить, существует ли заведение, надо иметь возможность его найти, и желательно, чтобы процесс поиска не включал в себя обход всех этажей торгового комплекса. Если для записи вертикального положения точек, доступных изнутри здания, мы по прежнему будем использовать level, нас ждут новые проблемы. Когда мы отмечаем POI, видимые с улицы, мы можем вообще не думать, как называется их этаж. «Первый» он или «цокольный» нам не важно, мы просто посмотрим на расположение относительно земли и из этого выведем значение уровня. Находясь же внутри здания мы не станем смотреть на землю снаружи. Ориентироваться мы будем по обозначениям этажей, которые написаны у лестниц, в лифтах и на схемах. Получается, что нужно будет проделывать следующие операции:

  1. Снаружи определить этаж, соответствующий нулевому уровню;
  2. Изнутри обнаружить обозначение этого этажа и таким образом установить соответствие этаж-уровень;
  3. При записи информации о POI преобразовать обозначение этажа в уровень и записать его;
  4. При поиске записанной POI преобразовать уровень в обозначение этажа, по которому точку и искать.

Получается многовато шагов и, соответственно, многовато возможностей ошибиться. Если бы просто записывать обозначение этажа, то всех этих соответствий-преобразований проделывать не надо было бы. Тут-то сторонники писать это обозначение в level могли бы заявить о своей правоте, но мы обратим их внимание на то, что никто не мешает записывать обозначение и в другой тег, ведь у этого обозначения другой смысл. Одним из вариантов другого тега является addr:floor, про который в английской вики говорится, что он редко используется, но теперь мы ему нашли применение.

Если вы при обозначении точек в ТК боитесь запутаться в level – не ставьте его, по крайней мере при первом обходе здания. Ставьте на точки addr:floor, который потом можно будет заменить на level или даже и не заменить, а поставить level дополнительно. level будет играть роль указателя положения в пространстве, существующего независимо от обозначений мест, а addr:floor будет частью адреса, которая пригодна для использования даже без геометрии. Кроме addr:floor в этом смысле может пригодиться и addr:door, обозначающий номер помещения. Это относится, в основном, к БЦ с номерами офисов, но номера помещений встречаются и в некоторых ТК.

Двери в номерами 39, 41, 43

Двери с номерами в ТК

Addr:floor подходит как замена для level не во всех случаях. Например, если рисовать коридоры и прочие проходы, на которые можно и нужно ставить level, то addr:floor для них подойдёт только если вас не смущает такое понятие как адрес коридора. В данном случае имеет смысл ограничиться указанием addr:floor для точек, рядом с которыми есть обозначение этажа на месте, таких как двери у лестничной клетки. Ещё лучше использовать вместо addr:floor тег level:ref, рассматриваемый ниже.

Есть применение для addr:floor и при обозначении POI с улицы. Это относится к тем POI, которые непосредственно не видны, зато видны таблички, указывающие, что они где-то в данном здании. Именно о них шла речь в прошлой записи там, где рассказывалось про дополнительную верификацию. На табличках могут быть указаны номера этажей, которые можно записать в тег addr:floor соответствующей точки. Использовать вместо этого level опять же может быть неудобно, так как для этого придётся определять, какой level соответствует какому этажу, чем при внешнем осмотре здания – том самом, при котором и приходится читать таблички – заниматься не хочется. Помимо адресации смысл записи этажа в данном случае заключается в том, чтобы показать, что это одна из точек, которая не видна снаружи, и её не надо искать с улицы и выравнивать относительно границы здания, если речь идёт не о первом этаже.

Можно возразить против использования для обозначения этажа именно тега addr:floor. Есть мнение, что в тегах addr: должны быть только части почтового адреса, а этаж частью почтового адреса не является. Например, этого мнения придерживаются разработчики Nominatim. Впрочем, то, что ищет Nominatim, и то, что рассматривается в указанном докладе полным адресом не является, там ограничиваются адресами зданий, а чтобы послать письмо, потребуется ещё и номер квартиры или помещения. На это не обращают внимания, потому что помещения в осме обычно не мапят, но это «обычно» – не наш случай, мы как раз офисы обозначать собираемся. Может быть, про этажи можно сказать нечто подобное, то есть, что их обычно не обозначают, но мы собираемся обозначать и их. Хотя обозначение этажа и не является частью почтового адреса, оно является частью адреса в более широком смысле как указания места, понятного человеку и состоящего из частей, постепенно это место уточняющих.

Ещё против этажа как адреса можно сказать, что он избыточен при указанном номере помещения и поэтому не нужен. Однако избыточных тегов адреса хватает и без этажа, начиная с почтового индекса. Также избыточной может быть литера, которую либо пишут в addr:letter, либо приписывают к номеру дома, либо делают и то и то.

Если мы всё-таки не хотим использовать тег addr:floor, несмотря даже на то, что это принятый пропозал, то придётся взять другой тег. Раз записывать мы хотим номер этажа, то это может быть что-то типа ref, но сам ref не годится, так как ставить мы его будем не на элемент, обозначающий весь этаж. Если мы захотим сказать, что это обозначение level’а, то его можно назвать level:ref, как сейчас предлагается в Simple Indoor Tagging. Правда, с таким названием он выглядит как дополнение к уже обозначенному level’у, а нам он может быть нужен также как альтернатива. Мы можем захотеть использовать тег для обозначения этажа только у отдельной точки, когда сам этаж ни как геометрию составляющих его помещений или проходов, ни как набор находящихся на нём POI мы рисовать не собираемся, и в этих случаях level:ref подходит не вполне. Зато он вполне годится быть поставленным на саму геометрию, хотя неизвестно, в каких количествах стоит его ставить. Нужен ли он на всём, на чём стоит level? Видимо, нет, его можно поставить временно, а после простановки level убрать, оставив только там, где есть сами обозначения этажей. Более точный ответ на этот вопрос зависит от того, как собираются вести себя приложения, показывающие планы этажей: им нужно откуда-то номер этажа взять.

Если нас не устраивает ни addr:floor, ни level:ref, что ещё можно использовать для подобных целей? Я встречал тег floor, хотя в вики он не задокументирован. Для временного использования, чтобы не запутаться в этажах, подойдёт и он. Ещё встречаются предложения записать все соответствия между уровнями и обозначениями этажей в один-два тега на здании. Этот вариант для временного использования уже не подойдёт, потому что на POI придётся ставить именно level.

Поскольку запись всё-таки про POI, то подытожим, какие теги уровней/этажей имеет смысл ставить на них, а что делать с коридорами и прочим, рассматривать здесь больше не будем. Выбор тегов зависит от того, насколько сильно точка POI привязана к окружающей её геометрии:

  • POI не привязана никак, то есть стоит в произвольном месте внутри здания, её истинное положение неизвестно, но известен этаж. В этом случае использовать level не имеет смысла, level:ref тоже не очень подходит, и лучшим вариантом оказывается addr:floor.

  • POI стоит на своём месте, но не соединена с какими-либо внутренностями здания, которые и не нарисованы. Так бывает, если POI видна снаружи и поставлена на основании внешнего осмотра. В этом случае наоборот больше подходит level, хотя, если известно обозначение этажа и нет несогласия с тем, что он является частью адреса, можно добавить addr:floor.

  • POI привязана к внутренней геометрии здания. По сравнению с предыдущим пунктом здесь становится нужнее обозначение этажа и больший смысл обретает тег level:ref. Level поставить тоже придётся, хотя можно сразу этого и не делать. Про addr:floor можно сказать то же, что и в предыдущем пункте.

Как видно из данного списка ситуаций, обозначения этажей появляются в осме на стыке ввода отдельных точек и детального indoor mapping. Первое предлагается делать даже новичкам из редакторов типа MAPS.ME, а вторым занимается мало кто. Этим, возможно, и объясняются разногласия в использовании тега level и неопределённость того, что надо или не надо к нему добавлять. Тут бы мне хотелось сказать, что тема этажей в этой записи закрыта, но к сожалению к ней ещё придется вернуться в ситуации с ещё более неопределённым набором действий.

location и layer

Разнообразие вертикального положения POI не ограничивается этажами зданий. POI могут быть и вне зданий, но всё равно над или под чем-то. «Под» это обычно в подземном переходе или в метро. Если проход под землёй, в котором расположена POI, ещё не нарисован, его надо нарисовать, иначе не будет никаких ориентиров для расположения точки. Когда проход нарисован, он обычно обозначен с помощью линии с тегами highway=footway, tunnel=yes, layer=(отрицательное значение). На нахождение прохода под землёй указывает, скорее, tunnel, чем layer.

Тег layer предназначен для указания относительного вертикального положения объектов, но его зона действия – только точки пересечения элементов, а не область, определённая другим элементом, таким как здание или его часть в случае тега level. Горизонтальный уровень тег layer не задаёт и, соответственно, используется для задания вертикального порядка таких объектов, которые могут быть весьма негоризонтальны. К подобным объектам относятся мосты и части развязок, а желание некоторых участников использовать этот тег для горизонтальных этажей выглядит довольно странно. Есть соглашение ставить отрицательные значения layer на объекты, находящиеся под землёй, но, строго говоря, само по себе это не является обозначением нахождения под землёй. Является же это обозначением нахождения под объектами со значением layer выше, в основном с layer=0, подразумевающимся по умолчанию для всех объектов, на которых тег layer не поставлен.

Если POI находится, допустим, в подземном переходе, то возникает желание обозначить её нахождение там копированием каких-либо тегов с самого перехода. Какие теги имеет смысл скопировать? Ясно, что не highway=footway. tunnel тоже не подходит, ведь сама POI туннелем не является. Остаётся layer, но он сам по себе не означает нахождение под землёй. В случае с подземным переходом для точки этот тег в большинстве случаев не означает ничего. Относительное положение он показывает только в точках пересечения объектов, а поскольку мы рассматриваем его установку на точку, пересечься она может только с площадным объектом, а его, скорее всего, не будет. Это не значит, что layer ставить на POI не надо, он покажет, что POI как-то относится к подземному проходу, находящемуся рядом, но это отношение может быть понятно только для редактирующих данные участников. Им, возможно, пригодится найти/выделить/отфильтровать подземный ход со всем его содержимым по значению layer.

Подземность придётся показывать другими средствами, в частности, тегом location. У него могут быть разные значения, но нас интересует преимущественно location=underground. Собственно его и можно поставить на POI, чтобы указать, что она находится под землёй. На сам подземный ход этот тег ставить не надо, так как там уже стоит tunnel. Среди прочих значений этого тега можно отметить overground и overhead, предназначенные для того, чтобы показать приподнят ли над землёй объект типа трубопровода или нет, для POI это вряд ли пригодится. Зато пригодиться может location=roof для POI, находящихся на крыше, что иногда бывает. Ещё есть location=indoor, при том, что мы уже встречались с тегом indoor=yes. Хотя большинство наших POI находятся внутри зданий, на них не ставят ни тот, ни другой тег. location=indoor на самом деле является одним из значений, предназначенных для подстанций.

Если точка находится в подземном ходу, и хочется однозначно показать, в каком именно, то ни layer, ни location этого сделать не могут. Точку POI придётся соединять с проходом подобно тому, как вход в здание соединяются с тротуаром, с теми же соображениями, описанными выше в соответствующем разделе, включающими использование нестандартных тегов. Ну то есть никто этого не делает.

Иногда для подземных сооружений включая метро вместо location и layer пользуются тегом level. Не так странно поставить level=-1 на подземный переход или что-нибудь подобное на метро, если оно неглубоко. Не вполне понятно, какой level ставить на платформу, до которой надо спускаться на эскалаторе две минуты, как в центре Петербурга.

POI полигонами

Преимущества

Выше описывались различные способы обозначить POI точкой, при этом отмечалось, что точка является абстракцией, которая может и не подойти в каких-то случаях. Случаи, когда вместо точки гораздо лучше подходит полигон, могут быть такие:

  • POI просто достаточно большая. Поскольку в основном мы отмечаем заведения внутри зданий, то «достаточно большая» означает «сопоставимая по размеру (длине, площади) с размером здания». Обозначать одной точкой то, что по величине похоже на практически всегда рисуемый полигоном объект – это какая-то дискриминация. Другое дело, что мы можем не знать, что POI на самом деле большая, и обозначить её точкой по этой причине.

  • POI занимает всё здание. Выше мы описывали способы, по которым можно выбрать место для точки POI. Здесь же нам предоставляется возможность этот выбор не делать, так как место уже отмечено. Остаётся только поставить теги POI на уже существующий полигон, что ещё проще, чем обозначить POI точкой. Правда, новые теги на полигоне могут пересечься с уже присутствующими тегами здания, тогда возникнут проблемы, которые рассматриваются в одном из следующих подразделов.

  • Надо что-то обозначить внутри POI. Внутри точки ничего нарисовать нельзя, значит нам понадобится элемент, имеющий площадь.

  • У POI несколько входов. Мы, конечно, можем обозначить эти входы и соединить их проходами с точкой POI, но тут опять надо совершать выбор места для точки. Вместо набора способов типа «напротив главного входа», «посередине между входами», «на углу» мы обозначим POI там, где она на самом деле, не сжимая её до точки. Также в случае, если за входами сразу находится заведение, просматривающему карту будет сразу понятно, что не надо идти по каким-то коридорам, чтобы в это заведение попасть.

  • У POI может быть окно заказа/выдачи. Мы так и не определились, чем его привязать к точке POI, а в контур полигона POI мы можем его спокойно включить.

  • POI может быть несвязна. Конечно, её всё равно можно обозначить точкой, но что если одна часть по одну сторону от чего-то, а другая – по другую? Тогда ставить точку где-то посередине будет странно, ведь эта середина как раз придётся на место, разделяющее части заведения. В роли таких разделителей могут быть арки или лестничные клетки. Зато при рисовании POI полигоном можно воспользоваться одним из самых популярных средств усложнения данных – отношением мультиполигона. То, что следует сделать в данном случае, а именно нарисовать отдельными полигонами несвязные части и объединить их в мультиполигон, усложнением, конечно же, не будет, так как по-другому подобного результата не добиться.

Два входа в магазин, между которыми арка

Две части магазина, разделённые аркой

Недостатки

Если нарисовать POI полигоном, а не точкой, то получится, вроде как, и точнее, и лучше для пользователей. Но на деле обозначение точками встречается гораздо чаще, и даже существует мнение, что, по крайней мере, внутри зданий, отмечать POI полигонами не принято. Почему полигоны обычно не используются?

  • Так дольше и сложнее рисовать. Вместо одной точки придётся поставить в лучшем случае четыре, но это далеко не предел.

  • Не видно границы POI на снимках, как на аэрофотосъёмке, так и на уличных панорамах, и трек внутри здания не записать. Эти проблемы уже упоминались в качестве недостатков при установки точки в центр заведения, теперь же они становятся более явными.

  • Такие данные сложнее поддерживать. Помимо того, что сами данные сложнее, они содержат в себе претензию на большую точность и, соответственно, причину эту точность повышать. Если граница POI нарисована весьма примерно – а нередко её так и приходится рисовать – то может потребоваться её изменить. Измениться может и сама граница в реальности, например, на месте одного магазина могут открыться два. Если бы POI была обозначена точкой, то в этом случае понадобилось бы подвинуть эту точку и добавить ещё одну. Если же был использован полигон, то его придётся делить на две части, для чего придётся выяснять и проводить линию раздела.

  • От этого может быть мало толку. Если заведение не было отмечено, а мы взяли и отметили его самым простым способом, то есть точкой, это будет серьёзным улучшением данных с точки зрения пользователя. Если мы точку перерисовали в полигон, то улучшение от этого действия гораздо менее существенное. Существенным оно будет, если внутри заведения можно заблудиться, правда в этом случае одного лишь полигона по контуру не хватит.

  • Есть редакторы POI, которые не имеют возможностей добавления POI каким-либо другим способом, кроме точки. В качестве примера можно привести MAPS.ME. Другой подобный редактор – OsmAnd – до недавнего времени не давал даже менять теги на уже отмеченных полигоном POI.

Помещения

Рассмотрим подробнее данный способ обозначения POI. Наиболее простое его описание выглядит так: провести замкнутую линию по границе заведения и поставить на неё теги POI. Но чтобы учесть упомянутые выше причины, по которым мы и захотели использовать этот способ, в его описание придётся добавить подробности. Во-первых, линия может быть или не быть общей с другими линиями и проходить или не проходить через имеющиеся точки. Во-вторых, одной линии может быть недостаточно.

Для начала надо определиться с тем, что находится внутри границы заведения, а что снаружи. Основной выбор тут такой: есть площадь, в которую могут попасть посетители и в которой оказываются услуги или демонстрируются и продаются товары. Она, конечно же, находится внутри границы. Но есть и площадь, в которую посетители попасть не могут, зато могут попасть работники, и работают они и на этой площади. Находится ли эта площадь внутри границы заведения, которую мы хотим провести? Тут можно рассуждать по-разному.

С точки зрения пользователя как потенциального посетителя эта область не входит в границы заведения, потому что услуг ему там не окажут и вообще туда не пустят. Однако так можно рассуждать только про заведения, предназначенные для посещения широким кругом лиц. Осмер, как правило, и является одним из этих лиц, ведь вряд ли для каждого заведения найдётся участник, там работающий, а договариваться со всеми об особом посещении слишком долго. Отсюда может возникнуть желание принять точку зрения посетителя. Если же вспомнить мой критерий для POI из предыдущей записи, то можно обнаружить, что точка зрения посетителя не подходит. В критерии деятельность в POI не ограничивалась обслуживанием посетителей. Мой критерий в данной роли может быть не совсем убедительным, ведь он предназначен для выбора POI, а не для определения того, как отмечать выбранные POI. К тому же это мой критерий выбора POI, а другие участники могут решить отметить какое-либо заведение и по другим причинам.

Можно ли сказать, что включать в границу POI только доступные места однозначно легче? Сразу отметим, что даже если ответ и окажется положительным, то это не будет означать, что так и надо поступать. Допустим, в магазине есть отдел без самообслуживания, то есть имеется прилавок, за которым продавец. Посетитель попасть за прилавок не может, значит это место надо было бы исключить из территории POI. Можно возразить, что место это не слишком большое, практически сразу за продавцом будет стена, вот примерно по этой стене мы и обозначим доступную территорию, а то, что в неё попала область между прилавком и стеной – это допустимая погрешность. Стены, однако может и не быть. Подобная ситуация наблюдается в фаст-фудах. Тут, конечно, всё равно можно возразить, что понятно, где начинается другое помещение, которым в случае фаст-фудов будет кухня, и что это не помешает отметить только доступные помещения. Может быть, так и есть, пока я только хочу показать, что случаи, когда служебные помещения включить легче, чем не включить, возможны.

Самым простым из таких случаев будет заведение, целиком занимающее здание. Если в случаях, когда заведение занимает лишь небольшую часть здания, надо производить какие-то дополнительные действия для включения служебных помещений, то в данном случае дополнительные действия понадобятся для их исключения.

Как отмечать сами помещения мы пока не рассматриваем, и наш контур заведения вовсе не обязан идти по их границам. В общем случае провести контур таким образом всё равно не выйдет, так как в одном помещении может находиться несколько POI. Если есть необходимость всё-таки отметить помещения, как доступные, так и недоступные, то можно воспользоваться схемой Simple Indoor Tagging. Необходимость эта возникнет, если отмечать мелкие POI типа торговых автоматов и банкоматов, которые уже не стоит привязывать к месту с помощью рисования проходов. Подобного рода POI я обычно не отмечаю, так что и необходимости рисовать помещения у меня обычно нет.

Раз уж мы обратили внимание на банкоматы, можно рассмотреть часто встречающийся случай, когда перед входом в банк находится холл с банкоматами так, чтобы ими можно было воспользоваться даже тогда, когда банк закрыт. Или он на самом деле не перед входом, а является как бы отделом внутри банка? Нужно его включать в границы банка или нет? В данном случае меньше споров вызовет рисование банка точкой. Банкоматы внутрь точки всё равно не поставить, они рисуются там, где находятся. Мимо них рисуется проход в собственно отделение банка, заканчивающийся точкой amenity=bank. Проход на самом деле есть, точка на самом деле внутри банка, значит всё правильно. Здесь же мы хотим сделать ещё более правильно.

Нам было бы легче, если холл с банкоматами не входил бы в границы банка. Какая причина ставить банкоматы в отдельное помещение? Свой режим работы. А у собственно банка другой режим. На самом деле, у банка может быть несколько разных режимов, например для физических и юридических лиц, так что сложностей может быть ещё больше, но пока допустим, что режим один. Если банкоматы окажутся внутри полигона с этим режимом, то своего режима у них не будет. Точнее, поставить opening_hours на них можно, но в результате получатся работающие банкоматы в закрытом банке. Режимы работы – тема для другой записи, здесь мы только отмечаем, что легче помещение с банкоматами не включать, а рисование банка точкой является одной из разновидностей этого невключения.

Правильно ли мы поступим, не включив банкоматы в банк, если не будем смотреть на режим работы? Вроде как неправильно, ведь мы пока разбираемся, включать ли нам недоступные помещения, а доступные помещения всегда включаем, и в данном случае рассматриваемое помещение доступно. Также, казалось бы, ясно, что этим помещением распоряжается банк, значит оно является частью банка. На самом деле, ясно это не всегда. Например, отделение банка может находиться в бизнес-центре, и банкоматы перед отделением могут находиться в помещении бизнес-центра, а не банка. Можно попытаться определить этот случай, глядя на двери, через которые необходимо пройти, чтобы попасть в помещение. За той дверью, на которой написано про банк и только про банк, начинается территория банка.

Окно, через которое виден вход в банк и банкомат

Банкомат перед первой дверью, на которой написано про банк

Аргумент с режимом работы как причиной рисовать границы в том или ином месте можно попробовать применить и к служебным помещениям. Какой у них режим? Он нам может быть неизвестен, и он может отличаться от того режима, который сообщается посетителям и становится известен осмерам. Это, скорее, говорит о том, что надо какими-то другими средствами отмечать режим, то есть обозначать внутри POI отделы и ставить opening_hours на них, или ставить access со временем, а в качестве критерия границы POI режим работы не годится.

Вернёмся к служебным помещениям. Допустим, что мы ещё не убеждены, что их надо включать в границы POI. Если отмечать не только обычные магазины, то выяснится, что существуют места, в которые никаким способом, кроме предварительной договорённости, не попасть. Ими будут, например, большинство офисов. Если служебные помещения в границы POI не включать, то у таких мест внутри границ не будет ничего, следовательно, их никак не отметить. Мы могли бы применять разные критерии для границ магазинов и офисов, но зачем? К тому же, нам придётся тогда отличать офисы от магазинов, а это может быть не всегда легко сделать. Например, турагентства в осме относятся к shop’ам, хотя часто выглядят как офисы.

Впрочем, в вики в ряде случаев наблюдаются рекомендации не включать в POI то, что не относится к прямому назначению заведения. Допустим, есть театр, и есть его дирекция. Следует ли всегда включать дирекцию в amenity=theatre? Она может находиться как в здании театра, так и отдельно, иногда достаточно далеко. Скорее всего, никто не захочет вырезать её из здания, но если она находится отдельно, то и объединять её с театром никто не будет. Подобным образом можно посмотреть и на университет, из которого никто не возьмётся вырезать офис приёмной комиссии на основании того, что там ничему не учат, зато если этот офис будет находиться отдельно, его никто не отметит как университет. То есть, можно действовать по принципу не включать в заведение то, что не относится к его основной деятельности, если оно географически достаточно обособлено.

Ещё мы можем отмечать входы, в том числе служебные, то есть entrance=service. Тогда мы захотим, чтобы каждый вход был по крайней мере рядом с тем заведением, в которое он ведёт. Служебные входы могут вести в служебные помещения, и чтобы не отрывать входы от POI, эти помещения удобнее сделать частью её полигона.

Стены

Проще было бы, если вход в здание, через который попадают в POI, не просто находился бы рядом с границей POI, а включался бы в неё. Тогда можно было бы обойтись без рисования соединяющего их прохода. Вход в большинстве случаев уже включён в контур здания, и ситуация, в которой его можно включить также и в контур POI возникает, когда POI находится сразу за рассматриваемым входом. Вместе со входом в этом случае придётся включить в POI и часть контура здания, чего мы можем как хотеть, так и не хотеть. Сравним эти два способа рисования POI.

  • Рисуя границу POI прямо по контуру здания, не нужно придумывать, где провести ещё одну линию. В противном случае пришлось бы рассуждать так: контур здания проведён по внешней стороне его внешней стены, стена имеет и внутреннюю сторону, контур POI надо провести именно по внутренней, для этого его нужно отодвинуть на ширину стены, которую придётся измерить. Стена обычно не такая широкая, чтобы пришлось отодвигать контур на существенное расстояние, а само расстояние будет меньше типичной погрешности рисования, так что с этой точки зрения проводить линию по внутренней стороне стены не имеет смысла.

  • Точка входа в отодвинутый контур уже не войдёт. Чтобы отразить в данных соответствие входа и POI, нам придётся либо изменить контур POI рядом с точкой входа, так чтобы он через неё прошёл, либо нарисовать проход-соединитель. Первое можно сделать, рассуждая так: стены в данном месте, по крайней мере на уровне человеческого роста, нет, потому что есть дверной проём, этот проём мы тоже включаем в площадь POI. Так получится, что надо рисовать мелкие детали, что дольше, и делать это будет лень. Второе потребует рисование очень короткого прохода, если только не продолжить его дальше внутрь заведения, чего мы тоже можем не хотеть.

  • Есть ещё и окна выдачи, про которые можно сказать примерно то же самое, что и про входы, только неизвестно, чем их соединять с POI. Соответственно, мы тем более хотим, чтобы в контур они вошли. В принципе, можно придумать и прочие объекты на контуре здания, относящиеся к POI, типа кнопок вызова и переговорных устройств.

  • В контур здания, в том месте, где находится POI, может быть включено то, что к POI не относится. Это могут быть телефоны, почтовые ящики и, что самое главное, входы, которые в POI не ведут. Если мы хотим правильного соответствия входов и POI, эти входы включать в контур POI нельзя. Если при этом контур POI ведётся по контуру здания, то их точки следует пропустить. Так получится линия, проходящая практически по упомянутым точкам, но не включающая их в себя, что неудобно. Ещё хуже, если объекты, которые в реальности существуют и могут быть отмечены на контуре здания, ещё не отмечены. Когда придёт время их ввести, то просто ткнув в редакторе на желаемое место, можно добавить точку в оба контура одновременно, а если нужно добавить только в один, то потребуются более хитрые операции. Их надо и самому не забыть произвести, и чтобы другие участники тоже не забывали и вообще понимали, что именно нужно делать. В случае если точки на контуре и POI находятся на разных этажах, нам могло бы помочь наличие на них тега level. Редактор мог бы выдавать предупреждения о проведении контура POI через точки с несовпадающим уровнем. К сожалению, этим не всегда удастся пользоваться для входов, так как вход может не быть на одном уровне со своим заведением, например, если за входной дверью находится лестница. Если по лестнице надо подняться достаточно высоко, и POI находится далеко от уровня земли, то в контур не должно входить практически ничего из того, что может быть обозначено на стене здания. Тогда гораздо проще и безопаснее контур POI по стене не проводить.

Получается, что контур POI прямо по контуру здания легче нарисовать, но не обязательно легче нарисовать правильно и в правильном состоянии поддерживать.

Несвязные части

Если несвязные части у POI есть, то, как нетрудно догадаться, нужно нарисовать контур каждой из частей замкнутой линией, а дальше собрать эти линии в отношение мультиполигона, на которое и поставить теги POI.

Тут можно заметить, что у некоторых участников возникает желание использовать мультиполигон и при отсутствии несвязности. Желание это у них возникает уже тогда, когда у двух полигонов есть общий отрезок, а, как было указано выше, такое вполне может быть при совпадении частей контуров здания и POI. Но выше было указано и то, что не все точки на совпадающих участках обязательно входят в оба контура. Если есть точки, входящие в контур здания, но не входящие в контур POI, или наоборот, от использования мультиполигона никакого толка не будет.

Некоторые, кстати, считают возможным включать в мультиполигон и те элементы, из которых площадной объект не собрать, в частности, точки. Руководит ими желание собрать в один элемент что угодно, чтобы повесить на всё это один набор тегов, и таким образом реализовать принцип один объект – один элемент. Если точки в мультиполигоне смысла не имеют, то существует отношение, в которое их включить уже можно. Это уже известное нам отношение site. Однако его поддержка в приложениях неизвестна и даже сама возможность поддержки вызывает вопросы.

С объединением несвязных частей можно и перестараться. Например, бывает, что объединяют в один мультиполигон части университетов, находящихся в разных местах, иногда довольно далеко друг от друга. Вместо этого лучше отметить каждую из частей своими тегами. Выше мы уже рассматривали случай, когда часть университета можно не считать собственно университетом, и как amenity=university не обозначать. Если части не признавать за университет нельзя, например, если это разные факультеты, у них могут быть свои собственные названия, которые можно добавить в name, или найдутся какие-нибудь другие теги, специфичные для отдельных частей. Однако нередко на части университет поделен неизвестным образом, по крайней мере для внешнего наблюдателя, и никаких специфичных для частей тегов задать не выходит. Когда теги на частях получаются одинаковыми, возникает желание объединить их в мультиполигон, а в противном случае смысл и даже возможность такого объединения пропадёт. Приведённый здесь пример является частным случаем проблемы определения того, одна это POI или несколько. Данная проблема уже упоминалась в разделе про входы в связи с окнами выдачи, но в этой записи подробно рассматриваться не будет.

Всё здание

Одним из преимуществ обозначения POI полигонами является отсутствие необходимости совершать произвольный, не в полной мере зависящий от реального положения объектов выбор места для точки POI. Остаётся сделать только зависящий от реальности выбор места для границы полигона, но бывают ситуации, когда не надо делать и его. Самая распространённая из них – совпадение POI со зданием, которое, как мы предполагаем, уже нарисовано. Значит остаётся поставить на него теги POI и дело сделано.

Но всё не так просто. Эта ситуация подобна описанному в разделе про входы совмещению входов и POI. Помимо того, что мы можем решить, что это плохо само по себе, возможна ещё и неопределённость с принадлежностью тегов на элементе, обозначающем две разные сущности. Со зданиями от этого больше проблем, так как у них бывает больше тегов, чем у входов, да и совпадение зданий и POI наблюдается чаще, чем совпадение входов и POI. Последнее не удивительно, так как даже вики советует в ряде случаев это совпадение устраивать.

Совет из вики относится к той ситуации, когда проблем от совмещения возникать не должно. Она возникает, если здание построено или предназначено специально для POI, и их можно как бы отождествить. Например, это здание театра, построенное для театра. Называют здание так же, как и театр, появилось оно тогда же, когда и театр и так далее. Таким зданием может быть и ларёк, даже если он появился раньше, чем туда пришли его текущие обитатели. Можно сказать, что у него самого по себе названия не было бы, и появляется оно только благодаря находящейся в нём POI, а значит конфликта названий ларька и POI нет.

Если же здание появилось задолго до обосновавшегося в нём заведения, то отождествить их не получится. Здание может обладать никак не относящимися к заведению свойствами, которые мы захотим записать в тегах, и наоборот. Одним из вариантов выйти из этого положения является разграничение объектов воздействия тегов: мы объявляем, что определённое множество тегов относится к зданию, а другое множество – к POI. Например, понятно, что building:levels относится к зданию. Но с таким распространённым тегом как name это не пройдёт, именно по причине его распространённости: название может быть и у здания, и у заведения. Чтобы устранить эту проблему, например, утверждается следующее: название здания – оно не название, а «историческое название». Раньше это был Дом Мятлевых, а теперь это прокуратура. Почему именно «был» – не совсем понятно, видимо, имеется в виду, что раз Мятлевы больше не являются владельцами здания, то здание больше не следует по ним именовать. «Историческое название» помещается не в тег name, а в тег historic_name, чтобы освободить name для прокуратуры. После этого возникает то же положение, которое производились попытки разрешить, только добавился ещё один тег. Почему именно name относится к прокуратуре, а historic_name ко зданию? Почему не наоборот?

Неподалёку от рассмотренного примера с прокуратурой находится здание Синода, в котором библиотека имени Ельцина. Если, опять же, хочется определить название, то можно посмотреть, что написано на месте, и обнаружить, что написано там и про библиотеку, и про Синод. И название – не единственный конфликтный тег. Есть ещё, например, start_date, в который можно записать дату постройки здания, в данном случае – 1834 год. Но, поскольку, этот тег попадёт и на библиотеку, не станет ли он означать также дату открытия библиотеки?

Можно подумать и решить, что никаких конфликтов тегов на самом деле нет. В осме мы обозначаем в первую очередь не здание и не заведение, а место, которое, в свою очередь, может получить название как от здания, так и от заведения. Тогда нам бы пришлось записывать в разные теги название, порождённое зданием и название, порождённое заведением, а в name писать наиболее употребимое название, если, конечно, мы в принципе признаём существование названия места отдельно от его содержания. Нечто подобное, видимо, и пытался сделать автор примера с historic_name, только тег пришлось бы назвать по-другому, а его историчность отразить в чём-то типа start_date, только, опять же, переименованному соответственно порождающей сущности. При этом, для самого места тег start_date не имеет смысла, так как оно существовало всегда, по крайней мере, относительно того, как человеки начали на нём что-то строить.

К счастью, вся эта философия нам не понадобится, так как есть другой способ: просто не ставить теги здания и заведения на один элемент в случаях, когда их нельзя отождествить. Сначала надо убедиться в том, действительно ли теги здания и заведения должны оказаться на одном и том же месте. Может оказаться, что заведение занимает не всё здание, или что оно занимает не только данное здание. Например, в расположенном рядом со зданием Синода здании Сената находится Конституционный суд. Но суд занимает также по крайней мере часть примыкающего здания, так что его границы не совпадают с границами здания Сената, и теги суда на здание ставить не понадобится.

Иногда можно сказать, что, помимо самого здания, к заведению относится и какая-то территория рядом с ним. Например, широко распространён способ отмечать школы и детские сады как раз по их территории, которая часто бывает ограничена забором. Другим примером территории, которой будет распоряжаться заведение, занимающее здание, является двор этого здания. Двор в само здание не входит, так что для POI понадобится другой полигон. Иногда этот полигон уже существует в виде внешнего контура здания, нарисованного мультиполигоном. Теги здания в этом случае стоят на самом отношении мультиполигона, а линия внешнего контура, как правило, тегов не содержит. Несколько лет назад теги здания было принято ставить именно на неё, но теперь их перенос на отношение уже завершён, и ничто не мешает воспользоваться этой линией для тегов POI. Хотя это может и странно выглядеть, это лучше, чем широко используемый способ совместить теги заведения с тегами забора вокруг него.

Если заведение занимает не всё здание, то его можно отметить любым из способов, рассматривавшихся до этого подраздела. Применительно же к данному подразделу можно заметить, что существуют разновидности POI, которые с большей вероятностью будут отмечены каким-либо участником на здании даже тогда, когда так делать было не нужно, например, те же школы. Соответственно, придётся заниматься обозначением для них новых мест и переносом туда тегов со зданий, хотя при этом мы лишаемся того преимущества, что не надо дополнительно что-то рисовать.

Возможна и такая ситуация, когда заведение занимает всё здание, и к этому ничего не прибавить, но на само здание теги POI ставить не следует. Тогда никто не мешает отметить место, занятое зданием ещё раз, что можно сделать несколькими способами:

  • если здание отмечено одной замкнутой линией, можно провести ещё одну такую же линию и проставить на неё теги POI;
  • можно создать мультиполигон с единственным членом – линией здания в роли outer, и поставить на этот мультиполигон теги POI;
  • можно создать новый мультиполигон, на которой перенести теги здания, а теги POI поставить на то, что было до того, но это лишняя правка исходной линии, и так делать не стоит.

Вертикальность

Может показаться, что полигон – хоть и более трудоёмкий способ представить POI, зато позволяющий отразить её истинную геометрию. На самом деле, поскольку полигон – фигура двумерная, то верно это только для геометрии на плоскости. С точки зрения вертикальной геометрии нас интересует возможность показать, на каком этаже располагается POI. В общем случае, POI может располагаться и на нескольких этажах. Что с этим делать мы уже подумали, в этом случае мы перечислим в теге level соответствующие уровни. Никаких проблем поставить этот тег на точку, в случае если POI обозначена таким способом, нет. В общем-то их нет и в случае с полигоном, однако на разных этажах заведение может занимать разную площадь. Когда мы обозначали POI точкой, на это можно было внимания не обращать, так как площадь обозначать мы не пытались. В случае обозначения полигоном площадь есть, но перечисленные уровни заведение занимает не на всей своей площади.

Магазин, под вторым этажом которого другие магазины

«Теремок» (справа) под вторым этажом «Фабрики» (вход слева)

Какая площадь должна входить в полигон POI? Как и для других объектов, например, зданий, это должна быть площадь проекции на горизонтальную плоскость. Её можно поделить на части, для которых заведение занимает разные множества этажей. Например, будет часть площади, где оно только на первом этаже, часть – на первом и втором, часть – только на втором. Видно, что это подобно зданиям, внутри которых могут быть части, обозначаемые с помощью building:part, у которых указывается этажность. Кажется, что и для POI должно быть подобное решение, но такого способа обозначения частей заведений, который был бы широко распространён, нет. Если мы захотим его сейчас придумать, как он должен выглядеть?

Допустим, мы отмечаем shop=*. По аналогии с building=* мы обозначили полигоном или мультиполигоном площадь его проекции. Внутри этой площади мы рисуем части магазина, занимающие разные этажи. Здание делить на части можно как по горизонтали, так и по вертикали. Для магазина мы тоже можем разрешить оба способа. Хотя в случае деления горизонтальными плоскостями получатся перекрывающиеся части, для POI это будет, как правило, более естественный вариант, так как перекрытия между этажами обычно есть, а стен в местах альтернативного вертикального деления может и не быть. Обозначим внутри площади магазина эти части полигонами с тегами, допустим, shop:part=yes. Плохо тут, конечно, то, что если бы мы обозначали не shop, а amenity, office и т.п., то для их частей понадобились бы другие теги: amenity:part, office:part и т.п. Если нам это кажется проблемой, мы можем обозначать части и другим тегом, например poi:part. В этом случае мы, возможно, добавим соответствующий тег и на всё заведение, в данном случае poi=yes.

Дальше надо указать этажи, а точнее уровни, соответствующие частям POI. У частей здания для этого используются теги building:levels и building:min_level. Очень редко встречается тег building:max_level. Здесь мы можем поступить либо так же, либо вспомнить, что мы уже используем для этой цели тег level. Если мы пойдём первым путём, то есть указанием диапазона уровней разными тегами, то имеет смысл использовать пару shop:min_level, shop:max_level (или amenity:min_level, или poi:min_level).

Если мы отмечаем части чего-либо, то должна быть возможность однозначно определить, чему эти части принадлежат. В случае со зданиями, часть, обозначенная с помощью building:part, относится к тому зданию, внутри которого она находится. Этого достаточно, так как проекции зданий на горизонтальную плоскость почти никогда не пересекаются. Бывают и исключения, такие как одно здание внутри другого, но тогда здание, находящееся внутри, обычно достаточно небольшое, например, это ларёк, и его на части делить не нужно. В случае же с POI возможны и довольно часто наблюдаются пересечения их проекций. Это особенно верно для многоэтажных POI, занимающих разную площадь на разных этажах, так как причиной не занимать одинаковую может являться то, что необходимое для этого место на другом этаже уже занято другим заведением. Следовательно, просто включения одной площади в другую может оказаться недостаточно для определения принадлежности части целому.

Когда другие способы не срабатывают, в ход идут отношения. Первое, что можно попробовать – использовать уже широко используемый вид отношения. Для объединения частей в единое целое широко используется мультиполигон, даже тогда, когда это неправильно. В данном случае, когда у одной POI могут быть перекрывающиеся части, он совсем не подходит. Мы можем запретить деление горизонтальными плоскостями и оставить деление вертикальными гранями. Тогда части POI не будут пересекаться, но будут соприкасаться. Для внешних границ мультиполигона это тоже не совсем правильно, но уже поддаётся осмысленной интерпретации. «Не совсем правильно» означает, что это будет расхождением со стандартом, которому спецификация мультиполигонов пытается следовать, но при этом разрешается от стандарта отойти для соприкасающихся границ, правда почему-то только для внутренних. Если идти таким путём, то полигона-проекции всего заведения рисовать не нужно, нужны только непересекающиеся части с установленными списками уровней, а прочие теги POI следует поставить на мультиполигон.

Это было, конечно, использование мультиполигона не по назначению, так что имеет смысл поискать что-то другое. При рассмотрении предыдущего использования отношений не по назначению, в разделе про несвязные POI упоминалось отношение site. Наш случай обсуждался как пример применения этого отношения. В этом случае можно оставить деление горизонтальными плоскостями, поставить на части теги level, а прочие теги POI поставить на отношение.

Если ни мультиполигон, ни site нас не устраивают, то можно придумать свой тип отношения. Назвать его можно чем-то вроде poi_parts. Для его членов нужно две роли – одна для проекции всего заведения целиком, другая – для его частей. Проекция целиком была бы не нужна, если бы мы были уверены, что всех сразу удастся заставить его использовать. Но, поскольку такое вряд ли произойдёт, проекция, на которой будут теги POI, будет существовать для обратной совместимости.

Все способы задать геометрию, которые используют отношения, будут менее популярны, чем те, которые отношения не используют. В осме есть один тип «естественного» отношения для этих целей – это мультиполигон. Его все понимают, и никто не стесняется использовать, даже слишком не стесняется. В случае с частями магазинов мы хотели бы без отношения обойтись, но нам нужно как-то обозначить отношение в широком смысле между частями и целым, то есть задать отношение, не используя элемент отношения. В осме есть средства и для этого, например тег is_in. Идут они из тех далёких времён, когда элементов отношений в осме не было, а теперь они как бы не нужны. Отношения они задают менее явно, но мы можем здесь захотеть пойти на их использование, так как для нас пока не так важно, чтобы результат был на 100% машиночитаемым, важнее, чтобы мы сами могли его прочитать. Если мы решимся пойти этим путём, то в is_in или ему подобный тег, например, is_in:poi, мы запишем название заведения, то есть то, что у заведения записано в теге name. Очевидный риск тут заключается в том, что name может измениться, но в принципе за этим можно автоматически следить.

Помимо вариантов с рисованием частей, можно предложить отметить помещения заведения по схеме Simple Indoor Tagging, поставить точку POI в какое-то одно из них, и оставить пользователям задачу догадаться, что они связаны. Ещё можно отметить POI отдельно на разных этажах. Тут уже можно использовать полигоны. Может быть, удастся даже придумать для этих разных экземпляров POI разные теги, не считая level.

Глядя на все эти теоретические рассуждения, можно усомниться в необходимости отмечания частей POI. Действительно, зачем они нужны? Если вы не собираетесь одновременно использовать и полигоны и level, то они и не нужны. Но если вы полигоны и level используете, то зачем вы это делаете? В контексте данной записи они нужны для того, чтобы не запутаться, где какая POI находится, когда POI расположены достаточно плотно. Двух- и более этажные POI как раз находятся в таких местах и как раз занимают разную площадь на разных этажах и по-всякому пересекаются в проекции с прочими POI. Если не рисовать части и просто поставить список этажей на проекцию, то из-за пересечений получится, что, согласно осмовским данным, в одном месте находятся несколько POI. Это совсем не то, что хочется получить.

Рисование неизвестного

Нарисовать полигон сложнее, чем поставить одну точку. Сложности при этом связаны не только с тем, что надо больше рисовать, но и с тем, что может понадобиться рисовать то, чего не видно. Если мы хотим нарисовать заведение, находящееся в здании и выходящее на улицу, то не так сложно получить его протяжённость вдоль здания. Это можно сделать подсчётом окон как изнутри, так и снаружи. Сложнее определить, насколько заведение уходит в глубину здания. Если нам повезёт, то мы увидим окна, выходящие на противоположную сторону здания, но чаще всего их не видно. Производить измерения без внешних ориентиров, насколько глубоко внутрь здания уходит не всегда полностью видимая площадь заведения, мы можем и не захотеть. Зато мы можем не захотеть и выбрасывать из вводимых данных известную нам протяжённость POI вдоль внешней стены здания.

Почему нам может быть важна эта протяжённость? Она нам важна применительно к сбору информации о POI, так как в первую очередь мы производим их внешнюю разведку. «В первую очередь» потому что даже если мы и зайдём внутрь интересующего нас места, то не раньше, чем увидим его снаружи. Если POI достаточно длинная, и, тем более, если по её длине располагаются несколько входов, то может быть важно эту длину как-то обозначить.

Точку мы ставить не хотим, а помимо точек для обозначения POI мы умеем использовать только полигоны. Но как мы нарисуем полигон, если у нас есть информация только о его «длине», и нет информации о «ширине»? Я рассматривал даже вариант обозначения POI незамкнутой линией, проходящей вдоль стены, но решил, что это будет выглядеть слишком странно. Скорее всего, сторонний наблюдатель подумает, что это ошибка, и линию просто забыли замкнуть.

Если нам повезло, то снаружи будет видна и «длина» и «ширина». Это произойдёт, если заведение находится на обозреваемом углу здания, на углу квартала. Это хорошо, так как именно угловые POI неудобнее всего обозначать точками, если пользоваться делением на области проверки, как это делаю я. Небольшое перемещение точки могло бы перебросить её из области одной улицы в область другой, а с полигоном такого не произойдёт.

Если нам не повезло, и у нас есть только граница заведения вдоль одной стены, то придётся решать, как эту границу замкнуть. Тут можно предложить два способа: через середину здания и через противоположную сторону здания. При первом способе мы проводим известную нам часть границы вдоль видимой стены, а дальше от её концов ведём перпендикуляры до точек, которые находятся посередине между видимой и противоположной стеной здания, затем соединяем эти точки линией такой формы, какая нам покажется наиболее подходящей, обычно просто прямой. При втором способе перпендикуляры мы ведём до противоположной границы здания и замыкаем контур по ней. Полученную отчасти фейковую геометрию мы предложим уточнить любому желающему, поставив на контур соответствующее примечание.

Полигон POI, уходящий вглубь здания до середины

Нарисованное по методу *до середины отделение почты, рисовал не я*

Если нет оснований поступить по-другому, замыкать границу POI лучше через середину здания. Так никто не решит, что заведение выходит и на противоположную сторону, чего мы не хотим утверждать, так как мы этого не знаем. Основанием же довести границу до противоположной стороны может служить, в случае если речь идёт о заведении общепита, наличие кухни. Тогда из неё куда-то ведут вытяжки, и если их нет на фасаде, а на нём их скорее всего нет, то они находятся с другой стороны.

Ещё в случае неизвестных размеров заведения может возникнуть соблазн срисовать их с плана эвакуации. Это, по идее, будет нарушением правил об использовании чужих карт, хотя некоторые участники открыто признаются в использовании таких планов.

POI вне зданий

Отчасти то, что касается обозначения POI, находящихся вне зданий, мы уже рассматривали в разделе про вертикальную геометрию. Там упоминался тег location и то, что он для обозначения расположения POI внутри здания не используется. Большинство наших POI находятся внутри, так что нужнее был бы тег для точек снаружи, но location=outdoor для последних не используется по тем же причинам. Из всех значений location для POI вне зданий подойдут underground и roof, а для обычного положения за пределами здания подходящего широко использующегося значения нет. Есть, правда, нерекомендуемое значение kiosk, показывающее попытки обозначить положение, промежуточное между indoor и outdoor.

С определённой точки зрения POI могут находиться вне зданий в разной степени. Самые вне это те, которые находятся под открытым небом. Среди тех видов POI, которые рассматриваются в этой серии записей, то есть тех, которые удовлетворяют критериям из предыдущей, подобные POI практически не встречаются. Несколько менее вне те POI, которые размещаются в палатках и им подобных конструкциях. Некоторые участники могут решить, что это здания, потому что у них есть крыша, некоторые другие с этим не согласятся. Лишь слегка вне располагаются POI, находящиеся в ларьках и небольших торговых павильонах, то есть в таких сооружениях, которые не сдует ветром, которые не демонтируются на ночь и которые мы ожидаем увидеть через неделю на том же самом месте. Такие сооружения обычно считаются зданиями.

Из этих разновидностей POI рассмотрим те, про которые мы решили, что они всё-таки внутри здания. Их особенность по сравнению с рассмотренными ранее находящимися совсем внутри POI заключается в том, что их здание мелкое и менее стабильное, а значит оно часто бывает не нарисовано на момент обозначения POI. Далее будем считать, что этим зданием является ларёк.

Если ларёк не нарисован, то есть два варианта действий: рисовать его как любое другое здание или не рисовать и сразу отмечать POI. Рисовать его как здание, то есть полигоном, бывает лень по уже упомянутым причинам размера и стабильности. Ларёк мелкий и его контур плохо виден на снимках, да и переместиться или исчезнуть он может с куда большей вероятностью, чем обычное здание, так что очень скоро может выясниться, что рисовали мы его зря. Полигон приходится рисовать, когда нужно внутрь поместить несколько объектов, в случае с ларьком же внутри него обычно что-то одно. Ещё нас может остановить то, что ларёк может находиться внутри другого здания, а вложенные здания мы рисовать не хотим. Если всё это нас или наших предшественников не остановило, и здание ларька нарисовано, то мы оказываемся в ситуации с POI, занимающей всё здание, рассмотренной в одном из предыдущих разделов.

Несколько ларьков под крышей

Ларьки в здании вокзала

Если же рисовать ларёк мы не решились, а POI мы обозначаем точкой, то к этой точке имеет смысл добавить тег building=kiosk. Это поможет показать, что точка POI не оказалась случайно за пределами здания. Эти случайности возникают либо когда саму точку ставят мимо, либо когда меняют геометрию здания не обращая внимания на то, что у него внутри.

Как я маплю

Это одна из записей про то, как я обозначаю POI. Выше я описывал разные способы обозначений, но при этом почти не говорил, каким из них я пользуюсь. Так я делал потому, что пользуюсь я разными способами. Я пытался их расположить в порядке усложнения, и их различная сложность и являлась причиной того, что они были рассмотрены. Простого способа может быть недостаточно, а всегда пользоваться сложным не выйдет заставить ни себя ни других. Конечно, для любой отдельно взятой POI можно нарисовать полигон, но когда нужно отметить сто POI, гораздо быстрее поставить для них только точки.

Рассмотренные способы

Перечислим рассмотренные способы обозначения POI.

  1. Отметить POI точкой.

    1.1. Поставить точку на границу POI, где вход, совместив её со входом. Можно сделать, если вход только один, и он принадлежит только данной POI.

    1.2. Поставить точку внутрь POI.

    1.2.1. Поставить точку посередине POI, для такого определения середины, при котором она будет внутри POI. Дополнительно может понадобиться решить, входят или не входят в пределы POI определённые помещения.

    1.2.2. Поставить точку на определённом расстоянии от входа или, если этого сделать нельзя, от границы здания.

  2. Отметить POI площадным объектом – полигоном или мультиполигоном, а возможно и более экзотическим отношением. Дополнительно понадобиться решить, входят или не входят в пределы POI определённые помещения.

Независимо от вышеперечисленного, можно:

  1. Не отметить входы.

  2. Отметить входы.

    2.1. Не соединять вход ни с POI, ни с глобальным графом маршрутизации.

    2.2. Соединить вход с POI. Может получиться само собой, если POI нарисована площадным объектом.

    2.3. Соединить вход с глобальным графом. Может получиться само собой, если ко входу ведёт отдельная дорожка.

    2.4. Соединить вход и с POI, и с глобальным графом.

Независимо от вышеперечисленного и друг от друга, можно поставить или не поставить вертикальные теги level, level:ref, addr:floor, location, layer.

Используемые мной способы

Из всего перечисленного выше, когда я где-либо обозначаю POI в первый раз, я обычно использую самый простой из методов, который позволит не запутаться в данном месте. Для большинства мест это обозначение POI точкой на расстоянии двух метров от входа без обозначения самого входа и без вертикальных тегов. Большинство мест – это те места, где (входы в) POI идут достаточно редко, допустим, они расположены не ближе 10 метров друг к другу. Поступать иначе, то есть мапить их более сложным методом, означало бы тратить время, которое лучше было бы потратить на ввод POI в другом месте. Кроме того, при первой проверке я не пытаюсь получить информацию, необходимую для рисования контуров POI и проходов к ним. Первую проверку я, как правило, делаю с записью трека, а если при этом заходить внутрь зданий, что понадобится для получения необходимой информации, то трек будет сбиваться.

Если входы в POI расположены близко, одной из причин этого является то, что ведут они на разные этажи. В этом случае я в первую очередь добавляю тег level. Так я могу обойтись без дополнительной геометрии, то есть без рисования входов, которое, как я писал в соответствующем разделе, будет подразумевать большую точность. Уровень этажа POI будет видно практически на любой фотографии, в том числе на той, на которой не виден вход. Цокольный или подвальный этаж (здесь имеется ввиду расположение этажа, а не его название в конкретном здании) нередко можно определить даже по фотографиям интерьера, которые часто бывают опубликованы на сайтах заведений. Это всё может пригодиться, если фотография со входом не получилась, и если нужно определить, какое заведение открылось вместо какого.

Выяснением номера этажа, который можно было бы записать в level:ref или addr:floor я специально не занимаюсь, и, соответственно, писать в эти теги мне обычно нечего. Каждый раз их использовать вместо или в дополнение к level и не получилось бы, потому что сам номер может не существовать. Случаи, когда номера нет, или, по крайней мере, когда он нигде не написан, встречаются довольно часто как раз тогда, когда я решаю использовать level. Речь идёт в первую очередь о цокольных или подвальных этажах, в которых могут находиться POI рядом с другими POI на первых этажах, и для которых никакого обозначения на месте, что это, например, этажи номер ноль я пока не встречал. Даже существующие обозначения этажей вряд ли будут написаны рядом с POI. Обозначения эти в центре Петербурга встречаются у входов на лестницы, и эти входы могут быть с другой стороны здания за закрытыми воротами.

Указатель с номерами этажей 0, 1, 2, 3, 4, 5

Этажи номер ноль, конечно, существуют, но в обычном здании подвал так никто не называет

Указатель с номерами этажей для лестницы жилого дома

У обычного здания этажи обозначаются так

Где обозначения этажей у POI можно встретить, так это на табличках в местах, где эти таблички служат единственным свидетельством существования POI, видимым с улицы. Тут я эти обозначения записываю в теги addr:floor на точках POI. А куда в этом случае, когда расположение самих POI остаётся неизвестным, я ставлю их точки? Я их ставлю рядом со входом, у которого про них написано. Если этажи точек известны, то ближе ко входу я ставлю те точки, у которых номер этажа меньше. Так может получиться несколько рядов точек, например, сначала точки второго этажа, потом третьего и так далее. У POI на первом этаже больше шансов быть видимыми снаружи, и их по описываемому принципу приходится ставить гораздо реже. Иногда этажи на табличках не написаны, но написаны номера офисов, и можно попытаться угадать этажи из них. Если это не получается, то я ставлю точки примерно в том порядке, в каком расположены их таблички.

POI, расставленные внутри здания в негеографическом порядке

«Матрица» из точек у БЦ

Подобное перемещение точек POI ко входу вместо их реального положения может привести к конфликтам. Точка могла быть уже поставлена туда, где она реально находится. Я уже писал о том, что мне это как правило не будет известно, и что я не смогу отличить просто поставленную куда-то внутри здания точку от поставленной целенаправленно в определённое место. Что это значит для вас:

  • Если я поставил точку внутри здания, не соединив её проходом, и она стоит рядом со входом в здание, и это не единственная точка рядом со входом, то у неё скорее всего фиктивное положение.

  • Иногда я пишу примечание или fixme о фиктивном положении – в основном, если ставлю точку глубоко внутрь здания, но вообще мне это делать лень, потому что в большинстве случаев точные координаты никого не интересуют.

  • Точки с фиктивным положением вы можете смело двигать, куда надо, только надо будет ещё что-то сделать, чтобы я их не подвинул обратно.

  • Лучший способ зафиксировать положение точки – соединить её с какой-либо геометрией, то есть нарисовать до неё проход. Понятно, что рисовать вам его будет лень, особенно если в него входит лестница, но, можно изобразить его хотя бы примерно, не пытаясь делить на части по level’ам. В принципе можно сказать, что фейковый проход – достойный ответ на фейковые координаты. Насколько проход фейковый можно указать в примечании на нём.

  • Другой способ – обозначить POI не точкой, а полигоном. Полигон я двигать никуда не буду, если только мне не понадобится сдвинуть всё здание. Этот способ особенно подойдёт, если в положении POI вы уверены не потому что знаете, как туда пройти, а потому что можете снаружи найти соответствующие окна. Тогда вы знаете протяжённость POI вдоль внешней стены и можете действовать по принципу, описанному в разделе Рисование неизвестного.

  • Если оба описанных выше варианта не подходят, то можно написать примечание, как пройти с улицы в POI.

Возможно, мне стоило бы вместо перемещения точек ко входу объединять их в отношение associated_entrance, но я этого пока не делаю.

Родственный тегу addr:floor тег level:ref я пока не использовал, но, возможно, буду использовать при indoor-маппинге. Его я намерен ставить туда, где в реальности есть обозначения этажей, обычно это выходы с лестниц внутри зданий. Пока за indoor я серьёзно не брался и только в одном здании подобным образом записал обозначения этажей, причём записал в тег addr:floor, и, видимо, зря, потому что по смыслу тут больше подходит именно level:ref. Мне кажется, что софту, который выводит планы этажей, стоило бы на всём level’е внутри здания или части здания с заданным количеством уровней искать эти обозначения, и если попадётся хотя бы одно, использовать его для всего этажа. Разработчики схемы Simple Indoor Tagging хотят, чтобы оно было именно на бесполезной с моей точки зрения обводке всего этажа, что является частным случаем того, чего хочу я.

Попадаются случаи, когда даже видя этаж, на котором расположена POI, сложно определить уровень, который пишется в level. Это как раз те питерские случаи, описанные в разделе про level. Тогда точно так же непонятно и как этаж называется, так что преимуществ у записи обозначения этажа вместо level не будет. К счастью в этом случае обычно магазины не идут в два этажа, так как непонятный этаж находится рядом с уровнем земли, а значит до другого этажа, который был бы уже далеко от уровня земли, понадобилась бы лестница существенной длины. Если магазины в здании только на одном этаже, level как средство отличить одно место POI от другого уже не нужен и я его не ставлю.

Если входы расположены близко, но ведут на один этаж, то без их рисования всё ещё можно обойтись. POI не перепутаются, так как я их ставлю на одинаковое расстояние от границы здания. В этом случае определить конкретное место помогут находящиеся рядом соседние заведения, ведь если и происходит их ротация, то, скорее всего, не всех сразу. Тогда то, что одна точка появилась на месте другой, будет ясно из того, что их неизменившиеся соседи совпадают. Пойти же на рисование и входов и проходов в данном случае меня могут заставить соображения обороны от правок участников, редактирующих каждую POI в отрыве от других точек. В первую очередь, это пользователи MAPS.ME, в случае с которыми можно не надеяться на то, что поставленный ими новый магазин окажется между двумя своими соседями. Нарисовать вход и проход они не могут, и если появляется подобный не привязанный к геометрии новый магазин, то он сразу становится заметным, и сразу ясно, что его надо куда-то переместить.

Пять входов в магазины на одинаковом расстоянии друг от друга

Хороший повод обозначить входы – их регулярное расположение, по которому можно выровнять и POI

Входы в здания могут быть уже обозначены другими участниками, но обычно это ещё не сделано. В первую очередь появляются входы на лестницы, но за ними редко бывают интересующие меня POI. Прочие входы, включая входы в магазины, обозначены бывают редко, если только их не совмещают с самим магазином. Такие совмещения я разделяю на две точки, соединённые проходом: вход на контуре здания и POI внутри. Проход тут нужен, чтобы не снести информацию о соответствии входа и POI. Историю редактирования точки я оставляю на POI, а не на входе, то есть операция разделения состоит из вырезания совмещённой точки из контура здания, её перемещения, удаления с неё тегов входа и создания новой точки входа на исходном месте. Делать приходится именно так, потому что часто сама POI существовала ещё до своего совмещения со входом. Если вход обозначен без POI, то я просто ставлю POI рядом с ним или перемещаю к нему уже обозначенную POI, а проход обычно не рисую, так как обычно его геометрия мне неизвестна.

Рисовать входы приходится при отсутствии взаимно однозначного соответствия между ними и POI. Если я их рисую, то, как правило, и соединяю их с POI. В случае нескольких заведений за одним входом, можно даже сказать, что в первую очередь я хочу обозначить проходы внутри здания, чтобы было понятно, в какую сторону идти к какой POI. Проходы должны откуда-то вести, и имеет смысл это место нарисовать, а им и является вход. Если геометрия проходов мне неизвестна, то я не обязательно нарисую вход.

Рисование проходов носит также оборонительный характер. POI может быть запрятана достаточно глубоко внутри здания, и нужно, чтобы не увидевший её снаружи участник её не потёр. Кстати, OsmAnd не сможет удалить точку, соединённую с линией, а то у нас есть участники, удаляющие POI из этого редактора. Те, кто пользуются нормальными редакторами, надеюсь, подумают, как удаление повлияет на форму этой линии. Впрочем есть те, кто удаляют сами проходы, так что, возможно, теперь придётся думать уже и об их обороне.

На сам вход я чаще всего ставлю тег entrance=yes. entrance=main я использую либо для очевидного главного входа в здание, который определяется независимо от находящихся в здании POI, либо для основного входа в крупное заведение, например, занимающее всё здание, или содержащее внутри себя множество POI, например ТК или БЦ. Если таких входов несколько, то я могу поставить несколько main. entrance=shop я пока не использую.

Когда у одного заведения несколько входов, то это повод не только их обозначить, но и использовать полигон для обозначения POI, что я и делаю. Вариант с точкой, при котором придётся рисовать соединения от входов мне нравится меньше. Для того, чтобы эти соединения нарисовать не выдумывая, как именно они идут, понадобится заходить внутрь, а к полигону входы можно пририсовать и без проходов, тогда внутрь заходить не понадобится. Правда, тогда может не получиться выяснить противоположную от улицы границу полигона, но её может не получиться выяснить в любом случае.

Несколько легче выяснить границы угловой POI, что для меня хорошо, в связи с используемым мной методом записи информации о произведённых проверках POI. Проверки я делаю по участкам, в которые обычно входят стороны кварталов. В прошлой записи в разделе Где? я обращал внимание на то, что вход POI должен быть внутри участка, а угловой вход или даже место, где вход может появиться, – внутри обоих участков. Это нужно было в том числе для того, чтобы точка, поставленная либо рядом с таким входом, либо по какой-нибудь другой причине на углу, тоже оказалась внутри участков. Другой причиной может являться установка точки на углу, когда входы в POI есть по обе стороны от угла. Сами входы находятся как в одном участке, так и в другом, POI я ищу по входам, значит хочу обозначить и её в обоих участках. Пока я обозначаю POI точкой, в оба участка её можно добавить, только поставив на углу. Однако подобный способ обозначения POI вынуждает принимать решения о расположении точки, которые ещё более произвольны, чем «два метра». Соответственно, я стараюсь места с несколькими входами обозначать не одной точкой, а полигоном, который естественным образом пересечётся со всеми необходимыми участками.

Полигон POI на углу здания

«Кондитерская» на углу с фотографии перед разделом про входы; перед ней и описываются решения об расположении точки

С проходами вне зданий входы я пока не соединяю, потому что для записи расположения POI они не нужны, и я не определился, какие теги на них ставить. Если я всё-таки решаюсь соединяющий проход нарисовать, то с тротуара необязательных тегов типа surface на него я не копирую. Здесь я поступаю так же, как и с пешеходными переходами через улицы – поверхность и прочие свойства улицы я на них не ставлю.

Какие теги ставить на внутренние проходы, я тоже не вполне определился. В простых случаях, когда не надо рисовать лестницы, я использую highway=corridor. В случаях посложнее – иногда использую его же, иногда highway=footway. Пока я не знаю, на чём остановлюсь, удобнее использовать corridor, так как если я решу от него отказаться, то его легко массово заменить на footway. Обратную замену сделать сложнее, так как footway используется гораздо шире и для других вещей.

Что касается того неприятного случая, когда POI занимает разную площадь на разных этажах, то использования всех описанных в соответствующем разделе ужасов разрезания на части и создания отношений я пока избегал. Какой из них менее ужасен, я пока не решил. Если для обозначения POI хватит одной точки, то проблем не будет. До сих пор мне пришлось нарисовать только один полигон для такой POI. Делать это пришлось из-за нескольких входов и углового расположения. Нарисовал полигон я по проекции, на части его не делил.

Немного истории

Способы, которыми я обозначал POI, менялись на протяжении того периода времени, как я стал отдельно этим заниматься, то есть с сентября 2016 года. Когда я начинал обозначать POI, я вообще не хотел делать геометрические правки, то есть рисовать какие-либо линии. После долгого перерыва мне было лень настраивать JOSM и вспоминать, как им пользоваться. Чтобы более-менее приемлемо в нём рисовать, нужно установить десяток плагинов. К тому же ещё выяснилось, что два нужных мне плагина – AlignWays и CommandLine – несовместимы с на тот момент текущей версией JOSM. В результате я три-четыре месяца ограничивался добавлением, редактированием, удалением точек и изменением тегов на уже существующей геометрии. Это значит, что POI я обозначал либо точками, либо тегами на всём здании целиком, входы и проходы не рисовал.

Когда другие участники стали изменять геометрию под редактируемыми мной точками, мне пришлось десяток плагинов всё-таки установить, но из геометрических правок я стал делать только минимально необходимые. Некоторые полигональные объекты я рисовать начал – в основном это было то, что полигонами обозначается традиционно, то есть детские сады, школы, бизнес-центры, но не обычные магазины. Таким образом я обошёл Адмиралтейский район и приступил к Центральному в апреле 2017 года.

Центральный район отличался более некачественной геометрией и большим вниманием со стороны добавляющих заметки. Иногда нужная для установки POI геометрия, то есть контуры зданий, была достаточно корявая, чтобы на неё нереально было наложить снимок. Мне пришлось смелее передвигать здания туда-сюда, что стало положительно влиять на личную статистику правок, и отрицательно на ввод того, что я собственно и собирался ввести, то есть POI.

Касательно заметок можно сказать, что на любую точку может прилететь что-нибудь типа что её не видно, а дальше те, кто считают своим долгом заметки закрывать, её потрут. Но точку на самом деле может быть не видно, потому что она глубоко внутри здания. Это «глубоко» лучше выразить через осмовские данные, то есть нарисовать до точки проход, что мне и пришлось начать делать в сложных случаях, когда за одной дверью находятся несколько POI. Для этого приходится заходить внутрь, чего я ни разу не делал при обходе Адмиралтейского района, и пока я не знаю, как это лучше совмещать с регулярными проверками, упомянутыми в предыдущей записи.

Трудности тут связаны с тем, что для мест, в которые необходимо заходить, я собирался создавать отдельные участки проверки. Теперь же выяснилось, что таких мест с одной стороны гораздо больше, и они могут обнаружиться где угодно, а не только в очевидных зданиях типа торговых комплексов, с другой стороны они могут быть достаточно маленькими по сравнению с другими участками, и, вроде как, своего участка не заслуживать. Те же места внутри зданий, которые участок очевидно заслуживают, я пока ввожу только в экспериментальном порядке. Более систематическое их рассмотрение является для меня задачей на ближайшее будущее.

Заключение

На протяжении этой записи, которая оказалась куда протяжённее, чем я ожидал, неоднократно встречались утверждения о том, что есть разные способы обозначения POI и примыкающих к ним объектов. В начале предыдущего раздела уже приводился список с вариантами обозначений, но это были более-менее бесспорные варианты, в которых не предлагалось ничего, что уже широко бы не использовалось. Но в записи также встречались и более дискуссионные предложения включая гипотетические теги. Приведём здесь их список.

  • Следует ли использовать entrance=shop и другие нетрадиционные типы входов?
  • Стоит ли использовать разные ключи для входов и выходов?
  • Обозначать ли окна заказа/выдачи, и если да, то каким тегом? Подойдёт ли для этого amenity=walk_up_window или они сами по себе не являются amenity, аналогично входам?
  • Ограничиваться ли традиционными тегами highway=footway и highway=steps при рисовании проходов внутри здания, использовать дополнительно highway=corridor или вводить ещё значения для highway=*? А, может быть, вводить их для footway=*?
  • Если использовать highway=corridor, то как широко? Для любого прохода насквозь помещения или только для основного? Для любого ли помещения или только для собственно коридора, если нам удастся однозначно определить, что такое коридор?
  • Как часто следует рисовать проходы с улицы ко входам в здания? К любым входам, только к тем, за которыми обозначены проходы, только к тем, за которыми сквозные проходы?
  • Какие теги использовать для проходов снаружи ко входам? Обычные highway=footway и highway=steps или другие, введённые специально для данной задачи?
  • Как обозначить заведение с разными по площади частями на разных этажах здания?

В этом списке я специально не привёл вопросов обозначения этажей. На эту тему, с одной стороны, существует глобально принятый взгляд, с другой стороны придерживающиеся этого взгляда часто не в курсе о том, что локально он бывает не столь принят, потому что не столь удобен. Есть несколько способов разрешения этого противоречия, но в этой записи мы просто принимали глобальный взгляд, хотя и для него привели несколько вариаций. Разбор же альтернатив может быть темой для отдельной записи.

Итого в этой записи мы рассмотрели, как отмечается место, в котором находится заведение, то есть подходящие для этой цели осмовские элементы, к которым пришлось добавить небольшой набор тегов. Эти теги предназначены для компенсации отсутствия трёхмерности у элементов, то есть того факта, что у осмовской точки есть широта и долгота, но нет высоты, а также отсутствия возможности и желания эту высоту вычислять. Пока мы не рассмотрели, как в данных отражается суть заведения, то есть теги помимо упомянутого набора, это предстоит сделать, скорее всего, в следующей записи. Однако, есть ещё важные последствия обозначения места (и времени), которые не уместились в эту запись, так что, возможно, придётся изложить сначала именно их.

Можно уже перейти к рассмотрению того, что я отмечаю при своих проверках POI, а заодно где и когда. Сразу надо предупредить, что если здесь написано, что я какие-либо объекты не отмечаю, то это не значит, что я их совсем никогда не отмечаю, это значит, что я не стремлюсь их отмечать при проведении проверок POI. Тем более это не значит, что я считаю, что они не нужны, и буду их удалять, когда они мне попадутся.

TL;DR

Что: любые стационарные точки ведения любого рода деятельности (в первую очередь – магазины, но также офисы) с присутствием персонала (не банкоматы, не торговые автоматы), видимые из свободно доступных для посещения мест, либо пожелавшие о себе сообщить любым способом в достаточно близком от себя месте (обычно табличкой) при наличии дополнительных способов верификации (обычно сайта).

Где: в данный момент – на территории Адмиралтейского и Центрального районов Санкт-Петербурга в первую очередь вдоль официальных улиц (согласно rgis), далее во дворах и ТК.

Когда: в какой-либо момент со вторника по пятницу с 11:00 по 18:00, при необходимости в другое время.

Что?

Целевые теги

Когда я пытаюсь написать, что я отмечаю, мне приходится говорить и о том, что я не отмечаю. Это связано с системой тегов в осме или, в ряде случаев, отсутствием системы. В данном случае, отмечаю я POI, а каким осмовским тегам это соответствует?

  • amenity – некоторым. Этот ключ соответствует разнородным объектам, как урнам, так и университетам. Университеты при данных проверках мне нужны, а урны – нет. Урны у меня относятся к особому виду проверок – урново-скамеечной картографии, для которых более-менее годится maps.me как редактор, но сейчас речь не о них.

  • club – всем. Это редко используемый тег, про который часто непонятно, стоит ли использовать именно его.

  • craft – всем, какие заметны в городской среде, а это те, которые предоставляют услуги населению, например, ателье.

  • highway – никаким. Этот ключ вообще не должен бы использоваться для POI, но он таки используется, например, для остановок транспорта. Но остановки не подходят по критериям, приведённым выше.

  • landuse – так сложилось, что некоторые крупные объекты, которые удовлетворяют критериям, например заводы, обозначаются этим тегом. Если я их могу обнаружить, то я их обозначаю, но в результаты проверки не включаю.

  • leisure – некоторым, например leisure=playground не подходит. Детские площадки я обозначаю при детальной отрисовке дворов, так что если я пойду искать во дворе POI, то чтобы отдельно туда не ходить за всем остальным, я отмечу и детские площадки.

  • office – всем, но большинство из них никак о себе не сообщают, и я такие не обозначаю.

  • shop – всем. Самый очевидный ключ для данных проверок.

  • tourism – некоторым. Музеи нужны, а viewpoint’ы – нет.

Видно, что невозможно придумать фильтр для типов точек, которые меня интересуют, так как в любой момент может войти в употребление новый тег из семейства amenity, leisure или tourism, и будет неизвестно, интересует ли он меня. То же самое с другой стороны выглядит как невозможность сформулировать определение интересующего меня множества объектов на местности на основе тегов осм.

Требования к POI

Как я уже писал, я определил интересующее меня множество POI по степени находимости и скорости изменений. Скорость изменений – это то, из-за чего в принципе приходится заниматься обновлением данных отдельно для POI. Но и среди того, что обычно относят к POI, скорость изменений разная. Некоторые из точек способны меняться быстрее, чем типичный магазин. Отсюда следует моё требование стационарности. Как я его обычно определяю: обозначаемое мной место не должно быть на колёсах и не должно быть переносимо парой человек. Такие точки могут не иметь постоянного местонахождения или запросто исчезнуть. На колёсах часто бывают фургоны «выпечка» или «кофе с собой».

Кофе с собой

Не подходит, так как на колёсах

К переносимым точкам относится стихийная торговля в подземных переходах, у станций метро, железнодорожных станций и рынков, возможно и внутри рынков. У этих точек обычно есть серьёзные причины переместиться или исчезнуть, а я не собираюсь заниматься учётом этих причин, например, законности или скорости, с которой весь их товар будет распродан.

Продажа симок

Поставите ли вы здесь office=telecommunication?

Обычным ларькам повезло подойти по моим критериям, хотя они были близки к тому, чтобы я не обращал на них внимание: они тоже перемещаются на небольшие расстояния и прекращают/возобновляют работу чаще, чем обычные магазины. Частое прекращение и возобновление работы ожидаемо для любой точки, на которой присутствует только один человек, а помимо ларьков это могут быть и те из торговых мест на рынках и в переходах, которые подходят по критериям проверок.

Закрытый ларёк

Этот ларёк не работает только сейчас или в принципе?

Всякие банкоматы, платёжные терминалы, торговые автоматы, для отсечения которых даётся требование наличия персонала, не угодили мне не только тем, что многие из них нестационарны, но и тем, что их сложнее найти. Типичный платёжный терминал находится в типичном магазине, и обнаружить его можно только зайдя в магазин. Помимо обнаружения присутствия для поддержки актуальности данных нужно и обнаружение отсутствия, а это ещё сложнее. Это значит, что я не ищу терминалы и т.п. на территориях определённых мной участков, не перепроверяю их, если они обозначены, хотя могу их удалить, если обозначены они были давно, и поменялось или закрылось содержащее их заведение. Заодно требование персонала отсекает много лишнего из amenity типа скамеек и почтовых ящиков.

Платёжный терминал

Типичный платёжный терминал в типичном магазине

Найти на месте может быть сложно и точку побольше, чем терминал. Когда магазин, кафе и т.п. видно с улицы или другого доступного места, то всё понятно с наличием точки, хотя не обязательно понятно, какие теги ставить. Но заведение может быть видимо только по косвенным признакам, таким как табличка, из которой следует, что где-то за дверью оно есть, а за дверь могут зайти только клиенты. Можно было бы такие заведения в проверки не включать, как я сначала и делал. К таким заведениям относятся практически все офисы. С другой стороны, есть и очень заметные офисы, которые видны не только по табличкам. Некоторые из них можно даже перепутать с магазинами, и то, что они не являются магазинами, выясняется уже при последующем поиске информации про них в интернете. Чтобы не игнорировать очень заметные офисы и не делить офисы на очень и не очень заметные, я стал обозначать их все, если они либо непосредственно видны, либо удовлетворяют дополнительному критерию, о котором написано ниже.

Что ещё обычно заметно только в виде таблички:

  • мини-отели – у некоторых нет даже и таблички, а у которых есть – таблички мелкие, так как располагаются на обычной двери жилого дома, и самих отелей часто бывает несколько. В этом случае цель существования таблички – информировать о коде домофона.

  • мелкие услуги типа изготовления ключей и ремонта всякой всячины.

  • всё, что находится в бизнес-центрах, а это не обязательно офисы. Не в каждый БЦ можно свободно войти.

  • заведения социальной направленности, которые не могут или не хотят быть слишком заметными.

Если искать строго только те заведения, которые непосредственно видны, то иногда придётся пропускать даже крупные места типа больниц. Откуда я знаю, что там, где написано «больница», действительно больница, если я в ней не был? В случае с магазинами и кафе можно в окно заглянуть или, если непонятно, зайти внутрь. В общем, если вводить только непосредственно видимое, можно лишиться довольно широкого класса заведений.

Но всё-таки наличие таблички не гарантирует наличия заведения, про которое на ней написано. Тогда как определить, надо ли его ввести? Также возникает и противоположный вопрос: если в осме уже есть заведение, которого не видно на месте, и про которое могло бы быть написано на какой-нибудь табличке, которую можно не заметить, надо ли его удалить? Чтобы уменьшить количество таких вопросов, у меня есть требование дополнительной верификации: про место должно быть написано где-то в интернете. Я стараюсь не вводить те места, наличие которых я не смогу проверить в случае исчезновения таблички.

Этим «где-то в интернете» обычно является сайт заведения или его страница в какой-либо соцсети, когда их нет, могут помочь всякие официальные документы. Понятно, что из «где-то» приходится исключить чужие базы данных типа 2ГИС, а также то, что поисковики любят показывать справа от результатов. Несколько раз я добавлял офисы компаний потому что про них сообщалось в СМИ, что бывает в связи с имущественными спорами с различной степенью криминальной составляющей.

Возможные офисы

Есть ли за этой дверью офисы, с учётом того, что на сайте соответствующих организаций про них не написано?

Ни один из этих двух фактов (написано на месте, написано в интернете) сам по себе не является гарантией наличия POI, так как есть существенная вероятность того, что табличку забыли убрать, и что информацию на сайте забыли обновить. Вероятность того, что одновременно забыли и то и то должна быть ниже, и я надеюсь, что она достаточно низкая. Проверить это утверждение можно позвонив по телефону, но этим я пока заниматься не собираюсь.

Предпочтения одних видов POI другим

Отдаю ли я предпочтение каким-либо точкам внутри обозначенного выше множества? Я не стал проверять в первую очередь «наиболее важные» POI. Как их в принципе можно было бы определить? Ну, например по нахождению на более оживлённой улице. Но я решил обойти все улицы в интересующих меня районах. Можно решить, что более важные заведения это те, которые более узнаваемы, а более узнаваемыми будут те, которые принадлежат крупной сети. Но я не ввожу в приоритетном порядке точки крупной сети только потому, что она крупная, хотя и штучным заведениям я не отдаю предпочтение только для того, чтобы поддержать их в борьбе с предполагаемым капиталистическим врагом.

Вопрос предпочтения определённых POI другим довольно легко переводится некоторыми в политическую плоскость. Например, смотрят на долю женщин среди участников, видят, что она мала, а затем делают утверждение типа «вы делаете карту, не отражающую потребностей половины пользователей». Дальше удаётся добраться до обвинений широких слоёв участников в каком-нибудь -изме, или даже в том, что они больше зарабатывают за счёт осма по сравнению с менее привилегированными классами. В данной записи на эту тему дальше рассуждать я не хочу, но могу попробовать рассмотреть упомянутое отражение потребностей тех или иных групп пользователей.

В критериях выбора POI у меня никакие социальные группы не упоминаются. Это, конечно, не означает, что мои данные будут одинаково нужны всем. Кого-то POI в принципе меньше интересуют, чем, например, состояние дорог. Можно себе представить велосипедиста, для которого я не отмечаю ни велодорожки, ни велопарковки, ни станции проката. Велосипедист может обвинить меня в том, что я поддерживаю сложившуюся ситуацию, когда предпочтение отдаётся автомобилям, ведь по моим критериям не подходят даже остановки общественного транспорта.

Автобусная остановка

Остановка не подходит, так как нет персонала

Может ли быть такое, что даже среди POI, удовлетворяющих моим критериям, я уделяю меньше внимания каким-то, которые больше нужны кому-то? В принципе может. Шансы быть добавленными выше у тех точек, которые более заметны при проходе мимо них. Одно из часто приводимых утверждений на тему, что осмеры мапят не то, что нужно, это то, что они уделяют недостаточно внимания детским садам, зато активно отмечают бары. В моём случае и у детских садов и у баров шансы быть отмеченными ниже среднего. Детские сады в центре Петербурга часто видны только по табличкам, которые могут быть в не самых заметных местах, например в окнах. Почему шансы ниже у баров написано далее в разделе Когда?

Некоторые участники, кстати, чаще отмечают POI определённого типа внутри обозначенного мной множества. Например, Pavel47, вводит почтовые отделения и ящики, а GaM – супермаркеты и прочие продуктовые магазины. Можно заметить, что эти точки, за исключением мелких продуктовых магазинов, отличаются большей стабильностью по сравнению с обычными магазинами, так что у маппинга отдельно «Пятёрочек» и «Дикси» смысл не только в том, что они для кого-то важнее. Несмотря на это, я пока не собираюсь придумывать дополнительные критерии для разделения POI по вероятной скорости изменения.

Помимо предпочтений какие места обозначать, могут быть предпочтения как обозначать, то есть какими тегами и насколько подробно. Это будет рассмотрено вместе с тем, какие я использую теги, в одной из следующих записей.

Где?

Географическое где

Ещё могут быть предпочтения географические. Обычно они звучат так: «вы отмечаете богатые районы (города, страны) более активно, чем бедные». Это уже ближе к моему случаю, ведь я маплю в основном центр, а не Купчино или Гражданку, хотя далеко не все места в центральных районах можно назвать богатыми. Объясняется это просто: я действую там, куда мне легче добраться, и до Невского проспекта мне добраться легче, чем до Невского района. Ещё я надеюсь, что центр нужен большему числу пользователей.

Адмиралтейский район

Западный край Адмиралтейского района

Систематически отмечать POI я начал с Адмиралтейского района. До того у меня была идея собирать данные по муниципальным округам. В Петербурге они меньше районов, например, в Адмиралтейском районе шесть округов. Так я делать не стал, потому что их границы неудобно для меня проходят, да и запоминать их мне лень. Между районами границы проходят более естественным образом, например, по Неве. Правда, этого нельзя сказать про границу между Адмиралтейским и Центральным районом. Например, станция метро «Адмиралтейская» находится именно в Центральном районе. В итоге после того, как я обошёл один раз все улицы Адмиралтейского района, я добрался и до Центрального.

Граница Адмиралтейского района

Железные дороги – ещё один вариант естественных границ районов

Прочие места Адмиралтейского района, где есть POI, я обхожу параллельно с улицами Центрального района. Эти прочие места, то есть дворы и всяческий indoor, уже нельзя мапить без предварительной подготовки, которая может заключаться в выяснении доступности для посещения самого места и скачивании данных в Vespucci. Этот процесс более растянут по времени, чем обход улиц, соответственно ждать, пока я обойду все дворы с POI в одном районе, прежде чем приступать к другому, непродуктивно.

POI в других местах я обычно вообще не трогаю и могу в случае несоответствия данных осма с реальностью оставить заметку с помощью maps.me, которую я сам закрывать не буду. У некоторых по этому поводу возникают вопросы, мол, раз я знаю, что тут что-то не так, то почему я не делаю правку? Ответ: потому что мне и в своих районах хватает данных для ввода, и эти данные – не только POI.

Геометрическое где

Имеет смысл объяснить здесь, как я рисую участки. Рисуются они так, чтобы внутри оказалась примерно половина ширины улицы, вдоль которой идёт проверка, и примерно половина ширины выходящих на неё зданий. Это линии вдоль «длинных» сторон участка. На его «коротких» сторонах граница участка должна проходить через угол здания, находящийся на перекрёстке улицы участка и пересекающей её улицы. Здесь может возникнуть упомянутая в прошлой записи проблема, из-за которой участки могут перекрываться: на самом углу может быть вход в POI. По ряду причин, о которых будет написано в следующих записях, мне нужно, чтобы вход был внутри участка, а угловой вход должен быть внутри двух участков, поэтому границу участка надо отодвинуть от угла в направлении от улицы метров на пять. То же самое надо сделать и для участка пересекающей улицы, и между границами этих двух участков будет часть здания, находящаяся одновременно в этих двух участках.

Прямой и срезанный угол в JOSM

Слева прямой, а справа срезанный угол с дверью. Поверх них изображены участки, вдоль одной из улиц границы участков выделены красным цветом.

Упомянутое выше «может быть вход» не значит, что вход обязательно есть. Это даже не значит, что есть дверь. На углу может быть и окно, а переделать на первом этаже окно в дверь достаточно легко, и это часто происходит. В итоге «может быть вход» означает «угол срезан или скруглён так, что вход там либо уже есть, либо может возникнуть без перестройки стен здания». Можно было бы перерисовать границы, когда вход появится, но хотелось бы, чтобы они были более-менее стабильны. Конечно, стабильными они не будут, если двигать и сами здания, а пока такие места, где бы их стоило подвинуть, имеются и в Адмиралтейском и в Центральном районе. Сейчас из-за этого границы участков мне приходится пододвигать, но со временем количество мест, где это приходится делать, и расстояния, на которые приходится двигать, должно уменьшаться.

Окно на первом этаже

Бывает, что дверь превращается обратно в окно

Вход на углу не является единственной проблемой. У здания может быть несколько углов рядом с перекрёстком. Так бывает, когда здание находится внутри острого угла пересечения улиц. В этом случае, если среди углов здания есть более острый, то границу участка можно провести через него. Если нет, то границу можно провести так, чтобы все углы оказались внутри участка – так опять получится общая для двух участков часть здания. Конечно, лучше чтобы общая часть была поменьше, так как её придётся проверять вдвое чаще.

Прямой и срезанный угол в JOSM

Граница участков проходит через более острый угол здания

Дальше от выбранного угла опускается перпендикуляр на пересекающую улицу, оттуда граница участка проводится к пересечению улиц, далее вдоль улицы участка она идёт до противоположного пересечения, а оттуда уже через перпендикуляр от противоположного угла здания к самому углу. Далее границу надо замкнуть на первый угол через примерно середины выходящих на улицу зданий. Это те здания, POI в которых будут хорошо видны, если идти по тротуару вдоль улицы, а точнее те, у которых можно без проблем сфотографировать входы и всё, что рядом со входами, и что может быть нужно для идентификации POI. Например, если между тротуаром и зданием газон, на котором только трава, то это здание включается в участок, но если на газоне деревья или высокие кусты, то здание исключается. Если вдоль улицы идёт забор, граница участка проводится по нему.

Нетрудно заметить, что из-за перпендикуляров помимо возможной общей для двух участков части здания также получится и общая территория на улице за пределами здания, причём она будет почти при любой геометрии угла. Зачем в принципе включать в участки территорию за пределами зданий? На ней тоже могут быть POI, например, ларьки, которые, кстати, часто бывают именно на перекрёстках. Из-за них и появилось правило с опусканием перпендикуляра: так легко оценить на месте, входит ли ларёк в проверяемый участок.

Цель этих правил – чтобы было понятно, где границы участка, не глядя на их изображение.

Когда?

Регулярные проверки

Теперь можно рассмотреть регулярные проверки, до которых я обещал добраться ещё в прошлой записи. Это те проверки на местности, при которых я выясняю, присутствуют ли и работают ли POI на всём участке целиком, и которые я делаю в те дни недели и то время суток, когда ожидаю, что большинство из POI работают. Дни недели это будние кроме понедельника, так как есть достаточно много POI, не работающих по выходным, а из будних дней самый популярный, чтобы не работать, это понедельник. По понедельникам любят не работать специализированные магазины для узкого круга покупателей, например shop=hifi. Время суток для проверки – между 11:00, когда уже открылись все, кто открывается до обеда, и 18:00, когда работающие в обычное рабочее время уже начинают закрываться. Зимой приходится заканчивать ещё раньше, потому что быстро темнеет и фотографии становится делать сложнее.

Проверки в указанное время не гарантируют, что удастся застать работающими все POI. Есть заведения, у которых в плане времени работы всё наоборот. Это всякие бары и клубы, которые могут открываться только к вечеру или из будних дней работать только в пятницу. Также бывают магазины, в которых, видимо, не ждут покупателей раньше обеда, и которые открываются, например, в час дня.

Что может случиться, если во время проверки место было закрыто, хотя в другое время оно работает? Худшее это если его в нерабочее время вообще не видно. Так может случиться, если у него нет никаких вывесок за пределами окон и дверей, а окна и двери закрыты, например, ролетами. Тогда о существовании места можно узнать только если его кто-нибудь уже добавил в осм, но и тут придётся как-то решать, не закрылось ли оно совсем. Менее плохой вариант – если место видно, но не видно, что оно работает, и неизвестно, когда оно должно работать.

Гараж

Это заведение раньше пяти вечера вы не заметите

В итоге приходится обращать внимание не только на POI, но и на места их возможного присутствия в виде закрытых дверей, и не торопиться удалять уже введённые точки, которых не видно на месте. Для сомнительных точек, а также для тех, для которых в результате проверки не хватает информации, приходится устраивать нерегулярные проверки.

Нерегулярные проверки

Нерегулярные проверки – это все проверки, при которых я не пытаюсь обойти весь участок. Пока я никак не записываю их результаты, кроме ввода данных в осм. Сначала я их делать не собирался, поскольку хотел всё вводить систематически, с записью какие когда участки проверены. Но в ходе проверок для некоторых точек не удаётся собрать необходимые данные. Например, выясняется, что плохо получилась фотография, и на ней не прочитать название заведения. Иногда, особенно если вводить данные существенно позже проверки на месте, возникает подозрение, что заведение больше не работает. В этих случаях надо сходить на место ещё раз, но задерживать ввод данных всего участка до этих дополнительных проверок неудобно. В итоге сначала у меня появился список мест для повторной проверки, впоследствии превратившийся в маркеры в maps.me. После того, как разработчики maps.me «переизобрели закладки», маркеры перешли в OsmAnd.

Также к нерегулярным проверкам относятся и все случаи, когда я заметил, что открылось что-то новое или закрылось то, что я уже вводил. Сначала я это игнорировал, так как опять же хотел вводить систематически. Однако так получалось бы, что ради своего процесса ввода я оставляю неправильные данные. Данный способ обновления информации я всё равно не считаю достаточно хорошим, в связи с чем возникают организационные вопросы типа «Стоит ли продолжать вводить таким образом замеченные POI?» или «Стоит ли смотреть на магазины мимо которых проходишь, когда не делаешь регулярную проверку, а то вдруг заметишь изменения?»

Требования ко времени были для регулярных проверок, а нерегулярные можно проводить когда угодно. Проверки типа «обратил внимание на изменившуюся точку и решил записать» проводятся когда угодно по естественным причинам. Сложнее с проверками возможно закрытых или невидимых в обычное время заведений. В этом случае бывает нужно идти в определённое время, когда заведение должно работать, и это время может отличаться от обычного, например, для упомянутых выше баров.

В связи с определённым временем проверок возникают ещё организационные вопросы, например, «Что делать, если в нужное время проверку вообще не получается?» До рассмотрения этих вопросов я доберусь, видимо, через пару записей в дневнике, а в следующей записи будет рассмотрено, как я отмечаю POI.

Почему пришлось взяться за POI

Если мы посмотрим на карту в масштабах города, то самыми важными объектами на ней будут, скорее всего, улицы, затем дома с адресами, а затем POI. На счёт этого порядка важности можно поспорить, некоторые утверждают, что без адресов карта бесполезна, хотя мне кажется, что это преувеличение. Лично я ближайшие POI помню не по номеру дома, и на вопросы, где находится дом номер такой-то обычно ответить не могу. Кстати, нередко такие вопросы задают рядом с искомым домом, после чего я проверяю, есть ли табличка с номером, и обычно она есть.

Дальше встречаются разные мнения, какие именно разновидности POI важнее. Например, кто-то скажет, что аптеки. На вопрос, что важнее – магазин или столовая, я пока решил не отвечать, и заняться всеми POI, которые подходят под определение, которое я приведу в одной из следующих записей. POI, которые под него попадают, выделены мной не по степени важности, а по степени находимости на местности и скорости изменений.

Мы знаем, что объекты на местности могут меняться, причём разного рода объекты будут меняться с разной скоростью. Из перечисленного выше, улицы меняются редко: иногда появляются новые, иногда продлеваются старые, иногда у них меняется название, и можно считать, что они практически никогда не исчезают. Правда, они могут закрываться на ремонт, что важно для навигации, но за этим не так сложно уследить, потому что самих улиц мало относительно других перечисленных выше объектов. Здания тоже меняются редко: иногда строятся новые, иногда перестраиваются старые. Во временных масштабах существования осма, отрисовка зданий – почти одноразовое дело.

Другое дело – магазины, кафе и т.п. По весьма примерным подсчётам их «время полураспада» составляет 5 лет. То есть если вы их все отметите и подождёте 5 лет, половина из них уже не будет существовать. И если их много, то найдётся какой-нибудь магазин, который закроется или откроется практически сразу после вашей проверки. А их очень даже может быть много – так много, что они на рендер не поместятся. Значит, просто один раз сходить и отметить подобного рода точки, а затем считать, что дело сделано, не выйдет.

Я хочу, чтобы данные о POI в осме были как можно ближе к действительности. Ясно, что для этого придётся перепроверять уже однажды проверенные места. Решать вопрос, куда и когда идти проверять можно по-разному, но при этом не обойтись без информации о том, когда производилась предыдущая проверка. Есть ли в данных осма такая информация?

Время проверок

Первое, что можно вспомнить, это время создания пакета правок. Однако, это время вовсе не обязательно совпадает со временем, когда редактирующий участник видел точку на месте. Строго говоря, оно всегда не совпадает, потому что правка делается позже проверки. Можно, конечно, пытаться делать правку сразу, но часто бывает некогда. Например, я сначала ставил себе задачу вводить данные на следующий день после проверки, потом срок превратился в две недели, теперь я рад, когда отстаю меньше, чем на два месяца. Иногда правка точки вообще не означает, что участник её видел или проверял каким-либо другим способом, например, сдвиг здания вместе со всем его содержимым или замена url. Короче, время проверки надо брать из какого-то другого места.

Вторая идея – пользоваться тегом check_date. Для POI он редко используется, так что первый недостаток – то, что придётся тегировать под x, где x – организация процесса обновления данных о POI. Может возникнуть вопрос, а уместна ли в принципе простановка на точки, линии и отношения тега check_date и подобных ему метаданных. Если нет, то мы могли бы его ставить на пакет, ведь у пакетов тоже есть теги. Тогда, правда, придётся аккуратно делать пакеты, чтобы они не затрагивали лишнего. Такая же проблема была бы и при использовании даты создания пакета, но проблема эта не единственная.

Другим источником проблем является то, что проверять приходится не сами точки, ну или не только сами точки, а ещё и места, где эти точки могут быть. Изначально в данных осм точек нет, так что и check_date искать не на чем. Допустим, мы ставим дату проверки на пакет, и список пакетов, в которых её надо искать, мы составим вручную, чтобы не просматривать все пакеты, затрагивающие интересующее нас место. Но что нам делать, если мы пройдём по месту, и увидим, что в соответствующих ему данных ничего менять не надо. Например, там как не было POI, так и нет. Тогда и правок делать не надо, пакет создавать не из чего, дату проверки писать некуда и читать неоткуда. И, вообще-то, мы так и не определили, что такое интересующие нас места. В осме таких объектов точно нет.

Места проверок

Становится понятно, что придётся задать информацию о местах за пределами данных осма, и информацию об их проверках тоже хранить не в осме. И подобное уже реализовано в MapCraft. Но эти нарезки носят одноразовый характер: вот вам участок, где что-то не нарисовано, пойдите нарисуйте, затем отметьте, что задача выполнена и всё. А у нас – не всё, нам надо перепроверить участок через некоторое время, и сами участки должны быть определены с учётом таких перепроверок.

Нарежем всю территорию, которую хотим проверять, на участки по-своему. Участки нам нужны достаточно небольшие, чтобы каждый из них можно было целиком проверить за один заход. Большинство интересующих нас POI видны с улицы, следовательно в качестве участков подойдут части кварталов, выходящие на определённые улицы. Так можно будет проверить весь участок, даже если он не являлся целью похода. Просто идём мимо, вдруг появляется желание помапить, и начать мапить можно, дойдя до следующего перекрёстка.

Естественное желание – сделать участки непересекающимися, чтобы любая точка попадала только в один из них. Но так не выйдет, потому что некоторые заведения находятся на углу квартала, причём даже вход в них находится прямо на углу. Да и физически POI не являются точками, а значит никто не мешает рисовать их полигонами, а полигон запросто может пересечься с несколькими участками. Полигоны для POI, правда, обычно не используют, к причинам этого мы ещё вернёмся. Итого наши участки могут перекрываться, особенно на углах кварталов, и POI может находиться одновременно в нескольких участках.

Помимо POI, выходящих на улицу, есть ещё POI во дворах, подземных переходах, торговых комплексах, бизнес-центрах. С ними иметь дело сложнее, и они для меня являются второстепенной задачей. Первая сложность тут ещё со сбором данных: их не видно с панорам улиц, и gps рядом с ними не работает, значит пройтись на месте с OsmTracker’ом, а вводить уже потом за компом не получится. Поэтому я пока не брался за ТК и не решил, на какие участки их делить. Весь ТК как один участок – это, наверное, слишком много с точки зрения «целиком проверить за один заход». Если делить, то, видимо, на этажи, хотя тогда получатся не просто перекрывающиеся участки, а полностью совпадающие в проекции на плоскость, а это по ряду причин неудобно.

Со внутриквартальными POI есть свои сложности. В центре Петербурга, как правило, зайти во двор можно через арку, а далее пройти можно только в ограниченную часть квартала. Часто из двора определённого дома никуда попасть нельзя, кроме как обратно на улицу. В этом случае можно сделать участком весь этот двор. Но если таким образом доступна большая часть квартала, да и сам квартал большой, то делить на участки придётся как-то по-другому. В новостройках придётся, видимо, делить вдоль внутриквартальных проездов. Мне это предстоит делать уже и в Центральном районе рядом с Московским вокзалом.

Метаданные проверок

Поскольку для начала я решил никаких инструментов не писать, то и сохранять данные пришлось самым примитивным способом. Это был csv-файл с записями (название участка, дата проверки, пакет правок). Название участка служит его идентификатором и обычно выглядит как (название улицы, тип улицы, диапазон номеров домов). Конечно, в будущем это должно стать таблицей в базе данных, и тогда идентификатором участка мог бы быть суррогатный ключ ещё одной таблицы с данными об участках. Но при редактировании вручную суррогатный ключ, то есть число, которое само по себе ничего не значит, использовать неудобно.

Информация о том, когда была произведена проверка, представлена в виде даты. Точнее даты время мне знать не нужно, соответственно я не слежу за тем, во сколько часов сколько минут я начал проверять определённый участок, главное, чтобы это было время регулярной проверки, об этом позже. Другой вопрос – не нужно ли специально хранить менее точные данные, например, из соображений privacy. Когда я начну принимать данные от других участников, мне, возможно, придётся вернуться к этому вопросу. По поводу намеренного предоставления менее точных данных есть две точки зрения. Одна из них – что для недавнего времени надо давать менее точную информацию, а позже её можно уточнить. Другая – что наоборот по прошествии времени данные надо делать менее детальными. Мне больше подходит первый вариант, в том числе потому что он получается сам собой. Собранные данные я ввожу не сразу, так что если вы захотите узнать, где я сейчас нахожусь, глядя на предоставляемые мной данные о проверках участков, то я уже давно оттуда ушёл. Вторая точка зрения связана с тем, что при точных данных о том, где кто когда был, идущих далеко назад по времени, можно сделать вывод, какие места данный человек имеет обыкновение посещать, например, в определённый день недели. Но те места, информацию о которых я ввожу в рамках данных проверок – это не те места, в которые я хожу с какой-либо другой целью. В большинство проверяемых заведений я вообще не захожу.

Что касается третьего элемента в записи – номера пакета правок, то как мы уже знаем, его может и не быть. Соответственно, уже с самого начала его указывать было необязательно. Тут можно поинтересоваться, зачем в принципе записывать пакет, ведь дата проверки берётся не из него. В данный момент это просто средство для меня, чтобы искать пакеты правок, относящиеся к определённому месту. По обычной истории правок это делать неудобно. В идеале хотелось бы иметь способ получить всю информацию по POI, признанную мной правильной на момент проверки, и она содержалась бы в пакете, если бы правки в обязательном порядке затрагивали все точки и, желательно, ничего кроме точек. Но это не так, хотя отчасти я пользуюсь записанными пакетами в качестве временного средства сделать snapshot данных. (примечание на июнь 2018: кое-что поменялось между написанием и публикацией; собственно snapshot уже делается, и полей в соответствующем csv-файле уже не три)

Далее обнаружилось, что не всегда реально сделать правки для всего участка за один заход. Соответственно, пришлось разрешить указывать множество пакетов правок для одной проверки. Связано это с тем, что попадаются участки, на которых может быть хоть пятьдесят POI, например, Лиговский проспект между площадью Восстания и Транспортным переулком (1, 2), и это если исключить из него Московский вокзал и «Галерею». Придумывать особенный способ деления на участки поменьше для «POI-плотных» мест мне не хочется, так как при текущем способе деления границы участков очевидны даже без разглядывания картинок, где они нарисованы, тем более, что изначально они не были нарисованы.

Метаданные участков

Сначала данные об участках содержались в первую очередь в их названиях. Названия эти состоят из названий улиц и диапазонов номеров домов. Названия улиц не уникальны во всём субъекте федерации, но уникальны внутри центральных районов. В районах, включающих разные населённые пункты, типа Пушкинского, подобной уникальности может уже не быть, но ими я пока систематически не занимаюсь. Если к названию улицы добавить номера домов, то так можно задать сторону квартала, выходящую на определённую улицу – тот тип участков, которые я проверяю в первую очередь. Проблема тут в том, что номеров по нужной улице может не существовать. Улицами здесь я называю всё, что в Петербурге официально ими считается, и отображается зелёными линиями в rgis. Это включает и площади, а по ним часто не бывает номеров, тогда в название участка приходится вместо них писать, какая это сторона, например, юго-западная. Даже если номера и есть, то они не всегда очевидны, их может не быть в осме и так далее. Дополнительно к номерам я решил давать текстовое описание, которое позволит в сочетании с именем участка найти его, даже если я ошибусь с номерами. Сначала это привело к появлению ещё одного csv-файла с записями (название участка, описание).

Через некоторое время это стало неудобно, ведь по прежнему не было никаких машиночитаемых данных о расположении участков. Расположение можно задать, нарисовав полигон, покрывающий участок. Несвязные участки, для которых это не сработает, скорее всего, не понадобятся. Так как я ввожу данные из josm, то и участки легче рисовать в нём же. Поскольку участки не являются данными осма, то их можно держать в отдельном слое. В нём можно рисовать полигоны и задавать им теги name и description для того, что было в csv-файле. Данные самих проверок, в принципе, тоже можно было бы сохранять в тегах полигона, но это менее удобно, и пока я этого не делаю. Слой с участками сохраняется в файл, а не закачивается в базу осма.

Недостатки у работы со слоем-файлом такие:

  • А вдруг его случайно закачаешь, тем более, что josm будет предлагать это сделать, если вносить изменения. К счастью, вскоре после того, как я перешёл к использованию слоя, в josm была добавлена возможность запретить закачивать слой, если в его файле есть xml-атрибут upload='never', поставленный на корневой элемент. Достаточно один раз его вручную поставить, и этот недостаток исчезает.

  • А вдруг в него случайно скачаешь данные осма, ведь их в нём быть не должно. Операцию скачивания ещё и нельзя отменить, так что приходится следить, какой слой выбран, и хранить версии файла, например, в git, чтобы в случае скачивания и сохранения лишних данных можно было бы откатиться к «чистой» версии. Впрочем, недавно был добавлен и атрибут download='never'.

  • josm всё-таки предназначен для редактирования данных осма, и у всех объектов должен быть осмовский идентификатор. А какие идентификаторы у объектов, которых в осме нет и не будет, то есть у наших участков? Всему, что не закачано, josm даёт временные идентификаторы – отрицательные числа - но нет гарантий, что они постоянны. А если мы начали пользоваться системой контроля версий, то изменения идентификаторов для нас нежелательны. Можно попробовать переустановить идентификаторы перед записью в git так, чтобы изменений было поменьше, но пока я этим не занимаюсь.

Теперь у нас есть набор метаданных, пригодный, например, для визуализации свежести данных POI. Про сами эти не-мета-данные POI будет написано в одной из следующих записей дневника.