Better handling of ambiguous centroids.
Rather than doing something like picking the last seen point, return an undefined centroid if it is ambiguous. Users can decide what to do, e.g. when picking an origin for a rotating globe, using the last coordinate in a MultiPoint or LineString seems reasonable in an ambiguous situation.
This commit is contained in:
Родитель
b87bcbc22a
Коммит
3d84b49ae4
|
@ -5891,7 +5891,10 @@
|
||||||
d3.geo.centroid = function(object) {
|
d3.geo.centroid = function(object) {
|
||||||
d3_geo_centroidW = d3_geo_centroidX = d3_geo_centroidY = d3_geo_centroidZ = 0;
|
d3_geo_centroidW = d3_geo_centroidX = d3_geo_centroidY = d3_geo_centroidZ = 0;
|
||||||
d3.geo.stream(object, d3_geo_centroid);
|
d3.geo.stream(object, d3_geo_centroid);
|
||||||
return d3_geo_centroidW ? [ Math.atan2(d3_geo_centroidY, d3_geo_centroidX) * d3_degrees, Math.asin(Math.max(-1, Math.min(1, d3_geo_centroidZ / Math.sqrt(d3_geo_centroidX * d3_geo_centroidX + d3_geo_centroidY * d3_geo_centroidY + d3_geo_centroidZ * d3_geo_centroidZ)))) * d3_degrees ] : null;
|
var m;
|
||||||
|
if (d3_geo_centroidW && Math.abs(m = Math.sqrt(d3_geo_centroidX * d3_geo_centroidX + d3_geo_centroidY * d3_geo_centroidY + d3_geo_centroidZ * d3_geo_centroidZ)) > ε) {
|
||||||
|
return [ Math.atan2(d3_geo_centroidY, d3_geo_centroidX) * d3_degrees, Math.asin(Math.max(-1, Math.min(1, d3_geo_centroidZ / m))) * d3_degrees ];
|
||||||
|
}
|
||||||
};
|
};
|
||||||
var d3_geo_centroidW, d3_geo_centroidX, d3_geo_centroidY, d3_geo_centroidZ;
|
var d3_geo_centroidW, d3_geo_centroidX, d3_geo_centroidY, d3_geo_centroidZ;
|
||||||
var d3_geo_centroid = {
|
var d3_geo_centroid = {
|
||||||
|
|
Различия файлов скрыты, потому что одна или несколько строк слишком длинны
|
@ -1,12 +1,15 @@
|
||||||
d3.geo.centroid = function(object) {
|
d3.geo.centroid = function(object) {
|
||||||
d3_geo_centroidW = d3_geo_centroidX = d3_geo_centroidY = d3_geo_centroidZ = 0;
|
d3_geo_centroidW = d3_geo_centroidX = d3_geo_centroidY = d3_geo_centroidZ = 0;
|
||||||
d3.geo.stream(object, d3_geo_centroid);
|
d3.geo.stream(object, d3_geo_centroid);
|
||||||
// TODO fallback to [0, 0] e.g. for sphere, equator?
|
|
||||||
// TODO mixed geometries
|
// TODO mixed geometries
|
||||||
return d3_geo_centroidW ? [
|
var m;
|
||||||
Math.atan2(d3_geo_centroidY, d3_geo_centroidX) * d3_degrees,
|
if (d3_geo_centroidW &&
|
||||||
Math.asin(Math.max(-1, Math.min(1, d3_geo_centroidZ / Math.sqrt(d3_geo_centroidX * d3_geo_centroidX + d3_geo_centroidY * d3_geo_centroidY + d3_geo_centroidZ * d3_geo_centroidZ)))) * d3_degrees
|
Math.abs(m = Math.sqrt(d3_geo_centroidX * d3_geo_centroidX + d3_geo_centroidY * d3_geo_centroidY + d3_geo_centroidZ * d3_geo_centroidZ)) > ε) {
|
||||||
] : null;
|
return [
|
||||||
|
Math.atan2(d3_geo_centroidY, d3_geo_centroidX) * d3_degrees,
|
||||||
|
Math.asin(Math.max(-1, Math.min(1, d3_geo_centroidZ / m))) * d3_degrees
|
||||||
|
];
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
var d3_geo_centroidW,
|
var d3_geo_centroidW,
|
||||||
|
|
|
@ -13,9 +13,21 @@ suite.addBatch({
|
||||||
"Point": function(centroid) {
|
"Point": function(centroid) {
|
||||||
assert.deepEqual(centroid({type: "Point", coordinates: [0, 0]}), [0, 0]);
|
assert.deepEqual(centroid({type: "Point", coordinates: [0, 0]}), [0, 0]);
|
||||||
},
|
},
|
||||||
"MultiPoint": function(centroid) {
|
"MultiPoint": {
|
||||||
assert.inDelta(centroid({type: "MultiPoint", coordinates: [[0, 0], [1, 2]]}), [0.499847, 1.000038], 1e-6);
|
"": function(centroid) {
|
||||||
assert.deepEqual(centroid({type: "MultiPoint", coordinates: [[179, 0], [-179, 0]]}), [180, 0]);
|
assert.inDelta(centroid({type: "MultiPoint", coordinates: [[0, 0], [1, 2]]}), [0.499847, 1.000038], 1e-6);
|
||||||
|
},
|
||||||
|
"antimeridian": function(centroid) {
|
||||||
|
assert.deepEqual(centroid({type: "MultiPoint", coordinates: [[179, 0], [-179, 0]]}), [180, 0]);
|
||||||
|
},
|
||||||
|
"rings": {
|
||||||
|
"equator": function(centroid) {
|
||||||
|
assert.isUndefined(centroid({type: "MultiPoint", coordinates: [[0, 0], [90, 0], [180, 0], [-90, 0]]}));
|
||||||
|
},
|
||||||
|
"polar": function(centroid) {
|
||||||
|
assert.isUndefined(centroid({type: "MultiPoint", coordinates: [[0, 0], [0, 90], [180, 0], [0, -90]]}));
|
||||||
|
}
|
||||||
|
}
|
||||||
},
|
},
|
||||||
"LineString": function(centroid) {
|
"LineString": function(centroid) {
|
||||||
assert.inDelta(centroid({type: "LineString", coordinates: [[0, 0], [1, 0]]}), [.5, 0], 1e-6);
|
assert.inDelta(centroid({type: "LineString", coordinates: [[0, 0], [1, 0]]}), [.5, 0], 1e-6);
|
||||||
|
@ -25,8 +37,8 @@ suite.addBatch({
|
||||||
assert.inDelta(centroid({type: "LineString", coordinates: [[-60, -1], [60, 1]]}), [0, 0], 1e-6);
|
assert.inDelta(centroid({type: "LineString", coordinates: [[-60, -1], [60, 1]]}), [0, 0], 1e-6);
|
||||||
assert.inDelta(centroid({type: "LineString", coordinates: [[179, -1], [-179, 1]]}), [180, 0], 1e-6);
|
assert.inDelta(centroid({type: "LineString", coordinates: [[179, -1], [-179, 1]]}), [180, 0], 1e-6);
|
||||||
assert.inDelta(centroid({type: "LineString", coordinates: [[-179, 0], [0, 0], [179, 0]]}), [0, 0], 1e-6);
|
assert.inDelta(centroid({type: "LineString", coordinates: [[-179, 0], [0, 0], [179, 0]]}), [0, 0], 1e-6);
|
||||||
assert.inDelta(centroid({type: "LineString", coordinates: [[0, -90], [0, 90]]}), [0, 0], 1e-6);
|
assert.inDelta(centroid({type: "LineString", coordinates: [[-180, -90], [0, 0], [0, 90]]}), [0, 0], 1e-6);
|
||||||
assert.inDelta(centroid({type: "LineString", coordinates: [[-180, -90], [0, 90]]}), [-90, 0], 1e-6);
|
assert.isUndefined(centroid({type: "LineString", coordinates: [[0, -90], [0, 90]]}));
|
||||||
},
|
},
|
||||||
"MultiLineString": function(centroid) {
|
"MultiLineString": function(centroid) {
|
||||||
assert.inDelta(centroid({type: "MultiLineString", coordinates: [[[0, 0], [0, 2]]]}), [0, 1], 1e-6);
|
assert.inDelta(centroid({type: "MultiLineString", coordinates: [[[0, 0], [0, 2]]]}), [0, 1], 1e-6);
|
||||||
|
|
Загрузка…
Ссылка в новой задаче