Wie berechne ich Eckpositionen / Markierungen eines gedrehten / gekippten Rechtecks?

17

Ich habe zwei Elemente, einen 2D-Punkt und eine rechteckige Fläche. Der Punkt repräsentiert die Mitte dieses Bereichs. Ich kenne auch die Breite und Höhe dieses Bereichs. Die Fläche ist gegenüber dem Raster um 40 ° geneigt.

Jetzt möchte ich die absoluten Positionen jeder Eckmarkierung dieses geneigten Bereichs nur unter Verwendung dieser Daten berechnen. Ist das möglich?

Stapelbar
quelle

Antworten:

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

Dadurch erhalten Sie die Position eines Punktes, der um θ Grad um den Ursprung gedreht wurde. Da die Ecken des Quadrats um die Mitte des Quadrats und nicht um den Ursprung gedreht werden, müssen einige Schritte hinzugefügt werden, um diese Formel verwenden zu können. Zuerst müssen Sie den Punkt relativ zum Ursprung festlegen. Dann können Sie die Rotationsformel verwenden. Nach der Drehung müssen Sie es relativ zur Mitte des Quadrats zurückbewegen.

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

Wende dies auf alle 4 Ecken an und du bist fertig!

Aholio
quelle
4

Es ist eine übliche Technik, einen Punkt um einen Drehpunkt zu drehen, indem in ein Koordinatensystem übersetzt wird, in dem der Drehpunkt der Ursprung ist, dann um diesen Ursprung gedreht wird und dann zurück in Weltkoordinaten übersetzt wird. (Eine sehr gute Erklärung für diesen Ansatz finden Sie an der Khan Academy. )

Sie speichern Ihre Rechteckecken jedoch nicht in Weltkoordinaten, sodass wir einen Ansatz entwickeln können, der Ihren verfügbaren Daten entspricht.

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

Dieser Ansatz kann dann problemlos auf die anderen drei Ecken angewendet werden.

Kelly Thomas
quelle
2

Basierend auf den anderen Antworten, und sie zu ergänzen, gelang es mir , mit P5 ein Beispiel erstellen hier .

Hier ist der Code, falls Sie direkt darauf zugreifen möchten:

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>

Danfus
quelle
1

Das Umgestalten des obigen Codes ergibt ein aufgeräumtes Formular, das auch die einfache Tatsache hervorhebt, dass jede Ecke im Grunde genommen center + height/2 + width/2mit entsprechenden Zeichen für jede Ecke versehen ist. Dies gilt auch, wenn Sie height/2und behandelnwidth/2 als gedrehte Vektoren behandeln.

Wenn wir dem Dolmetscher vertrauen, dass er die Helfer einbindet, sollte dies ziemlich effektiv sein, sollten wir versuchen, dies zu bewerten.

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);
}
Leamas
quelle
0

Siehe den Wikipedia-Artikel über Rotation . Das Wesentliche ist folgendes:

(1) Wenn c der Mittelpunkt ist, sind die Ecken c + ( L / 2, W / 2), +/- usw., wobei L und W die Länge und Breite des Rechtecks ​​sind.

(2) Verschieben Sie das Rechteck so, dass der Mittelpunkt c am Ursprung liegt, indem Sie c von allen vier Ecken abziehen .

(3) Drehen Sie das Rechteck mit den angegebenen Triggerformeln um 40 Grad.

(4) Zurückübersetzen durch Hinzufügen c zu jeder Koordinate .

Joseph O'Rourke
quelle
Vielen Dank für Ihre Antwort, aber ich fürchte, ich verstehe es nicht. Wie soll ich das Zentrum (bekannt) von den Ecken (unbekannt) abziehen, wenn sie unbekannt sind? Ich meine, die Koordinaten der Ecken sind genau die Dinge, die ich herausfinden will.
Stacky
Ich habe versucht zu klären.
Joseph O'Rourke
0

Möglicherweise gibt es einige Optimierungen, die das Problem in zwei Teile aufteilen:

  • Berechnen Sie die Mitte der oberen und unteren Seite, dh die Mitte + die gedrehte Höhe / 2.
  • Berechnen Sie die Ecken relativ zu diesen Mittelpunkten mit der gedrehten Breite / 2
  • Berechnen Sie ein für alle Mal den tatsächlichen Sinus und Cosinus.

Code unten, hier heißt das Rechteck Lineal. Lineal.x, Lineal, y ist das Zentrum des Rechtecks.

/** 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)
    }
}
Alec Leamas
quelle
0

Ein bisschen spät, aber hier ist eine kompakte Funktion, die ich verwendet habe. Der obere und der linke Punkt werden berechnet und dann für die gegenüberliegenden Ecken umgedreht.

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);
}
cmann
quelle
0

Alter Beitrag, aber hier ist eine andere Möglichkeit:

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

Ich hoffe es hilft!

Fleißiges Karma
quelle