3

I've written some C/C++ code to wrap mapnik-vector-tile and produce a mapbox vector tile from GeoJSON.

mvtc_return * mvtc_from_geo_json(const int tile_size,
                                 const char * geo_json,
                                 const char * layer_name,
                                 const char * mapnik_input_plugins_path,
                                 const int z,
                                 const int x,
                                 const int y)
{
  mvtc_return * rv = new mvtc_return();
  if (rv == NULL) return NULL;

  try
  {
    double area_threshold = 0.1;
    double simplify_distance = 0.0;
    bool strictly_simple = true;
    bool multi_polygon_union = false;
    mapnik::vector_tile_impl::polygon_fill_type fill_type = mapnik::vector_tile_impl::positive_fill;
    bool process_all_rings = false;

    mapnik::datasource_cache::instance().register_datasources(mapnik_input_plugins_path);

    mapnik::Map map(tile_size, tile_size, "+init=epsg:3857");
    mapnik::parameters p;
    p["type"] = "geojson";
    p["inline"] = geo_json;

    mapnik::layer lyr(layer_name,"+init=epsg:4326");
    lyr.set_datasource(mapnik::datasource_cache::instance().create(p));
    map.add_layer(lyr);

    mapnik::vector_tile_impl::merc_tile out_tile(x, y, z, tile_size);
    mapnik::vector_tile_impl::processor ren(map);
    ren.set_area_threshold(area_threshold);
    ren.set_strictly_simple(strictly_simple);
    ren.set_simplify_distance(simplify_distance);
    ren.set_multi_polygon_union(multi_polygon_union);
    ren.set_fill_type(fill_type);
    ren.set_process_all_rings(process_all_rings);
    ren.update_tile(out_tile);

    out_tile.serialize_to_string(rv->mvt);
    rv->return_code = MVTC_SUCCESS;
  }
  catch (std::exception & ex)
  {
    rv->mvt = "";
    rv->return_code = MVTC_FAILURE;
    rv->message = std::string(ex.what());
  }
  return rv;
}

The full code is available as a gist. If it looks familiar, that's because it's mostly a copy of node-mapnik's addGeoJSON function. My problem is that given GeoJSON with multiple features, the vector tile produced seems to only include the first feature.

For example, given the following GeoJSON I would expect a vector tile with 3 features.

{
  "features": [
    {
      "geometry": {
        "coordinates": [[115.859553, -31.951733], [115.859679, -31.951774]],
        "type": "LineString"
      },
      "type": "Feature",
      "properties": { "name": "Wellington St" }
    },
    {
      "geometry": {
        "coordinates": [[115.844394, -31.944039], [115.844396, -31.944256]],
        "type": "LineString"
      },
      "type": "Feature",
      "properties": { "name": "Railway St" }
    },
    {
      "geometry": {
        "coordinates": [[115.849276, -31.938264], [115.849227, -31.93725]],
        "type": "LineString"
      },
      "type": "Feature",
      "properties": { "name": "Cleaver St" }
    },
  ]
  "type": "FeatureCollection"
}

However, the tile produced by this GeoJSON (and dumped to the console) is

�@x
foolayer(�name"
Wellington St"  ��

Admittedly I haven't rendered the tile, however given there is only one street name in the output, I'm fairly confident only one feature is included in the tile.

My question, therefore, is why is my code not producing a tile that includes all of the features in my GeoJSON?

EDIT

The critical piece that I neglected to include is that this was part of an FFI from Haskell, which was taking a C string (i.e. null terminated). As the MVT contained a null, the marshalling into Haskell land was truncating the string. This code does appear to work correctly.

Not sure if this question should now be deleted - happy to do that if advised.

  • Is there any chance that's just the label you are seeing? Ie it rendered three but only labeled one? – Jamie Cook Oct 2 '16 at 3:21
  • I imagine it's possible, but I think it's highly unlikely. The size of the output remains the same, even when I have tens of features in my GeoJSON. If someone knows of a way to easily render a mapbox vector tile I can check. – ajmccluskey Oct 3 '16 at 23:05

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Browse other questions tagged or ask your own question.