Döndürülmüş / eğik bir dikdörtgenin köşe konumları / işaretleri nasıl hesaplanır?


17

İki elementim var, 2B nokta ve dikdörtgen alan. Nokta, o alanın ortasını temsil eder. Ayrıca o bölgenin genişliğini ve yüksekliğini de biliyorum. Ve alan ızgaraya göre 40 ° eğilir.

Şimdi sadece bu verileri kullanarak o eğik alanın her köşe işaretinin mutlak pozisyonlarını hesaplamak istiyorum. Mümkün mü?

Yanıtlar:


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

Bu, başlangıç ​​noktası etrafında θ derece döndürülmüş bir noktanın yerini verecektir. Meydanın köşeleri, başlangıç ​​noktası değil, meydanın etrafında döndürüldüğünden, bu formülü kullanabilmek için birkaç adımın eklenmesi gerekir. İlk önce noktayı başlangıç ​​noktasına göre ayarlamanız gerekir. Ardından döndürme formülünü kullanabilirsiniz. Döndürmeden sonra karenin merkezine göre geri taşımanız gerekir.

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

Bunu 4 köşeye de uygulayın ve işiniz bitti!


4

Pivotun başlangıç ​​noktası olduğu bir koordinat sistemine çevirerek, daha sonra bu orijin etrafında dönerek, sonra tekrar dünya koordinatlarına çevirerek, bir pivot hakkında bir noktayı döndürmek yaygın bir tekniktir. (Bu yaklaşımın çok iyi bir açıklaması Khan Academy'de mevcuttur )

Bununla birlikte, dikdörtgen köşelerinizi dünya koordinatlarında saklamıyorsunuz, böylece elinizdeki verilere uyacak şekilde bir yaklaşım uyarlayabiliyoruz.

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

Bu yaklaşım daha sonra diğer üç köşeye kolayca uygulanabilir.


2

Diğer cevaplara dayanarak ve bunları tamamlamak için burada P5 ile bir örnek oluşturmayı başardım .

Doğrudan erişmek istediğinizde kod aşağıdadır:

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

Yukarıdaki kodu yeniden düzenlemek, her köşenin temelde center + height/2 + width/2olduğu ve her köşe için uygun işaretlerle basit bir gerçeği vurgulayan temizlenmiş bir form verir . Bu aynı zamanda tedavi eğer tutan height/2ve width/2döndürülmüş vektörler olarak.

Tercümanı yardımcıları sıraya oturtmaya güvenmek, bunu karşılaştırmaya çalışmamız oldukça etkili olmalıdır.

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

Rotasyon hakkındaki Wikipedia makalesine bakın . Özü şudur:

(1) c merkez nokta ise, köşeler c + ( L / 2, W / 2), +/- vb'dir; burada L ve W , dikdörtgenin uzunluğu ve genişliğidir.

(2) Dikdörtgeni , c'nin dört köşesinden çıkararak, merkez c başlangıç noktasında olacak şekilde çevirin.

(3) Dikdörtgeni belirtilen trig formülleri aracılığıyla 40 derece döndürün.

(4) Her koordinata c ekleyerek geri çevirin.


Cevabınız için teşekkürler ama korkmuyorum. Bilinmiyorlarsa, merkezi (bilinen) köşelerden (bilinmeyen) nasıl özetleyebilirim? Yani, köşelerin koordinatları bulmaya çalıştığım şeyler.
Stacky

Açıklığa kavuşturmaya çalıştım.
Joseph O'Rourke

0

Muhtemelen, sorunu ikiye bölerek bazı optimizasyonlar vardır:

  • üst ve alt tarafın merkezini, yani merkez + döndürülmüş yüksekliği / 2 hesaplayın.
  • döndürülmüş genişliği / 2 kullanarak köşeleri bu merkez noktalara göre hesaplayın
  • Gerçek sinüsü ve kosinüsü bir kez ve herkes için hesaplayın.

Aşağıdaki kod, burada dikdörtgen cetvel olarak adlandırılır. ruler.x, cetvel, y dikdörtgen merkezidir.

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

Biraz geç, ama burada kullandığım kompakt bir işlev. Üst ve sol noktaları hesaplar, daha sonra onları ters köşeler için çevirir.

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

Eski yazı, ancak işte başka bir yol var:

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

Umarım yardımcı olur!

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.