diff --git a/src/Segment.cpp b/src/Segment.cpp new file mode 100644 index 0000000..cc77f44 --- /dev/null +++ b/src/Segment.cpp @@ -0,0 +1,37 @@ +#include "Segment.hpp" + +Segment::Segment() : Segment({0, 0}, {0, 0}) {}; + +Segment::Segment(const glm::vec2& location) : Segment(location, location) {}; + +Segment::Segment(const glm::vec2& start, const glm::vec2& end) : start(start), end(end) {}; + +glm::vec2 Segment::get_intersection() +{ +} + +float Segment::get_dx() +{ + return end.x - start.x; +} + +float Segment::get_length() +{ + return glm::distance(start, end); +} + +void Segment::move(const glm::vec2& delta) +{ + start += delta; + end += delta; +} + +glm::vec2 Segment::get_center() +{ +} + +std::ostream& operator<<(std::ostream& out, const Segment& segment) +{ + out << "{(" << segment.start.x << ", " << segment.start.y << "), (" << segment.end.x << ", " << segment.end.y << ")}"; + return out; +} diff --git a/src/Segment.hpp b/src/Segment.hpp new file mode 100644 index 0000000..fe7ac31 --- /dev/null +++ b/src/Segment.hpp @@ -0,0 +1,27 @@ +#ifndef Segment_h_ +#define Segment_h_ + +#include + +#include "glm/vec2.hpp" +#include "glm/geometric.hpp" + +struct Segment +{ + + glm::vec2 start, end; + + Segment(); + Segment(const glm::vec2&); + Segment(const glm::vec2&, const glm::vec2&); + glm::vec2 get_intersection(); + float get_dx(); + float get_length(); + void move(const glm::vec2&); + glm::vec2 get_center(); + +}; + +std::ostream& operator<<(std::ostream&, const Segment&); + +#endif diff --git a/src/extension.cpp b/src/extension.cpp index 4f8e7cc..ee67b86 100644 --- a/src/extension.cpp +++ b/src/extension.cpp @@ -11,6 +11,70 @@ void sfw::set_magnitude(glm::vec2& vector, float magnitude) vector = glm::normalize(vector) * magnitude; } +bool sfw::lines_intersect(const Segment& segment_a, const Segment& segment_b) +{ + glm::vec2 intersection; + return lines_intersect(segment_a, segment_b, intersection); +} + +/* + from http://www.realtimerendering.com/resources/GraphicsGems/gemsii/xlines.c +*/ +bool sfw::lines_intersect(const Segment& segment_a, const Segment& segment_b, glm::vec2& intersection) +{ + float x1 = segment_a.start.x, y1 = segment_a.start.y, x2 = segment_a.end.x, + y2 = segment_a.end.y, x3 = segment_b.start.x, y3 = segment_b.start.y, + x4 = segment_b.end.x, y4 = segment_b.end.y; + + float a1, a2, b1, b2, c1, c2; // Coefficients of line eqns. + float r1, r2, r3, r4; // 'Sign' values + float denom, num; // Intermediate values + + // Compute a1, b1, c1, where line joining points 1 and 2 is "a1 x + b1 y + c1 = 0" + a1 = y2 - y1; + b1 = x1 - x2; + c1 = x2 * y1 - x1 * y2; + + // Compute r3 and r4 + r3 = a1 * x3 + b1 * y3 + c1; + r4 = a1 * x4 + b1 * y4 + c1; + + // Check signs of r3 and r4. If both point 3 and point 4 lie on same side of + // line 1, the line segments do not intersect + if (r3 != 0 && r4 != 0 && std::copysign(1, r3) == std::copysign(1, r4)) + { + return false; + } + + // Compute a2, b2, c2 + a2 = y4 - y3; + b2 = x3 - x4; + c2 = x4 * y3 - x3 * y4; + + // Compute r1 and r2 + r1 = a2 * x1 + b2 * y1 + c2; + r2 = a2 * x2 + b2 * y2 + c2; + + // Check signs of r1 and r2. If both point 1 and point 2 lie on same side + // of second line segment, the line segments do not intersect + if (r1 != 0 && r2 != 0 && std::copysign(1, r1) == std::copysign(1, r2)) + { + return false; + } + + // Line segments intersect: compute intersection point + denom = a1 * b2 - a2 * b1; + if (denom == 0) + { + return false; + } + num = b1 * c2 - b2 * c1; + intersection.x = num / denom; + num = a2 * c1 - a1 * c2; + intersection.y = num / denom; + return true; +} + Box sfw::get_texture_box(SDL_Texture* texture) { int w, h; diff --git a/src/extension.hpp b/src/extension.hpp index dc2eddc..4329281 100644 --- a/src/extension.hpp +++ b/src/extension.hpp @@ -9,6 +9,7 @@ #include #include #include +#include #include "SDL.h" #include "SDL_image.h" @@ -19,6 +20,7 @@ #include "glm/gtx/vector_angle.hpp" #include "Box.hpp" +#include "Segment.hpp" #include "filesystem.hpp" namespace sfw @@ -27,6 +29,8 @@ namespace sfw glm::vec2 get_step(glm::vec2, glm::vec2, float); void set_magnitude(glm::vec2&, float); + bool lines_intersect(const Segment&, const Segment&); + bool lines_intersect(const Segment&, const Segment&, glm::fvec2&); Box get_texture_box(SDL_Texture*); void fill_texture(SDL_Renderer*, SDL_Texture*, Uint8, Uint8, Uint8, Uint8 = 0xff); void fill_texture(SDL_Renderer*, SDL_Texture*, SDL_Texture*);