1 // Copyright (C) 2018  Davis E. King (davis@dlib.net)
2 // License: Boost Software License   See LICENSE.txt for the full license.
3 
4 #include "opaque_types.h"
5 #include <dlib/python.h>
6 #include <dlib/matrix.h>
7 #include <dlib/geometry/vector.h>
8 #include <pybind11/stl_bind.h>
9 #include "indexing.h"
10 
11 using namespace dlib;
12 using namespace std;
13 
14 
line__repr__(const line & p)15 string line__repr__ (const line& p)
16 {
17     std::ostringstream sout;
18     sout << "line(" << p.p1() << ", " << p.p2() << ")";
19     return sout.str();
20 }
21 
line__str__(const line & p)22 string line__str__(const line& p)
23 {
24     std::ostringstream sout;
25     sout << "(" << p.p1() << ", " << p.p2() << ")";
26     return sout.str();
27 }
28 
29 // ----------------------------------------------------------------------------------------
30 
bind_line(py::module & m)31 void bind_line(py::module& m)
32 {
33 
34     const char* class_docs =
35 "This object represents a line in the 2D plane.  The line is defined by two points \n\
36 running through it, p1 and p2.  This object also includes a unit normal vector that \n\
37 is perpendicular to the line.";
38 
39     py::class_<line>(m, "line", class_docs)
40         .def(py::init<>(), "p1, p2, and normal are all the 0 vector.")
41         .def(py::init<dpoint,dpoint>(), py::arg("a"), py::arg("b"),
42 "ensures \n\
43     - #p1 == a \n\
44     - #p2 == b \n\
45     - #normal == A vector normal to the line passing through points a and b. \n\
46       Therefore, the normal vector is the vector (a-b) but unit normalized and rotated clockwise 90 degrees."
47         /*!
48             ensures
49                 - #p1 == a
50                 - #p2 == b
51                 - #normal == A vector normal to the line passing through points a and b.
52                   Therefore, the normal vector is the vector (a-b) but unit normalized and rotated clockwise 90 degrees.
53         !*/
54             )
55         .def(py::init<point,point>(), py::arg("a"), py::arg("b"),
56 "ensures \n\
57     - #p1 == a \n\
58     - #p2 == b \n\
59     - #normal == A vector normal to the line passing through points a and b. \n\
60       Therefore, the normal vector is the vector (a-b) but unit normalized and rotated clockwise 90 degrees."
61         /*!
62             ensures
63                 - #p1 == a
64                 - #p2 == b
65                 - #normal == A vector normal to the line passing through points a and b.
66                   Therefore, the normal vector is the vector (a-b) but unit normalized and rotated clockwise 90 degrees.
67         !*/
68             )
69         .def_property_readonly("normal", &line::normal, "returns a unit vector that is normal to the line passing through p1 and p2.")
70         .def("__repr__", &line__repr__)
71         .def("__str__", &line__str__)
72         .def_property_readonly("p1", &line::p1, "returns the first endpoint of the line.")
73         .def_property_readonly("p2", &line::p2, "returns the second endpoint of the line.");
74 
75 
76     m.def("signed_distance_to_line", &signed_distance_to_line<long>, py::arg("l"), py::arg("p"));
77     m.def("signed_distance_to_line", &signed_distance_to_line<double>, py::arg("l"), py::arg("p"),
78 "ensures \n\
79     - returns how far p is from the line l.  This is a signed distance.  The sign \n\
80       indicates which side of the line the point is on and the magnitude is the \n\
81       distance. Moreover, the direction of positive sign is pointed to by the \n\
82       vector l.normal. \n\
83     - To be specific, this routine returns dot(p-l.p1, l.normal)"
84     /*!
85         ensures
86             - returns how far p is from the line l.  This is a signed distance.  The sign
87               indicates which side of the line the point is on and the magnitude is the
88               distance. Moreover, the direction of positive sign is pointed to by the
89               vector l.normal.
90             - To be specific, this routine returns dot(p-l.p1, l.normal)
91     !*/
92         );
93 
94     m.def("distance_to_line", &distance_to_line<long>, py::arg("l"), py::arg("p"));
95     m.def("distance_to_line", &distance_to_line<double>, py::arg("l"), py::arg("p"),
96        "returns abs(signed_distance_to_line(l,p))" );
97 
98     m.def("reverse", [](const line& a){return reverse(a);}, py::arg("l"),
99 "ensures \n\
100     - returns line(l.p2, l.p1) \n\
101       (i.e. returns a line object that represents the same line as l but with the \n\
102       endpoints, and therefore, the normal vector flipped.  This means that the \n\
103       signed distance of operator() is also flipped)."
104     /*!
105         ensures
106             - returns line(l.p2, l.p1)
107               (i.e. returns a line object that represents the same line as l but with the
108               endpoints, and therefore, the normal vector flipped.  This means that the
109               signed distance of operator() is also flipped).
110     !*/
111         );
112 
113     m.def("intersect", [](const line& a, const line& b){return intersect(a,b);}, py::arg("a"), py::arg("b"),
114 "ensures \n\
115     - returns the point of intersection between lines a and b.  If no such point \n\
116       exists then this function returns a point with Inf values in it."
117     /*!
118         ensures
119             - returns the point of intersection between lines a and b.  If no such point
120               exists then this function returns a point with Inf values in it.
121     !*/
122         );
123 
124     m.def("angle_between_lines", [](const line& a, const line& b){return angle_between_lines(a,b);}, py::arg("a"), py::arg("b"),
125 "ensures \n\
126     - returns the angle, in degrees, between the given lines.  This is a number in \n\
127       the range [0 90]."
128     /*!
129         ensures
130             - returns the angle, in degrees, between the given lines.  This is a number in
131               the range [0 90].
132     !*/
133         );
134 
135     m.def("count_points_on_side_of_line", &count_points_on_side_of_line<long>,
136         py::arg("l"), py::arg("reference_point"), py::arg("pts"), py::arg("dist_thresh_min")=0, py::arg("dist_thresh_max")=std::numeric_limits<double>::infinity());
137     m.def("count_points_on_side_of_line", &count_points_on_side_of_line<double>,
138         py::arg("l"), py::arg("reference_point"), py::arg("pts"), py::arg("dist_thresh_min")=0, py::arg("dist_thresh_max")=std::numeric_limits<double>::infinity(),
139 "ensures \n\
140     - Returns a count of how many points in pts have a distance from the line l \n\
141       that is in the range [dist_thresh_min, dist_thresh_max].  This distance is a \n\
142       signed value that indicates how far a point is from the line. Moreover, if \n\
143       the point is on the same side as reference_point then the distance is \n\
144       positive, otherwise it is negative.  So for example, If this range is [0, \n\
145       infinity] then this function counts how many points are on the same side of l \n\
146       as reference_point."
147     /*!
148         ensures
149             - Returns a count of how many points in pts have a distance from the line l
150               that is in the range [dist_thresh_min, dist_thresh_max].  This distance is a
151               signed value that indicates how far a point is from the line. Moreover, if
152               the point is on the same side as reference_point then the distance is
153               positive, otherwise it is negative.  So for example, If this range is [0,
154               infinity] then this function counts how many points are on the same side of l
155               as reference_point.
156     !*/
157         );
158 
159     m.def("count_points_between_lines", &count_points_between_lines<long>, py::arg("l1"), py::arg("l2"), py::arg("reference_point"), py::arg("pts"));
160     m.def("count_points_between_lines", &count_points_between_lines<double>, py::arg("l1"), py::arg("l2"), py::arg("reference_point"), py::arg("pts"),
161 "ensures \n\
162     - Counts and returns the number of points in pts that are between lines l1 and \n\
163       l2.  Since a pair of lines will, in the general case, divide the plane into 4 \n\
164       regions, we identify the region of interest as the one that contains the \n\
165       reference_point.  Therefore, this function counts the number of points in pts \n\
166       that appear in the same region as reference_point."
167     /*!
168         ensures
169             - Counts and returns the number of points in pts that are between lines l1 and
170               l2.  Since a pair of lines will, in the general case, divide the plane into 4
171               regions, we identify the region of interest as the one that contains the
172               reference_point.  Therefore, this function counts the number of points in pts
173               that appear in the same region as reference_point.
174     !*/
175         );
176 
177 
178 }
179 
180