Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-01-18 09:35:36

0001 // Boost.Geometry (aka GGL, Generic Geometry Library)
0002 
0003 // Copyright (c) 2023 Adam Wulkiewicz, Lodz, Poland.
0004 
0005 // Copyright (c) 2015, Oracle and/or its affiliates.
0006 // Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle
0007 // Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
0008 
0009 // Licensed under the Boost Software License version 1.0.
0010 // http://www.boost.org/users/license.html
0011 
0012 #ifndef BOOST_GEOMETRY_POLICIES_IS_VALID_FAILING_REASON_POLICY_HPP
0013 #define BOOST_GEOMETRY_POLICIES_IS_VALID_FAILING_REASON_POLICY_HPP
0014 
0015 #include <sstream>
0016 
0017 #include <boost/geometry/io/dsv/write.hpp>
0018 #include <boost/geometry/util/constexpr.hpp>
0019 #include <boost/geometry/util/range.hpp>
0020 #include <boost/geometry/algorithms/validity_failure_type.hpp>
0021 #include <boost/geometry/algorithms/detail/overlay/debug_turn_info.hpp>
0022 
0023 
0024 namespace boost { namespace geometry
0025 {
0026 
0027 
0028 inline char const* validity_failure_type_message(validity_failure_type failure)
0029 {
0030     switch (failure)
0031     {
0032     case no_failure:
0033         return "Geometry is valid";
0034     case failure_few_points:
0035         return "Geometry has too few points";
0036     case failure_wrong_topological_dimension:
0037         return "Geometry has wrong topological dimension";
0038     case failure_not_closed:
0039         return "Geometry is defined as closed but is open";
0040     case failure_spikes:
0041         return "Geometry has spikes";
0042     case failure_self_intersections:
0043         return "Geometry has invalid self-intersections";
0044     case failure_wrong_orientation:
0045         return "Geometry has wrong orientation";
0046     case failure_interior_rings_outside:
0047         return "Geometry has interior rings defined outside the outer boundary";
0048     case failure_nested_interior_rings:
0049         return "Geometry has nested interior rings";
0050     case failure_disconnected_interior:
0051         return "Geometry has disconnected interior";
0052     case failure_intersecting_interiors:
0053         return "Multi-polygon has intersecting interiors";
0054     case failure_duplicate_points:
0055         return "Geometry has duplicate (consecutive) points";
0056     case failure_wrong_corner_order:
0057         return "Box has corners in wrong order";
0058     case failure_invalid_coordinate:
0059         return "Geometry has point(s) with invalid coordinate(s)";
0060     default: // to avoid -Wreturn-type warning
0061         return "";
0062     }
0063 }
0064 
0065 
0066 template <bool AllowDuplicates = true, bool AllowSpikes = true>
0067 class failing_reason_policy
0068 {
0069 private:
0070     static inline
0071     validity_failure_type transform_failure_type(validity_failure_type failure)
0072     {
0073         if BOOST_GEOMETRY_CONSTEXPR (AllowDuplicates)
0074         {
0075             if (failure == failure_duplicate_points)
0076             {
0077                 return no_failure;
0078             }
0079         }
0080         return failure;
0081     }
0082 
0083     static inline
0084     validity_failure_type transform_failure_type(validity_failure_type failure,
0085                                                  bool is_linear)
0086     {
0087         if BOOST_GEOMETRY_CONSTEXPR (AllowSpikes)
0088         {
0089             if (is_linear && failure == failure_spikes)
0090             {
0091                 return no_failure;
0092             }
0093         }
0094         return transform_failure_type(failure);
0095     }
0096 
0097     inline void set_failure_message(validity_failure_type failure)
0098     {
0099         m_oss.str("");
0100         m_oss.clear();
0101         m_oss << validity_failure_type_message(failure);
0102     }
0103 
0104     template
0105     <
0106         validity_failure_type Failure,
0107         typename Data1,
0108         typename Data2 = Data1,
0109         typename Dummy = void
0110     >
0111     struct process_data
0112     {
0113         static inline void apply(std::ostringstream&, Data1 const&)
0114         {
0115         }
0116 
0117         static inline void apply(std::ostringstream&,
0118                                  Data1 const&,
0119                                  Data2 const&)
0120         {
0121         }
0122     };
0123 
0124     template <typename SpikePoint>
0125     struct process_data<failure_spikes, bool, SpikePoint>
0126     {
0127         static inline void apply(std::ostringstream& oss,
0128                                  bool is_linear,
0129                                  SpikePoint const& spike_point)
0130         {
0131             if BOOST_GEOMETRY_CONSTEXPR (AllowSpikes)
0132             {
0133                 if (is_linear)
0134                 {
0135                     return;
0136                 }
0137             }
0138 
0139             oss << ". A spike point was found with apex at "
0140                 << geometry::dsv(spike_point);
0141         }
0142     };
0143 
0144     template <typename Turns>
0145     struct process_data<failure_self_intersections, Turns>
0146     {
0147         static inline
0148         void apply_to_segment_identifier(std::ostringstream& oss,
0149                                          segment_identifier seg_id)
0150         {
0151             oss << "{" << seg_id.source_index
0152                 << ", " << seg_id.multi_index
0153                 << ", " << seg_id.ring_index
0154                 << ", " << seg_id.segment_index
0155                 << "}";
0156         }
0157 
0158         static inline void apply(std::ostringstream& oss,
0159                                  Turns const& turns)
0160         {
0161             typedef typename boost::range_value<Turns>::type turn_type;
0162             turn_type const& turn = range::front(turns);
0163             oss << ". A self-intersection point was found at "
0164                 << geometry::dsv(turn.point);
0165 
0166             oss << "; method: " << method_char(turn.method)
0167                 << "; operations: "
0168                 << operation_char(turn.operations[0].operation)
0169                 << "/"
0170                 << operation_char(turn.operations[1].operation)
0171                 << "; segment IDs {source, multi, ring, segment}: ";
0172             apply_to_segment_identifier(oss, turn.operations[0].seg_id);
0173             oss << "/";
0174             apply_to_segment_identifier(oss, turn.operations[1].seg_id);
0175         }
0176     };
0177 
0178     template <typename Point>
0179     struct process_data<failure_duplicate_points, Point>
0180     {
0181         static inline void apply(std::ostringstream& oss,
0182                                  Point const& point)
0183         {
0184             if BOOST_GEOMETRY_CONSTEXPR (AllowDuplicates)
0185             {
0186                 return;
0187             }
0188             oss << ". Duplicate points were found near point "
0189                 << geometry::dsv(point);
0190         }
0191     };
0192 
0193 public:
0194     failing_reason_policy(std::ostringstream& oss)
0195         : m_oss(oss)
0196     {}
0197 
0198     template <validity_failure_type Failure>
0199     inline bool apply()
0200     {
0201         validity_failure_type const failure = transform_failure_type(Failure);
0202         set_failure_message(failure);
0203         return failure == no_failure;
0204     }
0205 
0206     template <validity_failure_type Failure, typename Data>
0207     inline bool apply(Data const& data)
0208     {
0209         validity_failure_type const failure = transform_failure_type(Failure);
0210         set_failure_message(failure);
0211         process_data<Failure, Data>::apply(m_oss, data);
0212         return failure == no_failure;
0213     }
0214 
0215     template <validity_failure_type Failure, typename Data1, typename Data2>
0216     inline bool apply(Data1 const& data1, Data2 const& data2)
0217     {
0218         validity_failure_type const failure
0219             = transform_failure_type(Failure, data1);
0220         set_failure_message(failure);
0221         process_data<Failure, Data1, Data2>::apply(m_oss, data1, data2);
0222         return failure == no_failure;
0223     }
0224 
0225 private:
0226     std::ostringstream& m_oss;
0227 };
0228 
0229 
0230 }} // namespace boost::geometry
0231 
0232 #endif // BOOST_GEOMETRY_POLICIES_IS_VALID_FAILING_REASON_POLICY_HPP