mirror of
https://github.com/boostorg/geometry.git
synced 2026-02-02 21:02:13 +00:00
Merge branch 'develop' into bg-prepare
Conflicts: test/algorithms/buffer/multi_point_buffer.cpp
This commit is contained in:
@@ -1,9 +1,9 @@
|
||||
[/============================================================================
|
||||
Boost.Geometry (aka GGL, Generic Geometry Library)
|
||||
|
||||
Copyright (c) 2009-2012 Barend Gehrels, Amsterdam, the Netherlands.
|
||||
Copyright (c) 2009-2012 Mateusz Loskot, London, UK.
|
||||
Copyright (c) 2009-2012 Bruno Lalande, Paris, France.
|
||||
Copyright (c) 2009-2015 Barend Gehrels, Amsterdam, the Netherlands.
|
||||
Copyright (c) 2009-2015 Mateusz Loskot, London, UK.
|
||||
Copyright (c) 2009-2015 Bruno Lalande, Paris, France.
|
||||
|
||||
Use, modification and distribution is subject to the Boost Software License,
|
||||
Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
|
||||
@@ -13,7 +13,7 @@
|
||||
[library Geometry
|
||||
[quickbook 1.5]
|
||||
[authors [Gehrels, Barend], [Lalande, Bruno], [Loskot, Mateusz], [Wulkiewicz, Adam], [Karavelas, Menelaos]]
|
||||
[copyright 2009-2014 Barend Gehrels, Bruno Lalande, Mateusz Loskot, Adam Wulkiewicz, Oracle and/or its affiliates]
|
||||
[copyright 2009-2015 Barend Gehrels, Bruno Lalande, Mateusz Loskot, Adam Wulkiewicz, Oracle and/or its affiliates]
|
||||
[purpose Documentation of Boost.Geometry library]
|
||||
[license
|
||||
Distributed under the Boost Software License, Version 1.0.
|
||||
|
||||
@@ -61,6 +61,7 @@
|
||||
* Bug in centroid(), non-deterministic result if calculated for e.g. a Polygon with zero-area.
|
||||
* Bug in buffers for joins with a limited number of points
|
||||
* Bug in buffers for joins with large buffer distances
|
||||
* Bug in buffers for round ends with an odd number of points
|
||||
* Bug in buffers for flat ends with large buffer distances
|
||||
* Bug in buffers for interior rings with large negative buffer distances
|
||||
* Bug in closing iterator not working properly when the input range is empty
|
||||
|
||||
@@ -168,6 +168,9 @@ struct buffered_piece_collection
|
||||
|
||||
struct piece
|
||||
{
|
||||
typedef robust_ring_type piece_robust_ring_type;
|
||||
typedef geometry::section<robust_box_type, 1> section_type;
|
||||
|
||||
strategy::buffer::piece_type type;
|
||||
int index;
|
||||
|
||||
@@ -191,6 +194,10 @@ struct buffered_piece_collection
|
||||
bool is_monotonic_increasing[2]; // 0=x, 1=y
|
||||
bool is_monotonic_decreasing[2]; // 0=x, 1=y
|
||||
|
||||
// Monotonic sections of pieces around points
|
||||
std::vector<section_type> sections;
|
||||
|
||||
|
||||
// Robust representations
|
||||
// 3: complete ring
|
||||
robust_ring_type robust_ring;
|
||||
@@ -199,8 +206,6 @@ struct buffered_piece_collection
|
||||
robust_box_type robust_offsetted_envelope;
|
||||
|
||||
std::vector<robust_turn> robust_turns; // Used only in insert_rescaled_piece_turns - we might use a map instead
|
||||
|
||||
typedef robust_ring_type piece_robust_ring_type;
|
||||
};
|
||||
|
||||
struct robust_original
|
||||
@@ -647,6 +652,29 @@ struct buffered_piece_collection
|
||||
}
|
||||
}
|
||||
|
||||
inline void prepare_buffered_point_piece(piece& pc)
|
||||
{
|
||||
// create monotonic sections in y-dimension
|
||||
typedef boost::mpl::vector_c<std::size_t, 1> dimensions;
|
||||
geometry::sectionalize<false, dimensions>(pc.robust_ring,
|
||||
detail::no_rescale_policy(), pc.sections);
|
||||
|
||||
// TODO (next phase) determine min/max radius
|
||||
}
|
||||
|
||||
inline void prepare_buffered_point_pieces()
|
||||
{
|
||||
for (typename piece_vector_type::iterator it = boost::begin(m_pieces);
|
||||
it != boost::end(m_pieces);
|
||||
++it)
|
||||
{
|
||||
if (it->type == geometry::strategy::buffer::buffered_point)
|
||||
{
|
||||
prepare_buffered_point_piece(*it);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
inline void get_turns()
|
||||
{
|
||||
for(typename boost::range_iterator<sections_type>::type it
|
||||
@@ -681,6 +709,8 @@ struct buffered_piece_collection
|
||||
|
||||
determine_properties();
|
||||
|
||||
prepare_buffered_point_pieces();
|
||||
|
||||
{
|
||||
// Check if it is inside any of the pieces
|
||||
turn_in_piece_visitor
|
||||
|
||||
@@ -16,6 +16,7 @@
|
||||
#include <boost/geometry/algorithms/detail/disjoint/box_box.hpp>
|
||||
#include <boost/geometry/algorithms/detail/overlay/segment_identifier.hpp>
|
||||
#include <boost/geometry/algorithms/detail/overlay/get_turn_info.hpp>
|
||||
#include <boost/geometry/algorithms/detail/sections/section_functions.hpp>
|
||||
|
||||
|
||||
namespace boost { namespace geometry
|
||||
@@ -88,6 +89,38 @@ class piece_turn_visitor
|
||||
return result;
|
||||
}
|
||||
|
||||
template <std::size_t Dimension, typename Iterator, typename Box>
|
||||
inline void move_begin_iterator(Iterator& it_begin, Iterator it_beyond,
|
||||
int& index, int dir, Box const& other_bounding_box)
|
||||
{
|
||||
for(; it_begin != it_beyond
|
||||
&& it_begin + 1 != it_beyond
|
||||
&& detail::section::preceding<Dimension>(dir, *(it_begin + 1),
|
||||
other_bounding_box, m_robust_policy);
|
||||
++it_begin, index++)
|
||||
{}
|
||||
}
|
||||
|
||||
template <std::size_t Dimension, typename Iterator, typename Box>
|
||||
inline void move_end_iterator(Iterator it_begin, Iterator& it_beyond,
|
||||
int dir, Box const& other_bounding_box)
|
||||
{
|
||||
while (it_beyond != it_begin
|
||||
&& it_beyond - 1 != it_begin
|
||||
&& it_beyond - 2 != it_begin)
|
||||
{
|
||||
if (detail::section::exceeding<Dimension>(dir, *(it_beyond - 2),
|
||||
other_bounding_box, m_robust_policy))
|
||||
{
|
||||
--it_beyond;
|
||||
}
|
||||
else
|
||||
{
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
template <typename Piece, typename Section>
|
||||
inline void calculate_turns(Piece const& piece1, Piece const& piece2,
|
||||
Section const& section1, Section const& section2)
|
||||
@@ -113,17 +146,38 @@ class piece_turn_visitor
|
||||
|
||||
// get geometry and iterators over these sections
|
||||
ring_type const& ring1 = m_rings[piece1.first_seg_id.multi_index];
|
||||
iterator const it1_first = boost::begin(ring1) + sec1_first_index;
|
||||
iterator const it1_beyond = boost::begin(ring1) + sec1_last_index + 1;
|
||||
iterator it1_first = boost::begin(ring1) + sec1_first_index;
|
||||
iterator it1_beyond = boost::begin(ring1) + sec1_last_index + 1;
|
||||
|
||||
ring_type const& ring2 = m_rings[piece2.first_seg_id.multi_index];
|
||||
iterator const it2_first = boost::begin(ring2) + sec2_first_index;
|
||||
iterator const it2_beyond = boost::begin(ring2) + sec2_last_index + 1;
|
||||
iterator it2_first = boost::begin(ring2) + sec2_first_index;
|
||||
iterator it2_beyond = boost::begin(ring2) + sec2_last_index + 1;
|
||||
|
||||
// Set begin/end of monotonic ranges, in both x/y directions
|
||||
int index1 = sec1_first_index;
|
||||
move_begin_iterator<0>(it1_first, it1_beyond, index1,
|
||||
section1.directions[0], section2.bounding_box);
|
||||
move_end_iterator<0>(it1_first, it1_beyond,
|
||||
section1.directions[0], section2.bounding_box);
|
||||
move_begin_iterator<1>(it1_first, it1_beyond, index1,
|
||||
section1.directions[1], section2.bounding_box);
|
||||
move_end_iterator<1>(it1_first, it1_beyond,
|
||||
section1.directions[1], section2.bounding_box);
|
||||
|
||||
int index2 = sec2_first_index;
|
||||
move_begin_iterator<0>(it2_first, it2_beyond, index2,
|
||||
section2.directions[0], section1.bounding_box);
|
||||
move_end_iterator<0>(it2_first, it2_beyond,
|
||||
section2.directions[0], section1.bounding_box);
|
||||
move_begin_iterator<1>(it2_first, it2_beyond, index2,
|
||||
section2.directions[1], section1.bounding_box);
|
||||
move_end_iterator<1>(it2_first, it2_beyond,
|
||||
section2.directions[1], section1.bounding_box);
|
||||
|
||||
turn_type the_model;
|
||||
the_model.operations[0].piece_index = piece1.index;
|
||||
the_model.operations[0].seg_id = piece1.first_seg_id;
|
||||
the_model.operations[0].seg_id.segment_index = sec1_first_index; // override
|
||||
the_model.operations[0].seg_id.segment_index = index1; // override
|
||||
|
||||
iterator it1 = it1_first;
|
||||
for (iterator prev1 = it1++;
|
||||
@@ -132,7 +186,7 @@ class piece_turn_visitor
|
||||
{
|
||||
the_model.operations[1].piece_index = piece2.index;
|
||||
the_model.operations[1].seg_id = piece2.first_seg_id;
|
||||
the_model.operations[1].seg_id.segment_index = sec2_first_index; // override
|
||||
the_model.operations[1].seg_id.segment_index = index2; // override
|
||||
|
||||
iterator next1 = next_point(ring1, it1);
|
||||
|
||||
|
||||
@@ -1,98 +0,0 @@
|
||||
// Boost.Geometry (aka GGL, Generic Geometry Library)
|
||||
|
||||
// Copyright (c) 2012-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_BUFFER_TURN_IN_INPUT_HPP
|
||||
#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_BUFFER_TURN_IN_INPUT_HPP
|
||||
|
||||
#include <boost/geometry/core/tags.hpp>
|
||||
#include <boost/geometry/algorithms/covered_by.hpp>
|
||||
|
||||
|
||||
namespace boost { namespace geometry
|
||||
{
|
||||
|
||||
#ifndef DOXYGEN_NO_DETAIL
|
||||
namespace detail { namespace buffer
|
||||
{
|
||||
|
||||
// Checks if an turn/intersection point is inside (or covered by) the input geometry
|
||||
|
||||
template <typename Tag>
|
||||
struct turn_in_input
|
||||
{
|
||||
};
|
||||
|
||||
template <>
|
||||
struct turn_in_input<polygon_tag>
|
||||
{
|
||||
template <typename Point, typename Geometry>
|
||||
static inline int apply(Point const& point, Geometry const& geometry)
|
||||
{
|
||||
return geometry::covered_by(point, geometry) ? 1 : -1;
|
||||
}
|
||||
};
|
||||
|
||||
template <>
|
||||
struct turn_in_input<linestring_tag>
|
||||
{
|
||||
template <typename Point, typename Geometry>
|
||||
static inline int apply(Point const& , Geometry const& )
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
};
|
||||
|
||||
template <>
|
||||
struct turn_in_input<point_tag>
|
||||
{
|
||||
template <typename Point, typename Geometry>
|
||||
static inline int apply(Point const& , Geometry const& )
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
};
|
||||
|
||||
template <>
|
||||
struct turn_in_input<multi_polygon_tag>
|
||||
{
|
||||
template <typename Point, typename Geometry>
|
||||
static inline int apply(Point const& point, Geometry const& geometry)
|
||||
{
|
||||
return geometry::covered_by(point, geometry) ? 1 : -1;
|
||||
}
|
||||
};
|
||||
|
||||
template <>
|
||||
struct turn_in_input<multi_linestring_tag>
|
||||
{
|
||||
template <typename Point, typename Geometry>
|
||||
static inline int apply(Point const& , Geometry const& )
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
};
|
||||
|
||||
template <>
|
||||
struct turn_in_input<multi_point_tag>
|
||||
{
|
||||
template <typename Point, typename Geometry>
|
||||
static inline int apply(Point const& , Geometry const& )
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
}} // namespace detail::buffer
|
||||
#endif // DOXYGEN_NO_DETAIL
|
||||
|
||||
|
||||
|
||||
}} // namespace boost::geometry
|
||||
|
||||
#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_BUFFER_TURN_IN_INPUT_HPP
|
||||
@@ -90,74 +90,134 @@ enum analyse_result
|
||||
analyse_near_offsetted
|
||||
};
|
||||
|
||||
class analyse_turn_wrt_piece
|
||||
template <typename Point>
|
||||
inline bool in_box(Point const& previous,
|
||||
Point const& current, Point const& point)
|
||||
{
|
||||
template <typename Point>
|
||||
static inline bool in_box(Point const& previous,
|
||||
Point const& current, Point const& point)
|
||||
{
|
||||
// Get its box (TODO: this can be prepared-on-demand later)
|
||||
typedef geometry::model::box<Point> box_type;
|
||||
box_type box;
|
||||
geometry::assign_inverse(box);
|
||||
geometry::expand(box, previous);
|
||||
geometry::expand(box, current);
|
||||
// Get its box (TODO: this can be prepared-on-demand later)
|
||||
typedef geometry::model::box<Point> box_type;
|
||||
box_type box;
|
||||
geometry::assign_inverse(box);
|
||||
geometry::expand(box, previous);
|
||||
geometry::expand(box, current);
|
||||
|
||||
return geometry::covered_by(point, box);
|
||||
return geometry::covered_by(point, box);
|
||||
}
|
||||
|
||||
template <typename Point, typename Turn>
|
||||
inline analyse_result check_segment(Point const& previous,
|
||||
Point const& current, Turn const& turn,
|
||||
bool from_monotonic)
|
||||
{
|
||||
typedef typename strategy::side::services::default_strategy
|
||||
<
|
||||
typename cs_tag<Point>::type
|
||||
>::type side_strategy;
|
||||
typedef typename geometry::coordinate_type<Point>::type coordinate_type;
|
||||
|
||||
coordinate_type const twice_area
|
||||
= side_strategy::template side_value
|
||||
<
|
||||
coordinate_type,
|
||||
coordinate_type
|
||||
>(previous, current, turn.robust_point);
|
||||
|
||||
if (twice_area == 0)
|
||||
{
|
||||
// Collinear, only on segment if it is covered by its bbox
|
||||
if (in_box(previous, current, turn.robust_point))
|
||||
{
|
||||
return analyse_on_offsetted;
|
||||
}
|
||||
}
|
||||
else if (twice_area < 0)
|
||||
{
|
||||
// It is in the triangle right-of the segment where the
|
||||
// segment is the hypothenusa. Check if it is close
|
||||
// (within rounding-area)
|
||||
if (twice_area * twice_area < geometry::comparable_distance(previous, current)
|
||||
&& in_box(previous, current, turn.robust_point))
|
||||
{
|
||||
return analyse_near_offsetted;
|
||||
}
|
||||
else if (from_monotonic)
|
||||
{
|
||||
return analyse_within;
|
||||
}
|
||||
}
|
||||
else if (twice_area > 0 && from_monotonic)
|
||||
{
|
||||
// Left of segment
|
||||
return analyse_disjoint;
|
||||
}
|
||||
|
||||
template <typename Point, typename Turn>
|
||||
static inline analyse_result check_segment(Point const& previous,
|
||||
Point const& current, Turn const& turn,
|
||||
bool from_monotonic)
|
||||
// Not monotonic, on left or right side: continue analysing
|
||||
return analyse_continue;
|
||||
}
|
||||
|
||||
|
||||
class analyse_turn_wrt_point_piece
|
||||
{
|
||||
public :
|
||||
template <typename Turn, typename Piece>
|
||||
static inline analyse_result apply(Turn const& turn, Piece const& piece)
|
||||
{
|
||||
typedef typename strategy::side::services::default_strategy
|
||||
<
|
||||
typename cs_tag<Point>::type
|
||||
>::type side_strategy;
|
||||
typedef typename geometry::coordinate_type<Point>::type coordinate_type;
|
||||
typedef typename Piece::section_type section_type;
|
||||
typedef typename Turn::robust_point_type point_type;
|
||||
typedef typename geometry::coordinate_type<point_type>::type coordinate_type;
|
||||
|
||||
coordinate_type const twice_area
|
||||
= side_strategy::template side_value
|
||||
<
|
||||
coordinate_type,
|
||||
coordinate_type
|
||||
>(previous, current, turn.robust_point);
|
||||
coordinate_type const point_y = geometry::get<1>(turn.robust_point);
|
||||
|
||||
if (twice_area == 0)
|
||||
typedef strategy::within::winding<point_type> strategy_type;
|
||||
|
||||
typename strategy_type::state_type state;
|
||||
strategy_type strategy;
|
||||
|
||||
for (std::size_t s = 0; s < piece.sections.size(); s++)
|
||||
{
|
||||
// Collinear, only on segment if it is covered by its bbox
|
||||
if (in_box(previous, current, turn.robust_point))
|
||||
section_type const& section = piece.sections[s];
|
||||
// If point within vertical range of monotonic section:
|
||||
if (! section.duplicate
|
||||
&& section.begin_index < section.end_index
|
||||
&& point_y >= geometry::get<min_corner, 1>(section.bounding_box) - 1
|
||||
&& point_y <= geometry::get<max_corner, 1>(section.bounding_box) + 1)
|
||||
{
|
||||
return analyse_on_offsetted;
|
||||
for (int i = section.begin_index + 1; i <= section.end_index; i++)
|
||||
{
|
||||
point_type const& previous = piece.robust_ring[i - 1];
|
||||
point_type const& current = piece.robust_ring[i];
|
||||
|
||||
analyse_result code = check_segment(previous, current, turn, false);
|
||||
if (code != analyse_continue)
|
||||
{
|
||||
return code;
|
||||
}
|
||||
|
||||
// Get the state (to determine it is within), we don't have
|
||||
// to cover the on-segment case (covered above)
|
||||
strategy.apply(turn.robust_point, previous, current, state);
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (twice_area < 0)
|
||||
|
||||
int const code = strategy.result(state);
|
||||
if (code == 1)
|
||||
{
|
||||
// It is in the triangle right-of the segment where the
|
||||
// segment is the hypothenusa. Check if it is close
|
||||
// (within rounding-area)
|
||||
if (twice_area * twice_area < geometry::comparable_distance(previous, current)
|
||||
&& in_box(previous, current, turn.robust_point))
|
||||
{
|
||||
return analyse_near_offsetted;
|
||||
}
|
||||
else if (from_monotonic)
|
||||
{
|
||||
return analyse_within;
|
||||
}
|
||||
return analyse_within;
|
||||
}
|
||||
else if (twice_area > 0 && from_monotonic)
|
||||
else if (code == -1)
|
||||
{
|
||||
// Left of segment
|
||||
return analyse_disjoint;
|
||||
}
|
||||
|
||||
// Not monotonic, on left or right side: continue analysing
|
||||
return analyse_continue;
|
||||
// Should normally not occur - on-segment is covered
|
||||
return analyse_unknown;
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
class analyse_turn_wrt_piece
|
||||
{
|
||||
template <typename Point, typename Turn>
|
||||
static inline analyse_result check_helper_segment(Point const& s1,
|
||||
Point const& s2, Turn const& turn,
|
||||
@@ -389,7 +449,7 @@ public :
|
||||
}
|
||||
}
|
||||
|
||||
return analyse_unknown;
|
||||
return analyse_unknown;
|
||||
}
|
||||
|
||||
};
|
||||
@@ -466,8 +526,10 @@ public:
|
||||
}
|
||||
|
||||
// TODO: mutable_piece to make some on-demand preparations in analyse
|
||||
analyse_result analyse_code
|
||||
= analyse_turn_wrt_piece::apply(turn, piece);
|
||||
analyse_result analyse_code =
|
||||
piece.type == geometry::strategy::buffer::buffered_point
|
||||
? analyse_turn_wrt_point_piece::apply(turn, piece)
|
||||
: analyse_turn_wrt_piece::apply(turn, piece);
|
||||
|
||||
Turn& mutable_turn = m_turns[turn.turn_index];
|
||||
switch(analyse_code)
|
||||
|
||||
@@ -63,6 +63,7 @@
|
||||
|
||||
#include <boost/geometry/algorithms/detail/sections/range_by_section.hpp>
|
||||
#include <boost/geometry/algorithms/detail/sections/sectionalize.hpp>
|
||||
#include <boost/geometry/algorithms/detail/sections/section_functions.hpp>
|
||||
|
||||
#ifdef BOOST_GEOMETRY_DEBUG_INTERSECTION
|
||||
# include <sstream>
|
||||
@@ -228,7 +229,7 @@ public :
|
||||
// section 2: [--------------]
|
||||
// section 1: |----|---|---|---|---|
|
||||
for (prev1 = it1++, next1++;
|
||||
it1 != end1 && ! exceeding<0>(dir1, *prev1, sec2.bounding_box, robust_policy);
|
||||
it1 != end1 && ! detail::section::exceeding<0>(dir1, *prev1, sec2.bounding_box, robust_policy);
|
||||
++prev1, ++it1, ++index1, ++next1, ++ndi1)
|
||||
{
|
||||
ever_circling_iterator<range1_iterator> nd_next1(
|
||||
@@ -246,7 +247,7 @@ public :
|
||||
next2++;
|
||||
|
||||
for (prev2 = it2++, next2++;
|
||||
it2 != end2 && ! exceeding<0>(dir2, *prev2, sec1.bounding_box, robust_policy);
|
||||
it2 != end2 && ! detail::section::exceeding<0>(dir2, *prev2, sec1.bounding_box, robust_policy);
|
||||
++prev2, ++it2, ++index2, ++next2, ++ndi2)
|
||||
{
|
||||
bool skip = same_source;
|
||||
@@ -317,25 +318,6 @@ private :
|
||||
typedef typename model::referring_segment<point1_type const> segment1_type;
|
||||
typedef typename model::referring_segment<point2_type const> segment2_type;
|
||||
|
||||
|
||||
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)
|
||||
{
|
||||
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 RobustPolicy>
|
||||
static inline bool exceeding(int dir, Point const& point, Box const& box, RobustPolicy const& robust_policy)
|
||||
{
|
||||
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 RobustPolicy>
|
||||
static inline void advance_to_non_duplicate_next(Iterator& next,
|
||||
RangeIterator const& it, Section const& section, RobustPolicy const& robust_policy)
|
||||
@@ -386,7 +368,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, robust_policy);
|
||||
for(; it != end && detail::section::preceding<0>(dir, *it, other_bounding_box, robust_policy);
|
||||
prev = it++, index++, ndi++)
|
||||
{}
|
||||
// Go back one step because we want to start completely preceding
|
||||
|
||||
@@ -0,0 +1,66 @@
|
||||
// Boost.Geometry (aka GGL, Generic Geometry Library)
|
||||
|
||||
// Copyright (c) 2015 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_SECTIONS_FUNCTIONS_HPP
|
||||
#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_SECTIONS_FUNCTIONS_HPP
|
||||
|
||||
|
||||
#include <boost/geometry/core/access.hpp>
|
||||
#include <boost/geometry/algorithms/detail/recalculate.hpp>
|
||||
#include <boost/geometry/policies/robustness/robust_point_type.hpp>
|
||||
|
||||
|
||||
namespace boost { namespace geometry
|
||||
{
|
||||
|
||||
#ifndef DOXYGEN_NO_DETAIL
|
||||
namespace detail { namespace section
|
||||
{
|
||||
|
||||
template
|
||||
<
|
||||
std::size_t Dimension,
|
||||
typename Point,
|
||||
typename RobustBox,
|
||||
typename RobustPolicy
|
||||
>
|
||||
static inline bool preceding(int dir, Point const& point,
|
||||
RobustBox const& robust_box,
|
||||
RobustPolicy const& robust_policy)
|
||||
{
|
||||
typename geometry::robust_point_type<Point, RobustPolicy>::type robust_point;
|
||||
geometry::recalculate(robust_point, point, robust_policy);
|
||||
return (dir == 1 && get<Dimension>(robust_point) < get<min_corner, Dimension>(robust_box))
|
||||
|| (dir == -1 && get<Dimension>(robust_point) > get<max_corner, Dimension>(robust_box));
|
||||
}
|
||||
|
||||
template
|
||||
<
|
||||
std::size_t Dimension,
|
||||
typename Point,
|
||||
typename RobustBox,
|
||||
typename RobustPolicy
|
||||
>
|
||||
static inline bool exceeding(int dir, Point const& point,
|
||||
RobustBox const& robust_box,
|
||||
RobustPolicy const& robust_policy)
|
||||
{
|
||||
typename geometry::robust_point_type<Point, RobustPolicy>::type robust_point;
|
||||
geometry::recalculate(robust_point, point, robust_policy);
|
||||
return (dir == 1 && get<Dimension>(robust_point) > get<max_corner, Dimension>(robust_box))
|
||||
|| (dir == -1 && get<Dimension>(robust_point) < get<min_corner, Dimension>(robust_box));
|
||||
}
|
||||
|
||||
|
||||
}} // namespace detail::section
|
||||
#endif
|
||||
|
||||
|
||||
}} // namespace boost::geometry
|
||||
|
||||
#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_SECTIONS_FUNCTIONS_HPP
|
||||
@@ -74,6 +74,7 @@ template
|
||||
struct section
|
||||
{
|
||||
typedef Box box_type;
|
||||
static std::size_t const dimension_count = DimensionCount;
|
||||
|
||||
int directions[DimensionCount];
|
||||
ring_identifier ring_id;
|
||||
@@ -286,13 +287,14 @@ struct sectionalize_part
|
||||
std::size_t max_count)
|
||||
{
|
||||
boost::ignore_unused_variable_warning(robust_policy);
|
||||
|
||||
typedef typename boost::range_value<Sections>::type section_type;
|
||||
BOOST_STATIC_ASSERT
|
||||
(
|
||||
(static_cast<int>(Sections::value)
|
||||
(static_cast<int>(section_type::dimension_count)
|
||||
== static_cast<int>(boost::mpl::size<DimensionVector>::value))
|
||||
);
|
||||
|
||||
typedef typename boost::range_value<Sections>::type section_type;
|
||||
typedef typename geometry::robust_point_type
|
||||
<
|
||||
Point,
|
||||
@@ -765,17 +767,13 @@ inline void sectionalize(Geometry const& geometry,
|
||||
{
|
||||
concept::check<Geometry const>();
|
||||
|
||||
BOOST_STATIC_ASSERT
|
||||
(
|
||||
(static_cast<int>(Sections::value)
|
||||
== static_cast<int>(boost::mpl::size<DimensionVector>::value))
|
||||
);
|
||||
typedef typename boost::range_value<Sections>::type section_type;
|
||||
|
||||
// Compiletime check for point type of section boxes
|
||||
// and point type related to robust policy
|
||||
typedef typename geometry::coordinate_type
|
||||
<
|
||||
typename Sections::box_type
|
||||
typename section_type::box_type
|
||||
>::type ctype1;
|
||||
typedef typename geometry::coordinate_type
|
||||
<
|
||||
|
||||
@@ -36,6 +36,7 @@
|
||||
#include <boost/geometry/strategies/within.hpp>
|
||||
#include <boost/geometry/strategies/covered_by.hpp>
|
||||
|
||||
#include <boost/geometry/util/range.hpp>
|
||||
#include <boost/geometry/views/detail/normalized_view.hpp>
|
||||
|
||||
namespace boost { namespace geometry {
|
||||
@@ -197,11 +198,11 @@ struct point_in_geometry<Linestring, linestring_tag>
|
||||
return -1; // exterior
|
||||
|
||||
// if the linestring doesn't have a boundary
|
||||
if ( detail::equals::equals_point_point(*boost::begin(linestring), *(--boost::end(linestring))) )
|
||||
if (detail::equals::equals_point_point(range::front(linestring), range::back(linestring)))
|
||||
return 1; // interior
|
||||
// else if the point is equal to the one of the terminal points
|
||||
else if ( detail::equals::equals_point_point(point, *boost::begin(linestring))
|
||||
|| detail::equals::equals_point_point(point, *(--boost::end(linestring))) )
|
||||
else if (detail::equals::equals_point_point(point, range::front(linestring))
|
||||
|| detail::equals::equals_point_point(point, range::back(linestring)))
|
||||
return 0; // boundary
|
||||
else
|
||||
return 1; // interior
|
||||
@@ -210,7 +211,7 @@ struct point_in_geometry<Linestring, linestring_tag>
|
||||
// throw an exception here?
|
||||
/*else if ( count == 1 )
|
||||
{
|
||||
if ( detail::equals::equals_point_point(point, *boost::begin(linestring)) )
|
||||
if ( detail::equals::equals_point_point(point, range::front(linestring)) )
|
||||
return 1;
|
||||
}*/
|
||||
|
||||
@@ -336,8 +337,8 @@ struct point_in_geometry<Geometry, multi_linestring_tag>
|
||||
if ( boost::size(*it) < 2 )
|
||||
continue;
|
||||
|
||||
point_type const& front = *boost::begin(*it);
|
||||
point_type const& back = *(--boost::end(*it));
|
||||
point_type const& front = range::front(*it);
|
||||
point_type const& back = range::back(*it);
|
||||
|
||||
// is closed_ring - no boundary
|
||||
if ( detail::equals::equals_point_point(front, back) )
|
||||
|
||||
@@ -95,8 +95,9 @@ public :
|
||||
|
||||
//! \brief Constructs the strategy
|
||||
//! \param points_per_circle points which would be used for a full circle
|
||||
//! (if points_per_circle is smaller than 4, it is internally set to 4)
|
||||
explicit inline end_round(std::size_t points_per_circle = 90)
|
||||
: m_points_per_circle(points_per_circle)
|
||||
: m_points_per_circle((points_per_circle < 4u) ? 4u : points_per_circle)
|
||||
{}
|
||||
|
||||
#ifndef DOXYGEN_SHOULD_SKIP_THIS
|
||||
@@ -106,7 +107,7 @@ public :
|
||||
inline void apply(Point const& penultimate_point,
|
||||
Point const& perp_left_point,
|
||||
Point const& ultimate_point,
|
||||
Point const& ,
|
||||
Point const& perp_right_point,
|
||||
buffer_side_selector side,
|
||||
DistanceStrategy const& distance,
|
||||
RangeOut& range_out) const
|
||||
@@ -142,6 +143,13 @@ public :
|
||||
set<1>(shifted_point, get<1>(ultimate_point) + dist_half_diff * sin(alpha));
|
||||
generate_points(shifted_point, alpha, (dist_left + dist_right) / two, range_out);
|
||||
}
|
||||
|
||||
if (m_points_per_circle % 2 == 1)
|
||||
{
|
||||
// For a half circle, if the number of points is not even,
|
||||
// we should insert the end point too, to generate a full cap
|
||||
range_out.push_back(perp_right_point);
|
||||
}
|
||||
}
|
||||
|
||||
template <typename NumericType>
|
||||
|
||||
@@ -35,6 +35,8 @@ namespace strategy { namespace buffer
|
||||
their length. The miter is not changed to a bevel form (as done in some
|
||||
other software), it is just adapted to the specified miter_limit but keeps
|
||||
its miter form.
|
||||
If the buffer distance is 5.0, and the miter limit is 2.0, generated points
|
||||
will be located at a distance of at most 10.0 (2*5) units.
|
||||
This strategy is only applicable for Cartesian coordinate systems.
|
||||
|
||||
\qbk{
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
// Boost.Geometry (aka GGL, Generic Geometry Library)
|
||||
|
||||
// Copyright (c) 2012-2014 Barend Gehrels, Amsterdam, the Netherlands.
|
||||
// Copyright (c) 2012-2015 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
|
||||
@@ -9,6 +9,8 @@
|
||||
#ifndef BOOST_GEOMETRY_STRATEGIES_CARTESIAN_BUFFER_JOIN_ROUND_HPP
|
||||
#define BOOST_GEOMETRY_STRATEGIES_CARTESIAN_BUFFER_JOIN_ROUND_HPP
|
||||
|
||||
#include <algorithm>
|
||||
|
||||
#include <boost/assert.hpp>
|
||||
#include <boost/geometry/core/cs.hpp>
|
||||
#include <boost/geometry/policies/compare.hpp>
|
||||
@@ -83,15 +85,13 @@ private :
|
||||
{
|
||||
angle2 -= two_pi;
|
||||
}
|
||||
PromotedType const dangle = angle1 - angle2;
|
||||
|
||||
// Divide the angle into an integer amount of steps to make it
|
||||
// visually correct also for a low number of points / circle
|
||||
int const n = static_cast<int>
|
||||
(
|
||||
m_points_per_circle * (angle1 - angle2) / two_pi
|
||||
);
|
||||
int const n = static_cast<int>(m_points_per_circle * dangle / two_pi);
|
||||
|
||||
PromotedType const diff = (angle1 - angle2) / static_cast<PromotedType>(n);
|
||||
PromotedType const diff = dangle / static_cast<PromotedType>(n);
|
||||
PromotedType a = angle1 - diff;
|
||||
for (int i = 0; i < n - 1; i++, a -= diff)
|
||||
{
|
||||
|
||||
@@ -1,5 +1,12 @@
|
||||
// Boost.Geometry (aka GGL, Generic Geometry Library)
|
||||
// Copyright (c) 2012-2014 Barend Gehrels, Amsterdam, the Netherlands.
|
||||
|
||||
// Copyright (c) 2012-2015 Barend Gehrels, Amsterdam, the Netherlands.
|
||||
|
||||
// This file was modified by Oracle on 2015.
|
||||
// Modifications copyright (c) 2015, 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
|
||||
// http://www.boost.org/LICENSE_1_0.txt)
|
||||
@@ -45,9 +52,10 @@ class point_circle
|
||||
{
|
||||
public :
|
||||
//! \brief Constructs the strategy
|
||||
//! \param count number of points for the created circle
|
||||
//! \param count number of points for the created circle (if count
|
||||
//! is smaller than 3, count is internally set to 3)
|
||||
explicit point_circle(std::size_t count = 90)
|
||||
: m_count(count)
|
||||
: m_count((count < 3u) ? 3u : count)
|
||||
{}
|
||||
|
||||
#ifndef DOXYGEN_SHOULD_SKIP_THIS
|
||||
|
||||
@@ -138,7 +138,7 @@ back(BidirectionalRange const& rng)
|
||||
{
|
||||
BOOST_RANGE_CONCEPT_ASSERT(( boost::BidirectionalRangeConcept<BidirectionalRange const> ));
|
||||
BOOST_ASSERT(!boost::empty(rng));
|
||||
return *(--boost::end(rng));
|
||||
return *(boost::rbegin(rng));
|
||||
}
|
||||
|
||||
/*!
|
||||
@@ -151,7 +151,7 @@ back(BidirectionalRange & rng)
|
||||
{
|
||||
BOOST_RANGE_CONCEPT_ASSERT(( boost::BidirectionalRangeConcept<BidirectionalRange> ));
|
||||
BOOST_ASSERT(!boost::empty(rng));
|
||||
return *(--boost::end(rng));
|
||||
return *(boost::rbegin(rng));
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -59,6 +59,10 @@ static std::string const crossing = "LINESTRING(0 0,10 10,10 0,0 10)";
|
||||
// Simplified cases from multi_linestring tesets:
|
||||
static std::string const mikado1 = "LINESTRING(11.406143344709896325639419956133 0.75426621160409546007485914742574,12 1,11.403846153846153299582510953769 0.75)";
|
||||
|
||||
static std::string const mysql_report_2015_03_02a = "LINESTRING(0 0,0 5,5 5,5 0,0 0)"; // closed
|
||||
static std::string const mysql_report_2015_03_02b = "LINESTRING(0 1,0 5,5 5,5 0,1 0)"; // not closed, 1 difference
|
||||
static std::string const mysql_report_2015_03_02c = "LINESTRING(0 2,0 5,5 5,5 0,2 0)"; // not closed, 2 difference
|
||||
|
||||
|
||||
template <bool Clockwise, typename P>
|
||||
void test_all()
|
||||
@@ -166,6 +170,40 @@ void test_all()
|
||||
test_one<linestring, polygon>("degenerate4", degenerate4, join_round, end_round, 36.7410, 3.0);
|
||||
test_one<linestring, polygon>("degenerate4", degenerate4, join_round, end_flat, 8.4853, 3.0);
|
||||
|
||||
{
|
||||
// These tests do test behaviour in end_round strategy:
|
||||
// -> it should generate closed pieces, also for an odd number of points.
|
||||
// It also tests behaviour in join_round strategy:
|
||||
// -> it should generate e.g. 4 points for a full circle,
|
||||
// so a quarter circle does not get points in between
|
||||
using bg::strategy::buffer::join_round;
|
||||
using bg::strategy::buffer::end_round;
|
||||
|
||||
double const d10 = 1.0;
|
||||
|
||||
test_one<linestring, polygon>("mysql_report_2015_03_02a_3", mysql_report_2015_03_02a, join_round(3), end_round(3), 38.000, d10);
|
||||
test_one<linestring, polygon>("mysql_report_2015_03_02a_4", mysql_report_2015_03_02a, join_round(4), end_round(4), 38.000, d10);
|
||||
test_one<linestring, polygon>("mysql_report_2015_03_02a_5", mysql_report_2015_03_02a, join_round(5), end_round(5), 38.169, d10);
|
||||
test_one<linestring, polygon>("mysql_report_2015_03_02a_6", mysql_report_2015_03_02a, join_round(6), end_round(6), 38.196, d10);
|
||||
test_one<linestring, polygon>("mysql_report_2015_03_02a_7", mysql_report_2015_03_02a, join_round(7), end_round(7), 38.230, d10);
|
||||
test_one<linestring, polygon>("mysql_report_2015_03_02b_3", mysql_report_2015_03_02b, join_round(3), end_round(3), 36.500, d10);
|
||||
test_one<linestring, polygon>("mysql_report_2015_03_02b_4", mysql_report_2015_03_02b, join_round(4), end_round(4), 36.500, d10);
|
||||
test_one<linestring, polygon>("mysql_report_2015_03_02b_5", mysql_report_2015_03_02b, join_round(5), end_round(5), 36.724, d10);
|
||||
test_one<linestring, polygon>("mysql_report_2015_03_02b_6", mysql_report_2015_03_02b, join_round(6), end_round(6), 36.781, d10);
|
||||
test_one<linestring, polygon>("mysql_report_2015_03_02b_7", mysql_report_2015_03_02b, join_round(7), end_round(7), 36.884, d10);
|
||||
test_one<linestring, polygon>("mysql_report_2015_03_02c_3", mysql_report_2015_03_02c, join_round(2), end_round(3), 32.500, d10);
|
||||
test_one<linestring, polygon>("mysql_report_2015_03_02c_4", mysql_report_2015_03_02c, join_round(4), end_round(4), 32.500, d10);
|
||||
test_one<linestring, polygon>("mysql_report_2015_03_02c_5", mysql_report_2015_03_02c, join_round(5), end_round(5), 32.990, d10);
|
||||
test_one<linestring, polygon>("mysql_report_2015_03_02c_6", mysql_report_2015_03_02c, join_round(6), end_round(6), 33.098, d10);
|
||||
test_one<linestring, polygon>("mysql_report_2015_03_02c_7", mysql_report_2015_03_02c, join_round(7), end_round(7), 33.279, d10);
|
||||
|
||||
// Testing the asymmetric end caps with odd number of points
|
||||
double const d15 = 1.5;
|
||||
test_one<linestring, polygon>("mysql_report_2015_03_02c_asym1", mysql_report_2015_03_02c, join_round(7), end_round(7), 39.093, d10, d15);
|
||||
test_one<linestring, polygon>("mysql_report_2015_03_02c_asym2", mysql_report_2015_03_02c, join_round(7), end_round(7), 44.718, d15, d10);
|
||||
}
|
||||
|
||||
|
||||
{
|
||||
double tolerance = 1.0e-10;
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
// Boost.Geometry (aka GGL, Generic Geometry Library)
|
||||
// Unit Test
|
||||
|
||||
// Copyright (c) 2012-2014 Barend Gehrels, Amsterdam, the Netherlands.
|
||||
// Copyright (c) 2012-2015 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
|
||||
@@ -73,44 +73,74 @@ void test_all()
|
||||
distance_strategy(0.54), side_strategy, point_strategy, 99);
|
||||
#endif
|
||||
|
||||
|
||||
}
|
||||
|
||||
test_with_custom_strategies<multi_point_type, polygon>("mysql_report_2015_02_25_1_800",
|
||||
mysql_report_2015_02_25_1, join_miter, end_flat,
|
||||
distance_strategy(6051788), side_strategy,
|
||||
bg::strategy::buffer::point_circle(800), 115057490003226.125, 1.0);
|
||||
}
|
||||
|
||||
template <typename P>
|
||||
void test_many_points_per_circle()
|
||||
{
|
||||
// Tests for large distances / many points in circles.
|
||||
// Before Boost 1.58, this would (seem to) hang. It is solved by using monotonic sections in get_turns for buffer
|
||||
// This is more time consuming, only calculate this for counter clockwise
|
||||
if (! BOOST_GEOMETRY_CONDITION(Clockwise))
|
||||
{
|
||||
// Reported by MySQL 2015-02-25
|
||||
// SELECT ST_ASTEXT(ST_BUFFER(ST_GEOMFROMTEXT(''), 6051788, ST_BUFFER_STRATEGY('point_circle', 83585)));
|
||||
// SELECT ST_ASTEXT(ST_BUFFER(ST_GEOMFROMTEXT(''), 5666962, ST_BUFFER_STRATEGY('point_circle', 46641))) ;
|
||||
// Reported by MySQL 2015-02-25
|
||||
// SELECT ST_ASTEXT(ST_BUFFER(ST_GEOMFROMTEXT(''), 6051788, ST_BUFFER_STRATEGY('point_circle', 83585)));
|
||||
// SELECT ST_ASTEXT(ST_BUFFER(ST_GEOMFROMTEXT(''), 5666962, ST_BUFFER_STRATEGY('point_circle', 46641))) ;
|
||||
|
||||
using bg::strategy::buffer::point_circle;
|
||||
test_with_custom_strategies<multi_point_type, polygon>("mysql_report_2015_02_25_1_800",
|
||||
mysql_report_2015_02_25_1, join_miter, end_flat,
|
||||
distance_strategy(6051788), side_strategy, point_circle(800), 115057490003226.125, 1.0);
|
||||
typedef bg::model::polygon<P, false> polygon;
|
||||
typedef bg::model::multi_point<P> multi_point_type;
|
||||
|
||||
test_with_custom_strategies<multi_point_type, polygon>("mysql_report_2015_02_25_1_8000",
|
||||
mysql_report_2015_02_25_1, join_miter, end_flat,
|
||||
distance_strategy(6051788), side_strategy, point_circle(8000), 115058661065242.812, 1.0);
|
||||
bg::strategy::buffer::join_miter join_miter;
|
||||
bg::strategy::buffer::end_flat end_flat;
|
||||
typedef bg::strategy::buffer::distance_symmetric
|
||||
<
|
||||
typename bg::coordinate_type<P>::type
|
||||
> distance_strategy;
|
||||
bg::strategy::buffer::side_straight side_strategy;
|
||||
|
||||
test_with_custom_strategies<multi_point_type, polygon>("mysql_report_2015_02_25_1",
|
||||
mysql_report_2015_02_25_1, join_miter, end_flat,
|
||||
distance_strategy(6051788), side_strategy, point_circle(83585), 115058672785611.219, 1.0);
|
||||
using bg::strategy::buffer::point_circle;
|
||||
|
||||
double const tolerance = 1.0;
|
||||
|
||||
// Strategies with many points, which are (very) slow in debug mode
|
||||
test_with_custom_strategies<multi_point_type, polygon>(
|
||||
"mysql_report_2015_02_25_1_8000",
|
||||
mysql_report_2015_02_25_1, join_miter, end_flat,
|
||||
distance_strategy(6051788), side_strategy, point_circle(8000),
|
||||
115058661065242.812, tolerance);
|
||||
|
||||
test_with_custom_strategies<multi_point_type, polygon>(
|
||||
"mysql_report_2015_02_25_1",
|
||||
mysql_report_2015_02_25_1, join_miter, end_flat,
|
||||
distance_strategy(6051788), side_strategy, point_circle(83585),
|
||||
115058672785611.219, tolerance);
|
||||
|
||||
// Takes about 20 seconds in release mode
|
||||
test_with_custom_strategies<multi_point_type, polygon>(
|
||||
"mysql_report_2015_02_25_1_250k",
|
||||
mysql_report_2015_02_25_1, join_miter, end_flat,
|
||||
distance_strategy(6051788), side_strategy, point_circle(250000),
|
||||
115058672880671.531, tolerance);
|
||||
|
||||
#if defined(BOOST_GEOMETRY_BUFFER_INCLUDE_FAILING_TESTS)
|
||||
// Try to specify even more points per circle
|
||||
// Turns are calculated in 23 seconds
|
||||
// But the follow-up still takes too long (there are 63409 turns), this might be improved too
|
||||
test_with_custom_strategies<multi_point_type, polygon>("mysql_report_2015_02_25_1",
|
||||
mysql_report_2015_02_25_1, join_miter, end_flat,
|
||||
distance_strategy(6051788), side_strategy, point_circle(800000), 115058672799999.999, 1.0); // area to be determined
|
||||
// Takes too long, TODO improve turn_in_piece_visitor
|
||||
test_with_custom_strategies<multi_point_type, polygon>(
|
||||
"mysql_report_2015_02_25_1",
|
||||
mysql_report_2015_02_25_1, join_miter, end_flat,
|
||||
distance_strategy(6051788), side_strategy, point_circle(800000),
|
||||
115058672799999.999, tolerance); // area to be determined
|
||||
#endif
|
||||
|
||||
test_with_custom_strategies<multi_point_type, polygon>("mysql_report_2015_02_25_2",
|
||||
mysql_report_2015_02_25_2, join_miter, end_flat,
|
||||
distance_strategy(5666962), side_strategy, point_circle(46641), 100891031341757.344, 1.0);
|
||||
}
|
||||
test_with_custom_strategies<multi_point_type, polygon>(
|
||||
"mysql_report_2015_02_25_2",
|
||||
mysql_report_2015_02_25_2, join_miter, end_flat,
|
||||
distance_strategy(5666962), side_strategy, point_circle(46641),
|
||||
100891031341757.344, tolerance);
|
||||
|
||||
}
|
||||
|
||||
int test_main(int, char* [])
|
||||
@@ -118,5 +148,11 @@ int test_main(int, char* [])
|
||||
test_all<true, bg::model::point<double, 2, bg::cs::cartesian> >();
|
||||
test_all<false, bg::model::point<double, 2, bg::cs::cartesian> >();
|
||||
|
||||
#if defined(BOOST_GEOMETRY_COMPILER_MODE_RELEASE) && ! defined(BOOST_GEOMETRY_COMPILER_MODE_DEBUG)
|
||||
test_many_points_per_circle<bg::model::point<double, 2, bg::cs::cartesian> >();
|
||||
#else
|
||||
std::cout << "Skipping some tests in debug or unknown mode" << std::endl;
|
||||
#endif
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -532,18 +532,65 @@ void test_all()
|
||||
|
||||
|
||||
{
|
||||
bg::strategy::buffer::join_round join_round12(12);
|
||||
buffer_custom_side_strategy side_strategy;
|
||||
using bg::strategy::buffer::join_round;
|
||||
using bg::strategy::buffer::join_miter;
|
||||
bg::strategy::buffer::side_straight side_strategy;
|
||||
bg::strategy::buffer::point_circle point_strategy;
|
||||
bg::strategy::buffer::distance_symmetric
|
||||
typedef bg::strategy::buffer::distance_symmetric
|
||||
<
|
||||
typename bg::coordinate_type<P>::type
|
||||
> distance_strategy(1.0);
|
||||
> distance;
|
||||
|
||||
test_with_custom_strategies<polygon_type, polygon_type>("sharp_triangle",
|
||||
test_with_custom_strategies<polygon_type, polygon_type>("sharp_triangle_j12",
|
||||
sharp_triangle,
|
||||
join_round12, end_flat, distance_strategy, side_strategy, point_strategy,
|
||||
31.0721);
|
||||
join_round(12), end_flat, distance(1.0), side_strategy, point_strategy,
|
||||
29.0980);
|
||||
// Test very various number of points (min is 3)
|
||||
test_with_custom_strategies<polygon_type, polygon_type>("sharp_triangle_j2",
|
||||
sharp_triangle,
|
||||
join_round(2), end_flat, distance(1.0), side_strategy, point_strategy,
|
||||
27.2399);
|
||||
test_with_custom_strategies<polygon_type, polygon_type>("sharp_triangle_j5",
|
||||
sharp_triangle,
|
||||
join_round(5), end_flat, distance(1.0), side_strategy, point_strategy,
|
||||
28.1091);
|
||||
|
||||
test_with_custom_strategies<polygon_type, polygon_type>("sharp_triangle_j36",
|
||||
sharp_triangle,
|
||||
join_round(36), end_flat, distance(1.0), side_strategy, point_strategy,
|
||||
29.2482);
|
||||
test_with_custom_strategies<polygon_type, polygon_type>("sharp_triangle_j360",
|
||||
sharp_triangle,
|
||||
join_round(360), end_flat, distance(1.0), side_strategy, point_strategy,
|
||||
29.2659);
|
||||
|
||||
// Test with various miter limits
|
||||
test_with_custom_strategies<polygon_type, polygon_type>("sharp_triangle_m2",
|
||||
sharp_triangle,
|
||||
join_miter(2), end_flat, distance(4.0), side_strategy, point_strategy,
|
||||
148.500);
|
||||
test_with_custom_strategies<polygon_type, polygon_type>("sharp_triangle_m3",
|
||||
sharp_triangle,
|
||||
join_miter(3), end_flat, distance(4.0), side_strategy, point_strategy,
|
||||
164.376);
|
||||
test_with_custom_strategies<polygon_type, polygon_type>("sharp_triangle_m4",
|
||||
sharp_triangle,
|
||||
join_miter(4), end_flat, distance(4.0), side_strategy, point_strategy,
|
||||
180.2529);
|
||||
test_with_custom_strategies<polygon_type, polygon_type>("sharp_triangle_m5",
|
||||
sharp_triangle,
|
||||
join_miter(5), end_flat, distance(4.0), side_strategy, point_strategy,
|
||||
196.1293);
|
||||
test_with_custom_strategies<polygon_type, polygon_type>("sharp_triangle_m25",
|
||||
sharp_triangle,
|
||||
join_miter(25), end_flat, distance(4.0), side_strategy, point_strategy,
|
||||
244.7471);
|
||||
|
||||
buffer_custom_side_strategy custom_side_strategy;
|
||||
test_with_custom_strategies<polygon_type, polygon_type>("sharp_triangle_custom_side",
|
||||
sharp_triangle,
|
||||
join_round(49), end_flat, distance(1.0), custom_side_strategy, point_strategy,
|
||||
31.1087);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -688,7 +688,10 @@ void test_one(std::string const& caseid, std::string const& wkt,
|
||||
check_self_intersections, expected_area,
|
||||
tolerance, NULL);
|
||||
|
||||
#if !defined(BOOST_GEOMETRY_COMPILER_MODE_DEBUG) && defined(BOOST_GEOMETRY_COMPILER_MODE_RELEASE)
|
||||
|
||||
// Also test symmetric distance strategy if right-distance is not specified
|
||||
// (only in release mode)
|
||||
if (bg::math::equals(distance_right, -999))
|
||||
{
|
||||
bg::strategy::buffer::distance_symmetric
|
||||
@@ -704,6 +707,7 @@ void test_one(std::string const& caseid, std::string const& wkt,
|
||||
tolerance, NULL);
|
||||
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
// Version (currently for the Aimes test) counting self-ip's instead of checking
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
// 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.
|
||||
// Copyright (c) 2007-2015 Barend Gehrels, Amsterdam, the Netherlands.
|
||||
// Copyright (c) 2008-2015 Bruno Lalande, Paris, France.
|
||||
// Copyright (c) 2009-2015 Mateusz Loskot, London, UK.
|
||||
|
||||
// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library
|
||||
// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands.
|
||||
@@ -15,6 +15,27 @@
|
||||
#ifndef GEOMETRY_TEST_GEOMETRY_TEST_COMMON_HPP
|
||||
#define GEOMETRY_TEST_GEOMETRY_TEST_COMMON_HPP
|
||||
|
||||
// Determine debug/release mode
|
||||
// (it would be convenient if Boost.Config or Boost.Test would define this)
|
||||
// Note that they might be combined (e.g. for optimize+no inline)
|
||||
#if defined (__clang__) || defined(__gcc__)
|
||||
#if defined(__OPTIMIZE__)
|
||||
#define BOOST_GEOMETRY_COMPILER_MODE_RELEASE
|
||||
#endif
|
||||
#if defined(__NO_INLINE__)
|
||||
#define BOOST_GEOMETRY_COMPILER_MODE_DEBUG
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#if defined(_MSC_VER)
|
||||
#if defined(_DEBUG)
|
||||
#define BOOST_GEOMETRY_COMPILER_MODE_DEBUG
|
||||
#else
|
||||
#define BOOST_GEOMETRY_COMPILER_MODE_RELEASE
|
||||
#endif
|
||||
#endif
|
||||
|
||||
|
||||
#if defined(_MSC_VER)
|
||||
// We deliberately mix float/double's so turn off warnings
|
||||
#pragma warning( disable : 4244 )
|
||||
|
||||
Reference in New Issue
Block a user