randomprogramming
randomprogramming

Reputation: 373

Finding the 4 corners of a rectangle which connects two moving objects

I am trying to make a line between two points, I am using sf::VertexArray shape(sf::Quads, 4); for this.

This is my entire draw function:

void Stick::draw(sf::RenderTarget& target, sf::RenderStates states) const {
sf::VertexArray shape(sf::Quads, 4);

sf::Vector2f p1Pos = this->p1->getPosition();
sf::Vector2f p2Pos = this->p2->getPosition();

shape[0].position = sf::Vector2f(p1Pos.x + 10.f, p1Pos.y + 10.f);
shape[1].position = sf::Vector2f(p1Pos.x - 10.f, p1Pos.y - 10.f);
shape[2].position = sf::Vector2f(p2Pos.x - 10.f, p2Pos.y - 10.f);
shape[3].position = sf::Vector2f(p2Pos.x + 10.f, p2Pos.y + 10.f);
shape[0].color = sf::Color::Green;
shape[1].color = sf::Color::Green;
shape[2].color = sf::Color::Green;
shape[3].color = sf::Color::Green;
target.draw(shape, states);
}

p1Pos and p2Pos are the center coordinates of the points.

What this gets me is a line which obviously won't work with moving objects, since the corner points of the rectangles are fixed, here's some examples: (the red dot isn't moving while the white one is in this example)

Example Example 2

I would like to implement a solution so that the 'Stick' (rectangle) works regardless of the positions of the two points, and I will later on be adding some sort of onClick event for the sticks, so that I can delete them by clicking on them, so the solution would need to be compatible with that as well... Thanks!

Upvotes: 2

Views: 265

Answers (4)

Stack Danny
Stack Danny

Reputation: 8156

You can find the normal of the line. This can be done by subtracting the positions p1Pos and p2Pos (and flipping either sign of x or y to get a 90° rotation) and dividing that by the length of the line. The length of the line can be found via Pythagoras theorem, since it can be thought of as the hypotenuse of a right triangle.

auto diff = p1Pos - p2Pos;
auto length = std::sqrt(diff.x * diff.x + diff.y * diff.y);
auto normal = sf::Vector2f(p1Pos.y - p2Pos.y, p2Pos.x - p1Pos.x) / length;
auto thickness = 15.0f;

shape[0].position = sf::Vector2f(p1Pos.x + normal.x * thickness, p1Pos.y + normal.y * thickness);
shape[1].position = sf::Vector2f(p1Pos.x - normal.x * thickness, p1Pos.y - normal.y * thickness);
shape[2].position = sf::Vector2f(p2Pos.x - normal.x * thickness, p2Pos.y - normal.y * thickness);
shape[3].position = sf::Vector2f(p2Pos.x + normal.x * thickness, p2Pos.y + normal.y * thickness);

and here's the result: the line

Upvotes: 6

Adam Smooch
Adam Smooch

Reputation: 1322

If you’re able to get the rectangle with square corners, you may need to include the corner calculation every time your points will move, relative to one another

So for each movement your calculations would look something like:

  • Step 1: figure out the angle between points A,B (using trigonometry) -> call it theta.
  • Step 2: the new corners will be at +/- 90 deg. from theta, 2r from the respective points.

So for example:

  • If theta is 45 (like your first example), your ends will extend towards -45(or 315) and 135.
  • if theta is 102.5, your ends will extend towards 12.5 and 192.5.

Upvotes: 0

Botje
Botje

Reputation: 31010

The concept you are looking for is a normal vector:

sf::Vector2f p1ToP2{p1Pos - p2Pos};
sf::Vector2f normal{p1ToP2.y, -p1ToP2.x}; // normal is now perpendicular to p1ToP2
normal /= sqrt(pow(normal.x, 2) + pow(normal.y, 2)); // normal is now of magnitude 1
normal *= 5; // ten pixels on each side

and then your four corners are: { p1Pos + normal, p1Pos - normal, p2Pos - normal, p2Pos + normal }

Upvotes: 1

LSerni
LSerni

Reputation: 57418

If you need to connect points (x1, y1) and (x2, y2) with a "thick line" (i.e. a rectangle), the vertices can be found by first calculating the line connecting points 1, 2. Then you calculate the normals to that line, passing from points 1 and 2. Your connecting line has an angular coefficient of (y2-y1)/(x2-x1), the normals will have (x2-x1)/(y2-y1).

Your four vertices are then on those two lines, at d/2 distance from points 1 and 2 respectively (d being the thickness of the rectangle). The cases where x1 = x2 or y1 = y2 are special since either the connecting line or its normals will have infinite angular coefficient.

There are several questions related to this problem - this is one.

Upvotes: 1

Related Questions