Skip to content

Commit ea8d215

Browse files
systemedetienneJr
andauthored
Allow combine_lines_below on each layer (#850)
Co-authored-by: Etilène Jourdier <[email protected]>
1 parent 80f53f3 commit ea8d215

File tree

5 files changed

+25
-19
lines changed

5 files changed

+25
-19
lines changed

README.md

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -128,11 +128,13 @@ Bug reports, suggestions and (especially!) pull requests are very welcome on the
128128

129129
Formatting: braces and indents as shown, hard tabs (4sp). (Yes, I know.) Please be conservative about adding dependencies or increasing the memory requirement.
130130

131+
The Makefile does not currently pick up changes to header files (.h). If you change these, you may need to run `make clean` before building with `make` and `sudo make install`.
132+
131133
## Copyright
132134

133135
tilemaker is maintained by Richard Fairhurst and supported by [many contributors](https://github.com/systemed/tilemaker/graphs/contributors). We particularly celebrate the invaluable contributions of Wouter van Kleunen, who passed away in 2022.
134136

135-
Copyright tilemaker contributors, 2015-2024.
137+
Copyright tilemaker contributors, 2015-2025.
136138

137139
The tilemaker code is licensed as FTWPL; you may do anything you like with this code and there is no warranty.
138140

docs/CONFIGURATION.md

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -33,12 +33,12 @@ It also includes these global settings:
3333
* `basezoom` - the zoom level for which tilemaker will generate tiles internally (should usually be the same as `maxzoom`)
3434
* `include_ids` - whether you want to store the OpenStreetMap IDs for each way/node within your vector tiles. This option is not compatible with the merging options defined by the `combine_xxx` settings (see the dedicated paragraph below)
3535
* `compress` - for mbtiles output, whether to compress vector tiles (Any of "gzip","deflate" or "none"(default)). For pmtiles output, compression is hardcoded to gzip
36-
* `combine_below` - whether to merge adjacent linestrings of the same type: will be done at zoom levels below that specified here (e.g. `"combine_below": 14` to merge at z1-13)
3736
* `name`, `version` and `description` - about your project (these are written into the MBTiles file)
3837
* `high_resolution` (optional) - whether to use extra coordinate precision at the maximum zoom level (makes tiles a bit bigger)
3938
* `bounding_box` (optional) - the bounding box to output, in [minlon, minlat, maxlon, maxlat] order
4039
* `default_view` (optional) - the default location for the client to view, in [lon, lat, zoom] order (MBTiles only)
4140
* `mvt_version` (optional) - the version of the [Mapbox Vector Tile](https://github.com/mapbox/vector-tile-spec) spec to use; defaults to 2
41+
* `combine_below` (deprecated) - whether to merge all linestrings in the tile with the same attributes: will be done at zoom levels below that specified here (e.g. `"combine_below": 14` to merge at z1-13). Please use the layer-specific parameter `combine_lines_below` instead.
4242

4343
A typical config file would look like this:
4444

@@ -83,6 +83,7 @@ You can add optional parameters to layers:
8383
* `feature_limit` - restrict the number of features written to each tile
8484
* `feature_limit_below` - restrict only below this zoom level
8585
* `combine_polygons_below` - merge adjacent polygons with the same attributes below this zoom level
86+
* `combine_lines_below` - whether to merge all linestrings in the tile with the same attributes. If not defined, the global setting `combine_below` will be used.
8687
* `combine_points` - merge points with the same attributes (defaults to `true`: specify `false` to disable)
8788
* `z_order_ascending` - sort features in ascending order by a numeric value set in the Lua processing script (defaults to `true`: specify `false` for descending order)
8889

@@ -118,12 +119,14 @@ For example:
118119

119120
### Including IDs
120121

121-
Be careful when using both the `include_ids: true` setting to include IDs and the `combine_xxx` settings to lighten tiles : they are not compatible. During the merging process, items with identical tags are combined in a collection, with only 1 ID being retained for all the merged items. If you need to have the exact ID for each item (for example, for a clickable map), you need to remove the merging settings in the target levels and layers:
122+
You can carry the original OpenStreetMap object ID through to each vector tile feature with the global `include_ids` option.
123+
124+
Note that this is not compatible with the `combine_xxx` settings to reduce tilesize. These settings merge items with identical tags into a collection, so only one ID will be retained for all the merged items. If you need to have the exact ID for each item, remove the merging settings in the target levels and layers:
122125

123126
* set `combine_points: false` (`true` is the default value) in the target layers
124-
* set `combine_below` and `combine_polygons_below` below the target zoom level (or remove them)
127+
* set `combine_lines_below` and `combine_polygons_below` in layer properties below the target zoom level (or remove them)
125128

126-
If you need the include OSM types as well, you will need to modify the `process.lua` script, check issue [#740](https://github.com/systemed/tilemaker/issues/740) for more information.
129+
If you need to include OSM object types as well, you can use the `OsmType()` function in your `process.lua` script.
127130

128131
## Lua processing reference
129132

@@ -163,7 +166,7 @@ To do that, you use these methods:
163166
* `OsmType()`: get the OSM type of the current object.
164167
* `IsClosed()`: returns true if the current object is a closed area.
165168
* `IsMultiPolygon()`: returns true if the current object is a multipolygon.
166-
* `ZOrder(number)`: Set a numeric value (default 0) used to sort features within a layer. Use this feature to ensure a proper rendering order if the rendering engine itself does not support sorting. Sorting is not supported across layers merged with `write_to`. Features with different z-order are not merged if `combine_below` or `combine_polygons_below` is used. Use this in conjunction with `feature_limit` to only write the most important (highest z-order) features within a tile. (Values can be -50,000,000 to 50,000,000 and are lossy, particularly beyond -1000 to 1000.)
169+
* `ZOrder(number)`: Set a numeric value (default 0) used to sort features within a layer. Use this feature to ensure a proper rendering order if the rendering engine itself does not support sorting. Sorting is not supported across layers merged with `write_to`. Features with different z-order are not merged if `combine_below`, `combine_lines_below` or `combine_polygons_below` is used. Use this in conjunction with `feature_limit` to only write the most important (highest z-order) features within a tile. (Values can be -50,000,000 to 50,000,000 and are lossy, particularly beyond -1000 to 1000.)
167170
* `MinZoom(zoom)`: set the minimum zoom level (0-15) at which this object will be written. Note that the JSON layer configuration minimum still applies (so `:MinZoom(5)` will have no effect if your layer only starts at z6).
168171
* `Length()` and `Area()`: return the length (metres)/area (square metres) of the current object. Requires Boost 1.67+.
169172
* `Centroid()`: return the lat/lon of the centre of the current object as a two-element Lua table (element 1 is lat, 2 is lon).

include/shared_data.h

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -26,11 +26,12 @@ struct LayerDef {
2626
uint simplifyAlgo;
2727
uint filterBelow;
2828
double filterArea;
29-
uint combinePolygonsBelow;
3029
bool sortZOrderAscending;
3130
uint featureLimit;
3231
uint featureLimitBelow;
3332
bool combinePoints;
33+
uint combineLinesBelow;
34+
uint combinePolygonsBelow;
3435
std::string source;
3536
std::vector<std::string> sourceColumns;
3637
bool allSourceColumns;
@@ -58,8 +59,8 @@ class LayerDefinition {
5859
// Define a layer (as read from the .json file)
5960
uint addLayer(std::string name, uint minzoom, uint maxzoom,
6061
uint simplifyBelow, double simplifyLevel, double simplifyLength, double simplifyRatio, uint simplifyAlgo,
61-
uint filterBelow, double filterArea, uint combinePolygonsBelow, bool sortZOrderAscending,
62-
uint featureLimit, uint featureLimitBelow, bool combinePoints,
62+
uint filterBelow, double filterArea, bool sortZOrderAscending,
63+
uint featureLimit, uint featureLimitBelow, bool combinePoints, uint combineLinesBelow, uint combinePolygonsBelow,
6364
const std::string &source,
6465
const std::vector<std::string> &sourceColumns,
6566
bool allSourceColumns,

src/shared_data.cpp

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -139,8 +139,8 @@ void SharedData::writePMTilesBounds() {
139139
// Define a layer (as read from the .json file)
140140
uint LayerDefinition::addLayer(string name, uint minzoom, uint maxzoom,
141141
uint simplifyBelow, double simplifyLevel, double simplifyLength, double simplifyRatio, uint simplifyAlgo,
142-
uint filterBelow, double filterArea, uint combinePolygonsBelow, bool sortZOrderAscending,
143-
uint featureLimit, uint featureLimitBelow, bool combinePoints,
142+
uint filterBelow, double filterArea, bool sortZOrderAscending,
143+
uint featureLimit, uint featureLimitBelow, bool combinePoints, uint combineLinesBelow, uint combinePolygonsBelow,
144144
const std::string &source,
145145
const std::vector<std::string> &sourceColumns,
146146
bool allSourceColumns,
@@ -150,7 +150,7 @@ uint LayerDefinition::addLayer(string name, uint minzoom, uint maxzoom,
150150

151151
bool isWriteTo = !writeTo.empty();
152152
LayerDef layer = { name, minzoom, maxzoom, simplifyBelow, simplifyLevel, simplifyLength, simplifyRatio, simplifyAlgo,
153-
filterBelow, filterArea, combinePolygonsBelow, sortZOrderAscending, featureLimit, featureLimitBelow, combinePoints,
153+
filterBelow, filterArea, sortZOrderAscending, featureLimit, featureLimitBelow, combinePoints, combineLinesBelow, combinePolygonsBelow,
154154
source, sourceColumns, allSourceColumns, indexed, indexName,
155155
std::map<std::string,uint>(), isWriteTo };
156156
layers.push_back(layer);
@@ -317,10 +317,11 @@ void Config::readConfig(rapidjson::Document &jsonConfig, bool &hasClippingBox, B
317317
double simplifyRatio = it->value.HasMember("simplify_ratio" ) ? it->value["simplify_ratio" ].GetDouble() : 2.0;
318318
int filterBelow = it->value.HasMember("filter_below" ) ? it->value["filter_below" ].GetInt() : 0;
319319
double filterArea = it->value.HasMember("filter_area" ) ? it->value["filter_area" ].GetDouble() : 0.5;
320-
int combinePolyBelow=it->value.HasMember("combine_polygons_below") ? it->value["combine_polygons_below"].GetInt() : 0;
321320
int featureLimit = it->value.HasMember("feature_limit" ) ? it->value["feature_limit" ].GetInt() : 0;
322321
int featureLimitBelow= it->value.HasMember("feature_limit_below") ? it->value["feature_limit_below"].GetInt() : (maxZoom+1);
323322
bool combinePoints = it->value.HasMember("combine_points" ) ? it->value["combine_points" ].GetBool() : true;
323+
int combineLinesBelow = it->value.HasMember("combine_lines_below" ) ? it->value["combine_lines_below" ].GetInt() : combineBelow;
324+
int combinePolyBelow=it->value.HasMember("combine_polygons_below") ? it->value["combine_polygons_below"].GetInt() : 0;
324325
bool sortZOrderAscending = it->value.HasMember("z_order_ascending") ? it->value["z_order_ascending"].GetBool() : (featureLimit==0);
325326
string algo = it->value.HasMember("simplify_algorithm") ? it->value["simplify_algorithm"].GetString() : "";
326327
uint simplifyAlgo = algo=="visvalingam" ? LayerDef::VISVALINGAM : LayerDef::DOUGLAS_PEUCKER;
@@ -343,7 +344,7 @@ void Config::readConfig(rapidjson::Document &jsonConfig, bool &hasClippingBox, B
343344

344345
layers.addLayer(layerName, minZoom, maxZoom,
345346
simplifyBelow, simplifyLevel, simplifyLength, simplifyRatio, simplifyAlgo,
346-
filterBelow, filterArea, combinePolyBelow, sortZOrderAscending, featureLimit, featureLimitBelow, combinePoints,
347+
filterBelow, filterArea, sortZOrderAscending, featureLimit, featureLimitBelow, combinePoints, combineLinesBelow, combinePolyBelow,
347348
source, sourceColumns, allSourceColumns, indexed, indexName,
348349
writeTo);
349350

src/tile_worker.cpp

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -277,13 +277,13 @@ void ProcessObjects(
277277
double simplifyLevel,
278278
unsigned simplifyAlgo,
279279
double filterArea,
280-
bool combinePolygons,
281280
bool combinePoints,
281+
bool combineLines,
282+
bool combinePolygons,
282283
unsigned zoom,
283284
const TileBbox &bbox,
284285
vtzero::layer_builder& vtLayer
285286
) {
286-
287287
for (auto jt = ooSameLayerBegin; jt != ooSameLayerEnd; ++jt) {
288288
OutputObjectID oo = *jt;
289289
if (zoom < oo.oo.minZoom) { continue; }
@@ -330,7 +330,7 @@ void ProcessObjects(
330330
}
331331

332332
//This may increment the jt iterator
333-
if (oo.oo.geomType == LINESTRING_ && zoom < sharedData.config.combineBelow) {
333+
if (oo.oo.geomType == LINESTRING_ && combineLines) {
334334
// Append successive linestrings, then reorder afterwards
335335
while (jt<(ooSameLayerEnd-1) && oo.oo.compatible((jt+1)->oo)) {
336336
jt++;
@@ -440,7 +440,6 @@ void ProcessLayer(
440440
if (zoom < ld.filterBelow) {
441441
filterArea = meter2degp(ld.filterArea, latp) * pow(2.0, (ld.filterBelow-1) - zoom);
442442
}
443-
444443
for (size_t i=0; i<sources.size(); i++) {
445444
// Loop through output objects
446445
auto ooListSameLayer = getObjectsAtSubLayer(data[i], layerNum);
@@ -449,7 +448,7 @@ void ProcessLayer(
449448
ProcessObjects(sources[i], attributeStore,
450449
ooListSameLayer.first, end, sharedData,
451450
simplifyLevel, ld.simplifyAlgo,
452-
filterArea, zoom < ld.combinePolygonsBelow, ld.combinePoints, zoom, bbox, vtLayer);
451+
filterArea, ld.combinePoints, zoom < ld.combineLinesBelow, zoom < ld.combinePolygonsBelow, zoom, bbox, vtLayer);
453452
}
454453
}
455454
if (verbose && std::time(0)-start>3) {

0 commit comments

Comments
 (0)