javascript:在数组中找到重叠的圆圈

时间:2017-10-09 19:20:25

标签: javascript arrays recursion geometry overlap

如何修复此代码以正确检测重叠的圆圈? 第一个圆圈是通过测试起点的位置来指定的。第一个圆圈应该是重叠圆图的基础。现在,只有当测试的圆圈在非分支线上重叠时才有效...

(各个圆圈为[x,y,radius])

var circles = [
    [6, 19, 1],
    [6, 11, 4],
    [8, 17, 3],
    [19, 19, 2],
    [19, 11, 4],
    [15, 7, 6],
    [12, 19, 4]
];
var i = 0;
var j = 0;
var start = [10, 19];
var starts = false;
var overlapping = [];

var isInside = function(point, list, check, push) {
    var temp = list.filter(function(item) { return Math.pow(item[0] - point[0], 2) + Math.pow(item[1] - point[1], 2) < item[2] * item[2] });
    if (push) { overlapping = overlapping.concat(temp) };
    return temp.length > 0
};

starts = isInside(start, circles, starts, true);

var overlappingCirclesTest = function() {
    if (j < circles.length && overlapping.length > 0) {
        var i = overlapping.length - 1;
        var r0 = overlapping[i][2];
        var r1 = circles[j][2];
        var x0 = overlapping[i][0];
        var x1 = circles[j][0];
        var y0 = overlapping[i][1];
        var y1 = circles[j][1];
        if (Math.hypot(x0 - x1, y0 - y1) <= (r0 + r1)) {
            overlapping.push(circles[j]);
            circles.splice(circles.indexOf(circles[j]), 1);
            j = 0;
            overlappingCirclesTest();
        }
        j++;
        overlappingCirclesTest();
    }
}
overlappingCirclesTest();

编辑:澄清:我们有一系列可能重叠的圆圈和两个点,即开始和结束。我们想要产生一个重叠圆的路径,从带有开头的那个开始,到以带有结尾的圆结束。可能有几条潜在的路径,我们只想知道是否有任何路径。

2 个答案:

答案 0 :(得分:0)

所以这是一个非常基本的碰撞检查系统。每当您更新时,运行碰撞并传递您正在检查碰撞的圆的参数。

function Collision (x, y, r) {
    for (i=0; i<circles.length; i++) {
        //Distance formula
        if (Math.sqrt((x-circles[i].x)(x-circles[i].x) + (y-circles[i].y)(y-circles[i].y) < r) {
            return true;
    }
}

这是一个圆形对象的示例,以及如何调用它:

function Circle() {
    this.x = Math.random()*100;
    this.y = Math.random()*100;
    this.r = Math.random()*50;

    this.update = function() {
        if (Collision(this.x, this.y, this.r) {
          console.log("circle collided with another circle");
        }
    }
};

此外,您可以查看我创建的项目的来源,该项目使用了大量的圆圈并检查所有项目与玩家之间的碰撞。 http://betaio.bitballoon.com

答案 1 :(得分:0)

这是一个更完整的答案,我没有尝试将圆圈可视化,因此我很难确定这是完全正确的,但我认为这会让你更接近。

我认为算法是O(N ^ 2)所以它不会很快但我采取的策略是在每个重叠的圆圈上建立一个索引,然后找到一个使用该点,然后基本上是recurse通过重叠索引找到它在一个组中关联的所有cirlces。

以下是代码:

function circleCollisionDetect (c1, c2) {
  var dx = c1[0] - c2[0]
  var dy = c1[1] - c2[1]
  var distance = Math.sqrt(dx * dx + dy * dy)
  return distance < c1[2] + c2[2]
}

function circlePointCollisionDetect (p, c) {
  const dx = p[0] - c[0]
  const dy = p[1] - c[1]
  const distance = Math.sqrt(dx * dx + dy * dy)
  return distance < c[2]
}

function search (i, circles, index) {
  const group = []
  function follow(i) {
    if (!~group.indexOf(i)) {
      group.push(i)
      const overlaps = index[i]
      for (let x = 0, n = overlaps.length; x < n; x++) {
        follow(overlaps[x])
      }
    }
  }
  follow(i)
  return group
}

const circles = [
  [6, 19, 1],
  [6, 11, 4],
  [8, 17, 3],
  [19, 19, 2],
  [19, 11, 4],
  [15, 7, 6],
  [12, 19, 4]
]
const overlaps = []
const p = [10, 19]

// Find one that overlaps the starting point
const c = circles.find(c => circlePointCollisionDetect(p, c))
const start = circles.indexOf(c)

// Build an index of all overlapping circles
for (let a = 0, n = circles.length; a < n; a++) {
  for (let b = 0; b < n; b++) {
    const c1 = circles[a]
    const c2 = circles[b]
    if (c1 === c2) continue;
    if (!overlaps[a]) overlaps[a] = []
    if (circleCollisionDetect(c1, c2)) overlaps[a].push(b)
  }
}

// Next search through the index recursively for unique overlapping circles
const overlapping = search(start, circles, overlaps)

console.log('start:', start)
console.log('index:', overlaps)
console.log('overlapping:', overlapping)

打印哪些:

start: 2
index: [ [ 2 ], [ 2, 5 ], [ 0, 1, 6 ], [], [ 5 ], [ 1, 4 ], [ 2 ] ]
overlapping: [ 2, 0, 1, 5, 4, 6 ]

所以基本上它们都是相互重叠的,除了[19, 19, 2],这是正确的吗?