|
16 | 16 | #include <boost/graph/properties.hpp> |
17 | 17 | #include <boost/graph/planar_detail/bucket_sort.hpp> |
18 | 18 |
|
| 19 | +#include <boost/geometry/algorithms/crosses.hpp> |
| 20 | +#include <boost/geometry/geometries/linestring.hpp> |
| 21 | +#include <boost/geometry/core/coordinate_type.hpp> |
| 22 | + |
| 23 | +#include <boost/numeric/conversion/cast.hpp> |
| 24 | + |
19 | 25 | #include <algorithm> |
20 | 26 | #include <vector> |
21 | | -#include <set> |
22 | 27 | #include <map> |
23 | 28 |
|
24 | 29 | namespace boost |
25 | 30 | { |
26 | | - |
27 | | -// Return true exactly when the line segments s1 = ((x1,y1), (x2,y2)) and |
28 | | -// s2 = ((a1,b1), (a2,b2)) intersect in a point other than the endpoints of |
29 | | -// the line segments. The one exception to this rule is when s1 = s2, in |
30 | | -// which case false is returned - this is to accomodate multiple edges |
31 | | -// between the same pair of vertices, which shouldn't invalidate the straight |
32 | | -// line embedding. A tolerance variable epsilon can also be used, which |
33 | | -// defines how far away from the endpoints of s1 and s2 we want to consider |
34 | | -// an intersection. |
35 | | - |
36 | | -inline bool intersects(double x1, double y1, double x2, double y2, double a1, |
37 | | - double b1, double a2, double b2, double epsilon = 0.000001) |
| 31 | +// Overload of make from Boost.Geometry. |
| 32 | +template<typename Geometry, typename Graph, typename GridPositionMap> |
| 33 | +Geometry make(typename graph_traits<Graph>::edge_descriptor e, |
| 34 | + Graph const &g, |
| 35 | + GridPositionMap const &drawing) |
38 | 36 | { |
| 37 | + auto e_source(source(e, g)); |
| 38 | + auto e_target(target(e, g)); |
| 39 | + using Float = typename geometry::coordinate_type<Geometry>::type; |
| 40 | + return {{numeric_cast<Float>(drawing[e_source].x), numeric_cast<Float>(drawing[e_source].y)}, |
| 41 | + {numeric_cast<Float>(drawing[e_target].x), numeric_cast<Float>(drawing[e_target].y)}}; |
| 42 | +} |
39 | 43 |
|
40 | | - if (x1 - x2 == 0) |
41 | | - { |
42 | | - std::swap(x1, a1); |
43 | | - std::swap(y1, b1); |
44 | | - std::swap(x2, a2); |
45 | | - std::swap(y2, b2); |
46 | | - } |
47 | | - |
48 | | - if (x1 - x2 == 0) |
49 | | - { |
50 | | - BOOST_USING_STD_MAX(); |
51 | | - BOOST_USING_STD_MIN(); |
52 | | - |
53 | | - // two vertical line segments |
54 | | - double min_y = min BOOST_PREVENT_MACRO_SUBSTITUTION(y1, y2); |
55 | | - double max_y = max BOOST_PREVENT_MACRO_SUBSTITUTION(y1, y2); |
56 | | - double min_b = min BOOST_PREVENT_MACRO_SUBSTITUTION(b1, b2); |
57 | | - double max_b = max BOOST_PREVENT_MACRO_SUBSTITUTION(b1, b2); |
58 | | - if ((max_y > max_b && max_b > min_y) |
59 | | - || (max_b > max_y && max_y > min_b)) |
60 | | - return true; |
61 | | - else |
62 | | - return false; |
63 | | - } |
64 | | - |
65 | | - double x_diff = x1 - x2; |
66 | | - double y_diff = y1 - y2; |
67 | | - double a_diff = a2 - a1; |
68 | | - double b_diff = b2 - b1; |
69 | | - |
70 | | - double beta_denominator = b_diff - (y_diff / ((double)x_diff)) * a_diff; |
71 | | - |
72 | | - if (beta_denominator == 0) |
73 | | - { |
74 | | - // parallel lines |
75 | | - return false; |
76 | | - } |
77 | | - |
78 | | - double beta = (b2 - y2 - (y_diff / ((double)x_diff)) * (a2 - x2)) |
79 | | - / beta_denominator; |
80 | | - double alpha = (a2 - x2 - beta * (a_diff)) / x_diff; |
81 | | - |
82 | | - double upper_bound = 1 - epsilon; |
83 | | - double lower_bound = 0 + epsilon; |
84 | | - |
85 | | - return (beta < upper_bound && beta > lower_bound && alpha < upper_bound |
86 | | - && alpha > lower_bound); |
| 44 | +// Overload of crosses from Boost.Geometry. |
| 45 | +template<typename Graph, typename GridPositionMap> |
| 46 | +bool crosses(typename graph_traits<Graph>::edge_descriptor e, |
| 47 | + typename graph_traits<Graph>::edge_descriptor f, |
| 48 | + Graph const &g, |
| 49 | + GridPositionMap const &drawing) |
| 50 | +{ |
| 51 | + using geometry::crosses; |
| 52 | + using geometry::model::linestring; |
| 53 | + using geometry::model::d2::point_xy; |
| 54 | + using linestring2d = geometry::model::linestring<geometry::model::d2::point_xy<double>>; |
| 55 | + return crosses(make<linestring2d>(e, g, drawing), |
| 56 | + make<linestring2d>(f, g, drawing)); |
87 | 57 | } |
88 | 58 |
|
89 | 59 | template < typename Graph, typename GridPositionMap, typename VertexIndexMap > |
@@ -161,33 +131,15 @@ bool is_straight_line_drawing( |
161 | 131 |
|
162 | 132 | if (before != active_edges.end()) |
163 | 133 | { |
164 | | - |
165 | 134 | edge_t f = before->second; |
166 | | - vertex_t e_source(source(e, g)); |
167 | | - vertex_t e_target(target(e, g)); |
168 | | - vertex_t f_source(source(f, g)); |
169 | | - vertex_t f_target(target(f, g)); |
170 | | - |
171 | | - if (intersects(drawing[e_source].x, drawing[e_source].y, |
172 | | - drawing[e_target].x, drawing[e_target].y, |
173 | | - drawing[f_source].x, drawing[f_source].y, |
174 | | - drawing[f_target].x, drawing[f_target].y)) |
| 135 | + if (crosses(e, f, g, drawing)) |
175 | 136 | return false; |
176 | 137 | } |
177 | 138 |
|
178 | 139 | if (after != active_edges.end()) |
179 | 140 | { |
180 | | - |
181 | 141 | edge_t f = after->second; |
182 | | - vertex_t e_source(source(e, g)); |
183 | | - vertex_t e_target(target(e, g)); |
184 | | - vertex_t f_source(source(f, g)); |
185 | | - vertex_t f_target(target(f, g)); |
186 | | - |
187 | | - if (intersects(drawing[e_source].x, drawing[e_source].y, |
188 | | - drawing[e_target].x, drawing[e_target].y, |
189 | | - drawing[f_source].x, drawing[f_source].y, |
190 | | - drawing[f_target].x, drawing[f_target].y)) |
| 142 | + if (crosses(e, f, g, drawing)) |
191 | 143 | return false; |
192 | 144 | } |
193 | 145 |
|
|
0 commit comments