画布三角形,五边形,矩形相互碰撞检测



我有一些代码,其中绘制一个三角形,并返回一个对象与x1, y1, x2, y2, x3, y3在它。我还有一个矩形绘制函数,它返回x, y, w, h,还有一个五边形绘制函数,它返回x1, y1, x2, y2, x3, y3, x4, y4, x5, y5。如何创建一个碰撞检测函数来检测矩形和五边形或者三角形和五边形是否发生了碰撞?

测试三角形的任何边(线段)是否与矩形的任何边相交

如果有任何边相交,则三角形&矩形在碰撞

  • 对矩形的每条边测试三角形的#1边,
  • 对矩形的每条边测试三角形的#2边,
  • 对矩形的每条边测试三角形的#3边,
  • 如果你在测试时发现一个拦截,你可以停止,因为形状确实在碰撞。

参见下面的"两条线段是否相交?"

对任何其他多边形进行相同的侧拦截测试,看看它们是否碰撞。

2行拦截的测试在这里重现:

// point object: {x:, y:}
// p0 & p1 form one segment, p2 & p3 form the second segment
// Returns true if lines segments are intercepting
var lineSegmentsIntercept = (function(){ // function as singleton so that closure can be used
    var v1, v2, v3, cross, u1, u2;  // working variable are closed over so they do not need creation 
                               // each time the function is called. This gives a significant performance boost.
    v1 = {x : null, y : null}; // line p0, p1 as vector
    v2 = {x : null, y : null}; // line p2, p3 as vector
    v3 = {x : null, y : null}; // the line from p0 to p2 as vector
    function lineSegmentsIntercept (p0, p1, p2, p3) {
        v1.x = p1.x - p0.x; // line p0, p1 as vector
        v1.y = p1.y - p0.y; 
        v2.x = p3.x - p2.x; // line p2, p3 as vector
        v2.y = p3.y - p2.y; 
        if((cross = v1.x * v2.y - v1.y * v2.x) === 0){  // cross prod 0 if lines parallel
            return false; // no intercept
        }
        v3 = {x : p0.x - p2.x, y : p0.y - p2.y};  // the line from p0 to p2 as vector
        u2 = (v1.x * v3.y - v1.y * v3.x) / cross; // get unit distance along line p2 p3 
        // code point B
        if (u2 >= 0 && u2 <= 1){                   // is intercept on line p2, p3
            u1 = (v2.x * v3.y - v2.y * v3.x) / cross; // get unit distance on line p0, p1;
            // code point A
            return (u1 >= 0 && u1 <= 1);           // return true if on line else false.
            // code point A end
        }
        return false; // no intercept;
        // code point B end
    }
    return lineSegmentsIntercept;  // return function with closure for optimisation.
})();


两条线段是否相交?

(归因于用户blindman67协助以下示例)

如果两个线段相交,函数返回true,如果不相交,函数返回false

这个例子是为性能而设计的,并使用闭包来保存工作变量

' ' ' Javascript//点对象:{x:, y:}//p0 &P1形成一段,p2 &P3形成第二段//如果线段截取,返回truevar lineSegmentsIntercept = (function(){//函数为单例,以便闭包可以使用

    var v1, v2, v3, cross, u1, u2;  // working variable are closed over so they do not need creation 
                               // each time the function is called. This gives a significant performance boost.
    v1 = {x : null, y : null}; // line p0, p1 as vector
    v2 = {x : null, y : null}; // line p2, p3 as vector
    v3 = {x : null, y : null}; // the line from p0 to p2 as vector
    function lineSegmentsIntercept (p0, p1, p2, p3) {
        v1.x = p1.x - p0.x; // line p0, p1 as vector
        v1.y = p1.y - p0.y; 
        v2.x = p3.x - p2.x; // line p2, p3 as vector
        v2.y = p3.y - p2.y; 
        if((cross = v1.x * v2.y - v1.y * v2.x) === 0){  // cross prod 0 if lines parallel
            return false; // no intercept
        }
        v3 = {x : p0.x - p2.x, y : p0.y - p2.y};  // the line from p0 to p2 as vector
        u2 = (v1.x * v3.y - v1.y * v3.x) / cross; // get unit distance along line p2 p3 
        // code point B
        if (u2 >= 0 && u2 <= 1){                   // is intercept on line p2, p3
            u1 = (v2.x * v3.y - v2.y * v3.x) / cross; // get unit distance on line p0, p1;
            // code point A
            return (u1 >= 0 && u1 <= 1);           // return true if on line else false.
            // code point A end
        }
        return false; // no intercept;
        // code point B end
    }
    return lineSegmentsIntercept;  // return function with closure for optimisation.
})();

```

使用示例
var p1 = {x: 100, y: 0};   // line 1
var p2 = {x: 120, y: 200};
var p3 = {x: 0,   y: 100}; // line 2
var p4 = {x: 100, y: 120};
var areIntersepting = lineSegmentsIntercept (p1, p2, p3, p4); // true

这个例子很容易修改为返回截距点。将code point AA end之间的代码替换为

if(u1 >= 0 && u1 <= 1){
    return {
        x : p0.x + v1.x * u1,
        y : p0.y + v1.y * u1,
    };
}

或者,如果您想获得行上的截距点,则忽略线段的开始和结束,将code point BB end之间的代码替换为

return {
    x : p2.x + v2.x * u2,
    y : p2.y + v2.y * u2,
};

如果没有拦截,这两个修改都将返回false,或者返回拦截点为{x : xCoord, y : yCoord}

最新更新