mapshaper 0.6.13 → 0.6.15
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/mapshaper.js +434 -225
- package/package.json +10 -7
- package/www/basemap.js +2 -2
- package/www/mapshaper-gui.js +151 -93
- package/www/mapshaper.js +434 -225
- package/www/modules.js +904 -2
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "mapshaper",
|
|
3
|
-
"version": "0.6.
|
|
3
|
+
"version": "0.6.15",
|
|
4
4
|
"description": "A tool for editing vector datasets for mapping and GIS.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"shapefile",
|
|
@@ -28,7 +28,7 @@
|
|
|
28
28
|
"lint": "eslint --ext mjs src/",
|
|
29
29
|
"prepublishOnly": "npm lint; npm test; ./pre-publish",
|
|
30
30
|
"postpublish": "./release_web_ui; ./release_github_version",
|
|
31
|
-
"browserify": "browserify -r sync-request -r mproj -r buffer -r iconv-lite -r fs -r flatbush -r rw -r path -r kdbush -r @tmcw/togeojson -o www/modules.js",
|
|
31
|
+
"browserify": "browserify -r sync-request -r mproj -r buffer -r iconv-lite -r fs -r flatbush -r rw -r path -r kdbush -r @tmcw/togeojson -r @placemarkio/tokml -o www/modules.js",
|
|
32
32
|
"dev": "rollup --config --watch"
|
|
33
33
|
},
|
|
34
34
|
"main": "./mapshaper.js",
|
|
@@ -40,12 +40,15 @@
|
|
|
40
40
|
"!.DS_Store"
|
|
41
41
|
],
|
|
42
42
|
"dependencies": {
|
|
43
|
-
"@
|
|
44
|
-
"@
|
|
43
|
+
"@placemarkio/tokml": "^0.3.3",
|
|
44
|
+
"@tmcw/togeojson": "^5.5.0",
|
|
45
|
+
"@xmldom/xmldom": "^0.8.6",
|
|
46
|
+
"adm-zip": "^0.5.9",
|
|
45
47
|
"commander": "7.0.0",
|
|
46
48
|
"cookies": "^0.8.0",
|
|
47
|
-
"d3-color": "
|
|
48
|
-
"d3-
|
|
49
|
+
"d3-color": "3.1.0",
|
|
50
|
+
"d3-interpolate": "^3.0.1",
|
|
51
|
+
"d3-scale-chromatic": "3.0.0",
|
|
49
52
|
"delaunator": "^5.0.0",
|
|
50
53
|
"flatbush": "^3.2.1",
|
|
51
54
|
"geokdbush": "^1.1.0",
|
|
@@ -64,7 +67,7 @@
|
|
|
64
67
|
"eslint": "^8.16.0",
|
|
65
68
|
"mocha": "^10.0.0",
|
|
66
69
|
"rollup": "^2.73.0",
|
|
67
|
-
"shell-quote": "^1.
|
|
70
|
+
"shell-quote": "^1.7.4",
|
|
68
71
|
"underscore": "^1.13.1"
|
|
69
72
|
},
|
|
70
73
|
"mocha": {
|
package/www/basemap.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
window.mapboxParams = {
|
|
2
|
-
js: 'https://api.mapbox.com/mapbox-gl-js/v2.
|
|
3
|
-
css: 'https://api.mapbox.com/mapbox-gl-js/v2.
|
|
2
|
+
js: 'https://api.mapbox.com/mapbox-gl-js/v2.11.1/mapbox-gl.js',
|
|
3
|
+
css: 'https://api.mapbox.com/mapbox-gl-js/v2.11.1/mapbox-gl.css',
|
|
4
4
|
key: 'pk.eyJ1IjoiZ3JhbW1hdGEiLCJhIjoiY2wxMzI4b3dqMDNhMjNpcDhzcmU0aGh5diJ9.m1lacx48pTYls-X3FVhG9g',
|
|
5
5
|
styles: [{
|
|
6
6
|
name: 'Map',
|
package/www/mapshaper-gui.js
CHANGED
|
@@ -392,7 +392,7 @@
|
|
|
392
392
|
function readEntry(entry) {
|
|
393
393
|
var filename = entry.filename,
|
|
394
394
|
isValid = !entry.directory && GUI.isReadableFileType(filename) &&
|
|
395
|
-
!/^__MACOSX/.test(filename); // ignore "resource-
|
|
395
|
+
!/^__MACOSX/.test(filename); // ignore "resource-fork" files
|
|
396
396
|
if (isValid) {
|
|
397
397
|
entry.getData(new zip.BlobWriter(), function(file) {
|
|
398
398
|
file.name = filename; // Give the Blob a name, like a File object
|
|
@@ -1420,12 +1420,14 @@
|
|
|
1420
1420
|
async function expandFiles(files) {
|
|
1421
1421
|
var files2 = [], expanded;
|
|
1422
1422
|
for (var f of files) {
|
|
1423
|
-
if (internal.isZipFile(f.name)
|
|
1423
|
+
if (internal.isZipFile(f.name)) {
|
|
1424
1424
|
expanded = await readZipFile(f);
|
|
1425
|
-
|
|
1425
|
+
} else if (internal.isKmzFile(f.name)) {
|
|
1426
|
+
expanded = await readKmzFile(f);
|
|
1426
1427
|
} else {
|
|
1427
|
-
|
|
1428
|
+
expanded = [f];
|
|
1428
1429
|
}
|
|
1430
|
+
files2 = files2.concat(expanded);
|
|
1429
1431
|
}
|
|
1430
1432
|
return files2;
|
|
1431
1433
|
}
|
|
@@ -1582,6 +1584,15 @@
|
|
|
1582
1584
|
});
|
|
1583
1585
|
}
|
|
1584
1586
|
|
|
1587
|
+
async function readKmzFile(file) {
|
|
1588
|
+
var files = await readZipFile(file);
|
|
1589
|
+
var name = files[0] && files[0].name;
|
|
1590
|
+
if (name == 'doc.kml') {
|
|
1591
|
+
files[0].name = internal.replaceFileExtension(file.name, 'kml');
|
|
1592
|
+
}
|
|
1593
|
+
return files;
|
|
1594
|
+
}
|
|
1595
|
+
|
|
1585
1596
|
async function readZipFile(file) {
|
|
1586
1597
|
var files = [];
|
|
1587
1598
|
await wait(35); // pause a beat so status message can display
|
|
@@ -2466,13 +2477,13 @@
|
|
|
2466
2477
|
// if map is at full extent, show full extent
|
|
2467
2478
|
// TODO: handle case that scale is 1 and map is panned away from center
|
|
2468
2479
|
if (ext.scale() == 1 || !dest) {
|
|
2469
|
-
ext.
|
|
2480
|
+
ext.setFullBounds(newBounds, strictBounds);
|
|
2470
2481
|
ext.home(); // sets full extent and triggers redraw
|
|
2471
2482
|
} else {
|
|
2472
2483
|
// if map is zoomed, stay centered on the same geographic location, at the same relative scale
|
|
2473
2484
|
proj = internal.getProjTransform2(src, dest);
|
|
2474
2485
|
newCP = proj(oldBounds.centerX(), oldBounds.centerY());
|
|
2475
|
-
ext.
|
|
2486
|
+
ext.setFullBounds(newBounds, strictBounds);
|
|
2476
2487
|
if (!newCP) {
|
|
2477
2488
|
// projection of center point failed; use center of bounds
|
|
2478
2489
|
// (also consider just resetting the view using ext.home())
|
|
@@ -3392,7 +3403,7 @@
|
|
|
3392
3403
|
}
|
|
3393
3404
|
|
|
3394
3405
|
function initFormatMenu() {
|
|
3395
|
-
var defaults = ['shapefile', 'geojson', 'topojson', 'json', 'dsv', 'svg'];
|
|
3406
|
+
var defaults = ['shapefile', 'geojson', 'topojson', 'json', 'dsv', 'kml', 'svg'];
|
|
3396
3407
|
var formats = utils$1.uniq(defaults.concat(getInputFormats()));
|
|
3397
3408
|
var items = formats.map(function(fmt) {
|
|
3398
3409
|
return utils$1.format('<div><label><input type="radio" name="format" value="%s"' +
|
|
@@ -3898,6 +3909,11 @@
|
|
|
3898
3909
|
var history, offset, stashedUndo;
|
|
3899
3910
|
reset();
|
|
3900
3911
|
|
|
3912
|
+
// Undo history is cleared when the editing mode changes.
|
|
3913
|
+
gui.on('interaction_mode_change', function(e) {
|
|
3914
|
+
gui.undo.clear();
|
|
3915
|
+
});
|
|
3916
|
+
|
|
3901
3917
|
function reset() {
|
|
3902
3918
|
history = [];
|
|
3903
3919
|
stashedUndo = null;
|
|
@@ -4167,12 +4183,28 @@
|
|
|
4167
4183
|
|
|
4168
4184
|
function InteractionMode(gui) {
|
|
4169
4185
|
|
|
4186
|
+
// TODO: finish this list
|
|
4187
|
+
// var modes = [{
|
|
4188
|
+
// name: 'info',
|
|
4189
|
+
// label: 'inspect features',
|
|
4190
|
+
// selection: true,
|
|
4191
|
+
// popup: true,
|
|
4192
|
+
// types: ['standard', 'polygons', 'lines', 'labels', 'points']
|
|
4193
|
+
// }, {
|
|
4194
|
+
// name: 'selection',
|
|
4195
|
+
// label: 'select features',
|
|
4196
|
+
// selection: true,
|
|
4197
|
+
// popup: true,
|
|
4198
|
+
// types: ['standard', 'polygons', 'lines', 'table', 'labels']
|
|
4199
|
+
// }]
|
|
4200
|
+
|
|
4170
4201
|
var menus = {
|
|
4171
4202
|
standard: ['info', 'selection', 'data', 'box'],
|
|
4172
4203
|
polygons: ['info', 'selection', 'data', 'box', 'vertices'],
|
|
4173
4204
|
lines: ['info', 'selection', 'data', 'box', 'vertices'],
|
|
4174
4205
|
table: ['info', 'selection', 'data'],
|
|
4175
4206
|
labels: ['info', 'selection', 'data', 'box', 'labels', 'location'],
|
|
4207
|
+
// points: ['info', 'selection', 'data', 'box', 'location', 'add-points']
|
|
4176
4208
|
points: ['info', 'selection', 'data', 'box', 'location']
|
|
4177
4209
|
};
|
|
4178
4210
|
|
|
@@ -4191,6 +4223,7 @@
|
|
|
4191
4223
|
location: 'drag points',
|
|
4192
4224
|
vertices: 'edit vertices',
|
|
4193
4225
|
selection: 'select features',
|
|
4226
|
+
'add-points': 'add points',
|
|
4194
4227
|
off: 'turn off'
|
|
4195
4228
|
};
|
|
4196
4229
|
var btn, menu;
|
|
@@ -4243,6 +4276,10 @@
|
|
|
4243
4276
|
setMode('off');
|
|
4244
4277
|
};
|
|
4245
4278
|
|
|
4279
|
+
this.modeUsesSelection = function(mode) {
|
|
4280
|
+
return ['info', 'selection', 'data', 'labels', 'location', 'vertices'].includes(mode);
|
|
4281
|
+
};
|
|
4282
|
+
|
|
4246
4283
|
this.modeUsesPopup = function(mode) {
|
|
4247
4284
|
return ['info', 'selection', 'data', 'box', 'labels', 'location'].includes(mode);
|
|
4248
4285
|
};
|
|
@@ -6289,10 +6326,11 @@
|
|
|
6289
6326
|
// (some modes do not support pinning)
|
|
6290
6327
|
gui.on('interaction_mode_change', function(e) {
|
|
6291
6328
|
updateSelectionState(null);
|
|
6292
|
-
if (e.mode == 'off' || e.mode == 'box') {
|
|
6293
|
-
|
|
6294
|
-
} else {
|
|
6329
|
+
// if (e.mode == 'off' || e.mode == 'box') {
|
|
6330
|
+
if (gui.interaction.modeUsesSelection(e.mode)) {
|
|
6295
6331
|
turnOn(e.mode);
|
|
6332
|
+
} else {
|
|
6333
|
+
turnOff();
|
|
6296
6334
|
}
|
|
6297
6335
|
});
|
|
6298
6336
|
|
|
@@ -7637,7 +7675,14 @@
|
|
|
7637
7675
|
});
|
|
7638
7676
|
|
|
7639
7677
|
_popup.on('update', function(e) {
|
|
7640
|
-
|
|
7678
|
+
// data_change event no longer needed (update is handled below)
|
|
7679
|
+
// _self.dispatchEvent('data_change', e.data); // let map know which field has changed
|
|
7680
|
+
gui.session.dataValueUpdated(e.id, e.field, e.value);
|
|
7681
|
+
// Refresh the display if a style variable has been changed interactively
|
|
7682
|
+
if (internal.isSupportedSvgStyleProperty(e.field)) {
|
|
7683
|
+
// drawLayers();
|
|
7684
|
+
gui.dispatchEvent('map-needs-refresh');
|
|
7685
|
+
}
|
|
7641
7686
|
});
|
|
7642
7687
|
|
|
7643
7688
|
hit.on('change', function(e) {
|
|
@@ -8135,10 +8180,6 @@
|
|
|
8135
8180
|
initPointDragging(gui, ext, hit);
|
|
8136
8181
|
initVertexDragging(gui, ext, hit);
|
|
8137
8182
|
|
|
8138
|
-
gui.on('interaction_mode_change', function(e) {
|
|
8139
|
-
gui.undo.clear(); // TODO: put this elsewhere?
|
|
8140
|
-
});
|
|
8141
|
-
|
|
8142
8183
|
// function isClickEvent(up, down) {
|
|
8143
8184
|
// var elapsed = Math.abs(down.timeStamp - up.timeStamp);
|
|
8144
8185
|
// var dx = up.screenX - down.screenX;
|
|
@@ -8148,6 +8189,39 @@
|
|
|
8148
8189
|
// }
|
|
8149
8190
|
}
|
|
8150
8191
|
|
|
8192
|
+
function initPointDrawing(gui, ext, hit) {
|
|
8193
|
+
function active(e) {
|
|
8194
|
+
return e.id > -1 && gui.interaction.getMode() == 'add-points';
|
|
8195
|
+
}
|
|
8196
|
+
|
|
8197
|
+
}
|
|
8198
|
+
|
|
8199
|
+
function Pencil(gui, mouse, hit) {
|
|
8200
|
+
var self = this;
|
|
8201
|
+
var _on = false;
|
|
8202
|
+
|
|
8203
|
+
self.turnOn = function() {
|
|
8204
|
+
_on = true;
|
|
8205
|
+
};
|
|
8206
|
+
|
|
8207
|
+
self.turnOff = function() {
|
|
8208
|
+
_on = false;
|
|
8209
|
+
};
|
|
8210
|
+
|
|
8211
|
+
|
|
8212
|
+
|
|
8213
|
+
|
|
8214
|
+
|
|
8215
|
+
|
|
8216
|
+
}
|
|
8217
|
+
|
|
8218
|
+
function initDrawing(gui, ext, mouse, hit) {
|
|
8219
|
+
|
|
8220
|
+
initPointDrawing(gui, new Pencil(gui, mouse, hit));
|
|
8221
|
+
|
|
8222
|
+
|
|
8223
|
+
}
|
|
8224
|
+
|
|
8151
8225
|
var darkStroke = "#334",
|
|
8152
8226
|
lightStroke = "#b7d9ea",
|
|
8153
8227
|
violet = "#cc6acc",
|
|
@@ -8473,27 +8547,27 @@
|
|
|
8473
8547
|
function MapExtent(_position) {
|
|
8474
8548
|
var _scale = 1,
|
|
8475
8549
|
_cx, _cy, // center in geographic units
|
|
8476
|
-
|
|
8550
|
+
_fullBounds, // full (zoomed-out) content bounds, including any padding
|
|
8477
8551
|
_strictBounds, // full extent must fit inside, if set
|
|
8478
8552
|
_self = this,
|
|
8479
8553
|
_frame;
|
|
8480
8554
|
|
|
8481
8555
|
_position.on('resize', function(e) {
|
|
8482
8556
|
if (ready()) {
|
|
8483
|
-
|
|
8557
|
+
triggerChangeEvent({resize: true});
|
|
8484
8558
|
}
|
|
8485
8559
|
});
|
|
8486
8560
|
|
|
8487
|
-
function ready() { return !!
|
|
8561
|
+
function ready() { return !!_fullBounds; }
|
|
8488
8562
|
|
|
8489
8563
|
this.reset = function() {
|
|
8490
8564
|
if (!ready()) return;
|
|
8491
|
-
recenter(
|
|
8565
|
+
recenter(_fullBounds.centerX(), _fullBounds.centerY(), 1, {reset: true});
|
|
8492
8566
|
};
|
|
8493
8567
|
|
|
8494
8568
|
this.home = function() {
|
|
8495
8569
|
if (!ready()) return;
|
|
8496
|
-
recenter(
|
|
8570
|
+
recenter(_fullBounds.centerX(), _fullBounds.centerY(), 1);
|
|
8497
8571
|
};
|
|
8498
8572
|
|
|
8499
8573
|
this.pan = function(xpix, ypix) {
|
|
@@ -8560,30 +8634,29 @@
|
|
|
8560
8634
|
|
|
8561
8635
|
// k scales the size of the bbox (used by gui to control fp error when zoomed very far)
|
|
8562
8636
|
this.getBounds = function(k) {
|
|
8563
|
-
if (!
|
|
8637
|
+
if (!_fullBounds) return new Bounds();
|
|
8564
8638
|
return calcBounds(_cx, _cy, _scale / (k || 1));
|
|
8565
8639
|
};
|
|
8566
8640
|
|
|
8567
8641
|
// Update the extent of 'full' zoom without navigating the current view
|
|
8568
8642
|
//
|
|
8569
|
-
this.
|
|
8570
|
-
var
|
|
8571
|
-
var
|
|
8643
|
+
this.setFullBounds = function(fullBounds, strictBounds) {
|
|
8644
|
+
var prev = _fullBounds;
|
|
8645
|
+
var b = _fullBounds = fullBounds;
|
|
8572
8646
|
if (!b.hasBounds()) return; // kludge
|
|
8573
8647
|
if (strictBounds) {
|
|
8574
8648
|
_strictBounds = Array.isArray(strictBounds) ? new Bounds(strictBounds) : strictBounds;
|
|
8575
8649
|
} else {
|
|
8576
8650
|
_strictBounds = null;
|
|
8577
8651
|
}
|
|
8578
|
-
_contentBounds = _frame ? b : padBounds(b, 4); // padding if not in frame mode
|
|
8579
8652
|
if (_strictBounds) {
|
|
8580
|
-
|
|
8653
|
+
_fullBounds = fitIn(_fullBounds, _strictBounds);
|
|
8581
8654
|
}
|
|
8582
8655
|
if (prev) {
|
|
8583
|
-
_scale = _scale * fillOut(
|
|
8656
|
+
_scale = _scale * fillOut(_fullBounds).width() / fillOut(prev).width();
|
|
8584
8657
|
} else {
|
|
8585
|
-
_cx =
|
|
8586
|
-
_cy =
|
|
8658
|
+
_cx = _fullBounds.centerX();
|
|
8659
|
+
_cy = _fullBounds.centerY();
|
|
8587
8660
|
}
|
|
8588
8661
|
};
|
|
8589
8662
|
|
|
@@ -8614,12 +8687,12 @@
|
|
|
8614
8687
|
scale = scale ? limitScale(scale) : _scale;
|
|
8615
8688
|
if (cx == _cx && cy == _cy && scale == _scale) return;
|
|
8616
8689
|
navigate(cx, cy, scale);
|
|
8617
|
-
|
|
8690
|
+
triggerChangeEvent(data);
|
|
8618
8691
|
}
|
|
8619
8692
|
|
|
8620
8693
|
function navigate(cx, cy, scale) {
|
|
8621
8694
|
if (_strictBounds) {
|
|
8622
|
-
var full = fillOut(
|
|
8695
|
+
var full = fillOut(_fullBounds);
|
|
8623
8696
|
var minScale = full.height() / _strictBounds.height();
|
|
8624
8697
|
if (scale < minScale) {
|
|
8625
8698
|
var dx = cx - _cx;
|
|
@@ -8641,7 +8714,7 @@
|
|
|
8641
8714
|
_scale = scale;
|
|
8642
8715
|
}
|
|
8643
8716
|
|
|
8644
|
-
function
|
|
8717
|
+
function triggerChangeEvent(data) {
|
|
8645
8718
|
data = data || {};
|
|
8646
8719
|
_self.dispatchEvent('change', data);
|
|
8647
8720
|
}
|
|
@@ -8649,10 +8722,10 @@
|
|
|
8649
8722
|
// stop zooming before rounding errors become too obvious
|
|
8650
8723
|
function maxScale() {
|
|
8651
8724
|
var minPixelScale = 1e-16;
|
|
8652
|
-
var xmax = maxAbs(
|
|
8653
|
-
var ymax = maxAbs(
|
|
8654
|
-
var xscale =
|
|
8655
|
-
var yscale =
|
|
8725
|
+
var xmax = maxAbs(_fullBounds.xmin, _fullBounds.xmax, _fullBounds.centerX());
|
|
8726
|
+
var ymax = maxAbs(_fullBounds.ymin, _fullBounds.ymax, _fullBounds.centerY());
|
|
8727
|
+
var xscale = _fullBounds.width() / _position.width() / xmax / minPixelScale;
|
|
8728
|
+
var yscale = _fullBounds.height() / _position.height() / ymax / minPixelScale;
|
|
8656
8729
|
return Math.min(xscale, yscale);
|
|
8657
8730
|
}
|
|
8658
8731
|
|
|
@@ -8669,7 +8742,7 @@
|
|
|
8669
8742
|
if (_frame) {
|
|
8670
8743
|
full = fillOutFrameBounds(_frame);
|
|
8671
8744
|
} else {
|
|
8672
|
-
full = fillOut(
|
|
8745
|
+
full = fillOut(_fullBounds);
|
|
8673
8746
|
}
|
|
8674
8747
|
if (_strictBounds) {
|
|
8675
8748
|
full = fitIn(full, _strictBounds);
|
|
@@ -8689,9 +8762,9 @@
|
|
|
8689
8762
|
return bounds;
|
|
8690
8763
|
}
|
|
8691
8764
|
|
|
8692
|
-
function padBounds(b,
|
|
8693
|
-
var wpix = _position.width() - 2 *
|
|
8694
|
-
hpix = _position.height() - 2 *
|
|
8765
|
+
function padBounds(b, marginpix) {
|
|
8766
|
+
var wpix = _position.width() - 2 * marginpix,
|
|
8767
|
+
hpix = _position.height() - 2 * marginpix,
|
|
8695
8768
|
xpad, ypad, b2;
|
|
8696
8769
|
if (wpix <= 0 || hpix <= 0) {
|
|
8697
8770
|
return new Bounds(0, 0, 0, 0);
|
|
@@ -8699,8 +8772,8 @@
|
|
|
8699
8772
|
b = b.clone();
|
|
8700
8773
|
b2 = b.clone();
|
|
8701
8774
|
b2.fillOut(wpix / hpix);
|
|
8702
|
-
xpad = b2.width() / wpix *
|
|
8703
|
-
ypad = b2.height() / hpix *
|
|
8775
|
+
xpad = b2.width() / wpix * marginpix;
|
|
8776
|
+
ypad = b2.height() / hpix * marginpix;
|
|
8704
8777
|
b.padBounds(xpad, ypad, xpad, ypad);
|
|
8705
8778
|
return b;
|
|
8706
8779
|
}
|
|
@@ -8830,8 +8903,8 @@
|
|
|
8830
8903
|
function getPixelColorFunction() {
|
|
8831
8904
|
var canv = El('canvas').node();
|
|
8832
8905
|
canv.width = canv.height = 1;
|
|
8906
|
+
var ctx = canv.getContext('2d', {willReadFrequently: true});
|
|
8833
8907
|
return function(col) {
|
|
8834
|
-
var ctx = canv.getContext('2d');
|
|
8835
8908
|
var pixels;
|
|
8836
8909
|
ctx.fillStyle = col;
|
|
8837
8910
|
ctx.fillRect(0, 0, 1, 1);
|
|
@@ -8843,6 +8916,8 @@
|
|
|
8843
8916
|
function DisplayCanvas() {
|
|
8844
8917
|
var _self = El('canvas'),
|
|
8845
8918
|
_canvas = _self.node(),
|
|
8919
|
+
// TODO: compare performance of willReadFrequently setting
|
|
8920
|
+
// _ctx = _canvas.getContext('2d', {willReadFrequently: true}),
|
|
8846
8921
|
_ctx = _canvas.getContext('2d'),
|
|
8847
8922
|
_pixelColor = getPixelColorFunction(),
|
|
8848
8923
|
_ext;
|
|
@@ -8997,7 +9072,6 @@
|
|
|
8997
9072
|
var w = _canvas.width,
|
|
8998
9073
|
h = _canvas.height,
|
|
8999
9074
|
rgba = _pixelColor(color),
|
|
9000
|
-
// imageData = _ctx.createImageData(w, h),
|
|
9001
9075
|
imageData = _ctx.getImageData(0, 0, w, h),
|
|
9002
9076
|
pixels = new Uint32Array(imageData.data.buffer),
|
|
9003
9077
|
shp, x, y, i, j, n, m,
|
|
@@ -10083,7 +10157,6 @@
|
|
|
10083
10157
|
return bl.concat(tr);
|
|
10084
10158
|
}
|
|
10085
10159
|
|
|
10086
|
-
|
|
10087
10160
|
function initMap() {
|
|
10088
10161
|
if (!enabled() || map || loading) return;
|
|
10089
10162
|
loading = true;
|
|
@@ -10177,17 +10250,15 @@
|
|
|
10177
10250
|
map = this,
|
|
10178
10251
|
_mouse = new MouseArea(el, position),
|
|
10179
10252
|
_ext = new MapExtent(position),
|
|
10180
|
-
_hit = new InteractiveSelection(gui, _ext, _mouse),
|
|
10181
10253
|
_nav = new MapNav(gui, _ext, _mouse),
|
|
10182
|
-
_boxTool = new BoxTool(gui, _ext, _nav),
|
|
10183
|
-
_selectionTool = new SelectionTool(gui, _ext, _hit),
|
|
10184
10254
|
_visibleLayers = [], // cached visible map layers
|
|
10185
10255
|
_fullBounds = null,
|
|
10256
|
+
_hit,
|
|
10257
|
+
_basemap,
|
|
10186
10258
|
_intersectionLyr, _activeLyr, _overlayLyr,
|
|
10187
|
-
|
|
10188
|
-
_dynamicCRS;
|
|
10259
|
+
_stack, _dynamicCRS;
|
|
10189
10260
|
|
|
10190
|
-
|
|
10261
|
+
_basemap = new Basemap(gui, _ext);
|
|
10191
10262
|
|
|
10192
10263
|
if (gui.options.showMouseCoordinates) {
|
|
10193
10264
|
new CoordinatesDisplay(gui, _ext, _mouse);
|
|
@@ -10326,16 +10397,16 @@
|
|
|
10326
10397
|
|
|
10327
10398
|
_activeLyr = getDisplayLayer(e.layer, e.dataset, getDisplayOptions());
|
|
10328
10399
|
_activeLyr.style = getActiveStyle(_activeLyr.layer, gui.state.dark_basemap);
|
|
10329
|
-
|
|
10330
10400
|
_activeLyr.active = true;
|
|
10331
|
-
|
|
10332
|
-
_hit.setLayer(_activeLyr);
|
|
10401
|
+
|
|
10333
10402
|
if (e.flags.same_table) {
|
|
10334
10403
|
// data may have changed; if popup is open, it needs to be refreshed
|
|
10335
10404
|
gui.dispatchEvent('popup-needs-refresh');
|
|
10336
|
-
} else {
|
|
10405
|
+
} else if (_hit) {
|
|
10406
|
+
_hit.setLayer(_activeLyr);
|
|
10337
10407
|
_hit.clearSelection();
|
|
10338
10408
|
}
|
|
10409
|
+
|
|
10339
10410
|
updateVisibleMapLayers();
|
|
10340
10411
|
fullBounds = getFullBounds();
|
|
10341
10412
|
|
|
@@ -10352,7 +10423,8 @@
|
|
|
10352
10423
|
} else {
|
|
10353
10424
|
_nav.setZoomFactor(1);
|
|
10354
10425
|
}
|
|
10355
|
-
_ext.
|
|
10426
|
+
_ext.setFullBounds(fullBounds, getStrictBounds()); // update 'home' button extent
|
|
10427
|
+
|
|
10356
10428
|
_fullBounds = fullBounds;
|
|
10357
10429
|
if (needReset) {
|
|
10358
10430
|
_ext.reset();
|
|
@@ -10368,19 +10440,13 @@
|
|
|
10368
10440
|
gui.buttons.show();
|
|
10369
10441
|
|
|
10370
10442
|
if (opts.inspectorControl) {
|
|
10371
|
-
|
|
10372
|
-
|
|
10373
|
-
|
|
10374
|
-
|
|
10375
|
-
// Refresh the display if a style variable has been changed interactively
|
|
10376
|
-
if (internal.isSupportedSvgStyleProperty(e.field)) {
|
|
10377
|
-
drawLayers();
|
|
10378
|
-
}
|
|
10379
|
-
});
|
|
10380
|
-
}
|
|
10381
|
-
|
|
10382
|
-
if (gui.interaction) {
|
|
10443
|
+
_hit = new InteractiveSelection(gui, _ext, _mouse),
|
|
10444
|
+
new InspectionControl2(gui, _hit);
|
|
10445
|
+
new SelectionTool(gui, _ext, _hit),
|
|
10446
|
+
new BoxTool(gui, _ext, _nav),
|
|
10383
10447
|
initInteractiveEditing(gui, _ext, _hit);
|
|
10448
|
+
// initDrawing(gui, _ext, _mouse, _hit);
|
|
10449
|
+
_hit.on('change', updateOverlayLayer);
|
|
10384
10450
|
}
|
|
10385
10451
|
|
|
10386
10452
|
_ext.on('change', function(e) {
|
|
@@ -10392,8 +10458,6 @@
|
|
|
10392
10458
|
drawLayers('nav');
|
|
10393
10459
|
});
|
|
10394
10460
|
|
|
10395
|
-
_hit.on('change', updateOverlayLayer);
|
|
10396
|
-
|
|
10397
10461
|
gui.on('resize', function() {
|
|
10398
10462
|
position.update(); // kludge to detect new map size after console toggle
|
|
10399
10463
|
});
|
|
@@ -10438,7 +10502,7 @@
|
|
|
10438
10502
|
var cy = viewBounds.centerY();
|
|
10439
10503
|
rec.bbox = [cx - w/2, cy - h/2, cx + w/2, cy + h/2];
|
|
10440
10504
|
_ext.setFrame(getFrameData());
|
|
10441
|
-
_ext.
|
|
10505
|
+
_ext.setFullBounds(new Bounds(rec.bbox));
|
|
10442
10506
|
_ext.reset();
|
|
10443
10507
|
}
|
|
10444
10508
|
|
|
@@ -10450,39 +10514,33 @@
|
|
|
10450
10514
|
}
|
|
10451
10515
|
|
|
10452
10516
|
function getFullBounds() {
|
|
10453
|
-
var b = new Bounds();
|
|
10454
|
-
var marginPct = 0.025;
|
|
10455
|
-
var pad = 1e-4;
|
|
10456
10517
|
if (isPreviewView()) {
|
|
10457
10518
|
return internal.getFrameLayerBounds(internal.findFrameLayer(model));
|
|
10458
10519
|
}
|
|
10520
|
+
var b = new Bounds();
|
|
10459
10521
|
getDrawableContentLayers().forEach(function(lyr) {
|
|
10460
10522
|
b.mergeBounds(lyr.bounds);
|
|
10461
|
-
if (isTableView()) {
|
|
10462
|
-
marginPct = getTableMargin(lyr.layer);
|
|
10463
|
-
}
|
|
10464
10523
|
});
|
|
10524
|
+
|
|
10465
10525
|
if (!b.hasBounds()) {
|
|
10466
10526
|
// assign bounds to empty layers, to prevent rendering errors downstream
|
|
10467
10527
|
b.setBounds(0,0,0,0);
|
|
10468
10528
|
}
|
|
10469
|
-
// Inflate display bounding box by a tiny amount (gives extent to single-point layers and collapsed shapes)
|
|
10470
|
-
b.padBounds(pad,pad,pad,pad);
|
|
10471
|
-
// add margin
|
|
10472
|
-
b.scale(1 + marginPct * 2);
|
|
10473
|
-
return b;
|
|
10474
|
-
}
|
|
10475
10529
|
|
|
10476
|
-
|
|
10477
|
-
|
|
10478
|
-
var
|
|
10479
|
-
var
|
|
10480
|
-
if (
|
|
10481
|
-
|
|
10482
|
-
|
|
10483
|
-
pct = 0.1;
|
|
10530
|
+
// add margin
|
|
10531
|
+
// use larger margin for small sizes
|
|
10532
|
+
var widthPx = _ext.width();
|
|
10533
|
+
var marginPct = widthPx < 700 && 3.5 || widthPx < 800 && 3 || 2.5;
|
|
10534
|
+
if (isTableView()) {
|
|
10535
|
+
var n = internal.getFeatureCount(_activeLyr.layer);
|
|
10536
|
+
marginPct = n < 5 && 20 || n < 100 && 10 || 4;
|
|
10484
10537
|
}
|
|
10485
|
-
|
|
10538
|
+
b.scale(1 + marginPct / 100 * 2);
|
|
10539
|
+
|
|
10540
|
+
// Inflate display bounding box by a tiny amount (gives extent to single-point layers and collapsed shapes)
|
|
10541
|
+
b.padBounds(1e-4, 1e-4, 1e-4, 1e-4);
|
|
10542
|
+
|
|
10543
|
+
return b;
|
|
10486
10544
|
}
|
|
10487
10545
|
|
|
10488
10546
|
function isActiveLayer(lyr) {
|
|
@@ -10615,7 +10673,7 @@
|
|
|
10615
10673
|
if (layersMayHaveChanged) {
|
|
10616
10674
|
// kludge to handle layer visibility toggling
|
|
10617
10675
|
_ext.setFrame(isPreviewView() ? getFrameData() : null);
|
|
10618
|
-
_ext.
|
|
10676
|
+
_ext.setFullBounds(getFullBounds(), getStrictBounds());
|
|
10619
10677
|
updateLayerStyles(contentLayers);
|
|
10620
10678
|
updateLayerStackOrder(model.getLayers());// update stack_id property of all layers
|
|
10621
10679
|
}
|