mapshaper 0.7.31 → 0.7.32
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 +45 -14
- package/package.json +1 -1
- package/www/mapshaper.js +45 -14
package/mapshaper.js
CHANGED
|
@@ -32938,6 +32938,10 @@ ${svg}
|
|
|
32938
32938
|
describe: 'shrinkage-correction (default 1; 0 = none, >1 exaggerates bends)',
|
|
32939
32939
|
type: 'number'
|
|
32940
32940
|
})
|
|
32941
|
+
.option('max-bend-angle', {
|
|
32942
|
+
describe: 'max bend between output segments in degrees (default is 8)',
|
|
32943
|
+
type: 'number'
|
|
32944
|
+
})
|
|
32941
32945
|
.option('planar', {
|
|
32942
32946
|
// describe: 'smooth decimal degree coords in 2D space (default is spherical)',
|
|
32943
32947
|
type: 'flag'
|
|
@@ -62587,20 +62591,25 @@ ${svg}
|
|
|
62587
62591
|
// chord * accumulatedTurn / 8 estimates the bow of a circular arc, and we also
|
|
62588
62592
|
// cut when it exceeds a fraction of the tolerance. Both tests are O(1) per dense
|
|
62589
62593
|
// vertex, so the pass stays O(n).
|
|
62590
|
-
var DENSE_STEP_FACTOR = 0.033; // dense sampling step = tolerance * this
|
|
62591
|
-
// resolve the sharpest
|
|
62592
|
-
// ~ the kernel scale)
|
|
62593
|
-
// angle filter can reach
|
|
62594
|
-
//
|
|
62595
|
-
// kept well under
|
|
62596
|
-
//
|
|
62597
|
-
|
|
62594
|
+
var DENSE_STEP_FACTOR = 0.033; // dense sampling step = tolerance * this at the
|
|
62595
|
+
// default bend angle. Must resolve the sharpest
|
|
62596
|
+
// smoothed feature (radius ~ the kernel scale)
|
|
62597
|
+
// finely enough that the angle filter can reach
|
|
62598
|
+
// the bend-angle joins: one dense segment turns
|
|
62599
|
+
// ~ this/0.4 radians there, kept well under the
|
|
62600
|
+
// bend angle so the discrete accumulation barely
|
|
62601
|
+
// overshoots the threshold. For a smaller-than-
|
|
62602
|
+
// default bend angle the step is refined in
|
|
62603
|
+
// proportion so the threshold stays reachable.
|
|
62604
|
+
var DEFAULT_BEND_ANGLE = 8 * Math.PI / 180; // keep a vertex after this much accumulated
|
|
62605
|
+
// turn (max turn between consecutive output
|
|
62606
|
+
// segments); user-overridable via max-bend-angle
|
|
62598
62607
|
var DEVIATION_FACTOR = 0.1; // sagitta guard: also cut a gentle bend that bows
|
|
62599
62608
|
// more than tolerance * this from its chord
|
|
62600
62609
|
|
|
62601
62610
|
// Smooth a single arc's coordinates.
|
|
62602
62611
|
// @xx, @yy: coordinate arrays (may be typed-array subarrays) for one arc.
|
|
62603
|
-
// @opts: {tolerance, method, spherical, closed, keepCorners}
|
|
62612
|
+
// @opts: {tolerance, method, spherical, closed, keepCorners, gain, maxBendAngle}
|
|
62604
62613
|
// Returns {xx: [], yy: []} with the smoothed coordinates. Endpoints of open
|
|
62605
62614
|
// arcs are preserved exactly (so shared topology nodes stay put); closed arcs
|
|
62606
62615
|
// are smoothed cyclically and returned closed (first point repeated at the end).
|
|
@@ -62615,6 +62624,16 @@ ${svg}
|
|
|
62615
62624
|
return g >= 0 ? g : 0;
|
|
62616
62625
|
}
|
|
62617
62626
|
|
|
62627
|
+
// Resolve the output bend-angle threshold from the user option (in degrees) to
|
|
62628
|
+
// radians. It caps the turn between consecutive output segments: a larger angle
|
|
62629
|
+
// keeps fewer vertices (coarser joins), a smaller one keeps more (smoother joins).
|
|
62630
|
+
// Non-positive or missing values fall back to the default.
|
|
62631
|
+
function resolveBendAngle(opts) {
|
|
62632
|
+
var deg = opts.maxBendAngle;
|
|
62633
|
+
if (deg === undefined || deg === null || !(deg > 0)) return DEFAULT_BEND_ANGLE;
|
|
62634
|
+
return deg * Math.PI / 180;
|
|
62635
|
+
}
|
|
62636
|
+
|
|
62618
62637
|
function smoothArcCoords(xx, yy, opts) {
|
|
62619
62638
|
var n = xx.length;
|
|
62620
62639
|
var origX = toArray(xx);
|
|
@@ -62627,12 +62646,18 @@ ${svg}
|
|
|
62627
62646
|
var closed = !!opts.closed;
|
|
62628
62647
|
var spherical = !!opts.spherical;
|
|
62629
62648
|
var keepCorners = !!opts.keepCorners;
|
|
62649
|
+
var bendAngle = resolveBendAngle(opts);
|
|
62630
62650
|
var ctx = {
|
|
62631
62651
|
tol: tol,
|
|
62632
62652
|
method: method,
|
|
62633
62653
|
spherical: spherical,
|
|
62634
62654
|
keepCorners: keepCorners,
|
|
62635
62655
|
gain: resolveGain(opts),
|
|
62656
|
+
bendAngle: bendAngle,
|
|
62657
|
+
// Refine the dense step for a smaller-than-default bend angle so one dense
|
|
62658
|
+
// segment still turns well under the threshold; never coarsen it beyond the
|
|
62659
|
+
// default (the angle filter alone thins the output for larger angles).
|
|
62660
|
+
denseStep: tol * DENSE_STEP_FACTOR * Math.min(1, bendAngle / DEFAULT_BEND_ANGLE),
|
|
62636
62661
|
radius: tol * WINDOW_RADIUS_FACTOR,
|
|
62637
62662
|
scale: (method == 'gaussian' ? GAUSSIAN_SIGMA_FACTOR : PAEK_SCALE_FACTOR) * tol
|
|
62638
62663
|
};
|
|
@@ -62864,7 +62889,7 @@ ${svg}
|
|
|
62864
62889
|
// "Output resampling" note above). Step 1 evaluates the smoother at a uniform
|
|
62865
62890
|
// dense step; step 2 makes one forward pass keeping the endpoints plus every
|
|
62866
62891
|
// interior vertex where the accumulated turn since the last kept vertex reaches
|
|
62867
|
-
//
|
|
62892
|
+
// the bend-angle threshold, or where the sagitta guard trips. @inputCount bounds the dense
|
|
62868
62893
|
// sampling (and thus the output). Returns one array per channel, ordered by
|
|
62869
62894
|
// increasing arc length, including both endpoints.
|
|
62870
62895
|
function sampleSmoothedCurve(src, a, b, closed, ctx, inputCount) {
|
|
@@ -62873,7 +62898,7 @@ ${svg}
|
|
|
62873
62898
|
var maxPoints = Math.max(inputCount, MIN_CLOSED_SEGMENTS) * MAX_OUTPUT_FACTOR;
|
|
62874
62899
|
|
|
62875
62900
|
// 1. dense uniform sampling of the smoothed curve
|
|
62876
|
-
var nDense = Math.ceil(span /
|
|
62901
|
+
var nDense = Math.ceil(span / ctx.denseStep) + 1;
|
|
62877
62902
|
if (nDense < MIN_CLOSED_SEGMENTS + 1) nDense = MIN_CLOSED_SEGMENTS + 1;
|
|
62878
62903
|
if (nDense > maxPoints) nDense = maxPoints;
|
|
62879
62904
|
if (nDense < 2) nDense = 2;
|
|
@@ -62883,7 +62908,7 @@ ${svg}
|
|
|
62883
62908
|
}
|
|
62884
62909
|
|
|
62885
62910
|
// 2. one-pass bend-angle filter
|
|
62886
|
-
var theta =
|
|
62911
|
+
var theta = ctx.bendAngle;
|
|
62887
62912
|
var epsDev = ctx.tol * DEVIATION_FACTOR;
|
|
62888
62913
|
var out = [];
|
|
62889
62914
|
for (var c = 0; c < K; c++) out.push([]);
|
|
@@ -63180,6 +63205,10 @@ ${svg}
|
|
|
63180
63205
|
if (opts.gain !== undefined && opts.gain !== null && !(opts.gain >= 0)) {
|
|
63181
63206
|
stop$1('Expected gain to be a number >= 0');
|
|
63182
63207
|
}
|
|
63208
|
+
if (opts.max_bend_angle !== undefined && opts.max_bend_angle !== null &&
|
|
63209
|
+
!(opts.max_bend_angle > 0)) {
|
|
63210
|
+
stop$1('Expected max-bend-angle to be a number > 0 (degrees)');
|
|
63211
|
+
}
|
|
63183
63212
|
var implicitlySmoothedNames = getImplicitlyTargetedLayerNames(dataset, targetLayers, layerHasPaths);
|
|
63184
63213
|
|
|
63185
63214
|
// Smoothing rewrites coordinates, so lock in any pending (non-destructive)
|
|
@@ -63210,7 +63239,8 @@ ${svg}
|
|
|
63210
63239
|
method: method,
|
|
63211
63240
|
spherical: spherical,
|
|
63212
63241
|
keepCorners: !!opts.keep_corners,
|
|
63213
|
-
gain: opts.gain
|
|
63242
|
+
gain: opts.gain,
|
|
63243
|
+
maxBendAngle: opts.max_bend_angle
|
|
63214
63244
|
});
|
|
63215
63245
|
|
|
63216
63246
|
if (implicitlySmoothedNames.length > 0) {
|
|
@@ -63237,6 +63267,7 @@ ${svg}
|
|
|
63237
63267
|
spherical: opts.spherical,
|
|
63238
63268
|
keepCorners: opts.keepCorners,
|
|
63239
63269
|
gain: opts.gain,
|
|
63270
|
+
maxBendAngle: opts.maxBendAngle,
|
|
63240
63271
|
closed: arcs.arcIsClosed(arcId)
|
|
63241
63272
|
});
|
|
63242
63273
|
nn.push(res.xx.length);
|
|
@@ -65053,7 +65084,7 @@ ${svg}
|
|
|
65053
65084
|
return name == 'rectangle' || name == 'rectangles' || name == 'filter' && opts.cleanup;
|
|
65054
65085
|
}
|
|
65055
65086
|
|
|
65056
|
-
var version = "0.7.
|
|
65087
|
+
var version = "0.7.32";
|
|
65057
65088
|
|
|
65058
65089
|
// Parse command line args into commands and run them
|
|
65059
65090
|
// Function takes an optional Node-style callback. A Promise is returned if no callback is given.
|
package/package.json
CHANGED
package/www/mapshaper.js
CHANGED
|
@@ -32938,6 +32938,10 @@ ${svg}
|
|
|
32938
32938
|
describe: 'shrinkage-correction (default 1; 0 = none, >1 exaggerates bends)',
|
|
32939
32939
|
type: 'number'
|
|
32940
32940
|
})
|
|
32941
|
+
.option('max-bend-angle', {
|
|
32942
|
+
describe: 'max bend between output segments in degrees (default is 8)',
|
|
32943
|
+
type: 'number'
|
|
32944
|
+
})
|
|
32941
32945
|
.option('planar', {
|
|
32942
32946
|
// describe: 'smooth decimal degree coords in 2D space (default is spherical)',
|
|
32943
32947
|
type: 'flag'
|
|
@@ -62587,20 +62591,25 @@ ${svg}
|
|
|
62587
62591
|
// chord * accumulatedTurn / 8 estimates the bow of a circular arc, and we also
|
|
62588
62592
|
// cut when it exceeds a fraction of the tolerance. Both tests are O(1) per dense
|
|
62589
62593
|
// vertex, so the pass stays O(n).
|
|
62590
|
-
var DENSE_STEP_FACTOR = 0.033; // dense sampling step = tolerance * this
|
|
62591
|
-
// resolve the sharpest
|
|
62592
|
-
// ~ the kernel scale)
|
|
62593
|
-
// angle filter can reach
|
|
62594
|
-
//
|
|
62595
|
-
// kept well under
|
|
62596
|
-
//
|
|
62597
|
-
|
|
62594
|
+
var DENSE_STEP_FACTOR = 0.033; // dense sampling step = tolerance * this at the
|
|
62595
|
+
// default bend angle. Must resolve the sharpest
|
|
62596
|
+
// smoothed feature (radius ~ the kernel scale)
|
|
62597
|
+
// finely enough that the angle filter can reach
|
|
62598
|
+
// the bend-angle joins: one dense segment turns
|
|
62599
|
+
// ~ this/0.4 radians there, kept well under the
|
|
62600
|
+
// bend angle so the discrete accumulation barely
|
|
62601
|
+
// overshoots the threshold. For a smaller-than-
|
|
62602
|
+
// default bend angle the step is refined in
|
|
62603
|
+
// proportion so the threshold stays reachable.
|
|
62604
|
+
var DEFAULT_BEND_ANGLE = 8 * Math.PI / 180; // keep a vertex after this much accumulated
|
|
62605
|
+
// turn (max turn between consecutive output
|
|
62606
|
+
// segments); user-overridable via max-bend-angle
|
|
62598
62607
|
var DEVIATION_FACTOR = 0.1; // sagitta guard: also cut a gentle bend that bows
|
|
62599
62608
|
// more than tolerance * this from its chord
|
|
62600
62609
|
|
|
62601
62610
|
// Smooth a single arc's coordinates.
|
|
62602
62611
|
// @xx, @yy: coordinate arrays (may be typed-array subarrays) for one arc.
|
|
62603
|
-
// @opts: {tolerance, method, spherical, closed, keepCorners}
|
|
62612
|
+
// @opts: {tolerance, method, spherical, closed, keepCorners, gain, maxBendAngle}
|
|
62604
62613
|
// Returns {xx: [], yy: []} with the smoothed coordinates. Endpoints of open
|
|
62605
62614
|
// arcs are preserved exactly (so shared topology nodes stay put); closed arcs
|
|
62606
62615
|
// are smoothed cyclically and returned closed (first point repeated at the end).
|
|
@@ -62615,6 +62624,16 @@ ${svg}
|
|
|
62615
62624
|
return g >= 0 ? g : 0;
|
|
62616
62625
|
}
|
|
62617
62626
|
|
|
62627
|
+
// Resolve the output bend-angle threshold from the user option (in degrees) to
|
|
62628
|
+
// radians. It caps the turn between consecutive output segments: a larger angle
|
|
62629
|
+
// keeps fewer vertices (coarser joins), a smaller one keeps more (smoother joins).
|
|
62630
|
+
// Non-positive or missing values fall back to the default.
|
|
62631
|
+
function resolveBendAngle(opts) {
|
|
62632
|
+
var deg = opts.maxBendAngle;
|
|
62633
|
+
if (deg === undefined || deg === null || !(deg > 0)) return DEFAULT_BEND_ANGLE;
|
|
62634
|
+
return deg * Math.PI / 180;
|
|
62635
|
+
}
|
|
62636
|
+
|
|
62618
62637
|
function smoothArcCoords(xx, yy, opts) {
|
|
62619
62638
|
var n = xx.length;
|
|
62620
62639
|
var origX = toArray(xx);
|
|
@@ -62627,12 +62646,18 @@ ${svg}
|
|
|
62627
62646
|
var closed = !!opts.closed;
|
|
62628
62647
|
var spherical = !!opts.spherical;
|
|
62629
62648
|
var keepCorners = !!opts.keepCorners;
|
|
62649
|
+
var bendAngle = resolveBendAngle(opts);
|
|
62630
62650
|
var ctx = {
|
|
62631
62651
|
tol: tol,
|
|
62632
62652
|
method: method,
|
|
62633
62653
|
spherical: spherical,
|
|
62634
62654
|
keepCorners: keepCorners,
|
|
62635
62655
|
gain: resolveGain(opts),
|
|
62656
|
+
bendAngle: bendAngle,
|
|
62657
|
+
// Refine the dense step for a smaller-than-default bend angle so one dense
|
|
62658
|
+
// segment still turns well under the threshold; never coarsen it beyond the
|
|
62659
|
+
// default (the angle filter alone thins the output for larger angles).
|
|
62660
|
+
denseStep: tol * DENSE_STEP_FACTOR * Math.min(1, bendAngle / DEFAULT_BEND_ANGLE),
|
|
62636
62661
|
radius: tol * WINDOW_RADIUS_FACTOR,
|
|
62637
62662
|
scale: (method == 'gaussian' ? GAUSSIAN_SIGMA_FACTOR : PAEK_SCALE_FACTOR) * tol
|
|
62638
62663
|
};
|
|
@@ -62864,7 +62889,7 @@ ${svg}
|
|
|
62864
62889
|
// "Output resampling" note above). Step 1 evaluates the smoother at a uniform
|
|
62865
62890
|
// dense step; step 2 makes one forward pass keeping the endpoints plus every
|
|
62866
62891
|
// interior vertex where the accumulated turn since the last kept vertex reaches
|
|
62867
|
-
//
|
|
62892
|
+
// the bend-angle threshold, or where the sagitta guard trips. @inputCount bounds the dense
|
|
62868
62893
|
// sampling (and thus the output). Returns one array per channel, ordered by
|
|
62869
62894
|
// increasing arc length, including both endpoints.
|
|
62870
62895
|
function sampleSmoothedCurve(src, a, b, closed, ctx, inputCount) {
|
|
@@ -62873,7 +62898,7 @@ ${svg}
|
|
|
62873
62898
|
var maxPoints = Math.max(inputCount, MIN_CLOSED_SEGMENTS) * MAX_OUTPUT_FACTOR;
|
|
62874
62899
|
|
|
62875
62900
|
// 1. dense uniform sampling of the smoothed curve
|
|
62876
|
-
var nDense = Math.ceil(span /
|
|
62901
|
+
var nDense = Math.ceil(span / ctx.denseStep) + 1;
|
|
62877
62902
|
if (nDense < MIN_CLOSED_SEGMENTS + 1) nDense = MIN_CLOSED_SEGMENTS + 1;
|
|
62878
62903
|
if (nDense > maxPoints) nDense = maxPoints;
|
|
62879
62904
|
if (nDense < 2) nDense = 2;
|
|
@@ -62883,7 +62908,7 @@ ${svg}
|
|
|
62883
62908
|
}
|
|
62884
62909
|
|
|
62885
62910
|
// 2. one-pass bend-angle filter
|
|
62886
|
-
var theta =
|
|
62911
|
+
var theta = ctx.bendAngle;
|
|
62887
62912
|
var epsDev = ctx.tol * DEVIATION_FACTOR;
|
|
62888
62913
|
var out = [];
|
|
62889
62914
|
for (var c = 0; c < K; c++) out.push([]);
|
|
@@ -63180,6 +63205,10 @@ ${svg}
|
|
|
63180
63205
|
if (opts.gain !== undefined && opts.gain !== null && !(opts.gain >= 0)) {
|
|
63181
63206
|
stop$1('Expected gain to be a number >= 0');
|
|
63182
63207
|
}
|
|
63208
|
+
if (opts.max_bend_angle !== undefined && opts.max_bend_angle !== null &&
|
|
63209
|
+
!(opts.max_bend_angle > 0)) {
|
|
63210
|
+
stop$1('Expected max-bend-angle to be a number > 0 (degrees)');
|
|
63211
|
+
}
|
|
63183
63212
|
var implicitlySmoothedNames = getImplicitlyTargetedLayerNames(dataset, targetLayers, layerHasPaths);
|
|
63184
63213
|
|
|
63185
63214
|
// Smoothing rewrites coordinates, so lock in any pending (non-destructive)
|
|
@@ -63210,7 +63239,8 @@ ${svg}
|
|
|
63210
63239
|
method: method,
|
|
63211
63240
|
spherical: spherical,
|
|
63212
63241
|
keepCorners: !!opts.keep_corners,
|
|
63213
|
-
gain: opts.gain
|
|
63242
|
+
gain: opts.gain,
|
|
63243
|
+
maxBendAngle: opts.max_bend_angle
|
|
63214
63244
|
});
|
|
63215
63245
|
|
|
63216
63246
|
if (implicitlySmoothedNames.length > 0) {
|
|
@@ -63237,6 +63267,7 @@ ${svg}
|
|
|
63237
63267
|
spherical: opts.spherical,
|
|
63238
63268
|
keepCorners: opts.keepCorners,
|
|
63239
63269
|
gain: opts.gain,
|
|
63270
|
+
maxBendAngle: opts.maxBendAngle,
|
|
63240
63271
|
closed: arcs.arcIsClosed(arcId)
|
|
63241
63272
|
});
|
|
63242
63273
|
nn.push(res.xx.length);
|
|
@@ -65053,7 +65084,7 @@ ${svg}
|
|
|
65053
65084
|
return name == 'rectangle' || name == 'rectangles' || name == 'filter' && opts.cleanup;
|
|
65054
65085
|
}
|
|
65055
65086
|
|
|
65056
|
-
var version = "0.7.
|
|
65087
|
+
var version = "0.7.32";
|
|
65057
65088
|
|
|
65058
65089
|
// Parse command line args into commands and run them
|
|
65059
65090
|
// Function takes an optional Node-style callback. A Promise is returned if no callback is given.
|