在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,95100105,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;
}
如果(d
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(函数(){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>');