Skip to content

Commit ac16714

Browse files
committed
Add robust, integer crosses check instead of relying on Boost.Geometry in is_straight_line_drawing.hpp.
1 parent 0cdf8dd commit ac16714

File tree

3 files changed

+39
-23
lines changed

3 files changed

+39
-23
lines changed

CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@ target_link_libraries(boost_graph
3737
Boost::move
3838
Boost::mpl
3939
Boost::multi_index
40+
Boost::multiprecision
4041
Boost::optional
4142
Boost::parameter
4243
Boost::preprocessor

build.jam

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@ constant boost_dependencies :
2727
/boost/move//boost_move
2828
/boost/mpl//boost_mpl
2929
/boost/multi_index//boost_multi_index
30+
/boost/multiprecision//boost_multiprecision
3031
/boost/optional//boost_optional
3132
/boost/parameter//boost_parameter
3233
/boost/preprocessor//boost_preprocessor

include/boost/graph/is_straight_line_drawing.hpp

Lines changed: 37 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -15,11 +15,7 @@
1515
#include <boost/property_map/property_map.hpp>
1616
#include <boost/graph/properties.hpp>
1717
#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>
2319
#include <boost/numeric/conversion/cast.hpp>
2420

2521
#include <algorithm>
@@ -28,32 +24,50 @@
2824

2925
namespace boost
3026
{
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));
4243
}
4344

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.
4547
template<typename Graph, typename GridPositionMap>
4648
bool crosses(typename graph_traits<Graph>::edge_descriptor e,
4749
typename graph_traits<Graph>::edge_descriptor f,
4850
Graph const &g,
4951
GridPositionMap const &drawing)
5052
{
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));
5771
}
5872

5973
template < typename Graph, typename GridPositionMap, typename VertexIndexMap >

0 commit comments

Comments
 (0)