game/sdlpp/sdlpp_geometry_line.hpp

72 lines
2.4 KiB
C++
Raw Permalink Normal View History

#ifndef SDLPP_HPP_GEOMETRY_LINE
#define SDLPP_HPP_GEOMETRY_LINE
#include "sdlpp_common.hpp"
#include "sdlpp_vector.hpp"
#include "sdlpp_line.hpp"
#include <algorithm>
2021-03-13 14:05:16 +00:00
#include <iostream>
namespace SDLPP {
2021-03-13 14:05:16 +00:00
template < typename T >
Vec2D< T > pointProjectionOnLine( const Vec2D< T > &point,
const Line< T > &line ) {
/* from here -
* https://stackoverflow.com/questions/849211/shortest-distance-between-a-point-and-a-line-segment
*/
auto length_squared = line.lengthSquared();
if ( length_squared == 0.0 )
return point;
auto t =
std::max( 0.0, std::min( 1.0, ( ( point - line.getStart() ) *
( line.getEnd() - line.getStart() ) ) /
length_squared ) );
return line.getStart() + t * ( line.getEnd() - line.getStart() );
}
2021-03-13 14:05:16 +00:00
template < typename T >
double pointLineDistance( const Vec2D< T > &point, const Line< T > &line ) {
return vecDistance( point, pointProjectionOnLine( point, line ) );
}
2021-03-13 14:05:16 +00:00
template < typename T >
int _determinant( const Line< T > &line, const Vec2D< T > &point ) {
auto res = ( line.getEnd().getX() - line.getStart().getX() ) *
( point.getY() - line.getStart().getY() ) -
( line.getEnd().getY() - line.getStart().getY() ) *
( point.getX() - line.getStart().getX() );
if ( res < 0 )
return -1;
if ( res > 0 )
return 1;
return 0;
}
template < typename T >
bool linesCross( const Line< T > &a, const Line< T > &b ) {
auto det_a_s = _determinant( a, b.getStart() );
auto det_a_e = _determinant( a, b.getEnd() );
if ( det_a_s == det_a_e && det_a_s != 0 )
return false;
// det_a_s == det_a_e == 0, means that lines have the same vector,
// we need to find out if they overlap
if ( det_a_s == det_a_e ) {
if ( a.getStart().getX() == a.getEnd().getX() ) {
// vertical lines
return a.bottomost().getY() > b.topmost().getY() &&
a.topmost().getY() < b.bottomost().getY();
} else {
// horizontal lines
return a.leftmost().getX() < b.rightmost().getX() &&
a.rightmost().getX() > b.leftmost().getX();
}
}
auto det_b_s = _determinant( b, a.getStart() );
auto det_b_e = _determinant( b, a.getEnd() );
if ( det_b_s == det_b_e )
return false;
return true;
}
} // namespace SDLPP
#endif