Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/algorithm/11.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Javascript 是否有一种算法可以检测我与多边形的哪一侧发生碰撞?_Javascript_Algorithm_Collision Detection_Computational Geometry_Polygons - Fatal编程技术网

Javascript 是否有一种算法可以检测我与多边形的哪一侧发生碰撞?

Javascript 是否有一种算法可以检测我与多边形的哪一侧发生碰撞?,javascript,algorithm,collision-detection,computational-geometry,polygons,Javascript,Algorithm,Collision Detection,Computational Geometry,Polygons,如果给定一个n边的多边形,以及一条长度k(在x,y和角度a)的直线,是否有一种算法来检测我与多边形的哪一侧(如果有)发生碰撞?到目前为止,我已经求助于测试x,y是否在多边形之外,然后迭代多边形的每个边,计算到每个端点的距离。这是一张展示我创造的世界的照片 以下是JavaScript(HTML和CSS不值得复制): var eventLoop, 最大速度=10, 敏捷度=5, 基准长度=5, 度=((2*Math.PI)/360), world=document.getElementById('w

如果给定一个
n
边的多边形,以及一条长度
k
(在
x,y
和角度
a
)的直线,是否有一种算法来检测我与多边形的哪一侧(如果有)发生碰撞?到目前为止,我已经求助于测试
x,y
是否在多边形之外,然后迭代多边形的每个边,计算到每个端点的距离。这是一张展示我创造的世界的照片

以下是JavaScript(HTML和CSS不值得复制):

var eventLoop,
最大速度=10,
敏捷度=5,
基准长度=5,
度=((2*Math.PI)/360),
world=document.getElementById('world'),
context=world.getContext(“2d”),
边界=[[180,120]、[240,60]、[360,40]、[420,120]、[360,220]、[350,240]、[360,265]、[470360]、[450480]、[360540]、[240550]、[140480]、[120470]、[100360]、[120300]、[220240]、[240220],
摄像机={
地点:{
x:300,
y:90
},
角度:0,
速度:0
},
发动机={
drawWorld:功能(形状、上下文){
var point,
指数
尺寸=形状。长度;
clearRect(0,0,world.width,world.height);
context.beginPath();
对于(索引=0;索引point.y)!=(shape[j][1]>point.y))&(point.x<(shape[j][0]-shape[i][0])*(point.y-shape[i][1])/(shape[j][1]-shape[i][1])+shape[i][0])){
c=!c;
}
}
返回c;
}
};
document.onkeydown=函数(e){
e=e | | window.event;
如果(e.keyCode=='37'){
//左箭头
相机角度+=度*敏捷度;
}
否则如果(e.keyCode=='39'){
//右箭头
相机角度-=度*敏捷度;
}
否则如果(e.keyCode=='38'){
//向上箭头
摄像机速度+=1;
如果(camera.velocity>maxVelocity){
camera.velocity=最大速度;
}
}
否则如果(e.keyCode=='40'){
//向下箭头
摄像机速度-=1;
如果(摄影机速度<0){
摄像机速度=0;
}
}
}
drawWorld(边界、上下文);
引擎。drawCamera(摄像头,上下文);
eventLoop=setInterval(函数(){
drawWorld(边界、上下文);
引擎。drawCamera(摄像头,上下文);
if(引擎isInside(摄像头位置、边界)){
camera.location=发动机.calcNextPoint(摄像头,1);
}
}, 100);

我一直在玩弄一些JavaScript来模拟ThatGameComapny游戏的二维版本,最终我想尝试实现Oculus Rift版本。我要解决的下一个问题是,一旦玩家与边缘发生碰撞,就要将玩家转回多边形。

一个通用的LS-to-LS测试将包括查找多边形端点p[I],p[I+1]是否位于向量(p,p+d)的另一侧,其中d是方向向量。为了使两条线交叉,也必须保持相反的顺序:两条(p,p+d)必须位于线段p[i],p[i+1]的不同侧

  o  P[i]              Here P[i], P[i+1] are on different side of p -> q=p+d
   \                   but not the opposite.
    \     q__----p
     \
      o  P[i+1]
在复杂或凹面场景中,向量可以跨越多个线段,需要求解最近的线段。这是从参数方程中最容易做到的

  (x0, y0) + (t * dx, t * dy) == i[0] + u * (i[1]-i[0]), j[0] + u * (j[1]-j[0])
编辑 比较点(i[n],j[n])与线(x0,y0)->(x0+dx,x1+dy)的符号距离需要两个点积和符号比较

  sameSide = sign((i0-x0)*(-dy)+(j0-y0)*dx) == sign((i1-x0)*(-dy)+(j1-y0)*dx))

在javascript中,这可以通过
a*b>0
最有效地完成,其中
a
b
是符号处于比较状态的表达式。

所以您基本上想知道多边形的哪些边与给定的线相交,对吗

这只是对表示边的几个的简单处理(更精确地说,是不等式)。您已经有了一个很棒的
内部
操作的实现,它也可以做到这一点。所有这些算法的共同点是比较
[x1,y1]
-
[x2,y2]
[x,y]
位于线的哪一侧:

compare = function (a, b) { // classical compare function, returns -1, 0, 1
    return a < b ? -1 : (a == b ? 0 : 1);
}
...
_lineSide: function (x, y, x1, y1, x2, y2) {
    return compare(x - x1, (x2 - x1) * (y - y1) / (y2 - y1));
}
现在,测试两条线是否相交非常容易。只要看看
[x1,y1]
[x2,y2]
是否位于
[x3,y3]
-
[x4,y4]
的对面,如果
[x3,y3]
[x4,y4]
位于
[x1,y1]
的对面。如果是,则两条线相交

// proper: true/false (default false) - if we want proper intersection, i.e. just 
// touching doesn't count
linesIntersect: function (x1, y1, x2, y2, x3, y3, x4, y4, proper) {
    var min_diff = proper ? 2 : 1;
    return Math.abs(this.lineSide(x1, y1, x3, y3, x4, y4) - 
                    this.lineSide(x2, y2, x3, y3, x4, y4)) >= min_diff 
        && Math.abs(this.lineSide(x3, y3, x1, y1, x2, y2) - 
                    this.lineSide(x4, y4, x1, y1, x2, y2)) >= min_diff;
},
最终解决方案- 现在,最终解决方案是eas
lineSide: function (x, y, x1, y1, x2, y2) {
    var eps = 1e-20; // some very small number
    if (Math.abs(y2 - y1) > eps)       // this way we avoid division by small number
        return _lineSide(x, y, x1, y1, x2, y2);
    else if (Math.abs(x2 - x1) > eps)  // flip the situation for horizontal lines
        return _lineSide(y, x, y1, x1, y2, x2);
    else // edge has close-to-zero length!
        throw new this.zeroLengthLineException()
},
zeroLengthLineException: function () {},
// proper: true/false (default false) - if we want proper intersection, i.e. just 
// touching doesn't count
linesIntersect: function (x1, y1, x2, y2, x3, y3, x4, y4, proper) {
    var min_diff = proper ? 2 : 1;
    return Math.abs(this.lineSide(x1, y1, x3, y3, x4, y4) - 
                    this.lineSide(x2, y2, x3, y3, x4, y4)) >= min_diff 
        && Math.abs(this.lineSide(x3, y3, x1, y1, x2, y2) - 
                    this.lineSide(x4, y4, x1, y1, x2, y2)) >= min_diff;
},
var lib = {
  // Find parameters of intersection of segments a->b and c->d or null for parallel lines
  intersectionParams: function(a, b, c, d) {
    var dx_ab = b.x - a.x
    var dy_ab = b.y - a.y
    var dx_dc = c.x - d.x
    var dy_dc = c.y - d.y
    var eps = 0.00001
    var det = dx_ab * dy_dc - dx_dc * dy_ab
    if (-eps < det && det < eps) return null
    var dx_ac = c.x - a.x
    var dy_ac = c.y - a.y
    var t_ab = (dx_ac * dy_dc - dx_dc * dy_ac) / det
    var t_cd = (dx_ab * dy_ac - dx_ac * dy_ab) / det
    return { t_ab: t_ab, t_cd: t_cd }
  },

  // Determine if intersection parameters represent an intersection.
  // This always counts parallel lines as non-intersecting even if they're touching.
  areIntersecting: function(ip) {
    return ip != null && 0 <= ip.t_ab && ip.t_ab <= 1 && 0 <= ip.t_cd && ip.t_cd <= 1
  },

  // Find the intersection from its parameters and two points.
  intersection: function(ip, a, b) {
    return { x: a.x + ip.t_ab * (b.x - a.x), y: a.y + ip.t_ab * (b.y - a.y) }
  }
}