Add polar coordinates constructor for sf::Vector2<T>

This commit is contained in:
Chris Thrasher 2022-04-29 09:37:29 -06:00 committed by Lukas Dürrenberger
parent 0785093ebc
commit 88515b2fca
5 changed files with 82 additions and 10 deletions

View File

@ -200,8 +200,7 @@ int main()
} }
// Move the ball // Move the ball
float factor = ballSpeed * deltaTime; ball.move({ballSpeed * deltaTime, ballAngle});
ball.move({std::cos(ballAngle.asRadians()) * factor, std::sin(ballAngle.asRadians()) * factor});
#ifdef SFML_SYSTEM_IOS #ifdef SFML_SYSTEM_IOS
const std::string inputString = "Touch the screen to restart."; const std::string inputString = "Touch the screen to restart.";

View File

@ -52,7 +52,7 @@ public:
constexpr Vector2(); constexpr Vector2();
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
/// \brief Construct the vector from its coordinates /// \brief Construct the vector from cartesian coordinates
/// ///
/// \param X X coordinate /// \param X X coordinate
/// \param Y Y coordinate /// \param Y Y coordinate
@ -74,6 +74,22 @@ public:
template <typename U> template <typename U>
constexpr explicit Vector2(const Vector2<U>& vector); constexpr explicit Vector2(const Vector2<U>& vector);
////////////////////////////////////////////////////////////
/// \brief Construct the vector from polar coordinates
///
/// \param r Length of vector (can be negative)
/// \param phi Angle from X axis
///
/// Note that this constructor is lossy: calling length() and angle()
/// may return values different to those provided in this constructor.
///
/// In particular, these transforms can be applied:
/// * Vector2(r, phi) == Vector2(-r, phi + 180_deg)
/// * Vector2(r, phi) == Vector2(r, phi + n * 360_deg)
///
////////////////////////////////////////////////////////////
Vector2(T r, Angle phi);
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
/// \brief Length of the vector <i><b>(floating-point)</b></i>. /// \brief Length of the vector <i><b>(floating-point)</b></i>.
/// ///
@ -103,7 +119,7 @@ public:
/// ///
/// \return The smallest angle which rotates \c *this in positive /// \return The smallest angle which rotates \c *this in positive
/// or negative direction, until it has the same direction as \c rhs. /// or negative direction, until it has the same direction as \c rhs.
/// The result has a sign and lies in the range [-180, 180°). /// The result has a sign and lies in the range [-180, 180) degrees.
/// \pre Neither \c *this nor \c rhs is a zero vector. /// \pre Neither \c *this nor \c rhs is a zero vector.
/// ///
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
@ -114,7 +130,7 @@ public:
/// ///
/// For example, the vector (1,0) corresponds to 0 degrees, (0,1) corresponds to 90 degrees. /// For example, the vector (1,0) corresponds to 0 degrees, (0,1) corresponds to 90 degrees.
/// ///
/// \return Angle in the range [-180°, 180°). /// \return Angle in the range [-180, 180) degrees.
/// \pre This vector is no zero vector. /// \pre This vector is no zero vector.
/// ///
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////

View File

@ -53,6 +53,16 @@ y(static_cast<T>(vector.y))
} }
////////////////////////////////////////////////////////////
template <typename T>
Vector2<T>::Vector2(T r, Angle phi) :
x(r * static_cast<T>(std::cos(phi.asRadians()))),
y(r * static_cast<T>(std::sin(phi.asRadians())))
{
static_assert(std::is_floating_point_v<T>, "Vector2::Vector2(T, Angle) is only supported for floating point types");
}
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
template <typename T> template <typename T>
T Vector2<T>::length() const T Vector2<T>::length() const

View File

@ -73,11 +73,7 @@ std::size_t CircleShape::getPointCount() const
Vector2f CircleShape::getPoint(std::size_t index) const Vector2f CircleShape::getPoint(std::size_t index) const
{ {
Angle angle = static_cast<float>(index) / static_cast<float>(m_pointCount) * sf::degrees(360) - sf::degrees(90); Angle angle = static_cast<float>(index) / static_cast<float>(m_pointCount) * sf::degrees(360) - sf::degrees(90);
float rad = angle.asRadians(); return Vector2f(m_radius, m_radius) + Vector2f(m_radius, angle);
float x = std::cos(rad) * m_radius;
float y = std::sin(rad) * m_radius;
return Vector2f(m_radius + x, m_radius + y);
} }
} // namespace sf } // namespace sf

View File

@ -37,6 +37,57 @@ TEST_CASE("sf::Vector2 class template - [system]")
CHECK(vector.x == static_cast<int>(sourceVector.x)); CHECK(vector.x == static_cast<int>(sourceVector.x));
CHECK(vector.y == static_cast<int>(sourceVector.y)); CHECK(vector.y == static_cast<int>(sourceVector.y));
} }
SUBCASE("Length and angle constructor")
{
CHECK(sf::Vector2f(0, sf::degrees(0)) == sf::Vector2f(0, 0));
CHECK(sf::Vector2f(0, sf::degrees(45)) == sf::Vector2f(0, 0));
CHECK(sf::Vector2f(0, sf::degrees(90)) == sf::Vector2f(0, 0));
CHECK(sf::Vector2f(0, sf::degrees(135)) == sf::Vector2f(0, 0));
CHECK(sf::Vector2f(0, sf::degrees(180)) == sf::Vector2f(0, 0));
CHECK(sf::Vector2f(0, sf::degrees(270)) == sf::Vector2f(0, 0));
CHECK(sf::Vector2f(0, sf::degrees(360)) == sf::Vector2f(0, 0));
CHECK(sf::Vector2f(0, sf::degrees(-90)) == sf::Vector2f(0, 0));
CHECK(sf::Vector2f(0, sf::degrees(-180)) == sf::Vector2f(0, 0));
CHECK(sf::Vector2f(0, sf::degrees(-270)) == sf::Vector2f(0, 0));
CHECK(sf::Vector2f(0, sf::degrees(-360)) == sf::Vector2f(0, 0));
CHECK(sf::Vector2f(1, sf::degrees(0)) == sf::Vector2f(1, 0));
CHECK(sf::Vector2f(1, sf::degrees(45)) == ApproxVec2(std::sqrt(2.f) / 2.f, std::sqrt(2.f) / 2.f));
CHECK(sf::Vector2f(1, sf::degrees(90)) == ApproxVec2(0, 1));
CHECK(sf::Vector2f(1, sf::degrees(135)) == ApproxVec2(-std::sqrt(2.f) / 2.f, std::sqrt(2.f) / 2.f));
CHECK(sf::Vector2f(1, sf::degrees(180)) == ApproxVec2(-1, 0));
CHECK(sf::Vector2f(1, sf::degrees(270)) == ApproxVec2(0, -1));
CHECK(sf::Vector2f(1, sf::degrees(360)) == ApproxVec2(1, 0));
CHECK(sf::Vector2f(1, sf::degrees(-90)) == ApproxVec2(0, -1));
CHECK(sf::Vector2f(1, sf::degrees(-180)) == ApproxVec2(-1, 0));
CHECK(sf::Vector2f(1, sf::degrees(-270)) == ApproxVec2(0, 1));
CHECK(sf::Vector2f(1, sf::degrees(-360)) == ApproxVec2(1, 0));
CHECK(sf::Vector2f(-1, sf::degrees(0)) == sf::Vector2f(-1, 0));
CHECK(sf::Vector2f(-1, sf::degrees(45)) == ApproxVec2(-std::sqrt(2.f) / 2.f, -std::sqrt(2.f) / 2.f));
CHECK(sf::Vector2f(-1, sf::degrees(90)) == ApproxVec2(0, -1));
CHECK(sf::Vector2f(-1, sf::degrees(135)) == ApproxVec2(std::sqrt(2.f) / 2.f, -std::sqrt(2.f) / 2.f));
CHECK(sf::Vector2f(-1, sf::degrees(180)) == ApproxVec2(1, 0));
CHECK(sf::Vector2f(-1, sf::degrees(270)) == ApproxVec2(0, 1));
CHECK(sf::Vector2f(-1, sf::degrees(360)) == ApproxVec2(-1, 0));
CHECK(sf::Vector2f(-1, sf::degrees(-90)) == ApproxVec2(0, 1));
CHECK(sf::Vector2f(-1, sf::degrees(-180)) == ApproxVec2(1, 0));
CHECK(sf::Vector2f(-1, sf::degrees(-270)) == ApproxVec2(0, -1));
CHECK(sf::Vector2f(-1, sf::degrees(-360)) == ApproxVec2(-1, 0));
CHECK(sf::Vector2f(4.2f, sf::degrees(0)) == sf::Vector2f(4.2f, 0));
CHECK(sf::Vector2f(4.2f, sf::degrees(45)) == ApproxVec2(4.2f * std::sqrt(2.f) / 2.f, 4.2f * std::sqrt(2.f) / 2.f));
CHECK(sf::Vector2f(4.2f, sf::degrees(90)) == ApproxVec2(0, 4.2f));
CHECK(sf::Vector2f(4.2f, sf::degrees(135)) == ApproxVec2(-4.2f * std::sqrt(2.f) / 2.f, 4.2f * std::sqrt(2.f) / 2.f));
CHECK(sf::Vector2f(4.2f, sf::degrees(180)) == ApproxVec2(-4.2f, 0));
CHECK(sf::Vector2f(4.2f, sf::degrees(270)) == ApproxVec2(0, -4.2f));
CHECK(sf::Vector2f(4.2f, sf::degrees(360)) == ApproxVec2(4.2f, 0));
CHECK(sf::Vector2f(4.2f, sf::degrees(-90)) == ApproxVec2(0, -4.2f));
CHECK(sf::Vector2f(4.2f, sf::degrees(-180)) == ApproxVec2(-4.2f, 0));
CHECK(sf::Vector2f(4.2f, sf::degrees(-270)) == ApproxVec2(0, 4.2f));
CHECK(sf::Vector2f(4.2f, sf::degrees(-360)) == ApproxVec2(4.2f, 0));
}
} }
SUBCASE("Unary operations") SUBCASE("Unary operations")