วิธีการคำนวณตำแหน่ง / เครื่องหมายมุมของสี่เหลี่ยมหมุน / เอียง


17

ฉันมีองค์ประกอบสองอย่างคือจุด 2D และพื้นที่สี่เหลี่ยม จุดแทนจุดกึ่งกลางของพื้นที่นั้น ฉันรู้ถึงความกว้างและความสูงของพื้นที่นั้นด้วย และพื้นที่เอียง 40 °เทียบกับกริด

ตอนนี้ฉันต้องการคำนวณตำแหน่งสัมบูรณ์ของแต่ละมุมของพื้นที่เอียงนั้นโดยใช้ข้อมูลนี้เท่านั้น เป็นไปได้ไหม

คำตอบ:


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

สิ่งนี้จะทำให้คุณทราบตำแหน่งของจุดที่หมุน around องศารอบจุดกำเนิด เนื่องจากมุมของสี่เหลี่ยมจัตุรัสหมุนรอบจุดศูนย์กลางของจัตุรัสไม่ใช่จุดกำเนิดจึงจำเป็นต้องเพิ่มสองขั้นตอนเพื่อให้สามารถใช้สูตรนี้ได้ ก่อนอื่นคุณต้องกำหนดจุดที่สัมพันธ์กับจุดกำเนิด จากนั้นคุณสามารถใช้สูตรการหมุนได้ หลังจากการหมุนคุณจำเป็นต้องย้ายกลับไปที่สัมพันธ์กับศูนย์กลางของตาราง

// 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 มุมและคุณทำเสร็จแล้ว!


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(θ))

วิธีการนี้สามารถนำไปใช้กับสามมุมได้อย่างง่ายดาย


2

ขึ้นอยู่กับคำตอบอื่น ๆ และเพื่อเติมเต็มพวกเขาก็จัดการเพื่อสร้างเช่นกับ 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>


1

การปรับโครงสร้างโค้ดด้านบนใหม่จะให้รูปแบบที่ทำความสะอาดซึ่งเน้นข้อเท็จจริงที่เรียบง่ายว่าแต่ละมุมนั้นเป็นพื้น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);
}

0

ดูบทความวิกิพีเดียในการหมุน สาระสำคัญคือ:

(1) ถ้าcเป็นจุดกึ่งกลางมุมจะเป็นc + ( L / 2, W / 2), +/- เป็นต้นโดยที่LและWคือความยาวและความกว้างของสี่เหลี่ยมผืนผ้า

(2) แปลสี่เหลี่ยมเพื่อให้ศูนย์ที่กำเนิดโดยการลบจากทั่วทุกมุมทั้งสี่

(3) หมุนสี่เหลี่ยมโดย 40 องศาผ่านสูตรตรีโกณมิติที่อ้างถึง

(4) แปลกลับโดยการเพิ่มcลงในแต่ละพิกัด


ขอบคุณสำหรับคำตอบของคุณ แต่ฉันเกรงว่าจะไม่เข้าใจ ฉันควรจะตัดทอนศูนย์กลาง (ทราบ) จากมุม (ไม่ทราบ) ได้อย่างไรถ้าไม่ทราบ ฉันหมายถึงพิกัดของมุมคือสิ่งที่ฉันพยายามค้นหา
Stacky

ฉันพยายามชี้แจง
Joseph O'Rourke

0

อาจมีการปรับให้เหมาะสมบางอย่างโดยการแบ่งปัญหาออกเป็นสองอย่าง:

  • คำนวณจุดศูนย์กลางของด้านบนและด้านล่างเช่นจุดศูนย์กลาง + ความสูงที่หมุนได้ / 2
  • คำนวณมุมเทียบกับจุดศูนย์กลางเหล่านี้โดยใช้ความกว้างหมุน / 2
  • คำนวณไซน์และโคไซน์จริงทันทีและทั้งหมด

โค้ดด้านล่างนี่สี่เหลี่ยมเรียกว่าไม้บรรทัด ruler.x, ไม้บรรทัด, 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)
    }
}

0

ช้าไปหน่อย แต่นี่คือฟังก์ชั่นขนาดกะทัดรัดที่ฉันเคยใช้ มันจะคำนวณคะแนนสูงสุดและซ้ายจากนั้นเพียงแค่โยนมันไปที่มุมตรงข้าม

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

โพสต์เก่า แต่นี่เป็นอีกวิธีที่จะทำ:

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;
}

หวังว่ามันจะช่วย!

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.