mirror of
https://github.com/boostorg/geometry.git
synced 2026-01-19 04:12:11 +00:00
refactor: removed unused functionality and minor changes preparing next pr
This commit is contained in:
@@ -185,23 +185,6 @@ struct map_visitor
|
||||
: m_mapper(mapper)
|
||||
{}
|
||||
|
||||
void print(char const* header)
|
||||
{}
|
||||
|
||||
template <typename Turns>
|
||||
void print(char const* header, Turns const& turns, int turn_index)
|
||||
{
|
||||
std::string style = "fill:rgb(0,0,0);font-family:Arial;font-size:6px";
|
||||
stream(turns, turns[turn_index], turns[turn_index].operations[0], header, style);
|
||||
}
|
||||
|
||||
template <typename Turns>
|
||||
void print(char const* header, Turns const& turns, int turn_index, int op_index)
|
||||
{
|
||||
std::string style = "fill:rgb(0,0,0);font-family:Arial;font-size:6px";
|
||||
stream(turns, turns[turn_index], turns[turn_index].operations[op_index], header, style);
|
||||
}
|
||||
|
||||
template <typename Turns>
|
||||
void visit_turns(int phase, Turns const& turns)
|
||||
{
|
||||
|
||||
@@ -87,20 +87,6 @@ g_backtrack_warning_count++;
|
||||
struct buffer_overlay_visitor
|
||||
{
|
||||
public :
|
||||
void print(char const* /*header*/)
|
||||
{
|
||||
}
|
||||
|
||||
template <typename Turns>
|
||||
void print(char const* /*header*/, Turns const& /*turns*/, int /*turn_index*/)
|
||||
{
|
||||
}
|
||||
|
||||
template <typename Turns>
|
||||
void print(char const* /*header*/, Turns const& /*turns*/, int /*turn_index*/, int /*op_index*/)
|
||||
{
|
||||
}
|
||||
|
||||
template <typename Turns>
|
||||
void visit_turns(int , Turns const& ) {}
|
||||
|
||||
@@ -170,26 +156,6 @@ struct buffer_turn_info
|
||||
{}
|
||||
};
|
||||
|
||||
struct buffer_less
|
||||
{
|
||||
template <typename Indexed>
|
||||
inline bool operator()(Indexed const& left, Indexed const& right) const
|
||||
{
|
||||
if (! (left.subject->seg_id == right.subject->seg_id))
|
||||
{
|
||||
return left.subject->seg_id < right.subject->seg_id;
|
||||
}
|
||||
|
||||
// Both left and right are located on the SAME segment.
|
||||
if (! (left.subject->fraction == right.subject->fraction))
|
||||
{
|
||||
return left.subject->fraction < right.subject->fraction;
|
||||
}
|
||||
|
||||
return left.turn_index < right.turn_index;
|
||||
}
|
||||
};
|
||||
|
||||
template <typename Strategy>
|
||||
struct piece_get_box
|
||||
{
|
||||
|
||||
@@ -104,8 +104,7 @@ inline void enrich_sort(Operations& operations,
|
||||
|
||||
// Assign travel-to-vertex/ip index for each turn.
|
||||
template <typename Operations, typename Turns>
|
||||
inline void enrich_assign(Operations& operations, Turns& turns,
|
||||
bool check_consecutive_turns)
|
||||
inline void enrich_assign(Operations& operations, Turns& turns)
|
||||
{
|
||||
for (auto const& item : util::enumerate(operations))
|
||||
{
|
||||
@@ -131,34 +130,6 @@ inline void enrich_assign(Operations& operations, Turns& turns,
|
||||
return next_turn.operations[operations[next_index].operation_index];
|
||||
};
|
||||
|
||||
if (check_consecutive_turns
|
||||
&& indexed.turn_index == operations[next_index].turn_index
|
||||
&& op.seg_id == next_operation().seg_id)
|
||||
{
|
||||
// If the two operations on the same turn are ordered consecutively,
|
||||
// and they are on the same segment, then the turn where to travel to should
|
||||
// be considered one further. Therefore next is increased.
|
||||
//
|
||||
// It often happens in buffer, in these configurations:
|
||||
// +---->--+
|
||||
// | |
|
||||
// | +->-*---->
|
||||
// | | |
|
||||
// ^ +-<-+
|
||||
// If the next index is not corrected, the small rectangle
|
||||
// will be kept in the output.
|
||||
|
||||
// This is a normal situation and occurs, for example, in every concave bend.
|
||||
// In general it should always travel from turn to next turn.
|
||||
// Only in some circumstances traveling to the same turn is necessary, for example
|
||||
// if there is only one turn in the outer ring.
|
||||
//
|
||||
// (For dissolve this is not done, turn_index is often
|
||||
// the same for two consecutive operations - but the conditions are changed
|
||||
// and this should be verified again)
|
||||
next_index = advance(next_index);
|
||||
}
|
||||
|
||||
// Cluster behaviour: next should point after cluster, unless
|
||||
// their seg_ids are not the same
|
||||
// (For dissolve, this is still to be examined - TODO)
|
||||
@@ -285,36 +256,50 @@ struct enriched_map_default_include_policy
|
||||
// Add all (non discarded) operations on this ring
|
||||
// Blocked operations or uu on clusters (for intersection)
|
||||
// should be included, to block potential paths in clusters
|
||||
template <typename Turns, typename MappedVector, typename IncludePolicy>
|
||||
inline void create_map(Turns const& turns, MappedVector& mapped_vector,
|
||||
IncludePolicy const& include_policy)
|
||||
template <typename Turns, typename IncludePolicy>
|
||||
inline auto create_map(Turns const& turns, IncludePolicy const& include_policy)
|
||||
{
|
||||
using turn_type = typename boost::range_value<Turns>::type;
|
||||
using indexed_turn_operation = detail::overlay::indexed_turn_operation
|
||||
<
|
||||
typename turn_type::turn_operation_type
|
||||
>;
|
||||
|
||||
std::map
|
||||
<
|
||||
ring_identifier,
|
||||
std::vector<indexed_turn_operation>
|
||||
> mapped_vector;
|
||||
|
||||
for (auto const& turn_item : util::enumerate(turns))
|
||||
{
|
||||
auto const& index = turn_item.index;
|
||||
auto const& turn = turn_item.value;
|
||||
if (! turn.discarded)
|
||||
if (turn.discarded)
|
||||
{
|
||||
for (auto const& op_item : util::enumerate(turn.operations))
|
||||
continue;
|
||||
}
|
||||
|
||||
for (auto const& op_item : util::enumerate(turn.operations))
|
||||
{
|
||||
auto const& op_index = op_item.index;
|
||||
auto const& op = op_item.value;
|
||||
if (include_policy.include(op.operation))
|
||||
{
|
||||
auto const& op_index = op_item.index;
|
||||
auto const& op = op_item.value;
|
||||
if (include_policy.include(op.operation))
|
||||
{
|
||||
ring_identifier const ring_id
|
||||
(
|
||||
op.seg_id.source_index,
|
||||
op.seg_id.multi_index,
|
||||
op.seg_id.ring_index
|
||||
);
|
||||
mapped_vector[ring_id].emplace_back
|
||||
(
|
||||
index, op_index, op, turn.operations[1 - op_index].seg_id
|
||||
);
|
||||
}
|
||||
ring_identifier const ring_id
|
||||
(
|
||||
op.seg_id.source_index,
|
||||
op.seg_id.multi_index,
|
||||
op.seg_id.ring_index
|
||||
);
|
||||
mapped_vector[ring_id].emplace_back
|
||||
(
|
||||
index, op_index, op, turn.operations[1 - op_index].seg_id
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
return mapped_vector;
|
||||
}
|
||||
|
||||
template <typename Point1, typename Point2>
|
||||
@@ -356,7 +341,6 @@ inline void calculate_remaining_distance(Turns& turns)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}} // namespace detail::overlay
|
||||
#endif //DOXYGEN_NO_DETAIL
|
||||
|
||||
@@ -398,51 +382,14 @@ inline void enrich_intersection_points(Turns& turns,
|
||||
? detail::overlay::operation_intersection
|
||||
: detail::overlay::operation_union;
|
||||
constexpr bool is_dissolve = OverlayType == overlay_dissolve;
|
||||
constexpr bool is_buffer = OverlayType == overlay_buffer;
|
||||
|
||||
using turn_type = typename boost::range_value<Turns>::type;
|
||||
using indexed_turn_operation = detail::overlay::indexed_turn_operation
|
||||
<
|
||||
typename turn_type::turn_operation_type
|
||||
> ;
|
||||
|
||||
using mapped_vector_type = std::map
|
||||
<
|
||||
ring_identifier,
|
||||
std::vector<indexed_turn_operation>
|
||||
>;
|
||||
|
||||
// Turns are often used by index (in clusters, next_index, etc)
|
||||
// and turns may therefore NOT be DELETED - they may only be flagged as discarded
|
||||
|
||||
bool has_cc = false;
|
||||
bool has_colocations = false;
|
||||
|
||||
if BOOST_GEOMETRY_CONSTEXPR (! is_buffer)
|
||||
{
|
||||
// Handle colocations, gathering clusters and (below) their properties.
|
||||
has_colocations = detail::overlay::handle_colocations
|
||||
<
|
||||
Reverse1, Reverse2, OverlayType, Geometry1, Geometry2
|
||||
>(turns, clusters);
|
||||
// Gather cluster properties (using even clusters with
|
||||
// discarded turns - for open turns)
|
||||
detail::overlay::gather_cluster_properties
|
||||
<
|
||||
Reverse1,
|
||||
Reverse2,
|
||||
OverlayType
|
||||
>(clusters, turns, target_operation,
|
||||
geometry1, geometry2, strategy);
|
||||
}
|
||||
else
|
||||
{
|
||||
// For buffer, this was already done before calling enrich_intersection_points.
|
||||
has_colocations = ! clusters.empty();
|
||||
}
|
||||
|
||||
discard_duplicate_turns(turns, geometry1, geometry2);
|
||||
|
||||
bool has_cc = false;
|
||||
|
||||
// Discard turns not part of target overlay
|
||||
for (auto& turn : turns)
|
||||
{
|
||||
@@ -491,11 +438,15 @@ inline void enrich_intersection_points(Turns& turns,
|
||||
strategy);
|
||||
}
|
||||
|
||||
if (! clusters.empty())
|
||||
{
|
||||
detail::overlay::cleanup_clusters(turns, clusters);
|
||||
detail::overlay::colocate_clusters(clusters, turns);
|
||||
}
|
||||
|
||||
// Create a map of vectors of indexed operation-types to be able
|
||||
// to sort intersection points PER RING
|
||||
mapped_vector_type mapped_vector;
|
||||
|
||||
detail::overlay::create_map(turns, mapped_vector,
|
||||
auto mapped_vector = detail::overlay::create_map(turns,
|
||||
detail::overlay::enriched_map_default_include_policy());
|
||||
|
||||
for (auto& pair : mapped_vector)
|
||||
@@ -506,14 +457,6 @@ inline void enrich_intersection_points(Turns& turns,
|
||||
strategy);
|
||||
}
|
||||
|
||||
if (has_colocations)
|
||||
{
|
||||
detail::overlay::cleanup_clusters(turns, clusters);
|
||||
detail::overlay::colocate_clusters(clusters, turns);
|
||||
}
|
||||
|
||||
// After cleaning up clusters assign the next turns
|
||||
|
||||
for (auto& pair : mapped_vector)
|
||||
{
|
||||
#ifdef BOOST_GEOMETRY_DEBUG_ENRICH
|
||||
@@ -524,7 +467,7 @@ inline void enrich_intersection_points(Turns& turns,
|
||||
detail::overlay::enrich_adapt(pair.second, turns);
|
||||
}
|
||||
|
||||
detail::overlay::enrich_assign(pair.second, turns, ! is_dissolve);
|
||||
detail::overlay::enrich_assign(pair.second, turns);
|
||||
}
|
||||
|
||||
if (has_cc)
|
||||
|
||||
@@ -364,23 +364,6 @@ inline bool handle_colocations(Turns& turns, Clusters& clusters)
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
struct is_turn_index
|
||||
{
|
||||
is_turn_index(signed_size_type index)
|
||||
: m_index(index)
|
||||
{}
|
||||
|
||||
template <typename Indexed>
|
||||
inline bool operator()(Indexed const& indexed) const
|
||||
{
|
||||
// Indexed is a indexed_turn_operation<Operation>
|
||||
return indexed.turn_index == m_index;
|
||||
}
|
||||
|
||||
signed_size_type m_index;
|
||||
};
|
||||
|
||||
template
|
||||
<
|
||||
typename Sbs,
|
||||
|
||||
@@ -43,7 +43,6 @@ struct indexed_turn_operation
|
||||
|
||||
std::size_t turn_index;
|
||||
std::size_t operation_index;
|
||||
bool skip;
|
||||
// use pointers to avoid copies, const& is not possible because of usage in vector
|
||||
segment_identifier const* other_seg_id; // segment id of other segment of intersection of two segments
|
||||
TurnOperation const* subject;
|
||||
@@ -53,7 +52,6 @@ struct indexed_turn_operation
|
||||
segment_identifier const& oid)
|
||||
: turn_index(ti)
|
||||
, operation_index(oi)
|
||||
, skip(false)
|
||||
, other_seg_id(&oid)
|
||||
, subject(boost::addressof(sub))
|
||||
{}
|
||||
|
||||
@@ -60,14 +60,6 @@ namespace detail { namespace overlay
|
||||
//! Default visitor for overlay, doing nothing
|
||||
struct overlay_null_visitor
|
||||
{
|
||||
void print(char const* ) {}
|
||||
|
||||
template <typename Turns>
|
||||
void print(char const* , Turns const& , int) {}
|
||||
|
||||
template <typename Turns>
|
||||
void print(char const* , Turns const& , int , int ) {}
|
||||
|
||||
template <typename Turns>
|
||||
void visit_turns(int , Turns const& ) {}
|
||||
|
||||
@@ -271,6 +263,8 @@ struct overlay
|
||||
cluster_info
|
||||
>;
|
||||
|
||||
constexpr operation_type target_operation = operation_from_overlay<OverlayType>::value;
|
||||
|
||||
turn_container_type turns;
|
||||
|
||||
detail::get_turns::no_interrupt_policy policy;
|
||||
@@ -303,6 +297,21 @@ struct overlay
|
||||
cluster_type clusters;
|
||||
std::map<ring_identifier, ring_turn_info> turn_info_per_ring;
|
||||
|
||||
// Handle colocations, gathering clusters and (below) their properties.
|
||||
detail::overlay::handle_colocations
|
||||
<
|
||||
Reverse1, Reverse2, OverlayType, Geometry1, Geometry2
|
||||
>(turns, clusters);
|
||||
|
||||
// Gather cluster properties (using even clusters with
|
||||
// discarded turns - for open turns)
|
||||
detail::overlay::gather_cluster_properties
|
||||
<
|
||||
Reverse1,
|
||||
Reverse2,
|
||||
OverlayType
|
||||
>(clusters, turns, target_operation, geometry1, geometry2, strategy);
|
||||
|
||||
geometry::enrich_intersection_points<Reverse1, Reverse2, OverlayType>(
|
||||
turns, clusters, geometry1, geometry2, strategy);
|
||||
|
||||
|
||||
@@ -173,6 +173,8 @@ struct dissolve_ring
|
||||
typename segment_ratio_type<point_type, RescalePolicy>::type
|
||||
>;
|
||||
|
||||
constexpr operation_type target_operation = operation_from_overlay<OverlayType>::value;
|
||||
|
||||
std::deque<turn_info> turns;
|
||||
detail::dissolve::no_interrupt_policy policy;
|
||||
detail::self_get_turn_points::self_turns
|
||||
@@ -198,6 +200,21 @@ struct dissolve_ring
|
||||
std::map<signed_size_type, detail::overlay::cluster_info> clusters;
|
||||
|
||||
// Enrich/traverse the polygons
|
||||
// Handle colocations, gathering clusters and (below) their properties.
|
||||
detail::overlay::handle_colocations
|
||||
<
|
||||
Reverse1, Reverse2, OverlayType, Geometry1, Geometry2
|
||||
>(turns, clusters);
|
||||
|
||||
// Gather cluster properties (using even clusters with
|
||||
// discarded turns - for open turns)
|
||||
detail::overlay::gather_cluster_properties
|
||||
<
|
||||
Reverse1,
|
||||
Reverse2,
|
||||
OverlayType
|
||||
>(clusters, turns, target_operation, geometry1, geometry2, strategy);
|
||||
|
||||
enrich_intersection_points<Reverse, Reverse, overlay_dissolve>(turns,
|
||||
clusters, input_ring, input_ring, rescale_policy,
|
||||
strategy);
|
||||
|
||||
@@ -159,6 +159,12 @@ std::vector<std::size_t> apply_overlay(
|
||||
|
||||
cluster_type clusters;
|
||||
|
||||
// Handle colocations, gathering clusters and (below) their properties.
|
||||
bg::detail::overlay::handle_colocations
|
||||
<
|
||||
Reverse1, Reverse2, OverlayType, Geometry1, Geometry2
|
||||
>(turns, clusters);
|
||||
|
||||
bg::enrich_intersection_points<Reverse1, Reverse2, OverlayType>(turns,
|
||||
clusters, geometry1, geometry2, strategy);
|
||||
|
||||
|
||||
@@ -79,45 +79,52 @@ void create_svg(std::string const& filename
|
||||
mapper.map(buffer, "stroke-opacity:0.9;stroke:rgb(0,0,0);fill:none;stroke-width:1");
|
||||
}
|
||||
|
||||
template <typename MultiPolygon, typename Settings>
|
||||
bool verify(std::string const& caseid, MultiPolygon const& mp, MultiPolygon const& buffer, Settings const& settings)
|
||||
template <typename Geometry, typename Buffer>
|
||||
bool verify_buffer(Geometry const& geometry, Buffer const& buffer, std::string& reason, bool check_validity)
|
||||
{
|
||||
using polygon_type = typename boost::range_value<MultiPolygon const>::type;
|
||||
|
||||
bool result = true;
|
||||
if (buffer.empty())
|
||||
{
|
||||
reason = "Buffer is empty";
|
||||
return false;
|
||||
}
|
||||
|
||||
// Area of buffer must be larger than of original polygon
|
||||
auto const area_mp = bg::area(mp);
|
||||
auto const area_mp = bg::area(geometry);
|
||||
auto const area_buf = bg::area(buffer);
|
||||
|
||||
if (area_buf < area_mp)
|
||||
{
|
||||
result = false;
|
||||
reason = "Buffer area is smaller than input area";
|
||||
return false;
|
||||
}
|
||||
|
||||
// Verify if all points are IN the buffer
|
||||
if (result)
|
||||
bool all_within = true;
|
||||
bg::for_each_point(geometry, [&all_within, &buffer](auto const& point)
|
||||
{
|
||||
for (auto const& polygon : mp)
|
||||
if (! bg::within(point, buffer))
|
||||
{
|
||||
typename bg::point_type<polygon_type>::type point;
|
||||
bg::point_on_border(point, polygon);
|
||||
if (! bg::within(point, buffer))
|
||||
{
|
||||
result = false;
|
||||
}
|
||||
all_within = false;
|
||||
}
|
||||
});
|
||||
|
||||
if (! all_within)
|
||||
{
|
||||
reason = "Any input points are outside the buffer";
|
||||
return false;
|
||||
}
|
||||
|
||||
if (result && settings.check_validity)
|
||||
return check_validity ? bg::is_valid(buffer, reason) : true;
|
||||
}
|
||||
|
||||
template <typename Geometry, typename MultiPolygon, typename Settings>
|
||||
bool verify(std::string const& caseid, Geometry const& geometry, MultiPolygon const& buffer, Settings const& settings)
|
||||
{
|
||||
std::string reason;
|
||||
bool const result = verify_buffer(geometry, buffer, reason, settings.check_validity);
|
||||
|
||||
if (! result)
|
||||
{
|
||||
bg::validity_failure_type failure;
|
||||
if (! bg::is_valid(buffer, failure)
|
||||
&& failure != bg::failure_intersecting_interiors)
|
||||
{
|
||||
std::cout << "Buffer is not valid: " << bg::validity_failure_type_message(failure) << std::endl;
|
||||
result = false;
|
||||
}
|
||||
std::cout << caseid << " " << reason << std::endl;
|
||||
}
|
||||
|
||||
bool svg = settings.svg;
|
||||
@@ -134,7 +141,7 @@ bool verify(std::string const& caseid, MultiPolygon const& mp, MultiPolygon cons
|
||||
{
|
||||
// Generate a unique name
|
||||
std::ostringstream out;
|
||||
out << "rec_pol_buffer_" << geometry_to_crc(mp)
|
||||
out << "rec_pol_buffer_" << geometry_to_crc(geometry)
|
||||
<< "_" << string_from_type<typename bg::coordinate_type<MultiPolygon>::type>::name()
|
||||
<< ".";
|
||||
filename = out.str();
|
||||
@@ -142,14 +149,14 @@ bool verify(std::string const& caseid, MultiPolygon const& mp, MultiPolygon cons
|
||||
|
||||
if (svg)
|
||||
{
|
||||
create_svg(filename + "svg", mp, buffer);
|
||||
create_svg(filename + "svg", geometry, buffer);
|
||||
}
|
||||
|
||||
if (wkt)
|
||||
{
|
||||
std::ofstream stream(filename + "wkt");
|
||||
// Stream input WKT
|
||||
stream << bg::wkt(mp) << std::endl;
|
||||
stream << bg::wkt(geometry) << std::endl;
|
||||
// If you need the output WKT, then stream bg::wkt(buffer)
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user