Làm thế nào để tính toán vị trí góc / dấu của hình chữ nhật xoay / nghiêng?


17

Tôi đã có hai yếu tố, một điểm 2D và một khu vực hình chữ nhật. Điểm đại diện cho giữa khu vực đó. Tôi cũng biết chiều rộng và chiều cao của khu vực đó. Và khu vực này nghiêng 40 ° so với lưới điện.

Bây giờ tôi muốn tính toán vị trí tuyệt đối của từng dấu góc của khu vực nghiêng đó chỉ bằng dữ liệu này. Điều đó có thể không?

Câu trả lời:


30
X = x*cos(θ) - y*sin(θ)
Y = x*sin(θ) + y*cos(θ)

Điều này sẽ cung cấp cho bạn vị trí của một điểm được quay θ độ quanh điểm gốc. Vì các góc của hình vuông được xoay quanh tâm hình vuông chứ không phải gốc tọa độ, nên cần thêm một vài bước để có thể sử dụng công thức này. Đầu tiên bạn cần đặt điểm liên quan đến điểm gốc. Sau đó, bạn có thể sử dụng công thức xoay vòng. Sau khi xoay bạn cần di chuyển nó trở lại so với tâm của hình vuông.

// cx, cy - center of square coordinates
// x, y - coordinates of a corner point of the square
// theta is the angle of rotation

// translate point to origin
float tempX = x - cx;
float tempY = y - cy;

// now apply rotation
float rotatedX = tempX*cos(theta) - tempY*sin(theta);
float rotatedY = tempX*sin(theta) + tempY*cos(theta);

// translate back
x = rotatedX + cx;
y = rotatedY + cy;

Áp dụng điều này cho tất cả 4 góc và bạn đã hoàn tất!


4

Đây là một kỹ thuật phổ biến để xoay một điểm về trục bằng cách dịch sang hệ tọa độ trong đó trục là gốc, sau đó xoay về gốc tọa độ này, sau đó dịch trở lại tọa độ thế giới. (Một lời giải thích rất hay về phương pháp này có sẵn tại Khan Academy )

Tuy nhiên, bạn không lưu trữ các góc hình chữ nhật của mình trong tọa độ thế giới để chúng tôi có thể điều chỉnh một cách tiếp cận cho phù hợp với dữ liệu bạn có sẵn.

Cx, Cy // the coordinates of your center point in world coordinates
W      // the width of your rectangle
H      // the height of your rectangle
θ      // the angle you wish to rotate

//The offset of a corner in local coordinates (i.e. relative to the pivot point)
//(which corner will depend on the coordinate reference system used in your environment)
Ox = W / 2
Oy = H / 2

//The rotated position of this corner in world coordinates    
Rx = Cx + (Ox  * cos(θ)) - (Oy * sin(θ))
Ry = Cy + (Ox  * sin(θ)) + (Oy * cos(θ))

Cách tiếp cận này sau đó có thể dễ dàng áp dụng cho ba góc còn lại.


2

Dựa trên các câu trả lời khác và để bổ sung cho chúng, tôi đã quản lý để tạo một ví dụ với P5 tại đây .

Đây là mã, trong trường hợp bạn muốn truy cập trực tiếp vào nó:

function setup() {
createCanvas(400, 400);
}

var count = 0;

function draw() {
  background(250);
  rectMode(CENTER);
  stroke(0,0,255);
  fill(0,0,255);
  count += 1;

  var box1X = 100;
  var box1Y = 100;
  var box2X = 160;
  var box2Y = 100;
  var box1R = count;
  var box2R = -60-count;
  var box1W = 50;
  var box1H = 50;
  var box2W = 50;
  var box2H = 50;

  translate(box1X, box1Y);
  rotate(radians(box1R));
  rect(0, 0, box1W, box1H);
  rotate(radians(-box1R));
  translate(-box1X, -box1Y);

  translate(box2X, box2Y);
  rotate(radians(box2R));
  rect(0, 0, box2W, box2H);
  rotate(radians(-box2R));
  translate(-box2X, -box2Y);

  stroke(255,0,0);
  fill(255,0,0);

  var pointRotated = [];
  pointRotated.push(GetPointRotated(box1X, box1Y, box1R, -box1W/2, box1H/2));  // Dot1
  pointRotated.push(GetPointRotated(box1X, box1Y, box1R, box1W/2, box1H/2));   // Dot2
  pointRotated.push(GetPointRotated(box1X, box1Y, box1R, -box1W/2, -box1H/2)); // Dot3
  pointRotated.push(GetPointRotated(box1X, box1Y, box1R, box1W/2, -box1H/2));  // Dot4
  pointRotated.push(createVector(box1X, box1Y)); // Dot5

  for (var i=0;i<pointRotated.length;i++){
ellipse(pointRotated[i].x,pointRotated[i].y,3,3);
  }
}

function GetPointRotated(X, Y, R, Xos, Yos){
// Xos, Yos // the coordinates of your center point of rect
// R      // the angle you wish to rotate

//The rotated position of this corner in world coordinates    
var rotatedX = X + (Xos  * cos(radians(R))) - (Yos * sin(radians(R)))
var rotatedY = Y + (Xos  * sin(radians(R))) + (Yos * cos(radians(R)))

return createVector(rotatedX, rotatedY)
}
<script src="//cdnjs.cloudflare.com/ajax/libs/p5.js/0.3.3/p5.min.js"></script>


1

Tái cấu trúc mã ở trên cung cấp một biểu mẫu được làm sạch, điều này cũng làm nổi bật một thực tế đơn giản là mỗi góc về cơ bản center + height/2 + width/2, với các dấu hiệu phù hợp cho từng góc. Điều này cũng giữ nếu bạn coi height/2width/2như các vectơ xoay.

Tin tưởng vào trình thông dịch để nội tuyến những người trợ giúp, điều này sẽ khá hiệu quả, chúng ta có nên thử điểm chuẩn này không.

function addPoints(p1, p2) {
    return { x: p1.x + p2.x, y: p1.y + p2.y }
}

function subPoints(p1, p2 ) {
    return { x: p1.x - p2.x, y: p1.y - p2.y }
}

function multPoints(p1, p2 ) {
    return { x: p1.x * p2.x, y: p1.y * p2.y }
}

function getRulerCorners() {
    const sin = Math.sin(ruler.angle);
    const cos = Math.cos(ruler.angle);
    const height = { x: sin * ruler.height/2, y: cos * ruler.height/2 };
    const heightUp = addPoints(ruler, multPoints({x: 1, y :-1}, height));
    const heightDown = addPoints(ruler, multPoints({x: -1, y: 1}, height));
    const width = { x: cos * ruler.width/2, y: sin * ruler.width/2 };
    ruler.nw = subPoints(heightUp, width);
    ruler.ne = addPoints(heightUp, width );
    ruler.sw = subPoints(heightDown, width);
    ruler.se = addPoints(heightDown, width);
}

0

Xem bài viết Wikipedia về luân chuyển . Bản chất là đây:

(1) Nếu c là điểm chính giữa thì các góc là c + ( L / 2, W / 2), +/- v.v., trong đó LW là chiều dài và chiều rộng của hình chữ nhật.

(2) Dịch hình chữ nhật sao cho tâm c ở gốc, bằng cách trừ c từ tất cả bốn góc.

(3) Xoay hình chữ nhật 40 độ thông qua các công thức trig được trích dẫn.

(4) Dịch trở lại bằng cách thêm c vào mỗi tọa độ.


Cảm ơn câu trả lời của bạn nhưng tôi sợ tôi không nhận được nó. Làm thế nào tôi có thể trừ trung tâm (được biết) từ các góc (chưa biết) nếu chúng không được biết? Ý tôi là, tọa độ của các góc là chính những điều tôi đang cố gắng tìm hiểu.
Stacky

Tôi đã cố gắng làm rõ.
Joseph O'Rourke

0

Có thể, có một số tối ưu hóa có sẵn bằng cách chia vấn đề thành hai:

  • tính toán tâm của đỉnh và cạnh dưới tức là trung tâm + chiều cao xoay / 2.
  • tính toán các góc tương ứng với các điểm trung tâm này bằng chiều rộng xoay / 2
  • Tính toán sin và cosin thực tế một lần và mãi mãi.

Mã dưới đây, ở đây hình chữ nhật được gọi là thước. thước kẻ.x, thước kẻ, y là tâm hình chữ nhật.

/** Middle point on rulers's top side. */
function getRulerTopMiddle(cos, sin) {
    return {
        x : ruler.x + sin * ruler.height/2,
        y : ruler.y - cos * ruler.height/2
    }
 }

/** Middle point on rulers's bottom side. */
function getRulerBottomMiddle(cos, sin) {
    return {
        x : ruler.x - sin * ruler.height/2,
        y : ruler.y + cos * ruler.height/2
    }
 }

/** Update ruler's four corner coordinates. */
function getRulerCorners() {
    const sin = Math.sin(ruler.angle);
    const cos = Math.cos(ruler.angle);
    const topMiddle = getRulerTopMiddle(cos, sin);
    const bottomMiddle = getRulerBottomMiddle(cos, sin);

    ruler.nw = {
        x: topMiddle.x - (cos * ruler.width/2),
        y: topMiddle.y - (sin * ruler.width/2)
    }   
    ruler.ne = {
        x: topMiddle.x + (cos * ruler.width/2),
        y: topMiddle.y + (sin * ruler.width/2)
    }   
    ruler.sw = {
        x: bottomMiddle.x - (cos * ruler.width/2),
        y: bottomMiddle.y - (sin * ruler.width/2)
    }   
    ruler.se = {
        x: bottomMiddle.x + (cos * ruler.width/2),
        y: bottomMiddle.y + (sin * ruler.width/2)
    }
}

0

Hơi muộn một chút, nhưng đây là một chức năng nhỏ gọn mà tôi đã sử dụng. Nó tính toán các điểm trên cùng và bên trái, sau đó chỉ cần lật chúng cho các góc đối diện.

rotatedRect(float x, float y, float halfWidth, float halfHeight, float angle)
{
    float c = cos(angle);
    float s = sin(angle);
    float r1x = -halfWidth * c - halfHeight * s;
    float r1y = -halfWidth * s + halfHeight * c;
    float r2x =  halfWidth * c - halfHeight * s;
    float r2y =  halfWidth * s + halfHeight * c;

    // Returns four points in clockwise order starting from the top left.
    return
        (x + r1x, y + r1y),
        (x + r2x, y + r2y),
        (x - r1x, y - r1y),
        (x - r2x, y - r2y);
}

0

Bài cũ, nhưng đây là một cách khác để làm điều đó:

public static Point[] GetRotatedCorners(Rectangle rectangleToRotate, float angle)
{

    // Calculate the center of rectangle.
    Point center = new Point(rectangleToRotate.Left + (rectangleToRotate.Left + rectangleToRotate.Right) / 2, rectangleToRotate.Top + (rectangleToRotate.Top + rectangleToRotate.Bottom) / 2);

    Matrix m = new Matrix();
    // Rotate the center.
    m.RotateAt(360.0f - angle, center);

    // Create an array with rectangle's corners, starting with top-left corner and going clock-wise.
    Point[] corners = new Point[]
        {
            new Point(rectangleToRotate.Left, rectangleToRotate.Top), // Top-left corner.
            new Point(rectangleToRotate.Right, rectangleToRotate.Top),    // Top-right corner.
            new Point(rectangleToRotate.Right, rectangleToRotate.Bottom), // Bottom-right corner.
            new Point(rectangleToRotate.Left, rectangleToRotate.Bottom),  // Botton-left corner
        };

    // Now apply the matrix to every corner of the rectangle.
    m.TransformPoints(corners);

    // Return the corners of rectangle rotated by the provided angle.
    return corners;
}

Hy vọng nó giúp!

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.