Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add a rectangle detection for "out of range" line detection #21

Merged
merged 1 commit into from
Oct 14, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
36 changes: 24 additions & 12 deletions include/Candle/RadialLight.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -13,15 +13,15 @@ namespace candle{
/**
* @brief LightSource that emits light from a single point
* @details
*
*
* A RadialLight is defined, mainly, by the position, the orientation, the
* range of the light and the beam angle. To manipulate the
* position and the orientation of the light, you can change the position
* and rotation of the object as you would do with any sf::Transformable.
* The range can be manipulated as with other LightSources, with
* @ref LightSource::setRange, and the angle of the beam with
* @ref LightSource::setRange, and the angle of the beam with
* @ref setBeamAngle.
*
*
* <table width="100%">
* <tr>
* <td align="center"> <img src="radial_1.png" width="300px"> <br> <em>Variables schema</em> </td>
Expand All @@ -33,23 +33,23 @@ namespace candle{
private:
static int s_instanceCount;
float m_beamAngle;

void draw(sf::RenderTarget& t, sf::RenderStates st) const override;
void resetColor() override;

public:
/**
* @brief Constructor
*/
RadialLight();

/**
* @brief Destructor
*/
virtual ~RadialLight();

void castLight(const EdgeVector::iterator& begin, const EdgeVector::iterator& end) override;

/**
* @brief Set the range for which rays may be casted.
* @details The angle shall be specified in degrees. The angle in which the rays will be casted will be
Expand All @@ -58,14 +58,26 @@ namespace candle{
* @see getBeamAngle
*/
void setBeamAngle(float angle);

/**
* @brief Get the range for which rays may be casted.
* @details It defaults to 360º.
* @details It defaults to 360º.
* @see setBeamAngle
*/
float getBeamAngle() const;

float getBeamAngle() const;

/**
* @brief Get the local bounding rectangle of the light.
* @returns The local bounding rectangle in float.
*/
sf::FloatRect getLocalBounds() const;

/**
* @brief Get the global bounding rectangle of the light.
* @returns The global bounding rectangle in float.
*/
sf::FloatRect getGlobalBounds() const;

};
}

Expand Down
42 changes: 26 additions & 16 deletions include/Candle/geometry/Line.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
#include <limits>

#include <SFML/System/Vector2.hpp>
#include <SFML/Graphics/Rect.hpp>

#include "Candle/geometry/Vector2.hpp"
#include "Candle/Constants.hpp"
Expand All @@ -29,23 +30,32 @@ namespace sfu{
};
sf::Vector2f m_origin; ///< Origin point of the line.
sf::Vector2f m_direction; ///< Direction vector (not necessarily normalized)

/**
* @brief Construct a line that passes through @p p1 and @p p2
* @details The direction is interpreted as p2 - p1.
* @param p1 First point
* @param p2 Second point
*/
Line(const sf::Vector2f& p1, const sf::Vector2f& p2);

/**
* @brief Construct a line defined by a point and an angle.
* @details The direction is interpreted as {cos(angle), sin(angle)}.
* @param p Origin point
* @param angle Angle defining the line
*/
Line(const sf::Vector2f& p, float angle);


/**
* @brief Get the global bounding rectangle of the line.
* @details The returned rectangle is in global coordinates, which
* means that it takes into account the transformations (translation,
* rotation, scale, ...) (see SFML).
* @returns Global bounding rectangle in float
*/
sf::FloatRect getGlobalBounds() const;

/**
* @brief Return the relative position of a point to the line.
* @details If the point is to the right of the direction vector, the
Expand All @@ -55,21 +65,21 @@ namespace sfu{
* @returns -1, 0 or 1
*/
int relativePosition(const sf::Vector2f& point) const;

/**
* @brief Return the minimum distance of a point to the line.
* @param point
* @returns The minimum distance of a point to the line.
*/
float distance(const sf::Vector2f& point) const;

/**
* @brief Returns the relative position of one line to another.
* @param line
* @returns The relative position of the two lines.
*/
LineRelativePosition intersection(const Line& line) const;

/**
* @brief Returns the relative position of one line to another.
* @details If the relative position is SECANT, the output argument
Expand All @@ -81,12 +91,12 @@ namespace sfu{
* @see point
*/
LineRelativePosition intersection(const Line& line, float& t) const;

/**
* @brief Returns the relative position of one line to another.
* @details If the relative position is SECANT, the output argument
* @p t1 contains the parameter required to get the intersection
* point with **this** line and @p t2, the parameter required to
* point with **this** line and @p t2, the parameter required to
* get it with @p line.
* @param line
* @param t1 (Output argument)
Expand All @@ -95,28 +105,28 @@ namespace sfu{
* @see point
*/
LineRelativePosition intersection(const Line& line, float& t1, float& t2) const;

/**
* @brief Get a point of the line.
* @details The point is obtained is m_origin + param * m_direction
* @param param
* @returns A point of the line
*/
sf::Vector2f point(float param) const;

};

/**
* @brief Cast a ray against a set of segments.
* @details Use a line as a ray, casted from its
* [origin](@ref sfu::Line::m_origin) in its
* @details Use a line as a ray, casted from its
* [origin](@ref sfu::Line::m_origin) in its
* [direction](@ref sfu::Line::m_direction). It is intersected with * a set
* of segments, represented as [Lines](sfu::Line) too, and the one closest
* to the cast point is returned.
*
*
* Segments are interpreted to be delimited by the @p ray.m_origin and
* @p ray.point(1).
*
*
* @param begin Iterator to the first ray.
* @param end Iterator to the last ray.
* @param ray
Expand All @@ -126,7 +136,7 @@ namespace sfu{
template <typename Iterator>
sf::Vector2f castRay(const Iterator& begin,
const Iterator& end,
Line ray,
Line ray,
float maxRange=std::numeric_limits<float>::infinity()){
float minRange = maxRange;
ray.m_direction = sfu::normalize(ray.m_direction);
Expand Down
29 changes: 21 additions & 8 deletions src/Line.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ namespace sfu{
Line::Line(const sf::Vector2f& p1, const sf::Vector2f& p2):
m_origin(p1),
m_direction(p2 - p1){}

Line::Line(const sf::Vector2f& p, float angle):
m_origin(p)
{
Expand All @@ -17,13 +17,26 @@ namespace sfu{
ang -= sfu::PI;
m_direction = {std::cos(ang), std::sin(ang)};
}



sf::FloatRect Line::getGlobalBounds() const{
const sf::Vector2f& point1 = m_origin;
sf::Vector2f point2 = m_direction + m_origin;

//Make sure that the rectangle begin from the upper left corner
sf::FloatRect rect;
rect.left = (point1.x < point2.x) ? point1.x : point2.x;
rect.top = (point1.y < point2.y) ? point1.y : point2.y;
rect.width = std::abs(m_direction.x) + 1.0f; //The +1 is here to avoid having a width of zero
rect.height = std::abs(m_direction.y) + 1.0f; //(SFML doesn't like 0 in rect)

return rect;
}

int Line::relativePosition(const sf::Vector2f& point) const{
float f = (point.x-m_origin.x) / m_direction.x - (point.y-m_origin.y) / m_direction.y;
return (0.f < f) - (f < 0.f);
}

float Line::distance(const sf::Vector2f& point) const{
float d;
if(m_direction.x == 0){
Expand All @@ -38,7 +51,7 @@ namespace sfu{
}
return d;
}

Line::LineRelativePosition Line::intersection(const Line& l) const{
float t1, t2;
return intersection(l,t1,t2);
Expand All @@ -52,7 +65,7 @@ namespace sfu{
auto& v = m_direction;
auto& b = l.m_origin;
auto& w = l.m_direction;

float th = angle(v, w);
if(th < 0.001f || th > 359.99f){
if(relativePosition(a) == 0){
Expand All @@ -61,15 +74,15 @@ namespace sfu{
return PARALLEL;
}
}

if(std::abs(w.y) < 0.001f){
t1 = (b.y-a.y) / v.y;
t2 = (a.x + t1*v.x - b.x) / w.x;
}else{
t1 = (w.y * (b.x-a.x) + w.x * (a.y-b.y)) / (v.x*w.y - v.y*w.x);
t2 = (t1*v.y + a.y - b.y) / w.y;
}

return SECANT;
}
sf::Vector2f Line::point(float param) const{
Expand Down
Loading