获取未旋转的旋转矩形的边界

10

我有一个矩形,它已经应用了旋转。我想获取未旋转的尺寸(x、y、宽度、高度)。

这是当前元素的尺寸:

Bounds at a 90 rotation: {
 height     30
 width      0
 x          25
 y          10
}

取消旋转后的尺寸为:

Bounds at rotation 0 {
 height     0
 width      30
 x          10
 y          25
}

以前,我能够把旋转设置为0,然后读取更新后的边界。但是,我使用的其中一种函数存在一个错误,所以现在我必须手动完成它。

是否有一个简单的公式可以利用我已经拥有的信息来获得旋转为0时的边界?

更新:物体围绕物体中心旋转。

更新:
我需要像下面这个函数一样的东西:

function getRectangleAtRotation(rect, rotation) {
    var rotatedRectangle = {}
    rotatedRectangle.x = Math.rotation(rect.x * rotation);
    rotatedRectangle.y = Math.rotation(rect.y * rotation);
    rotatedRectangle.width = Math.rotation(rect.width * rotation);
    rotatedRectangle.height = Math.rotation(rect.height * rotation);
    return rotatedRectangle;
}

var rectangle = {x: 25, y: 10, height: 30, width: 0 };
var rect2 = getRectangleAtRotation(rect, -90); // {x:10, y:25, height:0, width:30 }

我在这里找到了一个类似的问题

更新2
以下是我的代码。 它试图获取线的中心点,然后获取x,y,宽度和高度:

var centerPoint = getCenterPoint(line);
var lineBounds = {};
var halfSize;

halfSize = Math.max(Math.abs(line.end.x-line.start.x)/2, Math.abs(line.end.y-line.start.y)/2);
lineBounds.x = centerPoint.x-halfSize;
lineBounds.y = centerPoint.y;
lineBounds.width = line.end.x;
lineBounds.height = line.end.y;

function getCenterPoint(node) {
    return {
        x: node.boundsInParent.x + node.boundsInParent.width/2,
        y: node.boundsInParent.y + node.boundsInParent.height/2
    }
}

我知道我使用的例子是以直角为基础的,并且您可以使用该角度来交换x和y,但旋转角度可以是任意的。

更新3

我需要一个函数来返回矩形未旋转时的边界。我已经有了在特定旋转下的边界。

function getUnrotatedRectangleBounds(rect, currentRotation) {
    // magic
    return unrotatedRectangleBounds;
}

在画布上旋转时,更容易处理以下两个方面:1. 对象的原点,2. 三角形每个点的角度(想象一下它们位于一个虚拟圆上)。如果您有这些信息,我可以提供一个我经常使用的公式。 - kemicofa ghost
我有旋转的矩形和线条,我想要将它们还原。我可以获取旋转线条的起始x、起始y、结束x和结束y以及边界,这样可以帮助吗? - 1.21 gigawatts
@kemicofa 我可以为您获取一条线的中心位置。 - 1.21 gigawatts
当然,那会很好。另外,你注意到如果交换x、y和宽度、高度,似乎可以适应你的输出了吗? - kemicofa ghost
在这个例子中,我使用的是直角,但并不总是直角。我将把代码放在主贴中,以获取线段的中心点、x和y(可能不正确,但目前似乎可以工作)。 - 1.21 gigawatts
你能提供一个非退化案例吗?你的所有示例都表明宽度或高度为0。这会导致一条线。 - user10316640
4个回答

16

我认为我可以轻松处理边界大小的计算(少量方程),但我不确定您希望如何处理 xy

首先,让我们正确地命名事物:

enter image description here

现在,我们想要将其旋转一定角度 alpha (以弧度为单位):

enter image description here

要计算绿色边,显然它由两个重复的矩形三角形组成,如下所示:

enter image description here

所以,首先解决角度问题,我们知道:

  1. 三角形的角度之和是 PI,即 180°;
  2. 旋转角度为 alpha
  3. 一个角 gamma 是 PI / 2,即 90°;
  4. 最后一个角 beta 是 gamma - alpha

现在,知道了所有角度和一条边,我们可以使用正弦定理来计算其他边长。

简要回顾一下,正弦定理告诉我们,边长的比率与其对应的角度相等。更多信息请参见: https://en.wikipedia.org/wiki/Law_of_sines

在我们的情况下,对于上部左侧的三角形(和下部右侧的三角形),我们有:

enter image description here

记住,AD 是我们的原始高度。

由于 sin(gamma) 为 1,而我们也知道 AD 的值,我们可以写出以下方程式:

enter image description here

enter image description here

对于上部右侧的三角形(和下部左侧的三角形),我们有:

enter image description here

enter image description here

enter image description here

有了所有必要的边,我们可以轻松地计算宽度和高度:

width = EA + AF
height = ED + FB

在此时,我们可以编写一个相当简单的方法,该方法接受一个矩形和一个以弧度表示的旋转角度,并返回新的边界:

function rotate(rectangle, alpha) {
  const { width: AB, height: AD } = rectangle
  const gamma = Math.PI / 4,
        beta = gamma - alpha,
        EA = AD * Math.sin(alpha),
        ED = AD * Math.sin(beta),
        FB = AB * Math.sin(alpha),
        AF = AB * Math.sin(beta)

  return {
    width: EA + AF,
    height: ED + FB
  }
}

这个方法可以像这样使用:

const rect = { width: 30, height: 50 }
const rotation = Math.PI / 4.2 // this is a random value it put here
const bounds = rotate(rect, rotation)

希望没有拼写错误...


这非常详细,但我不确定如何将其与我所拥有的内容结合使用。如果我有一个在10 x 10处且大小为50 x 60(或任何值)的矩形,并且它旋转了85度,我想要将其逆时针旋转-85度并返回一个具有新x、y、宽度和高度的矩形。是否可以向rect添加x和y?我在主贴中有起始大小和结束大小。该矩形已经旋转,并且我拥有所有来自其中的值。我希望将其旋转回去。如果有必要,该矩形围绕中心旋转。 - 1.21 gigawatts
嗯,让我问你几个问题以便更清楚地了解:
  1. 你的矩形是否开始旋转?如果是,你知道它旋转了多少度吗?
  2. 在你的坐标系中,x和y是左上角(A点)的坐标,而不是边界的坐标,对吗?
  3. 你拥有的初始尺寸是外部边界,你需要矩形在取消旋转后的尺寸吗?
很抱歉重复了一遍,但英语不是我的母语。
- 0xc14m1z
没问题。1. 是的,它开始时旋转的角度可以是任何值,但在示例中为90度。2. x和y是顶部和左侧位置。 0 x 0是文档的左上角。小于0则超出屏幕。3. 是的。外边界。绘制边界或像素所在位置都计算在内。x和y会随着矩形的旋转而改变。它被旋转后,我需要将其旋转回零旋转时的大小。 - 1.21 gigawatts
@1.21gigawatts 我不确定是否可以在给定边界的另一个矩形中内接任何具有所有90度角的旋转矩形。我还想问你的是:你知道这个内部矩形是否倾斜吗?我正在这个codesandbox上进行概念验证:https://codesandbox.io/s/713k230m56 - 0xc14m1z
它没有偏移 @0xc14m1z - 1.21 gigawatts
我有一个被旋转角度的矩形,我想得到未旋转的边界框。我使用了您的函数,但它似乎并没有起作用。EF未定义,我尝试将其替换为AF,虽然已定义但未被使用,但结果不正确。如果您可以创建一个jsfiddle或sandbox,让我们一起尝试,那就太好了。谢谢。 - bigfanjs

12

我觉得我可能有一个解决方案,但为了安全起见,我更希望先重复一下我们已经知道的和需要确定的内容,以确保我正确理解了一切。正如我在评论中所说,英语不是我的母语,由于我对问题的理解不足,我已经写了一个错误的答案 :)

我们有什么

what we have

我们知道在xy处有一个边界矩形(绿色),大小为wh,其中包含另一个矩形(灰色虚线)旋转了alpha度。

我们知道y轴相对于笛卡尔坐标系被翻转,并且这使角度顺时针考虑而不是逆时针考虑。

我们需要什么

what we need at first

首先,我们需要找到内部矩形的4个顶点(ABCD),并知道顶点的位置,内部矩形的大小(WH)。

作为第二步,我们需要将内部矩形逆时针旋转90度,并找到它的位置 XY

what we need at the end

查找顶点

一般来说,对于每个顶点,我们只知道一个坐标,即x或y。另一个坐标沿着边界框滑动,与角度alpha有关。

让我们从A开始:我们知道Ay,我们需要Ax

我们知道Ax在角度alpha下位于xx + w之间。

alpha为0°时,Axx + 0。当alpha为90°时,Axx + w。当alpha为45°时,Axx + w / 2

基本上,Ax随着sin(alpha)的增长而增长,因此我们得到:

计算 Ax

有了 Ax,我们可以轻松计算出 Cx

计算 Cx

同样地,我们可以计算出 By,然后是 Dy

计算 By

计算 Dy

编写一些代码:

// bounds is a POJO with shape: { x, y, w, h }, update if needed
// alpha is the rotation IN RADIANS
const vertices = (bounds, alpha) => {
  const { x, y, w, h } = bounds,
        A = { x: x + w * Math.sin(alpha), y },
        B = { x, y: y + h * Math.sin(alpha) },
        C = { x: x + w - w * Math.sin(alpha), y },
        D = { x, y: y + h - h * Math.sin(alpha) }
  return { A, B, C, D }
}

寻找边长

现在我们已经有了所有的顶点,可以很容易地计算内部矩形的边长,需要定义两个附加点 EF 以便于解释:

additional points

很明显,我们可以使用勾股定理计算出 WH

compute H

compute W

其中:

compute EA

compute ED

compute AF

compute FB

在代码中:

// bounds is a POJO with shape: { x, y, w, h }, update if needed
// vertices is a POJO with shape: { A, B, C, D }, as returned by the `vertices` method
const sides = (bounds, vertices) => {
  const { x, y, w, h } = bounds,
        { A, B, C, D } = vertices,
        EA = A.x - x,
        ED = D.y - y,
        AF = w - EA,
        FB = h - ED,
        H = Math.sqrt(EA * EA + ED * ED),
        W = Math.sqrt(AF * AF + FB * FB
  return { h: H, w: W }
}

查找反向旋转内部矩形的位置

首先,我们必须找到内部矩形对角线的角度(betagamma)。

compute diagonals angles

让我们放大一点并添加一些额外的字母以增加清晰度:

add some letters to compute beta

我们可以使用正弦定理得到计算beta的方程式:

law of sines

为了进行一些计算,我们有:

compute GI

compute IC

delta

sin delta

我们需要首先计算GC,以便至少有一个方程式的一侧完全已知。 GC是内部矩形嵌入的圆周的半径,也是内部矩形对角线的一半。

得到内部矩形的两条边后,我们可以再次使用勾股定理:

compute GC

有了GC,我们可以解出beta的正弦定理:

compute beta 1

我们知道sin(delta)等于1。

计算 beta 2

计算 beta 3

计算 beta 4

计算 beta 5

现在,beta 是顶点 C 相对于未旋转的x轴的角度。

C顶点角度为beta

再次查看此图像,我们可以轻松获取所有其他顶点的角度:

所有顶点的角度

D的角度

A的角度

B的角度

现在我们已经几乎拥有所有元素,我们可以计算A顶点的新坐标:

计算 A 的位置

计算最终A_x

计算最终A_y

我们需要翻译AxAy,因为它们与圆心有关,即x + w / 2y + h / 2

compute translated A_x

compute translated A_y

因此,编写最后一段代码:

// bounds is a POJO with shape: { x, y, w, h }, update if needed
// sides is a POJO with shape: { w, h }, as returned by the `sides` method
const origin = (bounds, sides) => {
  const { x, y, w, h } = bounds
  const { w: W, h: H } = sides
  const GC = r = Math.sqrt(W * W + H * H) / 2,
        IC = H / 2,
        beta = Math.asin(IC / GC),
        angleA = Math.PI + beta,
        Ax = x + w / 2 + r * Math.cos(angleA),
        Ay = y + h / 2 + r * Math.sin(angleA)
  return { x: Ax, y: Ay }
}

集成所有内容...

// bounds is a POJO with shape: { x, y, w, h }, update if needed
// rotations is... the rotation of the inner rectangle IN RADIANS
const unrotate = (bounds, rotation) => {
  const points = vertices(bounds, rotation),
        dimensions = sides(bounds, points)
  const { x, y } = origin(bounds, dimensions)
  return { ...dimensions, x, y }
}

我真的希望这可以解决你的问题,也希望没有拼写错误。这是一个非常有趣的周末方式 :D

// bounds is a POJO with shape: { x, y, w, h }, update if needed
// alpha is the rotation IN RADIANS
const vertices = (bounds, alpha) => {
 const { x, y, w, h } = bounds,
    A = { x: x + w * Math.sin(alpha), y },
    B = { x, y: y + h * Math.sin(alpha) },
    C = { x: x + w - w * Math.sin(alpha), y },
    D = { x, y: y + h - h * Math.sin(alpha) }
 return { A, B, C, D }
 }
  
// bounds is a POJO with shape: { x, y, w, h }, update if needed
// vertices is a POJO with shape: { A, B, C, D }, as returned by the `vertices` method
const sides = (bounds, vertices) => {
  const { x, y, w, h } = bounds,
      { A, B, C, D } = vertices,
      EA = A.x - x,
      ED = D.y - y,
      AF = w - EA,
      FB = h - ED,
      H = Math.sqrt(EA * EA + ED * ED),
      W = Math.sqrt(AF * AF + FB * FB)
  return { h: H, w: W }
}

// bounds is a POJO with shape: { x, y, w, h }, update if needed
// sides is a POJO with shape: { w, h }, as returned by the `sides` method
const originPoint = (bounds, sides) => {
  const { x, y, w, h } = bounds
  const { w: W, h: H } = sides
  const GC = Math.sqrt(W * W + H * H) / 2,
      r = Math.sqrt(W * W + H * H) / 2,
      IC = H / 2,
      beta = Math.asin(IC / GC),
      angleA = Math.PI + beta,
      Ax = x + w / 2 + r * Math.cos(angleA),
      Ay = y + h / 2 + r * Math.sin(angleA)
  return { x: Ax, y: Ay }
}
  
// bounds is a POJO with shape: { x, y, w, h }, update if needed
// rotations is... the rotation of the inner rectangle IN RADIANS
const unrotate = (bounds, rotation) => {
  const points = vertices(bounds, rotation)
  const dimensions = sides(bounds, points)
  const { x, y } = originPoint(bounds, dimensions)
  return { ...dimensions, x, y }
}

function shortNumber(value) {
  var places = 2;
 value = Math.round(value * Math.pow(10, places)) / Math.pow(10, places);
 return value;
}

function getInputtedBounds() {
  var rectangle = {};
  rectangle.x = parseFloat(app.xInput.value);
  rectangle.y = parseFloat(app.yInput.value);
  rectangle.w = parseFloat(app.widthInput.value);
  rectangle.h = parseFloat(app.heightInput.value);
  return rectangle;
}

function rotationSliderHandler() {
  var rotation = app.rotationSlider.value;
  app.rotationOutput.value = rotation;
  rotate(rotation);
}

function rotationInputHandler() {
  var rotation = app.rotationInput.value;
  app.rotationSlider.value = rotation;
  app.rotationOutput.value = rotation;
  rotate(rotation);
}

function unrotateButtonHandler() {
  var rotation = app.rotationInput.value;
  app.rotationSlider.value = 0;
  app.rotationOutput.value = 0;
  var outerBounds = getInputtedBounds();
  var radians = Math.PI / 180 * rotation;
  var unrotatedBounds = unrotate(outerBounds, radians);
  updateOutput(unrotatedBounds);
}

function rotate(value) {
  var outerBounds = getInputtedBounds();
  var radians = Math.PI / 180 * value;
  var bounds = unrotate(outerBounds, radians);
  updateOutput(bounds);
}

function updateOutput(bounds) {
  app.xOutput.value = shortNumber(bounds.x);
  app.yOutput.value = shortNumber(bounds.y);
  app.widthOutput.value = shortNumber(bounds.w);
  app.heightOutput.value = shortNumber(bounds.h);
}

function onload() {
  app.xInput = document.getElementById("x");
  app.yInput = document.getElementById("y");
  app.widthInput = document.getElementById("w");
  app.heightInput = document.getElementById("h");
  app.rotationInput = document.getElementById("r");
  
  app.xOutput = document.getElementById("x2");
  app.yOutput = document.getElementById("y2");
  app.widthOutput = document.getElementById("w2");
  app.heightOutput = document.getElementById("h2");
  app.rotationOutput = document.getElementById("r2");
  app.rotationSlider = document.getElementById("rotationSlider");
  app.unrotateButton = document.getElementById("unrotateButton");
  
  app.unrotateButton.addEventListener("click", unrotateButtonHandler);
  app.rotationSlider.addEventListener("input", rotationSliderHandler);
  app.rotationInput.addEventListener("change", rotationInputHandler);
  app.rotationInput.addEventListener("input", rotationInputHandler);
  app.rotationInput.addEventListener("keyup", (e) => {if (e.keyCode==13) rotationInputHandler() });
  
  app.rotationSlider.value = app.rotationInput.value;
}

var app = {};
window.addEventListener("load", onload);
* {
  font-family: sans-serif;
  font-size: 12px;
  outline: 0px dashed red;
}

granola {
  display: flex;
  align-items: top;
}

flan {
  width: 90px;
  display: inline-block;
}

hamburger {
  display: flex:
  align-items: center;
}

spagetti {
  display: inline-block;
  font-size: 11px;
  font-weight: bold;
  letter-spacing: 1.5px;
}

fish {
  display: inline-block;
  padding-right: 40px;
  position: relative;
}

input[type=text] {
  width: 50px;
}

input[type=range] {
  padding-top: 10px;
  width: 140px;
  padding-left: 0;
  margin-left: 0;
}

button {
  padding-top: 3px;
  padding-bottom:1px;
  margin-top: 10px;
}
<granola>
  <fish>
    <spagetti>Bounds of Rectangle</spagetti><br><br>
    <flan>x: </flan><input id="x" type="text" value="14.39"><br>
    <flan>y: </flan><input id="y" type="text" value="14.39"><br>
    <flan>width: </flan><input id="w" type="text" value="21.2"><br>
    <flan>height: </flan><input id="h" type="text" value="21.2"><br>
    <flan>rotation:</flan><input id="r" type="text" value="90"><br>
    <button id="unrotateButton">Unrotate</button>    
  </fish>

  <fish>
    <spagetti>Computed Bounds</spagetti><br><br>
    <flan>x: </flan><input id="x2" type="text" disabled="true"><br>
    <flan>y: </flan><input id="y2" type="text"disabled="true"><br>
    <flan>width: </flan><input id="w2" type="text" disabled="true"><br>
    <flan>height: </flan><input id="h2" type="text" disabled="true"><br>
    <flan>rotation:</flan><input id="r2" type="text" disabled="true"><br>
    <input id="rotationSlider" type="range" min="-360" max="360" step="5"><br>
  </fish>
</granola>


@1.21千瓦时,你能试一下吗? - 0xc14m1z
我已经做了,我把代码组合在一起,但我不确定我是否做得正确。我已将代码放入你的答案中作为脚本示例供您测试和编辑(如果您选择这样做)。 - 1.21 gigawatts
我现在无法编辑答案,不知道为什么。不过,我认为我已经找到了问题所在。您正在使用的角度是以度为单位的。在将其传递给 unrotate 方法之前,请将其转换为弧度,并使用 Math.PI / 180 * [以度表示的角度] - 0xc14m1z
由于我正在编辑示例代码,可能不允许您进行编辑。我将把它转换为弧度制。请在10分钟后再查看。 - 1.21 gigawatts
已经添加了。我使用了你昨天发布的函数。你肯定需要进行审核。 - 1.21 gigawatts
显示剩余3条评论

5

这是如何工作的?

使用宽度、高度、x和y进行计算

弧度和角度

使用角度来计算弧度并计算sincos角度:

function calculateRadiansAndAngles(){
  const rotation = this.value;
  const dr = Math.PI / 180;
  const s = Math.sin(rotation * dr);
  const c = Math.cos(rotation * dr);
  console.log(rotation, s, c);
}

document.getElementById("range").oninput = calculateRadiansAndAngles;
<input type="range" min="-360" max="360" id="range"/>

生成4个点

我们假设矩形的原点是位于0,0的中心

双重循环将为ij创建以下值对:(-1,-1), (-1,1), (1,-1)和(1,1)

使用每一对,我们可以计算出4个正方形向量之一。

(例如,对于(-1,1),i=-1,j=1)

const px = w*i/2; //-> 30 * -1/2 = -15
const py = h*j/2; //-> 50 * 1/2  = 25
//[-15,25]

一旦我们有了一个点,我们可以通过包含旋转来计算该点的新位置。

const nx = (px*c) - (py*s);
const ny = (px*s) + (py*c);

解决方案

一旦所有点都根据旋转计算出来,我们就可以重新绘制正方形。

在绘制调用之前,使用translate将光标定位于矩形的xy处。这就是我能够假设矩形的中心和原点为0,0进行计算的原因。

const canvas = document.getElementById("canvas");
const range = document.getElementById("range");
const rotat = document.getElementById("rotat");

range.addEventListener("input", function(e) {
  rotat.innerText = this.value;
  handleRotation(this.value);
})

const context = canvas.getContext("2d");
const container = document.getElementById("container");

const rect = {
  x: 50,
  y: 75,
  w: 30,
  h: 50
}

function handleRotation(rotation) {
  const { w, h, x, y } = rect;
  
  const dr = Math.PI / 180;
  const s = Math.sin(rotation * dr);
  const c = Math.cos(rotation * dr);
  
  const points = [];
  for(let i = -1; i < 2; i+=2){
    for(let j = -1; j < 2; j+=2){
      
      const px = w*i/2;
      const py = h*j/2;
      
      const nx = (px*c) - (py*s);
      const ny = (px*s) + (py*c);
      points.push([nx, ny]);
    }
  }
  //console.log(points);
  draw(points);
  
}

function draw(points) {
  context.clearRect(0,0,canvas.width, canvas.height);
  context.save();
  context.translate(rect.x+(rect.w/2), rect.y + (rect.h/2))
  context.beginPath();
  context.moveTo(...points.shift());
  [...points.splice(0,1), ...points.reverse()]
  .forEach(p=>{
    context.lineTo(...p);
  })
  context.fill();
  context.restore();
}

window.onload = () => handleRotation(0);
div {
  display: flex;
  background-color: lightgrey;
  padding: 0 5px;
}

div>p {
  padding: 0px 10px;
}

div>input {
  flex-grow: 1;
}

canvas {
  border: 1px solid black;
}
<div>
  <p id="rotat">0</p>
  <input type="range" id="range" min="-360" max="360" value="0" step="5" />
</div>
<canvas id="canvas"></canvas>


这个例子很好,但我该如何将它应用到我的问题上呢? - 1.21 gigawatts
@1.21千兆瓦,啊,我可能有点过了。你所指的边界是什么?在特定角度下的x、y、宽度、高度吗?你能给我一个矩形以45度旋转后的预期输出吗?谢谢。 - kemicofa ghost
未变换的边界为 x: 10, y: 25, w: 30, h: 0(高度可以为1)。45度角的边界为 x: 14.39, y: 14.39, w: 21.2, h: 21.2 - 1.21 gigawatts

2

这是一个围绕其中心旋转的矩形基本代码(反向旋转只需使用负角度即可)。

function getUnrotatedRectangleBounds(rect, currentRotation) {

    //Convert deg to radians
    var rot = currentRotation / 180 * Math.PI;
    var hyp = Math.sqrt(rect.width * rect.width + rect.height * rect.height);
    return {
       x: rect.x + rect.width / 2 - hyp * Math.abs(Math.cos(rot)) / 2,
       y: rect.y + rect.height / 2 - hyp * Math.abs(Math.sin(rot)) / 2,
       width: hyp * Math.abs(Math.cos(rot)),
       height: hyp * Math.abs(Math.sin(rot))
       } 
}

从起点(0,0)到终点(width,height)的向量投影到目标角度的单位向量(cos rot, sin rot) * hyp。

绝对值保证宽度和高度都是正数。

投影的坐标分别为新矩形的宽度和高度。

对于x和y值,请取中心处的原始值(x + rect.x),并将其向外移动(- 1/2 * NewWidth)以使新矩形居中。

示例

function getUnrotatedRectangleBounds(rect, currentRotation) {
    //Convert deg to radians
    var rot = currentRotation / 180 * Math.PI;
    var hyp = Math.sqrt(rect.width * rect.width + rect.height * rect.height);
    return {
       x: rect.x + rect.width / 2 - hyp * Math.abs(Math.cos(rot)) / 2,
       y: rect.y + rect.height / 2 - hyp * Math.abs(Math.sin(rot)) / 2,
       width: hyp * Math.abs(Math.cos(rot)),
       height: hyp * Math.abs(Math.sin(rot))
    }
}

var originalRectangle = {x:10, y:25, width:30, height:0};
var rotatedRectangle = {x:14.39, y:14.39, width:21.2, height:21.2};
var rotation = 45;
var unrotatedRectangle = getUnrotatedRectangleBounds(rotatedRectangle, rotation);

var boundsLabel = document.getElementById("boundsLabel");
boundsLabel.innerHTML = JSON.stringify(unrotatedRectangle);
<span id="boundsLabel"></span>


我添加了一个代码片段示例。注册点是矩形的中心。 - 1.21 gigawatts
@1.21千兆瓦,您的示例片段中的originalRectangle是否应该来自rotatedRectangle?如果是这样,那么这不是原始矩形的旋转。它违反了三角不等式,除非在旋转之前进行平移(在矩形和角度中没有足够的信息来解决问题)。我不明白您在这种情况下所说的注册点是什么意思。我的答案中的两个矩形(输入和解决方案)都以左上角作为矩形的原点定义。它围绕中心点(枢轴)旋转。 - user10316640
通过注册点,我指的是中心点。如果矩形是100 x 100,则注册点将为50 x 50。我有设计软件可以提供矩形的边界。文档的左上角为0 x 0。原始矩形与此相偏移,其中10 x 10向下移动并向右移动10。它应该是笛卡尔坐标系,除非该信息发生变化。 - 1.21 gigawatts
我认为我的问题必须重新发布,因为现在显然这些信息从根本上改变了答案。我这么说是因为文档的坐标系从0x0开始,对象的旋转是以中心而不是左上角为基准,并且旋转是以度数而不是弧度表示的。 - 1.21 gigawatts
@1.21gigawatts,度数与弧度无关紧要。它已经在代码中处理了(通过rot变量),以及原点在0,0处)。问题在于边界(bounds)没有被正确处理。旋转后的边界是以其大小作为距离原点的距离来计算的吗? - user10316640

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