检测旋转矩形是否在画布弧线内

4

我有一个矩形,通过ctx.rotate旋转,并且有一个弧线。我想检查矩形的任何部分是否在该弧线内。例如,这应该是正确的:

Arc overlaps rectangle

我尝试使用isPointInPath,但我要找的“点”不是矩形的实际坐标,而是未旋转的坐标(实际为绿色,isPointInPath正在针对蓝色进行检查):

isPointInPath misses the point

以下是JS代码:

var canvas = document.querySelector('#canvas'),
    height = canvas.height = canvas.clientHeight,
    width = canvas.width = canvas.clientWidth,
    ctx = canvas.getContext('2d');
canvas.width = canvas.height = 512;

var shipx = 400,
    shipy = 256;

function moveShip() {
    ctx.fillStyle = '#000';
    ctx.fillRect(0, 0, canvas.width, canvas.height);

    ctx.save();
    ctx.translate(shipx, shipy);
    ctx.rotate(3.66);
    ctx.fillStyle = 'green';
    ctx.fillRect(0, 0, 80, 20);
    ctx.restore();

    // This is what isPointInPath is seeing
    ctx.fillStyle = 'rgba(0,0,255,0.5)';
    ctx.fillRect(shipx, shipy, 80, 20);

    ctx.fillStyle = 'rgba(255,0,0,0.5)';
    ctx.beginPath();
    ctx.moveTo(256, 256);
    ctx.arc(256, 256, 100, -20 * Math.PI / 180, 90 * Math.PI / 180);
    ctx.lineTo(256, 256);

    if (ctx.isPointInPath(shipx, shipy) || ctx.isPointInPath(shipx + 20, shipy + 20)) {
        // This *should* trigger
        ctx.fillStyle = 'rgba(0,0,255,0.5)';
    };

    ctx.fill();
}

moveShip();

JSBin 用于在线代码尝试


我正在为您准备答案。 - Asperger
1
在我看来,这个问题不能通过Canvas API解决。isPointInPath只处理单个点,而你有一组点(而且还旋转了)。你考虑过使用数学吗?它似乎更适合这样的问题。 - hindmost
1
@hindmost 数学是一个完全可行的答案 - 我只是不太擅长它。高中已经很久了... - SomeKittens
我不能为你解决这个问题。但是我可以给一些线索。试着看一下不等式。如果我没记错的话,那是你需要的东西。首先,你必须为弧线和矩形轮廓编写方程,然后以某种方式将它们转换为一组不等式。这就是我现在能想起来的所有内容(虽然我也不是数学大师,但我有数学教育 :))。 - hindmost
1个回答

4

您可以使用坐标旋转将矩形与系统对齐,然后只需使用适用于您情况的许多轴对齐算法之一:

var dx = arc.x - ship.x,
    dy = arc.y - ship.y;

ctx.rotate( -ship.rot );

ctx.beginPath();
ctx.moveTo( 0, 0 );
ctx.arc( 0, 0, arc.r, arc.sRot, arc.eRot );

if( ctx.isPointInPath( dx, dy ) ||
    ctx.isPointInPath( dx + rect.w, dy ) ||
    ctx.isPointInPath( dx, dy + rect.h ) ||
    ctx.isPointInPath( dx + rect.w, dy + rect.h ) )

    collisionIsTrue();

我不明白你的代码如何适用于他的第一幅图像,因为没有一个矩形的极点在扇形内,但它们仍然相交。 - caub
@crl 不是这样的。主要问题是让矩形与系统轴对齐,以便计算更容易,然后选择使用哪种碰撞算法取决于您。在他的特定情况下,检查形状中的顶点就足够了 ;) - towc
@towc:我无法让你的测试工作。:-//例如,如果ship.y=200,则您的测试应报告“false”,但它错误地返回“true”。也许我漏掉了什么:https://jsfiddle.net/m1erickson/ncyuh28r/ - markE

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接