【问题标题】:Get bounds of unrotated rotated rectangle获取未旋转的旋转矩形的边界
【发布时间】:2019-06-01 23:51:52
【问题描述】:

我有一个已经应用了旋转的矩形。我想获得未旋转的尺寸(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,然后读取更新后的 bounds 。但是,我使用的其中一个功能存在错误,所以现在我必须手动完成。

是否有一个简单的公式可以使用我已有的信息来获得旋转 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 }

我发现了一个类似的问题here

更新 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. 三角形每个点的角度(想象一下,如果它们位于想象的圆上)会容易得多。如果你有这些信息,我可以提供一个我经常使用的公式。
  • 我已经旋转了要取消旋转的矩形和线条。我可以得到旋转线的起点 x、起点 y、终点 x 和终点 y 以及所提到的边界吗?这会有帮助吗?
  • @kemicofa 我可以给你一条线的中心位置
  • 当然很好。另外,您注意到如果切换 x,y 和 width,height 它似乎适合您的输出?
  • 在示例中,我使用的是直角,但并不总是直角。我会将代码放在主帖中以获取线的中心点以及 x 和 y(它可能不正确,但到目前为止似乎有效)

标签: javascript canvas ecmascript-6 transform rectangles


【解决方案1】:

我认为我可以不费力气地处理边界大小的计算(几个方程),但我不确定您希望如何处理 xy

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

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

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

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

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

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

简要回顾一下,正弦定理告诉我们,边长之比与对角相等。更多信息在这里:https://en.wikipedia.org/wiki/Law_of_sines

在我们的例子中,对于左上三角(和右下三角),我们有:

记住AD是我们原来的高度。

鉴于sin(gamma)为1,并且我们也知道AD的值,我们可以写出等式:

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

有了所有需要的边,我们可以很容易地计算出宽度和高度:

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、宽度的矩形和高度。是否可以将 x 和 y 添加到 rect?我在主帖中有起始尺寸和结束尺寸。矩形已经旋转,我得到了所有的值。我想取消旋转它。如果有帮助,矩形会围绕中心旋转。
  • 嗯,让我问你几个问题,为我澄清一点:1. 你的矩形开始旋转了吗?如果是,你知道它旋转了多少度吗? 2. x 和 y,在您的坐标系中,是左上角(A 点)之一,而不是边界对吗? 3.您拥有的初始尺寸是外部边界,您需要在其未旋转后的矩形尺寸吗?抱歉重复,但英语不是我的母语。
  • 没问题。 1. 是的,它开始旋转它可以是任何值,但在示例中它是 90 度。 2. x 和 y 是顶部和左侧的位置。 0 x 0 是文档的左上角。小于 0 是屏幕外。 3. 是的。外界。绘制边界或像素所在的位置。 x 和 y 随着矩形的旋转而变化。它被旋转了,我需要它未旋转回零旋转后的大小
  • @1.21gigawatts 我不确定 任何 具有所有 90 度角的旋转矩形是否可以内接在另一个给定边界的矩形中。我的另一个问题是:你知道这个内部矩形是否倾斜吗?我正在这个代码框上进行概念验证:codesandbox.io/s/713k230m56
  • 没有歪斜@0xc14m1z
【解决方案2】:

这是如何工作的?

使用宽度、高度、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 的中心

双 for 循环将为 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.21gigawatts ,啊,我可能走得太远了。你指的界限到底是什么? x,y,宽度,特定角度的高度?你能给我一个以 45 度角旋转的矩形的预期输出吗?谢谢。
  • 未转换的边界是x: 10, y: 25, w: 30, h: 0(高度可以是1)。 45 度角的边界是x: 14.39, y: 14.39, w: 21.2, h: 21.2
【解决方案3】:

我想我可能会找到一个解决方案,但为了安全起见,我更愿意事先重复我们拥有的内容以及我们需要确保我正确理解所有内容的内容。正如我在评论中所说,英语不是我的母语,由于我对问题缺乏理解,我已经写了一个错误的答案:)

我们有什么

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

我们知道 y 轴相对于笛卡尔轴翻转,这使得角度被认为是顺时针而不是逆时针。

我们需要什么

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

作为第二步,我们需要将内部矩形反向旋转到 0 度,并找到它的位置 XY

找到顶点

一般来说,对于每个顶点,我们只知道一个坐标,即 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,我们可以轻松计算Cx

以同样的方式我们可以计算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 以便解释清楚:

很明显,我们可以使用皮塔哥拉斯定理计算WH

地点:

在代码中:

// 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)。

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

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

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

我们需要首先计算GC,以便至少完全知道等式的一侧。 GC 是内接矩形的圆周半径,也是内矩形对角线的一半。

有了内部矩形的两条边,我们可以再次使用皮塔哥拉斯定理:

使用GC,我们可以解决beta 上的正弦定理:

我们知道sin(delta) 是 1

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

再看这张图,我们可以很容易地得到所有其他顶点的角度:

现在我们几乎有了所有东西,我们可以计算A 顶点的新坐标:

从这里开始,我们需要同时翻译AxAy,因为它们与圆周的中心有关,即x + w / 2y + h / 2

所以,写最后一段代码:

// 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.21gigawatts 你能试试吗?
  • 我做了排序。我把代码放在一起,但我不确定我做得对。如果您愿意,我已将代码作为脚本示例放入您的答案中,供您测试和编辑。
  • 我现在无法编辑答案,不知道为什么。但是,我想我弄清楚了问题所在。您使用的角度以度为单位。将其转换为弧度,然后使用 Math.PI / 180 * [angle in degrees] 将其提供给 unrotate 方法
  • 它可能不允许您编辑它,因为我正在编辑示例代码。我将其转换为弧度。 10 分钟后再回来查看
  • 已添加。我使用了您昨天帖子中的功能。您显然会想要查看它。
【解决方案4】:

这是一个矩形围绕其中心旋转的基本代码(Unrotating 只是一个负角)。

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);
&lt;span id="boundsLabel"&gt;&lt;/span&gt;

【讨论】:

  • 我添加了一个代码 sn-p 示例。注册点是从矩形的中心。
  • @1.21gigawatts,originalRectangle 是否应该来自示例 sn-p 中的 rotateRectangle?如果是这样,这不是原件的旋转。它违反了三角不等式,除非在旋转之前发生平移(矩形和角度中没有足够的信息来解决)。在这种情况下,我不明白您所说的注册点是什么意思。我的答案中的两个矩形(输入和解决方案)都由左上角定义为矩形的原点。它围绕中心点(枢轴)旋转。
  • 注册点是指中心点。如果矩形是 100 x 100,则注册点将是 50 x 50。我有设计软件可以给出矩形的边界。文档的左上角是 0 x 0。原始矩形与 10 x 10 向下和向右移动 10 的位置偏移。它应该是笛卡尔坐标系,除非该信息改变了它。
  • 我认为我的问题必须重新发布,因为现在很明显,这些信息从根本上改变了答案。我这样说是因为文档的坐标系从 0x0 开始,对象的旋转是从中心而不是左上角,旋转是度数而不是弧度。
  • @1.21gigawatts,度数与弧度无关。它已经在代码中处理(rot 变量),以及 0,0 处的原点)这是造成混乱的界限。旋转边界的大小是否计算为与原点的距离?
猜你喜欢
  • 2018-12-29
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2010-10-11
  • 1970-01-01
  • 1970-01-01
  • 2020-01-26
相关资源
最近更新 更多