Math 如何检查两个旋转矩形之间的交点?

Math 如何检查两个旋转矩形之间的交点?,math,intersection,rect,Math,Intersection,Rect,有人能解释一下如何检查一个旋转的矩形是否与另一个矩形相交吗 对于两个多边形中的每条边,请检查它是否可以用作分隔线。如果是这样,您就完成了:无交叉口 如果未找到分隔线,则有一个交点 ///检查两个多边形是否相交。 布尔多边形相交(多边形a、多边形b) { foreach(新[]{a,b}中的var多边形) { 对于(int i1=0;i1

有人能解释一下如何检查一个旋转的矩形是否与另一个矩形相交吗

  • 对于两个多边形中的每条边,请检查它是否可以用作分隔线。如果是这样,您就完成了:无交叉口
  • 如果未找到分隔线,则有一个交点
  • ///检查两个多边形是否相交。
    布尔多边形相交(多边形a、多边形b)
    {
    foreach(新[]{a,b}中的var多边形)
    {
    对于(int i1=0;i1maxA)
    maxA=预测值;
    }
    double?minB=null,maxB=null;
    foreach(b点中的var p)
    {
    预计风险值=正常.X*p.X+正常.Y*p.Y;
    if(minB==null | |投影maxB)
    maxB=预测值;
    }
    if(maxA
    有关更多信息,请参阅本文:


    NB:该算法仅适用于按顺时针或逆时针顺序指定的凸多边形。

    在javascript中,完全相同的算法是(为方便起见):

    /**
    *用于确定所述两个多边形之间是否存在交点的辅助函数
    *通过顶点列表。使用分离轴定理
    *
    *@param一组连接点[{x:,y:},{x:,y:},…]构成一个闭合多边形
    *@param b一组连接点[{x:,y:},{x:,y:},…]构成一个闭合多边形
    *@如果两个多边形之间存在任何交点,则返回true,否则返回false
    */
    函数doPolygonsIntersect(a,b){
    var多边形=[a,b];
    var minA,maxA,projected,i,i1,j,minB,maxB;
    对于(i=0;i最大值){
    maxA=预测值;
    }
    }
    //对于第二个形状中的每个顶点,将其投影到与边垂直的线上
    //并跟踪这些值的最小值和最大值
    minB=maxB=未定义;
    对于(j=0;j最大值){
    maxB=预测值;
    }
    }
    //如果两个项目之间没有重叠,那么我们所看到的边缘将两者分开
    //多边形,我们知道没有重叠
    if(maxA

    希望这对别人有帮助

    查看Oren Becker设计的检测旋转矩形与形状相交的方法:

    struct _Vector2D 
    {
        float x, y;
    };
    
    // C:center; S: size (w,h); ang: in radians, 
    // rotate the plane by [-ang] to make the second rectangle axis in C aligned (vertical)
    struct _RotRect 
    {
        _Vector2D C;
        _Vector2D S;
        float ang;
    };
    
    调用以下函数将返回两个旋转的矩形是否相交:

    // Rotated Rectangles Collision Detection, Oren Becker, 2001
    bool check_two_rotated_rects_intersect(_RotRect * rr1, _RotRect * rr2)
    {
        _Vector2D A, B,   // vertices of the rotated rr2
           C,      // center of rr2
           BL, TR; // vertices of rr2 (bottom-left, top-right)
    
     float ang = rr1->ang - rr2->ang, // orientation of rotated rr1
           cosa = cos(ang),           // precalculated trigonometic -
           sina = sin(ang);           // - values for repeated use
    
     float t, x, a;      // temporary variables for various uses
     float dx;           // deltaX for linear equations
     float ext1, ext2;   // min/max vertical values
    
     // move rr2 to make rr1 cannonic
     C = rr2->C;
     SubVectors2D(&C, &rr1->C);
    
     // rotate rr2 clockwise by rr2->ang to make rr2 axis-aligned
     RotateVector2DClockwise(&C, rr2->ang);
    
     // calculate vertices of (moved and axis-aligned := 'ma') rr2
     BL = TR = C;
     /*SubVectors2D(&BL, &rr2->S);
     AddVectors2D(&TR, &rr2->S);*/
    
     //-----------------------------------
     BL.x -= rr2->S.x/2;    BL.y -= rr2->S.y/2;
     TR.x += rr2->S.x/2;    TR.y += rr2->S.y/2;
    
     // calculate vertices of (rotated := 'r') rr1
     A.x = -(rr1->S.y/2)*sina; B.x = A.x; t = (rr1->S.x/2)*cosa; A.x += t; B.x -= t;
     A.y =  (rr1->S.y/2)*cosa; B.y = A.y; t = (rr1->S.x/2)*sina; A.y += t; B.y -= t;
     //---------------------------------------
    
     //// calculate vertices of (rotated := 'r') rr1
     //A.x = -rr1->S.y*sina; B.x = A.x; t = rr1->S.x*cosa; A.x += t; B.x -= t;
     //A.y =  rr1->S.y*cosa; B.y = A.y; t = rr1->S.x*sina; A.y += t; B.y -= t;
    
     t = sina*cosa;
    
     // verify that A is vertical min/max, B is horizontal min/max
     if (t < 0)
     {
      t = A.x; A.x = B.x; B.x = t;
      t = A.y; A.y = B.y; B.y = t;
     }
    
     // verify that B is horizontal minimum (leftest-vertex)
     if (sina < 0) { B.x = -B.x; B.y = -B.y; }
    
     // if rr2(ma) isn't in the horizontal range of
     // colliding with rr1(r), collision is impossible
     if (B.x > TR.x || B.x > -BL.x) return 0;
    
     // if rr1(r) is axis-aligned, vertical min/max are easy to get
     if (t == 0) {ext1 = A.y; ext2 = -ext1; }
     // else, find vertical min/max in the range [BL.x, TR.x]
     else
     {
      x = BL.x-A.x; a = TR.x-A.x;
      ext1 = A.y;
      // if the first vertical min/max isn't in (BL.x, TR.x), then
      // find the vertical min/max on BL.x or on TR.x
      if (a*x > 0)
      {
       dx = A.x;
       if (x < 0) { dx -= B.x; ext1 -= B.y; x = a; }
       else       { dx += B.x; ext1 += B.y; }
       ext1 *= x; ext1 /= dx; ext1 += A.y;
      }
    
      x = BL.x+A.x; a = TR.x+A.x;
      ext2 = -A.y;
      // if the second vertical min/max isn't in (BL.x, TR.x), then
      // find the local vertical min/max on BL.x or on TR.x
      if (a*x > 0)
      {
       dx = -A.x;
       if (x < 0) { dx -= B.x; ext2 -= B.y; x = a; }
       else       { dx += B.x; ext2 += B.y; }
       ext2 *= x; ext2 /= dx; ext2 -= A.y;
      }
     }
    
     // check whether rr2(ma) is in the vertical range of colliding with rr1(r)
     // (for the horizontal range of rr2)
     return !((ext1 < BL.y && ext2 < BL.y) ||
          (ext1 > TR.y && ext2 > TR.y));
    }
    
    inline void AddVectors2D(_Vector2D * v1, _Vector2D * v2)
    { 
        v1->x += v2->x; v1->y += v2->y; 
    }
    
    inline void SubVectors2D(_Vector2D * v1, _Vector2D * v2)
    { 
        v1->x -= v2->x; v1->y -= v2->y; 
    }
    
    inline void RotateVector2DClockwise(_Vector2D * v, float ang)
    {
        float t, cosa = cos(ang), sina = sin(ang);
        t = v->x; 
        v->x = t*cosa + v->y*sina; 
        v->y = -t*sina + v->y*cosa;
    }
    
    旋转矩形碰撞检测,Oren Becker,2001 布尔检查两个旋转的矩形相交(_RotRect*rr1,_RotRect*rr2) { _向量2D A,B,//旋转的rr2的顶点 C、 //rr2的中心 BL,TR;//rr2的顶点(左下、右上) 浮动ang=rr1->ang-rr2->ang,//旋转rr1的方向 cosa=cos(ang),//预先计算的三角- sina=sin(ang);//-重复使用的值 float t t,x,a;//各种用途的临时变量 float dx;//线性方程组的deltaX 浮点ext1,ext2;//最小/最大垂直值 //移动rr2使rr1成为火炮 C=rr2->C; 子向量2d(&C,&rr1->C); //按rr2->ang顺时针旋转rr2,使rr2轴对齐 顺时针旋转驱动器2(&C,rr2->ang); //计算(移动并对齐轴:='ma')rr2的顶点 BL=TR=C; /*子向量2d(&BL,&rr2->S); 添加向量2d(&TR,&rr2->S)*/ //----------------------------------- BL.x-=rr2->S.x/2;BL.y-=rr2->S.y/2; TR.x+=rr2->S.x/2;TR.y+=rr2->S.y/2; //计算(旋转:='r')rr1的顶点 A.x=-(rr1->S.y/2)*sina;B.x=A.x;t=(rr1->S.x/2)*cosa;A.x+=t;B.x-=t; A.y=(rr1->S.y/2)*cosa;B.y=A.y;t=(rr1->S.x/2)*sina;A.y+=t;B.y-=t; //---------------
    bool IsIntersecting(UIElement element1, UIElement element2)
    {
        Rect area1 = new Rect(
            (double)element1.GetValue(Canvas.TopProperty),
            (double)element1.GetValue(Canvas.LeftProperty),
            (double)element1.GetValue(Canvas.WidthProperty),
            (double)element1.GetValue(Canvas.HeightProperty));
    
        Rect area2 = new Rect(
            (double)element2.GetValue(Canvas.TopProperty),
            (double)element2.GetValue(Canvas.LeftProperty),
            (double)element2.GetValue(Canvas.WidthProperty),
            (double)element2.GetValue(Canvas.HeightProperty));
    
        Transform transform1 = element1.RenderTransform as Transform;
        Transform transform2 = element2.RenderTransform as Transform;
    
        if (transform1 != null)
        {
            area1.Transform(transform1.Value);
        }
    
        if (transform2 != null)
        {
            area2.Transform(transform2.Value);
        }
    
        return area1.IntersectsWith(area2);
    }
    
    math.inf = 1e309
    function love.load()
        pol = {{0, 0}, {30, 2}, {8, 30}}
        pol2 = {{60, 60}, {90, 61}, {98, 100}, {80, 100}}
    end
    function love.draw()
        for k,v in ipairs(pol) do
            love.graphics.line(pol[k][1], pol[k][2], pol[k % #pol + 1][1], pol[k % #pol + 1][2])
        end
        for k,v in ipairs(pol2) do
            love.graphics.line(pol2[k][1], pol2[k][2], pol2[k % #pol2 + 1][1], pol2[k % #pol2 + 1][2])
        end
    end
    
    function love.update(dt)
        pol[1][1] = love.mouse.getX()
        pol[1][2] = love.mouse.getY()
        pol[2][1] = pol[1][1] + 30
        pol[2][2] = pol[1][2] + 2
        pol[3][1] = pol[1][1] + 8
        pol[3][2] = pol[1][2] + 30
    
        --lazy way to see that's function works
        print(doPolygonsIntersect(pol, pol2))
    end
    -------------------------------------------------------------------------
    function doPolygonsIntersect(a,b)
    polygons = {a,b}
    for i=1, #polygons do
        polygon = polygons[i]
        for i1=1, #polygon do
            i2 = i1 % #polygon + 1
            p1 = polygon[i1]
            p2 = polygon[i2]
    
            nx,ny = p2[2] - p1[2], p1[1] - p2[1]
    
            minA = math.inf
            maxA = -math.inf
            for j=1, #a do
                projected = nx * a[j][1] + ny * a[j][2]
                if projected < minA then minA = projected end
                if projected > maxA then maxA = projected end
            end
    
            minB = math.inf
            maxB = -math.inf
            for j=1, #b do
                projected = nx * b[j][1] + ny * b[j][2]
                if projected < minB then minB = projected end
                if projected > maxB then maxB = projected end
            end
    
            if maxA < minB or maxB < minA then return false end
        end
    end
    return true
    end
    
    def do_polygons_intersect(a, b):
        """
     * Helper function to determine whether there is an intersection between the two polygons described
     * by the lists of vertices. Uses the Separating Axis Theorem
     *
     * @param a an ndarray of connected points [[x_1, y_1], [x_2, y_2],...] that form a closed polygon
     * @param b an ndarray of connected points [[x_1, y_1], [x_2, y_2],...] that form a closed polygon
     * @return true if there is any intersection between the 2 polygons, false otherwise
        """
    
        polygons = [a, b];
        minA, maxA, projected, i, i1, j, minB, maxB = None, None, None, None, None, None, None, None
    
        for i in range(len(polygons)):
    
            # for each polygon, look at each edge of the polygon, and determine if it separates
            # the two shapes
            polygon = polygons[i];
            for i1 in range(len(polygon)):
    
                # grab 2 vertices to create an edge
                i2 = (i1 + 1) % len(polygon);
                p1 = polygon[i1];
                p2 = polygon[i2];
    
                # find the line perpendicular to this edge
                normal = { 'x': p2[1] - p1[1], 'y': p1[0] - p2[0] };
    
                minA, maxA = None, None
                # for each vertex in the first shape, project it onto the line perpendicular to the edge
                # and keep track of the min and max of these values
                for j in range(len(a)):
                    projected = normal['x'] * a[j][0] + normal['y'] * a[j][1];
                    if (minA is None) or (projected < minA): 
                        minA = projected
    
                    if (maxA is None) or (projected > maxA):
                        maxA = projected
    
                # for each vertex in the second shape, project it onto the line perpendicular to the edge
                # and keep track of the min and max of these values
                minB, maxB = None, None
                for j in range(len(b)): 
                    projected = normal['x'] * b[j][0] + normal['y'] * b[j][1]
                    if (minB is None) or (projected < minB):
                        minB = projected
    
                    if (maxB is None) or (projected > maxB):
                        maxB = projected
    
                # if there is no overlap between the projects, the edge we are looking at separates the two
                # polygons, and we know there is no overlap
                if (maxA < minB) or (maxB < minA):
                    print("polygons don't intersect!")
                    return False;
    
        return True
    
        /// Checks if the two Phaser 3 polygons are intersecting.
        gameScene.doPolygonsIntersect=function(a, b) {
            // https://stackoverflow.com/questions/10962379/how-to-check-intersection-between-2-rotated-rectangles#10965077
            /**
             * Helper function to determine whether there is an intersection between the two polygons described
             * by the lists of vertices. Uses the Separating Axis Theorem
             *
             * @param a an array of connected points [{x:, y:}, {x:, y:},...] that form a closed polygon
             * @param b an array of connected points [{x:, y:}, {x:, y:},...] that form a closed polygon
             * @return true if there is any intersection between the 2 polygons, false otherwise
             */
    
            var polygons = [a, b];
            var minA, maxA, projected, i, i1, j, minB, maxB;
    
            for (i = 0; i < polygons.length; i++) {
    
                // for each polygon, look at each edge of the polygon, and determine if it separates
                // the two shapes
                var polygon = polygons[i];
                for (i1 = 0; i1 < polygon.points.length; i1++) {
    
                    // grab 2 vertices to create an edge
                    var i2 = (i1 + 1) % polygon.points.length;
                    var p1 = polygon.points[i1];
                    var p2 = polygon.points[i2];
    
                    // find the line perpendicular to this edge
                    var normal = { x: p2.y - p1.y, y: p1.x - p2.x };
    
                    minA = maxA = undefined;
                    // for each vertex in the first shape, project it onto the line perpendicular to the edge
                    // and keep track of the min and max of these values
                    for (j = 0; j < a.points.length; j++) {
                        projected = normal.x * a.points[j].x + normal.y * a.points[j].y;
                        if (!isDef(minA) || projected < minA) {
                            minA = projected;
                        }
                        if (!isDef(maxA) || projected > maxA) {
                            maxA = projected;
                        }
                    }
    
                    // for each vertex in the second shape, project it onto the line perpendicular to the edge
                    // and keep track of the min and max of these values
                    minB = maxB = undefined;
                    for (j = 0; j < b.points.length; j++) {
                        projected = normal.x * b.points[j].x + normal.y * b.points[j].y;
                        if (!isDef(minB) || projected < minB) {
                            minB = projected;
                        }
                        if (!isDef(maxB) || projected > maxB) {
                            maxB = projected;
                        }
                    }
    
                    // if there is no overlap between the projects, the edge we are looking at separates the two
                    // polygons, and we know there is no overlap
                    if (maxA < minB || maxB < minA) {
                        console.log("polygons don't intersect!");
                        return false;
                    }
                }
            }
            return true;
        };
    
    function doPolygonsIntersect(a, b)
        local polygons = { a, b };
        local minA, maxA, projected, i, i1, j, minB, maxB;
    
        for i = 1, #polygons do
            --// for each polygon, look at each edge of the polygon, and determine if it separates
            --// the two shapes
            local polygon = polygons[i];
            for i1 = 0, (#polygon-1) do
                --// grab 2 vertices to create an edge
                local i2 = (i1 + 1) % (#polygon);
                local p1 = polygon[i1+1];
                local p2 = polygon[i2+1];
    
                --// find the line perpendicular to this edge
                local normal = { x = p2.y - p1.y, y = p1.x - p2.x };
                minA = nil;
                maxA = nil;
    
                --// for each vertex in the first shape, project it onto the line perpendicular to the edge
                --// and keep track of the min and max of these values
                for j = 1, #a do
                    projected = normal.x * a[j].x + normal.y * a[j].y;
                    if (minA == nil or projected < minA) then
                        minA = projected;
                    end
                    if (maxA == nil or projected > maxA) then
                        maxA = projected;
                    end
                end
    
                --// for each vertex in the second shape, project it onto the line perpendicular to the edge
                --// and keep track of the min and max of these values
                minB = nil;
                maxB = nil;
                for j = 1, #b do
                    projected = normal.x * b[j].x + normal.y * b[j].y;
                    if (minB == nil or projected < minB) then
                        minB = projected;
                    end
                    if (maxB == nil or projected > maxB) then
                        maxB = projected;
                    end
                end
    
                if (maxA < minB or maxB < minA) then
                    return false;
                end
            end
        end
    
        return true;
    end