# I need to find intersection point of a vector in an axis aligned rectangle

I need some help, I have one vector in a rectangle like following

(Ops, first A2 point on the top should be A1, assume it is A1)

Let's say the vector is like above It doesn't have intersection point actually, Basically, I need to find the point A1 and A2

I'm using cocos2d-x but framework specific solutions are not mandatory Thanks

• Possible duplicate of Intersection of a Line and a Rectangle – Vaillancourt Jun 17 '16 at 21:51
• Not necessarily a duplicate... In this case it's more like a projection. @FoxitcL Do you really mean a square or can it be a rectangle, like in the image? Is it always axis-aligned or can it be rotated? – 1000ml Jun 18 '16 at 13:18
• Yes, Its always axis aligned and its rectangle. Updating the question sorry for the missing info – Can Tecim Jun 18 '16 at 17:07
• How is your vector stored? Is it two points? A point and an offset? A point, an angle and a length? – HolyBlackCat Jun 18 '16 at 18:03
• I store it with a point, angle and a length – Can Tecim Jun 18 '16 at 18:07

## 1 Answer

The goal is to project the vector onto the correct sides of the rectangle. Using the tangens function we're already halfway done. The rest is basic trigonometry.

Input data
Depending on how you store the rectangle, we have to transform the input data first. This method expects a rectangle that is defined solely by it's size (width w and height h). It's top left corner lies on the origin [0,0]. The Y-axis of the coordinate system expands downwards (1).

We expect the point p to always be inside the rectangle. The angle is defined in radians.

#include <cmath>
#include <utility>
#include <iostream>

struct Vec2
{
float x, y;
Vec2() : x(0), y(0) {}
Vec2(float X, float Y) : x(X), y(Y) {}
};

typedef std::pair<Vec2, Vec2> Result;

// a  d
// b  c
struct Rect
{
Vec2 a, b, c, d;
};

void project(const Rect& rect, Vec2 p, float angle, Result& output)
{
float tanA = tan(angle);

// Avoid division by zero
if(tanA == 0)
{
output.first.x  = rect.d.x;
output.first.y  = p.y;
output.second.x = rect.a.x;
output.second.y = p.y;
}
else
{
// Transform input (make p relative to rectangle)
p.x -= rect.a.x;
p.y -= rect.a.y;

float w = rect.d.x - rect.a.x;
float h = rect.b.y - rect.a.y;
calcProjection(w, h, p, tanA, output);

// Transform result back to original coordinates
output.first.x  += rect.a.x;
output.first.y  += rect.a.y;
output.second.x += rect.a.x;
output.second.y += rect.a.y;
}
}

int main()
{
Rect rect {
Vec2(400, 600), // Top left
Vec2(400, 700), // Bottom left
Vec2(600, 700), // Bottom right
Vec2(600, 600)  // Top right
};

Vec2 p(550, 650);
float angle = -M_PI_4;

Result result;
project(rect, p, angle, result);

std::cout << "A1: x=" << result.first.x  << " y=" << result.first.y  << std::endl;
std::cout << "A2: x=" << result.second.x << " y=" << result.second.y << std::endl;
}


Projection Algorithm
The basic idea is like this:

1. Use tan() and offsets to project p onto sides CD and AB. Result: yCD yAB
2. Check for boundaries.
3. If outside, project yCD and yAB onto DA or BC using trigonometry.

void calcProjection(float w, float h, const Vec2& p, float tanA, Result& output)
{
float yCD = p.y - (tanA * (w - p.x));
float yAB = p.y + (tanA * p.x);

if(tanA < 0)
tanA = -tanA;

// First projection onto CD
if(yCD < 0)
{
output.first.x = w + (yCD / tanA);
}
else if(yCD > h)
{
float opposite = yCD - h;
output.first.x = w - (opposite / tanA);
output.first.y = h;
}
else
{
output.first.x = w;
output.first.y = yCD;
}

// Second projection onto AB
if(yAB < 0)
{
output.second.x = -yAB / tanA;
}
else if(yAB > h)
{
float opposite  = yAB - h;
output.second.x = opposite / tanA;
output.second.y = h;
}
else
{
output.second.y = yAB;
}
}


Note: The first result A1 will always be on the right side of the rectangle. A2 always on the left. If you want A1 to be on the front and A2 in the back of the vector, you can swap them when the following condition is true: angle >= PI/2 || angle <= -PI/2

I should also note that I haven't fully tested any of this.

(1) When using a coordinate system where the Y-axis expands upwards, simply negate the input angle: angle = -angle

• Thanks for your detailed reply, will try it soon and let you know – Can Tecim Jun 20 '16 at 3:14
• It works perfectly, I just completed porting it to cocos2dx. Thanks again :) – Can Tecim Jun 23 '16 at 21:10
• I couldn't up-vote your answer btw, if you could approve my question I might fill the required reputation to vote – Can Tecim Jun 23 '16 at 21:18
• Glad it worked. I already upvoted your Q. No problem, don't bother. – 1000ml Jun 24 '16 at 14:19