找到连接两个移动物体的矩形的 4 个角
Finding the 4 corners of a rectangle which connects two moving objects
我想在两点之间画一条线,为此我使用 sf::VertexArray shape(sf::Quads, 4);
。
这是我的全部 draw
功能:
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
和p2Pos
是点的中心坐标。
这让我明白了一条线显然不适用于移动的物体,因为矩形的角点是固定的,这里有一些例子:(红点不动,而白点在这个例子)
我想实现一个解决方案,这样 'Stick'(矩形)无论两点的位置如何都可以工作,稍后我会为棍子添加某种 onClick 事件,所以我可以通过单击它们来删除它们,因此解决方案也需要与之兼容...谢谢!
如果需要用“粗线”(即矩形)连接点(x1,y1)和(x2,y2),可以先计算点1、2的连线找到顶点。然后计算该线的法线,从点 1 和点 2 开始。您的连接线的 angular 系数为 (y2-y1)/(x2-x1),法线将具有 (x2-x1)/ (y2-y1).
然后您的四个顶点位于这两条线上,分别与点 1 和点 2 的距离为 d/2(d 是矩形的厚度)。 x1 = x2 或 y1 = y2 的情况是特殊的,因为连接线或其法线将具有无限 angular 系数。
有几个问题与此问题相关 - this 是一个。
您要查找的概念是法向量:
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
然后你的四个角是:
{ p1Pos + 正常,p1Pos - 正常,p2Pos - 正常,p2Pos + 正常}
如果您能够获得带有方角的矩形,则可能需要在每次点相对于彼此移动时都包含角计算
因此对于每个动作,您的计算结果如下:
- 第 1 步:计算出点 A、B 之间的角度(使用三角函数)-> 称之为 theta。
- 第 2 步:新 角将为 +/- 90 度。来自theta,来自各个点的2r。
例如:
- 如果 theta 是 45(就像你的第一个例子),你的末端将延伸到 -45(或 315)和 135。
- 如果 theta 为 102.5,您的两端将延伸至 12.5 和 192.5。
你可以找到线的法线。这可以通过减去位置 p1Pos
和 p2Pos
(并翻转 x 或 y 的符号以获得 90° 旋转)并将其除以线的长度来完成。直线的长度可以通过毕达哥拉斯定理找到,因为它可以被认为是直角三角形的斜边。
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);
结果如下:
我想在两点之间画一条线,为此我使用 sf::VertexArray shape(sf::Quads, 4);
。
这是我的全部 draw
功能:
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
和p2Pos
是点的中心坐标。
这让我明白了一条线显然不适用于移动的物体,因为矩形的角点是固定的,这里有一些例子:(红点不动,而白点在这个例子)
我想实现一个解决方案,这样 'Stick'(矩形)无论两点的位置如何都可以工作,稍后我会为棍子添加某种 onClick 事件,所以我可以通过单击它们来删除它们,因此解决方案也需要与之兼容...谢谢!
如果需要用“粗线”(即矩形)连接点(x1,y1)和(x2,y2),可以先计算点1、2的连线找到顶点。然后计算该线的法线,从点 1 和点 2 开始。您的连接线的 angular 系数为 (y2-y1)/(x2-x1),法线将具有 (x2-x1)/ (y2-y1).
然后您的四个顶点位于这两条线上,分别与点 1 和点 2 的距离为 d/2(d 是矩形的厚度)。 x1 = x2 或 y1 = y2 的情况是特殊的,因为连接线或其法线将具有无限 angular 系数。
有几个问题与此问题相关 - this 是一个。
您要查找的概念是法向量:
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
然后你的四个角是: { p1Pos + 正常,p1Pos - 正常,p2Pos - 正常,p2Pos + 正常}
如果您能够获得带有方角的矩形,则可能需要在每次点相对于彼此移动时都包含角计算
因此对于每个动作,您的计算结果如下:
- 第 1 步:计算出点 A、B 之间的角度(使用三角函数)-> 称之为 theta。
- 第 2 步:新 角将为 +/- 90 度。来自theta,来自各个点的2r。
例如:
- 如果 theta 是 45(就像你的第一个例子),你的末端将延伸到 -45(或 315)和 135。
- 如果 theta 为 102.5,您的两端将延伸至 12.5 和 192.5。
你可以找到线的法线。这可以通过减去位置 p1Pos
和 p2Pos
(并翻转 x 或 y 的符号以获得 90° 旋转)并将其除以线的长度来完成。直线的长度可以通过毕达哥拉斯定理找到,因为它可以被认为是直角三角形的斜边。
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);
结果如下: