Skip to content

Commit

Permalink
add new mapcss property to influence "small features" rendering
Browse files Browse the repository at this point in the history
the property `render` can have (currently) one of three values:

* `auto` (default): line or area features are rendered as points on "low" zoom levels (if not disabled globally in settings)
* `native`: line or area features are always rendered with their "native" geometries (and never compressed to points)
* `point`: all features are always rendered as points (e.g. in the centroid of the corresponding area)
  • Loading branch information
tyrasd committed Oct 18, 2023
1 parent 625aea0 commit a97a885
Show file tree
Hide file tree
Showing 3 changed files with 29 additions and 13 deletions.
17 changes: 13 additions & 4 deletions js/GeoJsonNoVanish.ts
Original file line number Diff line number Diff line change
Expand Up @@ -26,8 +26,12 @@ class GeoJsonNoVanish extends L.GeoJSON {
this.eachLayer(function (o) {
if (!o.feature || !o.feature.geometry) return; // skip invalid layers
if (o.feature.geometry.type == "Point" && !o.obj) return; // skip node features
const compress =
this.options.compress &&
this.options.compress(o.obj ? o.obj.feature : o.feature);
const crs = this._map.options.crs;
if (o.obj) {
if (compress === "point") return;
// already compressed feature
const bounds = o.obj.getBounds();
const p1 = crs.latLngToPoint(bounds.getSouthWest(), o._map.getZoom());
Expand All @@ -43,14 +47,19 @@ class GeoJsonNoVanish extends L.GeoJSON {
}
return;
}
if (is_max_zoom) return; // do not compress objects at max zoom
if (this.options.compress && !this.options.compress(o.feature)) return;
if (is_max_zoom && compress !== "point") return; // do not compress objects at max zoom, except if mapcss says always to render as points
if (compress === "native") return; // do not compress if mapcss specifies not to
const bounds = o.getBounds();
const p1 = crs.latLngToPoint(bounds.getSouthWest(), o._map.getZoom());
const p2 = crs.latLngToPoint(bounds.getNorthEast(), o._map.getZoom());
const d = Math.pow(p1.x - p2.x, 2) + Math.pow(p1.y - p2.y, 2);
if (d > Math.pow(this.threshold, 2)) return;
const center = bounds.getCenter();
if (d > Math.pow(this.threshold, 2) && compress !== "point") return;
let center;
if (d <= Math.pow(this.threshold, 2)) {
center = bounds.getCenter();
} else {
center = o.getCenter();
}
const f = L.extend({}, o.feature);
f.is_placeholder = true;
f.geometry = {
Expand Down
4 changes: 3 additions & 1 deletion js/jsmapcss/Style.ts
Original file line number Diff line number Diff line change
Expand Up @@ -158,7 +158,8 @@ styleparser.ShapeStyle.prototype = {
"casing_color",
"casing_opacity",
"casing_dashes",
"layer"
"layer",
"render"
],

width: 0,
Expand All @@ -176,6 +177,7 @@ styleparser.ShapeStyle.prototype = {
casing_opacity: NaN,
casing_dashes: [],
layer: NaN, // optional layer override (usually set by OSM tag)
render: null, // "auto" indicates that line/area features are allowed to be rendered as points on low zoom levels; the value "native" always renders features using their native geometry type; the value "point" always renders features as points in the centroid of the feature geometry
styleType: "ShapeStyle",

drawn() {
Expand Down
21 changes: 13 additions & 8 deletions js/overpass.ts
Original file line number Diff line number Diff line change
Expand Up @@ -314,9 +314,9 @@ class Overpass {
// point features
`node {color:#03f; width:2; opacity:0.7; fill-color:#fc0; fill-opacity:0.3;} \n` +
// line features
`line {color:#03f; width:5; opacity:0.6;} \n` +
`line {color:#03f; width:5; opacity:0.6; render:auto;} \n` +
// polygon features
`area {color:#03f; width:2; opacity:0.7; fill-color:#fc0; fill-opacity:0.3;} \n` +
`area {color:#03f; width:2; opacity:0.7; fill-color:#fc0; fill-opacity:0.3; render:auto;} \n` +
// style modifications
// objects in relations
`relation node, relation way, relation {color:#d0f;} \n` +
Expand Down Expand Up @@ -420,13 +420,14 @@ class Overpass {
afterParse() {
overpass.fire("onProgress", "rendering geoJSON");
},
baseLayerClass: settings.disable_poiomatic
? L.GeoJSON
: L_GeoJsonNoVanish,
baseLayerClass: L_GeoJsonNoVanish,
baseLayerOptions: {
threshold: 9 * Math.sqrt(2) * 2,
compress() {
return true;
compress(feature) {
const render = this.style(feature).render;
if (render === "auto" && settings.disable_poiomatic)
return "native";
else return render;
},
style(feature, highlight) {
const stl: L.PathOptions = {};
Expand Down Expand Up @@ -488,6 +489,8 @@ class Overpass {
if (p !== undefined) stl.dashOffset = String(-p); // MapCSS and PolylineOffset definitions use different signs
p = get_property(styles, ["dashes"]);
if (p !== undefined) stl.dashArray = p.join(" ");
p = get_property(styles, ["render"]);
if (p !== undefined) stl.render = p;
break;
case "Polygon":
case "MultiPolygon":
Expand All @@ -504,6 +507,8 @@ class Overpass {
if (p !== undefined) stl.fillOpacity = p;
p = get_property(styles, ["dashes"]);
if (p !== undefined) stl.dashArray = p.join(" ");
p = get_property(styles, ["render"]);
if (p !== undefined) stl.render = p;
break;
}
// todo: more style properties? linecap, linejoin?
Expand Down Expand Up @@ -581,7 +586,7 @@ class Overpass {
// if there is a placeholder on a line, polygon or multipolygon
// then get the center instead of the position of the click
else if (e.target.placeholder)
latlng = e.target.getBounds().getCenter();
latlng = e.target.placeholder._latlng;
else latlng = e.latlng; // all other (lines, polygons, multipolygons)
const p = L.popup({maxHeight: 600}, this)
.setLatLng(latlng)
Expand Down

0 comments on commit a97a885

Please sign in to comment.