|
15 | 15 | #include <boost/property_map/property_map.hpp> |
16 | 16 | #include <boost/graph/properties.hpp> |
17 | 17 | #include <boost/graph/planar_detail/bucket_sort.hpp> |
18 | | - |
19 | | -#include <boost/geometry/algorithms/crosses.hpp> |
20 | | -#include <boost/geometry/geometries/linestring.hpp> |
21 | | -#include <boost/geometry/core/coordinate_type.hpp> |
22 | | - |
| 18 | +#include <boost/multiprecision/cpp_int.hpp> |
23 | 19 | #include <boost/numeric/conversion/cast.hpp> |
24 | 20 |
|
25 | 21 | #include <algorithm> |
|
28 | 24 |
|
29 | 25 | namespace boost |
30 | 26 | { |
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) |
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)}}; |
| 27 | + |
| 28 | +template<typename Int128> |
| 29 | +int orientation2d(Int128 ax, Int128 ay, |
| 30 | + Int128 bx, Int128 by, |
| 31 | + Int128 cx, Int128 cy) { |
| 32 | + // If coordinates are in [0, 2^63], this will not overflow. |
| 33 | + const Int128 detleft = (bx - ax) * (cy - ay); |
| 34 | + const Int128 detright = (by - ay) * (cx - ax); |
| 35 | + return detleft > detright ? 1 : (detleft == detright ? 0 : -1); |
| 36 | +} |
| 37 | + |
| 38 | +template<typename Point> |
| 39 | +bool between(const Point& a, const Point& b, const Point& c) { |
| 40 | + return (b.y == a.y ? |
| 41 | + std::min(a.x, b.x) < c.x && c.x < std::max(a.x, b.x) |
| 42 | + : std::min(a.y, b.y) < c.y && c.y < std::max(a.y, b.y)); |
42 | 43 | } |
43 | 44 |
|
44 | | -// Overload of crosses from Boost.Geometry. |
| 45 | +// Crosses in the sense the e and f intersect but are not equal and the |
| 46 | +// intersection set is not a shared endpoint. |
45 | 47 | template<typename Graph, typename GridPositionMap> |
46 | 48 | bool crosses(typename graph_traits<Graph>::edge_descriptor e, |
47 | 49 | typename graph_traits<Graph>::edge_descriptor f, |
48 | 50 | Graph const &g, |
49 | 51 | GridPositionMap const &drawing) |
50 | 52 | { |
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)); |
| 53 | + const auto& p1 = drawing[source(e, g)]; |
| 54 | + const auto& p2 = drawing[target(e, g)]; |
| 55 | + const auto& q1 = drawing[source(f, g)]; |
| 56 | + const auto& q2 = drawing[target(f, g)]; |
| 57 | + |
| 58 | + using boost::multiprecision::int128_t; |
| 59 | + int o1 = orientation2d<int128_t>(p1.x, p1.y, p2.x, p2.y, q1.x, q1.y); |
| 60 | + int o2 = orientation2d<int128_t>(p1.x, p1.y, p2.x, p2.y, q2.x, q2.y); |
| 61 | + int o3 = orientation2d<int128_t>(q1.x, q1.y, q2.x, q2.y, p1.x, p1.y); |
| 62 | + int o4 = orientation2d<int128_t>(q1.x, q1.y, q2.x, q2.y, p2.x, p2.y); |
| 63 | + |
| 64 | + // X-like crossing of (p1, p2), (q1, q2) |
| 65 | + return ((o1 * o2 < 0) && (o3 * o4 < 0)) |
| 66 | + // T-like crossing, e.g. q1 in (p1, p2), or partial overlap |
| 67 | + || (o1 == 0 && between(p1, p2, q1)) |
| 68 | + || (o2 == 0 && between(p1, p2, q2)) |
| 69 | + || (o3 == 0 && between(q1, q2, p1)) |
| 70 | + || (o4 == 0 && between(q1, q2, p2)); |
57 | 71 | } |
58 | 72 |
|
59 | 73 | template < typename Graph, typename GridPositionMap, typename VertexIndexMap > |
|
0 commit comments