Skip to content

Commit

Permalink
Fix numerical issue for segments sharing a common point
Browse files Browse the repository at this point in the history
  • Loading branch information
vissarion committed Feb 13, 2024
1 parent b9737c5 commit 68a225d
Show file tree
Hide file tree
Showing 8 changed files with 63 additions and 18 deletions.
8 changes: 8 additions & 0 deletions include/boost/geometry/policies/relate/direction.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -163,6 +163,14 @@ struct segments_direction
;
}

template <typename SegmentIntersectionInfo, typename Point>
static inline return_type segments_share_common_point(side_info const& sides,
SegmentIntersectionInfo const& ,
Point const&)
{
return segments_crosses(sides, sides, sides, sides);
}

template <typename Ratio>
static inline int arrival_value(Ratio const& r_from, Ratio const& r_to)
{
Expand Down
16 changes: 16 additions & 0 deletions include/boost/geometry/policies/relate/intersection_points.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
#include <algorithm>
#include <string>

#include <boost/geometry/algorithms/assign.hpp>
#include <boost/geometry/algorithms/detail/assign_indexed_point.hpp>
#include <boost/geometry/core/access.hpp>
#include <boost/geometry/core/assert.hpp>
Expand Down Expand Up @@ -61,6 +62,21 @@ struct segments_intersection_points
return result;
}

template<typename SegmentIntersectionInfo, typename Point>
static inline return_type
segments_share_common_point(side_info const&, SegmentIntersectionInfo const& sinfo,
Point const& p)
{
return_type result;
result.count = 1;
boost::geometry::assign(result.intersections[0], p);

// Temporary - this should go later
result.fractions[0].assign(sinfo);

return result;
}

template <typename Segment1, typename Segment2, typename Ratio>
static inline return_type segments_collinear(
Segment1 const& a, Segment2 const& b, bool /*opposite*/,
Expand Down
13 changes: 13 additions & 0 deletions include/boost/geometry/policies/relate/intersection_policy.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,19 @@ struct segments_intersection_policy
);
}

template <typename SegmentIntersectionInfo, typename Point>
static inline return_type
segments_share_common_point(side_info const& sides,
SegmentIntersectionInfo const& sinfo,
Point const& p)
{
return return_type
(
pts_policy::segments_share_common_point(sides, sinfo, p),
dir_policy::segments_share_common_point(sides, sinfo, p)
);
}

template <typename Segment1, typename Segment2, typename Ratio>
static inline return_type segments_collinear(
Segment1 const& segment1,
Expand Down
10 changes: 10 additions & 0 deletions include/boost/geometry/policies/relate/intersection_ratios.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,16 @@ struct segments_intersection_ratios
return result;
}

template<typename SegmentIntersectionInfo, typename Point>
static inline return_type
segments_share_common_point(side_info const&, SegmentIntersectionInfo const& sinfo,
Point const& p)
{
return_type result;
result.assign(sinfo);
return result;
}

template <typename Segment1, typename Segment2, typename Ratio>
static inline return_type segments_collinear(
Segment1 const& , Segment2 const& ,
Expand Down
11 changes: 11 additions & 0 deletions include/boost/geometry/strategies/cartesian/intersection.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -459,6 +459,7 @@ struct cartesian_segments

bool collinear = sides.collinear();

//TODO: remove this when rescaling is removed
// Calculate the differences again
// (for rescaled version, this is different from dx_p etc)
coordinate_type const dx_p = get<0>(p2) - get<0>(p1);
Expand Down Expand Up @@ -533,6 +534,16 @@ struct cartesian_segments
}
}

if (equals_point_point(p1, q1) || equals_point_point(p1, q2))
{
return Policy::segments_share_common_point(sides, sinfo, p1);
}

if (equals_point_point(p2, q1) || equals_point_point(p2, q2))
{
return Policy::segments_share_common_point(sides, sinfo, p2);
}

return Policy::segments_crosses(sides, sinfo, p, q);
}

Expand Down
8 changes: 1 addition & 7 deletions test/algorithms/is_simple.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -263,14 +263,8 @@ BOOST_AUTO_TEST_CASE( test_geometry_with_NaN_coordinates )
std::cout << "************************************" << std::endl;
#endif

linestring_type ls1, ls2;
bg::read_wkt("LINESTRING(1 1,1.115235e+308 1.738137e+308)", ls1);
bg::read_wkt("LINESTRING(-1 1,1.115235e+308 1.738137e+308)", ls2);

// the intersection of the two linestrings is a new linestring
// (multilinestring with a single element) that has NaN coordinates
multi_linestring_type mls;
bg::intersection(ls1, ls2, mls);
bg::read_wkt("MULTILINESTRING((nan nan))", mls);

test_simple(mls, true, false);
}
Expand Down
8 changes: 1 addition & 7 deletions test/algorithms/is_valid.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1433,14 +1433,8 @@ BOOST_AUTO_TEST_CASE( test_with_NaN_coordinates )
std::cout << "************************************" << std::endl;
#endif

linestring_type ls1, ls2;
bg::read_wkt("LINESTRING(1 1,1.115235e+308 1.738137e+308)", ls1);
bg::read_wkt("LINESTRING(-1 1,1.115235e+308 1.738137e+308)", ls2);

// the intersection of the two linestrings is a new linestring
// (multilinestring with a single element) that has NaN coordinates
multi_linestring_type mls;
bg::intersection(ls1, ls2, mls);
bg::read_wkt("MULTILINESTRING((nan nan))", mls);

typedef validity_tester_linear<true> tester_allow_spikes;
typedef validity_tester_linear<false> tester_disallow_spikes;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@
// Licensed under the Boost Software License version 1.0.
// http://www.boost.org/users/license.html


#include <iostream>

#ifndef BOOST_TEST_MODULE
Expand Down Expand Up @@ -1300,7 +1299,7 @@ BOOST_AUTO_TEST_CASE( test_intersection_ml_ml_degenerate )
// NOTE: if get_turn_info uses policy_verify_all then the result is different

#if BOOST_GEOMETRY_INTERSECTION_DO_NOT_INCLUDE_ISOLATED_POINTS
from_wkt<ML>("MULTILINESTRING((-0.7654 8.88178e-16,-0.7654 0,5 3))"),
from_wkt<ML>("MULTILINESTRING((-0.7654 0,5 3))"),
#else
from_wkt<ML>("MULTILINESTRING((-0.756651 3.30964),(1.60494 6),\
(2.51371 6),(3.26673 6),(4 6),(8.18862 3.07616),\
Expand Down Expand Up @@ -1337,7 +1336,7 @@ BOOST_AUTO_TEST_CASE( test_intersection_ml_ml_degenerate )
(8.5655 2.85228),(5.26567 4.81254),(4 3.8),\
(1.4995 3.27036),(0.591231 3.43401),\
(-0.706503 3.66784),\
(-0.7654 8.88178e-16,-0.7654 0,5 3))"),
(-0.7654 0,5 3))"),
from_wkt<ML>("MULTILINESTRING((1.87562 6.68515),(1.60494 6),\
(1.18124 4.9275),(1.00439 4.47984),(0.91526 4.25422),\
(0.729883 3.78498),(0.614728 3.49349),\
Expand Down Expand Up @@ -1368,7 +1367,7 @@ BOOST_AUTO_TEST_CASE( test_intersection_ml_ml_degenerate )
(9.98265 0.00543606),(9.09826 -100.515944),\
(7.08745 -329.0674155),(5.06428 -559.024344),\
(3.23365 -767.0972558),(3.16036 -775.427199),\
(-0.7654 8.88178e-16,-0.7654 0,5 3))"),
(-0.7654 0,5 3))"),
#endif // isolated
"mlmli21",
1e-4
Expand Down

0 comments on commit 68a225d

Please sign in to comment.