<p>If you rotate your rectangles through a common origin, then your method works.
Your method works if there always exists a separating line that is parallel to a side of one of your rectangles. Such a line indeed exists. To see this, start from an arbitrary separating line and rotate it until it hits both rectangles, say in vertices <span class="math-container">$p$</span> and <span class="math-container">$q$</span>.
For a given angle <span class="math-container">$\alpha$</span>, consider the line <span class="math-container">$l_p(\alpha)$</span> through <span class="math-container">$p$</span> and <span class="math-container">$l_q(\alpha)$</span> through <span class="math-container">$q$</span>.
By construction, there exists some <span class="math-container">$\alpha$</span> such that these lines coincide (and pass through both <span class="math-container">$p$</span> and <span class="math-container">$q$</span>) and are both separating lines.
Now rotate these separating lines by varying <span class="math-container">$\alpha$</span> until one of them hits a second vertex of a rectangle. If a separating line hits vertices of different rectangles, then the separating lines must coincide (because the region between <span class="math-container">$l_p(\alpha)$</span> and <span class="math-container">$l_q(\alpha)$</span> contains no rectangles), so one of the separating lines hits two vertices of the same rectangle, and hence coincides with an side of a rectangle. Therefore, your method works if you rotate your rectangles through a common origin.</p>
<p><strong>Prior answer:</strong>
In my original answer, I misinterpreted your method and assumed that you rotated your rectangles around their respective centers. Under that assumption, the method may falsely report that rectangles collide, as illustrated in the figure below.
The blue squares do not overlap, but their axis-aligned bounding boxes do. Rotating the squares to make the top right square axis aligned results in the red squares, whose axis-aligned bounding boxes also overlap.</p>
<p><a href="https://i.sstatic.net/JJRj3.png" rel="nofollow noreferrer"><img src="https://i.sstatic.net/JJRj3.png" alt="Squares" /></a></p>

CC BY-SA 4.0
2021-09-13T23:57:56.000Z
Sorry, I'm not sure if I'm understanding you but I tried to make a reproduction of the case that you're describing here https://jsfiddle.net/4rhyp1q5 (move the rectangle with wasd), and I'm not seeing that issue. Maybe you could edit the fiddle with the case that you're describing?
Erick Weber
CC BY-SA 4.0
2021-09-14T03:39:39.270Z
This answer looks incorrect to me.  When you make the first blue square axis-aligned, there is overlap in the bounding boxes, but when you make the second blue square axis-aligned, there is no overlap in the bounding boxes.  Consequently the proposed method does not claim they collide -- the proposed method seems to work fine on the blue squares.
D.W.
CC BY-SA 4.0
2021-09-14T03:39:41.843Z
I find the picture confusing because it shows 4 squares, but the question talks about 2 squares.  I suggest you try to draw a picture with two squares, where you show the result of the first check (rotate to make the first square axis-aligned); and a separate picture with two squares, where you show the result of the second check (rotate to make the second square axis-aligned), and I think you'll see why this counterexample doesn't work.
D.W.
CC BY-SA 4.0
2021-09-14T08:08:40.657Z
I updated the figure.
Tim
CC BY-SA 4.0
2021-09-14T08:21:25.357Z
@Tim are you still saying that this is indeed a counter-example in some way?
Erick Weber
CC BY-SA 4.0
2021-09-14T08:30:24.127Z
The AABBs of the blue squares (which are rotated such that the left square is axis-aligned) overlap, and the AABBs of the red squares (which are rotated such that the right square is axis-aligned) overlap, that's what you're checking right?
Tim
CC BY-SA 4.0
2021-09-14T09:14:13.867Z
I think one of us is misunderstanding the other.. Were you able to take a look at the fiddle I linked? Can you reproduce your counter-example there?
Erick Weber
CC BY-SA 4.0
2021-09-14T10:08:44.907Z
I assumed you were rotating through the respective centers of the rectangles, in which case your method does not work. If instead, you rotate the rectangles through a common origin, then your method works, and I've added an explanation to why this method works in my answer.
Tim
CC BY-SA 4.0
2021-09-14T10:18:40.007Z
I'm a bit confused. The rectangles are rotated by their respective centers. You can see in the fiddle if you hit `q` that the rectangle rotates around its own center and it still seems to work fine, no?
Erick Weber
CC BY-SA 4.0
2021-09-14T10:20:52.380Z
The point is that when checking for collisions, you should rotate around a common origin, rather than the respective centers.
Tim
CC BY-SA 4.0
2021-09-14T10:35:20.230Z
Oh, yeah the algorithm does that so that's not a problem. Maybe edit out the "Therefore, your method falsely reports that the rectangles collide." from your reply then because I don't think that happens.
Erick Weber
CC BY-SA 4.0
2021-09-13T23:48:21.760Z
2021-09-14T15:47:46.733Z
2021-09-14T15:47:46.733Z
Tim
<p>I was trying to determine whether or not two rectangles rotated around their centers were colliding and randomly thought to try the following algorithm:</p>
<p>Rotate both rectangles by the negative rotation angle value of the first rectangle, such that the first rectangle becomes an AABB (axis-aligned bounding box) rectangle. Now calculate the bounding box of the second rotated rectangle and use the simple &quot;are two axis aligned rectangles colliding&quot; function to see if those two rectangles are colliding:</p>
<pre><code>function rectanglesCollide(r1X, r1Y, r1W, r1H, r2X, r2Y, r2W, r2H) {
  return r1X &lt; r2X + r2W &amp;&amp; r1X + r1W &gt; r2X &amp;&amp; r1Y &lt; r2Y + r2H &amp;&amp; r1Y + r1H &gt; r2Y;
}
</code></pre>
<p>Now do the same thing but in reverse. That is, rotate both rectangles by the negative rotation angle of the <em>second</em> rectangle, such that now the second rectangle becomes axis-aligned. Then calculate the bounding box for the first rectangle and use the same <code>rectanglesCollide</code> function to determine if those two rectangles are colliding.</p>
<p>From what I can tell, if <em>both</em> of those checks are true, then the rotated rectangles are colliding. I spent a couple days trying to figure out the math and finally got it working! Here's the function for it:</p>
<pre><code>function rotatedRectanglesCollide(r1X, r1Y, r1W, r1H, r1A, r2X, r2Y, r2W, r2H, r2A) {
  let r1CX = r1X + (r1W / 2);
  let r1CY = r1Y + (r1H / 2);
  let r2CX = r2X + (r2W / 2);
  let r2CY = r2Y + (r2H / 2);

  let cosR1A = Math.cos(r1A);
  let sinR1A = Math.sin(r1A);
  let cosR2A = Math.cos(r2A);
  let sinR2A = Math.sin(r2A);

  let r1RX =  cosR2A * (r1CX - r2CX) + sinR2A * (r1CY - r2CY) + r2CX;
  let r1RY = -sinR2A * (r1CX - r2CX) + cosR2A * (r1CY - r2CY) + r2CY;
  let r2RX =  cosR1A * (r2CX - r1CX) + sinR1A * (r2CY - r1CY) + r1CX;
  let r2RY = -sinR1A * (r2CX - r1CX) + cosR1A * (r2CY - r1CY) + r1CY;

  let cosR1AR2A = Math.abs(cosR1A * cosR2A + sinR1A * sinR2A);
  let sinR1AR2A = Math.abs(sinR1A * cosR2A - cosR1A * sinR2A);
  let cosR2AR1A = Math.abs(cosR2A * cosR1A + sinR2A * sinR1A);
  let sinR2AR1A = Math.abs(sinR2A * cosR1A - cosR2A * sinR1A);

  let r1BBH = r1W * sinR1AR2A + r1H * cosR1AR2A;
  let r1BBW = r1W * cosR1AR2A + r1H * sinR1AR2A;
  let r1BBX = r1RX - r1BBW / 2;
  let r1BBY = r1RY - r1BBH / 2;

  let r2BBH = r2W * sinR2AR1A + r2H * cosR2AR1A;
  let r2BBW = r2W * cosR2AR1A + r2H * sinR2AR1A;
  let r2BBX = r2RX - r2BBW / 2;
  let r2BBY = r2RY - r2BBH / 2;

  return r1X &lt; r2BBX + r2BBW &amp;&amp; r1X + r1W &gt; r2BBX &amp;&amp; r1Y &lt; r2BBY + r2BBH &amp;&amp; r1Y + r1H &gt; r2BBY &amp;&amp;
        r2X &lt; r1BBX + r1BBW &amp;&amp; r2X + r2W &gt; r1BBX &amp;&amp; r2Y &lt; r1BBY + r1BBH &amp;&amp; r2Y + r2H &gt; r1BBY;
}
</code></pre>
<p>I was wondering if this is novel, known, or even correct? The closest thing I could find was <a href="https://stackoverflow.com/a/20780108/16894127">this answer</a> on the original post that I found afterwards that seems to be pretty similar, or maybe it's the exact same thing coded differently? I'm not entirely sure how his code works or whether or not it's a different technique. Also, could this be optimized in any way?</p>
<p>Not sure if my explanation was any good but I ended up making a <a href="https://phretaddin.github.io/post/rotated-rectangle-collisions/" rel="nofollow noreferrer">post about it</a> with more details and a demo if that helps understanding at all.</p>

CC BY-SA 4.0
2021-09-14T12:04:26.540Z
Googling for "Separating axis theorem" yields https://gamedevelopment.tutsplus.com/tutorials/collision-detection-using-the-separating-axis-theorem--gamedev-169, which seems similar to what you propose.  I think this question probably isn't a research-level question in theoretical CS, so perhaps should be migrated to cs.stackexchange.com.
Neal Young
<ds.algorithms><reference-request><cg.comp-geom>
Is this a novel technique for determining whether or not two rotated rectangles collide?
Erick Weber
# Is this a novel technique for determining whether or not two rotated rectangles collide?

(Asked by: username_0 on 2021-09-13)

I was trying to determine whether or not two rectangles rotated around their centers were colliding and randomly thought to try the following algorithm:
Rotate both rectangles by the negative rotation angle value of the first rectangle, such that the first rectangle becomes an AABB (axis-aligned bounding box) rectangle. Now calculate the bounding box of the second rotated rectangle and use the simple "are two axis aligned rectangles colliding" function to see if those two rectangles are colliding:
function rectanglesCollide(r1X, r1Y, r1W, r1H, r2X, r2Y, r2W, r2H) {
  return r1X < r2X + r2W && r1X + r1W > r2X && r1Y < r2Y + r2H && r1Y + r1H > r2Y;
}

Now do the same thing but in reverse. That is, rotate both rectangles by the negative rotation angle of the second rectangle, such that now the second rectangle becomes axis-aligned. Then calculate the bounding box for the first rectangle and use the same rectanglesCollide function to determine if those two rectangles are colliding.
From what I can tell, if both of those checks are true, then the rotated rectangles are colliding. I spent a couple days trying to figure out the math and finally got it working! Here's the function for it:
function rotatedRectanglesCollide(r1X, r1Y, r1W, r1H, r1A, r2X, r2Y, r2W, r2H, r2A) {
  let r1CX = r1X + (r1W / 2);
  let r1CY = r1Y + (r1H / 2);
  let r2CX = r2X + (r2W / 2);
  let r2CY = r2Y + (r2H / 2);

  let cosR1A = Math.cos(r1A);
  let sinR1A = Math.sin(r1A);
  let cosR2A = Math.cos(r2A);
  let sinR2A = Math.sin(r2A);

  let r1RX =  cosR2A * (r1CX - r2CX) + sinR2A * (r1CY - r2CY) + r2CX;
  let r1RY = -sinR2A * (r1CX - r2CX) + cosR2A * (r1CY - r2CY) + r2CY;
  let r2RX =  cosR1A * (r2CX - r1CX) + sinR1A * (r2CY - r1CY) + r1CX;
  let r2RY = -sinR1A * (r2CX - r1CX) + cosR1A * (r2CY - r1CY) + r1CY;

  let cosR1AR2A = Math.abs(cosR1A * cosR2A + sinR1A * sinR2A);
  let sinR1AR2A = Math.abs(sinR1A * cosR2A - cosR1A * sinR2A);
  let cosR2AR1A = Math.abs(cosR2A * cosR1A + sinR2A * sinR1A);
  let sinR2AR1A = Math.abs(sinR2A * cosR1A - cosR2A * sinR1A);

  let r1BBH = r1W * sinR1AR2A + r1H * cosR1AR2A;
  let r1BBW = r1W * cosR1AR2A + r1H * sinR1AR2A;
  let r1BBX = r1RX - r1BBW / 2;
  let r1BBY = r1RY - r1BBH / 2;

  let r2BBH = r2W * sinR2AR1A + r2H * cosR2AR1A;
  let r2BBW = r2W * cosR2AR1A + r2H * sinR2AR1A;
  let r2BBX = r2RX - r2BBW / 2;
  let r2BBY = r2RY - r2BBH / 2;

  return r1X < r2BBX + r2BBW && r1X + r1W > r2BBX && r1Y < r2BBY + r2BBH && r1Y + r1H > r2BBY &&
        r2X < r1BBX + r1BBW && r2X + r2W > r1BBX && r2Y < r1BBY + r1BBH && r2Y + r2H > r1BBY;
}

I was wondering if this is novel, known, or even correct? The closest thing I could find was this answer on the original post that I found afterwards that seems to be pretty similar, or maybe it's the exact same thing coded differently? I'm not entirely sure how his code works or whether or not it's a different technique. Also, could this be optimized in any way?
Not sure if my explanation was any good but I ended up making a post about it with more details and a demo if that helps understanding at all.

**Tags:** ds.algorithms, reference-request, cg.comp-geom
> **Comments:**
> **username_1**: Googling for "Separating axis theorem" yields https://gamedevelopment.tutsplus.com/tutorials/collision-detection-using-the-separating-axis-theorem--gamedev-169, which seems similar to what you propose.  I think this question probably isn't a research-level question in theoretical CS, so perhaps should be migrated to cs.stackexchange.com.  

---

## 1 answers

### Answer by username_2 on 2021-09-13. Score: 1

If you rotate your rectangles through a common origin, then your method works.
Your method works if there always exists a separating line that is parallel to a side of one of your rectangles. Such a line indeed exists. To see this, start from an arbitrary separating line and rotate it until it hits both rectangles, say in vertices $p$ and $q$.
For a given angle $\alpha$, consider the line $l\_p(\alpha)$ through $p$ and $l\_q(\alpha)$ through $q$.
By construction, there exists some $\alpha$ such that these lines coincide (and pass through both $p$ and $q$) and are both separating lines.
Now rotate these separating lines by varying $\alpha$ until one of them hits a second vertex of a rectangle. If a separating line hits vertices of different rectangles, then the separating lines must coincide (because the region between $l\_p(\alpha)$ and $l\_q(\alpha)$ contains no rectangles), so one of the separating lines hits two vertices of the same rectangle, and hence coincides with an side of a rectangle. Therefore, your method works if you rotate your rectangles through a common origin.

**Prior answer:**
In my original answer, I misinterpreted your method and assumed that you rotated your rectangles around their respective centers. Under that assumption, the method may falsely report that rectangles collide, as illustrated in the figure below.
The blue squares do not overlap, but their axis-aligned bounding boxes do. Rotating the squares to make the top right square axis aligned results in the red squares, whose axis-aligned bounding boxes also overlap.

[![Squares](https://i.sstatic.net/JJRj3.png)](https://i.sstatic.net/JJRj3.png)

> **Comments:**
> **username_0**: Sorry, I'm not sure if I'm understanding you but I tried to make a reproduction of the case that you're describing here https://jsfiddle.net/4rhyp1q5 (move the rectangle with wasd), and I'm not seeing that issue. Maybe you could edit the fiddle with the case that you're describing?  
> **username_3**: This answer looks incorrect to me.  When you make the first blue square axis-aligned, there is overlap in the bounding boxes, but when you make the second blue square axis-aligned, there is no overlap in the bounding boxes.  Consequently the proposed method does not claim they collide -- the proposed method seems to work fine on the blue squares.  
> **username_3**: I find the picture confusing because it shows 4 squares, but the question talks about 2 squares.  I suggest you try to draw a picture with two squares, where you show the result of the first check (rotate to make the first square axis-aligned); and a separate picture with two squares, where you show the result of the second check (rotate to make the second square axis-aligned), and I think you'll see why this counterexample doesn't work.  
> **username_2**: I updated the figure.  
> **username_0**: @Tim are you still saying that this is indeed a counter-example in some way?  
> **username_2**: The AABBs of the blue squares (which are rotated such that the left square is axis-aligned) overlap, and the AABBs of the red squares (which are rotated such that the right square is axis-aligned) overlap, that's what you're checking right?  
> **username_0**: I think one of us is misunderstanding the other.. Were you able to take a look at the fiddle I linked? Can you reproduce your counter-example there?  
> **username_2**: I assumed you were rotating through the respective centers of the rectangles, in which case your method does not work. If instead, you rotate the rectangles through a common origin, then your method works, and I've added an explanation to why this method works in my answer.  
> **username_0**: I'm a bit confused. The rectangles are rotated by their respective centers. You can see in the fiddle if you hit `q` that the rectangle rotates around its own center and it still seems to work fine, no?  
> **username_2**: The point is that when checking for collisions, you should rotate around a common origin, rather than the respective centers.  
> **username_0**: Oh, yeah the algorithm does that so that's not a problem. Maybe edit out the "Therefore, your method falsely reports that the rectangles collide." from your reply then because I don't think that happens.  

---

