Skip to content
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

Optimize tile sizes #112

Merged
merged 1 commit into from
Sep 25, 2023
Merged
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
5 changes: 4 additions & 1 deletion src/main/java/org/openmaptiles/layers/Building.java
Original file line number Diff line number Diff line change
Expand Up @@ -178,7 +178,10 @@ public void process(Tables.OsmBuildingPolygon element, FeatureCollector features
@Override
public List<VectorTile.Feature> postProcess(int zoom,
List<VectorTile.Feature> items) throws GeometryException {
return (mergeZ13Buildings && zoom == 13) ? FeatureMerge.mergeNearbyPolygons(items, 4, 4, 0.5, 0.5) : items;
return (mergeZ13Buildings && zoom == 13) ?
FeatureMerge.mergeNearbyPolygons(items, 4, 4, 0.5, 0.5) :
// reduces the size of some heavy z14 tiles with many small buildings by 60% or more
FeatureMerge.mergeMultiPolygon(items);
}

private record BuildingRelationInfo(long id) implements OsmRelationInfo {
Expand Down
14 changes: 13 additions & 1 deletion src/main/java/org/openmaptiles/layers/Housenumber.java
Original file line number Diff line number Diff line change
Expand Up @@ -36,9 +36,14 @@ OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
package org.openmaptiles.layers;

import com.onthegomap.planetiler.FeatureCollector;
import com.onthegomap.planetiler.FeatureMerge;
import com.onthegomap.planetiler.ForwardingProfile;
import com.onthegomap.planetiler.VectorTile;
import com.onthegomap.planetiler.config.PlanetilerConfig;
import com.onthegomap.planetiler.geo.GeometryException;
import com.onthegomap.planetiler.stats.Stats;
import com.onthegomap.planetiler.util.Translations;
import java.util.List;
import org.openmaptiles.generated.OpenMapTilesSchema;
import org.openmaptiles.generated.Tables;

Expand All @@ -51,7 +56,8 @@ OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
*/
public class Housenumber implements
OpenMapTilesSchema.Housenumber,
Tables.OsmHousenumberPoint.Handler {
Tables.OsmHousenumberPoint.Handler,
ForwardingProfile.FeaturePostProcessor {

public Housenumber(Translations translations, PlanetilerConfig config, Stats stats) {}

Expand All @@ -62,4 +68,10 @@ public void process(Tables.OsmHousenumberPoint element, FeatureCollector feature
.setAttr(Fields.HOUSENUMBER, element.housenumber())
.setMinZoom(14);
}

@Override
public List<VectorTile.Feature> postProcess(int zoom, List<VectorTile.Feature> list) throws GeometryException {
// reduces the size of some heavy z14 tiles with many repeated housenumber values by 60% or more
return FeatureMerge.mergeMultiPoint(list);
}
}
2 changes: 2 additions & 0 deletions src/main/java/org/openmaptiles/layers/Landcover.java
Original file line number Diff line number Diff line change
Expand Up @@ -125,6 +125,8 @@ public void process(Tables.OsmLandcoverPolygon element, FeatureCollector feature
if (clazz != null) {
features.polygon(LAYER_NAME).setBufferPixels(BUFFER_SIZE)
.setMinPixelSizeOverrides(MIN_PIXEL_SIZE_THRESHOLDS)
// default is 0.1, this helps reduce size of some heavy z7-10 tiles
.setPixelToleranceBelowZoom(10, 0.25)
.setAttr(Fields.CLASS, clazz)
.setAttr(Fields.SUBCLASS, subclass)
.setNumPointsAttr(TEMP_NUM_POINTS_ATTR)
Expand Down
29 changes: 15 additions & 14 deletions src/main/java/org/openmaptiles/layers/Landuse.java
Original file line number Diff line number Diff line change
Expand Up @@ -48,10 +48,10 @@ OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
import com.onthegomap.planetiler.util.Parse;
import com.onthegomap.planetiler.util.Translations;
import com.onthegomap.planetiler.util.ZoomFunction;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.stream.Collectors;
import org.openmaptiles.OpenMapTilesProfile;
import org.openmaptiles.generated.OpenMapTilesSchema;
import org.openmaptiles.generated.Tables;
Expand Down Expand Up @@ -126,19 +126,20 @@ public void process(Tables.OsmLandusePolygon element, FeatureCollector features)
@Override
public List<VectorTile.Feature> postProcess(int zoom,
List<VectorTile.Feature> items) throws GeometryException {
if (zoom < 6 || zoom > 12) {
return items;
} else {
// merging only merges polygons with class "residential" for z6-z12
Map<Boolean, List<VectorTile.Feature>> splitLists =
items.stream().collect(Collectors.partitioningBy(
i -> FieldValues.CLASS_RESIDENTIAL.equals(i.attrs().get(Fields.CLASS)))
);
List<VectorTile.Feature> result = splitLists.get(Boolean.FALSE);
List<VectorTile.Feature> toMerge = splitLists.get(Boolean.TRUE);
var merged = FeatureMerge.mergeNearbyPolygons(toMerge, 1, 1, 0.1, 0.1);
result.addAll(merged);
return result;
List<VectorTile.Feature> toMerge = new ArrayList<>();
List<VectorTile.Feature> result = new ArrayList<>();
for (var item : items) {
if (FieldValues.CLASS_RESIDENTIAL.equals(item.attrs().get(Fields.CLASS))) {
toMerge.add(item);
} else {
result.add(item);
}
}
var merged = zoom <= 12 ?
FeatureMerge.mergeNearbyPolygons(toMerge, 1, 1, 0.1, 0.1) :
// reduces size of some heavy z13-14 tiles with lots of small polygons
FeatureMerge.mergeMultiPolygon(toMerge);
result.addAll(merged);
return result;
}
}
2 changes: 2 additions & 0 deletions src/main/java/org/openmaptiles/layers/Place.java
Original file line number Diff line number Diff line change
Expand Up @@ -267,6 +267,8 @@ public void process(Tables.OsmStatePoint element, FeatureCollector features) {
.putAttrs(names)
.setAttr(Fields.CLASS, element.place())
.setAttr(Fields.RANK, rank)
// TODO: This starts including every "state" point at z2, even before many countries show up.
// Instead we might want to set state min zooms based on rank from natural earth?
.setMinZoom(2)
.setSortKey(rank);
}
Expand Down
4 changes: 3 additions & 1 deletion src/main/java/org/openmaptiles/layers/Transportation.java
Original file line number Diff line number Diff line change
Expand Up @@ -361,8 +361,10 @@ public void process(Tables.OsmHighwayLinestring element, FeatureCollector featur
// main attributes at all zoom levels (used for grouping <= z8)
.setAttr(Fields.CLASS, highwayClass)
.setAttr(Fields.SUBCLASS, highwaySubclass(highwayClass, element.publicTransport(), highway))
.setAttr(Fields.BRUNNEL, brunnel(element.isBridge(), element.isTunnel(), element.isFord()))
.setAttr(Fields.NETWORK, networkType != null ? networkType.name : null)
// TODO: including brunnel at low zooms leads to some large 300-400+kb z4-7 tiles, instead
// we should only set brunnel if the line is above a certain length
.setAttr(Fields.BRUNNEL, brunnel(element.isBridge(), element.isTunnel(), element.isFord()))
// z8+
.setAttrWithMinzoom(Fields.EXPRESSWAY, element.expressway() && !"motorway".equals(highway) ? 1 : null, 8)
// z9+
Expand Down
3 changes: 2 additions & 1 deletion src/test/java/org/openmaptiles/OpenMapTilesTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@

import com.onthegomap.planetiler.TestUtils;
import com.onthegomap.planetiler.VectorTile;
import com.onthegomap.planetiler.archive.Tile;
import com.onthegomap.planetiler.config.Arguments;
import com.onthegomap.planetiler.mbtiles.Mbtiles;
import com.onthegomap.planetiler.util.FileUtils;
Expand Down Expand Up @@ -91,7 +92,7 @@ void testMetadata() {

@Test
void ensureValidGeometries() throws Exception {
Set<Mbtiles.TileEntry> parsedTiles = TestUtils.getAllTiles(mbtiles);
Set<Tile> parsedTiles = TestUtils.getTiles(mbtiles);
for (var tileEntry : parsedTiles) {
var decoded = VectorTile.decode(gunzip(tileEntry.bytes()));
for (VectorTile.Feature feature : decoded) {
Expand Down
13 changes: 12 additions & 1 deletion src/test/java/org/openmaptiles/layers/BuildingTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -143,13 +143,24 @@ void testMergePolygonsZ13() throws GeometryException {
);

Assertions.assertEquals(
2,
1, // merged into 1 multipolygon
profile.postProcessLayerFeatures(Building.LAYER_NAME, 14, List.of(poly1, poly2)).size()
);

Assertions.assertEquals(
2, // merged into 1 multipolygon
profile.postProcessLayerFeatures(Building.LAYER_NAME, 14, List.of(poly1, poly2)).get(0).geometry().decode()
.getNumGeometries()
);
Assertions.assertEquals(
1,
profile.postProcessLayerFeatures(Building.LAYER_NAME, 13, List.of(poly1, poly2)).size()
);
Assertions.assertEquals(
1,
profile.postProcessLayerFeatures(Building.LAYER_NAME, 13, List.of(poly1, poly2)).get(0).geometry().decode()
.getNumGeometries()
);
}

@Test
Expand Down
22 changes: 18 additions & 4 deletions src/test/java/org/openmaptiles/layers/LanduseTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -120,12 +120,26 @@ void testMergePolygonsZ12() throws GeometryException {
);

Assertions.assertEquals(
3,
profile.postProcessLayerFeatures(Landuse.LAYER_NAME, 13, List.of(poly1, poly2, poly3)).size()
List.of(1, 2),
profile.postProcessLayerFeatures(Landuse.LAYER_NAME, 13, List.of(poly1, poly2, poly3)).stream()
.map(d -> {
try {
return d.geometry().decode().getNumGeometries();
} catch (GeometryException e) {
throw new AssertionError(e);
}
}).toList()
);
Assertions.assertEquals(
2,
profile.postProcessLayerFeatures(Landuse.LAYER_NAME, 12, List.of(poly1, poly2, poly3)).size()
List.of(1, 1),
profile.postProcessLayerFeatures(Landuse.LAYER_NAME, 12, List.of(poly1, poly2, poly3)).stream()
.map(d -> {
try {
return d.geometry().decode().getNumGeometries();
} catch (GeometryException e) {
throw new AssertionError(e);
}
}).toList()
);
}
}
2 changes: 1 addition & 1 deletion src/test/java/org/openmaptiles/util/VerifyMonacoTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ void testEmptyTablesInvalid() {
}

@Test
void testStilInvalidWithOneTile() throws IOException {
void testStillInvalidWithOneTile() throws IOException {
mbtiles.createTablesWithIndexes();
mbtiles.metadataTable().setMetadata("name", "name");
try (var writer = mbtiles.newBatchedTileWriter()) {
Expand Down
Loading