在javascript数组中分散数字

我有一个 10+ 个数字的数组.它们代表圆上的坐标 - 以度为单位,即每个数字在 0359.999999...

I have an array of 10+ numbers. They represent coordinates on a circle - in degrees, i.e. each number is in between 0 and 359.999999...

我要解决的问题是,当我在圆圈上绘制项目时(通过 html5 canvas api),有时它们会聚集在一起,导致项目相互绘制.

The problem I am trying to solve is that when I draw my items on the circle (via html5 canvas api), sometimes they are clustered together and that results in items being drawn onto each other.

所以我想创建一个算法,将项目均匀地分布在它们的初始集群位置周围.假设(我希望这是一个可配置的选项)两个项目之间的最小距离是 5 度.

So I would like to create an algorithm which disperses items evenly around their initial cluster position. Let's say (and I'd like this to be a configurable option) the minimal distance between two items is 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 个或更多项目).

So if the initial array is [5, 41, 97, 101, 103, 158, 201, 214, 216, 217, 320] then I would like the algorithm come up with something like [5, 41, 95, 100, 105, 158, 201, 211, 216, 221, 320] (with bolded items being dispersed around their initial "gravity center" regardless whether those are 2 or more items).

此外,算法还需要识别 0 和 359 仅相差 1 个单位(度),并将这些项目均匀分布在周围.

Also what would be neccessary is that the algorithm recognizes 0 and 359 being just 1 unit (degree) apart and also spread such items evenly around.

有没有人创造过这样的算法或知道如何实现它?即使是一些一般性的想法也是受欢迎的.我确信我可以通过大量的试验和错误来实现这一目标,但如果你愿意的话,我想先听听一些有根据的猜测.

Has anyone ever created such algorithm or have a good idea how it could be achieved? Even some general thoughts are welcome. I'm sure I could achieve that with plenty of trial and error, but I'd like to hear some educated guesses, if you will, first.

推荐答案

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>');

代码将两对太近的情侣分开,每边各有一对.这是对称的,有时会导致值过远,可以纠正.

the code pushes two too close couples appart with one on each side. this is symetrically and results in sometimes to far pushed values, which can be corrected.

[未实施!]如果您的值的空间不足,[0..360[ 或超过 72 个元素相差 5,while 循环可能不会结束.

[not implemented!] if the space of your values is not sufficient, [0..360[ or by more then 72 elements with a difference of 5 the the while loop may not come to an end.

最小化块应该迭代直到所有值都被纠正.

edit: the minimise block should iterate until all values are correted.

相关文章