什么是最有效的圆圈碰撞算法?

时间:2016-12-19 13:33:08

标签: javascript algorithm

我正在研究能够尽快检测圆圈碰撞的扫描线,我只是想知道是否有人知道更有效的方式而不是扫描线。我的代码更像是一个行线的混合,使用最大潜在的圆圈大小来移除活动圆圈,当它们不可能发生碰撞时。

如果有人知道更好或者可以给我反馈我实际上已经完成任务的效率,我将非常感激,这一次伤害了我的大脑只是想着它。

的Javascript



var Width = 1200
var Height = 1200
const svg = document.getElementById('svg1')
svg.setAttribute('width', Width)
svg.setAttribute('height', Height)

function seg(x, y, c) {
  var segment = document.createElementNS("http://www.w3.org/2000/svg", "circle")
  segment.setAttribute("cx", x)
  segment.setAttribute("cy", y)
  segment.setAttribute("r", c)
  svg.appendChild(segment)
}

function seg2(x, y, c) {
  var segment = document.createElementNS("http://www.w3.org/2000/svg", "circle")
  segment.setAttribute("cx", x)
  segment.setAttribute("cy", y)
  segment.setAttribute("r", c)
  segment.setAttribute('fill', '#0f0')
  svg.appendChild(segment)
}

function seg3(x, y, c) {
  var segment = document.createElementNS("http://www.w3.org/2000/svg", "circle")
  segment.setAttribute("cx", x)
  segment.setAttribute("cy", y)
  segment.setAttribute("r", c)
  segment.setAttribute('fill', '#ff0')
  svg.appendChild(segment)
}
const circles = []
var addPoints = function(n) {
  for (i = 0; i < n; i++) {
    var o = {
      x: Math.random() * 1000,
      y: Math.random() * 1000,
      c: (Math.random() * 5) + 5
    }
    circles.push(o)
    seg(o.x, o.y, o.c)
  }
}
addPoints(1000)

circles.sort(function(a, b) {
  if (a.x > b.x) return 1
  if (a.x < b.x) return -1
  return 0
})

var peak = function(a) {
  L = 0
  for (i = 0; i < a.length; i++) {
    if (a[i].c > L) {
      L = a[i].c
    }
  }
  return L
}

var sweep = function(J) {
  var A = []
  var M = peak(J)
  for (i = 0; i < J.length; i++) {

    if (A.length > 0) {
      for (k = 0; k < A.length; k++) {
        ea = A[k].x + A[k].c
        jm = J[i].x - M
        if (ea < jm) {
          A.splice(k, 1)
        } else {
          bj = J[i].x - J[i].c
          if ((bj - ea) < 0) {
            yy = Math.abs(A[k].y - J[i].y)
            yt = A[k].c + J[i].c
            if (yy < yt) {
              xx = J[i].x - A[k].x
              yy = J[i].y - A[k].y
              cc = Math.sqrt((xx * xx) + (yy * yy))
              dd = J[i].c + A[k].c
              if (cc < dd) {
                seg2(A[k].x, A[k].y, A[k].c)
                seg3(J[i].x, J[i].y, J[i].c)
              }
            }
          }
        }
      }
    }
    A.push(J[i])
  }
}
sweep(circles)
&#13;
<svg id="svg1"></svg>
&#13;
&#13;
&#13;

1 个答案:

答案 0 :(得分:1)

单轴定理是这里的简单方法。对于圈子来说,它更容易;你只需要检查半径和圆圈之间的距离。这是一种平均在O(n log n)时间内运行的方法:

  1. 创建您喜欢的任何深度的四叉树(静态或动态;足够深但不太​​深)
  2. 地图中的Foreach圆圈,将其插入四叉树。
  3. 地图中的Foreach圆圈,从圆圈的中心查看最多2r的四叉树中的所有位置。如果那里没有任何东西,并且没有其他圈子找到我们,那么这个圆圈不会与任何东西发生碰撞。