mirror of
https://github.com/boostorg/geometry.git
synced 2026-02-13 00:22:10 +00:00
Merge branch 'develop' of https://github.com/boostorg/geometry into feature/is_simple
This commit is contained in:
@@ -21,6 +21,13 @@ def run_command(command):
|
||||
if os.system(command) != 0:
|
||||
raise Exception("Error running %s" % command)
|
||||
|
||||
def remove_all_files(dir):
|
||||
if os.path.exists(dir):
|
||||
for f in os.listdir(dir):
|
||||
os.remove(dir+f)
|
||||
|
||||
remove_all_files("xml/")
|
||||
|
||||
run_command("doxygen Doxyfile")
|
||||
run_command(cmd % ("classboost_1_1geometry_1_1index_1_1rtree", "rtree"))
|
||||
run_command(cmd % ("group__rtree__functions", "rtree_functions"))
|
||||
|
||||
@@ -17,8 +17,10 @@ exe interprocess : interprocess.cpp /boost/thread//boost_thread
|
||||
:
|
||||
<toolset>acc:<linkflags>-lrt
|
||||
<toolset>acc-pa_risc:<linkflags>-lrt
|
||||
<toolset>gcc-mingw:<linkflags>"-lole32 -loleaut32 -lpsapi -ladvapi32"
|
||||
<host-os>hpux,<toolset>gcc:<linkflags>"-Wl,+as,mpas"
|
||||
# <toolset>gcc-mingw:<linkflags>"-lole32 -loleaut32 -lpsapi -ladvapi32"
|
||||
<toolset>gcc,<target-os>windows:<linkflags>"-lole32 -loleaut32 -lpsapi -ladvapi32"
|
||||
<host-os>windows,<toolset>clang:<linkflags>"-lole32 -loleaut32 -lpsapi -ladvapi32"
|
||||
:
|
||||
<threading>multi
|
||||
: # requirements
|
||||
|
||||
@@ -40,9 +40,14 @@ def run_command(command):
|
||||
if os.system(command) != 0:
|
||||
raise Exception("Error running %s" % command)
|
||||
|
||||
def remove_all_files(dir):
|
||||
if os.path.exists(dir):
|
||||
for f in os.listdir(dir):
|
||||
os.remove(dir+f)
|
||||
|
||||
def call_doxygen():
|
||||
os.chdir("doxy");
|
||||
run_command("rm -f doxygen_output/xml/*.xml")
|
||||
os.chdir("doxy")
|
||||
remove_all_files("doxygen_output/xml/")
|
||||
run_command(doxygen_cmd)
|
||||
os.chdir("..")
|
||||
|
||||
|
||||
@@ -1,7 +1,12 @@
|
||||
[/============================================================================
|
||||
Boost.Geometry (aka GGL, Generic Geometry Library)
|
||||
|
||||
Copyright (c) 2011-2012 Barend Gehrels, Amsterdam, the Netherlands.
|
||||
Copyright (c) 2011-2014 Barend Gehrels, Amsterdam, the Netherlands.
|
||||
|
||||
This file was modified by Oracle on 2014.
|
||||
Modifications copyright (c) 2014, Oracle and/or its affiliates.
|
||||
|
||||
Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle
|
||||
|
||||
Use, modification and distribution is subject to the Boost Software License,
|
||||
Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
|
||||
@@ -14,6 +19,8 @@
|
||||
[[__2dim__][All combinations of: box, ring, polygon, multi_polygon]]
|
||||
[[__1dim__ / __2dim__][A combinations of a (multi) linestring with a (multi) polygon
|
||||
results in a collection of linestrings]]
|
||||
[[__1dim__][All combinations of: linestring, multi_linestring; results in a collection of linestrings]]
|
||||
[[__0dim__][All combinations of: point, multi_point; results in a collection of points]]
|
||||
[[__other__][__nyiversion__]]
|
||||
[[__sph__][__nyiversion__]]
|
||||
[[Three dimensional][__nyiversion__]]
|
||||
|
||||
@@ -27,11 +27,15 @@
|
||||
* [@https://svn.boost.org/trac/boost/ticket/9245 9245] Check for process errors in make_qbk.py
|
||||
* [@https://svn.boost.org/trac/boost/ticket/9081 9081] Booleans create self-intersecting polygons from non-self-intersecting polygons
|
||||
* [@https://svn.boost.org/trac/boost/ticket/8310 8310] Wrong results with overlapping polygons (fixed using point_on_surface for disjoint)
|
||||
* [@https://svn.boost.org/trac/boost/ticket/9871 9871] Remove spike in polygon with only a spike
|
||||
|
||||
[*Bugfixes]
|
||||
|
||||
* intersects(polygon) could return a self-intersection-point for its closing point, fixed
|
||||
|
||||
[*Solved tickets]
|
||||
|
||||
* [@https://svn.boost.org/trac/boost/ticket/9563 9563] (Sym)difference not successful, fixed by rescaling to robust type
|
||||
|
||||
[/=================]
|
||||
[heading Boost 1.55]
|
||||
|
||||
@@ -281,13 +281,18 @@ void test_all()
|
||||
test_one<multi_polygon_type, buf::join_round, buf::end_skip, polygon_type>("rt_d", rt_d, 18.8726, 0.3);
|
||||
test_one<multi_polygon_type, buf::join_miter, buf::end_skip, polygon_type>("rt_d", rt_d, 19.8823, 0.3);
|
||||
test_one<multi_polygon_type, buf::join_round, buf::end_skip, polygon_type>("rt_e", rt_e, 14.1866, 0.3);
|
||||
#if ! defined(BOOST_GEOMETRY_RESCALE_TO_ROBUST)
|
||||
test_one<multi_polygon_type, buf::join_miter, buf::end_skip, polygon_type>("rt_e", rt_e, 15.1198, 0.3);
|
||||
// This does not add anything: test_one<multi_polygon_type, buf::join_round, buf::end_skip, polygon_type>("rt_f", rt_f, 4.28937, 0.3);
|
||||
|
||||
test_one<multi_polygon_type, buf::join_miter, buf::end_skip, polygon_type>("rt_f", rt_f, 4.60853, 0.3);
|
||||
#endif
|
||||
|
||||
test_one<multi_polygon_type, buf::join_round, buf::end_skip, polygon_type>("rt_g1", rt_g1, 24.719, 1.0);
|
||||
#if ! defined(BOOST_GEOMETRY_RESCALE_TO_ROBUST)
|
||||
test_one<multi_polygon_type, buf::join_miter, buf::end_skip, polygon_type>("rt_g1", rt_g1, 30.3137, 1.0);
|
||||
test_one<multi_polygon_type, buf::join_miter, buf::end_skip, polygon_type>("rt_g2", rt_g2, 18.5711, 1.0);
|
||||
#endif
|
||||
test_one<multi_polygon_type, buf::join_miter, buf::end_skip, polygon_type>("rt_g3", rt_g3, 16.5711, 1.0);
|
||||
|
||||
test_one<multi_polygon_type, buf::join_round, buf::end_skip, polygon_type>("rt_h", rt_h, 47.6012, 1.0);
|
||||
@@ -299,13 +304,17 @@ void test_all()
|
||||
test_one<multi_polygon_type, buf::join_round, buf::end_skip, polygon_type>("rt_k", rt_k, 42.0092, 1.0);
|
||||
test_one<multi_polygon_type, buf::join_miter, buf::end_skip, polygon_type>("rt_k", rt_k, 48.0563, 1.0);
|
||||
// This does not add anything: test_one<multi_polygon_type, buf::join_round, buf::end_skip, polygon_type>("rt_l", rt_l, 14.1074, 1.0);
|
||||
#if ! defined(BOOST_GEOMETRY_RESCALE_TO_ROBUST)
|
||||
test_one<multi_polygon_type, buf::join_miter, buf::end_skip, polygon_type>("rt_l", rt_l, 19.3995, 1.0);
|
||||
#endif
|
||||
test_one<multi_polygon_type, buf::join_round, buf::end_skip, polygon_type>("rt_m1", rt_m1, 14.1074, 1.0);
|
||||
#if ! defined(BOOST_GEOMETRY_RESCALE_TO_ROBUST)
|
||||
test_one<multi_polygon_type, buf::join_miter, buf::end_skip, polygon_type>("rt_m1", rt_m1, 19.4853, 1.0);
|
||||
test_one<multi_polygon_type, buf::join_miter, buf::end_skip, polygon_type>("rt_m2", rt_m2, 21.4853, 1.0);
|
||||
|
||||
// This does not add anything: test_one<multi_polygon_type, buf::join_round, buf::end_skip, polygon_type>("rt_n", rt_n, 14.1074, 1.0);
|
||||
test_one<multi_polygon_type, buf::join_miter, buf::end_skip, polygon_type>("rt_n", rt_n, 18.4853, 1.0);
|
||||
#endif
|
||||
|
||||
test_one<multi_polygon_type, buf::join_round, buf::end_skip, polygon_type>("rt_o1", rt_o1, 17.536, 1.0);
|
||||
test_one<multi_polygon_type, buf::join_miter, buf::end_skip, polygon_type>("rt_o1", rt_o1, 20.9142, 1.0);
|
||||
@@ -323,7 +332,10 @@ void test_all()
|
||||
test_one<multi_polygon_type, buf::join_miter, buf::end_skip, polygon_type>("rt_p7", rt_p7, 26.2279, 1.0);
|
||||
test_one<multi_polygon_type, buf::join_miter, buf::end_skip, polygon_type>("rt_p8", rt_p8, 29.0563, 1.0);
|
||||
test_one<multi_polygon_type, buf::join_miter, buf::end_skip, polygon_type>("rt_p9", rt_p9, 26.1421, 1.0);
|
||||
#if ! defined(BOOST_GEOMETRY_RESCALE_TO_ROBUST)
|
||||
test_one<multi_polygon_type, buf::join_miter, buf::end_skip, polygon_type>("rt_p10", rt_p10, 23.3995, 1.0);
|
||||
#endif
|
||||
|
||||
test_one<multi_polygon_type, buf::join_miter, buf::end_skip, polygon_type>("rt_p11", rt_p11, 28.7426, 1.0);
|
||||
test_one<multi_polygon_type, buf::join_miter, buf::end_skip, polygon_type>("rt_p12", rt_p12, 22.5711, 1.0);
|
||||
test_one<multi_polygon_type, buf::join_miter, buf::end_skip, polygon_type>("rt_p13", rt_p13, 19.9142, 1.0);
|
||||
@@ -340,10 +352,14 @@ void test_all()
|
||||
test_one<multi_polygon_type, buf::join_miter, buf::end_skip, polygon_type>("rt_q1", rt_q1, 27, 1.0);
|
||||
test_one<multi_polygon_type, buf::join_miter, buf::end_skip, polygon_type>("rt_q2", rt_q2, 26.4853, 1.0);
|
||||
|
||||
#if ! defined(BOOST_GEOMETRY_RESCALE_TO_ROBUST)
|
||||
test_one<multi_polygon_type, buf::join_miter, buf::end_skip, polygon_type>("rt_r", rt_r, 21.0761, 1.0);
|
||||
#endif
|
||||
test_one<multi_polygon_type, buf::join_miter, buf::end_skip, polygon_type>("rt_s1", rt_s1, 20.4853, 1.0);
|
||||
test_one<multi_polygon_type, buf::join_miter, buf::end_skip, polygon_type>("rt_s2", rt_s2, 24.6495, 1.0);
|
||||
#if ! defined(BOOST_GEOMETRY_RESCALE_TO_ROBUST)
|
||||
test_one<multi_polygon_type, buf::join_miter, buf::end_skip, polygon_type>("rt_t", rt_t, 15.6569, 1.0);
|
||||
#endif
|
||||
|
||||
|
||||
}
|
||||
|
||||
@@ -138,9 +138,13 @@ void test_all()
|
||||
test_one<polygon_type, buf::join_round, buf::end_skip, polygon_type>("tipped_aitch9", tipped_aitch, 76.6457, 0.9);
|
||||
test_one<polygon_type, buf::join_round, buf::end_skip, polygon_type>("tipped_aitch13", tipped_aitch, 90.641, 1.3);
|
||||
|
||||
#if ! defined(BOOST_GEOMETRY_RESCALE_TO_ROBUST)
|
||||
test_one<polygon_type, buf::join_miter, buf::end_skip, polygon_type>("snake4", snake, 64.44, 0.4);
|
||||
#endif
|
||||
test_one<polygon_type, buf::join_miter, buf::end_skip, polygon_type>("snake5", snake, 72, 0.5);
|
||||
#if ! defined(BOOST_GEOMETRY_RESCALE_TO_ROBUST)
|
||||
test_one<polygon_type, buf::join_miter, buf::end_skip, polygon_type>("snake6", snake, 75.44, 0.6);
|
||||
#endif
|
||||
test_one<polygon_type, buf::join_miter, buf::end_skip, polygon_type>("snake16", snake, 114.24, 1.6);
|
||||
|
||||
test_one<polygon_type, buf::join_miter, buf::end_skip, polygon_type>("funnelgate2", funnelgate, 120.982, 2);
|
||||
@@ -347,4 +351,4 @@ select
|
||||
from bowl
|
||||
|
||||
|
||||
*/
|
||||
*/
|
||||
|
||||
@@ -53,12 +53,14 @@
|
||||
|
||||
#if defined(TEST_WITH_SVG)
|
||||
#include <boost/geometry/algorithms/detail/overlay/self_turn_points.hpp>
|
||||
template <typename Geometry, typename Mapper>
|
||||
void post_map(Geometry const& geometry, Mapper& mapper)
|
||||
template <typename Geometry, typename Mapper, typename RescalePolicy>
|
||||
void post_map(Geometry const& geometry, Mapper& mapper, RescalePolicy const& rescale_policy)
|
||||
{
|
||||
typedef typename bg::point_type<Geometry>::type point_type;
|
||||
typedef bg::detail::overlay::turn_info
|
||||
<
|
||||
typename bg::point_type<Geometry>::type
|
||||
point_type,
|
||||
typename bg::segment_ratio_type<point_type, RescalePolicy>::type
|
||||
> turn_info;
|
||||
|
||||
std::vector<turn_info> turns;
|
||||
@@ -67,7 +69,7 @@ void post_map(Geometry const& geometry, Mapper& mapper)
|
||||
bg::self_turns
|
||||
<
|
||||
bg::detail::overlay::assign_null_policy
|
||||
>(geometry, turns, policy);
|
||||
>(geometry, rescale_policy, turns, policy);
|
||||
|
||||
BOOST_FOREACH(turn_info const& turn, turns)
|
||||
{
|
||||
@@ -218,12 +220,20 @@ void test_buffer(std::string const& caseid, Geometry const& geometry,
|
||||
>
|
||||
distance_strategy(distance_left, distance_right);
|
||||
|
||||
typedef typename bg::point_type<Geometry>::type point_type;
|
||||
typedef typename bg::rescale_policy_type<point_type>::type
|
||||
rescale_policy_type;
|
||||
|
||||
rescale_policy_type rescale_policy
|
||||
= bg::get_rescale_policy<rescale_policy_type>(geometry);
|
||||
|
||||
std::vector<GeometryOut> buffered;
|
||||
|
||||
bg::buffer_inserter<GeometryOut>(geometry, std::back_inserter(buffered),
|
||||
distance_strategy,
|
||||
join_strategy,
|
||||
end_strategy
|
||||
end_strategy,
|
||||
rescale_policy
|
||||
#ifdef BOOST_GEOMETRY_DEBUG_WITH_MAPPER
|
||||
, mapper
|
||||
#endif
|
||||
@@ -299,7 +309,7 @@ void test_buffer(std::string const& caseid, Geometry const& geometry,
|
||||
{
|
||||
mapper.map(polygon, "opacity:0.4;fill:rgb(255,255,128);stroke:rgb(0,0,0);stroke-width:3");
|
||||
//mapper.map(polygon, "opacity:0.2;fill:none;stroke:rgb(255,0,0);stroke-width:3");
|
||||
post_map(polygon, mapper);
|
||||
post_map(polygon, mapper, rescale_policy);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
64
include/boost/geometry/algorithms/detail/get_max_size.hpp
Normal file
64
include/boost/geometry/algorithms/detail/get_max_size.hpp
Normal file
@@ -0,0 +1,64 @@
|
||||
// Boost.Geometry (aka GGL, Generic Geometry Library)
|
||||
|
||||
// Copyright (c) 2014 Barend Gehrels, Amsterdam, the Netherlands.
|
||||
// Copyright (c) 2014 Bruno Lalande, Paris, France.
|
||||
// Copyright (c) 2014 Mateusz Loskot, London, UK.
|
||||
// Copyright (c) 2014 Adam Wulkiewicz, Lodz, Poland.
|
||||
|
||||
// Use, modification and distribution is subject to the Boost Software License,
|
||||
// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
|
||||
// http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_GET_MAX_SIZE_HPP
|
||||
#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_GET_MAX_SIZE_HPP
|
||||
|
||||
|
||||
#include <cstddef>
|
||||
|
||||
#include <boost/geometry/core/access.hpp>
|
||||
#include <boost/geometry/util/math.hpp>
|
||||
|
||||
namespace boost { namespace geometry
|
||||
{
|
||||
|
||||
#ifndef DOXYGEN_NO_DETAIL
|
||||
namespace detail
|
||||
{
|
||||
|
||||
template <typename Box, std::size_t Dimension>
|
||||
struct get_max_size_box
|
||||
{
|
||||
static inline typename coordinate_type<Box>::type apply(Box const& box)
|
||||
{
|
||||
typename coordinate_type<Box>::type s
|
||||
= geometry::math::abs(geometry::get<1, Dimension>(box) - geometry::get<0, Dimension>(box));
|
||||
|
||||
return (std::max)(s, get_max_size_box<Box, Dimension - 1>::apply(box));
|
||||
}
|
||||
};
|
||||
|
||||
template <typename Box>
|
||||
struct get_max_size_box<Box, 0>
|
||||
{
|
||||
static inline typename coordinate_type<Box>::type apply(Box const& box)
|
||||
{
|
||||
return geometry::math::abs(geometry::get<1, 0>(box) - geometry::get<0, 0>(box));
|
||||
}
|
||||
};
|
||||
|
||||
// This might be implemented later on for other geometries too.
|
||||
// Not dispatched yet.
|
||||
template <typename Box>
|
||||
inline typename coordinate_type<Box>::type get_max_size(Box const& box)
|
||||
{
|
||||
return get_max_size_box<Box, dimension<Box>::value - 1>::apply(box);
|
||||
}
|
||||
|
||||
} // namespace detail
|
||||
#endif // DOXYGEN_NO_DETAIL
|
||||
|
||||
|
||||
}} // namespace boost::geometry
|
||||
|
||||
|
||||
#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_GET_MAX_SIZE_HPP
|
||||
@@ -16,7 +16,10 @@
|
||||
#include <boost/geometry/algorithms/detail/overlay/turn_info.hpp>
|
||||
#include <boost/geometry/algorithms/detail/overlay/get_turns.hpp>
|
||||
#include <boost/geometry/algorithms/detail/overlay/self_turn_points.hpp>
|
||||
#include <boost/geometry/algorithms/detail/rescale.hpp>
|
||||
|
||||
#include <boost/geometry/policies/robustness/robust_point_type.hpp>
|
||||
#include <boost/geometry/policies/robustness/segment_ratio_type.hpp>
|
||||
#include <boost/geometry/policies/robustness/get_rescale_policy.hpp>
|
||||
|
||||
#include <boost/geometry/multi/algorithms/detail/overlay/self_turn_points.hpp>
|
||||
|
||||
@@ -57,15 +60,19 @@ namespace detail { namespace overlay
|
||||
{
|
||||
|
||||
|
||||
template <typename Geometry, typename RescalePolicy>
|
||||
inline bool has_self_intersections(Geometry const& geometry, RescalePolicy const& rescale_policy)
|
||||
template <typename Geometry, typename RobustPolicy>
|
||||
inline bool has_self_intersections(Geometry const& geometry, RobustPolicy const& robust_policy)
|
||||
{
|
||||
typedef typename point_type<Geometry>::type point_type;
|
||||
typedef detail::overlay::turn_info<point_type> turn_info;
|
||||
typedef turn_info
|
||||
<
|
||||
point_type,
|
||||
typename segment_ratio_type<point_type, RobustPolicy>::type
|
||||
> turn_info;
|
||||
std::deque<turn_info> turns;
|
||||
detail::disjoint::disjoint_interrupt_policy policy;
|
||||
|
||||
geometry::self_turns<detail::overlay::assign_null_policy>(geometry, rescale_policy, turns, policy);
|
||||
geometry::self_turns<detail::overlay::assign_null_policy>(geometry, robust_policy, turns, policy);
|
||||
|
||||
#ifdef BOOST_GEOMETRY_DEBUG_HAS_SELF_INTERSECTIONS
|
||||
bool first = true;
|
||||
@@ -115,7 +122,14 @@ inline bool has_self_intersections(Geometry const& geometry, RescalePolicy const
|
||||
template <typename Geometry>
|
||||
inline bool has_self_intersections(Geometry const& geometry)
|
||||
{
|
||||
return has_self_intersections(geometry, detail::no_rescale_policy());
|
||||
typedef typename geometry::point_type<Geometry>::type point_type;
|
||||
typedef typename geometry::rescale_policy_type<point_type>::type
|
||||
rescale_policy_type;
|
||||
|
||||
rescale_policy_type robust_policy
|
||||
= geometry::get_rescale_policy<rescale_policy_type>(geometry);
|
||||
|
||||
return has_self_intersections(geometry, robust_policy);
|
||||
}
|
||||
|
||||
|
||||
|
||||
128
include/boost/geometry/algorithms/detail/intersection_side.hpp
Normal file
128
include/boost/geometry/algorithms/detail/intersection_side.hpp
Normal file
@@ -0,0 +1,128 @@
|
||||
// Boost.Geometry (aka GGL, Generic Geometry Library)
|
||||
|
||||
// Copyright (c) 2011-2014 Barend Gehrels, Amsterdam, the Netherlands.
|
||||
|
||||
// Use, modification and distribution is subject to the Boost Software License,
|
||||
// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
|
||||
// http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_INTERSECTION_SIDE_HPP
|
||||
#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_INTERSECTION_SIDE_HPP
|
||||
|
||||
#include <boost/geometry/algorithms/detail/recalculate.hpp>
|
||||
#include <boost/geometry/algorithms/detail/assign_indexed_point.hpp>
|
||||
#include <boost/geometry/geometries/segment.hpp>
|
||||
#include <boost/geometry/strategies/intersection_result.hpp>
|
||||
#include <boost/geometry/strategies/side.hpp>
|
||||
#include <boost/geometry/strategies/cartesian/cart_intersect.hpp>
|
||||
#include <boost/geometry/policies/robustness/segment_ratio_type.hpp>
|
||||
|
||||
namespace boost { namespace geometry
|
||||
{
|
||||
|
||||
namespace detail { namespace intersection_side
|
||||
{
|
||||
|
||||
|
||||
//! Calculates the side (left=1,right=-1,collinear=0) of the intersection point
|
||||
//! of p/q (if any) with respect to segment s.
|
||||
//! This is not done by calculating IP p/q and calling side, because that is
|
||||
//! (even if robust_policy is used) not robust: the IP can be rounded off.
|
||||
//! So it is done by investigating the sides of the segments, and calculating
|
||||
//! the segment_ratios of the IP and check which side it is.
|
||||
//! Return value is conform geometry::side
|
||||
//! Currently all points are of same type
|
||||
//! Even if there is no IP at all, a side is returned. IP is not calculated on
|
||||
//! itself
|
||||
template <typename Point, typename RobustPolicy>
|
||||
inline int intersection_side(Point const& pi, Point const& pj,
|
||||
Point const& qi, Point const& qj,
|
||||
Point const& si, Point const& sj,
|
||||
RobustPolicy const& robust_policy)
|
||||
{
|
||||
typedef typename geometry::robust_point_type
|
||||
<
|
||||
Point,
|
||||
RobustPolicy
|
||||
>::type robust_point_type;
|
||||
typedef typename geometry::segment_ratio_type
|
||||
<
|
||||
Point,
|
||||
RobustPolicy
|
||||
>::type segment_ratio_type;
|
||||
|
||||
robust_point_type pi_rob, pj_rob, qi_rob, qj_rob, si_rob, sj_rob;
|
||||
geometry::recalculate(pi_rob, pi, robust_policy);
|
||||
geometry::recalculate(pj_rob, pj, robust_policy);
|
||||
geometry::recalculate(qi_rob, qi, robust_policy);
|
||||
geometry::recalculate(qj_rob, qj, robust_policy);
|
||||
geometry::recalculate(si_rob, si, robust_policy);
|
||||
geometry::recalculate(sj_rob, sj, robust_policy);
|
||||
|
||||
typedef typename geometry::strategy::side::services::default_strategy
|
||||
<
|
||||
typename geometry::cs_tag<robust_point_type>::type
|
||||
>::type side_strategy;
|
||||
|
||||
int const side_pi = side_strategy::apply(pi_rob, si_rob, sj_rob);
|
||||
int const side_pj = side_strategy::apply(pj_rob, si_rob, sj_rob);
|
||||
if (side_pi == side_pj)
|
||||
{
|
||||
return side_pi;
|
||||
}
|
||||
|
||||
int const side_qi = side_strategy::apply(qi_rob, si_rob, sj_rob);
|
||||
int const side_qj = side_strategy::apply(qj_rob, si_rob, sj_rob);
|
||||
if (side_qi == side_qj)
|
||||
{
|
||||
// Same here, see comment above
|
||||
return side_qi;
|
||||
}
|
||||
|
||||
typedef model::referring_segment<const Point> segment_type;
|
||||
|
||||
segment_type p(pi, pj);
|
||||
segment_type q(qi, qj);
|
||||
segment_type s(si, sj);
|
||||
|
||||
// No segment lies on the left or right or completely collinear
|
||||
// Relate segments p // q and p // s, don't calculate IP's but just return
|
||||
// the ratios. Both ratios called "robust_ra" are measured on p and can be
|
||||
// related.
|
||||
fraction_type<segment_ratio_type> ratio_p_wrt_q
|
||||
= strategy::intersection::relate_cartesian_segments
|
||||
<
|
||||
policies::relate::segments_intersection_ratios
|
||||
<
|
||||
fraction_type<segment_ratio_type>
|
||||
>
|
||||
>::apply(p, q, robust_policy, pi_rob, pj_rob, qi_rob, qj_rob);
|
||||
|
||||
fraction_type<segment_ratio_type> ratio_p_wrt_s
|
||||
= strategy::intersection::relate_cartesian_segments
|
||||
<
|
||||
policies::relate::segments_intersection_ratios
|
||||
<
|
||||
fraction_type<segment_ratio_type>
|
||||
>
|
||||
>::apply(p, s, robust_policy, pi_rob, pj_rob, si_rob, sj_rob);
|
||||
|
||||
return
|
||||
|
||||
// Closer to the segment start point of p -> side of pi
|
||||
ratio_p_wrt_q.robust_ra < ratio_p_wrt_s.robust_ra ? side_pi
|
||||
|
||||
// Ratios are equal, IP must be exactly on the segment
|
||||
: ratio_p_wrt_q.robust_ra == ratio_p_wrt_s.robust_ra ? 0
|
||||
|
||||
// ratio p wrt q is larger than ratio p wrt s
|
||||
// So: close to the segment end point of p -> side of pj
|
||||
: side_pj;
|
||||
}
|
||||
|
||||
|
||||
}} // namespace detail::intersection_side
|
||||
|
||||
}} // namespace boost::geometry
|
||||
|
||||
#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_INTERSECTION_SIDE_HPP
|
||||
@@ -24,35 +24,118 @@ namespace boost { namespace geometry
|
||||
namespace detail { namespace overlay
|
||||
{
|
||||
|
||||
template <typename Range, typename Point>
|
||||
inline void append_no_dups_or_spikes(Range& range, Point const& point)
|
||||
// TODO: move this / rename this
|
||||
template <typename Point1, typename Point2, typename RobustPolicy>
|
||||
inline bool points_equal_or_close(Point1 const& point1,
|
||||
Point2 const& point2,
|
||||
RobustPolicy const& robust_policy)
|
||||
{
|
||||
if (detail::equals::equals_point_point(point1, point2))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
if (! RobustPolicy::enabled)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
// Try using specified robust policy
|
||||
typedef typename geometry::robust_point_type
|
||||
<
|
||||
Point1,
|
||||
RobustPolicy
|
||||
>::type robust_point_type;
|
||||
|
||||
robust_point_type point1_rob, point2_rob;
|
||||
geometry::recalculate(point1_rob, point1, robust_policy);
|
||||
geometry::recalculate(point2_rob, point2, robust_policy);
|
||||
|
||||
return detail::equals::equals_point_point(point1_rob, point2_rob);
|
||||
}
|
||||
|
||||
|
||||
template <typename Range, typename Point, typename RobustPolicy>
|
||||
inline void append_no_dups_or_spikes(Range& range, Point const& point,
|
||||
RobustPolicy const& robust_policy)
|
||||
{
|
||||
#ifdef BOOST_GEOMETRY_DEBUG_INTERSECTION
|
||||
std::cout << " add: ("
|
||||
<< geometry::get<0>(point) << ", " << geometry::get<1>(point) << ")"
|
||||
<< std::endl;
|
||||
#endif
|
||||
// The code below thies condition checks all spikes/dups
|
||||
// for geometries >= 3 points.
|
||||
// So we have to check the first potential duplicate differently
|
||||
if (boost::size(range) == 1
|
||||
&& points_equal_or_close(*(boost::begin(range)), point, robust_policy))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
traits::push_back<Range>::apply(range, point);
|
||||
|
||||
// If a point is equal, or forming a spike, remove the pen-ultimate point because this one caused the spike.
|
||||
// If so, the now-new-pen-ultimate point can again cause a spike (possibly at a corner). So keep doing this.
|
||||
// Besides spikes it will also avoid duplicates.
|
||||
// If a point is equal, or forming a spike, remove the pen-ultimate point
|
||||
// because this one caused the spike.
|
||||
// If so, the now-new-pen-ultimate point can again cause a spike
|
||||
// (possibly at a corner). So keep doing this.
|
||||
// Besides spikes it will also avoid adding duplicates.
|
||||
while(boost::size(range) >= 3
|
||||
&& point_is_spike_or_equal(point, *(boost::end(range) - 3), *(boost::end(range) - 2)))
|
||||
&& point_is_spike_or_equal(point,
|
||||
*(boost::end(range) - 3),
|
||||
*(boost::end(range) - 2),
|
||||
robust_policy))
|
||||
{
|
||||
// Use the Concept/traits, so resize and append again
|
||||
traits::resize<Range>::apply(range, boost::size(range) - 2);
|
||||
traits::push_back<Range>::apply(range, point);
|
||||
}
|
||||
}
|
||||
|
||||
// There might still be one duplicate not catched by the condition above
|
||||
if (boost::size(range) == 2
|
||||
&& geometry::detail::equals::equals_point_point(*boost::begin(range), point))
|
||||
template <typename Range, typename RobustPolicy>
|
||||
inline void clean_closing_dups_and_spikes(Range& range,
|
||||
RobustPolicy const& robust_policy)
|
||||
{
|
||||
int const minsize
|
||||
= core_detail::closure::minimum_ring_size
|
||||
<
|
||||
geometry::closure<Range>::value
|
||||
>::value;
|
||||
|
||||
if (boost::size(range) <= minsize)
|
||||
{
|
||||
traits::clear<Range>::apply(range);
|
||||
traits::push_back<Range>::apply(range, point);
|
||||
return;
|
||||
}
|
||||
|
||||
typedef typename boost::range_iterator<Range>::type iterator_type;
|
||||
const bool closed = geometry::closure<Range>::value == geometry::closed;
|
||||
bool found = false;
|
||||
do
|
||||
{
|
||||
found = false;
|
||||
iterator_type first = boost::begin(range);
|
||||
iterator_type second = first + 1;
|
||||
iterator_type ultimate = boost::end(range) - 1;
|
||||
if (closed)
|
||||
{
|
||||
ultimate--;
|
||||
}
|
||||
|
||||
// Check if closing point is a spike (this is so if the second point is
|
||||
// considered as a spike w.r.t. the last segment)
|
||||
if (point_is_spike_or_equal(*second, *ultimate, *first, robust_policy))
|
||||
{
|
||||
range.erase(first);
|
||||
if (closed)
|
||||
{
|
||||
// Remove closing last point
|
||||
traits::resize<Range>::apply(range, boost::size(range) - 1);
|
||||
// Add new closing point
|
||||
traits::push_back<Range>::apply(range, *boost::begin(range));
|
||||
}
|
||||
found = true;
|
||||
}
|
||||
} while(found && boost::size(range) > minsize);
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -79,14 +79,14 @@ class backtrack_check_self_intersections
|
||||
public :
|
||||
typedef state state_type;
|
||||
|
||||
template <typename Operation, typename Rings, typename Turns, typename RescalePolicy>
|
||||
template <typename Operation, typename Rings, typename Ring, typename Turns, typename RobustPolicy>
|
||||
static inline void apply(std::size_t size_at_start,
|
||||
Rings& rings, typename boost::range_value<Rings>::type& ring,
|
||||
Rings& rings, Ring& ring,
|
||||
Turns& turns, Operation& operation,
|
||||
std::string const& ,
|
||||
Geometry1 const& geometry1,
|
||||
Geometry2 const& geometry2,
|
||||
RescalePolicy const& rescale_policy,
|
||||
RobustPolicy const& robust_policy,
|
||||
state_type& state
|
||||
)
|
||||
{
|
||||
@@ -96,8 +96,8 @@ public :
|
||||
if (! state.m_checked)
|
||||
{
|
||||
state.m_checked = true;
|
||||
has_self_intersections(geometry1, rescale_policy);
|
||||
has_self_intersections(geometry2, rescale_policy);
|
||||
has_self_intersections(geometry1, robust_policy);
|
||||
has_self_intersections(geometry2, robust_policy);
|
||||
}
|
||||
|
||||
// Make bad output clean
|
||||
|
||||
@@ -1,64 +0,0 @@
|
||||
// Boost.Geometry (aka GGL, Generic Geometry Library)
|
||||
|
||||
// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.
|
||||
|
||||
// Use, modification and distribution is subject to the Boost Software License,
|
||||
// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
|
||||
// http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_OVERLAY_CALCULATE_DISTANCE_POLICY_HPP
|
||||
#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_OVERLAY_CALCULATE_DISTANCE_POLICY_HPP
|
||||
|
||||
|
||||
#include <boost/geometry/algorithms/comparable_distance.hpp>
|
||||
|
||||
|
||||
namespace boost { namespace geometry
|
||||
{
|
||||
|
||||
|
||||
#ifndef DOXYGEN_NO_DETAIL
|
||||
namespace detail { namespace overlay
|
||||
{
|
||||
|
||||
|
||||
/*!
|
||||
\brief Policy calculating distance
|
||||
\details get_turn_info has an optional policy to get some
|
||||
extra information.
|
||||
This policy calculates the distance (using default distance strategy)
|
||||
*/
|
||||
struct calculate_distance_policy
|
||||
{
|
||||
static bool const include_no_turn = false;
|
||||
static bool const include_degenerate = false;
|
||||
static bool const include_opposite = false;
|
||||
|
||||
template
|
||||
<
|
||||
typename Info,
|
||||
typename Point1,
|
||||
typename Point2,
|
||||
typename IntersectionInfo,
|
||||
typename DirInfo
|
||||
>
|
||||
static inline void apply(Info& info, Point1 const& p1, Point2 const& p2,
|
||||
IntersectionInfo const&, DirInfo const&)
|
||||
{
|
||||
info.operations[0].enriched.distance
|
||||
= geometry::comparable_distance(info.point, p1);
|
||||
info.operations[1].enriched.distance
|
||||
= geometry::comparable_distance(info.point, p2);
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
|
||||
}} // namespace detail::overlay
|
||||
#endif //DOXYGEN_NO_DETAIL
|
||||
|
||||
|
||||
}} // namespace boost::geometry
|
||||
|
||||
|
||||
#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_OVERLAY_CALCULATE_DISTANCE_POLICY_HPP
|
||||
@@ -22,6 +22,7 @@
|
||||
#include <boost/geometry/core/ring_type.hpp>
|
||||
#include <boost/geometry/core/exterior_ring.hpp>
|
||||
#include <boost/geometry/core/interior_rings.hpp>
|
||||
#include <boost/geometry/algorithms/not_implemented.hpp>
|
||||
#include <boost/geometry/geometries/concepts/check.hpp>
|
||||
#include <boost/geometry/iterators/ever_circling_iterator.hpp>
|
||||
#include <boost/geometry/views/closeable_view.hpp>
|
||||
@@ -38,34 +39,37 @@ namespace detail { namespace copy_segments
|
||||
{
|
||||
|
||||
|
||||
template
|
||||
<
|
||||
typename Ring,
|
||||
bool Reverse,
|
||||
typename SegmentIdentifier,
|
||||
typename RangeOut
|
||||
>
|
||||
template<bool Reverse>
|
||||
struct copy_segments_ring
|
||||
{
|
||||
typedef typename closeable_view
|
||||
template
|
||||
<
|
||||
typename Ring,
|
||||
typename SegmentIdentifier,
|
||||
typename RobustPolicy,
|
||||
typename RangeOut
|
||||
>
|
||||
static inline void apply(Ring const& ring,
|
||||
SegmentIdentifier const& seg_id, int to_index,
|
||||
RobustPolicy const& robust_policy,
|
||||
RangeOut& current_output)
|
||||
{
|
||||
typedef typename closeable_view
|
||||
<
|
||||
Ring const,
|
||||
closure<Ring>::value
|
||||
>::type cview_type;
|
||||
|
||||
typedef typename reversible_view
|
||||
typedef typename reversible_view
|
||||
<
|
||||
cview_type const,
|
||||
Reverse ? iterate_reverse : iterate_forward
|
||||
>::type rview_type;
|
||||
|
||||
typedef typename boost::range_iterator<rview_type const>::type iterator;
|
||||
typedef geometry::ever_circling_iterator<iterator> ec_iterator;
|
||||
typedef typename boost::range_iterator<rview_type const>::type iterator;
|
||||
typedef geometry::ever_circling_iterator<iterator> ec_iterator;
|
||||
|
||||
|
||||
static inline void apply(Ring const& ring,
|
||||
SegmentIdentifier const& seg_id, int to_index,
|
||||
RangeOut& current_output)
|
||||
{
|
||||
cview_type cview(ring);
|
||||
rview_type view(cview);
|
||||
|
||||
@@ -93,27 +97,27 @@ struct copy_segments_ring
|
||||
|
||||
for (size_type i = 0; i < count; ++i, ++it)
|
||||
{
|
||||
detail::overlay::append_no_dups_or_spikes(current_output, *it);
|
||||
detail::overlay::append_no_dups_or_spikes(current_output, *it, robust_policy);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
template
|
||||
<
|
||||
typename LineString,
|
||||
bool Reverse,
|
||||
typename SegmentIdentifier,
|
||||
typename RangeOut
|
||||
>
|
||||
template<bool Reverse>
|
||||
struct copy_segments_linestring
|
||||
{
|
||||
|
||||
typedef typename boost::range_iterator<LineString const>::type iterator;
|
||||
|
||||
template
|
||||
<
|
||||
typename LineString,
|
||||
typename SegmentIdentifier,
|
||||
typename RobustPolicy,
|
||||
typename RangeOut
|
||||
>
|
||||
static inline void apply(LineString const& ls,
|
||||
SegmentIdentifier const& seg_id, int to_index,
|
||||
RobustPolicy const& robust_policy,
|
||||
RangeOut& current_output)
|
||||
{
|
||||
typedef typename boost::range_iterator<LineString const>::type iterator;
|
||||
int const from_index = seg_id.segment_index + 1;
|
||||
|
||||
// Sanity check
|
||||
@@ -129,54 +133,54 @@ struct copy_segments_linestring
|
||||
|
||||
for (size_type i = 0; i < count; ++i, ++it)
|
||||
{
|
||||
detail::overlay::append_no_dups_or_spikes(current_output, *it);
|
||||
detail::overlay::append_no_dups_or_spikes(current_output, *it,
|
||||
robust_policy);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
template
|
||||
<
|
||||
typename Polygon,
|
||||
bool Reverse,
|
||||
typename SegmentIdentifier,
|
||||
typename RangeOut
|
||||
>
|
||||
template<bool Reverse>
|
||||
struct copy_segments_polygon
|
||||
{
|
||||
template
|
||||
<
|
||||
typename Polygon,
|
||||
typename SegmentIdentifier,
|
||||
typename RobustPolicy,
|
||||
typename RangeOut
|
||||
>
|
||||
static inline void apply(Polygon const& polygon,
|
||||
SegmentIdentifier const& seg_id, int to_index,
|
||||
RobustPolicy const& robust_policy,
|
||||
RangeOut& current_output)
|
||||
{
|
||||
// Call ring-version with the right ring
|
||||
copy_segments_ring
|
||||
<
|
||||
typename geometry::ring_type<Polygon>::type,
|
||||
Reverse,
|
||||
SegmentIdentifier,
|
||||
RangeOut
|
||||
>::apply
|
||||
(
|
||||
seg_id.ring_index < 0
|
||||
? geometry::exterior_ring(polygon)
|
||||
: geometry::interior_rings(polygon)[seg_id.ring_index],
|
||||
seg_id, to_index,
|
||||
current_output
|
||||
);
|
||||
copy_segments_ring<Reverse>::apply
|
||||
(
|
||||
seg_id.ring_index < 0
|
||||
? geometry::exterior_ring(polygon)
|
||||
: geometry::interior_rings(polygon)[seg_id.ring_index],
|
||||
seg_id, to_index,
|
||||
robust_policy,
|
||||
current_output
|
||||
);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
template
|
||||
<
|
||||
typename Box,
|
||||
bool Reverse,
|
||||
typename SegmentIdentifier,
|
||||
typename RangeOut
|
||||
>
|
||||
template<bool Reverse>
|
||||
struct copy_segments_box
|
||||
{
|
||||
template
|
||||
<
|
||||
typename Box,
|
||||
typename SegmentIdentifier,
|
||||
typename RobustPolicy,
|
||||
typename RangeOut
|
||||
>
|
||||
static inline void apply(Box const& box,
|
||||
SegmentIdentifier const& seg_id, int to_index,
|
||||
RobustPolicy const& robust_policy,
|
||||
RangeOut& current_output)
|
||||
{
|
||||
int index = seg_id.segment_index + 1;
|
||||
@@ -195,7 +199,8 @@ struct copy_segments_box
|
||||
// (see comments in ring-version)
|
||||
for (int i = 0; i < count; i++, index++)
|
||||
{
|
||||
detail::overlay::append_no_dups_or_spikes(current_output, bp[index % 5]);
|
||||
detail::overlay::append_no_dups_or_spikes(current_output,
|
||||
bp[index % 5], robust_policy);
|
||||
|
||||
}
|
||||
}
|
||||
@@ -213,80 +218,33 @@ namespace dispatch
|
||||
template
|
||||
<
|
||||
typename Tag,
|
||||
typename GeometryIn,
|
||||
bool Reverse,
|
||||
typename SegmentIdentifier,
|
||||
typename RangeOut
|
||||
bool Reverse
|
||||
>
|
||||
struct copy_segments
|
||||
{
|
||||
BOOST_MPL_ASSERT_MSG
|
||||
(
|
||||
false, NOT_OR_NOT_YET_IMPLEMENTED_FOR_THIS_GEOMETRY_TYPE
|
||||
, (types<GeometryIn>)
|
||||
);
|
||||
};
|
||||
|
||||
|
||||
template
|
||||
<
|
||||
typename Ring,
|
||||
bool Reverse,
|
||||
typename SegmentIdentifier,
|
||||
typename RangeOut
|
||||
>
|
||||
struct copy_segments<ring_tag, Ring, Reverse, SegmentIdentifier, RangeOut>
|
||||
: detail::copy_segments::copy_segments_ring
|
||||
<
|
||||
Ring, Reverse, SegmentIdentifier, RangeOut
|
||||
>
|
||||
struct copy_segments : not_implemented<Tag>
|
||||
{};
|
||||
|
||||
|
||||
|
||||
template
|
||||
<
|
||||
typename LineString,
|
||||
bool Reverse,
|
||||
typename SegmentIdentifier,
|
||||
typename RangeOut
|
||||
>
|
||||
struct copy_segments<linestring_tag, LineString, Reverse, SegmentIdentifier, RangeOut>
|
||||
: detail::copy_segments::copy_segments_linestring
|
||||
<
|
||||
LineString, Reverse, SegmentIdentifier, RangeOut
|
||||
>
|
||||
{};
|
||||
|
||||
template
|
||||
<
|
||||
typename Polygon,
|
||||
bool Reverse,
|
||||
typename SegmentIdentifier,
|
||||
typename RangeOut
|
||||
>
|
||||
struct copy_segments<polygon_tag, Polygon, Reverse, SegmentIdentifier, RangeOut>
|
||||
: detail::copy_segments::copy_segments_polygon
|
||||
<
|
||||
Polygon, Reverse, SegmentIdentifier, RangeOut
|
||||
>
|
||||
template<bool Reverse>
|
||||
struct copy_segments<ring_tag, Reverse>
|
||||
: detail::copy_segments::copy_segments_ring<Reverse>
|
||||
{};
|
||||
|
||||
|
||||
template
|
||||
<
|
||||
typename Box,
|
||||
bool Reverse,
|
||||
typename SegmentIdentifier,
|
||||
typename RangeOut
|
||||
>
|
||||
struct copy_segments<box_tag, Box, Reverse, SegmentIdentifier, RangeOut>
|
||||
: detail::copy_segments::copy_segments_box
|
||||
<
|
||||
Box, Reverse, SegmentIdentifier, RangeOut
|
||||
>
|
||||
template<bool Reverse>
|
||||
struct copy_segments<linestring_tag, Reverse>
|
||||
: detail::copy_segments::copy_segments_linestring<Reverse>
|
||||
{};
|
||||
|
||||
template<bool Reverse>
|
||||
struct copy_segments<polygon_tag, Reverse>
|
||||
: detail::copy_segments::copy_segments_polygon<Reverse>
|
||||
{};
|
||||
|
||||
|
||||
template<bool Reverse>
|
||||
struct copy_segments<box_tag, Reverse>
|
||||
: detail::copy_segments::copy_segments_box<Reverse>
|
||||
{};
|
||||
|
||||
|
||||
} // namespace dispatch
|
||||
@@ -303,10 +261,12 @@ template
|
||||
bool Reverse,
|
||||
typename Geometry,
|
||||
typename SegmentIdentifier,
|
||||
typename RobustPolicy,
|
||||
typename RangeOut
|
||||
>
|
||||
inline void copy_segments(Geometry const& geometry,
|
||||
SegmentIdentifier const& seg_id, int to_index,
|
||||
RobustPolicy const& robust_policy,
|
||||
RangeOut& range_out)
|
||||
{
|
||||
concept::check<Geometry const>();
|
||||
@@ -314,11 +274,8 @@ inline void copy_segments(Geometry const& geometry,
|
||||
dispatch::copy_segments
|
||||
<
|
||||
typename tag<Geometry>::type,
|
||||
Geometry,
|
||||
Reverse,
|
||||
SegmentIdentifier,
|
||||
RangeOut
|
||||
>::apply(geometry, seg_id, to_index, range_out);
|
||||
Reverse
|
||||
>::apply(geometry, seg_id, to_index, robust_policy, range_out);
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -30,6 +30,7 @@
|
||||
#include <boost/geometry/algorithms/detail/overlay/get_relative_order.hpp>
|
||||
#include <boost/geometry/algorithms/detail/overlay/handle_tangencies.hpp>
|
||||
#include <boost/geometry/algorithms/detail/zoom_to_robust.hpp>
|
||||
#include <boost/geometry/policies/robustness/robust_type.hpp>
|
||||
#ifdef BOOST_GEOMETRY_DEBUG_ENRICH
|
||||
# include <boost/geometry/algorithms/detail/overlay/check_enrich.hpp>
|
||||
#endif
|
||||
@@ -79,9 +80,9 @@ template
|
||||
bool Reverse1, bool Reverse2,
|
||||
typename Strategy
|
||||
>
|
||||
struct sort_on_segment_and_distance
|
||||
struct sort_on_segment_and_ratio
|
||||
{
|
||||
inline sort_on_segment_and_distance(TurnPoints const& turn_points
|
||||
inline sort_on_segment_and_ratio(TurnPoints const& turn_points
|
||||
, Geometry1 const& geometry1
|
||||
, Geometry2 const& geometry2
|
||||
, Strategy const& strategy
|
||||
@@ -104,7 +105,7 @@ private :
|
||||
|
||||
typedef model::point
|
||||
<
|
||||
typename geometry::robust_type
|
||||
typename detail::robust_type
|
||||
<
|
||||
typename select_coordinate_type<Geometry1, Geometry2>::type
|
||||
>::type,
|
||||
@@ -128,7 +129,7 @@ private :
|
||||
geometry::copy_segment_points<Reverse1, Reverse2>(m_geometry1, m_geometry2,
|
||||
right.subject.other_id,
|
||||
si, sj);
|
||||
geometry::zoom_to_robust(pi, pj, ri, rj, si, sj,
|
||||
detail::zoom_to_robust(pi, pj, ri, rj, si, sj,
|
||||
pi_rob, pj_rob, ri_rob, rj_rob, si_rob, sj_rob);
|
||||
}
|
||||
|
||||
@@ -157,9 +158,7 @@ public :
|
||||
if (sl == sr)
|
||||
{
|
||||
// Both left and right are located on the SAME segment.
|
||||
typedef typename geometry::coordinate_type<Geometry1>::type coordinate_type;
|
||||
coordinate_type diff = geometry::math::abs(left.subject.enriched.distance - right.subject.enriched.distance);
|
||||
if (diff < geometry::math::relaxed_epsilon<coordinate_type>(10))
|
||||
if (left.subject.fraction == right.subject.fraction)
|
||||
{
|
||||
// First check "real" intersection (crosses)
|
||||
// -> distance zero due to precision, solve it by sorting
|
||||
@@ -173,13 +172,12 @@ public :
|
||||
// Indicate that this is necessary.
|
||||
*m_clustered = true;
|
||||
|
||||
return left.subject.enriched.distance < right.subject.enriched.distance;
|
||||
return left.subject.fraction < right.subject.fraction;
|
||||
}
|
||||
}
|
||||
return sl == sr
|
||||
? left.subject.enriched.distance < right.subject.enriched.distance
|
||||
? left.subject.fraction < right.subject.fraction
|
||||
: sl < sr;
|
||||
|
||||
}
|
||||
};
|
||||
|
||||
@@ -217,14 +215,14 @@ template
|
||||
typename Container,
|
||||
typename TurnPoints,
|
||||
typename Geometry1, typename Geometry2,
|
||||
typename RescalePolicy,
|
||||
typename RobustPolicy,
|
||||
typename Strategy
|
||||
>
|
||||
inline void enrich_sort(Container& operations,
|
||||
TurnPoints& turn_points,
|
||||
operation_type for_operation,
|
||||
Geometry1 const& geometry1, Geometry2 const& geometry2,
|
||||
RescalePolicy const& rescale_policy,
|
||||
RobustPolicy const& robust_policy,
|
||||
Strategy const& strategy)
|
||||
{
|
||||
typedef typename IndexType::type operations_type;
|
||||
@@ -232,7 +230,7 @@ inline void enrich_sort(Container& operations,
|
||||
bool clustered = false;
|
||||
std::sort(boost::begin(operations),
|
||||
boost::end(operations),
|
||||
sort_on_segment_and_distance
|
||||
sort_on_segment_and_ratio
|
||||
<
|
||||
TurnPoints,
|
||||
IndexType,
|
||||
@@ -262,8 +260,7 @@ inline void enrich_sort(Container& operations,
|
||||
if (prev_op.seg_id == op.seg_id
|
||||
&& (turn_points[prev->index].method != method_crosses
|
||||
|| turn_points[it->index].method != method_crosses)
|
||||
&& geometry::math::equals(prev_op.enriched.distance,
|
||||
op.enriched.distance))
|
||||
&& prev_op.fraction == op.fraction)
|
||||
{
|
||||
if (begin_cluster == boost::end(operations))
|
||||
{
|
||||
@@ -273,14 +270,14 @@ inline void enrich_sort(Container& operations,
|
||||
else if (begin_cluster != boost::end(operations))
|
||||
{
|
||||
handle_cluster<IndexType, Reverse1, Reverse2>(begin_cluster, it, turn_points,
|
||||
for_operation, geometry1, geometry2, rescale_policy, strategy);
|
||||
for_operation, geometry1, geometry2, robust_policy, strategy);
|
||||
begin_cluster = boost::end(operations);
|
||||
}
|
||||
}
|
||||
if (begin_cluster != boost::end(operations))
|
||||
{
|
||||
handle_cluster<IndexType, Reverse1, Reverse2>(begin_cluster, it, turn_points,
|
||||
for_operation, geometry1, geometry2, rescale_policy, strategy);
|
||||
for_operation, geometry1, geometry2, robust_policy, strategy);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -370,7 +367,7 @@ inline void enrich_assign(Container& operations,
|
||||
std::cout << it->index
|
||||
<< " meth: " << method_char(turn_points[it->index].method)
|
||||
<< " seg: " << op.seg_id
|
||||
<< " dst: " << boost::numeric_cast<double>(op.enriched.distance)
|
||||
<< " dst: " << op.fraction // needs define
|
||||
<< " op: " << operation_char(turn_points[it->index].operations[0].operation)
|
||||
<< operation_char(turn_points[it->index].operations[1].operation)
|
||||
<< " dsc: " << (turn_points[it->index].discarded ? "T" : "F")
|
||||
@@ -453,13 +450,13 @@ template
|
||||
bool Reverse1, bool Reverse2,
|
||||
typename TurnPoints,
|
||||
typename Geometry1, typename Geometry2,
|
||||
typename RescalePolicy,
|
||||
typename RobustPolicy,
|
||||
typename Strategy
|
||||
>
|
||||
inline void enrich_intersection_points(TurnPoints& turn_points,
|
||||
detail::overlay::operation_type for_operation,
|
||||
Geometry1 const& geometry1, Geometry2 const& geometry2,
|
||||
RescalePolicy const& rescale_policy,
|
||||
RobustPolicy const& robust_policy,
|
||||
Strategy const& strategy)
|
||||
{
|
||||
typedef typename boost::range_value<TurnPoints>::type turn_point_type;
|
||||
@@ -514,7 +511,7 @@ inline void enrich_intersection_points(TurnPoints& turn_points,
|
||||
<< mit->first << std::endl;
|
||||
#endif
|
||||
detail::overlay::enrich_sort<indexed_turn_operation, Reverse1, Reverse2>(mit->second, turn_points, for_operation,
|
||||
geometry1, geometry2, rescale_policy, strategy);
|
||||
geometry1, geometry2, robust_policy, strategy);
|
||||
}
|
||||
|
||||
for (typename mapped_vector_type::iterator mit
|
||||
|
||||
@@ -10,9 +10,6 @@
|
||||
#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_OVERLAY_ENRICHMENT_INFO_HPP
|
||||
|
||||
|
||||
#include <boost/geometry/strategies/distance.hpp>
|
||||
|
||||
|
||||
namespace boost { namespace geometry
|
||||
{
|
||||
|
||||
@@ -31,24 +28,10 @@ namespace detail { namespace overlay
|
||||
template<typename P>
|
||||
struct enrichment_info
|
||||
{
|
||||
typedef typename strategy::distance::services::return_type
|
||||
<
|
||||
typename strategy::distance::services::comparable_type
|
||||
<
|
||||
typename strategy::distance::services::default_strategy
|
||||
<
|
||||
point_tag,
|
||||
P
|
||||
>::type
|
||||
>::type,
|
||||
P, P
|
||||
>::type distance_type;
|
||||
|
||||
inline enrichment_info()
|
||||
: travels_to_vertex_index(-1)
|
||||
, travels_to_ip_index(-1)
|
||||
, next_ip_index(-1)
|
||||
, distance(distance_type())
|
||||
{}
|
||||
|
||||
// vertex to which is free travel after this IP,
|
||||
@@ -61,8 +44,6 @@ struct enrichment_info
|
||||
|
||||
// index of next IP on this segment, -1 if there is no one
|
||||
int next_ip_index;
|
||||
|
||||
distance_type distance; // distance-measurement from segment.first to IP
|
||||
};
|
||||
|
||||
|
||||
|
||||
@@ -157,15 +157,19 @@ struct action_selector<overlay_intersection>
|
||||
typename LineStringOut,
|
||||
typename LineString,
|
||||
typename Point,
|
||||
typename Operation
|
||||
typename Operation,
|
||||
typename RobustPolicy
|
||||
>
|
||||
static inline void enter(LineStringOut& current_piece,
|
||||
LineString const& ,
|
||||
segment_identifier& segment_id,
|
||||
int , Point const& point,
|
||||
Operation const& operation, OutputIterator& )
|
||||
Operation const& operation,
|
||||
RobustPolicy const& ,
|
||||
OutputIterator& )
|
||||
{
|
||||
// On enter, append the intersection point and remember starting point
|
||||
// TODO: we don't check on spikes for linestrings (?). Consider this.
|
||||
detail::overlay::append_no_duplicates(current_piece, point);
|
||||
segment_id = operation.seg_id;
|
||||
}
|
||||
@@ -176,17 +180,20 @@ struct action_selector<overlay_intersection>
|
||||
typename LineStringOut,
|
||||
typename LineString,
|
||||
typename Point,
|
||||
typename Operation
|
||||
typename Operation,
|
||||
typename RobustPolicy
|
||||
>
|
||||
static inline void leave(LineStringOut& current_piece,
|
||||
LineString const& linestring,
|
||||
segment_identifier& segment_id,
|
||||
int index, Point const& point,
|
||||
Operation const& , OutputIterator& out)
|
||||
Operation const& ,
|
||||
RobustPolicy const& robust_policy,
|
||||
OutputIterator& out)
|
||||
{
|
||||
// On leave, copy all segments from starting point, append the intersection point
|
||||
// and add the output piece
|
||||
geometry::copy_segments<false>(linestring, segment_id, index, current_piece);
|
||||
geometry::copy_segments<false>(linestring, segment_id, index, robust_policy, current_piece);
|
||||
detail::overlay::append_no_duplicates(current_piece, point);
|
||||
if (::boost::size(current_piece) > 1)
|
||||
{
|
||||
@@ -225,8 +232,15 @@ struct action_selector<overlay_intersection>
|
||||
return entered;
|
||||
}
|
||||
|
||||
template <typename Point, typename Geometry>
|
||||
static inline bool included(Point const& point, Geometry const& geometry)
|
||||
template
|
||||
<
|
||||
typename Point,
|
||||
typename Geometry,
|
||||
typename RobustPolicy
|
||||
>
|
||||
static inline bool included(Point const& point,
|
||||
Geometry const& geometry,
|
||||
RobustPolicy const& )
|
||||
{
|
||||
return geometry::covered_by(point, geometry);
|
||||
}
|
||||
@@ -245,16 +259,19 @@ struct action_selector<overlay_difference>
|
||||
typename LineStringOut,
|
||||
typename LineString,
|
||||
typename Point,
|
||||
typename Operation
|
||||
typename Operation,
|
||||
typename RobustPolicy
|
||||
>
|
||||
static inline void enter(LineStringOut& current_piece,
|
||||
LineString const& linestring,
|
||||
segment_identifier& segment_id,
|
||||
int index, Point const& point,
|
||||
Operation const& operation, OutputIterator& out)
|
||||
Operation const& operation,
|
||||
RobustPolicy const& robust_policy,
|
||||
OutputIterator& out)
|
||||
{
|
||||
normal_action::leave(current_piece, linestring, segment_id, index,
|
||||
point, operation, out);
|
||||
point, operation, robust_policy, out);
|
||||
}
|
||||
|
||||
template
|
||||
@@ -263,16 +280,19 @@ struct action_selector<overlay_difference>
|
||||
typename LineStringOut,
|
||||
typename LineString,
|
||||
typename Point,
|
||||
typename Operation
|
||||
typename Operation,
|
||||
typename RobustPolicy
|
||||
>
|
||||
static inline void leave(LineStringOut& current_piece,
|
||||
LineString const& linestring,
|
||||
segment_identifier& segment_id,
|
||||
int index, Point const& point,
|
||||
Operation const& operation, OutputIterator& out)
|
||||
Operation const& operation,
|
||||
RobustPolicy const& robust_policy,
|
||||
OutputIterator& out)
|
||||
{
|
||||
normal_action::enter(current_piece, linestring, segment_id, index,
|
||||
point, operation, out);
|
||||
point, operation, robust_policy, out);
|
||||
}
|
||||
|
||||
template
|
||||
@@ -296,10 +316,17 @@ struct action_selector<overlay_difference>
|
||||
return ! normal_action::is_entered(entered);
|
||||
}
|
||||
|
||||
template <typename Point, typename Geometry>
|
||||
static inline bool included(Point const& point, Geometry const& geometry)
|
||||
template
|
||||
<
|
||||
typename Point,
|
||||
typename Geometry,
|
||||
typename RobustPolicy
|
||||
>
|
||||
static inline bool included(Point const& point,
|
||||
Geometry const& geometry,
|
||||
RobustPolicy const& robust_policy)
|
||||
{
|
||||
return ! normal_action::included(point, geometry);
|
||||
return ! normal_action::included(point, geometry, robust_policy);
|
||||
}
|
||||
|
||||
};
|
||||
@@ -349,9 +376,9 @@ class follow
|
||||
|
||||
inline bool use_distance(Turn const& left, Turn const& right) const
|
||||
{
|
||||
return geometry::math::equals(left.operations[0].enriched.distance, right.operations[0].enriched.distance)
|
||||
return left.operations[0].fraction == right.operations[0].fraction
|
||||
? use_operation(left, right)
|
||||
: left.operations[0].enriched.distance < right.operations[0].enriched.distance
|
||||
: left.operations[0].fraction < right.operations[0].fraction
|
||||
;
|
||||
}
|
||||
|
||||
@@ -372,16 +399,30 @@ class follow
|
||||
|
||||
public :
|
||||
|
||||
template <typename Point, typename Geometry>
|
||||
static inline bool included(Point const& point, Geometry const& geometry)
|
||||
template
|
||||
<
|
||||
typename Point,
|
||||
typename Geometry,
|
||||
typename RobustPolicy
|
||||
>
|
||||
static inline bool included(Point const& point,
|
||||
Geometry const& geometry,
|
||||
RobustPolicy const& robust_policy)
|
||||
{
|
||||
return following::action_selector<OverlayType>::included(point, geometry);
|
||||
return following::action_selector<OverlayType>::included(point, geometry, robust_policy);
|
||||
}
|
||||
|
||||
template<typename Turns, typename OutputIterator>
|
||||
template
|
||||
<
|
||||
typename Turns,
|
||||
typename OutputIterator,
|
||||
typename RobustPolicy
|
||||
>
|
||||
static inline OutputIterator apply(LineString const& linestring, Polygon const& polygon,
|
||||
detail::overlay::operation_type , // TODO: this parameter might be redundant
|
||||
Turns& turns, OutputIterator out)
|
||||
Turns& turns,
|
||||
RobustPolicy const& robust_policy,
|
||||
OutputIterator out)
|
||||
{
|
||||
typedef typename boost::range_iterator<Turns>::type turn_iterator;
|
||||
typedef typename boost::range_value<Turns>::type turn_type;
|
||||
@@ -423,14 +464,20 @@ public :
|
||||
debug_traverse(*it, *iit, "-> Entering");
|
||||
|
||||
entered = true;
|
||||
action::enter(current_piece, linestring, current_segment_id, iit->seg_id.segment_index, it->point, *iit, out);
|
||||
action::enter(current_piece, linestring, current_segment_id,
|
||||
iit->seg_id.segment_index, it->point, *iit,
|
||||
robust_policy,
|
||||
out);
|
||||
}
|
||||
else if (following::is_leaving(*it, *iit, entered, first, linestring, polygon))
|
||||
{
|
||||
debug_traverse(*it, *iit, "-> Leaving");
|
||||
|
||||
entered = false;
|
||||
action::leave(current_piece, linestring, current_segment_id, iit->seg_id.segment_index, it->point, *iit, out);
|
||||
action::leave(current_piece, linestring, current_segment_id,
|
||||
iit->seg_id.segment_index, it->point, *iit,
|
||||
robust_policy,
|
||||
out);
|
||||
}
|
||||
first = false;
|
||||
}
|
||||
@@ -439,6 +486,7 @@ public :
|
||||
{
|
||||
geometry::copy_segments<false>(linestring, current_segment_id,
|
||||
boost::size(linestring) - 1,
|
||||
robust_policy,
|
||||
current_piece);
|
||||
}
|
||||
|
||||
|
||||
@@ -11,6 +11,7 @@
|
||||
#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_OVERLAY_FOLLOW_LINEAR_LINEAR_HPP
|
||||
|
||||
#include <cstddef>
|
||||
#include <algorithm>
|
||||
#include <iterator>
|
||||
|
||||
#include <boost/assert.hpp>
|
||||
@@ -123,7 +124,7 @@ static inline bool is_isolated_point(Turn const& turn,
|
||||
return false;
|
||||
}
|
||||
|
||||
if ( turn.method == method_collinear )
|
||||
if ( turn.method == method_none )
|
||||
{
|
||||
BOOST_ASSERT( operation.operation == operation_continue );
|
||||
return true;
|
||||
@@ -184,13 +185,16 @@ protected:
|
||||
static inline OutputIterator
|
||||
process_turn(TurnIterator it,
|
||||
TurnOperationIterator op_it,
|
||||
bool& first, bool& entered,
|
||||
bool& entered,
|
||||
std::size_t& enter_count,
|
||||
Linestring const& linestring,
|
||||
LinestringOut& current_piece,
|
||||
SegmentIdentifier& current_segment_id,
|
||||
OutputIterator oit)
|
||||
{
|
||||
// We don't rescale linear/linear
|
||||
detail::no_rescale_policy robust_policy;
|
||||
|
||||
if ( is_entering(*it, *op_it) )
|
||||
{
|
||||
#ifdef GEOMETRY_TEST_DEBUG
|
||||
@@ -203,7 +207,7 @@ protected:
|
||||
action::enter(current_piece, linestring,
|
||||
current_segment_id,
|
||||
op_it->seg_id.segment_index,
|
||||
it->point, *op_it, oit);
|
||||
it->point, *op_it, robust_policy, oit);
|
||||
}
|
||||
++enter_count;
|
||||
}
|
||||
@@ -220,7 +224,7 @@ protected:
|
||||
action::leave(current_piece, linestring,
|
||||
current_segment_id,
|
||||
op_it->seg_id.segment_index,
|
||||
it->point, *op_it, oit);
|
||||
it->point, *op_it, robust_policy, oit);
|
||||
}
|
||||
}
|
||||
else if ( FollowIsolatedPoints
|
||||
@@ -244,7 +248,6 @@ protected:
|
||||
|
||||
entered = true;
|
||||
}
|
||||
first = false;
|
||||
return oit;
|
||||
}
|
||||
|
||||
@@ -262,9 +265,13 @@ protected:
|
||||
{
|
||||
if ( action::is_entered(entered) )
|
||||
{
|
||||
// We don't rescale linear/linear
|
||||
detail::no_rescale_policy robust_policy;
|
||||
|
||||
geometry::copy_segments<false>(linestring,
|
||||
current_segment_id,
|
||||
boost::size(linestring) - 1,
|
||||
robust_policy,
|
||||
current_piece);
|
||||
}
|
||||
|
||||
@@ -281,17 +288,9 @@ public:
|
||||
template <typename TurnIterator, typename OutputIterator>
|
||||
static inline OutputIterator
|
||||
apply(Linestring const& linestring, Linear const& linear,
|
||||
TurnIterator start, TurnIterator beyond,
|
||||
TurnIterator first, TurnIterator beyond,
|
||||
OutputIterator oit)
|
||||
{
|
||||
typedef typename boost::range_iterator
|
||||
<
|
||||
typename std::iterator_traits
|
||||
<
|
||||
TurnIterator
|
||||
>::value_type::container_type const
|
||||
>::type turn_operation_iterator;
|
||||
|
||||
// Iterate through all intersection points (they are
|
||||
// ordered along the each line)
|
||||
|
||||
@@ -299,15 +298,12 @@ public:
|
||||
geometry::segment_identifier current_segment_id(0, -1, -1, -1);
|
||||
|
||||
bool entered = false;
|
||||
bool first = true;
|
||||
std::size_t enter_count = 0;
|
||||
|
||||
for (TurnIterator it = start; it != beyond; ++it)
|
||||
for (TurnIterator it = first; it != beyond; ++it)
|
||||
{
|
||||
turn_operation_iterator op_it = boost::begin(it->operations);
|
||||
|
||||
oit = process_turn(it, op_it,
|
||||
first, entered, enter_count,
|
||||
oit = process_turn(it, boost::begin(it->operations),
|
||||
entered, enter_count,
|
||||
linestring,
|
||||
current_piece, current_segment_id,
|
||||
oit);
|
||||
@@ -365,8 +361,7 @@ protected:
|
||||
struct copy_linestrings_in_range
|
||||
{
|
||||
static inline OutputIt
|
||||
apply(linestring_iterator begin, linestring_iterator beyond,
|
||||
OutputIt oit)
|
||||
apply(linestring_iterator, linestring_iterator, OutputIt oit)
|
||||
{
|
||||
return oit;
|
||||
}
|
||||
@@ -376,10 +371,10 @@ protected:
|
||||
struct copy_linestrings_in_range<OutputIt, overlay_difference>
|
||||
{
|
||||
static inline OutputIt
|
||||
apply(linestring_iterator begin, linestring_iterator beyond,
|
||||
apply(linestring_iterator first, linestring_iterator beyond,
|
||||
OutputIt oit)
|
||||
{
|
||||
for (linestring_iterator ls_it = begin; ls_it != beyond; ++ls_it)
|
||||
for (linestring_iterator ls_it = first; ls_it != beyond; ++ls_it)
|
||||
{
|
||||
LinestringOut line_out;
|
||||
geometry::convert(*ls_it, line_out);
|
||||
@@ -389,68 +384,80 @@ protected:
|
||||
}
|
||||
};
|
||||
|
||||
template <typename TurnIterator>
|
||||
static inline int get_multi_index(TurnIterator it)
|
||||
{
|
||||
return boost::begin(it->operations)->seg_id.multi_index;
|
||||
}
|
||||
|
||||
class has_other_multi_id
|
||||
{
|
||||
private:
|
||||
int m_multi_id;
|
||||
|
||||
public:
|
||||
has_other_multi_id(int multi_id)
|
||||
: m_multi_id(multi_id) {}
|
||||
|
||||
template <typename Turn>
|
||||
bool operator()(Turn const& turn) const
|
||||
{
|
||||
return boost::begin(turn.operations)->seg_id.multi_index
|
||||
!= m_multi_id;
|
||||
}
|
||||
};
|
||||
|
||||
public:
|
||||
template <typename TurnIterator, typename OutputIterator>
|
||||
static inline OutputIterator
|
||||
apply(MultiLinestring const& multilinestring, Linear const& linear,
|
||||
TurnIterator start, TurnIterator beyond,
|
||||
TurnIterator first, TurnIterator beyond,
|
||||
OutputIterator oit)
|
||||
{
|
||||
BOOST_ASSERT( start != beyond );
|
||||
BOOST_ASSERT( first != beyond );
|
||||
|
||||
typedef copy_linestrings_in_range
|
||||
<
|
||||
OutputIterator, OverlayType
|
||||
> copy_linestrings;
|
||||
|
||||
linestring_iterator ls_begin = boost::begin(multilinestring);
|
||||
linestring_iterator ls_end = boost::end(multilinestring);
|
||||
linestring_iterator ls_first = boost::begin(multilinestring);
|
||||
linestring_iterator ls_beyond = boost::end(multilinestring);
|
||||
|
||||
// Iterate through all intersection points (they are
|
||||
// ordered along the each line)
|
||||
// ordered along the each linestring)
|
||||
|
||||
int current_multi_id =
|
||||
boost::begin(start->operations)->seg_id.multi_index;
|
||||
int current_multi_id = get_multi_index(first);
|
||||
|
||||
oit = copy_linestrings::apply(ls_begin,
|
||||
ls_begin + current_multi_id,
|
||||
oit = copy_linestrings::apply(ls_first,
|
||||
ls_first + current_multi_id,
|
||||
oit);
|
||||
|
||||
TurnIterator turns_begin = start, turns_end;
|
||||
TurnIterator per_ls_next = first;
|
||||
do {
|
||||
// find last turn with this multi-index
|
||||
turns_end = turns_begin;
|
||||
++turns_end;
|
||||
while ( turns_end != beyond )
|
||||
{
|
||||
if ( boost::begin(turns_end->operations)->seg_id.multi_index
|
||||
!= current_multi_id )
|
||||
{
|
||||
break;
|
||||
}
|
||||
++turns_end;
|
||||
}
|
||||
TurnIterator per_ls_current = per_ls_next;
|
||||
|
||||
oit = Base::apply(*(boost::begin(multilinestring)
|
||||
+ current_multi_id),
|
||||
linear, turns_begin, turns_end, oit);
|
||||
// find turn with different multi-index
|
||||
per_ls_next = std::find_if(per_ls_current, beyond,
|
||||
has_other_multi_id(current_multi_id));
|
||||
|
||||
int new_multi_id(0);
|
||||
linestring_iterator ls_beyond_last = ls_end;
|
||||
if ( turns_end != beyond )
|
||||
oit = Base::apply(*(ls_first + current_multi_id),
|
||||
linear, per_ls_current, per_ls_next, oit);
|
||||
|
||||
int next_multi_id(-1);
|
||||
linestring_iterator ls_next = ls_beyond;
|
||||
if ( per_ls_next != beyond )
|
||||
{
|
||||
new_multi_id =
|
||||
boost::begin(turns_end->operations)->seg_id.multi_index;
|
||||
ls_beyond_last = ls_begin + new_multi_id;
|
||||
next_multi_id = get_multi_index(per_ls_next);
|
||||
ls_next = ls_first + next_multi_id;
|
||||
}
|
||||
oit = copy_linestrings::apply(ls_begin + current_multi_id + 1,
|
||||
ls_beyond_last,
|
||||
oit = copy_linestrings::apply(ls_first + current_multi_id + 1,
|
||||
ls_next,
|
||||
oit);
|
||||
|
||||
current_multi_id = new_multi_id;
|
||||
turns_begin = turns_end;
|
||||
current_multi_id = next_multi_id;
|
||||
}
|
||||
while ( turns_end != beyond );
|
||||
while ( per_ls_next != beyond );
|
||||
|
||||
return oit;
|
||||
}
|
||||
|
||||
@@ -14,10 +14,10 @@
|
||||
|
||||
#include <boost/geometry/algorithms/convert.hpp>
|
||||
#include <boost/geometry/algorithms/detail/overlay/get_turns.hpp>
|
||||
#include <boost/geometry/algorithms/detail/rescale.hpp>
|
||||
|
||||
#include <boost/geometry/geometries/segment.hpp>
|
||||
|
||||
#include <boost/geometry/policies/robustness/robust_point_type.hpp>
|
||||
|
||||
namespace boost { namespace geometry
|
||||
{
|
||||
@@ -36,35 +36,45 @@ template
|
||||
>
|
||||
struct get_turn_without_info
|
||||
{
|
||||
typedef strategy_intersection
|
||||
<
|
||||
typename cs_tag<typename TurnInfo::point_type>::type,
|
||||
Point1,
|
||||
Point2,
|
||||
typename TurnInfo::point_type
|
||||
> si;
|
||||
|
||||
typedef typename si::segment_intersection_strategy_type strategy;
|
||||
|
||||
|
||||
|
||||
template <typename RescalePolicy, typename OutputIterator>
|
||||
template <typename RobustPolicy, typename OutputIterator>
|
||||
static inline OutputIterator apply(
|
||||
Point1 const& pi, Point1 const& pj, Point1 const& pk,
|
||||
Point2 const& qi, Point2 const& qj, Point2 const& qk,
|
||||
bool /*is_p_first*/, bool /*is_p_last*/,
|
||||
bool /*is_q_first*/, bool /*is_q_last*/,
|
||||
TurnInfo const& ,
|
||||
RescalePolicy const& rescale_policy,
|
||||
RobustPolicy const& robust_policy,
|
||||
OutputIterator out)
|
||||
{
|
||||
typedef strategy_intersection
|
||||
<
|
||||
typename cs_tag<typename TurnInfo::point_type>::type,
|
||||
Point1,
|
||||
Point2,
|
||||
typename TurnInfo::point_type,
|
||||
RobustPolicy
|
||||
> si;
|
||||
|
||||
typedef typename si::segment_intersection_strategy_type strategy;
|
||||
|
||||
typedef model::referring_segment<Point1 const> segment_type1;
|
||||
typedef model::referring_segment<Point1 const> segment_type2;
|
||||
segment_type1 p1(pi, pj), p2(pj, pk);
|
||||
segment_type2 q1(qi, qj), q2(qj, qk);
|
||||
segment_type1 p1(pi, pj);
|
||||
segment_type2 q1(qi, qj);
|
||||
|
||||
//
|
||||
typename strategy::return_type result = strategy::apply(p1, q1);
|
||||
typedef typename geometry::robust_point_type
|
||||
<
|
||||
Point1, RobustPolicy
|
||||
>::type robust_point_type;
|
||||
|
||||
robust_point_type pi_rob, pj_rob, qi_rob, qj_rob;
|
||||
geometry::recalculate(pi_rob, pi, robust_policy);
|
||||
geometry::recalculate(pj_rob, pj, robust_policy);
|
||||
geometry::recalculate(qi_rob, qi, robust_policy);
|
||||
geometry::recalculate(qj_rob, qj, robust_policy);
|
||||
typename strategy::return_type result
|
||||
= strategy::apply(p1, q1, robust_policy,
|
||||
pi_rob, pj_rob, qi_rob, qj_rob);
|
||||
|
||||
for (std::size_t i = 0; i < result.template get<0>().count; i++)
|
||||
{
|
||||
@@ -88,10 +98,12 @@ template
|
||||
<
|
||||
typename Geometry1,
|
||||
typename Geometry2,
|
||||
typename RobustPolicy,
|
||||
typename Turns
|
||||
>
|
||||
inline void get_intersection_points(Geometry1 const& geometry1,
|
||||
Geometry2 const& geometry2,
|
||||
RobustPolicy const& robust_policy,
|
||||
Turns& turns)
|
||||
{
|
||||
concept::check_concepts_and_equal_dimensions<Geometry1 const, Geometry2 const>();
|
||||
@@ -108,7 +120,8 @@ inline void get_intersection_points(Geometry1 const& geometry1,
|
||||
typename cs_tag<Geometry1>::type,
|
||||
Geometry1,
|
||||
Geometry2,
|
||||
typename boost::range_value<Turns>::type
|
||||
typename point_type<Geometry1>::type, // TODO from both
|
||||
RobustPolicy
|
||||
>::segment_intersection_strategy_type segment_intersection_strategy_type;
|
||||
|
||||
detail::get_turns::no_interrupt_policy interrupt_policy;
|
||||
@@ -135,7 +148,7 @@ inline void get_intersection_points(Geometry1 const& geometry1,
|
||||
>::type::apply(
|
||||
0, geometry1,
|
||||
1, geometry2,
|
||||
detail::no_rescale_policy(),
|
||||
robust_policy,
|
||||
turns, interrupt_policy);
|
||||
}
|
||||
|
||||
|
||||
@@ -36,15 +36,10 @@ namespace detail { namespace overlay
|
||||
template <typename Point1>
|
||||
struct get_relative_order
|
||||
{
|
||||
typedef strategy_intersection
|
||||
typedef typename strategy::side::services::default_strategy
|
||||
<
|
||||
typename cs_tag<Point1>::type,
|
||||
Point1,
|
||||
Point1,
|
||||
Point1
|
||||
> si;
|
||||
|
||||
typedef typename si::side_strategy_type strategy;
|
||||
typename cs_tag<Point1>::type
|
||||
>::type strategy;
|
||||
|
||||
template <typename Point>
|
||||
static inline int value_via_product(Point const& ti, Point const& tj,
|
||||
|
||||
@@ -16,9 +16,12 @@
|
||||
|
||||
#include <boost/geometry/algorithms/convert.hpp>
|
||||
#include <boost/geometry/algorithms/detail/overlay/turn_info.hpp>
|
||||
#include <boost/geometry/algorithms/detail/recalculate.hpp>
|
||||
|
||||
#include <boost/geometry/geometries/segment.hpp>
|
||||
|
||||
#include <boost/geometry/policies/robustness/robust_point_type.hpp>
|
||||
|
||||
|
||||
// Silence warning C4127: conditional expression is constant
|
||||
#if defined(_MSC_VER)
|
||||
@@ -57,13 +60,16 @@ public:
|
||||
namespace detail { namespace overlay
|
||||
{
|
||||
|
||||
template <typename Point1, typename Point2>
|
||||
template <typename PointP, typename PointQ,
|
||||
typename Pi = PointP, typename Pj = PointP, typename Pk = PointP,
|
||||
typename Qi = PointQ, typename Qj = PointQ, typename Qk = PointQ
|
||||
>
|
||||
struct side_calculator
|
||||
{
|
||||
typedef boost::geometry::strategy::side::side_by_triangle<> side; // todo: get from coordinate system
|
||||
|
||||
inline side_calculator(Point1 const& pi, Point1 const& pj, Point1 const& pk,
|
||||
Point2 const& qi, Point2 const& qj, Point2 const& qk)
|
||||
inline side_calculator(Pi const& pi, Pj const& pj, Pk const& pk,
|
||||
Qi const& qi, Qj const& qj, Qk const& qk)
|
||||
: m_pi(pi), m_pj(pj), m_pk(pk)
|
||||
, m_qi(qi), m_qj(qj), m_qk(qk)
|
||||
{}
|
||||
@@ -76,12 +82,12 @@ struct side_calculator
|
||||
inline int pk_wrt_q2() const { return side::apply(m_qj, m_qk, m_pk); }
|
||||
inline int qk_wrt_p2() const { return side::apply(m_pj, m_pk, m_qk); }
|
||||
|
||||
Point1 const& m_pi;
|
||||
Point1 const& m_pj;
|
||||
Point1 const& m_pk;
|
||||
Point2 const& m_qi;
|
||||
Point2 const& m_qj;
|
||||
Point2 const& m_qk;
|
||||
Pi const& m_pi;
|
||||
Pj const& m_pj;
|
||||
Pk const& m_pk;
|
||||
Qi const& m_qi;
|
||||
Qj const& m_qj;
|
||||
Qk const& m_qk;
|
||||
};
|
||||
|
||||
struct base_turn_handler
|
||||
@@ -124,6 +130,26 @@ struct base_turn_handler
|
||||
{
|
||||
both(ti, condition ? operation_union : operation_intersection);
|
||||
}
|
||||
|
||||
template <typename TurnInfo, typename IntersectionInfo>
|
||||
static inline void assign_point(TurnInfo& ti,
|
||||
method_type method,
|
||||
IntersectionInfo const& info, int index)
|
||||
{
|
||||
ti.method = method;
|
||||
BOOST_ASSERT(index >= 0 && unsigned(index) < info.count); // TODO remove this
|
||||
geometry::convert(info.intersections[index], ti.point);
|
||||
ti.operations[0].fraction = info.fractions[index].robust_ra;
|
||||
ti.operations[1].fraction = info.fractions[index].robust_rb;
|
||||
}
|
||||
|
||||
template <typename IntersectionInfo>
|
||||
static inline int non_opposite_to_index(IntersectionInfo const& info)
|
||||
{
|
||||
return info.fractions[0].robust_rb < info.fractions[1].robust_rb
|
||||
? 1 : 0;
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
|
||||
@@ -151,8 +177,7 @@ struct touch_interior : public base_turn_handler
|
||||
DirInfo const& dir_info,
|
||||
SidePolicy const& side)
|
||||
{
|
||||
ti.method = method_touch_interior;
|
||||
geometry::convert(intersection_info.intersections[0], ti.point);
|
||||
assign_point(ti, method_touch_interior, intersection_info, 0);
|
||||
|
||||
// Both segments of q touch segment p somewhere in its interior
|
||||
// 1) We know: if q comes from LEFT or RIGHT
|
||||
@@ -271,8 +296,7 @@ struct touch : public base_turn_handler
|
||||
DirInfo const& dir_info,
|
||||
SidePolicy const& side)
|
||||
{
|
||||
ti.method = method_touch;
|
||||
geometry::convert(intersection_info.intersections[0], ti.point);
|
||||
assign_point(ti, method_touch, intersection_info, 0);
|
||||
|
||||
int const side_qi_p1 = dir_info.sides.template get<1, 0>();
|
||||
int const side_qk_p1 = side.qk_wrt_p1();
|
||||
@@ -286,13 +310,9 @@ struct touch : public base_turn_handler
|
||||
int const side_pk_p = side.pk_wrt_p1();
|
||||
int const side_qk_q = side.qk_wrt_q1();
|
||||
|
||||
bool const both_continue = side_pk_p == 0 && side_qk_q == 0;
|
||||
bool const robustness_issue_in_continue = both_continue && side_pk_q2 != 0;
|
||||
|
||||
bool const q_turns_left = side_qk_q == 1;
|
||||
bool const block_q = side_qk_p1 == 0
|
||||
&& ! same(side_qi_p1, side_qk_q)
|
||||
&& ! robustness_issue_in_continue
|
||||
;
|
||||
|
||||
// If Pk at same side as Qi/Qk
|
||||
@@ -464,13 +484,12 @@ struct equal : public base_turn_handler
|
||||
Point1 const& , Point1 const& , Point1 const& ,
|
||||
Point2 const& , Point2 const& , Point2 const& ,
|
||||
TurnInfo& ti,
|
||||
IntersectionInfo const& intersection_info,
|
||||
DirInfo const& ,
|
||||
IntersectionInfo const& info,
|
||||
DirInfo const& ,
|
||||
SidePolicy const& side)
|
||||
{
|
||||
ti.method = method_equal;
|
||||
// Copy the SECOND intersection point
|
||||
geometry::convert(intersection_info.intersections[1], ti.point);
|
||||
// Copy the intersection point in TO direction
|
||||
assign_point(ti, method_equal, info, non_opposite_to_index(info));
|
||||
|
||||
int const side_pk_q2 = side.pk_wrt_q2();
|
||||
int const side_pk_p = side.pk_wrt_p1();
|
||||
@@ -538,7 +557,7 @@ struct equal_opposite : public base_turn_handler
|
||||
}
|
||||
for (unsigned int i = 0; i < intersection_info.count; i++)
|
||||
{
|
||||
geometry::convert(intersection_info.intersections[i], tp.point);
|
||||
assign_point(tp, method_none, intersection_info, i);
|
||||
AssignPolicy::apply(tp, pi, qi, intersection_info, dir_info);
|
||||
*out++ = tp;
|
||||
}
|
||||
@@ -596,12 +615,12 @@ struct collinear : public base_turn_handler
|
||||
Point1 const& , Point1 const& , Point1 const& ,
|
||||
Point2 const& , Point2 const& , Point2 const& ,
|
||||
TurnInfo& ti,
|
||||
IntersectionInfo const& intersection_info,
|
||||
IntersectionInfo const& info,
|
||||
DirInfo const& dir_info,
|
||||
SidePolicy const& side)
|
||||
{
|
||||
ti.method = method_collinear;
|
||||
geometry::convert(intersection_info.intersections[1], ti.point);
|
||||
// Copy the intersection point in TO direction
|
||||
assign_point(ti, method_collinear, info, non_opposite_to_index(info));
|
||||
|
||||
int const arrival = dir_info.arrival[0];
|
||||
// Should not be 0, this is checked before
|
||||
@@ -616,9 +635,6 @@ struct collinear : public base_turn_handler
|
||||
: side_q
|
||||
;
|
||||
|
||||
int const side_pk = side.pk_wrt_q1();
|
||||
int const side_qk = side.qk_wrt_p1();
|
||||
|
||||
// See comments above,
|
||||
// resulting in a strange sort of mathematic rule here:
|
||||
// The arrival-info multiplied by the relevant side
|
||||
@@ -626,15 +642,7 @@ struct collinear : public base_turn_handler
|
||||
|
||||
int const product = arrival * side_p_or_q;
|
||||
|
||||
// Robustness: side_p is supposed to be equal to side_pk (because p/q are collinear)
|
||||
// and side_q to side_qk
|
||||
bool const robustness_issue = side_pk != side_p || side_qk != side_q;
|
||||
|
||||
if (robustness_issue)
|
||||
{
|
||||
handle_robustness(ti, arrival, side_p, side_q, side_pk, side_qk);
|
||||
}
|
||||
else if(product == 0)
|
||||
if(product == 0)
|
||||
{
|
||||
both(ti, operation_continue);
|
||||
}
|
||||
@@ -644,37 +652,6 @@ struct collinear : public base_turn_handler
|
||||
}
|
||||
}
|
||||
|
||||
static inline void handle_robustness(TurnInfo& ti, int arrival,
|
||||
int side_p, int side_q, int side_pk, int side_qk)
|
||||
{
|
||||
// We take the longer one, i.e. if q arrives in p (arrival == -1),
|
||||
// then p exceeds q and we should take p for a union...
|
||||
|
||||
bool use_p_for_union = arrival == -1;
|
||||
|
||||
// ... unless one of the sides consistently directs to the other side
|
||||
int const consistent_side_p = side_p == side_pk ? side_p : 0;
|
||||
int const consistent_side_q = side_q == side_qk ? side_q : 0;
|
||||
if (arrival == -1 && (consistent_side_p == -1 || consistent_side_q == 1))
|
||||
{
|
||||
use_p_for_union = false;
|
||||
}
|
||||
if (arrival == 1 && (consistent_side_p == 1 || consistent_side_q == -1))
|
||||
{
|
||||
use_p_for_union = true;
|
||||
}
|
||||
|
||||
//std::cout << "ROBUSTNESS -> Collinear "
|
||||
// << " arr: " << arrival
|
||||
// << " dir: " << side_p << " " << side_q
|
||||
// << " rev: " << side_pk << " " << side_qk
|
||||
// << " cst: " << cside_p << " " << cside_q
|
||||
// << std::boolalpha << " " << use_p_for_union
|
||||
// << std::endl;
|
||||
|
||||
ui_else_iu(use_p_for_union, ti);
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
template
|
||||
@@ -716,21 +693,12 @@ private :
|
||||
typename IntersectionInfo
|
||||
>
|
||||
static inline bool set_tp(Point const& , Point const& , Point const& , int side_rk_r,
|
||||
bool const handle_robustness, Point const& , Point const& , int side_rk_s,
|
||||
bool const handle_robustness,
|
||||
Point const& , Point const& , int side_rk_s,
|
||||
TurnInfo& tp, IntersectionInfo const& intersection_info)
|
||||
{
|
||||
if (handle_robustness)
|
||||
{
|
||||
// For Robustness: also calculate rk w.r.t. the other line. Because they are collinear opposite, that direction should be the reverse of the first direction.
|
||||
// If this is not the case, we make it all-collinear, so zero
|
||||
if (side_rk_r != 0 && side_rk_r != -side_rk_s)
|
||||
{
|
||||
#ifdef BOOST_GEOMETRY_DEBUG_ROBUSTNESS
|
||||
std::cout << "Robustness correction: " << side_rk_r << " / " << side_rk_s << std::endl;
|
||||
#endif
|
||||
side_rk_r = 0;
|
||||
}
|
||||
}
|
||||
boost::ignore_unused_variable_warning(handle_robustness);
|
||||
boost::ignore_unused_variable_warning(side_rk_s);
|
||||
|
||||
operation_type blocked = operation_blocked;
|
||||
switch(side_rk_r)
|
||||
@@ -768,7 +736,7 @@ private :
|
||||
// If P arrives within Q, set info on P (which is done above, index=0),
|
||||
// this turn-info belongs to the second intersection point, index=1
|
||||
// (see e.g. figure CLO1)
|
||||
geometry::convert(intersection_info.intersections[1 - Index], tp.point);
|
||||
assign_point(tp, method_collinear, intersection_info, 1 - Index);
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -826,8 +794,6 @@ public:
|
||||
{
|
||||
TurnInfo tp = tp_model;
|
||||
|
||||
tp.method = method_collinear;
|
||||
|
||||
// If P arrives within Q, there is a turn dependent on P
|
||||
if ( dir_info.arrival[0] == 1
|
||||
&& is_pk_valid
|
||||
@@ -862,7 +828,7 @@ public:
|
||||
}
|
||||
for (unsigned int i = 0; i < intersection_info.count; i++)
|
||||
{
|
||||
geometry::convert(intersection_info.intersections[i], tp.point);
|
||||
assign_point(tp, method_collinear, intersection_info, i);
|
||||
AssignPolicy::apply(tp, pi, qi, intersection_info, dir_info);
|
||||
*out++ = tp;
|
||||
}
|
||||
@@ -893,8 +859,7 @@ struct crosses : public base_turn_handler
|
||||
IntersectionInfo const& intersection_info,
|
||||
DirInfo const& dir_info)
|
||||
{
|
||||
ti.method = method_crosses;
|
||||
geometry::convert(intersection_info.intersections[0], ti.point);
|
||||
assign_point(ti, method_crosses, intersection_info, 0);
|
||||
|
||||
// In all casees:
|
||||
// If Q crosses P from left to right
|
||||
@@ -908,14 +873,12 @@ struct crosses : public base_turn_handler
|
||||
}
|
||||
};
|
||||
|
||||
template<typename TurnInfo>
|
||||
struct only_convert
|
||||
struct only_convert : public base_turn_handler
|
||||
{
|
||||
template<typename IntersectionInfo>
|
||||
template<typename TurnInfo, typename IntersectionInfo>
|
||||
static inline void apply(TurnInfo& ti, IntersectionInfo const& intersection_info)
|
||||
{
|
||||
ti.method = method_collinear;
|
||||
geometry::convert(intersection_info.intersections[0], ti.point);
|
||||
assign_point(ti, method_none, intersection_info, 0); // was collinear
|
||||
ti.operations[0].operation = operation_continue;
|
||||
ti.operations[1].operation = operation_continue;
|
||||
}
|
||||
@@ -972,7 +935,7 @@ struct get_turn_info
|
||||
typename Point1,
|
||||
typename Point2,
|
||||
typename TurnInfo,
|
||||
typename RescalePolicy,
|
||||
typename RobustPolicy,
|
||||
typename OutputIterator
|
||||
>
|
||||
static inline OutputIterator apply(
|
||||
@@ -981,27 +944,42 @@ struct get_turn_info
|
||||
bool /*is_p_first*/, bool /*is_p_last*/,
|
||||
bool /*is_q_first*/, bool /*is_q_last*/,
|
||||
TurnInfo const& tp_model,
|
||||
RescalePolicy const& , // TODO: this will be used. rescale_policy,
|
||||
RobustPolicy const& robust_policy,
|
||||
OutputIterator out)
|
||||
{
|
||||
typedef typename geometry::robust_point_type
|
||||
<
|
||||
Point1, RobustPolicy
|
||||
>::type robust_point_type;
|
||||
|
||||
robust_point_type pi_rob, pj_rob, pk_rob, qi_rob, qj_rob, qk_rob;
|
||||
geometry::recalculate(pi_rob, pi, robust_policy);
|
||||
geometry::recalculate(pj_rob, pj, robust_policy);
|
||||
geometry::recalculate(pk_rob, pk, robust_policy);
|
||||
geometry::recalculate(qi_rob, qi, robust_policy);
|
||||
geometry::recalculate(qj_rob, qj, robust_policy);
|
||||
geometry::recalculate(qk_rob, qk, robust_policy);
|
||||
|
||||
typedef model::referring_segment<Point1 const> segment_type1;
|
||||
typedef model::referring_segment<Point2 const> segment_type2;
|
||||
segment_type1 p1(pi, pj), p2(pj, pk);
|
||||
segment_type2 q1(qi, qj), q2(qj, qk);
|
||||
segment_type1 p1(pi, pj);
|
||||
segment_type2 q1(qi, qj);
|
||||
|
||||
side_calculator<Point1, Point2> side_calc(pi, pj, pk, qi, qj, qk);
|
||||
side_calculator<robust_point_type, robust_point_type> side_calc(pi_rob, pj_rob, pk_rob, qi_rob, qj_rob, qk_rob);
|
||||
|
||||
typedef strategy_intersection
|
||||
<
|
||||
typename cs_tag<typename TurnInfo::point_type>::type,
|
||||
Point1,
|
||||
Point2,
|
||||
typename TurnInfo::point_type
|
||||
typename TurnInfo::point_type,
|
||||
RobustPolicy
|
||||
> si;
|
||||
|
||||
typedef typename si::segment_intersection_strategy_type strategy;
|
||||
|
||||
typename strategy::return_type result = strategy::apply(p1, q1);
|
||||
typename strategy::return_type result = strategy::apply(p1, q1,
|
||||
robust_policy, pi_rob, pj_rob, qi_rob, qj_rob);
|
||||
|
||||
char const method = result.template get<1>().how;
|
||||
|
||||
@@ -1017,7 +995,7 @@ struct get_turn_info
|
||||
if (AssignPolicy::include_no_turn
|
||||
&& result.template get<0>().count > 0)
|
||||
{
|
||||
only_convert<TurnInfo>::apply(tp,
|
||||
only_convert::apply(tp,
|
||||
result.template get<0>());
|
||||
AssignPolicy::apply(tp, pi, qi, result.template get<0>(), result.template get<1>());
|
||||
*out++ = tp;
|
||||
@@ -1044,7 +1022,7 @@ struct get_turn_info
|
||||
else
|
||||
{
|
||||
// Swap p/q
|
||||
side_calculator<Point1, Point2> swapped_side_calc(qi, qj, qk, pi, pj, pk);
|
||||
side_calculator<Point2, Point1> swapped_side_calc(qi, qj, qk, pi, pj, pk);
|
||||
policy::template apply<1>(qi, qj, qk, pi, pj, pk,
|
||||
tp, result.template get<0>(), result.template get<1>(),
|
||||
swapped_side_calc);
|
||||
@@ -1132,7 +1110,7 @@ struct get_turn_info
|
||||
// degenerate points
|
||||
if (AssignPolicy::include_degenerate)
|
||||
{
|
||||
only_convert<TurnInfo>::apply(tp, result.template get<0>());
|
||||
only_convert::apply(tp, result.template get<0>());
|
||||
AssignPolicy::apply(tp, pi, qi, result.template get<0>(), result.template get<1>());
|
||||
*out++ = tp;
|
||||
}
|
||||
|
||||
@@ -21,10 +21,13 @@ namespace boost { namespace geometry {
|
||||
#ifndef DOXYGEN_NO_DETAIL
|
||||
namespace detail { namespace overlay {
|
||||
|
||||
// TURN_OPERATION
|
||||
|
||||
enum turn_position { position_middle, position_front, position_back };
|
||||
|
||||
template <typename SegmentRatio>
|
||||
struct turn_operation_linear
|
||||
: public turn_operation
|
||||
: public turn_operation<SegmentRatio>
|
||||
{
|
||||
turn_operation_linear()
|
||||
: position(position_middle)
|
||||
@@ -35,6 +38,154 @@ struct turn_operation_linear
|
||||
bool is_collinear; // valid only for Linear geometry
|
||||
};
|
||||
|
||||
template <typename Point1, typename Point2, typename TurnPoint, typename RobustPolicy>
|
||||
class intersection_info
|
||||
{
|
||||
typedef typename strategy_intersection
|
||||
<
|
||||
typename cs_tag<TurnPoint>::type,
|
||||
Point1,
|
||||
Point2,
|
||||
TurnPoint,
|
||||
RobustPolicy
|
||||
>::segment_intersection_strategy_type strategy;
|
||||
|
||||
public:
|
||||
typedef model::referring_segment<Point1 const> segment_type1;
|
||||
typedef model::referring_segment<Point2 const> segment_type2;
|
||||
typedef side_calculator<Point1, Point2> side_calculator_type;
|
||||
|
||||
typedef typename strategy::return_type result_type;
|
||||
typedef typename boost::tuples::element<0, result_type>::type i_info_type; // intersection_info
|
||||
typedef typename boost::tuples::element<1, result_type>::type d_info_type; // dir_info
|
||||
|
||||
intersection_info(Point1 const& pi, Point1 const& pj, Point1 const& pk,
|
||||
Point2 const& qi, Point2 const& qj, Point2 const& qk,
|
||||
RobustPolicy const& robust_policy)
|
||||
: m_result(strategy::apply(segment_type1(pi, pj),
|
||||
segment_type2(qi, qj),
|
||||
robust_policy))
|
||||
, m_side_calc(pi, pj, pk, qi, qj, qk)
|
||||
, m_robust_policy(robust_policy)
|
||||
{}
|
||||
|
||||
inline Point1 const& pi() const { return m_side_calc.m_pi; }
|
||||
inline Point1 const& pj() const { return m_side_calc.m_pj; }
|
||||
inline Point1 const& pk() const { return m_side_calc.m_pk; }
|
||||
|
||||
inline Point2 const& qi() const { return m_side_calc.m_qi; }
|
||||
inline Point2 const& qj() const { return m_side_calc.m_qj; }
|
||||
inline Point2 const& qk() const { return m_side_calc.m_qk; }
|
||||
|
||||
inline side_calculator_type const& sides() const { return m_side_calc; }
|
||||
inline result_type const& result() const { return m_result; }
|
||||
inline i_info_type const& i_info() const { return m_result.template get<0>(); }
|
||||
inline d_info_type const& d_info() const { return m_result.template get<1>(); }
|
||||
|
||||
// TODO: not it's more like is_spike_ip_p
|
||||
inline bool is_spike_p() const
|
||||
{
|
||||
if ( m_side_calc.pk_wrt_p1() == 0 )
|
||||
{
|
||||
if ( ! is_ip_j<0>() )
|
||||
return false;
|
||||
|
||||
int const qk_p1 = m_side_calc.qk_wrt_p1();
|
||||
int const qk_p2 = m_side_calc.qk_wrt_p2();
|
||||
|
||||
if ( qk_p1 == -qk_p2 )
|
||||
{
|
||||
if ( qk_p1 == 0 )
|
||||
{
|
||||
return is_spike_of_collinear(pi(), pj(), pk());
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
// TODO: not it's more like is_spike_ip_q
|
||||
inline bool is_spike_q() const
|
||||
{
|
||||
if ( m_side_calc.qk_wrt_q1() == 0 )
|
||||
{
|
||||
if ( ! is_ip_j<1>() )
|
||||
return false;
|
||||
|
||||
int const pk_q1 = m_side_calc.pk_wrt_q1();
|
||||
int const pk_q2 = m_side_calc.pk_wrt_q2();
|
||||
|
||||
if ( pk_q1 == -pk_q2 )
|
||||
{
|
||||
if ( pk_q1 == 0 )
|
||||
{
|
||||
return is_spike_of_collinear(qi(), qj(), qk());
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
private:
|
||||
template <typename Point>
|
||||
inline bool is_spike_of_collinear(Point const& i, Point const& j, Point const& k) const
|
||||
{
|
||||
typedef model::referring_segment<Point const> seg_t;
|
||||
|
||||
typedef strategy_intersection
|
||||
<
|
||||
typename cs_tag<Point>::type, Point, Point, Point, RobustPolicy
|
||||
> si;
|
||||
|
||||
typedef typename si::segment_intersection_strategy_type strategy;
|
||||
|
||||
typename strategy::return_type result
|
||||
= strategy::apply(seg_t(i, j), seg_t(j, k), m_robust_policy);
|
||||
|
||||
return result.template get<0>().count == 2;
|
||||
}
|
||||
|
||||
template <std::size_t OpId>
|
||||
bool is_ip_j() const
|
||||
{
|
||||
int arrival = d_info().arrival[OpId];
|
||||
bool same_dirs = d_info().dir_a == 0 && d_info().dir_b == 0;
|
||||
|
||||
if ( same_dirs )
|
||||
{
|
||||
if ( i_info().count == 2 )
|
||||
{
|
||||
if ( ! d_info().opposite )
|
||||
{
|
||||
return arrival != -1;
|
||||
}
|
||||
else
|
||||
{
|
||||
return arrival != -1;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
return arrival == 0;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
return arrival == 1;
|
||||
}
|
||||
}
|
||||
|
||||
result_type m_result;
|
||||
side_calculator_type m_side_calc;
|
||||
RobustPolicy const& m_robust_policy;
|
||||
};
|
||||
|
||||
// SEGMENT_INTERSECTION RESULT
|
||||
|
||||
// C H0 H1 A0 A1 O IP1 IP2
|
||||
@@ -117,170 +268,99 @@ struct turn_operation_linear
|
||||
// |--------> 1 0 1 0 1 F u/x (P is vertical)
|
||||
//
|
||||
|
||||
template <typename AssignPolicy, bool EnableFirst, bool EnableLast>
|
||||
struct get_turn_info_for_endpoint
|
||||
class linear_intersections
|
||||
{
|
||||
BOOST_STATIC_ASSERT(EnableFirst || EnableLast);
|
||||
|
||||
template<typename Point1,
|
||||
typename Point2,
|
||||
typename TurnInfo,
|
||||
typename IntersectionResult,
|
||||
typename OutputIterator
|
||||
>
|
||||
static inline bool apply(Point1 const& pi, Point1 const& pj, Point1 const& pk,
|
||||
Point2 const& qi, Point2 const& qj, Point2 const& qk,
|
||||
bool is_p_first, bool is_p_last,
|
||||
bool is_q_first, bool is_q_last,
|
||||
TurnInfo const& tp_model,
|
||||
IntersectionResult const& result,
|
||||
method_type /*method*/,
|
||||
OutputIterator out)
|
||||
public:
|
||||
template <typename Point1, typename Point2, typename IntersectionResult>
|
||||
linear_intersections(Point1 const& pi,
|
||||
Point2 const& qi,
|
||||
IntersectionResult const& result,
|
||||
bool is_p_last, bool is_q_last)
|
||||
{
|
||||
std::size_t ip_count = result.template get<0>().count;
|
||||
// no intersection points
|
||||
if ( ip_count == 0 )
|
||||
return false;
|
||||
|
||||
int segment_index0 = tp_model.operations[0].seg_id.segment_index;
|
||||
int segment_index1 = tp_model.operations[1].seg_id.segment_index;
|
||||
BOOST_ASSERT(segment_index0 >= 0 && segment_index1 >= 0);
|
||||
|
||||
if ( !is_p_first && !is_p_last && !is_q_first && !is_q_last )
|
||||
return false;
|
||||
|
||||
operation_type p_operation0 = operation_none;
|
||||
operation_type q_operation0 = operation_none;
|
||||
operation_type p_operation1 = operation_none;
|
||||
operation_type q_operation1 = operation_none;
|
||||
bool p0i, p0j, q0i, q0j; // assign false?
|
||||
bool p1i, p1j, q1i, q1j; // assign false?
|
||||
|
||||
bool opposite = result.template get<1>().opposite;
|
||||
|
||||
{
|
||||
int p_how = result.template get<1>().how_a;
|
||||
int q_how = result.template get<1>().how_b;
|
||||
int p_arrival = result.template get<1>().arrival[0];
|
||||
int q_arrival = result.template get<1>().arrival[1];
|
||||
bool same_dirs = result.template get<1>().dir_a == 0 && result.template get<1>().dir_b == 0;
|
||||
|
||||
handle_segment(is_p_first, is_p_last, p_how, p_arrival,
|
||||
is_q_first, is_q_last, q_how, q_arrival,
|
||||
opposite, ip_count, same_dirs,
|
||||
result.template get<0>().intersections[0],
|
||||
result.template get<0>().intersections[1],
|
||||
p_operation0, q_operation0, p_operation1, q_operation1,
|
||||
p0i, p0j, q0i, q0j,
|
||||
p1i, p1j, q1i, q1j,
|
||||
pi, pj, pk, qi, qj, qk);
|
||||
}
|
||||
|
||||
bool append0_last
|
||||
= analyse_segment_and_assign_ip(pi, pj, pk, qi, qj, qk,
|
||||
result.template get<0>().intersections[0],
|
||||
is_p_first, is_p_last, is_q_first, is_q_last,
|
||||
p0i, p0j, q0i, q0j,
|
||||
p_operation0, q_operation0,
|
||||
tp_model, result, out);
|
||||
|
||||
// NOTE: opposite && ip_count == 1 may be true!
|
||||
|
||||
// don't ignore only for collinear opposite
|
||||
bool result_ignore_ip0 = append0_last && ( ip_count == 1 || !opposite );
|
||||
|
||||
if ( p_operation1 == operation_none )
|
||||
return result_ignore_ip0;
|
||||
|
||||
bool append1_last
|
||||
= analyse_segment_and_assign_ip(pi, pj, pk, qi, qj, qk,
|
||||
result.template get<0>().intersections[1],
|
||||
is_p_first, is_p_last, is_q_first, is_q_last,
|
||||
p1i, p1j, q1i, q1j,
|
||||
p_operation1, q_operation1,
|
||||
tp_model, result, out);
|
||||
|
||||
// don't ignore only for collinear opposite
|
||||
bool result_ignore_ip1 = append1_last && !opposite /*&& ip_count == 2*/;
|
||||
|
||||
return result_ignore_ip0 || result_ignore_ip1;
|
||||
}
|
||||
|
||||
template<typename Point, typename Point1, typename Point2>
|
||||
static inline
|
||||
void handle_segment(bool /*first_a*/, bool last_a, int how_a, int arrival_a,
|
||||
bool /*first_b*/, bool last_b, int how_b, int arrival_b,
|
||||
bool opposite, std::size_t ip_count, bool same_dirs/*collinear*/,
|
||||
Point const& ip0, Point const& /*ip1*/,
|
||||
operation_type & op0_a, operation_type & op0_b,
|
||||
operation_type & op1_a, operation_type & op1_b,
|
||||
bool & i0_a, bool & j0_a, bool & i0_b, bool & j0_b,
|
||||
bool & i1_a, bool & j1_a, bool & i1_b, bool & j1_b,
|
||||
Point1 const& pi, Point1 const& /*pj*/, Point1 const& /*pk*/,
|
||||
Point2 const& qi, Point2 const& /*qj*/, Point2 const& /*qk*/)
|
||||
{
|
||||
namespace ov = overlay;
|
||||
|
||||
i0_a = false; j0_a = false; i0_b = false; j0_b = false;
|
||||
i1_a = false; j1_a = false; i1_b = false; j1_b = false;
|
||||
int arrival_a = result.template get<1>().arrival[0];
|
||||
int arrival_b = result.template get<1>().arrival[1];
|
||||
bool same_dirs = result.template get<1>().dir_a == 0
|
||||
&& result.template get<1>().dir_b == 0;
|
||||
|
||||
if ( same_dirs )
|
||||
{
|
||||
if ( ip_count == 2 )
|
||||
if ( result.template get<0>().count == 2 )
|
||||
{
|
||||
BOOST_ASSERT( how_a == 0 && how_b == 0 );
|
||||
|
||||
if ( !opposite )
|
||||
if ( ! result.template get<1>().opposite )
|
||||
{
|
||||
op0_a = operation_intersection;
|
||||
op0_b = operation_intersection;
|
||||
op1_a = arrival_to_union_or_blocked(arrival_a, last_a);
|
||||
op1_b = arrival_to_union_or_blocked(arrival_b, last_b);
|
||||
ips[0].p_operation = operation_intersection;
|
||||
ips[0].q_operation = operation_intersection;
|
||||
ips[1].p_operation = union_or_blocked_same_dirs(arrival_a, is_p_last);
|
||||
ips[1].q_operation = union_or_blocked_same_dirs(arrival_b, is_q_last);
|
||||
|
||||
i0_a = equals::equals_point_point(pi, ip0);
|
||||
i0_b = equals::equals_point_point(qi, ip0);
|
||||
j1_a = arrival_a != -1;
|
||||
j1_b = arrival_b != -1;
|
||||
ips[0].is_pi
|
||||
= equals::equals_point_point(
|
||||
pi, result.template get<0>().intersections[0]);
|
||||
ips[0].is_qi
|
||||
= equals::equals_point_point(
|
||||
qi, result.template get<0>().intersections[0]);
|
||||
ips[1].is_pj = arrival_a != -1;
|
||||
ips[1].is_qj = arrival_b != -1;
|
||||
}
|
||||
else
|
||||
{
|
||||
op0_a = operation_intersection;
|
||||
op0_b = arrival_to_union_or_blocked(arrival_b, last_b);
|
||||
op1_a = arrival_to_union_or_blocked(arrival_a, last_a);
|
||||
op1_b = operation_intersection;
|
||||
ips[0].p_operation = operation_intersection;
|
||||
ips[0].q_operation = union_or_blocked_same_dirs(arrival_b, is_q_last);
|
||||
ips[1].p_operation = union_or_blocked_same_dirs(arrival_a, is_p_last);
|
||||
ips[1].q_operation = operation_intersection;
|
||||
|
||||
i0_a = arrival_b != 1;
|
||||
j0_b = arrival_b != -1;
|
||||
j1_a = arrival_a != -1;
|
||||
i1_b = arrival_a != 1;
|
||||
ips[0].is_pi = arrival_b != 1;
|
||||
ips[0].is_qj = arrival_b != -1;
|
||||
ips[1].is_pj = arrival_a != -1;
|
||||
ips[1].is_qi = arrival_a != 1;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
BOOST_ASSERT(ip_count == 1);
|
||||
op0_a = arrival_to_union_or_blocked(arrival_a, last_a);
|
||||
op0_b = arrival_to_union_or_blocked(arrival_b, last_b);
|
||||
BOOST_ASSERT(result.template get<0>().count == 1);
|
||||
ips[0].p_operation = union_or_blocked_same_dirs(arrival_a, is_p_last);
|
||||
ips[0].q_operation = union_or_blocked_same_dirs(arrival_b, is_q_last);
|
||||
|
||||
i0_a = how_a == -1;
|
||||
i0_b = how_b == -1;
|
||||
j0_a = arrival_a == 0;
|
||||
j0_b = arrival_b == 0;
|
||||
ips[0].is_pi = arrival_a == -1;
|
||||
ips[0].is_qi = arrival_b == -1;
|
||||
ips[0].is_pj = arrival_a == 0;
|
||||
ips[0].is_qj = arrival_b == 0;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
op0_a = how_to_union_or_blocked(how_a, last_a);
|
||||
op0_b = how_to_union_or_blocked(how_b, last_b);
|
||||
ips[0].p_operation = union_or_blocked_different_dirs(arrival_a, is_p_last);
|
||||
ips[0].q_operation = union_or_blocked_different_dirs(arrival_b, is_q_last);
|
||||
|
||||
i0_a = how_a == -1;
|
||||
i0_b = how_b == -1;
|
||||
j0_a = how_a == 1;
|
||||
j0_b = how_b == 1;
|
||||
ips[0].is_pi = arrival_a == -1;
|
||||
ips[0].is_qi = arrival_b == -1;
|
||||
ips[0].is_pj = arrival_a == 1;
|
||||
ips[0].is_qj = arrival_b == 1;
|
||||
}
|
||||
}
|
||||
|
||||
struct ip_info
|
||||
{
|
||||
inline ip_info()
|
||||
: p_operation(operation_none), q_operation(operation_none)
|
||||
, is_pi(false), is_pj(false), is_qi(false), is_qj(false)
|
||||
{}
|
||||
|
||||
operation_type p_operation, q_operation;
|
||||
bool is_pi, is_pj, is_qi, is_qj;
|
||||
};
|
||||
|
||||
template <std::size_t I>
|
||||
ip_info const& get() const
|
||||
{
|
||||
BOOST_STATIC_ASSERT(I < 2);
|
||||
return ips[I];
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
// only if collinear (same_dirs)
|
||||
static inline operation_type arrival_to_union_or_blocked(int arrival, bool is_last)
|
||||
static inline operation_type union_or_blocked_same_dirs(int arrival, bool is_last)
|
||||
{
|
||||
if ( arrival == 1 )
|
||||
return operation_blocked;
|
||||
@@ -292,75 +372,171 @@ struct get_turn_info_for_endpoint
|
||||
}
|
||||
|
||||
// only if not collinear (!same_dirs)
|
||||
static inline operation_type how_to_union_or_blocked(int how, bool is_last)
|
||||
static inline operation_type union_or_blocked_different_dirs(int arrival, bool is_last)
|
||||
{
|
||||
if ( how == 1 )
|
||||
if ( arrival == 1 )
|
||||
//return operation_blocked;
|
||||
return is_last ? operation_blocked : operation_union;
|
||||
else
|
||||
return operation_union;
|
||||
}
|
||||
|
||||
ip_info ips[2];
|
||||
};
|
||||
|
||||
template <typename AssignPolicy, bool EnableFirst, bool EnableLast>
|
||||
struct get_turn_info_for_endpoint
|
||||
{
|
||||
BOOST_STATIC_ASSERT(EnableFirst || EnableLast);
|
||||
|
||||
template<typename Point1,
|
||||
typename Point2,
|
||||
typename TurnInfo,
|
||||
typename IntersectionInfo,
|
||||
typename OutputIterator
|
||||
>
|
||||
static inline bool apply(Point1 const& pi, Point1 const& pj, Point1 const& pk,
|
||||
Point2 const& qi, Point2 const& qj, Point2 const& qk,
|
||||
bool is_p_first, bool is_p_last,
|
||||
bool is_q_first, bool is_q_last,
|
||||
TurnInfo const& tp_model,
|
||||
IntersectionInfo const& inters,
|
||||
method_type /*method*/,
|
||||
OutputIterator out)
|
||||
{
|
||||
std::size_t ip_count = inters.i_info().count;
|
||||
// no intersection points
|
||||
if ( ip_count == 0 )
|
||||
return false;
|
||||
|
||||
int segment_index0 = tp_model.operations[0].seg_id.segment_index;
|
||||
int segment_index1 = tp_model.operations[1].seg_id.segment_index;
|
||||
BOOST_ASSERT(segment_index0 >= 0 && segment_index1 >= 0);
|
||||
|
||||
if ( !is_p_first && !is_p_last && !is_q_first && !is_q_last )
|
||||
return false;
|
||||
|
||||
linear_intersections intersections(pi, qi, inters.result(), is_p_last, is_q_last);
|
||||
|
||||
bool append0_last
|
||||
= analyse_segment_and_assign_ip(pi, pj, pk, qi, qj, qk,
|
||||
is_p_first, is_p_last, is_q_first, is_q_last,
|
||||
intersections.template get<0>(),
|
||||
tp_model, inters, 0, out);
|
||||
|
||||
// NOTE: opposite && ip_count == 1 may be true!
|
||||
bool opposite = inters.d_info().opposite;
|
||||
|
||||
// don't ignore only for collinear opposite
|
||||
bool result_ignore_ip0 = append0_last && ( ip_count == 1 || !opposite );
|
||||
|
||||
if ( intersections.template get<1>().p_operation == operation_none )
|
||||
return result_ignore_ip0;
|
||||
|
||||
bool append1_last
|
||||
= analyse_segment_and_assign_ip(pi, pj, pk, qi, qj, qk,
|
||||
is_p_first, is_p_last, is_q_first, is_q_last,
|
||||
intersections.template get<1>(),
|
||||
tp_model, inters, 1, out);
|
||||
|
||||
// don't ignore only for collinear opposite
|
||||
bool result_ignore_ip1 = append1_last && !opposite /*&& ip_count == 2*/;
|
||||
|
||||
return result_ignore_ip0 || result_ignore_ip1;
|
||||
}
|
||||
|
||||
template <typename Point1,
|
||||
typename Point2,
|
||||
typename Point,
|
||||
typename TurnInfo,
|
||||
typename IntersectionResult,
|
||||
typename IntersectionInfo,
|
||||
typename OutputIterator>
|
||||
static inline
|
||||
bool analyse_segment_and_assign_ip(Point1 const& pi, Point1 const& pj, Point1 const& pk,
|
||||
Point2 const& qi, Point2 const& qj, Point2 const& qk,
|
||||
Point const& ip,
|
||||
bool is_p_first, bool is_p_last,
|
||||
bool is_q_first, bool is_q_last,
|
||||
bool is_pi_ip, bool is_pj_ip,
|
||||
bool is_qi_ip, bool is_qj_ip,
|
||||
operation_type p_operation,
|
||||
operation_type q_operation,
|
||||
linear_intersections::ip_info const& ip_info,
|
||||
TurnInfo const& tp_model,
|
||||
IntersectionResult const& result,
|
||||
IntersectionInfo const& inters,
|
||||
int ip_index,
|
||||
OutputIterator out)
|
||||
{
|
||||
#ifdef BOOST_GEOMETRY_DEBUG_GET_TURNS_LINEAR_LINEAR
|
||||
// may this give false positives for INTs?
|
||||
BOOST_ASSERT(is_pi_ip == equals::equals_point_point(pi, ip));
|
||||
BOOST_ASSERT(is_qi_ip == equals::equals_point_point(qi, ip));
|
||||
BOOST_ASSERT(is_pj_ip == equals::equals_point_point(pj, ip));
|
||||
BOOST_ASSERT(is_qj_ip == equals::equals_point_point(qj, ip));
|
||||
typename IntersectionResult::point_type const&
|
||||
inters_pt = result.template get<0>().intersections[ip_index];
|
||||
BOOST_ASSERT(ip_info.is_pi == equals::equals_point_point(pi, inters_pt));
|
||||
BOOST_ASSERT(ip_info.is_qi == equals::equals_point_point(qi, inters_pt));
|
||||
BOOST_ASSERT(ip_info.is_pj == equals::equals_point_point(pj, inters_pt));
|
||||
BOOST_ASSERT(ip_info.is_qj == equals::equals_point_point(qj, inters_pt));
|
||||
#endif
|
||||
|
||||
// TODO - calculate first/last only if needed
|
||||
bool is_p_first_ip = is_p_first && is_pi_ip;
|
||||
bool is_p_last_ip = is_p_last && is_pj_ip;
|
||||
bool is_q_first_ip = is_q_first && is_qi_ip;
|
||||
bool is_q_last_ip = is_q_last && is_qj_ip;
|
||||
bool is_p_first_ip = is_p_first && ip_info.is_pi;
|
||||
bool is_p_last_ip = is_p_last && ip_info.is_pj;
|
||||
bool is_q_first_ip = is_q_first && ip_info.is_qi;
|
||||
bool is_q_last_ip = is_q_last && ip_info.is_qj;
|
||||
bool append_first = EnableFirst && (is_p_first_ip || is_q_first_ip);
|
||||
bool append_last = EnableLast && (is_p_last_ip || is_q_last_ip);
|
||||
|
||||
operation_type p_operation = ip_info.p_operation;
|
||||
operation_type q_operation = ip_info.q_operation;
|
||||
|
||||
if ( append_first || append_last )
|
||||
{
|
||||
bool handled = handle_internal(pi, pj, pk, qi, qj, qk, ip,
|
||||
bool handled = handle_internal(pi, pj, pk, qi, qj, qk,
|
||||
is_p_first_ip, is_p_last_ip,
|
||||
is_q_first_ip, is_q_last_ip,
|
||||
is_qi_ip, is_qj_ip,
|
||||
tp_model, result, p_operation, q_operation);
|
||||
ip_info.is_qi, ip_info.is_qj,
|
||||
tp_model, inters.result(), ip_index,
|
||||
p_operation, q_operation);
|
||||
if ( !handled )
|
||||
{
|
||||
handle_internal(qi, qj, qk, pi, pj, pk, ip,
|
||||
handle_internal(qi, qj, qk, pi, pj, pk,
|
||||
is_q_first_ip, is_q_last_ip,
|
||||
is_p_first_ip, is_p_last_ip,
|
||||
is_pi_ip, is_pj_ip,
|
||||
tp_model, result, q_operation, p_operation);
|
||||
ip_info.is_pi, ip_info.is_pj,
|
||||
tp_model, inters.result(), ip_index,
|
||||
q_operation, p_operation);
|
||||
}
|
||||
|
||||
if ( p_operation != operation_none )
|
||||
{
|
||||
assign(pi, qi, result, ip,
|
||||
endpoint_ip_method(is_pi_ip, is_pj_ip, is_qi_ip, is_qj_ip),
|
||||
p_operation, q_operation,
|
||||
ip_position(is_p_first_ip, is_p_last_ip),
|
||||
ip_position(is_q_first_ip, is_q_last_ip),
|
||||
tp_model, out);
|
||||
method_type method = endpoint_ip_method(ip_info.is_pi, ip_info.is_pj,
|
||||
ip_info.is_qi, ip_info.is_qj);
|
||||
turn_position p_pos = ip_position(is_p_first_ip, is_p_last_ip);
|
||||
turn_position q_pos = ip_position(is_q_first_ip, is_q_last_ip);
|
||||
|
||||
// handle spikes
|
||||
|
||||
// P is spike and should be handled
|
||||
if ( !is_p_last
|
||||
&& ip_info.is_pj // this check is redundant (also in is_spike_p) but faster
|
||||
&& inters.i_info().count == 2
|
||||
&& inters.is_spike_p() )
|
||||
{
|
||||
assign(pi, qi, inters.result(), ip_index, method, operation_blocked, q_operation,
|
||||
p_pos, q_pos, tp_model, out);
|
||||
assign(pi, qi, inters.result(), ip_index, method, operation_intersection, q_operation,
|
||||
p_pos, q_pos, tp_model, out);
|
||||
}
|
||||
// Q is spike and should be handled
|
||||
else if ( !is_q_last
|
||||
&& ip_info.is_qj // this check is redundant (also in is_spike_q) but faster
|
||||
&& inters.i_info().count == 2
|
||||
&& inters.is_spike_q() )
|
||||
{
|
||||
assign(pi, qi, inters.result(), ip_index, method, p_operation, operation_blocked,
|
||||
p_pos, q_pos, tp_model, out);
|
||||
assign(pi, qi, inters.result(), ip_index, method, p_operation, operation_intersection,
|
||||
p_pos, q_pos, tp_model, out);
|
||||
}
|
||||
// no spikes
|
||||
else
|
||||
{
|
||||
assign(pi, qi, inters.result(), ip_index, method, p_operation, q_operation,
|
||||
p_pos, q_pos, tp_model, out);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -372,21 +548,17 @@ struct get_turn_info_for_endpoint
|
||||
|
||||
template<typename Point1,
|
||||
typename Point2,
|
||||
typename Point,
|
||||
typename TurnInfo,
|
||||
typename IntersectionResult
|
||||
>
|
||||
static inline bool handle_internal(Point1 const& i1, Point1 const& j1, Point1 const& /*k1*/,
|
||||
Point2 const& i2, Point2 const& j2, Point2 const& k2,
|
||||
Point const& ip,
|
||||
bool first1, bool last1,
|
||||
bool first2, bool last2,
|
||||
bool ip_i2, bool ip_j2,
|
||||
TurnInfo const& tp_model,
|
||||
IntersectionResult const& result,
|
||||
bool first1, bool last1, bool first2, bool last2,
|
||||
bool ip_i2, bool ip_j2, TurnInfo const& tp_model,
|
||||
IntersectionResult const& result, int ip_index,
|
||||
operation_type & op1, operation_type & op2)
|
||||
{
|
||||
boost::ignore_unused_variable_warning(ip);
|
||||
boost::ignore_unused_variable_warning(ip_index);
|
||||
boost::ignore_unused_variable_warning(tp_model);
|
||||
|
||||
if ( !first2 && !last2 )
|
||||
@@ -395,8 +567,10 @@ struct get_turn_info_for_endpoint
|
||||
{
|
||||
#ifdef BOOST_GEOMETRY_DEBUG_GET_TURNS_LINEAR_LINEAR
|
||||
// may this give false positives for INTs?
|
||||
BOOST_ASSERT(ip_i2 == equals::equals_point_point(i2, ip));
|
||||
BOOST_ASSERT(ip_j2 == equals::equals_point_point(j2, ip));
|
||||
typename IntersectionResult::point_type const&
|
||||
inters_pt = result.template get<0>().intersections[ip_index];
|
||||
BOOST_ASSERT(ip_i2 == equals::equals_point_point(i2, inters_pt));
|
||||
BOOST_ASSERT(ip_j2 == equals::equals_point_point(j2, inters_pt));
|
||||
#endif
|
||||
if ( ip_i2 )
|
||||
{
|
||||
@@ -407,10 +581,7 @@ struct get_turn_info_for_endpoint
|
||||
}
|
||||
else if ( ip_j2 )
|
||||
{
|
||||
// NOTE: this conversion may be problematic
|
||||
Point1 i2_conv;
|
||||
geometry::convert(i2, i2_conv);
|
||||
side_calculator<Point1, Point2> side_calc(i2_conv, i1, j1, i2, j2, k2);
|
||||
side_calculator<Point1, Point2, Point2> side_calc(i2, i1, j1, i2, j2, k2);
|
||||
|
||||
std::pair<operation_type, operation_type>
|
||||
operations = operations_of_equal(side_calc);
|
||||
@@ -441,8 +612,10 @@ struct get_turn_info_for_endpoint
|
||||
{
|
||||
#ifdef BOOST_GEOMETRY_DEBUG_GET_TURNS_LINEAR_LINEAR
|
||||
// may this give false positives for INTs?
|
||||
BOOST_ASSERT(ip_i2 == equals::equals_point_point(i2, ip));
|
||||
BOOST_ASSERT(ip_j2 == equals::equals_point_point(j2, ip));
|
||||
typename IntersectionResult::point_type const&
|
||||
inters_pt = result.template get<0>().intersections[ip_index];
|
||||
BOOST_ASSERT(ip_i2 == equals::equals_point_point(i2, inters_pt));
|
||||
BOOST_ASSERT(ip_j2 == equals::equals_point_point(j2, inters_pt));
|
||||
#endif
|
||||
if ( ip_i2 )
|
||||
{
|
||||
@@ -453,11 +626,7 @@ struct get_turn_info_for_endpoint
|
||||
}
|
||||
else if ( ip_j2 )
|
||||
{
|
||||
// NOTE: this conversion may be problematic
|
||||
Point1 i2_conv;
|
||||
geometry::convert(i2, i2_conv);
|
||||
|
||||
side_calculator<Point1, Point2> side_calc(i2_conv, j1, i1, i2, j2, k2);
|
||||
side_calculator<Point1, Point2, Point2> side_calc(i2, j1, i1, i2, j2, k2);
|
||||
|
||||
std::pair<operation_type, operation_type>
|
||||
operations = operations_of_equal(side_calc);
|
||||
@@ -507,12 +676,11 @@ struct get_turn_info_for_endpoint
|
||||
template <typename Point1,
|
||||
typename Point2,
|
||||
typename IntersectionResult,
|
||||
typename Point,
|
||||
typename TurnInfo,
|
||||
typename OutputIterator>
|
||||
static inline void assign(Point1 const& pi, Point2 const& qi,
|
||||
IntersectionResult const& result,
|
||||
Point const& ip,
|
||||
int ip_index,
|
||||
method_type method,
|
||||
operation_type op0, operation_type op1,
|
||||
turn_position pos0, turn_position pos1,
|
||||
@@ -520,8 +688,11 @@ struct get_turn_info_for_endpoint
|
||||
OutputIterator out)
|
||||
{
|
||||
TurnInfo tp = tp_model;
|
||||
geometry::convert(ip, tp.point);
|
||||
tp.method = method;
|
||||
|
||||
//geometry::convert(ip, tp.point);
|
||||
//tp.method = method;
|
||||
base_turn_handler::assign_point(tp, method, result.template get<0>(), ip_index);
|
||||
|
||||
tp.operations[0].operation = op0;
|
||||
tp.operations[1].operation = op1;
|
||||
tp.operations[0].position = pos0;
|
||||
|
||||
@@ -28,12 +28,14 @@ namespace detail { namespace overlay {
|
||||
template<typename AssignPolicy>
|
||||
struct get_turn_info_linear_areal
|
||||
{
|
||||
static const bool handle_spikes = true;
|
||||
|
||||
template
|
||||
<
|
||||
typename Point1,
|
||||
typename Point2,
|
||||
typename TurnInfo,
|
||||
typename RescalePolicy,
|
||||
typename RobustPolicy,
|
||||
typename OutputIterator
|
||||
>
|
||||
static inline OutputIterator apply(
|
||||
@@ -42,29 +44,13 @@ struct get_turn_info_linear_areal
|
||||
bool is_p_first, bool is_p_last,
|
||||
bool is_q_first, bool is_q_last,
|
||||
TurnInfo const& tp_model,
|
||||
RescalePolicy const& , // TODO: this will be used. rescale_policy,
|
||||
RobustPolicy const& robust_policy,
|
||||
OutputIterator out)
|
||||
{
|
||||
typedef model::referring_segment<Point1 const> segment_type1;
|
||||
typedef model::referring_segment<Point2 const> segment_type2;
|
||||
segment_type1 p1(pi, pj), p2(pj, pk);
|
||||
segment_type2 q1(qi, qj), q2(qj, qk);
|
||||
intersection_info<Point1, Point2, typename TurnInfo::point_type, RobustPolicy>
|
||||
inters(pi, pj, pk, qi, qj, qk, robust_policy);
|
||||
|
||||
side_calculator<Point1, Point2> side_calc(pi, pj, pk, qi, qj, qk);
|
||||
|
||||
typedef strategy_intersection
|
||||
<
|
||||
typename cs_tag<typename TurnInfo::point_type>::type,
|
||||
Point1,
|
||||
Point2,
|
||||
typename TurnInfo::point_type
|
||||
> si;
|
||||
|
||||
typedef typename si::segment_intersection_strategy_type strategy;
|
||||
|
||||
typename strategy::return_type result = strategy::apply(p1, q1);
|
||||
|
||||
char const method = result.template get<1>().how;
|
||||
char const method = inters.d_info().how;
|
||||
|
||||
// Copy, to copy possibly extended fields
|
||||
TurnInfo tp = tp_model;
|
||||
@@ -78,7 +64,7 @@ struct get_turn_info_linear_areal
|
||||
get_turn_info_for_endpoint<true, true>(
|
||||
pi, pj, pk, qi, qj, qk,
|
||||
is_p_first, is_p_last, is_q_first, is_q_last,
|
||||
tp_model, result, method_none, out);
|
||||
tp_model, inters.result(), method_none, out);
|
||||
break;
|
||||
|
||||
case 'd' : // disjoint: never do anything
|
||||
@@ -89,7 +75,7 @@ struct get_turn_info_linear_areal
|
||||
if ( get_turn_info_for_endpoint<false, true>(
|
||||
pi, pj, pk, qi, qj, qk,
|
||||
is_p_first, is_p_last, is_q_first, is_q_last,
|
||||
tp_model, result, method_touch_interior, out) )
|
||||
tp_model, inters.result(), method_touch_interior, out) )
|
||||
{
|
||||
// do nothing
|
||||
}
|
||||
@@ -101,18 +87,18 @@ struct get_turn_info_linear_areal
|
||||
> policy;
|
||||
|
||||
// If Q (1) arrives (1)
|
||||
if (result.template get<1>().arrival[1] == 1)
|
||||
if ( inters.d_info().arrival[1] == 1 )
|
||||
{
|
||||
policy::template apply<0>(pi, pj, pk, qi, qj, qk,
|
||||
tp, result.template get<0>(), result.template get<1>(),
|
||||
side_calc);
|
||||
tp, inters.i_info(), inters.d_info(),
|
||||
inters.sides());
|
||||
}
|
||||
else
|
||||
{
|
||||
// Swap p/q
|
||||
side_calculator<Point1, Point2> swapped_side_calc(qi, qj, qk, pi, pj, pk);
|
||||
side_calculator<Point2, Point1> swapped_side_calc(qi, qj, qk, pi, pj, pk);
|
||||
policy::template apply<1>(qi, qj, qk, pi, pj, pk,
|
||||
tp, result.template get<0>(), result.template get<1>(),
|
||||
tp, inters.i_info(), inters.d_info(),
|
||||
swapped_side_calc);
|
||||
}
|
||||
|
||||
@@ -121,9 +107,16 @@ struct get_turn_info_linear_areal
|
||||
tp.operations[0].is_collinear = true;
|
||||
}
|
||||
|
||||
replace_method_and_operations_tm(tp.method, tp.operations[0].operation, tp.operations[1].operation);
|
||||
replace_method_and_operations_tm(tp.method,
|
||||
tp.operations[0].operation,
|
||||
tp.operations[1].operation);
|
||||
|
||||
AssignPolicy::apply(tp, pi, qi, result.template get<0>(), result.template get<1>());
|
||||
// this function assumes that 'u' must be set for a spike
|
||||
calculate_spike_operation(tp.operations[0].operation,
|
||||
inters, is_p_last);
|
||||
|
||||
AssignPolicy::apply(tp, pi, qi, inters.i_info(), inters.d_info());
|
||||
|
||||
*out++ = tp;
|
||||
}
|
||||
}
|
||||
@@ -131,11 +124,11 @@ struct get_turn_info_linear_areal
|
||||
case 'i' :
|
||||
{
|
||||
crosses<TurnInfo>::apply(pi, pj, pk, qi, qj, qk,
|
||||
tp, result.template get<0>(), result.template get<1>());
|
||||
tp, inters.i_info(), inters.d_info());
|
||||
|
||||
replace_operations_i(tp.operations[0].operation, tp.operations[1].operation);
|
||||
|
||||
AssignPolicy::apply(tp, pi, qi, result.template get<0>(), result.template get<1>());
|
||||
AssignPolicy::apply(tp, pi, qi, inters.i_info(), inters.d_info());
|
||||
*out++ = tp;
|
||||
}
|
||||
break;
|
||||
@@ -145,24 +138,39 @@ struct get_turn_info_linear_areal
|
||||
if ( get_turn_info_for_endpoint<false, true>(
|
||||
pi, pj, pk, qi, qj, qk,
|
||||
is_p_first, is_p_last, is_q_first, is_q_last,
|
||||
tp_model, result, method_touch, out) )
|
||||
tp_model, inters.result(), method_touch, out) )
|
||||
{
|
||||
// do nothing
|
||||
}
|
||||
else
|
||||
{
|
||||
touch<TurnInfo>::apply(pi, pj, pk, qi, qj, qk,
|
||||
tp, result.template get<0>(), result.template get<1>(), side_calc);
|
||||
tp, inters.i_info(), inters.d_info(), inters.sides());
|
||||
|
||||
if ( tp.operations[1].operation == operation_blocked )
|
||||
{
|
||||
tp.operations[0].is_collinear = true;
|
||||
}
|
||||
|
||||
replace_method_and_operations_tm(tp.method, tp.operations[0].operation, tp.operations[1].operation);
|
||||
replace_method_and_operations_tm(tp.method,
|
||||
tp.operations[0].operation,
|
||||
tp.operations[1].operation);
|
||||
|
||||
AssignPolicy::apply(tp, pi, qi, result.template get<0>(), result.template get<1>());
|
||||
*out++ = tp;
|
||||
// this function assumes that 'u' must be set for a spike
|
||||
bool ignore_spike
|
||||
= calculate_spike_operation(tp.operations[0].operation,
|
||||
inters, is_p_last);
|
||||
|
||||
// TODO: move this into the append_xxx and call for each turn?
|
||||
AssignPolicy::apply(tp, pi, qi, inters.i_info(), inters.d_info());
|
||||
|
||||
if ( ! handle_spikes
|
||||
|| ignore_spike
|
||||
|| ! append_opposite_spikes<append_touches>( // for 'i' or 'c'
|
||||
tp, inters, is_p_last, is_q_last, out) )
|
||||
{
|
||||
*out++ = tp;
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
@@ -171,7 +179,7 @@ struct get_turn_info_linear_areal
|
||||
if ( get_turn_info_for_endpoint<true, true>(
|
||||
pi, pj, pk, qi, qj, qk,
|
||||
is_p_first, is_p_last, is_q_first, is_q_last,
|
||||
tp_model, result, method_equal, out) )
|
||||
tp_model, inters.result(), method_equal, out) )
|
||||
{
|
||||
// do nothing
|
||||
}
|
||||
@@ -179,26 +187,26 @@ struct get_turn_info_linear_areal
|
||||
{
|
||||
tp.operations[0].is_collinear = true;
|
||||
|
||||
if ( ! result.template get<1>().opposite )
|
||||
if ( ! inters.d_info().opposite )
|
||||
{
|
||||
// Both equal
|
||||
// or collinear-and-ending at intersection point
|
||||
equal<TurnInfo>::apply(pi, pj, pk, qi, qj, qk,
|
||||
tp, result.template get<0>(), result.template get<1>(), side_calc);
|
||||
tp, inters.i_info(), inters.d_info(), inters.sides());
|
||||
|
||||
replacer_of_method_and_operations_ec<false> replacer(method_touch);
|
||||
replacer(tp.method, tp.operations[0].operation, tp.operations[1].operation);
|
||||
|
||||
// TODO: This isn't correct handling, hence commented out
|
||||
/*spike_detector<Point1, Point2> spike_detect(side_calc);
|
||||
if ( tp.operations[0].operation == operation_union
|
||||
&& spike_detect.is_spike_p())
|
||||
// TODO: move this into the append_xxx and call for each turn?
|
||||
AssignPolicy::apply(tp, pi, qi, inters.i_info(), inters.d_info());
|
||||
|
||||
// conditionally handle spikes
|
||||
if ( ! handle_spikes
|
||||
|| ! append_collinear_spikes(tp, inters, is_p_last, is_q_last,
|
||||
method_touch, append_equal, out) )
|
||||
{
|
||||
tp.operations[0].operation = operation_continue;
|
||||
}*/
|
||||
|
||||
AssignPolicy::apply(tp, pi, qi, result.template get<0>(), result.template get<1>());
|
||||
*out++ = tp;
|
||||
*out++ = tp; // no spikes
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -207,7 +215,7 @@ struct get_turn_info_linear_areal
|
||||
TurnInfo,
|
||||
AssignPolicy
|
||||
>::apply(pi, qi,
|
||||
tp, out, result.template get<0>(), result.template get<1>());
|
||||
tp, out, inters.i_info(), inters.d_info());
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -218,7 +226,7 @@ struct get_turn_info_linear_areal
|
||||
if ( get_turn_info_for_endpoint<true, true>(
|
||||
pi, pj, pk, qi, qj, qk,
|
||||
is_p_first, is_p_last, is_q_first, is_q_last,
|
||||
tp_model, result, method_collinear, out) )
|
||||
tp_model, inters.result(), method_collinear, out) )
|
||||
{
|
||||
// do nothing
|
||||
}
|
||||
@@ -226,49 +234,67 @@ struct get_turn_info_linear_areal
|
||||
{
|
||||
tp.operations[0].is_collinear = true;
|
||||
|
||||
if (! result.template get<1>().opposite)
|
||||
if ( ! inters.d_info().opposite )
|
||||
{
|
||||
if (result.template get<1>().arrival[0] == 0)
|
||||
method_type method_replace = method_touch_interior;
|
||||
append_version_c version = append_collinear;
|
||||
|
||||
if ( inters.d_info().arrival[0] == 0 )
|
||||
{
|
||||
// Collinear, but similar thus handled as equal
|
||||
equal<TurnInfo>::apply(pi, pj, pk, qi, qj, qk,
|
||||
tp, result.template get<0>(), result.template get<1>(), side_calc);
|
||||
tp, inters.i_info(), inters.d_info(), inters.sides());
|
||||
|
||||
// TODO: This isn't correct handling, hence commented out
|
||||
/*spike_detector<Point1, Point2> spike_detect(side_calc);
|
||||
if ( tp.operations[0].operation == operation_union
|
||||
&& spike_detect.is_spike_p())
|
||||
{
|
||||
tp.operations[0].operation = operation_continue;
|
||||
}*/
|
||||
|
||||
replacer_of_method_and_operations_ec<false> replacer(method_touch);
|
||||
replacer(tp.method, tp.operations[0].operation, tp.operations[1].operation);
|
||||
method_replace = method_touch;
|
||||
version = append_equal;
|
||||
}
|
||||
else
|
||||
{
|
||||
collinear<TurnInfo>::apply(pi, pj, pk, qi, qj, qk,
|
||||
tp, result.template get<0>(), result.template get<1>(), side_calc);
|
||||
tp, inters.i_info(), inters.d_info(), inters.sides());
|
||||
|
||||
replacer_of_method_and_operations_ec<false> replacer(method_touch_interior);
|
||||
replacer(tp.method, tp.operations[0].operation, tp.operations[1].operation);
|
||||
//method_replace = method_touch_interior;
|
||||
//version = append_collinear;
|
||||
}
|
||||
|
||||
AssignPolicy::apply(tp, pi, qi, result.template get<0>(), result.template get<1>());
|
||||
*out++ = tp;
|
||||
replacer_of_method_and_operations_ec<false> replacer(method_replace);
|
||||
replacer(tp.method, tp.operations[0].operation, tp.operations[1].operation);
|
||||
|
||||
// TODO: move this into the append_xxx and call for each turn?
|
||||
AssignPolicy::apply(tp, pi, qi, inters.i_info(), inters.d_info());
|
||||
|
||||
// conditionally handle spikes
|
||||
if ( ! handle_spikes
|
||||
|| ! append_collinear_spikes(tp, inters, is_p_last, is_q_last,
|
||||
method_replace, version, out) )
|
||||
{
|
||||
// no spikes
|
||||
*out++ = tp;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// Is this always 'm' ?
|
||||
replacer_of_method_and_operations_ec<false> replacer(method_touch_interior);
|
||||
|
||||
// conditionally handle spikes
|
||||
if ( handle_spikes )
|
||||
{
|
||||
append_opposite_spikes<append_collinear_opposite>(
|
||||
tp, inters, is_p_last, is_q_last, out);
|
||||
}
|
||||
|
||||
// TODO: ignore for spikes?
|
||||
// E.g. pass is_p_valid = !is_p_last && !is_pj_spike,
|
||||
// the same with is_q_valid
|
||||
|
||||
collinear_opposite
|
||||
<
|
||||
TurnInfo,
|
||||
AssignPolicy
|
||||
>::apply(pi, pj, pk, qi, qj, qk,
|
||||
tp, out, result.template get<0>(), result.template get<1>(), side_calc,
|
||||
replacer);
|
||||
tp, out, inters.i_info(), inters.d_info(),
|
||||
inters.sides(), replacer);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -278,8 +304,21 @@ struct get_turn_info_linear_areal
|
||||
// degenerate points
|
||||
if (AssignPolicy::include_degenerate)
|
||||
{
|
||||
only_convert<TurnInfo>::apply(tp, result.template get<0>());
|
||||
AssignPolicy::apply(tp, pi, qi, result.template get<0>(), result.template get<1>());
|
||||
only_convert::apply(tp, inters.i_info());
|
||||
|
||||
if ( is_p_first
|
||||
&& equals::equals_point_point(pi, tp.point) )
|
||||
{
|
||||
tp.operations[0].position = position_front;
|
||||
}
|
||||
else if ( is_p_last
|
||||
&& equals::equals_point_point(pj, tp.point) )
|
||||
{
|
||||
tp.operations[0].position = position_back;
|
||||
}
|
||||
// tp.operations[1].position = position_middle;
|
||||
|
||||
AssignPolicy::apply(tp, pi, qi, inters.i_info(), inters.d_info());
|
||||
*out++ = tp;
|
||||
}
|
||||
}
|
||||
@@ -299,6 +338,128 @@ struct get_turn_info_linear_areal
|
||||
return out;
|
||||
}
|
||||
|
||||
template <typename Operation,
|
||||
typename IntersectionInfo>
|
||||
static inline bool calculate_spike_operation(Operation & op,
|
||||
IntersectionInfo const& inters,
|
||||
bool is_p_last)
|
||||
{
|
||||
bool is_p_spike = op == operation_union
|
||||
&& ! is_p_last
|
||||
&& inters.is_spike_p();
|
||||
|
||||
// we don't know where the spike is going since for both directions 'u' is set
|
||||
if ( is_p_spike )
|
||||
{
|
||||
if ( inters.sides().pk_wrt_q1() < 0 && inters.sides().pk_wrt_q2() < 0 )
|
||||
{
|
||||
op = operation_intersection;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
enum append_version_c { append_equal, append_collinear };
|
||||
|
||||
template <typename TurnInfo,
|
||||
typename IntersectionInfo,
|
||||
typename OutIt>
|
||||
static inline bool append_collinear_spikes(TurnInfo & tp,
|
||||
IntersectionInfo const& inters,
|
||||
bool is_p_last, bool is_q_last,
|
||||
method_type method, append_version_c version,
|
||||
OutIt out)
|
||||
{
|
||||
// method == touch || touch_interior
|
||||
// both position == middle
|
||||
|
||||
bool is_p_spike = ( version == append_equal ?
|
||||
( tp.operations[0].operation == operation_union
|
||||
|| tp.operations[0].operation == operation_intersection ) :
|
||||
tp.operations[0].operation == operation_continue )
|
||||
&& ! is_p_last
|
||||
&& inters.is_spike_p();
|
||||
|
||||
// TODO: throw an exception for spike in Areal?
|
||||
/*bool is_q_spike = tp.operations[1].operation == spike_op
|
||||
&& ! is_q_last
|
||||
&& inters.is_spike_q();*/
|
||||
|
||||
if ( is_p_spike )
|
||||
{
|
||||
tp.method = method;
|
||||
tp.operations[0].operation = operation_blocked;
|
||||
tp.operations[1].operation = operation_union;
|
||||
*out++ = tp;
|
||||
tp.operations[0].operation = operation_continue; // boundary
|
||||
//tp.operations[1].operation = operation_union;
|
||||
*out++ = tp;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
enum append_version_o { append_touches, append_collinear_opposite };
|
||||
|
||||
template <append_version_o Version,
|
||||
typename TurnInfo,
|
||||
typename IntersectionInfo,
|
||||
typename OutIt>
|
||||
static inline bool append_opposite_spikes(TurnInfo & tp,
|
||||
IntersectionInfo const& inters,
|
||||
bool is_p_last, bool is_q_last,
|
||||
OutIt out)
|
||||
{
|
||||
bool is_p_spike = ( Version == append_touches ?
|
||||
( tp.operations[0].operation == operation_continue
|
||||
|| tp.operations[0].operation == operation_intersection ) :
|
||||
true )
|
||||
&& ! is_p_last
|
||||
&& inters.is_spike_p();
|
||||
// TODO: throw an exception for spike in Areal?
|
||||
/*bool is_q_spike = ( Version == append_touches ?
|
||||
( tp.operations[1].operation == operation_continue
|
||||
|| tp.operations[1].operation == operation_intersection ) :
|
||||
true )
|
||||
&& ! is_q_last
|
||||
&& inters.is_spike_q();*/
|
||||
|
||||
if ( is_p_spike && ( Version == append_touches || inters.d_info().arrival[0] == 1 ) )
|
||||
{
|
||||
if ( Version == append_touches )
|
||||
{
|
||||
tp.operations[0].is_collinear = true;
|
||||
//tp.operations[1].is_collinear = ???
|
||||
tp.method = method_touch;
|
||||
}
|
||||
else
|
||||
{
|
||||
//tp.operations[0].is_collinear = true;
|
||||
//tp.operations[1].is_collinear = true;
|
||||
|
||||
BOOST_ASSERT(inters.i_info().count > 1);
|
||||
base_turn_handler::assign_point(tp, method_touch_interior, inters.i_info(), 1);
|
||||
|
||||
AssignPolicy::apply(tp, inters.pi(), inters.qi(), inters.i_info(), inters.d_info());
|
||||
}
|
||||
|
||||
tp.operations[0].operation = operation_blocked;
|
||||
tp.operations[1].operation = operation_continue; // boundary
|
||||
*out++ = tp;
|
||||
tp.operations[0].operation = operation_continue; // boundary
|
||||
//tp.operations[1].operation = operation_continue; // boundary
|
||||
*out++ = tp;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
static inline void replace_method_and_operations_tm(method_type & method,
|
||||
operation_type & op0,
|
||||
operation_type & op1)
|
||||
@@ -323,6 +484,14 @@ struct get_turn_info_linear_areal
|
||||
{
|
||||
op1 = operation_union;
|
||||
}
|
||||
|
||||
// spikes in 'm'
|
||||
if ( method == method_error )
|
||||
{
|
||||
method = method_touch_interior;
|
||||
op0 = operation_union;
|
||||
op1 = operation_union;
|
||||
}
|
||||
}
|
||||
|
||||
template <bool IsFront>
|
||||
@@ -371,6 +540,10 @@ struct get_turn_info_linear_areal
|
||||
op1 = operation_union;
|
||||
}
|
||||
|
||||
// NOTE: Spikes may NOT be handled for Linear endpoints because it's not
|
||||
// possible to define a spike on an endpoint. Areal geometries must
|
||||
// NOT have spikes at all. One thing that could be done is to throw
|
||||
// an exception when spike is detected in Areal geometry.
|
||||
|
||||
template <bool EnableFirst,
|
||||
bool EnableLast,
|
||||
@@ -404,38 +577,16 @@ struct get_turn_info_linear_areal
|
||||
if ( !is_p_first && !is_p_last )
|
||||
return false;
|
||||
|
||||
ov::operation_type p_operation0 = ov::operation_none;
|
||||
ov::operation_type q_operation0 = ov::operation_none;
|
||||
ov::operation_type p_operation1 = ov::operation_none;
|
||||
ov::operation_type q_operation1 = ov::operation_none;
|
||||
bool p0i, p0j, q0i, q0j; // assign false?
|
||||
bool p1i, p1j, q1i, q1j; // assign false?
|
||||
linear_intersections intersections(pi, qi, result, is_p_last, is_q_last);
|
||||
linear_intersections::ip_info const& ip0 = intersections.template get<0>();
|
||||
linear_intersections::ip_info const& ip1 = intersections.template get<1>();
|
||||
|
||||
const bool opposite = result.template get<1>().opposite;
|
||||
const bool same_dirs = result.template get<1>().dir_a == 0 && result.template get<1>().dir_b == 0;
|
||||
|
||||
{
|
||||
const int p_how = result.template get<1>().how_a;
|
||||
const int q_how = result.template get<1>().how_b;
|
||||
const int p_arrival = result.template get<1>().arrival[0];
|
||||
const int q_arrival = result.template get<1>().arrival[1];
|
||||
|
||||
get_info_e::handle_segment(
|
||||
is_p_first, is_p_last, p_how, p_arrival,
|
||||
is_q_first, is_q_last, q_how, q_arrival,
|
||||
opposite, ip_count, same_dirs,
|
||||
result.template get<0>().intersections[0],
|
||||
result.template get<0>().intersections[1],
|
||||
p_operation0, q_operation0, p_operation1, q_operation1,
|
||||
p0i, p0j, q0i, q0j,
|
||||
p1i, p1j, q1i, q1j,
|
||||
pi, pj, pk, qi, qj, qk);
|
||||
}
|
||||
|
||||
// ANALYSE AND ASSIGN FIRST
|
||||
|
||||
// IP on the first point of Linear Geometry
|
||||
if ( EnableFirst && is_p_first && p0i && !q0i ) // !q0i prevents duplication
|
||||
if ( EnableFirst && is_p_first && ip0.is_pi && !ip0.is_qi ) // !q0i prevents duplication
|
||||
{
|
||||
TurnInfo tp = tp_model;
|
||||
tp.operations[0].position = position_front;
|
||||
@@ -445,19 +596,15 @@ struct get_turn_info_linear_areal
|
||||
{
|
||||
tp.operations[0].operation = operation_continue;
|
||||
tp.operations[1].operation = operation_union;
|
||||
tp.method = q0j ? method_touch : method_touch_interior;
|
||||
tp.method = ip0.is_qj ? method_touch : method_touch_interior;
|
||||
}
|
||||
else
|
||||
{
|
||||
// NOTE: the conversion may be problematic
|
||||
Point1 qi_conv;
|
||||
geometry::convert(qi, qi_conv);
|
||||
|
||||
method_type replaced_method = method_touch_interior;
|
||||
|
||||
if ( q0j )
|
||||
if ( ip0.is_qj )
|
||||
{
|
||||
side_calculator<Point1, Point2> side_calc(qi_conv, pi, pj, qi, qj, qk);
|
||||
side_calculator<Point1, Point2, Point2> side_calc(qi, pi, pj, qi, qj, qk);
|
||||
|
||||
std::pair<operation_type, operation_type>
|
||||
operations = get_info_e::operations_of_equal(side_calc);
|
||||
@@ -469,11 +616,9 @@ struct get_turn_info_linear_areal
|
||||
}
|
||||
else
|
||||
{
|
||||
// NOTE: the conversion may be problematic
|
||||
Point2 pi_conv;
|
||||
geometry::convert(pi, pi_conv);
|
||||
|
||||
side_calculator<Point1, Point2> side_calc(qi_conv, pi, pj, qi, pi_conv, qj);
|
||||
side_calculator<Point1, Point2,
|
||||
Point2, Point1, Point1,
|
||||
Point2, Point1, Point2> side_calc(qi, pi, pj, qi, pi, qj);
|
||||
|
||||
std::pair<operation_type, operation_type>
|
||||
operations = get_info_e::operations_of_equal(side_calc);
|
||||
@@ -488,7 +633,7 @@ struct get_turn_info_linear_areal
|
||||
|
||||
// equals<> or collinear<> will assign the second point,
|
||||
// we'd like to assign the first one
|
||||
geometry::convert(result.template get<0>().intersections[0], tp.point);
|
||||
base_turn_handler::assign_point(tp, tp.method, result.template get<0>(), 0);
|
||||
|
||||
// NOTE: not really needed especially for the first point
|
||||
// for which there is no preceding segment (but consistent with the L/L)
|
||||
@@ -507,7 +652,7 @@ struct get_turn_info_linear_areal
|
||||
// IP on the last point of Linear Geometry
|
||||
if ( EnableLast
|
||||
&& is_p_last
|
||||
&& ( ip_count > 1 ? (p1j && !q1i) : (p0j && !q0i) ) ) // prevents duplication
|
||||
&& ( ip_count > 1 ? (ip1.is_pj && !ip1.is_qi) : (ip0.is_pj && !ip0.is_qi) ) ) // prevents duplication
|
||||
{
|
||||
TurnInfo tp = tp_model;
|
||||
|
||||
@@ -519,9 +664,7 @@ struct get_turn_info_linear_areal
|
||||
}
|
||||
else //if ( result.template get<0>().count == 1 )
|
||||
{
|
||||
Point1 qi_conv;
|
||||
geometry::convert(qi, qi_conv);
|
||||
side_calculator<Point1, Point2> side_calc(qi_conv, pj, pi, qi, qj, qk);
|
||||
side_calculator<Point1, Point2, Point2> side_calc(qi, pj, pi, qi, qj, qk);
|
||||
|
||||
std::pair<operation_type, operation_type>
|
||||
operations = get_info_e::operations_of_equal(side_calc);
|
||||
@@ -538,7 +681,7 @@ struct get_turn_info_linear_areal
|
||||
}
|
||||
}
|
||||
|
||||
tp.method = ( ip_count > 1 ? q1j : q0j ) ? method_touch : method_touch_interior;
|
||||
tp.method = ( ip_count > 1 ? ip1.is_qj : ip0.is_qj ) ? method_touch : method_touch_interior;
|
||||
tp.operations[0].operation = operation_blocked;
|
||||
tp.operations[0].position = position_back;
|
||||
tp.operations[1].position = position_middle;
|
||||
@@ -546,7 +689,7 @@ struct get_turn_info_linear_areal
|
||||
// equals<> or collinear<> will assign the second point,
|
||||
// we'd like to assign the first one
|
||||
std::size_t ip_index = ip_count > 1 ? 1 : 0;
|
||||
geometry::convert(result.template get<0>().intersections[ip_index], tp.point);
|
||||
base_turn_handler::assign_point(tp, tp.method, result.template get<0>(), ip_index);
|
||||
|
||||
AssignPolicy::apply(tp, pi, qi, result.template get<0>(), result.template get<1>());
|
||||
*out++ = tp;
|
||||
|
||||
@@ -22,71 +22,17 @@ namespace boost { namespace geometry {
|
||||
#ifndef DOXYGEN_NO_DETAIL
|
||||
namespace detail { namespace overlay {
|
||||
|
||||
template <typename Point1,
|
||||
typename Point2,
|
||||
typename SideCalc = side_calculator<Point1, Point2> >
|
||||
class spike_detector
|
||||
{
|
||||
public:
|
||||
explicit spike_detector(SideCalc const& side_calc)
|
||||
: m_side_calc(side_calc)
|
||||
{}
|
||||
|
||||
inline bool is_spike_p() const
|
||||
{
|
||||
if ( m_side_calc.pk_wrt_p1() == 0 )
|
||||
{
|
||||
int const qk_p1 = m_side_calc.qk_wrt_p1();
|
||||
int const qk_p2 = m_side_calc.qk_wrt_p2();
|
||||
|
||||
if ( qk_p1 == -qk_p2 )
|
||||
{
|
||||
if ( qk_p1 == 0 )
|
||||
{
|
||||
// TODO check additional things
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
inline bool is_spike_q() const
|
||||
{
|
||||
if ( m_side_calc.qk_wrt_q1() == 0 )
|
||||
{
|
||||
int const pk_q1 = m_side_calc.pk_wrt_q1();
|
||||
int const pk_q2 = m_side_calc.pk_wrt_q2();
|
||||
|
||||
if ( pk_q1 == -pk_q2 )
|
||||
{
|
||||
if ( pk_q1 == 0 )
|
||||
{
|
||||
// TODO check additional things
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
private:
|
||||
SideCalc const& m_side_calc;
|
||||
};
|
||||
|
||||
template<typename AssignPolicy>
|
||||
struct get_turn_info_linear_linear
|
||||
{
|
||||
static const bool handle_spikes = true;
|
||||
|
||||
template
|
||||
<
|
||||
typename Point1,
|
||||
typename Point2,
|
||||
typename TurnInfo,
|
||||
typename RescalePolicy,
|
||||
typename RobustPolicy,
|
||||
typename OutputIterator
|
||||
>
|
||||
static inline OutputIterator apply(
|
||||
@@ -95,29 +41,13 @@ struct get_turn_info_linear_linear
|
||||
bool is_p_first, bool is_p_last,
|
||||
bool is_q_first, bool is_q_last,
|
||||
TurnInfo const& tp_model,
|
||||
RescalePolicy const& , // TODO: this will be used. rescale_policy,
|
||||
RobustPolicy const& robust_policy,
|
||||
OutputIterator out)
|
||||
{
|
||||
typedef model::referring_segment<Point1 const> segment_type1;
|
||||
typedef model::referring_segment<Point2 const> segment_type2;
|
||||
segment_type1 p1(pi, pj), p2(pj, pk);
|
||||
segment_type2 q1(qi, qj), q2(qj, qk);
|
||||
intersection_info<Point1, Point2, typename TurnInfo::point_type, RobustPolicy>
|
||||
inters(pi, pj, pk, qi, qj, qk, robust_policy);
|
||||
|
||||
side_calculator<Point1, Point2> side_calc(pi, pj, pk, qi, qj, qk);
|
||||
|
||||
typedef strategy_intersection
|
||||
<
|
||||
typename cs_tag<typename TurnInfo::point_type>::type,
|
||||
Point1,
|
||||
Point2,
|
||||
typename TurnInfo::point_type
|
||||
> si;
|
||||
|
||||
typedef typename si::segment_intersection_strategy_type strategy;
|
||||
|
||||
typename strategy::return_type result = strategy::apply(p1, q1);
|
||||
|
||||
char const method = result.template get<1>().how;
|
||||
char const method = inters.d_info().how;
|
||||
|
||||
// Copy, to copy possibly extended fields
|
||||
TurnInfo tp = tp_model;
|
||||
@@ -131,7 +61,7 @@ struct get_turn_info_linear_linear
|
||||
get_turn_info_for_endpoint<AssignPolicy, true, true>
|
||||
::apply(pi, pj, pk, qi, qj, qk,
|
||||
is_p_first, is_p_last, is_q_first, is_q_last,
|
||||
tp_model, result, method_none, out);
|
||||
tp_model, inters, method_none, out);
|
||||
break;
|
||||
|
||||
case 'd' : // disjoint: never do anything
|
||||
@@ -142,7 +72,7 @@ struct get_turn_info_linear_linear
|
||||
if ( get_turn_info_for_endpoint<AssignPolicy, false, true>
|
||||
::apply(pi, pj, pk, qi, qj, qk,
|
||||
is_p_first, is_p_last, is_q_first, is_q_last,
|
||||
tp_model, result, method_touch_interior, out) )
|
||||
tp_model, inters, method_touch_interior, out) )
|
||||
{
|
||||
// do nothing
|
||||
}
|
||||
@@ -154,21 +84,21 @@ struct get_turn_info_linear_linear
|
||||
> policy;
|
||||
|
||||
// If Q (1) arrives (1)
|
||||
if (result.template get<1>().arrival[1] == 1)
|
||||
if ( inters.d_info().arrival[1] == 1)
|
||||
{
|
||||
policy::template apply<0>(pi, pj, pk, qi, qj, qk,
|
||||
tp, result.template get<0>(), result.template get<1>(),
|
||||
side_calc);
|
||||
tp, inters.i_info(), inters.d_info(),
|
||||
inters.sides());
|
||||
}
|
||||
else
|
||||
{
|
||||
// Swap p/q
|
||||
side_calculator<Point1, Point2> swapped_side_calc(qi, qj, qk, pi, pj, pk);
|
||||
side_calculator<Point2, Point1> swapped_side_calc(qi, qj, qk, pi, pj, pk);
|
||||
policy::template apply<1>(qi, qj, qk, pi, pj, pk,
|
||||
tp, result.template get<0>(), result.template get<1>(),
|
||||
swapped_side_calc);
|
||||
tp, inters.i_info(), inters.d_info(),
|
||||
swapped_side_calc);
|
||||
}
|
||||
|
||||
|
||||
if ( tp.operations[0].operation == operation_blocked )
|
||||
{
|
||||
tp.operations[1].is_collinear = true;
|
||||
@@ -178,9 +108,11 @@ struct get_turn_info_linear_linear
|
||||
tp.operations[0].is_collinear = true;
|
||||
}
|
||||
|
||||
replace_method_and_operations_tm(tp.method, tp.operations[0].operation, tp.operations[1].operation);
|
||||
replace_method_and_operations_tm(tp.method,
|
||||
tp.operations[0].operation,
|
||||
tp.operations[1].operation);
|
||||
|
||||
AssignPolicy::apply(tp, pi, qi, result.template get<0>(), result.template get<1>());
|
||||
AssignPolicy::apply(tp, pi, qi, inters.i_info(), inters.d_info());
|
||||
*out++ = tp;
|
||||
}
|
||||
}
|
||||
@@ -188,11 +120,11 @@ struct get_turn_info_linear_linear
|
||||
case 'i' :
|
||||
{
|
||||
crosses<TurnInfo>::apply(pi, pj, pk, qi, qj, qk,
|
||||
tp, result.template get<0>(), result.template get<1>());
|
||||
tp, inters.i_info(), inters.d_info());
|
||||
|
||||
replace_operations_i(tp.operations[0].operation, tp.operations[1].operation);
|
||||
|
||||
AssignPolicy::apply(tp, pi, qi, result.template get<0>(), result.template get<1>());
|
||||
AssignPolicy::apply(tp, pi, qi, inters.i_info(), inters.d_info());
|
||||
*out++ = tp;
|
||||
}
|
||||
break;
|
||||
@@ -202,14 +134,14 @@ struct get_turn_info_linear_linear
|
||||
if ( get_turn_info_for_endpoint<AssignPolicy, false, true>
|
||||
::apply(pi, pj, pk, qi, qj, qk,
|
||||
is_p_first, is_p_last, is_q_first, is_q_last,
|
||||
tp_model, result, method_touch, out) )
|
||||
tp_model, inters, method_touch, out) )
|
||||
{
|
||||
// do nothing
|
||||
}
|
||||
else
|
||||
{
|
||||
touch<TurnInfo>::apply(pi, pj, pk, qi, qj, qk,
|
||||
tp, result.template get<0>(), result.template get<1>(), side_calc);
|
||||
tp, inters.i_info(), inters.d_info(), inters.sides());
|
||||
|
||||
if ( tp.operations[0].operation == operation_blocked )
|
||||
{
|
||||
@@ -220,10 +152,20 @@ struct get_turn_info_linear_linear
|
||||
tp.operations[0].is_collinear = true;
|
||||
}
|
||||
|
||||
replace_method_and_operations_tm(tp.method, tp.operations[0].operation, tp.operations[1].operation);
|
||||
replace_method_and_operations_tm(tp.method,
|
||||
tp.operations[0].operation,
|
||||
tp.operations[1].operation);
|
||||
|
||||
AssignPolicy::apply(tp, pi, qi, result.template get<0>(), result.template get<1>());
|
||||
*out++ = tp;
|
||||
// TODO: move this into the append_xxx and call for each turn?
|
||||
AssignPolicy::apply(tp, pi, qi, inters.i_info(), inters.d_info());
|
||||
|
||||
if ( ! handle_spikes
|
||||
|| ! append_opposite_spikes<append_touches>(tp, inters,
|
||||
is_p_last, is_q_last,
|
||||
out) )
|
||||
{
|
||||
*out++ = tp;
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
@@ -232,7 +174,7 @@ struct get_turn_info_linear_linear
|
||||
if ( get_turn_info_for_endpoint<AssignPolicy, true, true>
|
||||
::apply(pi, pj, pk, qi, qj, qk,
|
||||
is_p_first, is_p_last, is_q_first, is_q_last,
|
||||
tp_model, result, method_equal, out) )
|
||||
tp_model, inters, method_equal, out) )
|
||||
{
|
||||
// do nothing
|
||||
}
|
||||
@@ -241,40 +183,38 @@ struct get_turn_info_linear_linear
|
||||
tp.operations[0].is_collinear = true;
|
||||
tp.operations[1].is_collinear = true;
|
||||
|
||||
if ( ! result.template get<1>().opposite )
|
||||
if ( ! inters.d_info().opposite )
|
||||
{
|
||||
// Both equal
|
||||
// or collinear-and-ending at intersection point
|
||||
equal<TurnInfo>::apply(pi, pj, pk, qi, qj, qk,
|
||||
tp, result.template get<0>(), result.template get<1>(), side_calc);
|
||||
tp, inters.i_info(), inters.d_info(), inters.sides());
|
||||
|
||||
replacer_of_method_and_operations_ec replacer(method_touch);
|
||||
replacer(tp.method, tp.operations[0].operation, tp.operations[1].operation);
|
||||
|
||||
// TODO: This isn't correct handling, hence commented out
|
||||
/*spike_detector<Point1, Point2> spike_detect(side_calc);
|
||||
if ( tp.operations[0].operation == operation_union
|
||||
&& spike_detect.is_spike_p())
|
||||
// TODO: move this into the append_xxx and call for each turn?
|
||||
AssignPolicy::apply(tp, pi, qi, inters.i_info(), inters.d_info());
|
||||
|
||||
// conditionally handle spikes
|
||||
if ( ! handle_spikes
|
||||
|| ! append_collinear_spikes(tp, inters,
|
||||
is_p_last, is_q_last,
|
||||
method_touch, operation_union,
|
||||
out) )
|
||||
{
|
||||
tp.operations[0].operation = operation_continue;
|
||||
*out++ = tp; // no spikes
|
||||
}
|
||||
if ( tp.operations[1].operation == operation_union
|
||||
&& spike_detect.is_spike_q())
|
||||
{
|
||||
tp.operations[1].operation = operation_continue;
|
||||
}*/
|
||||
|
||||
AssignPolicy::apply(tp, pi, qi, result.template get<0>(), result.template get<1>());
|
||||
*out++ = tp;
|
||||
}
|
||||
else
|
||||
{
|
||||
// TODO: ignore for spikes or generate something else than opposite?
|
||||
|
||||
equal_opposite
|
||||
<
|
||||
TurnInfo,
|
||||
AssignPolicy
|
||||
>::apply(pi, qi,
|
||||
tp, out, result.template get<0>(), result.template get<1>());
|
||||
>::apply(pi, qi, tp, out, inters.i_info(), inters.d_info());
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -285,7 +225,7 @@ struct get_turn_info_linear_linear
|
||||
if ( get_turn_info_for_endpoint<AssignPolicy, true, true>
|
||||
::apply(pi, pj, pk, qi, qj, qk,
|
||||
is_p_first, is_p_last, is_q_first, is_q_last,
|
||||
tp_model, result, method_collinear, out) )
|
||||
tp_model, inters, method_collinear, out) )
|
||||
{
|
||||
// do nothing
|
||||
}
|
||||
@@ -294,63 +234,69 @@ struct get_turn_info_linear_linear
|
||||
tp.operations[0].is_collinear = true;
|
||||
tp.operations[1].is_collinear = true;
|
||||
|
||||
if (! result.template get<1>().opposite)
|
||||
{
|
||||
if (result.template get<1>().arrival[0] == 0)
|
||||
if ( ! inters.d_info().opposite )
|
||||
{
|
||||
method_type method_replace = method_touch_interior;
|
||||
operation_type spike_op = operation_continue;
|
||||
|
||||
if ( inters.d_info().arrival[0] == 0 )
|
||||
{
|
||||
// Collinear, but similar thus handled as equal
|
||||
equal<TurnInfo>::apply(pi, pj, pk, qi, qj, qk,
|
||||
tp, result.template get<0>(), result.template get<1>(), side_calc);
|
||||
tp, inters.i_info(), inters.d_info(), inters.sides());
|
||||
|
||||
// NOTE: don't change the method only if methods are WRT IPs, not segments!
|
||||
// (currently this approach is used)
|
||||
// override assigned method
|
||||
//tp.method = method_collinear;
|
||||
|
||||
replacer_of_method_and_operations_ec replacer(method_touch);
|
||||
replacer(tp.method, tp.operations[0].operation, tp.operations[1].operation);
|
||||
|
||||
// TODO: This isn't correct handling, hence commented out
|
||||
/*spike_detector<Point1, Point2> spike_detect(side_calc);
|
||||
if ( tp.operations[0].operation == operation_union
|
||||
&& spike_detect.is_spike_p())
|
||||
{
|
||||
tp.operations[0].operation = operation_continue;
|
||||
}
|
||||
if ( tp.operations[1].operation == operation_union
|
||||
&& spike_detect.is_spike_q())
|
||||
{
|
||||
tp.operations[1].operation = operation_continue;
|
||||
}*/
|
||||
method_replace = method_touch;
|
||||
spike_op = operation_union;
|
||||
}
|
||||
else
|
||||
{
|
||||
collinear<TurnInfo>::apply(pi, pj, pk, qi, qj, qk,
|
||||
tp, result.template get<0>(), result.template get<1>(), side_calc);
|
||||
tp, inters.i_info(), inters.d_info(), inters.sides());
|
||||
|
||||
replacer_of_method_and_operations_ec replacer(method_touch_interior);
|
||||
replacer(tp.method, tp.operations[0].operation, tp.operations[1].operation);
|
||||
|
||||
// TEST
|
||||
//spike_detector<Point1, Point2> spike_detect(side_calc);
|
||||
//spike_detect.is_spike_p();
|
||||
//spike_detect.is_spike_q();
|
||||
//method_replace = method_touch_interior;
|
||||
//spike_op = operation_continue;
|
||||
}
|
||||
|
||||
AssignPolicy::apply(tp, pi, qi, result.template get<0>(), result.template get<1>());
|
||||
*out++ = tp;
|
||||
replacer_of_method_and_operations_ec replacer(method_replace);
|
||||
replacer(tp.method, tp.operations[0].operation, tp.operations[1].operation);
|
||||
|
||||
// TODO: move this into the append_xxx and call for each turn?
|
||||
AssignPolicy::apply(tp, pi, qi, inters.i_info(), inters.d_info());
|
||||
|
||||
// conditionally handle spikes
|
||||
if ( ! handle_spikes
|
||||
|| ! append_collinear_spikes(tp, inters,
|
||||
is_p_last, is_q_last,
|
||||
method_replace, spike_op,
|
||||
out) )
|
||||
{
|
||||
// no spikes
|
||||
*out++ = tp;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// If this always 'm' ?
|
||||
replacer_of_method_and_operations_ec replacer(method_touch_interior);
|
||||
|
||||
// conditionally handle spikes
|
||||
if ( handle_spikes )
|
||||
{
|
||||
append_opposite_spikes<append_collinear_opposite>(tp, inters,
|
||||
is_p_last, is_q_last,
|
||||
out);
|
||||
}
|
||||
|
||||
// TODO: ignore for spikes?
|
||||
// E.g. pass is_p_valid = !is_p_last && !is_pj_spike,
|
||||
// the same with is_q_valid
|
||||
|
||||
collinear_opposite
|
||||
<
|
||||
TurnInfo,
|
||||
AssignPolicy
|
||||
>::apply(pi, pj, pk, qi, qj, qk,
|
||||
tp, out, result.template get<0>(), result.template get<1>(), side_calc,
|
||||
tp, out, inters.i_info(), inters.d_info(), inters.sides(),
|
||||
replacer, !is_p_last, !is_q_last);
|
||||
}
|
||||
}
|
||||
@@ -361,8 +307,31 @@ struct get_turn_info_linear_linear
|
||||
// degenerate points
|
||||
if (AssignPolicy::include_degenerate)
|
||||
{
|
||||
only_convert<TurnInfo>::apply(tp, result.template get<0>());
|
||||
AssignPolicy::apply(tp, pi, qi, result.template get<0>(), result.template get<1>());
|
||||
only_convert::apply(tp, inters.i_info());
|
||||
|
||||
// if any, only one of those should be true
|
||||
if ( is_p_first
|
||||
&& equals::equals_point_point(pi, tp.point) )
|
||||
{
|
||||
tp.operations[0].position = position_front;
|
||||
}
|
||||
else if ( is_p_last
|
||||
&& equals::equals_point_point(pj, tp.point) )
|
||||
{
|
||||
tp.operations[0].position = position_back;
|
||||
}
|
||||
else if ( is_q_first
|
||||
&& equals::equals_point_point(qi, tp.point) )
|
||||
{
|
||||
tp.operations[1].position = position_front;
|
||||
}
|
||||
else if ( is_q_last
|
||||
&& equals::equals_point_point(qj, tp.point) )
|
||||
{
|
||||
tp.operations[1].position = position_back;
|
||||
}
|
||||
|
||||
AssignPolicy::apply(tp, pi, qi, inters.i_info(), inters.d_info());
|
||||
*out++ = tp;
|
||||
}
|
||||
}
|
||||
@@ -382,6 +351,157 @@ struct get_turn_info_linear_linear
|
||||
return out;
|
||||
}
|
||||
|
||||
template <typename TurnInfo,
|
||||
typename IntersectionInfo,
|
||||
typename OutIt>
|
||||
static inline bool append_collinear_spikes(TurnInfo & tp,
|
||||
IntersectionInfo const& inters_info,
|
||||
bool is_p_last, bool is_q_last,
|
||||
method_type method, operation_type spike_op,
|
||||
OutIt out)
|
||||
{
|
||||
// method == touch || touch_interior
|
||||
// both position == middle
|
||||
|
||||
bool is_p_spike = tp.operations[0].operation == spike_op
|
||||
&& ! is_p_last
|
||||
&& inters_info.is_spike_p();
|
||||
bool is_q_spike = tp.operations[1].operation == spike_op
|
||||
&& ! is_q_last
|
||||
&& inters_info.is_spike_q();
|
||||
|
||||
if ( is_p_spike && is_q_spike )
|
||||
{
|
||||
tp.method = method;
|
||||
tp.operations[0].operation = operation_blocked;
|
||||
tp.operations[1].operation = operation_blocked;
|
||||
*out++ = tp;
|
||||
tp.operations[0].operation = operation_intersection;
|
||||
tp.operations[1].operation = operation_intersection;
|
||||
*out++ = tp;
|
||||
|
||||
return true;
|
||||
}
|
||||
else if ( is_p_spike )
|
||||
{
|
||||
tp.method = method;
|
||||
tp.operations[0].operation = operation_blocked;
|
||||
tp.operations[1].operation = operation_union;
|
||||
*out++ = tp;
|
||||
tp.operations[0].operation = operation_intersection;
|
||||
//tp.operations[1].operation = operation_union;
|
||||
*out++ = tp;
|
||||
|
||||
return true;
|
||||
}
|
||||
else if ( is_q_spike )
|
||||
{
|
||||
tp.method = method;
|
||||
tp.operations[0].operation = operation_union;
|
||||
tp.operations[1].operation = operation_blocked;
|
||||
*out++ = tp;
|
||||
//tp.operations[0].operation = operation_union;
|
||||
tp.operations[1].operation = operation_intersection;
|
||||
*out++ = tp;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
enum append_version { append_touches, append_collinear_opposite };
|
||||
|
||||
template <append_version Version,
|
||||
typename TurnInfo,
|
||||
typename IntersectionInfo,
|
||||
typename OutIt>
|
||||
static inline bool append_opposite_spikes(TurnInfo & tp,
|
||||
IntersectionInfo const& inters,
|
||||
bool is_p_last, bool is_q_last,
|
||||
OutIt out)
|
||||
{
|
||||
bool is_p_spike = ( Version == append_touches ?
|
||||
( tp.operations[0].operation == operation_continue
|
||||
|| tp.operations[0].operation == operation_intersection ) :
|
||||
true )
|
||||
&& ! is_p_last
|
||||
&& inters.is_spike_p();
|
||||
bool is_q_spike = ( Version == append_touches ?
|
||||
( tp.operations[1].operation == operation_continue
|
||||
|| tp.operations[1].operation == operation_intersection ) :
|
||||
true )
|
||||
&& ! is_q_last
|
||||
&& inters.is_spike_q();
|
||||
|
||||
bool res = false;
|
||||
|
||||
if ( is_p_spike && ( Version == append_touches || inters.d_info().arrival[0] == 1 ) )
|
||||
{
|
||||
if ( Version == append_touches )
|
||||
{
|
||||
tp.operations[0].is_collinear = true;
|
||||
//tp.operations[1].is_collinear = ???
|
||||
tp.method = method_touch;
|
||||
}
|
||||
else
|
||||
{
|
||||
//tp.operations[0].is_collinear = true;
|
||||
//tp.operations[1].is_collinear = true;
|
||||
|
||||
BOOST_ASSERT(inters.i_info().count > 1);
|
||||
|
||||
base_turn_handler::assign_point(tp, method_touch_interior,
|
||||
inters.i_info(), 1);
|
||||
|
||||
AssignPolicy::apply(tp, inters.pi(), inters.qi(),
|
||||
inters.i_info(), inters.d_info());
|
||||
}
|
||||
|
||||
tp.operations[0].operation = operation_blocked;
|
||||
tp.operations[1].operation = operation_intersection;
|
||||
*out++ = tp;
|
||||
tp.operations[0].operation = operation_intersection;
|
||||
//tp.operations[1].operation = operation_intersection;
|
||||
*out++ = tp;
|
||||
|
||||
res = true;
|
||||
}
|
||||
|
||||
if ( is_q_spike && ( Version == append_touches || inters.d_info().arrival[1] == 1 ) )
|
||||
{
|
||||
if ( Version == append_touches )
|
||||
{
|
||||
//tp.operations[0].is_collinear = ???
|
||||
tp.operations[1].is_collinear = true;
|
||||
tp.method = method_touch;
|
||||
}
|
||||
else
|
||||
{
|
||||
//tp.operations[0].is_collinear = true;
|
||||
//tp.operations[1].is_collinear = true;
|
||||
|
||||
BOOST_ASSERT(inters.i_info().count > 0);
|
||||
|
||||
base_turn_handler::assign_point(tp, method_touch_interior, inters.i_info(), 0);
|
||||
|
||||
AssignPolicy::apply(tp, inters.pi(), inters.qi(),
|
||||
inters.i_info(), inters.d_info());
|
||||
}
|
||||
|
||||
tp.operations[0].operation = operation_intersection;
|
||||
tp.operations[1].operation = operation_blocked;
|
||||
*out++ = tp;
|
||||
//tp.operations[0].operation = operation_intersection;
|
||||
tp.operations[1].operation = operation_intersection;
|
||||
*out++ = tp;
|
||||
|
||||
res = true;
|
||||
}
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
static inline void replace_method_and_operations_tm(method_type & method,
|
||||
operation_type & op0,
|
||||
operation_type & op1)
|
||||
@@ -412,6 +532,14 @@ struct get_turn_info_linear_linear
|
||||
{
|
||||
op1 = operation_union;
|
||||
}
|
||||
|
||||
// spikes in 'm'
|
||||
if ( method == method_error )
|
||||
{
|
||||
method = method_touch_interior;
|
||||
op0 = operation_union;
|
||||
op1 = operation_union;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -51,6 +51,7 @@
|
||||
#include <boost/geometry/algorithms/detail/disjoint/box_box.hpp>
|
||||
#include <boost/geometry/algorithms/detail/disjoint/point_point.hpp>
|
||||
#include <boost/geometry/algorithms/detail/partition.hpp>
|
||||
#include <boost/geometry/algorithms/detail/recalculate.hpp>
|
||||
#include <boost/geometry/algorithms/detail/overlay/get_turn_info.hpp>
|
||||
#include <boost/geometry/algorithms/detail/overlay/get_turn_info_ll.hpp>
|
||||
#include <boost/geometry/algorithms/detail/overlay/get_turn_info_la.hpp>
|
||||
@@ -171,12 +172,12 @@ class get_turns_in_sections
|
||||
|
||||
public :
|
||||
// Returns true if terminated, false if interrupted
|
||||
template <typename Turns, typename RescalePolicy, typename InterruptPolicy>
|
||||
template <typename Turns, typename RobustPolicy, typename InterruptPolicy>
|
||||
static inline bool apply(
|
||||
int source_id1, Geometry1 const& geometry1, Section1 const& sec1,
|
||||
int source_id2, Geometry2 const& geometry2, Section2 const& sec2,
|
||||
bool skip_larger,
|
||||
RescalePolicy const& rescale_policy,
|
||||
RobustPolicy const& robust_policy,
|
||||
Turns& turns,
|
||||
InterruptPolicy& interrupt_policy)
|
||||
{
|
||||
@@ -216,7 +217,7 @@ public :
|
||||
range1_iterator prev1, it1, end1;
|
||||
|
||||
get_start_point_iterator(sec1, view1, prev1, it1, end1,
|
||||
index1, ndi1, dir1, sec2.bounding_box, rescale_policy);
|
||||
index1, ndi1, dir1, sec2.bounding_box, robust_policy);
|
||||
|
||||
// We need a circular iterator because it might run through the closing point.
|
||||
// One circle is actually enough but this one is just convenient.
|
||||
@@ -227,12 +228,12 @@ public :
|
||||
// section 2: [--------------]
|
||||
// section 1: |----|---|---|---|---|
|
||||
for (prev1 = it1++, next1++;
|
||||
it1 != end1 && ! exceeding<0>(dir1, *prev1, sec2.bounding_box, rescale_policy);
|
||||
it1 != end1 && ! exceeding<0>(dir1, *prev1, sec2.bounding_box, robust_policy);
|
||||
++prev1, ++it1, ++index1, ++next1, ++ndi1)
|
||||
{
|
||||
ever_circling_iterator<range1_iterator> nd_next1(
|
||||
begin_range_1, end_range_1, next1, true);
|
||||
advance_to_non_duplicate_next(nd_next1, it1, sec1, rescale_policy);
|
||||
advance_to_non_duplicate_next(nd_next1, it1, sec1, robust_policy);
|
||||
|
||||
int index2 = sec2.begin_index;
|
||||
int ndi2 = sec2.non_duplicate_index;
|
||||
@@ -240,12 +241,12 @@ public :
|
||||
range2_iterator prev2, it2, end2;
|
||||
|
||||
get_start_point_iterator(sec2, view2, prev2, it2, end2,
|
||||
index2, ndi2, dir2, sec1.bounding_box, rescale_policy);
|
||||
index2, ndi2, dir2, sec1.bounding_box, robust_policy);
|
||||
ever_circling_iterator<range2_iterator> next2(begin_range_2, end_range_2, it2, true);
|
||||
next2++;
|
||||
|
||||
for (prev2 = it2++, next2++;
|
||||
it2 != end2 && ! exceeding<0>(dir2, *prev2, sec1.bounding_box, rescale_policy);
|
||||
it2 != end2 && ! exceeding<0>(dir2, *prev2, sec1.bounding_box, robust_policy);
|
||||
++prev2, ++it2, ++index2, ++next2, ++ndi2)
|
||||
{
|
||||
bool skip = same_source;
|
||||
@@ -271,7 +272,7 @@ public :
|
||||
// Move to the "non duplicate next"
|
||||
ever_circling_iterator<range2_iterator> nd_next2(
|
||||
begin_range_2, end_range_2, next2, true);
|
||||
advance_to_non_duplicate_next(nd_next2, it2, sec2, rescale_policy);
|
||||
advance_to_non_duplicate_next(nd_next2, it2, sec2, robust_policy);
|
||||
|
||||
typedef typename boost::range_value<Turns>::type turn_info;
|
||||
|
||||
@@ -293,7 +294,7 @@ public :
|
||||
|
||||
TurnPolicy::apply(*prev1, *it1, *nd_next1, *prev2, *it2, *nd_next2,
|
||||
is_1_first, is_1_last, is_2_first, is_2_last,
|
||||
ti, rescale_policy, std::back_inserter(turns));
|
||||
ti, robust_policy, std::back_inserter(turns));
|
||||
|
||||
if (InterruptPolicy::enabled)
|
||||
{
|
||||
@@ -318,27 +319,34 @@ private :
|
||||
typedef typename model::referring_segment<point2_type const> segment2_type;
|
||||
|
||||
|
||||
template <size_t Dim, typename Point, typename Box, typename RescalePolicy>
|
||||
static inline bool preceding(int dir, Point const& point, Box const& box, RescalePolicy const& rescale_policy)
|
||||
template <size_t Dim, typename Point, typename Box, typename RobustPolicy>
|
||||
static inline bool preceding(int dir, Point const& point, Box const& box, RobustPolicy const& robust_policy)
|
||||
{
|
||||
boost::ignore_unused_variable_warning(rescale_policy);
|
||||
return (dir == 1 && get<Dim>(point) < get<min_corner, Dim>(box))
|
||||
|| (dir == -1 && get<Dim>(point) > get<max_corner, Dim>(box));
|
||||
typename robust_point_type<Point, RobustPolicy>::type robust_point;
|
||||
geometry::recalculate(robust_point, point, robust_policy);
|
||||
return (dir == 1 && get<Dim>(robust_point) < get<min_corner, Dim>(box))
|
||||
|| (dir == -1 && get<Dim>(robust_point) > get<max_corner, Dim>(box));
|
||||
}
|
||||
|
||||
template <size_t Dim, typename Point, typename Box, typename RescalePolicy>
|
||||
static inline bool exceeding(int dir, Point const& point, Box const& box, RescalePolicy const& rescale_policy)
|
||||
template <size_t Dim, typename Point, typename Box, typename RobustPolicy>
|
||||
static inline bool exceeding(int dir, Point const& point, Box const& box, RobustPolicy const& robust_policy)
|
||||
{
|
||||
boost::ignore_unused_variable_warning(rescale_policy);
|
||||
return (dir == 1 && get<Dim>(point) > get<max_corner, Dim>(box))
|
||||
|| (dir == -1 && get<Dim>(point) < get<min_corner, Dim>(box));
|
||||
typename robust_point_type<Point, RobustPolicy>::type robust_point;
|
||||
geometry::recalculate(robust_point, point, robust_policy);
|
||||
return (dir == 1 && get<Dim>(robust_point) > get<max_corner, Dim>(box))
|
||||
|| (dir == -1 && get<Dim>(robust_point) < get<min_corner, Dim>(box));
|
||||
}
|
||||
|
||||
template <typename Iterator, typename RangeIterator, typename Section, typename RescalePolicy>
|
||||
template <typename Iterator, typename RangeIterator, typename Section, typename RobustPolicy>
|
||||
static inline void advance_to_non_duplicate_next(Iterator& next,
|
||||
RangeIterator const& it, Section const& section, RescalePolicy const& rescale_policy)
|
||||
RangeIterator const& it, Section const& section, RobustPolicy const& robust_policy)
|
||||
{
|
||||
boost::ignore_unused_variable_warning(rescale_policy);
|
||||
typedef typename robust_point_type<point1_type, RobustPolicy>::type robust_point_type;
|
||||
robust_point_type robust_point_from_it;
|
||||
robust_point_type robust_point_from_next;
|
||||
geometry::recalculate(robust_point_from_it, *it, robust_policy);
|
||||
geometry::recalculate(robust_point_from_next, *next, robust_policy);
|
||||
|
||||
// To see where the next segments bend to, in case of touch/intersections
|
||||
// on end points, we need (in case of degenerate/duplicate points) an extra
|
||||
// iterator which moves to the REAL next point, so non duplicate.
|
||||
@@ -349,10 +357,14 @@ private :
|
||||
// So advance to the "non duplicate next"
|
||||
// (the check is defensive, to avoid endless loops)
|
||||
std::size_t check = 0;
|
||||
while(! detail::disjoint::disjoint_point_point(*it, *next)
|
||||
while(! detail::disjoint::disjoint_point_point
|
||||
(
|
||||
robust_point_from_it, robust_point_from_next
|
||||
)
|
||||
&& check++ < section.range_count)
|
||||
{
|
||||
next++;
|
||||
geometry::recalculate(robust_point_from_next, *next, robust_policy);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -360,14 +372,14 @@ private :
|
||||
// because of the logistics of "index" (the section-iterator automatically
|
||||
// skips to the begin-point, we loose the index or have to recalculate it)
|
||||
// So we mimic it here
|
||||
template <typename Range, typename Section, typename Box, typename RescalePolicy>
|
||||
template <typename Range, typename Section, typename Box, typename RobustPolicy>
|
||||
static inline void get_start_point_iterator(Section & section,
|
||||
Range const& range,
|
||||
typename boost::range_iterator<Range const>::type& it,
|
||||
typename boost::range_iterator<Range const>::type& prev,
|
||||
typename boost::range_iterator<Range const>::type& end,
|
||||
int& index, int& ndi,
|
||||
int dir, Box const& other_bounding_box, RescalePolicy const& rescale_policy)
|
||||
int dir, Box const& other_bounding_box, RobustPolicy const& robust_policy)
|
||||
{
|
||||
it = boost::begin(range) + section.begin_index;
|
||||
end = boost::begin(range) + section.end_index + 1;
|
||||
@@ -375,7 +387,7 @@ private :
|
||||
// Mimic section-iterator:
|
||||
// Skip to point such that section interects other box
|
||||
prev = it++;
|
||||
for(; it != end && preceding<0>(dir, *it, other_bounding_box, rescale_policy);
|
||||
for(; it != end && preceding<0>(dir, *it, other_bounding_box, robust_policy);
|
||||
prev = it++, index++, ndi++)
|
||||
{}
|
||||
// Go back one step because we want to start completely preceding
|
||||
@@ -407,7 +419,7 @@ template
|
||||
bool Reverse1, bool Reverse2,
|
||||
typename Turns,
|
||||
typename TurnPolicy,
|
||||
typename RescalePolicy,
|
||||
typename RobustPolicy,
|
||||
typename InterruptPolicy
|
||||
>
|
||||
struct section_visitor
|
||||
@@ -416,17 +428,17 @@ struct section_visitor
|
||||
Geometry1 const& m_geometry1;
|
||||
int m_source_id2;
|
||||
Geometry2 const& m_geometry2;
|
||||
RescalePolicy const& m_rescale_policy;
|
||||
RobustPolicy const& m_rescale_policy;
|
||||
Turns& m_turns;
|
||||
InterruptPolicy& m_interrupt_policy;
|
||||
|
||||
section_visitor(int id1, Geometry1 const& g1,
|
||||
int id2, Geometry2 const& g2,
|
||||
RescalePolicy const& rescale_policy,
|
||||
RobustPolicy const& robust_policy,
|
||||
Turns& turns, InterruptPolicy& ip)
|
||||
: m_source_id1(id1), m_geometry1(g1)
|
||||
, m_source_id2(id2), m_geometry2(g2)
|
||||
, m_rescale_policy(rescale_policy)
|
||||
, m_rescale_policy(robust_policy)
|
||||
, m_turns(turns)
|
||||
, m_interrupt_policy(ip)
|
||||
{}
|
||||
@@ -465,32 +477,39 @@ class get_turns_generic
|
||||
{
|
||||
|
||||
public:
|
||||
template <typename RescalePolicy, typename Turns, typename InterruptPolicy>
|
||||
template <typename RobustPolicy, typename Turns, typename InterruptPolicy>
|
||||
static inline void apply(
|
||||
int source_id1, Geometry1 const& geometry1,
|
||||
int source_id2, Geometry2 const& geometry2,
|
||||
RescalePolicy const& rescale_policy,
|
||||
RobustPolicy const& robust_policy,
|
||||
Turns& turns,
|
||||
InterruptPolicy& interrupt_policy)
|
||||
{
|
||||
// First create monotonic sections...
|
||||
typedef typename boost::range_value<Turns>::type ip_type;
|
||||
typedef typename ip_type::point_type point_type;
|
||||
typedef model::box<point_type> box_type;
|
||||
|
||||
typedef model::box
|
||||
<
|
||||
typename geometry::robust_point_type
|
||||
<
|
||||
point_type, RobustPolicy
|
||||
>::type
|
||||
> box_type;
|
||||
typedef typename geometry::sections<box_type, 2> sections_type;
|
||||
|
||||
sections_type sec1, sec2;
|
||||
|
||||
geometry::sectionalize<Reverse1>(geometry1, rescale_policy, true, sec1, 0);
|
||||
geometry::sectionalize<Reverse2>(geometry2, rescale_policy, true, sec2, 1);
|
||||
geometry::sectionalize<Reverse1>(geometry1, robust_policy, true, sec1, 0);
|
||||
geometry::sectionalize<Reverse2>(geometry2, robust_policy, true, sec2, 1);
|
||||
|
||||
// ... and then partition them, intersecting overlapping sections in visitor method
|
||||
section_visitor
|
||||
<
|
||||
Geometry1, Geometry2,
|
||||
Reverse1, Reverse2,
|
||||
Turns, TurnPolicy, RescalePolicy, InterruptPolicy
|
||||
> visitor(source_id1, geometry1, source_id2, geometry2, rescale_policy, turns, interrupt_policy);
|
||||
Turns, TurnPolicy, RobustPolicy, InterruptPolicy
|
||||
> visitor(source_id1, geometry1, source_id2, geometry2, robust_policy, turns, interrupt_policy);
|
||||
|
||||
geometry::partition
|
||||
<
|
||||
@@ -530,11 +549,11 @@ struct get_turns_cs
|
||||
>::type iterator_type;
|
||||
|
||||
|
||||
template <typename RescalePolicy, typename Turns, typename InterruptPolicy>
|
||||
template <typename RobustPolicy, typename Turns, typename InterruptPolicy>
|
||||
static inline void apply(
|
||||
int source_id1, Range const& range,
|
||||
int source_id2, Box const& box,
|
||||
RescalePolicy const& rescale_policy,
|
||||
RobustPolicy const& robust_policy,
|
||||
Turns& turns,
|
||||
InterruptPolicy& interrupt_policy,
|
||||
int multi_index = -1, int ring_index = -1)
|
||||
@@ -605,7 +624,7 @@ struct get_turns_cs
|
||||
// NOTE: some dummy values could be passed below since this would be called only for Polygons and Boxes
|
||||
index == 0,
|
||||
unsigned(index) == segments_count1,
|
||||
rescale_policy,
|
||||
robust_policy,
|
||||
turns, interrupt_policy);
|
||||
// Future performance enhancement:
|
||||
// return if told by the interrupt policy
|
||||
@@ -634,7 +653,7 @@ private:
|
||||
else return 0;
|
||||
}
|
||||
|
||||
template <typename RescalePolicy, typename Turns, typename InterruptPolicy>
|
||||
template <typename RobustPolicy, typename Turns, typename InterruptPolicy>
|
||||
static inline void get_turns_with_box(segment_identifier const& seg_id, int source_id2,
|
||||
// Points from a range:
|
||||
point_type const& rp0,
|
||||
@@ -647,7 +666,7 @@ private:
|
||||
box_point_type const& bp3,
|
||||
bool const is_range_first,
|
||||
bool const is_range_last,
|
||||
RescalePolicy const& rescale_policy,
|
||||
RobustPolicy const& robust_policy,
|
||||
// Output
|
||||
Turns& turns,
|
||||
InterruptPolicy& interrupt_policy)
|
||||
@@ -667,25 +686,25 @@ private:
|
||||
TurnPolicy::apply(rp0, rp1, rp2, bp0, bp1, bp2,
|
||||
is_range_first, is_range_last,
|
||||
true, false,
|
||||
ti, rescale_policy, std::back_inserter(turns));
|
||||
ti, robust_policy, std::back_inserter(turns));
|
||||
|
||||
ti.operations[1].seg_id = segment_identifier(source_id2, -1, -1, 1);
|
||||
TurnPolicy::apply(rp0, rp1, rp2, bp1, bp2, bp3,
|
||||
is_range_first, is_range_last,
|
||||
false, false,
|
||||
ti, rescale_policy, std::back_inserter(turns));
|
||||
ti, robust_policy, std::back_inserter(turns));
|
||||
|
||||
ti.operations[1].seg_id = segment_identifier(source_id2, -1, -1, 2);
|
||||
TurnPolicy::apply(rp0, rp1, rp2, bp2, bp3, bp0,
|
||||
is_range_first, is_range_last,
|
||||
false, false,
|
||||
ti, rescale_policy, std::back_inserter(turns));
|
||||
ti, robust_policy, std::back_inserter(turns));
|
||||
|
||||
ti.operations[1].seg_id = segment_identifier(source_id2, -1, -1, 3);
|
||||
TurnPolicy::apply(rp0, rp1, rp2, bp3, bp0, bp1,
|
||||
is_range_first, is_range_last,
|
||||
false, true,
|
||||
ti, rescale_policy, std::back_inserter(turns));
|
||||
ti, robust_policy, std::back_inserter(turns));
|
||||
|
||||
if (InterruptPolicy::enabled)
|
||||
{
|
||||
@@ -705,11 +724,11 @@ template
|
||||
>
|
||||
struct get_turns_polygon_cs
|
||||
{
|
||||
template <typename RescalePolicy, typename Turns, typename InterruptPolicy>
|
||||
template <typename RobustPolicy, typename Turns, typename InterruptPolicy>
|
||||
static inline void apply(
|
||||
int source_id1, Polygon const& polygon,
|
||||
int source_id2, Box const& box,
|
||||
RescalePolicy const& rescale_policy,
|
||||
RobustPolicy const& robust_policy,
|
||||
Turns& turns, InterruptPolicy& interrupt_policy,
|
||||
int multi_index = -1)
|
||||
{
|
||||
@@ -725,7 +744,7 @@ struct get_turns_polygon_cs
|
||||
intersector_type::apply(
|
||||
source_id1, geometry::exterior_ring(polygon),
|
||||
source_id2, box,
|
||||
rescale_policy,
|
||||
robust_policy,
|
||||
turns, interrupt_policy,
|
||||
multi_index, -1);
|
||||
|
||||
@@ -739,7 +758,7 @@ struct get_turns_polygon_cs
|
||||
intersector_type::apply(
|
||||
source_id1, *it,
|
||||
source_id2, box,
|
||||
rescale_policy,
|
||||
robust_policy,
|
||||
turns, interrupt_policy,
|
||||
multi_index, i);
|
||||
}
|
||||
@@ -772,24 +791,24 @@ struct get_turn_info_type<Geometry1, Geometry2, AssignPolicy, Tag1, Tag2, linear
|
||||
: overlay::get_turn_info_linear_areal<AssignPolicy>
|
||||
{};
|
||||
|
||||
template <typename Geometry1, typename Geometry2,
|
||||
template <typename Geometry1, typename Geometry2, typename SegmentRatio,
|
||||
typename Tag1 = typename tag<Geometry1>::type, typename Tag2 = typename tag<Geometry2>::type,
|
||||
typename TagBase1 = typename topological_tag_base<Geometry1>::type, typename TagBase2 = typename topological_tag_base<Geometry2>::type>
|
||||
struct turn_operation_type
|
||||
{
|
||||
typedef overlay::turn_operation type;
|
||||
typedef overlay::turn_operation<SegmentRatio> type;
|
||||
};
|
||||
|
||||
template <typename Geometry1, typename Geometry2, typename Tag1, typename Tag2>
|
||||
struct turn_operation_type<Geometry1, Geometry2, Tag1, Tag2, linear_tag, linear_tag>
|
||||
template <typename Geometry1, typename Geometry2, typename SegmentRatio, typename Tag1, typename Tag2>
|
||||
struct turn_operation_type<Geometry1, Geometry2, SegmentRatio, Tag1, Tag2, linear_tag, linear_tag>
|
||||
{
|
||||
typedef overlay::turn_operation_linear type;
|
||||
typedef overlay::turn_operation_linear<SegmentRatio> type;
|
||||
};
|
||||
|
||||
template <typename Geometry1, typename Geometry2, typename Tag1, typename Tag2>
|
||||
struct turn_operation_type<Geometry1, Geometry2, Tag1, Tag2, linear_tag, areal_tag>
|
||||
template <typename Geometry1, typename Geometry2, typename SegmentRatio, typename Tag1, typename Tag2>
|
||||
struct turn_operation_type<Geometry1, Geometry2, SegmentRatio, Tag1, Tag2, linear_tag, areal_tag>
|
||||
{
|
||||
typedef overlay::turn_operation_linear type;
|
||||
typedef overlay::turn_operation_linear<SegmentRatio> type;
|
||||
};
|
||||
|
||||
}} // namespace detail::get_turns
|
||||
@@ -870,11 +889,11 @@ template
|
||||
>
|
||||
struct get_turns_reversed
|
||||
{
|
||||
template <typename RescalePolicy, typename Turns, typename InterruptPolicy>
|
||||
template <typename RobustPolicy, typename Turns, typename InterruptPolicy>
|
||||
static inline void apply(
|
||||
int source_id1, Geometry1 const& g1,
|
||||
int source_id2, Geometry2 const& g2,
|
||||
RescalePolicy const& rescale_policy,
|
||||
RobustPolicy const& robust_policy,
|
||||
Turns& turns,
|
||||
InterruptPolicy& interrupt_policy)
|
||||
{
|
||||
@@ -884,7 +903,7 @@ struct get_turns_reversed
|
||||
Geometry2, Geometry1,
|
||||
Reverse2, Reverse1,
|
||||
TurnPolicy
|
||||
>::apply(source_id2, g2, source_id1, g1, rescale_policy,
|
||||
>::apply(source_id2, g2, source_id1, g1, robust_policy,
|
||||
turns, interrupt_policy);
|
||||
}
|
||||
};
|
||||
@@ -913,26 +932,18 @@ template
|
||||
typename AssignPolicy,
|
||||
typename Geometry1,
|
||||
typename Geometry2,
|
||||
typename RescalePolicy,
|
||||
typename RobustPolicy,
|
||||
typename Turns,
|
||||
typename InterruptPolicy
|
||||
>
|
||||
inline void get_turns(Geometry1 const& geometry1,
|
||||
Geometry2 const& geometry2,
|
||||
RescalePolicy const& rescale_policy,
|
||||
RobustPolicy const& robust_policy,
|
||||
Turns& turns,
|
||||
InterruptPolicy& interrupt_policy)
|
||||
{
|
||||
concept::check_concepts_and_equal_dimensions<Geometry1 const, Geometry2 const>();
|
||||
|
||||
//typedef typename strategy_intersection
|
||||
// <
|
||||
// typename cs_tag<Geometry1>::type,
|
||||
// Geometry1,
|
||||
// Geometry2,
|
||||
// typename boost::range_value<Turns>::type
|
||||
// >::segment_intersection_strategy_type segment_intersection_strategy_type;
|
||||
|
||||
typedef detail::overlay::get_turn_info<AssignPolicy> TurnPolicy;
|
||||
//typedef detail::get_turns::get_turn_info_type<Geometry1, Geometry2, AssignPolicy> TurnPolicy;
|
||||
|
||||
@@ -958,7 +969,7 @@ inline void get_turns(Geometry1 const& geometry1,
|
||||
>::type::apply(
|
||||
0, geometry1,
|
||||
1, geometry2,
|
||||
rescale_policy,
|
||||
robust_policy,
|
||||
turns, interrupt_policy);
|
||||
}
|
||||
|
||||
|
||||
@@ -14,8 +14,17 @@
|
||||
#include <boost/geometry/algorithms/detail/ring_identifier.hpp>
|
||||
#include <boost/geometry/algorithms/detail/overlay/copy_segment_point.hpp>
|
||||
#include <boost/geometry/algorithms/detail/overlay/turn_info.hpp>
|
||||
#include <boost/geometry/algorithms/detail/recalculate.hpp>
|
||||
|
||||
#include <boost/geometry/policies/robustness/robust_point_type.hpp>
|
||||
#include <boost/geometry/policies/robustness/segment_ratio_type.hpp>
|
||||
#include <boost/geometry/policies/robustness/robust_type.hpp>
|
||||
#include <boost/geometry/algorithms/detail/zoom_to_robust.hpp>
|
||||
|
||||
#if defined(BOOST_GEOMETRY_DEBUG_HANDLE_TANGENCIES)
|
||||
#include <boost/geometry/algorithms/detail/overlay/debug_turn_info.hpp>
|
||||
#endif
|
||||
|
||||
#include <boost/geometry/geometries/point.hpp>
|
||||
#include <boost/geometry/geometries/segment.hpp>
|
||||
|
||||
@@ -33,7 +42,7 @@ template
|
||||
typename TurnPoints,
|
||||
typename Indexed,
|
||||
typename Geometry1, typename Geometry2,
|
||||
typename RescalePolicy,
|
||||
typename RobustPolicy,
|
||||
bool Reverse1, bool Reverse2,
|
||||
typename Strategy
|
||||
>
|
||||
@@ -42,12 +51,12 @@ struct sort_in_cluster
|
||||
inline sort_in_cluster(TurnPoints const& turn_points
|
||||
, Geometry1 const& geometry1
|
||||
, Geometry2 const& geometry2
|
||||
, RescalePolicy const& rescale_policy
|
||||
, RobustPolicy const& robust_policy
|
||||
, Strategy const& strategy)
|
||||
: m_turn_points(turn_points)
|
||||
, m_geometry1(geometry1)
|
||||
, m_geometry2(geometry2)
|
||||
, m_rescale_policy(rescale_policy)
|
||||
, m_rescale_policy(robust_policy)
|
||||
, m_strategy(strategy)
|
||||
{}
|
||||
|
||||
@@ -56,15 +65,15 @@ private :
|
||||
TurnPoints const& m_turn_points;
|
||||
Geometry1 const& m_geometry1;
|
||||
Geometry2 const& m_geometry2;
|
||||
RescalePolicy const& m_rescale_policy;
|
||||
RobustPolicy const& m_rescale_policy;
|
||||
Strategy const& m_strategy;
|
||||
|
||||
typedef typename Indexed::type turn_operation_type;
|
||||
typedef typename geometry::point_type<Geometry1>::type point_type;
|
||||
|
||||
typedef model::point
|
||||
<
|
||||
typename geometry::robust_type
|
||||
<
|
||||
typename detail::robust_type
|
||||
<
|
||||
typename select_coordinate_type<Geometry1, Geometry2>::type
|
||||
>::type,
|
||||
@@ -72,6 +81,8 @@ private :
|
||||
typename geometry::coordinate_system<Geometry1>::type
|
||||
> robust_point_type;
|
||||
|
||||
// Still called by #case_102_multi, #case_107_multi
|
||||
// #case_recursive_boxes_3
|
||||
inline void get_situation_map(Indexed const& left, Indexed const& right,
|
||||
robust_point_type& pi_rob, robust_point_type& pj_rob,
|
||||
robust_point_type& ri_rob, robust_point_type& rj_rob,
|
||||
@@ -89,47 +100,67 @@ private :
|
||||
geometry::copy_segment_points<Reverse1, Reverse2>(m_geometry1, m_geometry2,
|
||||
right.subject.other_id,
|
||||
si, sj);
|
||||
geometry::zoom_to_robust(pi, pj, ri, rj, si, sj,
|
||||
pi_rob, pj_rob,
|
||||
ri_rob, rj_rob,
|
||||
si_rob, sj_rob);
|
||||
|
||||
geometry::recalculate(pi_rob, pi, m_rescale_policy);
|
||||
geometry::recalculate(pj_rob, pj, m_rescale_policy);
|
||||
geometry::recalculate(ri_rob, ri, m_rescale_policy);
|
||||
geometry::recalculate(rj_rob, rj, m_rescale_policy);
|
||||
geometry::recalculate(si_rob, si, m_rescale_policy);
|
||||
geometry::recalculate(sj_rob, sj, m_rescale_policy);
|
||||
}
|
||||
|
||||
#if BOOST_GEOMETRY_HANDLE_TANGENCIES_WITH_OVERLAP_INFO
|
||||
// This method was still called but did no effect whatsoever on the results,
|
||||
// with or without robustness-rescaling.
|
||||
// Probable cause: we rescale in this file ourselves, ignoring passed policy
|
||||
// TODO: check this more.
|
||||
// Besides this, it currently does not compile for yet unknown reasons
|
||||
// (does not find specialization for segment_ratio_type)
|
||||
// It is currently only called from the Unit Test "multi_intersection.cpp"
|
||||
|
||||
// Determine how p/r and p/s are located.
|
||||
static inline void overlap_info(robust_point_type const& pi, robust_point_type const& pj,
|
||||
inline void overlap_info(
|
||||
robust_point_type const& pi, robust_point_type const& pj,
|
||||
robust_point_type const& ri, robust_point_type const& rj,
|
||||
robust_point_type const& si, robust_point_type const& sj,
|
||||
bool& pr_overlap, bool& ps_overlap, bool& rs_overlap)
|
||||
bool& pr_overlap, bool& ps_overlap, bool& rs_overlap) const
|
||||
{
|
||||
// Determine how p/r and p/s are located.
|
||||
// One of them is coming from opposite direction.
|
||||
|
||||
typedef model::referring_segment<robust_point_type const> segment_type;
|
||||
typedef segment_intersection_points
|
||||
<
|
||||
point_type,
|
||||
typename segment_ratio_type
|
||||
<
|
||||
point_type, RobustPolicy
|
||||
>::type
|
||||
> intersection_return_type;
|
||||
|
||||
typedef strategy::intersection::relate_cartesian_segments
|
||||
<
|
||||
policies::relate::segments_intersection_points
|
||||
<
|
||||
segment_type,
|
||||
segment_type,
|
||||
segment_intersection_points<point_type>
|
||||
intersection_return_type
|
||||
>
|
||||
> policy;
|
||||
|
||||
typedef model::referring_segment<robust_point_type const> segment_type;
|
||||
segment_type p(pi, pj);
|
||||
segment_type r(ri, rj);
|
||||
segment_type s(si, sj);
|
||||
|
||||
|
||||
// Get the intersection point (or two points)
|
||||
segment_intersection_points<point_type> pr = policy::apply(p, r);
|
||||
segment_intersection_points<point_type> ps = policy::apply(p, s);
|
||||
segment_intersection_points<point_type> rs = policy::apply(r, s);
|
||||
intersection_return_type pr = policy::apply(p, r, m_rescale_policy, pi, pj, ri, rj);
|
||||
intersection_return_type ps = policy::apply(p, s, m_rescale_policy, pi, pj, si, sj);
|
||||
intersection_return_type rs = policy::apply(r, s, m_rescale_policy, ri, rj, si, sj);
|
||||
|
||||
// Check on overlap
|
||||
pr_overlap = pr.count == 2;
|
||||
ps_overlap = ps.count == 2;
|
||||
rs_overlap = rs.count == 2;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
#ifdef BOOST_GEOMETRY_DEBUG_HANDLE_TANGENCIES
|
||||
@@ -141,11 +172,15 @@ private :
|
||||
{
|
||||
if (skip) return;
|
||||
|
||||
std::cout << "Case: " << header << " for " << left.index << " / " << right.index << std::endl;
|
||||
|
||||
robust_point_type pi, pj, ri, rj, si, sj;
|
||||
get_situation_map(left, right, pi, pj, ri, rj, si, sj);
|
||||
|
||||
#if BOOST_GEOMETRY_HANDLE_TANGENCIES_WITH_OVERLAP_INFO
|
||||
bool prc = false, psc = false, rsc = false;
|
||||
overlap_info(pi, pj, ri, rj, si, sj, prc, psc, rsc);
|
||||
#endif
|
||||
|
||||
int const side_ri_p = m_strategy.apply(pi, pj, ri);
|
||||
int const side_rj_p = m_strategy.apply(pi, pj, rj);
|
||||
@@ -154,7 +189,6 @@ private :
|
||||
int const side_si_r = m_strategy.apply(ri, rj, si);
|
||||
int const side_sj_r = m_strategy.apply(ri, rj, sj);
|
||||
|
||||
std::cout << "Case: " << header << " for " << left.index << " / " << right.index << std::endl;
|
||||
#ifdef BOOST_GEOMETRY_DEBUG_HANDLE_TANGENCIES_MORE
|
||||
std::cout << " Segment p:" << geometry::wkt(pi) << " .. " << geometry::wkt(pj) << std::endl;
|
||||
std::cout << " Segment r:" << geometry::wkt(ri) << " .. " << geometry::wkt(rj) << std::endl;
|
||||
@@ -172,7 +206,9 @@ private :
|
||||
<< " ri//p: " << side_ri_p
|
||||
<< " si//p: " << side_si_p
|
||||
<< " si//r: " << side_si_r
|
||||
#if BOOST_GEOMETRY_HANDLE_TANGENCIES_WITH_OVERLAP_INFO
|
||||
<< " cnts: " << int(prc) << "," << int(psc) << "," << int(rsc)
|
||||
#endif
|
||||
//<< " idx: " << left.index << "/" << right.index
|
||||
;
|
||||
|
||||
@@ -365,9 +401,13 @@ private :
|
||||
#endif
|
||||
}
|
||||
|
||||
#if BOOST_GEOMETRY_HANDLE_TANGENCIES_WITH_OVERLAP_INFO
|
||||
// We need EXTRA information here: are p/r/s overlapping?
|
||||
bool pr_ov = false, ps_ov = false, rs_ov = false;
|
||||
overlap_info(pi, pj, ri, rj, si, sj, pr_ov, ps_ov, rs_ov);
|
||||
#else
|
||||
// std::cout << "Boost.Geometry: skipping overlap_info" << std::endl;
|
||||
#endif
|
||||
|
||||
// One coming from right (#83,#90)
|
||||
// One coming from left (#90, #94, #95)
|
||||
@@ -375,12 +415,14 @@ private :
|
||||
{
|
||||
bool ret = false;
|
||||
|
||||
#if BOOST_GEOMETRY_HANDLE_TANGENCIES_WITH_OVERLAP_INFO
|
||||
if (pr_ov || ps_ov)
|
||||
{
|
||||
int r = side_ri_p != 0 ? side_ri_p : side_si_p;
|
||||
ret = r * side_si_r == 1;
|
||||
}
|
||||
else
|
||||
#endif
|
||||
{
|
||||
ret = side_si_r == 1;
|
||||
}
|
||||
@@ -397,6 +439,7 @@ private :
|
||||
// Take the one NOT overlapping
|
||||
bool ret = false;
|
||||
bool found = false;
|
||||
#if BOOST_GEOMETRY_HANDLE_TANGENCIES_WITH_OVERLAP_INFO
|
||||
if (pr_ov && ! ps_ov)
|
||||
{
|
||||
ret = true;
|
||||
@@ -407,6 +450,7 @@ private :
|
||||
ret = false;
|
||||
found = true;
|
||||
}
|
||||
#endif
|
||||
|
||||
debug_consider(0, left, right, header, false, "aligned", ret);
|
||||
if (found)
|
||||
@@ -655,14 +699,14 @@ template
|
||||
typename TurnPoints,
|
||||
typename Geometry1,
|
||||
typename Geometry2,
|
||||
typename RescalePolicy,
|
||||
typename RobustPolicy,
|
||||
typename Strategy
|
||||
>
|
||||
inline void handle_cluster(Iterator begin_cluster, Iterator end_cluster,
|
||||
TurnPoints& turn_points,
|
||||
operation_type for_operation,
|
||||
Geometry1 const& geometry1, Geometry2 const& geometry2,
|
||||
RescalePolicy& rescale_policy,
|
||||
RobustPolicy& robust_policy,
|
||||
Strategy const& strategy)
|
||||
{
|
||||
// First inspect and (possibly) discard rows
|
||||
@@ -677,15 +721,15 @@ inline void handle_cluster(Iterator begin_cluster, Iterator end_cluster,
|
||||
TurnPoints,
|
||||
IndexType,
|
||||
Geometry1, Geometry2,
|
||||
RescalePolicy,
|
||||
RobustPolicy,
|
||||
Reverse1, Reverse2,
|
||||
Strategy
|
||||
>(turn_points, geometry1, geometry2, rescale_policy, strategy));
|
||||
>(turn_points, geometry1, geometry2, robust_policy, strategy));
|
||||
|
||||
#if defined(BOOST_GEOMETRY_DEBUG_HANDLE_TANGENCIES)
|
||||
typedef typename IndexType::type operations_type;
|
||||
operations_type const& op = turn_points[begin_cluster->index].operations[begin_cluster->operation_index];
|
||||
std::cout << std::endl << "Clustered points on equal distance " << op.enriched.distance << std::endl;
|
||||
std::cout << std::endl << "Clustered points on equal distance " << op.fraction << std::endl;
|
||||
|
||||
std::cout << "->Indexes ";
|
||||
for (Iterator it = begin_cluster; it != end_cluster; ++it)
|
||||
|
||||
@@ -33,7 +33,10 @@
|
||||
#include <boost/geometry/algorithms/detail/overlay/overlay.hpp>
|
||||
#include <boost/geometry/algorithms/detail/overlay/overlay_type.hpp>
|
||||
#include <boost/geometry/algorithms/detail/overlay/follow.hpp>
|
||||
#include <boost/geometry/algorithms/detail/rescale.hpp>
|
||||
|
||||
#include <boost/geometry/policies/robustness/robust_point_type.hpp>
|
||||
#include <boost/geometry/policies/robustness/segment_ratio_type.hpp>
|
||||
#include <boost/geometry/policies/robustness/get_rescale_policy.hpp>
|
||||
|
||||
#include <boost/geometry/views/segment_view.hpp>
|
||||
|
||||
@@ -58,25 +61,58 @@ struct intersection_segment_segment_point
|
||||
template
|
||||
<
|
||||
typename Segment1, typename Segment2,
|
||||
typename RobustPolicy,
|
||||
typename OutputIterator, typename Strategy
|
||||
>
|
||||
static inline OutputIterator apply(Segment1 const& segment1,
|
||||
Segment2 const& segment2, OutputIterator out,
|
||||
Segment2 const& segment2,
|
||||
RobustPolicy const& robust_policy,
|
||||
OutputIterator out,
|
||||
Strategy const& )
|
||||
{
|
||||
typedef typename point_type<PointOut>::type point_type;
|
||||
|
||||
typedef typename geometry::robust_point_type
|
||||
<
|
||||
typename geometry::point_type<Segment1>::type,
|
||||
RobustPolicy
|
||||
>::type robust_point_type;
|
||||
|
||||
// TODO: rescale segment -> robust points
|
||||
robust_point_type pi_rob, pj_rob, qi_rob, qj_rob;
|
||||
{
|
||||
// Workaround:
|
||||
point_type pi, pj, qi, qj;
|
||||
assign_point_from_index<0>(segment1, pi);
|
||||
assign_point_from_index<1>(segment1, pj);
|
||||
assign_point_from_index<0>(segment2, qi);
|
||||
assign_point_from_index<1>(segment2, qj);
|
||||
geometry::recalculate(pi_rob, pi, robust_policy);
|
||||
geometry::recalculate(pj_rob, pj, robust_policy);
|
||||
geometry::recalculate(qi_rob, qi, robust_policy);
|
||||
geometry::recalculate(qj_rob, qj, robust_policy);
|
||||
}
|
||||
|
||||
// Get the intersection point (or two points)
|
||||
segment_intersection_points<point_type> is
|
||||
= strategy::intersection::relate_cartesian_segments
|
||||
typedef segment_intersection_points
|
||||
<
|
||||
point_type,
|
||||
typename segment_ratio_type
|
||||
<
|
||||
point_type, RobustPolicy
|
||||
>::type
|
||||
> intersection_return_type;
|
||||
|
||||
typedef strategy::intersection::relate_cartesian_segments
|
||||
<
|
||||
policies::relate::segments_intersection_points
|
||||
<
|
||||
Segment1,
|
||||
Segment2,
|
||||
segment_intersection_points<point_type>
|
||||
intersection_return_type
|
||||
>
|
||||
>::apply(segment1, segment2);
|
||||
> policy;
|
||||
|
||||
intersection_return_type is = policy::apply(segment1, segment2,
|
||||
robust_policy, pi_rob, pj_rob, qi_rob, qj_rob);
|
||||
|
||||
for (std::size_t i = 0; i < is.count; i++)
|
||||
{
|
||||
@@ -94,18 +130,25 @@ struct intersection_linestring_linestring_point
|
||||
template
|
||||
<
|
||||
typename Linestring1, typename Linestring2,
|
||||
typename RobustPolicy,
|
||||
typename OutputIterator, typename Strategy
|
||||
>
|
||||
static inline OutputIterator apply(Linestring1 const& linestring1,
|
||||
Linestring2 const& linestring2, OutputIterator out,
|
||||
Linestring2 const& linestring2,
|
||||
RobustPolicy const& robust_policy,
|
||||
OutputIterator out,
|
||||
Strategy const& )
|
||||
{
|
||||
typedef typename point_type<PointOut>::type point_type;
|
||||
|
||||
typedef detail::overlay::turn_info<point_type> turn_info;
|
||||
typedef detail::overlay::turn_info
|
||||
<
|
||||
point_type,
|
||||
typename segment_ratio_type<point_type, RobustPolicy>::type
|
||||
> turn_info;
|
||||
std::deque<turn_info> turns;
|
||||
|
||||
geometry::get_intersection_points(linestring1, linestring2, turns);
|
||||
geometry::get_intersection_points(linestring1, linestring2, robust_policy, turns);
|
||||
|
||||
for (typename boost::range_iterator<std::deque<turn_info> const>::type
|
||||
it = boost::begin(turns); it != boost::end(turns); ++it)
|
||||
@@ -149,9 +192,11 @@ struct intersection_of_linestring_with_areal
|
||||
template
|
||||
<
|
||||
typename LineString, typename Areal,
|
||||
typename RobustPolicy,
|
||||
typename OutputIterator, typename Strategy
|
||||
>
|
||||
static inline OutputIterator apply(LineString const& linestring, Areal const& areal,
|
||||
RobustPolicy const& robust_policy,
|
||||
OutputIterator out,
|
||||
Strategy const& )
|
||||
{
|
||||
@@ -169,8 +214,11 @@ struct intersection_of_linestring_with_areal
|
||||
> follower;
|
||||
|
||||
typedef typename point_type<LineStringOut>::type point_type;
|
||||
|
||||
typedef detail::overlay::traversal_turn_info<point_type> turn_info;
|
||||
typedef detail::overlay::traversal_turn_info
|
||||
<
|
||||
point_type,
|
||||
typename geometry::segment_ratio_type<point_type, RobustPolicy>::type
|
||||
> turn_info;
|
||||
std::deque<turn_info> turns;
|
||||
|
||||
detail::get_turns::no_interrupt_policy policy;
|
||||
@@ -178,8 +226,8 @@ struct intersection_of_linestring_with_areal
|
||||
<
|
||||
false,
|
||||
(OverlayType == overlay_intersection ? ReverseAreal : !ReverseAreal),
|
||||
detail::overlay::calculate_distance_policy
|
||||
>(linestring, areal, detail::no_rescale_policy(), turns, policy);
|
||||
detail::overlay::assign_null_policy
|
||||
>(linestring, areal, robust_policy, turns, policy);
|
||||
|
||||
if (turns.empty())
|
||||
{
|
||||
@@ -195,8 +243,7 @@ struct intersection_of_linestring_with_areal
|
||||
return out;
|
||||
}
|
||||
|
||||
|
||||
if (follower::included(border_point, areal))
|
||||
if (follower::included(border_point, areal, robust_policy))
|
||||
{
|
||||
LineStringOut copy;
|
||||
geometry::convert(linestring, copy);
|
||||
@@ -217,7 +264,7 @@ struct intersection_of_linestring_with_areal
|
||||
(
|
||||
linestring, areal,
|
||||
geometry::detail::overlay::operation_intersection,
|
||||
turns, out
|
||||
turns, robust_policy, out
|
||||
);
|
||||
}
|
||||
};
|
||||
@@ -359,9 +406,11 @@ struct intersection_insert
|
||||
false, true, false
|
||||
>
|
||||
{
|
||||
template <typename OutputIterator, typename Strategy>
|
||||
template <typename RobustPolicy, typename OutputIterator, typename Strategy>
|
||||
static inline OutputIterator apply(Linestring const& linestring,
|
||||
Box const& box, OutputIterator out, Strategy const& )
|
||||
Box const& box,
|
||||
RobustPolicy const& ,
|
||||
OutputIterator out, Strategy const& )
|
||||
{
|
||||
typedef typename point_type<GeometryOut>::type point_type;
|
||||
strategy::intersection::liang_barsky<Box, point_type> lb_strategy;
|
||||
@@ -435,9 +484,11 @@ struct intersection_insert
|
||||
false, true, false
|
||||
>
|
||||
{
|
||||
template <typename OutputIterator, typename Strategy>
|
||||
template <typename RobustPolicy, typename OutputIterator, typename Strategy>
|
||||
static inline OutputIterator apply(Segment const& segment,
|
||||
Box const& box, OutputIterator out, Strategy const& )
|
||||
Box const& box,
|
||||
RobustPolicy const& ,// TODO: propagate to clip_range_with_box
|
||||
OutputIterator out, Strategy const& )
|
||||
{
|
||||
geometry::segment_view<Segment> range(segment);
|
||||
|
||||
@@ -467,19 +518,25 @@ struct intersection_insert
|
||||
Areal1, Areal2, false
|
||||
>
|
||||
{
|
||||
template <typename OutputIterator, typename Strategy>
|
||||
template <typename RobustPolicy, typename OutputIterator, typename Strategy>
|
||||
static inline OutputIterator apply(Geometry1 const& geometry1,
|
||||
Geometry2 const& geometry2, OutputIterator out, Strategy const& )
|
||||
Geometry2 const& geometry2,
|
||||
RobustPolicy const& robust_policy,
|
||||
OutputIterator out, Strategy const& )
|
||||
{
|
||||
|
||||
typedef detail::overlay::turn_info<PointOut> turn_info;
|
||||
typedef detail::overlay::turn_info
|
||||
<
|
||||
PointOut,
|
||||
typename segment_ratio_type<PointOut, RobustPolicy>::type
|
||||
> turn_info;
|
||||
std::vector<turn_info> turns;
|
||||
|
||||
detail::get_turns::no_interrupt_policy policy;
|
||||
geometry::get_turns
|
||||
<
|
||||
false, false, detail::overlay::assign_null_policy
|
||||
>(geometry1, geometry2, detail::no_rescale_policy(), turns, policy);
|
||||
>(geometry1, geometry2, robust_policy, turns, policy);
|
||||
for (typename std::vector<turn_info>::const_iterator it
|
||||
= turns.begin(); it != turns.end(); ++it)
|
||||
{
|
||||
@@ -499,9 +556,11 @@ template
|
||||
>
|
||||
struct intersection_insert_reversed
|
||||
{
|
||||
template <typename OutputIterator, typename Strategy>
|
||||
template <typename RobustPolicy, typename OutputIterator, typename Strategy>
|
||||
static inline OutputIterator apply(Geometry1 const& g1,
|
||||
Geometry2 const& g2, OutputIterator out,
|
||||
Geometry2 const& g2,
|
||||
RobustPolicy const& robust_policy,
|
||||
OutputIterator out,
|
||||
Strategy const& strategy)
|
||||
{
|
||||
return intersection_insert
|
||||
@@ -509,7 +568,7 @@ struct intersection_insert_reversed
|
||||
Geometry2, Geometry1, GeometryOut,
|
||||
OverlayType,
|
||||
Reverse2, Reverse1, ReverseOut
|
||||
>::apply(g2, g1, out, strategy);
|
||||
>::apply(g2, g1, robust_policy, out, strategy);
|
||||
}
|
||||
};
|
||||
|
||||
@@ -656,35 +715,37 @@ template
|
||||
bool ReverseSecond,
|
||||
overlay_type OverlayType,
|
||||
typename Geometry1, typename Geometry2,
|
||||
typename RobustPolicy,
|
||||
typename OutputIterator,
|
||||
typename Strategy
|
||||
>
|
||||
inline OutputIterator insert(Geometry1 const& geometry1,
|
||||
Geometry2 const& geometry2,
|
||||
RobustPolicy robust_policy,
|
||||
OutputIterator out,
|
||||
Strategy const& strategy)
|
||||
{
|
||||
return boost::mpl::if_c
|
||||
<
|
||||
geometry::reverse_dispatch<Geometry1, Geometry2>::type::value,
|
||||
geometry::dispatch::intersection_insert_reversed
|
||||
<
|
||||
geometry::reverse_dispatch<Geometry1, Geometry2>::type::value,
|
||||
geometry::dispatch::intersection_insert_reversed
|
||||
<
|
||||
Geometry1, Geometry2,
|
||||
GeometryOut,
|
||||
OverlayType,
|
||||
overlay::do_reverse<geometry::point_order<Geometry1>::value>::value,
|
||||
overlay::do_reverse<geometry::point_order<Geometry2>::value, ReverseSecond>::value,
|
||||
overlay::do_reverse<geometry::point_order<GeometryOut>::value>::value
|
||||
>,
|
||||
geometry::dispatch::intersection_insert
|
||||
<
|
||||
Geometry1, Geometry2,
|
||||
GeometryOut,
|
||||
OverlayType,
|
||||
geometry::detail::overlay::do_reverse<geometry::point_order<Geometry1>::value>::value,
|
||||
geometry::detail::overlay::do_reverse<geometry::point_order<Geometry2>::value, ReverseSecond>::value
|
||||
>
|
||||
>::type::apply(geometry1, geometry2, out, strategy);
|
||||
Geometry1, Geometry2,
|
||||
GeometryOut,
|
||||
OverlayType,
|
||||
overlay::do_reverse<geometry::point_order<Geometry1>::value>::value,
|
||||
overlay::do_reverse<geometry::point_order<Geometry2>::value, ReverseSecond>::value,
|
||||
overlay::do_reverse<geometry::point_order<GeometryOut>::value>::value
|
||||
>,
|
||||
geometry::dispatch::intersection_insert
|
||||
<
|
||||
Geometry1, Geometry2,
|
||||
GeometryOut,
|
||||
OverlayType,
|
||||
geometry::detail::overlay::do_reverse<geometry::point_order<Geometry1>::value>::value,
|
||||
geometry::detail::overlay::do_reverse<geometry::point_order<Geometry2>::value, ReverseSecond>::value
|
||||
>
|
||||
>::type::apply(geometry1, geometry2, robust_policy, out, strategy);
|
||||
}
|
||||
|
||||
|
||||
@@ -723,10 +784,14 @@ inline OutputIterator intersection_insert(Geometry1 const& geometry1,
|
||||
concept::check<Geometry1 const>();
|
||||
concept::check<Geometry2 const>();
|
||||
|
||||
typedef typename Strategy::rescale_policy_type rescale_policy_type;
|
||||
rescale_policy_type robust_policy
|
||||
= geometry::get_rescale_policy<rescale_policy_type>(geometry1, geometry2);
|
||||
|
||||
return detail::intersection::insert
|
||||
<
|
||||
GeometryOut, false, overlay_intersection
|
||||
>(geometry1, geometry2, out, strategy);
|
||||
>(geometry1, geometry2, robust_policy, out, strategy);
|
||||
}
|
||||
|
||||
|
||||
@@ -760,12 +825,18 @@ inline OutputIterator intersection_insert(Geometry1 const& geometry1,
|
||||
concept::check<Geometry1 const>();
|
||||
concept::check<Geometry2 const>();
|
||||
|
||||
typedef typename geometry::rescale_policy_type
|
||||
<
|
||||
typename geometry::point_type<Geometry1>::type // TODO from both
|
||||
>::type rescale_policy_type;
|
||||
|
||||
typedef strategy_intersection
|
||||
<
|
||||
typename cs_tag<GeometryOut>::type,
|
||||
Geometry1,
|
||||
Geometry2,
|
||||
typename geometry::point_type<GeometryOut>::type
|
||||
typename geometry::point_type<GeometryOut>::type,
|
||||
rescale_policy_type
|
||||
> strategy;
|
||||
|
||||
return intersection_insert<GeometryOut>(geometry1, geometry2, out,
|
||||
|
||||
@@ -144,10 +144,10 @@ protected:
|
||||
typename IntersectionInfo,
|
||||
typename DirInfo
|
||||
>
|
||||
static inline void apply(Info& info, Point1 const& p1, Point2 const& p2,
|
||||
IntersectionInfo const& ii, DirInfo const& di)
|
||||
static inline void apply(Info& , Point1 const& , Point2 const& ,
|
||||
IntersectionInfo const& , DirInfo const& )
|
||||
{
|
||||
calculate_distance_policy::apply(info, p1, p2, ii, di);
|
||||
//calculate_distance_policy::apply(info, p1, p2, ii, di);
|
||||
}
|
||||
};
|
||||
|
||||
@@ -224,10 +224,11 @@ protected:
|
||||
public:
|
||||
template
|
||||
<
|
||||
typename OutputIterator, typename Strategy
|
||||
typename RobustPolicy, typename OutputIterator, typename Strategy
|
||||
>
|
||||
static inline OutputIterator apply(Linear1 const& linear1,
|
||||
Linear2 const& linear2,
|
||||
RobustPolicy const&,
|
||||
OutputIterator oit,
|
||||
Strategy const& )
|
||||
{
|
||||
@@ -244,9 +245,6 @@ public:
|
||||
if ( turns.empty() )
|
||||
{
|
||||
// the two linear geometries are disjoint
|
||||
#ifdef GEOMETRY_TEST_DEBUG
|
||||
std::cout << "NO INTERSECTIONS" << std::endl;
|
||||
#endif
|
||||
return linear_linear_no_intersections
|
||||
<
|
||||
LinestringOut,
|
||||
@@ -284,10 +282,11 @@ struct linear_linear_linestring
|
||||
{
|
||||
template
|
||||
<
|
||||
typename OutputIterator, typename Strategy
|
||||
typename RobustPolicy, typename OutputIterator, typename Strategy
|
||||
>
|
||||
static inline OutputIterator apply(Linear1 const& linear1,
|
||||
Linear2 const& linear2,
|
||||
RobustPolicy const& robust_policy,
|
||||
OutputIterator oit,
|
||||
Strategy const& strategy)
|
||||
{
|
||||
@@ -304,7 +303,7 @@ struct linear_linear_linestring
|
||||
Linear2, Linear1, LinestringOut, overlay_difference,
|
||||
EnableFilterContinueTurns, EnableRemoveDuplicateTurns,
|
||||
EnableDegenerateTurns
|
||||
>::apply(linear2, linear1, oit, strategy);
|
||||
>::apply(linear2, linear1, robust_policy, oit, strategy);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@@ -18,7 +18,6 @@
|
||||
#include <boost/mpl/assert.hpp>
|
||||
|
||||
|
||||
#include <boost/geometry/algorithms/detail/overlay/calculate_distance_policy.hpp>
|
||||
#include <boost/geometry/algorithms/detail/overlay/enrich_intersection_points.hpp>
|
||||
#include <boost/geometry/algorithms/detail/overlay/enrichment_info.hpp>
|
||||
#include <boost/geometry/algorithms/detail/overlay/get_turns.hpp>
|
||||
@@ -27,7 +26,7 @@
|
||||
#include <boost/geometry/algorithms/detail/overlay/traversal_info.hpp>
|
||||
#include <boost/geometry/algorithms/detail/overlay/turn_info.hpp>
|
||||
|
||||
#include <boost/geometry/algorithms/detail/rescale.hpp>
|
||||
#include <boost/geometry/algorithms/detail/recalculate.hpp>
|
||||
|
||||
#include <boost/geometry/algorithms/num_points.hpp>
|
||||
#include <boost/geometry/algorithms/reverse.hpp>
|
||||
@@ -38,6 +37,9 @@
|
||||
#include <boost/geometry/algorithms/detail/overlay/select_rings.hpp>
|
||||
#include <boost/geometry/algorithms/detail/overlay/do_reverse.hpp>
|
||||
|
||||
#include <boost/geometry/policies/robustness/segment_ratio_type.hpp>
|
||||
|
||||
|
||||
#ifdef BOOST_GEOMETRY_DEBUG_ASSEMBLE
|
||||
# include <boost/geometry/io/dsv/write.hpp>
|
||||
#endif
|
||||
@@ -156,9 +158,10 @@ template
|
||||
>
|
||||
struct overlay
|
||||
{
|
||||
template <typename OutputIterator, typename Strategy>
|
||||
template <typename RobustPolicy, typename OutputIterator, typename Strategy>
|
||||
static inline OutputIterator apply(
|
||||
Geometry1 const& geometry1, Geometry2 const& geometry2,
|
||||
RobustPolicy const& robust_policy,
|
||||
OutputIterator out,
|
||||
Strategy const& )
|
||||
{
|
||||
@@ -177,8 +180,13 @@ struct overlay
|
||||
>(geometry1, geometry2, out);
|
||||
}
|
||||
|
||||
typedef typename geometry::coordinate_type<GeometryOut>::type coordinate_type;
|
||||
typedef typename geometry::point_type<GeometryOut>::type point_type;
|
||||
typedef detail::overlay::traversal_turn_info<point_type> turn_info;
|
||||
typedef detail::overlay::traversal_turn_info
|
||||
<
|
||||
point_type,
|
||||
typename geometry::segment_ratio_type<point_type, RobustPolicy>::type
|
||||
> turn_info;
|
||||
typedef std::deque<turn_info> container_type;
|
||||
|
||||
typedef std::deque
|
||||
@@ -192,8 +200,6 @@ struct overlay
|
||||
boost::timer timer;
|
||||
#endif
|
||||
|
||||
detail::no_rescale_policy rescale_policy;
|
||||
|
||||
#ifdef BOOST_GEOMETRY_DEBUG_ASSEMBLE
|
||||
std::cout << "get turns" << std::endl;
|
||||
#endif
|
||||
@@ -201,8 +207,8 @@ std::cout << "get turns" << std::endl;
|
||||
geometry::get_turns
|
||||
<
|
||||
Reverse1, Reverse2,
|
||||
detail::overlay::calculate_distance_policy
|
||||
>(geometry1, geometry2, rescale_policy, turn_points, policy);
|
||||
detail::overlay::assign_null_policy
|
||||
>(geometry1, geometry2, robust_policy, turn_points, policy);
|
||||
|
||||
#ifdef BOOST_GEOMETRY_TIME_OVERLAY
|
||||
std::cout << "get_turns: " << timer.elapsed() << std::endl;
|
||||
@@ -217,7 +223,7 @@ std::cout << "enrich" << std::endl;
|
||||
? geometry::detail::overlay::operation_union
|
||||
: geometry::detail::overlay::operation_intersection,
|
||||
geometry1, geometry2,
|
||||
rescale_policy,
|
||||
robust_policy,
|
||||
side_strategy);
|
||||
|
||||
#ifdef BOOST_GEOMETRY_TIME_OVERLAY
|
||||
@@ -238,7 +244,7 @@ std::cout << "traverse" << std::endl;
|
||||
Direction == overlay_union
|
||||
? geometry::detail::overlay::operation_union
|
||||
: geometry::detail::overlay::operation_intersection,
|
||||
rescale_policy,
|
||||
robust_policy,
|
||||
turn_points, rings
|
||||
);
|
||||
|
||||
|
||||
@@ -142,9 +142,10 @@ template
|
||||
>
|
||||
struct point_point_point
|
||||
{
|
||||
template <typename OutputIterator, typename Strategy>
|
||||
template <typename RobustPolicy, typename OutputIterator, typename Strategy>
|
||||
static inline OutputIterator apply(Point1 const& point1,
|
||||
Point2 const& point2,
|
||||
RobustPolicy const& ,
|
||||
OutputIterator oit,
|
||||
Strategy const&)
|
||||
{
|
||||
@@ -175,9 +176,10 @@ template
|
||||
>
|
||||
struct multipoint_point_point
|
||||
{
|
||||
template <typename OutputIterator, typename Strategy>
|
||||
template <typename RobustPolicy, typename OutputIterator, typename Strategy>
|
||||
static inline OutputIterator apply(MultiPoint const& multipoint,
|
||||
Point const& point,
|
||||
RobustPolicy const& ,
|
||||
OutputIterator oit,
|
||||
Strategy const&)
|
||||
{
|
||||
@@ -209,9 +211,10 @@ template
|
||||
>
|
||||
struct point_multipoint_point
|
||||
{
|
||||
template <typename OutputIterator, typename Strategy>
|
||||
template <typename RobustPolicy, typename OutputIterator, typename Strategy>
|
||||
static inline OutputIterator apply(Point const& point,
|
||||
MultiPoint const& multipoint,
|
||||
RobustPolicy const& ,
|
||||
OutputIterator oit,
|
||||
Strategy const&)
|
||||
{
|
||||
@@ -244,9 +247,10 @@ template
|
||||
>
|
||||
struct multipoint_multipoint_point
|
||||
{
|
||||
template <typename OutputIterator, typename Strategy>
|
||||
template <typename RobustPolicy, typename OutputIterator, typename Strategy>
|
||||
static inline OutputIterator apply(MultiPoint1 const& multipoint1,
|
||||
MultiPoint2 const& multipoint2,
|
||||
RobustPolicy const& robust_policy,
|
||||
OutputIterator oit,
|
||||
Strategy const& strategy)
|
||||
{
|
||||
@@ -256,7 +260,7 @@ struct multipoint_multipoint_point
|
||||
return multipoint_multipoint_point
|
||||
<
|
||||
MultiPoint2, MultiPoint1, PointOut, OverlayType
|
||||
>::apply(multipoint2, multipoint1, oit, strategy);
|
||||
>::apply(multipoint2, multipoint1, robust_policy, oit, strategy);
|
||||
}
|
||||
|
||||
std::vector<typename point_type<MultiPoint2>::type>
|
||||
@@ -399,9 +403,10 @@ template
|
||||
>
|
||||
struct union_pointlike_pointlike_point
|
||||
{
|
||||
template <typename OutputIterator, typename Strategy>
|
||||
template <typename RobustPolicy, typename OutputIterator, typename Strategy>
|
||||
static inline OutputIterator apply(PointLike1 const& pointlike1,
|
||||
PointLike2 const& pointlike2,
|
||||
RobustPolicy const& robust_policy,
|
||||
OutputIterator oit,
|
||||
Strategy const& strategy)
|
||||
{
|
||||
@@ -412,7 +417,7 @@ struct union_pointlike_pointlike_point
|
||||
PointLike2, PointLike1, PointOut, overlay_difference,
|
||||
typename tag<PointLike2>::type,
|
||||
typename tag<PointLike1>::type
|
||||
>::apply(pointlike2, pointlike1, oit, strategy);
|
||||
>::apply(pointlike2, pointlike1, robust_policy, oit, strategy);
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
@@ -55,18 +55,18 @@ template
|
||||
typename Geometry,
|
||||
typename Turns,
|
||||
typename TurnPolicy,
|
||||
typename RescalePolicy,
|
||||
typename RobustPolicy,
|
||||
typename InterruptPolicy
|
||||
>
|
||||
struct self_section_visitor
|
||||
{
|
||||
Geometry const& m_geometry;
|
||||
RescalePolicy const& m_rescale_policy;
|
||||
RobustPolicy const& m_rescale_policy;
|
||||
Turns& m_turns;
|
||||
InterruptPolicy& m_interrupt_policy;
|
||||
|
||||
inline self_section_visitor(Geometry const& g,
|
||||
RescalePolicy const& rp,
|
||||
RobustPolicy const& rp,
|
||||
Turns& turns, InterruptPolicy& ip)
|
||||
: m_geometry(g)
|
||||
, m_rescale_policy(rp)
|
||||
@@ -110,10 +110,10 @@ struct self_section_visitor
|
||||
template<typename TurnPolicy>
|
||||
struct get_turns
|
||||
{
|
||||
template <typename Geometry, typename RescalePolicy, typename Turns, typename InterruptPolicy>
|
||||
template <typename Geometry, typename RobustPolicy, typename Turns, typename InterruptPolicy>
|
||||
static inline bool apply(
|
||||
Geometry const& geometry,
|
||||
RescalePolicy const& rescale_policy,
|
||||
RobustPolicy const& robust_policy,
|
||||
Turns& turns,
|
||||
InterruptPolicy& interrupt_policy)
|
||||
{
|
||||
@@ -127,13 +127,13 @@ struct get_turns
|
||||
> sections_type;
|
||||
|
||||
sections_type sec;
|
||||
geometry::sectionalize<false>(geometry, rescale_policy, false, sec);
|
||||
geometry::sectionalize<false>(geometry, robust_policy, false, sec);
|
||||
|
||||
self_section_visitor
|
||||
<
|
||||
Geometry,
|
||||
Turns, TurnPolicy, RescalePolicy, InterruptPolicy
|
||||
> visitor(geometry, rescale_policy, turns, interrupt_policy);
|
||||
Turns, TurnPolicy, RobustPolicy, InterruptPolicy
|
||||
> visitor(geometry, robust_policy, turns, interrupt_policy);
|
||||
|
||||
try
|
||||
{
|
||||
@@ -198,10 +198,10 @@ struct self_get_turn_points
|
||||
TurnPolicy
|
||||
>
|
||||
{
|
||||
template <typename RescalePolicy, typename Turns, typename InterruptPolicy>
|
||||
template <typename RobustPolicy, typename Turns, typename InterruptPolicy>
|
||||
static inline bool apply(
|
||||
Box const& ,
|
||||
RescalePolicy const& ,
|
||||
RobustPolicy const& ,
|
||||
Turns& ,
|
||||
InterruptPolicy& )
|
||||
{
|
||||
@@ -243,12 +243,12 @@ template
|
||||
<
|
||||
typename AssignPolicy,
|
||||
typename Geometry,
|
||||
typename RescalePolicy,
|
||||
typename RobustPolicy,
|
||||
typename Turns,
|
||||
typename InterruptPolicy
|
||||
>
|
||||
inline void self_turns(Geometry const& geometry,
|
||||
RescalePolicy const& rescale_policy,
|
||||
RobustPolicy const& robust_policy,
|
||||
Turns& turns, InterruptPolicy& interrupt_policy)
|
||||
{
|
||||
concept::check<Geometry const>();
|
||||
@@ -260,7 +260,7 @@ inline void self_turns(Geometry const& geometry,
|
||||
typename tag<Geometry>::type,
|
||||
Geometry,
|
||||
TurnPolicy
|
||||
>::apply(geometry, rescale_policy, turns, interrupt_policy);
|
||||
>::apply(geometry, robust_policy, turns, interrupt_policy);
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -35,7 +35,6 @@ namespace detail { namespace overlay
|
||||
template <typename P>
|
||||
std::ostream& operator<<(std::ostream &os, turn_info<P> const& info)
|
||||
{
|
||||
typename geometry::coordinate_type<P>::type d = info.distance;
|
||||
os << "\t"
|
||||
<< " src " << info.seg_id.source_index
|
||||
<< " seg " << info.seg_id.segment_index
|
||||
@@ -54,7 +53,7 @@ namespace detail { namespace overlay
|
||||
<< " nxt seg " << info.travels_to_vertex_index
|
||||
<< " , ip " << info.travels_to_ip_index
|
||||
<< " , or " << info.next_ip_index
|
||||
<< " dst " << double(d)
|
||||
<< " frac " << info.fraction
|
||||
<< info.visit_state;
|
||||
if (info.flagged)
|
||||
{
|
||||
|
||||
@@ -24,15 +24,21 @@ namespace detail { namespace overlay
|
||||
{
|
||||
|
||||
|
||||
template <typename P>
|
||||
struct traversal_turn_operation : public turn_operation
|
||||
template <typename Point, typename SegmentRatio>
|
||||
struct traversal_turn_operation : public turn_operation<SegmentRatio>
|
||||
{
|
||||
enrichment_info<P> enriched;
|
||||
enrichment_info<Point> enriched;
|
||||
visit_info visited;
|
||||
};
|
||||
|
||||
template <typename P>
|
||||
struct traversal_turn_info : public turn_info<P, traversal_turn_operation<P> >
|
||||
template <typename Point, typename SegmentRatio>
|
||||
struct traversal_turn_info
|
||||
: public turn_info
|
||||
<
|
||||
Point,
|
||||
SegmentRatio,
|
||||
traversal_turn_operation<Point, SegmentRatio>
|
||||
>
|
||||
{};
|
||||
|
||||
|
||||
|
||||
@@ -13,7 +13,6 @@
|
||||
|
||||
#include <boost/range.hpp>
|
||||
|
||||
#include <boost/geometry/algorithms/detail/overlay/append_no_dups_or_spikes.hpp>
|
||||
#include <boost/geometry/algorithms/detail/overlay/backtrack_check_si.hpp>
|
||||
#include <boost/geometry/algorithms/detail/overlay/copy_segments.hpp>
|
||||
#include <boost/geometry/algorithms/detail/overlay/turn_info.hpp>
|
||||
@@ -94,14 +93,16 @@ template
|
||||
typename G1,
|
||||
typename G2,
|
||||
typename Turns,
|
||||
typename IntersectionInfo
|
||||
typename IntersectionInfo,
|
||||
typename RobustPolicy
|
||||
>
|
||||
inline bool assign_next_ip(G1 const& g1, G2 const& g2,
|
||||
Turns& turns,
|
||||
typename boost::range_iterator<Turns>::type& ip,
|
||||
GeometryOut& current_output,
|
||||
IntersectionInfo& info,
|
||||
segment_identifier& seg_id)
|
||||
segment_identifier& seg_id,
|
||||
RobustPolicy const& robust_policy)
|
||||
{
|
||||
info.visited.set_visited();
|
||||
set_visited_for_continue(*ip, info);
|
||||
@@ -122,12 +123,14 @@ inline bool assign_next_ip(G1 const& g1, G2 const& g2,
|
||||
{
|
||||
geometry::copy_segments<Reverse1>(g1, info.seg_id,
|
||||
info.enriched.travels_to_vertex_index,
|
||||
robust_policy,
|
||||
current_output);
|
||||
}
|
||||
else
|
||||
{
|
||||
geometry::copy_segments<Reverse2>(g2, info.seg_id,
|
||||
info.enriched.travels_to_vertex_index,
|
||||
robust_policy,
|
||||
current_output);
|
||||
}
|
||||
seg_id = info.seg_id;
|
||||
@@ -139,7 +142,8 @@ inline bool assign_next_ip(G1 const& g1, G2 const& g2,
|
||||
seg_id = info.seg_id;
|
||||
}
|
||||
|
||||
detail::overlay::append_no_dups_or_spikes(current_output, ip->point);
|
||||
detail::overlay::append_no_dups_or_spikes(current_output, ip->point,
|
||||
robust_policy);
|
||||
|
||||
return true;
|
||||
}
|
||||
@@ -230,11 +234,11 @@ template
|
||||
class traverse
|
||||
{
|
||||
public :
|
||||
template <typename RescalePolicy, typename Turns, typename Rings>
|
||||
template <typename RobustPolicy, typename Turns, typename Rings>
|
||||
static inline void apply(Geometry1 const& geometry1,
|
||||
Geometry2 const& geometry2,
|
||||
detail::overlay::operation_type operation,
|
||||
RescalePolicy const& rescale_policy,
|
||||
RobustPolicy const& robust_policy,
|
||||
Turns& turns, Rings& rings)
|
||||
{
|
||||
typedef typename boost::range_value<Rings>::type ring_type;
|
||||
@@ -279,7 +283,8 @@ public :
|
||||
set_visited_for_continue(*it, *iit);
|
||||
|
||||
ring_type current_output;
|
||||
geometry::append(current_output, it->point);
|
||||
detail::overlay::append_no_dups_or_spikes(current_output,
|
||||
it->point, robust_policy);
|
||||
|
||||
turn_iterator current = it;
|
||||
turn_operation_iterator_type current_iit = iit;
|
||||
@@ -289,13 +294,14 @@ public :
|
||||
geometry1, geometry2,
|
||||
turns,
|
||||
current, current_output,
|
||||
*iit, current_seg_id))
|
||||
*iit, current_seg_id,
|
||||
robust_policy))
|
||||
{
|
||||
Backtrack::apply(
|
||||
size_at_start,
|
||||
rings, current_output, turns, *current_iit,
|
||||
"No next IP",
|
||||
geometry1, geometry2, rescale_policy, state);
|
||||
geometry1, geometry2, robust_policy, state);
|
||||
}
|
||||
|
||||
if (! detail::overlay::select_next_ip(
|
||||
@@ -308,7 +314,7 @@ public :
|
||||
size_at_start,
|
||||
rings, current_output, turns, *iit,
|
||||
"Dead end at start",
|
||||
geometry1, geometry2, rescale_policy, state);
|
||||
geometry1, geometry2, robust_policy, state);
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -330,7 +336,7 @@ public :
|
||||
size_at_start,
|
||||
rings, current_output, turns, *iit,
|
||||
"Visit again",
|
||||
geometry1, geometry2, rescale_policy, state);
|
||||
geometry1, geometry2, robust_policy, state);
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -349,7 +355,8 @@ public :
|
||||
detail::overlay::assign_next_ip<Reverse1, Reverse2>(
|
||||
geometry1, geometry2,
|
||||
turns, current, current_output,
|
||||
*current_iit, current_seg_id);
|
||||
*current_iit, current_seg_id,
|
||||
robust_policy);
|
||||
|
||||
if (! detail::overlay::select_next_ip(
|
||||
operation,
|
||||
@@ -364,7 +371,7 @@ public :
|
||||
size_at_start,
|
||||
rings, current_output, turns, *iit,
|
||||
"Dead end",
|
||||
geometry1, geometry2, rescale_policy, state);
|
||||
geometry1, geometry2, robust_policy, state);
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -380,7 +387,7 @@ public :
|
||||
size_at_start,
|
||||
rings, current_output, turns, *iit,
|
||||
"Endless loop",
|
||||
geometry1, geometry2, rescale_policy, state);
|
||||
geometry1, geometry2, robust_policy, state);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -391,6 +398,7 @@ public :
|
||||
detail::overlay::debug_traverse(*current, *iit, "->Finished");
|
||||
if (geometry::num_points(current_output) >= min_num_points)
|
||||
{
|
||||
clean_closing_dups_and_spikes(current_output, robust_policy);
|
||||
rings.push_back(current_output);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -54,11 +54,13 @@ enum method_type
|
||||
The class is to be included in the turn_info class, either direct
|
||||
or a derived or similar class with more (e.g. enrichment) information.
|
||||
*/
|
||||
template <typename SegmentRatio>
|
||||
struct turn_operation
|
||||
{
|
||||
operation_type operation;
|
||||
segment_identifier seg_id;
|
||||
segment_identifier other_id;
|
||||
SegmentRatio fraction;
|
||||
|
||||
inline turn_operation()
|
||||
: operation(operation_none)
|
||||
@@ -78,7 +80,8 @@ struct turn_operation
|
||||
template
|
||||
<
|
||||
typename Point,
|
||||
typename Operation = turn_operation,
|
||||
typename SegmentRatio,
|
||||
typename Operation = turn_operation<SegmentRatio>,
|
||||
typename Container = boost::array<Operation, 2>
|
||||
>
|
||||
struct turn_info
|
||||
|
||||
@@ -14,6 +14,8 @@
|
||||
|
||||
#include <boost/geometry/arithmetic/arithmetic.hpp>
|
||||
#include <boost/geometry/algorithms/detail/convert_point_to_point.hpp>
|
||||
#include <boost/geometry/algorithms/detail/recalculate.hpp>
|
||||
#include <boost/geometry/policies/robustness/robust_point_type.hpp>
|
||||
#include <boost/geometry/strategies/side.hpp>
|
||||
#include <boost/geometry/util/math.hpp>
|
||||
|
||||
@@ -25,8 +27,18 @@ namespace boost { namespace geometry
|
||||
namespace detail
|
||||
{
|
||||
|
||||
// Checks if a point ("last_point") causes a spike w.r.t.
|
||||
// the specified two other points (segment_a, segment_b)
|
||||
//
|
||||
// x-------x------x
|
||||
// a lp b
|
||||
//
|
||||
// Above, lp generates a spike w.r.t. segment(a,b)
|
||||
// So specify last point first, then (a,b) (this is unordered, so unintuitive)
|
||||
template <typename Point1, typename Point2, typename Point3>
|
||||
static inline bool point_is_spike_or_equal(Point1 const& last_point, Point2 const& segment_a, Point3 const& segment_b)
|
||||
static inline bool point_is_spike_or_equal(Point1 const& last_point,
|
||||
Point2 const& segment_a,
|
||||
Point3 const& segment_b)
|
||||
{
|
||||
typedef typename strategy::side::services::default_strategy
|
||||
<
|
||||
@@ -62,6 +74,49 @@ static inline bool point_is_spike_or_equal(Point1 const& last_point, Point2 cons
|
||||
return false;
|
||||
}
|
||||
|
||||
template
|
||||
<
|
||||
typename Point1,
|
||||
typename Point2,
|
||||
typename Point3,
|
||||
typename RobustPolicy
|
||||
>
|
||||
static inline bool point_is_spike_or_equal(Point1 const& last_point,
|
||||
Point2 const& segment_a,
|
||||
Point3 const& segment_b,
|
||||
RobustPolicy const& robust_policy)
|
||||
{
|
||||
if (point_is_spike_or_equal(last_point, segment_a, segment_b))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
if (! RobustPolicy::enabled)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
// Try using specified robust policy
|
||||
typedef typename geometry::robust_point_type
|
||||
<
|
||||
Point1,
|
||||
RobustPolicy
|
||||
>::type robust_point_type;
|
||||
|
||||
robust_point_type last_point_rob, segment_a_rob, segment_b_rob;
|
||||
geometry::recalculate(last_point_rob, last_point, robust_policy);
|
||||
geometry::recalculate(segment_a_rob, segment_a, robust_policy);
|
||||
geometry::recalculate(segment_b_rob, segment_b, robust_policy);
|
||||
|
||||
return point_is_spike_or_equal
|
||||
(
|
||||
last_point_rob,
|
||||
segment_a_rob,
|
||||
segment_b_rob
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
} // namespace detail
|
||||
#endif
|
||||
|
||||
|
||||
@@ -22,6 +22,7 @@
|
||||
#include <boost/numeric/conversion/bounds.hpp>
|
||||
#include <boost/numeric/conversion/cast.hpp>
|
||||
#include <boost/type_traits.hpp>
|
||||
#include <boost/typeof/typeof.hpp>
|
||||
|
||||
#include <boost/geometry/arithmetic/arithmetic.hpp>
|
||||
#include <boost/geometry/algorithms/append.hpp>
|
||||
@@ -33,9 +34,6 @@
|
||||
#include <boost/geometry/geometries/concepts/check.hpp>
|
||||
|
||||
|
||||
#include <boost/geometry/util/for_each_coordinate.hpp>
|
||||
|
||||
|
||||
namespace boost { namespace geometry
|
||||
{
|
||||
|
||||
@@ -72,7 +70,7 @@ struct recalculate_indexed
|
||||
static inline void apply(Geometry1& geometry1, Geometry2 const& geometry2, Strategy const& strategy)
|
||||
{
|
||||
// Do it for both indices in one dimension
|
||||
std::size_t const dim = Dimension - 1;
|
||||
static std::size_t const dim = Dimension - 1;
|
||||
geometry::set<0, dim>(geometry1, strategy.template apply<dim>(geometry::get<0, dim>(geometry2)));
|
||||
geometry::set<1, dim>(geometry1, strategy.template apply<dim>(geometry::get<1, dim>(geometry2)));
|
||||
recalculate_indexed<dim>::apply(geometry1, geometry2, strategy);
|
||||
@@ -89,7 +87,71 @@ struct recalculate_indexed<0>
|
||||
}
|
||||
};
|
||||
|
||||
struct range_to_range
|
||||
{
|
||||
template
|
||||
<
|
||||
typename Range1,
|
||||
typename Range2,
|
||||
typename Strategy
|
||||
>
|
||||
static inline void apply(Range1& destination, Range2 const& source,
|
||||
Strategy const& strategy)
|
||||
{
|
||||
typedef typename geometry::point_type<Range2>::type point_type;
|
||||
typedef recalculate_point<geometry::dimension<point_type>::value> per_point;
|
||||
geometry::clear(destination);
|
||||
|
||||
for (typename boost::range_iterator<Range2 const>::type it
|
||||
= boost::begin(source);
|
||||
it != boost::end(source);
|
||||
++it)
|
||||
{
|
||||
point_type p;
|
||||
per_point::apply(p, *it, strategy);
|
||||
geometry::append(destination, p);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
struct polygon_to_polygon
|
||||
{
|
||||
template
|
||||
<
|
||||
typename Polygon1,
|
||||
typename Polygon2,
|
||||
typename Strategy
|
||||
>
|
||||
static inline void apply(Polygon1& destination, Polygon2 const& source,
|
||||
Strategy const& strategy)
|
||||
{
|
||||
typedef range_to_range per_ring;
|
||||
|
||||
per_ring::apply(geometry::exterior_ring(destination),
|
||||
geometry::exterior_ring(source), strategy);
|
||||
|
||||
traits::resize
|
||||
<
|
||||
typename boost::remove_reference
|
||||
<
|
||||
typename traits::interior_mutable_type<Polygon1>::type
|
||||
>::type
|
||||
>::apply(interior_rings(destination), num_interior_rings(source));
|
||||
|
||||
typename interior_return_type<Polygon1>::type rings_dest
|
||||
= interior_rings(destination);
|
||||
typename interior_return_type<Polygon2 const>::type rings_source
|
||||
= interior_rings(source);
|
||||
|
||||
BOOST_AUTO_TPL(it_source, boost::begin(rings_source));
|
||||
BOOST_AUTO_TPL(it_dest, boost::begin(rings_dest));
|
||||
|
||||
for ( ; it_source != boost::end(rings_source); ++it_source, ++it_dest)
|
||||
{
|
||||
per_ring::apply(*it_dest, *it_source, strategy);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
}} // namespace detail::recalculate
|
||||
#endif // DOXYGEN_NO_DETAIL
|
||||
@@ -105,14 +167,8 @@ template
|
||||
typename Tag1 = typename geometry::tag<Geometry1>::type,
|
||||
typename Tag2 = typename geometry::tag<Geometry2>::type
|
||||
>
|
||||
struct recalculate
|
||||
{
|
||||
BOOST_MPL_ASSERT_MSG
|
||||
(
|
||||
false, NOT_OR_NOT_YET_IMPLEMENTED_FOR_THIS_GEOMETRY_TYPE
|
||||
, (types<Geometry1>)
|
||||
);
|
||||
};
|
||||
struct recalculate : not_implemented<Tag1, Tag2>
|
||||
{};
|
||||
|
||||
template <typename Point1, typename Point2>
|
||||
struct recalculate<Point1, Point2, point_tag, point_tag>
|
||||
@@ -129,6 +185,10 @@ struct recalculate<Segment1, Segment2, segment_tag, segment_tag>
|
||||
: detail::recalculate::recalculate_indexed<geometry::dimension<Segment1>::value>
|
||||
{};
|
||||
|
||||
template <typename Polygon1, typename Polygon2>
|
||||
struct recalculate<Polygon1, Polygon2, polygon_tag, polygon_tag>
|
||||
: detail::recalculate::polygon_to_polygon
|
||||
{};
|
||||
|
||||
} // namespace dispatch
|
||||
#endif // DOXYGEN_NO_DISPATCH
|
||||
|
||||
@@ -17,6 +17,8 @@
|
||||
#include <boost/geometry/core/topological_dimension.hpp>
|
||||
#include <boost/geometry/util/range.hpp>
|
||||
|
||||
#include <boost/geometry/algorithms/num_interior_rings.hpp>
|
||||
#include <boost/geometry/algorithms/detail/point_on_border.hpp>
|
||||
#include <boost/geometry/algorithms/detail/sub_range.hpp>
|
||||
#include <boost/geometry/algorithms/detail/single_geometry.hpp>
|
||||
|
||||
@@ -193,7 +195,7 @@ struct areal_areal
|
||||
// TODO: If Areal geometry may have infinite size, change the following line:
|
||||
|
||||
// The result should be FFFFFFFFF
|
||||
set<exterior, exterior, result_dimension<Geometry2>::value>(result);// FFFFFFFFd, d in [1,9] or T
|
||||
relate::set<exterior, exterior, result_dimension<Geometry2>::value>(result);// FFFFFFFFd, d in [1,9] or T
|
||||
|
||||
if ( result.interrupt )
|
||||
return;
|
||||
@@ -561,13 +563,6 @@ struct areal_areal
|
||||
static const bool transpose_result = OpId != 0;
|
||||
static const int other_id = (OpId + 1) % 2;
|
||||
|
||||
static const iterate_direction direction = order_as_direction<geometry::point_order<Geometry const>::value>::value;
|
||||
static const closure_selector closure = geometry::closure<Geometry const>::value;
|
||||
|
||||
typedef typename ring_type<Geometry const>::type ring_type;
|
||||
typedef typename reversible_view<ring_type const, direction>::type reversible_type;
|
||||
typedef typename closeable_view<reversible_type const, closure>::type closeable_type;
|
||||
|
||||
public:
|
||||
inline uncertain_rings_analyser(Result & result,
|
||||
Geometry const& geom,
|
||||
|
||||
@@ -12,6 +12,7 @@
|
||||
#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_RELATE_BOUNDARY_CHECKER_HPP
|
||||
|
||||
#include <boost/geometry/util/range.hpp>
|
||||
#include <boost/geometry/algorithms/num_points.hpp>
|
||||
#include <boost/geometry/algorithms/detail/sub_range.hpp>
|
||||
|
||||
#include <boost/geometry/algorithms/detail/disjoint/point_point.hpp>
|
||||
@@ -54,34 +55,6 @@ public:
|
||||
return has_boundary;
|
||||
}
|
||||
|
||||
template <boundary_query BoundaryQuery>
|
||||
bool is_boundary(point_type const& pt, segment_identifier const& sid) const
|
||||
{
|
||||
if ( !has_boundary )
|
||||
return false;
|
||||
|
||||
if ( BoundaryQuery == boundary_front )
|
||||
{
|
||||
return sid.segment_index == 0
|
||||
&& detail::equals::equals_point_point(pt, range::front(geometry));
|
||||
}
|
||||
else if ( BoundaryQuery == boundary_back )
|
||||
{
|
||||
return sid.segment_index + 2 == geometry::num_points(geometry)
|
||||
&& detail::equals::equals_point_point(pt, range::back(geometry));
|
||||
}
|
||||
else if ( BoundaryQuery == boundary_any )
|
||||
{
|
||||
return ( sid.segment_index == 0
|
||||
&& detail::equals::equals_point_point(pt, range::front(geometry)) )
|
||||
|| ( sid.segment_index + 2 == geometry::num_points(geometry)
|
||||
&& detail::equals::equals_point_point(pt, range::back(geometry)) );
|
||||
}
|
||||
|
||||
BOOST_ASSERT(false);
|
||||
return false;
|
||||
}
|
||||
|
||||
private:
|
||||
bool has_boundary;
|
||||
Geometry const& geometry;
|
||||
@@ -97,41 +70,10 @@ public:
|
||||
: is_filled(false), geometry(g)
|
||||
{}
|
||||
|
||||
template <boundary_query BoundaryQuery>
|
||||
bool is_endpoint_boundary(point_type const& pt) const
|
||||
{
|
||||
return is_boundary_point(pt);
|
||||
}
|
||||
|
||||
template <boundary_query BoundaryQuery>
|
||||
bool is_boundary(point_type const& pt, segment_identifier const& sid) const
|
||||
{
|
||||
if ( BoundaryQuery == boundary_front )
|
||||
{
|
||||
if ( sid.segment_index != 0 )
|
||||
return false;
|
||||
}
|
||||
|
||||
if ( BoundaryQuery == boundary_back )
|
||||
{
|
||||
if ( sid.segment_index + 2 != geometry::num_points(sub_range(geometry, sid)) )
|
||||
return false;
|
||||
}
|
||||
|
||||
if ( BoundaryQuery == boundary_any )
|
||||
{
|
||||
if ( sid.segment_index != 0
|
||||
&& sid.segment_index + 2 != geometry::num_points(sub_range(geometry, sid)) )
|
||||
return false;
|
||||
}
|
||||
|
||||
return is_boundary_point(pt);
|
||||
}
|
||||
|
||||
private:
|
||||
// First call O(NlogN)
|
||||
// Each next call O(logN)
|
||||
bool is_boundary_point(point_type const& pt) const
|
||||
template <boundary_query BoundaryQuery>
|
||||
bool is_endpoint_boundary(point_type const& pt) const
|
||||
{
|
||||
typedef typename boost::range_size<Geometry>::type size_type;
|
||||
size_type multi_count = boost::size(geometry);
|
||||
@@ -176,6 +118,7 @@ private:
|
||||
return equal_points_count % 2 != 0;// && equal_points_count > 0; // the number is odd and > 0
|
||||
}
|
||||
|
||||
private:
|
||||
mutable bool is_filled;
|
||||
// TODO: store references/pointers instead of points?
|
||||
mutable std::vector<point_type> boundary_points;
|
||||
|
||||
@@ -23,9 +23,8 @@ namespace boost { namespace geometry
|
||||
#ifndef DOXYGEN_NO_DETAIL
|
||||
namespace detail { namespace relate {
|
||||
|
||||
// TODO:
|
||||
// For 1-point linestrings or with all equal points turns won't be generated!
|
||||
// Check for those degenerated cases may be connected with this one!
|
||||
// NOTE: This iterates through single geometries for which turns were not generated.
|
||||
// It doesn't mean that the geometry is disjoint, only that no turns were detected.
|
||||
|
||||
template <std::size_t OpId,
|
||||
typename Geometry,
|
||||
@@ -130,14 +129,12 @@ struct for_each_disjoint_geometry_if<OpId, Geometry, Tag, true>
|
||||
|
||||
// WARNING! This class stores pointers!
|
||||
// Passing a reference to local variable will result in undefined behavior!
|
||||
|
||||
// TODO: rename to point_id_ref?
|
||||
template <typename Point>
|
||||
class point_identifier
|
||||
class point_info
|
||||
{
|
||||
public:
|
||||
point_identifier() : sid_ptr(0), pt_ptr(0) {}
|
||||
point_identifier(segment_identifier const& sid, Point const& pt)
|
||||
point_info() : sid_ptr(NULL), pt_ptr(NULL) {}
|
||||
point_info(Point const& pt, segment_identifier const& sid)
|
||||
: sid_ptr(boost::addressof(sid))
|
||||
, pt_ptr(boost::addressof(pt))
|
||||
{}
|
||||
@@ -165,10 +162,10 @@ private:
|
||||
|
||||
// WARNING! This class stores pointers!
|
||||
// Passing a reference to local variable will result in undefined behavior!
|
||||
class same_single_geometry
|
||||
class same_single
|
||||
{
|
||||
public:
|
||||
same_single_geometry(segment_identifier const& sid)
|
||||
same_single(segment_identifier const& sid)
|
||||
: sid_ptr(boost::addressof(sid))
|
||||
{}
|
||||
|
||||
@@ -178,7 +175,7 @@ public:
|
||||
}
|
||||
|
||||
template <typename Point>
|
||||
bool operator()(point_identifier<Point> const& pid) const
|
||||
bool operator()(point_info<Point> const& pid) const
|
||||
{
|
||||
return operator()(pid.seg_id());
|
||||
}
|
||||
@@ -206,12 +203,12 @@ private:
|
||||
|
||||
// WARNING! This class stores pointers!
|
||||
// Passing a reference to local variable will result in undefined behavior!
|
||||
template <typename SameRange = same_single_geometry>
|
||||
template <typename SameRange = same_single>
|
||||
class segment_watcher
|
||||
{
|
||||
public:
|
||||
segment_watcher()
|
||||
: m_seg_id_ptr(0)
|
||||
: m_seg_id_ptr(NULL)
|
||||
{}
|
||||
|
||||
bool update(segment_identifier const& seg_id)
|
||||
@@ -234,21 +231,24 @@ class exit_watcher
|
||||
static const std::size_t other_op_id = (OpId + 1) % 2;
|
||||
|
||||
typedef typename TurnInfo::point_type point_type;
|
||||
typedef point_identifier<point_type> point_info;
|
||||
typedef detail::relate::point_info<point_type> point_info;
|
||||
|
||||
public:
|
||||
exit_watcher()
|
||||
: exit_operation(overlay::operation_none)
|
||||
, exit_turn(0)
|
||||
: m_exit_operation(overlay::operation_none)
|
||||
, m_exit_turn_ptr(NULL)
|
||||
{}
|
||||
|
||||
void enter(TurnInfo const& turn)
|
||||
{
|
||||
other_entry_points.push_back(
|
||||
point_info(turn.operations[other_op_id].seg_id, turn.point) );
|
||||
m_other_entry_points.push_back(
|
||||
point_info(turn.point, turn.operations[other_op_id].seg_id) );
|
||||
}
|
||||
|
||||
void exit(TurnInfo const& turn)
|
||||
// TODO: exit_per_geometry parameter looks not very safe
|
||||
// wrong value may be easily passed
|
||||
|
||||
void exit(TurnInfo const& turn, bool exit_per_geometry = true)
|
||||
{
|
||||
//segment_identifier const& seg_id = turn.operations[op_id].seg_id;
|
||||
segment_identifier const& other_id = turn.operations[other_op_id].seg_id;
|
||||
@@ -256,63 +256,76 @@ public:
|
||||
|
||||
typedef typename std::vector<point_info>::iterator point_iterator;
|
||||
// search for the entry point in the same range of other geometry
|
||||
point_iterator entry_it = std::find_if(other_entry_points.begin(),
|
||||
other_entry_points.end(),
|
||||
same_single_geometry(other_id));
|
||||
point_iterator entry_it = std::find_if(m_other_entry_points.begin(),
|
||||
m_other_entry_points.end(),
|
||||
same_single(other_id));
|
||||
|
||||
// this end point has corresponding entry point
|
||||
if ( entry_it != other_entry_points.end() )
|
||||
if ( entry_it != m_other_entry_points.end() )
|
||||
{
|
||||
// here we know that we possibly left LS
|
||||
// we must still check if we didn't get back on the same point
|
||||
exit_operation = exit_op;
|
||||
exit_turn = boost::addressof(turn);
|
||||
|
||||
// erase the corresponding entry point
|
||||
other_entry_points.erase(entry_it);
|
||||
m_other_entry_points.erase(entry_it);
|
||||
|
||||
if ( exit_per_geometry || m_other_entry_points.empty() )
|
||||
{
|
||||
// here we know that we possibly left LS
|
||||
// we must still check if we didn't get back on the same point
|
||||
m_exit_operation = exit_op;
|
||||
m_exit_turn_ptr = boost::addressof(turn);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool is_outside() const
|
||||
{
|
||||
// if we didn't entered anything in the past, we're outside
|
||||
return other_entry_points.empty();
|
||||
return m_other_entry_points.empty();
|
||||
}
|
||||
|
||||
bool is_outside(TurnInfo const& turn) const
|
||||
{
|
||||
return m_other_entry_points.empty()
|
||||
|| std::find_if(m_other_entry_points.begin(),
|
||||
m_other_entry_points.end(),
|
||||
same_single(
|
||||
turn.operations[other_op_id].seg_id))
|
||||
== m_other_entry_points.end();
|
||||
}
|
||||
|
||||
overlay::operation_type get_exit_operation() const
|
||||
{
|
||||
return exit_operation;
|
||||
return m_exit_operation;
|
||||
}
|
||||
|
||||
point_type const& get_exit_point() const
|
||||
{
|
||||
BOOST_ASSERT(exit_operation != overlay::operation_none);
|
||||
BOOST_ASSERT(exit_turn);
|
||||
return exit_turn->point;
|
||||
BOOST_ASSERT(m_exit_operation != overlay::operation_none);
|
||||
BOOST_ASSERT(m_exit_turn_ptr);
|
||||
return m_exit_turn_ptr->point;
|
||||
}
|
||||
|
||||
TurnInfo const& get_exit_turn() const
|
||||
{
|
||||
BOOST_ASSERT(exit_operation != overlay::operation_none);
|
||||
BOOST_ASSERT(exit_turn);
|
||||
return *exit_turn;
|
||||
BOOST_ASSERT(m_exit_operation != overlay::operation_none);
|
||||
BOOST_ASSERT(m_exit_turn_ptr);
|
||||
return *m_exit_turn_ptr;
|
||||
}
|
||||
|
||||
void reset_detected_exit()
|
||||
{
|
||||
exit_operation = overlay::operation_none;
|
||||
m_exit_operation = overlay::operation_none;
|
||||
}
|
||||
|
||||
void reset()
|
||||
{
|
||||
exit_operation = overlay::operation_none;
|
||||
other_entry_points.clear();
|
||||
m_exit_operation = overlay::operation_none;
|
||||
m_other_entry_points.clear();
|
||||
}
|
||||
|
||||
private:
|
||||
overlay::operation_type exit_operation;
|
||||
const TurnInfo * exit_turn;
|
||||
std::vector<point_info> other_entry_points; // TODO: use map here or sorted vector?
|
||||
overlay::operation_type m_exit_operation;
|
||||
const TurnInfo * m_exit_turn_ptr;
|
||||
std::vector<point_info> m_other_entry_points; // TODO: use map here or sorted vector?
|
||||
};
|
||||
|
||||
template <std::size_t OpId, typename Turn>
|
||||
@@ -327,8 +340,10 @@ inline bool turn_on_the_same_ip(Turn const& prev_turn, Turn const& curr_turn)
|
||||
return false;
|
||||
}
|
||||
|
||||
// TODO: will this work if between segments there will be some number of degenerated ones?
|
||||
|
||||
if ( prev_seg_id.segment_index != curr_seg_id.segment_index
|
||||
&& ( ! geometry::math::equals(curr_turn.operations[OpId].enriched.distance, 0)
|
||||
&& ( ! curr_turn.operations[OpId].fraction.is_zero()
|
||||
|| prev_seg_id.segment_index + 1 != curr_seg_id.segment_index ) )
|
||||
{
|
||||
return false;
|
||||
@@ -361,97 +376,22 @@ static inline bool is_ip_on_boundary(IntersectionPoint const& ip,
|
||||
|
||||
// IP on the last point of the linestring
|
||||
if ( (BoundaryQuery == boundary_back || BoundaryQuery == boundary_any)
|
||||
&& operation_info.operation == overlay::operation_blocked )
|
||||
&& operation_info.position == overlay::position_back )
|
||||
{
|
||||
BOOST_ASSERT(operation_info.position == overlay::position_back);
|
||||
// check if this point is a boundary
|
||||
res = boundary_checker.template is_endpoint_boundary<boundary_back>(ip);
|
||||
|
||||
#ifdef BOOST_GEOMETRY_DEBUG_RELATE
|
||||
BOOST_ASSERT(res == boundary_checker.template is_boundary<boundary_back>(ip, seg_id));
|
||||
#endif
|
||||
}
|
||||
// IP on the last point of the linestring
|
||||
else if ( (BoundaryQuery == boundary_front || BoundaryQuery == boundary_any)
|
||||
&& operation_info.position == overlay::position_front )
|
||||
&& operation_info.position == overlay::position_front )
|
||||
{
|
||||
// check if this point is a boundary
|
||||
res = boundary_checker.template is_endpoint_boundary<boundary_front>(ip);
|
||||
|
||||
#ifdef BOOST_GEOMETRY_DEBUG_RELATE
|
||||
BOOST_ASSERT(res == boundary_checker.template is_boundary<boundary_front>(ip, seg_id));
|
||||
#endif
|
||||
}
|
||||
// IP somewhere in the interior
|
||||
else
|
||||
{
|
||||
#ifdef BOOST_GEOMETRY_DEBUG_RELATE
|
||||
BOOST_ASSERT(res == boundary_checker.template is_boundary<boundary_any>(ip, seg_id));
|
||||
#endif
|
||||
}
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
// TODO: The tool like this would be useful but this can't be done with the current implementation of
|
||||
// reversible and closeable views because the reference to local variable would be returned!
|
||||
|
||||
//template <typename Geometry>
|
||||
//struct normalized_range_type
|
||||
//{
|
||||
// static const iterate_direction direction = order_as_direction<geometry::point_order<Geometry>::value>::value;
|
||||
// static const closure_selector closure = geometry::closure<Geometry>::value;
|
||||
//
|
||||
// typedef typename ring_type<Geometry>::type ring_type;
|
||||
// typedef typename reversible_view
|
||||
// <
|
||||
// typename boost::mpl::if_c
|
||||
// <
|
||||
// boost::is_const<Geometry>::value,
|
||||
// ring_type const,
|
||||
// ring_type
|
||||
// >::type,
|
||||
// direction
|
||||
// >::type reversible_type;
|
||||
// typedef typename closeable_view
|
||||
// <
|
||||
// typename boost::mpl::if_c
|
||||
// <
|
||||
// boost::is_const<Geometry>::value,
|
||||
// reversible_type const,
|
||||
// reversible_type
|
||||
// >::type,
|
||||
// closure
|
||||
// >::type closeable_type;
|
||||
//
|
||||
// typedef closeable_type type;
|
||||
//};
|
||||
//
|
||||
//template <typename Geometry>
|
||||
//struct normalized_range
|
||||
//{
|
||||
// template <typename Range>
|
||||
// static inline
|
||||
// typename normalized_range_type<Geometry>::type
|
||||
// apply(Range & rng)
|
||||
// {
|
||||
// typename normalized_range_type<Geometry>::reversible_type
|
||||
// rev_view(rng);
|
||||
// typename normalized_range_type<Geometry>::closeable_type
|
||||
// view(rev_view);
|
||||
//
|
||||
//// ERROR! HERE THE REFERENCE TO LOCAL rev_view IS RETURNED!
|
||||
// return view;
|
||||
// }
|
||||
//};
|
||||
//
|
||||
//template <typename Geometry, typename Id>
|
||||
//inline
|
||||
//typename normalized_range_type<Geometry>::type
|
||||
//normalized_sub_range(Geometry & geometry, Id const& id)
|
||||
//{
|
||||
// return normalized_range<Geometry>::apply(detail::sub_range(geometry, id));
|
||||
//}
|
||||
|
||||
}} // namespace detail::relate
|
||||
#endif // DOXYGEN_NO_DETAIL
|
||||
|
||||
@@ -17,6 +17,8 @@
|
||||
#include <boost/geometry/core/topological_dimension.hpp>
|
||||
#include <boost/geometry/util/range.hpp>
|
||||
|
||||
#include <boost/geometry/algorithms/num_interior_rings.hpp>
|
||||
#include <boost/geometry/algorithms/detail/point_on_border.hpp>
|
||||
#include <boost/geometry/algorithms/detail/sub_range.hpp>
|
||||
#include <boost/geometry/algorithms/detail/single_geometry.hpp>
|
||||
|
||||
@@ -25,6 +27,8 @@
|
||||
#include <boost/geometry/algorithms/detail/relate/boundary_checker.hpp>
|
||||
#include <boost/geometry/algorithms/detail/relate/follow_helpers.hpp>
|
||||
|
||||
#include <boost/geometry/views/normalized_view.hpp>
|
||||
|
||||
namespace boost { namespace geometry
|
||||
{
|
||||
|
||||
@@ -194,7 +198,7 @@ struct linear_areal
|
||||
// TODO: If Areal geometry may have infinite size, change the following line:
|
||||
|
||||
// The result should be FFFFFFFFF
|
||||
set<exterior, exterior, result_dimension<Geometry2>::value, TransposeResult>(result);// FFFFFFFFd, d in [1,9] or T
|
||||
relate::set<exterior, exterior, result_dimension<Geometry2>::value, TransposeResult>(result);// FFFFFFFFd, d in [1,9] or T
|
||||
|
||||
if ( result.interrupt )
|
||||
return;
|
||||
@@ -232,20 +236,14 @@ struct linear_areal
|
||||
|
||||
// This is set here because in the case if empty Areal geometry were passed
|
||||
// those shouldn't be set
|
||||
set<exterior, interior, '2', TransposeResult>(result);// FFFFFF2Fd
|
||||
relate::set<exterior, interior, '2', TransposeResult>(result);// FFFFFF2Fd
|
||||
if ( result.interrupt )
|
||||
return;
|
||||
|
||||
{
|
||||
// for different multi or same ring id: x, u, i, c
|
||||
// for same multi and different ring id: c, i, u, x
|
||||
typedef turns::less
|
||||
<
|
||||
0, turns::less_greater_op_for_other_same_m_diff_r
|
||||
<
|
||||
turns::op_to_int<0,2,3,1,4,0>
|
||||
>
|
||||
> less;
|
||||
typedef turns::less<0, turns::less_op_linear_areal> less;
|
||||
std::sort(turns.begin(), turns.end(), less());
|
||||
|
||||
turns_analyser<turn_type> analyser;
|
||||
@@ -261,7 +259,7 @@ struct linear_areal
|
||||
// If 'c' (insersection_boundary) was not found we know that any Ls isn't equal to one of the Rings
|
||||
if ( !interrupt_policy.is_boundary_found )
|
||||
{
|
||||
set<exterior, boundary, '1', TransposeResult>(result);
|
||||
relate::set<exterior, boundary, '1', TransposeResult>(result);
|
||||
}
|
||||
// Don't calculate it if it's required
|
||||
else if ( may_update<exterior, boundary, '1', TransposeResult>(result) )
|
||||
@@ -292,7 +290,7 @@ struct linear_areal
|
||||
if ( it->operations[1].seg_id.ring_index > -1 )
|
||||
{
|
||||
// we can be sure that the exterior overlaps the boundary
|
||||
set<exterior, boundary, '1', TransposeResult>(result);
|
||||
relate::set<exterior, boundary, '1', TransposeResult>(result);
|
||||
break;
|
||||
}
|
||||
// if there was some previous ring
|
||||
@@ -307,7 +305,7 @@ struct linear_areal
|
||||
single_geometry(geometry2, *prev_seg_id_ptr)) )
|
||||
{
|
||||
// we can be sure that the exterior overlaps the boundary
|
||||
set<exterior, boundary, '1', TransposeResult>(result);
|
||||
relate::set<exterior, boundary, '1', TransposeResult>(result);
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -320,7 +318,7 @@ struct linear_areal
|
||||
&& prev_seg_id_ptr->ring_index + 1 < it->operations[1].seg_id.ring_index )
|
||||
{
|
||||
// we can be sure that the exterior overlaps the boundary
|
||||
set<exterior, boundary, '1', TransposeResult>(result);
|
||||
relate::set<exterior, boundary, '1', TransposeResult>(result);
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -335,20 +333,14 @@ struct linear_areal
|
||||
if ( !has_boundary_inters.result )
|
||||
{
|
||||
// we can be sure that the exterior overlaps the boundary
|
||||
set<exterior, boundary, '1', TransposeResult>(result);
|
||||
relate::set<exterior, boundary, '1', TransposeResult>(result);
|
||||
break;
|
||||
}
|
||||
// else there is 1d overlap with the boundary so we must analyse the boundary
|
||||
else
|
||||
{
|
||||
// u, c
|
||||
typedef turns::less
|
||||
<
|
||||
1, turns::less_greater_op_for_other_same_m_diff_r
|
||||
<
|
||||
turns::op_to_int<0,1,0,0,2,0>
|
||||
>
|
||||
> less;
|
||||
typedef turns::less<1, turns::less_op_areal_linear> less;
|
||||
std::sort(it, next, less());
|
||||
|
||||
// analyse
|
||||
@@ -364,7 +356,7 @@ struct linear_areal
|
||||
if ( analyser.is_union_detected )
|
||||
{
|
||||
// we can be sure that the boundary of Areal overlaps the exterior of Linear
|
||||
set<exterior, boundary, '1', TransposeResult>(result);
|
||||
relate::set<exterior, boundary, '1', TransposeResult>(result);
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -384,7 +376,7 @@ struct linear_areal
|
||||
single_geometry(geometry2, *prev_seg_id_ptr)) )
|
||||
{
|
||||
// we can be sure that the exterior overlaps the boundary
|
||||
set<exterior, boundary, '1', TransposeResult>(result);
|
||||
relate::set<exterior, boundary, '1', TransposeResult>(result);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -460,10 +452,11 @@ struct linear_areal
|
||||
|
||||
public:
|
||||
turns_analyser()
|
||||
: m_previous_turn_ptr(0)
|
||||
: m_previous_turn_ptr(NULL)
|
||||
, m_previous_operation(overlay::operation_none)
|
||||
, m_boundary_counter(0)
|
||||
, m_interior_detected(false)
|
||||
, m_first_interior_other_id_ptr(NULL)
|
||||
{}
|
||||
|
||||
template <typename Result,
|
||||
@@ -490,7 +483,7 @@ struct linear_areal
|
||||
}
|
||||
|
||||
segment_identifier const& seg_id = it->operations[op_id].seg_id;
|
||||
//segment_identifier const& other_id = it->operations[other_op_id].seg_id;
|
||||
segment_identifier const& other_id = it->operations[other_op_id].seg_id;
|
||||
|
||||
const bool first_in_range = m_seg_watcher.update(seg_id);
|
||||
|
||||
@@ -521,6 +514,13 @@ struct linear_areal
|
||||
if ( op == overlay::operation_blocked )
|
||||
return;
|
||||
|
||||
if ( ( op == overlay::operation_intersection
|
||||
|| op == overlay::operation_continue )
|
||||
&& turn_on_the_same_ip<op_id>(m_exit_watcher.get_exit_turn(), *it) )
|
||||
{
|
||||
fake_enter_detected = true;
|
||||
}
|
||||
|
||||
m_exit_watcher.reset_detected_exit();
|
||||
}
|
||||
|
||||
@@ -548,33 +548,20 @@ struct linear_areal
|
||||
{
|
||||
m_interior_detected = false;
|
||||
}
|
||||
else if ( op == overlay::operation_union )
|
||||
{
|
||||
// TODO: this probably is not a good way of handling the interiors/enters
|
||||
// the solution similar to exit_watcher would be more robust
|
||||
// all enters should be kept and handled.
|
||||
// maybe integrate it with the exit_watcher -> enter_exit_watcher
|
||||
if ( m_first_interior_other_id_ptr
|
||||
&& m_first_interior_other_id_ptr->multi_index == other_id.multi_index )
|
||||
{
|
||||
m_interior_detected = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// if the new linestring started just now,
|
||||
// but the previous one went out on the previous point,
|
||||
// we must check if the boundary of the previous segment is outside
|
||||
// NOTE: couldn't it be integrated with the handling of the union above?
|
||||
// THIS IS REDUNDANT WITH THE HANDLING OF THE END OF THE RANGE
|
||||
//if ( first_in_range
|
||||
// && ! fake_enter_detected
|
||||
// && m_previous_operation == overlay::operation_union )
|
||||
//{
|
||||
// BOOST_ASSERT(it != first);
|
||||
// BOOST_ASSERT(m_previous_turn_ptr);
|
||||
|
||||
// segment_identifier const& prev_seg_id = m_previous_turn_ptr->operations[op_id].seg_id;
|
||||
|
||||
// bool prev_back_b = is_endpoint_on_boundary<boundary_back>(
|
||||
// range::back(sub_geometry::get(geometry, prev_seg_id)),
|
||||
// boundary_checker);
|
||||
|
||||
// // if there is a boundary on the last point
|
||||
// if ( prev_back_b )
|
||||
// {
|
||||
// update<boundary, exterior, '0', TransposeResult>(res);
|
||||
// }
|
||||
//}
|
||||
|
||||
// i/u, c/u
|
||||
if ( op == overlay::operation_intersection
|
||||
|| op == overlay::operation_continue ) // operation_boundary/operation_boundary_intersection
|
||||
@@ -592,9 +579,15 @@ struct linear_areal
|
||||
// interiors overlaps
|
||||
//update<interior, interior, '1', TransposeResult>(res);
|
||||
|
||||
// don't update now
|
||||
// we might enter a boundary of some other ring on the same IP
|
||||
m_interior_detected = true;
|
||||
// TODO: think about the implementation of the more robust version
|
||||
// this way only the first enter will be handled
|
||||
if ( !m_interior_detected )
|
||||
{
|
||||
// don't update now
|
||||
// we might enter a boundary of some other ring on the same IP
|
||||
m_interior_detected = true;
|
||||
m_first_interior_other_id_ptr = boost::addressof(other_id);
|
||||
}
|
||||
}
|
||||
}
|
||||
else // operation_boundary
|
||||
@@ -675,7 +668,8 @@ struct linear_areal
|
||||
// we're inside, possibly going out right now
|
||||
if ( ! no_enters_detected )
|
||||
{
|
||||
if ( op_blocked )
|
||||
if ( op_blocked
|
||||
&& it->operations[op_id].position == overlay::position_back ) // ignore spikes!
|
||||
{
|
||||
// check if this is indeed the boundary point
|
||||
// NOTE: is_ip_on_boundary<>() should be called here but the result will be the same
|
||||
@@ -780,7 +774,8 @@ struct linear_areal
|
||||
// here, the possible exit is the real one
|
||||
// we know that we entered and now we exit
|
||||
if ( /*m_exit_watcher.get_exit_operation() == overlay::operation_union // THIS CHECK IS REDUNDANT
|
||||
||*/ m_previous_operation == overlay::operation_union )
|
||||
||*/ m_previous_operation == overlay::operation_union
|
||||
&& !m_interior_detected )
|
||||
{
|
||||
// for sure
|
||||
update<interior, exterior, '1', TransposeResult>(res);
|
||||
@@ -801,10 +796,12 @@ struct linear_areal
|
||||
}
|
||||
}
|
||||
// we might enter some Areal and didn't go out,
|
||||
else if ( m_previous_operation == overlay::operation_intersection )
|
||||
else if ( m_previous_operation == overlay::operation_intersection
|
||||
|| m_interior_detected )
|
||||
{
|
||||
// just in case
|
||||
update<interior, interior, '1', TransposeResult>(res);
|
||||
m_interior_detected = false;
|
||||
|
||||
BOOST_ASSERT(first != last);
|
||||
BOOST_ASSERT(m_previous_turn_ptr);
|
||||
@@ -822,14 +819,6 @@ struct linear_areal
|
||||
}
|
||||
}
|
||||
|
||||
// handle the interior overlap
|
||||
if ( m_interior_detected )
|
||||
{
|
||||
// just in case
|
||||
update<interior, interior, '1', TransposeResult>(res);
|
||||
m_interior_detected = false;
|
||||
}
|
||||
|
||||
BOOST_ASSERT_MSG(m_previous_operation != overlay::operation_continue,
|
||||
"Unexpected operation! Probably the error in get_turns(L,A) or relate(L,A)");
|
||||
|
||||
@@ -848,28 +837,13 @@ struct linear_areal
|
||||
if ( turn.operations[op_id].position == overlay::position_front )
|
||||
return false;
|
||||
|
||||
static const bool reverse2 = detail::overlay::do_reverse<
|
||||
geometry::point_order<Geometry2>::value
|
||||
>::value;
|
||||
|
||||
typedef typename closeable_view
|
||||
<
|
||||
typename range_type<Geometry2>::type const,
|
||||
closure<Geometry2>::value
|
||||
>::type range2_cview;
|
||||
|
||||
typedef typename reversible_view
|
||||
<
|
||||
range2_cview const,
|
||||
reverse2 ? iterate_reverse : iterate_forward
|
||||
>::type range2_view;
|
||||
|
||||
typedef typename sub_range_return_type<Geometry1 const>::type range1_ref;
|
||||
|
||||
range1_ref range1 = sub_range(geometry1, turn.operations[op_id].seg_id);
|
||||
range2_cview const cview(sub_range(geometry2, turn.operations[other_op_id].seg_id));
|
||||
range2_view const range2(cview);
|
||||
|
||||
typename sub_range_return_type<Geometry1 const>::type
|
||||
range1 = sub_range(geometry1, turn.operations[op_id].seg_id);
|
||||
|
||||
typedef detail::normalized_view<Geometry2 const> const range2_type;
|
||||
typedef typename boost::range_iterator<range2_type>::type range2_iterator;
|
||||
range2_type range2(sub_range(geometry2, turn.operations[other_op_id].seg_id));
|
||||
|
||||
std::size_t s1 = boost::size(range1);
|
||||
std::size_t s2 = boost::size(range2);
|
||||
BOOST_ASSERT(s1 > 1 && s2 > 2);
|
||||
@@ -897,10 +871,9 @@ struct linear_areal
|
||||
std::size_t q_seg_jk = (q_seg_ij + 1) % seg_count2;
|
||||
// TODO: the following function should return immediately, however the worst case complexity is O(N)
|
||||
// It would be good to replace it with some O(1) mechanism
|
||||
typename boost::range_iterator<range2_view>::type
|
||||
qk_it = find_next_non_duplicated(boost::begin(range2),
|
||||
boost::begin(range2) + q_seg_jk,
|
||||
boost::end(range2));
|
||||
range2_iterator qk_it = find_next_non_duplicated(boost::begin(range2),
|
||||
boost::begin(range2) + q_seg_jk,
|
||||
boost::end(range2));
|
||||
|
||||
// Will this sequence of points be always correct?
|
||||
overlay::side_calculator<point1_type, point2_type> side_calc(qi_conv, new_pj, pi, qi, qj, *qk_it);
|
||||
@@ -962,11 +935,12 @@ struct linear_areal
|
||||
|
||||
private:
|
||||
exit_watcher<TurnInfo, op_id> m_exit_watcher;
|
||||
segment_watcher<same_single_geometry> m_seg_watcher;
|
||||
segment_watcher<same_single> m_seg_watcher;
|
||||
TurnInfo * m_previous_turn_ptr;
|
||||
overlay::operation_type m_previous_operation;
|
||||
unsigned m_boundary_counter;
|
||||
bool m_interior_detected;
|
||||
const segment_identifier * m_first_interior_other_id_ptr;
|
||||
};
|
||||
|
||||
// call analyser.apply() for each turn in range
|
||||
|
||||
@@ -17,6 +17,7 @@
|
||||
#include <boost/geometry/util/range.hpp>
|
||||
|
||||
#include <boost/geometry/algorithms/detail/sub_range.hpp>
|
||||
#include <boost/geometry/algorithms/detail/single_geometry.hpp>
|
||||
|
||||
#include <boost/geometry/algorithms/detail/relate/point_geometry.hpp>
|
||||
#include <boost/geometry/algorithms/detail/relate/turns.hpp>
|
||||
@@ -67,18 +68,28 @@ public:
|
||||
return true;
|
||||
}
|
||||
|
||||
update<interior, exterior, '1', TransposeResult>(m_result);
|
||||
m_flags |= 1;
|
||||
|
||||
// check if there is a boundary
|
||||
if ( m_flags < 2
|
||||
&& ( m_boundary_checker.template
|
||||
is_endpoint_boundary<boundary_front>(range::front(linestring))
|
||||
|| m_boundary_checker.template
|
||||
is_endpoint_boundary<boundary_back>(range::back(linestring)) ) )
|
||||
// point-like linestring
|
||||
if ( count == 2
|
||||
&& equals::equals_point_point(range::front(linestring),
|
||||
range::back(linestring)) )
|
||||
{
|
||||
update<boundary, exterior, '0', TransposeResult>(m_result);
|
||||
m_flags |= 2;
|
||||
update<interior, exterior, '0', TransposeResult>(m_result);
|
||||
}
|
||||
else
|
||||
{
|
||||
update<interior, exterior, '1', TransposeResult>(m_result);
|
||||
m_flags |= 1;
|
||||
|
||||
// check if there is a boundary
|
||||
if ( m_flags < 2
|
||||
&& ( m_boundary_checker.template
|
||||
is_endpoint_boundary<boundary_front>(range::front(linestring))
|
||||
|| m_boundary_checker.template
|
||||
is_endpoint_boundary<boundary_back>(range::back(linestring)) ) )
|
||||
{
|
||||
update<boundary, exterior, '0', TransposeResult>(m_result);
|
||||
m_flags |= 2;
|
||||
}
|
||||
}
|
||||
|
||||
return m_flags != 3
|
||||
@@ -91,126 +102,6 @@ private:
|
||||
unsigned m_flags;
|
||||
};
|
||||
|
||||
//enum linestring_kind { linestring_exterior, linestring_point, linestring_closed, linestring_open };
|
||||
//
|
||||
//template <typename Linestring>
|
||||
//linestring_kind check_linestring_kind(Linestring const& ls)
|
||||
//{
|
||||
// std::size_t count = boost::size(ls);
|
||||
// if ( count == 0 )
|
||||
// return linestring_exterior;
|
||||
// else if ( count == 1 )
|
||||
// return linestring_point;
|
||||
// else
|
||||
// {
|
||||
// bool equal_fb = equals::equals_point_point(range::front(ls), range::back(ls));
|
||||
// if ( equal_fb )
|
||||
// {
|
||||
// typedef typename boost::range_iterator<Linestring const>::type iterator;
|
||||
// iterator first = boost::begin(ls);
|
||||
// ++first;
|
||||
// iterator last = boost::end(ls);
|
||||
// --last;
|
||||
// for ( iterator it = first ; it != last ; ++it )
|
||||
// {
|
||||
// if ( !equals::equals_point_point(range::front(ls), *it) )
|
||||
// return linestring_closed;
|
||||
// }
|
||||
//
|
||||
// return linestring_point;
|
||||
// }
|
||||
// else
|
||||
// return linestring_open;
|
||||
// }
|
||||
//}
|
||||
|
||||
// Called in a loop for:
|
||||
// Ls/Ls - worst O(N) - 1x point_in_geometry(MLs)
|
||||
// Ls/MLs - worst O(N) - 1x point_in_geometry(MLs)
|
||||
// MLs/Ls - worst O(N^2) - Bx point_in_geometry(Ls)
|
||||
// MLs/MLs - worst O(N^2) - Bx point_in_geometry(Ls)
|
||||
// TODO: later use spatial index
|
||||
//template <std::size_t OpId, typename Result, typename BoundaryChecker, typename OtherGeometry>
|
||||
//class disjoint_linestring_pred_with_point_size_handling
|
||||
//{
|
||||
// static const bool transpose_result = OpId != 0;
|
||||
//
|
||||
//public:
|
||||
// disjoint_linestring_pred_with_point_size_handling(Result & res,
|
||||
// BoundaryChecker & boundary_checker,
|
||||
// OtherGeometry const& other_geometry)
|
||||
// : m_result_ptr(boost::addressof(res))
|
||||
// , m_boundary_checker_ptr(boost::addressof(boundary_checker))
|
||||
// , m_other_geometry(boost::addressof(other_geometry))
|
||||
// , m_detected_mask_point(0)
|
||||
// , m_detected_open_boundary(false)
|
||||
// {}
|
||||
//
|
||||
// template <typename Linestring>
|
||||
// bool operator()(Linestring const& linestring)
|
||||
// {
|
||||
// linestring_kind lk = check_linestring_kind(linestring);
|
||||
//
|
||||
// if ( lk == linestring_point ) // just an optimization
|
||||
// {
|
||||
// if ( m_detected_mask_point != 7 )
|
||||
// {
|
||||
// // check the relation
|
||||
// int pig = within::point_in_geometry(range::front(linestring), *m_other_geometry);
|
||||
//
|
||||
// // point inside
|
||||
// if ( pig > 0 )
|
||||
// {
|
||||
// update<interior, interior, '0', transpose_result>(*m_result_ptr);
|
||||
// m_detected_mask_point |= 1;
|
||||
// }
|
||||
// // point on boundary
|
||||
// else if ( pig == 0 )
|
||||
// {
|
||||
// update<interior, boundary, '0', transpose_result>(*m_result_ptr);
|
||||
// m_detected_mask_point |= 2;
|
||||
// }
|
||||
// // point outside
|
||||
// else
|
||||
// {
|
||||
// update<interior, exterior, '0', transpose_result>(*m_result_ptr);
|
||||
// m_detected_mask_point |= 4;
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// // NOTE: For closed Linestrings I/I=1 could be set automatically
|
||||
// // but for MultiLinestrings endpoints of closed Linestrings must also be checked for boundary
|
||||
// else if ( lk == linestring_open || lk == linestring_closed )
|
||||
// {
|
||||
// if ( !m_detected_open_boundary ) // just an optimization
|
||||
// {
|
||||
// update<interior, exterior, '1', transpose_result>(*m_result_ptr);
|
||||
//
|
||||
// // check if there is a boundary
|
||||
// if ( m_boundary_checker_ptr->template
|
||||
// is_endpoint_boundary<boundary_front>(range::front(linestring))
|
||||
// || m_boundary_checker_ptr->template
|
||||
// is_endpoint_boundary<boundary_back>(range::back(linestring)) )
|
||||
// {
|
||||
// update<boundary, exterior, '0', transpose_result>(*m_result_ptr);
|
||||
//
|
||||
// m_detected_open_boundary = true;
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// bool all_detected = m_detected_mask_point == 7 && m_detected_open_boundary;
|
||||
// return !all_detected && !m_result_ptr->interrupt;
|
||||
// }
|
||||
//
|
||||
//private:
|
||||
// Result * m_result_ptr;
|
||||
// BoundaryChecker * m_boundary_checker_ptr;
|
||||
// const OtherGeometry * m_other_geometry;
|
||||
// char m_detected_mask_point;
|
||||
// bool m_detected_open_boundary;
|
||||
//};
|
||||
|
||||
template <typename Geometry1, typename Geometry2>
|
||||
struct linear_linear
|
||||
{
|
||||
@@ -223,7 +114,7 @@ struct linear_linear
|
||||
static inline void apply(Geometry1 const& geometry1, Geometry2 const& geometry2, Result & result)
|
||||
{
|
||||
// The result should be FFFFFFFFF
|
||||
set<exterior, exterior, result_dimension<Geometry1>::value>(result);// FFFFFFFFd, d in [1,9] or T
|
||||
relate::set<exterior, exterior, result_dimension<Geometry1>::value>(result);// FFFFFFFFd, d in [1,9] or T
|
||||
if ( result.interrupt )
|
||||
return;
|
||||
|
||||
@@ -234,7 +125,12 @@ struct linear_linear
|
||||
|
||||
interrupt_policy_linear_linear<Result> interrupt_policy(result);
|
||||
|
||||
turns::get_turns<Geometry1, Geometry2>::apply(turns, geometry1, geometry2, interrupt_policy);
|
||||
turns::get_turns
|
||||
<
|
||||
Geometry1,
|
||||
Geometry2,
|
||||
detail::get_turns::get_turn_info_type<Geometry1, Geometry2, turns::assign_policy<true> >
|
||||
>::apply(turns, geometry1, geometry2, interrupt_policy);
|
||||
|
||||
if ( result.interrupt )
|
||||
return;
|
||||
@@ -264,14 +160,7 @@ struct linear_linear
|
||||
|| may_update<boundary, boundary, '0'>(result)
|
||||
|| may_update<boundary, exterior, '0'>(result) )
|
||||
{
|
||||
// x, u, i, c
|
||||
typedef turns::less
|
||||
<
|
||||
0, turns::less_greater_op_for_other_same_m_diff_r
|
||||
<
|
||||
turns::op_to_int<0,2,3,1,4,0>
|
||||
>
|
||||
> less;
|
||||
typedef turns::less<0, turns::less_op_linear_linear> less;
|
||||
std::sort(turns.begin(), turns.end(), less());
|
||||
|
||||
turns_analyser<turn_type, 0> analyser;
|
||||
@@ -291,14 +180,7 @@ struct linear_linear
|
||||
|| may_update<boundary, boundary, '0', true>(result)
|
||||
|| may_update<boundary, exterior, '0', true>(result) )
|
||||
{
|
||||
// x, u, i, c
|
||||
typedef turns::less
|
||||
<
|
||||
1, turns::less_greater_op_for_other_same_m_diff_r
|
||||
<
|
||||
turns::op_to_int<0,2,3,1,4,0>
|
||||
>
|
||||
> less;
|
||||
typedef turns::less<1, turns::less_op_linear_linear> less;
|
||||
std::sort(turns.begin(), turns.end(), less());
|
||||
|
||||
turns_analyser<turn_type, 1> analyser;
|
||||
@@ -364,8 +246,9 @@ struct linear_linear
|
||||
|
||||
public:
|
||||
turns_analyser()
|
||||
: m_previous_turn_ptr(0)
|
||||
: m_previous_turn_ptr(NULL)
|
||||
, m_previous_operation(overlay::operation_none)
|
||||
, m_degenerated_turn_ptr(NULL)
|
||||
{}
|
||||
|
||||
template <typename Result,
|
||||
@@ -377,7 +260,7 @@ struct linear_linear
|
||||
void apply(Result & res,
|
||||
TurnIt first, TurnIt it, TurnIt last,
|
||||
Geometry const& geometry,
|
||||
OtherGeometry const& /*other_geometry*/,
|
||||
OtherGeometry const& other_geometry,
|
||||
BoundaryChecker const& boundary_checker,
|
||||
OtherBoundaryChecker const& other_boundary_checker)
|
||||
{
|
||||
@@ -385,18 +268,47 @@ struct linear_linear
|
||||
|
||||
overlay::operation_type op = it->operations[op_id].operation;
|
||||
|
||||
if ( op != overlay::operation_union
|
||||
&& op != overlay::operation_intersection
|
||||
&& op != overlay::operation_blocked )
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
segment_identifier const& seg_id = it->operations[op_id].seg_id;
|
||||
segment_identifier const& other_id = it->operations[other_op_id].seg_id;
|
||||
|
||||
const bool first_in_range = m_seg_watcher.update(seg_id);
|
||||
|
||||
if ( op != overlay::operation_union
|
||||
&& op != overlay::operation_intersection
|
||||
&& op != overlay::operation_blocked )
|
||||
{
|
||||
// degenerated turn
|
||||
if ( op == overlay::operation_continue
|
||||
&& it->method == overlay::method_none
|
||||
&& m_exit_watcher.is_outside(*it)
|
||||
/*&& ( m_exit_watcher.get_exit_operation() == overlay::operation_none
|
||||
|| ! turn_on_the_same_ip<op_id>(m_exit_watcher.get_exit_turn(), *it) )*/ )
|
||||
{
|
||||
// TODO: rewrite the above condition
|
||||
|
||||
// WARNING! For spikes the above condition may be TRUE
|
||||
// When degenerated turns are be marked in a different way than c,c/c
|
||||
// different condition will be checked
|
||||
|
||||
handle_degenerated(res, *it,
|
||||
geometry, other_geometry,
|
||||
boundary_checker, other_boundary_checker,
|
||||
first_in_range);
|
||||
|
||||
// TODO: not elegant solution! should be rewritten.
|
||||
if ( it->operations[op_id].position == overlay::position_back )
|
||||
{
|
||||
m_previous_operation = overlay::operation_blocked;
|
||||
m_exit_watcher.reset_detected_exit();
|
||||
}
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
// reset
|
||||
m_degenerated_turn_ptr = NULL;
|
||||
|
||||
// handle possible exit
|
||||
bool fake_enter_detected = false;
|
||||
if ( m_exit_watcher.get_exit_operation() == overlay::operation_union )
|
||||
@@ -423,34 +335,15 @@ struct linear_linear
|
||||
if ( op == overlay::operation_blocked )
|
||||
return;
|
||||
|
||||
if ( op == overlay::operation_intersection
|
||||
&& turn_on_the_same_ip<op_id>(m_exit_watcher.get_exit_turn(), *it) )
|
||||
{
|
||||
fake_enter_detected = true;
|
||||
}
|
||||
|
||||
m_exit_watcher.reset_detected_exit();
|
||||
}
|
||||
|
||||
// if the new linestring started just now,
|
||||
// but the previous one went out on the previous point,
|
||||
// we must check if the boundary of the previous segment is outside
|
||||
// NOTE: couldn't it be integrated with the handling of the union above?
|
||||
// THIS IS REDUNDANT WITH THE HANDLING OF THE END OF THE RANGE
|
||||
//if ( first_in_range
|
||||
// && ! fake_enter_detected
|
||||
// && m_previous_operation == overlay::operation_union )
|
||||
//{
|
||||
// BOOST_ASSERT(it != first);
|
||||
// BOOST_ASSERT(m_previous_turn_ptr);
|
||||
|
||||
// segment_identifier const& prev_seg_id = m_previous_turn_ptr->operations[op_id].seg_id;
|
||||
|
||||
// bool prev_back_b = is_endpoint_on_boundary<boundary_back>(
|
||||
// range::back(sub_geometry::get(geometry, prev_seg_id)),
|
||||
// boundary_checker);
|
||||
|
||||
// // if there is a boundary on the last point
|
||||
// if ( prev_back_b )
|
||||
// {
|
||||
// update<boundary, exterior, '0', transpose_result>(res);
|
||||
// }
|
||||
//}
|
||||
|
||||
// i/i, i/x, i/u
|
||||
if ( op == overlay::operation_intersection )
|
||||
{
|
||||
@@ -459,8 +352,9 @@ struct linear_linear
|
||||
|
||||
// interiors overlaps
|
||||
update<interior, interior, '1', transpose_result>(res);
|
||||
|
||||
bool this_b = is_ip_on_boundary<boundary_front>(it->point,
|
||||
|
||||
bool this_b = it->operations[op_id].position == overlay::position_front // ignore spikes!
|
||||
&& is_ip_on_boundary<boundary_front>(it->point,
|
||||
it->operations[op_id],
|
||||
boundary_checker,
|
||||
seg_id);
|
||||
@@ -489,7 +383,9 @@ struct linear_linear
|
||||
else
|
||||
{
|
||||
// if we didn't enter in the past, we were outside
|
||||
if ( was_outside && !fake_enter_detected )
|
||||
if ( was_outside
|
||||
&& ! fake_enter_detected
|
||||
&& it->operations[op_id].position != overlay::position_front )
|
||||
{
|
||||
update<interior, exterior, '1', transpose_result>(res);
|
||||
|
||||
@@ -521,7 +417,7 @@ struct linear_linear
|
||||
// to exit we must be currently inside and the current segment must be collinear
|
||||
if ( !was_outside && is_collinear )
|
||||
{
|
||||
m_exit_watcher.exit(*it);
|
||||
m_exit_watcher.exit(*it, false);
|
||||
}
|
||||
|
||||
bool op_blocked = op == overlay::operation_blocked;
|
||||
@@ -530,7 +426,8 @@ struct linear_linear
|
||||
// possibly going out right now
|
||||
if ( ! was_outside && is_collinear )
|
||||
{
|
||||
if ( op_blocked )
|
||||
if ( op_blocked
|
||||
&& it->operations[op_id].position == overlay::position_back ) // ignore spikes!
|
||||
{
|
||||
// check if this is indeed the boundary point
|
||||
// NOTE: is_ip_on_boundary<>() should be called here but the result will be the same
|
||||
@@ -665,24 +562,33 @@ struct linear_linear
|
||||
// here, the possible exit is the real one
|
||||
// we know that we entered and now we exit
|
||||
if ( /*m_exit_watcher.get_exit_operation() == overlay::operation_union // THIS CHECK IS REDUNDANT
|
||||
||*/ m_previous_operation == overlay::operation_union )
|
||||
||*/ m_previous_operation == overlay::operation_union
|
||||
|| m_degenerated_turn_ptr )
|
||||
{
|
||||
// for sure
|
||||
update<interior, exterior, '1', transpose_result>(res);
|
||||
|
||||
BOOST_ASSERT(first != last);
|
||||
BOOST_ASSERT(m_previous_turn_ptr);
|
||||
|
||||
segment_identifier const& prev_seg_id = m_previous_turn_ptr->operations[op_id].seg_id;
|
||||
|
||||
bool prev_back_b = is_endpoint_on_boundary<boundary_back>(
|
||||
range::back(sub_range(geometry, prev_seg_id)),
|
||||
boundary_checker);
|
||||
|
||||
// if there is a boundary on the last point
|
||||
if ( prev_back_b )
|
||||
const TurnInfo * turn_ptr = NULL;
|
||||
if ( m_degenerated_turn_ptr )
|
||||
turn_ptr = m_degenerated_turn_ptr;
|
||||
else if ( m_previous_turn_ptr )
|
||||
turn_ptr = m_previous_turn_ptr;
|
||||
|
||||
if ( turn_ptr )
|
||||
{
|
||||
update<boundary, exterior, '0', transpose_result>(res);
|
||||
segment_identifier const& prev_seg_id = turn_ptr->operations[op_id].seg_id;
|
||||
|
||||
//BOOST_ASSERT(!boost::empty(sub_range(geometry, prev_seg_id)));
|
||||
bool prev_back_b = is_endpoint_on_boundary<boundary_back>(
|
||||
range::back(sub_range(geometry, prev_seg_id)),
|
||||
boundary_checker);
|
||||
|
||||
// if there is a boundary on the last point
|
||||
if ( prev_back_b )
|
||||
{
|
||||
update<boundary, exterior, '0', transpose_result>(res);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -690,13 +596,127 @@ struct linear_linear
|
||||
// reset exit watcher before the analysis of the next Linestring
|
||||
// note that if there are some enters stored there may be some error above
|
||||
m_exit_watcher.reset();
|
||||
|
||||
m_previous_turn_ptr = NULL;
|
||||
m_previous_operation = overlay::operation_none;
|
||||
m_degenerated_turn_ptr = NULL;
|
||||
}
|
||||
|
||||
template <typename Result,
|
||||
typename Turn,
|
||||
typename Geometry,
|
||||
typename OtherGeometry,
|
||||
typename BoundaryChecker,
|
||||
typename OtherBoundaryChecker>
|
||||
void handle_degenerated(Result & res,
|
||||
Turn const& turn,
|
||||
Geometry const& geometry,
|
||||
OtherGeometry const& other_geometry,
|
||||
BoundaryChecker const& boundary_checker,
|
||||
OtherBoundaryChecker const& other_boundary_checker,
|
||||
bool first_in_range)
|
||||
{
|
||||
typename detail::single_geometry_return_type<Geometry const>::type
|
||||
ls1_ref = detail::single_geometry(geometry, turn.operations[op_id].seg_id);
|
||||
typename detail::single_geometry_return_type<OtherGeometry const>::type
|
||||
ls2_ref = detail::single_geometry(other_geometry, turn.operations[op_id].other_id);
|
||||
|
||||
// only one of those should be true:
|
||||
|
||||
if ( turn.operations[op_id].position == overlay::position_front )
|
||||
{
|
||||
// valid, point-sized
|
||||
if ( boost::size(ls2_ref) == 2 )
|
||||
{
|
||||
bool front_b = is_endpoint_on_boundary<boundary_front>(turn.point, boundary_checker);
|
||||
|
||||
if ( front_b )
|
||||
{
|
||||
update<boundary, interior, '0', transpose_result>(res);
|
||||
}
|
||||
else
|
||||
{
|
||||
update<interior, interior, '0', transpose_result>(res);
|
||||
}
|
||||
|
||||
// operation 'c' should be last for the same IP so we know that the next point won't be the same
|
||||
update<interior, exterior, '1', transpose_result>(res);
|
||||
|
||||
m_degenerated_turn_ptr = boost::addressof(turn);
|
||||
}
|
||||
}
|
||||
else if ( turn.operations[op_id].position == overlay::position_back )
|
||||
{
|
||||
// valid, point-sized
|
||||
if ( boost::size(ls2_ref) == 2 )
|
||||
{
|
||||
update<interior, exterior, '1', transpose_result>(res);
|
||||
|
||||
bool back_b = is_endpoint_on_boundary<boundary_back>(turn.point, boundary_checker);
|
||||
|
||||
if ( back_b )
|
||||
{
|
||||
update<boundary, interior, '0', transpose_result>(res);
|
||||
}
|
||||
else
|
||||
{
|
||||
update<interior, interior, '0', transpose_result>(res);
|
||||
}
|
||||
|
||||
if ( first_in_range )
|
||||
{
|
||||
//BOOST_ASSERT(!boost::empty(ls1_ref));
|
||||
bool front_b = is_endpoint_on_boundary<boundary_front>(
|
||||
range::front(ls1_ref), boundary_checker);
|
||||
if ( front_b )
|
||||
{
|
||||
update<boundary, exterior, '0', transpose_result>(res);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else if ( turn.operations[op_id].position == overlay::position_middle
|
||||
&& turn.operations[other_op_id].position == overlay::position_middle )
|
||||
{
|
||||
update<interior, interior, '0', transpose_result>(res);
|
||||
|
||||
// here we don't know which one is degenerated
|
||||
|
||||
bool is_point1 = boost::size(ls1_ref) == 2
|
||||
&& equals::equals_point_point(range::front(ls1_ref), range::back(ls1_ref));
|
||||
bool is_point2 = boost::size(ls2_ref) == 2
|
||||
&& equals::equals_point_point(range::front(ls2_ref), range::back(ls2_ref));
|
||||
|
||||
// if the second one is degenerated
|
||||
if ( !is_point1 && is_point2 )
|
||||
{
|
||||
update<interior, exterior, '1', transpose_result>(res);
|
||||
|
||||
if ( first_in_range )
|
||||
{
|
||||
//BOOST_ASSERT(!boost::empty(ls1_ref));
|
||||
bool front_b = is_endpoint_on_boundary<boundary_front>(
|
||||
range::front(ls1_ref), boundary_checker);
|
||||
if ( front_b )
|
||||
{
|
||||
update<boundary, exterior, '0', transpose_result>(res);
|
||||
}
|
||||
}
|
||||
|
||||
m_degenerated_turn_ptr = boost::addressof(turn);
|
||||
}
|
||||
}
|
||||
|
||||
// NOTE: other.position == front and other.position == back
|
||||
// will be handled later, for the other geometry
|
||||
}
|
||||
|
||||
private:
|
||||
exit_watcher<TurnInfo, OpId> m_exit_watcher;
|
||||
segment_watcher<same_single_geometry> m_seg_watcher;
|
||||
TurnInfo * m_previous_turn_ptr;
|
||||
segment_watcher<same_single> m_seg_watcher;
|
||||
const TurnInfo * m_previous_turn_ptr;
|
||||
overlay::operation_type m_previous_operation;
|
||||
const TurnInfo * m_degenerated_turn_ptr;
|
||||
};
|
||||
|
||||
template <typename Result,
|
||||
|
||||
@@ -198,19 +198,22 @@ struct interruption_enabled
|
||||
detail_dispatch::relate::relate<Geometry1, Geometry2>::interruption_enabled;
|
||||
};
|
||||
|
||||
template <typename Geometry1, typename Geometry2, typename Result>
|
||||
template <typename Geometry1,
|
||||
typename Geometry2,
|
||||
typename Result,
|
||||
bool IsSequence = boost::mpl::is_sequence<Result>::value>
|
||||
struct result_handler_type
|
||||
: not_implemented<Result>
|
||||
{};
|
||||
|
||||
template <typename Geometry1, typename Geometry2>
|
||||
struct result_handler_type<Geometry1, Geometry2, matrix9>
|
||||
struct result_handler_type<Geometry1, Geometry2, matrix9, false>
|
||||
{
|
||||
typedef matrix_handler<matrix9> type;
|
||||
};
|
||||
|
||||
template <typename Geometry1, typename Geometry2>
|
||||
struct result_handler_type<Geometry1, Geometry2, mask9>
|
||||
struct result_handler_type<Geometry1, Geometry2, mask9, false>
|
||||
{
|
||||
typedef mask_handler
|
||||
<
|
||||
@@ -224,7 +227,7 @@ struct result_handler_type<Geometry1, Geometry2, mask9>
|
||||
};
|
||||
|
||||
template <typename Geometry1, typename Geometry2, typename Head, typename Tail>
|
||||
struct result_handler_type<Geometry1, Geometry2, boost::tuples::cons<Head, Tail> >
|
||||
struct result_handler_type<Geometry1, Geometry2, boost::tuples::cons<Head, Tail>, false>
|
||||
{
|
||||
typedef mask_handler
|
||||
<
|
||||
@@ -241,7 +244,7 @@ template <typename Geometry1, typename Geometry2,
|
||||
char II, char IB, char IE,
|
||||
char BI, char BB, char BE,
|
||||
char EI, char EB, char EE>
|
||||
struct result_handler_type<Geometry1, Geometry2, static_mask<II, IB, IE, BI, BB, BE, EI, EB, EE> >
|
||||
struct result_handler_type<Geometry1, Geometry2, static_mask<II, IB, IE, BI, BB, BE, EI, EB, EE>, false>
|
||||
{
|
||||
typedef static_mask_handler
|
||||
<
|
||||
@@ -254,6 +257,20 @@ struct result_handler_type<Geometry1, Geometry2, static_mask<II, IB, IE, BI, BB,
|
||||
> type;
|
||||
};
|
||||
|
||||
template <typename Geometry1, typename Geometry2, typename StaticSequence>
|
||||
struct result_handler_type<Geometry1, Geometry2, StaticSequence, true>
|
||||
{
|
||||
typedef static_mask_handler
|
||||
<
|
||||
StaticSequence,
|
||||
interruption_enabled
|
||||
<
|
||||
Geometry1,
|
||||
Geometry2
|
||||
>::value
|
||||
> type;
|
||||
};
|
||||
|
||||
template <typename MatrixOrMask, typename Geometry1, typename Geometry2>
|
||||
inline
|
||||
typename result_handler_type
|
||||
|
||||
@@ -468,7 +468,7 @@ struct check_dispatch< boost::tuple<T0, T1, T2, T3, T4, T5, T6, T7, T8, T9> >
|
||||
template <typename Matrix>
|
||||
static inline bool apply(mask_type const& mask, Matrix const& matrix)
|
||||
{
|
||||
return check_dispatch_tuple<mask_type>::template apply(mask, matrix);
|
||||
return check_dispatch_tuple<mask_type>::apply(mask, matrix);
|
||||
}
|
||||
};
|
||||
|
||||
@@ -480,7 +480,7 @@ struct check_dispatch< boost::tuples::cons<Head, Tail> >
|
||||
template <typename Matrix>
|
||||
static inline bool apply(mask_type const& mask, Matrix const& matrix)
|
||||
{
|
||||
return check_dispatch_tuple<mask_type>::template apply(mask, matrix);
|
||||
return check_dispatch_tuple<mask_type>::apply(mask, matrix);
|
||||
}
|
||||
};
|
||||
|
||||
@@ -620,8 +620,8 @@ public:
|
||||
|
||||
// static_should_handle_element
|
||||
|
||||
template <typename StaticMask, field F1, field F2>
|
||||
struct static_should_handle_element
|
||||
template <typename StaticMask, field F1, field F2, bool IsSequence>
|
||||
struct static_should_handle_element_dispatch
|
||||
{
|
||||
static const char mask_el = StaticMask::template get<F1, F2>::value;
|
||||
static const bool value = mask_el == 'F'
|
||||
@@ -629,6 +629,56 @@ struct static_should_handle_element
|
||||
|| ( mask_el >= '0' && mask_el <= '9' );
|
||||
};
|
||||
|
||||
template <typename First, typename Last, field F1, field F2>
|
||||
struct static_should_handle_element_sequence
|
||||
{
|
||||
typedef typename boost::mpl::deref<First>::type StaticMask;
|
||||
|
||||
static const bool value
|
||||
= static_should_handle_element_dispatch
|
||||
<
|
||||
StaticMask,
|
||||
F1, F2,
|
||||
boost::mpl::is_sequence<StaticMask>::value
|
||||
>::value
|
||||
|| static_should_handle_element_sequence
|
||||
<
|
||||
typename boost::mpl::next<First>::type,
|
||||
Last,
|
||||
F1, F2
|
||||
>::value;
|
||||
};
|
||||
|
||||
template <typename Last, field F1, field F2>
|
||||
struct static_should_handle_element_sequence<Last, Last, F1, F2>
|
||||
{
|
||||
static const bool value = false;
|
||||
};
|
||||
|
||||
template <typename StaticMask, field F1, field F2>
|
||||
struct static_should_handle_element_dispatch<StaticMask, F1, F2, true>
|
||||
{
|
||||
static const bool value
|
||||
= static_should_handle_element_sequence
|
||||
<
|
||||
typename boost::mpl::begin<StaticMask>::type,
|
||||
typename boost::mpl::end<StaticMask>::type,
|
||||
F1, F2
|
||||
>::value;
|
||||
};
|
||||
|
||||
template <typename StaticMask, field F1, field F2>
|
||||
struct static_should_handle_element
|
||||
{
|
||||
static const bool value
|
||||
= static_should_handle_element_dispatch
|
||||
<
|
||||
StaticMask,
|
||||
F1, F2,
|
||||
boost::mpl::is_sequence<StaticMask>::value
|
||||
>::value;
|
||||
};
|
||||
|
||||
// static_interrupt
|
||||
|
||||
template <typename StaticMask, char V, field F1, field F2, bool InterruptEnabled, bool IsSequence>
|
||||
@@ -1081,7 +1131,7 @@ template <typename Geometry1,
|
||||
typename Geometry2,
|
||||
std::size_t Dim1 = topological_dimension<Geometry1>::value,
|
||||
std::size_t Dim2 = topological_dimension<Geometry2>::value>
|
||||
struct static_mask_touches_type
|
||||
struct static_mask_touches_impl
|
||||
{
|
||||
typedef boost::mpl::vector<
|
||||
static_mask<'F', 'T', '*', '*', '*', '*', '*', '*', '*'>,
|
||||
@@ -1092,11 +1142,16 @@ struct static_mask_touches_type
|
||||
// According to OGC, doesn't apply to P/P
|
||||
// Using the above mask the result would be always false
|
||||
template <typename Geometry1, typename Geometry2>
|
||||
struct static_mask_touches_type<Geometry1, Geometry2, 0, 0>
|
||||
struct static_mask_touches_impl<Geometry1, Geometry2, 0, 0>
|
||||
: not_implemented<typename geometry::tag<Geometry1>::type,
|
||||
typename geometry::tag<Geometry2>::type>
|
||||
{};
|
||||
|
||||
template <typename Geometry1, typename Geometry2>
|
||||
struct static_mask_touches_type
|
||||
: static_mask_touches_impl<Geometry1, Geometry2>
|
||||
{};
|
||||
|
||||
// WITHIN
|
||||
typedef static_mask<'T', '*', 'F', '*', '*', 'F', '*', '*', '*'> static_mask_within;
|
||||
|
||||
|
||||
@@ -15,9 +15,9 @@
|
||||
#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_RELATE_TURNS_HPP
|
||||
|
||||
#include <boost/geometry/strategies/distance.hpp>
|
||||
#include <boost/geometry/algorithms/detail/overlay/do_reverse.hpp>
|
||||
#include <boost/geometry/algorithms/detail/overlay/get_turns.hpp>
|
||||
#include <boost/geometry/algorithms/detail/overlay/get_turn_info.hpp>
|
||||
#include <boost/geometry/algorithms/detail/overlay/calculate_distance_policy.hpp>
|
||||
|
||||
#include <boost/type_traits/is_base_of.hpp>
|
||||
|
||||
@@ -26,44 +26,11 @@ namespace boost { namespace geometry {
|
||||
#ifndef DOXYGEN_NO_DETAIL
|
||||
namespace detail { namespace relate { namespace turns {
|
||||
|
||||
// TURN_INFO
|
||||
|
||||
// distance_info
|
||||
// enriched_distance_info
|
||||
// distance_enriched_info
|
||||
// distance_enrichment_info
|
||||
|
||||
template<typename P>
|
||||
struct enriched_info
|
||||
template <bool IncludeDegenerate = false>
|
||||
struct assign_policy
|
||||
: overlay::assign_null_policy
|
||||
{
|
||||
typedef typename strategy::distance::services::return_type
|
||||
<
|
||||
typename strategy::distance::services::comparable_type
|
||||
<
|
||||
typename strategy::distance::services::default_strategy
|
||||
<
|
||||
point_tag,
|
||||
P
|
||||
>::type
|
||||
>::type,
|
||||
P, P
|
||||
>::type distance_type;
|
||||
|
||||
inline enriched_info()
|
||||
: distance(distance_type())
|
||||
{}
|
||||
|
||||
distance_type distance; // distance-measurement from segment.first to IP
|
||||
};
|
||||
|
||||
// turn_operation_linear_with_distance
|
||||
// distance_enriched_turn_operation_linear
|
||||
|
||||
template <typename P>
|
||||
struct enriched_turn_operation_linear
|
||||
: public overlay::turn_operation_linear
|
||||
{
|
||||
enriched_info<P> enriched;
|
||||
static bool const include_degenerate = IncludeDegenerate;
|
||||
};
|
||||
|
||||
// GET_TURNS
|
||||
@@ -71,16 +38,21 @@ struct enriched_turn_operation_linear
|
||||
template <typename Geometry1,
|
||||
typename Geometry2,
|
||||
typename GetTurnPolicy
|
||||
= detail::get_turns::get_turn_info_type<Geometry1, Geometry2, overlay::calculate_distance_policy> >
|
||||
= detail::get_turns::get_turn_info_type<Geometry1, Geometry2, assign_policy<> > >
|
||||
struct get_turns
|
||||
{
|
||||
typedef typename geometry::point_type<Geometry1>::type point1_type;
|
||||
|
||||
typedef overlay::turn_info
|
||||
<
|
||||
point1_type,
|
||||
enriched_turn_operation_linear<point1_type>
|
||||
> turn_info;
|
||||
<
|
||||
point1_type,
|
||||
typename segment_ratio_type<point1_type, detail::no_rescale_policy>::type,
|
||||
typename detail::get_turns::turn_operation_type
|
||||
<
|
||||
Geometry1, Geometry2,
|
||||
typename segment_ratio_type<point1_type, detail::no_rescale_policy>::type
|
||||
>::type
|
||||
> turn_info;
|
||||
|
||||
template <typename Turns>
|
||||
static inline void apply(Turns & turns,
|
||||
@@ -98,6 +70,8 @@ struct get_turns
|
||||
Geometry2 const& geometry2,
|
||||
InterruptPolicy & interrupt_policy)
|
||||
{
|
||||
typedef typename geometry::point_type<Geometry1>::type point1_type;
|
||||
|
||||
static const bool reverse1 = detail::overlay::do_reverse<geometry::point_order<Geometry1>::value>::value;
|
||||
static const bool reverse2 = detail::overlay::do_reverse<geometry::point_order<Geometry2>::value>::value;
|
||||
|
||||
@@ -135,28 +109,48 @@ struct op_to_int
|
||||
}
|
||||
};
|
||||
|
||||
template <typename OpToInt = op_to_int<> >
|
||||
struct less_greater_op_for_other_same_m_diff_r
|
||||
template <typename OpToInt>
|
||||
struct less_op_xxx_linear
|
||||
{
|
||||
template <typename Op>
|
||||
inline bool operator()(Op const& left, Op const& right)
|
||||
{
|
||||
static OpToInt op_to_int;
|
||||
return op_to_int(left) < op_to_int(right);
|
||||
}
|
||||
};
|
||||
|
||||
struct less_op_linear_linear
|
||||
: less_op_xxx_linear< op_to_int<0,2,3,1,4,0> >
|
||||
{};
|
||||
|
||||
struct less_op_linear_areal
|
||||
{
|
||||
template <typename Op>
|
||||
inline bool operator()(Op const& left, Op const& right)
|
||||
{
|
||||
static turns::op_to_int<0,2,3,1,4,0> op_to_int_xuic;
|
||||
static turns::op_to_int<0,3,2,1,4,0> op_to_int_xiuc;
|
||||
|
||||
if ( left.other_id.multi_index == right.other_id.multi_index )
|
||||
{
|
||||
if ( left.other_id.ring_index == right.other_id.ring_index )
|
||||
return op_to_int(left) < op_to_int(right);
|
||||
return op_to_int_xuic(left) < op_to_int_xuic(right);
|
||||
else
|
||||
return op_to_int(left) > op_to_int(right);
|
||||
return op_to_int_xiuc(left) < op_to_int_xiuc(right);
|
||||
}
|
||||
else
|
||||
{
|
||||
return op_to_int(left) < op_to_int(right);
|
||||
//return op_to_int_xuic(left) < op_to_int_xuic(right);
|
||||
return left.other_id.multi_index < right.other_id.multi_index;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
struct less_op_areal_linear
|
||||
: less_op_xxx_linear< op_to_int<0,1,0,0,2,0> >
|
||||
{};
|
||||
|
||||
struct less_op_areal_areal
|
||||
{
|
||||
template <typename Op>
|
||||
@@ -201,20 +195,20 @@ struct less_op_areal_areal
|
||||
// sort turns by G1 - source_index == 0 by:
|
||||
// seg_id -> distance -> operation
|
||||
template <std::size_t OpId = 0,
|
||||
typename LessOp = less_greater_op_for_other_same_m_diff_r<> >
|
||||
typename LessOp = less_op_xxx_linear< op_to_int<> > >
|
||||
struct less
|
||||
{
|
||||
BOOST_STATIC_ASSERT(OpId < 2);
|
||||
|
||||
template <typename Op> static inline
|
||||
bool use_distance(Op const& left, Op const& right)
|
||||
bool use_fraction(Op const& left, Op const& right)
|
||||
{
|
||||
static LessOp less_op;
|
||||
|
||||
if ( geometry::math::equals(left.enriched.distance, right.enriched.distance) )
|
||||
if ( left.fraction == right.fraction )
|
||||
return less_op(left, right);
|
||||
else
|
||||
return left.enriched.distance < right.enriched.distance;
|
||||
return left.fraction < right.fraction;
|
||||
}
|
||||
|
||||
template <typename Turn>
|
||||
@@ -223,7 +217,7 @@ struct less
|
||||
segment_identifier const& sl = left.operations[OpId].seg_id;
|
||||
segment_identifier const& sr = right.operations[OpId].seg_id;
|
||||
|
||||
return sl < sr || ( sl == sr && use_distance(left.operations[OpId], right.operations[OpId]) );
|
||||
return sl < sr || ( sl == sr && use_fraction(left.operations[OpId], right.operations[OpId]) );
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@@ -29,7 +29,7 @@
|
||||
#include <boost/geometry/algorithms/assign.hpp>
|
||||
#include <boost/geometry/algorithms/expand.hpp>
|
||||
|
||||
#include <boost/geometry/algorithms/detail/rescale.hpp>
|
||||
#include <boost/geometry/algorithms/detail/recalculate.hpp>
|
||||
#include <boost/geometry/algorithms/detail/ring_identifier.hpp>
|
||||
|
||||
#include <boost/geometry/core/access.hpp>
|
||||
@@ -37,13 +37,17 @@
|
||||
#include <boost/geometry/core/exterior_ring.hpp>
|
||||
#include <boost/geometry/core/point_order.hpp>
|
||||
|
||||
|
||||
#include <boost/geometry/geometries/concepts/check.hpp>
|
||||
#include <boost/geometry/util/math.hpp>
|
||||
#include <boost/geometry/policies/robustness/no_rescale_policy.hpp>
|
||||
#include <boost/geometry/policies/robustness/robust_point_type.hpp>
|
||||
#include <boost/geometry/views/closeable_view.hpp>
|
||||
#include <boost/geometry/views/reversible_view.hpp>
|
||||
#include <boost/geometry/geometries/segment.hpp>
|
||||
|
||||
|
||||
|
||||
namespace boost { namespace geometry
|
||||
{
|
||||
|
||||
@@ -257,22 +261,25 @@ struct sectionalize_part
|
||||
template
|
||||
<
|
||||
typename Range, // Can be closeable_view
|
||||
typename RescalePolicy,
|
||||
typename RobustPolicy,
|
||||
typename Sections
|
||||
>
|
||||
static inline void apply(Sections& sections,
|
||||
Range const& range,
|
||||
RescalePolicy const& rescale_policy,
|
||||
RobustPolicy const& robust_policy,
|
||||
bool make_rescaled_boxes,
|
||||
ring_identifier ring_id,
|
||||
std::size_t max_count)
|
||||
{
|
||||
boost::ignore_unused_variable_warning(rescale_policy);
|
||||
boost::ignore_unused_variable_warning(robust_policy);
|
||||
boost::ignore_unused_variable_warning(make_rescaled_boxes);
|
||||
|
||||
typedef model::referring_segment<Point const> segment_type;
|
||||
typedef typename boost::range_value<Sections>::type section_type;
|
||||
|
||||
typedef model::segment
|
||||
<
|
||||
typename robust_point_type<Point, RobustPolicy>::type
|
||||
> robust_segment_type;
|
||||
typedef typename boost::range_iterator<Range const>::type iterator_type;
|
||||
|
||||
if ( boost::empty(range) )
|
||||
@@ -294,12 +301,14 @@ struct sectionalize_part
|
||||
++previous, ++it, index++)
|
||||
{
|
||||
segment_type segment(*previous, *it);
|
||||
robust_segment_type robust_segment;
|
||||
geometry::recalculate(robust_segment, segment, robust_policy);
|
||||
|
||||
int direction_classes[DimensionCount] = {0};
|
||||
get_direction_loop
|
||||
<
|
||||
0, DimensionCount
|
||||
>::apply(segment, direction_classes);
|
||||
>::apply(robust_segment, direction_classes);
|
||||
|
||||
// if "dir" == 0 for all point-dimensions, it is duplicate.
|
||||
// Those sections might be omitted, if wished, lateron
|
||||
@@ -313,7 +322,7 @@ struct sectionalize_part
|
||||
if (check_duplicate_loop
|
||||
<
|
||||
0, geometry::dimension<Point>::type::value
|
||||
>::apply(segment)
|
||||
>::apply(robust_segment)
|
||||
)
|
||||
{
|
||||
duplicate = true;
|
||||
@@ -365,10 +374,11 @@ struct sectionalize_part
|
||||
<
|
||||
int, 0, DimensionCount
|
||||
>::apply(direction_classes, section.directions);
|
||||
geometry::expand(section.bounding_box, *previous);
|
||||
|
||||
expand_box(*previous, robust_policy, section);
|
||||
}
|
||||
|
||||
geometry::expand(section.bounding_box, *it);
|
||||
expand_box(*it, robust_policy, section);
|
||||
section.end_index = index + 1;
|
||||
section.count++;
|
||||
if (! duplicate)
|
||||
@@ -394,6 +404,16 @@ struct sectionalize_part
|
||||
sections[last_non_duplicate_index].is_non_duplicate_last = true;
|
||||
}
|
||||
}
|
||||
|
||||
template <typename InputPoint, typename RobustPolicy, typename Section>
|
||||
static inline void expand_box(InputPoint const& point,
|
||||
RobustPolicy const& robust_policy,
|
||||
Section& section)
|
||||
{
|
||||
typename geometry::point_type<typename Section::box_type>::type robust_point;
|
||||
geometry::recalculate(robust_point, point, robust_policy);
|
||||
geometry::expand(section.bounding_box, robust_point);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@@ -408,11 +428,11 @@ struct sectionalize_range
|
||||
template
|
||||
<
|
||||
typename Range,
|
||||
typename RescalePolicy,
|
||||
typename RobustPolicy,
|
||||
typename Sections
|
||||
>
|
||||
static inline void apply(Range const& range,
|
||||
RescalePolicy const& rescale_policy,
|
||||
RobustPolicy const& robust_policy,
|
||||
bool make_rescaled_boxes,
|
||||
Sections& sections,
|
||||
ring_identifier ring_id,
|
||||
@@ -442,7 +462,7 @@ struct sectionalize_range
|
||||
}
|
||||
|
||||
sectionalize_part<Point, DimensionCount>
|
||||
::apply(sections, view, rescale_policy, make_rescaled_boxes, ring_id, max_count);
|
||||
::apply(sections, view, robust_policy, make_rescaled_boxes, ring_id, max_count);
|
||||
}
|
||||
};
|
||||
|
||||
@@ -456,11 +476,11 @@ struct sectionalize_polygon
|
||||
template
|
||||
<
|
||||
typename Polygon,
|
||||
typename RescalePolicy,
|
||||
typename RobustPolicy,
|
||||
typename Sections
|
||||
>
|
||||
static inline void apply(Polygon const& poly,
|
||||
RescalePolicy const& rescale_policy,
|
||||
RobustPolicy const& robust_policy,
|
||||
bool make_rescaled_boxes,
|
||||
Sections& sections,
|
||||
ring_identifier ring_id, std::size_t max_count)
|
||||
@@ -474,7 +494,7 @@ struct sectionalize_polygon
|
||||
> per_range;
|
||||
|
||||
ring_id.ring_index = -1;
|
||||
per_range::apply(exterior_ring(poly), rescale_policy, make_rescaled_boxes, sections, ring_id, max_count);
|
||||
per_range::apply(exterior_ring(poly), robust_policy, make_rescaled_boxes, sections, ring_id, max_count);
|
||||
|
||||
ring_id.ring_index++;
|
||||
typename interior_return_type<Polygon const>::type rings
|
||||
@@ -482,7 +502,7 @@ struct sectionalize_polygon
|
||||
for (BOOST_AUTO_TPL(it, boost::begin(rings)); it != boost::end(rings);
|
||||
++it, ++ring_id.ring_index)
|
||||
{
|
||||
per_range::apply(*it, rescale_policy, make_rescaled_boxes, sections, ring_id, max_count);
|
||||
per_range::apply(*it, robust_policy, make_rescaled_boxes, sections, ring_id, max_count);
|
||||
}
|
||||
}
|
||||
};
|
||||
@@ -496,11 +516,11 @@ struct sectionalize_box
|
||||
template
|
||||
<
|
||||
typename Box,
|
||||
typename RescalePolicy,
|
||||
typename RobustPolicy,
|
||||
typename Sections
|
||||
>
|
||||
static inline void apply(Box const& box,
|
||||
RescalePolicy const& rescale_policy,
|
||||
RobustPolicy const& robust_policy,
|
||||
bool make_rescaled_boxes,
|
||||
Sections& sections,
|
||||
ring_identifier const& ring_id, std::size_t max_count)
|
||||
@@ -532,7 +552,7 @@ struct sectionalize_box
|
||||
closed, false,
|
||||
point_type,
|
||||
DimensionCount
|
||||
>::apply(points, rescale_policy, make_rescaled_boxes, sections,
|
||||
>::apply(points, robust_policy, make_rescaled_boxes, sections,
|
||||
ring_id, max_count);
|
||||
}
|
||||
};
|
||||
@@ -551,7 +571,7 @@ inline void set_section_unique_ids(Sections& sections)
|
||||
}
|
||||
|
||||
template <typename Sections>
|
||||
inline void enlargeSections(Sections& sections)
|
||||
inline void enlarge_sections(Sections& sections)
|
||||
{
|
||||
// Robustness issue. Increase sections a tiny bit such that all points are really within (and not on border)
|
||||
// Reason: turns might, rarely, be missed otherwise (case: "buffer_mp1")
|
||||
@@ -669,9 +689,9 @@ struct sectionalize<polygon_tag, Polygon, Reverse, DimensionCount>
|
||||
\param sections structure with sections
|
||||
\param source_index index to assign to the ring_identifiers
|
||||
*/
|
||||
template<bool Reverse, typename Geometry, typename Sections, typename RescalePolicy>
|
||||
template<bool Reverse, typename Geometry, typename Sections, typename RobustPolicy>
|
||||
inline void sectionalize(Geometry const& geometry,
|
||||
RescalePolicy const& rescale_policy,
|
||||
RobustPolicy const& robust_policy,
|
||||
bool make_rescaled_boxes,
|
||||
Sections& sections,
|
||||
int source_index = 0)
|
||||
@@ -690,26 +710,28 @@ inline void sectionalize(Geometry const& geometry,
|
||||
Geometry,
|
||||
Reverse,
|
||||
Sections::value
|
||||
>::apply(geometry, rescale_policy, make_rescaled_boxes, sections, ring_id, 10);
|
||||
>::apply(geometry, robust_policy, make_rescaled_boxes, sections, ring_id, 10);
|
||||
|
||||
detail::sectionalize::set_section_unique_ids(sections);
|
||||
if (make_rescaled_boxes)
|
||||
if (! make_rescaled_boxes)
|
||||
{
|
||||
detail::sectionalize::enlargeSections(sections);
|
||||
detail::sectionalize::enlarge_sections(sections);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#if defined(BOOST_GEOMETRY_UNIT_TEST_SECTIONALIZE)
|
||||
// Backwards compatibility
|
||||
template<bool Reverse, typename Geometry, typename Sections>
|
||||
inline void sectionalize(Geometry const& geometry,
|
||||
Sections& sections,
|
||||
int source_index = 0)
|
||||
Sections& sections,
|
||||
int source_index = 0)
|
||||
{
|
||||
return sectionalize<Reverse>(geometry, detail::no_rescale_policy(),
|
||||
false, sections,
|
||||
source_index);
|
||||
return geometry::sectionalize<Reverse>(geometry, detail::no_rescale_policy(),
|
||||
false, sections,
|
||||
source_index);
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
}} // namespace boost::geometry
|
||||
|
||||
@@ -79,11 +79,10 @@ struct less_seg_dist_other_op
|
||||
}
|
||||
|
||||
template <typename Op>
|
||||
static inline bool use_distance(Op const& left, Op const& right)
|
||||
static inline bool use_fraction(Op const& left, Op const& right)
|
||||
{
|
||||
return left.enriched.distance < right.enriched.distance
|
||||
|| ( geometry::math::equals(left.enriched.distance,
|
||||
right.enriched.distance)
|
||||
return left.fraction < right.fraction
|
||||
|| ( geometry::math::equals(left.fraction, right.fraction)
|
||||
&& use_other_id(left, right)
|
||||
);
|
||||
}
|
||||
@@ -94,7 +93,7 @@ struct less_seg_dist_other_op
|
||||
segment_identifier const& sl = left.operations[OpId].seg_id;
|
||||
segment_identifier const& sr = right.operations[OpId].seg_id;
|
||||
|
||||
return sl < sr || ( sl == sr && use_distance(left.operations[OpId], right.operations[OpId]) );
|
||||
return sl < sr || ( sl == sr && use_fraction(left.operations[OpId], right.operations[OpId]) );
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@@ -52,6 +52,11 @@ static inline void print_turns(Geometry1 const& g1,
|
||||
else
|
||||
out << '\n';
|
||||
|
||||
double fraction[2];
|
||||
|
||||
fraction[0] = turn.operations[0].fraction.numerator()
|
||||
/ turn.operations[0].fraction.denominator();
|
||||
|
||||
out << geometry::operation_char(turn.operations[0].operation)
|
||||
<<": seg: " << turn.operations[0].seg_id.source_index
|
||||
<< ", m: " << turn.operations[0].seg_id.multi_index
|
||||
@@ -61,11 +66,15 @@ static inline void print_turns(Geometry1 const& g1,
|
||||
<< ", m: " << turn.operations[0].other_id.multi_index
|
||||
<< ", r: " << turn.operations[0].other_id.ring_index
|
||||
<< ", s: " << turn.operations[0].other_id.segment_index;
|
||||
out << ", fr: " << fraction[0];
|
||||
out << ", col?: " << turn.operations[0].is_collinear;
|
||||
out << ' ' << geometry::dsv(turn.point) << ' ';
|
||||
|
||||
out << '\n';
|
||||
|
||||
fraction[1] = turn.operations[1].fraction.numerator()
|
||||
/ turn.operations[1].fraction.denominator();
|
||||
|
||||
out << geometry::operation_char(turn.operations[1].operation)
|
||||
<< ": seg: " << turn.operations[1].seg_id.source_index
|
||||
<< ", m: " << turn.operations[1].seg_id.multi_index
|
||||
@@ -75,6 +84,7 @@ static inline void print_turns(Geometry1 const& g1,
|
||||
<< ", m: " << turn.operations[1].other_id.multi_index
|
||||
<< ", r: " << turn.operations[1].other_id.ring_index
|
||||
<< ", s: " << turn.operations[1].other_id.segment_index;
|
||||
out << ", fr: " << fraction[1];
|
||||
out << ", col?: " << turn.operations[1].is_collinear;
|
||||
out << ' ' << geometry::dsv(turn.point) << ' ';
|
||||
|
||||
|
||||
@@ -20,7 +20,7 @@
|
||||
#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_WITHIN_POINT_IN_GEOMETRY_HPP
|
||||
|
||||
#include <boost/assert.hpp>
|
||||
#include <boost/static_assert.hpp>
|
||||
#include <boost/mpl/assert.hpp>
|
||||
#include <boost/type_traits/is_same.hpp>
|
||||
#include <boost/range.hpp>
|
||||
|
||||
@@ -114,7 +114,10 @@ inline int point_in_range(Point const& point, Range const& range)
|
||||
Geometry
|
||||
>::type strategy_type2;
|
||||
|
||||
BOOST_STATIC_ASSERT(boost::is_same<strategy_type, strategy_type2>::value);
|
||||
static const bool same_strategies = boost::is_same<strategy_type, strategy_type2>::value;
|
||||
BOOST_MPL_ASSERT_MSG((same_strategies),
|
||||
DEFAULT_WITHIN_AND_COVERED_BY_STRATEGIES_NOT_COMPATIBLE,
|
||||
(strategy_type, strategy_type2));
|
||||
|
||||
return point_in_range(point, range, strategy_type());
|
||||
}
|
||||
@@ -419,7 +422,10 @@ inline int point_in_geometry(Point const& point, Geometry const& geometry)
|
||||
Geometry
|
||||
>::type strategy_type2;
|
||||
|
||||
BOOST_STATIC_ASSERT(boost::is_same<strategy_type, strategy_type2>::value);
|
||||
static const bool same_strategies = boost::is_same<strategy_type, strategy_type2>::value;
|
||||
BOOST_MPL_ASSERT_MSG((same_strategies),
|
||||
DEFAULT_WITHIN_AND_COVERED_BY_STRATEGIES_NOT_COMPATIBLE,
|
||||
(strategy_type, strategy_type2));
|
||||
|
||||
return point_in_geometry(point, geometry, strategy_type());
|
||||
}
|
||||
|
||||
@@ -20,93 +20,21 @@
|
||||
#include <boost/geometry/algorithms/envelope.hpp>
|
||||
#include <boost/geometry/algorithms/expand.hpp>
|
||||
#include <boost/geometry/algorithms/detail/recalculate.hpp>
|
||||
#include <boost/geometry/algorithms/detail/get_max_size.hpp>
|
||||
|
||||
#include <boost/geometry/geometries/box.hpp>
|
||||
#include <boost/geometry/geometries/point.hpp>
|
||||
|
||||
#include <boost/geometry/policies/robustness/rescale_policy.hpp>
|
||||
|
||||
namespace boost { namespace geometry
|
||||
{
|
||||
|
||||
#ifndef DOXYGEN_NO_DETAIL
|
||||
namespace detail { namespace zoom_to_robust
|
||||
{
|
||||
|
||||
template <typename Box, std::size_t Dimension>
|
||||
struct get_max_size
|
||||
{
|
||||
static inline typename coordinate_type<Box>::type apply(Box const& box)
|
||||
{
|
||||
typename coordinate_type<Box>::type s
|
||||
= geometry::math::abs(geometry::get<1, Dimension>(box) - geometry::get<0, Dimension>(box));
|
||||
|
||||
return (std::max)(s, get_max_size<Box, Dimension - 1>::apply(box));
|
||||
}
|
||||
};
|
||||
|
||||
template <typename Box>
|
||||
struct get_max_size<Box, 0>
|
||||
{
|
||||
static inline typename coordinate_type<Box>::type apply(Box const& box)
|
||||
{
|
||||
return geometry::math::abs(geometry::get<1, 0>(box) - geometry::get<0, 0>(box));
|
||||
}
|
||||
};
|
||||
|
||||
template <typename FpPoint, typename IntPoint, typename CalculationType>
|
||||
struct rescale_strategy
|
||||
{
|
||||
typedef typename geometry::coordinate_type<IntPoint>::type output_ct;
|
||||
|
||||
rescale_strategy(FpPoint const& fp_min, IntPoint const& int_min, CalculationType const& the_factor)
|
||||
: m_fp_min(fp_min)
|
||||
, m_int_min(int_min)
|
||||
, m_multiplier(the_factor)
|
||||
{
|
||||
}
|
||||
|
||||
template <std::size_t Dimension, typename Value>
|
||||
inline output_ct apply(Value const& value) const
|
||||
{
|
||||
// a + (v-b)*f
|
||||
CalculationType const a = static_cast<CalculationType>(get<Dimension>(m_int_min));
|
||||
CalculationType const b = static_cast<CalculationType>(get<Dimension>(m_fp_min));
|
||||
CalculationType const result = a + (value - b) * m_multiplier;
|
||||
return static_cast<output_ct>(result);
|
||||
}
|
||||
|
||||
FpPoint const& m_fp_min;
|
||||
IntPoint const& m_int_min;
|
||||
CalculationType m_multiplier;
|
||||
};
|
||||
|
||||
}} // namespace detail::zoom_to_robust
|
||||
#endif // DOXYGEN_NO_DETAIL
|
||||
|
||||
template <typename Box>
|
||||
inline typename coordinate_type<Box>::type get_max_size(Box const& box)
|
||||
{
|
||||
return detail::zoom_to_robust::get_max_size<Box, dimension<Box>::value - 1>::apply(box);
|
||||
}
|
||||
|
||||
#ifndef DOXYGEN_NO_DISPATCH
|
||||
namespace dispatch
|
||||
{
|
||||
|
||||
template <typename CoordinateType, typename IsFloatingPoint>
|
||||
struct robust_type
|
||||
{
|
||||
};
|
||||
|
||||
template <typename CoordinateType>
|
||||
struct robust_type<CoordinateType, boost::false_type>
|
||||
{
|
||||
typedef CoordinateType type;
|
||||
};
|
||||
|
||||
template <typename CoordinateType>
|
||||
struct robust_type<CoordinateType, boost::true_type>
|
||||
{
|
||||
typedef int type; // long long?
|
||||
};
|
||||
|
||||
|
||||
template <typename IsFloatingPoint>
|
||||
@@ -160,9 +88,9 @@ struct zoom_to_robust<boost::true_type>
|
||||
geometry::expand(env, g6);
|
||||
|
||||
// Scale this to integer-range
|
||||
typename geometry::coordinate_type<point1_type>::type diff = get_max_size(env);
|
||||
typename geometry::coordinate_type<point1_type>::type diff = detail::get_max_size(env);
|
||||
double range = 1000000000.0; // Define a large range to get precise integer coordinates
|
||||
double factor = double(int(range / double(diff)));
|
||||
double factor = double(boost::long_long_type(range / double(diff)));
|
||||
|
||||
// Assign input/output minimal points
|
||||
point1_type min_point1;
|
||||
@@ -170,9 +98,9 @@ struct zoom_to_robust<boost::true_type>
|
||||
|
||||
typedef typename point_type<GeometryOut>::type point2_type;
|
||||
point2_type min_point2;
|
||||
assign_values(min_point2, int(-range/2.0), int(-range/2.0));
|
||||
assign_values(min_point2, boost::long_long_type(-range/2.0), boost::long_long_type(-range/2.0));
|
||||
|
||||
detail::zoom_to_robust::rescale_strategy<point1_type, point2_type, double> strategy(min_point1, min_point2, factor);
|
||||
detail::robust_policy<point1_type, point2_type, double> strategy(min_point1, min_point2, factor);
|
||||
|
||||
geometry::recalculate(og1, g1, strategy);
|
||||
geometry::recalculate(og2, g2, strategy);
|
||||
@@ -187,15 +115,9 @@ struct zoom_to_robust<boost::true_type>
|
||||
} // namespace dispatch
|
||||
#endif // DOXYGEN_NO_DISPATCH
|
||||
|
||||
template <typename CoordinateType>
|
||||
struct robust_type
|
||||
#ifndef DOXYGEN_NO_DETAIL
|
||||
namespace detail
|
||||
{
|
||||
typedef typename dispatch::robust_type
|
||||
<
|
||||
CoordinateType,
|
||||
typename boost::is_floating_point<CoordinateType>::type
|
||||
>::type type;
|
||||
};
|
||||
|
||||
|
||||
template <typename Geometry1, typename Geometry2>
|
||||
@@ -209,21 +131,21 @@ inline void zoom_to_robust(Geometry1 const& g1a, Geometry1 const& g1b, Geometry2
|
||||
|
||||
// Get the envelop of inputs
|
||||
model::box<point1_type> env;
|
||||
envelope(g1a, env);
|
||||
expand(env, g1b);
|
||||
geometry::envelope(g1a, env);
|
||||
geometry::expand(env, g1b);
|
||||
|
||||
// Scale this to integer-range
|
||||
typename coordinate_type<point1_type>::type diff = get_max_size(env);
|
||||
typename coordinate_type<point1_type>::type diff = detail::get_max_size(env);
|
||||
double range = 1000000000.0; // Define a large range to get precise integer coordinates
|
||||
double factor = range / diff;
|
||||
|
||||
// Assign input/output minimal points
|
||||
detail::assign_point_from_index<0>(env, min_point1);
|
||||
assign_values(min_point2, int(-range/2.0), int(-range/2.0));
|
||||
assign_values(min_point2, boost::long_long_type(-range/2.0), boost::long_long_type(-range/2.0));
|
||||
|
||||
detail::zoom_to_robust::rescale_strategy<point1_type, point2_type, double> strategy(min_point1, min_point2, factor);
|
||||
recalculate(g2a, g1a, strategy);
|
||||
recalculate(g2b, g1b, strategy);
|
||||
detail::robust_policy<point1_type, point2_type, double> strategy(min_point1, min_point2, factor);
|
||||
geometry::recalculate(g2a, g1a, strategy);
|
||||
geometry::recalculate(g2b, g1b, strategy);
|
||||
}
|
||||
|
||||
template
|
||||
@@ -248,6 +170,9 @@ void zoom_to_robust(Geometry1 const& g1, Geometry2 const& g2, Geometry3 const& g
|
||||
>::apply(g1, g2, g3, g4, g5, g6, og1, og2, og3, og4, og5, og6);
|
||||
}
|
||||
|
||||
} // namespace detail
|
||||
#endif // DOXYGEN_NO_DETAIL
|
||||
|
||||
|
||||
}} // namespace boost::geometry
|
||||
|
||||
|
||||
@@ -12,6 +12,7 @@
|
||||
#include <algorithm>
|
||||
|
||||
#include <boost/geometry/algorithms/detail/overlay/intersection_insert.hpp>
|
||||
#include <boost/geometry/policies/robustness/get_rescale_policy.hpp>
|
||||
|
||||
namespace boost { namespace geometry
|
||||
{
|
||||
@@ -43,11 +44,14 @@ template
|
||||
typename GeometryOut,
|
||||
typename Geometry1,
|
||||
typename Geometry2,
|
||||
typename RobustPolicy,
|
||||
typename OutputIterator,
|
||||
typename Strategy
|
||||
>
|
||||
inline OutputIterator difference_insert(Geometry1 const& geometry1,
|
||||
Geometry2 const& geometry2, OutputIterator out,
|
||||
Geometry2 const& geometry2,
|
||||
RobustPolicy const& robust_policy,
|
||||
OutputIterator out,
|
||||
Strategy const& strategy)
|
||||
{
|
||||
concept::check<Geometry1 const>();
|
||||
@@ -61,7 +65,7 @@ inline OutputIterator difference_insert(Geometry1 const& geometry1,
|
||||
overlay_difference,
|
||||
geometry::detail::overlay::do_reverse<geometry::point_order<Geometry1>::value>::value,
|
||||
geometry::detail::overlay::do_reverse<geometry::point_order<Geometry2>::value, true>::value
|
||||
>::apply(geometry1, geometry2, out, strategy);
|
||||
>::apply(geometry1, geometry2, robust_policy, out, strategy);
|
||||
}
|
||||
|
||||
/*!
|
||||
@@ -85,10 +89,13 @@ template
|
||||
typename GeometryOut,
|
||||
typename Geometry1,
|
||||
typename Geometry2,
|
||||
typename RobustPolicy,
|
||||
typename OutputIterator
|
||||
>
|
||||
inline OutputIterator difference_insert(Geometry1 const& geometry1,
|
||||
Geometry2 const& geometry2, OutputIterator out)
|
||||
Geometry2 const& geometry2,
|
||||
RobustPolicy const& robust_policy,
|
||||
OutputIterator out)
|
||||
{
|
||||
concept::check<Geometry1 const>();
|
||||
concept::check<Geometry2 const>();
|
||||
@@ -99,11 +106,12 @@ inline OutputIterator difference_insert(Geometry1 const& geometry1,
|
||||
typename cs_tag<GeometryOut>::type,
|
||||
Geometry1,
|
||||
Geometry2,
|
||||
typename geometry::point_type<GeometryOut>::type
|
||||
typename geometry::point_type<GeometryOut>::type,
|
||||
RobustPolicy
|
||||
> strategy;
|
||||
|
||||
return difference_insert<GeometryOut>(geometry1, geometry2,
|
||||
out, strategy());
|
||||
robust_policy, out, strategy());
|
||||
}
|
||||
|
||||
|
||||
@@ -140,8 +148,17 @@ inline void difference(Geometry1 const& geometry1,
|
||||
typedef typename boost::range_value<Collection>::type geometry_out;
|
||||
concept::check<geometry_out>();
|
||||
|
||||
typedef typename geometry::rescale_overlay_policy_type
|
||||
<
|
||||
Geometry1,
|
||||
Geometry2
|
||||
>::type rescale_policy_type;
|
||||
|
||||
rescale_policy_type robust_policy
|
||||
= geometry::get_rescale_policy<rescale_policy_type>(geometry1, geometry2);
|
||||
|
||||
detail::difference::difference_insert<geometry_out>(
|
||||
geometry1, geometry2,
|
||||
geometry1, geometry2, robust_policy,
|
||||
std::back_inserter(output_collection));
|
||||
}
|
||||
|
||||
|
||||
@@ -39,7 +39,6 @@
|
||||
#include <boost/geometry/algorithms/detail/point_on_border.hpp>
|
||||
#include <boost/geometry/algorithms/point_on_surface.hpp>
|
||||
#include <boost/geometry/algorithms/detail/for_each_range.hpp>
|
||||
#include <boost/geometry/algorithms/detail/rescale.hpp>
|
||||
|
||||
#include <boost/geometry/geometries/concepts/check.hpp>
|
||||
|
||||
@@ -48,6 +47,10 @@
|
||||
#include <boost/geometry/algorithms/detail/overlay/do_reverse.hpp>
|
||||
#include <boost/geometry/views/segment_view.hpp>
|
||||
|
||||
#include <boost/geometry/policies/robustness/no_rescale_policy.hpp>
|
||||
#include <boost/geometry/policies/robustness/segment_ratio_type.hpp>
|
||||
|
||||
|
||||
namespace boost { namespace geometry
|
||||
{
|
||||
|
||||
@@ -116,8 +119,12 @@ struct disjoint_linear
|
||||
static inline bool apply(Geometry1 const& geometry1, Geometry2 const& geometry2)
|
||||
{
|
||||
typedef typename geometry::point_type<Geometry1>::type point_type;
|
||||
|
||||
typedef overlay::turn_info<point_type> turn_info;
|
||||
typedef detail::no_rescale_policy rescale_policy_type;
|
||||
typedef overlay::turn_info
|
||||
<
|
||||
point_type,
|
||||
typename segment_ratio_type<point_type, rescale_policy_type>::type
|
||||
> turn_info;
|
||||
std::deque<turn_info> turns;
|
||||
|
||||
static const bool reverse1 = overlay::do_reverse<geometry::point_order<Geometry1>::value>::value; // should be false
|
||||
@@ -127,11 +134,12 @@ struct disjoint_linear
|
||||
// 1) Stop at any intersection
|
||||
// 2) In assignment, include also degenerate points (which are normally skipped)
|
||||
disjoint_interrupt_policy policy;
|
||||
rescale_policy_type robust_policy;
|
||||
geometry::get_turns
|
||||
<
|
||||
reverse1, reverse2,
|
||||
assign_disjoint_policy
|
||||
>(geometry1, geometry2, detail::no_rescale_policy(), turns, policy);
|
||||
>(geometry1, geometry2, robust_policy, turns, policy);
|
||||
|
||||
return !policy.has_intersections;
|
||||
}
|
||||
@@ -144,16 +152,28 @@ struct disjoint_segment
|
||||
{
|
||||
typedef typename point_type<Segment1>::type point_type;
|
||||
|
||||
segment_intersection_points<point_type> is
|
||||
// We don't need to rescale to detect disjointness
|
||||
typedef no_rescale_policy rescale_policy_type;
|
||||
rescale_policy_type robust_policy;
|
||||
|
||||
typedef segment_intersection_points
|
||||
<
|
||||
point_type,
|
||||
typename segment_ratio_type
|
||||
<
|
||||
point_type,
|
||||
rescale_policy_type
|
||||
>::type
|
||||
> intersection_return_type;
|
||||
|
||||
intersection_return_type is
|
||||
= strategy::intersection::relate_cartesian_segments
|
||||
<
|
||||
policies::relate::segments_intersection_points
|
||||
<
|
||||
Segment1,
|
||||
Segment2,
|
||||
segment_intersection_points<point_type>
|
||||
intersection_return_type
|
||||
>
|
||||
>::apply(segment1, segment2);
|
||||
>::apply(segment1, segment2, robust_policy);
|
||||
|
||||
return is.count == 0;
|
||||
}
|
||||
|
||||
@@ -13,6 +13,7 @@
|
||||
#include <boost/geometry/core/coordinate_dimension.hpp>
|
||||
#include <boost/geometry/algorithms/detail/overlay/intersection_insert.hpp>
|
||||
#include <boost/geometry/algorithms/intersects.hpp>
|
||||
#include <boost/geometry/policies/robustness/get_rescale_policy.hpp>
|
||||
|
||||
|
||||
namespace boost { namespace geometry
|
||||
@@ -27,11 +28,15 @@ struct intersection_box_box
|
||||
{
|
||||
template
|
||||
<
|
||||
typename Box1, typename Box2, typename BoxOut,
|
||||
typename Box1, typename Box2,
|
||||
typename RobustPolicy,
|
||||
typename BoxOut,
|
||||
typename Strategy
|
||||
>
|
||||
static inline bool apply(Box1 const& box1,
|
||||
Box2 const& box2, BoxOut& box_out,
|
||||
Box2 const& box2,
|
||||
RobustPolicy const& robust_policy,
|
||||
BoxOut& box_out,
|
||||
Strategy const& strategy)
|
||||
{
|
||||
typedef typename coordinate_type<BoxOut>::type ct;
|
||||
@@ -50,7 +55,7 @@ struct intersection_box_box
|
||||
set<max_corner, Dimension>(box_out, max1 > max2 ? max2 : max1);
|
||||
|
||||
return intersection_box_box<Dimension + 1, DimensionCount>
|
||||
::apply(box1, box2, box_out, strategy);
|
||||
::apply(box1, box2, robust_policy, box_out, strategy);
|
||||
}
|
||||
};
|
||||
|
||||
@@ -59,10 +64,13 @@ struct intersection_box_box<DimensionCount, DimensionCount>
|
||||
{
|
||||
template
|
||||
<
|
||||
typename Box1, typename Box2, typename BoxOut,
|
||||
typename Box1, typename Box2,
|
||||
typename RobustPolicy,
|
||||
typename BoxOut,
|
||||
typename Strategy
|
||||
>
|
||||
static inline bool apply(Box1 const&, Box2 const&, BoxOut&, Strategy const&)
|
||||
static inline bool apply(Box1 const&, Box2 const&,
|
||||
RobustPolicy const&, BoxOut&, Strategy const&)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
@@ -88,9 +96,10 @@ template
|
||||
>
|
||||
struct intersection
|
||||
{
|
||||
template <typename GeometryOut, typename Strategy>
|
||||
template <typename RobustPolicy, typename GeometryOut, typename Strategy>
|
||||
static inline bool apply(Geometry1 const& geometry1,
|
||||
Geometry2 const& geometry2,
|
||||
RobustPolicy const& robust_policy,
|
||||
GeometryOut& geometry_out,
|
||||
Strategy const& strategy)
|
||||
{
|
||||
@@ -100,7 +109,7 @@ struct intersection
|
||||
<
|
||||
Geometry1, Geometry2, OneOut,
|
||||
overlay_intersection
|
||||
>::apply(geometry1, geometry2, std::back_inserter(geometry_out), strategy);
|
||||
>::apply(geometry1, geometry2, robust_policy, std::back_inserter(geometry_out), strategy);
|
||||
|
||||
return true;
|
||||
}
|
||||
@@ -122,10 +131,11 @@ struct intersection
|
||||
>
|
||||
: intersection<Geometry2, Geometry1, Tag2, Tag1, false>
|
||||
{
|
||||
template <typename GeometryOut, typename Strategy>
|
||||
template <typename RobustPolicy, typename GeometryOut, typename Strategy>
|
||||
static inline bool apply(
|
||||
Geometry1 const& g1,
|
||||
Geometry2 const& g2,
|
||||
RobustPolicy const& robust_policy,
|
||||
GeometryOut& out,
|
||||
Strategy const& strategy)
|
||||
{
|
||||
@@ -133,7 +143,7 @@ struct intersection
|
||||
Geometry2, Geometry1,
|
||||
Tag2, Tag1,
|
||||
false
|
||||
>::apply(g2, g1, out, strategy);
|
||||
>::apply(g2, g1, robust_policy, out, strategy);
|
||||
}
|
||||
};
|
||||
|
||||
@@ -186,19 +196,29 @@ inline bool intersection(Geometry1 const& geometry1,
|
||||
concept::check<Geometry1 const>();
|
||||
concept::check<Geometry2 const>();
|
||||
|
||||
typedef typename geometry::rescale_overlay_policy_type
|
||||
<
|
||||
Geometry1,
|
||||
Geometry2
|
||||
>::type rescale_policy_type;
|
||||
|
||||
rescale_policy_type robust_policy
|
||||
= geometry::get_rescale_policy<rescale_policy_type>(geometry1, geometry2);
|
||||
|
||||
typedef strategy_intersection
|
||||
<
|
||||
typename cs_tag<Geometry1>::type,
|
||||
Geometry1,
|
||||
Geometry2,
|
||||
typename geometry::point_type<Geometry1>::type
|
||||
typename geometry::point_type<Geometry1>::type,
|
||||
rescale_policy_type
|
||||
> strategy;
|
||||
|
||||
|
||||
return dispatch::intersection<
|
||||
Geometry1,
|
||||
Geometry2
|
||||
>::apply(geometry1, geometry2, geometry_out, strategy());
|
||||
return dispatch::intersection
|
||||
<
|
||||
Geometry1,
|
||||
Geometry2
|
||||
>::apply(geometry1, geometry2, robust_policy, geometry_out, strategy());
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -19,9 +19,11 @@
|
||||
|
||||
#include <boost/geometry/geometries/concepts/check.hpp>
|
||||
#include <boost/geometry/algorithms/detail/overlay/self_turn_points.hpp>
|
||||
#include <boost/geometry/algorithms/detail/rescale.hpp>
|
||||
#include <boost/geometry/algorithms/disjoint.hpp>
|
||||
|
||||
#include <boost/geometry/policies/robustness/segment_ratio_type.hpp>
|
||||
#include <boost/geometry/policies/robustness/get_rescale_policy.hpp>
|
||||
|
||||
|
||||
namespace boost { namespace geometry
|
||||
{
|
||||
@@ -44,31 +46,40 @@ inline bool intersects(Geometry const& geometry)
|
||||
{
|
||||
concept::check<Geometry const>();
|
||||
|
||||
typedef typename geometry::point_type<Geometry>::type point_type;
|
||||
typedef typename rescale_policy_type<point_type>::type
|
||||
rescale_policy_type;
|
||||
|
||||
typedef detail::overlay::turn_info
|
||||
<
|
||||
typename geometry::point_type<Geometry>::type
|
||||
point_type,
|
||||
typename segment_ratio_type<point_type, rescale_policy_type>::type
|
||||
> turn_info;
|
||||
std::deque<turn_info> turns;
|
||||
|
||||
typedef typename strategy_intersection
|
||||
<
|
||||
typename cs_tag<Geometry>::type,
|
||||
Geometry,
|
||||
Geometry,
|
||||
typename geometry::point_type<Geometry>::type
|
||||
>::segment_intersection_strategy_type segment_intersection_strategy_type;
|
||||
std::deque<turn_info> turns;
|
||||
|
||||
typedef detail::overlay::get_turn_info
|
||||
<
|
||||
detail::overlay::assign_null_policy
|
||||
> TurnPolicy;
|
||||
|
||||
typedef typename strategy_intersection
|
||||
<
|
||||
typename cs_tag<Geometry>::type,
|
||||
Geometry,
|
||||
Geometry,
|
||||
point_type,
|
||||
rescale_policy_type
|
||||
>::segment_intersection_strategy_type segment_intersection_strategy_type;
|
||||
|
||||
rescale_policy_type robust_policy
|
||||
= geometry::get_rescale_policy<rescale_policy_type>(geometry);
|
||||
|
||||
detail::disjoint::disjoint_interrupt_policy policy;
|
||||
detail::self_get_turn_points::get_turns
|
||||
<
|
||||
TurnPolicy
|
||||
>::apply(geometry, detail::no_rescale_policy(), turns, policy);
|
||||
>::apply(geometry, robust_policy, turns, policy);
|
||||
return policy.has_intersections;
|
||||
}
|
||||
|
||||
|
||||
@@ -315,13 +315,13 @@ inline bool calculate_point_on_surface(Geometry const& geometry, Point& point)
|
||||
|
||||
|
||||
/*!
|
||||
\brief Returns point guaranteed to lie on the surface
|
||||
\brief Assigns a Point guaranteed to lie on the surface of the Geometry
|
||||
\tparam Geometry geometry type. This also defines the type of the output point
|
||||
\param point to assign
|
||||
\param geometry geometry to take point from
|
||||
\param geometry Geometry to take point from
|
||||
\param point Point to assign
|
||||
*/
|
||||
template <typename Geometry, typename Point>
|
||||
inline void point_on_surface(Geometry const& geometry, Point& point)
|
||||
inline void point_on_surface(Geometry const& geometry, Point & point)
|
||||
{
|
||||
concept::check<Point>();
|
||||
concept::check<Geometry const>();
|
||||
@@ -334,12 +334,18 @@ inline void point_on_surface(Geometry const& geometry, Point& point)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*!
|
||||
\brief Returns point guaranteed to lie on the surface of the Geometry
|
||||
\tparam Geometry geometry type. This also defines the type of the output point
|
||||
\param geometry Geometry to take point from
|
||||
\return The Point guaranteed to lie on the surface of the Geometry
|
||||
*/
|
||||
template<typename Geometry>
|
||||
inline typename geometry::point_type<Geometry>::type return_point_on_surface(Geometry const& geometry)
|
||||
inline typename geometry::point_type<Geometry>::type
|
||||
return_point_on_surface(Geometry const& geometry)
|
||||
{
|
||||
typename geometry::point_type<Geometry>::type result;
|
||||
point_on_surface(geometry, result);
|
||||
geometry::point_on_surface(geometry, result);
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
@@ -69,7 +69,7 @@ struct range_remove_spikes
|
||||
std::size_t const min_num_points = core_detail::closure::minimum_ring_size
|
||||
<
|
||||
geometry::closure<Range>::value
|
||||
>::value;
|
||||
>::value - 1; // subtract one: a polygon with only one spike should result into one point
|
||||
if (n < min_num_points)
|
||||
{
|
||||
return;
|
||||
@@ -104,13 +104,13 @@ struct range_remove_spikes
|
||||
found = false;
|
||||
// Check for spike in first point
|
||||
int const penultimate = 2;
|
||||
while(cleaned.size() > 3 && detail::point_is_spike_or_equal(cleaned.front(), *(cleaned.end() - penultimate), cleaned.back()))
|
||||
while(cleaned.size() >= 3 && detail::point_is_spike_or_equal(cleaned.front(), *(cleaned.end() - penultimate), cleaned.back()))
|
||||
{
|
||||
cleaned.pop_back();
|
||||
found = true;
|
||||
}
|
||||
// Check for spike in second point
|
||||
while(cleaned.size() > 3 && detail::point_is_spike_or_equal(*(cleaned.begin() + 1), cleaned.back(), cleaned.front()))
|
||||
while(cleaned.size() >= 3 && detail::point_is_spike_or_equal(*(cleaned.begin() + 1), cleaned.back(), cleaned.front()))
|
||||
{
|
||||
cleaned.pop_front();
|
||||
found = true;
|
||||
@@ -118,6 +118,13 @@ struct range_remove_spikes
|
||||
}
|
||||
while (found);
|
||||
|
||||
if (cleaned.size() == 2)
|
||||
{
|
||||
// Ticket #9871: open polygon with only two points.
|
||||
// the second point forms, by definition, a spike
|
||||
cleaned.pop_back();
|
||||
}
|
||||
|
||||
// Close if necessary
|
||||
if (geometry::closure<Range>::value == geometry::closed)
|
||||
{
|
||||
|
||||
@@ -46,11 +46,14 @@ template
|
||||
typename GeometryOut,
|
||||
typename Geometry1,
|
||||
typename Geometry2,
|
||||
typename RobustPolicy,
|
||||
typename OutputIterator,
|
||||
typename Strategy
|
||||
>
|
||||
inline OutputIterator sym_difference_insert(Geometry1 const& geometry1,
|
||||
Geometry2 const& geometry2, OutputIterator out,
|
||||
Geometry2 const& geometry2,
|
||||
RobustPolicy const& robust_policy,
|
||||
OutputIterator out,
|
||||
Strategy const& strategy)
|
||||
{
|
||||
concept::check<Geometry1 const>();
|
||||
@@ -64,7 +67,7 @@ inline OutputIterator sym_difference_insert(Geometry1 const& geometry1,
|
||||
overlay_difference,
|
||||
geometry::detail::overlay::do_reverse<geometry::point_order<Geometry1>::value>::value,
|
||||
geometry::detail::overlay::do_reverse<geometry::point_order<Geometry2>::value, true>::value
|
||||
>::apply(geometry1, geometry2, out, strategy);
|
||||
>::apply(geometry1, geometry2, robust_policy, out, strategy);
|
||||
out = geometry::dispatch::intersection_insert
|
||||
<
|
||||
Geometry2, Geometry1,
|
||||
@@ -73,7 +76,7 @@ inline OutputIterator sym_difference_insert(Geometry1 const& geometry1,
|
||||
geometry::detail::overlay::do_reverse<geometry::point_order<Geometry2>::value>::value,
|
||||
geometry::detail::overlay::do_reverse<geometry::point_order<Geometry1>::value, true>::value,
|
||||
geometry::detail::overlay::do_reverse<geometry::point_order<GeometryOut>::value>::value
|
||||
>::apply(geometry2, geometry1, out, strategy);
|
||||
>::apply(geometry2, geometry1, robust_policy, out, strategy);
|
||||
return out;
|
||||
}
|
||||
|
||||
@@ -97,10 +100,12 @@ template
|
||||
typename GeometryOut,
|
||||
typename Geometry1,
|
||||
typename Geometry2,
|
||||
typename RobustPolicy,
|
||||
typename OutputIterator
|
||||
>
|
||||
inline OutputIterator sym_difference_insert(Geometry1 const& geometry1,
|
||||
Geometry2 const& geometry2, OutputIterator out)
|
||||
Geometry2 const& geometry2,
|
||||
RobustPolicy const& robust_policy, OutputIterator out)
|
||||
{
|
||||
concept::check<Geometry1 const>();
|
||||
concept::check<Geometry2 const>();
|
||||
@@ -111,10 +116,11 @@ inline OutputIterator sym_difference_insert(Geometry1 const& geometry1,
|
||||
typename cs_tag<GeometryOut>::type,
|
||||
Geometry1,
|
||||
Geometry2,
|
||||
typename geometry::point_type<GeometryOut>::type
|
||||
typename geometry::point_type<GeometryOut>::type,
|
||||
RobustPolicy
|
||||
> strategy_type;
|
||||
|
||||
return sym_difference_insert<GeometryOut>(geometry1, geometry2, out, strategy_type());
|
||||
return sym_difference_insert<GeometryOut>(geometry1, geometry2, robust_policy, out, strategy_type());
|
||||
}
|
||||
|
||||
}} // namespace detail::sym_difference
|
||||
@@ -150,8 +156,17 @@ inline void sym_difference(Geometry1 const& geometry1,
|
||||
typedef typename boost::range_value<Collection>::type geometry_out;
|
||||
concept::check<geometry_out>();
|
||||
|
||||
typedef typename geometry::rescale_overlay_policy_type
|
||||
<
|
||||
Geometry1,
|
||||
Geometry2
|
||||
>::type rescale_policy_type;
|
||||
|
||||
rescale_policy_type robust_policy
|
||||
= geometry::get_rescale_policy<rescale_policy_type>(geometry1, geometry2);
|
||||
|
||||
detail::sym_difference::sym_difference_insert<geometry_out>(
|
||||
geometry1, geometry2,
|
||||
geometry1, geometry2, robust_policy,
|
||||
std::back_inserter(output_collection));
|
||||
}
|
||||
|
||||
|
||||
@@ -5,8 +5,8 @@
|
||||
// Copyright (c) 2009-2012 Mateusz Loskot, London, UK.
|
||||
// Copyright (c) 2013 Adam Wulkiewicz, Lodz, Poland.
|
||||
|
||||
// This file was modified by Oracle on 2013.
|
||||
// Modifications copyright (c) 2013, Oracle and/or its affiliates.
|
||||
// This file was modified by Oracle on 2013, 2014.
|
||||
// Modifications copyright (c) 2013, 2014, Oracle and/or its affiliates.
|
||||
|
||||
// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library
|
||||
// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands.
|
||||
@@ -15,6 +15,8 @@
|
||||
// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
|
||||
// http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
|
||||
|
||||
#ifndef BOOST_GEOMETRY_ALGORITHMS_TOUCHES_HPP
|
||||
#define BOOST_GEOMETRY_ALGORITHMS_TOUCHES_HPP
|
||||
|
||||
@@ -29,10 +31,13 @@
|
||||
#include <boost/geometry/algorithms/intersects.hpp>
|
||||
#include <boost/geometry/algorithms/num_geometries.hpp>
|
||||
#include <boost/geometry/algorithms/detail/sub_range.hpp>
|
||||
#include <boost/geometry/policies/robustness/no_rescale_policy.hpp>
|
||||
#include <boost/variant/static_visitor.hpp>
|
||||
#include <boost/variant/apply_visitor.hpp>
|
||||
#include <boost/variant/variant_fwd.hpp>
|
||||
|
||||
#include <boost/geometry/algorithms/detail/relate/relate.hpp>
|
||||
|
||||
namespace boost { namespace geometry
|
||||
{
|
||||
|
||||
@@ -40,6 +45,86 @@ namespace boost { namespace geometry
|
||||
namespace detail { namespace touches
|
||||
{
|
||||
|
||||
// Box/Box
|
||||
|
||||
template
|
||||
<
|
||||
std::size_t Dimension,
|
||||
std::size_t DimensionCount
|
||||
>
|
||||
struct box_box_loop
|
||||
{
|
||||
template <typename Box1, typename Box2>
|
||||
static inline bool apply(Box1 const& b1, Box2 const& b2, bool & touch)
|
||||
{
|
||||
typedef typename coordinate_type<Box1>::type coordinate_type1;
|
||||
typedef typename coordinate_type<Box2>::type coordinate_type2;
|
||||
|
||||
coordinate_type1 const& min1 = get<min_corner, Dimension>(b1);
|
||||
coordinate_type1 const& max1 = get<max_corner, Dimension>(b1);
|
||||
coordinate_type2 const& min2 = get<min_corner, Dimension>(b2);
|
||||
coordinate_type2 const& max2 = get<max_corner, Dimension>(b2);
|
||||
|
||||
// TODO assert or exception?
|
||||
//BOOST_ASSERT(min1 <= max1 && min2 <= max2);
|
||||
|
||||
if ( max1 < min2 || max2 < min1 )
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if ( max1 == min2 || max2 == min1 )
|
||||
{
|
||||
touch = true;
|
||||
}
|
||||
|
||||
return box_box_loop
|
||||
<
|
||||
Dimension + 1,
|
||||
DimensionCount
|
||||
>::apply(b1, b2, touch);
|
||||
}
|
||||
};
|
||||
|
||||
template
|
||||
<
|
||||
std::size_t DimensionCount
|
||||
>
|
||||
struct box_box_loop<DimensionCount, DimensionCount>
|
||||
{
|
||||
template <typename Box1, typename Box2>
|
||||
static inline bool apply(Box1 const& , Box2 const&, bool &)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
struct box_box
|
||||
{
|
||||
template <typename Box1, typename Box2>
|
||||
static inline bool apply(Box1 const& b1, Box2 const& b2)
|
||||
{
|
||||
BOOST_STATIC_ASSERT((boost::is_same
|
||||
<
|
||||
typename geometry::coordinate_system<Box1>::type,
|
||||
typename geometry::coordinate_system<Box2>::type
|
||||
>::value
|
||||
));
|
||||
assert_dimension_equal<Box1, Box2>();
|
||||
|
||||
bool touches = false;
|
||||
bool ok = box_box_loop
|
||||
<
|
||||
0,
|
||||
dimension<Box1>::type::value
|
||||
>::apply(b1, b2, touches);
|
||||
|
||||
return ok && touches;
|
||||
}
|
||||
};
|
||||
|
||||
// Areal/Areal
|
||||
|
||||
struct areal_interrupt_policy
|
||||
{
|
||||
static bool const enabled = true;
|
||||
@@ -117,134 +202,6 @@ struct areal_interrupt_policy
|
||||
}
|
||||
};
|
||||
|
||||
template <typename Linear>
|
||||
struct linear_areal_interrupt_policy
|
||||
{
|
||||
static bool const enabled = true;
|
||||
bool found_touch;
|
||||
bool found_not_touch;
|
||||
|
||||
Linear const& linear;
|
||||
|
||||
// dummy variable required by self_get_turn_points::get_turns
|
||||
static bool const has_intersections = false;
|
||||
|
||||
inline bool result()
|
||||
{
|
||||
return found_touch && !found_not_touch;
|
||||
}
|
||||
|
||||
inline linear_areal_interrupt_policy(Linear const& l)
|
||||
: found_touch(false), found_not_touch(false), linear(l)
|
||||
{}
|
||||
|
||||
template <typename Range>
|
||||
inline bool apply(Range const& range)
|
||||
{
|
||||
// if already rejected (temp workaround?)
|
||||
if ( found_not_touch )
|
||||
return true;
|
||||
|
||||
typedef typename boost::range_iterator<Range const>::type iterator;
|
||||
for ( iterator it = boost::begin(range) ; it != boost::end(range) ; ++it )
|
||||
{
|
||||
if ( it->operations[0].operation == overlay::operation_intersection )
|
||||
{
|
||||
if ( it->operations[1].operation == overlay::operation_union &&
|
||||
is_turn_on_last_point(*it) )
|
||||
{
|
||||
found_touch = true;
|
||||
continue;
|
||||
}
|
||||
else
|
||||
{
|
||||
found_not_touch = true;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
switch(it->method)
|
||||
{
|
||||
case overlay::method_crosses:
|
||||
found_not_touch = true;
|
||||
return true;
|
||||
case overlay::method_equal:
|
||||
case overlay::method_touch:
|
||||
case overlay::method_touch_interior:
|
||||
case overlay::method_collinear:
|
||||
if ( ok_for_touch(*it) )
|
||||
{
|
||||
found_touch = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
found_not_touch = true;
|
||||
return true;
|
||||
}
|
||||
break;
|
||||
case overlay::method_none :
|
||||
case overlay::method_disjoint :
|
||||
case overlay::method_error :
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
template <typename Turn>
|
||||
inline bool ok_for_touch(Turn const& turn)
|
||||
{
|
||||
return turn.both(overlay::operation_union)
|
||||
|| turn.both(overlay::operation_blocked)
|
||||
|| turn.combination(overlay::operation_union, overlay::operation_blocked)
|
||||
|
||||
|| turn.both(overlay::operation_continue)
|
||||
|| turn.combination(overlay::operation_union, overlay::operation_intersection)
|
||||
;
|
||||
}
|
||||
|
||||
template <typename Turn>
|
||||
inline bool is_turn_on_last_point(Turn const& turn)
|
||||
{
|
||||
typename sub_range_return_type<Linear const>::type
|
||||
g = sub_range(linear, turn.operations[0].seg_id);
|
||||
|
||||
std::size_t s = boost::size(g);
|
||||
|
||||
if ( s == 0 )
|
||||
return false; // shouldn't return here
|
||||
else if ( s == 1 )
|
||||
return equals::equals_point_point(turn.point, *boost::begin(g)); // nor here
|
||||
else
|
||||
return equals::equals_point_point(turn.point, *(boost::end(g)-1));
|
||||
}
|
||||
};
|
||||
|
||||
template <std::size_t Max>
|
||||
struct turns_count_interrupt_policy
|
||||
{
|
||||
static bool const enabled = true;
|
||||
std::size_t turns_count;
|
||||
|
||||
// dummy variable required by self_get_turn_points::get_turns
|
||||
static bool const has_intersections = false;
|
||||
|
||||
inline turns_count_interrupt_policy()
|
||||
: turns_count(0)
|
||||
{}
|
||||
|
||||
template <typename Range>
|
||||
inline bool apply(Range const& range)
|
||||
{
|
||||
turns_count += boost::size(range);
|
||||
if ( Max < turns_count )
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
template<typename Geometry>
|
||||
struct check_each_ring_for_within
|
||||
{
|
||||
@@ -261,16 +218,13 @@ struct check_each_ring_for_within
|
||||
{
|
||||
typename geometry::point_type<Range>::type p;
|
||||
geometry::point_on_border(p, range);
|
||||
if (geometry::within(p, m_geometry))
|
||||
if ( !has_within && geometry::within(p, m_geometry) )
|
||||
{
|
||||
has_within = true;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
// TODO: currently this function checks if a point of at least one range from g2 is within g1
|
||||
// shouldn't it check the opposite?
|
||||
|
||||
template <typename FirstGeometry, typename SecondGeometry>
|
||||
inline bool rings_containing(FirstGeometry const& geometry1,
|
||||
SecondGeometry const& geometry2)
|
||||
@@ -286,9 +240,12 @@ struct areal_areal
|
||||
static inline
|
||||
bool apply(Geometry1 const& geometry1, Geometry2 const& geometry2)
|
||||
{
|
||||
typedef detail::no_rescale_policy rescale_policy_type;
|
||||
typedef typename geometry::point_type<Geometry1>::type point_type;
|
||||
typedef detail::overlay::turn_info
|
||||
<
|
||||
typename geometry::point_type<Geometry1>::type
|
||||
point_type,
|
||||
typename segment_ratio_type<point_type, rescale_policy_type>::type
|
||||
> turn_info;
|
||||
|
||||
typedef detail::overlay::get_turn_info
|
||||
@@ -298,12 +255,13 @@ struct areal_areal
|
||||
|
||||
std::deque<turn_info> turns;
|
||||
detail::touches::areal_interrupt_policy policy;
|
||||
rescale_policy_type robust_policy;
|
||||
boost::geometry::get_turns
|
||||
<
|
||||
detail::overlay::do_reverse<geometry::point_order<Geometry1>::value>::value,
|
||||
detail::overlay::do_reverse<geometry::point_order<Geometry2>::value>::value,
|
||||
detail::overlay::assign_null_policy
|
||||
>(geometry1, geometry2, detail::no_rescale_policy(), turns, policy);
|
||||
>(geometry1, geometry2, robust_policy, turns, policy);
|
||||
|
||||
return policy.result()
|
||||
&& ! geometry::detail::touches::rings_containing(geometry1, geometry2)
|
||||
@@ -311,99 +269,17 @@ struct areal_areal
|
||||
}
|
||||
};
|
||||
|
||||
template <typename Geometry1, typename Geometry2>
|
||||
struct linear_areal
|
||||
// P/*
|
||||
|
||||
struct use_point_in_geometry
|
||||
{
|
||||
static inline
|
||||
bool apply(Geometry1 const& geometry1, Geometry2 const& geometry2)
|
||||
{
|
||||
typedef detail::overlay::turn_info
|
||||
<
|
||||
typename geometry::point_type<Geometry1>::type
|
||||
> turn_info;
|
||||
|
||||
typedef detail::overlay::get_turn_info
|
||||
<
|
||||
detail::overlay::assign_null_policy
|
||||
> policy_type;
|
||||
|
||||
std::deque<turn_info> turns;
|
||||
detail::touches::linear_areal_interrupt_policy<Geometry1> policy(geometry1);
|
||||
boost::geometry::get_turns
|
||||
<
|
||||
detail::overlay::do_reverse<geometry::point_order<Geometry1>::value>::value,
|
||||
detail::overlay::do_reverse<geometry::point_order<Geometry2>::value>::value,
|
||||
detail::overlay::assign_null_policy
|
||||
>(geometry1, geometry2, detail::no_rescale_policy(), turns, policy);
|
||||
|
||||
return policy.result()
|
||||
&& ! geometry::detail::touches::rings_containing(geometry2, geometry1);
|
||||
}
|
||||
};
|
||||
|
||||
template <typename Point, typename Geometry>
|
||||
struct point_geometry
|
||||
{
|
||||
static inline
|
||||
bool apply(Point const& point, Geometry const& geometry)
|
||||
template <typename Point, typename Geometry>
|
||||
static inline bool apply(Point const& point, Geometry const& geometry)
|
||||
{
|
||||
return detail::within::point_in_geometry(point, geometry) == 0;
|
||||
}
|
||||
};
|
||||
|
||||
template <typename Geometry1, typename Geometry2>
|
||||
struct linestring_linestring
|
||||
{
|
||||
static inline
|
||||
bool apply(Geometry1 const& geometry1, Geometry2 const& geometry2)
|
||||
{
|
||||
std::size_t s1 = boost::size(geometry1);
|
||||
std::size_t s2 = boost::size(geometry2);
|
||||
// TODO: throw on empty input?
|
||||
if ( s1 == 0 || s2 == 0 )
|
||||
return false;
|
||||
|
||||
typedef detail::overlay::turn_info
|
||||
<
|
||||
typename geometry::point_type<Geometry1>::type
|
||||
> turn_info;
|
||||
|
||||
typedef detail::overlay::get_turn_info
|
||||
<
|
||||
detail::overlay::assign_null_policy
|
||||
> policy_type;
|
||||
|
||||
std::deque<turn_info> turns;
|
||||
turns_count_interrupt_policy<2> policy;
|
||||
boost::geometry::get_turns
|
||||
<
|
||||
detail::overlay::do_reverse<geometry::point_order<Geometry1>::value>::value,
|
||||
detail::overlay::do_reverse<geometry::point_order<Geometry2>::value>::value,
|
||||
detail::overlay::assign_null_policy
|
||||
>(geometry1, geometry2, detail::no_rescale_policy(), turns, policy);
|
||||
|
||||
if ( 2 < policy.turns_count )
|
||||
return false;
|
||||
else if ( 2 == policy.turns_count )
|
||||
{
|
||||
return ( detail::equals::equals_point_point(turns[0].point, *(boost::end(geometry1)-1))
|
||||
&& detail::equals::equals_point_point(turns[1].point, *(boost::end(geometry2)-1)) )
|
||||
|| ( detail::equals::equals_point_point(turns[0].point, *(boost::end(geometry2)-1))
|
||||
&& detail::equals::equals_point_point(turns[1].point, *(boost::end(geometry1)-1)) );
|
||||
}
|
||||
else if ( 1 == policy.turns_count )
|
||||
{
|
||||
return detail::equals::equals_point_point(turns[0].point, *(boost::end(geometry1)-1))
|
||||
|| detail::equals::equals_point_point(turns[0].point, *(boost::end(geometry2)-1));
|
||||
}
|
||||
else
|
||||
{
|
||||
return detail::within::point_in_geometry(*boost::begin(geometry1), geometry2) >= 0
|
||||
|| detail::within::point_in_geometry(*boost::begin(geometry2), geometry1) >= 0;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
}}
|
||||
#endif // DOXYGEN_NO_DETAIL
|
||||
|
||||
@@ -417,11 +293,12 @@ template
|
||||
typename Geometry1, typename Geometry2,
|
||||
typename Tag1 = typename tag<Geometry1>::type,
|
||||
typename Tag2 = typename tag<Geometry2>::type,
|
||||
typename CastedTag1 = typename tag_cast<Tag1, point_tag, linear_tag, areal_tag>::type,
|
||||
typename CastedTag2 = typename tag_cast<Tag2, point_tag, linear_tag, areal_tag>::type,
|
||||
typename CastedTag1 = typename tag_cast<Tag1, pointlike_tag, linear_tag, areal_tag>::type,
|
||||
typename CastedTag2 = typename tag_cast<Tag2, pointlike_tag, linear_tag, areal_tag>::type,
|
||||
bool Reverse = reverse_dispatch<Geometry1, Geometry2>::type::value
|
||||
>
|
||||
struct touches : not_implemented<Tag1, Tag2>
|
||||
struct touches
|
||||
: not_implemented<Tag1, Tag2>
|
||||
{};
|
||||
|
||||
// If reversal is needed, perform it
|
||||
@@ -440,10 +317,10 @@ struct touches<Geometry1, Geometry2, Tag1, Tag2, CastedTag1, CastedTag2, true>
|
||||
}
|
||||
};
|
||||
|
||||
// touches(Pt, Pt), touches(Pt, MPt), touches(MPt, MPt)
|
||||
// P/P
|
||||
|
||||
template <typename Geometry1, typename Geometry2, typename Tag1, typename Tag2>
|
||||
struct touches<Geometry1, Geometry2, Tag1, Tag2, point_tag, point_tag, false>
|
||||
: detail::touches::point_geometry<Geometry1, Geometry2>
|
||||
struct touches<Geometry1, Geometry2, Tag1, Tag2, pointlike_tag, pointlike_tag, false>
|
||||
{
|
||||
static inline bool apply(Geometry1 const& , Geometry2 const& )
|
||||
{
|
||||
@@ -451,38 +328,64 @@ struct touches<Geometry1, Geometry2, Tag1, Tag2, point_tag, point_tag, false>
|
||||
}
|
||||
};
|
||||
|
||||
// touches(Point, Linear), touches(Point, Areal)
|
||||
// P/*
|
||||
|
||||
template <typename Point, typename Geometry, typename Tag2, typename CastedTag2>
|
||||
struct touches<Point, Geometry, point_tag, Tag2, point_tag, CastedTag2, false>
|
||||
: detail::touches::point_geometry<Point, Geometry>
|
||||
struct touches<Point, Geometry, point_tag, Tag2, pointlike_tag, CastedTag2, false>
|
||||
: detail::touches::use_point_in_geometry
|
||||
{};
|
||||
|
||||
// TODO: support touches(MPt, Linear/Areal)
|
||||
|
||||
// touches(Linestring, Linestring)
|
||||
template <typename Linestring1, typename Linestring2>
|
||||
struct touches<Linestring1, Linestring2, linestring_tag, linestring_tag, linear_tag, linear_tag, false>
|
||||
: detail::touches::linestring_linestring<Linestring1, Linestring2>
|
||||
// Box/Box
|
||||
|
||||
template <typename Box1, typename Box2, typename CastedTag1, typename CastedTag2>
|
||||
struct touches<Box1, Box2, box_tag, box_tag, CastedTag1, CastedTag2, false>
|
||||
: detail::touches::box_box
|
||||
{};
|
||||
|
||||
// TODO: support touches(MLs, MLs) and touches(Ls, MLs)
|
||||
template <typename Box1, typename Box2>
|
||||
struct touches<Box1, Box2, box_tag, box_tag, areal_tag, areal_tag, false>
|
||||
: detail::touches::box_box
|
||||
{};
|
||||
|
||||
// L/L
|
||||
|
||||
template <typename Linear1, typename Linear2, typename Tag1, typename Tag2>
|
||||
struct touches<Linear1, Linear2, Tag1, Tag2, linear_tag, linear_tag, false>
|
||||
: detail::relate::relate_base
|
||||
<
|
||||
detail::relate::static_mask_touches_type,
|
||||
Linear1,
|
||||
Linear2
|
||||
>
|
||||
{};
|
||||
|
||||
// L/A
|
||||
|
||||
// touches(Linear, Areal)
|
||||
template <typename Linear, typename Areal, typename Tag1, typename Tag2>
|
||||
struct touches<Linear, Areal, Tag1, Tag2, linear_tag, areal_tag, false>
|
||||
: detail::touches::linear_areal<Linear, Areal>
|
||||
: detail::relate::relate_base
|
||||
<
|
||||
detail::relate::static_mask_touches_type,
|
||||
Linear,
|
||||
Areal
|
||||
>
|
||||
{};
|
||||
// e.g. for touches(Poly, MLs)
|
||||
template <typename Areal, typename Linear, typename Tag1, typename Tag2>
|
||||
struct touches<Areal, Linear, Tag1, Tag2, areal_tag, linear_tag, false>
|
||||
{
|
||||
static inline bool apply(Areal const& areal, Linear const& linear)
|
||||
{
|
||||
return detail::touches::linear_areal<Linear, Areal>::apply(linear, areal);
|
||||
}
|
||||
};
|
||||
|
||||
// touches(Areal, Areal)
|
||||
// A/L
|
||||
template <typename Linear, typename Areal, typename Tag1, typename Tag2>
|
||||
struct touches<Linear, Areal, Tag1, Tag2, linear_tag, areal_tag, true>
|
||||
: detail::relate::relate_base
|
||||
<
|
||||
detail::relate::static_mask_touches_type,
|
||||
Areal,
|
||||
Linear
|
||||
>
|
||||
{};
|
||||
|
||||
// A/A
|
||||
|
||||
template <typename Areal1, typename Areal2, typename Tag1, typename Tag2>
|
||||
struct touches<Areal1, Areal2, Tag1, Tag2, areal_tag, areal_tag, false>
|
||||
: detail::touches::areal_areal<Areal1, Areal2>
|
||||
@@ -585,10 +488,13 @@ struct self_touches
|
||||
{
|
||||
concept::check<Geometry const>();
|
||||
|
||||
typedef detail::no_rescale_policy rescale_policy_type;
|
||||
typedef typename geometry::point_type<Geometry>::type point_type;
|
||||
typedef detail::overlay::turn_info
|
||||
<
|
||||
typename geometry::point_type<Geometry>::type
|
||||
> turn_info;
|
||||
<
|
||||
point_type,
|
||||
typename segment_ratio_type<point_type, rescale_policy_type>::type
|
||||
> turn_info;
|
||||
|
||||
typedef detail::overlay::get_turn_info
|
||||
<
|
||||
@@ -597,10 +503,11 @@ struct self_touches
|
||||
|
||||
std::deque<turn_info> turns;
|
||||
detail::touches::areal_interrupt_policy policy;
|
||||
rescale_policy_type robust_policy;
|
||||
detail::self_get_turn_points::get_turns
|
||||
<
|
||||
policy_type
|
||||
>::apply(geometry, detail::no_rescale_policy(), turns, policy);
|
||||
>::apply(geometry, robust_policy, turns, policy);
|
||||
|
||||
return policy.result();
|
||||
}
|
||||
|
||||
@@ -23,6 +23,7 @@
|
||||
#include <boost/geometry/geometries/concepts/check.hpp>
|
||||
#include <boost/geometry/algorithms/not_implemented.hpp>
|
||||
#include <boost/geometry/algorithms/detail/overlay/overlay.hpp>
|
||||
#include <boost/geometry/policies/robustness/get_rescale_policy.hpp>
|
||||
|
||||
#include <boost/geometry/algorithms/detail/overlay/linear_linear.hpp>
|
||||
#include <boost/geometry/algorithms/detail/overlay/pointlike_pointlike.hpp>
|
||||
@@ -71,15 +72,17 @@ struct union_insert
|
||||
true
|
||||
>: union_insert<Geometry2, Geometry1, GeometryOut>
|
||||
{
|
||||
template <typename OutputIterator, typename Strategy>
|
||||
template <typename RobustPolicy, typename OutputIterator, typename Strategy>
|
||||
static inline OutputIterator apply(Geometry1 const& g1,
|
||||
Geometry2 const& g2, OutputIterator out,
|
||||
Geometry2 const& g2,
|
||||
RobustPolicy const& robust_policy,
|
||||
OutputIterator out,
|
||||
Strategy const& strategy)
|
||||
{
|
||||
return union_insert
|
||||
<
|
||||
Geometry2, Geometry1, GeometryOut
|
||||
>::apply(g2, g1, out, strategy);
|
||||
>::apply(g2, g1, robust_policy, out, strategy);
|
||||
}
|
||||
};
|
||||
|
||||
@@ -180,18 +183,20 @@ template
|
||||
<
|
||||
typename GeometryOut,
|
||||
typename Geometry1, typename Geometry2,
|
||||
typename RobustPolicy,
|
||||
typename OutputIterator,
|
||||
typename Strategy
|
||||
>
|
||||
inline OutputIterator insert(Geometry1 const& geometry1,
|
||||
Geometry2 const& geometry2,
|
||||
RobustPolicy const& robust_policy,
|
||||
OutputIterator out,
|
||||
Strategy const& strategy)
|
||||
{
|
||||
return dispatch::union_insert
|
||||
<
|
||||
Geometry1, Geometry2, GeometryOut
|
||||
>::apply(geometry1, geometry2, out, strategy);
|
||||
>::apply(geometry1, geometry2, robust_policy, out, strategy);
|
||||
}
|
||||
|
||||
/*!
|
||||
@@ -229,7 +234,11 @@ inline OutputIterator union_insert(Geometry1 const& geometry1,
|
||||
concept::check<Geometry2 const>();
|
||||
concept::check<GeometryOut>();
|
||||
|
||||
return detail::union_::insert<GeometryOut>(geometry1, geometry2, out, strategy);
|
||||
typedef typename Strategy::rescale_policy_type rescale_policy_type;
|
||||
rescale_policy_type robust_policy
|
||||
= geometry::get_rescale_policy<rescale_policy_type>(geometry1, geometry2);
|
||||
|
||||
return detail::union_::insert<GeometryOut>(geometry1, geometry2, robust_policy, out, strategy);
|
||||
}
|
||||
|
||||
/*!
|
||||
@@ -261,12 +270,19 @@ inline OutputIterator union_insert(Geometry1 const& geometry1,
|
||||
concept::check<Geometry2 const>();
|
||||
concept::check<GeometryOut>();
|
||||
|
||||
typedef typename geometry::rescale_overlay_policy_type
|
||||
<
|
||||
Geometry1,
|
||||
Geometry2
|
||||
>::type rescale_policy_type;
|
||||
|
||||
typedef strategy_intersection
|
||||
<
|
||||
typename cs_tag<GeometryOut>::type,
|
||||
Geometry1,
|
||||
Geometry2,
|
||||
typename geometry::point_type<GeometryOut>::type
|
||||
typename geometry::point_type<GeometryOut>::type,
|
||||
rescale_policy_type
|
||||
> strategy;
|
||||
|
||||
return union_insert<GeometryOut>(geometry1, geometry2, out, strategy());
|
||||
|
||||
@@ -14,7 +14,6 @@
|
||||
#ifndef BOOST_GEOMETRY_CORE_TAG_HPP
|
||||
#define BOOST_GEOMETRY_CORE_TAG_HPP
|
||||
|
||||
|
||||
#include <boost/mpl/assert.hpp>
|
||||
|
||||
#include <boost/geometry/core/tags.hpp>
|
||||
|
||||
@@ -447,7 +447,8 @@ template
|
||||
typename OutputIterator,
|
||||
typename DistanceStrategy,
|
||||
typename JoinStrategy,
|
||||
typename EndStrategy
|
||||
typename EndStrategy,
|
||||
typename RobustPolicy
|
||||
#ifdef BOOST_GEOMETRY_DEBUG_WITH_MAPPER
|
||||
, typename Mapper
|
||||
#endif
|
||||
@@ -455,7 +456,8 @@ template
|
||||
inline void buffer_inserter(GeometryInput const& geometry_input, OutputIterator out,
|
||||
DistanceStrategy const& distance_strategy,
|
||||
JoinStrategy const& join_strategy,
|
||||
EndStrategy const& end_strategy
|
||||
EndStrategy const& end_strategy,
|
||||
RobustPolicy const& robust_policy
|
||||
#ifdef BOOST_GEOMETRY_DEBUG_WITH_MAPPER
|
||||
, Mapper& mapper
|
||||
#endif
|
||||
@@ -467,8 +469,9 @@ inline void buffer_inserter(GeometryInput const& geometry_input, OutputIterator
|
||||
detail::buffer::buffered_piece_collection
|
||||
#endif
|
||||
<
|
||||
typename geometry::ring_type<GeometryOutput>::type
|
||||
> collection;
|
||||
typename geometry::ring_type<GeometryOutput>::type,
|
||||
RobustPolicy
|
||||
> collection(robust_policy);
|
||||
|
||||
dispatch::buffer_inserter
|
||||
<
|
||||
@@ -495,7 +498,7 @@ inline void buffer_inserter(GeometryInput const& geometry_input, OutputIterator
|
||||
|
||||
#ifdef BOOST_GEOMETRY_DEBUG_WITH_MAPPER
|
||||
//collection.map_turns(mapper);
|
||||
collection.map_pieces<geometry::polygon_tag>(mapper); //, false, true);
|
||||
collection.template map_pieces<geometry::polygon_tag>(mapper); //, false, true);
|
||||
//collection.map_traverse(mapper);
|
||||
#endif
|
||||
|
||||
|
||||
@@ -21,7 +21,6 @@
|
||||
#include <boost/geometry/extensions/strategies/buffer_side.hpp>
|
||||
|
||||
#include <boost/geometry/algorithms/detail/overlay/backtrack_check_si.hpp>
|
||||
#include <boost/geometry/algorithms/detail/overlay/calculate_distance_policy.hpp>
|
||||
#include <boost/geometry/algorithms/detail/overlay/turn_info.hpp>
|
||||
|
||||
|
||||
@@ -46,14 +45,14 @@ class backtrack_for_buffer
|
||||
public :
|
||||
typedef detail::overlay::backtrack_state state_type;
|
||||
|
||||
template <typename Operation, typename Rings, typename Turns, typename Geometry, typename RescalePolicy>
|
||||
template <typename Operation, typename Rings, typename Turns, typename Geometry, typename RobustPolicy>
|
||||
static inline void apply(std::size_t size_at_start,
|
||||
Rings& rings, typename boost::range_value<Rings>::type& ring,
|
||||
Turns& turns, Operation& operation,
|
||||
std::string const& /*reason*/,
|
||||
Geometry const& ,
|
||||
Geometry const& ,
|
||||
RescalePolicy const& ,
|
||||
RobustPolicy const& ,
|
||||
state_type& state
|
||||
)
|
||||
{
|
||||
@@ -88,8 +87,6 @@ struct turn_assign_for_buffer
|
||||
template <typename Point1, typename Point2, typename Turn, typename IntersectionInfo, typename DirInfo>
|
||||
static inline void apply(Turn& turn, Point1 const& p1, Point2 const& p2, IntersectionInfo const& intersection_info, DirInfo const& dir_info)
|
||||
{
|
||||
detail::overlay::calculate_distance_policy::apply(turn, p1, p2,
|
||||
intersection_info, dir_info);
|
||||
if (dir_info.opposite && intersection_info.count == 2)
|
||||
{
|
||||
turn.is_opposite = true;
|
||||
@@ -99,8 +96,9 @@ struct turn_assign_for_buffer
|
||||
|
||||
// Should follow traversal-turn-concept (enrichment, visit structure)
|
||||
// and adds index in piece vector to find it back
|
||||
template <typename Point>
|
||||
struct buffer_turn_operation : public detail::overlay::traversal_turn_operation<Point>
|
||||
template <typename Point, typename SegmentRatio>
|
||||
struct buffer_turn_operation
|
||||
: public detail::overlay::traversal_turn_operation<Point, SegmentRatio>
|
||||
{
|
||||
int piece_index;
|
||||
bool include_in_occupation_map;
|
||||
@@ -112,8 +110,14 @@ struct buffer_turn_operation : public detail::overlay::traversal_turn_operation<
|
||||
};
|
||||
|
||||
// Version for buffer including type of location, is_opposite, and helper variables
|
||||
template <typename Point>
|
||||
struct buffer_turn_info : public detail::overlay::turn_info<Point, buffer_turn_operation<Point> >
|
||||
template <typename Point, typename SegmentRatio>
|
||||
struct buffer_turn_info
|
||||
: public detail::overlay::turn_info
|
||||
<
|
||||
Point,
|
||||
SegmentRatio,
|
||||
buffer_turn_operation<Point, SegmentRatio>
|
||||
>
|
||||
{
|
||||
bool is_opposite;
|
||||
|
||||
|
||||
@@ -30,7 +30,6 @@
|
||||
|
||||
#include <boost/geometry/algorithms/detail/overlay/add_rings.hpp>
|
||||
#include <boost/geometry/algorithms/detail/overlay/assign_parents.hpp>
|
||||
#include <boost/geometry/algorithms/detail/overlay/calculate_distance_policy.hpp>
|
||||
#include <boost/geometry/algorithms/detail/overlay/enrich_intersection_points.hpp>
|
||||
#include <boost/geometry/algorithms/detail/overlay/enrichment_info.hpp>
|
||||
#include <boost/geometry/algorithms/detail/overlay/enrich_intersection_points.hpp>
|
||||
@@ -104,61 +103,7 @@ struct check_original<point_tag>
|
||||
};
|
||||
|
||||
|
||||
template <typename P>
|
||||
class relaxed_side
|
||||
{
|
||||
public :
|
||||
|
||||
// Template member function, because it is not always trivial
|
||||
// or convenient to explicitly mention the typenames in the
|
||||
// strategy-struct itself.
|
||||
|
||||
// Types can be all three different. Therefore it is
|
||||
// not implemented (anymore) as "segment"
|
||||
|
||||
static inline int apply(P const& p1, P const& p2, P const& p)
|
||||
{
|
||||
typedef typename coordinate_type<P>::type coordinate_type;
|
||||
|
||||
coordinate_type const x = get<0>(p);
|
||||
coordinate_type const y = get<1>(p);
|
||||
|
||||
coordinate_type const sx1 = get<0>(p1);
|
||||
coordinate_type const sy1 = get<1>(p1);
|
||||
coordinate_type const sx2 = get<0>(p2);
|
||||
coordinate_type const sy2 = get<1>(p2);
|
||||
|
||||
// Promote float->double, small int->int
|
||||
typedef typename geometry::select_most_precise
|
||||
<
|
||||
coordinate_type,
|
||||
double
|
||||
>::type promoted_type;
|
||||
|
||||
promoted_type const dx = sx2 - sx1;
|
||||
promoted_type const dy = sy2 - sy1;
|
||||
promoted_type const dpx = x - sx1;
|
||||
promoted_type const dpy = y - sy1;
|
||||
|
||||
promoted_type const s
|
||||
= geometry::detail::determinant<promoted_type>
|
||||
(
|
||||
dx, dy,
|
||||
dpx, dpy
|
||||
);
|
||||
|
||||
promoted_type const zero = promoted_type();
|
||||
promoted_type const relaxed_epsilon = std::numeric_limits<double>::epsilon() * 5.0;
|
||||
|
||||
return math::abs(s) < relaxed_epsilon ? 0
|
||||
: s > zero ? 1
|
||||
: -1;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
|
||||
template <typename Ring>
|
||||
template <typename Ring, typename RobustPolicy>
|
||||
struct buffered_piece_collection
|
||||
{
|
||||
typedef typename geometry::point_type<Ring>::type point_type;
|
||||
@@ -193,20 +138,42 @@ struct buffered_piece_collection
|
||||
|
||||
std::map<std::pair<segment_identifier, segment_identifier>, std::set<int> > m_turn_indices_per_segment_pair;
|
||||
|
||||
typedef typename geometry::rescale_policy_type
|
||||
<
|
||||
typename geometry::point_type<Ring>::type
|
||||
>::type rescale_policy_type;
|
||||
|
||||
typedef typename geometry::segment_ratio_type
|
||||
<
|
||||
point_type,
|
||||
RobustPolicy
|
||||
>::type segment_ratio_type;
|
||||
|
||||
typedef buffer_turn_info
|
||||
<
|
||||
point_type,
|
||||
segment_ratio_type
|
||||
> buffer_turn_info_type;
|
||||
|
||||
typedef buffer_turn_operation
|
||||
<
|
||||
point_type,
|
||||
segment_ratio_type
|
||||
> buffer_turn_operation_type;
|
||||
|
||||
typedef std::vector<buffer_turn_info_type> turn_vector_type;
|
||||
|
||||
typedef std::vector<buffer_turn_info<point_type> > turn_vector_type;
|
||||
typedef detail::overlay::get_turn_info
|
||||
<
|
||||
turn_assign_for_buffer
|
||||
> turn_policy;
|
||||
turn_vector_type m_turns;
|
||||
|
||||
geometry::detail::no_rescale_policy m_rescale_policy;
|
||||
|
||||
|
||||
// To check clustered locations we keep track of segments being opposite somewhere
|
||||
std::set<segment_identifier> m_in_opposite_segments;
|
||||
|
||||
RobustPolicy const& m_rescale_policy;
|
||||
|
||||
struct buffer_occupation_info : public occupation_info<angle_info<point_type, coordinate_type> >
|
||||
{
|
||||
std::set<segment_identifier> seg_ids;
|
||||
@@ -216,10 +183,9 @@ struct buffered_piece_collection
|
||||
typedef occupation_map<point_type, buffer_occupation_info> occupation_map_type;
|
||||
occupation_map_type m_occupation_map;
|
||||
|
||||
|
||||
struct redundant_turn
|
||||
{
|
||||
inline bool operator()(buffer_turn_info<point_type> const& turn) const
|
||||
inline bool operator()(buffer_turn_info_type const& turn) const
|
||||
{
|
||||
// Erase discarded turns (location not OK) and the turns
|
||||
// only used to detect oppositeness.
|
||||
@@ -228,6 +194,10 @@ struct buffered_piece_collection
|
||||
}
|
||||
};
|
||||
|
||||
buffered_piece_collection(RobustPolicy const& robust_policy)
|
||||
: m_rescale_policy(robust_policy)
|
||||
{}
|
||||
|
||||
|
||||
inline bool is_neighbor(piece const& piece1, piece const& piece2) const
|
||||
{
|
||||
@@ -294,7 +264,7 @@ struct buffered_piece_collection
|
||||
iterator it2_first = boost::begin(ring2) + seg_id2.segment_index;
|
||||
iterator it2_last = boost::begin(ring2) + piece2.last_segment_index;
|
||||
|
||||
buffer_turn_info<point_type> the_model;
|
||||
buffer_turn_info_type the_model;
|
||||
the_model.operations[0].piece_index = piece1.index;
|
||||
the_model.operations[0].seg_id = piece1.first_seg_id;
|
||||
|
||||
@@ -340,32 +310,7 @@ struct buffered_piece_collection
|
||||
}
|
||||
}
|
||||
|
||||
inline segment_relation_code get_segment_relation(point_type const& point,
|
||||
segment_identifier const& seg_id) const
|
||||
{
|
||||
typedef typename boost::range_iterator<std::vector<point_type> const>::type iterator_type;
|
||||
iterator_type it = boost::begin(offsetted_rings[seg_id.multi_index]) + seg_id.segment_index;
|
||||
iterator_type prev = it++;
|
||||
int side = side_strategy::apply(point, *prev, *it);
|
||||
if (side == 0)
|
||||
{
|
||||
if (geometry::equals(point, *prev))
|
||||
{
|
||||
return segment_relation_on_left;
|
||||
}
|
||||
else if (geometry::equals(point, *it))
|
||||
{
|
||||
return segment_relation_on_right;
|
||||
}
|
||||
else if (collinear_point_on_segment(point, *prev, *it))
|
||||
{
|
||||
return segment_relation_within;
|
||||
}
|
||||
}
|
||||
return segment_relation_disjoint;
|
||||
}
|
||||
|
||||
inline void add_angles(int turn_index, int operation_index, point_type const& point, buffer_turn_operation<point_type> const& operation)
|
||||
inline void add_angles(int turn_index, int operation_index, point_type const& point, buffer_turn_operation_type const& operation)
|
||||
{
|
||||
point_type mapped_point;
|
||||
buffer_occupation_info& info = m_occupation_map.find_or_insert(point, mapped_point);
|
||||
@@ -384,7 +329,7 @@ struct buffered_piece_collection
|
||||
{
|
||||
m_occupation_map.insert_turn_index(turn_index);
|
||||
|
||||
buffer_turn_info<point_type> const& turn = m_turns[turn_index];
|
||||
buffer_turn_info_type const& turn = m_turns[turn_index];
|
||||
|
||||
//std::cout << "Adding point " << turn_index << " " << geometry::wkt(turn.point) << std::endl;
|
||||
|
||||
@@ -395,7 +340,7 @@ struct buffered_piece_collection
|
||||
|
||||
|
||||
|
||||
inline void classify_turn(buffer_turn_info<point_type>& turn, piece const& pc) const
|
||||
inline void classify_turn(buffer_turn_info_type& turn, piece const& pc) const
|
||||
{
|
||||
if (pc.type == buffered_flat_end)
|
||||
{
|
||||
@@ -440,10 +385,10 @@ struct buffered_piece_collection
|
||||
{
|
||||
// The piece is a full (pseudo) circle. There are no helper segments. We only check if it is the turn is inside the generated circle,
|
||||
// or on the border.
|
||||
int const side_wrt_circle = side_on_convex_range< /*relaxed_side<point_type> */ side_strategy >(turn.point,
|
||||
int const side_wrt_circle = side_on_convex_range<side_strategy>(turn.point,
|
||||
boost::begin(ring) + seg_id.segment_index,
|
||||
boost::begin(ring) + pc.last_segment_index,
|
||||
seg_id, on_segment_seg_id);
|
||||
seg_id, on_segment_seg_id, m_rescale_policy);
|
||||
switch (side_wrt_circle)
|
||||
{
|
||||
case 0 : turn.count_on_offsetted++; break;
|
||||
@@ -452,17 +397,17 @@ struct buffered_piece_collection
|
||||
return;
|
||||
}
|
||||
|
||||
int side_helper = side_on_convex_range<side_strategy>(turn.point, pc.helper_segments);
|
||||
int side_helper = side_on_convex_range<side_strategy>(turn.point, pc.helper_segments, m_rescale_policy);
|
||||
if (side_helper == 1)
|
||||
{
|
||||
// Left or outside
|
||||
return;
|
||||
}
|
||||
|
||||
int const side_offsetted = side_on_convex_range< /*relaxed_side<point_type> */ side_strategy >(turn.point,
|
||||
int const side_offsetted = side_on_convex_range<side_strategy>(turn.point,
|
||||
boost::begin(ring) + seg_id.segment_index,
|
||||
boost::begin(ring) + pc.last_segment_index,
|
||||
seg_id, on_segment_seg_id);
|
||||
seg_id, on_segment_seg_id, m_rescale_policy);
|
||||
if (side_offsetted == 1)
|
||||
{
|
||||
return;
|
||||
@@ -479,8 +424,8 @@ struct buffered_piece_collection
|
||||
}
|
||||
if (side_helper == 0)
|
||||
{
|
||||
if (geometry::equals(turn.point, pc.helper_segments.back())
|
||||
|| geometry::equals(turn.point, pc.helper_segments.front()))
|
||||
if (detail::overlay::points_equal_or_close(turn.point, pc.helper_segments.back(), m_rescale_policy)
|
||||
|| detail::overlay::points_equal_or_close(turn.point, pc.helper_segments.front(), m_rescale_policy))
|
||||
{
|
||||
turn.count_on_corner++;
|
||||
}
|
||||
@@ -692,17 +637,6 @@ struct buffered_piece_collection
|
||||
}
|
||||
}
|
||||
|
||||
#define BOOST_GEOMETRY_DEBUG_BUFFER_SITUATION_MAP
|
||||
#ifdef BOOST_GEOMETRY_DEBUG_BUFFER_SITUATION_MAP
|
||||
inline int get_side(point_type const& point, Ring const& ring, int segment_index)
|
||||
{
|
||||
typedef typename boost::range_iterator<Ring const> iterator_type;
|
||||
iterator_type it = boost::begin(ring) + segment_index;
|
||||
iterator_type prev = it++;
|
||||
return side_strategy::apply(point, *prev, *it);
|
||||
}
|
||||
#endif
|
||||
|
||||
template <typename Iterator>
|
||||
static inline point_type const& select_for_side(Iterator first, Iterator second, int index)
|
||||
{
|
||||
@@ -723,53 +657,32 @@ struct buffered_piece_collection
|
||||
iterator_type prev1 = it1++;
|
||||
iterator_type prev2 = it2++;
|
||||
|
||||
int code1 = side_strategy::apply(select_for_side(prev1, it1, which), *prev2, *it2);
|
||||
int code2 = side_strategy::apply(select_for_side(prev2, it2, which), *prev1, *it1);
|
||||
typedef typename geometry::robust_point_type
|
||||
<
|
||||
point_type,
|
||||
RobustPolicy
|
||||
>::type robust_point_type;
|
||||
|
||||
robust_point_type p1_rob, p2_rob, prev1_rob, prev2_rob, cur1_rob, cur2_rob;
|
||||
geometry::recalculate(p1_rob, select_for_side(prev1, it1, which), m_rescale_policy);
|
||||
geometry::recalculate(p2_rob, select_for_side(prev2, it2, which), m_rescale_policy);
|
||||
geometry::recalculate(prev1_rob, *prev1, m_rescale_policy);
|
||||
geometry::recalculate(prev2_rob, *prev2, m_rescale_policy);
|
||||
geometry::recalculate(cur1_rob, *it1, m_rescale_policy);
|
||||
geometry::recalculate(cur2_rob, *it2, m_rescale_policy);
|
||||
|
||||
int const code1 = side_strategy::apply(p1_rob, prev2_rob, cur2_rob);
|
||||
int const code2 = side_strategy::apply(p2_rob, prev1_rob, cur1_rob);
|
||||
|
||||
if (code1 == 1 && code2 == -1) return 1;
|
||||
if (code1 == -1 && code2 == 1) return -1;
|
||||
|
||||
// ROBUSTNESS: in near collinear cases one might be zero, the other non-zero.
|
||||
// This happens several times.
|
||||
if (code1 != 0) return code1;
|
||||
if (code2 != 0) return -code2;
|
||||
|
||||
// // Check if the other side gives some more info
|
||||
// // (I've never seen this is the case though it might be so, if they are much longer.
|
||||
//int code1f = side_strategy::apply(*prev1, *prev2, *it2);
|
||||
//int code2f = side_strategy::apply(*prev2, *prev1, *it1);
|
||||
|
||||
// if (code1f != 0 || code2f != 0)
|
||||
// {
|
||||
// std::cout << "From: " << code1f << " " << code2f << std::endl;
|
||||
// if (code1f != 0) return -code1f;
|
||||
// if (code2f != 0) return code2f;
|
||||
// }
|
||||
|
||||
// Collinear?
|
||||
#ifdef BOOST_GEOMETRY_DEBUG_BUFFER_SITUATION_MAP
|
||||
//std::cout << "Collinear: " << code1 << " " << code2 << std::endl;
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
inline void debug_segment(segment_identifier id)
|
||||
{
|
||||
typedef typename boost::range_iterator<buffered_ring<Ring> const>::type iterator;
|
||||
|
||||
buffered_ring<Ring> const& ring = offsetted_rings[id.multi_index];
|
||||
iterator it = boost::begin(ring) + id.segment_index;
|
||||
iterator prev = it++;
|
||||
geometry::model::referring_segment<point_type const&> segment(*prev, *it);
|
||||
//std::cout << geometry::wkt(*prev) << " " << geometry::wkt(*it) << std::endl;
|
||||
}
|
||||
|
||||
|
||||
struct cluster_info
|
||||
{
|
||||
inline cluster_info(int i, point_type p, buffer_turn_operation<point_type> op)
|
||||
inline cluster_info(int i, point_type p, buffer_turn_operation_type op)
|
||||
: turn_index(i)
|
||||
, point(p)
|
||||
, operation(op)
|
||||
@@ -781,7 +694,7 @@ struct buffered_piece_collection
|
||||
|
||||
int turn_index;
|
||||
point_type point;
|
||||
buffer_turn_operation<point_type> operation;
|
||||
buffer_turn_operation_type operation;
|
||||
};
|
||||
|
||||
struct clustered_info
|
||||
@@ -791,14 +704,6 @@ struct buffered_piece_collection
|
||||
std::vector<cluster_info> intersecting_segments;
|
||||
};
|
||||
|
||||
#ifdef OLD
|
||||
struct situation_info
|
||||
{
|
||||
std::set<int> turn_indices;
|
||||
std::set<segment_identifier> seg_ids;
|
||||
};
|
||||
#endif
|
||||
|
||||
static inline bool add_mutual_intersection(clustered_info const& cluster, segment_identifier const& seg_id)
|
||||
{
|
||||
bool result = false;
|
||||
@@ -838,19 +743,12 @@ struct buffered_piece_collection
|
||||
return true;
|
||||
}
|
||||
|
||||
if (geometry::equals(a.point, b.point))
|
||||
if (detail::overlay::points_equal_or_close(a.point, b.point, m_rescale_policy))
|
||||
{
|
||||
std::cout << "=";
|
||||
return true;
|
||||
}
|
||||
|
||||
relaxed_less<point_type> comparator;
|
||||
if (comparator.equals(a.point, b.point))
|
||||
{
|
||||
std::cout << "*";
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -891,7 +789,7 @@ struct buffered_piece_collection
|
||||
for (typename boost::range_iterator<turn_vector_type>::type it =
|
||||
boost::begin(m_turns); it != boost::end(m_turns); ++it, ++index)
|
||||
{
|
||||
buffer_turn_info<point_type> const& turn = *it;
|
||||
buffer_turn_info_type const& turn = *it;
|
||||
|
||||
// Take care with all the indices
|
||||
map[turn.operations[0].seg_id].piece_index = turn.operations[0].piece_index;
|
||||
@@ -924,7 +822,7 @@ struct buffered_piece_collection
|
||||
for (typename boost::range_iterator<turn_vector_type>::type it =
|
||||
boost::begin(m_turns); it != boost::end(m_turns); ++it, ++index)
|
||||
{
|
||||
buffer_turn_info<point_type>& turn = *it;
|
||||
buffer_turn_info_type& turn = *it;
|
||||
//std::cout << "Referring to point " << geometry::wkt(turn.point) << std::endl;
|
||||
if (m_in_opposite_segments.count(turn.operations[0].seg_id) > 0
|
||||
|| m_in_opposite_segments.count(turn.operations[1].seg_id) > 0)
|
||||
@@ -941,7 +839,7 @@ struct buffered_piece_collection
|
||||
for (typename boost::range_iterator<turn_vector_type>::type it =
|
||||
boost::begin(m_turns); it != boost::end(m_turns); ++it, ++index)
|
||||
{
|
||||
buffer_turn_info<point_type>& turn = *it;
|
||||
buffer_turn_info_type& turn = *it;
|
||||
if (m_in_opposite_segments.count(turn.operations[0].seg_id) == 0
|
||||
&& m_in_opposite_segments.count(turn.operations[1].seg_id) == 0)
|
||||
{
|
||||
|
||||
@@ -26,18 +26,24 @@ namespace detail { namespace buffer
|
||||
|
||||
#ifdef BOOST_GEOMETRY_DEBUG_WITH_MAPPER
|
||||
|
||||
template <typename Ring>
|
||||
template <typename Ring, typename RobustPolicy>
|
||||
struct buffered_piece_collection_with_mapper
|
||||
: public buffered_piece_collection<Ring>
|
||||
: public buffered_piece_collection<Ring, RobustPolicy>
|
||||
{
|
||||
typedef buffered_piece_collection<Ring, RobustPolicy> super_type;
|
||||
|
||||
buffered_piece_collection_with_mapper(RobustPolicy const& robust_policy)
|
||||
: super_type(robust_policy)
|
||||
{}
|
||||
|
||||
|
||||
template <typename Mapper>
|
||||
inline void map_opposite_locations(Mapper& mapper)
|
||||
{
|
||||
typedef typename super_type::occupation_map_type occupation_map_type;
|
||||
for (typename boost::range_iterator<typename occupation_map_type::map_type>::type it =
|
||||
boost::begin(m_occupation_map.map);
|
||||
it != boost::end(m_occupation_map.map); ++it)
|
||||
boost::begin(this->m_occupation_map.map);
|
||||
it != boost::end(this->m_occupation_map.map); ++it)
|
||||
{
|
||||
mapper.map(it->first, it->second.occupied() ? "fill:rgb(255,0,255);" : "fill:rgb(0,192,0);", 7);
|
||||
|
||||
@@ -55,6 +61,8 @@ struct buffered_piece_collection_with_mapper
|
||||
bool const incoming = it->second.angles[i].incoming;
|
||||
segment_identifier seg_id = it->second.angles[i].seg_id;
|
||||
|
||||
typedef typename super_type::point_type point_type;
|
||||
|
||||
geometry::model::linestring<point_type> line;
|
||||
point_type p1, p2;
|
||||
geometry::set<0>(p1, geometry::get<0>(it->first) + cos(angle) * 0.1);
|
||||
@@ -90,13 +98,16 @@ struct buffered_piece_collection_with_mapper
|
||||
template <typename Mapper>
|
||||
inline void map_turns(Mapper& mapper)
|
||||
{
|
||||
typedef typename super_type::point_type point_type;
|
||||
typedef typename super_type::turn_vector_type turn_vector_type;
|
||||
|
||||
typedef typename geometry::coordinate_type<point_type>::type coordinate_type;
|
||||
std::map<std::pair<coordinate_type, coordinate_type>, int> offsets;
|
||||
|
||||
|
||||
int index = 0;
|
||||
for (typename boost::range_iterator<turn_vector_type>::type it =
|
||||
boost::begin(m_turns); it != boost::end(m_turns); ++it)
|
||||
boost::begin(this->m_turns); it != boost::end(this->m_turns); ++it)
|
||||
{
|
||||
if (! it->opposite())
|
||||
{
|
||||
@@ -152,8 +163,9 @@ struct buffered_piece_collection_with_mapper
|
||||
template <typename Tag, typename Mapper>
|
||||
inline void map_pieces(Mapper& mapper, bool pieces = true, bool indices = true)
|
||||
{
|
||||
for(typename piece_vector::const_iterator it = boost::begin(m_pieces);
|
||||
it != boost::end(m_pieces);
|
||||
typedef typename super_type::piece_vector piece_vector;
|
||||
for(typename piece_vector::const_iterator it = boost::begin(this->m_pieces);
|
||||
it != boost::end(this->m_pieces);
|
||||
++it)
|
||||
{
|
||||
Ring corner;
|
||||
@@ -162,7 +174,7 @@ struct buffered_piece_collection_with_mapper
|
||||
|
||||
if (seg_id.segment_index >= 0)
|
||||
{
|
||||
buffered_ring<Ring> const& ring = offsetted_rings[seg_id.multi_index];
|
||||
buffered_ring<Ring> const& ring = this->offsetted_rings[seg_id.multi_index];
|
||||
|
||||
std::copy(boost::begin(ring) + seg_id.segment_index,
|
||||
boost::begin(ring) + it->last_segment_index,
|
||||
@@ -207,6 +219,8 @@ struct buffered_piece_collection_with_mapper
|
||||
{
|
||||
|
||||
// Put starting piece_index / segment_index in centroid
|
||||
typedef typename super_type::point_type point_type;
|
||||
|
||||
point_type centroid;
|
||||
if (corner.size() > 3)
|
||||
{
|
||||
@@ -227,8 +241,10 @@ struct buffered_piece_collection_with_mapper
|
||||
template <typename Mapper>
|
||||
inline void map_offsetted_points(Mapper& mapper)
|
||||
{
|
||||
for(typename buffered_ring_collection<buffered_ring<Ring> >::const_iterator oit = boost::begin(offsetted_rings);
|
||||
oit != boost::end(offsetted_rings);
|
||||
typedef typename super_type::point_type point_type;
|
||||
|
||||
for(typename buffered_ring_collection<buffered_ring<Ring> >::const_iterator oit = boost::begin(this->offsetted_rings);
|
||||
oit != boost::end(this->offsetted_rings);
|
||||
++oit)
|
||||
{
|
||||
int index = 0;
|
||||
@@ -245,8 +261,8 @@ struct buffered_piece_collection_with_mapper
|
||||
template <typename Mapper>
|
||||
inline void map_traverse(Mapper& mapper)
|
||||
{
|
||||
for(typename buffered_ring_collection<Ring>::const_iterator it = boost::begin(traversed_rings);
|
||||
it != boost::end(traversed_rings);
|
||||
for(typename buffered_ring_collection<Ring>::const_iterator it = boost::begin(this->traversed_rings);
|
||||
it != boost::end(this->traversed_rings);
|
||||
++it)
|
||||
{
|
||||
mapper.map(*it, "opacity:0.4;fill:none;stroke:rgb(0,255,0);stroke-width:8");
|
||||
@@ -256,8 +272,8 @@ struct buffered_piece_collection_with_mapper
|
||||
template <typename Mapper>
|
||||
inline void map_offsetted(Mapper& mapper)
|
||||
{
|
||||
for(typename buffered_ring_collection<buffered_ring<Ring> >::const_iterator it = boost::begin(offsetted_rings);
|
||||
it != boost::end(offsetted_rings);
|
||||
for(typename buffered_ring_collection<buffered_ring<Ring> >::const_iterator it = boost::begin(this->offsetted_rings);
|
||||
it != boost::end(this->offsetted_rings);
|
||||
++it)
|
||||
{
|
||||
if (it->discarded())
|
||||
|
||||
@@ -179,33 +179,15 @@ struct copy_segment_point
|
||||
{};
|
||||
|
||||
|
||||
template
|
||||
<
|
||||
typename MultiRing,
|
||||
bool Reverse,
|
||||
typename SegmentIdentifier,
|
||||
typename RangeOut
|
||||
>
|
||||
template<bool Reverse>
|
||||
struct copy_segments
|
||||
<
|
||||
detail::buffer::buffered_ring_collection_tag,
|
||||
MultiRing,
|
||||
Reverse,
|
||||
SegmentIdentifier,
|
||||
RangeOut
|
||||
Reverse
|
||||
>
|
||||
: detail::copy_segments::copy_segments_multi
|
||||
<
|
||||
MultiRing,
|
||||
SegmentIdentifier,
|
||||
RangeOut,
|
||||
detail::copy_segments::copy_segments_ring
|
||||
<
|
||||
typename boost::range_value<MultiRing>::type,
|
||||
Reverse,
|
||||
SegmentIdentifier,
|
||||
RangeOut
|
||||
>
|
||||
detail::copy_segments::copy_segments_ring<Reverse>
|
||||
>
|
||||
{};
|
||||
|
||||
|
||||
@@ -52,9 +52,11 @@ inline bool collinear_point_on_segment(P0 const& subject, P1 const& p1, P2 const
|
||||
}
|
||||
|
||||
|
||||
template <typename SideStrategy, typename Point, typename Range>
|
||||
inline int side_on_convex_range(Point const& subject, Range const& range)
|
||||
template <typename SideStrategy, typename Point, typename Range, typename RobustPolicy>
|
||||
inline int side_on_convex_range(Point const& subject,
|
||||
Range const& range, RobustPolicy const& robust_policy)
|
||||
{
|
||||
// TODO merge this implementation with next function with same name
|
||||
if (boost::empty(range))
|
||||
{
|
||||
return 1;
|
||||
@@ -62,17 +64,26 @@ inline int side_on_convex_range(Point const& subject, Range const& range)
|
||||
|
||||
bool has_collinear = false;
|
||||
|
||||
typedef typename boost::range_iterator
|
||||
<
|
||||
Range const
|
||||
>::type iterator_type;
|
||||
typedef typename geometry::robust_point_type
|
||||
<
|
||||
Point,
|
||||
RobustPolicy
|
||||
>::type robust_point_type;
|
||||
|
||||
typedef typename boost::range_iterator<Range const>::type iterator_type;
|
||||
|
||||
iterator_type it = boost::begin(range);
|
||||
for (iterator_type prev = it++;
|
||||
it != boost::end(range);
|
||||
prev = it++)
|
||||
|
||||
robust_point_type subject_rob, previous_rob;
|
||||
geometry::recalculate(subject_rob, subject, robust_policy);
|
||||
geometry::recalculate(previous_rob, *it, robust_policy);
|
||||
|
||||
for (++it; it != boost::end(range); ++it)
|
||||
{
|
||||
int const side = SideStrategy::apply(subject, *prev, *it);
|
||||
robust_point_type current_rob;
|
||||
geometry::recalculate(current_rob, *it, robust_policy);
|
||||
|
||||
int const side = SideStrategy::apply(subject_rob, previous_rob, current_rob);
|
||||
switch(side)
|
||||
{
|
||||
case 1 :
|
||||
@@ -81,28 +92,50 @@ inline int side_on_convex_range(Point const& subject, Range const& range)
|
||||
// Check if it is really on the segment.
|
||||
// If not, it is either on the left (because polygon is convex)
|
||||
// or it is still on one of the other segments (if segments are collinear)
|
||||
if (collinear_point_on_segment(subject, *prev, *it))
|
||||
if (collinear_point_on_segment(subject_rob, previous_rob, current_rob))
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
has_collinear = true;
|
||||
break;
|
||||
}
|
||||
previous_rob = current_rob;
|
||||
}
|
||||
return has_collinear ? 1 : -1;
|
||||
}
|
||||
|
||||
template <typename SideStrategy, typename Point, typename Iterator>
|
||||
template <typename SideStrategy, typename Point, typename Iterator, typename RobustPolicy>
|
||||
static inline int side_on_convex_range(Point const& subject,
|
||||
Iterator first, Iterator last,
|
||||
/* by value: */ segment_identifier seg_id,
|
||||
segment_identifier& on_segment_seg_id)
|
||||
segment_identifier& on_segment_seg_id,
|
||||
RobustPolicy const& robust_policy)
|
||||
{
|
||||
|
||||
typedef typename geometry::robust_point_type
|
||||
<
|
||||
Point,
|
||||
RobustPolicy
|
||||
>::type robust_point_type;
|
||||
|
||||
bool has_collinear = false;
|
||||
Iterator it = first;
|
||||
for (Iterator prev = it++; it != last; prev = it++, seg_id.segment_index++)
|
||||
|
||||
if (it == last)
|
||||
{
|
||||
int side = SideStrategy::apply(subject, *prev, *it);
|
||||
return 1;
|
||||
}
|
||||
|
||||
robust_point_type subject_rob, previous_rob;
|
||||
geometry::recalculate(subject_rob, subject, robust_policy);
|
||||
geometry::recalculate(previous_rob, *it, robust_policy);
|
||||
|
||||
for (++it; it != last; ++it, seg_id.segment_index++)
|
||||
{
|
||||
robust_point_type current_rob;
|
||||
geometry::recalculate(current_rob, *it, robust_policy);
|
||||
|
||||
int const side = SideStrategy::apply(subject_rob, previous_rob, current_rob);
|
||||
switch(side)
|
||||
{
|
||||
case 1 :
|
||||
@@ -111,7 +144,7 @@ static inline int side_on_convex_range(Point const& subject,
|
||||
// Check if it is REALLY on the segment.
|
||||
// If not, it is either on the left (because polygon is convex)
|
||||
// or it is still on one of the other segments (if segments are collinear)
|
||||
if (collinear_point_on_segment(subject, *prev, *it))
|
||||
if (collinear_point_on_segment(subject_rob, previous_rob, current_rob))
|
||||
{
|
||||
on_segment_seg_id = seg_id;
|
||||
return 0;
|
||||
@@ -119,6 +152,7 @@ static inline int side_on_convex_range(Point const& subject,
|
||||
has_collinear = true;
|
||||
break;
|
||||
}
|
||||
previous_rob = current_rob;
|
||||
}
|
||||
return has_collinear ? 1 : -1;
|
||||
}
|
||||
|
||||
@@ -21,7 +21,6 @@
|
||||
#include <boost/geometry/algorithms/detail/overlay/turn_info.hpp>
|
||||
#include <boost/geometry/algorithms/detail/overlay/enrichment_info.hpp>
|
||||
#include <boost/geometry/algorithms/detail/overlay/traversal_info.hpp>
|
||||
#include <boost/geometry/algorithms/detail/overlay/calculate_distance_policy.hpp>
|
||||
|
||||
#include <boost/geometry/algorithms/detail/point_on_border.hpp>
|
||||
|
||||
@@ -110,7 +109,7 @@ struct dissolve_ring_or_polygon
|
||||
detail::dissolve::no_interrupt_policy policy;
|
||||
geometry::self_turns
|
||||
<
|
||||
detail::overlay::calculate_distance_policy
|
||||
detail::overlay::assign_null_policy
|
||||
>(geometry, rescale_policy, turns, policy);
|
||||
|
||||
// The dissolve process is not necessary if there are no turns at all
|
||||
|
||||
@@ -10,7 +10,9 @@
|
||||
#ifndef BOOST_GEOMETRY_ITERATORS_CONCATENATE_ITERATOR_HPP
|
||||
#define BOOST_GEOMETRY_ITERATORS_CONCATENATE_ITERATOR_HPP
|
||||
|
||||
#include <boost/type_traits.hpp>
|
||||
#include <boost/assert.hpp>
|
||||
#include <boost/mpl/assert.hpp>
|
||||
#include <boost/type_traits/is_convertible.hpp>
|
||||
#include <boost/iterator.hpp>
|
||||
#include <boost/iterator/iterator_facade.hpp>
|
||||
#include <boost/iterator/iterator_categories.hpp>
|
||||
@@ -57,18 +59,26 @@ public:
|
||||
(concatenate_iterator<OtherIt1, OtherIt2, OtherValue> const& other)
|
||||
: m_it1(other.m_it1), m_end1(other.m_end1), m_it2(other.m_it2)
|
||||
{
|
||||
BOOST_STATIC_ASSERT
|
||||
( boost::is_convertible<OtherIt1, Iterator1>::value
|
||||
&& boost::is_convertible<OtherIt2, Iterator2>::value );
|
||||
static const bool are_conv
|
||||
= boost::is_convertible<OtherIt1, Iterator1>::value
|
||||
&& boost::is_convertible<OtherIt2, Iterator2>::value;
|
||||
|
||||
BOOST_MPL_ASSERT_MSG((are_conv),
|
||||
NOT_CONVERTIBLE,
|
||||
(types<OtherIt1, OtherIt2>));
|
||||
}
|
||||
|
||||
template <typename OtherIt1, typename OtherIt2, typename OtherValue>
|
||||
concatenate_iterator
|
||||
operator=(concatenate_iterator<OtherIt1, OtherIt2, OtherValue> const& other)
|
||||
{
|
||||
BOOST_STATIC_ASSERT
|
||||
( boost::is_convertible<OtherIt1, Iterator1>::value
|
||||
&& boost::is_convertible<OtherIt2, Iterator2>::value );
|
||||
static const bool are_conv
|
||||
= boost::is_convertible<OtherIt1, Iterator1>::value
|
||||
&& boost::is_convertible<OtherIt2, Iterator2>::value;
|
||||
|
||||
BOOST_MPL_ASSERT_MSG((are_conv),
|
||||
NOT_CONVERTIBLE,
|
||||
(types<OtherIt1, OtherIt2>));
|
||||
|
||||
m_it1 = other.m_it1;
|
||||
m_end1 = other.m_end1;
|
||||
|
||||
@@ -10,7 +10,9 @@
|
||||
#ifndef BOOST_GEOMETRY_ITERATORS_FLATTEN_ITERATOR_HPP
|
||||
#define BOOST_GEOMETRY_ITERATORS_FLATTEN_ITERATOR_HPP
|
||||
|
||||
#include <boost/type_traits.hpp>
|
||||
#include <boost/assert.hpp>
|
||||
#include <boost/mpl/assert.hpp>
|
||||
#include <boost/type_traits/is_convertible.hpp>
|
||||
#include <boost/iterator.hpp>
|
||||
#include <boost/iterator/iterator_facade.hpp>
|
||||
#include <boost/iterator/iterator_categories.hpp>
|
||||
@@ -84,15 +86,19 @@ public:
|
||||
m_outer_end(other.m_outer_end),
|
||||
m_inner_it(other.m_inner_it)
|
||||
{
|
||||
BOOST_STATIC_ASSERT( boost::is_convertible
|
||||
<
|
||||
OtherOuterIterator, OuterIterator
|
||||
>::value
|
||||
&& boost::is_convertible
|
||||
<
|
||||
OtherInnerIterator, InnerIterator
|
||||
>::value );
|
||||
|
||||
static const bool are_conv
|
||||
= boost::is_convertible
|
||||
<
|
||||
OtherOuterIterator, OuterIterator
|
||||
>::value
|
||||
&& boost::is_convertible
|
||||
<
|
||||
OtherInnerIterator, InnerIterator
|
||||
>::value;
|
||||
|
||||
BOOST_MPL_ASSERT_MSG((are_conv),
|
||||
NOT_CONVERTIBLE,
|
||||
(types<OtherOuterIterator, OtherInnerIterator>));
|
||||
}
|
||||
|
||||
template
|
||||
@@ -112,14 +118,19 @@ public:
|
||||
OtherAccessInnerEnd
|
||||
> const& other)
|
||||
{
|
||||
BOOST_STATIC_ASSERT( boost::is_convertible
|
||||
<
|
||||
OtherOuterIterator, OuterIterator
|
||||
>::value
|
||||
&& boost::is_convertible
|
||||
<
|
||||
OtherInnerIterator, InnerIterator
|
||||
>::value );
|
||||
static const bool are_conv
|
||||
= boost::is_convertible
|
||||
<
|
||||
OtherOuterIterator, OuterIterator
|
||||
>::value
|
||||
&& boost::is_convertible
|
||||
<
|
||||
OtherInnerIterator, InnerIterator
|
||||
>::value;
|
||||
|
||||
BOOST_MPL_ASSERT_MSG((are_conv),
|
||||
NOT_CONVERTIBLE,
|
||||
(types<OtherOuterIterator, OtherInnerIterator>));
|
||||
|
||||
m_outer_it = other.m_outer_it;
|
||||
m_outer_end = other.m_outer_end;
|
||||
@@ -184,17 +195,17 @@ private:
|
||||
OtherAccessInnerEnd
|
||||
> const& other) const
|
||||
{
|
||||
if ( this->m_outer_it != other.m_outer_it )
|
||||
if ( m_outer_it != other.m_outer_it )
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if ( this->m_outer_it == m_outer_end )
|
||||
if ( m_outer_it == m_outer_end )
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
return this->m_inner_it == other.m_inner_it;
|
||||
return m_inner_it == other.m_inner_it;
|
||||
}
|
||||
|
||||
inline void increment()
|
||||
|
||||
@@ -10,6 +10,15 @@
|
||||
#ifndef BOOST_GEOMETRY_ITERATORS_POINT_ITERATOR_HPP
|
||||
#define BOOST_GEOMETRY_ITERATORS_POINT_ITERATOR_HPP
|
||||
|
||||
#include <boost/mpl/assert.hpp>
|
||||
#include <boost/type_traits/is_convertible.hpp>
|
||||
#include <boost/range.hpp>
|
||||
|
||||
#include <boost/geometry/core/exterior_ring.hpp>
|
||||
#include <boost/geometry/core/interior_rings.hpp>
|
||||
#include <boost/geometry/core/tags.hpp>
|
||||
#include <boost/geometry/multi/core/tags.hpp>
|
||||
|
||||
#include <boost/geometry/iterators/dispatch/point_iterator.hpp>
|
||||
#include <boost/geometry/iterators/point_iterator_type.hpp>
|
||||
|
||||
@@ -234,12 +243,15 @@ public:
|
||||
point_iterator(point_iterator<OtherGeometry> const& other)
|
||||
: base(*other.base_ptr())
|
||||
{
|
||||
BOOST_STATIC_ASSERT
|
||||
( boost::is_convertible
|
||||
<
|
||||
typename dispatch::point_iterator_type<OtherGeometry>::type,
|
||||
typename dispatch::point_iterator_type<Geometry>::type
|
||||
>::value );
|
||||
static const bool is_conv
|
||||
= boost::is_convertible<
|
||||
typename dispatch::point_iterator_type<OtherGeometry>::type,
|
||||
typename dispatch::point_iterator_type<Geometry>::type
|
||||
>::value;
|
||||
|
||||
BOOST_MPL_ASSERT_MSG((is_conv),
|
||||
NOT_CONVERTIBLE,
|
||||
(point_iterator<OtherGeometry>));
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@@ -14,9 +14,14 @@
|
||||
#include <boost/geometry/iterators/dispatch/point_iterator.hpp>
|
||||
|
||||
#include <boost/range.hpp>
|
||||
#include <boost/type_traits.hpp>
|
||||
#include <boost/mpl/if.hpp>
|
||||
|
||||
#include <boost/geometry/core/point_type.hpp>
|
||||
#include <boost/geometry/core/ring_type.hpp>
|
||||
#include <boost/geometry/core/tags.hpp>
|
||||
#include <boost/geometry/multi/core/tags.hpp>
|
||||
|
||||
#include <boost/geometry/iterators/flatten_iterator.hpp>
|
||||
#include <boost/geometry/iterators/concatenate_iterator.hpp>
|
||||
|
||||
@@ -107,12 +112,12 @@ private:
|
||||
typedef typename detail_dispatch::point_iterator_inner_range_type
|
||||
<
|
||||
Polygon
|
||||
>::type InnerRange;
|
||||
>::type inner_range;
|
||||
|
||||
public:
|
||||
typedef concatenate_iterator
|
||||
<
|
||||
typename boost::range_iterator<InnerRange>::type,
|
||||
typename boost::range_iterator<inner_range>::type,
|
||||
flatten_iterator
|
||||
<
|
||||
typename boost::range_iterator
|
||||
@@ -121,14 +126,14 @@ public:
|
||||
>::type,
|
||||
typename dispatch::point_iterator_type
|
||||
<
|
||||
InnerRange
|
||||
inner_range
|
||||
>::type,
|
||||
typename detail_dispatch::point_iterator_value_type
|
||||
<
|
||||
Polygon
|
||||
>::type,
|
||||
dispatch::points_begin<InnerRange>,
|
||||
dispatch::points_end<InnerRange>
|
||||
dispatch::points_begin<inner_range>,
|
||||
dispatch::points_end<inner_range>
|
||||
>,
|
||||
typename detail_dispatch::point_iterator_value_type<Polygon>::type
|
||||
> type;
|
||||
@@ -149,19 +154,19 @@ private:
|
||||
typedef typename detail_dispatch::point_iterator_inner_range_type
|
||||
<
|
||||
MultiLinestring
|
||||
>::type InnerRange;
|
||||
>::type inner_range;
|
||||
|
||||
public:
|
||||
typedef flatten_iterator
|
||||
<
|
||||
typename boost::range_iterator<MultiLinestring>::type,
|
||||
typename dispatch::point_iterator_type<InnerRange>::type,
|
||||
typename dispatch::point_iterator_type<inner_range>::type,
|
||||
typename detail_dispatch::point_iterator_value_type
|
||||
<
|
||||
MultiLinestring
|
||||
>::type,
|
||||
dispatch::points_begin<InnerRange>,
|
||||
dispatch::points_end<InnerRange>
|
||||
dispatch::points_begin<inner_range>,
|
||||
dispatch::points_end<inner_range>
|
||||
> type;
|
||||
};
|
||||
|
||||
@@ -173,19 +178,19 @@ private:
|
||||
typedef typename detail_dispatch::point_iterator_inner_range_type
|
||||
<
|
||||
MultiPolygon
|
||||
>::type InnerRange;
|
||||
>::type inner_range;
|
||||
|
||||
public:
|
||||
typedef flatten_iterator
|
||||
<
|
||||
typename boost::range_iterator<MultiPolygon>::type,
|
||||
typename dispatch::point_iterator_type<InnerRange>::type,
|
||||
typename dispatch::point_iterator_type<inner_range>::type,
|
||||
typename detail_dispatch::point_iterator_value_type
|
||||
<
|
||||
MultiPolygon
|
||||
>::type,
|
||||
dispatch::points_begin<InnerRange>,
|
||||
dispatch::points_end<InnerRange>
|
||||
dispatch::points_begin<inner_range>,
|
||||
dispatch::points_end<inner_range>
|
||||
> type;
|
||||
};
|
||||
|
||||
|
||||
@@ -28,17 +28,19 @@ namespace detail { namespace copy_segments
|
||||
{
|
||||
|
||||
|
||||
template
|
||||
<
|
||||
typename MultiGeometry,
|
||||
typename SegmentIdentifier,
|
||||
typename RangeOut,
|
||||
typename Policy
|
||||
>
|
||||
template<typename Policy>
|
||||
struct copy_segments_multi
|
||||
{
|
||||
template
|
||||
<
|
||||
typename MultiGeometry,
|
||||
typename SegmentIdentifier,
|
||||
typename RobustPolicy,
|
||||
typename RangeOut
|
||||
>
|
||||
static inline void apply(MultiGeometry const& multi_geometry,
|
||||
SegmentIdentifier const& seg_id, int to_index,
|
||||
RobustPolicy const& robust_policy,
|
||||
RangeOut& current_output)
|
||||
{
|
||||
|
||||
@@ -50,7 +52,9 @@ struct copy_segments_multi
|
||||
|
||||
// Call the single-version
|
||||
Policy::apply(multi_geometry[seg_id.multi_index],
|
||||
seg_id, to_index, current_output);
|
||||
seg_id, to_index,
|
||||
robust_policy,
|
||||
current_output);
|
||||
}
|
||||
};
|
||||
|
||||
@@ -64,33 +68,11 @@ namespace dispatch
|
||||
{
|
||||
|
||||
|
||||
template
|
||||
<
|
||||
typename MultiPolygon,
|
||||
bool Reverse,
|
||||
typename SegmentIdentifier,
|
||||
typename RangeOut
|
||||
>
|
||||
struct copy_segments
|
||||
<
|
||||
multi_polygon_tag,
|
||||
MultiPolygon,
|
||||
Reverse,
|
||||
SegmentIdentifier,
|
||||
RangeOut
|
||||
>
|
||||
template<bool Reverse>
|
||||
struct copy_segments<multi_polygon_tag, Reverse>
|
||||
: detail::copy_segments::copy_segments_multi
|
||||
<
|
||||
MultiPolygon,
|
||||
SegmentIdentifier,
|
||||
RangeOut,
|
||||
detail::copy_segments::copy_segments_polygon
|
||||
<
|
||||
typename boost::range_value<MultiPolygon>::type,
|
||||
Reverse,
|
||||
SegmentIdentifier,
|
||||
RangeOut
|
||||
>
|
||||
detail::copy_segments::copy_segments_polygon<Reverse>
|
||||
>
|
||||
{};
|
||||
|
||||
|
||||
@@ -39,11 +39,11 @@ template
|
||||
>
|
||||
struct get_turns_multi_polygon_cs
|
||||
{
|
||||
template <typename RescalePolicy, typename Turns, typename InterruptPolicy>
|
||||
template <typename RobustPolicy, typename Turns, typename InterruptPolicy>
|
||||
static inline void apply(
|
||||
int source_id1, Multi const& multi,
|
||||
int source_id2, Box const& box,
|
||||
RescalePolicy const& rescale_policy,
|
||||
RobustPolicy const& robust_policy,
|
||||
Turns& turns, InterruptPolicy& interrupt_policy)
|
||||
{
|
||||
typedef typename boost::range_iterator
|
||||
@@ -63,7 +63,7 @@ struct get_turns_multi_polygon_cs
|
||||
Reverse, ReverseBox,
|
||||
TurnPolicy
|
||||
>::apply(source_id1, *it, source_id2, box,
|
||||
rescale_policy, turns, interrupt_policy, i);
|
||||
robust_policy, turns, interrupt_policy, i);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
@@ -43,11 +43,11 @@ struct sectionalize_multi
|
||||
template
|
||||
<
|
||||
typename MultiGeometry,
|
||||
typename RescalePolicy,
|
||||
typename RobustPolicy,
|
||||
typename Sections
|
||||
>
|
||||
static inline void apply(MultiGeometry const& multi,
|
||||
RescalePolicy const& rescale_policy,
|
||||
RobustPolicy const& robust_policy,
|
||||
bool make_rescaled_boxes,
|
||||
Sections& sections, ring_identifier ring_id, std::size_t max_count)
|
||||
{
|
||||
@@ -57,7 +57,7 @@ struct sectionalize_multi
|
||||
it != boost::end(multi);
|
||||
++it, ++ring_id.multi_index)
|
||||
{
|
||||
Policy::apply(*it, rescale_policy, make_rescaled_boxes, sections, ring_id, max_count);
|
||||
Policy::apply(*it, robust_policy, make_rescaled_boxes, sections, ring_id, max_count);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
@@ -45,10 +45,13 @@ struct intersection_multi_linestring_multi_linestring_point
|
||||
template
|
||||
<
|
||||
typename MultiLinestring1, typename MultiLinestring2,
|
||||
typename RobustPolicy,
|
||||
typename OutputIterator, typename Strategy
|
||||
>
|
||||
static inline OutputIterator apply(MultiLinestring1 const& ml1,
|
||||
MultiLinestring2 const& ml2, OutputIterator out,
|
||||
MultiLinestring2 const& ml2,
|
||||
RobustPolicy const& robust_policy,
|
||||
OutputIterator out,
|
||||
Strategy const& strategy)
|
||||
{
|
||||
// Note, this loop is quadratic w.r.t. number of linestrings per input.
|
||||
@@ -68,7 +71,7 @@ struct intersection_multi_linestring_multi_linestring_point
|
||||
++it2)
|
||||
{
|
||||
out = intersection_linestring_linestring_point<PointOut>
|
||||
::apply(*it1, *it2, out, strategy);
|
||||
::apply(*it1, *it2, robust_policy, out, strategy);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -83,10 +86,13 @@ struct intersection_linestring_multi_linestring_point
|
||||
template
|
||||
<
|
||||
typename Linestring, typename MultiLinestring,
|
||||
typename RobustPolicy,
|
||||
typename OutputIterator, typename Strategy
|
||||
>
|
||||
static inline OutputIterator apply(Linestring const& linestring,
|
||||
MultiLinestring const& ml, OutputIterator out,
|
||||
MultiLinestring const& ml,
|
||||
RobustPolicy const& robust_policy,
|
||||
OutputIterator out,
|
||||
Strategy const& strategy)
|
||||
{
|
||||
for (typename boost::range_iterator
|
||||
@@ -97,7 +103,7 @@ struct intersection_linestring_multi_linestring_point
|
||||
++it)
|
||||
{
|
||||
out = intersection_linestring_linestring_point<PointOut>
|
||||
::apply(linestring, *it, out, strategy);
|
||||
::apply(linestring, *it, robust_policy, out, strategy);
|
||||
}
|
||||
|
||||
return out;
|
||||
@@ -118,9 +124,11 @@ struct intersection_of_multi_linestring_with_areal
|
||||
template
|
||||
<
|
||||
typename MultiLinestring, typename Areal,
|
||||
typename RobustPolicy,
|
||||
typename OutputIterator, typename Strategy
|
||||
>
|
||||
static inline OutputIterator apply(MultiLinestring const& ml, Areal const& areal,
|
||||
RobustPolicy const& robust_policy,
|
||||
OutputIterator out,
|
||||
Strategy const& strategy)
|
||||
{
|
||||
@@ -134,7 +142,7 @@ struct intersection_of_multi_linestring_with_areal
|
||||
out = intersection_of_linestring_with_areal
|
||||
<
|
||||
ReverseAreal, LineStringOut, OverlayType
|
||||
>::apply(*it, areal, out, strategy);
|
||||
>::apply(*it, areal, robust_policy, out, strategy);
|
||||
}
|
||||
|
||||
return out;
|
||||
@@ -154,16 +162,18 @@ struct intersection_of_areal_with_multi_linestring
|
||||
template
|
||||
<
|
||||
typename Areal, typename MultiLinestring,
|
||||
typename RobustPolicy,
|
||||
typename OutputIterator, typename Strategy
|
||||
>
|
||||
static inline OutputIterator apply(Areal const& areal, MultiLinestring const& ml,
|
||||
RobustPolicy const& robust_policy,
|
||||
OutputIterator out,
|
||||
Strategy const& strategy)
|
||||
{
|
||||
return intersection_of_multi_linestring_with_areal
|
||||
<
|
||||
ReverseAreal, LineStringOut, OverlayType
|
||||
>::apply(ml, areal, out, strategy);
|
||||
>::apply(ml, areal, robust_policy, out, strategy);
|
||||
}
|
||||
};
|
||||
|
||||
@@ -175,10 +185,13 @@ struct clip_multi_linestring
|
||||
template
|
||||
<
|
||||
typename MultiLinestring, typename Box,
|
||||
typename RobustPolicy,
|
||||
typename OutputIterator, typename Strategy
|
||||
>
|
||||
static inline OutputIterator apply(MultiLinestring const& multi_linestring,
|
||||
Box const& box, OutputIterator out, Strategy const& )
|
||||
Box const& box,
|
||||
RobustPolicy const& robust_policy,
|
||||
OutputIterator out, Strategy const& )
|
||||
{
|
||||
typedef typename point_type<LinestringOut>::type point_type;
|
||||
strategy::intersection::liang_barsky<Box, point_type> lb_strategy;
|
||||
@@ -187,7 +200,7 @@ struct clip_multi_linestring
|
||||
it != boost::end(multi_linestring); ++it)
|
||||
{
|
||||
out = detail::intersection::clip_range_with_box
|
||||
<LinestringOut>(box, *it, out, lb_strategy);
|
||||
<LinestringOut>(box, *it, robust_policy, out, lb_strategy);
|
||||
}
|
||||
return out;
|
||||
}
|
||||
|
||||
@@ -158,15 +158,6 @@ struct segments_de9im
|
||||
false, false, false, true);
|
||||
}
|
||||
|
||||
static inline return_type collinear_disjoint()
|
||||
{
|
||||
return de9im_segment(0,0,
|
||||
-1, -1, 1,
|
||||
-1, -1, 0,
|
||||
1, 0, 2,
|
||||
true);
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
|
||||
|
||||
@@ -88,7 +88,8 @@ struct direction_type
|
||||
|
||||
// New information
|
||||
side_info sides;
|
||||
int arrival[2]; // 1=arrival, -1departure, 0=neutral; == how_a//how_b
|
||||
// THIS IS EQUAL TO arrival_a, arrival_b - they probably can go now we have robust fractions
|
||||
int arrival[2]; // 1=arrival, -1=departure, 0=neutral; == how_a//how_b
|
||||
|
||||
|
||||
// About arrival[0] (== arrival of a2 w.r.t. b) for COLLINEAR cases
|
||||
@@ -110,28 +111,19 @@ struct direction_type
|
||||
|
||||
};
|
||||
|
||||
|
||||
template <typename S1, typename S2, typename CalculationType = void>
|
||||
struct segments_direction
|
||||
{
|
||||
typedef direction_type return_type;
|
||||
typedef S1 segment_type1;
|
||||
typedef S2 segment_type2;
|
||||
typedef typename select_calculation_type
|
||||
<
|
||||
S1, S2, CalculationType
|
||||
>::type coordinate_type;
|
||||
|
||||
// Get the same type, but at least a double
|
||||
typedef typename select_most_precise<coordinate_type, double>::type rtype;
|
||||
|
||||
|
||||
template <typename R>
|
||||
static inline return_type segments_intersect(side_info const& sides,
|
||||
R const&,
|
||||
coordinate_type const& , coordinate_type const& ,
|
||||
coordinate_type const& , coordinate_type const& ,
|
||||
S1 const& , S2 const& )
|
||||
template
|
||||
<
|
||||
typename Segment1,
|
||||
typename Segment2,
|
||||
typename SegmentIntersectionInfo
|
||||
>
|
||||
static inline return_type segments_crosses(side_info const& sides,
|
||||
SegmentIntersectionInfo const& ,
|
||||
Segment1 const& , Segment2 const& )
|
||||
{
|
||||
bool const ra0 = sides.get<0,0>() == 0;
|
||||
bool const ra1 = sides.get<0,1>() == 0;
|
||||
@@ -171,63 +163,112 @@ struct segments_direction
|
||||
;
|
||||
}
|
||||
|
||||
static inline return_type collinear_touch(
|
||||
coordinate_type const& ,
|
||||
coordinate_type const& , int arrival_a, int arrival_b)
|
||||
template <typename Ratio>
|
||||
static inline int arrival_value(Ratio const& r_from, Ratio const& r_to)
|
||||
{
|
||||
// Though this is 'collinear', we handle it as To/From/Angle because it is the same.
|
||||
// It only does NOT have a direction.
|
||||
side_info sides;
|
||||
//int const arrive = how == 'T' ? 1 : -1;
|
||||
bool opposite = arrival_a == arrival_b;
|
||||
return
|
||||
! opposite
|
||||
? return_type(sides, 'a', arrival_a, arrival_b)
|
||||
: return_type(sides, arrival_a == 0 ? 't' : 'f', arrival_a, arrival_b, 0, 0, true);
|
||||
// a1--------->a2
|
||||
// b1----->b2
|
||||
// a departs: -1
|
||||
|
||||
// a1--------->a2
|
||||
// b1----->b2
|
||||
// a arrives: 1
|
||||
|
||||
// a1--------->a2
|
||||
// b1----->b2
|
||||
// both arrive there -> r-to = 1/1, or 0/1 (on_segment)
|
||||
|
||||
// First check the TO (for arrival), then FROM (for departure)
|
||||
return r_to.in_segment() ? 1
|
||||
: r_to.on_segment() ? 0
|
||||
: r_from.on_segment() ? -1
|
||||
: -1
|
||||
;
|
||||
}
|
||||
|
||||
template <typename S>
|
||||
static inline return_type collinear_interior_boundary_intersect(S const& , bool,
|
||||
int arrival_a, int arrival_b, bool opposite)
|
||||
template <typename Ratio>
|
||||
static inline void analyze(Ratio const& r,
|
||||
int& in_segment_count,
|
||||
int& on_end_count,
|
||||
int& outside_segment_count)
|
||||
{
|
||||
if (r.on_end())
|
||||
{
|
||||
on_end_count++;
|
||||
}
|
||||
else if (r.in_segment())
|
||||
{
|
||||
in_segment_count++;
|
||||
}
|
||||
else
|
||||
{
|
||||
outside_segment_count++;
|
||||
}
|
||||
}
|
||||
|
||||
template <typename Segment1, typename Segment2, typename Ratio>
|
||||
static inline return_type segments_collinear(
|
||||
Segment1 const& , Segment2 const&,
|
||||
Ratio const& ra_from_wrt_b, Ratio const& ra_to_wrt_b,
|
||||
Ratio const& rb_from_wrt_a, Ratio const& rb_to_wrt_a)
|
||||
{
|
||||
// If segments are opposite, the ratio of the FROM w.r.t. the other
|
||||
// is larger than the ratio of the TO w.r.t. the other
|
||||
bool const opposite = ra_to_wrt_b < ra_from_wrt_b;
|
||||
|
||||
return_type r('c', opposite);
|
||||
r.arrival[0] = arrival_a;
|
||||
r.arrival[1] = arrival_b;
|
||||
|
||||
// IMPORTANT: the order of conditions is different as in intersection_points.hpp
|
||||
// We assign A in 0 and B in 1
|
||||
r.arrival[0] = arrival_value(ra_from_wrt_b, ra_to_wrt_b);
|
||||
r.arrival[1] = arrival_value(rb_from_wrt_a, rb_to_wrt_a);
|
||||
|
||||
// Analyse them
|
||||
int a_in_segment_count = 0;
|
||||
int a_on_end_count = 0;
|
||||
int a_outside_segment_count = 0;
|
||||
int b_in_segment_count = 0;
|
||||
int b_on_end_count = 0;
|
||||
int b_outside_segment_count = 0;
|
||||
analyze(ra_from_wrt_b,
|
||||
a_in_segment_count, a_on_end_count, a_outside_segment_count);
|
||||
analyze(ra_to_wrt_b,
|
||||
a_in_segment_count, a_on_end_count, a_outside_segment_count);
|
||||
analyze(rb_from_wrt_a,
|
||||
b_in_segment_count, b_on_end_count, b_outside_segment_count);
|
||||
analyze(rb_to_wrt_a,
|
||||
b_in_segment_count, b_on_end_count, b_outside_segment_count);
|
||||
|
||||
if (a_on_end_count == 1
|
||||
&& b_on_end_count == 1
|
||||
&& a_outside_segment_count == 1
|
||||
&& b_outside_segment_count == 1)
|
||||
{
|
||||
// This is a collinear touch
|
||||
// --------> A (or B)
|
||||
// <---------- B (or A)
|
||||
// We adapt the "how"
|
||||
// TODO: how was to be refactored anyway,
|
||||
if (! opposite)
|
||||
{
|
||||
r.how = 'a';
|
||||
}
|
||||
else
|
||||
{
|
||||
r.how = r.arrival[0] == 0 ? 't' : 'f';
|
||||
}
|
||||
}
|
||||
else if (a_on_end_count == 2
|
||||
&& b_on_end_count == 2)
|
||||
{
|
||||
r.how = 'e';
|
||||
}
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
static inline return_type collinear_a_in_b(S1 const& , bool opposite)
|
||||
{
|
||||
return_type r('c', opposite);
|
||||
r.arrival[0] = 1;
|
||||
r.arrival[1] = -1;
|
||||
return r;
|
||||
}
|
||||
static inline return_type collinear_b_in_a(S2 const& , bool opposite)
|
||||
{
|
||||
return_type r('c', opposite);
|
||||
r.arrival[0] = -1;
|
||||
r.arrival[1] = 1;
|
||||
return r;
|
||||
}
|
||||
|
||||
static inline return_type collinear_overlaps(
|
||||
coordinate_type const& , coordinate_type const& ,
|
||||
coordinate_type const& , coordinate_type const& ,
|
||||
int arrival_a, int arrival_b, bool opposite)
|
||||
{
|
||||
return_type r('c', opposite);
|
||||
r.arrival[0] = arrival_a;
|
||||
r.arrival[1] = arrival_b;
|
||||
return r;
|
||||
}
|
||||
|
||||
static inline return_type segment_equal(S1 const& , bool opposite)
|
||||
{
|
||||
return return_type('e', opposite);
|
||||
}
|
||||
|
||||
static inline return_type degenerate(S1 const& , bool)
|
||||
template <typename Segment>
|
||||
static inline return_type degenerate(Segment const& , bool)
|
||||
{
|
||||
return return_type('0', false);
|
||||
}
|
||||
@@ -237,11 +278,6 @@ struct segments_direction
|
||||
return return_type('d', false);
|
||||
}
|
||||
|
||||
static inline return_type collinear_disjoint()
|
||||
{
|
||||
return return_type('d', false);
|
||||
}
|
||||
|
||||
static inline return_type error(std::string const&)
|
||||
{
|
||||
// Return "E" to denote error
|
||||
|
||||
@@ -16,7 +16,7 @@
|
||||
#include <boost/concept_check.hpp>
|
||||
#include <boost/numeric/conversion/cast.hpp>
|
||||
|
||||
#include <boost/geometry/arithmetic/determinant.hpp>
|
||||
#include <boost/geometry/algorithms/detail/assign_indexed_point.hpp>
|
||||
#include <boost/geometry/core/access.hpp>
|
||||
#include <boost/geometry/strategies/side_info.hpp>
|
||||
#include <boost/geometry/util/select_calculation_type.hpp>
|
||||
@@ -29,106 +29,154 @@ namespace boost { namespace geometry
|
||||
namespace policies { namespace relate
|
||||
{
|
||||
|
||||
template <typename S1, typename S2, typename ReturnType, typename CalculationType = void>
|
||||
|
||||
/*!
|
||||
\brief Policy calculating the intersection points themselves
|
||||
*/
|
||||
template
|
||||
<
|
||||
typename ReturnType
|
||||
>
|
||||
struct segments_intersection_points
|
||||
{
|
||||
typedef ReturnType return_type;
|
||||
typedef S1 segment_type1;
|
||||
typedef S2 segment_type2;
|
||||
|
||||
typedef typename select_calculation_type
|
||||
<
|
||||
S1, S2, CalculationType
|
||||
>::type coordinate_type;
|
||||
|
||||
template <typename R>
|
||||
static inline return_type segments_intersect(side_info const&,
|
||||
R const& r,
|
||||
coordinate_type const& dx1, coordinate_type const& dy1,
|
||||
coordinate_type const& , coordinate_type const& ,
|
||||
S1 const& s1, S2 const& )
|
||||
template
|
||||
<
|
||||
typename Point,
|
||||
typename Segment,
|
||||
typename SegmentRatio,
|
||||
typename T
|
||||
>
|
||||
static inline void assign(Point& point,
|
||||
Segment const& segment,
|
||||
SegmentRatio const& ratio,
|
||||
T const& dx, T const& dy)
|
||||
{
|
||||
typedef typename geometry::coordinate_type
|
||||
<
|
||||
typename return_type::point_type
|
||||
>::type return_coordinate_type;
|
||||
typedef typename geometry::coordinate_type<Point>::type coordinate_type;
|
||||
|
||||
coordinate_type const s1x = get<0, 0>(s1);
|
||||
coordinate_type const s1y = get<0, 1>(s1);
|
||||
|
||||
return_type result;
|
||||
result.count = 1;
|
||||
set<0>(result.intersections[0],
|
||||
geometry::math::round<return_coordinate_type>(R(s1x) + r * R(dx1)));
|
||||
set<1>(result.intersections[0],
|
||||
geometry::math::round<return_coordinate_type>(R(s1y) + r * R(dy1)));
|
||||
|
||||
return result;
|
||||
// Calculate the intersection point based on segment_ratio
|
||||
// Up to know, division was postponed. Here we divide using numerator/
|
||||
// denominator. In case of integer this might result in an integer
|
||||
// division.
|
||||
BOOST_ASSERT(ratio.denominator() != 0);
|
||||
set<0>(point, boost::numeric_cast<coordinate_type>(
|
||||
get<0, 0>(segment)
|
||||
+ ratio.numerator() * dx / ratio.denominator()));
|
||||
set<1>(point, boost::numeric_cast<coordinate_type>(
|
||||
get<0, 1>(segment)
|
||||
+ ratio.numerator() * dy / ratio.denominator()));
|
||||
}
|
||||
|
||||
static inline return_type collinear_touch(coordinate_type const& x,
|
||||
coordinate_type const& y, int, int)
|
||||
|
||||
template
|
||||
<
|
||||
typename Segment1,
|
||||
typename Segment2,
|
||||
typename SegmentIntersectionInfo
|
||||
>
|
||||
static inline return_type segments_crosses(side_info const&,
|
||||
SegmentIntersectionInfo const& sinfo,
|
||||
Segment1 const& s1, Segment2 const& s2)
|
||||
{
|
||||
return_type result;
|
||||
result.count = 1;
|
||||
set<0>(result.intersections[0], x);
|
||||
set<1>(result.intersections[0], y);
|
||||
|
||||
if (sinfo.robust_ra < sinfo.robust_rb)
|
||||
{
|
||||
assign(result.intersections[0], s1, sinfo.robust_ra,
|
||||
sinfo.dx_a, sinfo.dy_a);
|
||||
}
|
||||
else
|
||||
{
|
||||
assign(result.intersections[0], s2, sinfo.robust_rb,
|
||||
sinfo.dx_b, sinfo.dy_b);
|
||||
}
|
||||
|
||||
result.fractions[0].assign(sinfo);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
template <typename S>
|
||||
static inline return_type collinear_inside(S const& s, int index1 = 0, int index2 = 1)
|
||||
template <typename Segment1, typename Segment2, typename Ratio>
|
||||
static inline return_type segments_collinear(
|
||||
Segment1 const& a, Segment2 const& b,
|
||||
Ratio const& ra_from_wrt_b, Ratio const& ra_to_wrt_b,
|
||||
Ratio const& rb_from_wrt_a, Ratio const& rb_to_wrt_a)
|
||||
{
|
||||
return_type result;
|
||||
result.count = 2;
|
||||
set<0>(result.intersections[index1], get<0, 0>(s));
|
||||
set<1>(result.intersections[index1], get<0, 1>(s));
|
||||
set<0>(result.intersections[index2], get<1, 0>(s));
|
||||
set<1>(result.intersections[index2], get<1, 1>(s));
|
||||
return result;
|
||||
}
|
||||
int index = 0, count_a = 0, count_b = 0;
|
||||
Ratio on_a[2];
|
||||
|
||||
template <typename S>
|
||||
static inline return_type collinear_interior_boundary_intersect(S const& s, bool a_in_b,
|
||||
int, int, bool opposite)
|
||||
{
|
||||
int index1 = opposite && ! a_in_b ? 1 : 0;
|
||||
return collinear_inside(s, index1, 1 - index1);
|
||||
}
|
||||
// The conditions "index < 2" are necessary for non-robust handling,
|
||||
// if index would be 2 this indicate an (currently uncatched) error
|
||||
|
||||
static inline return_type collinear_a_in_b(S1 const& s, bool)
|
||||
{
|
||||
return collinear_inside(s);
|
||||
}
|
||||
static inline return_type collinear_b_in_a(S2 const& s, bool opposite)
|
||||
{
|
||||
int index1 = opposite ? 1 : 0;
|
||||
return collinear_inside(s, index1, 1 - index1);
|
||||
}
|
||||
// IMPORTANT: the order of conditions is different as in direction.hpp
|
||||
if (ra_from_wrt_b.on_segment()
|
||||
&& index < 2)
|
||||
{
|
||||
// a1--------->a2
|
||||
// b1----->b2
|
||||
//
|
||||
// ra1 (relative to b) is between 0/1:
|
||||
// -> First point of A is intersection point
|
||||
detail::assign_point_from_index<0>(a, result.intersections[index]);
|
||||
result.fractions[index].assign(Ratio::zero(), ra_from_wrt_b);
|
||||
on_a[index] = Ratio::zero();
|
||||
index++;
|
||||
count_a++;
|
||||
}
|
||||
if (rb_from_wrt_a.in_segment()
|
||||
&& index < 2)
|
||||
{
|
||||
// We take the first intersection point of B
|
||||
// a1--------->a2
|
||||
// b1----->b2
|
||||
// But only if it is not located on A
|
||||
// a1--------->a2
|
||||
// b1----->b2 rb_from_wrt_a == 0/1 -> a already taken
|
||||
|
||||
static inline return_type collinear_overlaps(
|
||||
coordinate_type const& x1, coordinate_type const& y1,
|
||||
coordinate_type const& x2, coordinate_type const& y2,
|
||||
int, int, bool)
|
||||
{
|
||||
return_type result;
|
||||
result.count = 2;
|
||||
set<0>(result.intersections[0], x1);
|
||||
set<1>(result.intersections[0], y1);
|
||||
set<0>(result.intersections[1], x2);
|
||||
set<1>(result.intersections[1], y2);
|
||||
return result;
|
||||
}
|
||||
detail::assign_point_from_index<0>(b, result.intersections[index]);
|
||||
result.fractions[index].assign(rb_from_wrt_a, Ratio::zero());
|
||||
on_a[index] = rb_from_wrt_a;
|
||||
index++;
|
||||
count_b++;
|
||||
}
|
||||
|
||||
if (ra_to_wrt_b.on_segment()
|
||||
&& index < 2)
|
||||
{
|
||||
// Similarly, second IP (here a2)
|
||||
// a1--------->a2
|
||||
// b1----->b2
|
||||
detail::assign_point_from_index<1>(a, result.intersections[index]);
|
||||
result.fractions[index].assign(Ratio::one(), ra_to_wrt_b);
|
||||
on_a[index] = Ratio::one();
|
||||
index++;
|
||||
count_a++;
|
||||
}
|
||||
if (rb_to_wrt_a.in_segment()
|
||||
&& index < 2)
|
||||
{
|
||||
detail::assign_point_from_index<1>(b, result.intersections[index]);
|
||||
result.fractions[index].assign(rb_to_wrt_a, Ratio::one());
|
||||
on_a[index] = rb_to_wrt_a;
|
||||
index++;
|
||||
count_b++;
|
||||
}
|
||||
|
||||
// TEMPORARY
|
||||
// If both are from b, and b is reversed w.r.t. a, we swap IP's
|
||||
// to align them w.r.t. a
|
||||
// get_turn_info still relies on some order (in some collinear cases)
|
||||
if (index == 2 && on_a[1] < on_a[0])
|
||||
{
|
||||
std::swap(result.fractions[0], result.fractions[1]);
|
||||
std::swap(result.intersections[0], result.intersections[1]);
|
||||
}
|
||||
|
||||
result.count = index;
|
||||
|
||||
static inline return_type segment_equal(S1 const& s, bool)
|
||||
{
|
||||
return_type result;
|
||||
result.count = 2;
|
||||
// TODO: order of IP's
|
||||
set<0>(result.intersections[0], get<0, 0>(s));
|
||||
set<1>(result.intersections[0], get<0, 1>(s));
|
||||
set<0>(result.intersections[1], get<1, 0>(s));
|
||||
set<1>(result.intersections[1], get<1, 1>(s));
|
||||
return result;
|
||||
}
|
||||
|
||||
@@ -141,17 +189,13 @@ struct segments_intersection_points
|
||||
return return_type();
|
||||
}
|
||||
|
||||
static inline return_type collinear_disjoint()
|
||||
{
|
||||
return return_type();
|
||||
}
|
||||
|
||||
static inline return_type degenerate(S1 const& s, bool)
|
||||
template <typename Segment>
|
||||
static inline return_type degenerate(Segment const& segment, bool)
|
||||
{
|
||||
return_type result;
|
||||
result.count = 1;
|
||||
set<0>(result.intersections[0], get<0, 0>(s));
|
||||
set<1>(result.intersections[0], get<0, 1>(s));
|
||||
set<0>(result.intersections[0], get<0, 0>(segment));
|
||||
set<1>(result.intersections[0], get<0, 1>(segment));
|
||||
return result;
|
||||
}
|
||||
};
|
||||
|
||||
109
include/boost/geometry/policies/relate/intersection_ratios.hpp
Normal file
109
include/boost/geometry/policies/relate/intersection_ratios.hpp
Normal file
@@ -0,0 +1,109 @@
|
||||
// Boost.Geometry (aka GGL, Generic Geometry Library)
|
||||
|
||||
// Copyright (c) 2007-2014 Barend Gehrels, Amsterdam, the Netherlands.
|
||||
|
||||
// Use, modification and distribution is subject to the Boost Software License,
|
||||
// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
|
||||
// http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
#ifndef BOOST_GEOMETRY_GEOMETRY_POLICIES_RELATE_INTERSECTION_RATIOS_HPP
|
||||
#define BOOST_GEOMETRY_GEOMETRY_POLICIES_RELATE_INTERSECTION_RATIOS_HPP
|
||||
|
||||
|
||||
#include <algorithm>
|
||||
#include <string>
|
||||
|
||||
#include <boost/concept_check.hpp>
|
||||
#include <boost/numeric/conversion/cast.hpp>
|
||||
|
||||
#include <boost/geometry/algorithms/detail/assign_indexed_point.hpp>
|
||||
#include <boost/geometry/core/access.hpp>
|
||||
#include <boost/geometry/strategies/side_info.hpp>
|
||||
|
||||
|
||||
namespace boost { namespace geometry
|
||||
{
|
||||
|
||||
namespace policies { namespace relate
|
||||
{
|
||||
|
||||
|
||||
/*!
|
||||
\brief Policy returning segment ratios
|
||||
\note Template argument FractionType should be a fraction_type<SegmentRatio>
|
||||
*/
|
||||
template
|
||||
<
|
||||
typename FractionType
|
||||
>
|
||||
struct segments_intersection_ratios
|
||||
{
|
||||
typedef FractionType return_type;
|
||||
|
||||
template
|
||||
<
|
||||
typename Segment1,
|
||||
typename Segment2,
|
||||
typename SegmentIntersectionInfo
|
||||
>
|
||||
static inline return_type segments_crosses(side_info const&,
|
||||
SegmentIntersectionInfo const& sinfo,
|
||||
Segment1 const& , Segment2 const& )
|
||||
{
|
||||
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& ,
|
||||
Ratio const& ra_from_wrt_b, Ratio const& ra_to_wrt_b,
|
||||
Ratio const& rb_from_wrt_a, Ratio const& rb_to_wrt_a)
|
||||
{
|
||||
// We have only one result, for (potentially) two IP's,
|
||||
// so we take a first one
|
||||
return_type result;
|
||||
|
||||
if (ra_from_wrt_b.on_segment())
|
||||
{
|
||||
result.assign(Ratio::zero(), ra_from_wrt_b);
|
||||
}
|
||||
else if (rb_from_wrt_a.in_segment())
|
||||
{
|
||||
result.assign(rb_from_wrt_a, Ratio::zero());
|
||||
}
|
||||
else if (ra_to_wrt_b.on_segment())
|
||||
{
|
||||
result.assign(Ratio::one(), ra_to_wrt_b);
|
||||
}
|
||||
else if (rb_to_wrt_a.in_segment())
|
||||
{
|
||||
result.assign(rb_to_wrt_a, Ratio::one());
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
static inline return_type disjoint()
|
||||
{
|
||||
return return_type();
|
||||
}
|
||||
static inline return_type error(std::string const&)
|
||||
{
|
||||
return return_type();
|
||||
}
|
||||
|
||||
template <typename Segment>
|
||||
static inline return_type degenerate(Segment const& segment, bool)
|
||||
{
|
||||
return return_type();
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
}} // namespace policies::relate
|
||||
|
||||
}} // namespace boost::geometry
|
||||
|
||||
#endif // BOOST_GEOMETRY_GEOMETRY_POLICIES_RELATE_INTERSECTION_RATIOS_HPP
|
||||
@@ -14,8 +14,6 @@
|
||||
|
||||
#include <boost/tuple/tuple.hpp>
|
||||
#include <boost/geometry/strategies/side_info.hpp>
|
||||
#include <boost/geometry/util/select_calculation_type.hpp>
|
||||
#include <boost/geometry/util/select_most_precise.hpp>
|
||||
|
||||
namespace boost { namespace geometry
|
||||
{
|
||||
@@ -26,7 +24,7 @@ namespace policies { namespace relate
|
||||
|
||||
// "tupled" to return intersection results together.
|
||||
// Now with two, with some meta-programming and derivations it can also be three (or more)
|
||||
template <typename Policy1, typename Policy2, typename CalculationType = void>
|
||||
template <typename Policy1, typename Policy2>
|
||||
struct segments_tupled
|
||||
{
|
||||
typedef boost::tuple
|
||||
@@ -35,101 +33,32 @@ struct segments_tupled
|
||||
typename Policy2::return_type
|
||||
> return_type;
|
||||
|
||||
// Take segments of first policy, they should be equal
|
||||
typedef typename Policy1::segment_type1 segment_type1;
|
||||
typedef typename Policy1::segment_type2 segment_type2;
|
||||
|
||||
typedef typename select_calculation_type
|
||||
<
|
||||
segment_type1,
|
||||
segment_type2,
|
||||
CalculationType
|
||||
>::type coordinate_type;
|
||||
|
||||
// Get the same type, but at least a double
|
||||
typedef typename select_most_precise<coordinate_type, double>::type rtype;
|
||||
|
||||
template <typename R>
|
||||
static inline return_type segments_intersect(side_info const& sides,
|
||||
R const& r,
|
||||
coordinate_type const& dx1, coordinate_type const& dy1,
|
||||
coordinate_type const& dx2, coordinate_type const& dy2,
|
||||
segment_type1 const& s1, segment_type2 const& s2)
|
||||
template <typename Segment1, typename Segment2, typename SegmentIntersectionInfo>
|
||||
static inline return_type segments_crosses(side_info const& sides,
|
||||
SegmentIntersectionInfo const& sinfo,
|
||||
Segment1 const& s1, Segment2 const& s2)
|
||||
{
|
||||
return boost::make_tuple
|
||||
(
|
||||
Policy1::segments_intersect(sides, r,
|
||||
dx1, dy1, dx2, dy2, s1, s2),
|
||||
Policy2::segments_intersect(sides, r,
|
||||
dx1, dy1, dx2, dy2, s1, s2)
|
||||
Policy1::segments_crosses(sides, sinfo, s1, s2),
|
||||
Policy2::segments_crosses(sides, sinfo, s1, s2)
|
||||
);
|
||||
}
|
||||
|
||||
static inline return_type collinear_touch(coordinate_type const& x,
|
||||
coordinate_type const& y, int arrival_a, int arrival_b)
|
||||
template <typename Segment1, typename Segment2, typename Ratio>
|
||||
static inline return_type segments_collinear(
|
||||
Segment1 const& segment1, Segment2 const& segment2,
|
||||
Ratio const& ra1, Ratio const& ra2, Ratio const& rb1, Ratio const& rb2)
|
||||
{
|
||||
return boost::make_tuple
|
||||
(
|
||||
Policy1::collinear_touch(x, y, arrival_a, arrival_b),
|
||||
Policy2::collinear_touch(x, y, arrival_a, arrival_b)
|
||||
Policy1::segments_collinear(segment1, segment2, ra1, ra2, rb1, rb2),
|
||||
Policy2::segments_collinear(segment1, segment2, ra1, ra2, rb1, rb2)
|
||||
);
|
||||
}
|
||||
|
||||
template <typename S>
|
||||
static inline return_type collinear_interior_boundary_intersect(S const& segment,
|
||||
bool a_within_b,
|
||||
int arrival_a, int arrival_b, bool opposite)
|
||||
{
|
||||
return boost::make_tuple
|
||||
(
|
||||
Policy1::collinear_interior_boundary_intersect(segment, a_within_b, arrival_a, arrival_b, opposite),
|
||||
Policy2::collinear_interior_boundary_intersect(segment, a_within_b, arrival_a, arrival_b, opposite)
|
||||
);
|
||||
}
|
||||
|
||||
static inline return_type collinear_a_in_b(segment_type1 const& segment,
|
||||
bool opposite)
|
||||
{
|
||||
return boost::make_tuple
|
||||
(
|
||||
Policy1::collinear_a_in_b(segment, opposite),
|
||||
Policy2::collinear_a_in_b(segment, opposite)
|
||||
);
|
||||
}
|
||||
static inline return_type collinear_b_in_a(segment_type2 const& segment,
|
||||
bool opposite)
|
||||
{
|
||||
return boost::make_tuple
|
||||
(
|
||||
Policy1::collinear_b_in_a(segment, opposite),
|
||||
Policy2::collinear_b_in_a(segment, opposite)
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
static inline return_type collinear_overlaps(
|
||||
coordinate_type const& x1, coordinate_type const& y1,
|
||||
coordinate_type const& x2, coordinate_type const& y2,
|
||||
int arrival_a, int arrival_b, bool opposite)
|
||||
{
|
||||
return boost::make_tuple
|
||||
(
|
||||
Policy1::collinear_overlaps(x1, y1, x2, y2, arrival_a, arrival_b, opposite),
|
||||
Policy2::collinear_overlaps(x1, y1, x2, y2, arrival_a, arrival_b, opposite)
|
||||
);
|
||||
}
|
||||
|
||||
static inline return_type segment_equal(segment_type1 const& s,
|
||||
bool opposite)
|
||||
{
|
||||
return boost::make_tuple
|
||||
(
|
||||
Policy1::segment_equal(s, opposite),
|
||||
Policy2::segment_equal(s, opposite)
|
||||
);
|
||||
}
|
||||
|
||||
static inline return_type degenerate(segment_type1 const& segment,
|
||||
template <typename Segment>
|
||||
static inline return_type degenerate(Segment const& segment,
|
||||
bool a_degenerate)
|
||||
{
|
||||
return boost::make_tuple
|
||||
@@ -157,15 +86,6 @@ struct segments_tupled
|
||||
);
|
||||
}
|
||||
|
||||
static inline return_type collinear_disjoint()
|
||||
{
|
||||
return boost::make_tuple
|
||||
(
|
||||
Policy1::collinear_disjoint(),
|
||||
Policy2::collinear_disjoint()
|
||||
);
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
}} // namespace policies::relate
|
||||
|
||||
@@ -0,0 +1,285 @@
|
||||
// Boost.Geometry (aka GGL, Generic Geometry Library)
|
||||
|
||||
// Copyright (c) 2014 Barend Gehrels, Amsterdam, the Netherlands.
|
||||
// Copyright (c) 2014 Bruno Lalande, Paris, France.
|
||||
// Copyright (c) 2014 Mateusz Loskot, London, UK.
|
||||
// Copyright (c) 2014 Adam Wulkiewicz, Lodz, Poland.
|
||||
|
||||
// Use, modification and distribution is subject to the Boost Software License,
|
||||
// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
|
||||
// http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
#ifndef BOOST_GEOMETRY_POLICIES_ROBUSTNESS_GET_RESCALE_POLICY_HPP
|
||||
#define BOOST_GEOMETRY_POLICIES_ROBUSTNESS_GET_RESCALE_POLICY_HPP
|
||||
|
||||
|
||||
#include <cstddef>
|
||||
|
||||
#include <boost/type_traits.hpp>
|
||||
|
||||
#include <boost/geometry/core/tag_cast.hpp>
|
||||
|
||||
#include <boost/geometry/algorithms/envelope.hpp>
|
||||
#include <boost/geometry/algorithms/expand.hpp>
|
||||
#include <boost/geometry/algorithms/detail/recalculate.hpp>
|
||||
#include <boost/geometry/algorithms/detail/get_max_size.hpp>
|
||||
#include <boost/geometry/policies/robustness/robust_type.hpp>
|
||||
|
||||
#include <boost/geometry/geometries/point.hpp>
|
||||
#include <boost/geometry/geometries/box.hpp>
|
||||
|
||||
#include <boost/geometry/policies/robustness/no_rescale_policy.hpp>
|
||||
#include <boost/geometry/policies/robustness/rescale_policy.hpp>
|
||||
|
||||
#include <boost/geometry/util/promote_floating_point.hpp>
|
||||
|
||||
namespace boost { namespace geometry
|
||||
{
|
||||
|
||||
#ifndef DOXYGEN_NO_DETAIL
|
||||
namespace detail { namespace get_rescale_policy
|
||||
{
|
||||
|
||||
template <typename Point, typename RobustPoint, typename Geometry, typename Factor>
|
||||
static inline void init_rescale_policy(Geometry const& geometry,
|
||||
Point& min_point,
|
||||
RobustPoint& min_robust_point,
|
||||
Factor& factor)
|
||||
{
|
||||
// Get bounding boxes
|
||||
model::box<Point> env = geometry::return_envelope<model::box<Point> >(geometry);
|
||||
|
||||
// Scale this to integer-range
|
||||
typedef typename promote_floating_point
|
||||
<
|
||||
typename geometry::coordinate_type<Point>::type
|
||||
>::type num_type;
|
||||
num_type const diff = boost::numeric_cast<num_type>(detail::get_max_size(env));
|
||||
num_type const range = 10000000.0; // Define a large range to get precise integer coordinates
|
||||
num_type const half = 0.5;
|
||||
factor = boost::numeric_cast<num_type>(
|
||||
boost::numeric_cast<boost::long_long_type>(half + range / diff));
|
||||
|
||||
// Assign input/output minimal points
|
||||
detail::assign_point_from_index<0>(env, min_point);
|
||||
num_type const two = 2;
|
||||
boost::long_long_type const min_coordinate
|
||||
= boost::numeric_cast<boost::long_long_type>(-range / two);
|
||||
assign_values(min_robust_point, min_coordinate, min_coordinate);
|
||||
}
|
||||
|
||||
template <typename Point, typename RobustPoint, typename Geometry1, typename Geometry2, typename Factor>
|
||||
static inline void init_rescale_policy(Geometry1 const& geometry1,
|
||||
Geometry2 const& geometry2,
|
||||
Point& min_point,
|
||||
RobustPoint& min_robust_point,
|
||||
Factor& factor)
|
||||
{
|
||||
// Get bounding boxes
|
||||
model::box<Point> env = geometry::return_envelope<model::box<Point> >(geometry1);
|
||||
model::box<Point> env2 = geometry::return_envelope<model::box<Point> >(geometry2);
|
||||
geometry::expand(env, env2);
|
||||
|
||||
// TODO: merge this with implementation above
|
||||
// Scale this to integer-range
|
||||
typedef typename promote_floating_point
|
||||
<
|
||||
typename geometry::coordinate_type<Point>::type
|
||||
>::type num_type;
|
||||
num_type const diff = boost::numeric_cast<num_type>(detail::get_max_size(env));
|
||||
num_type const range = 10000000.0; // Define a large range to get precise integer coordinates
|
||||
num_type const half = 0.5;
|
||||
factor = boost::numeric_cast<num_type>(
|
||||
boost::numeric_cast<boost::long_long_type>(half + range / diff));
|
||||
|
||||
// Assign input/output minimal points
|
||||
detail::assign_point_from_index<0>(env, min_point);
|
||||
num_type const two = 2;
|
||||
boost::long_long_type const min_coordinate
|
||||
= boost::numeric_cast<boost::long_long_type>(-range / two);
|
||||
assign_values(min_robust_point, min_coordinate, min_coordinate);
|
||||
}
|
||||
|
||||
|
||||
template
|
||||
<
|
||||
typename Point,
|
||||
bool IsFloatingPoint
|
||||
>
|
||||
struct rescale_policy_type
|
||||
{
|
||||
typedef no_rescale_policy type;
|
||||
};
|
||||
|
||||
// We rescale only all FP types
|
||||
template
|
||||
<
|
||||
typename Point
|
||||
>
|
||||
struct rescale_policy_type<Point, true>
|
||||
{
|
||||
typedef typename geometry::coordinate_type<Point>::type coordinate_type;
|
||||
typedef model::point
|
||||
<
|
||||
typename detail::robust_type<coordinate_type>::type,
|
||||
geometry::dimension<Point>::value,
|
||||
typename geometry::coordinate_system<Point>::type
|
||||
> robust_point_type;
|
||||
typedef typename promote_floating_point<coordinate_type>::type factor_type;
|
||||
typedef detail::robust_policy<Point, robust_point_type, factor_type> type;
|
||||
};
|
||||
|
||||
template <typename Policy>
|
||||
struct get_rescale_policy
|
||||
{
|
||||
template <typename Geometry>
|
||||
static inline Policy apply(Geometry const& geometry)
|
||||
{
|
||||
typedef typename point_type<Geometry>::type point_type;
|
||||
typedef typename geometry::coordinate_type<Geometry>::type coordinate_type;
|
||||
typedef typename promote_floating_point<coordinate_type>::type factor_type;
|
||||
typedef model::point
|
||||
<
|
||||
typename detail::robust_type<coordinate_type>::type,
|
||||
geometry::dimension<point_type>::value,
|
||||
typename geometry::coordinate_system<point_type>::type
|
||||
> robust_point_type;
|
||||
|
||||
point_type min_point;
|
||||
robust_point_type min_robust_point;
|
||||
factor_type factor;
|
||||
init_rescale_policy(geometry, min_point, min_robust_point, factor);
|
||||
|
||||
return Policy(min_point, min_robust_point, factor);
|
||||
}
|
||||
|
||||
template <typename Geometry1, typename Geometry2>
|
||||
static inline Policy apply(Geometry1 const& geometry1, Geometry2 const& geometry2)
|
||||
{
|
||||
typedef typename point_type<Geometry1>::type point_type;
|
||||
typedef typename geometry::coordinate_type<Geometry1>::type coordinate_type;
|
||||
typedef typename promote_floating_point<coordinate_type>::type factor_type;
|
||||
typedef model::point
|
||||
<
|
||||
typename detail::robust_type<coordinate_type>::type,
|
||||
geometry::dimension<point_type>::value,
|
||||
typename geometry::coordinate_system<point_type>::type
|
||||
> robust_point_type;
|
||||
|
||||
point_type min_point;
|
||||
robust_point_type min_robust_point;
|
||||
factor_type factor;
|
||||
init_rescale_policy(geometry1, geometry2, min_point, min_robust_point, factor);
|
||||
|
||||
return Policy(min_point, min_robust_point, factor);
|
||||
}
|
||||
};
|
||||
|
||||
// Specialization for no-rescaling
|
||||
template <>
|
||||
struct get_rescale_policy<no_rescale_policy>
|
||||
{
|
||||
template <typename Geometry>
|
||||
static inline no_rescale_policy apply(Geometry const& )
|
||||
{
|
||||
return no_rescale_policy();
|
||||
}
|
||||
|
||||
template <typename Geometry1, typename Geometry2>
|
||||
static inline no_rescale_policy apply(Geometry1 const& , Geometry2 const& )
|
||||
{
|
||||
return no_rescale_policy();
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
}} // namespace detail::get_rescale_policy
|
||||
#endif // DOXYGEN_NO_DETAIL
|
||||
|
||||
template<typename Point>
|
||||
struct rescale_policy_type
|
||||
: public detail::get_rescale_policy::rescale_policy_type
|
||||
<
|
||||
Point,
|
||||
#if defined(BOOST_GEOMETRY_NO_ROBUSTNESS)
|
||||
false
|
||||
#else
|
||||
boost::is_floating_point
|
||||
<
|
||||
typename geometry::coordinate_type<Point>::type
|
||||
>::type::value
|
||||
#endif
|
||||
>
|
||||
{
|
||||
BOOST_STATIC_ASSERT
|
||||
((
|
||||
boost::is_same
|
||||
<
|
||||
typename geometry::tag<Point>::type,
|
||||
geometry::point_tag
|
||||
>::type::value
|
||||
));
|
||||
};
|
||||
|
||||
|
||||
template
|
||||
<
|
||||
typename Geometry1,
|
||||
typename Geometry2,
|
||||
typename Tag1 = typename tag_cast
|
||||
<
|
||||
typename tag<Geometry1>::type,
|
||||
box_tag,
|
||||
pointlike_tag,
|
||||
linear_tag,
|
||||
areal_tag
|
||||
>::type,
|
||||
typename Tag2 = typename tag_cast
|
||||
<
|
||||
typename tag<Geometry2>::type,
|
||||
box_tag,
|
||||
pointlike_tag,
|
||||
linear_tag,
|
||||
areal_tag
|
||||
>::type
|
||||
>
|
||||
struct rescale_overlay_policy_type
|
||||
// Default: no rescaling
|
||||
: public detail::get_rescale_policy::rescale_policy_type
|
||||
<
|
||||
typename geometry::point_type<Geometry1>::type,
|
||||
false
|
||||
>
|
||||
{};
|
||||
|
||||
// Areal/areal: get rescale policy based on coordinate type
|
||||
template
|
||||
<
|
||||
typename Geometry1,
|
||||
typename Geometry2
|
||||
>
|
||||
struct rescale_overlay_policy_type<Geometry1, Geometry2, areal_tag, areal_tag>
|
||||
: public rescale_policy_type
|
||||
<
|
||||
typename geometry::point_type<Geometry1>::type
|
||||
>
|
||||
{};
|
||||
|
||||
|
||||
template <typename Policy, typename Geometry>
|
||||
inline Policy get_rescale_policy(Geometry const& geometry)
|
||||
{
|
||||
return detail::get_rescale_policy::get_rescale_policy<Policy>::apply(geometry);
|
||||
}
|
||||
|
||||
template <typename Policy, typename Geometry1, typename Geometry2>
|
||||
inline Policy get_rescale_policy(Geometry1 const& geometry1, Geometry2 const& geometry2)
|
||||
{
|
||||
return detail::get_rescale_policy::get_rescale_policy<Policy>::apply(geometry1, geometry2);
|
||||
}
|
||||
|
||||
|
||||
}} // namespace boost::geometry
|
||||
|
||||
|
||||
#endif // BOOST_GEOMETRY_POLICIES_ROBUSTNESS_GET_RESCALE_POLICY_HPP
|
||||
@@ -0,0 +1,66 @@
|
||||
// Boost.Geometry (aka GGL, Generic Geometry Library)
|
||||
|
||||
// Copyright (c) 2013 Barend Gehrels, Amsterdam, the Netherlands.
|
||||
// Copyright (c) 2013 Bruno Lalande, Paris, France.
|
||||
// Copyright (c) 2013 Mateusz Loskot, London, UK.
|
||||
// Copyright (c) 2013 Adam Wulkiewicz, Lodz, Poland.
|
||||
|
||||
// Use, modification and distribution is subject to the Boost Software License,
|
||||
// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
|
||||
// http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
#ifndef BOOST_GEOMETRY_POLICIES_ROBUSTNESS_NO_RESCALE_POLICY_HPP
|
||||
#define BOOST_GEOMETRY_POLICIES_ROBUSTNESS_NO_RESCALE_POLICY_HPP
|
||||
|
||||
#include <stddef.h>
|
||||
|
||||
#include <boost/geometry/core/coordinate_type.hpp>
|
||||
#include <boost/geometry/policies/robustness/robust_point_type.hpp>
|
||||
#include <boost/geometry/policies/robustness/segment_ratio.hpp>
|
||||
#include <boost/geometry/policies/robustness/segment_ratio_type.hpp>
|
||||
|
||||
namespace boost { namespace geometry
|
||||
{
|
||||
|
||||
#ifndef DOXYGEN_NO_DETAIL
|
||||
namespace detail
|
||||
{
|
||||
|
||||
// Probably this will be moved out of namespace detail
|
||||
struct no_rescale_policy
|
||||
{
|
||||
static bool const enabled = false;
|
||||
|
||||
// We don't rescale but return the reference of the input
|
||||
template <std::size_t Dimension, typename Value>
|
||||
inline Value const& apply(Value const& value) const
|
||||
{
|
||||
return value;
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace detail
|
||||
#endif
|
||||
|
||||
|
||||
// Implement meta-functions for this policy
|
||||
template <typename Point>
|
||||
struct robust_point_type<Point, detail::no_rescale_policy>
|
||||
{
|
||||
// The point itself
|
||||
typedef Point type;
|
||||
};
|
||||
|
||||
template <typename Point>
|
||||
struct segment_ratio_type<Point, detail::no_rescale_policy>
|
||||
{
|
||||
// Define a segment_ratio defined on coordinate type, e.g.
|
||||
// int/int or float/float
|
||||
typedef typename geometry::coordinate_type<Point>::type coordinate_type;
|
||||
typedef segment_ratio<coordinate_type> type;
|
||||
};
|
||||
|
||||
|
||||
}} // namespace boost::geometry
|
||||
|
||||
#endif // BOOST_GEOMETRY_POLICIES_ROBUSTNESS_NO_RESCALE_POLICY_HPP
|
||||
@@ -0,0 +1,82 @@
|
||||
// Boost.Geometry (aka GGL, Generic Geometry Library)
|
||||
|
||||
// Copyright (c) 2014 Barend Gehrels, Amsterdam, the Netherlands.
|
||||
// Copyright (c) 2014 Bruno Lalande, Paris, France.
|
||||
// Copyright (c) 2014 Mateusz Loskot, London, UK.
|
||||
// Copyright (c) 2014 Adam Wulkiewicz, Lodz, Poland.
|
||||
|
||||
// Use, modification and distribution is subject to the Boost Software License,
|
||||
// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
|
||||
// http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
#ifndef BOOST_GEOMETRY_POLICIES_ROBUSTNESS_RESCALE_POLICY_HPP
|
||||
#define BOOST_GEOMETRY_POLICIES_ROBUSTNESS_RESCALE_POLICY_HPP
|
||||
|
||||
#include <cstddef>
|
||||
|
||||
#include <boost/type_traits.hpp>
|
||||
|
||||
#include <boost/geometry/policies/robustness/segment_ratio_type.hpp>
|
||||
#include <boost/geometry/policies/robustness/robust_point_type.hpp>
|
||||
|
||||
namespace boost { namespace geometry
|
||||
{
|
||||
|
||||
#ifndef DOXYGEN_NO_DETAIL
|
||||
namespace detail
|
||||
{
|
||||
|
||||
template <typename FpPoint, typename IntPoint, typename CalculationType>
|
||||
struct robust_policy
|
||||
{
|
||||
static bool const enabled = true;
|
||||
|
||||
typedef typename geometry::coordinate_type<IntPoint>::type output_ct;
|
||||
|
||||
robust_policy(FpPoint const& fp_min, IntPoint const& int_min, CalculationType const& the_factor)
|
||||
: m_fp_min(fp_min)
|
||||
, m_int_min(int_min)
|
||||
, m_multiplier(the_factor)
|
||||
{
|
||||
}
|
||||
|
||||
template <std::size_t Dimension, typename Value>
|
||||
inline output_ct apply(Value const& value) const
|
||||
{
|
||||
// a + (v-b)*f
|
||||
CalculationType const a = static_cast<CalculationType>(get<Dimension>(m_int_min));
|
||||
CalculationType const b = static_cast<CalculationType>(get<Dimension>(m_fp_min));
|
||||
CalculationType const result = a + (value - b) * m_multiplier;
|
||||
return static_cast<output_ct>(result);
|
||||
}
|
||||
|
||||
FpPoint m_fp_min;
|
||||
IntPoint m_int_min;
|
||||
CalculationType m_multiplier;
|
||||
};
|
||||
|
||||
} // namespace detail
|
||||
#endif
|
||||
|
||||
|
||||
// Implement meta-functions for this policy
|
||||
|
||||
// Define the IntPoint as a robust-point type
|
||||
template <typename Point, typename FpPoint, typename IntPoint, typename CalculationType>
|
||||
struct robust_point_type<Point, detail::robust_policy<FpPoint, IntPoint, CalculationType> >
|
||||
{
|
||||
typedef IntPoint type;
|
||||
};
|
||||
|
||||
// Meta function for rescaling, if rescaling is done segment_ratio is based on long long
|
||||
template <typename Point, typename FpPoint, typename IntPoint, typename CalculationType>
|
||||
struct segment_ratio_type<Point, detail::robust_policy<FpPoint, IntPoint, CalculationType> >
|
||||
{
|
||||
typedef segment_ratio<boost::long_long_type> type;
|
||||
};
|
||||
|
||||
|
||||
}} // namespace boost::geometry
|
||||
|
||||
|
||||
#endif // BOOST_GEOMETRY_POLICIES_ROBUSTNESS_RESCALE_POLICY_HPP
|
||||
@@ -0,0 +1,28 @@
|
||||
// Boost.Geometry (aka GGL, Generic Geometry Library)
|
||||
|
||||
// Copyright (c) 2013 Barend Gehrels, Amsterdam, the Netherlands.
|
||||
// Copyright (c) 2013 Bruno Lalande, Paris, France.
|
||||
// Copyright (c) 2013 Mateusz Loskot, London, UK.
|
||||
// Copyright (c) 2013 Adam Wulkiewicz, Lodz, Poland.
|
||||
|
||||
// Use, modification and distribution is subject to the Boost Software License,
|
||||
// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
|
||||
// http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
#ifndef BOOST_GEOMETRY_POLICIES_ROBUSTNESS_ROBUST_POINT_TYPE_HPP
|
||||
#define BOOST_GEOMETRY_POLICIES_ROBUSTNESS_ROBUST_POINT_TYPE_HPP
|
||||
|
||||
#include <boost/geometry/algorithms/not_implemented.hpp>
|
||||
|
||||
namespace boost { namespace geometry
|
||||
{
|
||||
|
||||
// Meta-function to typedef a robust point type for a policy
|
||||
template <typename Point, typename Policy>
|
||||
struct robust_point_type {}; //: not_implemented<> {};
|
||||
|
||||
|
||||
}} // namespace boost::geometry
|
||||
|
||||
|
||||
#endif // BOOST_GEOMETRY_POLICIES_ROBUSTNESS_ROBUST_POINT_TYPE_HPP
|
||||
67
include/boost/geometry/policies/robustness/robust_type.hpp
Normal file
67
include/boost/geometry/policies/robustness/robust_type.hpp
Normal file
@@ -0,0 +1,67 @@
|
||||
// Boost.Geometry (aka GGL, Generic Geometry Library)
|
||||
|
||||
// Copyright (c) 2014 Barend Gehrels, Amsterdam, the Netherlands.
|
||||
// Copyright (c) 2014 Bruno Lalande, Paris, France.
|
||||
// Copyright (c) 2014 Mateusz Loskot, London, UK.
|
||||
// Copyright (c) 2014 Adam Wulkiewicz, Lodz, Poland.
|
||||
|
||||
// Use, modification and distribution is subject to the Boost Software License,
|
||||
// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
|
||||
// http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
#ifndef BOOST_GEOMETRY_POLICIES_ROBUSTNESS_ROBUST_TYPE_HPP
|
||||
#define BOOST_GEOMETRY_POLICIES_ROBUSTNESS_ROBUST_TYPE_HPP
|
||||
|
||||
|
||||
#include <boost/type_traits.hpp>
|
||||
#include <boost/config.hpp>
|
||||
|
||||
|
||||
namespace boost { namespace geometry
|
||||
{
|
||||
|
||||
#ifndef DOXYGEN_NO_DETAIL
|
||||
|
||||
namespace detail_dispatch
|
||||
{
|
||||
|
||||
template <typename CoordinateType, typename IsFloatingPoint>
|
||||
struct robust_type
|
||||
{
|
||||
};
|
||||
|
||||
template <typename CoordinateType>
|
||||
struct robust_type<CoordinateType, boost::false_type>
|
||||
{
|
||||
typedef CoordinateType type;
|
||||
};
|
||||
|
||||
template <typename CoordinateType>
|
||||
struct robust_type<CoordinateType, boost::true_type>
|
||||
{
|
||||
typedef boost::long_long_type type;
|
||||
};
|
||||
|
||||
} // namespace detail_dispatch
|
||||
|
||||
namespace detail
|
||||
{
|
||||
|
||||
template <typename CoordinateType>
|
||||
struct robust_type
|
||||
{
|
||||
typedef typename detail_dispatch::robust_type
|
||||
<
|
||||
CoordinateType,
|
||||
typename boost::is_floating_point<CoordinateType>::type
|
||||
>::type type;
|
||||
};
|
||||
|
||||
} // namespace detail
|
||||
#endif // DOXYGEN_NO_DETAIL
|
||||
|
||||
|
||||
}} // namespace boost::geometry
|
||||
|
||||
|
||||
#endif // BOOST_GEOMETRY_POLICIES_ROBUSTNESS_ROBUST_TYPE_HPP
|
||||
236
include/boost/geometry/policies/robustness/segment_ratio.hpp
Normal file
236
include/boost/geometry/policies/robustness/segment_ratio.hpp
Normal file
@@ -0,0 +1,236 @@
|
||||
// Boost.Geometry (aka GGL, Generic Geometry Library)
|
||||
|
||||
// Copyright (c) 2013 Barend Gehrels, Amsterdam, the Netherlands.
|
||||
|
||||
// Use, modification and distribution is subject to the Boost Software License,
|
||||
// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
|
||||
// http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
#ifndef BOOST_GEOMETRY_POLICIES_ROBUSTNESS_SEGMENT_RATIO_HPP
|
||||
#define BOOST_GEOMETRY_POLICIES_ROBUSTNESS_SEGMENT_RATIO_HPP
|
||||
|
||||
#include <boost/assert.hpp>
|
||||
#include <boost/config.hpp>
|
||||
#include <boost/rational.hpp>
|
||||
|
||||
#include <boost/geometry/util/math.hpp>
|
||||
#include <boost/geometry/util/promote_floating_point.hpp>
|
||||
|
||||
namespace boost { namespace geometry
|
||||
{
|
||||
|
||||
|
||||
namespace detail { namespace segment_ratio
|
||||
{
|
||||
|
||||
template
|
||||
<
|
||||
typename Type,
|
||||
bool IsIntegral = boost::is_integral<Type>::type::value
|
||||
>
|
||||
struct less {};
|
||||
|
||||
template <typename Type>
|
||||
struct less<Type, true>
|
||||
{
|
||||
template <typename Ratio>
|
||||
static inline bool apply(Ratio const& lhs, Ratio const& rhs)
|
||||
{
|
||||
return boost::rational<Type>(lhs.numerator(), lhs.denominator())
|
||||
< boost::rational<Type>(rhs.numerator(), rhs.denominator());
|
||||
}
|
||||
};
|
||||
|
||||
template <typename Type>
|
||||
struct less<Type, false>
|
||||
{
|
||||
template <typename Ratio>
|
||||
static inline bool apply(Ratio const& lhs, Ratio const& rhs)
|
||||
{
|
||||
BOOST_ASSERT(lhs.denominator() != 0);
|
||||
BOOST_ASSERT(rhs.denominator() != 0);
|
||||
return lhs.numerator() * rhs.denominator()
|
||||
< rhs.numerator() * lhs.denominator();
|
||||
}
|
||||
};
|
||||
|
||||
template
|
||||
<
|
||||
typename Type,
|
||||
bool IsIntegral = boost::is_integral<Type>::type::value
|
||||
>
|
||||
struct equal {};
|
||||
|
||||
template <typename Type>
|
||||
struct equal<Type, true>
|
||||
{
|
||||
template <typename Ratio>
|
||||
static inline bool apply(Ratio const& lhs, Ratio const& rhs)
|
||||
{
|
||||
return boost::rational<Type>(lhs.numerator(), lhs.denominator())
|
||||
== boost::rational<Type>(rhs.numerator(), rhs.denominator());
|
||||
}
|
||||
};
|
||||
|
||||
template <typename Type>
|
||||
struct equal<Type, false>
|
||||
{
|
||||
template <typename Ratio>
|
||||
static inline bool apply(Ratio const& lhs, Ratio const& rhs)
|
||||
{
|
||||
BOOST_ASSERT(lhs.denominator() != 0);
|
||||
BOOST_ASSERT(rhs.denominator() != 0);
|
||||
return geometry::math::equals
|
||||
(
|
||||
lhs.numerator() * rhs.denominator(),
|
||||
rhs.numerator() * lhs.denominator()
|
||||
);
|
||||
}
|
||||
};
|
||||
|
||||
}}
|
||||
|
||||
//! Small class to keep a ratio (e.g. 1/4)
|
||||
//! Main purpose is intersections and checking on 0, 1, and smaller/larger
|
||||
//! The prototype used Boost.Rational. However, we also want to store FP ratios,
|
||||
//! (so numerator/denominator both in float)
|
||||
//! and Boost.Rational starts with GCD which we prefer to avoid if not necessary
|
||||
//! On a segment means: this ratio is between 0 and 1 (both inclusive)
|
||||
//!
|
||||
template <typename Type>
|
||||
class segment_ratio
|
||||
{
|
||||
public :
|
||||
typedef Type numeric_type;
|
||||
|
||||
// Type-alias for the type itself
|
||||
typedef segment_ratio<Type> thistype;
|
||||
|
||||
inline segment_ratio()
|
||||
: m_numerator(0)
|
||||
, m_denominator(1)
|
||||
, m_approximation(0)
|
||||
{}
|
||||
|
||||
inline segment_ratio(const Type& nominator, const Type& denominator)
|
||||
: m_numerator(nominator)
|
||||
, m_denominator(denominator)
|
||||
{
|
||||
initialize();
|
||||
}
|
||||
|
||||
inline Type const& numerator() const { return m_numerator; }
|
||||
inline Type const& denominator() const { return m_denominator; }
|
||||
|
||||
inline void assign(const Type& nominator, const Type& denominator)
|
||||
{
|
||||
m_numerator = nominator;
|
||||
m_denominator = denominator;
|
||||
initialize();
|
||||
}
|
||||
|
||||
inline void initialize()
|
||||
{
|
||||
// Minimal normalization
|
||||
// 1/-4 => -1/4, -1/-4 => 1/4
|
||||
if (m_denominator < 0)
|
||||
{
|
||||
m_numerator = -m_numerator;
|
||||
m_denominator = -m_denominator;
|
||||
}
|
||||
|
||||
typedef typename promote_floating_point<Type>::type num_type;
|
||||
static const num_type scale = 1000000.0;
|
||||
m_approximation =
|
||||
m_denominator == 0 ? 0
|
||||
: boost::numeric_cast<int>
|
||||
(
|
||||
boost::numeric_cast<num_type>(m_numerator) * scale
|
||||
/ boost::numeric_cast<num_type>(m_denominator)
|
||||
);
|
||||
}
|
||||
|
||||
inline bool is_zero() const { return math::equals(m_numerator, 0); }
|
||||
inline bool is_one() const { return math::equals(m_numerator, m_denominator); }
|
||||
inline bool on_segment() const
|
||||
{
|
||||
// e.g. 0/4 or 4/4 or 2/4
|
||||
return m_numerator >= 0 && m_numerator <= m_denominator;
|
||||
}
|
||||
inline bool in_segment() const
|
||||
{
|
||||
// e.g. 1/4
|
||||
return m_numerator > 0 && m_numerator < m_denominator;
|
||||
}
|
||||
inline bool on_end() const
|
||||
{
|
||||
// e.g. 0/4 or 4/4
|
||||
return is_zero() || is_one();
|
||||
}
|
||||
inline bool left() const
|
||||
{
|
||||
// e.g. -1/4
|
||||
return m_numerator < 0;
|
||||
}
|
||||
inline bool right() const
|
||||
{
|
||||
// e.g. 5/4
|
||||
return m_numerator > m_denominator;
|
||||
}
|
||||
|
||||
inline bool close_to(thistype const& other) const
|
||||
{
|
||||
return geometry::math::abs(m_approximation - other.m_approximation) < 2;
|
||||
}
|
||||
|
||||
inline bool operator< (thistype const& other) const
|
||||
{
|
||||
return close_to(other)
|
||||
? detail::segment_ratio::less<Type>::apply(*this, other)
|
||||
: m_approximation < other.m_approximation;
|
||||
}
|
||||
|
||||
inline bool operator== (thistype const& other) const
|
||||
{
|
||||
return close_to(other)
|
||||
&& detail::segment_ratio::equal<Type>::apply(*this, other);
|
||||
}
|
||||
|
||||
static inline thistype zero()
|
||||
{
|
||||
static thistype result(0, 1);
|
||||
return result;
|
||||
}
|
||||
|
||||
static inline thistype one()
|
||||
{
|
||||
static thistype result(1, 1);
|
||||
return result;
|
||||
}
|
||||
|
||||
#if defined(BOOST_GEOMETRY_DEFINE_STREAM_OPERATOR_SEGMENT_RATIO)
|
||||
friend std::ostream& operator<<(std::ostream &os, segment_ratio const& ratio)
|
||||
{
|
||||
os << ratio.m_numerator << "/" << ratio.m_denominator;
|
||||
return os;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
private :
|
||||
Type m_numerator;
|
||||
Type m_denominator;
|
||||
|
||||
// Contains ratio on scale 0..1000000 (for 0..1)
|
||||
// This is an approximation for fast and rough comparisons
|
||||
// Boost.Rational is used if the approximations are close.
|
||||
// Reason: performance, Boost.Rational does a GCD by default and also the
|
||||
// comparisons contain while-loops.
|
||||
int m_approximation;
|
||||
};
|
||||
|
||||
|
||||
}} // namespace boost::geometry
|
||||
|
||||
#endif // BOOST_GEOMETRY_POLICIES_ROBUSTNESS_SEGMENT_RATIO_HPP
|
||||
@@ -9,24 +9,20 @@
|
||||
// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
|
||||
// http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_RESCALE_HPP
|
||||
#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_RESCALE_HPP
|
||||
#ifndef BOOST_GEOMETRY_POLICIES_ROBUSTNESS_SEGMENT_RATIO_TYPE_HPP
|
||||
#define BOOST_GEOMETRY_POLICIES_ROBUSTNESS_SEGMENT_RATIO_TYPE_HPP
|
||||
|
||||
#include <boost/geometry/algorithms/not_implemented.hpp>
|
||||
|
||||
namespace boost { namespace geometry
|
||||
{
|
||||
|
||||
#ifndef DOXYGEN_NO_DETAIL
|
||||
// Meta-function to access segment-ratio for a policy
|
||||
template <typename Point, typename Policy>
|
||||
struct segment_ratio_type {}; // : not_implemented<> {};
|
||||
|
||||
// To be removed later, when we will initialize a real policy
|
||||
namespace detail
|
||||
{
|
||||
struct no_rescale_policy {};
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
}} // namespace boost::geometry
|
||||
|
||||
|
||||
#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_RESCALE_HPP
|
||||
#endif // BOOST_GEOMETRY_POLICIES_ROBUSTNESS_SEGMENT_RATIO_TYPE_HPP
|
||||
@@ -319,7 +319,7 @@ private:
|
||||
typedef typename strategy::side::services::default_strategy<cs_tag>::type side;
|
||||
|
||||
output.push_back(p);
|
||||
register std::size_t output_size = output.size();
|
||||
std::size_t output_size = output.size();
|
||||
while (output_size >= 3)
|
||||
{
|
||||
rev_iterator rit = output.rbegin();
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -20,38 +20,44 @@
|
||||
#include <boost/geometry/strategies/intersection_result.hpp>
|
||||
|
||||
#include <boost/geometry/strategies/cartesian/cart_intersect.hpp>
|
||||
#include <boost/geometry/policies/robustness/segment_ratio_type.hpp>
|
||||
|
||||
|
||||
namespace boost { namespace geometry
|
||||
{
|
||||
|
||||
|
||||
// The intersection strategy is a "compound strategy",
|
||||
// it contains a segment-intersection-strategy
|
||||
// and a side-strategy
|
||||
/*!
|
||||
\tparam CalculationType \tparam_calculation
|
||||
*/
|
||||
\brief "compound strategy", containing a segment-intersection-strategy
|
||||
and a side-strategy
|
||||
*/
|
||||
template
|
||||
<
|
||||
typename Tag,
|
||||
typename Geometry1,
|
||||
typename Geometry2,
|
||||
typename IntersectionPoint,
|
||||
typename RobustPolicy,
|
||||
typename CalculationType = void
|
||||
>
|
||||
struct strategy_intersection
|
||||
{
|
||||
private :
|
||||
// for development BOOST_STATIC_ASSERT((! boost::is_same<RobustPolicy, void>::type::value));
|
||||
|
||||
typedef typename geometry::point_type<Geometry1>::type point1_type;
|
||||
typedef typename geometry::point_type<Geometry2>::type point2_type;
|
||||
typedef typename model::referring_segment<point1_type const> segment1_type;
|
||||
typedef typename model::referring_segment<point2_type const> segment2_type;
|
||||
|
||||
typedef segment_intersection_points
|
||||
<
|
||||
IntersectionPoint,
|
||||
typename geometry::segment_ratio_type
|
||||
<
|
||||
IntersectionPoint
|
||||
> ip_type;
|
||||
IntersectionPoint, RobustPolicy
|
||||
>::type
|
||||
> ip_type;
|
||||
|
||||
public:
|
||||
typedef strategy::intersection::relate_cartesian_segments
|
||||
@@ -60,18 +66,9 @@ public:
|
||||
<
|
||||
policies::relate::segments_intersection_points
|
||||
<
|
||||
segment1_type,
|
||||
segment2_type,
|
||||
ip_type,
|
||||
CalculationType
|
||||
ip_type
|
||||
> ,
|
||||
policies::relate::segments_direction
|
||||
<
|
||||
segment1_type,
|
||||
segment2_type,
|
||||
CalculationType
|
||||
>,
|
||||
CalculationType
|
||||
>,
|
||||
CalculationType
|
||||
> segment_intersection_strategy_type;
|
||||
@@ -81,6 +78,8 @@ public:
|
||||
Tag,
|
||||
CalculationType
|
||||
>::type side_strategy_type;
|
||||
|
||||
typedef RobustPolicy rescale_policy_type;
|
||||
};
|
||||
|
||||
|
||||
|
||||
@@ -16,6 +16,7 @@
|
||||
#include <cstddef>
|
||||
|
||||
|
||||
|
||||
namespace boost { namespace geometry
|
||||
{
|
||||
|
||||
@@ -153,13 +154,47 @@ struct de9im_segment : public de9im
|
||||
#endif
|
||||
};
|
||||
|
||||
template <typename SegmentRatio>
|
||||
struct fraction_type
|
||||
{
|
||||
SegmentRatio robust_ra; // TODO this can be renamed now to "ra"
|
||||
SegmentRatio robust_rb;
|
||||
|
||||
bool initialized;
|
||||
inline fraction_type()
|
||||
: initialized(false)
|
||||
{}
|
||||
|
||||
template <typename Point>
|
||||
template <typename Info>
|
||||
inline void assign(Info const& info)
|
||||
{
|
||||
initialized = true;
|
||||
robust_ra = info.robust_ra;
|
||||
robust_rb = info.robust_rb;
|
||||
}
|
||||
|
||||
inline void assign(SegmentRatio const& a, SegmentRatio const& b)
|
||||
{
|
||||
initialized = true;
|
||||
robust_ra = a;
|
||||
robust_rb = b;
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
//
|
||||
/*!
|
||||
\brief return-type for segment-intersection
|
||||
\note Set in intersection_points.hpp, from segment_intersection_info
|
||||
*/
|
||||
template <typename Point, typename SegmentRatio>
|
||||
struct segment_intersection_points
|
||||
{
|
||||
std::size_t count;
|
||||
std::size_t count; // The number of intersection points
|
||||
|
||||
// TODO: combine intersections and fractions in one struct
|
||||
Point intersections[2];
|
||||
fraction_type<SegmentRatio> fractions[2];
|
||||
typedef Point point_type;
|
||||
|
||||
segment_intersection_points()
|
||||
@@ -167,6 +202,18 @@ struct segment_intersection_points
|
||||
{}
|
||||
};
|
||||
|
||||
// All assigned in cart_intersect, passed to intersection_points
|
||||
template <typename CoordinateType, typename PromotedType, typename SegmentRatio>
|
||||
struct segment_intersection_info
|
||||
{
|
||||
typedef PromotedType promoted_type;
|
||||
|
||||
CoordinateType dx_a, dy_a;
|
||||
CoordinateType dx_b, dy_b; // TODO b can be removed
|
||||
SegmentRatio robust_ra;
|
||||
SegmentRatio robust_rb;
|
||||
};
|
||||
|
||||
|
||||
}} // namespace boost::geometry
|
||||
|
||||
|
||||
116
include/boost/geometry/views/normalized_view.hpp
Normal file
116
include/boost/geometry/views/normalized_view.hpp
Normal file
@@ -0,0 +1,116 @@
|
||||
// Boost.Geometry (aka GGL, Generic Geometry Library)
|
||||
|
||||
// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.
|
||||
// Copyright (c) 2008-2012 Bruno Lalande, Paris, France.
|
||||
// Copyright (c) 2009-2012 Mateusz Loskot, London, UK.
|
||||
|
||||
// This file was modified by Oracle on 2014.
|
||||
// Modifications copyright (c) 2014 Oracle and/or its affiliates.
|
||||
|
||||
// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library
|
||||
// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands.
|
||||
|
||||
// Use, modification and distribution is subject to the Boost Software License,
|
||||
// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
|
||||
// http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
|
||||
|
||||
#ifndef BOOST_GEOMETRY_VIEWS_NORMALIZED_VIEW_HPP
|
||||
#define BOOST_GEOMETRY_VIEWS_NORMALIZED_VIEW_HPP
|
||||
|
||||
|
||||
#include <boost/range/begin.hpp>
|
||||
#include <boost/range/end.hpp>
|
||||
#include <boost/range/iterator.hpp>
|
||||
#include <boost/mpl/if.hpp>
|
||||
#include <boost/type_traits/is_const.hpp>
|
||||
#include <boost/geometry/views/detail/range_type.hpp>
|
||||
#include <boost/geometry/views/reversible_view.hpp>
|
||||
#include <boost/geometry/views/closeable_view.hpp>
|
||||
|
||||
namespace boost { namespace geometry {
|
||||
|
||||
|
||||
#ifndef DOXYGEN_NO_DETAIL
|
||||
|
||||
namespace detail {
|
||||
|
||||
template <typename Geometry>
|
||||
struct normalized_view
|
||||
{
|
||||
static const bool is_const = boost::is_const<Geometry>::value;
|
||||
|
||||
//typedef typename ring_type<Geometry>::type ring_type;
|
||||
|
||||
typedef typename detail::range_type<Geometry>::type range_type;
|
||||
|
||||
typedef typename
|
||||
boost::mpl::if_c
|
||||
<
|
||||
is_const,
|
||||
range_type const,
|
||||
range_type
|
||||
>::type range;
|
||||
|
||||
typedef typename
|
||||
reversible_view
|
||||
<
|
||||
range,
|
||||
order_as_direction
|
||||
<
|
||||
geometry::point_order<Geometry>::value
|
||||
>::value
|
||||
>::type reversible_type;
|
||||
|
||||
typedef typename
|
||||
boost::mpl::if_c
|
||||
<
|
||||
is_const,
|
||||
reversible_type const,
|
||||
reversible_type
|
||||
>::type reversible;
|
||||
|
||||
typedef typename
|
||||
closeable_view
|
||||
<
|
||||
reversible,
|
||||
geometry::closure<Geometry>::value
|
||||
>::type closeable_type;
|
||||
|
||||
typedef typename
|
||||
boost::mpl::if_c
|
||||
<
|
||||
is_const,
|
||||
closeable_type const,
|
||||
closeable_type
|
||||
>::type closeable;
|
||||
|
||||
explicit inline normalized_view(range & r)
|
||||
: m_reversible(r)
|
||||
, m_closeable(m_reversible)
|
||||
{}
|
||||
|
||||
typedef typename boost::range_iterator<closeable>::type iterator;
|
||||
typedef typename boost::range_const_iterator<closeable>::type const_iterator;
|
||||
|
||||
inline const_iterator begin() const { return boost::begin(m_closeable); }
|
||||
inline const_iterator end() const { return boost::end(m_closeable); }
|
||||
|
||||
inline iterator begin() { return boost::begin(m_closeable); }
|
||||
inline iterator end() { return boost::end(m_closeable); }
|
||||
|
||||
private:
|
||||
reversible_type m_reversible;
|
||||
closeable_type m_closeable;
|
||||
};
|
||||
|
||||
} // namespace detail
|
||||
|
||||
#endif // DOXYGEN_NO_DETAIL
|
||||
|
||||
|
||||
}} // namespace boost::geometry
|
||||
|
||||
|
||||
#endif // BOOST_GEOMETRY_VIEWS_NORMALIZED_VIEW_HPP
|
||||
@@ -20,7 +20,7 @@ project boost-geometry-index-test
|
||||
test-suite boost-geometry-index-varray
|
||||
:
|
||||
[ run varray_old.cpp ]
|
||||
[ run varray.cpp ]
|
||||
[ run varray.cpp : : : <toolset>msvc:<cxxflags>/bigobj ]
|
||||
;
|
||||
|
||||
build-project algorithms ;
|
||||
|
||||
@@ -12,7 +12,12 @@ rule test_all
|
||||
|
||||
for local fileb in [ glob *.cpp ]
|
||||
{
|
||||
all_rules += [ run $(fileb) ] ;
|
||||
all_rules += [ run $(fileb)
|
||||
: # additional args
|
||||
: # test-files
|
||||
: # requirements
|
||||
<toolset>msvc:<cxxflags>/bigobj
|
||||
] ;
|
||||
}
|
||||
|
||||
return $(all_rules) ;
|
||||
|
||||
@@ -12,7 +12,12 @@ rule test_all
|
||||
|
||||
for local fileb in [ glob *.cpp ]
|
||||
{
|
||||
all_rules += [ run $(fileb) ] ;
|
||||
all_rules += [ run $(fileb)
|
||||
: # additional args
|
||||
: # test-files
|
||||
: # requirements
|
||||
<toolset>msvc:<cxxflags>/bigobj
|
||||
] ;
|
||||
}
|
||||
|
||||
return $(all_rules) ;
|
||||
|
||||
@@ -18,9 +18,11 @@ rule test_all
|
||||
: # requirements
|
||||
<toolset>acc:<linkflags>-lrt
|
||||
<toolset>acc-pa_risc:<linkflags>-lrt
|
||||
<toolset>gcc-mingw:<linkflags>"-lole32 -loleaut32 -lpsapi -ladvapi32"
|
||||
<host-os>hpux,<toolset>gcc:<linkflags>"-Wl,+as,mpas"
|
||||
# <toolset>gcc-mingw:<linkflags>"-lole32 -loleaut32 -lpsapi -ladvapi32"
|
||||
<toolset>gcc,<target-os>windows:<linkflags>"-lole32 -loleaut32 -lpsapi -ladvapi32"
|
||||
<host-os>windows,<toolset>clang:<linkflags>"-lole32 -loleaut32 -lpsapi -ladvapi32"
|
||||
<toolset>msvc:<cxxflags>/bigobj
|
||||
] ;
|
||||
}
|
||||
|
||||
|
||||
@@ -13,8 +13,6 @@
|
||||
# Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
|
||||
# http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
import testing ;
|
||||
|
||||
test-suite boost-geometry-algorithms
|
||||
:
|
||||
[ run append.cpp : : : <toolset>msvc:<cxxflags>/bigobj ]
|
||||
@@ -29,8 +27,8 @@ test-suite boost-geometry-algorithms
|
||||
[ run covered_by.cpp ]
|
||||
[ run crosses.cpp ]
|
||||
[ run difference.cpp : : : <define>BOOST_GEOMETRY_TEST_ONLY_ONE_TYPE <toolset>msvc:<cxxflags>/bigobj ]
|
||||
[ run difference_linear_linear.cpp /boost/test//boost_unit_test_framework ]
|
||||
[ run difference_pl_pl.cpp /boost/test//boost_unit_test_framework ]
|
||||
[ run difference_linear_linear.cpp ]
|
||||
[ run difference_pl_pl.cpp ]
|
||||
[ run disjoint.cpp ]
|
||||
[ run distance.cpp : : : <toolset>msvc:<cxxflags>/bigobj ]
|
||||
[ run envelope.cpp ]
|
||||
@@ -38,26 +36,33 @@ test-suite boost-geometry-algorithms
|
||||
[ run expand.cpp ]
|
||||
[ run for_each.cpp ]
|
||||
[ run intersection.cpp : : : <define>BOOST_GEOMETRY_TEST_ONLY_ONE_TYPE <toolset>msvc:<cxxflags>/bigobj ]
|
||||
[ run intersection_linear_linear.cpp /boost/test//boost_unit_test_framework ]
|
||||
[ run intersection_pl_pl.cpp /boost/test//boost_unit_test_framework ]
|
||||
[ run intersection_linear_linear.cpp ]
|
||||
[ run intersection_pl_pl.cpp ]
|
||||
[ run intersects.cpp : : : <toolset>msvc:<cxxflags>/bigobj ]
|
||||
[ run length.cpp ]
|
||||
[ run make.cpp ]
|
||||
[ run overlaps.cpp ]
|
||||
[ run perimeter.cpp ]
|
||||
[ run point_on_surface.cpp ]
|
||||
[ run relate.cpp ]
|
||||
[ run relate_areal_areal.cpp : : : <toolset>msvc:<cxxflags>/bigobj ]
|
||||
[ run relate_linear_areal.cpp : : : <toolset>msvc:<cxxflags>/bigobj ]
|
||||
[ run relate_linear_linear.cpp : : : <toolset>msvc:<cxxflags>/bigobj ]
|
||||
[ run relate_pointlike_xxx.cpp : : : <toolset>msvc:<cxxflags>/bigobj ]
|
||||
[ run remove_spikes.cpp ]
|
||||
[ run reverse.cpp ]
|
||||
[ run simplify.cpp ]
|
||||
[ run sym_difference_linear_linear.cpp /boost/test//boost_unit_test_framework ]
|
||||
[ run sym_difference_linear_linear.cpp ]
|
||||
[ run touches.cpp ]
|
||||
[ run transform.cpp ]
|
||||
[ run union.cpp : : : <define>BOOST_GEOMETRY_TEST_ONLY_ONE_TYPE ]
|
||||
[ run union_linear_linear.cpp /boost/test//boost_unit_test_framework ]
|
||||
[ run union_pl_pl.cpp /boost/test//boost_unit_test_framework ]
|
||||
[ run union_linear_linear.cpp ]
|
||||
[ run union_pl_pl.cpp ]
|
||||
[ run unique.cpp ]
|
||||
[ run within.cpp : : : <toolset>msvc:<cxxflags>/bigobj ]
|
||||
[ run within_areal_areal.cpp : : : <toolset>msvc:<cxxflags>/bigobj ]
|
||||
[ run within_linear_areal.cpp : : : <toolset>msvc:<cxxflags>/bigobj ]
|
||||
[ run within_linear_linear.cpp : : : <toolset>msvc:<cxxflags>/bigobj ]
|
||||
[ run within_pointlike_xxx.cpp : : : <toolset>msvc:<cxxflags>/bigobj ]
|
||||
;
|
||||
|
||||
build-project overlay
|
||||
|
||||
@@ -10,6 +10,7 @@
|
||||
|
||||
test-suite boost-geometry-algorithms-detail
|
||||
:
|
||||
[ run intersection_side.cpp ]
|
||||
[ run partition.cpp ]
|
||||
;
|
||||
|
||||
|
||||
197
test/algorithms/detail/intersection_side.cpp
Normal file
197
test/algorithms/detail/intersection_side.cpp
Normal file
@@ -0,0 +1,197 @@
|
||||
// Boost.Geometry (aka GGL, Generic Geometry Library)
|
||||
//
|
||||
// Copyright (c) 2007-2014 Barend Gehrels, Amsterdam, the Netherlands.
|
||||
// Use, modification and distribution is subject to the Boost Software License,
|
||||
// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
|
||||
// http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
#define BOOST_GEOMETRY_DEFINE_STREAM_OPERATOR_SEGMENT_RATIO
|
||||
|
||||
#include <geometry_test_common.hpp>
|
||||
|
||||
#include <boost/geometry/geometries/point_xy.hpp>
|
||||
|
||||
#include <boost/geometry/strategies/cartesian/cart_intersect.hpp>
|
||||
#include <boost/geometry/strategies/intersection_result.hpp>
|
||||
#include <boost/geometry/policies/relate/intersection_points.hpp>
|
||||
#include <boost/geometry/policies/relate/intersection_ratios.hpp>
|
||||
#include <boost/geometry/policies/robustness/no_rescale_policy.hpp>
|
||||
#include <boost/geometry/algorithms/detail/intersection_side.hpp>
|
||||
#include <boost/geometry/algorithms/make.hpp>
|
||||
|
||||
#if defined(TEST_WITH_SVG)
|
||||
# include <boost/geometry/io/svg/svg_mapper.hpp>
|
||||
#endif
|
||||
|
||||
|
||||
template <typename Point, typename T>
|
||||
void test_one(std::string const& caseid,
|
||||
T pi_x, T pi_y, T pj_x, T pj_y, // line p to intersect
|
||||
T qi_x, T qi_y, T qj_x, T qj_y, // line q to intersect
|
||||
T si_x, T si_y, T sj_x, T sj_y, // subject line to find side on of IP p/q
|
||||
int expected_side)
|
||||
{
|
||||
typedef bg::detail::no_rescale_policy robust_policy_type;
|
||||
robust_policy_type robust_policy;
|
||||
|
||||
Point pi = bg::make<Point>(pi_x, pi_y);
|
||||
Point pj = bg::make<Point>(pj_x, pj_y);
|
||||
Point qi = bg::make<Point>(qi_x, qi_y);
|
||||
Point qj = bg::make<Point>(qj_x, qj_y);
|
||||
Point si = bg::make<Point>(si_x, si_y);
|
||||
Point sj = bg::make<Point>(sj_x, sj_y);
|
||||
|
||||
typedef bg::model::referring_segment<const Point> segment_type;
|
||||
|
||||
segment_type p(pi, pj);
|
||||
segment_type q(qi, qj);
|
||||
segment_type s(si, sj);
|
||||
|
||||
int detected_side = bg::detail::intersection_side::intersection_side(pi, pj,
|
||||
qi, qj, si, sj, robust_policy);
|
||||
|
||||
BOOST_CHECK_EQUAL(expected_side, detected_side);
|
||||
|
||||
#if defined(TEST_WITH_SVG)
|
||||
{
|
||||
std::ostringstream filename;
|
||||
filename << "intersection_side_" << caseid
|
||||
<< "_" << string_from_type<typename bg::coordinate_type<Point>::type>::name()
|
||||
<< ".svg";
|
||||
|
||||
std::ofstream svg(filename.str().c_str());
|
||||
|
||||
bg::svg_mapper<Point> mapper(svg, 500, 500);
|
||||
mapper.add(p);
|
||||
mapper.add(q);
|
||||
mapper.add(s);
|
||||
|
||||
mapper.map(p, "opacity:0.7;stroke:rgb(0,192,0);stroke-width:3");
|
||||
mapper.map(q, "opacity:0.7;stroke:rgb(0,0,255);stroke-width:3");
|
||||
mapper.map(s, "opacity:0.7;stroke:rgb(255,0,0);stroke-width:2");
|
||||
|
||||
std::string style = ";font-family='Verdana';font-weight:bold";
|
||||
std::string align = ";text-anchor:end;text-align:end";
|
||||
int offset = 8;
|
||||
|
||||
mapper.text(pi, "pi", "fill:rgb(0,192,0)" + style, offset, offset);
|
||||
mapper.text(pj, "pj", "fill:rgb(0,192,0)" + style, offset, offset);
|
||||
|
||||
mapper.text(qi, "qi", "fill:rgb(0,0,255)" + style + align, -offset, offset);
|
||||
mapper.text(qj, "qj", "fill:rgb(0,0,255)" + style + align, -offset, offset);
|
||||
|
||||
mapper.text(si, "si", "fill:rgb(255,0,0)" + style + align, -offset, offset);
|
||||
mapper.text(sj, "sj", "fill:rgb(255,0,0)" + style + align, -offset, offset);
|
||||
|
||||
// Map the intersection point on the SVG
|
||||
{
|
||||
typedef typename bg::segment_ratio_type
|
||||
<
|
||||
Point,
|
||||
robust_policy_type
|
||||
>::type segment_ratio_type;
|
||||
|
||||
// Get the intersection point (or two points)
|
||||
bg::segment_intersection_points<Point, segment_ratio_type> is
|
||||
= bg::strategy::intersection::relate_cartesian_segments
|
||||
<
|
||||
bg::policies::relate::segments_intersection_points
|
||||
<
|
||||
bg::segment_intersection_points<Point, segment_ratio_type>
|
||||
>
|
||||
>::apply(p, q, robust_policy);
|
||||
|
||||
bg::fraction_type<segment_ratio_type> rs
|
||||
= bg::strategy::intersection::relate_cartesian_segments
|
||||
<
|
||||
bg::policies::relate::segments_intersection_ratios
|
||||
<
|
||||
bg::fraction_type<segment_ratio_type>
|
||||
>
|
||||
>::apply(p, q, robust_policy);
|
||||
|
||||
for (int i = 0; i < is.count; i++)
|
||||
{
|
||||
mapper.map(is.intersections[i], "opacity:0.8;stroke:rgb(255,128,0);stroke-width:3", 3);
|
||||
std::ostringstream out;
|
||||
out << detected_side << " " << is.fractions[i].robust_ra << " / " << is.fractions[i].robust_rb
|
||||
<< std::endl
|
||||
<< rs.robust_ra << " / " << rs.robust_rb;
|
||||
mapper.text(is.intersections[i], out.str(), "fill:rgb(255,128,0)" + style + align, -2 * offset, offset);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
|
||||
template <typename P>
|
||||
void test_all()
|
||||
{
|
||||
test_one<P, double>("simplex_left",
|
||||
0, 0, 4, 4, // p
|
||||
-1, 4, 3, 0, // q
|
||||
2, 0, 2, 4, // subject
|
||||
1);
|
||||
test_one<P, double>("simplex_right",
|
||||
0, 0, 4, 4, // p
|
||||
1, 4, 5, 0, // q
|
||||
2, 0, 2, 4, // subject
|
||||
-1);
|
||||
test_one<P, double>("simplex_collinear",
|
||||
0, 0, 4, 4, // p
|
||||
0, 4, 4, 0, // q
|
||||
2, 0, 2, 4, // subject
|
||||
0);
|
||||
|
||||
test_one<P, double>("p_left",
|
||||
0, 0, 0, 4, // p
|
||||
1, 4, 5, 0, // q
|
||||
2, 0, 2, 4, // subject
|
||||
1);
|
||||
|
||||
test_one<P, double>("p_right",
|
||||
4, 0, 4, 4, // p
|
||||
1, 4, 5, 0, // q
|
||||
2, 0, 2, 4, // subject
|
||||
-1);
|
||||
test_one<P, double>("p_left",
|
||||
1, 0, 1, 4, // p
|
||||
1, 4, 5, 0, // q
|
||||
2, 0, 2, 4, // subject
|
||||
1);
|
||||
|
||||
test_one<P, double>("p_collinear",
|
||||
2, -1, 2, 5, // p
|
||||
1, 4, 5, 0, // q
|
||||
2, 0, 2, 4, // subject
|
||||
0);
|
||||
|
||||
test_one<P, double>("q_left",
|
||||
0, 0, 4, 4, // p
|
||||
1, 4, 1, 0, // q
|
||||
2, 0, 2, 4, // subject
|
||||
1);
|
||||
|
||||
test_one<P, double>("q_right",
|
||||
0, 0, 4, 4, // p
|
||||
3, 4, 3, 0, // q
|
||||
2, 0, 2, 4, // subject
|
||||
-1);
|
||||
|
||||
test_one<P, double>("q_collinear",
|
||||
0, 0, 4, 4, // p
|
||||
2, 1, 2, 3, // q
|
||||
2, 0, 2, 4, // subject
|
||||
0);
|
||||
}
|
||||
|
||||
|
||||
int test_main( int , char* [] )
|
||||
{
|
||||
test_all<bg::model::d2::point_xy<double> >();
|
||||
|
||||
return 0;
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user