// Copyright (C) 2018 Davis E. King (davis@dlib.net) // License: Boost Software License See LICENSE.txt for the full license. #ifndef DLIB_LInE_H_ #define DLIB_LInE_H_ #include "line_abstract.h" #include "vector.h" #include <utility> namespace dlib { // ---------------------------------------------------------------------------------------- class line { public: line() = default; line(const dpoint& a, const dpoint& b) : end1(a), end2(b) { normal_vector = (end1-end2).cross(dlib::vector<double,3>(0,0,1)).normalize(); } template <typename T> line(const std::pair<vector<T,2>,vector<T,2>>& l) : line(l.first, l.second) {} const dpoint& p1() const { return end1; } const dpoint& p2() const { return end2; } const dpoint& normal() const { return normal_vector; } private: dpoint end1; dpoint end2; dpoint normal_vector; }; // ---------------------------------------------------------------------------------------- template <typename U> double signed_distance_to_line ( const line& l, const vector<U,2>& p ) { return dot(p-l.p1(), l.normal()); } template <typename T, typename U> double signed_distance_to_line ( const std::pair<vector<T,2>,vector<T,2> >& l, const vector<U,2>& p ) { return signed_distance_to_line(line(l),p); } template <typename T, typename U> double distance_to_line ( const std::pair<vector<T,2>,vector<T,2> >& l, const vector<U,2>& p ) { return std::abs(signed_distance_to_line(l,p)); } template <typename U> double distance_to_line ( const line& l, const vector<U,2>& p ) { return std::abs(signed_distance_to_line(l,p)); } // ---------------------------------------------------------------------------------------- inline line reverse(const line& l) { return line(l.p2(), l.p1()); } // ---------------------------------------------------------------------------------------- template <typename T> inline dpoint intersect( const std::pair<vector<T,2>,vector<T,2>>& a, const std::pair<vector<T,2>,vector<T,2>>& b ) { // convert to homogeneous coordinates dlib::vector<double,3> a1 = a.first; dlib::vector<double,3> a2 = a.second; dlib::vector<double,3> b1 = b.first; dlib::vector<double,3> b2 = b.second; a1.z() = 1; a2.z() = 1; b1.z() = 1; b2.z() = 1; // find lines between pairs of points. auto l1 = a1.cross(a2); auto l2 = b1.cross(b2); // find intersection of the lines. auto p = l1.cross(l2); if (p.z() != 0) return p/p.z(); else return dpoint(std::numeric_limits<double>::infinity(), std::numeric_limits<double>::infinity()); } // ---------------------------------------------------------------------------------------- inline dpoint intersect( const line& a, const line& b ) { return intersect(std::make_pair(a.p1(),a.p2()), std::make_pair(b.p1(), b.p2())); } // ---------------------------------------------------------------------------------------- template <typename T> inline size_t count_points_on_side_of_line( line l, const dpoint& reference_point, const std::vector<vector<T,2>>& pts, const double& dist_thresh ) { if (signed_distance_to_line(l,reference_point) < 0) l = reverse(l); size_t cnt = 0; for (auto& p : pts) { double dist = signed_distance_to_line(l,p); if (0 <= dist && dist <= dist_thresh) ++cnt; } return cnt; } // ---------------------------------------------------------------------------------------- template <typename T> inline double count_points_between_lines( line l1, line l2, const dpoint& reference_point, const std::vector<vector<T,2>>& pts ) { if (signed_distance_to_line(l1,reference_point) < 0) l1 = reverse(l1); if (signed_distance_to_line(l2,reference_point) < 0) l2 = reverse(l2); size_t cnt = 0; for (auto& p : pts) { if (signed_distance_to_line(l1,p) > 0 && signed_distance_to_line(l2,p) > 0) ++cnt; } return cnt; } // ---------------------------------------------------------------------------------------- } #endif // DLIB_LInE_H_