13

アニメーション化する線を動的に生成し、線が別の線にぶつかったことを検出したいと考えています。基本的な線形代数を実装して線の方程式を取得し、x、y について解こうとしていますが、結果が不安定です。この時点で、2 本の線のみでテストしています。つまり、1 つの交点を取得する必要がありますが、2 つ取得しています。私は自分の数学が大丈夫であることを確認したいだけで、問題を他の場所で探す必要があります.

function collision(boid1, boid2) {
  var x1 = boid1.initialX, y1 = boid1.initialY, x2 = boid1.x, y2 = boid1.y, x3 = boid2.initialX, y3 = boid2.initialY, x4 = boid2.x, y4 = boid2.y;
  slope1 = (y1 - y2)/(x1 - x2);
  slope2 = (y3 - y4)/(x3- x4);

  if(slope1 != slope2){
    var b1 = getB(slope1,x1,y1);
    var b2 = getB(slope2,x3,y3);

    if(slope2 >= 0){
      u = slope1 - slope2;
    }else{
      u = slope1 + slope2;
    }

    if(b1 >= 0){
      z = b2 - b1;
    }else{
      z = b2 + b1;
    }
    pointX = z / u;
    pointY = (slope1*pointX)+b1;
    pointYOther = (slope2*pointX)+b2;
    console.log("pointx:"+pointX+" pointy:"+pointY+" othery:"+pointYOther);
    context.beginPath();
    context.arc(pointX, pointY, 2, 0, 2 * Math.PI, false);
    context.fillStyle = 'green';
    context.fill();
    context.lineWidth = 1;
    context.strokeStyle = '#003300';
    context.stroke();
  }
  return false;
}

function getB(slope,x,y){
  var y = y, x = x, m = slope;
  a = m*x;
  if(a>=0){
    b = y - a;
  }else{
    b = y + a;
  }
  return b;
}

問題は、交点に対して 2 つの異なる値を取得していることです。1 つしかないはずなので、私の計算が間違っていると思い込んでしまいます。はい、x2、y2、x4、y4 はすべて動いていますが、それらには角度が設定されており、一貫した勾配がそれを裏付けています。

4

5 に答える 5

22

Paul Bourke による素晴らしい解決策を見つけました。これが JavaScript で実装されたものです。

function line_intersect(x1, y1, x2, y2, x3, y3, x4, y4)
{
    var ua, ub, denom = (y4 - y3)*(x2 - x1) - (x4 - x3)*(y2 - y1);
    if (denom == 0) {
        return null;
    }
    ua = ((x4 - x3)*(y1 - y3) - (y4 - y3)*(x1 - x3))/denom;
    ub = ((x2 - x1)*(y1 - y3) - (y2 - y1)*(x1 - x3))/denom;
    return {
        x: x1 + ua * (x2 - x1),
        y: y1 + ua * (y2 - y1),
        seg1: ua >= 0 && ua <= 1,
        seg2: ub >= 0 && ub <= 1
    };
}
于 2016-08-16T14:36:59.337 に答える
6

'found-x' を方程式の 1 つに戻すときに、y 交差の加算/減算を交互に行う必要はありません。

(function () {
    window.linear = {
        slope: function (x1, y1, x2, y2) {
            if (x1 == x2) return false;
            return (y1 - y2) / (x1 - x2);
        },
        yInt: function (x1, y1, x2, y2) {
            if (x1 === x2) return y1 === 0 ? 0 : false;
            if (y1 === y2) return y1;
            return y1 - this.slope(x1, y1, x2, y2) * x1 ;
        },
        getXInt: function (x1, y1, x2, y2) {
            var slope;
            if (y1 === y2) return x1 == 0 ? 0 : false;
            if (x1 === x2) return x1;
            return (-1 * ((slope = this.slope(x1, y1, x2, y2)) * x1 - y1)) / slope;
        },
        getIntersection: function (x11, y11, x12, y12, x21, y21, x22, y22) {
            var slope1, slope2, yint1, yint2, intx, inty;
            if (x11 == x21 && y11 == y21) return [x11, y11];
            if (x12 == x22 && y12 == y22) return [x12, y22];

            slope1 = this.slope(x11, y11, x12, y12);
            slope2 = this.slope(x21, y21, x22, y22);
            if (slope1 === slope2) return false;

            yint1 = this.yInt(x11, y11, x12, y12);
            yint2 = this.yInt(x21, y21, x22, y22);
            if (yint1 === yint2) return yint1 === false ? false : [0, yint1];

            if (slope1 === false) return [y21, slope2 * y21 + yint2];
            if (slope2 === false) return [y11, slope1 * y11 + yint1];
            intx = (slope1 * x11 + yint1 - yint2)/ slope2;
            return [intx, slope1 * intx + yint1];
        }
    }
}());
于 2012-12-18T17:55:50.380 に答える
3

次のようにすることができます。

function lineIntersect(a,b){
  a.m = (a[0].y-a[1].y)/(a[0].x-a[1].x);  // slope of line 1
  b.m = (b[0].y-b[1].y)/(b[0].x-b[1].x);  // slope of line 2
  return a.m - b.m < Number.EPSILON ? undefined
                                    : { x: (a.m * a[0].x - b.m*b[0].x + b[0].y - a[0].y) / (a.m - b.m),
                                        y: (a.m*b.m*(b[0].x-a[0].x) + b.m*a[0].y - a.m*b[0].y) / (b.m - a.m)};
}

var line1 = [{x:3, y:3},{x:17, y:8}],
    line2 = [{x:7, y:10},{x:11, y:2}];
console.log(lineIntersect(line1, line2));

于 2016-12-03T23:32:32.277 に答える