在javascript数组中分散数字
我有一个在javascript数组中分散数字,javascript,arrays,algorithm,sorting,html5-canvas,Javascript,Arrays,Algorithm,Sorting,Html5 Canvas,我有一个10+数字数组。它们以度表示圆上的坐标,即每个数字介于0和359.999999… 我试图解决的问题是,当我在圆圈上绘制项目时(通过html5画布api),有时它们会聚集在一起,导致项目相互绘制 因此,我想创建一个算法,将项目均匀地分布在其初始集群位置周围。比方说(我希望这是一个可配置的选项),两个项目之间的最小距离是5degrees 因此,如果初始数组是[5,41,97,101,103,158,201,214,216,217,320],那么我希望算法能给出类似[5,41,95,100,1
10+
数字数组。它们以度表示圆上的坐标,即每个数字介于0
和359.999999…
我试图解决的问题是,当我在圆圈上绘制项目时(通过html5画布api),有时它们会聚集在一起,导致项目相互绘制
因此,我想创建一个算法,将项目均匀地分布在其初始集群位置周围。比方说(我希望这是一个可配置的选项),两个项目之间的最小距离是5
degrees
因此,如果初始数组是[5,41,97,101,103,158,201,214,216,217,320]
,那么我希望算法能给出类似[5,41,95,100,105,158,201,211,216,221,320]
(粗体项目分散在其初始“重心”周围,无论这些项目是2个还是更多)
此外,算法还需要识别出0和359之间的间隔仅为1个单位(度),并将这些项均匀分布
有没有人创建过这样的算法,或者对如何实现它有一个好主意?甚至一些一般性的想法都是受欢迎的。
我相信我可以通过大量的尝试和错误来实现这一点,但如果你愿意的话,我想先听听一些有根据的猜测。要获得“均匀随机”分布,假设你有N个数字-将圆分割成N个段,然后将每个数字随机放入其段中
这样,您甚至不需要关心0和359之间仅相差1个单位
这里有一个想法:
var数=5;
var段=360/个数字;
var结果=[];
对于(变量i=0;i 警报(result.join(',')代码>漂亮打印图形的算法使用弹簧系统在顶点重叠时移动顶点。在这里,您只需要处理一个维度,可以通过迭代调整附近的角度来解决问题,直到所有节点至少相隔5度
您可以通过创建辅助工作数组来处理循环值,以便在最大间隙之后对元素重新排序。这使您可以将数组视为线性值,而无需考虑换行:
[2, 7, 320, 359] -> [-40, -1, 2, 7]
下面的代码就是这样做的。不过,节点的移动方式相当粗糙:代码只查看太近的成对节点。通过在两个或多个彼此太近的节点组成的集群上移动,代码可能会得到改进:
function adjust(arr, dist)
{
var offset = 0;
var max = 360.0 + arr[0] - arr[arr.length - 1];
var min = max;
var mix = 0; // index of first elment after largest gap
// exit early if array can't be adjusted
if (dist * arr.length > 240.0) return arr;
// find largest gap
for (var i = 1; i < arr.length; i++) {
var d = arr[i] - arr[i - 1];
if (d > max) {
max = d;
mix = i;
}
if (d < min) min = d;
}
var x = []; // working array
var adj = []; // final, adjusted array
// create working array on greatest gap
for (var i = 0; i < arr.length; i++) {
if (i + mix < arr.length) {
x.push(arr[i + mix] - 360);
} else {
x.push(arr[i + mix - arr.length]);
}
}
// iteratively adjust angles
while (min < dist) {
min = dist;
for (var i = 1; i < x.length; i++) {
var d = x[i] - x[i - 1];
if (d < dist) {
if (d < min) min = d;
x[i - 1] -= (dist - d) / 2;
x[i] += (dist - d) / 2;
}
}
}
// create final array
for (var i = 0; i < x.length; i++) {
if (i - mix < 0) {
adj.push(x[i - mix + x.length]);
} else {
adj.push(x[i - mix] + 360);
}
}
return adj;
}
功能调整(arr、dist)
{
var偏移=0;
var max=360.0+arr[0]-arr[arr.length-1];
最小值=最大值;
var mix=0;//最大间隙后第一个元素的索引
//如果阵列无法调整,请提前退出
如果(dist*arr.length>240.0)返回arr;
//找到最大的差距
对于(变量i=1;i最大值){
max=d;
mix=i;
}
如果(dvar val=[5,41,96,101,103,158,201,214,216,217,320,1201,1213,1214,1216,1217,1320],
delta=Array.apply(null,{length:val.length}).map(函数(){return 0}),
结果,,
阈值=5,
收敛=错误;
document.write('val:'+val+'
');
而(!收敛){
收敛=真;
delta=delta.map(函数(d,i){
如果(i1){
if(val[i+1]+delta[i+1]-val[i]-d<阈值){
收敛=错误;
δ[i+1]+=1;
返回d-1;
}
}
返回d;
});
编写('delta:'+delta+'
');
}
结果=值映射(函数(v,i){
返回v+delta[i];
});
document.write('result:'+result+'
');
//尽量减少差异
收敛=错误;
而(!收敛){
收敛=真;
delta=delta.map(函数(d,i){
如果(i阈值){
收敛=错误;
返回d+空格-阈值;
}
}
返回d;
});
写入('delta min:'+delta+'
');
}
结果=值映射(函数(v,i){
返回v+delta[i];
});
document.write('result:'+result+'
');
代码将两对距离过近的情侣推到一起,两边各有一对。这是对称的,有时会产生远推的值,可以进行校正
[未实施!]
如果值的空间不足,[0..360]或相差5的72个元素,则while循环可能不会结束
编辑:最小化块应迭代,直到所有值都正确。“[5、41、96、100、105、158、201、211、216、221、320]”<
var val = [5, 41, 96, 101, 103, 158, 201, 214, 216, 217, 320, 1201, 1213, 1214, 1216, 1217, 1320],
delta = Array.apply(null, { length: val.length }).map(function () { return 0 }),
result,
threshold = 5,
converged = false;
document.write('val: ' + val + '<br>');
while (!converged) {
converged = true;
delta = delta.map(function (d, i) {
if (i < delta.length - 1 && delta.length > 1) {
if (val[i + 1] + delta[i + 1] - val[i] - d < threshold) {
converged = false;
delta[i + 1] += 1;
return d - 1;
}
}
return d;
});
document.write('delta: ' + delta + '<br>');
}
result = val.map(function (v, i) {
return v + delta[i];
});
document.write('result: ' + result + '<br>');
// try to minimise difference
converged = false;
while (!converged) {
converged = true;
delta = delta.map(function (d, i) {
if (i < delta.length - 2) {
var space = val[i + 1] + delta[i + 1] - val[i] - d;
if (d < 0 && space > threshold) {
converged = false;
return d + space - threshold;
}
}
return d;
});
document.write('delta min: ' + delta + '<br>');
}
result = val.map(function (v, i) {
return v + delta[i];
});
document.write('result: ' + result + '<br>');