Skip to content

Add geojson datasource option use_id_from_source #972

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Draft
wants to merge 1 commit into
base: master
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
24 changes: 23 additions & 1 deletion src/mapnik_feature.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -76,16 +76,38 @@ Napi::Value Feature::fromJSON(Napi::CallbackInfo const& info)
{
Napi::Env env = info.Env();
Napi::EscapableHandleScope scope(env);
Napi::Object options = Napi::Object::New(env);

if (info.Length() < 1 || !info[0].IsString())
{
Napi::TypeError::New(env, "requires one argument: a string representing a GeoJSON feature").ThrowAsJavaScriptException();
return env.Undefined();
}
bool use_id_from_source = false;
if (info.Length() > 1)
{
// options object
if (!info[1].IsObject())
{
Napi::Error::New(env, "optional second argument must be an options object").ThrowAsJavaScriptException();
return env.Undefined();
}
options = info[1].As<Napi::Object>();
if (options.Has("use_id_from_source"))
{
Napi::Value param_val = options.Get("use_id_from_source");
if (!param_val.IsBoolean())
{
Napi::TypeError::New(env, "option 'use_id_from_source' must be a boolean").ThrowAsJavaScriptException();
return env.Undefined();
}
use_id_from_source = param_val.As<Napi::Boolean>();
}
}
std::string json = info[0].As<Napi::String>();
try
{
mapnik::feature_ptr feature(mapnik::feature_factory::create(std::make_shared<mapnik::context_type>(), 1));
mapnik::feature_ptr feature(mapnik::feature_factory::create(std::make_shared<mapnik::context_type>(), 1, use_id_from_source));
if (!mapnik::json::from_geojson(json, *feature))
{
Napi::Error::New(env, "Failed to read GeoJSON").ThrowAsJavaScriptException();
Expand Down
12 changes: 12 additions & 0 deletions src/mapnik_vector_tile_json.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1003,6 +1003,7 @@ Napi::Value VectorTile::addGeoJSON(Napi::CallbackInfo const& info)
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;
bool use_id_from_source = false;

if (info.Length() > 2)
{
Expand Down Expand Up @@ -1089,6 +1090,16 @@ Napi::Value VectorTile::addGeoJSON(Napi::CallbackInfo const& info)
}
process_all_rings = param_val.As<Napi::Boolean>();
}
if (options.Has("use_id_from_source"))
{
Napi::Value param_val = options.Get("use_id_from_source");
if (!param_val.IsBoolean())
{
Napi::TypeError::New(env, "option 'use_id_from_source' must be a boolean").ThrowAsJavaScriptException();
return env.Undefined();
}
use_id_from_source = param_val.As<Napi::Boolean>();
}
}

try
Expand All @@ -1099,6 +1110,7 @@ Napi::Value VectorTile::addGeoJSON(Napi::CallbackInfo const& info)
mapnik::parameters p;
p["type"] = "geojson";
p["inline"] = geojson_string;
p["use_id_from_source"] = use_id_from_source;
mapnik::layer lyr(geojson_name, "+init=epsg:4326");
lyr.set_datasource(mapnik::datasource_cache::instance().create(p));
map.add_layer(lyr);
Expand Down
19 changes: 19 additions & 0 deletions test/datasource.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -202,6 +202,25 @@ test('test empty geojson datasource', (assert) => {
assert.end();
});

test('test geojson datasource with id are read using "use_id_from_source" param', (assert) => {
var input = {
"id": 12345,
"type": "Feature",
"properties": {
"something": []
},
"geometry": {
"type": "Point",
"coordinates": [ 1, 1 ]
}
};
var ds = new mapnik.Datasource({ type:'geojson', inline: JSON.stringify(input), use_id_from_source: true });
var fs = ds.featureset()
var feat = fs.next();
assert.equal(feat.id(), 12345);
assert.end();
});

test('test empty geojson datasource due to invalid json string', (assert) => {
var input = "{ \"type\": \"FeatureCollection\", \"features\": [{ \"oofda\" } ] }";
// from string will fail to parse
Expand Down
15 changes: 15 additions & 0 deletions test/feature.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,21 @@ test('should match known features', (assert) => {
assert.end();
});

test('should accept option to use_id_from_source', (assert) => {
var expected = {
id: 12345,
type: "Feature",
properties: {},
geometry: {
type: 'Polygon',
coordinates: [[[1,1],[2,1],[2,2],[1,2],[1,1]]]
}
};
var feature = new mapnik.Feature.fromJSON(JSON.stringify(expected), { use_id_from_source: true });
assert.equal(expected.id, feature.id());
assert.end();
});

test('should output the same geojson that it read', (assert) => {
var expected = {
type: "Feature",
Expand Down
29 changes: 29 additions & 0 deletions test/vector-tile.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -185,6 +185,35 @@ test('should fail when adding bad parameters to add geoJSON', (assert) => {
assert.end();
});

test('should accept "use_id_from_source" param when adding geojson', (assert) => {
var vtile = new mapnik.VectorTile(0,0,0);
var geojson = {
"type": "FeatureCollection",
"features": [
{
"id": 12345,
"type": "Feature",
"geometry": {
"type": "Point",
"coordinates": [
-122,
48
]
},
"properties": {
"name": "geojson data"
}
}
]
};
vtile.addGeoJSON(JSON.stringify(geojson),"layer-name", { use_id_from_source: true });
var out = JSON.parse(vtile.toGeoJSON(0));
assert.equal(out.type,'FeatureCollection');
assert.equal(out.features.length,1);
assert.equal(out.features[0].id, 12345);
assert.end();
});

test('should be able to create a vector tile from geojson', (assert) => {
var vtile = new mapnik.VectorTile(0,0,0);
var geojson = {
Expand Down