123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381 |
- // Boost.Geometry (aka GGL, Generic Geometry Library)
- // Copyright (c) 2014-2015, Oracle and/or its affiliates.
- // Licensed under the Boost Software License version 1.0.
- // http://www.boost.org/users/license.html
- // Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle
- #ifndef BOOST_GEOMETRY_TEST_SET_OPS_LINEAR_LINEAR_HPP
- #define BOOST_GEOMETRY_TEST_SET_OPS_LINEAR_LINEAR_HPP
- #include <string>
- #include <fstream>
- #include <sstream>
- #include <algorithm>
- #include <boost/core/ignore_unused.hpp>
- #include <boost/range.hpp>
- #include <boost/typeof/typeof.hpp>
- #include <boost/geometry/policies/compare.hpp>
- #include <boost/geometry/algorithms/equals.hpp>
- #include <boost/geometry/algorithms/reverse.hpp>
- #include "test_get_turns_ll_invariance.hpp"
- namespace bg = ::boost::geometry;
- template <typename Linestring1, typename Linestring2>
- struct ls_less
- {
- typedef typename boost::range_iterator<Linestring1 const>::type Iterator1;
- typedef typename boost::range_iterator<Linestring2 const>::type Iterator2;
- typedef bg::less<typename bg::point_type<Linestring1>::type> point_less;
- bool operator()(Linestring1 const& linestring1,
- Linestring2 const& linestring2) const
- {
- if (boost::size(linestring1) != boost::size(linestring2))
- {
- return boost::size(linestring1) < boost::size(linestring2);
- }
- Iterator1 it1 = boost::begin(linestring1);
- Iterator2 it2 = boost::begin(linestring2);
- point_less less;
- for (; it1 != boost::end(linestring1); ++it1, ++it2)
- {
- if (less(*it1, *it2))
- {
- return true;
- }
- if (less(*it2, *it1))
- {
- return false;
- }
- }
- return false;
- }
- };
- template <typename Linestring1, typename Linestring2>
- struct ls_equal
- {
- bool operator()(Linestring1 const& linestring1,
- Linestring2 const& linestring2) const
- {
- ls_less<Linestring1, Linestring2> less;
- return ! less(linestring1, linestring2)
- && ! less(linestring2, linestring1);
- }
- };
- template <typename Point1, typename Point2>
- class pt_equal
- {
- private:
- double m_tolerence;
- template <typename T>
- static inline T const& get_max(T const& a, T const& b, T const& c)
- {
- return (std::max)((std::max)(a, b), c);
- }
- template <typename T>
- static inline bool check_close(T const& a, T const& b, T const& tol)
- {
- return (a == b)
- || (std::abs(a - b) <= tol * get_max(std::abs(a), std::abs(b), 1.0));
- }
- public:
- pt_equal(double tolerence) : m_tolerence(tolerence) {}
- bool operator()(Point1 const& point1, Point2 const& point2) const
- {
- // allow for some tolerence in testing equality of points
- return check_close(bg::get<0>(point1), bg::get<0>(point2), m_tolerence)
- && check_close(bg::get<1>(point1), bg::get<1>(point2), m_tolerence);
- }
- };
- template <bool EnableUnique = false>
- struct multilinestring_equals
- {
- template <typename MultiLinestring, bool Enable>
- struct unique
- {
- typedef typename boost::range_value<MultiLinestring>::type Linestring;
- typedef typename bg::point_type<MultiLinestring>::type point_type;
- typedef ls_equal<Linestring, Linestring> linestring_equal;
- typedef pt_equal<point_type, point_type> point_equal;
- template <typename Range, typename EqualTo>
- void apply_to_range(Range& range, EqualTo const& equal_to)
- {
- range.erase(std::unique(boost::begin(range), boost::end(range),
- equal_to),
- boost::end(range));
- }
- void operator()(MultiLinestring& mls, double tolerance)
- {
- for (typename boost::range_iterator<MultiLinestring>::type it
- = boost::begin(mls); it != boost::end(mls); ++it)
- {
- apply_to_range(*it, point_equal(tolerance));
- }
- apply_to_range(mls, linestring_equal());
- }
- };
- template <typename MultiLinestring>
- struct unique<MultiLinestring, false>
- {
- void operator()(MultiLinestring&, double)
- {
- }
- };
- template <typename MultiLinestring1, typename MultiLinestring2>
- static inline
- bool apply(MultiLinestring1 const& multilinestring1,
- MultiLinestring2 const& multilinestring2,
- double tolerance)
- {
- typedef typename boost::range_iterator
- <
- MultiLinestring1 const
- >::type ls1_iterator;
- typedef typename boost::range_iterator
- <
- MultiLinestring2 const
- >::type ls2_iterator;
- typedef typename boost::range_value<MultiLinestring1>::type Linestring1;
- typedef typename boost::range_value<MultiLinestring2>::type Linestring2;
- typedef typename boost::range_iterator
- <
- Linestring1 const
- >::type point1_iterator;
- typedef typename boost::range_iterator
- <
- Linestring2 const
- >::type point2_iterator;
- typedef ls_less<Linestring1, Linestring2> linestring_less;
- typedef pt_equal
- <
- typename boost::range_value
- <
- typename boost::range_value<MultiLinestring1>::type
- >::type,
- typename boost::range_value
- <
- typename boost::range_value<MultiLinestring2>::type
- >::type
- > point_equal;
- MultiLinestring1 mls1 = multilinestring1;
- MultiLinestring2 mls2 = multilinestring2;
- std::sort(boost::begin(mls1), boost::end(mls1), linestring_less());
- std::sort(boost::begin(mls2), boost::end(mls2), linestring_less());
- unique<MultiLinestring1, EnableUnique>()(mls1, tolerance);
- unique<MultiLinestring2, EnableUnique>()(mls2, tolerance);
- if (boost::size(mls1) != boost::size(mls2))
- {
- return false;
- }
- ls1_iterator it1 = boost::begin(mls1);
- ls2_iterator it2 = boost::begin(mls2);
- for (; it1 != boost::end(mls1); ++it1, ++it2)
- {
- if (boost::size(*it1) != boost::size(*it2))
- {
- return false;
- }
- point1_iterator pit1 = boost::begin(*it1);
- point2_iterator pit2 = boost::begin(*it2);
- for (; pit1 != boost::end(*it1); ++pit1, ++pit2)
- {
- if (! point_equal(tolerance)(*pit1, *pit2))
- {
- return false;
- }
- }
- }
- return true;
- }
- };
- class equals
- {
- private:
- template <typename Linestring, typename OutputIterator>
- static inline OutputIterator
- isolated_point_to_segment(Linestring const& linestring, OutputIterator oit)
- {
- BOOST_ASSERT( boost::size(linestring) == 1 );
- *oit++ = *boost::begin(linestring);
- *oit++ = *boost::begin(linestring);
- return oit;
- }
- template <typename MultiLinestring, typename OutputIterator>
- static inline OutputIterator
- convert_isolated_points_to_segments(MultiLinestring const& multilinestring,
- OutputIterator oit)
- {
- BOOST_AUTO_TPL(it, boost::begin(multilinestring));
- for (; it != boost::end(multilinestring); ++it)
- {
- if (boost::size(*it) == 1)
- {
- typename boost::range_value<MultiLinestring>::type linestring;
- isolated_point_to_segment(*it, std::back_inserter(linestring));
- *oit++ = linestring;
- }
- else
- {
- *oit++ = *it;
- }
- }
- return oit;
- }
- template <typename MultiLinestring1, typename MultiLinestring2>
- static inline bool apply_base(MultiLinestring1 const& multilinestring1,
- MultiLinestring2 const& multilinestring2,
- double tolerance)
- {
- typedef multilinestring_equals<true> mls_equals;
- if (mls_equals::apply(multilinestring1, multilinestring2, tolerance))
- {
- return true;
- }
- MultiLinestring1 reverse_multilinestring1 = multilinestring1;
- bg::reverse(reverse_multilinestring1);
- if (mls_equals::apply(reverse_multilinestring1,
- multilinestring2,
- tolerance))
- {
- return true;
- }
- MultiLinestring2 reverse_multilinestring2 = multilinestring2;
- bg::reverse(reverse_multilinestring2);
- if (mls_equals::apply(multilinestring1,
- reverse_multilinestring2,
- tolerance))
- {
- return true;
- }
- return mls_equals::apply(reverse_multilinestring1,
- reverse_multilinestring2,
- tolerance);
- }
- public:
- template <typename MultiLinestring1, typename MultiLinestring2>
- static inline bool apply(MultiLinestring1 const& multilinestring1,
- MultiLinestring2 const& multilinestring2,
- double tolerance)
- {
- #ifndef BOOST_GEOMETRY_ALLOW_ONE_POINT_LINESTRINGS
- MultiLinestring1 converted_multilinestring1;
- convert_isolated_points_to_segments
- (multilinestring1, std::back_inserter(converted_multilinestring1));
- MultiLinestring2 converted_multilinestring2;
- convert_isolated_points_to_segments
- (multilinestring2, std::back_inserter(converted_multilinestring2));
- return apply_base(converted_multilinestring1,
- converted_multilinestring2, tolerance);
- #else
- return apply_base(multilinestring1, multilinestring2, tolerance);
- #endif
- }
- };
- template <typename Output, typename G1, typename G2>
- void set_operation_output(std::string const& set_op_id,
- std::string const& caseid,
- G1 const& g1, G2 const& g2,
- Output const& output)
- {
- boost::ignore_unused(set_op_id, caseid, g1, g2, output);
- #if defined(TEST_WITH_SVG)
- typedef typename bg::coordinate_type<G1>::type coordinate_type;
- typedef typename bg::point_type<G1>::type point_type;
- std::ostringstream filename;
- filename << "svgs/" << set_op_id << "_" << caseid << ".svg";
- std::ofstream svg(filename.str().c_str());
- bg::svg_mapper<point_type> mapper(svg, 500, 500);
- mapper.add(g1);
- mapper.add(g2);
- mapper.map(g2, "stroke-opacity:1;stroke:rgb(153,204,0);stroke-width:4");
- mapper.map(g1, "stroke-opacity:1;stroke:rgb(51,51,153);stroke-width:2");
- BOOST_AUTO_TPL(it, output.begin());
- for (; it != output.end(); ++it)
- {
- if ( boost::size(*it) == 2
- && bg::equals(*boost::begin(*it), *++boost::begin(*it)) )
- {
- // draw isolated points (generated by the intersection operation)
- mapper.map(*boost::begin(*it),
- "fill:rgb(255,0,255);stroke:rgb(0,0,0);stroke-width:1",
- 4);
- }
- else
- {
- mapper.map(*it,
- "stroke-opacity:0.4;stroke:rgb(255,0,255);stroke-width:8");
- }
- }
- #endif
- }
- #endif // BOOST_GEOMETRY_TEST_SET_OPS_LINEAR_LINEAR_HPP
|