mapshaper 0.6.108 → 0.6.110
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/bin/mapshaper-gui +3 -2
- package/mapshaper.js +1782 -516
- package/package.json +2 -1
- package/www/assets/SourceSans3-VariableFont_wght.ttf +0 -0
- package/www/elements.css +1 -1
- package/www/index.html +45 -51
- package/www/mapshaper-gui.js +200 -25
- package/www/mapshaper.js +1782 -516
- package/www/page.css +21 -23
- package/www/assets/SourceSansPro-Regular.woff +0 -0
- package/www/assets/SourceSansPro-Semibold.woff +0 -0
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "mapshaper",
|
|
3
|
-
"version": "0.6.
|
|
3
|
+
"version": "0.6.110",
|
|
4
4
|
"description": "A tool for editing vector datasets for mapping and GIS.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"shapefile",
|
|
@@ -43,6 +43,7 @@
|
|
|
43
43
|
"@tmcw/togeojson": "^5.6.0",
|
|
44
44
|
"@xmldom/xmldom": "^0.8.6",
|
|
45
45
|
"adm-zip": "^0.5.9",
|
|
46
|
+
"big.js": "^7.0.1",
|
|
46
47
|
"commander": "7.0.0",
|
|
47
48
|
"cookies": "^0.8.0",
|
|
48
49
|
"d3-color": "3.1.0",
|
|
Binary file
|
package/www/elements.css
CHANGED
package/www/index.html
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
<!DOCTYPE html>
|
|
2
|
-
<html>
|
|
2
|
+
<html lang="en">
|
|
3
3
|
<head>
|
|
4
4
|
<title>mapshaper</title>
|
|
5
5
|
<meta name="Description" content="A tool for topologically aware shape simplification. Reads and writes Shapefile, GeoJSON and TopoJSON formats.">
|
|
@@ -42,24 +42,6 @@
|
|
|
42
42
|
<svg id="ribbon-icon" data-name="Layer 1" xmlns="http://www.w3.org/2000/svg" width="15" height="25" viewBox="0 1 15 20">
|
|
43
43
|
<polygon points="8 14.5 13 19 13 4 3 4 3 19 8 14.5" fill="#30d4ef"/>
|
|
44
44
|
</svg>
|
|
45
|
-
|
|
46
|
-
<defs>
|
|
47
|
-
<style>
|
|
48
|
-
.cls-1 {
|
|
49
|
-
fill: #0c0a0a;
|
|
50
|
-
}
|
|
51
|
-
</style>
|
|
52
|
-
</defs>
|
|
53
|
-
<g id="left_arrow">
|
|
54
|
-
<polygon class="cls-1" points="0.5 6 6.5 11.5 6.5 0.5 0.5 6"/>
|
|
55
|
-
</g>
|
|
56
|
-
</svg>
|
|
57
|
-
|
|
58
|
-
<svg id="info-menu-icon" xmlns="http://www.w3.org/2000/svg" width="8" height="12" viewBox="0 0 8 12">
|
|
59
|
-
<g id="left_arrow">
|
|
60
|
-
<polygon class="cls-1" points="0.5 6 6.5 11.5 6.5 0.5 0.5 6"/>
|
|
61
|
-
</g>
|
|
62
|
-
</svg>
|
|
63
45
|
|
|
64
46
|
</div>
|
|
65
47
|
|
|
@@ -70,13 +52,15 @@
|
|
|
70
52
|
|
|
71
53
|
<div class="simplify-control-wrapper"><div class="simplify-control"><div class="header-btn btn simplify-settings-btn">Settings</div>
|
|
72
54
|
<div class="slider">
|
|
73
|
-
<div class="handle"><img src="images/slider_handle_v1.png" alt=""
|
|
55
|
+
<div class="handle"><img src="images/slider_handle_v1.png" alt=""></div>
|
|
74
56
|
<div class="track"></div>
|
|
75
57
|
</div>
|
|
76
|
-
<input type="text" value="label" class="clicktext"
|
|
58
|
+
<input type="text" value="label" class="clicktext">
|
|
59
|
+
<!-- <div class="header-btn btn simplify-done-btn">Done</div> -->
|
|
77
60
|
</div></div>
|
|
78
61
|
<div id="mode-buttons" class="page-header-buttons">
|
|
79
|
-
<span class="
|
|
62
|
+
<!-- <span class="project-btn header-btn btn">Project</span><span class="separator"> -->
|
|
63
|
+
<span class="console-btn header-btn btn">Console</span><span class="display-btn header-btn btn">Display</span><span class="separator"></span><span class="separator"></span></span><span class="simplify-btn header-btn btn">Simplify</span><span class="separator"></span><span class="export-btn header-btn btn">Export</span>
|
|
80
64
|
</div>
|
|
81
65
|
<div id="splash-buttons" class="page-header-buttons">
|
|
82
66
|
<a href="https://github.com/mbloch/mapshaper/wiki"><span id="wiki-btn" class="header-btn btn">Wiki</span></a><span class="separator"></span><a href="https://github.com/mbloch/mapshaper"><span id="github-btn" class="header-btn btn">GitHub</span></a>
|
|
@@ -96,8 +80,8 @@
|
|
|
96
80
|
<div class="layer-menu">
|
|
97
81
|
<h3>Layers</h3>
|
|
98
82
|
<div class="pin-all pinnable">
|
|
99
|
-
<img class="eye-btn black-eye" src="images/eye.png">
|
|
100
|
-
<img class="eye-btn green-eye" src="images/eye2.png">
|
|
83
|
+
<img class="eye-btn black-eye" src="images/eye.png" alt="">
|
|
84
|
+
<img class="eye-btn green-eye" src="images/eye2.png" alt="">
|
|
101
85
|
</div>
|
|
102
86
|
<div class="layer-list"></div>
|
|
103
87
|
<!-- <h4>Sources</h4> -->
|
|
@@ -146,7 +130,7 @@
|
|
|
146
130
|
<div class="info-box">
|
|
147
131
|
<div class="close2-btn"></div>
|
|
148
132
|
<h3>Export options</h3>
|
|
149
|
-
<div class=export-layers>
|
|
133
|
+
<div class="export-layers">
|
|
150
134
|
<h4 class="menu-title">Layers</h4>
|
|
151
135
|
<div class="export-layer-list option-menu"></div>
|
|
152
136
|
</div>
|
|
@@ -161,8 +145,8 @@
|
|
|
161
145
|
|
|
162
146
|
<div style="height:11px"></div>
|
|
163
147
|
|
|
164
|
-
<div class="option-menu"><input type="text" class="text-input advanced-options" placeholder="command line options"
|
|
165
|
-
<a href="https://github.com/mbloch/mapshaper/wiki/Command-Reference#-o-output" target="
|
|
148
|
+
<div class="option-menu"><input type="text" class="text-input advanced-options" placeholder="command line options">
|
|
149
|
+
<a href="https://github.com/mbloch/mapshaper/wiki/Command-Reference#-o-output" target="mapshaper_output_docs">
|
|
166
150
|
<div class="tip-button">?<div class="tip-anchor">
|
|
167
151
|
<div class="tip">Enter options from the command line interface for
|
|
168
152
|
the -o command. Examples: bbox no-quantization
|
|
@@ -171,8 +155,8 @@ precision=0.001. Click to see all options.</div></div></div></a>
|
|
|
171
155
|
<!-- <div class="option-menu">
|
|
172
156
|
<input id="ofile-name" class="text-input" type="text" placeholder="output file name" />
|
|
173
157
|
</div> -->
|
|
174
|
-
<div><span id="save-preference" style="display: none;"><input type="checkbox"
|
|
175
|
-
<div><span id="save-to-clipboard" style="display: inline-block;"><input type="checkbox"
|
|
158
|
+
<div><span id="save-preference" style="display: none;"><input type="checkbox">choose output directory</span></div>
|
|
159
|
+
<div><span id="save-to-clipboard" style="display: inline-block;"><input type="checkbox">save to clipboard</span></div>
|
|
176
160
|
</div>
|
|
177
161
|
<div id="export-btn" class="btn dialog-btn" style="margin-top: 5px;">Export</div>
|
|
178
162
|
|
|
@@ -184,8 +168,8 @@ precision=0.001. Click to see all options.</div></div></div></a>
|
|
|
184
168
|
<div class="close2-btn"></div>
|
|
185
169
|
<h3>Display options</h3>
|
|
186
170
|
|
|
187
|
-
<div class=""><label
|
|
188
|
-
<div class=""><label
|
|
171
|
+
<div class=""><label><input type="checkbox" id="intersections-opt" class="checkbox intersections-opt">detect line intersections</label></div>
|
|
172
|
+
<div class=""><label><input type="checkbox" id="ghost-opt" class="checkbox ghost-opt">show reference lines</label></div>
|
|
189
173
|
|
|
190
174
|
<div class="basemap-opts">
|
|
191
175
|
<h4>Basemaps</h4>
|
|
@@ -202,18 +186,33 @@ precision=0.001. Click to see all options.</div></div></div></a>
|
|
|
202
186
|
</div>
|
|
203
187
|
</div>
|
|
204
188
|
|
|
189
|
+
<div class="project-options main-area popup-dialog popup-align-left">
|
|
190
|
+
<div class="info-box">
|
|
191
|
+
<div class="close2-btn"></div>
|
|
192
|
+
<h3>Projections</h3>
|
|
193
|
+
<div class="option-menu">
|
|
194
|
+
<div id="proj-list"></div>
|
|
195
|
+
<div id="proj-option-list"></div>
|
|
196
|
+
</div>
|
|
197
|
+
<div>
|
|
198
|
+
<div class="preview-btn btn dialog-btn">Preview</div>
|
|
199
|
+
<div class="apply-btn btn dialog-btn">Apply</div>
|
|
200
|
+
</div>
|
|
201
|
+
</div>
|
|
202
|
+
</div>
|
|
203
|
+
|
|
205
204
|
<div class="simplify-options main-area popup-dialog">
|
|
206
205
|
<div class="info-box">
|
|
207
206
|
<div class="close2-btn"></div>
|
|
208
207
|
<h3>Simplification</h3>
|
|
209
208
|
<div class="option-menu">
|
|
210
|
-
<div><label
|
|
209
|
+
<div><label><input type="checkbox" class="checkbox import-retain-opt" id="import-retain-opt">prevent shape removal</label>
|
|
211
210
|
<div class="tip-button">?<div class="tip-anchor">
|
|
212
211
|
<div class="tip">Prevent small polygon features from
|
|
213
212
|
disappearing at high simplification. Keeps
|
|
214
213
|
the largest ring of multi-ring features.
|
|
215
214
|
</div></div></div></div>
|
|
216
|
-
<div class="planar-opt-wrapper"><label
|
|
215
|
+
<div class="planar-opt-wrapper"><label><input type="checkbox" class="checkbox planar-opt" id="planar-opt">use planar geometry</label>
|
|
217
216
|
<div class="tip-button">?<div class="tip-anchor">
|
|
218
217
|
<div class="tip">Treat x, y values as Cartesian coordinates
|
|
219
218
|
on a plane, rather than as longitude, latitude
|
|
@@ -229,7 +228,7 @@ coordinates on a sphere.
|
|
|
229
228
|
distance of original lines. Good for
|
|
230
229
|
thinning dense points, but spikes
|
|
231
230
|
tend to form at high simplification.</div></div></div>
|
|
232
|
-
</div>
|
|
231
|
+
</div>
|
|
233
232
|
|
|
234
233
|
<div><label><input type="radio" name="method" value="visvalingam" class="radio">Visvalingam / effective area</label><div class="tip-button">?<div class="tip-anchor">
|
|
235
234
|
<div class="tip">Lines are simplified by iteratively
|
|
@@ -258,7 +257,7 @@ a smoother appearance.</div></div></div></div>
|
|
|
258
257
|
<div class="cancel-btn close2-btn"></div>
|
|
259
258
|
<h3 class="list-header">Import files</h3>
|
|
260
259
|
<div class="import-instructions">
|
|
261
|
-
<span><input type="checkbox" class="advanced-import-options"
|
|
260
|
+
<span><input type="checkbox" class="advanced-import-options">with advanced options</span>
|
|
262
261
|
<div class="mini-drop-area">
|
|
263
262
|
<div class="subtitle">Drop, paste or <span class="add-btn inline-btn btn"><span class="label-text">select</span></span> files to import.</div>
|
|
264
263
|
<div class="subtitle">Shapefile, GeoJSON, TopoJSON, KML and CSV formats are supported. Files can be zipped or gzipped.</div>
|
|
@@ -267,29 +266,24 @@ a smoother appearance.</div></div></div></div>
|
|
|
267
266
|
<div class="queued-file-section">
|
|
268
267
|
<!-- <h4>Files</h4> -->
|
|
269
268
|
<div class="dropped-file-list"></div>
|
|
270
|
-
|
|
271
269
|
<div class="option-menu">
|
|
272
|
-
|
|
273
|
-
<div id="path-import-options">
|
|
274
|
-
<!-- <h4>Options</h4> -->
|
|
270
|
+
<div id="path-import-options">
|
|
275
271
|
</div>
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
<a href="https://github.com/mbloch/mapshaper/wiki/Command-Reference#-i-input" target="_mapshaper_import_docs">
|
|
272
|
+
<div style="margin-top: 10px"><input type="text" class="text-input advanced-options" placeholder="import options">
|
|
273
|
+
<a href="https://github.com/mbloch/mapshaper/wiki/Command-Reference#-i-input" target="mapshaper_import_docs">
|
|
279
274
|
<div class="tip-button">?<div class="tip-anchor">
|
|
280
275
|
<div class="tip">Enter options from the command line
|
|
281
276
|
interface. Examples: <span id="import-option-examples">snap no-topology
|
|
282
|
-
encoding=big5</span>. Click to see all options.</div></div></div
|
|
277
|
+
encoding=big5</span>. Click to see all options.</div></div></div>
|
|
283
278
|
</a>
|
|
284
|
-
|
|
285
279
|
</div>
|
|
286
280
|
|
|
287
281
|
<!-- <div class="cancel-btn btn dialog-btn">Cancel</div>
|
|
288
282
|
<div class="add-btn btn dialog-btn">Select</div> -->
|
|
289
283
|
<div class="submit-btn btn dialog-btn default-btn disabled">Submit</div>
|
|
290
284
|
|
|
285
|
+
</div>
|
|
291
286
|
</div>
|
|
292
|
-
|
|
293
287
|
</div> <!-- .info-box -->
|
|
294
288
|
</div> <!-- import-options -->
|
|
295
289
|
|
|
@@ -310,14 +304,14 @@ encoding=big5</span>. Click to see all options.</div></div></div></div>
|
|
|
310
304
|
</div>
|
|
311
305
|
</div>
|
|
312
306
|
|
|
313
|
-
<div id="import-options-drop-area" class="main-area drop-area-wrapper hidden">
|
|
307
|
+
<div id="import-options-drop-area" class="main-area drop-area-wrapper hidden">
|
|
314
308
|
<div class="drop-area"></div>
|
|
315
309
|
</div>
|
|
316
310
|
|
|
317
|
-
<script src="basemap.js"
|
|
318
|
-
<script src="modules.js"
|
|
319
|
-
<script src="mapshaper.js"
|
|
320
|
-
<script src="manifest.js"
|
|
321
|
-
<script src="mapshaper-gui.js"
|
|
311
|
+
<script src="basemap.js"></script>
|
|
312
|
+
<script src="modules.js"></script>
|
|
313
|
+
<script src="mapshaper.js"></script>
|
|
314
|
+
<script src="manifest.js"></script>
|
|
315
|
+
<script src="mapshaper-gui.js"></script>
|
|
322
316
|
</body>
|
|
323
317
|
</html>
|
package/www/mapshaper-gui.js
CHANGED
|
@@ -2726,11 +2726,12 @@
|
|
|
2726
2726
|
// p1: [x, y] coords
|
|
2727
2727
|
// p2: [x, y] coords offset by 1x1 pixel
|
|
2728
2728
|
function formatCoordsForDisplay(p1, p2) {
|
|
2729
|
+
var maxD = 13;
|
|
2729
2730
|
var dx = Math.abs(p1[0] - p2[0]);
|
|
2730
2731
|
var dy = Math.abs(p1[1] - p2[1]);
|
|
2731
2732
|
var offs = (dx + dy) / 2;
|
|
2732
2733
|
var decimals = 0;
|
|
2733
|
-
while (offs < 1 && decimals
|
|
2734
|
+
while (offs < 1 && decimals <= maxD) {
|
|
2734
2735
|
offs *= 10;
|
|
2735
2736
|
decimals++;
|
|
2736
2737
|
}
|
|
@@ -3226,18 +3227,20 @@
|
|
|
3226
3227
|
}
|
|
3227
3228
|
|
|
3228
3229
|
// p1, p2: two points in source data CRS coords.
|
|
3229
|
-
function appendNewPath(lyr,
|
|
3230
|
+
function appendNewPath(lyr, points) {
|
|
3230
3231
|
var arcId = lyr.gui.displayArcs.size();
|
|
3231
3232
|
internal.appendEmptyArc(lyr.gui.displayArcs);
|
|
3232
3233
|
lyr.shapes.push([[arcId]]);
|
|
3233
3234
|
if (isProjectedLayer(lyr)) {
|
|
3234
3235
|
internal.appendEmptyArc(lyr.gui.source.dataset.arcs);
|
|
3235
3236
|
}
|
|
3236
|
-
|
|
3237
|
-
|
|
3237
|
+
points.forEach(function(p) {
|
|
3238
|
+
appendVertex$1(lyr, p);
|
|
3239
|
+
});
|
|
3238
3240
|
appendNewDataRecord(lyr);
|
|
3239
3241
|
}
|
|
3240
3242
|
|
|
3243
|
+
|
|
3241
3244
|
function deleteLastPath(lyr) {
|
|
3242
3245
|
var arcId = lyr.gui.displayArcs.size() - 1;
|
|
3243
3246
|
if (lyr.data) {
|
|
@@ -4309,7 +4312,9 @@
|
|
|
4309
4312
|
if (_unsimplifiedXX && action == 'simplify_drag_end') {
|
|
4310
4313
|
// re-use previously generated intersection data (optimization)
|
|
4311
4314
|
} else {
|
|
4315
|
+
// console.time('xx');
|
|
4312
4316
|
_unsimplifiedXX = internal.findSegmentIntersections(arcs, intersectionOpts);
|
|
4317
|
+
// console.timeEnd('xx');
|
|
4313
4318
|
}
|
|
4314
4319
|
}
|
|
4315
4320
|
showIntersections(_simplifiedXX || _unsimplifiedXX, e.layer, arcs);
|
|
@@ -4757,6 +4762,7 @@
|
|
|
4757
4762
|
if (_open) close();
|
|
4758
4763
|
menu.empty();
|
|
4759
4764
|
|
|
4765
|
+
|
|
4760
4766
|
if (openMenu && openMenu != this) {
|
|
4761
4767
|
openMenu.close();
|
|
4762
4768
|
}
|
|
@@ -5838,7 +5844,7 @@
|
|
|
5838
5844
|
empty: ['edit_polygons', 'edit_lines', 'edit_points', 'box'],
|
|
5839
5845
|
polygons: ['info', 'selection', 'box', 'edit_polygons'],
|
|
5840
5846
|
rectangles: ['info', 'selection', 'box', 'rectangles', 'edit_polygons'],
|
|
5841
|
-
lines: ['info', 'selection', 'box'
|
|
5847
|
+
lines: ['info', 'selection', 'box', 'edit_lines'], // 'snip_lines'
|
|
5842
5848
|
table: ['info', 'selection'],
|
|
5843
5849
|
labels: ['info', 'selection', 'box', 'labels', 'edit_points'],
|
|
5844
5850
|
points: ['info', 'selection', 'box', 'edit_points'] // , 'add-points'
|
|
@@ -5859,6 +5865,7 @@
|
|
|
5859
5865
|
edit_points: 'add/drag points',
|
|
5860
5866
|
edit_lines: 'draw/edit polylines',
|
|
5861
5867
|
edit_polygons: 'draw/edit polygons',
|
|
5868
|
+
snip_lines: 'snip polylines',
|
|
5862
5869
|
vertices: 'edit vertices',
|
|
5863
5870
|
selection: 'selection tool',
|
|
5864
5871
|
'add-points': 'add points',
|
|
@@ -5922,7 +5929,7 @@
|
|
|
5922
5929
|
};
|
|
5923
5930
|
|
|
5924
5931
|
this.modeUsesHitDetection = function(mode) {
|
|
5925
|
-
return ['info', 'selection', 'data', 'labels', 'edit_points', 'vertices', 'rectangles', 'edit_lines', 'edit_polygons'].includes(mode);
|
|
5932
|
+
return ['info', 'selection', 'data', 'labels', 'edit_points', 'vertices', 'rectangles', 'edit_lines', 'edit_polygons', 'snip_lines'].includes(mode);
|
|
5926
5933
|
};
|
|
5927
5934
|
|
|
5928
5935
|
this.modeUsesPopup = function(mode) {
|
|
@@ -6268,13 +6275,21 @@
|
|
|
6268
6275
|
|
|
6269
6276
|
function verbose() {
|
|
6270
6277
|
// verbose can be set globally with the -verbose command or separately for each command
|
|
6271
|
-
if (
|
|
6278
|
+
if (useVerbose()) {
|
|
6272
6279
|
message.apply(null, arguments);
|
|
6273
6280
|
}
|
|
6274
6281
|
}
|
|
6275
6282
|
|
|
6283
|
+
function useVerbose() {
|
|
6284
|
+
return getStashedVar('VERBOSE');
|
|
6285
|
+
}
|
|
6286
|
+
|
|
6287
|
+
function useDebug() {
|
|
6288
|
+
return getStashedVar('DEBUG');
|
|
6289
|
+
}
|
|
6290
|
+
|
|
6276
6291
|
function debug() {
|
|
6277
|
-
if (
|
|
6292
|
+
if (useDebug()) {
|
|
6278
6293
|
logArgs(arguments);
|
|
6279
6294
|
}
|
|
6280
6295
|
}
|
|
@@ -9952,7 +9967,7 @@
|
|
|
9952
9967
|
|
|
9953
9968
|
hit.on('contextmenu', function(e) {
|
|
9954
9969
|
if (!e.overMap || e.mode == 'edit_lines' || e.mode == 'edit_polygons' ||
|
|
9955
|
-
e.mode == 'edit_points') {
|
|
9970
|
+
e.mode == 'edit_points' || e.mode == 'snip_lines') {
|
|
9956
9971
|
return;
|
|
9957
9972
|
}
|
|
9958
9973
|
var target = hit.getHitTarget();
|
|
@@ -10080,7 +10095,8 @@
|
|
|
10080
10095
|
return [lyr];
|
|
10081
10096
|
}
|
|
10082
10097
|
if (styleOpts.interactionMode == 'edit_lines' ||
|
|
10083
|
-
styleOpts.interactionMode == 'edit_polygons'
|
|
10098
|
+
styleOpts.interactionMode == 'edit_polygons' ||
|
|
10099
|
+
styleOpts.interactionMode == 'snip_lines') {
|
|
10084
10100
|
// special overlay: shape editing mode
|
|
10085
10101
|
lyr = getOverlayLayer(activeLyr, hitData.ids);
|
|
10086
10102
|
lyr.gui.style = getLineEditingStyle(hitData);
|
|
@@ -10581,7 +10597,7 @@
|
|
|
10581
10597
|
}
|
|
10582
10598
|
|
|
10583
10599
|
// pixel distance threshold for hovering near a vertex or segment midpoint
|
|
10584
|
-
var HOVER_THRESHOLD = 10;
|
|
10600
|
+
var HOVER_THRESHOLD$1 = 10;
|
|
10585
10601
|
|
|
10586
10602
|
function initLineEditing(gui, ext, hit) {
|
|
10587
10603
|
var hoverVertexInfo;
|
|
@@ -10643,7 +10659,7 @@
|
|
|
10643
10659
|
gui.on('redo_path_add', function(e) {
|
|
10644
10660
|
var target = hit.getHitTarget();
|
|
10645
10661
|
clearDrawingInfo();
|
|
10646
|
-
appendNewPath(target, e.p1, e.p2);
|
|
10662
|
+
appendNewPath(target, [e.p1, e.p2]);
|
|
10647
10663
|
deleteLastVertex(target); // second vertex is a placeholder
|
|
10648
10664
|
gui.undo.redo(); // add next vertex in the path
|
|
10649
10665
|
fullRedraw();
|
|
@@ -11042,7 +11058,7 @@
|
|
|
11042
11058
|
function startNewPath(p2) {
|
|
11043
11059
|
var target = hit.getHitTarget();
|
|
11044
11060
|
var p1 = hoverVertexInfo?.point || p2;
|
|
11045
|
-
appendNewPath(target, p1, p2);
|
|
11061
|
+
appendNewPath(target, [p1, p2]);
|
|
11046
11062
|
gui.dispatchEvent('path_add', {target, p1, p2});
|
|
11047
11063
|
drawingId = target.shapes.length - 1;
|
|
11048
11064
|
hit.setDrawingId(drawingId);
|
|
@@ -11118,7 +11134,7 @@
|
|
|
11118
11134
|
var i = data.ii[arcId];
|
|
11119
11135
|
var pathLen = data.nn[arcId];
|
|
11120
11136
|
var pixelDist = dist / ext.getPixelSize();
|
|
11121
|
-
if (pixelDist > HOVER_THRESHOLD || pathLen < 4) {
|
|
11137
|
+
if (pixelDist > HOVER_THRESHOLD$1 || pathLen < 4) {
|
|
11122
11138
|
return null;
|
|
11123
11139
|
}
|
|
11124
11140
|
return {
|
|
@@ -11137,7 +11153,7 @@
|
|
|
11137
11153
|
var p2 = target.gui.displayArcs.getVertex2(ids[0]);
|
|
11138
11154
|
var dist = geom.distance2D(p[0], p[1], p2[0], p2[1]);
|
|
11139
11155
|
var pixelDist = dist / ext.getPixelSize();
|
|
11140
|
-
if (pixelDist > HOVER_THRESHOLD) {
|
|
11156
|
+
if (pixelDist > HOVER_THRESHOLD$1) {
|
|
11141
11157
|
return null;
|
|
11142
11158
|
}
|
|
11143
11159
|
var point = getVertexCoords(target, ids[0]); // data coordinates
|
|
@@ -11175,7 +11191,7 @@
|
|
|
11175
11191
|
}
|
|
11176
11192
|
});
|
|
11177
11193
|
|
|
11178
|
-
if (closest.distance / ext.getPixelSize() > HOVER_THRESHOLD) {
|
|
11194
|
+
if (closest.distance / ext.getPixelSize() > HOVER_THRESHOLD$1) {
|
|
11179
11195
|
return null;
|
|
11180
11196
|
}
|
|
11181
11197
|
closest.point = translateDisplayPoint(target, closest.displayPoint);
|
|
@@ -11225,10 +11241,154 @@
|
|
|
11225
11241
|
}
|
|
11226
11242
|
}
|
|
11227
11243
|
|
|
11244
|
+
function snipLineAtVertex(lyr, fid, vid) {
|
|
11245
|
+
// find the feature part and arc containing the vertex
|
|
11246
|
+
// divide the one feature into two features
|
|
11247
|
+
// divide the arc into two new arcs
|
|
11248
|
+
var arc1, arc2;
|
|
11249
|
+
// divide the feature into two parts
|
|
11250
|
+
}
|
|
11251
|
+
|
|
11252
|
+
function mergeLinesAtVertex(lyr) {
|
|
11253
|
+
|
|
11254
|
+
}
|
|
11255
|
+
|
|
11256
|
+
// TODO: support snipping rings (by snipping in two places)
|
|
11257
|
+
|
|
11258
|
+
|
|
11259
|
+
// pixel distance threshold for hovering near a vertex or segment midpoint
|
|
11260
|
+
var HOVER_THRESHOLD = 10;
|
|
11261
|
+
|
|
11262
|
+
function initSnipTool(gui, ext, hit) {
|
|
11263
|
+
var _active = true;
|
|
11264
|
+
var hoverVertexInfo;
|
|
11265
|
+
var prevHoverEvent;
|
|
11266
|
+
|
|
11267
|
+
gui.on('interaction_mode_change', function(e) {
|
|
11268
|
+
if (active()) {
|
|
11269
|
+
turnOff();
|
|
11270
|
+
}
|
|
11271
|
+
// updateCursor();
|
|
11272
|
+
}, null, 10); // higher priority than hit control, so turnOff() has correct hit target
|
|
11273
|
+
|
|
11274
|
+
|
|
11275
|
+
// hover event highlights the nearest point in close proximity to the pointer
|
|
11276
|
+
// ... or the closest point along the segment (for adding a new vertex)
|
|
11277
|
+
hit.on('hover', function(e) {
|
|
11278
|
+
if (!active()) return;
|
|
11279
|
+
|
|
11280
|
+
// highlight nearby snappable vertex (the closest vertex on a nearby line,
|
|
11281
|
+
// or the first vertex of the current drawing path if not near a line)
|
|
11282
|
+
hoverVertexInfo = e.id >= 0 && findDraggableVertices(e) ||
|
|
11283
|
+
e.id >= 0 && findInterpolatedPoint(e);
|
|
11284
|
+
if (hoverVertexInfo) {
|
|
11285
|
+
// hovering near a vertex: highlight the vertex
|
|
11286
|
+
hit.setHoverVertex(hoverVertexInfo.displayPoint, hoverVertexInfo.type);
|
|
11287
|
+
} else {
|
|
11288
|
+
clearHoverVertex();
|
|
11289
|
+
}
|
|
11290
|
+
// updateCursor();
|
|
11291
|
+
prevHoverEvent = e;
|
|
11292
|
+
}, null, 100);
|
|
11293
|
+
|
|
11294
|
+
hit.on('click', function(e) {
|
|
11295
|
+
if (!active() || !hoverVertexInfo) return;
|
|
11296
|
+
var target = hit.getHitTarget();
|
|
11297
|
+
if (vertexIsEndpoint(hoverVertexInfo, target)) {
|
|
11298
|
+
// TODO: don't allow hovering on endpoints
|
|
11299
|
+
return;
|
|
11300
|
+
}
|
|
11301
|
+
|
|
11302
|
+
if (hoverVertexInfo.type == 'interpolated') {
|
|
11303
|
+
insertVertex$1(target, hoverVertexInfo.i, hoverVertexInfo.point);
|
|
11304
|
+
hoverVertexInfo.ids = [hoverVertexInfo.i];
|
|
11305
|
+
}
|
|
11306
|
+
|
|
11307
|
+
snipLineAtVertex(target, e.id, hoverVertexInfo.ids[0]);
|
|
11308
|
+
|
|
11309
|
+
hit.setHoverVertex(hoverVertexInfo.displayPoint, hoverVertexInfo.type);
|
|
11310
|
+
|
|
11311
|
+
});
|
|
11312
|
+
|
|
11313
|
+
// return data on the nearest vertex (or identical vertices) to the pointer
|
|
11314
|
+
// (if within a distance threshold)
|
|
11315
|
+
//
|
|
11316
|
+
function findDraggableVertices(e) {
|
|
11317
|
+
var target = hit.getHitTarget();
|
|
11318
|
+
var shp = target.shapes[e.id];
|
|
11319
|
+
var p = ext.pixCoordsToMapCoords(e.x, e.y);
|
|
11320
|
+
var ids = internal.findNearestVertices(p, shp, target.gui.displayArcs);
|
|
11321
|
+
var p2 = target.gui.displayArcs.getVertex2(ids[0]);
|
|
11322
|
+
var dist = geom.distance2D(p[0], p[1], p2[0], p2[1]);
|
|
11323
|
+
var pixelDist = dist / ext.getPixelSize();
|
|
11324
|
+
if (pixelDist > HOVER_THRESHOLD) {
|
|
11325
|
+
return null;
|
|
11326
|
+
}
|
|
11327
|
+
var point = getVertexCoords(target, ids[0]); // data coordinates
|
|
11328
|
+
var displayPoint = target.gui.displayArcs.getVertex2(ids[0]);
|
|
11329
|
+
return {target, ids, point, displayPoint, type: 'vertex'};
|
|
11330
|
+
}
|
|
11331
|
+
|
|
11332
|
+
function findInterpolatedPoint(e) {
|
|
11333
|
+
var target = hit.getHitTarget();
|
|
11334
|
+
//// vertex insertion not supported with simplification
|
|
11335
|
+
// if (!target.arcs.isFlat()) return null;
|
|
11336
|
+
var p = ext.pixCoordsToMapCoords(e.x, e.y);
|
|
11337
|
+
var minDist = Infinity;
|
|
11338
|
+
var shp = target.shapes[e.id];
|
|
11339
|
+
var closest;
|
|
11340
|
+
internal.forEachSegmentInShape(shp, target.gui.displayArcs, function(i, j, xx, yy) {
|
|
11341
|
+
var x1 = xx[i],
|
|
11342
|
+
y1 = yy[i],
|
|
11343
|
+
x2 = xx[j],
|
|
11344
|
+
y2 = yy[j],
|
|
11345
|
+
p2 = internal.findClosestPointOnSeg(p[0], p[1], x1, y1, x2, y2, 0),
|
|
11346
|
+
dist = geom.distance2D(p2[0], p2[1], p[0], p[1]);
|
|
11347
|
+
if (dist < minDist) {
|
|
11348
|
+
minDist = dist;
|
|
11349
|
+
closest = {
|
|
11350
|
+
i: (i < j ? i : j) + 1, // insertion vertex id
|
|
11351
|
+
displayPoint: p2,
|
|
11352
|
+
distance: dist
|
|
11353
|
+
};
|
|
11354
|
+
}
|
|
11355
|
+
});
|
|
11356
|
+
|
|
11357
|
+
if (closest.distance / ext.getPixelSize() > HOVER_THRESHOLD) {
|
|
11358
|
+
return null;
|
|
11359
|
+
}
|
|
11360
|
+
closest.point = translateDisplayPoint(target, closest.displayPoint);
|
|
11361
|
+
closest.type = 'interpolated';
|
|
11362
|
+
closest.target = target;
|
|
11363
|
+
return closest;
|
|
11364
|
+
}
|
|
11365
|
+
|
|
11366
|
+
function vertexIsEndpoint(info, target) {
|
|
11367
|
+
var vId = info.ids[0];
|
|
11368
|
+
return internal.vertexIsArcStart(vId, target.gui.displayArcs) ||
|
|
11369
|
+
internal.vertexIsArcEnd(vId, target.gui.displayArcs);
|
|
11370
|
+
}
|
|
11371
|
+
|
|
11372
|
+
function clearHoverVertex() {
|
|
11373
|
+
hit.clearHoverVertex();
|
|
11374
|
+
hoverVertexInfo = null;
|
|
11375
|
+
}
|
|
11376
|
+
|
|
11377
|
+
function active() {
|
|
11378
|
+
return _active && gui.interaction.getMode() == 'snip_lines';
|
|
11379
|
+
}
|
|
11380
|
+
|
|
11381
|
+
function turnOff() {
|
|
11382
|
+
|
|
11383
|
+
}
|
|
11384
|
+
|
|
11385
|
+
}
|
|
11386
|
+
|
|
11228
11387
|
function initInteractiveEditing(gui, ext, hit) {
|
|
11229
11388
|
initLabelDragging(gui, ext, hit);
|
|
11230
11389
|
initPointEditing(gui, ext, hit);
|
|
11231
11390
|
initLineEditing(gui, ext, hit);
|
|
11391
|
+
initSnipTool(gui, ext, hit);
|
|
11232
11392
|
}
|
|
11233
11393
|
|
|
11234
11394
|
var darkStroke = "#334",
|
|
@@ -11560,11 +11720,13 @@
|
|
|
11560
11720
|
// stop zooming before rounding errors become too obvious
|
|
11561
11721
|
function maxScale() {
|
|
11562
11722
|
var minPixelScale = 1e-16;
|
|
11723
|
+
// var minPixelScale = 1e-17; // gets jumpy
|
|
11563
11724
|
var xmax = maxAbs(_fullBounds.xmin, _fullBounds.xmax, _fullBounds.centerX());
|
|
11564
11725
|
var ymax = maxAbs(_fullBounds.ymin, _fullBounds.ymax, _fullBounds.centerY());
|
|
11565
11726
|
var xscale = _fullBounds.width() / _position.width() / xmax / minPixelScale;
|
|
11566
11727
|
var yscale = _fullBounds.height() / _position.height() / ymax / minPixelScale;
|
|
11567
|
-
return Math.min(xscale, yscale);
|
|
11728
|
+
// return Math.min(xscale, yscale);
|
|
11729
|
+
return Math.max(xscale, yscale);
|
|
11568
11730
|
}
|
|
11569
11731
|
|
|
11570
11732
|
function maxAbs() {
|
|
@@ -11906,9 +12068,8 @@
|
|
|
11906
12068
|
var iter = new internal.ShapeIter(arcs);
|
|
11907
12069
|
var t = getScaledTransform(_ext);
|
|
11908
12070
|
var bounds = _ext.getBounds();
|
|
11909
|
-
var radius = (style.strokeWidth > 2 ? style.strokeWidth *
|
|
12071
|
+
var radius = (style.strokeWidth > 2 ? style.strokeWidth * 1 : 2.2) * GUI.getPixelRatio() * getScaledLineScale(_ext, style);
|
|
11910
12072
|
var color = style.strokeColor || 'black';
|
|
11911
|
-
|
|
11912
12073
|
var i, j, p;
|
|
11913
12074
|
_ctx.beginPath();
|
|
11914
12075
|
_ctx.fillStyle = color;
|
|
@@ -12167,8 +12328,8 @@
|
|
|
12167
12328
|
s = 1;
|
|
12168
12329
|
if (mapScale < 0.5) {
|
|
12169
12330
|
s *= Math.pow(mapScale + 0.5, 0.35);
|
|
12170
|
-
} else if (mapScale >
|
|
12171
|
-
s *= Math.pow(mapScale -
|
|
12331
|
+
} else if (mapScale > 30) {
|
|
12332
|
+
s *= Math.pow(mapScale - 29, 0.065);
|
|
12172
12333
|
}
|
|
12173
12334
|
return s;
|
|
12174
12335
|
}
|
|
@@ -12994,6 +13155,10 @@ GUI and setting the size and crop of SVG output.</p><div><input type="text" clas
|
|
|
12994
13155
|
var fullBounds;
|
|
12995
13156
|
var needReset;
|
|
12996
13157
|
|
|
13158
|
+
if (!updated) {
|
|
13159
|
+
return; // e.g. if command is run in console before data is loaded
|
|
13160
|
+
}
|
|
13161
|
+
|
|
12997
13162
|
if (arcsMayHaveChanged(e.flags)) {
|
|
12998
13163
|
// regenerate filtered arcs the next time they are needed for rendering
|
|
12999
13164
|
// delete e.dataset.gui.displayArcs
|
|
@@ -13099,15 +13264,17 @@ GUI and setting the size and crop of SVG output.</p><div><input type="text" clas
|
|
|
13099
13264
|
// add margin
|
|
13100
13265
|
// use larger margin for small sizes
|
|
13101
13266
|
var widthPx = _ext.width();
|
|
13102
|
-
var marginPct = widthPx < 700 &&
|
|
13267
|
+
var marginPct = widthPx < 700 && 4.5 || widthPx < 800 && 4 || 3.5;
|
|
13103
13268
|
if (isTableView()) {
|
|
13104
13269
|
var n = internal.getFeatureCount(_activeLyr);
|
|
13105
13270
|
marginPct = n < 5 && 20 || n < 100 && 10 || 4;
|
|
13106
13271
|
}
|
|
13107
13272
|
b.scale(1 + marginPct / 100 * 2);
|
|
13108
13273
|
|
|
13109
|
-
// Inflate display bounding box
|
|
13110
|
-
b.
|
|
13274
|
+
// Inflate display bounding box of single-point layers and collapsed shapes a bit
|
|
13275
|
+
if (b.width() === 0 || b.height() === 0) {
|
|
13276
|
+
b.padBounds(1e-4, 1e-4, 1e-4, 1e-4);
|
|
13277
|
+
}
|
|
13111
13278
|
return b;
|
|
13112
13279
|
}
|
|
13113
13280
|
|
|
@@ -13604,7 +13771,11 @@ GUI and setting the size and crop of SVG output.</p><div><input type="text" clas
|
|
|
13604
13771
|
}
|
|
13605
13772
|
}
|
|
13606
13773
|
|
|
13607
|
-
|
|
13774
|
+
function isOn() {
|
|
13775
|
+
return !!activeStyle;
|
|
13776
|
+
}
|
|
13777
|
+
|
|
13778
|
+
return {refresh, show: onUpdate, isOn};
|
|
13608
13779
|
}
|
|
13609
13780
|
|
|
13610
13781
|
function DisplayOptions(gui) {
|
|
@@ -13665,6 +13836,9 @@ GUI and setting the size and crop of SVG output.</p><div><input type="text" clas
|
|
|
13665
13836
|
};
|
|
13666
13837
|
}
|
|
13667
13838
|
|
|
13839
|
+
// import { ProjectOptions } from './gui-project-control';
|
|
13840
|
+
|
|
13841
|
+
|
|
13668
13842
|
function GuiInstance(container, opts) {
|
|
13669
13843
|
var gui = new ModeSwitcher();
|
|
13670
13844
|
opts = utils$1.extend({
|
|
@@ -13688,6 +13862,7 @@ GUI and setting the size and crop of SVG output.</p><div><input type="text" clas
|
|
|
13688
13862
|
gui.contextMenu = new ContextMenu();
|
|
13689
13863
|
gui.undo = new Undo(gui);
|
|
13690
13864
|
gui.map = new MshpMap(gui);
|
|
13865
|
+
// gui.project = new ProjectOptions(gui);
|
|
13691
13866
|
|
|
13692
13867
|
|
|
13693
13868
|
gui.state = {};
|