Skip to content

Commit

Permalink
map rendering fixes
Browse files Browse the repository at this point in the history
  • Loading branch information
mbloch committed Mar 7, 2024
1 parent 5b86c98 commit d7afd0d
Show file tree
Hide file tree
Showing 4 changed files with 111 additions and 89 deletions.
21 changes: 13 additions & 8 deletions src/gui/gui-canvas.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -157,7 +157,7 @@ export function DisplayCanvas() {
var iter = new internal.ShapeIter(arcs);
var t = getScaledTransform(_ext);
var bounds = _ext.getBounds();
var radius = (style.strokeWidth > 2 ? style.strokeWidth * 0.9 : 2) * GUI.getPixelRatio() * getScaledLineScale(_ext);
var radius = (style.strokeWidth > 2 ? style.strokeWidth * 0.9 : 2) * GUI.getPixelRatio() * getScaledLineScale(_ext, style);
var color = style.strokeColor || 'black';

var i, j, p;
Expand Down Expand Up @@ -191,7 +191,7 @@ export function DisplayCanvas() {
_self.drawStyledPaths = function(shapes, arcs, style, filter) {
var styleIndex = {};
var batchSize = 1500;
var startPath = getPathStart(_ext, getScaledLineScale(_ext));
var startPath = getPathStart(_ext, getScaledLineScale(_ext, style));
var draw = getShapePencil(arcs, _ext);
var key, item, shp;
var styler = style.styler || null;
Expand Down Expand Up @@ -367,7 +367,7 @@ export function DisplayCanvas() {
return (style.strokeWidth > 0 ? style.strokeColor + '~' + style.strokeWidth +
'~' + (style.lineDash ? style.lineDash + '~' : '') : '') +
(style.fillColor || '') +
// styles with <1 opacity are no longer batch-rendered
// styles with <1 opacity are no longer batch-rendered, not relevent to key
// (style.strokeOpacity >= 0 ? style.strokeOpacity + '~' : '') : '') +
// (style.fillOpacity ? '~' + style.fillOpacity : '') +
// (style.opacity < 1 ? '~' + style.opacity : '') +
Expand All @@ -376,9 +376,17 @@ export function DisplayCanvas() {
return _self;
}

function getScaledLineScale(ext) {
function getScaledLineScale(ext, style) {
var previewScale = ext.getSymbolScale();
return previewScale == 1 ? getLineScale(ext) : previewScale;
var k = 1;
if (previewScale == 1 || style.type != 'styled' || style.baseStyle && style.baseStyle.type != 'styled') {
return getLineScale(ext);
}
if (style.baseStyle?.type == 'styled') {
// bump up overlay line width in preview mode
k = previewScale < 2 && 2 || previewScale < 5 && 1.5 || previewScale < 10 && 1.25 || 1.1;
}
return previewScale * k;
}

// Vary line width according to zoom ratio.
Expand Down Expand Up @@ -548,9 +556,6 @@ function getPathStart(ext, lineScale) {
return function(ctx, style) {
var strokeWidth;
ctx.beginPath();
// if (style.opacity >= 0) {
// ctx.globalAlpha = style.opacity;
// }
if (style.strokeWidth > 0) {
strokeWidth = style.strokeWidth;
if (pixRatio > 1) {
Expand Down
14 changes: 4 additions & 10 deletions src/gui/gui-map-extent.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -199,19 +199,13 @@ export function MapExtent(_position) {
}

function calcBounds(cx, cy, scale) {
var full, bounds, w, h;
if (_frame) {
full = fillOutFrameBounds(_frame);
} else {
full = fillOut(_fullBounds);
}
var full = fillOut(_fullBounds);
if (_strictBounds) {
full = fitIn(full, _strictBounds);
}
w = full.width() / scale;
h = full.height() / scale;
bounds = new Bounds(cx - w/2, cy - h/2, cx + w/2, cy + h/2);
return bounds;
var w = full.width() / scale;
var h = full.height() / scale;
return new Bounds(cx - w/2, cy - h/2, cx + w/2, cy + h/2);
}

// Calculate viewport bounds from frame data
Expand Down
143 changes: 78 additions & 65 deletions src/gui/gui-map-style.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -100,86 +100,43 @@ var darkStroke = "#334",
dotColor: violet,
dotSize: 3
}, polyline: {
strokeColor: black, // violet,
strokeColor: violet, // black, // violet,
strokeWidth: 3
}
};

export function getIntersectionStyle(lyr) {
export function getIntersectionStyle(lyr, opts) {
return getDefaultStyle(lyr, intersectionStyle);
}

function getDefaultStyle(lyr, baseStyle) {
var style = utils.extend({}, baseStyle);
// reduce the dot size of large point layers
if (lyr.geometry_type == 'point' && style.dotSize > 0) {
style.dotSize *= getDotScale(lyr);
}
return style;
}

function getDotScale(lyr) {
var topTier = 50000;
var n = countPoints(lyr.shapes, topTier + 2); // short-circuit point counting above top threshold
var k = n < 200 && 4 || n < 2500 && 3 || n < 10000 && 2 || 1;
// var k = n >= topTier && 0.25 || n > 10000 && 0.45 || n > 2500 && 0.65 || n > 200 && 0.85 || 1;
return k;
}

function countPoints(shapes, max) {
var count = 0;
var i, n, shp;
max = max || Infinity;
for (i=0, n=shapes.length; i<n && count<=max; i++) {
shp = shapes[i];
count += shp ? shp.length : 0;
}
return count;
}

// Style for unselected layers with visibility turned on
// (styled layers have)
export function getReferenceStyle(lyr) {
export function getReferenceLayerStyle(lyr, opts) {
var style;
if (layerHasCanvasDisplayStyle(lyr)) {
if (layerHasCanvasDisplayStyle(lyr) && !opts.outlineMode) {
style = getCanvasDisplayStyle(lyr);
} else if (internal.layerHasLabels(lyr)) {
} else if (internal.layerHasLabels(lyr) && !opts.outlineMode) {
style = {dotSize: 0}; // no reference dots if labels are visible
} else {
style = getDefaultStyle(lyr, referenceStyle);
}
return style;
}

export function getActiveStyle(lyr, darkMode) {
export function getActiveLayerStyle(lyr, opts) {
var style;
if (layerHasCanvasDisplayStyle(lyr)) {
if (layerHasCanvasDisplayStyle(lyr) && !opts.outlineMode) {
style = getCanvasDisplayStyle(lyr);
} else if (internal.layerHasLabels(lyr)) {
} else if (internal.layerHasLabels(lyr) && !opts.outlineMode) {
style = getDefaultStyle(lyr, activeStyleForLabels);
} else if (darkMode) {
} else if (opts.darkMode) {
style = getDefaultStyle(lyr, activeStyleDarkMode);
} else {
style = getDefaultStyle(lyr, activeStyle);
}
return style;
}

// style for vertex edit mode
function getVertexStyle(lyr, o) {
return {
ids: o.ids,
overlay: true,
strokeColor: black,
strokeWidth: 1.5,
vertices: true,
vertex_overlay_color: violet,
vertex_overlay: o.hit_coordinates || null,
selected_points: o.selected_points || null,
fillColor: null
};
}

// Returns a display style for the overlay layer.
// The overlay layer renders several kinds of feature, each of which is displayed
// with a different style.
Expand All @@ -188,47 +145,103 @@ function getVertexStyle(lyr, o) {
// * selected shapes
// * pinned shapes
//
export function getOverlayStyle(lyr, o) {
if (o.mode == 'vertices') {
return getVertexStyle(lyr, o);
export function getOverlayStyle(baseLyr, o, opts) {
if (opts.interactionMode == 'vertices') {
return getVertexStyle(baseLyr, o);
}
var geomType = lyr.geometry_type;
var geomType = baseLyr.geometry_type;
var topId = o.id; // pinned id (if pinned) or hover id
var topIdx = -1;
var styler = function(style, i) {
utils.extend(style, i === topIdx ? topStyle: baseStyle);
var defaultStyle = i === topIdx ? topStyle : outlineStyle;
if (baseStyle.styler) {
Object.assign(style, baseStyle);
baseStyle.styler(style, i);
style.strokeColor = defaultStyle.strokeColor;
style.fillColor = defaultStyle.fillColor;
} else {
Object.assign(style, defaultStyle);
}
};
var baseStyle = getDefaultStyle(lyr, selectionStyles[geomType]);
// var baseStyle = getDefaultStyle(baseLyr, selectionStyles[geomType]);
var baseStyle = getActiveLayerStyle(baseLyr, opts);
var outlineStyle = getDefaultStyle(baseLyr, selectionStyles[geomType]);
var topStyle;
var ids = o.ids.filter(function(i) {
return i != o.id; // move selected id to the end
});
if (o.id > -1) { // pinned or hover style
topStyle = getSelectedFeatureStyle(lyr, o);
topStyle = getSelectedFeatureStyle(baseLyr, o, opts);
topIdx = ids.length;
ids.push(o.id); // put the pinned/hover feature last in the render order
}
var style = {
styler: styler,
ids: ids,
baseStyle: baseStyle,
styler,
ids,
overlay: true
};

if (layerHasCanvasDisplayStyle(lyr)) {
if (layerHasCanvasDisplayStyle(baseLyr) && !opts.outlineMode) {
if (geomType == 'point') {
style.styler = getOverlayPointStyler(getCanvasDisplayStyle(lyr).styler, styler);
style.styler = getOverlayPointStyler(getCanvasDisplayStyle(baseLyr).styler, styler);
}
style.type = 'styled';
}
return ids.length > 0 ? style : null;
}

function getSelectedFeatureStyle(lyr, o) {

function getDefaultStyle(lyr, baseStyle) {
var style = Object.assign({}, baseStyle);
// reduce the dot size of large point layers
if (lyr.geometry_type == 'point' && style.dotSize > 0) {
style.dotSize *= getDotScale(lyr);
}
return style;
}

function getDotScale(lyr) {
var topTier = 10000;
var n = countPoints(lyr.shapes, topTier); // short-circuit point counting above top threshold
var k = n < 200 && 4 || n < 2500 && 3 || n < topTier && 2 || 1;
return k;
}

function countPoints(shapes, max) {
var count = 0;
var i, n, shp;
max = max || Infinity;
for (i=0, n=shapes.length; i<n && count<max; i++) {
shp = shapes[i];
count += shp ? shp.length : 0;
}
return count;
}


// style for vertex edit mode
function getVertexStyle(lyr, o) {
return {
ids: o.ids,
overlay: true,
strokeColor: black,
strokeWidth: 1.5,
vertices: true,
vertex_overlay_color: violet,
vertex_overlay: o.hit_coordinates || null,
selected_points: o.selected_points || null,
fillColor: null
};
}


function getSelectedFeatureStyle(lyr, o, opts) {
var isPinned = o.pinned;
var inSelection = o.ids.indexOf(o.id) > -1;
var geomType = lyr.geometry_type;
var style;
if (isPinned && o.mode == 'rectangles') {
if (isPinned && opts.interactionMode == 'rectangles') {
// kludge for rectangle editing mode
style = selectionStyles[geomType];
} else if (isPinned) {
Expand Down
22 changes: 16 additions & 6 deletions src/gui/gui-map.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,7 @@ export function MshpMap(gui) {
if (lyr == _intersectionLyr) return; // no change
if (lyr) {
_intersectionLyr = getDisplayLayer(lyr, dataset, getDisplayOptions());
_intersectionLyr.style = MapStyle.getIntersectionStyle(_intersectionLyr.layer);
_intersectionLyr.style = MapStyle.getIntersectionStyle(_intersectionLyr.layer, getGlobalStyleOptions());
} else {
_intersectionLyr = null;
}
Expand Down Expand Up @@ -108,6 +108,7 @@ export function MshpMap(gui) {
};

this.getExtent = function() {return _ext;};
this.getMouse = function() {return _mouse;};
this.isActiveLayer = isActiveLayer;
this.isVisibleLayer = isVisibleLayer;
this.getActiveLayer = function() { return _activeLyr; };
Expand Down Expand Up @@ -144,6 +145,15 @@ export function MshpMap(gui) {
updateFullBounds();
};

function getGlobalStyleOptions() {
var mode = gui.state.interaction_mode;
return {
darkMode: !!gui.state.dark_basemap,
outlineMode: mode == 'vertices',
interactionMode: mode
};
}

// Refresh map display in response to data changes, layer selection, etc.
function onUpdate(e) {
var prevLyr = _activeLyr || null;
Expand Down Expand Up @@ -176,7 +186,6 @@ export function MshpMap(gui) {
}

_activeLyr = getDisplayLayer(e.layer, e.dataset, getDisplayOptions());
_activeLyr.style = MapStyle.getActiveStyle(_activeLyr.layer, gui.state.dark_basemap);
_activeLyr.active = true;

if (popupCanStayOpen(e.flags)) {
Expand Down Expand Up @@ -234,7 +243,7 @@ export function MshpMap(gui) {
}

function updateOverlayLayer(e) {
var style = MapStyle.getOverlayStyle(_activeLyr.layer, e);
var style = MapStyle.getOverlayStyle(_activeLyr.layer, e, getGlobalStyleOptions());
if (style) {
_overlayLyr = utils.defaults({
layer: filterLayerByIds(_activeLyr.layer, style.ids),
Expand Down Expand Up @@ -381,9 +390,10 @@ export function MshpMap(gui) {
function updateLayerStyles(layers) {
layers.forEach(function(mapLayer, i) {
if (mapLayer.active) {
// assume: style is already assigned
// regenerating active style everytime, to support style change when
// switching between outline and preview modes.
mapLayer.style = MapStyle.getActiveLayerStyle(mapLayer.layer, getGlobalStyleOptions());
if (mapLayer.style.type != 'styled' && layers.length > 1 && mapLayer.style.strokeColors) {
// if (false) { // always show ghosted arcs
// kludge to hide ghosted layers when reference layers are present
// TODO: consider never showing ghosted layers (which appear after
// commands like dissolve and filter).
Expand All @@ -395,7 +405,7 @@ export function MshpMap(gui) {
if (mapLayer.layer == _activeLyr.layer) {
console.error("Error: shared map layer");
}
mapLayer.style = MapStyle.getReferenceStyle(mapLayer.layer);
mapLayer.style = MapStyle.getReferenceLayerStyle(mapLayer.layer, getGlobalStyleOptions());
}
});
}
Expand Down

0 comments on commit d7afd0d

Please sign in to comment.