【问题标题】:How can I get rotated rectangle corner points from side points如何从边点获得旋转的矩形角点
【发布时间】:2015-11-23 22:29:38
【问题描述】:

假设我有一组四个或更多点位于矩形的周长上,并且矩形旋转了一些未知量。我知道矩形的每一侧至少有一个点。一个任意的边点被指定为 (0, 0),其他点是到这个起点的距离。如何获取这个矩形的非旋转角点?

【问题讨论】:

  • 4 分是不够的。想象一个正方形,四个输入点是它的角。现在画一个菱形,使四个点成为每条边的中点。作为矩形确切角的任何四个点可以绘制任意数量的其他矩形,使得这些点不是角(并且一旦旋转到正交,它们都会不同)。
  • 我不确定我是否理解。您的示例中的所有矩形是否都具有相同的高度和宽度?如果是这样,那很好,在矩形旋转到正交后,我可以根据左上角的 (0, 0) 值重新计算每个点的相对偏移量。
  • 你证明在纸上没有唯一的解决方案:画一个正方形,现在在你的正方形上画一个旋转的矩形(不同高度和宽度)。选择 4 个交叉点。您有 4 个点位于 2 个明显不同的矩形上(并且有超过 2 个矩形可以满足您的 4 个点)。

标签: math


【解决方案1】:

假设您不是想找到一个独特的解决方案:

  1. 围绕 0,0 旋转您的点,直到最顶部、最底部、 最左边和最右边的点都是不同的点
  2. 在最顶部和最底部绘制水平线,从最左侧和最右侧绘制垂直线
  3. 大功告成

var points = [];
var bs = document.body.style;
var ds = document.documentElement.style;
bs.height = bs.width = ds.height = ds.width = "100%";
bs.border = bs.margin = bs.padding = 0;
var c = document.createElement("canvas");
c.style.display = "block";
c.addEventListener("mousedown", addPoint, false);
document.body.appendChild(c);
var ctx = c.getContext("2d");
var interval;

function addPoint(e) {
    if (points.length >= 4) points = [];
    points.push({
        x: e.x - c.offsetLeft,
        y: e.y - c.offsetTop
    });
    while (points.length > 4) points.shift();
    redraw();
}
function rotateAround(a, b, r) {
    d = {x:a.x - b.x, y:a.y - b.y};
    return {
        x: b.x + Math.cos(r) * d.x - Math.sin(r) * d.y,
        y: b.y + Math.cos(r) * d.y + Math.sin(r) * d.x
    }
}
function drawPoint(p) {
    ctx.strokeStyle = "rgb(0,0,0)";
    ctx.beginPath();
    ctx.arc(p.x, p.y, 10, 0, 2 * Math.PI, true);
    ctx.closePath();
    ctx.stroke();
}

var last_few = [];

function redraw() {
    if (interval) clearInterval(interval);
    last_few = [];
    c.width = window.innerWidth;
    c.height = window.innerHeight;
    ctx.clearRect(0, 0, c.width, c.height);
    ctx.fillStyle = "rgb(200, 200, 200)";
    ctx.font = "40px serif";
    if (points.length < 4) {
        ctx.fillText("click " + (4 - points.length) + " times", 20, 40);
        points.forEach(drawPoint);
    } else {
        var average = {x:0, y:0};
        points.forEach(function (p) {
            average.x += p.x / 4;
            average.y += p.y / 4;
        });
        var step = 0;
        interval = setInterval(function () {
    		ctx.clearRect(0, 0, c.width, c.height);
	        ctx.fillText("click anywhere to start over", 20, 40);
            last_few.forEach(function(r) {
            	ctx.strokeStyle = "rgb(200,255,200)";
                ctx.save();
                ctx.translate(average.x, average.y);
                ctx.rotate((step -r.step) * Math.PI / 180);
            	ctx.strokeRect(r.lm - average.x, r.tm - average.y, (r.rm - r.lm), (r.bm - r.tm));
                ctx.restore();
            });
            var tm = Infinity;
            var bm = -Infinity;
            var lm = Infinity;
            var rm = -Infinity;
            points.forEach(function (p) {
                p = rotateAround(p, average, step * Math.PI / 180);
                drawPoint(p);
                tm = Math.min(p.y, tm);
                bm = Math.max(p.y, bm);
                lm = Math.min(p.x, lm);
                rm = Math.max(p.x, rm);
            });
            if (points.every(function (p) {
                p = rotateAround(p, average, step * Math.PI / 180);
                return (p.x == lm) || (p.x == rm) || (p.y == tm) || (p.y == bm);
            })) {
                ctx.strokeStyle = "rgb(0,255,0)";
                ctx.strokeRect(lm, tm, (rm - lm), (bm - tm));
                last_few.push({tm:tm, bm:bm, lm:lm, rm:rm, step:step});
                while(last_few.length > 30) last_few.shift();
            } else {
                ctx.strokeStyle = "rgb(255,0,0)";
                ctx.strokeRect(lm, tm, (rm - lm), (bm - tm));
            }
            step++;
        }, 30);
    }
}

window.onresize = redraw;
redraw();

【讨论】:

  • 如果我在进行旋转时测量点之间的水平距离,而不是您的第 1 步。矩形在这个测量值最大的地方没有旋转是真的吗?例如。这将是矩形与 2D 网格对齐的点,宽度 >= 比高度。
  • 1) 是无用的指令,4点已经不一样了。 2) 没有帮助,因为这些点可能不是角落。
  • @Kevin 找到最大距离不一定能帮助您找到每个点的边;有一些方法可以排列点,使得相邻边的点之间的距离最长
  • @Draco18s 1) 想象一个非常宽的矩形,顺时针旋转 45º,并在 4 条边的中间选择点,最上面和最左边的点是同一个点。 2)不假设他们在角落,它假设他们在边
  • @dtudury 想象一个宽 1.3 倍、旋转 44 度的矩形,其中四个点是我的矩形与您的矩形相交的四个点。鉴于这四点,该算法如何在这两个有效解决方案之间进行选择?
猜你喜欢
  • 1970-01-01
  • 2012-02-06
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-11-07
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多