• 碰撞检测 :Polygon


    目录

    引子

    Collision Detection :Line 中主要介绍了直线相关的碰撞检测,接着来看看更加复杂一些的多边形的情况。

    以下示例未做兼容性检查,建议在最新的 Chrome 浏览器中查看。

    Polygon/Point

    这是示例页面

    多边形与点的碰撞检测,需要每一条边与点进行检测,才能确定是否产生了碰撞:

    const points = []; // 多边形顶点坐标
    const pointsLen = points.length;
    let collision = false; // 初始化碰撞状态
    
    for(let index = 0; index < pointsLen; index ++) {
      // checkCondition 边与检测点的判断
      if (checkCondition()) {
        collision = !collision;
      }
    }
    

    假设一条边的一个端点的坐标为 [cx,cy] ,另一端点坐标为 [nx,ny],检测点的坐标为 [px,py] ,需要检测的条件为:

    if ( ((cy > py) != (ny > py)) && (px < (nx-cx) * (py-cy) / (ny-cy) + cx) ) {
      collision = !collision;
    }
    

    这里的判断条件做了两个检测,首先是检查检测点的 Y 坐标是否在两个端点的 Y 坐标范围内:

    (cy >= py && ny < py) || (cy < py && ny >= py)
    // 等同于
    (cy > py) != (ny > py)
    

    61-polygon-point

    然后检查监测点的 X 坐标,依赖的方法是 Jordan Curve Theorem :

    px < (nx-cx) * (py-cy) / (ny-cy) + cx)
    

    每次检测后,符合条件都需要将 collision 的布尔值取反。直到检测所有的边后,最后的 collision 值才是最终结果。

    下面是完整检测逻辑:

    /*
     * points 多边形顶点坐标,形式为 [[x1,y1],[x2,y2]]
     * (px,py) 检测点坐标
     */
    function checkPolygonPoint({points,px,py}) {
      let collision = false;
      const pointsLen = points.length;
    
      for (let index = 0; index < pointsLen; index++) {
        const currentPoint = points[index];
        const next = index === pointsLen-1 ? 0:index+1;
        const nextPoint = points[next];
        const [cx,cy] = currentPoint;
        const [nx,ny] = nextPoint;
        const judgeX = px < (nx-cx)*(py-cy) / (ny-cy)+cx;
        const judgeY = (cy >= py && ny < py) || (cy < py && ny >= py);
        if (judgeX && judgeY) {
          collision = !collision;
        }
      }
    
      return collision;
    }
    

    Polygon/Circle

    这是示例页面

    多边形与圆的碰撞检测,可以分解为多边形的边与圆的碰撞检测,只要有一条边产生了碰撞,就可以进行判定。这个时候可以使用之前介绍的关于 Line/Circle 检测的方法。

    下面是完整检测逻辑:

    /*
     * points 多边形顶点坐标,形式为 [[x1,y1],[x2,y2]]
     * (cx,cy) 圆心坐标
     * radius 圆半径
     */
    function checkPolygonCircle({points,cx,cy,radius}) {
      const pointsLen = points.length;
    
      for (let index = 0; index < pointsLen; index++) {
        const currentPoint = points[index];
        const next = index === pointsLen-1 ? 0:index+1;
        const nextPoint = points[next];
        const [x1,y1] = currentPoint;
        const [x2,y2] = nextPoint;
        const collision = checkLineCircle({x1,y1,x2,y2,cx,cy,radius});
        if (collision) {
          return true;
        }
      }
    
      return false;
    }
    

    Polygon/Rectangle

    这是示例页面

    多边形与矩形的碰撞检测,可以分解为多边形的边与矩形的碰撞检测,只要有一条边产生了碰撞,就可以进行判定。这个时候可以使用之前介绍的关于 Line/Rectangle 检测的方法。

    下面是完整检测逻辑:

    /*
     * points 多边形顶点坐标,形式为 [[x1,y1],[x2,y2]]
     * (rx,ry) 矩形左上角顶点坐标
     * rw 矩形宽度
     * rh 矩形高度
     */
    function checkPolygonRectangle({points,rx,ry,rw,rh}) {
      const pointsLen = points.length;
    
      for (let index = 0; index < pointsLen; index++) {
        const currentPoint = points[index];
        const next = index === pointsLen-1 ? 0:index+1;
        const nextPoint = points[next];
        const [x1,y1] = currentPoint;
        const [x2,y2] = nextPoint;
        const collision = checkLineRectangle({x1,y1,x2,y2,rx,ry,rw,rh});
        if (collision) {
          return true;
        }
      }
    
      return false;
    
    }
    

    Polygon/Line

    这是示例页面

    多边形与直线的碰撞检测,可以分解为多边形的边与直线的碰撞检测,只要有一条边产生了碰撞,就可以进行判定。这个时候可以使用之前介绍的关于 Line/Line 检测的方法。

    下面是完整检测逻辑:

    /*
     * points 多边形顶点坐标,形式为 [[x1,y1],[x2,y2]]
     * (x1,y1) 直线线端点坐标
     * (x2,y2) 直线另一个端点坐标
     */
    function checkPolygonLine({points,x1,y1,x2,y2}) {
      const pointsLen = points.length;
    
      for (let index = 0; index < pointsLen; index++) {
        const currentPoint = points[index];
        const next = index === pointsLen-1 ? 0:index+1;
        const nextPoint = points[next];
        const [x3,y3] = currentPoint;
        const [x4,y4] = nextPoint;
    
        const collision = checkLineLine({x1,y1,x2,y2,x3,y3,x4,y4});
        if (collision) {
          return true;
        }
      }
    
      return false;
    
    }
    

    Polygon/Polygon

    这是示例页面,刷新页面,会生成随机的多边形。

    多边形与多边形的碰撞检测,思路是检测一个多边形任意边是否与另外一个多边形的任意边产生碰撞。这个时候可以使用前面介绍的关于 Polygon/Line 检测的方法。

    下面是完整检测逻辑:

    /*
     * points1 多边形1顶点坐标,形式为 [[x1,y1],[x2,y2]]
     * points2 多边形2顶点坐标,形式为 [[x1,y1],[x2,y2]]
     */
    function checkPolygonPolygon({points1,points2}) {
      const pointsLen = points1.length;
    
      for (let index = 0; index < pointsLen; index++) {
        const currentPoint = points1[index];
        const next = index === pointsLen-1 ? 0:index+1;
        const nextPoint = points1[next];
        const [x1,y1] = currentPoint;
        const [x2,y2] = nextPoint;
        const collision = checkPolygonLine({points:points2,x1,y1,x2,y2});
        if (collision) {
          return true;
        }
      }
    
      return false;
    
    }
    

    参考资料

  • 相关阅读:
    Sass基础——Rem与Px的转换
    彻底弄懂css中单位px和em,rem的区别
    在Eclipse Android中设置模拟器屏幕大小
    设置Android模拟器的窗口大小
    安卓模拟器Android SDK 4.0.3 R2安装完整图文教程
    自适应网页设计(Responsive Web Design)
    手机web——自适应网页设计(html/css控制)
    jQuery动态创建html元素的常用方法汇总
    javascript——URI的编解码方法
    为革命保护视力 --- 给 Visual Studio 换颜色
  • 原文地址:https://www.cnblogs.com/thyshare/p/13703651.html
Copyright © 2020-2023  润新知