Math 二维空间中三角形碰撞的检测

Math 二维空间中三角形碰撞的检测,math,geometry,collision-detection,Math,Geometry,Collision Detection,给定两个三角形在二维坐标平面上的顶点,如何通过编程检测它们是否相互接触?这包括接触点或边,以及一个三角形是否完全位于另一个三角形内。使用直线相交 也考虑某些顶点可能接触另一个三角形的一个边的可能性。 或者查看此链接并向下滚动 您可以通过找到一条边(构成两个三角形的总共6条边中的一条)来证明这两个三角形没有碰撞,该边充当分隔线,其中一个三角形的所有顶点位于一侧,而另一个三角形的顶点位于另一侧。如果可以找到这样的边,则表示三角形不相交,否则三角形会发生碰撞 这里是一个三角形碰撞函数的Matlab

给定两个三角形在二维坐标平面上的顶点,如何通过编程检测它们是否相互接触?这包括接触点或边,以及一个三角形是否完全位于另一个三角形内。

使用直线相交

也考虑某些顶点可能接触另一个三角形的一个边的可能性。

或者查看此链接并向下滚动


您可以通过找到一条边(构成两个三角形的总共6条边中的一条)来证明这两个三角形没有碰撞,该边充当分隔线,其中一个三角形的所有顶点位于一侧,而另一个三角形的顶点位于另一侧。如果可以找到这样的边,则表示三角形不相交,否则三角形会发生碰撞

这里是一个三角形碰撞函数的Matlab实现。您可以在这里找到
sameside
函数的原理:


简而言之,哈桑的答案是最快的

这是javascript中最快的代码:

// check that all points of the other triangle are on the same side of the triangle after mapping to barycentric coordinates.
// returns true if all points are outside on the same side
var cross2 = function(points, triangle) {
  var pa = points.a;
  var pb = points.b;
  var pc = points.c;
  var p0 = triangle.a;
  var p1 = triangle.b;
  var p2 = triangle.c;
  var dXa = pa.x - p2.x;
  var dYa = pa.y - p2.y;
  var dXb = pb.x - p2.x;
  var dYb = pb.y - p2.y;
  var dXc = pc.x - p2.x;
  var dYc = pc.y - p2.y;
  var dX21 = p2.x - p1.x;
  var dY12 = p1.y - p2.y;
  var D = dY12 * (p0.x - p2.x) + dX21 * (p0.y - p2.y);
  var sa = dY12 * dXa + dX21 * dYa;
  var sb = dY12 * dXb + dX21 * dYb;
  var sc = dY12 * dXc + dX21 * dYc;
  var ta = (p2.y - p0.y) * dXa + (p0.x - p2.x) * dYa;
  var tb = (p2.y - p0.y) * dXb + (p0.x - p2.x) * dYb;
  var tc = (p2.y - p0.y) * dXc + (p0.x - p2.x) * dYc;
  if (D < 0) return ((sa >= 0 && sb >= 0 && sc >= 0) ||
                     (ta >= 0 && tb >= 0 && tc >= 0) ||
                     (sa+ta <= D && sb+tb <= D && sc+tc <= D));
  return ((sa <= 0 && sb <= 0 && sc <= 0) ||
          (ta <= 0 && tb <= 0 && tc <= 0) ||
          (sa+ta >= D && sb+tb >= D && sc+tc >= D));
}

var trianglesIntersect4 = function(t0, t1) {
  return !(cross2(t0,t1) ||
           cross2(t1,t0));
}
//映射到重心坐标后,检查其他三角形的所有点是否位于三角形的同一侧。
//如果所有点位于同一侧的外侧,则返回true
var cross2=函数(点、三角形){
var pa=点a;
var pb=点b;
var pc=点c;
var p0=三角形a;
var p1=三角形b;
var p2=三角形c;
var dXa=pa.x-p2.x;
var dYa=pa.y-p2.y;
var dXb=pb.x-p2.x;
var dYb=pb.y-p2.y;
var dXc=pc.x-p2.x;
var dYc=pc.y-p2.y;
var dX21=p2.x-p1.x;
var dY12=p1.y-p2.y;
var D=dY12*(p0.x-p2.x)+dX21*(p0.y-p2.y);
var sa=dY12*dXa+dX21*dYa;
var sb=dY12*dXb+dX21*dYb;
var sc=dY12*dXc+dX21*dYc;
var ta=(p2.y-p0.y)*dXa+(p0.x-p2.x)*dYa;
var-tb=(p2.y-p0.y)*dXb+(p0.x-p2.x)*dYb;
var-tc=(p2.y-p0.y)*dXc+(p0.x-p2.x)*dYc;
如果(D<0)返回((sa>=0&&sb>=0&&sc>=0)||
(ta>=0&&tb>=0&&tc>=0)||

(sa+ta看起来很像这个问题的副本:这是3D的,不是2D的,但也许那里的一些答案会对你有所帮助。我已经看过这个问题了,它似乎有比我需要的更多的信息,因为它是3D的,我不想让这里的计算过于复杂(这些将在一个循环中执行,并且应该尽可能经济高效)。可能的重复并不能检查一个三角形是否完全位于另一个三角形内,是吗。@SpikeX:我想说同样的话,但我认为您需要单击底部的链接以查找PointInPolygon writeup()为此,你需要确保所有3个顶点都在边上或三角形内部。让我找到一个链接。同时,请随意向上投票。好吧,这可能并不漂亮,但我可以将你的“PointInTriangle”函数与线条检测函数结合起来,以获得我所需要的。(我在这里的第一条评论是在编辑帖子之前)如果你想以可读性为代价进行超级优化的话,先考虑编写单元测试,然后再把代码放在代码中以加快速度。如果你记住所有三角形都是凸形的,那么你可以做得更快。因为它们是凸的,当你绕着这些点旋转时,它们都在同一个方向上旋转,所以YO。你总是知道三角形的点在哪一边。你如何找到交点,如何排除相同的点?
function flag = triangle_intersection(P1, P2)
% triangle_test : returns true if the triangles overlap and false otherwise

% P1, P2: a 3 by 2 array (each), describing the vertices of a triangle,
% the first column corresponds to the x coordinates while the second column
% corresponds to the y coordinates

    function flag = sameside(p1,p2,a,b)
        % sameside : returns true if the p1,p1 lie on same sides of the
        % edge ab and false otherwise

        p1(3) = 0; p2(3) = 0; a(3) = 0; b(3) = 0;
        cp1 = cross(b-a, p1-a);
        cp2 = cross(b-a, p2-a);
        if(dot(cp1, cp2) >= 0)
            flag = true;
        else
            flag = false;
        end
    end

% Repeat the vertices for the loop
P1(4:5,:) = P1(1:2,:);
P2(4:5,:) = P2(1:2,:);

flag = true;

% Testing all the edges of P1
for i=1:3
    if(~sameside(P1(i,:), P2(1,:), P1(i+1,:), P1(i+2,:)) ...
            && sameside(P2(1,:), P2(2,:), P1(i+1,:), P1(i+2,:)) ...
            && sameside(P2(2,:), P2(3,:), P1(i+1,:), P1(i+2,:)))
        flag = false; return;
    end
end

% Testing all the edges of P2
for i=1:3
    if(~sameside(P2(i,:), P1(1,:), P2(i+1,:), P2(i+2,:)) ...
            && sameside(P1(1,:), P1(2,:), P2(i+1,:), P2(i+2,:)) ...
            && sameside(P1(2,:), P1(3,:), P2(i+1,:), P2(i+2,:)))
        flag = false; return;
    end
end

end
// check that all points of the other triangle are on the same side of the triangle after mapping to barycentric coordinates.
// returns true if all points are outside on the same side
var cross2 = function(points, triangle) {
  var pa = points.a;
  var pb = points.b;
  var pc = points.c;
  var p0 = triangle.a;
  var p1 = triangle.b;
  var p2 = triangle.c;
  var dXa = pa.x - p2.x;
  var dYa = pa.y - p2.y;
  var dXb = pb.x - p2.x;
  var dYb = pb.y - p2.y;
  var dXc = pc.x - p2.x;
  var dYc = pc.y - p2.y;
  var dX21 = p2.x - p1.x;
  var dY12 = p1.y - p2.y;
  var D = dY12 * (p0.x - p2.x) + dX21 * (p0.y - p2.y);
  var sa = dY12 * dXa + dX21 * dYa;
  var sb = dY12 * dXb + dX21 * dYb;
  var sc = dY12 * dXc + dX21 * dYc;
  var ta = (p2.y - p0.y) * dXa + (p0.x - p2.x) * dYa;
  var tb = (p2.y - p0.y) * dXb + (p0.x - p2.x) * dYb;
  var tc = (p2.y - p0.y) * dXc + (p0.x - p2.x) * dYc;
  if (D < 0) return ((sa >= 0 && sb >= 0 && sc >= 0) ||
                     (ta >= 0 && tb >= 0 && tc >= 0) ||
                     (sa+ta <= D && sb+tb <= D && sc+tc <= D));
  return ((sa <= 0 && sb <= 0 && sc <= 0) ||
          (ta <= 0 && tb <= 0 && tc <= 0) ||
          (sa+ta >= D && sb+tb >= D && sc+tc >= D));
}

var trianglesIntersect4 = function(t0, t1) {
  return !(cross2(t0,t1) ||
           cross2(t1,t0));
}