답변:
X = x*cos(θ) - y*sin(θ)
Y = x*sin(θ) + y*cos(θ)
원점을 중심으로 θ도 회전 한 지점의 위치를 알려줍니다. 정사각형의 모서리는 원점이 아닌 정사각형 중심을 중심으로 회전하므로이 수식을 사용하려면 몇 단계를 추가해야합니다. 먼저 원점을 기준으로 점을 설정해야합니다. 그런 다음 회전 수식을 사용할 수 있습니다. 회전 후 사각형의 중심을 기준으로 다시 이동해야합니다.
// 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;
이것을 4 개의 모퉁이에 모두 적용하면 완료됩니다!
피벗이 원점 인 좌표계로 변환 한 다음이 원점을 중심으로 회전 한 다음 다시 월드 좌표로 변환하여 피벗을 기준으로 점을 회전시키는 것이 일반적인 기술입니다. (이 접근법에 대한 아주 좋은 설명은 Khan Academy 에서 볼 수 있습니다 )
그러나 직사각형 모서리를 절대 좌표로 저장하지 않으므로 사용 가능한 데이터에 맞게 접근 방식을 조정할 수 있습니다.
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(θ))
그런 다음이 접근 방식을 다른 세 모서리에 쉽게 적용 할 수 있습니다.
다른 답변을 기반으로하고 보완하기 위해 P5를 사용하여 예제를 만들었 습니다 .
직접 액세스하려는 경우를위한 코드는 다음과 같습니다.
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>
위의 코드를 리팩토링하면 각 모서리에 기본적으로 표시되는 간단한 사실을 강조하는 정리 된 양식을 제공합니다 center + height/2 + width/2
. 이것은 또한 당신이 취급하는 경우 보유 height/2
및 width/2
회전 벡터 등.
헬퍼를 인라인하기 위해 인터프리터를 믿으면, 우리가 이것을 벤치마킹하려고 시도하면 매우 효과적입니다.
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);
}
회전에 관한 Wikipedia 기사를 참조하십시오 . 본질은 이것입니다 :
(1) c 가 중심점이면 모서리는 c + ( L / 2, W / 2), +/- 등입니다. 여기서 L 과 W 는 사각형의 길이와 너비입니다.
(2) 네 모퉁이에서 c 를 빼서 중심 c 가 원점이 되도록 사각형을 변환합니다 .
(3) 인용 된 삼각 공식을 통해 사각형을 40도 회전시킵니다.
(4) 각 좌표에 c 를 추가하여 다시 변환 합니다.
문제를 두 가지로 나눠서 사용 가능한 최적화가있을 수 있습니다.
아래 코드는 사각형을 눈금자라고합니다. ruler.x, ruler, y는 사각형 중심입니다.
/** 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)
}
}
조금 늦었지만 여기에 사용했던 컴팩트 한 기능이 있습니다. 상단 및 왼쪽 지점을 계산 한 다음 반대쪽 모서리로 뒤집습니다.
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);
}
오래된 게시물이지만 여기에 다른 방법이 있습니다.
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;
}
그것이 도움이되기를 바랍니다!