Become a Patron!

My Amazon wishlist can be found here.

Life Line

Adressing Flats

I recently moved into a new area in London, and that means, a new area to map. That means drawing in all the buildings, but also adding shops and addresses. Unlike my old area, the new neighbourhood has lots of buildings with flats. In OpenStreetMap, you can tag addresses on flats with the addr:flats tag. In most cases, the addresses of the flats are formed by a flat number, building name (addr:housename) and street name (addr:street). Only occasionally the address consists of flat number, house number, and street name.

When I started tagging a nearby collection of flat blocks, and the flat number/house name/street name on their entrance nodes, I noticed that it rendered as:

As you can see, it ignored the addr:flats tag, and instead just rendered the addr:housename tag over and over again. Not particularly useful.

So I thought, why not "fix" the rendering. In the past, I already added a basic rendering for natural=tree_row to the "default" rendering style. So I had another look on how to make addr:flats render and show up instead of the house name 20 times.

OpenStreetMap's style sheet is developed through the Git repository at git@github.com:gravitystorm/openstreetmap-carto.git. I cloned the repository and searched after the places where I needed to make modifications to add the flat numbers. The style sheets first require a "style" file to tell which data to import from the main database (or .xml file). Only fields that are copied into the rendering database are available for use in the style sheets. OpenStreetMap Carto stores these definitions in the project.mml file. But that's a nasty JSON file, so instead, you add the definition into the project.yaml file. There is a script to convert the YAML file into the project.mml file which the carto tool can use to generate a Mapnik stylesheet. Mapnik is then responsible for rendering the map.

In project.yaml, just above the - id: "housenumbers" line, I added the following section:

- id: "flatnumbers"
  name: "flatnumbers"
  class: ""
  geometry: "point"
  <<: *extents
  Datasource:
    <<: *osm2pgsql
    table: |-
      (SELECT
          way,
          "addr:flats",
          way_area/NULLIF(!pixel_width!::real*!pixel_height!::real,0) AS way_pixels
        FROM planet_osm_polygon
        WHERE "addr:flats" IS NOT NULL
          AND building IS NOT NULL
      UNION ALL
      SELECT
          way,
          "addr:flats",
          NULL AS way_pixels
        FROM planet_osm_point
        WHERE "addr:flats" IS NOT NULL
        ORDER BY way_pixels DESC NULLS LAST
      ) AS flatnumbers
  properties:
    minzoom: 17
  advanced: {}

It basically instructs the stylesheet to run an extra query to obtain information on addr:flats and make that information available to the actual styles.

It requires an extra column in the database (addr:flats), the import "style" needs to include this data while importing from the data source into the rendering database. The file containing the import definitions is openstreetmap-carto.style. I added the following line in between the definitions for access and addr:housenumber:

node,way   addr:flats   text         linear

Adding an extra column into the "style" means that it is necessary to reimport the data from the main database (or XML file) into the rendering database. My original source is the openstreetmap.osm file, which I re-imported with:

/home/derick/install/osm2pgsql/osm2pgsql \
        -S openstreetmap-carto.style --slim -d gis -C 2400 openstreetmap.osm

To render the flat numbers, and attach a style to them, I had to add a section to the addressing.mss file which is a sub-stylesheet that deals with address information. This stylesheet is linked from the project file. I added the following lines in between the #interpolation and #housenumbers sections:

#flatnumbers {
  [zoom >= 17] {
        text-name: "[addr:flats]";
        text-placement: interior;
        text-min-distance: 1;
        text-wrap-width: 0;
        text-face-name: @book-fonts;
        text-fill: #666;
        text-size: 8;
  }
}

I picked the same style as for standard house numbers, but one size smaller.

With all the sections added to the right files I had to regenerate the project.mml file from project.yaml with:

./scripts/yaml2mml.py < project.yaml > project.mml

And generate a Mapnik stylesheet from the project.mml file with:

carto project.mml > mapnik.osm

With all that in place, I re-rendered the area. The flat numbers are now visible on the map:

I have packaged up all the changes, and prepared a pull request for openstreetmap-carto. With some luck, the changes will make it to the OpenStreetMap website at some point in the future.

Shortlink

This article has a short URL available: https://drck.me/flats-bt2

Comments

Nice bit of work. In reading it I've noticed that 'reimporting the database' is often mention in the context of adding a column. I dont think this is necessary:

ALTER TABLE planet_x ADD "addr:flats" VARCHAR(256) NULL;

assuming data has been imported with hstore;

UPDATE planet_x
SET "addr_flats" = tags->'addr:flats'
WHERE tags?'addr:flats'

This costs roughly a table scan per table.

Obviously you cant do anything if the tags column wasn't imported.

These ought to be capable of being wrapped up as a reversible database update (i.e., ALTER TABLE planet_x DROP "addr:flats" takes us back to where we started), which is useful if doing stuff on the live system.

Add Comment

Name:
Email:

Will not be posted. Please leave empty instead of filling in garbage though!
Comment:

Please follow the reStructured Text format. Do not use the comment form to report issues in software, use the relevant issue tracker. I will not answer them here.


All comments are moderated