diff --git a/examples/deepzoom/thumb.png b/examples/deepzoom/thumb.png deleted file mode 100644 index 5581b85822..0000000000 Binary files a/examples/deepzoom/thumb.png and /dev/null differ diff --git a/examples/lines/example.json b/examples/lines/example.json index c8d23e6279..c04bd3b649 100644 --- a/examples/lines/example.json +++ b/examples/lines/example.json @@ -2,7 +2,7 @@ "title": "Line Feature", "exampleCss": ["main.css"], "exampleJs": ["main.js"], - "thumbquery": "lines=250000", + "thumbquery": "lines=250000&lineCap=round&strokeWidth=%7B%22residential%22%3A1%2C%22service%22%3A0.25%2C%22other%22%3A3%7D", "about": { "text": "This example shows the variations that are available for line features." } diff --git a/examples/lines/index.pug b/examples/lines/index.pug index da614711aa..96f48e9147 100644 --- a/examples/lines/index.pug +++ b/examples/lines/index.pug @@ -36,6 +36,15 @@ block append mainContent .form-group(title="Show an OSM map underneath the lines.") label(for="showmap") Show Map input#showmap(type="checkbox", placeholder="true", checked="checked") + .form-group(title="Reduce line complexity based on zoom level.") + label(for="simplify") Simplify Lines + input#simplify(type="checkbox", placeholder="false") + input#simplify_tolerance(placeholder="0.5", title="Maximum change in pixels at the current zoom level") + span#simple-lines-shown + .form-group(title="When simplification is turned on, update it when zooming the map.") + label(for="resimplify") Zoom Resimplifies + input#resimplify(type="checkbox", placeholder="false") + input#resimplify_delay(placeholder="500", title="Delay in milliseconds before resimplifying lines after a change in zoom level") .form-group .shortlabel Presets button.preset(strokeColor='{"residential":"blue","service":"green","other":"black"}', strokeWidth='{"residential":4,"service":1,"other":8}', lineCap='round', showmap='true', title='Properties based on road category') Categories diff --git a/examples/lines/main.css b/examples/lines/main.css index d6a1cd06b8..6902a1884a 100644 --- a/examples/lines/main.css +++ b/examples/lines/main.css @@ -29,7 +29,7 @@ #controls #lines { width: 100px; } -#controls #lines-loaded,#controls #lines-shown { +#controls #lines-loaded,#controls #lines-shown,#controls #simple-lines-shown { display: inline-block; font-size: 11px; padding-left: 5px; @@ -58,3 +58,7 @@ font-size: 12px; color: black; } +#controls #simplify_tolerance,#controls #resimplify_delay { + width: 80px; +} + diff --git a/examples/lines/main.js b/examples/lines/main.js index eddcde5c4b..8a2ee355ec 100644 --- a/examples/lines/main.js +++ b/examples/lines/main.js @@ -4,6 +4,14 @@ $(function () { 'use strict'; + function lineAccessor(data, index) { + return data.data; + } + + function positionAccessor(data, index) { + return {x: data[0], y: data[1]}; + } + // Get query parameters var query = utils.getQuery(); @@ -16,7 +24,8 @@ $(function () { }, zoom: 11 }); - var osm, mapUrl, layer, lineFeature, lines, rawdata, skipdraw; + var osm, mapUrl, layer, lineFeature, lines, rawdata, reduceddata, skipdraw, + lastSimplifyZoom, resimplifyTimeout; // By default, use the best renderer that supports lines. This can be // changed on with the 'renderer' query parameter to force a particular @@ -80,15 +89,23 @@ $(function () { lines = ctlvalue = parseInt(value, 10); } break; - case 'showmap': - ctlvalue = value !== 'false'; - break; case 'miterLimit': value = value.length ? parseFloat(value) : undefined; if (!isNaN(value) && value > 0 && value !== undefined) { lineOptions.style[key] = ctlvalue = value; } break; + case 'resimplify': + case 'showmap': + case 'simplify': + ctlvalue = value !== 'false'; + break; + case 'resimplify_delay': + ctlvalue = value.length ? parseInt(value) : undefined; + break; + case 'simplify_tolerance': + ctlvalue = value.length ? parseFloat(value) : undefined; + break; } if (ctlvalue !== undefined) { if ($('#' + ctlkey).is('[type="checkbox"]')) { @@ -124,11 +141,13 @@ $(function () { * Given a set of lines, optionally truncate or expand it, then show it as a * lineFeature. * - * @param {array} rawdata: an array of lines to show. Each entry contains an + * @param {array} rawdata An array of lines to show. Each entry contains an * object that has a 'data' element which is an array of points that form * the line. + * @param {boolean} [simplify] If present, use this as the flag to decide if + * lines should be simplified. */ - function show_lines(rawdata) { + function show_lines(rawdata, simplify) { $('#map').removeClass('ready').attr('segments', ''); if (!rawdata) { return; @@ -140,9 +159,21 @@ $(function () { for (numlines = 0; numlines < rawdata.length && segments < maxsegments; numlines += 1) { segments += rawdata[numlines].data.length - 1; } - var data = rawdata.slice(0, numlines); - lineFeature.data(data); - lineFeature.draw(); + reduceddata = rawdata.slice(0, numlines); + if (simplify === undefined) { + simplify = query.simplify; + } + if (!simplify || simplify === 'false') { + // set the data, and reset the line and position accessors in case we + // changed them with the line simplication + lineFeature.data(reduceddata) + .line(lineAccessor) + .position(positionAccessor); + lineFeature.draw(); + $('#simple-lines-shown').text('').attr('title', ''); + } else { + simplify_lines(reduceddata); + } var text = 'Shown: ' + segments; $('#lines-shown').text(text).attr('title', text); map.onIdle(function () { @@ -150,13 +181,74 @@ $(function () { }); } + /** + * When the map is zoomed, if resimplifying lines is active, set a timer to + * do so after the currently specified delay. + * + * @param {geo.event} evt geojs event that triggered this call. + */ + function resimplifyOnZoom(evt) { + if (resimplifyTimeout) { + window.cancelTimeout(resimplifyTimeout); + resimplifyTimeout = null; + } + if (!query.simplify || query.simplify === 'false' || + !query.resimplify || query.resimplify === 'false') { + return; + } + window.setTimeout(function () { + resimplifyTimeout = null; + if (map.zoom() !== lastSimplifyZoom) { + simplify_lines(reduceddata); + } + }, parseInt(query.resimplify_delay, 10) || 500); + } + + /** + * Simplify lines based on the current zoom level. + * + * @param {array} data The data to simplify. + * @param {number} [tolerance=query.simplify_tolerance] The tolerance in + * pixels at the current map zoom level. + */ + function simplify_lines(data, tolerance) { + if (!data) { + return; + } + lastSimplifyZoom = map.zoom(); + if (resimplifyTimeout) { + window.cancelTimeout(resimplifyTimeout); + resimplifyTimeout = null; + } + tolerance = parseFloat(tolerance !== undefined ? tolerance : query.simplify_tolerance || 0.5); + lineFeature.rdpSimplifyData( + data, + map.unitsPerPixel(map.zoom()) * tolerance, + positionAccessor, + lineAccessor); + lineFeature.draw(); + var segments = 0, + lineFunc = lineFeature.line(); + lineFeature.data().forEach(function (d, i) { + var len = lineFunc(d, i).length; + segments += len >= 2 ? len - 1 : 0; + }); + var text = 'Shown: ' + segments; + $('#simple-lines-shown').text(text).attr('title', text); + text = $('#lines-shown').text(); + if (text.indexOf('Shown') === 0) { + text = 'Used' + text.substr(5); + $('#lines-shown').text(text).attr('title', text); + } + } + /** * For styles that can vary, parse the string and either return a simple * string or a function that computes the value. * - * @param {string} key: the property key. Used to get a default value if + * @param {string} key the property key. Used to get a default value if * needed. - * @param {string} value: the string form of the value. If this has a { in + * @param {string} value the string form of the value. If this has a { in * it, it is parsed as a JSON dictionary, and expects to be a list of * category names which are used to determine the values. These values * applied uniformly per line. Otherwise, if this has a , in it, it is a @@ -204,7 +296,7 @@ $(function () { /** * Handle changes to our controls. * - * @param {object} evt jquery evt that triggered this call. + * @param {object} evt jquery event that triggered this call. */ function change_controls(evt) { var ctl = $(evt.target), @@ -257,9 +349,6 @@ $(function () { lines = parseInt(value); show_lines(rawdata); break; - case 'showmap': - set_osm_url(value); - break; case 'miterLimit': value = value.length ? parseFloat(value) : undefined; if (isNaN(value) || value <= 0 || value === undefined) { @@ -271,6 +360,30 @@ $(function () { lineFeature.draw(); } break; + case 'showmap': + set_osm_url(value); + break; + case 'simplify': + if (!processedValue) { + show_lines(rawdata, false); + } else { + simplify_lines(reduceddata); + } + break; + case 'simplify_tolerance': + processedValue = value.length ? parseFloat(value) : undefined; + if (query.simplify) { + simplify_lines(reduceddata, processedValue); + } + break; + case 'resimplify': + if (processedValue && query.simplify && query.simplify !== 'false' && + map.zoom() !== lastSimplifyZoom) { + simplify_lines(reduceddata); + } + break; + case 'resimplify_delay': + break; } // Update the url to reflect the changes query[param] = value; @@ -286,7 +399,7 @@ $(function () { /** * Handle selecting a preset button. * - * @param {object} evt: jquery event with the triggered button. + * @param {object} evt jquery event with the triggered button. */ function select_preset(evt) { var update; @@ -315,7 +428,7 @@ $(function () { /** * Set the map to either use the original default url or a blank white image. * - * @param {string} value: 'false' to use a white image, anything else to use + * @param {string} value 'false' to use a white image, anything else to use * the original url. */ function set_osm_url(value) { @@ -341,12 +454,8 @@ $(function () { 'hidden'); // Ceate a line feature lineFeature = layer.createFeature('line', lineOptions) - .line(function (d) { - return d.data; - }) - .position(function (d) { - return {x: d[0], y: d[1]}; - }) + .line(lineAccessor) + .position(positionAccessor) // add hover events -- use mouseon and mouseoff, since we only show one // tootip. If we showed one tooltip per item we were over, use mouseover // and mouseout. @@ -361,7 +470,8 @@ $(function () { }) .geoOn(geo.event.feature.mouseoff, function (evt) { tooltipElem.addClass('hidden'); - }); + }) + .geoOn(geo.event.zoom, resimplifyOnZoom); // Make some values available in the global context so curious people can // play with them. diff --git a/examples/lines/thumb.jpg b/examples/lines/thumb.jpg index 68292c72f7..00c9527377 100755 Binary files a/examples/lines/thumb.jpg and b/examples/lines/thumb.jpg differ diff --git a/testing/test-data/base-images.tgz.md5 b/testing/test-data/base-images.tgz.md5 index 3923d4e6fe..b0a4cb7bba 100644 --- a/testing/test-data/base-images.tgz.md5 +++ b/testing/test-data/base-images.tgz.md5 @@ -1 +1 @@ -db9d881cbba3139e98d026c7c823c3c8 \ No newline at end of file +2333a69e96ce063d10862bd8d563eb3d \ No newline at end of file diff --git a/testing/test-data/base-images.tgz.url b/testing/test-data/base-images.tgz.url index bd31e78cde..0107cbdd36 100644 --- a/testing/test-data/base-images.tgz.url +++ b/testing/test-data/base-images.tgz.url @@ -1 +1 @@ -https://data.kitware.com/api/v1/file/5a3c0f7b8d777f5e872f7508/download \ No newline at end of file +https://data.kitware.com/api/v1/file/5a9ed5838d777f0685786207/download \ No newline at end of file