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