diff options
Diffstat (limited to 'boost/geometry/policies/is_valid/failing_reason_policy.hpp')
-rw-r--r-- | boost/geometry/policies/is_valid/failing_reason_policy.hpp | 218 |
1 files changed, 218 insertions, 0 deletions
diff --git a/boost/geometry/policies/is_valid/failing_reason_policy.hpp b/boost/geometry/policies/is_valid/failing_reason_policy.hpp new file mode 100644 index 0000000000..b99803bead --- /dev/null +++ b/boost/geometry/policies/is_valid/failing_reason_policy.hpp @@ -0,0 +1,218 @@ +// Boost.Geometry (aka GGL, Generic Geometry Library) + +// Copyright (c) 2015, Oracle and/or its affiliates. + +// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle + +// Licensed under the Boost Software License version 1.0. +// http://www.boost.org/users/license.html + +#ifndef BOOST_GEOMETRY_POLICIES_IS_VALID_FAILING_REASON_POLICY_HPP +#define BOOST_GEOMETRY_POLICIES_IS_VALID_FAILING_REASON_POLICY_HPP + +#include <sstream> + +#include <boost/geometry/io/dsv/write.hpp> +#include <boost/geometry/util/range.hpp> +#include <boost/geometry/algorithms/validity_failure_type.hpp> +#include <boost/geometry/algorithms/detail/overlay/debug_turn_info.hpp> + + +namespace boost { namespace geometry +{ + + +inline char const* validity_failure_type_message(validity_failure_type failure) +{ + switch (failure) + { + case no_failure: + return "Geometry is valid"; + case failure_few_points: + return "Geometry has too few points"; + case failure_wrong_topological_dimension: + return "Geometry has wrong topological dimension"; + case failure_not_closed: + return "Geometry is defined as closed but is open"; + case failure_spikes: + return "Geometry has spikes"; + case failure_self_intersections: + return "Geometry has invalid self-intersections"; + case failure_wrong_orientation: + return "Geometry has wrong orientation"; + case failure_interior_rings_outside: + return "Geometry has interior rings defined outside the outer boundary"; + case failure_nested_interior_rings: + return "Geometry has nested interior rings"; + case failure_disconnected_interior: + return "Geometry has disconnected interior"; + case failure_intersecting_interiors: + return "Multi-polygon has intersecting interiors"; + case failure_duplicate_points: + return "Geometry has duplicate (consecutive) points"; + case failure_wrong_corner_order: + return "Box has corners in wrong order"; + default: // to avoid -Wreturn-type warning + return ""; + } +} + + +template <bool AllowDuplicates = true, bool AllowSpikes = true> +class failing_reason_policy +{ +private: + static inline + validity_failure_type transform_failure_type(validity_failure_type failure) + { + if (AllowDuplicates && failure == failure_duplicate_points) + { + return no_failure; + } + return failure; + } + + static inline + validity_failure_type transform_failure_type(validity_failure_type failure, + bool is_linear) + { + if (is_linear && AllowSpikes && failure == failure_spikes) + { + return no_failure; + } + return transform_failure_type(failure); + } + + inline void set_failure_message(validity_failure_type failure) + { + m_oss.str(""); + m_oss.clear(); + m_oss << validity_failure_type_message(failure); + } + + template + < + validity_failure_type Failure, + typename Data1, + typename Data2 = Data1, + typename Dummy = void + > + struct process_data + { + static inline void apply(std::ostringstream&, Data1 const&) + { + } + + static inline void apply(std::ostringstream&, + Data1 const&, + Data2 const&) + { + } + }; + + template <typename SpikePoint> + struct process_data<failure_spikes, bool, SpikePoint> + { + static inline void apply(std::ostringstream& oss, + bool is_linear, + SpikePoint const& spike_point) + { + if (is_linear && AllowSpikes) + { + return; + } + + oss << ". A spike point was found with apex at " + << geometry::dsv(spike_point); + } + }; + + template <typename Turns> + struct process_data<failure_self_intersections, Turns> + { + static inline + void apply_to_segment_identifier(std::ostringstream& oss, + segment_identifier seg_id) + { + oss << "{" << seg_id.source_index + << ", " << seg_id.multi_index + << ", " << seg_id.ring_index + << ", " << seg_id.segment_index + << "}"; + } + + static inline void apply(std::ostringstream& oss, + Turns const& turns) + { + typedef typename boost::range_value<Turns>::type turn_type; + turn_type const& turn = range::front(turns); + oss << ". A self-intersection point was found at " + << geometry::dsv(turn.point); + + oss << "; method: " << method_char(turn.method) + << "; operations: " + << operation_char(turn.operations[0].operation) + << "/" + << operation_char(turn.operations[1].operation) + << "; segment IDs {source, multi, ring, segment}: "; + apply_to_segment_identifier(oss, turn.operations[0].seg_id); + oss << "/"; + apply_to_segment_identifier(oss, turn.operations[1].seg_id); + } + }; + + template <typename Point> + struct process_data<failure_duplicate_points, Point> + { + static inline void apply(std::ostringstream& oss, + Point const& point) + { + if (AllowDuplicates) + { + return; + } + oss << ". Duplicate points were found near point " + << geometry::dsv(point); + } + }; + +public: + failing_reason_policy(std::ostringstream& oss) + : m_oss(oss) + {} + + template <validity_failure_type Failure> + inline bool apply() + { + validity_failure_type const failure = transform_failure_type(Failure); + set_failure_message(failure); + return failure == no_failure; + } + + template <validity_failure_type Failure, typename Data> + inline bool apply(Data const& data) + { + validity_failure_type const failure = transform_failure_type(Failure); + set_failure_message(failure); + process_data<Failure, Data>::apply(m_oss, data); + return failure == no_failure; + } + + template <validity_failure_type Failure, typename Data1, typename Data2> + inline bool apply(Data1 const& data1, Data2 const& data2) + { + validity_failure_type const failure + = transform_failure_type(Failure, data1); + set_failure_message(failure); + process_data<Failure, Data1, Data2>::apply(m_oss, data1, data2); + return failure == no_failure; + } + +private: + std::ostringstream& m_oss; +}; + + +}} // namespace boost::geometry + +#endif // BOOST_GEOMETRY_POLICIES_IS_VALID_FAILING_REASON_POLICY_HPP |