1

I have a rectangle like this...

image 1

... and I also know the rectangle's corner positions, as in the array below:

var corners = [[107, 0], [0, 21], [111, 24], [4, 45]]

Because I need to calculate the rectangle's angle like I've symbolized in the image above, my idea was to just use this code:

var rectangle_angle = ((180/Math.PI) * Math.atan((a[1] - b[1]) / (a[0] - b[0]))).toFixed(2)
console.log('angle : ' + rectangle_angle)

In the case above I'm using the first two corner points to calculate the angle:

var a = corners[0], b = corners[1]

But e.g. I was using a rectangle like below and tried to calculate the rectangle's angle...

image2

(corners: [[101, 0], [110, 22], [0, 38], [9, 60]])

... but the result I got is this -> angle : 67.75, what absolutely is not the right rotation angle.

Afterwards I fixed the problem by just using corner[0] and corner[2] for the calculation instead of using corner[0] and corner[1].

So the result I get now is -20.62°. Way better.


Now my question: How can I extract the right points from my corners array that I have to use for my calculation?

You can try the function here:

var corners = [[107, 0], [0, 21], [111, 24], [4, 45]]

var a = corners[0], b = corners[1]
var rectangle_angle = ((180/Math.PI) * Math.atan((a[1] - b[1]) / (a[0] - b[0]))).toFixed(2)
console.log('angle : ' + rectangle_angle)
trincot
  • 317,000
  • 35
  • 244
  • 286
Jonas0000
  • 1,085
  • 1
  • 12
  • 36
  • Bro, please read the question, I am not trying to find the corners, I'm trying to calculate the angle of a rectangle @JonasW. – Jonas0000 Nov 19 '17 at 11:36
  • `Now my question: How can I extract the right corner positions that I have to use for my calculation?` but the problem is finding the right corners. – Jonas Wilms Nov 19 '17 at 11:37
  • `...and I also know the rectangles corner positions...` trying to find the angle, yes! – Jonas0000 Nov 19 '17 at 11:39
  • Do you always put the X axis in the opposite direction? Confusing. – trincot Nov 19 '17 at 11:42
  • Do you mean the Y asis in my images? - Well yeah.. because I can not really get your comment :( @trincot – Jonas0000 Nov 19 '17 at 11:44
  • No, I mean your X axis, which seems to run from right to left. Normally, you would have them: `|_`, but you have `_|` – trincot Nov 19 '17 at 11:45
  • Well, your right. Yeah customary thing! However, I hope it will not affect my question :p – Jonas0000 Nov 19 '17 at 11:46
  • This has been fun and all, but: duplicate of [How to convert x,y coordinates to an angle?](https://stackoverflow.com/questions/15994194/how-to-convert-x-y-coordinates-to-an-angle) – Daniel Beck Nov 19 '17 at 11:50

3 Answers3

0

How can I extract the right points from my corners array that I have to use for my calculation?

Your a corner of your calculation is where your x-value is 0. Therefor you need to search for the x = 0 value:

var a;
$.each(corners, function(i, corner) {
    if (corner[0] === 0) {
        // you have found your a corner (corners[i])
        a = corner;
    }
});

Your b corner of your calculation is where your y value is 0:

var b;
$.each(corners, function(i, corner) {
    if (corner[1] === 0) {
        // you have found your b corner (corners[i])
        b = corner;
    }
});

But then your calculation needs to be fixed as following:

var rectangle_angle = ((180/Math.PI) * Math.atan((a[1] - b[1]) / (b[0] - a[0]))).toFixed(2)
1stthomas
  • 731
  • 2
  • 15
  • 22
0

The reason why you get the unexpected angle is that your two rectangles have their corners defined in a different order.

The first one has as first two corners the two end-points of its lower long side, while the second one has as first two corners the two end-points of a short side of it. As can be seen from the image, that shorter side indeed has a steeper angle.

As you indicate you cannot influence the order of the points in the rectangle's definitions, you could proceed as follows:

  • sort the corners by increasing Y coordinate: the first corner will then be the bottom one, and the next two will be points with which that bottom corner has an edge
  • Of these two edges, choose the longest one
  • Perform the calculation of the angle based on that edge

Here is some code you could use to make that happen:

function rectangleTilt(rect) {
    const distance2 = (a, b) => (a[0]-b[0])**2 + (a[1]-b[1])**2,
        angle = (a, b) => 180 - Math.atan2(b[1]-a[1], b[0]-a[0]) * 180 / Math.PI,
        // Sort the corners by increasing Y coordinate:
        [a, b, c] = rect.slice().sort( (a, b) => a[1] - b[1] );
    // Return the angle of the longest edge having the lowest corner:
    return distance2(a, b) < distance2(a, c) ? angle(a, c) : angle(a, b);
}

function drawRectangle(ctx, rect) {
    const [a, b, c, d] = rect.slice().sort( (a, b) => a[1] - b[1] );
    ctx.moveTo(a[0], a[1]);
    ctx.lineTo(b[0], b[1]);
    ctx.lineTo(d[0], d[1]);
    ctx.lineTo(c[0], c[1]);
    ctx.lineTo(a[0], a[1]);
    ctx.stroke(); 
}

const ctx = canvas.getContext("2d");
// Make Y axis go upwards, and X axis backwards
ctx.transform(-1, 0, 0, -1, canvas.width, canvas.height);

var rect = [[101, 0], [110, 22], [0, 38], [9, 60]];
drawRectangle(ctx, rect);
console.log(rectangleTilt(rect).toFixed(2) + "°");
<canvas id="canvas" width="200"></canvas>
trincot
  • 317,000
  • 35
  • 244
  • 286
  • I'm completely aware that my rectangles have different corner characteristics, but I can not define my rectangle because I got this rectangle corner points, I've mentioned above and I'd like to now which of them I have to use in my calculation! – Jonas0000 Nov 19 '17 at 11:58
  • I added an algorithm (and snippet) for finding the longest edge linked to the bottom corner, and performing the angle calculation on that. – trincot Nov 19 '17 at 12:54
0

Filter through corners so you can get corners a and b:

const corners = [[107, 0], [0, 21], [111, 24], [4, 45]]

const cornerA = corners.filter(x => x[1] == 0).reduce((a, b) => a.concat(b))
const cornerB = corners.filter(y => y[0] == 0).reduce((a, b) => a.concat(b))

const rectangleAngle = ((180/Math.PI) * Math.atan((cornerA[1] - cornerB[1]) / (cornerA[0] - cornerB[0]))).toFixed(2)

console.log(rectangleAngle)
codejockie
  • 9,020
  • 4
  • 40
  • 46
  • Hey John, look like a good working solution but I got problems with this corner positions `[[10, 0], [0, 1], [108, 27], [82, 27]]`. (In this case the rectangle is rotated clockwise!) – Jonas0000 Nov 19 '17 at 12:22
  • you might probably want to swap cornerA and cornerB – codejockie Nov 19 '17 at 12:26