Extract d3_geo_resample.
This commit is contained in:
Родитель
6091249215
Коммит
c0f9ae7ad1
1
Makefile
1
Makefile
|
@ -185,6 +185,7 @@ d3.geo.js: \
|
||||||
src/geo/type.js \
|
src/geo/type.js \
|
||||||
src/geo/clip.js \
|
src/geo/clip.js \
|
||||||
src/geo/cut.js \
|
src/geo/cut.js \
|
||||||
|
src/geo/resample.js \
|
||||||
src/geo/albers-usa.js \
|
src/geo/albers-usa.js \
|
||||||
src/geo/albers.js \
|
src/geo/albers.js \
|
||||||
src/geo/azimuthal-equal-area.js \
|
src/geo/azimuthal-equal-area.js \
|
||||||
|
|
|
@ -5635,6 +5635,71 @@
|
||||||
}
|
}
|
||||||
return [ to ];
|
return [ to ];
|
||||||
}
|
}
|
||||||
|
function d3_geo_resample(projectPoint) {
|
||||||
|
var δ2 = .5, maxDepth = 16;
|
||||||
|
var resample = d3_geo_type({
|
||||||
|
Point: function(o) {
|
||||||
|
o.coordinates = resamplePoint(o.coordinates);
|
||||||
|
},
|
||||||
|
MultiPoint: function(o) {
|
||||||
|
o.coordinates = o.coordinates.map(resamplePoint);
|
||||||
|
},
|
||||||
|
LineString: function(o) {
|
||||||
|
o.coordinates = resampleLine(o.coordinates);
|
||||||
|
},
|
||||||
|
MultiLineString: function(o) {
|
||||||
|
o.coordinates = o.coordinates.map(resampleLine);
|
||||||
|
},
|
||||||
|
Polygon: function(o) {
|
||||||
|
o.coordinates = resamplePolygon(o.coordinates);
|
||||||
|
},
|
||||||
|
MultiPolygon: function(o) {
|
||||||
|
o.coordinates = o.coordinates.map(resamplePolygon);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
resample.precision = function(_) {
|
||||||
|
if (!arguments.length) return Math.sqrt(δ2);
|
||||||
|
maxDepth = (δ2 = _ * _) > 0 && 16;
|
||||||
|
return resample;
|
||||||
|
};
|
||||||
|
return resample;
|
||||||
|
function resamplePoint(point) {
|
||||||
|
return projectPoint(point[0], point[1]);
|
||||||
|
}
|
||||||
|
function resampleLine(coordinates) {
|
||||||
|
if (!(n = coordinates.length)) return coordinates;
|
||||||
|
var n, i = 0, p = coordinates[0], λ, φ, λ0, line = [ p = projectPoint(λ0 = p[0], φ = p[1]) ], sinφ0 = Math.sin(φ), cosφ0 = Math.cos(φ), x0 = p[0], y0 = p[1];
|
||||||
|
while (++i < n) {
|
||||||
|
p = coordinates[i];
|
||||||
|
p = projectPoint(λ = p[0], φ = p[1]);
|
||||||
|
resampleLineTo(x0, y0, λ0, sinφ0, cosφ0, x0 = p[0], y0 = p[1], λ0 = λ, sinφ0 = Math.sin(φ), cosφ0 = Math.cos(φ), maxDepth, line);
|
||||||
|
line.push([ x0, y0 ]);
|
||||||
|
}
|
||||||
|
return line;
|
||||||
|
}
|
||||||
|
function resamplePolygon(coordinates) {
|
||||||
|
var n = coordinates.length, i = -1, polygon = [], ring, resampled, l, m, p;
|
||||||
|
while (++i < n) {
|
||||||
|
polygon.push(resampled = resampleLine(ring = coordinates[i]));
|
||||||
|
m = ring.length - 1;
|
||||||
|
l = resampled.length - 1;
|
||||||
|
resampleLineTo((p = ring[0])[0], p[1], (p = resampled[0])[0], Math.sin(p[1]), Math.cos(p[1]), (p = ring[m])[0], p[1], (p = resampled[l])[0], Math.sin(p[1]), Math.cos(p[1]), maxDepth, ring);
|
||||||
|
}
|
||||||
|
return polygon;
|
||||||
|
}
|
||||||
|
function resampleLineTo(x0, y0, λ0, sinφ0, cosφ0, x1, y1, λ1, sinφ1, cosφ1, depth, line) {
|
||||||
|
var dx = x1 - x0, dy = y1 - y0, distance2 = dx * dx + dy * dy;
|
||||||
|
if (distance2 > 4 * δ2 && depth--) {
|
||||||
|
var cosΩ = sinφ0 * sinφ1 + cosφ0 * cosφ1 * Math.cos(λ1 - λ0), k = 1 / (Math.SQRT2 * Math.sqrt(1 + cosΩ)), x = k * (cosφ0 * Math.cos(λ0) + cosφ1 * Math.cos(λ1)), y = k * (cosφ0 * Math.sin(λ0) + cosφ1 * Math.sin(λ1)), z = Math.max(-1, Math.min(1, k * (sinφ0 + sinφ1))), φ2 = Math.asin(z), zε = Math.abs(Math.abs(z) - 1), λ2 = zε < ε || zε < εε && (Math.abs(cosφ0) < εε || Math.abs(cosφ1) < εε) ? (λ0 + λ1) / 2 : Math.atan2(y, x), p = projectPoint(λ2, φ2), x2 = p[0], y2 = p[1], dx2 = x0 - x2, dy2 = y0 - y2, dz = dx * dy2 - dy * dx2;
|
||||||
|
if (dz * dz / distance2 > δ2) {
|
||||||
|
var cosφ2 = Math.cos(φ2);
|
||||||
|
resampleLineTo(x0, y0, λ0, sinφ0, cosφ0, x2, y2, λ2, z, cosφ2, depth, line);
|
||||||
|
line.push([ x2, y2 ]);
|
||||||
|
resampleLineTo(x2, y2, λ2, z, cosφ2, x1, y1, λ1, sinφ1, cosφ1, depth, line);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
d3.geo.albersUsa = function() {
|
d3.geo.albersUsa = function() {
|
||||||
var lower48 = d3.geo.albers();
|
var lower48 = d3.geo.albers();
|
||||||
var alaska = d3.geo.albers().rotate([ 160, 0 ]).center([ 0, 60 ]).parallels([ 55, 65 ]);
|
var alaska = d3.geo.albers().rotate([ 160, 0 ]).center([ 0, 60 ]).parallels([ 55, 65 ]);
|
||||||
|
@ -6297,7 +6362,7 @@
|
||||||
})();
|
})();
|
||||||
}
|
}
|
||||||
function d3_geo_projectionMutator(projectAt) {
|
function d3_geo_projectionMutator(projectAt) {
|
||||||
var project, rotate, rotation, projectRotate, k = 150, x = 480, y = 250, λ = 0, φ = 0, δλ = 0, δφ = 0, δγ = 0, δx, δy, δ2 = .5, maxDepth = 16, clip = d3_geo_cut, clipAngle = null;
|
var project, rotate, rotation, projectRotate, k = 150, x = 480, y = 250, λ = 0, φ = 0, δλ = 0, δφ = 0, δγ = 0, δx, δy, clip = d3_geo_cut, clipAngle = null, resample = d3_geo_resample(projectPoint);
|
||||||
function projection(coordinates) {
|
function projection(coordinates) {
|
||||||
coordinates = projectRotate(coordinates[0] * d3_radians, coordinates[1] * d3_radians);
|
coordinates = projectRotate(coordinates[0] * d3_radians, coordinates[1] * d3_radians);
|
||||||
return [ coordinates[0] * k + δx, δy - coordinates[1] * k ];
|
return [ coordinates[0] * k + δx, δy - coordinates[1] * k ];
|
||||||
|
@ -6340,11 +6405,7 @@
|
||||||
δγ = _.length > 2 ? _[2] % 360 * d3_radians : 0;
|
δγ = _.length > 2 ? _[2] % 360 * d3_radians : 0;
|
||||||
return reset();
|
return reset();
|
||||||
};
|
};
|
||||||
projection.precision = function(_) {
|
d3.rebind(projection, resample, "precision");
|
||||||
if (!arguments.length) return Math.sqrt(δ2);
|
|
||||||
maxDepth = (δ2 = _ * _) > 0 && 16;
|
|
||||||
return projection;
|
|
||||||
};
|
|
||||||
function reset() {
|
function reset() {
|
||||||
projectRotate = d3_geo_compose(rotate = d3_geo_rotation(δλ, δφ, δγ), project);
|
projectRotate = d3_geo_compose(rotate = d3_geo_rotation(δλ, δφ, δγ), project);
|
||||||
var center = project(λ, φ);
|
var center = project(λ, φ);
|
||||||
|
@ -6352,26 +6413,6 @@
|
||||||
δy = y + center[1] * k;
|
δy = y + center[1] * k;
|
||||||
return projection;
|
return projection;
|
||||||
}
|
}
|
||||||
var resample = d3_geo_type({
|
|
||||||
Point: function(o) {
|
|
||||||
o.coordinates = resamplePoint(o.coordinates);
|
|
||||||
},
|
|
||||||
MultiPoint: function(o) {
|
|
||||||
o.coordinates = o.coordinates.map(resamplePoint);
|
|
||||||
},
|
|
||||||
LineString: function(o) {
|
|
||||||
o.coordinates = resampleLine(o.coordinates);
|
|
||||||
},
|
|
||||||
MultiLineString: function(o) {
|
|
||||||
o.coordinates = o.coordinates.map(resampleLine);
|
|
||||||
},
|
|
||||||
Polygon: function(o) {
|
|
||||||
o.coordinates = resamplePolygon(o.coordinates);
|
|
||||||
},
|
|
||||||
MultiPolygon: function(o) {
|
|
||||||
o.coordinates = o.coordinates.map(resamplePolygon);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
var rotation = d3_geo_type({
|
var rotation = d3_geo_type({
|
||||||
point: function(coordinates) {
|
point: function(coordinates) {
|
||||||
return rotate(coordinates[0] * d3_radians, coordinates[1] * d3_radians);
|
return rotate(coordinates[0] * d3_radians, coordinates[1] * d3_radians);
|
||||||
|
@ -6382,42 +6423,6 @@
|
||||||
var point = project(λ, φ);
|
var point = project(λ, φ);
|
||||||
return [ point[0] * k + δx, δy - point[1] * k ];
|
return [ point[0] * k + δx, δy - point[1] * k ];
|
||||||
}
|
}
|
||||||
function resamplePoint(point) {
|
|
||||||
return projectPoint(point[0], point[1]);
|
|
||||||
}
|
|
||||||
function resampleLine(coordinates) {
|
|
||||||
if (!(n = coordinates.length)) return coordinates;
|
|
||||||
var n, i = 0, p = coordinates[0], λ, φ, λ0, line = [ p = projectPoint(λ0 = p[0], φ = p[1]) ], sinφ0 = Math.sin(φ), cosφ0 = Math.cos(φ), x0 = p[0], y0 = p[1];
|
|
||||||
while (++i < n) {
|
|
||||||
p = coordinates[i];
|
|
||||||
p = projectPoint(λ = p[0], φ = p[1]);
|
|
||||||
resampleLineTo(x0, y0, λ0, sinφ0, cosφ0, x0 = p[0], y0 = p[1], λ0 = λ, sinφ0 = Math.sin(φ), cosφ0 = Math.cos(φ), maxDepth, line);
|
|
||||||
line.push([ x0, y0 ]);
|
|
||||||
}
|
|
||||||
return line;
|
|
||||||
}
|
|
||||||
function resamplePolygon(coordinates) {
|
|
||||||
var n = coordinates.length, i = -1, polygon = [], ring, resampled, l, m, p;
|
|
||||||
while (++i < n) {
|
|
||||||
polygon.push(resampled = resampleLine(ring = coordinates[i]));
|
|
||||||
m = ring.length - 1;
|
|
||||||
l = resampled.length - 1;
|
|
||||||
resampleLineTo((p = ring[0])[0], p[1], (p = resampled[0])[0], Math.sin(p[1]), Math.cos(p[1]), (p = ring[m])[0], p[1], (p = resampled[l])[0], Math.sin(p[1]), Math.cos(p[1]), maxDepth, ring);
|
|
||||||
}
|
|
||||||
return polygon;
|
|
||||||
}
|
|
||||||
function resampleLineTo(x0, y0, λ0, sinφ0, cosφ0, x1, y1, λ1, sinφ1, cosφ1, depth, line) {
|
|
||||||
var dx = x1 - x0, dy = y1 - y0, distance2 = dx * dx + dy * dy;
|
|
||||||
if (distance2 > 4 * δ2 && depth--) {
|
|
||||||
var cosΩ = sinφ0 * sinφ1 + cosφ0 * cosφ1 * Math.cos(λ1 - λ0), k = 1 / (Math.SQRT2 * Math.sqrt(1 + cosΩ)), x = k * (cosφ0 * Math.cos(λ0) + cosφ1 * Math.cos(λ1)), y = k * (cosφ0 * Math.sin(λ0) + cosφ1 * Math.sin(λ1)), z = Math.max(-1, Math.min(1, k * (sinφ0 + sinφ1))), φ2 = Math.asin(z), zε = Math.abs(Math.abs(z) - 1), λ2 = zε < ε || zε < εε && (Math.abs(cosφ0) < εε || Math.abs(cosφ1) < εε) ? (λ0 + λ1) / 2 : Math.atan2(y, x), p = projectPoint(λ2, φ2), x2 = p[0], y2 = p[1], dx2 = x0 - x2, dy2 = y0 - y2, dz = dx * dy2 - dy * dx2;
|
|
||||||
if (dz * dz / distance2 > δ2) {
|
|
||||||
var cosφ2 = Math.cos(φ2);
|
|
||||||
resampleLineTo(x0, y0, λ0, sinφ0, cosφ0, x2, y2, λ2, z, cosφ2, depth, line);
|
|
||||||
line.push([ x2, y2 ]);
|
|
||||||
resampleLineTo(x2, y2, λ2, z, cosφ2, x1, y1, λ1, sinφ1, cosφ1, depth, line);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return function() {
|
return function() {
|
||||||
project = projectAt.apply(this, arguments);
|
project = projectAt.apply(this, arguments);
|
||||||
projection.invert = project.invert && invert;
|
projection.invert = project.invert && invert;
|
||||||
|
|
Различия файлов скрыты, потому что одна или несколько строк слишком длинны
|
@ -20,10 +20,9 @@ function d3_geo_projectionMutator(projectAt) {
|
||||||
δγ = 0,
|
δγ = 0,
|
||||||
δx, // center
|
δx, // center
|
||||||
δy,
|
δy,
|
||||||
δ2 = .5, // precision, px²
|
|
||||||
maxDepth = 16,
|
|
||||||
clip = d3_geo_cut, // TODO rename: it's often cutting, not clipping!
|
clip = d3_geo_cut, // TODO rename: it's often cutting, not clipping!
|
||||||
clipAngle = null;
|
clipAngle = null,
|
||||||
|
resample = d3_geo_resample(projectPoint);
|
||||||
|
|
||||||
function projection(coordinates) {
|
function projection(coordinates) {
|
||||||
coordinates = projectRotate(coordinates[0] * d3_radians, coordinates[1] * d3_radians);
|
coordinates = projectRotate(coordinates[0] * d3_radians, coordinates[1] * d3_radians);
|
||||||
|
@ -77,11 +76,7 @@ function d3_geo_projectionMutator(projectAt) {
|
||||||
return reset();
|
return reset();
|
||||||
};
|
};
|
||||||
|
|
||||||
projection.precision = function(_) {
|
d3.rebind(projection, resample, "precision");
|
||||||
if (!arguments.length) return Math.sqrt(δ2);
|
|
||||||
maxDepth = (δ2 = _ * _) > 0 && 16;
|
|
||||||
return projection;
|
|
||||||
};
|
|
||||||
|
|
||||||
function reset() {
|
function reset() {
|
||||||
projectRotate = d3_geo_compose(rotate = d3_geo_rotation(δλ, δφ, δγ), project);
|
projectRotate = d3_geo_compose(rotate = d3_geo_rotation(δλ, δφ, δγ), project);
|
||||||
|
@ -91,29 +86,6 @@ function d3_geo_projectionMutator(projectAt) {
|
||||||
return projection;
|
return projection;
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO extract resampling from projection (say, d3_geo_resample?)
|
|
||||||
// TODO rename: this is not just resampling, it also projects and transforms!
|
|
||||||
var resample = d3_geo_type({
|
|
||||||
Point: function(o) {
|
|
||||||
o.coordinates = resamplePoint(o.coordinates);
|
|
||||||
},
|
|
||||||
MultiPoint: function(o) {
|
|
||||||
o.coordinates = o.coordinates.map(resamplePoint);
|
|
||||||
},
|
|
||||||
LineString: function(o) {
|
|
||||||
o.coordinates = resampleLine(o.coordinates);
|
|
||||||
},
|
|
||||||
MultiLineString: function(o) {
|
|
||||||
o.coordinates = o.coordinates.map(resampleLine);
|
|
||||||
},
|
|
||||||
Polygon: function(o) {
|
|
||||||
o.coordinates = resamplePolygon(o.coordinates);
|
|
||||||
},
|
|
||||||
MultiPolygon: function(o) {
|
|
||||||
o.coordinates = o.coordinates.map(resamplePolygon);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
// TODO rename: this is not just rotation, it also converts to radians!
|
// TODO rename: this is not just rotation, it also converts to radians!
|
||||||
// TODO don't create new objects for rotation? (since clipping does the same?)
|
// TODO don't create new objects for rotation? (since clipping does the same?)
|
||||||
// TODO don't call rotate when rotate is a no-op
|
// TODO don't call rotate when rotate is a no-op
|
||||||
|
@ -132,88 +104,6 @@ function d3_geo_projectionMutator(projectAt) {
|
||||||
return [point[0] * k + δx, δy - point[1] * k];
|
return [point[0] * k + δx, δy - point[1] * k];
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO rename: this is not just resampling, it also projects and transforms!
|
|
||||||
function resamplePoint(point) {
|
|
||||||
return projectPoint(point[0], point[1]);
|
|
||||||
}
|
|
||||||
|
|
||||||
// TODO rename: this is not just resampling, it also projects and transforms!
|
|
||||||
function resampleLine(coordinates) {
|
|
||||||
if (!(n = coordinates.length)) return coordinates;
|
|
||||||
var n,
|
|
||||||
i = 0,
|
|
||||||
p = coordinates[0],
|
|
||||||
λ,
|
|
||||||
φ,
|
|
||||||
λ0,
|
|
||||||
line = [p = projectPoint(λ0 = p[0], φ = p[1])],
|
|
||||||
sinφ0 = Math.sin(φ),
|
|
||||||
cosφ0 = Math.cos(φ),
|
|
||||||
x0 = p[0],
|
|
||||||
y0 = p[1];
|
|
||||||
while (++i < n) {
|
|
||||||
p = coordinates[i];
|
|
||||||
p = projectPoint(λ = p[0], φ = p[1]);
|
|
||||||
resampleLineTo(x0, y0, λ0, sinφ0, cosφ0,
|
|
||||||
x0 = p[0], y0 = p[1], λ0 = λ, sinφ0 = Math.sin(φ), cosφ0 = Math.cos(φ),
|
|
||||||
maxDepth, line);
|
|
||||||
line.push([x0, y0]);
|
|
||||||
}
|
|
||||||
return line;
|
|
||||||
}
|
|
||||||
|
|
||||||
// TODO rename: this is not just resampling, it also projects and transforms!
|
|
||||||
function resamplePolygon(coordinates) {
|
|
||||||
var n = coordinates.length,
|
|
||||||
i = -1,
|
|
||||||
polygon = [],
|
|
||||||
ring,
|
|
||||||
resampled,
|
|
||||||
l,
|
|
||||||
m,
|
|
||||||
p;
|
|
||||||
while (++i < n) {
|
|
||||||
polygon.push(resampled = resampleLine(ring = coordinates[i]));
|
|
||||||
m = ring.length - 1;
|
|
||||||
l = resampled.length - 1;
|
|
||||||
resampleLineTo(
|
|
||||||
(p = ring[0])[0], p[1], (p = resampled[0])[0], Math.sin(p[1]), Math.cos(p[1]),
|
|
||||||
(p = ring[m])[0], p[1], (p = resampled[l])[0], Math.sin(p[1]), Math.cos(p[1]),
|
|
||||||
maxDepth, ring);
|
|
||||||
}
|
|
||||||
return polygon;
|
|
||||||
}
|
|
||||||
|
|
||||||
// TODO rename: this is not just resampling, it also projects and transforms!
|
|
||||||
function resampleLineTo(x0, y0, λ0, sinφ0, cosφ0, x1, y1, λ1, sinφ1, cosφ1, depth, line) {
|
|
||||||
var dx = x1 - x0,
|
|
||||||
dy = y1 - y0,
|
|
||||||
distance2 = dx * dx + dy * dy;
|
|
||||||
if (distance2 > 4 * δ2 && depth--) {
|
|
||||||
var cosΩ = sinφ0 * sinφ1 + cosφ0 * cosφ1 * Math.cos(λ1 - λ0),
|
|
||||||
k = 1 / (Math.SQRT2 * Math.sqrt(1 + cosΩ)),
|
|
||||||
x = k * (cosφ0 * Math.cos(λ0) + cosφ1 * Math.cos(λ1)),
|
|
||||||
y = k * (cosφ0 * Math.sin(λ0) + cosφ1 * Math.sin(λ1)),
|
|
||||||
z = Math.max(-1, Math.min(1, k * (sinφ0 + sinφ1))),
|
|
||||||
φ2 = Math.asin(z),
|
|
||||||
zε = Math.abs(Math.abs(z) - 1),
|
|
||||||
λ2 = zε < ε || zε < εε && (Math.abs(cosφ0) < εε || Math.abs(cosφ1) < εε)
|
|
||||||
? (λ0 + λ1) / 2 : Math.atan2(y, x),
|
|
||||||
p = projectPoint(λ2, φ2),
|
|
||||||
x2 = p[0],
|
|
||||||
y2 = p[1],
|
|
||||||
dx2 = x0 - x2,
|
|
||||||
dy2 = y0 - y2,
|
|
||||||
dz = dx * dy2 - dy * dx2;
|
|
||||||
if (dz * dz / distance2 > δ2) {
|
|
||||||
var cosφ2 = Math.cos(φ2);
|
|
||||||
resampleLineTo(x0, y0, λ0, sinφ0, cosφ0, x2, y2, λ2, z, cosφ2, depth, line);
|
|
||||||
line.push([x2, y2]);
|
|
||||||
resampleLineTo(x2, y2, λ2, z, cosφ2, x1, y1, λ1, sinφ1, cosφ1, depth, line);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return function() {
|
return function() {
|
||||||
project = projectAt.apply(this, arguments);
|
project = projectAt.apply(this, arguments);
|
||||||
projection.invert = project.invert && invert;
|
projection.invert = project.invert && invert;
|
||||||
|
|
|
@ -0,0 +1,116 @@
|
||||||
|
function d3_geo_resample(projectPoint) {
|
||||||
|
var δ2 = .5, // precision, px²
|
||||||
|
maxDepth = 16;
|
||||||
|
|
||||||
|
// TODO rename: this is not just resampling, it also projects and transforms!
|
||||||
|
var resample = d3_geo_type({
|
||||||
|
Point: function(o) {
|
||||||
|
o.coordinates = resamplePoint(o.coordinates);
|
||||||
|
},
|
||||||
|
MultiPoint: function(o) {
|
||||||
|
o.coordinates = o.coordinates.map(resamplePoint);
|
||||||
|
},
|
||||||
|
LineString: function(o) {
|
||||||
|
o.coordinates = resampleLine(o.coordinates);
|
||||||
|
},
|
||||||
|
MultiLineString: function(o) {
|
||||||
|
o.coordinates = o.coordinates.map(resampleLine);
|
||||||
|
},
|
||||||
|
Polygon: function(o) {
|
||||||
|
o.coordinates = resamplePolygon(o.coordinates);
|
||||||
|
},
|
||||||
|
MultiPolygon: function(o) {
|
||||||
|
o.coordinates = o.coordinates.map(resamplePolygon);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
resample.precision = function(_) {
|
||||||
|
if (!arguments.length) return Math.sqrt(δ2);
|
||||||
|
maxDepth = (δ2 = _ * _) > 0 && 16;
|
||||||
|
return resample;
|
||||||
|
};
|
||||||
|
|
||||||
|
return resample;
|
||||||
|
|
||||||
|
// TODO rename: this is not just resampling, it also projects and transforms!
|
||||||
|
function resamplePoint(point) {
|
||||||
|
return projectPoint(point[0], point[1]);
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO rename: this is not just resampling, it also projects and transforms!
|
||||||
|
function resampleLine(coordinates) {
|
||||||
|
if (!(n = coordinates.length)) return coordinates;
|
||||||
|
var n,
|
||||||
|
i = 0,
|
||||||
|
p = coordinates[0],
|
||||||
|
λ,
|
||||||
|
φ,
|
||||||
|
λ0,
|
||||||
|
line = [p = projectPoint(λ0 = p[0], φ = p[1])],
|
||||||
|
sinφ0 = Math.sin(φ),
|
||||||
|
cosφ0 = Math.cos(φ),
|
||||||
|
x0 = p[0],
|
||||||
|
y0 = p[1];
|
||||||
|
while (++i < n) {
|
||||||
|
p = coordinates[i];
|
||||||
|
p = projectPoint(λ = p[0], φ = p[1]);
|
||||||
|
resampleLineTo(x0, y0, λ0, sinφ0, cosφ0,
|
||||||
|
x0 = p[0], y0 = p[1], λ0 = λ, sinφ0 = Math.sin(φ), cosφ0 = Math.cos(φ),
|
||||||
|
maxDepth, line);
|
||||||
|
line.push([x0, y0]);
|
||||||
|
}
|
||||||
|
return line;
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO rename: this is not just resampling, it also projects and transforms!
|
||||||
|
function resamplePolygon(coordinates) {
|
||||||
|
var n = coordinates.length,
|
||||||
|
i = -1,
|
||||||
|
polygon = [],
|
||||||
|
ring,
|
||||||
|
resampled,
|
||||||
|
l,
|
||||||
|
m,
|
||||||
|
p;
|
||||||
|
while (++i < n) {
|
||||||
|
polygon.push(resampled = resampleLine(ring = coordinates[i]));
|
||||||
|
m = ring.length - 1;
|
||||||
|
l = resampled.length - 1;
|
||||||
|
resampleLineTo(
|
||||||
|
(p = ring[0])[0], p[1], (p = resampled[0])[0], Math.sin(p[1]), Math.cos(p[1]),
|
||||||
|
(p = ring[m])[0], p[1], (p = resampled[l])[0], Math.sin(p[1]), Math.cos(p[1]),
|
||||||
|
maxDepth, ring);
|
||||||
|
}
|
||||||
|
return polygon;
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO rename: this is not just resampling, it also projects and transforms!
|
||||||
|
function resampleLineTo(x0, y0, λ0, sinφ0, cosφ0, x1, y1, λ1, sinφ1, cosφ1, depth, line) {
|
||||||
|
var dx = x1 - x0,
|
||||||
|
dy = y1 - y0,
|
||||||
|
distance2 = dx * dx + dy * dy;
|
||||||
|
if (distance2 > 4 * δ2 && depth--) {
|
||||||
|
var cosΩ = sinφ0 * sinφ1 + cosφ0 * cosφ1 * Math.cos(λ1 - λ0),
|
||||||
|
k = 1 / (Math.SQRT2 * Math.sqrt(1 + cosΩ)),
|
||||||
|
x = k * (cosφ0 * Math.cos(λ0) + cosφ1 * Math.cos(λ1)),
|
||||||
|
y = k * (cosφ0 * Math.sin(λ0) + cosφ1 * Math.sin(λ1)),
|
||||||
|
z = Math.max(-1, Math.min(1, k * (sinφ0 + sinφ1))),
|
||||||
|
φ2 = Math.asin(z),
|
||||||
|
zε = Math.abs(Math.abs(z) - 1),
|
||||||
|
λ2 = zε < ε || zε < εε && (Math.abs(cosφ0) < εε || Math.abs(cosφ1) < εε)
|
||||||
|
? (λ0 + λ1) / 2 : Math.atan2(y, x),
|
||||||
|
p = projectPoint(λ2, φ2),
|
||||||
|
x2 = p[0],
|
||||||
|
y2 = p[1],
|
||||||
|
dx2 = x0 - x2,
|
||||||
|
dy2 = y0 - y2,
|
||||||
|
dz = dx * dy2 - dy * dx2;
|
||||||
|
if (dz * dz / distance2 > δ2) {
|
||||||
|
var cosφ2 = Math.cos(φ2);
|
||||||
|
resampleLineTo(x0, y0, λ0, sinφ0, cosφ0, x2, y2, λ2, z, cosφ2, depth, line);
|
||||||
|
line.push([x2, y2]);
|
||||||
|
resampleLineTo(x2, y2, λ2, z, cosφ2, x1, y1, λ1, sinφ1, cosφ1, depth, line);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
Загрузка…
Ссылка в новой задаче