From d7afd0d72e3ac3c8e56fa39a35c877a353c96343 Mon Sep 17 00:00:00 2001 From: Matthew Bloch Date: Thu, 7 Mar 2024 15:39:30 -0500 Subject: [PATCH] map rendering fixes --- src/gui/gui-canvas.mjs | 21 +++--- src/gui/gui-map-extent.mjs | 14 ++-- src/gui/gui-map-style.mjs | 143 ++++++++++++++++++++----------------- src/gui/gui-map.mjs | 22 ++++-- 4 files changed, 111 insertions(+), 89 deletions(-) diff --git a/src/gui/gui-canvas.mjs b/src/gui/gui-canvas.mjs index 3b7f1807..12bf612e 100644 --- a/src/gui/gui-canvas.mjs +++ b/src/gui/gui-canvas.mjs @@ -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; @@ -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; @@ -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 : '') + @@ -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. @@ -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) { diff --git a/src/gui/gui-map-extent.mjs b/src/gui/gui-map-extent.mjs index 19018639..7785e421 100644 --- a/src/gui/gui-map-extent.mjs +++ b/src/gui/gui-map-extent.mjs @@ -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 diff --git a/src/gui/gui-map-style.mjs b/src/gui/gui-map-style.mjs index 842bb6de..2bf7767f 100644 --- a/src/gui/gui-map-style.mjs +++ b/src/gui/gui-map-style.mjs @@ -100,50 +100,22 @@ 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 -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 -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) { diff --git a/src/gui/gui-map.mjs b/src/gui/gui-map.mjs index 209facf5..ddb31269 100644 --- a/src/gui/gui-map.mjs +++ b/src/gui/gui-map.mjs @@ -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; } @@ -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; }; @@ -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; @@ -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)) { @@ -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), @@ -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). @@ -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()); } }); }