Skip to content

Commit 9202e38

Browse files
committed
Add vector_layers JSON support
1 parent db971cf commit 9202e38

File tree

6 files changed

+116
-38
lines changed

6 files changed

+116
-38
lines changed

include/osm_object.h

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,9 @@
99
#include "geomtypes.h"
1010
#include "osm_store.h"
1111
#include "output_object.h"
12+
#include "rapidjson/document.h"
13+
#include "rapidjson/writer.h"
14+
#include "rapidjson/stringbuffer.h"
1215

1316
// Protobuf
1417
#include "osmformat.pb.h"
@@ -22,6 +25,7 @@ struct LayerDef {
2225
double simplifyLevel;
2326
double simplifyLength;
2427
double simplifyRatio;
28+
std::map<std::string, uint> attributeMap;
2529
};
2630

2731
/*
@@ -220,6 +224,11 @@ class OSMObject {
220224
void Attribute(const std::string &key, const std::string &val);
221225
void AttributeNumeric(const std::string &key, const float val);
222226
void AttributeBoolean(const std::string &key, const bool val);
227+
228+
// ---- vector_layers metadata entry
229+
230+
void setVectorLayerMetadata(const uint_least8_t layer, const std::string &key, const uint type);
231+
std::string serialiseLayerJSON();
223232
};
224233

225234
#endif //_OSM_OBJECT_H

include/read_shp.h

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
#include <map>
88
#include "geomtypes.h"
99
#include "output_object.h"
10+
#include "osm_object.h"
1011

1112
// Shapelib
1213
#include "shapefil.h"
@@ -24,13 +25,15 @@ void addToTileIndexPolyline(OutputObject &oo, std::map< uint, std::vector<Output
2425
void addShapefileAttributes(DBFHandle &dbf, OutputObject &oo, int recordNum, std::unordered_map<int,std::string> &columnMap, std::unordered_map<int,int> &columnTypeMap);
2526

2627
/// Read shapefile, and create OutputObjects for all objects within the specified bounding box
27-
void readShapefile(std::string filename,
28+
void readShapefile(std::string filename,
2829
std::vector<std::string> &columns,
29-
Box &clippingBox,
30-
std::map< uint, std::vector<OutputObject> > &tileIndex,
31-
std::vector<Geometry> &cachedGeometries, std::map< uint, std::string > &cachedGeometryNames,
30+
Box &clippingBox,
31+
std::map< uint, std::vector<OutputObject> > &tileIndex,
32+
std::vector<Geometry> &cachedGeometries,
33+
OSMObject &osmObject,
3234
uint baseZoom, uint layerNum, std::string &layerName,
33-
bool isIndexed, std::map<std::string,RTree> &indices, std::string &indexName);
35+
bool isIndexed,
36+
std::string &indexName);
3437

3538
#endif //_READ_SHP_H
3639

src/osm_object.cpp

Lines changed: 42 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
#include "osm_object.h"
22
using namespace std;
3+
using namespace rapidjson;
34

45
// ---- initialization routines
56

@@ -15,7 +16,7 @@ OSMObject::OSMObject(kaguya::State *luaPtr, map< string, RTree> *idxPtr, vector<
1516
// Define a layer (as read from the .json file)
1617
uint OSMObject::addLayer(string name, uint minzoom, uint maxzoom,
1718
uint simplifyBelow, double simplifyLevel, double simplifyLength, double simplifyRatio, string writeTo) {
18-
LayerDef layer = { name, minzoom, maxzoom, simplifyBelow, simplifyLevel, simplifyLength, simplifyRatio };
19+
LayerDef layer = { name, minzoom, maxzoom, simplifyBelow, simplifyLevel, simplifyLength, simplifyRatio, std::map<std::string,uint>() };
1920
layers.push_back(layer);
2021
uint layerNum = layers.size()-1;
2122
layerMap[name] = layerNum;
@@ -256,19 +257,59 @@ void OSMObject::Attribute(const string &key, const string &val) {
256257
vector_tile::Tile_Value v;
257258
v.set_string_value(val);
258259
outputs[outputs.size()-1].addAttribute(key, v);
260+
setVectorLayerMetadata(outputs[outputs.size()-1].layer, key, 0);
259261
}
260262

261263
void OSMObject::AttributeNumeric(const string &key, const float val) {
262264
if (outputs.size()==0) { cerr << "Can't add Attribute " << key << " if no Layer set" << endl; return; }
263265
vector_tile::Tile_Value v;
264266
v.set_float_value(val);
265267
outputs[outputs.size()-1].addAttribute(key, v);
268+
setVectorLayerMetadata(outputs[outputs.size()-1].layer, key, 1);
266269
}
267270

268271
void OSMObject::AttributeBoolean(const string &key, const bool val) {
269272
if (outputs.size()==0) { cerr << "Can't add Attribute " << key << " if no Layer set" << endl; return; }
270273
vector_tile::Tile_Value v;
271274
v.set_bool_value(val);
272275
outputs[outputs.size()-1].addAttribute(key, v);
276+
setVectorLayerMetadata(outputs[outputs.size()-1].layer, key, 2);
273277
}
274278

279+
// Record attribute name/type for vector_layers table
280+
void OSMObject::setVectorLayerMetadata(const uint_least8_t layer, const string &key, const uint type) {
281+
layers[layer].attributeMap[key] = type;
282+
}
283+
std::string OSMObject::serialiseLayerJSON() {
284+
Document document;
285+
document.SetObject();
286+
Document::AllocatorType& allocator = document.GetAllocator();
287+
288+
Value layerArray(kArrayType);
289+
for (auto it = layers.begin(); it != layers.end(); ++it) {
290+
Value fieldObj(kObjectType);
291+
for (auto jt = it->attributeMap.begin(); jt != it->attributeMap.end(); ++jt) {
292+
Value k(jt->first.c_str(), allocator);
293+
switch (jt->second) {
294+
case 0: fieldObj.AddMember(k, "String" , allocator); break;
295+
case 1: fieldObj.AddMember(k, "Number" , allocator); break;
296+
case 2: fieldObj.AddMember(k, "Boolean", allocator); break;
297+
}
298+
}
299+
Value layerObj(kObjectType);
300+
Value name(it->name.c_str(), allocator);
301+
layerObj.AddMember("id", name, allocator);
302+
layerObj.AddMember("fields", fieldObj, allocator);
303+
layerObj.AddMember("minzoom", it->minzoom, allocator);
304+
layerObj.AddMember("maxzoom", it->maxzoom, allocator);
305+
layerArray.PushBack(layerObj, allocator);
306+
}
307+
308+
document.AddMember("vector_layers", layerArray, allocator);
309+
310+
StringBuffer buffer;
311+
Writer<StringBuffer> writer(buffer);
312+
document.Accept(writer);
313+
string json(buffer.GetString(), buffer.GetSize());
314+
return json;
315+
}

src/read_shp.cpp

Lines changed: 28 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -64,15 +64,26 @@ void addToTileIndexPolyline(OutputObject &oo, map< uint, vector<OutputObject> >
6464
}
6565

6666
// Read requested attributes from a shapefile, and encode into an OutputObject
67-
void addShapefileAttributes(DBFHandle &dbf, OutputObject &oo, int recordNum, unordered_map<int,string> &columnMap, unordered_map<int,int> &columnTypeMap) {
67+
void addShapefileAttributes(
68+
DBFHandle &dbf,
69+
OutputObject &oo,
70+
int recordNum, unordered_map<int,string> &columnMap, unordered_map<int,int> &columnTypeMap,
71+
OSMObject &osmObject) {
72+
6873
for (auto it : columnMap) {
6974
int pos = it.first;
7075
string key = it.second;
7176
vector_tile::Tile_Value v;
7277
switch (columnTypeMap[pos]) {
73-
case 1: v.set_int_value(DBFReadIntegerAttribute(dbf, recordNum, pos)); break;
74-
case 2: v.set_double_value(DBFReadDoubleAttribute(dbf, recordNum, pos)); break;
75-
default: v.set_string_value(DBFReadStringAttribute(dbf, recordNum, pos)); break;
78+
case 1: v.set_int_value(DBFReadIntegerAttribute(dbf, recordNum, pos));
79+
osmObject.setVectorLayerMetadata(oo.layer, key, 1);
80+
break;
81+
case 2: v.set_double_value(DBFReadDoubleAttribute(dbf, recordNum, pos));
82+
osmObject.setVectorLayerMetadata(oo.layer, key, 1);
83+
break;
84+
default: v.set_string_value(DBFReadStringAttribute(dbf, recordNum, pos));
85+
osmObject.setVectorLayerMetadata(oo.layer, key, 3);
86+
break;
7687
}
7788
oo.addAttribute(key, v);
7889
}
@@ -84,9 +95,11 @@ void readShapefile(string filename,
8495
vector<string> &columns,
8596
Box &clippingBox,
8697
map< uint, vector<OutputObject> > &tileIndex,
87-
vector<Geometry> &cachedGeometries, map< uint, string > &cachedGeometryNames,
98+
vector<Geometry> &cachedGeometries,
99+
OSMObject &osmObject,
88100
uint baseZoom, uint layerNum, string &layerName,
89-
bool isIndexed, map<string,RTree> &indices, string &indexName) {
101+
bool isIndexed,
102+
string &indexName) {
90103

91104
// open shapefile
92105
SHPHandle shp = SHPOpen(filename.c_str(), "rb");
@@ -124,12 +137,12 @@ void readShapefile(string filename,
124137
uint tiley = latp2tiley(p.y(), baseZoom);
125138
cachedGeometries.push_back(p);
126139
OutputObject oo(CACHED_POINT, layerNum, cachedGeometries.size()-1);
127-
addShapefileAttributes(dbf,oo,i,columnMap,columnTypeMap);
140+
addShapefileAttributes(dbf,oo,i,columnMap,columnTypeMap,osmObject);
128141
tileIndex[tilex*65536+tiley].push_back(oo);
129142
if (isIndexed) {
130143
uint id = cachedGeometries.size()-1;
131-
geom::envelope(p, box); indices[layerName].insert(std::make_pair(box, id));
132-
if (indexField>-1) { cachedGeometryNames[id]=DBFReadStringAttribute(dbf, i, indexField); }
144+
geom::envelope(p, box); osmObject.indices->at(layerName).insert(std::make_pair(box, id));
145+
if (indexField>-1) { osmObject.cachedGeometryNames->operator[](id)=DBFReadStringAttribute(dbf, i, indexField); }
133146
}
134147
}
135148

@@ -146,12 +159,12 @@ void readShapefile(string filename,
146159
for (MultiLinestring::const_iterator it = out.begin(); it != out.end(); ++it) {
147160
cachedGeometries.push_back(*it);
148161
OutputObject oo(CACHED_LINESTRING, layerNum, cachedGeometries.size()-1);
149-
addShapefileAttributes(dbf,oo,i,columnMap,columnTypeMap);
162+
addShapefileAttributes(dbf,oo,i,columnMap,columnTypeMap,osmObject);
150163
addToTileIndexPolyline(oo, tileIndex, baseZoom, *it);
151164
if (isIndexed) {
152165
uint id = cachedGeometries.size()-1;
153-
geom::envelope(*it, box); indices[layerName].insert(std::make_pair(box, id));
154-
if (indexField>-1) { cachedGeometryNames[id]=DBFReadStringAttribute(dbf, i, indexField); }
166+
geom::envelope(*it, box); osmObject.indices->at(layerName).insert(std::make_pair(box, id));
167+
if (indexField>-1) { osmObject.cachedGeometryNames->operator[](id)=DBFReadStringAttribute(dbf, i, indexField); }
155168
}
156169
}
157170
}
@@ -212,15 +225,15 @@ void readShapefile(string filename,
212225
// create OutputObject
213226
cachedGeometries.push_back(out);
214227
OutputObject oo(CACHED_POLYGON, layerNum, cachedGeometries.size()-1);
215-
addShapefileAttributes(dbf,oo,i,columnMap,columnTypeMap);
228+
addShapefileAttributes(dbf,oo,i,columnMap,columnTypeMap,osmObject);
216229
// add to tile index
217230
geom::model::box<Point> box;
218231
geom::envelope(out, box);
219232
addToTileIndexByBbox(oo, tileIndex, baseZoom, box.min_corner().get<0>(), box.min_corner().get<1>(), box.max_corner().get<0>(), box.max_corner().get<1>());
220233
if (isIndexed) {
221234
uint id = cachedGeometries.size()-1;
222-
indices[layerName].insert(std::make_pair(box, id));
223-
if (indexField>-1) { cachedGeometryNames[id]=DBFReadStringAttribute(dbf, i, indexField); }
235+
osmObject.indices->at(layerName).insert(std::make_pair(box, id));
236+
if (indexField>-1) { osmObject.cachedGeometryNames->operator[](id)=DBFReadStringAttribute(dbf, i, indexField); }
224237
}
225238
}
226239

src/shared_data.cpp

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -108,7 +108,10 @@ class SharedData
108108
}
109109
string indexName = it->value.HasMember("index_column") ? it->value["index_column"].GetString() : "";
110110
readShapefile(it->value["source"].GetString(), sourceColumns, clippingBox, tileIndex,
111-
cachedGeometries, *osmObject.cachedGeometryNames, baseZoom, layerNum, layerName, indexed, *osmObject.indices, indexName);
111+
cachedGeometries,
112+
osmObject,
113+
baseZoom, layerNum, layerName, indexed,
114+
indexName);
112115
}
113116
}
114117
}

src/tilemaker.cpp

Lines changed: 25 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -433,19 +433,6 @@ int main(int argc, char* argv[]) {
433433
sharedData.mbtiles.writeMetadata("bounds",bounds.str());
434434
sharedData.mbtiles.writeMetadata("minzoom",to_string(sharedData.startZoom));
435435
sharedData.mbtiles.writeMetadata("maxzoom",to_string(sharedData.endZoom));
436-
if (jsonConfig["settings"].HasMember("metadata")) {
437-
const rapidjson::Value &md = jsonConfig["settings"]["metadata"];
438-
for(rapidjson::Value::ConstMemberIterator it=md.MemberBegin(); it != md.MemberEnd(); ++it) {
439-
if (it->value.IsString()) {
440-
sharedData.mbtiles.writeMetadata(it->name.GetString(), it->value.GetString());
441-
} else {
442-
rapidjson::StringBuffer strbuf;
443-
rapidjson::Writer<rapidjson::StringBuffer> writer(strbuf);
444-
it->value.Accept(writer);
445-
sharedData.mbtiles.writeMetadata(it->name.GetString(), strbuf.GetString());
446-
}
447-
}
448-
}
449436
}
450437

451438
// ---- Read all PBFs
@@ -804,10 +791,32 @@ int main(int argc, char* argv[]) {
804791
sharedData.tileIndexForZoom = nullptr;
805792
}
806793

807-
cout << endl << "Filled the tileset with good things at " << sharedData.outputFile << endl;
808-
if (sqlite) { sharedData.mbtiles.close(); }
794+
// ---- Close tileset
795+
796+
if (sqlite) {
797+
// Write mbtiles 1.3+ json object
798+
sharedData.mbtiles.writeMetadata("json", sharedData.osmObject.serialiseLayerJSON());
799+
800+
// Write user-defined metadata
801+
if (jsonConfig["settings"].HasMember("metadata")) {
802+
const rapidjson::Value &md = jsonConfig["settings"]["metadata"];
803+
for(rapidjson::Value::ConstMemberIterator it=md.MemberBegin(); it != md.MemberEnd(); ++it) {
804+
if (it->value.IsString()) {
805+
sharedData.mbtiles.writeMetadata(it->name.GetString(), it->value.GetString());
806+
} else {
807+
rapidjson::StringBuffer strbuf;
808+
rapidjson::Writer<rapidjson::StringBuffer> writer(strbuf);
809+
it->value.Accept(writer);
810+
sharedData.mbtiles.writeMetadata(it->name.GetString(), strbuf.GetString());
811+
}
812+
}
813+
}
814+
sharedData.mbtiles.close();
815+
}
809816
google::protobuf::ShutdownProtobufLibrary();
810817

811-
// ---- Call exit_function of Lua logic
818+
// Call exit_function of Lua logic
812819
luaState("if exit_function~=nil then exit_function() end");
820+
821+
cout << endl << "Filled the tileset with good things at " << sharedData.outputFile << endl;
813822
}

0 commit comments

Comments
 (0)