systemed / tilemaker

Make OpenStreetMap vector tiles without the stack
https://tilemaker.org/
Other
1.49k stars 230 forks source link

How to configure fields? #121

Closed wboykinm closed 6 years ago

wboykinm commented 6 years ago

I'm interested in pulling building height data into MVTs generated with tilemaker. Using the "default" config file, I edited this line to read

{ "id": "building", "description": "building", "fields": { "height": "Integer" }}

Tilemaker then runs smoothly and produces outputs that render in Mapbox GL when given static properties:

screenshot 2018-10-15 10 29 13

Unfortunately, when I try to use the height info for dynamic styling, I get this error:

Expected value to be of type number, but found null instead.

It appears that my adjustment to the config file above is producing NULLs. What is the proper way to pass usable building height data (or indeed any data from osm properties) through to generated MVTs?

systemed commented 6 years ago

Oh wow, that looks nice!

The bit of tilemaker that maps OSM keys into MVT fields is the config.lua file. (The vector_layers part of the JSON config is a slightly confusing Mapbox addition which documents what the client will find in the tiles, but it doesn't actually change anything. tilemaker can now generate that automatically.)

So you'd need to make config.lua take the OSM data and write it into the vector tiles. You should be able to do this by editing https://github.com/systemed/tilemaker/blob/master/process.lua#L43, and adding a couple of new lines:

local metres = to_number(way:Find("height")) or 5
way:AttributeNumeric("height", metres)

That takes the height tag from OSM; converts it to a number; falls back to a default height of 5 if there's no height tag; and writes it to the vector tile as the "height" attribute.

There's doubtless lots more you could do in terms of parsing the weird and wonderful values that are no doubt in the height tag, but that should do for a start. Lua's really well-suited to doing this sort of OSM tag-mangling (it's used for the same purpose in OSRM and osm2pgsql).

wboykinm commented 6 years ago

@systemed That's a marvelous explanation, and makes this super-extensible. Thanks so much!

I am however running into what appears to be a coalesce failure, and my troglodytic searching around the lua docs is not turning up an answer.

Given:

if building~="" then
  local metres = (to_number(way:Find("height"))) or 5
  way:AttributeNumeric("height",metres)
  way:Layer("building", true)
end

Any idea what's causing this?

libc++abi.dylib: terminating with uncaught exception of type kaguya::LuaRuntimeError: process.lua:44: attempt to call global 'to_number' (a nil value)

It seems to happen no matter where I put the metres declaration. For reference I'm using a geofabrik extract.

systemed commented 6 years ago

Gah! Mea culpa. Should be tonumber (no underscore).

wboykinm commented 6 years ago

@systemed That did the trick!

screenshot 2018-10-15 16 00 04

Thanks again!

tgdbepe4 commented 3 years ago

Where you place exacty this:

I'm interested in pulling building height data into MVTs generated with tilemaker. Using the "default" config file, I edited this line to read

{ "id": "building", "description": "building", "fields": { "height": "Integer" }}