?????????? ????????? - ??????????????? - /home/agenciai/public_html/cd38d8/polygon.zip
???????
PK �b�[睚o�K �K polygon_45_set_concept.hppnu �[��� /* Copyright 2008 Intel Corporation Use, modification and distribution are 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_POLYGON_POLYGON_45_SET_CONCEPT_HPP #define BOOST_POLYGON_POLYGON_45_SET_CONCEPT_HPP #include "polygon_45_set_data.hpp" #include "polygon_45_set_traits.hpp" #include "detail/polygon_45_touch.hpp" namespace boost { namespace polygon{ template <typename T, typename T2> struct is_either_polygon_45_set_type { typedef typename gtl_or<typename is_polygon_45_set_type<T>::type, typename is_polygon_45_set_type<T2>::type >::type type; }; template <typename T> struct is_polygon_45_or_90_set_type { typedef typename gtl_or<typename is_polygon_45_set_type<T>::type, typename is_polygon_90_set_type<T>::type >::type type; }; template <typename polygon_set_type> typename enable_if< typename gtl_if<typename is_polygon_45_or_90_set_type<polygon_set_type>::type>::type, typename polygon_45_set_traits<polygon_set_type>::iterator_type>::type begin_45_set_data(const polygon_set_type& polygon_set) { return polygon_45_set_traits<polygon_set_type>::begin(polygon_set); } template <typename polygon_set_type> typename enable_if< typename gtl_if<typename is_polygon_45_or_90_set_type<polygon_set_type>::type>::type, typename polygon_45_set_traits<polygon_set_type>::iterator_type>::type end_45_set_data(const polygon_set_type& polygon_set) { return polygon_45_set_traits<polygon_set_type>::end(polygon_set); } template <typename polygon_set_type> typename enable_if< typename gtl_if<typename is_polygon_45_set_type<polygon_set_type>::type>::type, bool>::type clean(const polygon_set_type& polygon_set) { return polygon_45_set_traits<polygon_set_type>::clean(polygon_set); } //assign template <typename polygon_set_type_1, typename polygon_set_type_2> typename enable_if< typename gtl_and< typename gtl_if<typename is_mutable_polygon_45_set_type<polygon_set_type_1>::type>::type, typename gtl_if<typename is_polygon_45_or_90_set_type<polygon_set_type_2>::type>::type>::type, polygon_set_type_1>::type & assign(polygon_set_type_1& lvalue, const polygon_set_type_2& rvalue) { polygon_45_set_mutable_traits<polygon_set_type_1>::set(lvalue, begin_45_set_data(rvalue), end_45_set_data(rvalue)); return lvalue; } //get trapezoids template <typename output_container_type, typename polygon_set_type> typename enable_if< typename gtl_if<typename is_polygon_45_set_type<polygon_set_type>::type>::type, void>::type get_trapezoids(output_container_type& output, const polygon_set_type& polygon_set) { clean(polygon_set); polygon_45_set_data<typename polygon_45_set_traits<polygon_set_type>::coordinate_type> ps; assign(ps, polygon_set); ps.get_trapezoids(output); } //get trapezoids template <typename output_container_type, typename polygon_set_type> typename enable_if< typename gtl_if<typename is_polygon_45_set_type<polygon_set_type>::type>::type, void>::type get_trapezoids(output_container_type& output, const polygon_set_type& polygon_set, orientation_2d slicing_orientation) { clean(polygon_set); polygon_45_set_data<typename polygon_45_set_traits<polygon_set_type>::coordinate_type> ps; assign(ps, polygon_set); ps.get_trapezoids(output, slicing_orientation); } //equivalence template <typename polygon_set_type_1, typename polygon_set_type_2> typename enable_if< typename gtl_and_3<typename gtl_if<typename is_polygon_45_or_90_set_type<polygon_set_type_1>::type>::type, typename gtl_if<typename is_polygon_45_or_90_set_type<polygon_set_type_2>::type>::type, typename gtl_if<typename is_either_polygon_45_set_type<polygon_set_type_1, polygon_set_type_2>::type>::type>::type, bool>::type equivalence(const polygon_set_type_1& lvalue, const polygon_set_type_2& rvalue) { polygon_45_set_data<typename polygon_45_set_traits<polygon_set_type_1>::coordinate_type> ps1; assign(ps1, lvalue); polygon_45_set_data<typename polygon_45_set_traits<polygon_set_type_2>::coordinate_type> ps2; assign(ps2, rvalue); return ps1 == ps2; } //clear template <typename polygon_set_type> typename enable_if< typename gtl_if<typename is_mutable_polygon_45_set_type<polygon_set_type>::type>::type, void>::type clear(polygon_set_type& polygon_set) { polygon_45_set_data<typename polygon_45_set_traits<polygon_set_type>::coordinate_type> ps; assign(polygon_set, ps); } //empty template <typename polygon_set_type> typename enable_if< typename gtl_if<typename is_mutable_polygon_45_set_type<polygon_set_type>::type>::type, bool>::type empty(const polygon_set_type& polygon_set) { if(clean(polygon_set)) return begin_45_set_data(polygon_set) == end_45_set_data(polygon_set); polygon_45_set_data<typename polygon_45_set_traits<polygon_set_type>::coordinate_type> ps; assign(ps, polygon_set); ps.clean(); return ps.empty(); } //extents template <typename polygon_set_type, typename rectangle_type> typename enable_if< typename gtl_and< typename gtl_if<typename is_mutable_polygon_45_set_type<polygon_set_type>::type>::type, typename is_mutable_rectangle_concept<typename geometry_concept<rectangle_type>::type>::type>::type, bool>::type extents(rectangle_type& extents_rectangle, const polygon_set_type& polygon_set) { clean(polygon_set); polygon_45_set_data<typename polygon_45_set_traits<polygon_set_type>::coordinate_type> ps; assign(ps, polygon_set); return ps.extents(extents_rectangle); } //area template <typename polygon_set_type> typename enable_if< typename is_mutable_polygon_45_set_type<polygon_set_type>::type, typename coordinate_traits<typename polygon_45_set_traits<polygon_set_type>::coordinate_type>::area_type>::type area(const polygon_set_type& polygon_set) { typedef typename polygon_45_set_traits<polygon_set_type>::coordinate_type Unit; typedef polygon_45_with_holes_data<Unit> p_type; typedef typename coordinate_traits<Unit>::area_type area_type; std::vector<p_type> polys; assign(polys, polygon_set); area_type retval = (area_type)0; for(std::size_t i = 0; i < polys.size(); ++i) { retval += area(polys[i]); } return retval; } //interact template <typename polygon_set_type_1, typename polygon_set_type_2> typename enable_if < typename gtl_and< typename gtl_if<typename is_mutable_polygon_45_set_type<polygon_set_type_1>::type>::type, typename gtl_if<typename is_polygon_45_or_90_set_type<polygon_set_type_2>::type>::type >::type, polygon_set_type_1>::type& interact(polygon_set_type_1& polygon_set_1, const polygon_set_type_2& polygon_set_2) { typedef typename polygon_45_set_traits<polygon_set_type_1>::coordinate_type Unit; std::vector<polygon_45_data<Unit> > polys; assign(polys, polygon_set_1); std::vector<std::set<int> > graph(polys.size()+1, std::set<int>()); connectivity_extraction_45<Unit> ce; ce.insert(polygon_set_2); for(std::size_t i = 0; i < polys.size(); ++i){ ce.insert(polys[i]); } ce.extract(graph); clear(polygon_set_1); polygon_45_set_data<Unit> ps; for(std::set<int>::iterator itr = graph[0].begin(); itr != graph[0].end(); ++itr){ ps.insert(polys[(*itr)-1]); } assign(polygon_set_1, ps); return polygon_set_1; } // //self_intersect // template <typename polygon_set_type> // typename enable_if< typename is_mutable_polygon_45_set_type<polygon_set_type>::type>::type, // polygon_set_type>::type & // self_intersect(polygon_set_type& polygon_set) { // typedef typename polygon_45_set_traits<polygon_set_type>::coordinate_type Unit; // //TODO // } template <typename polygon_set_type, typename coord_type> typename enable_if< typename is_mutable_polygon_45_set_type<polygon_set_type>::type, polygon_set_type>::type & resize(polygon_set_type& polygon_set, coord_type resizing, RoundingOption rounding = CLOSEST, CornerOption corner = INTERSECTION) { typedef typename polygon_45_set_traits<polygon_set_type>::coordinate_type Unit; clean(polygon_set); polygon_45_set_data<Unit> ps; assign(ps, polygon_set); ps.resize(resizing, rounding, corner); assign(polygon_set, ps); return polygon_set; } template <typename polygon_set_type> typename enable_if< typename is_mutable_polygon_45_set_type<polygon_set_type>::type, polygon_set_type>::type & bloat(polygon_set_type& polygon_set, typename coordinate_traits<typename polygon_45_set_traits<polygon_set_type>::coordinate_type>::unsigned_area_type bloating) { return resize(polygon_set, static_cast<typename polygon_45_set_traits<polygon_set_type>::coordinate_type>(bloating)); } template <typename polygon_set_type> typename enable_if< typename is_mutable_polygon_45_set_type<polygon_set_type>::type, polygon_set_type>::type & shrink(polygon_set_type& polygon_set, typename coordinate_traits<typename polygon_45_set_traits<polygon_set_type>::coordinate_type>::unsigned_area_type shrinking) { return resize(polygon_set, -(typename polygon_45_set_traits<polygon_set_type>::coordinate_type)shrinking); } template <typename polygon_set_type> typename enable_if< typename is_mutable_polygon_45_set_type<polygon_set_type>::type, polygon_set_type>::type & grow_and(polygon_set_type& polygon_set, typename coordinate_traits<typename polygon_45_set_traits<polygon_set_type>::coordinate_type>::unsigned_area_type bloating) { typedef typename polygon_45_set_traits<polygon_set_type>::coordinate_type Unit; std::vector<polygon_45_data<Unit> > polys; assign(polys, polygon_set); clear(polygon_set); polygon_45_set_data<Unit> ps; for(std::size_t i = 0; i < polys.size(); ++i) { polygon_45_set_data<Unit> tmpPs; tmpPs.insert(polys[i]); bloat(tmpPs, bloating); tmpPs.clean(); //apply implicit OR on tmp polygon set ps.insert(tmpPs); } ps.self_intersect(); assign(polygon_set, ps); return polygon_set; } template <typename polygon_set_type> typename enable_if< typename is_mutable_polygon_45_set_type<polygon_set_type>::type, polygon_set_type>::type & scale_up(polygon_set_type& polygon_set, typename coordinate_traits<typename polygon_45_set_traits<polygon_set_type>::coordinate_type>::unsigned_area_type factor) { typedef typename polygon_45_set_traits<polygon_set_type>::coordinate_type Unit; clean(polygon_set); polygon_45_set_data<Unit> ps; assign(ps, polygon_set); ps.scale_up(factor); assign(polygon_set, ps); return polygon_set; } template <typename polygon_set_type> typename enable_if< typename is_mutable_polygon_45_set_type<polygon_set_type>::type, polygon_set_type>::type & scale_down(polygon_set_type& polygon_set, typename coordinate_traits<typename polygon_45_set_traits<polygon_set_type>::coordinate_type>::unsigned_area_type factor) { typedef typename polygon_45_set_traits<polygon_set_type>::coordinate_type Unit; clean(polygon_set); polygon_45_set_data<Unit> ps; assign(ps, polygon_set); ps.scale_down(factor); assign(polygon_set, ps); return polygon_set; } template <typename polygon_set_type> typename enable_if< typename is_mutable_polygon_45_set_type<polygon_set_type>::type, polygon_set_type>::type & scale(polygon_set_type& polygon_set, double factor) { typedef typename polygon_45_set_traits<polygon_set_type>::coordinate_type Unit; clean(polygon_set); polygon_45_set_data<Unit> ps; assign(ps, polygon_set); ps.scale(factor); assign(polygon_set, ps); return polygon_set; } //self_intersect template <typename polygon_set_type> typename enable_if< typename is_mutable_polygon_45_set_type<polygon_set_type>::type, polygon_set_type>::type & self_intersect(polygon_set_type& polygon_set) { typedef typename polygon_45_set_traits<polygon_set_type>::coordinate_type Unit; polygon_45_set_data<Unit> ps; assign(ps, polygon_set); ps.self_intersect(); assign(polygon_set, ps); return polygon_set; } //self_xor template <typename polygon_set_type> typename enable_if< typename is_mutable_polygon_45_set_type<polygon_set_type>::type, polygon_set_type>::type & self_xor(polygon_set_type& polygon_set) { typedef typename polygon_45_set_traits<polygon_set_type>::coordinate_type Unit; polygon_45_set_data<Unit> ps; assign(ps, polygon_set); ps.self_xor(); assign(polygon_set, ps); return polygon_set; } //transform template <typename polygon_set_type, typename transformation_type> typename enable_if< typename is_mutable_polygon_45_set_type<polygon_set_type>::type, polygon_set_type>::type & transform(polygon_set_type& polygon_set, const transformation_type& transformation) { typedef typename polygon_45_set_traits<polygon_set_type>::coordinate_type Unit; clean(polygon_set); polygon_45_set_data<Unit> ps; assign(ps, polygon_set); ps.transform(transformation); assign(polygon_set, ps); return polygon_set; } //keep template <typename polygon_set_type> typename enable_if< typename is_mutable_polygon_45_set_type<polygon_set_type>::type, polygon_set_type>::type & keep(polygon_set_type& polygon_set, typename coordinate_traits<typename polygon_45_set_traits<polygon_set_type>::coordinate_type>::area_type min_area, typename coordinate_traits<typename polygon_45_set_traits<polygon_set_type>::coordinate_type>::area_type max_area, typename coordinate_traits<typename polygon_45_set_traits<polygon_set_type>::coordinate_type>::unsigned_area_type min_width, typename coordinate_traits<typename polygon_45_set_traits<polygon_set_type>::coordinate_type>::unsigned_area_type max_width, typename coordinate_traits<typename polygon_45_set_traits<polygon_set_type>::coordinate_type>::unsigned_area_type min_height, typename coordinate_traits<typename polygon_45_set_traits<polygon_set_type>::coordinate_type>::unsigned_area_type max_height) { typedef typename polygon_45_set_traits<polygon_set_type>::coordinate_type Unit; typedef typename coordinate_traits<Unit>::unsigned_area_type uat; std::list<polygon_45_data<Unit> > polys; assign(polys, polygon_set); typename std::list<polygon_45_data<Unit> >::iterator itr_nxt; for(typename std::list<polygon_45_data<Unit> >::iterator itr = polys.begin(); itr != polys.end(); itr = itr_nxt){ itr_nxt = itr; ++itr_nxt; rectangle_data<Unit> bbox; extents(bbox, *itr); uat pwidth = delta(bbox, HORIZONTAL); if(pwidth > min_width && pwidth <= max_width){ uat pheight = delta(bbox, VERTICAL); if(pheight > min_height && pheight <= max_height){ typename coordinate_traits<Unit>::area_type parea = area(*itr); if(parea <= max_area && parea >= min_area) { continue; } } } polys.erase(itr); } assign(polygon_set, polys); return polygon_set; } template <typename T> struct view_of<polygon_90_set_concept, T> { typedef typename get_coordinate_type<T, typename geometry_concept<T>::type >::type coordinate_type; T* tp; std::vector<polygon_90_with_holes_data<coordinate_type> > polys; view_of(T& obj) : tp(&obj), polys() { std::vector<polygon_with_holes_data<coordinate_type> > gpolys; assign(gpolys, obj); for(typename std::vector<polygon_with_holes_data<coordinate_type> >::iterator itr = gpolys.begin(); itr != gpolys.end(); ++itr) { polys.push_back(polygon_90_with_holes_data<coordinate_type>()); assign(polys.back(), view_as<polygon_90_with_holes_concept>(*itr)); } } view_of(const T& obj) : tp(), polys() { std::vector<polygon_with_holes_data<coordinate_type> > gpolys; assign(gpolys, obj); for(typename std::vector<polygon_with_holes_data<coordinate_type> >::iterator itr = gpolys.begin(); itr != gpolys.end(); ++itr) { polys.push_back(polygon_90_with_holes_data<coordinate_type>()); assign(polys.back(), view_as<polygon_90_with_holes_concept>(*itr)); } } typedef typename std::vector<polygon_90_with_holes_data<coordinate_type> >::const_iterator iterator_type; typedef view_of operator_arg_type; inline iterator_type begin() const { return polys.begin(); } inline iterator_type end() const { return polys.end(); } inline orientation_2d orient() const { return HORIZONTAL; } inline bool clean() const { return false; } inline bool sorted() const { return false; } inline T& get() { return *tp; } }; template <typename T> struct polygon_90_set_traits<view_of<polygon_90_set_concept, T> > { typedef typename view_of<polygon_90_set_concept, T>::coordinate_type coordinate_type; typedef typename view_of<polygon_90_set_concept, T>::iterator_type iterator_type; typedef view_of<polygon_90_set_concept, T> operator_arg_type; static inline iterator_type begin(const view_of<polygon_90_set_concept, T>& polygon_set) { return polygon_set.begin(); } static inline iterator_type end(const view_of<polygon_90_set_concept, T>& polygon_set) { return polygon_set.end(); } static inline orientation_2d orient(const view_of<polygon_90_set_concept, T>& polygon_set) { return polygon_set.orient(); } static inline bool clean(const view_of<polygon_90_set_concept, T>& polygon_set) { return polygon_set.clean(); } static inline bool sorted(const view_of<polygon_90_set_concept, T>& polygon_set) { return polygon_set.sorted(); } }; template <typename T> struct geometry_concept<view_of<polygon_90_set_concept, T> > { typedef polygon_90_set_concept type; }; template <typename T> struct get_coordinate_type<view_of<polygon_90_set_concept, T>, polygon_90_set_concept> { typedef typename view_of<polygon_90_set_concept, T>::coordinate_type type; }; template <typename T> struct get_iterator_type_2<view_of<polygon_90_set_concept, T>, polygon_90_set_concept> { typedef typename view_of<polygon_90_set_concept, T>::iterator_type type; static type begin(const view_of<polygon_90_set_concept, T>& t) { return t.begin(); } static type end(const view_of<polygon_90_set_concept, T>& t) { return t.end(); } }; } } #include "detail/polygon_45_set_view.hpp" #endif PK �b�[����C@ C@ polygon_90_set_traits.hppnu �[��� /* Copyright 2008 Intel Corporation Use, modification and distribution are 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_POLYGON_POLYGON_90_SET_TRAITS_HPP #define BOOST_POLYGON_POLYGON_90_SET_TRAITS_HPP namespace boost { namespace polygon{ struct polygon_90_set_concept {}; template <typename T, typename T2> struct traits_by_concept {}; template <typename T> struct traits_by_concept<T, coordinate_concept> { typedef coordinate_traits<T> type; }; template <typename T> struct traits_by_concept<T, interval_concept> { typedef interval_traits<T> type; }; template <typename T> struct traits_by_concept<T, point_concept> { typedef point_traits<T> type; }; template <typename T> struct traits_by_concept<T, rectangle_concept> { typedef rectangle_traits<T> type; }; template <typename T> struct traits_by_concept<T, segment_concept> { typedef segment_traits<T> type; }; template <typename T> struct traits_by_concept<T, polygon_90_concept> { typedef polygon_traits<T> type; }; template <typename T> struct traits_by_concept<T, polygon_90_with_holes_concept> { typedef polygon_traits<T> type; }; template <typename T> struct traits_by_concept<T, polygon_45_concept> { typedef polygon_traits<T> type; }; template <typename T> struct traits_by_concept<T, polygon_45_with_holes_concept> { typedef polygon_traits<T> type; }; template <typename T> struct traits_by_concept<T, polygon_concept> { typedef polygon_traits<T> type; }; template <typename T> struct traits_by_concept<T, polygon_with_holes_concept> { typedef polygon_traits<T> type; }; struct polygon_45_set_concept; struct polygon_set_concept; template <typename T> struct polygon_90_set_traits; template <typename T> struct polygon_45_set_traits; template <typename T> struct polygon_set_traits; template <typename T> struct traits_by_concept<T, polygon_90_set_concept> { typedef polygon_90_set_traits<T> type; }; template <typename T> struct traits_by_concept<T, polygon_45_set_concept> { typedef polygon_45_set_traits<T> type; }; template <typename T> struct traits_by_concept<T, polygon_set_concept> { typedef polygon_set_traits<T> type; }; template <typename T, typename T2> struct get_coordinate_type { typedef typename traits_by_concept<T, T2>::type traits_type; typedef typename traits_type::coordinate_type type; }; //want to prevent recursive template definition syntax errors, so duplicate get_coordinate_type template <typename T, typename T2> struct get_coordinate_type_2 { typedef typename traits_by_concept<T, T2>::type traits_type; typedef typename traits_type::coordinate_type type; }; template <typename T> struct get_coordinate_type<T, undefined_concept> { typedef typename get_coordinate_type_2<typename std::iterator_traits <typename T::iterator>::value_type, typename geometry_concept<typename std::iterator_traits <typename T::iterator>::value_type>::type>::type type; }; template <typename T, typename T2> struct get_iterator_type_2 { typedef const T* type; static type begin(const T& t) { return &t; } static type end(const T& t) { const T* tp = &t; ++tp; return tp; } }; template <typename T> struct get_iterator_type { typedef get_iterator_type_2<T, typename geometry_concept<T>::type> indirect_type; typedef typename indirect_type::type type; static type begin(const T& t) { return indirect_type::begin(t); } static type end(const T& t) { return indirect_type::end(t); } }; template <typename T> struct get_iterator_type_2<T, undefined_concept> { typedef typename T::const_iterator type; static type begin(const T& t) { return t.begin(); } static type end(const T& t) { return t.end(); } }; // //helpers for allowing polygon 45 and containers of polygon 45 to behave interchangably in polygon_45_set_traits // template <typename T, typename T2> // struct get_coordinate_type_45 {}; // template <typename T, typename T2> // struct get_coordinate_type_2_45 {}; // template <typename T> // struct get_coordinate_type_45<T, void> { // typedef typename get_coordinate_type_2_45< typename T::value_type, typename geometry_concept<typename T::value_type>::type >::type type; }; // template <typename T> // struct get_coordinate_type_45<T, polygon_45_concept> { typedef typename polygon_traits<T>::coordinate_type type; }; // template <typename T> // struct get_coordinate_type_45<T, polygon_45_with_holes_concept> { typedef typename polygon_traits<T>::coordinate_type type; }; // template <typename T> // struct get_coordinate_type_2_45<T, polygon_45_concept> { typedef typename polygon_traits<T>::coordinate_type type; }; // template <typename T> // struct get_coordinate_type_2_45<T, polygon_45_with_holes_concept> { typedef typename polygon_traits<T>::coordinate_type type; }; // template <typename T, typename T2> // struct get_iterator_type_45 {}; // template <typename T> // struct get_iterator_type_45<T, void> { // typedef typename T::const_iterator type; // static type begin(const T& t) { return t.begin(); } // static type end(const T& t) { return t.end(); } // }; // template <typename T> // struct get_iterator_type_45<T, polygon_45_concept> { // typedef const T* type; // static type begin(const T& t) { return &t; } // static type end(const T& t) { const T* tp = &t; ++tp; return tp; } // }; // template <typename T> // struct get_iterator_type_45<T, polygon_45_with_holes_concept> { // typedef const T* type; // static type begin(const T& t) { return &t; } // static type end(const T& t) { const T* tp = &t; ++tp; return tp; } // }; // template <typename T> // struct get_iterator_type_45<T, polygon_90_set_concept> { // typedef const T* type; // static type begin(const T& t) { return &t; } // static type end(const T& t) { const T* tp = &t; ++tp; return tp; } // }; template <typename T> struct polygon_90_set_traits { typedef typename get_coordinate_type<T, typename geometry_concept<T>::type >::type coordinate_type; typedef get_iterator_type<T> indirection_type; typedef typename get_iterator_type<T>::type iterator_type; typedef T operator_arg_type; static inline iterator_type begin(const T& polygon_set) { return indirection_type::begin(polygon_set); } static inline iterator_type end(const T& polygon_set) { return indirection_type::end(polygon_set); } static inline orientation_2d orient(const T&) { return HORIZONTAL; } static inline bool clean(const T&) { return false; } static inline bool sorted(const T&) { return false; } }; template <typename T> struct is_manhattan_polygonal_concept { typedef gtl_no type; }; template <> struct is_manhattan_polygonal_concept<rectangle_concept> { typedef gtl_yes type; }; template <> struct is_manhattan_polygonal_concept<polygon_90_concept> { typedef gtl_yes type; }; template <> struct is_manhattan_polygonal_concept<polygon_90_with_holes_concept> { typedef gtl_yes type; }; template <> struct is_manhattan_polygonal_concept<polygon_90_set_concept> { typedef gtl_yes type; }; template <typename T> struct is_polygon_90_set_type { typedef typename is_manhattan_polygonal_concept<typename geometry_concept<T>::type>::type type; }; template <typename T> struct is_polygon_90_set_type<std::list<T> > { typedef typename gtl_or< typename is_manhattan_polygonal_concept<typename geometry_concept<std::list<T> >::type>::type, typename is_manhattan_polygonal_concept<typename geometry_concept<typename std::list<T>::value_type>::type>::type>::type type; }; template <typename T> struct is_polygon_90_set_type<std::vector<T> > { typedef typename gtl_or< typename is_manhattan_polygonal_concept<typename geometry_concept<std::vector<T> >::type>::type, typename is_manhattan_polygonal_concept<typename geometry_concept<typename std::vector<T>::value_type>::type>::type>::type type; }; template <typename T> struct is_mutable_polygon_90_set_type { typedef typename gtl_same_type<polygon_90_set_concept, typename geometry_concept<T>::type>::type type; }; template <typename T> struct is_mutable_polygon_90_set_type<std::list<T> > { typedef typename gtl_or< typename gtl_same_type<polygon_90_set_concept, typename geometry_concept<std::list<T> >::type>::type, typename is_manhattan_polygonal_concept<typename geometry_concept<typename std::list<T>::value_type>::type>::type>::type type; }; template <typename T> struct is_mutable_polygon_90_set_type<std::vector<T> > { typedef typename gtl_or< typename gtl_same_type<polygon_90_set_concept, typename geometry_concept<std::vector<T> >::type>::type, typename is_manhattan_polygonal_concept<typename geometry_concept<typename std::vector<T>::value_type>::type>::type>::type type; }; // //specialization for rectangle, polygon_90 and polygon_90_with_holes types // template <typename T> // struct polygon_90_set_traits // typedef typename geometry_concept<T>::type concept_type; // typedef typename get_coordinate_type<T, concept_type>::type coordinate_type; // typedef iterator_geometry_to_set<concept_type, T> iterator_type; // typedef T operator_arg_type; // static inline iterator_type begin(const T& polygon_set) { // return iterator_geometry_to_set<concept_type, T>(polygon_set, LOW, HORIZONTAL); // } // static inline iterator_type end(const T& polygon_set) { // return iterator_geometry_to_set<concept_type, T>(polygon_set, HIGH, HORIZONTAL); // } // static inline orientation_2d orient(const T& polygon_set) { return HORIZONTAL; } // static inline bool clean(const T& polygon_set) { return false; } // static inline bool sorted(const T& polygon_set) { return false; } // }; // //specialization for containers of recangle, polygon_90, polygon_90_with_holes // template <typename T> // struct polygon_90_set_traits<T, typename is_manhattan_polygonal_concept<typename std::iterator_traits<typename T::iterator>::value_type>::type> { // typedef typename std::iterator_traits<typename T::iterator>::value_type geometry_type; // typedef typename geometry_concept<geometry_type>::type concept_type; // typedef typename get_coordinate_type<geometry_type, concept_type>::type coordinate_type; // typedef iterator_geometry_range_to_set<concept_type, typename T::const_iterator> iterator_type; // typedef T operator_arg_type; // static inline iterator_type begin(const T& polygon_set) { // return iterator_type(polygon_set.begin(), HORIZONTAL); // } // static inline iterator_type end(const T& polygon_set) { // return iterator_type(polygon_set.end(), HORIZONTAL); // } // static inline orientation_2d orient(const T& polygon_set) { return HORIZONTAL; } // static inline bool clean(const T& polygon_set) { return false; } // static inline bool sorted(const T& polygon_set) { return false; } // }; //get dispatch functions template <typename output_container_type, typename pst> void get_90_dispatch(output_container_type& output, const pst& ps, orientation_2d orient, rectangle_concept ) { form_rectangles(output, ps.begin(), ps.end(), orient, rectangle_concept()); } template <typename output_container_type, typename pst> void get_90_dispatch(output_container_type& output, const pst& ps, orientation_2d orient, polygon_90_concept tag) { get_polygons(output, ps.begin(), ps.end(), orient, true, tag); } template <typename output_container_type, typename pst> void get_90_dispatch(output_container_type& output, const pst& ps, orientation_2d orient, polygon_90_with_holes_concept tag) { get_polygons(output, ps.begin(), ps.end(), orient, false, tag); } //by default works with containers of rectangle, polygon or polygon with holes //must be specialized to work with anything else template <typename T> struct polygon_90_set_mutable_traits {}; template <typename T> struct polygon_90_set_mutable_traits<std::list<T> > { typedef typename geometry_concept<T>::type concept_type; template <typename input_iterator_type> static inline void set(std::list<T>& polygon_set, input_iterator_type input_begin, input_iterator_type input_end, orientation_2d orient) { polygon_set.clear(); polygon_90_set_data<typename polygon_90_set_traits<std::list<T> >::coordinate_type> ps(orient); ps.reserve(std::distance(input_begin, input_end)); ps.insert(input_begin, input_end, orient); ps.clean(); get_90_dispatch(polygon_set, ps, orient, concept_type()); } }; template <typename T> struct polygon_90_set_mutable_traits<std::vector<T> > { typedef typename geometry_concept<T>::type concept_type; template <typename input_iterator_type> static inline void set(std::vector<T>& polygon_set, input_iterator_type input_begin, input_iterator_type input_end, orientation_2d orient) { polygon_set.clear(); size_t num_ele = std::distance(input_begin, input_end); polygon_set.reserve(num_ele); polygon_90_set_data<typename polygon_90_set_traits<std::list<T> >::coordinate_type> ps(orient); ps.reserve(num_ele); ps.insert(input_begin, input_end, orient); ps.clean(); get_90_dispatch(polygon_set, ps, orient, concept_type()); } }; template <typename T> struct polygon_90_set_mutable_traits<polygon_90_set_data<T> > { template <typename input_iterator_type> static inline void set(polygon_90_set_data<T>& polygon_set, input_iterator_type input_begin, input_iterator_type input_end, orientation_2d orient) { polygon_set.clear(); polygon_set.reserve(std::distance(input_begin, input_end)); polygon_set.insert(input_begin, input_end, orient); } }; template <typename T> struct polygon_90_set_traits<polygon_90_set_data<T> > { typedef typename polygon_90_set_data<T>::coordinate_type coordinate_type; typedef typename polygon_90_set_data<T>::iterator_type iterator_type; typedef typename polygon_90_set_data<T>::operator_arg_type operator_arg_type; static inline iterator_type begin(const polygon_90_set_data<T>& polygon_set) { return polygon_set.begin(); } static inline iterator_type end(const polygon_90_set_data<T>& polygon_set) { return polygon_set.end(); } static inline orientation_2d orient(const polygon_90_set_data<T>& polygon_set) { return polygon_set.orient(); } static inline bool clean(const polygon_90_set_data<T>& polygon_set) { polygon_set.clean(); return true; } static inline bool sorted(const polygon_90_set_data<T>& polygon_set) { polygon_set.sort(); return true; } }; template <typename T> struct is_polygon_90_set_concept { }; template <> struct is_polygon_90_set_concept<polygon_90_set_concept> { typedef gtl_yes type; }; template <> struct is_polygon_90_set_concept<rectangle_concept> { typedef gtl_yes type; }; template <> struct is_polygon_90_set_concept<polygon_90_concept> { typedef gtl_yes type; }; template <> struct is_polygon_90_set_concept<polygon_90_with_holes_concept> { typedef gtl_yes type; }; template <typename T> struct is_mutable_polygon_90_set_concept { typedef gtl_no type; }; template <> struct is_mutable_polygon_90_set_concept<polygon_90_set_concept> { typedef gtl_yes type; }; template <typename T> struct geometry_concept<polygon_90_set_data<T> > { typedef polygon_90_set_concept type; }; //template <typename T> //typename enable_if<typename is_polygon_90_set_type<T>::type, void>::type //print_is_polygon_90_set_concept(const T& t) { std::cout << "is polygon 90 set concept\n"; } //template <typename T> //typename enable_if<typename is_mutable_polygon_90_set_type<T>::type, void>::type //print_is_mutable_polygon_90_set_concept(const T& t) { std::cout << "is mutable polygon 90 set concept\n"; } } } #endif PK �b�[�2�WvN vN segment_concept.hppnu �[��� // Boost.Polygon library segment_concept.hpp header file // Copyright (c) Intel Corporation 2008. // Copyright (c) 2008-2012 Simonson Lucanus. // Copyright (c) 2012-2012 Andrii Sydorchuk. // See http://www.boost.org for updates, documentation, and revision history. // 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_POLYGON_SEGMENT_CONCEPT_HPP #define BOOST_POLYGON_SEGMENT_CONCEPT_HPP #include "isotropy.hpp" #include "segment_traits.hpp" #include "rectangle_concept.hpp" namespace boost { namespace polygon { struct segment_concept {}; template <typename ConceptType> struct is_segment_concept { typedef gtl_no type; }; template <> struct is_segment_concept<segment_concept> { typedef gtl_yes type; }; template <typename ConceptType> struct is_mutable_segment_concept { typedef gtl_no type; }; template <> struct is_mutable_segment_concept<segment_concept> { typedef gtl_yes type; }; template <typename GeometryType, typename BoolType> struct segment_distance_type_by_concept { typedef void type; }; template <typename GeometryType> struct segment_distance_type_by_concept<GeometryType, gtl_yes> { typedef typename coordinate_traits< typename segment_traits<GeometryType>::coordinate_type >::coordinate_distance type; }; template <typename GeometryType> struct segment_distance_type { typedef typename segment_distance_type_by_concept< GeometryType, typename is_segment_concept< typename geometry_concept<GeometryType>::type >::type >::type type; }; template <typename GeometryType, typename BoolType> struct segment_point_type_by_concept { typedef void type; }; template <typename GeometryType> struct segment_point_type_by_concept<GeometryType, gtl_yes> { typedef typename segment_traits<GeometryType>::point_type type; }; template <typename GeometryType> struct segment_point_type { typedef typename segment_point_type_by_concept< GeometryType, typename is_segment_concept< typename geometry_concept<GeometryType>::type >::type >::type type; }; template <typename GeometryType, typename BoolType> struct segment_coordinate_type_by_concept { typedef void type; }; template <typename GeometryType> struct segment_coordinate_type_by_concept<GeometryType, gtl_yes> { typedef typename segment_traits<GeometryType>::coordinate_type type; }; template <typename GeometryType> struct segment_coordinate_type { typedef typename segment_coordinate_type_by_concept< GeometryType, typename is_segment_concept< typename geometry_concept<GeometryType>::type >::type >::type type; }; struct y_s_get : gtl_yes {}; template <typename Segment> typename enable_if< typename gtl_and< y_s_get, typename is_segment_concept< typename geometry_concept<Segment>::type >::type >::type, typename segment_point_type<Segment>::type>::type get(const Segment& segment, direction_1d dir) { return segment_traits<Segment>::get(segment, dir); } struct y_s_set : gtl_yes {}; template <typename Segment, typename Point> typename enable_if< typename gtl_and_3< y_s_set, typename is_mutable_segment_concept< typename geometry_concept<Segment>::type >::type, typename is_point_concept< typename geometry_concept<Point>::type >::type >::type, void>::type set(Segment& segment, direction_1d dir, const Point& point) { segment_mutable_traits<Segment>::set(segment, dir, point); } struct y_s_construct : gtl_yes {}; template <typename Segment, typename Point1, typename Point2> typename enable_if< typename gtl_and_4< y_s_construct, typename is_mutable_segment_concept< typename geometry_concept<Segment>::type >::type, typename is_point_concept< typename geometry_concept<Point1>::type >::type, typename is_point_concept< typename geometry_concept<Point2>::type >::type >::type, Segment>::type construct(const Point1& low, const Point2& high) { return segment_mutable_traits<Segment>::construct(low, high); } struct y_s_copy_construct : gtl_yes {}; template <typename Segment1, typename Segment2> typename enable_if< typename gtl_and_3< y_s_copy_construct, typename is_mutable_segment_concept< typename geometry_concept<Segment1>::type >::type, typename is_segment_concept< typename geometry_concept<Segment2>::type >::type >::type, Segment1>::type copy_construct(const Segment2& segment) { return construct<Segment1>(get(segment, LOW), get(segment, HIGH)); } struct y_s_assign : gtl_yes {}; template <typename Segment1, typename Segment2> typename enable_if< typename gtl_and_3< y_s_assign, typename is_mutable_segment_concept< typename geometry_concept<Segment1>::type >::type, typename is_segment_concept< typename geometry_concept<Segment2>::type >::type >::type, Segment1>::type& assign(Segment1& segment1, const Segment2& segment2) { return segment1 = copy_construct<Segment1>(segment2); } struct y_s_equivalence : gtl_yes {}; template <typename Segment1, typename Segment2> typename enable_if< typename gtl_and_3< y_s_equivalence, typename is_segment_concept< typename geometry_concept<Segment1>::type >::type, typename is_segment_concept< typename geometry_concept<Segment2>::type >::type >::type, bool>::type equivalence(const Segment1& segment1, const Segment2& segment2) { return get(segment1, LOW) == get(segment2, LOW) && get(segment1, HIGH) == get(segment2, HIGH); } struct y_s_low : gtl_yes {}; template <typename Segment> typename enable_if< typename gtl_and< y_s_low, typename is_segment_concept< typename geometry_concept<Segment>::type >::type >::type, typename segment_point_type<Segment>::type>::type low(const Segment& segment) { return get(segment, LOW); } struct y_s_high : gtl_yes {}; template <typename Segment> typename enable_if< typename gtl_and< y_s_high, typename is_segment_concept< typename geometry_concept<Segment>::type >::type >::type, typename segment_point_type<Segment>::type>::type high(const Segment& segment) { return get(segment, HIGH); } struct y_s_center : gtl_yes {}; template <typename Segment> typename enable_if< typename gtl_and< y_s_center, typename is_segment_concept< typename geometry_concept<Segment>::type >::type >::type, typename segment_point_type<Segment>::type>::type center(const Segment& segment) { return construct<typename segment_point_type<Segment>::type>( (x(high(segment)) + x(low(segment)))/2, (y(high(segment)) + y(low(segment)))/2); } struct y_s_low2 : gtl_yes {}; template <typename Segment, typename Point> typename enable_if< typename gtl_and_3< y_s_low2, typename is_mutable_segment_concept< typename geometry_concept<Segment>::type >::type, typename is_point_concept< typename geometry_concept<Point>::type >::type >::type, void>::type low(Segment& segment, const Point& point) { set(segment, LOW, point); } struct y_s_high2 : gtl_yes {}; template <typename Segment, typename Point> typename enable_if< typename gtl_and_3< y_s_high2, typename is_mutable_segment_concept< typename geometry_concept<Segment>::type >::type, typename is_point_concept< typename geometry_concept<Point>::type >::type >::type, void>::type high(Segment& segment, const Point& point) { set(segment, HIGH, point); } struct y_s_orientation1 : gtl_yes {}; // -1 for CW, 0 for collinear and 1 for CCW. template <typename Segment1, typename Segment2> typename enable_if< typename gtl_and_3< y_s_orientation1, typename is_segment_concept< typename geometry_concept<Segment1>::type >::type, typename is_segment_concept< typename geometry_concept<Segment2>::type >::type >::type, int>::type orientation(const Segment1& segment1, const Segment2& segment2) { typedef typename coordinate_traits< typename segment_traits<Segment1>::coordinate_type >::manhattan_area_type int_x2; typedef typename coordinate_traits< typename segment_traits<Segment1>::coordinate_type >::unsigned_area_type uint_x2; int_x2 a1 = (int_x2)x(high(segment1)) - (int_x2)x(low(segment1)); int_x2 b1 = (int_x2)y(high(segment1)) - (int_x2)y(low(segment1)); int_x2 a2 = (int_x2)x(high(segment2)) - (int_x2)x(low(segment2)); int_x2 b2 = (int_x2)y(high(segment2)) - (int_x2)y(low(segment2)); int sign1 = 0; int sign2 = 0; if (a1 && b2) sign1 = ((a1 > 0) ^ (b2 > 0)) ? -1 : 1; if (a2 && b1) sign2 = ((a2 > 0) ^ (b1 > 0)) ? -1 : 1; if (sign1 != sign2) return (sign1 < sign2) ? -1 : 1; uint_x2 a3 = (uint_x2)(a1 < 0 ? -a1 : a1) * (uint_x2)(b2 < 0 ? -b2 : b2); uint_x2 b3 = (uint_x2)(b1 < 0 ? -b1 : b1) * (uint_x2)(a2 < 0 ? -a2 : a2); if (a3 == b3) return 0; return ((a3 < b3) ^ (sign1 == 1)) ? 1 : -1; } struct y_s_orientation2 : gtl_yes {}; // -1 for right, 0 for collinear and 1 for left. template <typename Segment, typename Point> typename enable_if< typename gtl_and_3< y_s_orientation2, typename is_segment_concept< typename geometry_concept<Segment>::type >::type, typename is_point_concept< typename geometry_concept<Point>::type >::type >::type, int>::type orientation(const Segment& segment, const Point& point) { Segment segment2 = construct<Segment>(high(segment), point); return orientation(segment, segment2); } struct y_s_contains : gtl_yes {}; template <typename Segment, typename Point> typename enable_if< typename gtl_and_3< y_s_contains, typename is_segment_concept< typename geometry_concept<Segment>::type >::type, typename is_point_concept< typename geometry_concept<Point>::type >::type >::type, bool>::type contains(const Segment& segment, const Point& point, bool consider_touch = true ) { if (orientation(segment, point)) return false; rectangle_data<typename segment_coordinate_type<Segment>::type> rect; set_points(rect, low(segment), high(segment)); if (!contains(rect, point, true)) return false; if (!consider_touch && (equivalence(low(segment), point) || equivalence(high(segment), point))) return false; return true; } struct y_s_contains2 : gtl_yes {}; template <typename Segment1, typename Segment2> typename enable_if< typename gtl_and_3< y_s_contains2, typename is_segment_concept< typename geometry_concept<Segment1>::type >::type, typename is_segment_concept< typename geometry_concept<Segment2>::type >::type >::type, bool>::type contains(const Segment1& segment1, const Segment2& segment2, bool consider_touch = true) { return contains(segment1, get(segment2, LOW), consider_touch) && contains(segment1, get(segment2, HIGH), consider_touch); } struct y_s_length : gtl_yes {}; template <typename Segment> typename enable_if< typename gtl_and< y_s_length, typename is_segment_concept< typename geometry_concept<Segment>::type >::type >::type, typename segment_distance_type<Segment>::type>::type length(const Segment& segment) { return euclidean_distance(low(segment), high(segment)); } struct y_s_scale_up : gtl_yes {}; template <typename Segment> typename enable_if< typename gtl_and< y_s_scale_up, typename is_mutable_segment_concept< typename geometry_concept<Segment>::type >::type >::type, Segment>::type& scale_up(Segment& segment, typename coordinate_traits< typename segment_coordinate_type<Segment>::type >::unsigned_area_type factor) { typename segment_point_type<Segment>::type l = low(segment); typename segment_point_type<Segment>::type h = high(segment); low(segment, scale_up(l, factor)); high(segment, scale_up(h, factor)); return segment; } struct y_s_scale_down : gtl_yes {}; template <typename Segment> typename enable_if< typename gtl_and< y_s_scale_down, typename is_mutable_segment_concept< typename geometry_concept<Segment>::type >::type >::type, Segment>::type& scale_down(Segment& segment, typename coordinate_traits< typename segment_coordinate_type<Segment>::type >::unsigned_area_type factor) { typename segment_point_type<Segment>::type l = low(segment); typename segment_point_type<Segment>::type h = high(segment); low(segment, scale_down(l, factor)); high(segment, scale_down(h, factor)); return segment; } struct y_s_scale : gtl_yes {}; template <typename Segment, typename Scale> typename enable_if< typename gtl_and< y_s_scale, typename is_mutable_segment_concept< typename geometry_concept<Segment>::type >::type >::type, Segment>::type& scale(Segment& segment, const Scale& sc) { typename segment_point_type<Segment>::type l = low(segment); typename segment_point_type<Segment>::type h = high(segment); low(segment, scale(l, sc)); high(segment, scale(h, sc)); return segment; } struct y_s_transform : gtl_yes {}; template <typename Segment, typename Transform> typename enable_if< typename gtl_and< y_s_transform, typename is_mutable_segment_concept< typename geometry_concept<Segment>::type >::type >::type, Segment>::type& transform(Segment& segment, const Transform& tr) { typename segment_point_type<Segment>::type l = low(segment); typename segment_point_type<Segment>::type h = high(segment); low(segment, transform(l, tr)); high(segment, transform(h, tr)); return segment; } struct y_s_move : gtl_yes {}; template <typename Segment> typename enable_if< typename gtl_and< y_s_move, typename is_mutable_segment_concept< typename geometry_concept<Segment>::type >::type >::type, Segment>::type& move(Segment& segment, orientation_2d orient, typename segment_coordinate_type<Segment>::type displacement) { typename segment_point_type<Segment>::type l = low(segment); typename segment_point_type<Segment>::type h = high(segment); low(segment, move(l, orient, displacement)); high(segment, move(h, orient, displacement)); return segment; } struct y_s_convolve : gtl_yes {}; template <typename Segment, typename Point> typename enable_if< typename gtl_and_3< y_s_convolve, typename is_mutable_segment_concept< typename geometry_concept<Segment>::type >::type, typename is_point_concept< typename geometry_concept<Point>::type >::type >::type, Segment>::type& convolve(Segment& segment, const Point& point) { typename segment_point_type<Segment>::type l = low(segment); typename segment_point_type<Segment>::type h = high(segment); low(segment, convolve(l, point)); high(segment, convolve(h, point)); return segment; } struct y_s_deconvolve : gtl_yes {}; template <typename Segment, typename Point> typename enable_if< typename gtl_and_3< y_s_deconvolve, typename is_mutable_segment_concept< typename geometry_concept<Segment>::type >::type, typename is_point_concept< typename geometry_concept<Point>::type >::type >::type, Segment>::type& deconvolve(Segment& segment, const Point& point) { typename segment_point_type<Segment>::type l = low(segment); typename segment_point_type<Segment>::type h = high(segment); low(segment, deconvolve(l, point)); high(segment, deconvolve(h, point)); return segment; } struct y_s_abuts1 : gtl_yes {}; template <typename Segment1, typename Segment2> typename enable_if< typename gtl_and_3< y_s_abuts1, typename is_segment_concept< typename geometry_concept<Segment1>::type >::type, typename is_segment_concept< typename geometry_concept<Segment2>::type >::type >::type, bool>::type abuts(const Segment1& segment1, const Segment2& segment2, direction_1d dir) { return dir.to_int() ? equivalence(low(segment2) , high(segment1)) : equivalence(low(segment1) , high(segment2)); } struct y_s_abuts2 : gtl_yes {}; template <typename Segment1, typename Segment2> typename enable_if< typename gtl_and_3< y_s_abuts2, typename is_segment_concept< typename geometry_concept<Segment1>::type >::type, typename is_segment_concept< typename geometry_concept<Segment2>::type >::type >::type, bool>::type abuts(const Segment1& segment1, const Segment2& segment2) { return abuts(segment1, segment2, HIGH) || abuts(segment1, segment2, LOW); } struct y_s_e_intersects : gtl_yes {}; template <typename Segment1, typename Segment2> typename enable_if< typename gtl_and_3< y_s_e_intersects, typename is_segment_concept< typename geometry_concept<Segment1>::type >::type, typename is_segment_concept< typename geometry_concept<Segment2>::type >::type >::type, bool >::type intersects(const Segment1& segment1, const Segment2& segment2, bool consider_touch = true) { rectangle_data<typename segment_coordinate_type<Segment1>::type> rect1, rect2; set_points(rect1, low(segment1), high(segment1)); set_points(rect2, low(segment2), high(segment2)); // Check if axis-parallel rectangles containing segments intersect. if (!intersects(rect1, rect2, true)) return false; int or1_1 = orientation(segment1, low(segment2)); int or1_2 = orientation(segment1, high(segment2)); if (or1_1 * or1_2 > 0) return false; int or2_1 = orientation(segment2, low(segment1)); int or2_2 = orientation(segment2, high(segment1)); if (or2_1 * or2_2 > 0) return false; if (consider_touch || (or1_1 && or1_2) || (or2_1 && or2_2)) return true; if (or1_1 || or1_2) return false; return intersects(vertical(rect1), vertical(rect2), false) || intersects(horizontal(rect1), horizontal(rect2), false); } struct y_s_e_dist : gtl_yes {}; template <typename Segment, typename Point> typename enable_if< typename gtl_and_3< y_s_e_dist, typename is_segment_concept< typename geometry_concept<Segment>::type >::type, typename is_point_concept< typename geometry_concept<Point>::type >::type >::type, typename segment_distance_type<Segment>::type>::type euclidean_distance(const Segment& segment, const Point& point) { typedef typename segment_distance_type<Segment>::type Unit; Unit x1 = x(low(segment)); Unit y1 = y(low(segment)); Unit x2 = x(high(segment)); Unit y2 = y(high(segment)); Unit X = x(point); Unit Y = y(point); Unit A = X - x1; Unit B = Y - y1; Unit C = x2 - x1; Unit D = y2 - y1; Unit param = (A * C + B * D); Unit length_sq = C * C + D * D; if (param > length_sq) { return euclidean_distance(high(segment), point); } else if (param < 0.0) { return euclidean_distance(low(segment), point); } if (length_sq == 0.0) return 0.0; Unit denom = std::sqrt(length_sq); Unit result = (A * D - C * B) / denom; return (result < 0.0) ? -result : result; } struct y_s_e_dist2 : gtl_yes {}; template <typename Segment1, typename Segment2> typename enable_if< typename gtl_and_3< y_s_e_dist2, typename is_segment_concept< typename geometry_concept<Segment1>::type >::type, typename is_segment_concept< typename geometry_concept<Segment2>::type >::type >::type, typename segment_distance_type<Segment1>::type>::type euclidean_distance(const Segment1& segment1, const Segment2& segment2) { if (intersects(segment1, segment2)) return 0.0; typename segment_distance_type<Segment1>::type result1 = euclidean_distance(segment1, low(segment2)), result2 = euclidean_distance(segment1, high(segment2)), result3 = euclidean_distance(segment2, low(segment1)), result4 = euclidean_distance(segment2, high(segment1)); if (result2 < result1) result1 = result2; if (result4 < result3) result3 = result4; return (result1 < result3) ? result1 : result3; } } // polygon } // boost #endif // BOOST_POLYGON_SEGMENT_CONCEPT_HPP PK �b�[�I�e �e interval_concept.hppnu �[��� // Boost.Polygon library interval_concept.hpp header file // Copyright (c) Intel Corporation 2008. // Copyright (c) 2008-2012 Simonson Lucanus. // Copyright (c) 2012-2012 Andrii Sydorchuk. // See http://www.boost.org for updates, documentation, and revision history. // 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_POLYGON_INTERVAL_CONCEPT_HPP #define BOOST_POLYGON_INTERVAL_CONCEPT_HPP #include "isotropy.hpp" #include "interval_traits.hpp" namespace boost { namespace polygon { struct interval_concept {}; template <typename ConceptType> struct is_interval_concept { typedef gtl_no type; }; template <> struct is_interval_concept<interval_concept> { typedef gtl_yes type; }; template <typename ConceptType> struct is_mutable_interval_concept { typedef gtl_no type; }; template <> struct is_mutable_interval_concept<interval_concept> { typedef gtl_yes type; }; template <typename GeometryType, typename BoolType> struct interval_coordinate_type_by_concept { typedef void type; }; template <typename GeometryType> struct interval_coordinate_type_by_concept<GeometryType, gtl_yes> { typedef typename interval_traits<GeometryType>::coordinate_type type; }; template <typename GeometryType> struct interval_coordinate_type { typedef typename interval_coordinate_type_by_concept< GeometryType, typename is_interval_concept< typename geometry_concept<GeometryType>::type >::type >::type type; }; template <typename GeometryType, typename BoolType> struct interval_difference_type_by_concept { typedef void type; }; template <typename GeometryType> struct interval_difference_type_by_concept<GeometryType, gtl_yes> { typedef typename coordinate_traits< typename interval_traits<GeometryType>::coordinate_type >::coordinate_difference type; }; template <typename GeometryType> struct interval_difference_type { typedef typename interval_difference_type_by_concept< GeometryType, typename is_interval_concept< typename geometry_concept<GeometryType>::type >::type >::type type; }; struct y_i_get : gtl_yes {}; template <typename IntervalType> typename enable_if< typename gtl_and< y_i_get, typename is_interval_concept< typename geometry_concept<IntervalType>::type >::type >::type, typename interval_coordinate_type<IntervalType>::type >::type get(const IntervalType& interval, direction_1d dir) { return interval_traits<IntervalType>::get(interval, dir); } struct y_i_set : gtl_yes {}; template <typename IntervalType> typename enable_if< typename gtl_and< y_i_set, typename is_mutable_interval_concept< typename geometry_concept<IntervalType>::type >::type >::type, void >::type set(IntervalType& interval, direction_1d dir, typename interval_mutable_traits<IntervalType>::coordinate_type value) { interval_mutable_traits<IntervalType>::set(interval, dir, value); } struct y_i_construct : gtl_yes {}; template <typename IntervalType> typename enable_if< typename gtl_and< y_i_construct, typename is_mutable_interval_concept< typename geometry_concept<IntervalType>::type >::type >::type, IntervalType >::type construct( typename interval_mutable_traits<IntervalType>::coordinate_type low, typename interval_mutable_traits<IntervalType>::coordinate_type high) { if (low > high) { (std::swap)(low, high); } return interval_mutable_traits<IntervalType>::construct(low, high); } struct y_i_copy_construct : gtl_yes {}; template <typename IntervalType1, typename IntervalType2> typename enable_if< typename gtl_and_3< y_i_copy_construct, typename is_mutable_interval_concept< typename geometry_concept<IntervalType1>::type >::type, typename is_interval_concept< typename geometry_concept<IntervalType2>::type >::type >::type, IntervalType1 >::type copy_construct(const IntervalType2& interval) { return construct<IntervalType1>(get(interval, LOW), get(interval, HIGH)); } struct y_i_assign : gtl_yes {}; template <typename IntervalType1, typename IntervalType2> typename enable_if< typename gtl_and_3< y_i_assign, typename is_mutable_interval_concept< typename geometry_concept<IntervalType1>::type >::type, typename is_interval_concept< typename geometry_concept<IntervalType2>::type >::type >::type, IntervalType1 >::type& assign(IntervalType1& lvalue, const IntervalType2& rvalue) { set(lvalue, LOW, get(rvalue, LOW)); set(lvalue, HIGH, get(rvalue, HIGH)); return lvalue; } struct y_i_low : gtl_yes {}; template <typename IntervalType> typename enable_if< typename gtl_and< y_i_low, typename is_interval_concept< typename geometry_concept<IntervalType>::type >::type >::type, typename interval_coordinate_type<IntervalType>::type >::type low(const IntervalType& interval) { return get(interval, LOW); } struct y_i_high : gtl_yes {}; template <typename IntervalType> typename enable_if< typename gtl_and< y_i_high, typename is_interval_concept< typename geometry_concept<IntervalType>::type >::type >::type, typename interval_coordinate_type<IntervalType>::type >::type high(const IntervalType& interval) { return get(interval, HIGH); } struct y_i_low2 : gtl_yes {}; template <typename IntervalType> typename enable_if< typename gtl_and< y_i_low2, typename is_mutable_interval_concept< typename geometry_concept<IntervalType>::type >::type >::type, void >::type low(IntervalType& interval, typename interval_mutable_traits<IntervalType>::coordinate_type value) { set(interval, LOW, value); } struct y_i_high2 : gtl_yes {}; template <typename IntervalType> typename enable_if< typename gtl_and< y_i_high2, typename is_mutable_interval_concept< typename geometry_concept<IntervalType>::type >::type >::type, void >::type high(IntervalType& interval, typename interval_mutable_traits<IntervalType>::coordinate_type value) { set(interval, HIGH, value); } struct y_i_equivalence : gtl_yes {}; template <typename IntervalType1, typename IntervalType2> typename enable_if< typename gtl_and_3< y_i_equivalence, typename is_interval_concept< typename geometry_concept<IntervalType1>::type >::type, typename is_interval_concept< typename geometry_concept<IntervalType2>::type >::type >::type, bool >::type equivalence( const IntervalType1& interval1, const IntervalType2& interval2) { return (get(interval1, LOW) == get(interval2, LOW)) && (get(interval1, HIGH) == get(interval2, HIGH)); } struct y_i_contains : gtl_yes {}; template <typename IntervalType> typename enable_if< typename gtl_and< y_i_contains, typename is_interval_concept< typename geometry_concept<IntervalType>::type >::type >::type, bool >::type contains( const IntervalType& interval, typename interval_coordinate_type<IntervalType>::type value, bool consider_touch = true ) { if (consider_touch) { return value <= high(interval) && value >= low(interval); } else { return value < high(interval) && value > low(interval); } } struct y_i_contains2 : gtl_yes {}; template <typename IntervalType1, typename IntervalType2> typename enable_if< typename gtl_and_3< y_i_contains2, typename is_interval_concept< typename geometry_concept<IntervalType1>::type >::type, typename is_interval_concept< typename geometry_concept<IntervalType2>::type >::type >::type, bool >::type contains( const IntervalType1& interval1, const IntervalType2& interval2, bool consider_touch = true) { return contains(interval1, get(interval2, LOW), consider_touch) && contains(interval1, get(interval2, HIGH), consider_touch); } struct y_i_center : gtl_yes {}; template <typename IntervalType> typename enable_if< typename gtl_and< y_i_center, typename is_interval_concept< typename geometry_concept<IntervalType>::type >::type >::type, typename interval_coordinate_type<IntervalType>::type >::type center(const IntervalType& interval) { return (high(interval) + low(interval)) / 2; } struct y_i_delta : gtl_yes {}; template <typename IntervalType> typename enable_if< typename gtl_and< y_i_delta, typename is_interval_concept< typename geometry_concept<IntervalType>::type >::type >::type, typename interval_difference_type<IntervalType>::type >::type delta(const IntervalType& interval) { typedef typename interval_difference_type<IntervalType>::type diff_type; return static_cast<diff_type>(high(interval)) - static_cast<diff_type>(low(interval)); } struct y_i_flip : gtl_yes {}; template <typename IntervalType> typename enable_if< typename gtl_and< y_i_flip, typename is_mutable_interval_concept< typename geometry_concept<IntervalType>::type >::type >::type, IntervalType>::type& flip( IntervalType& interval, typename interval_coordinate_type<IntervalType>::type axis = 0) { typename interval_coordinate_type<IntervalType>::type newLow, newHigh; newLow = 2 * axis - high(interval); newHigh = 2 * axis - low(interval); low(interval, newLow); high(interval, newHigh); return interval; } struct y_i_scale_up : gtl_yes {}; template <typename IntervalType> typename enable_if< typename gtl_and< y_i_scale_up, typename is_mutable_interval_concept< typename geometry_concept<IntervalType>::type >::type >::type, IntervalType >::type& scale_up( IntervalType& interval, typename interval_coordinate_type<IntervalType>::type factor) { typename interval_coordinate_type<IntervalType>::type newHigh = high(interval) * factor; low(interval, low(interval) * factor); high(interval, (newHigh)); return interval; } struct y_i_scale_down : gtl_yes {}; template <typename IntervalType> typename enable_if< typename gtl_and< y_i_scale_down, typename is_mutable_interval_concept< typename geometry_concept<IntervalType>::type >::type >::type, IntervalType >::type& scale_down( IntervalType& interval, typename interval_coordinate_type<IntervalType>::type factor) { typename interval_coordinate_type<IntervalType>::type newHigh = high(interval) / factor; low(interval, low(interval) / factor); high(interval, (newHigh)); return interval; } // TODO(asydorchuk): Deprecated. struct y_i_scale : gtl_yes {}; template <typename IntervalType> typename enable_if< typename gtl_and< y_i_scale, typename is_mutable_interval_concept< typename geometry_concept<IntervalType>::type >::type >::type, IntervalType >::type& scale(IntervalType& interval, double factor) { typedef typename interval_coordinate_type<IntervalType>::type Unit; Unit newHigh = scaling_policy<Unit>::round( static_cast<double>(high(interval)) * factor); low(interval, scaling_policy<Unit>::round( static_cast<double>(low(interval)) * factor)); high(interval, (newHigh)); return interval; } struct y_i_move : gtl_yes {}; template <typename IntervalType> typename enable_if< typename gtl_and< y_i_move, typename is_mutable_interval_concept< typename geometry_concept<IntervalType>::type >::type >::type, IntervalType >::type& move( IntervalType& interval, typename interval_difference_type<IntervalType>::type displacement) { typedef typename interval_coordinate_type<IntervalType>::type ctype; typedef typename coordinate_traits<ctype>::coordinate_difference Unit; low(interval, static_cast<ctype>( static_cast<Unit>(low(interval)) + displacement)); high(interval, static_cast<ctype>( static_cast<Unit>(high(interval)) + displacement)); return interval; } struct y_i_convolve : gtl_yes {}; template <typename IntervalType> typename enable_if< typename gtl_and< y_i_convolve, typename is_mutable_interval_concept< typename geometry_concept<IntervalType>::type >::type >::type, IntervalType >::type& convolve( IntervalType& interval, typename interval_coordinate_type<IntervalType>::type value) { typedef typename interval_coordinate_type<IntervalType>::type Unit; Unit newLow = low(interval) + value; Unit newHigh = high(interval) + value; low(interval, newLow); high(interval, newHigh); return interval; } struct y_i_deconvolve : gtl_yes {}; template <typename IntervalType> typename enable_if< typename gtl_and< y_i_deconvolve, typename is_mutable_interval_concept< typename geometry_concept<IntervalType>::type >::type >::type, IntervalType >::type& deconvolve( IntervalType& interval, typename interval_coordinate_type<IntervalType>::type value) { typedef typename interval_coordinate_type<IntervalType>::type Unit; Unit newLow = low(interval) - value; Unit newHigh = high(interval) - value; low(interval, newLow); high(interval, newHigh); return interval; } struct y_i_convolve2 : gtl_yes {}; template <typename IntervalType1, typename IntervalType2> typename enable_if< typename gtl_and_3< y_i_convolve2, typename is_mutable_interval_concept< typename geometry_concept<IntervalType1>::type >::type, typename is_interval_concept< typename geometry_concept<IntervalType2>::type >::type >::type, IntervalType1 >::type& convolve(IntervalType1& lvalue, const IntervalType2& rvalue) { typedef typename interval_coordinate_type<IntervalType1>::type Unit; Unit newLow = low(lvalue) + low(rvalue); Unit newHigh = high(lvalue) + high(rvalue); low(lvalue, newLow); high(lvalue, newHigh); return lvalue; } struct y_i_deconvolve2 : gtl_yes {}; template <typename IntervalType1, typename IntervalType2> typename enable_if< typename gtl_and_3< y_i_deconvolve2, typename is_mutable_interval_concept< typename geometry_concept<IntervalType1>::type >::type, typename is_interval_concept< typename geometry_concept<IntervalType2>::type >::type >::type, IntervalType1 >::type& deconvolve(IntervalType1& lvalue, const IntervalType2& rvalue) { typedef typename interval_coordinate_type<IntervalType1>::type Unit; Unit newLow = low(lvalue) - low(rvalue); Unit newHigh = high(lvalue) - high(rvalue); low(lvalue, newLow); high(lvalue, newHigh); return lvalue; } struct y_i_reconvolve : gtl_yes {}; template <typename IntervalType1, typename IntervalType2> typename enable_if< typename gtl_and_3< y_i_reconvolve, typename is_mutable_interval_concept< typename geometry_concept<IntervalType1>::type >::type, typename is_interval_concept< typename geometry_concept<IntervalType2>::type >::type >::type, IntervalType1 >::type& reflected_convolve( IntervalType1& lvalue, const IntervalType2& rvalue) { typedef typename interval_coordinate_type<IntervalType1>::type Unit; Unit newLow = low(lvalue) - high(rvalue); Unit newHigh = high(lvalue) - low(rvalue); low(lvalue, newLow); high(lvalue, newHigh); return lvalue; } struct y_i_redeconvolve : gtl_yes {}; template <typename IntervalType1, typename IntervalType2> typename enable_if< typename gtl_and_3< y_i_redeconvolve, typename is_mutable_interval_concept< typename geometry_concept<IntervalType1>::type >::type, typename is_interval_concept< typename geometry_concept<IntervalType2>::type >::type >::type, IntervalType1 >::type& reflected_deconvolve( IntervalType1& lvalue, const IntervalType2& rvalue) { typedef typename interval_coordinate_type<IntervalType1>::type Unit; Unit newLow = low(lvalue) + high(rvalue); Unit newHigh = high(lvalue) + low(rvalue); low(lvalue, newLow); high(lvalue, newHigh); return lvalue; } struct y_i_e_dist1 : gtl_yes {}; template <typename IntervalType> typename enable_if< typename gtl_and<y_i_e_dist1, typename is_interval_concept< typename geometry_concept<IntervalType>::type >::type >::type, typename interval_difference_type<IntervalType>::type >::type euclidean_distance( const IntervalType& interval, typename interval_coordinate_type<IntervalType>::type position) { typedef typename interval_difference_type<IntervalType>::type Unit; Unit dist[3] = { 0, (Unit)low(interval) - (Unit)position, (Unit)position - (Unit)high(interval) }; return dist[(dist[1] > 0) + ((dist[2] > 0) << 1)]; } struct y_i_e_dist2 : gtl_yes {}; template <typename IntervalType1, typename IntervalType2> typename enable_if< typename gtl_and_3< y_i_e_dist2, typename is_interval_concept< typename geometry_concept<IntervalType1>::type >::type, typename is_interval_concept< typename geometry_concept<IntervalType2>::type >::type >::type, typename interval_difference_type<IntervalType1>::type >::type euclidean_distance( const IntervalType1& interval1, const IntervalType2& interval2) { typedef typename interval_difference_type<IntervalType1>::type Unit; Unit dist[3] = { 0, (Unit)low(interval1) - (Unit)high(interval2), (Unit)low(interval2) - (Unit)high(interval1) }; return dist[(dist[1] > 0) + ((dist[2] > 0) << 1)]; } struct y_i_e_intersects : gtl_yes {}; template <typename IntervalType1, typename IntervalType2> typename enable_if< typename gtl_and_3< y_i_e_intersects, typename is_interval_concept< typename geometry_concept<IntervalType1>::type >::type, typename is_interval_concept< typename geometry_concept<IntervalType2>::type >::type >::type, bool >::type intersects( const IntervalType1& interval1, const IntervalType2& interval2, bool consider_touch = true) { return consider_touch ? (low(interval1) <= high(interval2)) && (high(interval1) >= low(interval2)) : (low(interval1) < high(interval2)) && (high(interval1) > low(interval2)); } struct y_i_e_bintersect : gtl_yes {}; template <typename IntervalType1, typename IntervalType2> typename enable_if< typename gtl_and_3< y_i_e_bintersect, typename is_interval_concept< typename geometry_concept<IntervalType1>::type >::type, typename is_interval_concept< typename geometry_concept<IntervalType2>::type >::type >::type, bool >::type boundaries_intersect( const IntervalType1& interval1, const IntervalType2& interval2, bool consider_touch = true) { return (contains(interval1, low(interval2), consider_touch) || contains(interval1, high(interval2), consider_touch)) && (contains(interval2, low(interval1), consider_touch) || contains(interval2, high(interval1), consider_touch)); } struct y_i_intersect : gtl_yes {}; template <typename IntervalType1, typename IntervalType2> typename enable_if< typename gtl_and_3< y_i_intersect, typename is_mutable_interval_concept< typename geometry_concept<IntervalType1>::type >::type, typename is_interval_concept< typename geometry_concept<IntervalType2>::type >::type >::type, bool >::type intersect( IntervalType1& lvalue, const IntervalType2& rvalue, bool consider_touch = true) { typedef typename interval_coordinate_type<IntervalType1>::type Unit; Unit lowVal = (std::max)(low(lvalue), low(rvalue)); Unit highVal = (std::min)(high(lvalue), high(rvalue)); bool valid = consider_touch ? lowVal <= highVal : lowVal < highVal; if (valid) { low(lvalue, lowVal); high(lvalue, highVal); } return valid; } struct y_i_g_intersect : gtl_yes {}; // TODO(asydorchuk): Deprecated. template <typename IntervalType1, typename IntervalType2> typename enable_if< typename gtl_and_3< y_i_g_intersect, typename is_mutable_interval_concept< typename geometry_concept<IntervalType1>::type >::type, typename is_interval_concept< typename geometry_concept<IntervalType2>::type >::type >::type, IntervalType1 >::type& generalized_intersect( IntervalType1& lvalue, const IntervalType2& rvalue) { typedef typename interval_coordinate_type<IntervalType1>::type Unit; Unit coords[4] = {low(lvalue), high(lvalue), low(rvalue), high(rvalue)}; // TODO(asydorchuk): consider implementing faster sorting of small // fixed length range. polygon_sort(coords, coords+4); low(lvalue, coords[1]); high(lvalue, coords[2]); return lvalue; } struct y_i_abuts1 : gtl_yes {}; template <typename IntervalType1, typename IntervalType2> typename enable_if< typename gtl_and_3< y_i_abuts1, typename is_interval_concept< typename geometry_concept<IntervalType1>::type >::type, typename is_interval_concept< typename geometry_concept<IntervalType2>::type >::type >::type, bool >::type abuts( const IntervalType1& interval1, const IntervalType2& interval2, direction_1d dir) { return dir.to_int() ? low(interval2) == high(interval1) : low(interval1) == high(interval2); } struct y_i_abuts2 : gtl_yes {}; template <typename IntervalType1, typename IntervalType2> typename enable_if< typename gtl_and_3< y_i_abuts2, typename is_interval_concept< typename geometry_concept<IntervalType1>::type >::type, typename is_interval_concept< typename geometry_concept<IntervalType2>::type >::type >::type, bool >::type abuts( const IntervalType1& interval1, const IntervalType2& interval2) { return abuts(interval1, interval2, HIGH) || abuts(interval1, interval2, LOW); } struct y_i_bloat : gtl_yes {}; template <typename IntervalType> typename enable_if< typename gtl_and< y_i_bloat, typename is_mutable_interval_concept< typename geometry_concept<IntervalType>::type >::type >::type, IntervalType >::type& bloat( IntervalType& interval, typename interval_coordinate_type<IntervalType>::type bloating) { low(interval, low(interval) - bloating); high(interval, high(interval) + bloating); return interval; } struct y_i_bloat2 : gtl_yes {}; template <typename IntervalType> typename enable_if< typename gtl_and< y_i_bloat2, typename is_mutable_interval_concept< typename geometry_concept<IntervalType>::type >::type >::type, IntervalType >::type& bloat( IntervalType& interval, direction_1d dir, typename interval_coordinate_type<IntervalType>::type bloating) { set(interval, dir, get(interval, dir) + dir.get_sign() * bloating); return interval; } struct y_i_shrink : gtl_yes {}; template <typename IntervalType> typename enable_if< typename gtl_and< y_i_shrink, typename is_mutable_interval_concept< typename geometry_concept<IntervalType>::type >::type >::type, IntervalType >::type& shrink( IntervalType& interval, typename interval_coordinate_type<IntervalType>::type shrinking) { return bloat(interval, -shrinking); } struct y_i_shrink2 : gtl_yes {}; template <typename IntervalType> typename enable_if< typename gtl_and< y_i_shrink2, typename is_mutable_interval_concept< typename geometry_concept<IntervalType>::type >::type >::type, IntervalType >::type& shrink( IntervalType& interval, direction_1d dir, typename interval_coordinate_type<IntervalType>::type shrinking) { return bloat(interval, dir, -shrinking); } struct y_i_encompass : gtl_yes {}; template <typename IntervalType1, typename IntervalType2> typename enable_if< typename gtl_and_3< y_i_encompass, typename is_mutable_interval_concept< typename geometry_concept<IntervalType1>::type >::type, typename is_interval_concept< typename geometry_concept<IntervalType2>::type >::type >::type, bool >::type encompass(IntervalType1& interval1, const IntervalType2& interval2) { bool retval = !contains(interval1, interval2, true); low(interval1, (std::min)(low(interval1), low(interval2))); high(interval1, (std::max)(high(interval1), high(interval2))); return retval; } struct y_i_encompass2 : gtl_yes {}; template <typename IntervalType> typename enable_if< typename gtl_and< y_i_encompass2, typename is_mutable_interval_concept< typename geometry_concept<IntervalType>::type >::type >::type, bool >::type encompass( IntervalType& interval, typename interval_coordinate_type<IntervalType>::type value) { bool retval = !contains(interval, value, true); low(interval, (std::min)(low(interval), value)); high(interval, (std::max)(high(interval), value)); return retval; } struct y_i_get_half : gtl_yes {}; template <typename IntervalType> typename enable_if< typename gtl_and< y_i_get_half, typename is_mutable_interval_concept< typename geometry_concept<IntervalType>::type >::type >::type, IntervalType >::type get_half(const IntervalType& interval, direction_1d dir) { typedef typename interval_coordinate_type<IntervalType>::type Unit; Unit c = (get(interval, LOW) + get(interval, HIGH)) / 2; return construct<IntervalType>( (dir == LOW) ? get(interval, LOW) : c, (dir == LOW) ? c : get(interval, HIGH)); } struct y_i_join_with : gtl_yes {}; template <typename IntervalType1, typename IntervalType2> typename enable_if< typename gtl_and_3< y_i_join_with, typename is_mutable_interval_concept< typename geometry_concept<IntervalType1>::type >::type, typename is_interval_concept< typename geometry_concept<IntervalType2>::type >::type>::type, bool >::type join_with(IntervalType1& interval1, const IntervalType2& interval2) { if (abuts(interval1, interval2)) { encompass(interval1, interval2); return true; } return false; } } // polygon } // boost #endif // BOOST_POLYGON_INTERVAL_CONCEPT_HPP PK �b�[Ht�c� � point_data.hppnu �[��� // Boost.Polygon library point_data.hpp header file // Copyright (c) Intel Corporation 2008. // Copyright (c) 2008-2012 Simonson Lucanus. // Copyright (c) 2012-2012 Andrii Sydorchuk. // See http://www.boost.org for updates, documentation, and revision history. // 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_POLYGON_POINT_DATA_HPP #define BOOST_POLYGON_POINT_DATA_HPP #include "isotropy.hpp" #include "point_concept.hpp" namespace boost { namespace polygon { template <typename T> class point_data { public: typedef T coordinate_type; point_data() #ifndef BOOST_POLYGON_MSVC : coords_() #endif {} point_data(coordinate_type x, coordinate_type y) { coords_[HORIZONTAL] = x; coords_[VERTICAL] = y; } explicit point_data(const point_data& that) { coords_[0] = that.coords_[0]; coords_[1] = that.coords_[1]; } point_data& operator=(const point_data& that) { coords_[0] = that.coords_[0]; coords_[1] = that.coords_[1]; return *this; } #if defined(__GNUC__) && __GNUC__ < 6 // "explicit" to work around a bug in GCC < 6: https://gcc.gnu.org/bugzilla/show_bug.cgi?id=63356 template <typename PointType> explicit point_data(const PointType& that) { *this = that; } #else // __GNUC__ < 6 template <typename PointType> point_data(const PointType& that) { *this = that; } #endif // __GNUC__ < 6 template <typename PointType> point_data& operator=(const PointType& that) { assign(*this, that); return *this; } // TODO(asydorchuk): Deprecated. template <typename CT> point_data(const point_data<CT>& that) { coords_[HORIZONTAL] = (coordinate_type)that.x(); coords_[VERTICAL] = (coordinate_type)that.y(); } coordinate_type get(orientation_2d orient) const { return coords_[orient.to_int()]; } void set(orientation_2d orient, coordinate_type value) { coords_[orient.to_int()] = value; } coordinate_type x() const { return coords_[HORIZONTAL]; } point_data& x(coordinate_type value) { coords_[HORIZONTAL] = value; return *this; } coordinate_type y() const { return coords_[VERTICAL]; } point_data& y(coordinate_type value) { coords_[VERTICAL] = value; return *this; } bool operator==(const point_data& that) const { return (coords_[0] == that.coords_[0]) && (coords_[1] == that.coords_[1]); } bool operator!=(const point_data& that) const { return !(*this == that); } bool operator<(const point_data& that) const { return (coords_[0] < that.coords_[0]) || ((coords_[0] == that.coords_[0]) && (coords_[1] < that.coords_[1])); } bool operator<=(const point_data& that) const { return !(that < *this); } bool operator>(const point_data& that) const { return that < *this; } bool operator>=(const point_data& that) const { return !(*this < that); } private: coordinate_type coords_[2]; }; template <typename CType> struct geometry_concept< point_data<CType> > { typedef point_concept type; }; } // polygon } // boost #endif // BOOST_POLYGON_POINT_DATA_HPP PK �b�[+zL�� � gmp_override.hppnu �[��� /* Copyright 2008 Intel Corporation Use, modification and distribution are 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_POLYGON_GMP_OVERRIDE_HPP #define BOOST_POLYGON_GMP_OVERRIDE_HPP #include <gmpxx.h> namespace boost { namespace polygon { class gmp_int { private: inline gmp_int(const mpq_class& input) : v_(input) {} public: inline gmp_int() {} explicit inline gmp_int(long input) : v_(input) {} inline gmp_int(const gmp_int& input) : v_(input.v_) {} inline gmp_int& operator=(const gmp_int& that) { v_ = that.v_; return (*this); } inline gmp_int& operator=(long that) { v_ = that; return (*this); } inline operator int() const { std::cout << "cast\n"; mpz_class num = v_.get_num(); mpz_class den = v_.get_den(); num /= den; return num.get_si(); } inline double get_d() const { return v_.get_d(); } inline int get_num() const { return v_.get_num().get_si(); } inline int get_den() const { return v_.get_den().get_si(); } inline bool operator==(const gmp_int& that) const { return v_ == that.v_; } inline bool operator!=(const gmp_int& that) const { return v_ != that.v_; } inline bool operator<(const gmp_int& that) const { bool retval = v_ < that.v_; return retval; } inline bool operator<=(const gmp_int& that) const { return v_ <= that.v_; } inline bool operator>(const gmp_int& that) const { return v_ > that.v_; } inline bool operator>=(const gmp_int& that) const { return v_ >= that.v_; } inline gmp_int operator+(const gmp_int& b) { return gmp_int((*this).v_ + b.v_); } inline gmp_int operator-(const gmp_int& b) { return gmp_int((*this).v_ - b.v_); } inline gmp_int operator*(const gmp_int& b) { return gmp_int((*this).v_ * b.v_); } inline gmp_int operator/(const gmp_int& b) { return gmp_int((*this).v_ / b.v_); } inline gmp_int& operator+=(const gmp_int& b) { (*this).v_ += b.v_; return (*this); } inline gmp_int& operator-=(const gmp_int& b) { (*this).v_ -= b.v_; return (*this); } inline gmp_int& operator*=(const gmp_int& b) { (*this).v_ *= b.v_; return (*this); } inline gmp_int& operator/=(const gmp_int& b) { (*this).v_ /= b.v_; return (*this); } inline gmp_int& operator++() { ++v_; return (*this); } inline gmp_int& operator--() { --v_; return (*this); } inline gmp_int operator++(int) { gmp_int retval(*this); ++(*this); return retval; } inline gmp_int operator--(int) { gmp_int retval(*this); --(*this); return retval; } private: mpq_class v_; }; template <> struct high_precision_type<int> { typedef mpq_class type; }; template <> int convert_high_precision_type<int>(const mpq_class& v) { mpz_class num = v.get_num(); mpz_class den = v.get_den(); num /= den; return num.get_si(); }; } } #endif PK �b�[�4�: �: transform.hppnu �[��� // Boost.Polygon library transform.hpp header file // Copyright (c) Intel Corporation 2008. // Copyright (c) 2008-2012 Simonson Lucanus. // Copyright (c) 2012-2012 Andrii Sydorchuk. // See http://www.boost.org for updates, documentation, and revision history. // 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_POLYGON_TRANSFORM_HPP #define BOOST_POLYGON_TRANSFORM_HPP #include "isotropy.hpp" namespace boost { namespace polygon { // Transformation of Coordinate System. // Enum meaning: // Select which direction_2d to change the positive direction of each // axis in the old coordinate system to map it to the new coordiante system. // The first direction_2d listed for each enum is the direction to map the // positive horizontal direction to. // The second direction_2d listed for each enum is the direction to map the // positive vertical direction to. // The zero position bit (LSB) indicates whether the horizontal axis flips // when transformed. // The 1st postion bit indicates whether the vertical axis flips when // transformed. // The 2nd position bit indicates whether the horizontal and vertical axis // swap positions when transformed. // Enum Values: // 000 EAST NORTH // 001 WEST NORTH // 010 EAST SOUTH // 011 WEST SOUTH // 100 NORTH EAST // 101 SOUTH EAST // 110 NORTH WEST // 111 SOUTH WEST class axis_transformation { public: enum ATR { #ifdef BOOST_POLYGON_ENABLE_DEPRECATED EN = 0, WN = 1, ES = 2, WS = 3, NE = 4, SE = 5, NW = 6, SW = 7, #endif NULL_TRANSFORM = 0, BEGIN_TRANSFORM = 0, EAST_NORTH = 0, WEST_NORTH = 1, FLIP_X = 1, EAST_SOUTH = 2, FLIP_Y = 2, WEST_SOUTH = 3, FLIP_XY = 3, NORTH_EAST = 4, SWAP_XY = 4, SOUTH_EAST = 5, ROTATE_LEFT = 5, NORTH_WEST = 6, ROTATE_RIGHT = 6, SOUTH_WEST = 7, FLIP_SWAP_XY = 7, END_TRANSFORM = 7 }; // Individual axis enum values indicate which axis an implicit individual // axis will be mapped to. // The value of the enum paired with an axis provides the information // about what the axis will transform to. // Three individual axis values, one for each axis, are equivalent to one // ATR enum value, but easier to work with because they are independent. // Converting to and from the individual axis values from the ATR value // is a convenient way to implement tranformation related functionality. // Enum meanings: // PX: map to positive x axis // NX: map to negative x axis // PY: map to positive y axis // NY: map to negative y axis enum INDIVIDUAL_AXIS { PX = 0, NX = 1, PY = 2, NY = 3 }; axis_transformation() : atr_(NULL_TRANSFORM) {} explicit axis_transformation(ATR atr) : atr_(atr) {} axis_transformation(const axis_transformation& atr) : atr_(atr.atr_) {} explicit axis_transformation(const orientation_2d& orient) { const ATR tmp[2] = { NORTH_EAST, // sort x, then y EAST_NORTH // sort y, then x }; atr_ = tmp[orient.to_int()]; } explicit axis_transformation(const direction_2d& dir) { const ATR tmp[4] = { SOUTH_EAST, // sort x, then y NORTH_EAST, // sort x, then y EAST_SOUTH, // sort y, then x EAST_NORTH // sort y, then x }; atr_ = tmp[dir.to_int()]; } // assignment operator axis_transformation& operator=(const axis_transformation& a) { atr_ = a.atr_; return *this; } // assignment operator axis_transformation& operator=(const ATR& atr) { atr_ = atr; return *this; } // equivalence operator bool operator==(const axis_transformation& a) const { return atr_ == a.atr_; } // inequivalence operator bool operator!=(const axis_transformation& a) const { return !(*this == a); } // ordering bool operator<(const axis_transformation& a) const { return atr_ < a.atr_; } // concatenate this with that axis_transformation& operator+=(const axis_transformation& a) { bool abit2 = (a.atr_ & 4) != 0; bool abit1 = (a.atr_ & 2) != 0; bool abit0 = (a.atr_ & 1) != 0; bool bit2 = (atr_ & 4) != 0; bool bit1 = (atr_ & 2) != 0; bool bit0 = (atr_ & 1) != 0; int indexes[2][2] = { { (int)bit2, (int)(!bit2) }, { (int)abit2, (int)(!abit2) } }; int zero_bits[2][2] = { {bit0, bit1}, {abit0, abit1} }; int nbit1 = zero_bits[0][1] ^ zero_bits[1][indexes[0][1]]; int nbit0 = zero_bits[0][0] ^ zero_bits[1][indexes[0][0]]; indexes[0][0] = indexes[1][indexes[0][0]]; indexes[0][1] = indexes[1][indexes[0][1]]; int nbit2 = indexes[0][0] & 1; // swap xy atr_ = (ATR)((nbit2 << 2) + (nbit1 << 1) + nbit0); return *this; } // concatenation operator axis_transformation operator+(const axis_transformation& a) const { axis_transformation retval(*this); return retval+=a; } // populate_axis_array writes the three INDIVIDUAL_AXIS values that the // ATR enum value of 'this' represent into axis_array void populate_axis_array(INDIVIDUAL_AXIS axis_array[]) const { bool bit2 = (atr_ & 4) != 0; bool bit1 = (atr_ & 2) != 0; bool bit0 = (atr_ & 1) != 0; axis_array[1] = (INDIVIDUAL_AXIS)(((int)(!bit2) << 1) + bit1); axis_array[0] = (INDIVIDUAL_AXIS)(((int)(bit2) << 1) + bit0); } // it is recommended that the directions stored in an array // in the caller code for easier isotropic access by orientation value void get_directions(direction_2d& horizontal_dir, direction_2d& vertical_dir) const { bool bit2 = (atr_ & 4) != 0; bool bit1 = (atr_ & 2) != 0; bool bit0 = (atr_ & 1) != 0; vertical_dir = direction_2d((direction_2d_enum)(((int)(!bit2) << 1) + !bit1)); horizontal_dir = direction_2d((direction_2d_enum)(((int)(bit2) << 1) + !bit0)); } // combine_axis_arrays concatenates this_array and that_array overwriting // the result into this_array static void combine_axis_arrays(INDIVIDUAL_AXIS this_array[], const INDIVIDUAL_AXIS that_array[]) { int indexes[2] = { this_array[0] >> 1, this_array[1] >> 1 }; int zero_bits[2][2] = { { this_array[0] & 1, this_array[1] & 1 }, { that_array[0] & 1, that_array[1] & 1 } }; this_array[0] = (INDIVIDUAL_AXIS)((int)this_array[0] | ((int)zero_bits[0][0] ^ (int)zero_bits[1][indexes[0]])); this_array[1] = (INDIVIDUAL_AXIS)((int)this_array[1] | ((int)zero_bits[0][1] ^ (int)zero_bits[1][indexes[1]])); } // write_back_axis_array converts an array of three INDIVIDUAL_AXIS values // to the ATR enum value and sets 'this' to that value void write_back_axis_array(const INDIVIDUAL_AXIS this_array[]) { int bit2 = ((int)this_array[0] & 2) != 0; // swap xy int bit1 = ((int)this_array[1] & 1); int bit0 = ((int)this_array[0] & 1); atr_ = ATR((bit2 << 2) + (bit1 << 1) + bit0); } // behavior is deterministic but undefined in the case where illegal // combinations of directions are passed in. axis_transformation& set_directions(const direction_2d& horizontal_dir, const direction_2d& vertical_dir) { int bit2 = (static_cast<orientation_2d>(horizontal_dir).to_int()) != 0; int bit1 = !(vertical_dir.to_int() & 1); int bit0 = !(horizontal_dir.to_int() & 1); atr_ = ATR((bit2 << 2) + (bit1 << 1) + bit0); return *this; } // transform the three coordinates by reference template <typename coordinate_type> void transform(coordinate_type& x, coordinate_type& y) const { int bit2 = (atr_ & 4) != 0; int bit1 = (atr_ & 2) != 0; int bit0 = (atr_ & 1) != 0; x *= -((bit0 << 1) - 1); y *= -((bit1 << 1) - 1); predicated_swap(bit2 != 0, x, y); } // invert this axis_transformation axis_transformation& invert() { int bit2 = ((atr_ & 4) != 0); int bit1 = ((atr_ & 2) != 0); int bit0 = ((atr_ & 1) != 0); // swap bit 0 and bit 1 if bit2 is 1 predicated_swap(bit2 != 0, bit0, bit1); bit1 = bit1 << 1; atr_ = (ATR)(atr_ & (32+16+8+4)); // mask away bit0 and bit1 atr_ = (ATR)(atr_ | bit0 | bit1); return *this; } // get the inverse axis_transformation of this axis_transformation inverse() const { axis_transformation retval(*this); return retval.invert(); } private: ATR atr_; }; // Scaling object to be used to store the scale factor for each axis. // For use by the transformation object, in that context the scale factor // is the amount that each axis scales by when transformed. template <typename scale_factor_type> class anisotropic_scale_factor { public: anisotropic_scale_factor() { scale_[0] = 1; scale_[1] = 1; } anisotropic_scale_factor(scale_factor_type xscale, scale_factor_type yscale) { scale_[0] = xscale; scale_[1] = yscale; } // get a component of the anisotropic_scale_factor by orientation scale_factor_type get(orientation_2d orient) const { return scale_[orient.to_int()]; } // set a component of the anisotropic_scale_factor by orientation void set(orientation_2d orient, scale_factor_type value) { scale_[orient.to_int()] = value; } scale_factor_type x() const { return scale_[HORIZONTAL]; } scale_factor_type y() const { return scale_[VERTICAL]; } void x(scale_factor_type value) { scale_[HORIZONTAL] = value; } void y(scale_factor_type value) { scale_[VERTICAL] = value; } // concatination operator (convolve scale factors) anisotropic_scale_factor operator+(const anisotropic_scale_factor& s) const { anisotropic_scale_factor<scale_factor_type> retval(*this); return retval += s; } // concatinate this with that const anisotropic_scale_factor& operator+=( const anisotropic_scale_factor& s) { scale_[0] *= s.scale_[0]; scale_[1] *= s.scale_[1]; return *this; } // transform this scale with an axis_transform anisotropic_scale_factor& transform(axis_transformation atr) { direction_2d dirs[2]; atr.get_directions(dirs[0], dirs[1]); scale_factor_type tmp[2] = {scale_[0], scale_[1]}; for (int i = 0; i < 2; ++i) { scale_[orientation_2d(dirs[i]).to_int()] = tmp[i]; } return *this; } // scale the two coordinates template <typename coordinate_type> void scale(coordinate_type& x, coordinate_type& y) const { x = scaling_policy<coordinate_type>::round( (scale_factor_type)x * get(HORIZONTAL)); y = scaling_policy<coordinate_type>::round( (scale_factor_type)y * get(HORIZONTAL)); } // invert this scale factor to give the reverse scale factor anisotropic_scale_factor& invert() { x(1/x()); y(1/y()); return *this; } private: scale_factor_type scale_[2]; }; // Transformation object, stores and provides services for transformations. // Consits of axis transformation, scale factor and translation. // The tranlation is the position of the origin of the new coordinate system of // in the old system. Coordinates are scaled before they are transformed. template <typename coordinate_type> class transformation { public: transformation() : atr_(), p_(0, 0) {} explicit transformation(axis_transformation atr) : atr_(atr), p_(0, 0) {} explicit transformation(axis_transformation::ATR atr) : atr_(atr), p_(0, 0) {} transformation(const transformation& tr) : atr_(tr.atr_), p_(tr.p_) {} template <typename point_type> explicit transformation(const point_type& p) : atr_(), p_(0, 0) { set_translation(p); } template <typename point_type> transformation(axis_transformation atr, const point_type& p) : atr_(atr), p_(0, 0) { set_translation(p); } template <typename point_type> transformation(axis_transformation atr, const point_type& referencePt, const point_type& destinationPt) : atr_(), p_(0, 0) { transformation<coordinate_type> tmp(referencePt); transformation<coordinate_type> rotRef(atr); transformation<coordinate_type> tmpInverse = tmp.inverse(); point_type decon(referencePt); deconvolve(decon, destinationPt); transformation<coordinate_type> displacement(decon); tmp += rotRef; tmp += tmpInverse; tmp += displacement; (*this) = tmp; } // equivalence operator bool operator==(const transformation& tr) const { return (atr_ == tr.atr_) && (p_ == tr.p_); } // inequivalence operator bool operator!=(const transformation& tr) const { return !(*this == tr); } // ordering bool operator<(const transformation& tr) const { return (atr_ < tr.atr_) || ((atr_ == tr.atr_) && (p_ < tr.p_)); } // concatenation operator transformation operator+(const transformation& tr) const { transformation<coordinate_type> retval(*this); return retval+=tr; } // concatenate this with that const transformation& operator+=(const transformation& tr) { coordinate_type x, y; transformation<coordinate_type> inv = inverse(); inv.transform(x, y); p_.set(HORIZONTAL, p_.get(HORIZONTAL) + x); p_.set(VERTICAL, p_.get(VERTICAL) + y); // concatenate axis transforms atr_ += tr.atr_; return *this; } // get the axis_transformation portion of this axis_transformation get_axis_transformation() const { return atr_; } // set the axis_transformation portion of this void set_axis_transformation(const axis_transformation& atr) { atr_ = atr; } // get the translation template <typename point_type> void get_translation(point_type& p) const { assign(p, p_); } // set the translation template <typename point_type> void set_translation(const point_type& p) { assign(p_, p); } // apply the 2D portion of this transformation to the two coordinates given void transform(coordinate_type& x, coordinate_type& y) const { y -= p_.get(VERTICAL); x -= p_.get(HORIZONTAL); atr_.transform(x, y); } // invert this transformation transformation& invert() { coordinate_type x = p_.get(HORIZONTAL), y = p_.get(VERTICAL); atr_.transform(x, y); x *= -1; y *= -1; p_ = point_data<coordinate_type>(x, y); atr_.invert(); return *this; } // get the inverse of this transformation transformation inverse() const { transformation<coordinate_type> ret_val(*this); return ret_val.invert(); } void get_directions(direction_2d& horizontal_dir, direction_2d& vertical_dir) const { return atr_.get_directions(horizontal_dir, vertical_dir); } private: axis_transformation atr_; point_data<coordinate_type> p_; }; } // polygon } // boost #endif // BOOST_POLYGON_TRANSFORM_HPP PK �b�[#7�%� � polygon_data.hppnu �[��� /* Copyright 2008 Intel Corporation Use, modification and distribution are 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_POLYGON_POLYGON_DATA_HPP #define BOOST_POLYGON_POLYGON_DATA_HPP namespace boost { namespace polygon{ struct polygon_concept; template <typename T> class polygon_data { public: typedef polygon_concept geometry_type; typedef T coordinate_type; typedef typename std::vector<point_data<coordinate_type> >::const_iterator iterator_type; typedef typename coordinate_traits<T>::coordinate_distance area_type; typedef point_data<T> point_type; inline polygon_data() : coords_() {} //do nothing default constructor template<class iT> inline polygon_data(iT input_begin, iT input_end) : coords_(input_begin, input_end) {} template<class iT> inline polygon_data& set(iT input_begin, iT input_end) { coords_.clear(); //just in case there was some old data there coords_.insert(coords_.end(), input_begin, input_end); return *this; } // copy constructor (since we have dynamic memory) inline polygon_data(const polygon_data& that) : coords_(that.coords_) {} // assignment operator (since we have dynamic memory do a deep copy) inline polygon_data& operator=(const polygon_data& that) { coords_ = that.coords_; return *this; } template <typename T2> inline polygon_data& operator=(const T2& rvalue); inline bool operator==(const polygon_data& that) const { if(coords_.size() != that.coords_.size()) return false; for(std::size_t i = 0; i < coords_.size(); ++i) { if(coords_[i] != that.coords_[i]) return false; } return true; } inline bool operator!=(const polygon_data& that) const { return !((*this) == that); } // get begin iterator, returns a pointer to a const Unit inline iterator_type begin() const { return coords_.begin(); } // get end iterator, returns a pointer to a const Unit inline iterator_type end() const { return coords_.end(); } inline std::size_t size() const { return coords_.size(); } public: std::vector<point_data<coordinate_type> > coords_; }; } } #endif PK �b�[g�Q�L �L voronoi_builder.hppnu �[��� // Boost.Polygon library voronoi_builder.hpp header file // Copyright Andrii Sydorchuk 2010-2012. // Distributed under 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) // See http://www.boost.org for updates, documentation, and revision history. #ifndef BOOST_POLYGON_VORONOI_BUILDER #define BOOST_POLYGON_VORONOI_BUILDER #include <algorithm> #include <map> #include <queue> #include <utility> #include <vector> #include "detail/voronoi_ctypes.hpp" #include "detail/voronoi_predicates.hpp" #include "detail/voronoi_structures.hpp" #include "voronoi_geometry_type.hpp" namespace boost { namespace polygon { // GENERAL INFO: // The sweepline algorithm implementation to compute Voronoi diagram of // points and non-intersecting segments (excluding endpoints). // Complexity - O(N*logN), memory usage - O(N), where N is the total number // of input geometries. // // CONTRACT: // 1) Input geometries should have integral (e.g. int32, int64) coordinate type. // 2) Input geometries should not intersect except their endpoints. // // IMPLEMENTATION DETAILS: // Each input point creates one input site. Each input segment creates three // input sites: two for its endpoints and one for the segment itself (this is // made to simplify output construction). All the site objects are constructed // and sorted at the algorithm initialization step. Priority queue is used to // dynamically hold circle events. At each step of the algorithm execution the // leftmost event is retrieved by comparing the current site event and the // topmost element from the circle event queue. STL map (red-black tree) // container was chosen to hold state of the beach line. The keys of the map // correspond to the neighboring sites that form a bisector and values map to // the corresponding Voronoi edges in the output data structure. template <typename T, typename CTT = detail::voronoi_ctype_traits<T>, typename VP = detail::voronoi_predicates<CTT> > class voronoi_builder { public: typedef typename CTT::int_type int_type; typedef typename CTT::fpt_type fpt_type; voronoi_builder() : index_(0) {} // Each point creates a single site event. std::size_t insert_point(const int_type& x, const int_type& y) { site_events_.push_back(site_event_type(x, y)); site_events_.back().initial_index(index_); site_events_.back().source_category(SOURCE_CATEGORY_SINGLE_POINT); return index_++; } // Each segment creates three site events that correspond to: // 1) the start point of the segment; // 2) the end point of the segment; // 3) the segment itself defined by its start point. std::size_t insert_segment( const int_type& x1, const int_type& y1, const int_type& x2, const int_type& y2) { // Set up start point site. point_type p1(x1, y1); site_events_.push_back(site_event_type(p1)); site_events_.back().initial_index(index_); site_events_.back().source_category(SOURCE_CATEGORY_SEGMENT_START_POINT); // Set up end point site. point_type p2(x2, y2); site_events_.push_back(site_event_type(p2)); site_events_.back().initial_index(index_); site_events_.back().source_category(SOURCE_CATEGORY_SEGMENT_END_POINT); // Set up segment site. if (point_comparison_(p1, p2)) { site_events_.push_back(site_event_type(p1, p2)); site_events_.back().source_category(SOURCE_CATEGORY_INITIAL_SEGMENT); } else { site_events_.push_back(site_event_type(p2, p1)); site_events_.back().source_category(SOURCE_CATEGORY_REVERSE_SEGMENT); } site_events_.back().initial_index(index_); return index_++; } // Run sweepline algorithm and fill output data structure. template <typename OUTPUT> void construct(OUTPUT* output) { // Init structures. output->_reserve(site_events_.size()); init_sites_queue(); init_beach_line(output); // The algorithm stops when there are no events to process. event_comparison_predicate event_comparison; while (!circle_events_.empty() || !(site_event_iterator_ == site_events_.end())) { if (circle_events_.empty()) { process_site_event(output); } else if (site_event_iterator_ == site_events_.end()) { process_circle_event(output); } else { if (event_comparison(*site_event_iterator_, circle_events_.top().first)) { process_site_event(output); } else { process_circle_event(output); } } while (!circle_events_.empty() && !circle_events_.top().first.is_active()) { circle_events_.pop(); } } beach_line_.clear(); // Finish construction. output->_build(); } void clear() { index_ = 0; site_events_.clear(); } private: typedef detail::point_2d<int_type> point_type; typedef detail::site_event<int_type> site_event_type; typedef typename std::vector<site_event_type>::const_iterator site_event_iterator_type; typedef detail::circle_event<fpt_type> circle_event_type; typedef typename VP::template point_comparison_predicate<point_type> point_comparison_predicate; typedef typename VP:: template event_comparison_predicate<site_event_type, circle_event_type> event_comparison_predicate; typedef typename VP:: template circle_formation_predicate<site_event_type, circle_event_type> circle_formation_predicate_type; typedef void edge_type; typedef detail::beach_line_node_key<site_event_type> key_type; typedef detail::beach_line_node_data<edge_type, circle_event_type> value_type; typedef typename VP::template node_comparison_predicate<key_type> node_comparer_type; typedef std::map< key_type, value_type, node_comparer_type > beach_line_type; typedef typename beach_line_type::iterator beach_line_iterator; typedef std::pair<circle_event_type, beach_line_iterator> event_type; struct event_comparison_type { bool operator()(const event_type& lhs, const event_type& rhs) const { return predicate(rhs.first, lhs.first); } event_comparison_predicate predicate; }; typedef detail::ordered_queue<event_type, event_comparison_type> circle_event_queue_type; typedef std::pair<point_type, beach_line_iterator> end_point_type; void init_sites_queue() { // Sort site events. std::sort(site_events_.begin(), site_events_.end(), event_comparison_predicate()); // Remove duplicates. site_events_.erase(std::unique( site_events_.begin(), site_events_.end()), site_events_.end()); // Index sites. for (std::size_t cur = 0; cur < site_events_.size(); ++cur) { site_events_[cur].sorted_index(cur); } // Init site iterator. site_event_iterator_ = site_events_.begin(); } template <typename OUTPUT> void init_beach_line(OUTPUT* output) { if (site_events_.empty()) return; if (site_events_.size() == 1) { // Handle single site event case. output->_process_single_site(site_events_[0]); ++site_event_iterator_; } else { int skip = 0; while (site_event_iterator_ != site_events_.end() && VP::is_vertical(site_event_iterator_->point0(), site_events_.begin()->point0()) && VP::is_vertical(*site_event_iterator_)) { ++site_event_iterator_; ++skip; } if (skip == 1) { // Init beach line with the first two sites. init_beach_line_default(output); } else { // Init beach line with collinear vertical sites. init_beach_line_collinear_sites(output); } } } // Init beach line with the two first sites. // The first site is always a point. template <typename OUTPUT> void init_beach_line_default(OUTPUT* output) { // Get the first and the second site event. site_event_iterator_type it_first = site_events_.begin(); site_event_iterator_type it_second = site_events_.begin(); ++it_second; insert_new_arc( *it_first, *it_first, *it_second, beach_line_.end(), output); // The second site was already processed. Move the iterator. ++site_event_iterator_; } // Init beach line with collinear sites. template <typename OUTPUT> void init_beach_line_collinear_sites(OUTPUT* output) { site_event_iterator_type it_first = site_events_.begin(); site_event_iterator_type it_second = site_events_.begin(); ++it_second; while (it_second != site_event_iterator_) { // Create a new beach line node. key_type new_node(*it_first, *it_second); // Update the output. edge_type* edge = output->_insert_new_edge(*it_first, *it_second).first; // Insert a new bisector into the beach line. beach_line_.insert(beach_line_.end(), std::pair<key_type, value_type>(new_node, value_type(edge))); // Update iterators. ++it_first; ++it_second; } } void deactivate_circle_event(value_type* value) { if (value->circle_event()) { value->circle_event()->deactivate(); value->circle_event(NULL); } } template <typename OUTPUT> void process_site_event(OUTPUT* output) { // Get next site event to process. site_event_type site_event = *site_event_iterator_; // Move site iterator. site_event_iterator_type last = site_event_iterator_ + 1; // If a new site is an end point of some segment, // remove temporary nodes from the beach line data structure. if (!site_event.is_segment()) { while (!end_points_.empty() && end_points_.top().first == site_event.point0()) { beach_line_iterator b_it = end_points_.top().second; end_points_.pop(); beach_line_.erase(b_it); } } else { while (last != site_events_.end() && last->is_segment() && last->point0() == site_event.point0()) ++last; } // Find the node in the binary search tree with left arc // lying above the new site point. key_type new_key(*site_event_iterator_); beach_line_iterator right_it = beach_line_.lower_bound(new_key); for (; site_event_iterator_ != last; ++site_event_iterator_) { site_event = *site_event_iterator_; beach_line_iterator left_it = right_it; // Do further processing depending on the above node position. // For any two neighboring nodes the second site of the first node // is the same as the first site of the second node. if (right_it == beach_line_.end()) { // The above arc corresponds to the second arc of the last node. // Move the iterator to the last node. --left_it; // Get the second site of the last node const site_event_type& site_arc = left_it->first.right_site(); // Insert new nodes into the beach line. Update the output. right_it = insert_new_arc( site_arc, site_arc, site_event, right_it, output); // Add a candidate circle to the circle event queue. // There could be only one new circle event formed by // a new bisector and the one on the left. activate_circle_event(left_it->first.left_site(), left_it->first.right_site(), site_event, right_it); } else if (right_it == beach_line_.begin()) { // The above arc corresponds to the first site of the first node. const site_event_type& site_arc = right_it->first.left_site(); // Insert new nodes into the beach line. Update the output. left_it = insert_new_arc( site_arc, site_arc, site_event, right_it, output); // If the site event is a segment, update its direction. if (site_event.is_segment()) { site_event.inverse(); } // Add a candidate circle to the circle event queue. // There could be only one new circle event formed by // a new bisector and the one on the right. activate_circle_event(site_event, right_it->first.left_site(), right_it->first.right_site(), right_it); right_it = left_it; } else { // The above arc corresponds neither to the first, // nor to the last site in the beach line. const site_event_type& site_arc2 = right_it->first.left_site(); const site_event_type& site3 = right_it->first.right_site(); // Remove the candidate circle from the event queue. deactivate_circle_event(&right_it->second); --left_it; const site_event_type& site_arc1 = left_it->first.right_site(); const site_event_type& site1 = left_it->first.left_site(); // Insert new nodes into the beach line. Update the output. beach_line_iterator new_node_it = insert_new_arc(site_arc1, site_arc2, site_event, right_it, output); // Add candidate circles to the circle event queue. // There could be up to two circle events formed by // a new bisector and the one on the left or right. activate_circle_event(site1, site_arc1, site_event, new_node_it); // If the site event is a segment, update its direction. if (site_event.is_segment()) { site_event.inverse(); } activate_circle_event(site_event, site_arc2, site3, right_it); right_it = new_node_it; } } } // In general case circle event is made of the three consecutive sites // that form two bisectors in the beach line data structure. // Let circle event sites be A, B, C, two bisectors that define // circle event are (A, B), (B, C). During circle event processing // we remove (A, B), (B, C) and insert (A, C). As beach line comparison // works correctly only if one of the nodes is a new one we remove // (B, C) bisector and change (A, B) bisector to the (A, C). That's // why we use const_cast there and take all the responsibility that // map data structure keeps correct ordering. template <typename OUTPUT> void process_circle_event(OUTPUT* output) { // Get the topmost circle event. const event_type& e = circle_events_.top(); const circle_event_type& circle_event = e.first; beach_line_iterator it_first = e.second; beach_line_iterator it_last = it_first; // Get the C site. site_event_type site3 = it_first->first.right_site(); // Get the half-edge corresponding to the second bisector - (B, C). edge_type* bisector2 = it_first->second.edge(); // Get the half-edge corresponding to the first bisector - (A, B). --it_first; edge_type* bisector1 = it_first->second.edge(); // Get the A site. site_event_type site1 = it_first->first.left_site(); if (!site1.is_segment() && site3.is_segment() && site3.point1() == site1.point0()) { site3.inverse(); } // Change the (A, B) bisector node to the (A, C) bisector node. const_cast<key_type&>(it_first->first).right_site(site3); // Insert the new bisector into the beach line. it_first->second.edge(output->_insert_new_edge( site1, site3, circle_event, bisector1, bisector2).first); // Remove the (B, C) bisector node from the beach line. beach_line_.erase(it_last); it_last = it_first; // Pop the topmost circle event from the event queue. circle_events_.pop(); // Check new triplets formed by the neighboring arcs // to the left for potential circle events. if (it_first != beach_line_.begin()) { deactivate_circle_event(&it_first->second); --it_first; const site_event_type& site_l1 = it_first->first.left_site(); activate_circle_event(site_l1, site1, site3, it_last); } // Check the new triplet formed by the neighboring arcs // to the right for potential circle events. ++it_last; if (it_last != beach_line_.end()) { deactivate_circle_event(&it_last->second); const site_event_type& site_r1 = it_last->first.right_site(); activate_circle_event(site1, site3, site_r1, it_last); } } // Insert new nodes into the beach line. Update the output. template <typename OUTPUT> beach_line_iterator insert_new_arc( const site_event_type& site_arc1, const site_event_type &site_arc2, const site_event_type& site_event, beach_line_iterator position, OUTPUT* output) { // Create two new bisectors with opposite directions. key_type new_left_node(site_arc1, site_event); key_type new_right_node(site_event, site_arc2); // Set correct orientation for the first site of the second node. if (site_event.is_segment()) { new_right_node.left_site().inverse(); } // Update the output. std::pair<edge_type*, edge_type*> edges = output->_insert_new_edge(site_arc2, site_event); position = beach_line_.insert(position, typename beach_line_type::value_type( new_right_node, value_type(edges.second))); if (site_event.is_segment()) { // Update the beach line with temporary bisector, that will // disappear after processing site event corresponding to the // second endpoint of the segment site. key_type new_node(site_event, site_event); new_node.right_site().inverse(); position = beach_line_.insert(position, typename beach_line_type::value_type(new_node, value_type(NULL))); // Update the data structure that holds temporary bisectors. end_points_.push(std::make_pair(site_event.point1(), position)); } position = beach_line_.insert(position, typename beach_line_type::value_type( new_left_node, value_type(edges.first))); return position; } // Add a new circle event to the event queue. // bisector_node corresponds to the (site2, site3) bisector. void activate_circle_event(const site_event_type& site1, const site_event_type& site2, const site_event_type& site3, beach_line_iterator bisector_node) { circle_event_type c_event; // Check if the three input sites create a circle event. if (circle_formation_predicate_(site1, site2, site3, c_event)) { // Add the new circle event to the circle events queue. // Update bisector's circle event iterator to point to the // new circle event in the circle event queue. event_type& e = circle_events_.push( std::pair<circle_event_type, beach_line_iterator>( c_event, bisector_node)); bisector_node->second.circle_event(&e.first); } } private: point_comparison_predicate point_comparison_; struct end_point_comparison { bool operator() (const end_point_type& end1, const end_point_type& end2) const { return point_comparison(end2.first, end1.first); } point_comparison_predicate point_comparison; }; std::vector<site_event_type> site_events_; site_event_iterator_type site_event_iterator_; std::priority_queue< end_point_type, std::vector<end_point_type>, end_point_comparison > end_points_; circle_event_queue_type circle_events_; beach_line_type beach_line_; circle_formation_predicate_type circle_formation_predicate_; std::size_t index_; // Disallow copy constructor and operator= voronoi_builder(const voronoi_builder&); void operator=(const voronoi_builder&); }; typedef voronoi_builder<detail::int32> default_voronoi_builder; } // polygon } // boost #endif // BOOST_POLYGON_VORONOI_BUILDER PK �b�[�L �� � polygon_90_with_holes_data.hppnu �[��� /* Copyright 2008 Intel Corporation Use, modification and distribution are 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_POLYGON_POLYGON_90_WITH_HOLES_DATA_HPP #define BOOST_POLYGON_POLYGON_90_WITH_HOLES_DATA_HPP namespace boost { namespace polygon{ #include "isotropy.hpp" #include "polygon_90_data.hpp" struct polygon_90_with_holes_concept; template <typename T> class polygon_90_with_holes_data { public: typedef polygon_90_with_holes_concept geometry_type; typedef T coordinate_type; typedef typename polygon_90_data<T>::iterator_type iterator_type; typedef typename polygon_90_data<T>::compact_iterator_type compact_iterator_type; typedef typename std::list<polygon_90_data<coordinate_type> >::const_iterator iterator_holes_type; typedef polygon_90_data<coordinate_type> hole_type; typedef typename coordinate_traits<T>::area_type area_type; typedef point_data<T> point_type; // default constructor of point does not initialize x and y inline polygon_90_with_holes_data() : self_(), holes_() {} //do nothing default constructor // initialize a polygon from x,y values, it is assumed that the first is an x // and that the input is a well behaved polygon template<class iT> inline polygon_90_with_holes_data& set(iT input_begin, iT input_end) { self_.set(input_begin, input_end); return *this; } // initialize a polygon from x,y values, it is assumed that the first is an x // and that the input is a well behaved polygon template<class iT> inline polygon_90_with_holes_data& set_compact(iT input_begin, iT input_end) { self_.set_compact(input_begin, input_end); return *this; } // initialize a polygon from x,y values, it is assumed that the first is an x // and that the input is a well behaved polygon template<class iT> inline polygon_90_with_holes_data& set_holes(iT input_begin, iT input_end) { holes_.clear(); //just in case there was some old data there for( ; input_begin != input_end; ++ input_begin) { holes_.push_back(hole_type()); holes_.back().set_compact((*input_begin).begin_compact(), (*input_begin).end_compact()); } return *this; } // copy constructor (since we have dynamic memory) inline polygon_90_with_holes_data(const polygon_90_with_holes_data& that) : self_(that.self_), holes_(that.holes_) {} // assignment operator (since we have dynamic memory do a deep copy) inline polygon_90_with_holes_data& operator=(const polygon_90_with_holes_data& that) { self_ = that.self_; holes_ = that.holes_; return *this; } template <typename T2> inline polygon_90_with_holes_data& operator=(const T2& rvalue); // get begin iterator, returns a pointer to a const coordinate_type inline const iterator_type begin() const { return self_.begin(); } // get end iterator, returns a pointer to a const coordinate_type inline const iterator_type end() const { return self_.end(); } // get begin iterator, returns a pointer to a const coordinate_type inline const compact_iterator_type begin_compact() const { return self_.begin_compact(); } // get end iterator, returns a pointer to a const coordinate_type inline const compact_iterator_type end_compact() const { return self_.end_compact(); } inline std::size_t size() const { return self_.size(); } // get begin iterator, returns a pointer to a const polygon inline const iterator_holes_type begin_holes() const { return holes_.begin(); } // get end iterator, returns a pointer to a const polygon inline const iterator_holes_type end_holes() const { return holes_.end(); } inline std::size_t size_holes() const { return holes_.size(); } private: polygon_90_data<coordinate_type> self_; std::list<hole_type> holes_; }; } } #endif PK �b�[���խ խ polygon_90_set_data.hppnu �[��� /* Copyright 2008 Intel Corporation Use, modification and distribution are 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_POLYGON_POLYGON_90_SET_DATA_HPP #define BOOST_POLYGON_POLYGON_90_SET_DATA_HPP #include "isotropy.hpp" #include "point_concept.hpp" #include "transform.hpp" #include "interval_concept.hpp" #include "rectangle_concept.hpp" #include "segment_concept.hpp" #include "detail/iterator_points_to_compact.hpp" #include "detail/iterator_compact_to_points.hpp" #include "polygon_traits.hpp" //manhattan boolean algorithms #include "detail/boolean_op.hpp" #include "detail/polygon_formation.hpp" #include "detail/rectangle_formation.hpp" #include "detail/max_cover.hpp" #include "detail/property_merge.hpp" #include "detail/polygon_90_touch.hpp" #include "detail/iterator_geometry_to_set.hpp" namespace boost { namespace polygon{ template <typename ltype, typename rtype, typename op_type> class polygon_90_set_view; template <typename T> class polygon_90_set_data { public: typedef T coordinate_type; typedef std::vector<std::pair<coordinate_type, std::pair<coordinate_type, int> > > value_type; typedef typename std::vector<std::pair<coordinate_type, std::pair<coordinate_type, int> > >::const_iterator iterator_type; typedef polygon_90_set_data operator_arg_type; // default constructor inline polygon_90_set_data() : orient_(HORIZONTAL), data_(), dirty_(false), unsorted_(false) {} // constructor inline polygon_90_set_data(orientation_2d orient) : orient_(orient), data_(), dirty_(false), unsorted_(false) {} // constructor from an iterator pair over vertex data template <typename iT> inline polygon_90_set_data(orientation_2d, iT input_begin, iT input_end) : orient_(HORIZONTAL), data_(), dirty_(false), unsorted_(false) { dirty_ = true; unsorted_ = true; for( ; input_begin != input_end; ++input_begin) { insert(*input_begin); } } // copy constructor inline polygon_90_set_data(const polygon_90_set_data& that) : orient_(that.orient_), data_(that.data_), dirty_(that.dirty_), unsorted_(that.unsorted_) {} template <typename ltype, typename rtype, typename op_type> inline polygon_90_set_data(const polygon_90_set_view<ltype, rtype, op_type>& that); // copy with orientation change constructor inline polygon_90_set_data(orientation_2d orient, const polygon_90_set_data& that) : orient_(orient), data_(), dirty_(false), unsorted_(false) { insert(that, false, that.orient_); } // destructor inline ~polygon_90_set_data() {} // assignement operator inline polygon_90_set_data& operator=(const polygon_90_set_data& that) { if(this == &that) return *this; orient_ = that.orient_; data_ = that.data_; dirty_ = that.dirty_; unsorted_ = that.unsorted_; return *this; } template <typename ltype, typename rtype, typename op_type> inline polygon_90_set_data& operator=(const polygon_90_set_view<ltype, rtype, op_type>& that); template <typename geometry_object> inline polygon_90_set_data& operator=(const geometry_object& geometry) { data_.clear(); insert(geometry); return *this; } // insert iterator range inline void insert(iterator_type input_begin, iterator_type input_end, orientation_2d orient = HORIZONTAL) { if(input_begin == input_end || (!data_.empty() && &(*input_begin) == &(*(data_.begin())))) return; dirty_ = true; unsorted_ = true; if(orient == orient_) data_.insert(data_.end(), input_begin, input_end); else { for( ; input_begin != input_end; ++input_begin) { insert(*input_begin, false, orient); } } } // insert iterator range template <typename iT> inline void insert(iT input_begin, iT input_end, orientation_2d orient = HORIZONTAL) { if(input_begin == input_end) return; dirty_ = true; unsorted_ = true; for( ; input_begin != input_end; ++input_begin) { insert(*input_begin, false, orient); } } inline void insert(const polygon_90_set_data& polygon_set) { insert(polygon_set.begin(), polygon_set.end(), polygon_set.orient()); } inline void insert(const std::pair<std::pair<point_data<coordinate_type>, point_data<coordinate_type> >, int>& edge, bool is_hole = false, orientation_2d = HORIZONTAL) { std::pair<coordinate_type, std::pair<coordinate_type, int> > vertex; vertex.first = edge.first.first.x(); vertex.second.first = edge.first.first.y(); vertex.second.second = edge.second * (is_hole ? -1 : 1); insert(vertex, false, VERTICAL); vertex.first = edge.first.second.x(); vertex.second.first = edge.first.second.y(); vertex.second.second *= -1; insert(vertex, false, VERTICAL); } template <typename geometry_type> inline void insert(const geometry_type& geometry_object, bool is_hole = false, orientation_2d = HORIZONTAL) { iterator_geometry_to_set<typename geometry_concept<geometry_type>::type, geometry_type> begin_input(geometry_object, LOW, orient_, is_hole), end_input(geometry_object, HIGH, orient_, is_hole); insert(begin_input, end_input, orient_); } inline void insert(const std::pair<coordinate_type, std::pair<coordinate_type, int> >& vertex, bool is_hole = false, orientation_2d orient = HORIZONTAL) { data_.push_back(vertex); if(orient != orient_) std::swap(data_.back().first, data_.back().second.first); if(is_hole) data_.back().second.second *= -1; dirty_ = true; unsorted_ = true; } inline void insert(coordinate_type major_coordinate, const std::pair<interval_data<coordinate_type>, int>& edge) { std::pair<coordinate_type, std::pair<coordinate_type, int> > vertex; vertex.first = major_coordinate; vertex.second.first = edge.first.get(LOW); vertex.second.second = edge.second; insert(vertex, false, orient_); vertex.second.first = edge.first.get(HIGH); vertex.second.second *= -1; insert(vertex, false, orient_); } template <typename output_container> inline void get(output_container& output) const { get_dispatch(output, typename geometry_concept<typename output_container::value_type>::type()); } template <typename output_container> inline void get(output_container& output, size_t vthreshold) const { get_dispatch(output, typename geometry_concept<typename output_container::value_type>::type(), vthreshold); } template <typename output_container> inline void get_polygons(output_container& output) const { get_dispatch(output, polygon_90_concept()); } template <typename output_container> inline void get_rectangles(output_container& output) const { clean(); form_rectangles(output, data_.begin(), data_.end(), orient_, rectangle_concept()); } template <typename output_container> inline void get_rectangles(output_container& output, orientation_2d slicing_orientation) const { if(slicing_orientation == orient_) { get_rectangles(output); } else { polygon_90_set_data<coordinate_type> ps(*this); ps.transform(axis_transformation(axis_transformation::SWAP_XY)); output_container result; ps.get_rectangles(result); for(typename output_container::iterator itr = result.begin(); itr != result.end(); ++itr) { ::boost::polygon::transform(*itr, axis_transformation(axis_transformation::SWAP_XY)); } output.insert(output.end(), result.begin(), result.end()); } } // equivalence operator inline bool operator==(const polygon_90_set_data& p) const { if(orient_ == p.orient()) { clean(); p.clean(); return data_ == p.data_; } else { return false; } } // inequivalence operator inline bool operator!=(const polygon_90_set_data& p) const { return !((*this) == p); } // get iterator to begin vertex data inline iterator_type begin() const { return data_.begin(); } // get iterator to end vertex data inline iterator_type end() const { return data_.end(); } const value_type& value() const { return data_; } // clear the contents of the polygon_90_set_data inline void clear() { data_.clear(); dirty_ = unsorted_ = false; } // find out if Polygon set is empty inline bool empty() const { clean(); return data_.empty(); } // get the Polygon set size in vertices inline std::size_t size() const { clean(); return data_.size(); } // get the current Polygon set capacity in vertices inline std::size_t capacity() const { return data_.capacity(); } // reserve size of polygon set in vertices inline void reserve(std::size_t size) { return data_.reserve(size); } // find out if Polygon set is sorted inline bool sorted() const { return !unsorted_; } // find out if Polygon set is clean inline bool dirty() const { return dirty_; } // get the scanline orientation of the polygon set inline orientation_2d orient() const { return orient_; } // Start BM // The problem: If we have two polygon sets with two different scanline orientations: // I tried changing the orientation of one to coincide with other (If not, resulting boolean operation // produces spurious results). // First I tried copying polygon data from one of the sets into another set with corrected orientation // using one of the copy constructor that takes in orientation (see somewhere above in this file) --> copy constructor throws error // Then I tried another approach:(see below). This approach also fails to produce the desired results when test case is run. // Here is the part that beats me: If I comment out the whole section, I can do all the operations (^=, -=, &= )these commented out // operations perform. So then why do we need them?. Hence, I commented out this whole section. // End BM // polygon_90_set_data<coordinate_type>& operator-=(const polygon_90_set_data& that) { // sort(); // that.sort(); // value_type data; // std::swap(data, data_); // applyBooleanBinaryOp(data.begin(), data.end(), // that.begin(), that.end(), boolean_op::BinaryCount<boolean_op::BinaryNot>()); // return *this; // } // polygon_90_set_data<coordinate_type>& operator^=(const polygon_90_set_data& that) { // sort(); // that.sort(); // value_type data; // std::swap(data, data_); // applyBooleanBinaryOp(data.begin(), data.end(), // that.begin(), that.end(), boolean_op::BinaryCount<boolean_op::BinaryXor>()); // return *this; // } // polygon_90_set_data<coordinate_type>& operator&=(const polygon_90_set_data& that) { // sort(); // that.sort(); // value_type data; // std::swap(data, data_); // applyBooleanBinaryOp(data.begin(), data.end(), // that.begin(), that.end(), boolean_op::BinaryCount<boolean_op::BinaryAnd>()); // return *this; // } // polygon_90_set_data<coordinate_type>& operator|=(const polygon_90_set_data& that) { // insert(that); // return *this; // } void clean() const { sort(); if(dirty_) { boolean_op::default_arg_workaround<int>::applyBooleanOr(data_); dirty_ = false; } } void sort() const{ if(unsorted_) { polygon_sort(data_.begin(), data_.end()); unsorted_ = false; } } template <typename input_iterator_type> void set(input_iterator_type input_begin, input_iterator_type input_end, orientation_2d orient) { data_.clear(); reserve(std::distance(input_begin, input_end)); data_.insert(data_.end(), input_begin, input_end); orient_ = orient; dirty_ = true; unsorted_ = true; } void set(const value_type& value, orientation_2d orient) { data_ = value; orient_ = orient; dirty_ = true; unsorted_ = true; } //extents template <typename rectangle_type> bool extents(rectangle_type& extents_rectangle) const { clean(); if(data_.empty()) return false; if(orient_ == HORIZONTAL) set_points(extents_rectangle, point_data<coordinate_type>(data_[0].second.first, data_[0].first), point_data<coordinate_type>(data_[data_.size() - 1].second.first, data_[data_.size() - 1].first)); else set_points(extents_rectangle, point_data<coordinate_type>(data_[0].first, data_[0].second.first), point_data<coordinate_type>(data_[data_.size() - 1].first, data_[data_.size() - 1].second.first)); for(std::size_t i = 1; i < data_.size() - 1; ++i) { if(orient_ == HORIZONTAL) encompass(extents_rectangle, point_data<coordinate_type>(data_[i].second.first, data_[i].first)); else encompass(extents_rectangle, point_data<coordinate_type>(data_[i].first, data_[i].second.first)); } return true; } polygon_90_set_data& bloat2(typename coordinate_traits<coordinate_type>::unsigned_area_type west_bloating, typename coordinate_traits<coordinate_type>::unsigned_area_type east_bloating, typename coordinate_traits<coordinate_type>::unsigned_area_type south_bloating, typename coordinate_traits<coordinate_type>::unsigned_area_type north_bloating) { std::vector<rectangle_data<coordinate_type> > rects; clean(); rects.reserve(data_.size() / 2); get(rects); rectangle_data<coordinate_type> convolutionRectangle(interval_data<coordinate_type>(-((coordinate_type)west_bloating), (coordinate_type)east_bloating), interval_data<coordinate_type>(-((coordinate_type)south_bloating), (coordinate_type)north_bloating)); for(typename std::vector<rectangle_data<coordinate_type> >::iterator itr = rects.begin(); itr != rects.end(); ++itr) { convolve(*itr, convolutionRectangle); } clear(); insert(rects.begin(), rects.end()); return *this; } static void modify_pt(point_data<coordinate_type>& pt, const point_data<coordinate_type>& prev_pt, const point_data<coordinate_type>& current_pt, const point_data<coordinate_type>& next_pt, coordinate_type west_bloating, coordinate_type east_bloating, coordinate_type south_bloating, coordinate_type north_bloating) { bool pxl = prev_pt.x() < current_pt.x(); bool pyl = prev_pt.y() < current_pt.y(); bool nxl = next_pt.x() < current_pt.x(); bool nyl = next_pt.y() < current_pt.y(); bool pxg = prev_pt.x() > current_pt.x(); bool pyg = prev_pt.y() > current_pt.y(); bool nxg = next_pt.x() > current_pt.x(); bool nyg = next_pt.y() > current_pt.y(); //two of the four if statements will execute if(pxl) pt.y(current_pt.y() - south_bloating); if(pxg) pt.y(current_pt.y() + north_bloating); if(nxl) pt.y(current_pt.y() + north_bloating); if(nxg) pt.y(current_pt.y() - south_bloating); if(pyl) pt.x(current_pt.x() + east_bloating); if(pyg) pt.x(current_pt.x() - west_bloating); if(nyl) pt.x(current_pt.x() - west_bloating); if(nyg) pt.x(current_pt.x() + east_bloating); } static void resize_poly_up(std::vector<point_data<coordinate_type> >& poly, coordinate_type west_bloating, coordinate_type east_bloating, coordinate_type south_bloating, coordinate_type north_bloating) { point_data<coordinate_type> first_pt = poly[0]; point_data<coordinate_type> second_pt = poly[1]; point_data<coordinate_type> prev_pt = poly[0]; point_data<coordinate_type> current_pt = poly[1]; for(std::size_t i = 2; i < poly.size(); ++i) { point_data<coordinate_type> next_pt = poly[i]; modify_pt(poly[i-1], prev_pt, current_pt, next_pt, west_bloating, east_bloating, south_bloating, north_bloating); prev_pt = current_pt; current_pt = next_pt; } point_data<coordinate_type> next_pt = first_pt; modify_pt(poly.back(), prev_pt, current_pt, next_pt, west_bloating, east_bloating, south_bloating, north_bloating); prev_pt = current_pt; current_pt = next_pt; next_pt = second_pt; modify_pt(poly[0], prev_pt, current_pt, next_pt, west_bloating, east_bloating, south_bloating, north_bloating); remove_colinear_pts(poly); } static bool resize_poly_down(std::vector<point_data<coordinate_type> >& poly, coordinate_type west_shrinking, coordinate_type east_shrinking, coordinate_type south_shrinking, coordinate_type north_shrinking) { rectangle_data<coordinate_type> extents_rectangle; set_points(extents_rectangle, poly[0], poly[0]); point_data<coordinate_type> first_pt = poly[0]; point_data<coordinate_type> second_pt = poly[1]; point_data<coordinate_type> prev_pt = poly[0]; point_data<coordinate_type> current_pt = poly[1]; encompass(extents_rectangle, current_pt); for(std::size_t i = 2; i < poly.size(); ++i) { point_data<coordinate_type> next_pt = poly[i]; encompass(extents_rectangle, next_pt); modify_pt(poly[i-1], prev_pt, current_pt, next_pt, west_shrinking, east_shrinking, south_shrinking, north_shrinking); prev_pt = current_pt; current_pt = next_pt; } if(delta(extents_rectangle, HORIZONTAL) < std::abs(west_shrinking + east_shrinking)) return false; if(delta(extents_rectangle, VERTICAL) < std::abs(north_shrinking + south_shrinking)) return false; point_data<coordinate_type> next_pt = first_pt; modify_pt(poly.back(), prev_pt, current_pt, next_pt, west_shrinking, east_shrinking, south_shrinking, north_shrinking); prev_pt = current_pt; current_pt = next_pt; next_pt = second_pt; modify_pt(poly[0], prev_pt, current_pt, next_pt, west_shrinking, east_shrinking, south_shrinking, north_shrinking); return remove_colinear_pts(poly); } static bool remove_colinear_pts(std::vector<point_data<coordinate_type> >& poly) { bool found_colinear = true; while(found_colinear && poly.size() >= 4) { found_colinear = false; typename std::vector<point_data<coordinate_type> >::iterator itr = poly.begin(); itr += poly.size() - 1; //get last element position typename std::vector<point_data<coordinate_type> >::iterator itr2 = poly.begin(); typename std::vector<point_data<coordinate_type> >::iterator itr3 = itr2; ++itr3; std::size_t count = 0; for( ; itr3 < poly.end(); ++itr3) { if(((*itr).x() == (*itr2).x() && (*itr).x() == (*itr3).x()) || ((*itr).y() == (*itr2).y() && (*itr).y() == (*itr3).y()) ) { ++count; found_colinear = true; } else { itr = itr2; ++itr2; } *itr2 = *itr3; } itr3 = poly.begin(); if(((*itr).x() == (*itr2).x() && (*itr).x() == (*itr3).x()) || ((*itr).y() == (*itr2).y() && (*itr).y() == (*itr3).y()) ) { ++count; found_colinear = true; } poly.erase(poly.end() - count, poly.end()); } return poly.size() >= 4; } polygon_90_set_data& bloat(typename coordinate_traits<coordinate_type>::unsigned_area_type west_bloating, typename coordinate_traits<coordinate_type>::unsigned_area_type east_bloating, typename coordinate_traits<coordinate_type>::unsigned_area_type south_bloating, typename coordinate_traits<coordinate_type>::unsigned_area_type north_bloating) { std::list<polygon_45_with_holes_data<coordinate_type> > polys; get(polys); clear(); for(typename std::list<polygon_45_with_holes_data<coordinate_type> >::iterator itr = polys.begin(); itr != polys.end(); ++itr) { //polygon_90_set_data<coordinate_type> psref; //psref.insert(view_as<polygon_90_concept>((*itr).self_)); //rectangle_data<coordinate_type> prerect; //psref.extents(prerect); resize_poly_up((*itr).self_.coords_, (coordinate_type)west_bloating, (coordinate_type)east_bloating, (coordinate_type)south_bloating, (coordinate_type)north_bloating); iterator_geometry_to_set<polygon_90_concept, view_of<polygon_90_concept, polygon_45_data<coordinate_type> > > begin_input(view_as<polygon_90_concept>((*itr).self_), LOW, orient_, false, true, COUNTERCLOCKWISE), end_input(view_as<polygon_90_concept>((*itr).self_), HIGH, orient_, false, true, COUNTERCLOCKWISE); insert(begin_input, end_input, orient_); //polygon_90_set_data<coordinate_type> pstest; //pstest.insert(view_as<polygon_90_concept>((*itr).self_)); //psref.bloat2(west_bloating, east_bloating, south_bloating, north_bloating); //if(!equivalence(psref, pstest)) { // std::cout << "test failed\n"; //} for(typename std::list<polygon_45_data<coordinate_type> >::iterator itrh = (*itr).holes_.begin(); itrh != (*itr).holes_.end(); ++itrh) { //rectangle_data<coordinate_type> rect; //psref.extents(rect); //polygon_90_set_data<coordinate_type> psrefhole; //psrefhole.insert(prerect); //psrefhole.insert(view_as<polygon_90_concept>(*itrh), true); //polygon_45_data<coordinate_type> testpoly(*itrh); if(resize_poly_down((*itrh).coords_,(coordinate_type)west_bloating, (coordinate_type)east_bloating, (coordinate_type)south_bloating, (coordinate_type)north_bloating)) { iterator_geometry_to_set<polygon_90_concept, view_of<polygon_90_concept, polygon_45_data<coordinate_type> > > begin_input2(view_as<polygon_90_concept>(*itrh), LOW, orient_, true, true), end_input2(view_as<polygon_90_concept>(*itrh), HIGH, orient_, true, true); insert(begin_input2, end_input2, orient_); //polygon_90_set_data<coordinate_type> pstesthole; //pstesthole.insert(rect); //iterator_geometry_to_set<polygon_90_concept, view_of<polygon_90_concept, polygon_45_data<coordinate_type> > > // begin_input2(view_as<polygon_90_concept>(*itrh), LOW, orient_, true, true); //pstesthole.insert(begin_input2, end_input, orient_); //psrefhole.bloat2(west_bloating, east_bloating, south_bloating, north_bloating); //if(!equivalence(psrefhole, pstesthole)) { // std::cout << (winding(testpoly) == CLOCKWISE) << std::endl; // std::cout << (winding(*itrh) == CLOCKWISE) << std::endl; // polygon_90_set_data<coordinate_type> c(psrefhole); // c.clean(); // polygon_90_set_data<coordinate_type> a(pstesthole); // polygon_90_set_data<coordinate_type> b(pstesthole); // a.sort(); // b.clean(); // std::cout << "test hole failed\n"; // //std::cout << testpoly << std::endl; //} } } } return *this; } polygon_90_set_data& shrink(typename coordinate_traits<coordinate_type>::unsigned_area_type west_shrinking, typename coordinate_traits<coordinate_type>::unsigned_area_type east_shrinking, typename coordinate_traits<coordinate_type>::unsigned_area_type south_shrinking, typename coordinate_traits<coordinate_type>::unsigned_area_type north_shrinking) { std::list<polygon_45_with_holes_data<coordinate_type> > polys; get(polys); clear(); for(typename std::list<polygon_45_with_holes_data<coordinate_type> >::iterator itr = polys.begin(); itr != polys.end(); ++itr) { //polygon_90_set_data<coordinate_type> psref; //psref.insert(view_as<polygon_90_concept>((*itr).self_)); //rectangle_data<coordinate_type> prerect; //psref.extents(prerect); //polygon_45_data<coordinate_type> testpoly((*itr).self_); if(resize_poly_down((*itr).self_.coords_, -(coordinate_type)west_shrinking, -(coordinate_type)east_shrinking, -(coordinate_type)south_shrinking, -(coordinate_type)north_shrinking)) { iterator_geometry_to_set<polygon_90_concept, view_of<polygon_90_concept, polygon_45_data<coordinate_type> > > begin_input(view_as<polygon_90_concept>((*itr).self_), LOW, orient_, false, true, COUNTERCLOCKWISE), end_input(view_as<polygon_90_concept>((*itr).self_), HIGH, orient_, false, true, COUNTERCLOCKWISE); insert(begin_input, end_input, orient_); //iterator_geometry_to_set<polygon_90_concept, view_of<polygon_90_concept, polygon_45_data<coordinate_type> > > // begin_input2(view_as<polygon_90_concept>((*itr).self_), LOW, orient_, false, true, COUNTERCLOCKWISE); //polygon_90_set_data<coordinate_type> pstest; //pstest.insert(begin_input2, end_input, orient_); //psref.shrink2(west_shrinking, east_shrinking, south_shrinking, north_shrinking); //if(!equivalence(psref, pstest)) { // std::cout << "test failed\n"; //} for(typename std::list<polygon_45_data<coordinate_type> >::iterator itrh = (*itr).holes_.begin(); itrh != (*itr).holes_.end(); ++itrh) { //rectangle_data<coordinate_type> rect; //psref.extents(rect); //polygon_90_set_data<coordinate_type> psrefhole; //psrefhole.insert(prerect); //psrefhole.insert(view_as<polygon_90_concept>(*itrh), true); //polygon_45_data<coordinate_type> testpoly(*itrh); resize_poly_up((*itrh).coords_, -(coordinate_type)west_shrinking, -(coordinate_type)east_shrinking, -(coordinate_type)south_shrinking, -(coordinate_type)north_shrinking); iterator_geometry_to_set<polygon_90_concept, view_of<polygon_90_concept, polygon_45_data<coordinate_type> > > begin_input2(view_as<polygon_90_concept>(*itrh), LOW, orient_, true, true), end_input2(view_as<polygon_90_concept>(*itrh), HIGH, orient_, true, true); insert(begin_input2, end_input2, orient_); //polygon_90_set_data<coordinate_type> pstesthole; //pstesthole.insert(rect); //iterator_geometry_to_set<polygon_90_concept, view_of<polygon_90_concept, polygon_45_data<coordinate_type> > > // begin_input2(view_as<polygon_90_concept>(*itrh), LOW, orient_, true, true); //pstesthole.insert(begin_input2, end_input, orient_); //psrefhole.shrink2(west_shrinking, east_shrinking, south_shrinking, north_shrinking); //if(!equivalence(psrefhole, pstesthole)) { // std::cout << (winding(testpoly) == CLOCKWISE) << std::endl; // std::cout << (winding(*itrh) == CLOCKWISE) << std::endl; // polygon_90_set_data<coordinate_type> c(psrefhole); // c.clean(); // polygon_90_set_data<coordinate_type> a(pstesthole); // polygon_90_set_data<coordinate_type> b(pstesthole); // a.sort(); // b.clean(); // std::cout << "test hole failed\n"; // //std::cout << testpoly << std::endl; //} } } } return *this; } polygon_90_set_data& shrink2(typename coordinate_traits<coordinate_type>::unsigned_area_type west_shrinking, typename coordinate_traits<coordinate_type>::unsigned_area_type east_shrinking, typename coordinate_traits<coordinate_type>::unsigned_area_type south_shrinking, typename coordinate_traits<coordinate_type>::unsigned_area_type north_shrinking) { rectangle_data<coordinate_type> externalBoundary; if(!extents(externalBoundary)) return *this; ::boost::polygon::bloat(externalBoundary, 10); //bloat by diferential ammount //insert a hole that encompasses the data insert(externalBoundary, true); //note that the set is in a dirty state now sort(); //does not apply implicit OR operation std::vector<rectangle_data<coordinate_type> > rects; rects.reserve(data_.size() / 2); //begin does not apply implicit or operation, this is a dirty range form_rectangles(rects, data_.begin(), data_.end(), orient_, rectangle_concept()); clear(); rectangle_data<coordinate_type> convolutionRectangle(interval_data<coordinate_type>(-((coordinate_type)east_shrinking), (coordinate_type)west_shrinking), interval_data<coordinate_type>(-((coordinate_type)north_shrinking), (coordinate_type)south_shrinking)); for(typename std::vector<rectangle_data<coordinate_type> >::iterator itr = rects.begin(); itr != rects.end(); ++itr) { rectangle_data<coordinate_type>& rect = *itr; convolve(rect, convolutionRectangle); //insert rectangle as a hole insert(rect, true); } convolve(externalBoundary, convolutionRectangle); //insert duplicate of external boundary as solid to cancel out the external hole boundaries insert(externalBoundary); clean(); //we have negative values in the set, so we need to apply an OR operation to make it valid input to a boolean return *this; } polygon_90_set_data& shrink(direction_2d dir, typename coordinate_traits<coordinate_type>::unsigned_area_type shrinking) { if(dir == WEST) return shrink(shrinking, 0, 0, 0); if(dir == EAST) return shrink(0, shrinking, 0, 0); if(dir == SOUTH) return shrink(0, 0, shrinking, 0); return shrink(0, 0, 0, shrinking); } polygon_90_set_data& bloat(direction_2d dir, typename coordinate_traits<coordinate_type>::unsigned_area_type shrinking) { if(dir == WEST) return bloat(shrinking, 0, 0, 0); if(dir == EAST) return bloat(0, shrinking, 0, 0); if(dir == SOUTH) return bloat(0, 0, shrinking, 0); return bloat(0, 0, 0, shrinking); } polygon_90_set_data& resize(coordinate_type west, coordinate_type east, coordinate_type south, coordinate_type north); polygon_90_set_data& move(coordinate_type x_delta, coordinate_type y_delta) { for(typename std::vector<std::pair<coordinate_type, std::pair<coordinate_type, int> > >::iterator itr = data_.begin(); itr != data_.end(); ++itr) { if(orient_ == orientation_2d(VERTICAL)) { (*itr).first += x_delta; (*itr).second.first += y_delta; } else { (*itr).second.first += x_delta; (*itr).first += y_delta; } } return *this; } // transform set template <typename transformation_type> polygon_90_set_data& transform(const transformation_type& transformation) { direction_2d dir1, dir2; transformation.get_directions(dir1, dir2); int sign = dir1.get_sign() * dir2.get_sign(); for(typename std::vector<std::pair<coordinate_type, std::pair<coordinate_type, int> > >::iterator itr = data_.begin(); itr != data_.end(); ++itr) { if(orient_ == orientation_2d(VERTICAL)) { transformation.transform((*itr).first, (*itr).second.first); } else { transformation.transform((*itr).second.first, (*itr).first); } (*itr).second.second *= sign; } if(dir1 != EAST || dir2 != NORTH) unsorted_ = true; //some mirroring or rotation must have happened return *this; } // scale set polygon_90_set_data& scale_up(typename coordinate_traits<coordinate_type>::unsigned_area_type factor) { for(typename std::vector<std::pair<coordinate_type, std::pair<coordinate_type, int> > >::iterator itr = data_.begin(); itr != data_.end(); ++itr) { (*itr).first *= (coordinate_type)factor; (*itr).second.first *= (coordinate_type)factor; } return *this; } polygon_90_set_data& scale_down(typename coordinate_traits<coordinate_type>::unsigned_area_type factor) { typedef typename coordinate_traits<coordinate_type>::coordinate_distance dt; for(typename std::vector<std::pair<coordinate_type, std::pair<coordinate_type, int> > >::iterator itr = data_.begin(); itr != data_.end(); ++itr) { (*itr).first = scaling_policy<coordinate_type>::round((dt)((*itr).first) / (dt)factor); (*itr).second.first = scaling_policy<coordinate_type>::round((dt)((*itr).second.first) / (dt)factor); } unsorted_ = true; //scaling down can make coordinates equal that were not previously equal return *this; } template <typename scaling_type> polygon_90_set_data& scale(const anisotropic_scale_factor<scaling_type>& scaling) { for(typename std::vector<std::pair<coordinate_type, std::pair<coordinate_type, int> > >::iterator itr = data_.begin(); itr != data_.end(); ++itr) { if(orient_ == orientation_2d(VERTICAL)) { scaling.scale((*itr).first, (*itr).second.first); } else { scaling.scale((*itr).second.first, (*itr).first); } } unsorted_ = true; return *this; } template <typename scaling_type> polygon_90_set_data& scale_with(const scaling_type& scaling) { for(typename std::vector<std::pair<coordinate_type, std::pair<coordinate_type, int> > >::iterator itr = data_.begin(); itr != data_.end(); ++itr) { if(orient_ == orientation_2d(VERTICAL)) { scaling.scale((*itr).first, (*itr).second.first); } else { scaling.scale((*itr).second.first, (*itr).first); } } unsorted_ = true; return *this; } polygon_90_set_data& scale(double factor) { typedef typename coordinate_traits<coordinate_type>::coordinate_distance dt; for(typename std::vector<std::pair<coordinate_type, std::pair<coordinate_type, int> > >::iterator itr = data_.begin(); itr != data_.end(); ++itr) { (*itr).first = scaling_policy<coordinate_type>::round((dt)((*itr).first) * (dt)factor); (*itr).second.first = scaling_policy<coordinate_type>::round((dt)((*itr).second.first) * (dt)factor); } unsorted_ = true; //scaling make coordinates equal that were not previously equal return *this; } polygon_90_set_data& self_xor() { sort(); if(dirty_) { //if it is clean it is a no-op boolean_op::default_arg_workaround<boolean_op::UnaryCount>::applyBooleanOr(data_); dirty_ = false; } return *this; } polygon_90_set_data& self_intersect() { sort(); if(dirty_) { //if it is clean it is a no-op interval_data<coordinate_type> ivl((std::numeric_limits<coordinate_type>::min)(), (std::numeric_limits<coordinate_type>::max)()); rectangle_data<coordinate_type> rect(ivl, ivl); insert(rect, true); clean(); } return *this; } inline polygon_90_set_data& interact(const polygon_90_set_data& that) { typedef coordinate_type Unit; if(that.dirty_) that.clean(); typename touch_90_operation<Unit>::TouchSetData tsd; touch_90_operation<Unit>::populateTouchSetData(tsd, that.data_, 0); std::vector<polygon_90_data<Unit> > polys; get(polys); std::vector<std::set<int> > graph(polys.size()+1, std::set<int>()); for(std::size_t i = 0; i < polys.size(); ++i){ polygon_90_set_data<Unit> psTmp(that.orient_); psTmp.insert(polys[i]); psTmp.clean(); touch_90_operation<Unit>::populateTouchSetData(tsd, psTmp.data_, i+1); } touch_90_operation<Unit>::performTouch(graph, tsd); clear(); for(std::set<int>::iterator itr = graph[0].begin(); itr != graph[0].end(); ++itr){ insert(polys[(*itr)-1]); } dirty_ = false; return *this; } template <class T2, typename iterator_type_1, typename iterator_type_2> void applyBooleanBinaryOp(iterator_type_1 itr1, iterator_type_1 itr1_end, iterator_type_2 itr2, iterator_type_2 itr2_end, T2 defaultCount) { data_.clear(); boolean_op::applyBooleanBinaryOp(data_, itr1, itr1_end, itr2, itr2_end, defaultCount); } private: orientation_2d orient_; mutable value_type data_; mutable bool dirty_; mutable bool unsorted_; private: //functions template <typename output_container> void get_dispatch(output_container& output, rectangle_concept ) const { clean(); form_rectangles(output, data_.begin(), data_.end(), orient_, rectangle_concept()); } template <typename output_container> void get_dispatch(output_container& output, polygon_90_concept tag) const { get_fracture(output, true, tag); } template <typename output_container> void get_dispatch(output_container& output, polygon_90_concept tag, size_t vthreshold) const { get_fracture(output, true, tag, vthreshold); } template <typename output_container> void get_dispatch(output_container& output, polygon_90_with_holes_concept tag) const { get_fracture(output, false, tag); } template <typename output_container> void get_dispatch(output_container& output, polygon_90_with_holes_concept tag, size_t vthreshold) const { get_fracture(output, false, tag, vthreshold); } template <typename output_container> void get_dispatch(output_container& output, polygon_45_concept tag) const { get_fracture(output, true, tag); } template <typename output_container> void get_dispatch(output_container& output, polygon_45_with_holes_concept tag) const { get_fracture(output, false, tag); } template <typename output_container> void get_dispatch(output_container& output, polygon_concept tag) const { get_fracture(output, true, tag); } template <typename output_container> void get_dispatch(output_container& output, polygon_with_holes_concept tag) const { get_fracture(output, false, tag); } template <typename output_container, typename concept_type> void get_fracture(output_container& container, bool fracture_holes, concept_type tag) const { clean(); ::boost::polygon::get_polygons(container, data_.begin(), data_.end(), orient_, fracture_holes, tag); } template <typename output_container, typename concept_type> void get_fracture(output_container& container, bool fracture_holes, concept_type tag, size_t vthreshold) const { clean(); ::boost::polygon::get_polygons(container, data_.begin(), data_.end(), orient_, fracture_holes, tag, vthreshold); } }; template <typename coordinate_type> polygon_90_set_data<coordinate_type>& polygon_90_set_data<coordinate_type>::resize(coordinate_type west, coordinate_type east, coordinate_type south, coordinate_type north) { move(-west, -south); coordinate_type e_total = west + east; coordinate_type n_total = south + north; if((e_total < 0) ^ (n_total < 0)) { //different signs if(e_total < 0) { shrink(0, -e_total, 0, 0); if(n_total != 0) return bloat(0, 0, 0, n_total); else return (*this); } else { shrink(0, 0, 0, -n_total); //shrink first if(e_total != 0) return bloat(0, e_total, 0, 0); else return (*this); } } else { if(e_total < 0) { return shrink(0, -e_total, 0, -n_total); } return bloat(0, e_total, 0, n_total); } } template <typename coordinate_type, typename property_type> class property_merge_90 { private: std::vector<std::pair<property_merge_point<coordinate_type>, std::pair<property_type, int> > > pmd_; public: inline property_merge_90() : pmd_() {} inline property_merge_90(const property_merge_90& that) : pmd_(that.pmd_) {} inline property_merge_90& operator=(const property_merge_90& that) { pmd_ = that.pmd_; return *this; } inline void insert(const polygon_90_set_data<coordinate_type>& ps, const property_type& property) { merge_scanline<coordinate_type, property_type, polygon_90_set_data<coordinate_type> >:: populate_property_merge_data(pmd_, ps.begin(), ps.end(), property, ps.orient()); } template <class GeoObjT> inline void insert(const GeoObjT& geoObj, const property_type& property) { polygon_90_set_data<coordinate_type> ps; ps.insert(geoObj); insert(ps, property); } //merge properties of input geometries and store the resulting geometries of regions //with unique sets of merged properties to polygons sets in a map keyed by sets of properties // T = std::map<std::set<property_type>, polygon_90_set_data<coordiante_type> > or // T = std::map<std::vector<property_type>, polygon_90_set_data<coordiante_type> > template <typename ResultType> inline void merge(ResultType& result) { merge_scanline<coordinate_type, property_type, polygon_90_set_data<coordinate_type>, typename ResultType::key_type> ms; ms.perform_merge(result, pmd_); } }; //ConnectivityExtraction computes the graph of connectivity between rectangle, polygon and //polygon set graph nodes where an edge is created whenever the geometry in two nodes overlap template <typename coordinate_type> class connectivity_extraction_90 { private: typedef typename touch_90_operation<coordinate_type>::TouchSetData tsd; tsd tsd_; unsigned int nodeCount_; public: inline connectivity_extraction_90() : tsd_(), nodeCount_(0) {} inline connectivity_extraction_90(const connectivity_extraction_90& that) : tsd_(that.tsd_), nodeCount_(that.nodeCount_) {} inline connectivity_extraction_90& operator=(const connectivity_extraction_90& that) { tsd_ = that.tsd_; nodeCount_ = that.nodeCount_; {} return *this; } //insert a polygon set graph node, the value returned is the id of the graph node inline unsigned int insert(const polygon_90_set_data<coordinate_type>& ps) { ps.clean(); touch_90_operation<coordinate_type>::populateTouchSetData(tsd_, ps.begin(), ps.end(), nodeCount_); return nodeCount_++; } template <class GeoObjT> inline unsigned int insert(const GeoObjT& geoObj) { polygon_90_set_data<coordinate_type> ps; ps.insert(geoObj); return insert(ps); } //extract connectivity and store the edges in the graph //graph must be indexable by graph node id and the indexed value must be a std::set of //graph node id template <class GraphT> inline void extract(GraphT& graph) { touch_90_operation<coordinate_type>::performTouch(graph, tsd_); } }; } } #endif PK �b�[N/[��1 �1 polygon_45_set_data.hppnu �[��� /* Copyright 2008 Intel Corporation Use, modification and distribution are 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_POLYGON_POLYGON_45_SET_DATA_HPP #define BOOST_POLYGON_POLYGON_45_SET_DATA_HPP #include "polygon_90_set_data.hpp" #include "detail/boolean_op_45.hpp" #include "detail/polygon_45_formation.hpp" #include "detail/polygon_45_touch.hpp" #include "detail/property_merge_45.hpp" namespace boost { namespace polygon{ enum RoundingOption { CLOSEST = 0, OVERSIZE = 1, UNDERSIZE = 2, SQRT2 = 3, SQRT1OVER2 = 4 }; enum CornerOption { INTERSECTION = 0, ORTHOGONAL = 1, UNFILLED = 2 }; template <typename ltype, typename rtype, int op_type> class polygon_45_set_view; struct polygon_45_set_concept {}; template <typename Unit> class polygon_45_set_data { public: typedef typename polygon_45_formation<Unit>::Vertex45Compact Vertex45Compact; typedef std::vector<Vertex45Compact> Polygon45VertexData; typedef Unit coordinate_type; typedef Polygon45VertexData value_type; typedef typename value_type::const_iterator iterator_type; typedef polygon_45_set_data operator_arg_type; // default constructor inline polygon_45_set_data() : error_data_(), data_(), dirty_(false), unsorted_(false), is_manhattan_(true) {} // constructor from a geometry object template <typename geometry_type> inline polygon_45_set_data(const geometry_type& that) : error_data_(), data_(), dirty_(false), unsorted_(false), is_manhattan_(true) { insert(that); } // copy constructor inline polygon_45_set_data(const polygon_45_set_data& that) : error_data_(that.error_data_), data_(that.data_), dirty_(that.dirty_), unsorted_(that.unsorted_), is_manhattan_(that.is_manhattan_) {} template <typename ltype, typename rtype, int op_type> inline polygon_45_set_data(const polygon_45_set_view<ltype, rtype, op_type>& that) : error_data_(), data_(), dirty_(false), unsorted_(false), is_manhattan_(true) { (*this) = that.value(); } // destructor inline ~polygon_45_set_data() {} // assignement operator inline polygon_45_set_data& operator=(const polygon_45_set_data& that) { if(this == &that) return *this; error_data_ = that.error_data_; data_ = that.data_; dirty_ = that.dirty_; unsorted_ = that.unsorted_; is_manhattan_ = that.is_manhattan_; return *this; } template <typename ltype, typename rtype, int op_type> inline polygon_45_set_data& operator=(const polygon_45_set_view<ltype, rtype, op_type>& that) { (*this) = that.value(); return *this; } template <typename geometry_object> inline polygon_45_set_data& operator=(const geometry_object& geometry) { data_.clear(); insert(geometry); return *this; } // insert iterator range inline void insert(iterator_type input_begin, iterator_type input_end, bool is_hole = false) { if(input_begin == input_end || (!data_.empty() && &(*input_begin) == &(*(data_.begin())))) return; dirty_ = true; unsorted_ = true; while(input_begin != input_end) { insert(*input_begin, is_hole); ++input_begin; } } // insert iterator range template <typename iT> inline void insert(iT input_begin, iT input_end, bool is_hole = false) { if(input_begin == input_end) return; dirty_ = true; unsorted_ = true; while(input_begin != input_end) { insert(*input_begin, is_hole); ++input_begin; } } inline void insert(const polygon_45_set_data& polygon_set, bool is_hole = false); template <typename coord_type> inline void insert(const polygon_45_set_data<coord_type>& polygon_set, bool is_hole = false); template <typename geometry_type> inline void insert(const geometry_type& geometry_object, bool is_hole = false) { insert_dispatch(geometry_object, is_hole, typename geometry_concept<geometry_type>::type()); } inline void insert_clean(const Vertex45Compact& vertex_45, bool is_hole = false) { if(vertex_45.count.is_45()) is_manhattan_ = false; data_.push_back(vertex_45); if(is_hole) data_.back().count.invert(); } inline void insert(const Vertex45Compact& vertex_45, bool is_hole = false) { dirty_ = true; unsorted_ = true; insert_clean(vertex_45, is_hole); } template <typename coordinate_type_2> inline void insert(const polygon_90_set_data<coordinate_type_2>& polygon_set, bool is_hole = false) { if(polygon_set.orient() == VERTICAL) { for(typename polygon_90_set_data<coordinate_type_2>::iterator_type itr = polygon_set.begin(); itr != polygon_set.end(); ++itr) { Vertex45Compact vertex_45(point_data<Unit>((*itr).first, (*itr).second.first), 2, (*itr).second.second); vertex_45.count[1] = (*itr).second.second; if(is_hole) vertex_45.count[1] *= - 1; insert_clean(vertex_45, is_hole); } } else { for(typename polygon_90_set_data<coordinate_type_2>::iterator_type itr = polygon_set.begin(); itr != polygon_set.end(); ++itr) { Vertex45Compact vertex_45(point_data<Unit>((*itr).second.first, (*itr).first), 2, (*itr).second.second); vertex_45.count[1] = (*itr).second.second; if(is_hole) vertex_45.count[1] *= - 1; insert_clean(vertex_45, is_hole); } } dirty_ = true; unsorted_ = true; } template <typename output_container> inline void get(output_container& output) const { get_dispatch(output, typename geometry_concept<typename output_container::value_type>::type()); } inline bool has_error_data() const { return !error_data_.empty(); } inline std::size_t error_count() const { return error_data_.size() / 4; } inline void get_error_data(polygon_45_set_data& p) const { p.data_.insert(p.data_.end(), error_data_.begin(), error_data_.end()); } // equivalence operator inline bool operator==(const polygon_45_set_data& p) const { clean(); p.clean(); return data_ == p.data_; } // inequivalence operator inline bool operator!=(const polygon_45_set_data& p) const { return !((*this) == p); } // get iterator to begin vertex data inline iterator_type begin() const { return data_.begin(); } // get iterator to end vertex data inline iterator_type end() const { return data_.end(); } const value_type& value() const { return data_; } // clear the contents of the polygon_45_set_data inline void clear() { data_.clear(); error_data_.clear(); dirty_ = unsorted_ = false; is_manhattan_ = true; } // find out if Polygon set is empty inline bool empty() const { return data_.empty(); } // get the Polygon set size in vertices inline std::size_t size() const { clean(); return data_.size(); } // get the current Polygon set capacity in vertices inline std::size_t capacity() const { return data_.capacity(); } // reserve size of polygon set in vertices inline void reserve(std::size_t size) { return data_.reserve(size); } // find out if Polygon set is sorted inline bool sorted() const { return !unsorted_; } // find out if Polygon set is clean inline bool dirty() const { return dirty_; } // find out if Polygon set is clean inline bool is_manhattan() const { return is_manhattan_; } bool clean() const; void sort() const{ if(unsorted_) { polygon_sort(data_.begin(), data_.end()); unsorted_ = false; } } template <typename input_iterator_type> void set(input_iterator_type input_begin, input_iterator_type input_end) { data_.clear(); reserve(std::distance(input_begin, input_end)); insert(input_begin, input_end); dirty_ = true; unsorted_ = true; } void set_clean(const value_type& value) { data_ = value; dirty_ = false; unsorted_ = false; } void set(const value_type& value) { data_ = value; dirty_ = true; unsorted_ = true; } // append to the container cT with polygons (holes will be fractured vertically) template <class cT> void get_polygons(cT& container) const { get_dispatch(container, polygon_45_concept()); } // append to the container cT with PolygonWithHoles objects template <class cT> void get_polygons_with_holes(cT& container) const { get_dispatch(container, polygon_45_with_holes_concept()); } // append to the container cT with polygons of three or four verticies // slicing orientation is vertical template <class cT> void get_trapezoids(cT& container) const { clean(); typename polygon_45_formation<Unit>::Polygon45Tiling pf; //std::cout << "FORMING POLYGONS\n"; pf.scan(container, data_.begin(), data_.end()); //std::cout << "DONE FORMING POLYGONS\n"; } // append to the container cT with polygons of three or four verticies template <class cT> void get_trapezoids(cT& container, orientation_2d slicing_orientation) const { if(slicing_orientation == VERTICAL) { get_trapezoids(container); } else { polygon_45_set_data<Unit> ps(*this); ps.transform(axis_transformation(axis_transformation::SWAP_XY)); cT result; ps.get_trapezoids(result); for(typename cT::iterator itr = result.begin(); itr != result.end(); ++itr) { ::boost::polygon::transform(*itr, axis_transformation(axis_transformation::SWAP_XY)); } container.insert(container.end(), result.begin(), result.end()); } } // insert vertex sequence template <class iT> void insert_vertex_sequence(iT begin_vertex, iT end_vertex, direction_1d winding, bool is_hole = false); // get the external boundary rectangle template <typename rectangle_type> bool extents(rectangle_type& rect) const; // snap verticies of set to even,even or odd,odd coordinates void snap() const; // |= &= += *= -= ^= binary operators polygon_45_set_data& operator|=(const polygon_45_set_data& b); polygon_45_set_data& operator&=(const polygon_45_set_data& b); polygon_45_set_data& operator+=(const polygon_45_set_data& b); polygon_45_set_data& operator*=(const polygon_45_set_data& b); polygon_45_set_data& operator-=(const polygon_45_set_data& b); polygon_45_set_data& operator^=(const polygon_45_set_data& b); // resizing operations polygon_45_set_data& operator+=(Unit delta); polygon_45_set_data& operator-=(Unit delta); // shrink the Polygon45Set by shrinking polygon_45_set_data& resize(coordinate_type resizing, RoundingOption rounding = CLOSEST, CornerOption corner = INTERSECTION); // transform set template <typename transformation_type> polygon_45_set_data& transform(const transformation_type& tr); // scale set polygon_45_set_data& scale_up(typename coordinate_traits<Unit>::unsigned_area_type factor); polygon_45_set_data& scale_down(typename coordinate_traits<Unit>::unsigned_area_type factor); polygon_45_set_data& scale(double scaling); // self_intersect polygon_45_set_data& self_intersect() { sort(); applyAdaptiveUnary_<1>(); //1 = AND dirty_ = false; return *this; } // self_xor polygon_45_set_data& self_xor() { sort(); applyAdaptiveUnary_<3>(); //3 = XOR dirty_ = false; return *this; } // accumulate the bloated polygon template <typename geometry_type> polygon_45_set_data& insert_with_resize(const geometry_type& poly, coordinate_type resizing, RoundingOption rounding = CLOSEST, CornerOption corner = INTERSECTION, bool hole = false) { return insert_with_resize_dispatch(poly, resizing, rounding, corner, hole, typename geometry_concept<geometry_type>::type()); } private: mutable value_type error_data_; mutable value_type data_; mutable bool dirty_; mutable bool unsorted_; mutable bool is_manhattan_; private: //functions template <typename output_container> void get_dispatch(output_container& output, polygon_45_concept tag) const { get_fracture(output, true, tag); } template <typename output_container> void get_dispatch(output_container& output, polygon_45_with_holes_concept tag) const { get_fracture(output, false, tag); } template <typename output_container> void get_dispatch(output_container& output, polygon_concept tag) const { get_fracture(output, true, tag); } template <typename output_container> void get_dispatch(output_container& output, polygon_with_holes_concept tag) const { get_fracture(output, false, tag); } template <typename output_container, typename concept_type> void get_fracture(output_container& container, bool fracture_holes, concept_type ) const { clean(); typename polygon_45_formation<Unit>::Polygon45Formation pf(fracture_holes); //std::cout << "FORMING POLYGONS\n"; pf.scan(container, data_.begin(), data_.end()); } template <typename geometry_type> void insert_dispatch(const geometry_type& geometry_object, bool is_hole, undefined_concept) { insert(geometry_object.begin(), geometry_object.end(), is_hole); } template <typename geometry_type> void insert_dispatch(const geometry_type& geometry_object, bool is_hole, rectangle_concept tag); template <typename geometry_type> void insert_dispatch(const geometry_type& geometry_object, bool is_hole, polygon_90_concept ) { insert_vertex_sequence(begin_points(geometry_object), end_points(geometry_object), winding(geometry_object), is_hole); } template <typename geometry_type> void insert_dispatch(const geometry_type& geometry_object, bool is_hole, polygon_90_with_holes_concept ) { insert_vertex_sequence(begin_points(geometry_object), end_points(geometry_object), winding(geometry_object), is_hole); for(typename polygon_with_holes_traits<geometry_type>::iterator_holes_type itr = begin_holes(geometry_object); itr != end_holes(geometry_object); ++itr) { insert_vertex_sequence(begin_points(*itr), end_points(*itr), winding(*itr), !is_hole); } } template <typename geometry_type> void insert_dispatch(const geometry_type& geometry_object, bool is_hole, polygon_45_concept ) { insert_vertex_sequence(begin_points(geometry_object), end_points(geometry_object), winding(geometry_object), is_hole); } template <typename geometry_type> void insert_dispatch(const geometry_type& geometry_object, bool is_hole, polygon_45_with_holes_concept ) { insert_vertex_sequence(begin_points(geometry_object), end_points(geometry_object), winding(geometry_object), is_hole); for(typename polygon_with_holes_traits<geometry_type>::iterator_holes_type itr = begin_holes(geometry_object); itr != end_holes(geometry_object); ++itr) { insert_vertex_sequence(begin_points(*itr), end_points(*itr), winding(*itr), !is_hole); } } template <typename geometry_type> void insert_dispatch(const geometry_type& geometry_object, bool is_hole, polygon_45_set_concept ) { polygon_45_set_data ps; assign(ps, geometry_object); insert(ps, is_hole); } template <typename geometry_type> void insert_dispatch(const geometry_type& geometry_object, bool is_hole, polygon_90_set_concept ) { std::list<polygon_90_data<coordinate_type> > pl; assign(pl, geometry_object); insert(pl.begin(), pl.end(), is_hole); } void insert_vertex_half_edge_45_pair(const point_data<Unit>& pt1, point_data<Unit>& pt2, const point_data<Unit>& pt3, direction_1d wdir); template <typename geometry_type> polygon_45_set_data& insert_with_resize_dispatch(const geometry_type& poly, coordinate_type resizing, RoundingOption rounding, CornerOption corner, bool hole, polygon_45_concept tag); // accumulate the bloated polygon with holes template <typename geometry_type> polygon_45_set_data& insert_with_resize_dispatch(const geometry_type& poly, coordinate_type resizing, RoundingOption rounding, CornerOption corner, bool hole, polygon_45_with_holes_concept tag); static void snap_vertex_45(Vertex45Compact& vertex); public: template <int op> void applyAdaptiveBoolean_(const polygon_45_set_data& rvalue) const; template <int op> void applyAdaptiveBoolean_(polygon_45_set_data& result, const polygon_45_set_data& rvalue) const; template <int op> void applyAdaptiveUnary_() const; }; template <typename T> struct geometry_concept<polygon_45_set_data<T> > { typedef polygon_45_set_concept type; }; template <typename iT, typename T> void scale_up_vertex_45_compact_range(iT beginr, iT endr, T factor) { for( ; beginr != endr; ++beginr) { scale_up((*beginr).pt, factor); } } template <typename iT, typename T> void scale_down_vertex_45_compact_range_blindly(iT beginr, iT endr, T factor) { for( ; beginr != endr; ++beginr) { scale_down((*beginr).pt, factor); } } template <typename Unit> inline std::pair<int, int> characterizeEdge45(const point_data<Unit>& pt1, const point_data<Unit>& pt2) { std::pair<int, int> retval(0, 1); if(pt1.x() == pt2.x()) { retval.first = 3; retval.second = -1; return retval; } //retval.second = pt1.x() < pt2.x() ? -1 : 1; retval.second = 1; if(pt1.y() == pt2.y()) { retval.first = 1; } else if(pt1.x() < pt2.x()) { if(pt1.y() < pt2.y()) { retval.first = 2; } else { retval.first = 0; } } else { if(pt1.y() < pt2.y()) { retval.first = 0; } else { retval.first = 2; } } return retval; } template <typename cT, typename pT> bool insert_vertex_half_edge_45_pair_into_vector(cT& output, const pT& pt1, pT& pt2, const pT& pt3, direction_1d wdir) { int multiplier = wdir == LOW ? -1 : 1; typename cT::value_type vertex(pt2, 0, 0); //std::cout << pt1 << " " << pt2 << " " << pt3 << std::endl; std::pair<int, int> check; check = characterizeEdge45(pt1, pt2); //std::cout << "index " << check.first << " " << check.second * -multiplier << std::endl; vertex.count[check.first] += check.second * -multiplier; check = characterizeEdge45(pt2, pt3); //std::cout << "index " << check.first << " " << check.second * multiplier << std::endl; vertex.count[check.first] += check.second * multiplier; output.push_back(vertex); return vertex.count.is_45(); } template <typename Unit> inline void polygon_45_set_data<Unit>::insert_vertex_half_edge_45_pair(const point_data<Unit>& pt1, point_data<Unit>& pt2, const point_data<Unit>& pt3, direction_1d wdir) { if(insert_vertex_half_edge_45_pair_into_vector(data_, pt1, pt2, pt3, wdir)) is_manhattan_ = false; } template <typename Unit> template <class iT> inline void polygon_45_set_data<Unit>::insert_vertex_sequence(iT begin_vertex, iT end_vertex, direction_1d winding, bool is_hole) { if(begin_vertex == end_vertex) return; if(is_hole) winding = winding.backward(); iT itr = begin_vertex; if(itr == end_vertex) return; point_data<Unit> firstPt = *itr; ++itr; point_data<Unit> secondPt(firstPt); //skip any duplicate points do { if(itr == end_vertex) return; secondPt = *itr; ++itr; } while(secondPt == firstPt); point_data<Unit> prevPt = secondPt; point_data<Unit> prevPrevPt = firstPt; while(itr != end_vertex) { point_data<Unit> pt = *itr; //skip any duplicate points if(pt == prevPt) { ++itr; continue; } //operate on the three points insert_vertex_half_edge_45_pair(prevPrevPt, prevPt, pt, winding); prevPrevPt = prevPt; prevPt = pt; ++itr; } if(prevPt != firstPt) { insert_vertex_half_edge_45_pair(prevPrevPt, prevPt, firstPt, winding); insert_vertex_half_edge_45_pair(prevPt, firstPt, secondPt, winding); } else { insert_vertex_half_edge_45_pair(prevPrevPt, firstPt, secondPt, winding); } dirty_ = true; unsorted_ = true; } // insert polygon set template <typename Unit> inline void polygon_45_set_data<Unit>::insert(const polygon_45_set_data<Unit>& polygon_set, bool is_hole) { std::size_t count = data_.size(); data_.insert(data_.end(), polygon_set.data_.begin(), polygon_set.data_.end()); error_data_.insert(error_data_.end(), polygon_set.error_data_.begin(), polygon_set.error_data_.end()); if(is_hole) { for(std::size_t i = count; i < data_.size(); ++i) { data_[i].count = data_[i].count.invert(); } } dirty_ = true; unsorted_ = true; if(polygon_set.is_manhattan_ == false) is_manhattan_ = false; return; } // insert polygon set template <typename Unit> template <typename coord_type> inline void polygon_45_set_data<Unit>::insert(const polygon_45_set_data<coord_type>& polygon_set, bool is_hole) { std::size_t count = data_.size(); for(typename polygon_45_set_data<coord_type>::iterator_type itr = polygon_set.begin(); itr != polygon_set.end(); ++itr) { const typename polygon_45_set_data<coord_type>::Vertex45Compact& v = *itr; typename polygon_45_set_data<Unit>::Vertex45Compact v2; v2.pt.x(static_cast<Unit>(v.pt.x())); v2.pt.y(static_cast<Unit>(v.pt.y())); v2.count = typename polygon_45_formation<Unit>::Vertex45Count(v.count[0], v.count[1], v.count[2], v.count[3]); data_.push_back(v2); } polygon_45_set_data<coord_type> tmp; polygon_set.get_error_data(tmp); for(typename polygon_45_set_data<coord_type>::iterator_type itr = tmp.begin(); itr != tmp.end(); ++itr) { const typename polygon_45_set_data<coord_type>::Vertex45Compact& v = *itr; typename polygon_45_set_data<Unit>::Vertex45Compact v2; v2.pt.x(static_cast<Unit>(v.pt.x())); v2.pt.y(static_cast<Unit>(v.pt.y())); v2.count = typename polygon_45_formation<Unit>::Vertex45Count(v.count[0], v.count[1], v.count[2], v.count[3]); error_data_.push_back(v2); } if(is_hole) { for(std::size_t i = count; i < data_.size(); ++i) { data_[i].count = data_[i].count.invert(); } } dirty_ = true; unsorted_ = true; if(polygon_set.is_manhattan() == false) is_manhattan_ = false; return; } template <typename cT, typename rT> void insert_rectangle_into_vector_45(cT& output, const rT& rect, bool is_hole) { point_data<typename rectangle_traits<rT>::coordinate_type> llpt = ll(rect), lrpt = lr(rect), ulpt = ul(rect), urpt = ur(rect); direction_1d dir = COUNTERCLOCKWISE; if(is_hole) dir = CLOCKWISE; insert_vertex_half_edge_45_pair_into_vector(output, llpt, lrpt, urpt, dir); insert_vertex_half_edge_45_pair_into_vector(output, lrpt, urpt, ulpt, dir); insert_vertex_half_edge_45_pair_into_vector(output, urpt, ulpt, llpt, dir); insert_vertex_half_edge_45_pair_into_vector(output, ulpt, llpt, lrpt, dir); } template <typename Unit> template <typename geometry_type> inline void polygon_45_set_data<Unit>::insert_dispatch(const geometry_type& geometry_object, bool is_hole, rectangle_concept ) { dirty_ = true; unsorted_ = true; insert_rectangle_into_vector_45(data_, geometry_object, is_hole); } // get the external boundary rectangle template <typename Unit> template <typename rectangle_type> inline bool polygon_45_set_data<Unit>::extents(rectangle_type& rect) const{ clean(); if(empty()) { return false; } Unit low = (std::numeric_limits<Unit>::max)(); Unit high = (std::numeric_limits<Unit>::min)(); interval_data<Unit> xivl(low, high); interval_data<Unit> yivl(low, high); for(typename value_type::const_iterator itr = data_.begin(); itr != data_.end(); ++ itr) { if((*itr).pt.x() > xivl.get(HIGH)) xivl.set(HIGH, (*itr).pt.x()); if((*itr).pt.x() < xivl.get(LOW)) xivl.set(LOW, (*itr).pt.x()); if((*itr).pt.y() > yivl.get(HIGH)) yivl.set(HIGH, (*itr).pt.y()); if((*itr).pt.y() < yivl.get(LOW)) yivl.set(LOW, (*itr).pt.y()); } rect = construct<rectangle_type>(xivl, yivl); return true; } //this function snaps the vertex and two half edges //to be both even or both odd coordinate values if one of the edges is 45 //and throws an excpetion if an edge is non-manhattan, non-45. template <typename Unit> inline void polygon_45_set_data<Unit>::snap_vertex_45(typename polygon_45_set_data<Unit>::Vertex45Compact& vertex) { bool plus45 = vertex.count[2] != 0; bool minus45 = vertex.count[0] != 0; if(plus45 || minus45) { if(local_abs(vertex.pt.x()) % 2 != local_abs(vertex.pt.y()) % 2) { if(vertex.count[1] != 0 || (plus45 && minus45)) { //move right vertex.pt.x(vertex.pt.x() + 1); } else { //assert that vertex.count[3] != 0 Unit modifier = plus45 ? -1 : 1; vertex.pt.y(vertex.pt.y() + modifier); } } } } template <typename Unit> inline void polygon_45_set_data<Unit>::snap() const { for(typename value_type::iterator itr = data_.begin(); itr != data_.end(); ++itr) { snap_vertex_45(*itr); } } // |= &= += *= -= ^= binary operators template <typename Unit> inline polygon_45_set_data<Unit>& polygon_45_set_data<Unit>::operator|=(const polygon_45_set_data<Unit>& b) { insert(b); return *this; } template <typename Unit> inline polygon_45_set_data<Unit>& polygon_45_set_data<Unit>::operator&=(const polygon_45_set_data<Unit>& b) { //b.sort(); //sort(); applyAdaptiveBoolean_<1>(b); dirty_ = false; unsorted_ = false; return *this; } template <typename Unit> inline polygon_45_set_data<Unit>& polygon_45_set_data<Unit>::operator+=(const polygon_45_set_data<Unit>& b) { return (*this) |= b; } template <typename Unit> inline polygon_45_set_data<Unit>& polygon_45_set_data<Unit>::operator*=(const polygon_45_set_data<Unit>& b) { return (*this) &= b; } template <typename Unit> inline polygon_45_set_data<Unit>& polygon_45_set_data<Unit>::operator-=(const polygon_45_set_data<Unit>& b) { //b.sort(); //sort(); applyAdaptiveBoolean_<2>(b); dirty_ = false; unsorted_ = false; return *this; } template <typename Unit> inline polygon_45_set_data<Unit>& polygon_45_set_data<Unit>::operator^=(const polygon_45_set_data<Unit>& b) { //b.sort(); //sort(); applyAdaptiveBoolean_<3>(b); dirty_ = false; unsorted_ = false; return *this; } template <typename Unit> inline polygon_45_set_data<Unit>& polygon_45_set_data<Unit>::operator+=(Unit delta) { return resize(delta); } template <typename Unit> inline polygon_45_set_data<Unit>& polygon_45_set_data<Unit>::operator-=(Unit delta) { return (*this) += -delta; } template <typename Unit> inline polygon_45_set_data<Unit>& polygon_45_set_data<Unit>::resize(Unit resizing, RoundingOption rounding, CornerOption corner) { if(resizing == 0) return *this; std::list<polygon_45_with_holes_data<Unit> > pl; get_polygons_with_holes(pl); clear(); for(typename std::list<polygon_45_with_holes_data<Unit> >::iterator itr = pl.begin(); itr != pl.end(); ++itr) { insert_with_resize(*itr, resizing, rounding, corner); } clean(); //perterb 45 edges to prevent non-integer intersection errors upon boolean op //snap(); return *this; } //distance is assumed to be positive inline int roundClosest(double distance) { int f = (int)distance; if(distance - (double)f < 0.5) return f; return f+1; } //distance is assumed to be positive template <typename Unit> inline Unit roundWithOptions(double distance, RoundingOption rounding) { if(rounding == CLOSEST) { return roundClosest(distance); } else if(rounding == OVERSIZE) { return (Unit)distance + 1; } else { //UNDERSIZE return (Unit)distance; } } // 0 is east, 1 is northeast, 2 is north, 3 is northwest, 4 is west, 5 is southwest, 6 is south // 7 is southwest template <typename Unit> inline point_data<Unit> bloatVertexInDirWithOptions(const point_data<Unit>& point, unsigned int dir, Unit bloating, RoundingOption rounding) { const double sqrt2 = 1.4142135623730950488016887242097; if(dir & 1) { Unit unitDistance = (Unit)bloating; if(rounding != SQRT2) { //45 degree bloating double distance = (double)bloating; distance /= sqrt2; // multiply by 1/sqrt2 unitDistance = roundWithOptions<Unit>(distance, rounding); } int xMultiplier = 1; int yMultiplier = 1; if(dir == 3 || dir == 5) xMultiplier = -1; if(dir == 5 || dir == 7) yMultiplier = -1; return point_data<Unit>(point.x()+xMultiplier*unitDistance, point.y()+yMultiplier*unitDistance); } else { if(dir == 0) return point_data<Unit>(point.x()+bloating, point.y()); if(dir == 2) return point_data<Unit>(point.x(), point.y()+bloating); if(dir == 4) return point_data<Unit>(point.x()-bloating, point.y()); if(dir == 6) return point_data<Unit>(point.x(), point.y()-bloating); return point_data<Unit>(); } } template <typename Unit> inline unsigned int getEdge45Direction(const point_data<Unit>& pt1, const point_data<Unit>& pt2) { if(pt1.x() == pt2.x()) { if(pt1.y() < pt2.y()) return 2; return 6; } if(pt1.y() == pt2.y()) { if(pt1.x() < pt2.x()) return 0; return 4; } if(pt2.y() > pt1.y()) { if(pt2.x() > pt1.x()) return 1; return 3; } if(pt2.x() > pt1.x()) return 7; return 5; } inline unsigned int getEdge45NormalDirection(unsigned int dir, int multiplier) { if(multiplier < 0) return (dir + 2) % 8; return (dir + 4 + 2) % 8; } template <typename Unit> inline point_data<Unit> getIntersectionPoint(const point_data<Unit>& pt1, unsigned int slope1, const point_data<Unit>& pt2, unsigned int slope2) { //the intention here is to use all integer arithmetic without causing overflow //turncation error or divide by zero error //I don't use floating point arithmetic because its precision may not be high enough //at the extremes of the integer range typedef typename coordinate_traits<Unit>::area_type LongUnit; const Unit rises[8] = {0, 1, 1, 1, 0, -1, -1, -1}; const Unit runs[8] = {1, 1, 0, -1, -1, -1, 0, 1}; LongUnit rise1 = rises[slope1]; LongUnit rise2 = rises[slope2]; LongUnit run1 = runs[slope1]; LongUnit run2 = runs[slope2]; LongUnit x1 = (LongUnit)pt1.x(); LongUnit x2 = (LongUnit)pt2.x(); LongUnit y1 = (LongUnit)pt1.y(); LongUnit y2 = (LongUnit)pt2.y(); Unit x = 0; Unit y = 0; if(run1 == 0) { x = pt1.x(); y = (Unit)(((x1 - x2) * rise2) / run2) + pt2.y(); } else if(run2 == 0) { x = pt2.x(); y = (Unit)(((x2 - x1) * rise1) / run1) + pt1.y(); } else { // y - y1 = (rise1/run1)(x - x1) // y - y2 = (rise2/run2)(x - x2) // y = (rise1/run1)(x - x1) + y1 = (rise2/run2)(x - x2) + y2 // (rise1/run1 - rise2/run2)x = y2 - y1 + rise1/run1 x1 - rise2/run2 x2 // x = (y2 - y1 + rise1/run1 x1 - rise2/run2 x2)/(rise1/run1 - rise2/run2) // x = (y2 - y1 + rise1/run1 x1 - rise2/run2 x2)(rise1 run2 - rise2 run1)/(run1 run2) x = (Unit)((y2 - y1 + ((rise1 * x1) / run1) - ((rise2 * x2) / run2)) * (run1 * run2) / (rise1 * run2 - rise2 * run1)); if(rise1 == 0) { y = pt1.y(); } else if(rise2 == 0) { y = pt2.y(); } else { // y - y1 = (rise1/run1)(x - x1) // (run1/rise1)(y - y1) = x - x1 // x = (run1/rise1)(y - y1) + x1 = (run2/rise2)(y - y2) + x2 y = (Unit)((x2 - x1 + ((run1 * y1) / rise1) - ((run2 * y2) / rise2)) * (rise1 * rise2) / (run1 * rise2 - run2 * rise1)); } } return point_data<Unit>(x, y); } template <typename Unit> inline void handleResizingEdge45_SQRT1OVER2(polygon_45_set_data<Unit>& sizingSet, point_data<Unit> first, point_data<Unit> second, Unit resizing, CornerOption corner) { if(first.x() == second.x()) { sizingSet.insert(rectangle_data<Unit>(first.x() - resizing, first.y(), first.x() + resizing, second.y())); return; } if(first.y() == second.y()) { sizingSet.insert(rectangle_data<Unit>(first.x(), first.y() - resizing, second.x(), first.y() + resizing)); return; } std::vector<point_data<Unit> > pts; Unit bloating = resizing < 0 ? -resizing : resizing; if(corner == UNFILLED) { //we have to round up bloating = bloating / 2 + bloating % 2 ; //round up if(second.x() < first.x()) std::swap(first, second); if(first.y() < second.y()) { //upward sloping pts.push_back(point_data<Unit>(first.x() + bloating, first.y() - bloating)); pts.push_back(point_data<Unit>(first.x() - bloating, first.y() + bloating)); pts.push_back(point_data<Unit>(second.x() - bloating, second.y() + bloating)); pts.push_back(point_data<Unit>(second.x() + bloating, second.y() - bloating)); sizingSet.insert_vertex_sequence(pts.begin(), pts.end(), CLOCKWISE, false); } else { //downward sloping pts.push_back(point_data<Unit>(first.x() + bloating, first.y() + bloating)); pts.push_back(point_data<Unit>(first.x() - bloating, first.y() - bloating)); pts.push_back(point_data<Unit>(second.x() - bloating, second.y() - bloating)); pts.push_back(point_data<Unit>(second.x() + bloating, second.y() + bloating)); sizingSet.insert_vertex_sequence(pts.begin(), pts.end(), COUNTERCLOCKWISE, false); } return; } if(second.x() < first.x()) std::swap(first, second); if(first.y() < second.y()) { //upward sloping pts.push_back(point_data<Unit>(first.x(), first.y() - bloating)); pts.push_back(point_data<Unit>(first.x() - bloating, first.y())); pts.push_back(point_data<Unit>(second.x(), second.y() + bloating)); pts.push_back(point_data<Unit>(second.x() + bloating, second.y())); sizingSet.insert_vertex_sequence(pts.begin(), pts.end(), CLOCKWISE, false); } else { //downward sloping pts.push_back(point_data<Unit>(first.x() - bloating, first.y())); pts.push_back(point_data<Unit>(first.x(), first.y() + bloating)); pts.push_back(point_data<Unit>(second.x() + bloating, second.y())); pts.push_back(point_data<Unit>(second.x(), second.y() - bloating)); sizingSet.insert_vertex_sequence(pts.begin(), pts.end(), CLOCKWISE, false); } } template <typename Unit> inline void handleResizingEdge45(polygon_45_set_data<Unit>& sizingSet, point_data<Unit> first, point_data<Unit> second, Unit resizing, RoundingOption rounding) { if(first.x() == second.x()) { sizingSet.insert(rectangle_data<int>(first.x() - resizing, first.y(), first.x() + resizing, second.y())); return; } if(first.y() == second.y()) { sizingSet.insert(rectangle_data<int>(first.x(), first.y() - resizing, second.x(), first.y() + resizing)); return; } //edge is 45 std::vector<point_data<Unit> > pts; Unit bloating = resizing < 0 ? -resizing : resizing; if(second.x() < first.x()) std::swap(first, second); if(first.y() < second.y()) { pts.push_back(bloatVertexInDirWithOptions(first, 3, bloating, rounding)); pts.push_back(bloatVertexInDirWithOptions(first, 7, bloating, rounding)); pts.push_back(bloatVertexInDirWithOptions(second, 7, bloating, rounding)); pts.push_back(bloatVertexInDirWithOptions(second, 3, bloating, rounding)); sizingSet.insert_vertex_sequence(pts.begin(), pts.end(), HIGH, false); } else { pts.push_back(bloatVertexInDirWithOptions(first, 1, bloating, rounding)); pts.push_back(bloatVertexInDirWithOptions(first, 5, bloating, rounding)); pts.push_back(bloatVertexInDirWithOptions(second, 5, bloating, rounding)); pts.push_back(bloatVertexInDirWithOptions(second, 1, bloating, rounding)); sizingSet.insert_vertex_sequence(pts.begin(), pts.end(), HIGH, false); } } template <typename Unit> inline point_data<Unit> bloatVertexInDirWithSQRT1OVER2(int edge1, int normal1, const point_data<Unit>& second, Unit bloating, bool first) { orientation_2d orient = first ? HORIZONTAL : VERTICAL; orientation_2d orientp = orient.get_perpendicular(); int multiplier = first ? 1 : -1; point_data<Unit> pt1(second); if(edge1 == 1) { if(normal1 == 3) { move(pt1, orient, -multiplier * bloating); } else { move(pt1, orientp, -multiplier * bloating); } } else if(edge1 == 3) { if(normal1 == 1) { move(pt1, orient, multiplier * bloating); } else { move(pt1, orientp, -multiplier * bloating); } } else if(edge1 == 5) { if(normal1 == 3) { move(pt1, orientp, multiplier * bloating); } else { move(pt1, orient, multiplier * bloating); } } else { if(normal1 == 5) { move(pt1, orient, -multiplier * bloating); } else { move(pt1, orientp, multiplier * bloating); } } return pt1; } template <typename Unit> inline void handleResizingVertex45(polygon_45_set_data<Unit>& sizingSet, const point_data<Unit>& first, const point_data<Unit>& second, const point_data<Unit>& third, Unit resizing, RoundingOption rounding, CornerOption corner, int multiplier) { unsigned int edge1 = getEdge45Direction(first, second); unsigned int edge2 = getEdge45Direction(second, third); unsigned int diffAngle; if(multiplier < 0) diffAngle = (edge2 + 8 - edge1) % 8; else diffAngle = (edge1 + 8 - edge2) % 8; if(diffAngle < 4) { if(resizing > 0) return; //accute interior corner else multiplier *= -1; //make it appear to be an accute exterior angle } Unit bloating = local_abs(resizing); if(rounding == SQRT1OVER2) { if(edge1 % 2 && edge2 % 2) return; if(corner == ORTHOGONAL && edge1 % 2 == 0 && edge2 % 2 == 0) { rectangle_data<Unit> insertion_rect; set_points(insertion_rect, second, second); bloat(insertion_rect, bloating); sizingSet.insert(insertion_rect); } else if(corner != ORTHOGONAL) { point_data<Unit> pt1(0, 0); point_data<Unit> pt2(0, 0); unsigned int normal1 = getEdge45NormalDirection(edge1, multiplier); unsigned int normal2 = getEdge45NormalDirection(edge2, multiplier); if(edge1 % 2) { pt1 = bloatVertexInDirWithSQRT1OVER2(edge1, normal1, second, bloating, true); } else { pt1 = bloatVertexInDirWithOptions(second, normal1, bloating, UNDERSIZE); } if(edge2 % 2) { pt2 = bloatVertexInDirWithSQRT1OVER2(edge2, normal2, second, bloating, false); } else { pt2 = bloatVertexInDirWithOptions(second, normal2, bloating, UNDERSIZE); } std::vector<point_data<Unit> > pts; pts.push_back(pt1); pts.push_back(second); pts.push_back(pt2); pts.push_back(getIntersectionPoint(pt1, edge1, pt2, edge2)); polygon_45_data<Unit> poly(pts.begin(), pts.end()); sizingSet.insert(poly); } else { //ORTHOGONAL of a 45 degree corner int normal = 0; if(edge1 % 2) { normal = getEdge45NormalDirection(edge2, multiplier); } else { normal = getEdge45NormalDirection(edge1, multiplier); } rectangle_data<Unit> insertion_rect; point_data<Unit> edgePoint = bloatVertexInDirWithOptions(second, normal, bloating, UNDERSIZE); set_points(insertion_rect, second, edgePoint); if(normal == 0 || normal == 4) bloat(insertion_rect, VERTICAL, bloating); else bloat(insertion_rect, HORIZONTAL, bloating); sizingSet.insert(insertion_rect); } return; } unsigned int normal1 = getEdge45NormalDirection(edge1, multiplier); unsigned int normal2 = getEdge45NormalDirection(edge2, multiplier); point_data<Unit> edgePoint1 = bloatVertexInDirWithOptions(second, normal1, bloating, rounding); point_data<Unit> edgePoint2 = bloatVertexInDirWithOptions(second, normal2, bloating, rounding); //if the change in angle is 135 degrees it is an accute exterior corner if((edge1+ multiplier * 3) % 8 == edge2) { if(corner == ORTHOGONAL) { rectangle_data<Unit> insertion_rect; set_points(insertion_rect, edgePoint1, edgePoint2); sizingSet.insert(insertion_rect); return; } } std::vector<point_data<Unit> > pts; pts.push_back(edgePoint1); pts.push_back(second); pts.push_back(edgePoint2); pts.push_back(getIntersectionPoint(edgePoint1, edge1, edgePoint2, edge2)); polygon_45_data<Unit> poly(pts.begin(), pts.end()); sizingSet.insert(poly); } template <typename Unit> template <typename geometry_type> inline polygon_45_set_data<Unit>& polygon_45_set_data<Unit>::insert_with_resize_dispatch(const geometry_type& poly, coordinate_type resizing, RoundingOption rounding, CornerOption corner, bool hole, polygon_45_concept ) { direction_1d wdir = winding(poly); int multiplier = wdir == LOW ? -1 : 1; if(hole) resizing *= -1; typedef typename polygon_45_data<Unit>::iterator_type piterator; piterator first, second, third, end, real_end; real_end = end_points(poly); third = begin_points(poly); first = third; if(first == real_end) return *this; ++third; if(third == real_end) return *this; second = end = third; ++third; if(third == real_end) return *this; polygon_45_set_data<Unit> sizingSet; //insert minkofski shapes on edges and corners do { if(rounding != SQRT1OVER2) { handleResizingEdge45(sizingSet, *first, *second, resizing, rounding); } else { handleResizingEdge45_SQRT1OVER2(sizingSet, *first, *second, resizing, corner); } if(corner != UNFILLED) handleResizingVertex45(sizingSet, *first, *second, *third, resizing, rounding, corner, multiplier); first = second; second = third; ++third; if(third == real_end) { third = begin_points(poly); if(*second == *third) { ++third; //skip first point if it is duplicate of last point } } } while(second != end); //sizingSet.snap(); polygon_45_set_data<Unit> tmp; //insert original shape tmp.insert_dispatch(poly, false, polygon_45_concept()); if(resizing < 0) tmp -= sizingSet; else tmp += sizingSet; tmp.clean(); insert(tmp, hole); dirty_ = true; unsorted_ = true; return (*this); } // accumulate the bloated polygon with holes template <typename Unit> template <typename geometry_type> inline polygon_45_set_data<Unit>& polygon_45_set_data<Unit>::insert_with_resize_dispatch(const geometry_type& poly, coordinate_type resizing, RoundingOption rounding, CornerOption corner, bool hole, polygon_45_with_holes_concept ) { insert_with_resize_dispatch(poly, resizing, rounding, corner, hole, polygon_45_concept()); for(typename polygon_with_holes_traits<geometry_type>::iterator_holes_type itr = begin_holes(poly); itr != end_holes(poly); ++itr) { insert_with_resize_dispatch(*itr, resizing, rounding, corner, !hole, polygon_45_concept()); } return *this; } // transform set template <typename Unit> template <typename transformation_type> inline polygon_45_set_data<Unit>& polygon_45_set_data<Unit>::transform(const transformation_type& tr){ clean(); std::vector<polygon_45_with_holes_data<Unit> > polys; get(polys); for(typename std::vector<polygon_45_with_holes_data<Unit> >::iterator itr = polys.begin(); itr != polys.end(); ++itr) { ::boost::polygon::transform(*itr, tr); } clear(); insert(polys.begin(), polys.end()); dirty_ = true; unsorted_ = true; return *this; } template <typename Unit> inline polygon_45_set_data<Unit>& polygon_45_set_data<Unit>::scale_up(typename coordinate_traits<Unit>::unsigned_area_type factor) { scale_up_vertex_45_compact_range(data_.begin(), data_.end(), factor); return *this; } template <typename Unit> inline polygon_45_set_data<Unit>& polygon_45_set_data<Unit>::scale_down(typename coordinate_traits<Unit>::unsigned_area_type factor) { clean(); std::vector<polygon_45_with_holes_data<Unit> > polys; get_polygons_with_holes(polys); for(typename std::vector<polygon_45_with_holes_data<Unit> >::iterator itr = polys.begin(); itr != polys.end(); ++itr) { ::boost::polygon::scale_down(*itr, factor); } clear(); insert(polys.begin(), polys.end()); dirty_ = true; unsorted_ = true; return *this; } template <typename Unit> inline polygon_45_set_data<Unit>& polygon_45_set_data<Unit>::scale(double factor) { clean(); std::vector<polygon_45_with_holes_data<Unit> > polys; get_polygons_with_holes(polys); for(typename std::vector<polygon_45_with_holes_data<Unit> >::iterator itr = polys.begin(); itr != polys.end(); ++itr) { ::boost::polygon::scale(*itr, factor); } clear(); insert(polys.begin(), polys.end()); dirty_ = true; unsorted_ = true; return *this; } template <typename Unit> inline bool polygon_45_set_data<Unit>::clean() const { if(unsorted_) sort(); if(dirty_) { applyAdaptiveUnary_<0>(); dirty_ = false; } return true; } template <typename Unit> template <int op> inline void polygon_45_set_data<Unit>::applyAdaptiveBoolean_(const polygon_45_set_data<Unit>& rvalue) const { polygon_45_set_data<Unit> tmp; applyAdaptiveBoolean_<op>(tmp, rvalue); data_.swap(tmp.data_); //swapping vectors should be constant time operation error_data_.swap(tmp.error_data_); is_manhattan_ = tmp.is_manhattan_; unsorted_ = false; dirty_ = false; } template <typename Unit2, int op> bool applyBoolean45OpOnVectors(std::vector<typename polygon_45_formation<Unit2>::Vertex45Compact>& result_data, std::vector<typename polygon_45_formation<Unit2>::Vertex45Compact>& lvalue_data, std::vector<typename polygon_45_formation<Unit2>::Vertex45Compact>& rvalue_data ) { bool result_is_manhattan_ = true; typename boolean_op_45<Unit2>::template Scan45<typename boolean_op_45<Unit2>::Count2, typename boolean_op_45<Unit2>::template boolean_op_45_output_functor<op> > scan45; std::vector<typename boolean_op_45<Unit2>::Vertex45> eventOut; typedef std::pair<typename boolean_op_45<Unit2>::Point, typename boolean_op_45<Unit2>::template Scan45CountT<typename boolean_op_45<Unit2>::Count2> > Scan45Vertex; std::vector<Scan45Vertex> eventIn; typedef std::vector<typename polygon_45_formation<Unit2>::Vertex45Compact> value_type; typename value_type::const_iterator iter1 = lvalue_data.begin(); typename value_type::const_iterator iter2 = rvalue_data.begin(); typename value_type::const_iterator end1 = lvalue_data.end(); typename value_type::const_iterator end2 = rvalue_data.end(); const Unit2 UnitMax = (std::numeric_limits<Unit2>::max)(); Unit2 x = UnitMax; while(iter1 != end1 || iter2 != end2) { Unit2 currentX = UnitMax; if(iter1 != end1) currentX = iter1->pt.x(); if(iter2 != end2) currentX = (std::min)(currentX, iter2->pt.x()); if(currentX != x) { //std::cout << "SCAN " << currentX << "\n"; //scan event scan45.scan(eventOut, eventIn.begin(), eventIn.end()); polygon_sort(eventOut.begin(), eventOut.end()); std::size_t ptCount = 0; for(std::size_t i = 0; i < eventOut.size(); ++i) { if(!result_data.empty() && result_data.back().pt == eventOut[i].pt) { result_data.back().count += eventOut[i]; ++ptCount; } else { if(!result_data.empty()) { if(result_data.back().count.is_45()) { result_is_manhattan_ = false; } if(ptCount == 2 && result_data.back().count == (typename polygon_45_formation<Unit2>::Vertex45Count(0, 0, 0, 0))) { result_data.pop_back(); } } result_data.push_back(eventOut[i]); ptCount = 1; } } if(ptCount == 2 && result_data.back().count == (typename polygon_45_formation<Unit2>::Vertex45Count(0, 0, 0, 0))) { result_data.pop_back(); } eventOut.clear(); eventIn.clear(); x = currentX; } //std::cout << "get next\n"; if(iter2 != end2 && (iter1 == end1 || iter2->pt.x() < iter1->pt.x() || (iter2->pt.x() == iter1->pt.x() && iter2->pt.y() < iter1->pt.y()) )) { //std::cout << "case1 next\n"; eventIn.push_back(Scan45Vertex (iter2->pt, typename polygon_45_formation<Unit2>:: Scan45Count(typename polygon_45_formation<Unit2>::Count2(0, iter2->count[0]), typename polygon_45_formation<Unit2>::Count2(0, iter2->count[1]), typename polygon_45_formation<Unit2>::Count2(0, iter2->count[2]), typename polygon_45_formation<Unit2>::Count2(0, iter2->count[3])))); ++iter2; } else if(iter1 != end1 && (iter2 == end2 || iter1->pt.x() < iter2->pt.x() || (iter1->pt.x() == iter2->pt.x() && iter1->pt.y() < iter2->pt.y()) )) { //std::cout << "case2 next\n"; eventIn.push_back(Scan45Vertex (iter1->pt, typename polygon_45_formation<Unit2>:: Scan45Count( typename polygon_45_formation<Unit2>::Count2(iter1->count[0], 0), typename polygon_45_formation<Unit2>::Count2(iter1->count[1], 0), typename polygon_45_formation<Unit2>::Count2(iter1->count[2], 0), typename polygon_45_formation<Unit2>::Count2(iter1->count[3], 0)))); ++iter1; } else { //std::cout << "case3 next\n"; eventIn.push_back(Scan45Vertex (iter2->pt, typename polygon_45_formation<Unit2>:: Scan45Count(typename polygon_45_formation<Unit2>::Count2(iter1->count[0], iter2->count[0]), typename polygon_45_formation<Unit2>::Count2(iter1->count[1], iter2->count[1]), typename polygon_45_formation<Unit2>::Count2(iter1->count[2], iter2->count[2]), typename polygon_45_formation<Unit2>::Count2(iter1->count[3], iter2->count[3])))); ++iter1; ++iter2; } } scan45.scan(eventOut, eventIn.begin(), eventIn.end()); polygon_sort(eventOut.begin(), eventOut.end()); std::size_t ptCount = 0; for(std::size_t i = 0; i < eventOut.size(); ++i) { if(!result_data.empty() && result_data.back().pt == eventOut[i].pt) { result_data.back().count += eventOut[i]; ++ptCount; } else { if(!result_data.empty()) { if(result_data.back().count.is_45()) { result_is_manhattan_ = false; } if(ptCount == 2 && result_data.back().count == (typename polygon_45_formation<Unit2>::Vertex45Count(0, 0, 0, 0))) { result_data.pop_back(); } } result_data.push_back(eventOut[i]); ptCount = 1; } } if(ptCount == 2 && result_data.back().count == (typename polygon_45_formation<Unit2>::Vertex45Count(0, 0, 0, 0))) { result_data.pop_back(); } if(!result_data.empty() && result_data.back().count.is_45()) { result_is_manhattan_ = false; } return result_is_manhattan_; } template <typename Unit2, int op> bool applyUnary45OpOnVectors(std::vector<typename polygon_45_formation<Unit2>::Vertex45Compact>& result_data, std::vector<typename polygon_45_formation<Unit2>::Vertex45Compact>& lvalue_data ) { bool result_is_manhattan_ = true; typename boolean_op_45<Unit2>::template Scan45<typename boolean_op_45<Unit2>::Count1, typename boolean_op_45<Unit2>::template unary_op_45_output_functor<op> > scan45; std::vector<typename boolean_op_45<Unit2>::Vertex45> eventOut; typedef typename boolean_op_45<Unit2>::template Scan45CountT<typename boolean_op_45<Unit2>::Count1> Scan45Count; typedef std::pair<typename boolean_op_45<Unit2>::Point, Scan45Count> Scan45Vertex; std::vector<Scan45Vertex> eventIn; typedef std::vector<typename polygon_45_formation<Unit2>::Vertex45Compact> value_type; typename value_type::const_iterator iter1 = lvalue_data.begin(); typename value_type::const_iterator end1 = lvalue_data.end(); const Unit2 UnitMax = (std::numeric_limits<Unit2>::max)(); Unit2 x = UnitMax; while(iter1 != end1) { Unit2 currentX = iter1->pt.x(); if(currentX != x) { //std::cout << "SCAN " << currentX << "\n"; //scan event scan45.scan(eventOut, eventIn.begin(), eventIn.end()); polygon_sort(eventOut.begin(), eventOut.end()); std::size_t ptCount = 0; for(std::size_t i = 0; i < eventOut.size(); ++i) { if(!result_data.empty() && result_data.back().pt == eventOut[i].pt) { result_data.back().count += eventOut[i]; ++ptCount; } else { if(!result_data.empty()) { if(result_data.back().count.is_45()) { result_is_manhattan_ = false; } if(ptCount == 2 && result_data.back().count == (typename polygon_45_formation<Unit2>::Vertex45Count(0, 0, 0, 0))) { result_data.pop_back(); } } result_data.push_back(eventOut[i]); ptCount = 1; } } if(ptCount == 2 && result_data.back().count == (typename polygon_45_formation<Unit2>::Vertex45Count(0, 0, 0, 0))) { result_data.pop_back(); } eventOut.clear(); eventIn.clear(); x = currentX; } //std::cout << "get next\n"; eventIn.push_back(Scan45Vertex (iter1->pt, Scan45Count( typename boolean_op_45<Unit2>::Count1(iter1->count[0]), typename boolean_op_45<Unit2>::Count1(iter1->count[1]), typename boolean_op_45<Unit2>::Count1(iter1->count[2]), typename boolean_op_45<Unit2>::Count1(iter1->count[3])))); ++iter1; } scan45.scan(eventOut, eventIn.begin(), eventIn.end()); polygon_sort(eventOut.begin(), eventOut.end()); std::size_t ptCount = 0; for(std::size_t i = 0; i < eventOut.size(); ++i) { if(!result_data.empty() && result_data.back().pt == eventOut[i].pt) { result_data.back().count += eventOut[i]; ++ptCount; } else { if(!result_data.empty()) { if(result_data.back().count.is_45()) { result_is_manhattan_ = false; } if(ptCount == 2 && result_data.back().count == (typename polygon_45_formation<Unit2>::Vertex45Count(0, 0, 0, 0))) { result_data.pop_back(); } } result_data.push_back(eventOut[i]); ptCount = 1; } } if(ptCount == 2 && result_data.back().count == (typename polygon_45_formation<Unit2>::Vertex45Count(0, 0, 0, 0))) { result_data.pop_back(); } if(!result_data.empty() && result_data.back().count.is_45()) { result_is_manhattan_ = false; } return result_is_manhattan_; } template <typename cT, typename iT> void get_error_rects_shell(cT& posE, cT& negE, iT beginr, iT endr) { typedef typename std::iterator_traits<iT>::value_type Point; typedef typename point_traits<Point>::coordinate_type Unit; typedef typename coordinate_traits<Unit>::area_type area_type; Point pt1, pt2, pt3; bool i1 = true; bool i2 = true; bool not_done = beginr != endr; bool next_to_last = false; bool last = false; Point first, second; while(not_done) { if(last) { last = false; not_done = false; pt3 = second; } else if(next_to_last) { next_to_last = false; last = true; pt3 = first; } else if(i1) { const Point& pt = *beginr; first = pt1 = pt; i1 = false; i2 = true; ++beginr; if(beginr == endr) return; //too few points continue; } else if (i2) { const Point& pt = *beginr; second = pt2 = pt; i2 = false; ++beginr; if(beginr == endr) return; //too few points continue; } else { const Point& pt = *beginr; pt3 = pt; ++beginr; if(beginr == endr) { next_to_last = true; //skip last point equal to first continue; } } if(local_abs(x(pt2)) % 2) { //y % 2 should also be odd //is corner concave or convex? Point pts[] = {pt1, pt2, pt3}; area_type ar = point_sequence_area<Point*, area_type>(pts, pts+3); direction_1d dir = ar < 0 ? COUNTERCLOCKWISE : CLOCKWISE; //std::cout << pt1 << " " << pt2 << " " << pt3 << " " << ar << std::endl; if(dir == CLOCKWISE) { posE.push_back(rectangle_data<typename Point::coordinate_type> (x(pt2) - 1, y(pt2) - 1, x(pt2) + 1, y(pt2) + 1)); } else { negE.push_back(rectangle_data<typename Point::coordinate_type> (x(pt2) - 1, y(pt2) - 1, x(pt2) + 1, y(pt2) + 1)); } } pt1 = pt2; pt2 = pt3; } } template <typename cT, typename pT> void get_error_rects(cT& posE, cT& negE, const pT& p) { get_error_rects_shell(posE, negE, p.begin(), p.end()); for(typename pT::iterator_holes_type iHb = p.begin_holes(); iHb != p.end_holes(); ++iHb) { get_error_rects_shell(posE, negE, iHb->begin(), iHb->end()); } } template <typename Unit> template <int op> inline void polygon_45_set_data<Unit>::applyAdaptiveBoolean_(polygon_45_set_data<Unit>& result, const polygon_45_set_data<Unit>& rvalue) const { result.clear(); result.error_data_ = error_data_; result.error_data_.insert(result.error_data_.end(), rvalue.error_data_.begin(), rvalue.error_data_.end()); if(is_manhattan() && rvalue.is_manhattan()) { //convert each into polygon_90_set data and call boolean operations polygon_90_set_data<Unit> l90sd(VERTICAL), r90sd(VERTICAL), output(VERTICAL); for(typename value_type::const_iterator itr = data_.begin(); itr != data_.end(); ++itr) { if((*itr).count[3] == 0) continue; //skip all non vertical edges l90sd.insert(std::make_pair((*itr).pt.x(), std::make_pair<Unit, int>((*itr).pt.y(), (*itr).count[3])), false, VERTICAL); } for(typename value_type::const_iterator itr = rvalue.data_.begin(); itr != rvalue.data_.end(); ++itr) { if((*itr).count[3] == 0) continue; //skip all non vertical edges r90sd.insert(std::make_pair((*itr).pt.x(), std::make_pair<Unit, int>((*itr).pt.y(), (*itr).count[3])), false, VERTICAL); } l90sd.sort(); r90sd.sort(); #ifdef BOOST_POLYGON_MSVC #pragma warning (push) #pragma warning (disable: 4127) #endif if(op == 0) { output.applyBooleanBinaryOp(l90sd.begin(), l90sd.end(), r90sd.begin(), r90sd.end(), boolean_op::BinaryCount<boolean_op::BinaryOr>()); } else if (op == 1) { output.applyBooleanBinaryOp(l90sd.begin(), l90sd.end(), r90sd.begin(), r90sd.end(), boolean_op::BinaryCount<boolean_op::BinaryAnd>()); } else if (op == 2) { output.applyBooleanBinaryOp(l90sd.begin(), l90sd.end(), r90sd.begin(), r90sd.end(), boolean_op::BinaryCount<boolean_op::BinaryNot>()); } else if (op == 3) { output.applyBooleanBinaryOp(l90sd.begin(), l90sd.end(), r90sd.begin(), r90sd.end(), boolean_op::BinaryCount<boolean_op::BinaryXor>()); } #ifdef BOOST_POLYGON_MSVC #pragma warning (pop) #endif result.data_.clear(); result.insert(output); result.is_manhattan_ = true; result.dirty_ = false; result.unsorted_ = false; } else { sort(); rvalue.sort(); try { result.is_manhattan_ = applyBoolean45OpOnVectors<Unit, op>(result.data_, data_, rvalue.data_); } catch (std::string str) { std::string msg = "GTL 45 Boolean error, precision insufficient to represent edge intersection coordinate value."; if(str == msg) { result.clear(); typedef typename coordinate_traits<Unit>::manhattan_area_type Unit2; typedef typename polygon_45_formation<Unit2>::Vertex45Compact Vertex45Compact2; typedef std::vector<Vertex45Compact2> Data2; Data2 rvalue_data, lvalue_data, result_data; rvalue_data.reserve(rvalue.data_.size()); lvalue_data.reserve(data_.size()); for(std::size_t i = 0 ; i < data_.size(); ++i) { const Vertex45Compact& vi = data_[i]; Vertex45Compact2 ci; ci.pt = point_data<Unit2>(x(vi.pt), y(vi.pt)); ci.count = typename polygon_45_formation<Unit2>::Vertex45Count ( vi.count[0], vi.count[1], vi.count[2], vi.count[3]); lvalue_data.push_back(ci); } for(std::size_t i = 0 ; i < rvalue.data_.size(); ++i) { const Vertex45Compact& vi = rvalue.data_[i]; Vertex45Compact2 ci; ci.pt = (point_data<Unit2>(x(vi.pt), y(vi.pt))); ci.count = typename polygon_45_formation<Unit2>::Vertex45Count ( vi.count[0], vi.count[1], vi.count[2], vi.count[3]); rvalue_data.push_back(ci); } scale_up_vertex_45_compact_range(lvalue_data.begin(), lvalue_data.end(), 2); scale_up_vertex_45_compact_range(rvalue_data.begin(), rvalue_data.end(), 2); bool result_is_manhattan = applyBoolean45OpOnVectors<Unit2, op>(result_data, lvalue_data, rvalue_data ); if(!result_is_manhattan) { typename polygon_45_formation<Unit2>::Polygon45Formation pf(false); //std::cout << "FORMING POLYGONS\n"; std::vector<polygon_45_with_holes_data<Unit2> > container; pf.scan(container, result_data.begin(), result_data.end()); Data2 error_data_out; std::vector<rectangle_data<Unit2> > pos_error_rects; std::vector<rectangle_data<Unit2> > neg_error_rects; for(std::size_t i = 0; i < container.size(); ++i) { get_error_rects(pos_error_rects, neg_error_rects, container[i]); } for(std::size_t i = 0; i < pos_error_rects.size(); ++i) { insert_rectangle_into_vector_45(result_data, pos_error_rects[i], false); insert_rectangle_into_vector_45(error_data_out, pos_error_rects[i], false); } for(std::size_t i = 0; i < neg_error_rects.size(); ++i) { insert_rectangle_into_vector_45(result_data, neg_error_rects[i], true); insert_rectangle_into_vector_45(error_data_out, neg_error_rects[i], false); } scale_down_vertex_45_compact_range_blindly(error_data_out.begin(), error_data_out.end(), 2); for(std::size_t i = 0 ; i < error_data_out.size(); ++i) { const Vertex45Compact2& vi = error_data_out[i]; Vertex45Compact ci; ci.pt.x(static_cast<Unit>(x(vi.pt))); ci.pt.y(static_cast<Unit>(y(vi.pt))); ci.count = typename polygon_45_formation<Unit>::Vertex45Count ( vi.count[0], vi.count[1], vi.count[2], vi.count[3]); result.error_data_.push_back(ci); } Data2 new_result_data; polygon_sort(result_data.begin(), result_data.end()); applyUnary45OpOnVectors<Unit2, 0>(new_result_data, result_data); //OR operation result_data.swap(new_result_data); } scale_down_vertex_45_compact_range_blindly(result_data.begin(), result_data.end(), 2); //result.data_.reserve(result_data.size()); for(std::size_t i = 0 ; i < result_data.size(); ++i) { const Vertex45Compact2& vi = result_data[i]; Vertex45Compact ci; ci.pt.x(static_cast<Unit>(x(vi.pt))); ci.pt.y(static_cast<Unit>(y(vi.pt))); ci.count = typename polygon_45_formation<Unit>::Vertex45Count ( vi.count[0], vi.count[1], vi.count[2], vi.count[3]); result.data_.push_back(ci); } result.is_manhattan_ = result_is_manhattan; result.dirty_ = false; result.unsorted_ = false; } else { throw str; } } //std::cout << "DONE SCANNING\n"; } } template <typename Unit> template <int op> inline void polygon_45_set_data<Unit>::applyAdaptiveUnary_() const { polygon_45_set_data<Unit> result; result.error_data_ = error_data_; if(is_manhattan()) { //convert each into polygon_90_set data and call boolean operations polygon_90_set_data<Unit> l90sd(VERTICAL); for(typename value_type::const_iterator itr = data_.begin(); itr != data_.end(); ++itr) { if((*itr).count[3] == 0) continue; //skip all non vertical edges l90sd.insert(std::make_pair((*itr).pt.x(), std::make_pair<Unit, int>((*itr).pt.y(), (*itr).count[3])), false, VERTICAL); } l90sd.sort(); #ifdef BOOST_POLYGON_MSVC #pragma warning (push) #pragma warning (disable: 4127) #endif if(op == 0) { l90sd.clean(); } else if (op == 1) { l90sd.self_intersect(); } else if (op == 3) { l90sd.self_xor(); } #ifdef BOOST_POLYGON_MSVC #pragma warning (pop) #endif result.data_.clear(); result.insert(l90sd); result.is_manhattan_ = true; result.dirty_ = false; result.unsorted_ = false; } else { sort(); try { result.is_manhattan_ = applyUnary45OpOnVectors<Unit, op>(result.data_, data_); } catch (std::string str) { std::string msg = "GTL 45 Boolean error, precision insufficient to represent edge intersection coordinate value."; if(str == msg) { result.clear(); typedef typename coordinate_traits<Unit>::manhattan_area_type Unit2; typedef typename polygon_45_formation<Unit2>::Vertex45Compact Vertex45Compact2; typedef std::vector<Vertex45Compact2> Data2; Data2 lvalue_data, result_data; lvalue_data.reserve(data_.size()); for(std::size_t i = 0 ; i < data_.size(); ++i) { const Vertex45Compact& vi = data_[i]; Vertex45Compact2 ci; ci.pt.x(static_cast<Unit>(x(vi.pt))); ci.pt.y(static_cast<Unit>(y(vi.pt))); ci.count = typename polygon_45_formation<Unit2>::Vertex45Count ( vi.count[0], vi.count[1], vi.count[2], vi.count[3]); lvalue_data.push_back(ci); } scale_up_vertex_45_compact_range(lvalue_data.begin(), lvalue_data.end(), 2); bool result_is_manhattan = applyUnary45OpOnVectors<Unit2, op>(result_data, lvalue_data ); if(!result_is_manhattan) { typename polygon_45_formation<Unit2>::Polygon45Formation pf(false); //std::cout << "FORMING POLYGONS\n"; std::vector<polygon_45_with_holes_data<Unit2> > container; pf.scan(container, result_data.begin(), result_data.end()); Data2 error_data_out; std::vector<rectangle_data<Unit2> > pos_error_rects; std::vector<rectangle_data<Unit2> > neg_error_rects; for(std::size_t i = 0; i < container.size(); ++i) { get_error_rects(pos_error_rects, neg_error_rects, container[i]); } for(std::size_t i = 0; i < pos_error_rects.size(); ++i) { insert_rectangle_into_vector_45(result_data, pos_error_rects[i], false); insert_rectangle_into_vector_45(error_data_out, pos_error_rects[i], false); } for(std::size_t i = 0; i < neg_error_rects.size(); ++i) { insert_rectangle_into_vector_45(result_data, neg_error_rects[i], true); insert_rectangle_into_vector_45(error_data_out, neg_error_rects[i], false); } scale_down_vertex_45_compact_range_blindly(error_data_out.begin(), error_data_out.end(), 2); for(std::size_t i = 0 ; i < error_data_out.size(); ++i) { const Vertex45Compact2& vi = error_data_out[i]; Vertex45Compact ci; ci.pt.x(static_cast<Unit>(x(vi.pt))); ci.pt.y(static_cast<Unit>(y(vi.pt))); ci.count = typename polygon_45_formation<Unit>::Vertex45Count ( vi.count[0], vi.count[1], vi.count[2], vi.count[3]); result.error_data_.push_back(ci); } Data2 new_result_data; polygon_sort(result_data.begin(), result_data.end()); applyUnary45OpOnVectors<Unit2, 0>(new_result_data, result_data); //OR operation result_data.swap(new_result_data); } scale_down_vertex_45_compact_range_blindly(result_data.begin(), result_data.end(), 2); //result.data_.reserve(result_data.size()); for(std::size_t i = 0 ; i < result_data.size(); ++i) { const Vertex45Compact2& vi = result_data[i]; Vertex45Compact ci; ci.pt.x(static_cast<Unit>(x(vi.pt))); ci.pt.y(static_cast<Unit>(y(vi.pt))); ci.count = typename polygon_45_formation<Unit>::Vertex45Count ( vi.count[0], vi.count[1], vi.count[2], vi.count[3]); result.data_.push_back(ci); } result.is_manhattan_ = result_is_manhattan; result.dirty_ = false; result.unsorted_ = false; } else { throw str; } } //std::cout << "DONE SCANNING\n"; } data_.swap(result.data_); error_data_.swap(result.error_data_); dirty_ = result.dirty_; unsorted_ = result.unsorted_; is_manhattan_ = result.is_manhattan_; } template <typename coordinate_type, typename property_type> class property_merge_45 { private: typedef typename coordinate_traits<coordinate_type>::manhattan_area_type big_coord; typedef typename polygon_45_property_merge<big_coord, property_type>::MergeSetData tsd; tsd tsd_; public: inline property_merge_45() : tsd_() {} inline property_merge_45(const property_merge_45& that) : tsd_(that.tsd_) {} inline property_merge_45& operator=(const property_merge_45& that) { tsd_ = that.tsd_; return *this; } inline void insert(const polygon_45_set_data<coordinate_type>& ps, property_type property) { ps.clean(); polygon_45_property_merge<big_coord, property_type>::populateMergeSetData(tsd_, ps.begin(), ps.end(), property); } template <class GeoObjT> inline void insert(const GeoObjT& geoObj, property_type property) { polygon_45_set_data<coordinate_type> ps; ps.insert(geoObj); insert(ps, property); } //merge properties of input geometries and store the resulting geometries of regions //with unique sets of merged properties to polygons sets in a map keyed by sets of properties // T = std::map<std::set<property_type>, polygon_45_set_data<coordiante_type> > or // T = std::map<std::vector<property_type>, polygon_45_set_data<coordiante_type> > template <class result_type> inline void merge(result_type& result) { typedef typename result_type::key_type keytype; typedef std::map<keytype, polygon_45_set_data<big_coord> > bigtype; bigtype result_big; polygon_45_property_merge<big_coord, property_type>::performMerge(result_big, tsd_); std::vector<polygon_45_with_holes_data<big_coord> > polys; std::vector<rectangle_data<big_coord> > pos_error_rects; std::vector<rectangle_data<big_coord> > neg_error_rects; for(typename std::map<keytype, polygon_45_set_data<big_coord> >::iterator itr = result_big.begin(); itr != result_big.end(); ++itr) { polys.clear(); (*itr).second.get(polys); for(std::size_t i = 0; i < polys.size(); ++i) { get_error_rects(pos_error_rects, neg_error_rects, polys[i]); } (*itr).second += pos_error_rects; (*itr).second -= neg_error_rects; (*itr).second.scale_down(2); result[(*itr).first].insert((*itr).second); } } }; //ConnectivityExtraction computes the graph of connectivity between rectangle, polygon and //polygon set graph nodes where an edge is created whenever the geometry in two nodes overlap template <typename coordinate_type> class connectivity_extraction_45 { private: typedef typename coordinate_traits<coordinate_type>::manhattan_area_type big_coord; typedef typename polygon_45_touch<big_coord>::TouchSetData tsd; tsd tsd_; unsigned int nodeCount_; public: inline connectivity_extraction_45() : tsd_(), nodeCount_(0) {} inline connectivity_extraction_45(const connectivity_extraction_45& that) : tsd_(that.tsd_), nodeCount_(that.nodeCount_) {} inline connectivity_extraction_45& operator=(const connectivity_extraction_45& that) { tsd_ = that.tsd_; nodeCount_ = that.nodeCount_; {} return *this; } //insert a polygon set graph node, the value returned is the id of the graph node inline unsigned int insert(const polygon_45_set_data<coordinate_type>& ps) { ps.clean(); polygon_45_touch<big_coord>::populateTouchSetData(tsd_, ps.begin(), ps.end(), nodeCount_); return nodeCount_++; } template <class GeoObjT> inline unsigned int insert(const GeoObjT& geoObj) { polygon_45_set_data<coordinate_type> ps; ps.insert(geoObj); return insert(ps); } //extract connectivity and store the edges in the graph //graph must be indexable by graph node id and the indexed value must be a std::set of //graph node id template <class GraphT> inline void extract(GraphT& graph) { polygon_45_touch<big_coord>::performTouch(graph, tsd_); } }; } } #endif PK �b�[��LH H polygon_90_data.hppnu �[��� /* Copyright 2008 Intel Corporation Use, modification and distribution are 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_POLYGON_POLYGON_90_DATA_HPP #define BOOST_POLYGON_POLYGON_90_DATA_HPP namespace boost { namespace polygon{ struct polygon_90_concept; template <typename T> class polygon_90_data { public: typedef polygon_90_concept geometry_type; typedef T coordinate_type; typedef typename std::vector<coordinate_type>::const_iterator compact_iterator_type; typedef iterator_compact_to_points<compact_iterator_type, point_data<coordinate_type> > iterator_type; typedef typename coordinate_traits<T>::area_type area_type; inline polygon_90_data() : coords_() {} //do nothing default constructor // initialize a polygon from x,y values, it is assumed that the first is an x // and that the input is a well behaved polygon template<class iT> inline polygon_90_data& set(iT begin_point, iT end_point) { return set_compact(iterator_points_to_compact<iT, typename std::iterator_traits<iT>::value_type>(begin_point, end_point), iterator_points_to_compact<iT, typename std::iterator_traits<iT>::value_type>(end_point, end_point)); } template<class iT> inline polygon_90_data& set_compact(iT input_begin, iT input_end) { coords_.clear(); //just in case there was some old data there while(input_begin != input_end) { coords_.insert(coords_.end(), *input_begin); ++input_begin; } return *this; } // copy constructor (since we have dynamic memory) inline polygon_90_data(const polygon_90_data& that) : coords_(that.coords_) {} // assignment operator (since we have dynamic memory do a deep copy) inline polygon_90_data& operator=(const polygon_90_data& that) { coords_ = that.coords_; return *this; } template <typename T2> inline polygon_90_data& operator=(const T2& rvalue); // assignment operator (since we have dynamic memory do a deep copy) inline bool operator==(const polygon_90_data& that) const { return coords_ == that.coords_; } // get begin iterator, returns a pointer to a const Unit inline iterator_type begin() const { return iterator_type(coords_.begin(), coords_.end()); } // get end iterator, returns a pointer to a const Unit inline iterator_type end() const { return iterator_type(coords_.end(), coords_.end()); } // get begin iterator, returns a pointer to a const Unit inline compact_iterator_type begin_compact() const { return coords_.begin(); } // get end iterator, returns a pointer to a const Unit inline compact_iterator_type end_compact() const { return coords_.end(); } inline std::size_t size() const { return coords_.size(); } private: std::vector<coordinate_type> coords_; }; } } #endif PK �b�[��4� � gtl.hppnu �[��� /* Copyright 2008 Intel Corporation Use, modification and distribution are 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_POLYGON_GTL_HPP #define BOOST_POLYGON_GTL_HPP #ifdef __ICC #pragma warning (push) #pragma warning (disable:1125) #endif #ifdef WIN32 #pragma warning (push) #pragma warning( disable: 4996 ) #pragma warning( disable: 4800 ) #endif #define BOOST_POLYGON_NO_DEPS #include "polygon.hpp" namespace gtl = boost::polygon; using namespace boost::polygon::operators; #ifdef WIN32 #pragma warning (pop) #endif #ifdef __ICC #pragma warning (pop) #endif #endif PK �b�[���H H rectangle_data.hppnu �[��� /* Copyright 2008 Intel Corporation Use, modification and distribution are 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_POLYGON_RECTANGLE_DATA_HPP #define BOOST_POLYGON_RECTANGLE_DATA_HPP #include "isotropy.hpp" //interval #include "interval_data.hpp" namespace boost { namespace polygon{ template <typename T> class rectangle_data { public: typedef T coordinate_type; typedef interval_data<T> interval_type; inline rectangle_data():ranges_() {} inline rectangle_data(T xl, T yl, T xh, T yh):ranges_() { if(xl > xh) std::swap(xl, xh); if(yl > yh) std::swap(yl, yh); ranges_[HORIZONTAL] = interval_data<T>(xl, xh); ranges_[VERTICAL] = interval_data<T>(yl, yh); } template <typename interval_type_1, typename interval_type_2> inline rectangle_data(const interval_type_1& hrange, const interval_type_2& vrange):ranges_() { set(HORIZONTAL, hrange); set(VERTICAL, vrange); } inline rectangle_data(const rectangle_data& that):ranges_() { (*this) = that; } inline rectangle_data& operator=(const rectangle_data& that) { ranges_[0] = that.ranges_[0]; ranges_[1] = that.ranges_[1]; return *this; } template <typename T2> inline rectangle_data& operator=(const T2& rvalue); template <typename T2> inline bool operator==(const T2& rvalue) const; template <typename T2> inline bool operator!=(const T2& rvalue) const { return !((*this) == rvalue); } inline interval_data<coordinate_type> get(orientation_2d orient) const { return ranges_[orient.to_int()]; } inline coordinate_type get(direction_2d dir) const { return ranges_[orientation_2d(dir).to_int()].get(direction_1d(dir)); } inline void set(direction_2d dir, coordinate_type value) { return ranges_[orientation_2d(dir).to_int()].set(direction_1d(dir), value); } template <typename interval_type_1> inline void set(orientation_2d orient, const interval_type_1& interval); private: interval_data<coordinate_type> ranges_[2]; }; } } #endif PK �b�[��܍ � interval_data.hppnu �[��� // Boost.Polygon library interval_data.hpp header file // Copyright (c) Intel Corporation 2008. // Copyright (c) 2008-2012 Simonson Lucanus. // Copyright (c) 2012-2012 Andrii Sydorchuk. // See http://www.boost.org for updates, documentation, and revision history. // 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_POLYGON_INTERVAL_DATA_HPP #define BOOST_POLYGON_INTERVAL_DATA_HPP #include "isotropy.hpp" #include "interval_concept.hpp" namespace boost { namespace polygon { template <typename T> class interval_data { public: typedef T coordinate_type; interval_data() #ifndef BOOST_POLYGON_MSVC : coords_() #endif {} interval_data(coordinate_type low, coordinate_type high) { coords_[LOW] = low; coords_[HIGH] = high; } interval_data(const interval_data& that) { coords_[0] = that.coords_[0]; coords_[1] = that.coords_[1]; } interval_data& operator=(const interval_data& that) { coords_[0] = that.coords_[0]; coords_[1] = that.coords_[1]; return *this; } template <typename IntervalType> interval_data& operator=(const IntervalType& that) { assign(*this, that); return *this; } coordinate_type get(direction_1d dir) const { return coords_[dir.to_int()]; } void set(direction_1d dir, coordinate_type value) { coords_[dir.to_int()] = value; } coordinate_type low() const { return coords_[0]; } interval_data& low(coordinate_type value) { coords_[LOW] = value; return *this; } coordinate_type high() const { return coords_[1]; } interval_data& high(coordinate_type value) { coords_[HIGH] = value; return *this; } bool operator==(const interval_data& that) const { return low() == that.low() && high() == that.high(); } bool operator!=(const interval_data& that) const { return low() != that.low() || high() != that.high(); } bool operator<(const interval_data& that) const { if (coords_[0] != that.coords_[0]) { return coords_[0] < that.coords_[0]; } return coords_[1] < that.coords_[1]; } bool operator<=(const interval_data& that) const { return !(that < *this); } bool operator>(const interval_data& that) const { return that < *this; } bool operator>=(const interval_data& that) const { return !((*this) < that); } private: coordinate_type coords_[2]; }; template <typename CType> struct geometry_concept< interval_data<CType> > { typedef interval_concept type; }; } // polygon } // boost #endif // BOOST_POLYGON_INTERVAL_DATA_HPP PK �b�[M�N++i +i polygon_90_set_concept.hppnu �[��� /* Copyright 2008 Intel Corporation Use, modification and distribution are 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_POLYGON_POLYGON_90_SET_CONCEPT_HPP #define BOOST_POLYGON_POLYGON_90_SET_CONCEPT_HPP #include "polygon_90_set_data.hpp" #include "polygon_90_set_traits.hpp" namespace boost { namespace polygon{ template <typename polygon_set_type> typename enable_if< typename is_polygon_90_set_type<polygon_set_type>::type, typename polygon_90_set_traits<polygon_set_type>::iterator_type>::type begin_90_set_data(const polygon_set_type& polygon_set) { return polygon_90_set_traits<polygon_set_type>::begin(polygon_set); } template <typename polygon_set_type> typename enable_if< typename is_polygon_90_set_type<polygon_set_type>::type, typename polygon_90_set_traits<polygon_set_type>::iterator_type>::type end_90_set_data(const polygon_set_type& polygon_set) { return polygon_90_set_traits<polygon_set_type>::end(polygon_set); } template <typename polygon_set_type> typename enable_if< typename is_polygon_90_set_type<polygon_set_type>::type, orientation_2d>::type scanline_orientation(const polygon_set_type& polygon_set) { return polygon_90_set_traits<polygon_set_type>::orient(polygon_set); } template <typename polygon_set_type> typename enable_if< typename is_polygon_90_set_type<polygon_set_type>::type, bool>::type clean(const polygon_set_type& polygon_set) { return polygon_90_set_traits<polygon_set_type>::clean(polygon_set); } //assign template <typename polygon_set_type_1, typename polygon_set_type_2> typename enable_if < typename gtl_and< typename is_mutable_polygon_90_set_type<polygon_set_type_1>::type, typename is_polygon_90_set_type<polygon_set_type_2>::type>::type, polygon_set_type_1>::type & assign(polygon_set_type_1& lvalue, const polygon_set_type_2& rvalue) { polygon_90_set_mutable_traits<polygon_set_type_1>::set(lvalue, begin_90_set_data(rvalue), end_90_set_data(rvalue), scanline_orientation(rvalue)); return lvalue; } template <typename T1, typename T2> struct are_not_both_rectangle_concept { typedef gtl_yes type; }; template <> struct are_not_both_rectangle_concept<rectangle_concept, rectangle_concept> { typedef gtl_no type; }; //equivalence template <typename polygon_set_type_1, typename polygon_set_type_2> typename enable_if< typename gtl_and_3< typename is_polygon_90_set_type<polygon_set_type_1>::type, typename is_polygon_90_set_type<polygon_set_type_2>::type, typename are_not_both_rectangle_concept<typename geometry_concept<polygon_set_type_1>::type, typename geometry_concept<polygon_set_type_2>::type>::type>::type, bool>::type equivalence(const polygon_set_type_1& lvalue, const polygon_set_type_2& rvalue) { polygon_90_set_data<typename polygon_90_set_traits<polygon_set_type_1>::coordinate_type> ps1; assign(ps1, lvalue); polygon_90_set_data<typename polygon_90_set_traits<polygon_set_type_2>::coordinate_type> ps2; assign(ps2, rvalue); return ps1 == ps2; } //get rectangle tiles (slicing orientation is vertical) template <typename output_container_type, typename polygon_set_type> typename enable_if< typename gtl_if<typename is_polygon_90_set_type<polygon_set_type>::type>::type, void>::type get_rectangles(output_container_type& output, const polygon_set_type& polygon_set) { clean(polygon_set); polygon_90_set_data<typename polygon_90_set_traits<polygon_set_type>::coordinate_type> ps(VERTICAL); assign(ps, polygon_set); ps.get_rectangles(output); } //get rectangle tiles template <typename output_container_type, typename polygon_set_type> typename enable_if< typename gtl_if<typename is_polygon_90_set_type<polygon_set_type>::type>::type, void>::type get_rectangles(output_container_type& output, const polygon_set_type& polygon_set, orientation_2d slicing_orientation) { clean(polygon_set); polygon_90_set_data<typename polygon_90_set_traits<polygon_set_type>::coordinate_type> ps; assign(ps, polygon_set); ps.get_rectangles(output, slicing_orientation); } //get: min_rectangles max_rectangles template <typename output_container_type, typename polygon_set_type> typename enable_if <typename gtl_and< typename is_polygon_90_set_type<polygon_set_type>::type, typename gtl_same_type<rectangle_concept, typename geometry_concept <typename std::iterator_traits <typename output_container_type::iterator>::value_type>::type>::type>::type, void>::type get_max_rectangles(output_container_type& output, const polygon_set_type& polygon_set) { std::vector<rectangle_data<typename polygon_90_set_traits<polygon_set_type>::coordinate_type> > rects; assign(rects, polygon_set); MaxCover<typename polygon_90_set_traits<polygon_set_type>::coordinate_type>::getMaxCover(output, rects, scanline_orientation(polygon_set)); } //clear template <typename polygon_set_type> typename enable_if< typename is_mutable_polygon_90_set_type<polygon_set_type>::type, void>::type clear(polygon_set_type& polygon_set) { polygon_90_set_data<typename polygon_90_set_traits<polygon_set_type>::coordinate_type> ps(scanline_orientation(polygon_set)); assign(polygon_set, ps); } //empty template <typename polygon_set_type> typename enable_if< typename is_mutable_polygon_90_set_type<polygon_set_type>::type, bool>::type empty(const polygon_set_type& polygon_set) { if(clean(polygon_set)) return begin_90_set_data(polygon_set) == end_90_set_data(polygon_set); polygon_90_set_data<typename polygon_90_set_traits<polygon_set_type>::coordinate_type> ps; assign(ps, polygon_set); ps.clean(); return ps.empty(); } //extents template <typename polygon_set_type, typename rectangle_type> typename enable_if <typename gtl_and< typename is_mutable_polygon_90_set_type<polygon_set_type>::type, typename is_mutable_rectangle_concept<typename geometry_concept<rectangle_type>::type>::type>::type, bool>::type extents(rectangle_type& extents_rectangle, const polygon_set_type& polygon_set) { typedef typename polygon_90_set_traits<polygon_set_type>::coordinate_type Unit; polygon_90_set_data<Unit> ps; assign(ps, polygon_set); return ps.extents(extents_rectangle); } //area template <typename polygon_set_type> typename enable_if< typename is_mutable_polygon_90_set_type<polygon_set_type>::type, typename coordinate_traits<typename polygon_90_set_traits<polygon_set_type>::coordinate_type>::manhattan_area_type>::type area(const polygon_set_type& polygon_set) { typedef rectangle_data<typename polygon_90_set_traits<polygon_set_type>::coordinate_type> rectangle_type; typedef typename coordinate_traits<typename polygon_90_set_traits<polygon_set_type>::coordinate_type>::manhattan_area_type area_type; std::vector<rectangle_type> rects; assign(rects, polygon_set); area_type retval = (area_type)0; for(std::size_t i = 0; i < rects.size(); ++i) { retval += (area_type)area(rects[i]); } return retval; } //interact template <typename polygon_set_type_1, typename polygon_set_type_2> typename enable_if <typename gtl_and< typename is_mutable_polygon_90_set_type<polygon_set_type_1>::type, typename is_mutable_polygon_90_set_type<polygon_set_type_2>::type>::type, polygon_set_type_1>::type& interact(polygon_set_type_1& polygon_set_1, const polygon_set_type_2& polygon_set_2) { typedef typename polygon_90_set_traits<polygon_set_type_1>::coordinate_type Unit; polygon_90_set_data<Unit> ps(scanline_orientation(polygon_set_2)); polygon_90_set_data<Unit> ps2(ps); ps.insert(polygon_set_1); ps2.insert(polygon_set_2); ps.interact(ps2); assign(polygon_set_1, ps); return polygon_set_1; } //self_intersect template <typename polygon_set_type> typename enable_if< typename is_mutable_polygon_90_set_type<polygon_set_type>::type, polygon_set_type>::type & self_intersect(polygon_set_type& polygon_set) { typedef typename polygon_90_set_traits<polygon_set_type>::coordinate_type Unit; polygon_90_set_data<Unit> ps; assign(ps, polygon_set); ps.self_intersect(); assign(polygon_set, ps); return polygon_set; } //self_xor template <typename polygon_set_type> typename enable_if< typename is_mutable_polygon_90_set_type<polygon_set_type>::type, polygon_set_type>::type & self_xor(polygon_set_type& polygon_set) { typedef typename polygon_90_set_traits<polygon_set_type>::coordinate_type Unit; polygon_90_set_data<Unit> ps; assign(ps, polygon_set); ps.self_xor(); assign(polygon_set, ps); return polygon_set; } template <typename polygon_set_type> typename enable_if< typename is_mutable_polygon_90_set_type<polygon_set_type>::type, polygon_set_type>::type & bloat(polygon_set_type& polygon_set, typename coordinate_traits<typename polygon_90_set_traits<polygon_set_type>::coordinate_type>::unsigned_area_type bloating) { return bloat(polygon_set, bloating, bloating, bloating, bloating); } template <typename polygon_set_type> typename enable_if< typename is_mutable_polygon_90_set_type<polygon_set_type>::type, polygon_set_type>::type & bloat(polygon_set_type& polygon_set, orientation_2d orient, typename coordinate_traits<typename polygon_90_set_traits<polygon_set_type>::coordinate_type>::unsigned_area_type bloating) { if(orient == orientation_2d(HORIZONTAL)) return bloat(polygon_set, bloating, bloating, 0, 0); return bloat(polygon_set, 0, 0, bloating, bloating); } template <typename polygon_set_type> typename enable_if< typename is_mutable_polygon_90_set_type<polygon_set_type>::type, polygon_set_type>::type & bloat(polygon_set_type& polygon_set, orientation_2d orient, typename coordinate_traits<typename polygon_90_set_traits<polygon_set_type>::coordinate_type>::unsigned_area_type low_bloating, typename coordinate_traits<typename polygon_90_set_traits<polygon_set_type>::coordinate_type>::unsigned_area_type high_bloating) { if(orient == orientation_2d(HORIZONTAL)) return bloat(polygon_set, low_bloating, high_bloating, 0, 0); return bloat(polygon_set, 0, 0, low_bloating, high_bloating); } template <typename polygon_set_type> typename enable_if< typename is_mutable_polygon_90_set_type<polygon_set_type>::type, polygon_set_type>::type & bloat(polygon_set_type& polygon_set, direction_2d dir, typename coordinate_traits<typename polygon_90_set_traits<polygon_set_type>::coordinate_type>::unsigned_area_type bloating) { if(dir == direction_2d(EAST)) return bloat(polygon_set, 0, bloating, 0, 0); if(dir == direction_2d(WEST)) return bloat(polygon_set, bloating, 0, 0, 0); if(dir == direction_2d(SOUTH)) return bloat(polygon_set, 0, 0, bloating, 0); return bloat(polygon_set, 0, 0, 0, bloating); } template <typename polygon_set_type> typename enable_if< typename is_mutable_polygon_90_set_type<polygon_set_type>::type, polygon_set_type>::type & bloat(polygon_set_type& polygon_set, typename coordinate_traits<typename polygon_90_set_traits<polygon_set_type>::coordinate_type>::unsigned_area_type west_bloating, typename coordinate_traits<typename polygon_90_set_traits<polygon_set_type>::coordinate_type>::unsigned_area_type east_bloating, typename coordinate_traits<typename polygon_90_set_traits<polygon_set_type>::coordinate_type>::unsigned_area_type south_bloating, typename coordinate_traits<typename polygon_90_set_traits<polygon_set_type>::coordinate_type>::unsigned_area_type north_bloating) { typedef typename polygon_90_set_traits<polygon_set_type>::coordinate_type Unit; polygon_90_set_data<Unit> ps; assign(ps, polygon_set); ps.bloat(west_bloating, east_bloating, south_bloating, north_bloating); ps.clean(); assign(polygon_set, ps); return polygon_set; } template <typename polygon_set_type> typename enable_if< typename is_mutable_polygon_90_set_type<polygon_set_type>::type, polygon_set_type>::type & shrink(polygon_set_type& polygon_set, typename coordinate_traits<typename polygon_90_set_traits<polygon_set_type>::coordinate_type>::unsigned_area_type shrinking) { return shrink(polygon_set, shrinking, shrinking, shrinking, shrinking); } template <typename polygon_set_type> typename enable_if< typename is_mutable_polygon_90_set_type<polygon_set_type>::type, polygon_set_type>::type & shrink(polygon_set_type& polygon_set, orientation_2d orient, typename coordinate_traits<typename polygon_90_set_traits<polygon_set_type>::coordinate_type>::unsigned_area_type shrinking) { if(orient == orientation_2d(HORIZONTAL)) return shrink(polygon_set, shrinking, shrinking, 0, 0); return shrink(polygon_set, 0, 0, shrinking, shrinking); } template <typename polygon_set_type> typename enable_if< typename is_mutable_polygon_90_set_type<polygon_set_type>::type, polygon_set_type>::type & shrink(polygon_set_type& polygon_set, orientation_2d orient, typename coordinate_traits<typename polygon_90_set_traits<polygon_set_type>::coordinate_type>::unsigned_area_type low_shrinking, typename coordinate_traits<typename polygon_90_set_traits<polygon_set_type>::coordinate_type>::unsigned_area_type high_shrinking) { if(orient == orientation_2d(HORIZONTAL)) return shrink(polygon_set, low_shrinking, high_shrinking, 0, 0); return shrink(polygon_set, 0, 0, low_shrinking, high_shrinking); } template <typename polygon_set_type> typename enable_if< typename is_mutable_polygon_90_set_type<polygon_set_type>::type, polygon_set_type>::type & shrink(polygon_set_type& polygon_set, direction_2d dir, typename coordinate_traits<typename polygon_90_set_traits<polygon_set_type>::coordinate_type>::unsigned_area_type shrinking) { if(dir == direction_2d(EAST)) return shrink(polygon_set, 0, shrinking, 0, 0); if(dir == direction_2d(WEST)) return shrink(polygon_set, shrinking, 0, 0, 0); if(dir == direction_2d(SOUTH)) return shrink(polygon_set, 0, 0, shrinking, 0); return shrink(polygon_set, 0, 0, 0, shrinking); } template <typename polygon_set_type> typename enable_if< typename is_mutable_polygon_90_set_type<polygon_set_type>::type, polygon_set_type>::type & shrink(polygon_set_type& polygon_set, typename coordinate_traits<typename polygon_90_set_traits<polygon_set_type>::coordinate_type>::unsigned_area_type west_shrinking, typename coordinate_traits<typename polygon_90_set_traits<polygon_set_type>::coordinate_type>::unsigned_area_type east_shrinking, typename coordinate_traits<typename polygon_90_set_traits<polygon_set_type>::coordinate_type>::unsigned_area_type south_shrinking, typename coordinate_traits<typename polygon_90_set_traits<polygon_set_type>::coordinate_type>::unsigned_area_type north_shrinking) { typedef typename polygon_90_set_traits<polygon_set_type>::coordinate_type Unit; polygon_90_set_data<Unit> ps; assign(ps, polygon_set); ps.shrink(west_shrinking, east_shrinking, south_shrinking, north_shrinking); ps.clean(); assign(polygon_set, ps); return polygon_set; } template <typename polygon_set_type, typename coord_type> typename enable_if< typename is_mutable_polygon_90_set_type<polygon_set_type>::type, polygon_set_type>::type & resize(polygon_set_type& polygon_set, coord_type resizing) { if(resizing > 0) { return bloat(polygon_set, resizing); } if(resizing < 0) { return shrink(polygon_set, -resizing); } return polygon_set; } //positive or negative values allow for any and all directions of sizing template <typename polygon_set_type, typename coord_type> typename enable_if< typename is_mutable_polygon_90_set_type<polygon_set_type>::type, polygon_set_type>::type & resize(polygon_set_type& polygon_set, coord_type west, coord_type east, coord_type south, coord_type north) { typedef typename polygon_90_set_traits<polygon_set_type>::coordinate_type Unit; polygon_90_set_data<Unit> ps; assign(ps, polygon_set); ps.resize(west, east, south, north); assign(polygon_set, ps); return polygon_set; } template <typename polygon_set_type> typename enable_if< typename is_mutable_polygon_90_set_type<polygon_set_type>::type, polygon_set_type>::type & grow_and(polygon_set_type& polygon_set, typename coordinate_traits<typename polygon_90_set_traits<polygon_set_type>::coordinate_type>::unsigned_area_type bloating) { return grow_and(polygon_set, bloating, bloating, bloating, bloating); } template <typename polygon_set_type> typename enable_if< typename is_mutable_polygon_90_set_type<polygon_set_type>::type, polygon_set_type>::type & grow_and(polygon_set_type& polygon_set, orientation_2d orient, typename coordinate_traits<typename polygon_90_set_traits<polygon_set_type>::coordinate_type>::unsigned_area_type bloating) { if(orient == orientation_2d(HORIZONTAL)) return grow_and(polygon_set, bloating, bloating, 0, 0); return grow_and(polygon_set, 0, 0, bloating, bloating); } template <typename polygon_set_type> typename enable_if< typename is_mutable_polygon_90_set_type<polygon_set_type>::type, polygon_set_type>::type & grow_and(polygon_set_type& polygon_set, orientation_2d orient, typename coordinate_traits<typename polygon_90_set_traits<polygon_set_type>::coordinate_type>::unsigned_area_type low_bloating, typename coordinate_traits<typename polygon_90_set_traits<polygon_set_type>::coordinate_type>::unsigned_area_type high_bloating) { if(orient == orientation_2d(HORIZONTAL)) return grow_and(polygon_set, low_bloating, high_bloating, 0, 0); return grow_and(polygon_set, 0, 0, low_bloating, high_bloating); } template <typename polygon_set_type> typename enable_if< typename is_mutable_polygon_90_set_type<polygon_set_type>::type, polygon_set_type>::type & grow_and(polygon_set_type& polygon_set, direction_2d dir, typename coordinate_traits<typename polygon_90_set_traits<polygon_set_type>::coordinate_type>::unsigned_area_type bloating) { if(dir == direction_2d(EAST)) return grow_and(polygon_set, 0, bloating, 0, 0); if(dir == direction_2d(WEST)) return grow_and(polygon_set, bloating, 0, 0, 0); if(dir == direction_2d(SOUTH)) return grow_and(polygon_set, 0, 0, bloating, 0); return grow_and(polygon_set, 0, 0, 0, bloating); } template <typename polygon_set_type> typename enable_if< typename gtl_if<typename is_mutable_polygon_90_set_type<polygon_set_type>::type>::type, polygon_set_type>::type & grow_and(polygon_set_type& polygon_set, typename coordinate_traits<typename polygon_90_set_traits<polygon_set_type>::coordinate_type>::unsigned_area_type west_bloating, typename coordinate_traits<typename polygon_90_set_traits<polygon_set_type>::coordinate_type>::unsigned_area_type east_bloating, typename coordinate_traits<typename polygon_90_set_traits<polygon_set_type>::coordinate_type>::unsigned_area_type south_bloating, typename coordinate_traits<typename polygon_90_set_traits<polygon_set_type>::coordinate_type>::unsigned_area_type north_bloating) { typedef typename polygon_90_set_traits<polygon_set_type>::coordinate_type Unit; std::vector<polygon_90_data<Unit> > polys; assign(polys, polygon_set); clear(polygon_set); polygon_90_set_data<Unit> ps(scanline_orientation(polygon_set)); for(std::size_t i = 0; i < polys.size(); ++i) { polygon_90_set_data<Unit> tmpPs(scanline_orientation(polygon_set)); tmpPs.insert(polys[i]); bloat(tmpPs, west_bloating, east_bloating, south_bloating, north_bloating); tmpPs.clean(); //apply implicit OR on tmp polygon set ps.insert(tmpPs); } self_intersect(ps); assign(polygon_set, ps); return polygon_set; } template <typename polygon_set_type> typename enable_if< typename is_mutable_polygon_90_set_type<polygon_set_type>::type, polygon_set_type>::type & scale_up(polygon_set_type& polygon_set, typename coordinate_traits<typename polygon_90_set_traits<polygon_set_type>::coordinate_type> ::unsigned_area_type factor) { typedef typename polygon_90_set_traits<polygon_set_type>::coordinate_type Unit; polygon_90_set_data<Unit> ps; assign(ps, polygon_set); ps.scale_up(factor); assign(polygon_set, ps); return polygon_set; } template <typename polygon_set_type> typename enable_if< typename is_mutable_polygon_90_set_type<polygon_set_type>::type, polygon_set_type>::type & scale_down(polygon_set_type& polygon_set, typename coordinate_traits<typename polygon_90_set_traits<polygon_set_type>::coordinate_type> ::unsigned_area_type factor) { typedef typename polygon_90_set_traits<polygon_set_type>::coordinate_type Unit; polygon_90_set_data<Unit> ps; assign(ps, polygon_set); ps.scale_down(factor); assign(polygon_set, ps); return polygon_set; } template <typename polygon_set_type, typename scaling_type> typename enable_if< typename is_mutable_polygon_90_set_type<polygon_set_type>::type, polygon_set_type>::type & scale(polygon_set_type& polygon_set, const scaling_type& scaling) { typedef typename polygon_90_set_traits<polygon_set_type>::coordinate_type Unit; polygon_90_set_data<Unit> ps; assign(ps, polygon_set); ps.scale(scaling); assign(polygon_set, ps); return polygon_set; } struct y_p_s_move : gtl_yes {}; //move template <typename polygon_set_type> typename enable_if< typename gtl_and<y_p_s_move, typename gtl_if<typename is_mutable_polygon_90_set_type<polygon_set_type>::type>::type>::type, polygon_set_type>::type & move(polygon_set_type& polygon_set, orientation_2d orient, typename polygon_90_set_traits<polygon_set_type>::coordinate_type displacement) { if(orient == HORIZONTAL) return move(polygon_set, displacement, 0); else return move(polygon_set, 0, displacement); } struct y_p_s_move2 : gtl_yes {}; template <typename polygon_set_type> typename enable_if< typename gtl_and<y_p_s_move2, typename gtl_if<typename is_mutable_polygon_90_set_type<polygon_set_type>::type>::type>::type, polygon_set_type>::type & move(polygon_set_type& polygon_set, typename polygon_90_set_traits<polygon_set_type>::coordinate_type x_displacement, typename polygon_90_set_traits<polygon_set_type>::coordinate_type y_displacement) { typedef typename polygon_90_set_traits<polygon_set_type>::coordinate_type Unit; polygon_90_set_data<Unit> ps; assign(ps, polygon_set); ps.move(x_displacement, y_displacement); ps.clean(); assign(polygon_set, ps); return polygon_set; } //transform template <typename polygon_set_type, typename transformation_type> typename enable_if< typename is_mutable_polygon_90_set_type<polygon_set_type>::type, polygon_set_type>::type & transform(polygon_set_type& polygon_set, const transformation_type& transformation) { typedef typename polygon_90_set_traits<polygon_set_type>::coordinate_type Unit; polygon_90_set_data<Unit> ps; assign(ps, polygon_set); ps.transform(transformation); ps.clean(); assign(polygon_set, ps); return polygon_set; typedef typename polygon_90_set_traits<polygon_set_type>::coordinate_type Unit; } //keep template <typename polygon_set_type> typename enable_if< typename is_mutable_polygon_90_set_type<polygon_set_type>::type, polygon_set_type>::type & keep(polygon_set_type& polygon_set, typename coordinate_traits<typename polygon_90_set_traits<polygon_set_type>::coordinate_type>::unsigned_area_type min_area, typename coordinate_traits<typename polygon_90_set_traits<polygon_set_type>::coordinate_type>::unsigned_area_type max_area, typename coordinate_traits<typename polygon_90_set_traits<polygon_set_type>::coordinate_type>::unsigned_area_type min_width, typename coordinate_traits<typename polygon_90_set_traits<polygon_set_type>::coordinate_type>::unsigned_area_type max_width, typename coordinate_traits<typename polygon_90_set_traits<polygon_set_type>::coordinate_type>::unsigned_area_type min_height, typename coordinate_traits<typename polygon_90_set_traits<polygon_set_type>::coordinate_type>::unsigned_area_type max_height) { typedef typename polygon_90_set_traits<polygon_set_type>::coordinate_type Unit; typedef typename coordinate_traits<Unit>::unsigned_area_type uat; std::list<polygon_90_data<Unit> > polys; assign(polys, polygon_set); clear(polygon_set); typename std::list<polygon_90_data<Unit> >::iterator itr_nxt; for(typename std::list<polygon_90_data<Unit> >::iterator itr = polys.begin(); itr != polys.end(); itr = itr_nxt){ itr_nxt = itr; ++itr_nxt; rectangle_data<Unit> bbox; extents(bbox, *itr); uat pwidth = delta(bbox, HORIZONTAL); if(pwidth > min_width && pwidth <= max_width){ uat pheight = delta(bbox, VERTICAL); if(pheight > min_height && pheight <= max_height){ uat parea = area(*itr); if(parea <= max_area && parea >= min_area) { continue; } } } polys.erase(itr); } assign(polygon_set, polys); return polygon_set; } } } #include "detail/polygon_90_set_view.hpp" #endif PK �b�[q�M�� � segment_data.hppnu �[��� // Boost.Polygon library segment_data.hpp header file // Copyright (c) Intel Corporation 2008. // Copyright (c) 2008-2012 Simonson Lucanus. // Copyright (c) 2012-2012 Andrii Sydorchuk. // See http://www.boost.org for updates, documentation, and revision history. // 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_POLYGON_SEGMENT_DATA_HPP #define BOOST_POLYGON_SEGMENT_DATA_HPP #include "isotropy.hpp" #include "segment_concept.hpp" namespace boost { namespace polygon { template <typename T> class segment_data { public: typedef T coordinate_type; typedef point_data<T> point_type; segment_data() #ifndef BOOST_POLYGON_MSVC : points_() #endif {} segment_data(const point_type& low, const point_type& high) { points_[LOW] = low; points_[HIGH] = high; } segment_data(const segment_data& that) { points_[0] = that.points_[0]; points_[1] = that.points_[1]; } segment_data& operator=(const segment_data& that) { points_[0] = that.points_[0]; points_[1] = that.points_[1]; return *this; } template <typename SegmentType> segment_data& operator=(const SegmentType& that) { assign(*this, that); return *this; } point_type get(direction_1d dir) const { return points_[dir.to_int()]; } void set(direction_1d dir, const point_type& point) { points_[dir.to_int()] = point; } point_type low() const { return points_[LOW]; } segment_data& low(const point_type& point) { points_[LOW] = point; return *this; } point_type high() const { return points_[HIGH]; } segment_data& high(const point_type& point) { points_[HIGH] = point; return *this; } bool operator==(const segment_data& that) const { return (points_[0] == that.points_[0]) && (points_[1] == that.points_[1]); } bool operator!=(const segment_data& that) const { return (points_[0] != that.points_[0]) || (points_[1] != that.points_[1]); } bool operator<(const segment_data& that) const { if (points_[0] != that.points_[0]) { return points_[0] < that.points_[0]; } return points_[1] < that.points_[1]; } bool operator<=(const segment_data& that) const { return !(that < *this); } bool operator>(const segment_data& that) const { return that < *this; } bool operator>=(const segment_data& that) const { return !((*this) < that); } private: point_type points_[2]; }; template <typename CType> struct geometry_concept<segment_data<CType> > { typedef segment_concept type; }; } // polygon } // boost #endif // BOOST_POLYGON_SEGMENT_DATA_HPP PK �b�[�p�� �� rectangle_concept.hppnu �[��� /* Copyright 2008 Intel Corporation Use, modification and distribution are 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_POLYGON_RECTANGLE_CONCEPT_HPP #define BOOST_POLYGON_RECTANGLE_CONCEPT_HPP #include "isotropy.hpp" //point #include "point_data.hpp" #include "point_traits.hpp" #include "point_concept.hpp" //interval #include "interval_data.hpp" #include "interval_traits.hpp" #include "interval_concept.hpp" #include "rectangle_data.hpp" #include "rectangle_traits.hpp" namespace boost { namespace polygon{ struct rectangle_concept {}; template <typename T> struct is_rectangle_concept { typedef gtl_no type; }; template <> struct is_rectangle_concept<rectangle_concept> { typedef gtl_yes type; }; template <typename T> struct is_mutable_rectangle_concept { typedef gtl_no type; }; template <> struct is_mutable_rectangle_concept<rectangle_concept> { typedef gtl_yes type; }; template <> struct geometry_domain<rectangle_concept> { typedef manhattan_domain type; }; template <typename T, typename CT> struct rectangle_interval_type_by_concept { typedef void type; }; template <typename T> struct rectangle_interval_type_by_concept<T, gtl_yes> { typedef typename rectangle_traits<T>::interval_type type; }; template <typename T> struct rectangle_interval_type { typedef typename rectangle_interval_type_by_concept<T, typename is_rectangle_concept<typename geometry_concept<T>::type>::type>::type type; }; template <typename T, typename CT> struct rectangle_coordinate_type_by_concept { typedef void type; }; template <typename T> struct rectangle_coordinate_type_by_concept<T, gtl_yes> { typedef typename rectangle_traits<T>::coordinate_type type; }; template <typename T> struct rectangle_coordinate_type { typedef typename rectangle_coordinate_type_by_concept<T, typename is_rectangle_concept<typename geometry_concept<T>::type>::type>::type type; }; template <typename T, typename CT> struct rectangle_difference_type_by_concept { typedef void type; }; template <typename T> struct rectangle_difference_type_by_concept<T, gtl_yes> { typedef typename coordinate_traits<typename rectangle_traits<T>::coordinate_type>::coordinate_difference type; }; template <typename T> struct rectangle_difference_type { typedef typename rectangle_difference_type_by_concept< T, typename is_rectangle_concept<typename geometry_concept<T>::type>::type>::type type; }; template <typename T, typename CT> struct rectangle_distance_type_by_concept { typedef void type; }; template <typename T> struct rectangle_distance_type_by_concept<T, gtl_yes> { typedef typename coordinate_traits<typename rectangle_coordinate_type<T>::type>::coordinate_distance type; }; template <typename T> struct rectangle_distance_type { typedef typename rectangle_distance_type_by_concept< T, typename is_rectangle_concept<typename geometry_concept<T>::type>::type>::type type; }; struct y_r_get_interval : gtl_yes {}; template <typename T> typename enable_if< typename gtl_and<y_r_get_interval, typename is_rectangle_concept<typename geometry_concept<T>::type>::type>::type, typename rectangle_interval_type<T>::type>::type get(const T& rectangle, orientation_2d orient) { return rectangle_traits<T>::get(rectangle, orient); } struct y_r_h : gtl_yes {}; template <typename T> typename enable_if< typename gtl_and<y_r_h, typename is_rectangle_concept<typename geometry_concept<T>::type>::type>::type, typename rectangle_interval_type<T>::type>::type horizontal(const T& rectangle) { return rectangle_traits<T>::get(rectangle, HORIZONTAL); } struct y_r_v : gtl_yes {}; template <typename T> typename enable_if< typename gtl_and<y_r_v, typename is_rectangle_concept<typename geometry_concept<T>::type>::type>::type, typename rectangle_interval_type<T>::type>::type vertical(const T& rectangle) { return rectangle_traits<T>::get(rectangle, VERTICAL); } struct y_r_set : gtl_yes {}; template <orientation_2d_enum orient, typename T, typename T2> typename enable_if< typename gtl_and_3<y_r_set, typename is_mutable_rectangle_concept<typename geometry_concept<T>::type>::type, typename is_interval_concept<typename geometry_concept<T2>::type>::type>::type, void>::type set(T& rectangle, const T2& interval) { rectangle_mutable_traits<T>::set(rectangle, orient, interval); } struct y_r_set2 : gtl_yes {}; template <typename T, typename T2> typename enable_if< typename gtl_and_3<y_r_set2, typename is_mutable_rectangle_concept<typename geometry_concept<T>::type>::type, typename is_interval_concept<typename geometry_concept<T2>::type>::type>::type, void>::type set(T& rectangle, orientation_2d orient, const T2& interval) { rectangle_mutable_traits<T>::set(rectangle, orient, interval); } struct y_r_h2 : gtl_yes {}; template <typename T, typename T2> typename enable_if< typename gtl_and_3<y_r_h2, typename is_mutable_rectangle_concept<typename geometry_concept<T>::type>::type, typename is_interval_concept<typename geometry_concept<T2>::type>::type>::type, void>::type horizontal(T& rectangle, const T2& interval) { rectangle_mutable_traits<T>::set(rectangle, HORIZONTAL, interval); } struct y_r_v2 : gtl_yes {}; template <typename T, typename T2> typename enable_if< typename gtl_and_3<y_r_v2, typename is_mutable_rectangle_concept<typename geometry_concept<T>::type>::type, typename is_interval_concept<typename geometry_concept<T2>::type>::type>::type, void>::type vertical(T& rectangle, const T2& interval) { rectangle_mutable_traits<T>::set(rectangle, VERTICAL, interval); } struct y_r_construct : gtl_yes {}; template <typename T, typename T2, typename T3> typename enable_if< typename gtl_and<y_r_construct, typename is_mutable_rectangle_concept<typename geometry_concept<T>::type>::type>::type, T>::type construct(const T2& interval_horizontal, const T3& interval_vertical) { return rectangle_mutable_traits<T>::construct(interval_horizontal, interval_vertical); } struct y_r_construct2 : gtl_yes {}; template <typename T, typename coord_type> typename enable_if< typename gtl_and<y_r_construct2, typename is_mutable_rectangle_concept<typename geometry_concept<T>::type>::type>::type, T>::type construct(coord_type xl, coord_type yl, coord_type xh, coord_type yh) { return rectangle_mutable_traits<T>::construct(interval_data<coord_type>(xl, xh), interval_data<coord_type>(yl, yh)); } struct y_r_cconstruct : gtl_yes {}; template <typename T, typename T2> typename enable_if< typename gtl_and_3<y_r_cconstruct, typename is_mutable_rectangle_concept<typename geometry_concept<T>::type>::type, typename is_rectangle_concept<typename geometry_concept<T2>::type>::type>::type, T>::type copy_construct(const T2& rectangle) { return construct<T> (get(rectangle, HORIZONTAL), get(rectangle, VERTICAL)); } struct y_r_assign : gtl_yes {}; template <typename rectangle_type_1, typename rectangle_type_2> typename enable_if< typename gtl_and_3< y_r_assign, typename is_mutable_rectangle_concept<typename geometry_concept<rectangle_type_1>::type>::type, typename is_rectangle_concept<typename geometry_concept<rectangle_type_2>::type>::type>::type, rectangle_type_1>::type & assign(rectangle_type_1& lvalue, const rectangle_type_2& rvalue) { set(lvalue, HORIZONTAL, get(rvalue, HORIZONTAL)); set(lvalue, VERTICAL, get(rvalue, VERTICAL)); return lvalue; } struct y_r_equiv : gtl_yes {}; template <typename T, typename T2> typename enable_if< typename gtl_and_3< y_r_equiv, typename is_rectangle_concept<typename geometry_concept<T>::type>::type, typename is_rectangle_concept<typename geometry_concept<T2>::type>::type>::type, bool>::type equivalence(const T& rect1, const T2& rect2) { return equivalence(get(rect1, HORIZONTAL), get(rect2, HORIZONTAL)) && equivalence(get(rect1, VERTICAL), get(rect2, VERTICAL)); } struct y_r_get : gtl_yes {}; template <typename rectangle_type> typename enable_if< typename gtl_and<y_r_get, typename is_rectangle_concept<typename geometry_concept<rectangle_type>::type>::type>::type, typename rectangle_coordinate_type<rectangle_type>::type>::type get(const rectangle_type& rectangle, orientation_2d orient, direction_1d dir) { return get(rectangle_traits<rectangle_type>::get(rectangle, orient), dir); } struct y_r_set3 : gtl_yes {}; template <typename rectangle_type> typename enable_if<typename gtl_and<y_r_set3, typename is_mutable_rectangle_concept<typename geometry_concept<rectangle_type>::type>::type>::type, void>::type set(rectangle_type& rectangle, orientation_2d orient, direction_1d dir, typename rectangle_coordinate_type<rectangle_type>::type value) { typename rectangle_interval_type<rectangle_type>::type ivl = get(rectangle, orient); set(ivl, dir, value); set(rectangle, orient, ivl); } struct y_r_xl : gtl_yes {}; template <typename rectangle_type> typename enable_if< typename gtl_and<y_r_xl, typename is_rectangle_concept<typename geometry_concept<rectangle_type>::type>::type>::type, typename rectangle_coordinate_type<rectangle_type>::type>::type xl(const rectangle_type& rectangle) { return get(rectangle, HORIZONTAL, LOW); } struct y_r_xl2 : gtl_yes {}; template <typename rectangle_type> typename enable_if<typename gtl_and<y_r_xl2, typename is_mutable_rectangle_concept<typename geometry_concept<rectangle_type>::type>::type>::type, void>::type xl(rectangle_type& rectangle, typename rectangle_coordinate_type<rectangle_type>::type value) { return set(rectangle, HORIZONTAL, LOW, value); } struct y_r_xh : gtl_yes {}; template <typename rectangle_type> typename enable_if< typename gtl_and<y_r_xh, typename is_rectangle_concept<typename geometry_concept<rectangle_type>::type>::type>::type, typename rectangle_coordinate_type<rectangle_type>::type>::type xh(const rectangle_type& rectangle) { return get(rectangle, HORIZONTAL, HIGH); } struct y_r_xh2 : gtl_yes {}; template <typename rectangle_type> typename enable_if<typename gtl_and<y_r_xh2, typename is_mutable_rectangle_concept<typename geometry_concept<rectangle_type>::type>::type>::type, void>::type xh(rectangle_type& rectangle, typename rectangle_coordinate_type<rectangle_type>::type value) { return set(rectangle, HORIZONTAL, HIGH, value); } struct y_r_yl : gtl_yes {}; template <typename rectangle_type> typename enable_if< typename gtl_and<y_r_yl, typename is_rectangle_concept<typename geometry_concept<rectangle_type>::type>::type>::type, typename rectangle_coordinate_type<rectangle_type>::type>::type yl(const rectangle_type& rectangle) { return get(rectangle, VERTICAL, LOW); } struct y_r_yl2 : gtl_yes {}; template <typename rectangle_type> typename enable_if<typename gtl_and<y_r_yl2, typename is_mutable_rectangle_concept<typename geometry_concept<rectangle_type>::type>::type>::type, void>::type yl(rectangle_type& rectangle, typename rectangle_coordinate_type<rectangle_type>::type value) { return set(rectangle, VERTICAL, LOW, value); } struct y_r_yh : gtl_yes {}; template <typename rectangle_type> typename enable_if< typename gtl_and<y_r_yh, typename is_rectangle_concept<typename geometry_concept<rectangle_type>::type>::type>::type, typename rectangle_coordinate_type<rectangle_type>::type>::type yh(const rectangle_type& rectangle) { return get(rectangle, VERTICAL, HIGH); } struct y_r_yh2 : gtl_yes {}; template <typename rectangle_type> typename enable_if<typename gtl_and<y_r_yh2, typename is_mutable_rectangle_concept<typename geometry_concept<rectangle_type>::type>::type>::type, void>::type yh(rectangle_type& rectangle, typename rectangle_coordinate_type<rectangle_type>::type value) { return set(rectangle, VERTICAL, HIGH, value); } struct y_r_ll : gtl_yes {}; template <typename rectangle_type> typename enable_if<typename gtl_and<y_r_ll, typename is_rectangle_concept<typename geometry_concept<rectangle_type>::type>::type>::type, point_data<typename rectangle_coordinate_type<rectangle_type>::type> >::type ll(const rectangle_type& rectangle) { return point_data<typename rectangle_coordinate_type<rectangle_type>::type> (xl(rectangle), yl(rectangle)); } struct y_r_lr : gtl_yes {}; template <typename rectangle_type> typename enable_if<typename gtl_and<y_r_lr, typename is_rectangle_concept<typename geometry_concept<rectangle_type>::type>::type>::type, point_data<typename rectangle_coordinate_type<rectangle_type>::type> >::type lr(const rectangle_type& rectangle) { return point_data<typename rectangle_coordinate_type<rectangle_type>::type> (xh(rectangle), yl(rectangle)); } struct y_r_ul : gtl_yes {}; template <typename rectangle_type> typename enable_if<typename gtl_and<y_r_ul, typename is_rectangle_concept<typename geometry_concept<rectangle_type>::type>::type>::type, point_data<typename rectangle_coordinate_type<rectangle_type>::type> >::type ul(const rectangle_type& rectangle) { return point_data<typename rectangle_coordinate_type<rectangle_type>::type> (xl(rectangle), yh(rectangle)); } struct y_r_ur : gtl_yes {}; template <typename rectangle_type> typename enable_if<typename gtl_and<y_r_ur, typename is_rectangle_concept<typename geometry_concept<rectangle_type>::type>::type>::type, point_data<typename rectangle_coordinate_type<rectangle_type>::type> >::type ur(const rectangle_type& rectangle) { return point_data<typename rectangle_coordinate_type<rectangle_type>::type> (xh(rectangle), yh(rectangle)); } struct y_r_contains : gtl_yes {}; template <typename rectangle_type, typename rectangle_type_2> typename enable_if< typename gtl_and_3<y_r_contains, typename is_rectangle_concept<typename geometry_concept<rectangle_type>::type>::type, typename is_rectangle_concept<typename geometry_concept<rectangle_type_2>::type>::type>::type, bool>::type contains(const rectangle_type& rectangle, const rectangle_type_2 rectangle_contained, bool consider_touch = true) { return contains(horizontal(rectangle), horizontal(rectangle_contained), consider_touch) && contains(vertical(rectangle), vertical(rectangle_contained), consider_touch); } struct y_r_contains2 : gtl_yes {}; template <typename rectangle_type, typename point_type> typename enable_if< typename gtl_and_3<y_r_contains2, typename is_rectangle_concept<typename geometry_concept<rectangle_type>::type>::type, typename is_point_concept<typename geometry_concept<point_type>::type>::type>::type, bool>::type contains(const rectangle_type& rectangle, const point_type point_contained, bool consider_touch = true) { return contains(horizontal(rectangle), x(point_contained), consider_touch) && contains(vertical(rectangle), y(point_contained), consider_touch); } struct y_r_set_points : gtl_yes {}; // set all four coordinates based upon two points template <typename rectangle_type, typename point_type_1, typename point_type_2> typename enable_if< typename gtl_and_4< y_r_set_points, typename is_mutable_rectangle_concept<typename geometry_concept<rectangle_type>::type>::type, typename is_point_concept<typename geometry_concept<point_type_1>::type>::type, typename is_point_concept<typename geometry_concept<point_type_2>::type>::type>::type, rectangle_type>::type & set_points(rectangle_type& rectangle, const point_type_1& p1, const point_type_2& p2) { typedef typename rectangle_coordinate_type<rectangle_type>::type Unit; Unit x1(x(p1)); Unit x2(x(p2)); Unit y1(y(p1)); Unit y2(y(p2)); horizontal(rectangle, construct<typename rectangle_interval_type<rectangle_type>::type>(x1, x2)); vertical(rectangle, construct<typename rectangle_interval_type<rectangle_type>::type>(y1, y2)); return rectangle; } struct y_r_move : gtl_yes {}; // move rectangle by delta in orient template <typename rectangle_type> typename enable_if< typename gtl_and<y_r_move, typename is_mutable_rectangle_concept<typename geometry_concept<rectangle_type>::type>::type>::type, rectangle_type>::type & move(rectangle_type& rectangle, orientation_2d orient, typename coordinate_traits<typename rectangle_coordinate_type<rectangle_type>::type>::coordinate_difference delta) { typename rectangle_interval_type<rectangle_type>::type ivl = get(rectangle, orient); move(ivl, delta); set(rectangle, orient, ivl); return rectangle; } struct y_r_convolve : gtl_yes {}; // convolve this with b template <typename rectangle_type_1, typename rectangle_type_2> typename enable_if< typename gtl_and_3< y_r_convolve, typename is_mutable_rectangle_concept<typename geometry_concept<rectangle_type_1>::type>::type, typename is_rectangle_concept<typename geometry_concept<rectangle_type_2>::type>::type>::type, rectangle_type_1>::type & convolve(rectangle_type_1& rectangle, const rectangle_type_2& convolution_rectangle) { typename rectangle_interval_type<rectangle_type_1>::type ivl = horizontal(rectangle); horizontal(rectangle, convolve(ivl, horizontal(convolution_rectangle))); ivl = vertical(rectangle); vertical(rectangle, convolve(ivl, vertical(convolution_rectangle))); return rectangle; } struct y_r_deconvolve : gtl_yes {}; // deconvolve this with b template <typename rectangle_type_1, typename rectangle_type_2> typename enable_if< typename gtl_and_3< y_r_deconvolve, typename is_mutable_rectangle_concept<typename geometry_concept<rectangle_type_1>::type>::type, typename is_rectangle_concept<typename geometry_concept<rectangle_type_2>::type>::type>::type, rectangle_type_1>::type & deconvolve(rectangle_type_1& rectangle, const rectangle_type_2& convolution_rectangle) { typename rectangle_interval_type<rectangle_type_1>::type ivl = horizontal(rectangle); horizontal(rectangle, deconvolve(ivl, horizontal(convolution_rectangle))); ivl = vertical(rectangle); vertical(rectangle, deconvolve(ivl, vertical(convolution_rectangle))); return rectangle; } struct y_r_reconvolve : gtl_yes {}; // reflectedConvolve this with b template <typename rectangle_type_1, typename rectangle_type_2> typename enable_if< typename gtl_and_3<y_r_reconvolve, typename is_mutable_rectangle_concept<typename geometry_concept<rectangle_type_1>::type>::type, typename is_rectangle_concept<typename geometry_concept<rectangle_type_2>::type>::type>::type, rectangle_type_1>::type & reflected_convolve(rectangle_type_1& rectangle, const rectangle_type_2& convolution_rectangle) { typename rectangle_interval_type<rectangle_type_1>::type ivl = horizontal(rectangle); horizontal(rectangle, reflected_convolve(ivl, horizontal(convolution_rectangle))); ivl = vertical(rectangle); vertical(rectangle, reflected_convolve(ivl, vertical(convolution_rectangle))); return rectangle; } struct y_r_redeconvolve : gtl_yes {}; // reflectedDeconvolve this with b // deconvolve this with b template <typename rectangle_type_1, typename rectangle_type_2> typename enable_if< typename gtl_and_3<y_r_redeconvolve, typename is_mutable_rectangle_concept<typename geometry_concept<rectangle_type_1>::type>::type, typename is_rectangle_concept<typename geometry_concept<rectangle_type_2>::type>::type>::type, rectangle_type_1>::type & reflected_deconvolve(rectangle_type_1& rectangle, const rectangle_type_2& convolution_rectangle) { typename rectangle_interval_type<rectangle_type_1>::type ivl = horizontal(rectangle); horizontal(rectangle, reflected_deconvolve(ivl, horizontal(convolution_rectangle))); ivl = vertical(rectangle); vertical(rectangle, reflected_deconvolve(ivl, vertical(convolution_rectangle))); return rectangle; } struct y_r_convolve2 : gtl_yes {}; // convolve with point template <typename rectangle_type, typename point_type> typename enable_if< typename gtl_and_3<y_r_convolve2, typename is_mutable_rectangle_concept<typename geometry_concept<rectangle_type>::type>::type, typename is_point_concept<typename geometry_concept<point_type>::type>::type>::type, rectangle_type>::type & convolve(rectangle_type& rectangle, const point_type& convolution_point) { typename rectangle_interval_type<rectangle_type>::type ivl = horizontal(rectangle); horizontal(rectangle, convolve(ivl, x(convolution_point))); ivl = vertical(rectangle); vertical(rectangle, convolve(ivl, y(convolution_point))); return rectangle; } struct y_r_deconvolve2 : gtl_yes {}; // deconvolve with point template <typename rectangle_type, typename point_type> typename enable_if< typename gtl_and_3<y_r_deconvolve2, typename is_mutable_rectangle_concept<typename geometry_concept<rectangle_type>::type>::type, typename is_point_concept<typename geometry_concept<point_type>::type>::type>::type, rectangle_type>::type & deconvolve(rectangle_type& rectangle, const point_type& convolution_point) { typename rectangle_interval_type<rectangle_type>::type ivl = horizontal(rectangle); horizontal(rectangle, deconvolve(ivl, x(convolution_point))); ivl = vertical(rectangle); vertical(rectangle, deconvolve(ivl, y(convolution_point))); return rectangle; } struct y_r_delta : gtl_yes {}; // get the magnitude of the interval range depending on orient template <typename rectangle_type> typename enable_if< typename gtl_and<y_r_delta, typename is_rectangle_concept<typename geometry_concept<rectangle_type>::type>::type>::type, typename rectangle_difference_type<rectangle_type>::type>::type delta(const rectangle_type& rectangle, orientation_2d orient) { return delta(get(rectangle, orient)); } struct y_r_area : gtl_yes {}; // get the area of the rectangle template <typename rectangle_type> typename enable_if< typename gtl_and<y_r_area, typename is_rectangle_concept<typename geometry_concept<rectangle_type>::type>::type>::type, typename coordinate_traits<typename rectangle_coordinate_type<rectangle_type>::type>::manhattan_area_type>::type area(const rectangle_type& rectangle) { typedef typename coordinate_traits<typename rectangle_coordinate_type<rectangle_type>::type>::manhattan_area_type area_type; return (area_type)delta(rectangle, HORIZONTAL) * (area_type)delta(rectangle, VERTICAL); } struct y_r_go : gtl_yes {}; // returns the orientation of the longest side template <typename rectangle_type> typename enable_if<typename gtl_and<y_r_go, typename is_rectangle_concept<typename geometry_concept<rectangle_type>::type>::type>::type, orientation_2d>::type guess_orientation(const rectangle_type& rectangle) { return delta(rectangle, HORIZONTAL) >= delta(rectangle, VERTICAL) ? HORIZONTAL : VERTICAL; } struct y_r_half_p : gtl_yes {}; // get the half perimeter of the rectangle template <typename rectangle_type> typename enable_if< typename gtl_and<y_r_half_p, typename is_rectangle_concept<typename geometry_concept<rectangle_type>::type>::type>::type, typename rectangle_difference_type<rectangle_type>::type>::type half_perimeter(const rectangle_type& rectangle) { return delta(rectangle, HORIZONTAL) + delta(rectangle, VERTICAL); } struct y_r_perimeter : gtl_yes {}; // get the perimeter of the rectangle template <typename rectangle_type> typename enable_if< typename gtl_and<y_r_perimeter, typename is_rectangle_concept<typename geometry_concept<rectangle_type>::type>::type>::type, typename rectangle_difference_type<rectangle_type>::type>::type perimeter(const rectangle_type& rectangle) { return 2 * half_perimeter(rectangle); } struct y_r_intersects : gtl_yes {}; // check if Rectangle b intersects `this` Rectangle // [in] b Rectangle that will be checked // [in] considerTouch If true, return true even if b touches the boundary // [ret] . true if `t` intersects b template <typename rectangle_type_1, typename rectangle_type_2> typename enable_if< typename gtl_and_3<y_r_intersects, typename is_rectangle_concept<typename geometry_concept<rectangle_type_1>::type>::type, typename is_rectangle_concept<typename geometry_concept<rectangle_type_2>::type>::type>::type, bool>::type intersects(const rectangle_type_1& rectangle, const rectangle_type_2& b, bool consider_touch = true) { return intersects(horizontal(rectangle), horizontal(b), consider_touch) && intersects(vertical(rectangle), vertical(b), consider_touch); } struct y_r_b_intersect : gtl_yes {}; // Check if boundaries of Rectangle b and `this` Rectangle intersect // [in] b Rectangle that will be checked // [in] considerTouch If true, return true even if p is on the foundary // [ret] . true if `t` contains p template <typename rectangle_type_1, typename rectangle_type_2> typename enable_if< typename gtl_and_3<y_r_b_intersect, typename is_rectangle_concept<typename geometry_concept<rectangle_type_1>::type>::type, typename is_rectangle_concept<typename geometry_concept<rectangle_type_2>::type>::type>::type, bool>::type boundaries_intersect(const rectangle_type_1& rectangle, const rectangle_type_2& b, bool consider_touch = true) { return (intersects(rectangle, b, consider_touch) && !(contains(rectangle, b, !consider_touch)) && !(contains(b, rectangle, !consider_touch))); } struct y_r_b_abuts : gtl_yes {}; // check if b is touching 'this' on the end specified by dir template <typename rectangle_type_1, typename rectangle_type_2> typename enable_if< typename gtl_and_3<y_r_b_abuts, typename is_rectangle_concept<typename geometry_concept<rectangle_type_1>::type>::type, typename is_rectangle_concept<typename geometry_concept<rectangle_type_2>::type>::type>::type, bool>::type abuts(const rectangle_type_1& rectangle, const rectangle_type_2& b, direction_2d dir) { return abuts(get(rectangle, orientation_2d(dir)), get(b, orientation_2d(dir)), direction_1d(dir)) && intersects(get(rectangle, orientation_2d(dir).get_perpendicular()), get(b, orientation_2d(dir).get_perpendicular()), true); } struct y_r_b_abuts2 : gtl_yes {}; // check if they are touching in the given orientation template <typename rectangle_type_1, typename rectangle_type_2> typename enable_if< typename gtl_and_3<y_r_b_abuts2, typename is_rectangle_concept<typename geometry_concept<rectangle_type_1>::type>::type, typename is_rectangle_concept<typename geometry_concept<rectangle_type_2>::type>::type>::type, bool>::type abuts(const rectangle_type_1& rectangle, const rectangle_type_2& b, orientation_2d orient) { return abuts(get(rectangle, orient), get(b, orient)) && intersects(get(rectangle, orient.get_perpendicular()), get(b, orient.get_perpendicular()), true); } struct y_r_b_abuts3 : gtl_yes {}; // check if they are touching but not overlapping template <typename rectangle_type_1, typename rectangle_type_2> typename enable_if< typename gtl_and_3<y_r_b_abuts3, typename is_rectangle_concept<typename geometry_concept<rectangle_type_1>::type>::type, typename is_rectangle_concept<typename geometry_concept<rectangle_type_2>::type>::type>::type, bool>::type abuts(const rectangle_type_1& rectangle, const rectangle_type_2& b) { return abuts(rectangle, b, HORIZONTAL) || abuts(rectangle, b, VERTICAL); } struct y_r_b_intersect2 : gtl_yes {}; // intersect rectangle with interval on orient template <typename rectangle_type, typename interval_type> typename enable_if< typename gtl_and_3<y_r_b_intersect2, typename is_mutable_rectangle_concept<typename geometry_concept<rectangle_type>::type>::type, typename is_interval_concept<typename geometry_concept<interval_type>::type>::type>::type, bool>::type intersect(rectangle_type& rectangle, const interval_type& b, orientation_2d orient, bool consider_touch = true) { typename rectangle_interval_type<rectangle_type>::type ivl = get(rectangle, orient); if(intersect(ivl, b, consider_touch)) { set(rectangle, orient, ivl); return true; } return false; } struct y_r_b_intersect3 : gtl_yes {}; // clip rectangle to b template <typename rectangle_type_1, typename rectangle_type_2> typename enable_if< typename gtl_and_3<y_r_b_intersect3, typename is_mutable_rectangle_concept<typename geometry_concept<rectangle_type_1>::type>::type, typename is_rectangle_concept<typename geometry_concept<rectangle_type_2>::type>::type>::type, bool>::type intersect(rectangle_type_1& rectangle, const rectangle_type_2& b, bool consider_touch = true) { if(intersects(rectangle, b)) { intersect(rectangle, horizontal(b), HORIZONTAL, consider_touch); intersect(rectangle, vertical(b), VERTICAL, consider_touch); return true; } return false; } struct y_r_g_intersect : gtl_yes {}; // Sets this to the generalized intersection of this and the given rectangle template <typename rectangle_type_1, typename rectangle_type_2> typename enable_if< typename gtl_and_3<y_r_g_intersect, typename is_mutable_rectangle_concept<typename geometry_concept<rectangle_type_1>::type>::type, typename is_rectangle_concept<typename geometry_concept<rectangle_type_2>::type>::type>::type, rectangle_type_1>::type & generalized_intersect(rectangle_type_1& rectangle, const rectangle_type_2& b) { typename rectangle_interval_type<rectangle_type_1>::type ivl = get(rectangle, HORIZONTAL); generalized_intersect(ivl, horizontal(b)); horizontal(rectangle, ivl); ivl = vertical(rectangle); generalized_intersect(ivl, vertical(b)); vertical(rectangle, ivl); return rectangle; } struct y_r_bloat : gtl_yes {}; // bloat the interval specified by orient by bloating template <typename rectangle_type> typename enable_if<typename gtl_and<y_r_bloat, typename is_rectangle_concept<typename geometry_concept<rectangle_type>::type>::type>::type, rectangle_type>::type & bloat(rectangle_type& rectangle, orientation_2d orient, typename rectangle_coordinate_type<rectangle_type>::type bloating) { typename rectangle_interval_type<rectangle_type>::type ivl = get(rectangle, orient); bloat(ivl, bloating); set(rectangle, orient, ivl); return rectangle; } struct y_r_bloat2 : gtl_yes {}; // bloat the Rectangle by bloating template <typename rectangle_type> typename enable_if<typename gtl_and<y_r_bloat2, typename is_rectangle_concept<typename geometry_concept<rectangle_type>::type>::type>::type, rectangle_type>::type & bloat(rectangle_type& rectangle, typename rectangle_coordinate_type<rectangle_type>::type bloating) { bloat(rectangle, HORIZONTAL, bloating); return bloat(rectangle, VERTICAL, bloating); } struct y_r_bloat3 : gtl_yes {}; // bloat the interval cooresponding to orient by bloating in dir direction template <typename rectangle_type> typename enable_if<typename gtl_and<y_r_bloat3, typename is_rectangle_concept<typename geometry_concept<rectangle_type>::type>::type>::type, rectangle_type>::type & bloat(rectangle_type& rectangle, direction_2d dir, typename rectangle_coordinate_type<rectangle_type>::type bloating) { typename rectangle_interval_type<rectangle_type>::type ivl = get(rectangle, orientation_2d(dir)); bloat(ivl, direction_1d(dir), bloating); set(rectangle, orientation_2d(dir), ivl); return rectangle; } struct y_r_shrink : gtl_yes {}; // shrink the interval specified by orient by bloating template <typename rectangle_type> typename enable_if<typename gtl_and<y_r_shrink, typename is_rectangle_concept<typename geometry_concept<rectangle_type>::type>::type>::type, rectangle_type>::type & shrink(rectangle_type& rectangle, orientation_2d orient, typename rectangle_coordinate_type<rectangle_type>::type shrinking) { return bloat(rectangle, orient, -shrinking); } struct y_r_shrink2 : gtl_yes {}; // shrink the Rectangle by bloating template <typename rectangle_type> typename enable_if<typename gtl_and<y_r_shrink2, typename is_rectangle_concept<typename geometry_concept<rectangle_type>::type>::type>::type, rectangle_type>::type & shrink(rectangle_type& rectangle, typename rectangle_coordinate_type<rectangle_type>::type shrinking) { return bloat(rectangle, -shrinking); } struct y_r_shrink3 : gtl_yes {}; // shrink the interval cooresponding to orient by bloating in dir direction template <typename rectangle_type> typename enable_if<typename gtl_and<y_r_shrink3, typename is_rectangle_concept<typename geometry_concept<rectangle_type>::type>::type>::type, rectangle_type>::type & shrink(rectangle_type& rectangle, direction_2d dir, typename rectangle_coordinate_type<rectangle_type>::type shrinking) { return bloat(rectangle, dir, -shrinking); } struct y_r_encompass : gtl_yes {}; // encompass interval on orient template <typename rectangle_type, typename interval_type> typename enable_if<typename gtl_and_3< y_r_encompass, typename is_mutable_rectangle_concept<typename geometry_concept<rectangle_type>::type>::type, typename is_interval_concept<typename geometry_concept<interval_type>::type>::type>::type, bool>::type encompass(rectangle_type& rectangle, const interval_type& b, orientation_2d orient) { typename rectangle_interval_type<rectangle_type>::type ivl = get(rectangle, orient); if(encompass(ivl, b)) { set(rectangle, orient, ivl); return true; } return false; } struct y_r_encompass2 : gtl_yes {}; // enlarge rectangle to encompass the Rectangle b template <typename rectangle_type_1, typename rectangle_type_2> typename enable_if< typename gtl_and_3< y_r_encompass2, typename is_mutable_rectangle_concept<typename geometry_concept<rectangle_type_1>::type>::type, typename is_rectangle_concept<typename geometry_concept<rectangle_type_2>::type>::type >::type, bool>::type encompass(rectangle_type_1& rectangle, const rectangle_type_2& b) { //note that operator | is intentional because both should be called regardless return encompass(rectangle, horizontal(b), HORIZONTAL) | encompass(rectangle, vertical(b), VERTICAL); } struct y_r_encompass3 : gtl_yes {}; // enlarge rectangle to encompass the point b template <typename rectangle_type_1, typename point_type> typename enable_if<typename gtl_and_3< y_r_encompass3, typename is_mutable_rectangle_concept<typename geometry_concept<rectangle_type_1>::type>::type, typename is_point_concept<typename geometry_concept<point_type>::type>::type>::type, bool>::type encompass(rectangle_type_1& rectangle, const point_type& b) { typename rectangle_interval_type<rectangle_type_1>::type hivl, vivl; hivl = horizontal(rectangle); vivl = vertical(rectangle); //note that operator | is intentional because both should be called regardless bool retval = encompass(hivl, x(b)) | encompass(vivl, y(b)); if(retval) { horizontal(rectangle, hivl); vertical(rectangle, vivl); } return retval; } struct y_r_center : gtl_yes {}; // returns the center of the rectangle template <typename point_type, typename rectangle_type> typename enable_if< typename gtl_and_3<y_r_center, typename is_mutable_point_concept<typename geometry_concept<point_type>::type>::type, typename is_rectangle_concept<typename geometry_concept<rectangle_type>::type>::type>::type, bool>::type center(point_type& center_point, const rectangle_type& rectangle) { center_point = construct<point_type>(center(horizontal(rectangle)), center(vertical(rectangle))); return true; } struct y_r_get_corner : gtl_yes {}; template <typename point_type, typename rectangle_type> typename enable_if< typename gtl_and_3<y_r_get_corner, typename is_mutable_point_concept<typename geometry_concept<point_type>::type>::type, typename is_rectangle_concept<typename geometry_concept<rectangle_type>::type>::type>::type, bool>::type get_corner(point_type& corner_point, const rectangle_type& rectangle, direction_2d direction_facing, direction_1d direction_turning) { typedef typename rectangle_coordinate_type<rectangle_type>::type Unit; Unit u1 = get(rectangle, direction_facing); Unit u2 = get(rectangle, direction_facing.turn(direction_turning)); if(orientation_2d(direction_facing).to_int()) std::swap(u1, u2); corner_point = construct<point_type>(u1, u2); return true; } struct y_r_get_half : gtl_yes {}; template <typename rectangle_type> typename enable_if<typename gtl_and<y_r_get_half, typename is_mutable_rectangle_concept<typename geometry_concept<rectangle_type>::type>::type>::type, rectangle_type>::type get_half(const rectangle_type& rectangle, direction_2d dir) { rectangle_type retval(rectangle); set(retval, orientation_2d(dir), get_half(get(rectangle, orientation_2d(dir)), direction_1d(dir))); return retval; } struct y_r_join_with : gtl_yes {}; template <typename rectangle_type_1, typename rectangle_type_2> typename enable_if< typename gtl_and_3<y_r_join_with, typename is_mutable_rectangle_concept<typename geometry_concept<rectangle_type_1>::type>::type, typename is_rectangle_concept<typename geometry_concept<rectangle_type_2>::type>::type>::type, bool>::type join_with(rectangle_type_1& rectangle, const rectangle_type_2& b) { typedef typename rectangle_interval_type<rectangle_type_1>::type Interval1; typedef typename rectangle_interval_type<rectangle_type_2>::type Interval2; Interval1 hi1 = get(rectangle, HORIZONTAL); Interval1 vi1 = get(rectangle, VERTICAL); Interval2 hi2 = get(b, HORIZONTAL), vi2 = get(b, VERTICAL); Interval1 temp; if (equivalence(hi1, hi2) && join_with(vi1, vi2)) { vertical(rectangle, vi1); return true; } if (equivalence(vi1, vi2) && join_with(hi1, hi2)) { horizontal(rectangle, hi1); return true; } return false; } struct y_r_eda2 : gtl_yes {}; template <typename rectangle_type, typename point_type> typename enable_if< typename gtl_and_3<y_r_eda2, typename is_rectangle_concept<typename geometry_concept<rectangle_type>::type>::type, typename is_point_concept<typename geometry_concept<point_type>::type>::type>::type, typename rectangle_difference_type<rectangle_type>::type>::type euclidean_distance(const rectangle_type& lvalue, const point_type& rvalue, orientation_2d orient) { return euclidean_distance(get(lvalue, orient), get(rvalue, orient)); } struct y_r_eda : gtl_yes {}; template <typename rectangle_type, typename rectangle_type_2> typename enable_if< typename gtl_and_3<y_r_eda, typename is_rectangle_concept<typename geometry_concept<rectangle_type>::type>::type, typename is_rectangle_concept<typename geometry_concept<rectangle_type_2>::type>::type>::type, typename rectangle_difference_type<rectangle_type>::type>::type euclidean_distance(const rectangle_type& lvalue, const rectangle_type_2& rvalue, orientation_2d orient) { return euclidean_distance(get(lvalue, orient), get(rvalue, orient)); } struct y_r_sed : gtl_yes {}; template <typename rectangle_type, typename point_type> typename enable_if< typename gtl_and_3<y_r_sed, typename is_rectangle_concept<typename geometry_concept<rectangle_type>::type>::type, typename is_point_concept<typename geometry_concept<point_type>::type>::type>::type, typename rectangle_difference_type<rectangle_type>::type>::type square_euclidean_distance(rectangle_type& lvalue, const point_type& rvalue) { typename coordinate_traits<typename rectangle_coordinate_type<rectangle_type>::type>::coordinate_difference xdist, ydist; xdist = euclidean_distance(lvalue, rvalue, HORIZONTAL); ydist = euclidean_distance(lvalue, rvalue, VERTICAL); return (xdist * xdist) + (ydist * ydist); } struct y_r_sed2 : gtl_yes {}; template <typename rectangle_type, typename rectangle_type_2> typename enable_if< typename gtl_and_3<y_r_sed2, typename is_rectangle_concept< typename geometry_concept<rectangle_type>::type>::type, typename is_rectangle_concept< typename geometry_concept<rectangle_type_2>::type>::type>::type, typename rectangle_difference_type<rectangle_type>::type>::type square_euclidean_distance(const rectangle_type& lvalue, const rectangle_type_2& rvalue) { typename coordinate_traits<typename rectangle_coordinate_type<rectangle_type>::type>::coordinate_difference xdist, ydist; xdist = euclidean_distance(lvalue, rvalue, HORIZONTAL); ydist = euclidean_distance(lvalue, rvalue, VERTICAL); return (xdist * xdist) + (ydist * ydist); } struct y_r_edist : gtl_yes {}; template <typename rectangle_type, typename point_type> typename enable_if< typename gtl_and_3<y_r_edist, typename is_rectangle_concept<typename geometry_concept<rectangle_type>::type>::type, typename is_point_concept<typename geometry_concept<point_type>::type>::type>::type, typename rectangle_distance_type<rectangle_type>::type>::type euclidean_distance(rectangle_type& lvalue, const point_type& rvalue) { return std::sqrt((double)(square_euclidean_distance(lvalue, rvalue))); } struct y_r_edist2 : gtl_yes {}; template <typename rectangle_type, typename rectangle_type_2> typename enable_if< typename gtl_and_3<y_r_edist2, typename is_rectangle_concept<typename geometry_concept<rectangle_type>::type>::type, typename is_rectangle_concept<typename geometry_concept<rectangle_type_2>::type>::type>::type, typename rectangle_distance_type<rectangle_type>::type>::type euclidean_distance(const rectangle_type& lvalue, const rectangle_type_2& rvalue) { double val = (int)square_euclidean_distance(lvalue, rvalue); return std::sqrt(val); } struct y_r_mdist : gtl_yes {}; template <typename rectangle_type, typename point_type> typename enable_if< typename gtl_and_3<y_r_mdist, typename is_rectangle_concept<typename geometry_concept<rectangle_type>::type>::type, typename is_point_concept<typename geometry_concept<point_type>::type>::type>::type, typename rectangle_difference_type<rectangle_type>::type>::type manhattan_distance(rectangle_type& lvalue, const point_type& rvalue) { typename coordinate_traits<typename rectangle_coordinate_type<rectangle_type>::type>::coordinate_difference xdist, ydist; xdist = euclidean_distance(lvalue, rvalue, HORIZONTAL); ydist = euclidean_distance(lvalue, rvalue, VERTICAL); return xdist + ydist; } struct y_r_mdist2 : gtl_yes {}; template <typename rectangle_type, typename rectangle_type_2> typename enable_if< typename gtl_and_3<y_r_mdist2, typename is_rectangle_concept<typename geometry_concept<rectangle_type>::type>::type, typename is_rectangle_concept<typename geometry_concept<rectangle_type_2>::type>::type>::type, typename rectangle_difference_type<rectangle_type>::type>::type manhattan_distance(const rectangle_type& lvalue, const rectangle_type_2& rvalue) { typename coordinate_traits<typename rectangle_coordinate_type<rectangle_type>::type>::coordinate_difference xdist, ydist; xdist = euclidean_distance(lvalue, rvalue, HORIZONTAL); ydist = euclidean_distance(lvalue, rvalue, VERTICAL); return xdist + ydist; } struct y_r_scale_up : gtl_yes {}; template <typename rectangle_type> typename enable_if<typename gtl_and<y_r_scale_up, typename is_mutable_rectangle_concept<typename geometry_concept<rectangle_type>::type>::type>::type, rectangle_type>::type & scale_up(rectangle_type& rectangle, typename coordinate_traits<typename rectangle_coordinate_type<rectangle_type>::type>::unsigned_area_type factor) { typename rectangle_interval_type<rectangle_type>::type h = horizontal(rectangle); horizontal(rectangle, scale_up(h, factor)); typename rectangle_interval_type<rectangle_type>::type v = vertical(rectangle); vertical(rectangle, scale_up(v, factor)); return rectangle; } struct y_r_scale_down : gtl_yes {}; template <typename rectangle_type> typename enable_if<typename gtl_and<y_r_scale_down, typename is_mutable_rectangle_concept<typename geometry_concept<rectangle_type>::type>::type>::type, rectangle_type>::type & scale_down(rectangle_type& rectangle, typename coordinate_traits<typename rectangle_coordinate_type<rectangle_type>::type>::unsigned_area_type factor) { typename rectangle_interval_type<rectangle_type>::type h = horizontal(rectangle); horizontal(rectangle, scale_down(h, factor)); typename rectangle_interval_type<rectangle_type>::type v = vertical(rectangle); vertical(rectangle, scale_down(v, factor)); return rectangle; } struct y_r_scale : gtl_yes {}; template <typename rectangle_type, typename scaling_type> typename enable_if<typename gtl_and<y_r_scale, typename is_mutable_rectangle_concept<typename geometry_concept<rectangle_type>::type>::type>::type, rectangle_type>::type & scale(rectangle_type& rectangle, const scaling_type& scaling) { point_data<typename rectangle_coordinate_type<rectangle_type>::type> llp(xl(rectangle), yl(rectangle)); point_data<typename rectangle_coordinate_type<rectangle_type>::type> urp(xl(rectangle), yl(rectangle)); scale(llp, scaling); scale(urp, scaling); set_points(rectangle, llp, urp); return rectangle; } struct y_r_transform : gtl_yes {}; template <typename rectangle_type, typename transformation_type> typename enable_if<typename gtl_and<y_r_transform, typename is_mutable_rectangle_concept<typename geometry_concept<rectangle_type>::type>::type>::type, rectangle_type>::type & transform(rectangle_type& rectangle, const transformation_type& transformation) { point_data<typename rectangle_coordinate_type<rectangle_type>::type> llp(xl(rectangle), yl(rectangle)); point_data<typename rectangle_coordinate_type<rectangle_type>::type> urp(xh(rectangle), yh(rectangle)); transform(llp, transformation); transform(urp, transformation); set_points(rectangle, llp, urp); return rectangle; } template <typename rectangle_type_1, typename rectangle_type_2> class less_rectangle_concept { private: orientation_2d orient_; public: inline less_rectangle_concept(orientation_2d orient = VERTICAL) : orient_(orient) {} typename enable_if< typename gtl_and< typename is_rectangle_concept<typename geometry_concept<rectangle_type_1>::type>::type, typename is_rectangle_concept<typename geometry_concept<rectangle_type_2>::type>::type>::type, bool>::type operator () (const rectangle_type_1& a, const rectangle_type_2& b) const { typedef typename rectangle_coordinate_type<rectangle_type_1>::type Unit; Unit vl1 = get(get(a, orient_), LOW); Unit vl2 = get(get(b, orient_), LOW); if(vl1 > vl2) return false; if(vl1 == vl2) { orientation_2d perp = orient_.get_perpendicular(); Unit hl1 = get(get(a, perp), LOW); Unit hl2 = get(get(b, perp), LOW); if(hl1 > hl2) return false; if(hl1 == hl2) { Unit vh1 = get(get(a, orient_), HIGH); Unit vh2 = get(get(b, orient_), HIGH); if(vh1 > vh2) return false; if(vh1 == vh2) { Unit hh1 = get(get(a, perp), HIGH); Unit hh2 = get(get(b, perp), HIGH); return hh1 < hh2; } } } return true; } }; template <typename T> template <typename interval_type_1> inline void rectangle_data<T>::set(orientation_2d orient, const interval_type_1& interval) { assign(ranges_[orient.to_int()], interval); } template <class T> template <class T2> rectangle_data<T>& rectangle_data<T>::operator=(const T2& rvalue) { assign(*this, rvalue); return *this; } template <class T> template <class T2> bool rectangle_data<T>::operator==(const T2& rvalue) const { return equivalence(*this, rvalue); } template <typename T> struct geometry_concept<rectangle_data<T> > { typedef rectangle_concept type; }; } } #endif PK �b�[7!��g �g polygon_set_concept.hppnu �[��� /* Copyright 2008 Intel Corporation Use, modification and distribution are 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_POLYGON_POLYGON_SET_CONCEPT_HPP #define BOOST_POLYGON_POLYGON_SET_CONCEPT_HPP #include "polygon_set_data.hpp" #include "detail/polygon_simplify.hpp" namespace boost { namespace polygon{ template <typename T, typename T2> struct is_either_polygon_set_type { typedef typename gtl_or<typename is_polygon_set_type<T>::type, typename is_polygon_set_type<T2>::type >::type type; }; template <typename T> struct is_any_polygon_set_type { typedef typename gtl_or<typename is_polygon_45_or_90_set_type<T>::type, typename is_polygon_set_type<T>::type >::type type; }; template <typename polygon_set_type> typename enable_if< typename is_any_polygon_set_type<polygon_set_type>::type, typename polygon_set_traits<polygon_set_type>::iterator_type>::type begin_polygon_set_data(const polygon_set_type& polygon_set) { return polygon_set_traits<polygon_set_type>::begin(polygon_set); } template <typename polygon_set_type> typename enable_if< typename is_any_polygon_set_type<polygon_set_type>::type, typename polygon_set_traits<polygon_set_type>::iterator_type>::type end_polygon_set_data(const polygon_set_type& polygon_set) { return polygon_set_traits<polygon_set_type>::end(polygon_set); } template <typename polygon_set_type> typename enable_if< typename is_polygon_set_type<polygon_set_type>::type, bool>::type clean(const polygon_set_type& polygon_set) { return polygon_set_traits<polygon_set_type>::clean(polygon_set); } //assign template <typename polygon_set_type_1, typename polygon_set_type_2> typename enable_if< typename gtl_and< typename is_mutable_polygon_set_type<polygon_set_type_1>::type, typename is_any_polygon_set_type<polygon_set_type_2>::type>::type, polygon_set_type_1>::type & assign(polygon_set_type_1& lvalue, const polygon_set_type_2& rvalue) { if(clean(rvalue)) polygon_set_mutable_traits<polygon_set_type_1>::set(lvalue, begin_polygon_set_data(rvalue), end_polygon_set_data(rvalue)); else { polygon_set_data<typename polygon_set_traits<polygon_set_type_2>::coordinate_type> ps; ps.insert(begin_polygon_set_data(rvalue), end_polygon_set_data(rvalue)); ps.clean(); polygon_set_mutable_traits<polygon_set_type_1>::set(lvalue, ps.begin(), ps.end()); } return lvalue; } //get trapezoids template <typename output_container_type, typename polygon_set_type> typename enable_if< typename is_mutable_polygon_set_type<polygon_set_type>::type, void>::type get_trapezoids(output_container_type& output, const polygon_set_type& polygon_set) { polygon_set_data<typename polygon_set_traits<polygon_set_type>::coordinate_type> ps; assign(ps, polygon_set); ps.get_trapezoids(output); } //get trapezoids template <typename output_container_type, typename polygon_set_type> typename enable_if< typename is_mutable_polygon_set_type<polygon_set_type>::type, void>::type get_trapezoids(output_container_type& output, const polygon_set_type& polygon_set, orientation_2d orient) { polygon_set_data<typename polygon_set_traits<polygon_set_type>::coordinate_type> ps; assign(ps, polygon_set); ps.get_trapezoids(output, orient); } //equivalence template <typename polygon_set_type_1, typename polygon_set_type_2> typename enable_if< typename gtl_and_3 < typename is_any_polygon_set_type<polygon_set_type_1>::type, typename is_any_polygon_set_type<polygon_set_type_2>::type, typename is_either_polygon_set_type<polygon_set_type_1, polygon_set_type_2>::type>::type, bool>::type equivalence(const polygon_set_type_1& lvalue, const polygon_set_type_2& rvalue) { polygon_set_data<typename polygon_set_traits<polygon_set_type_1>::coordinate_type> ps1; assign(ps1, lvalue); polygon_set_data<typename polygon_set_traits<polygon_set_type_2>::coordinate_type> ps2; assign(ps2, rvalue); return ps1 == ps2; } //clear template <typename polygon_set_type> typename enable_if< typename is_mutable_polygon_set_type<polygon_set_type>::type, void>::type clear(polygon_set_type& polygon_set) { polygon_set_data<typename polygon_set_traits<polygon_set_type>::coordinate_type> ps; assign(polygon_set, ps); } //empty template <typename polygon_set_type> typename enable_if< typename is_mutable_polygon_set_type<polygon_set_type>::type, bool>::type empty(const polygon_set_type& polygon_set) { if(clean(polygon_set)) return begin_polygon_set_data(polygon_set) == end_polygon_set_data(polygon_set); polygon_set_data<typename polygon_set_traits<polygon_set_type>::coordinate_type> ps; assign(ps, polygon_set); ps.clean(); return ps.empty(); } //extents template <typename polygon_set_type, typename rectangle_type> typename enable_if< typename gtl_and< typename is_mutable_polygon_set_type<polygon_set_type>::type, typename is_mutable_rectangle_concept<typename geometry_concept<rectangle_type>::type>::type>::type, bool>::type extents(rectangle_type& extents_rectangle, const polygon_set_type& polygon_set) { clean(polygon_set); polygon_set_data<typename polygon_set_traits<polygon_set_type>::coordinate_type> ps; assign(ps, polygon_set); return ps.extents(extents_rectangle); } //area template <typename polygon_set_type> typename enable_if< typename is_mutable_polygon_set_type<polygon_set_type>::type, typename coordinate_traits<typename polygon_set_traits<polygon_set_type>::coordinate_type>::area_type>::type area(const polygon_set_type& polygon_set) { typedef typename polygon_set_traits<polygon_set_type>::coordinate_type Unit; typedef polygon_with_holes_data<Unit> p_type; typedef typename coordinate_traits<Unit>::area_type area_type; std::vector<p_type> polys; assign(polys, polygon_set); area_type retval = (area_type)0; for(std::size_t i = 0; i < polys.size(); ++i) { retval += area(polys[i]); } return retval; } template <typename polygon_set_type> typename enable_if< typename is_mutable_polygon_set_type<polygon_set_type>::type, std::size_t>::type simplify(polygon_set_type& polygon_set, typename coordinate_traits< typename polygon_set_traits<polygon_set_type>::coordinate_type >::coordinate_distance threshold) { typedef typename polygon_set_traits<polygon_set_type>::coordinate_type Unit; typedef polygon_with_holes_data<Unit> p_type; std::vector<p_type> polys; assign(polys, polygon_set); std::size_t retval = 0; for(std::size_t i = 0; i < polys.size(); ++i) { retval += detail::simplify_detail::simplify(polys[i].self_.coords_, polys[i].self_.coords_, threshold); for(typename std::list<polygon_data<Unit> >::iterator itrh = polys[i].holes_.begin(); itrh != (polys[i].holes_.end()); ++itrh) { retval += detail::simplify_detail::simplify((*itrh).coords_, (*itrh).coords_, threshold); } } assign(polygon_set, polys); return retval; } template <typename polygon_set_type, typename coord_type> typename enable_if< typename is_mutable_polygon_set_type<polygon_set_type>::type, polygon_set_type>::type & resize(polygon_set_type& polygon_set, coord_type resizing, bool corner_fill_arcs = false, int num_circle_segments = 0) { typedef typename polygon_set_traits<polygon_set_type>::coordinate_type Unit; clean(polygon_set); polygon_set_data<Unit> ps; assign(ps, polygon_set); ps.resize(resizing, corner_fill_arcs,num_circle_segments); assign(polygon_set, ps); return polygon_set; } template <typename polygon_set_type> typename enable_if< typename is_mutable_polygon_set_type<polygon_set_type>::type, polygon_set_type>::type & bloat(polygon_set_type& polygon_set, typename coordinate_traits<typename polygon_set_traits<polygon_set_type>::coordinate_type>::unsigned_area_type bloating) { return resize(polygon_set, bloating); } template <typename polygon_set_type> typename enable_if< typename is_mutable_polygon_set_type<polygon_set_type>::type, polygon_set_type>::type & shrink(polygon_set_type& polygon_set, typename coordinate_traits<typename polygon_set_traits<polygon_set_type>::coordinate_type>::unsigned_area_type shrinking) { return resize(polygon_set, -(typename polygon_set_traits<polygon_set_type>::coordinate_type)shrinking); } //interact template <typename polygon_set_type_1, typename polygon_set_type_2> typename enable_if< typename gtl_and_3 < typename is_any_polygon_set_type<polygon_set_type_1>::type, typename is_any_polygon_set_type<polygon_set_type_2>::type, typename is_either_polygon_set_type<polygon_set_type_1, polygon_set_type_2>::type>::type, polygon_set_type_1>::type& interact(polygon_set_type_1& polygon_set_1, const polygon_set_type_2& polygon_set_2) { polygon_set_data<typename polygon_set_traits<polygon_set_type_1>::coordinate_type> ps1; assign(ps1, polygon_set_1); polygon_set_data<typename polygon_set_traits<polygon_set_type_2>::coordinate_type> ps2; assign(ps2, polygon_set_2); ps1.interact(ps2); assign(polygon_set_1, ps1); return polygon_set_1; } template <typename polygon_set_type> typename enable_if< typename is_mutable_polygon_set_type<polygon_set_type>::type, polygon_set_type>::type & scale_up(polygon_set_type& polygon_set, typename coordinate_traits<typename polygon_set_traits<polygon_set_type>::coordinate_type>::unsigned_area_type factor) { typedef typename polygon_set_traits<polygon_set_type>::coordinate_type Unit; clean(polygon_set); polygon_set_data<Unit> ps; assign(ps, polygon_set); ps.scale_up(factor); assign(polygon_set, ps); return polygon_set; } template <typename polygon_set_type> typename enable_if< typename is_mutable_polygon_set_type<polygon_set_type>::type, polygon_set_type>::type & scale_down(polygon_set_type& polygon_set, typename coordinate_traits<typename polygon_set_traits<polygon_set_type>::coordinate_type>::unsigned_area_type factor) { typedef typename polygon_set_traits<polygon_set_type>::coordinate_type Unit; clean(polygon_set); polygon_set_data<Unit> ps; assign(ps, polygon_set); ps.scale_down(factor); assign(polygon_set, ps); return polygon_set; } //transform template <typename polygon_set_type, typename transformation_type> typename enable_if< typename is_mutable_polygon_set_type<polygon_set_type>::type, polygon_set_type>::type & transform(polygon_set_type& polygon_set, const transformation_type& transformation) { typedef typename polygon_set_traits<polygon_set_type>::coordinate_type Unit; clean(polygon_set); polygon_set_data<Unit> ps; assign(ps, polygon_set); ps.transform(transformation); assign(polygon_set, ps); return polygon_set; } //keep template <typename polygon_set_type> typename enable_if< typename is_mutable_polygon_set_type<polygon_set_type>::type, polygon_set_type>::type & keep(polygon_set_type& polygon_set, typename coordinate_traits<typename polygon_set_traits<polygon_set_type>::coordinate_type>::area_type min_area, typename coordinate_traits<typename polygon_set_traits<polygon_set_type>::coordinate_type>::area_type max_area, typename coordinate_traits<typename polygon_set_traits<polygon_set_type>::coordinate_type>::unsigned_area_type min_width, typename coordinate_traits<typename polygon_set_traits<polygon_set_type>::coordinate_type>::unsigned_area_type max_width, typename coordinate_traits<typename polygon_set_traits<polygon_set_type>::coordinate_type>::unsigned_area_type min_height, typename coordinate_traits<typename polygon_set_traits<polygon_set_type>::coordinate_type>::unsigned_area_type max_height) { typedef typename polygon_set_traits<polygon_set_type>::coordinate_type Unit; typedef typename coordinate_traits<Unit>::unsigned_area_type uat; std::list<polygon_with_holes_data<Unit> > polys; assign(polys, polygon_set); typename std::list<polygon_with_holes_data<Unit> >::iterator itr_nxt; for(typename std::list<polygon_with_holes_data<Unit> >::iterator itr = polys.begin(); itr != polys.end(); itr = itr_nxt){ itr_nxt = itr; ++itr_nxt; rectangle_data<Unit> bbox; extents(bbox, *itr); uat pwidth = delta(bbox, HORIZONTAL); if(pwidth > min_width && pwidth <= max_width){ uat pheight = delta(bbox, VERTICAL); if(pheight > min_height && pheight <= max_height){ typename coordinate_traits<Unit>::area_type parea = area(*itr); if(parea <= max_area && parea >= min_area) { continue; } } } polys.erase(itr); } assign(polygon_set, polys); return polygon_set; } namespace operators { struct yes_ps_ob : gtl_yes {}; template <typename geometry_type_1, typename geometry_type_2> typename enable_if< typename gtl_and_4 < yes_ps_ob, typename is_any_polygon_set_type<geometry_type_1>::type, typename is_any_polygon_set_type<geometry_type_2>::type, typename is_either_polygon_set_type<geometry_type_1, geometry_type_2>::type>::type, polygon_set_view<geometry_type_1, geometry_type_2, 0> >::type operator|(const geometry_type_1& lvalue, const geometry_type_2& rvalue) { return polygon_set_view<geometry_type_1, geometry_type_2, 0> (lvalue, rvalue); } struct yes_ps_op : gtl_yes {}; template <typename geometry_type_1, typename geometry_type_2> typename enable_if< typename gtl_and_4 < yes_ps_op, typename gtl_if<typename is_any_polygon_set_type<geometry_type_1>::type>::type, typename gtl_if<typename is_any_polygon_set_type<geometry_type_2>::type>::type, typename gtl_if<typename is_either_polygon_set_type<geometry_type_1, geometry_type_2>::type>::type> ::type, polygon_set_view<geometry_type_1, geometry_type_2, 0> >::type operator+(const geometry_type_1& lvalue, const geometry_type_2& rvalue) { return polygon_set_view<geometry_type_1, geometry_type_2, 0> (lvalue, rvalue); } struct yes_ps_os : gtl_yes {}; template <typename geometry_type_1, typename geometry_type_2> typename enable_if< typename gtl_and_4 < yes_ps_os, typename is_any_polygon_set_type<geometry_type_1>::type, typename is_any_polygon_set_type<geometry_type_2>::type, typename is_either_polygon_set_type<geometry_type_1, geometry_type_2>::type>::type, polygon_set_view<geometry_type_1, geometry_type_2, 1> >::type operator*(const geometry_type_1& lvalue, const geometry_type_2& rvalue) { return polygon_set_view<geometry_type_1, geometry_type_2, 1> (lvalue, rvalue); } struct yes_ps_oa : gtl_yes {}; template <typename geometry_type_1, typename geometry_type_2> typename enable_if< typename gtl_and_4 < yes_ps_oa, typename is_any_polygon_set_type<geometry_type_1>::type, typename is_any_polygon_set_type<geometry_type_2>::type, typename is_either_polygon_set_type<geometry_type_1, geometry_type_2>::type>::type, polygon_set_view<geometry_type_1, geometry_type_2, 1> >::type operator&(const geometry_type_1& lvalue, const geometry_type_2& rvalue) { return polygon_set_view<geometry_type_1, geometry_type_2, 1> (lvalue, rvalue); } struct yes_ps_ox : gtl_yes {}; template <typename geometry_type_1, typename geometry_type_2> typename enable_if< typename gtl_and_4 < yes_ps_ox, typename is_any_polygon_set_type<geometry_type_1>::type, typename is_any_polygon_set_type<geometry_type_2>::type, typename is_either_polygon_set_type<geometry_type_1, geometry_type_2>::type>::type, polygon_set_view<geometry_type_1, geometry_type_2, 2> >::type operator^(const geometry_type_1& lvalue, const geometry_type_2& rvalue) { return polygon_set_view<geometry_type_1, geometry_type_2, 2> (lvalue, rvalue); } struct yes_ps_om : gtl_yes {}; template <typename geometry_type_1, typename geometry_type_2> typename enable_if< typename gtl_and_4 < yes_ps_om, typename gtl_if<typename is_any_polygon_set_type<geometry_type_1>::type>::type, typename gtl_if<typename is_any_polygon_set_type<geometry_type_2>::type>::type, typename gtl_if<typename is_either_polygon_set_type<geometry_type_1, geometry_type_2>::type>::type> ::type, polygon_set_view<geometry_type_1, geometry_type_2, 3> >::type operator-(const geometry_type_1& lvalue, const geometry_type_2& rvalue) { return polygon_set_view<geometry_type_1, geometry_type_2, 3> (lvalue, rvalue); } struct yes_ps_ope : gtl_yes {}; template <typename geometry_type_1, typename geometry_type_2> typename enable_if< typename gtl_and_4< yes_ps_ope, gtl_yes, typename is_mutable_polygon_set_type<geometry_type_1>::type, typename is_any_polygon_set_type<geometry_type_2>::type>::type, geometry_type_1>::type & operator+=(geometry_type_1& lvalue, const geometry_type_2& rvalue) { return self_assignment_boolean_op<geometry_type_1, geometry_type_2, 0>(lvalue, rvalue); } struct yes_ps_obe : gtl_yes {}; template <typename geometry_type_1, typename geometry_type_2> typename enable_if< typename gtl_and_3< yes_ps_obe, typename is_mutable_polygon_set_type<geometry_type_1>::type, typename is_any_polygon_set_type<geometry_type_2>::type>::type, geometry_type_1>::type & operator|=(geometry_type_1& lvalue, const geometry_type_2& rvalue) { return self_assignment_boolean_op<geometry_type_1, geometry_type_2, 0>(lvalue, rvalue); } struct yes_ps_ose : gtl_yes {}; template <typename geometry_type_1, typename geometry_type_2> typename enable_if< typename gtl_and_3< yes_ps_ose, typename is_mutable_polygon_set_type<geometry_type_1>::type, typename is_any_polygon_set_type<geometry_type_2>::type>::type, geometry_type_1>::type & operator*=(geometry_type_1& lvalue, const geometry_type_2& rvalue) { return self_assignment_boolean_op<geometry_type_1, geometry_type_2, 1>(lvalue, rvalue); } struct yes_ps_oae : gtl_yes {}; template <typename geometry_type_1, typename geometry_type_2> typename enable_if< typename gtl_and_3< yes_ps_oae, typename is_mutable_polygon_set_type<geometry_type_1>::type, typename is_any_polygon_set_type<geometry_type_2>::type>::type, geometry_type_1>::type & operator&=(geometry_type_1& lvalue, const geometry_type_2& rvalue) { return self_assignment_boolean_op<geometry_type_1, geometry_type_2, 1>(lvalue, rvalue); } struct yes_ps_oxe : gtl_yes {}; template <typename geometry_type_1, typename geometry_type_2> typename enable_if< typename gtl_and_3< yes_ps_oxe, typename is_mutable_polygon_set_type<geometry_type_1>::type, typename is_any_polygon_set_type<geometry_type_2>::type>::type, geometry_type_1>::type & operator^=(geometry_type_1& lvalue, const geometry_type_2& rvalue) { return self_assignment_boolean_op<geometry_type_1, geometry_type_2, 2>(lvalue, rvalue); } struct yes_ps_ome : gtl_yes {}; template <typename geometry_type_1, typename geometry_type_2> typename enable_if< typename gtl_and_3< yes_ps_ome, typename is_mutable_polygon_set_type<geometry_type_1>::type, typename is_any_polygon_set_type<geometry_type_2>::type>::type, geometry_type_1>::type & operator-=(geometry_type_1& lvalue, const geometry_type_2& rvalue) { return self_assignment_boolean_op<geometry_type_1, geometry_type_2, 3>(lvalue, rvalue); } // TODO: Dafna, test these four resizing operators struct y_ps_rpe : gtl_yes {}; template <typename geometry_type_1, typename coordinate_type_1> typename enable_if< typename gtl_and_3< y_ps_rpe, typename is_mutable_polygon_set_type<geometry_type_1>::type, typename gtl_same_type<typename geometry_concept<coordinate_type_1>::type, coordinate_concept>::type>::type, geometry_type_1>::type & operator+=(geometry_type_1& lvalue, coordinate_type_1 rvalue) { return resize(lvalue, rvalue); } struct y_ps_rme : gtl_yes {}; template <typename geometry_type_1, typename coordinate_type_1> typename enable_if< typename gtl_and_3<y_ps_rme, typename gtl_if<typename is_mutable_polygon_set_type<geometry_type_1>::type>::type, typename gtl_same_type<typename geometry_concept<coordinate_type_1>::type, coordinate_concept>::type>::type, geometry_type_1>::type & operator-=(geometry_type_1& lvalue, coordinate_type_1 rvalue) { return resize(lvalue, -rvalue); } struct y_ps_rp : gtl_yes {}; template <typename geometry_type_1, typename coordinate_type_1> typename enable_if< typename gtl_and_3<y_ps_rp, typename gtl_if<typename is_mutable_polygon_set_type<geometry_type_1>::type>::type, typename gtl_same_type<typename geometry_concept<coordinate_type_1>::type, coordinate_concept>::type> ::type, geometry_type_1>::type operator+(const geometry_type_1& lvalue, coordinate_type_1 rvalue) { geometry_type_1 retval(lvalue); retval += rvalue; return retval; } struct y_ps_rm : gtl_yes {}; template <typename geometry_type_1, typename coordinate_type_1> typename enable_if< typename gtl_and_3<y_ps_rm, typename gtl_if<typename is_mutable_polygon_set_type<geometry_type_1>::type>::type, typename gtl_same_type<typename geometry_concept<coordinate_type_1>::type, coordinate_concept>::type> ::type, geometry_type_1>::type operator-(const geometry_type_1& lvalue, coordinate_type_1 rvalue) { geometry_type_1 retval(lvalue); retval -= rvalue; return retval; } } //end operators namespace template <typename T> struct view_of<polygon_45_set_concept, T> { typedef typename get_coordinate_type<T, typename geometry_concept<T>::type >::type coordinate_type; T* tp; std::vector<polygon_45_with_holes_data<coordinate_type> > polys; view_of(const T& obj) : tp(), polys() { std::vector<polygon_with_holes_data<coordinate_type> > gpolys; assign(gpolys, obj); for(typename std::vector<polygon_with_holes_data<coordinate_type> >::iterator itr = gpolys.begin(); itr != gpolys.end(); ++itr) { polys.push_back(polygon_45_with_holes_data<coordinate_type>()); assign(polys.back(), view_as<polygon_45_with_holes_concept>(*itr)); } } view_of(T& obj) : tp(&obj), polys() { std::vector<polygon_with_holes_data<coordinate_type> > gpolys; assign(gpolys, obj); for(typename std::vector<polygon_with_holes_data<coordinate_type> >::iterator itr = gpolys.begin(); itr != gpolys.end(); ++itr) { polys.push_back(polygon_45_with_holes_data<coordinate_type>()); assign(polys.back(), view_as<polygon_45_with_holes_concept>(*itr)); } } typedef typename std::vector<polygon_45_with_holes_data<coordinate_type> >::const_iterator iterator_type; typedef view_of operator_arg_type; inline iterator_type begin() const { return polys.begin(); } inline iterator_type end() const { return polys.end(); } inline orientation_2d orient() const { return HORIZONTAL; } inline bool clean() const { return false; } inline bool sorted() const { return false; } inline T& get() { return *tp; } }; template <typename T> struct polygon_45_set_traits<view_of<polygon_45_set_concept, T> > { typedef typename view_of<polygon_45_set_concept, T>::coordinate_type coordinate_type; typedef typename view_of<polygon_45_set_concept, T>::iterator_type iterator_type; typedef view_of<polygon_45_set_concept, T> operator_arg_type; static inline iterator_type begin(const view_of<polygon_45_set_concept, T>& polygon_set) { return polygon_set.begin(); } static inline iterator_type end(const view_of<polygon_45_set_concept, T>& polygon_set) { return polygon_set.end(); } static inline orientation_2d orient(const view_of<polygon_45_set_concept, T>& polygon_set) { return polygon_set.orient(); } static inline bool clean(const view_of<polygon_45_set_concept, T>& polygon_set) { return polygon_set.clean(); } static inline bool sorted(const view_of<polygon_45_set_concept, T>& polygon_set) { return polygon_set.sorted(); } }; template <typename T> struct geometry_concept<view_of<polygon_45_set_concept, T> > { typedef polygon_45_set_concept type; }; template <typename T> struct get_coordinate_type<view_of<polygon_45_set_concept, T>, polygon_45_set_concept> { typedef typename view_of<polygon_45_set_concept, T>::coordinate_type type; }; template <typename T> struct get_iterator_type_2<view_of<polygon_45_set_concept, T>, polygon_45_set_concept> { typedef typename view_of<polygon_45_set_concept, T>::iterator_type type; static type begin(const view_of<polygon_45_set_concept, T>& t) { return t.begin(); } static type end(const view_of<polygon_45_set_concept, T>& t) { return t.end(); } }; } } #endif PK �b�[l�O� � polygon_with_holes_data.hppnu �[��� /* Copyright 2008 Intel Corporation Use, modification and distribution are 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_POLYGON_POLYGON_WITH_HOLES_DATA_HPP #define BOOST_POLYGON_POLYGON_WITH_HOLES_DATA_HPP #include "isotropy.hpp" #include "polygon_data.hpp" namespace boost { namespace polygon{ struct polygon_with_holes_concept; template <typename T> class polygon_with_holes_data { public: typedef polygon_with_holes_concept geometry_type; typedef T coordinate_type; typedef typename polygon_data<T>::iterator_type iterator_type; typedef typename std::list<polygon_data<coordinate_type> >::const_iterator iterator_holes_type; typedef polygon_data<coordinate_type> hole_type; typedef typename coordinate_traits<T>::coordinate_distance area_type; typedef point_data<T> point_type; // default constructor of point does not initialize x and y inline polygon_with_holes_data() : self_(), holes_() {} //do nothing default constructor template<class iT> inline polygon_with_holes_data(iT input_begin, iT input_end) : self_(), holes_() { set(input_begin, input_end); } template<class iT, typename hiT> inline polygon_with_holes_data(iT input_begin, iT input_end, hiT holes_begin, hiT holes_end) : self_(), holes_() { set(input_begin, input_end); set_holes(holes_begin, holes_end); } template<class iT> inline polygon_with_holes_data& set(iT input_begin, iT input_end) { self_.set(input_begin, input_end); return *this; } // initialize a polygon from x,y values, it is assumed that the first is an x // and that the input is a well behaved polygon template<class iT> inline polygon_with_holes_data& set_holes(iT input_begin, iT input_end) { holes_.clear(); //just in case there was some old data there for( ; input_begin != input_end; ++ input_begin) { holes_.push_back(hole_type()); holes_.back().set((*input_begin).begin(), (*input_begin).end()); } return *this; } // copy constructor (since we have dynamic memory) inline polygon_with_holes_data(const polygon_with_holes_data& that) : self_(that.self_), holes_(that.holes_) {} // assignment operator (since we have dynamic memory do a deep copy) inline polygon_with_holes_data& operator=(const polygon_with_holes_data& that) { self_ = that.self_; holes_ = that.holes_; return *this; } template <typename T2> inline polygon_with_holes_data& operator=(const T2& rvalue); // get begin iterator, returns a pointer to a const coordinate_type inline const iterator_type begin() const { return self_.begin(); } // get end iterator, returns a pointer to a const coordinate_type inline const iterator_type end() const { return self_.end(); } inline std::size_t size() const { return self_.size(); } // get begin iterator, returns a pointer to a const polygon inline const iterator_holes_type begin_holes() const { return holes_.begin(); } // get end iterator, returns a pointer to a const polygon inline const iterator_holes_type end_holes() const { return holes_.end(); } inline std::size_t size_holes() const { return holes_.size(); } public: polygon_data<coordinate_type> self_; std::list<hole_type> holes_; }; } } #endif PK �b�[��=�! �! polygon_traits.hppnu �[��� /* Copyright 2008 Intel Corporation Use, modification and distribution are 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_POLYGON_POLYGON_TRAITS_HPP #define BOOST_POLYGON_POLYGON_TRAITS_HPP namespace boost { namespace polygon{ template <typename T, typename enable = gtl_yes> struct polygon_90_traits { typedef typename T::coordinate_type coordinate_type; typedef typename T::compact_iterator_type compact_iterator_type; // Get the begin iterator static inline compact_iterator_type begin_compact(const T& t) { return t.begin_compact(); } // Get the end iterator static inline compact_iterator_type end_compact(const T& t) { return t.end_compact(); } // Get the number of sides of the polygon static inline std::size_t size(const T& t) { return t.size(); } // Get the winding direction of the polygon static inline winding_direction winding(const T&) { return unknown_winding; } }; template <typename T> struct polygon_traits_general { typedef typename T::coordinate_type coordinate_type; typedef typename T::iterator_type iterator_type; typedef typename T::point_type point_type; // Get the begin iterator static inline iterator_type begin_points(const T& t) { return t.begin(); } // Get the end iterator static inline iterator_type end_points(const T& t) { return t.end(); } // Get the number of sides of the polygon static inline std::size_t size(const T& t) { return t.size(); } // Get the winding direction of the polygon static inline winding_direction winding(const T&) { return unknown_winding; } }; template <typename T> struct polygon_traits_90 { typedef typename polygon_90_traits<T>::coordinate_type coordinate_type; typedef iterator_compact_to_points<typename polygon_90_traits<T>::compact_iterator_type, point_data<coordinate_type> > iterator_type; typedef point_data<coordinate_type> point_type; // Get the begin iterator static inline iterator_type begin_points(const T& t) { return iterator_type(polygon_90_traits<T>::begin_compact(t), polygon_90_traits<T>::end_compact(t)); } // Get the end iterator static inline iterator_type end_points(const T& t) { return iterator_type(polygon_90_traits<T>::end_compact(t), polygon_90_traits<T>::end_compact(t)); } // Get the number of sides of the polygon static inline std::size_t size(const T& t) { return polygon_90_traits<T>::size(t); } // Get the winding direction of the polygon static inline winding_direction winding(const T& t) { return polygon_90_traits<T>::winding(t); } }; #ifndef BOOST_VERY_LITTLE_SFINAE template <typename T, typename enable = gtl_yes> struct polygon_traits {}; template <typename T> struct polygon_traits<T, typename gtl_or_4< typename gtl_same_type<typename geometry_concept<T>::type, polygon_concept>::type, typename gtl_same_type<typename geometry_concept<T>::type, polygon_45_concept>::type, typename gtl_same_type<typename geometry_concept<T>::type, polygon_with_holes_concept>::type, typename gtl_same_type<typename geometry_concept<T>::type, polygon_45_with_holes_concept>::type >::type> : public polygon_traits_general<T> {}; template <typename T> struct polygon_traits< T, typename gtl_or< typename gtl_same_type<typename geometry_concept<T>::type, polygon_90_concept>::type, typename gtl_same_type<typename geometry_concept<T>::type, polygon_90_with_holes_concept>::type >::type > : public polygon_traits_90<T> {}; #else template <typename T, typename T_IF, typename T_ELSE> struct gtl_ifelse {}; template <typename T_IF, typename T_ELSE> struct gtl_ifelse<gtl_no, T_IF, T_ELSE> { typedef T_ELSE type; }; template <typename T_IF, typename T_ELSE> struct gtl_ifelse<gtl_yes, T_IF, T_ELSE> { typedef T_IF type; }; template <typename T, typename enable = gtl_yes> struct polygon_traits {}; template <typename T> struct polygon_traits<T, typename gtl_or<typename gtl_or_4< typename gtl_same_type<typename geometry_concept<T>::type, polygon_concept>::type, typename gtl_same_type<typename geometry_concept<T>::type, polygon_45_concept>::type, typename gtl_same_type<typename geometry_concept<T>::type, polygon_with_holes_concept>::type, typename gtl_same_type<typename geometry_concept<T>::type, polygon_45_with_holes_concept>::type >::type, typename gtl_or< typename gtl_same_type<typename geometry_concept<T>::type, polygon_90_concept>::type, typename gtl_same_type<typename geometry_concept<T>::type, polygon_90_with_holes_concept>::type >::type>::type > : public gtl_ifelse<typename gtl_or< typename gtl_same_type<typename geometry_concept<T>::type, polygon_90_concept>::type, typename gtl_same_type<typename geometry_concept<T>::type, polygon_90_with_holes_concept>::type >::type, polygon_traits_90<T>, polygon_traits_general<T> >::type { }; #endif template <typename T, typename enable = void> struct polygon_with_holes_traits { typedef typename T::iterator_holes_type iterator_holes_type; typedef typename T::hole_type hole_type; // Get the begin iterator static inline iterator_holes_type begin_holes(const T& t) { return t.begin_holes(); } // Get the end iterator static inline iterator_holes_type end_holes(const T& t) { return t.end_holes(); } // Get the number of holes static inline std::size_t size_holes(const T& t) { return t.size_holes(); } }; template <typename T, typename enable = void> struct polygon_90_mutable_traits { // Set the data of a polygon with the unique coordinates in an iterator, starting with an x template <typename iT> static inline T& set_compact(T& t, iT input_begin, iT input_end) { t.set_compact(input_begin, input_end); return t; } }; template <typename T, typename enable = void> struct polygon_mutable_traits { // Set the data of a polygon with the unique coordinates in an iterator, starting with an x template <typename iT> static inline T& set_points(T& t, iT input_begin, iT input_end) { t.set(input_begin, input_end); return t; } }; template <typename T, typename enable = void> struct polygon_with_holes_mutable_traits { // Set the data of a polygon with the unique coordinates in an iterator, starting with an x template <typename iT> static inline T& set_holes(T& t, iT inputBegin, iT inputEnd) { t.set_holes(inputBegin, inputEnd); return t; } }; } } #include "isotropy.hpp" //point #include "point_data.hpp" #include "point_traits.hpp" #include "point_concept.hpp" //interval #include "interval_data.hpp" #include "interval_traits.hpp" #include "interval_concept.hpp" //rectangle #include "rectangle_data.hpp" #include "rectangle_traits.hpp" #include "rectangle_concept.hpp" //algorithms needed by polygon types #include "detail/iterator_points_to_compact.hpp" #include "detail/iterator_compact_to_points.hpp" //polygons #include "polygon_45_data.hpp" #include "polygon_data.hpp" #include "polygon_90_data.hpp" #include "polygon_90_with_holes_data.hpp" #include "polygon_45_with_holes_data.hpp" #include "polygon_with_holes_data.hpp" namespace boost { namespace polygon{ struct polygon_concept {}; struct polygon_with_holes_concept {}; struct polygon_45_concept {}; struct polygon_45_with_holes_concept {}; struct polygon_90_concept {}; struct polygon_90_with_holes_concept {}; template <typename T> struct is_polygon_90_type { typedef typename geometry_concept<T>::type GC; typedef typename gtl_same_type<polygon_90_concept, GC>::type type; }; template <typename T> struct is_polygon_45_type { typedef typename geometry_concept<T>::type GC; typedef typename gtl_or<typename is_polygon_90_type<T>::type, typename gtl_same_type<polygon_45_concept, GC>::type>::type type; }; template <typename T> struct is_polygon_type { typedef typename geometry_concept<T>::type GC; typedef typename gtl_or<typename is_polygon_45_type<T>::type, typename gtl_same_type<polygon_concept, GC>::type>::type type; }; template <typename T> struct is_polygon_90_with_holes_type { typedef typename geometry_concept<T>::type GC; typedef typename gtl_or<typename is_polygon_90_type<T>::type, typename gtl_same_type<polygon_90_with_holes_concept, GC>::type>::type type; }; template <typename T> struct is_polygon_45_with_holes_type { typedef typename geometry_concept<T>::type GC; typedef typename gtl_or_3<typename is_polygon_90_with_holes_type<T>::type, typename is_polygon_45_type<T>::type, typename gtl_same_type<polygon_45_with_holes_concept, GC>::type>::type type; }; template <typename T> struct is_polygon_with_holes_type { typedef typename geometry_concept<T>::type GC; typedef typename gtl_or_3<typename is_polygon_45_with_holes_type<T>::type, typename is_polygon_type<T>::type, typename gtl_same_type<polygon_with_holes_concept, GC>::type>::type type; }; template <typename T> struct is_mutable_polygon_90_type { typedef typename geometry_concept<T>::type GC; typedef typename gtl_same_type<polygon_90_concept, GC>::type type; }; template <typename T> struct is_mutable_polygon_45_type { typedef typename geometry_concept<T>::type GC; typedef typename gtl_same_type<polygon_45_concept, GC>::type type; }; template <typename T> struct is_mutable_polygon_type { typedef typename geometry_concept<T>::type GC; typedef typename gtl_same_type<polygon_concept, GC>::type type; }; template <typename T> struct is_mutable_polygon_90_with_holes_type { typedef typename geometry_concept<T>::type GC; typedef typename gtl_same_type<polygon_90_with_holes_concept, GC>::type type; }; template <typename T> struct is_mutable_polygon_45_with_holes_type { typedef typename geometry_concept<T>::type GC; typedef typename gtl_same_type<polygon_45_with_holes_concept, GC>::type type; }; template <typename T> struct is_mutable_polygon_with_holes_type { typedef typename geometry_concept<T>::type GC; typedef typename gtl_same_type<polygon_with_holes_concept, GC>::type type; }; template <typename T> struct is_any_mutable_polygon_with_holes_type { typedef typename gtl_or_3<typename is_mutable_polygon_90_with_holes_type<T>::type, typename is_mutable_polygon_45_with_holes_type<T>::type, typename is_mutable_polygon_with_holes_type<T>::type>::type type; }; template <typename T> struct is_any_mutable_polygon_without_holes_type { typedef typename gtl_or_3< typename is_mutable_polygon_90_type<T>::type, typename is_mutable_polygon_45_type<T>::type, typename is_mutable_polygon_type<T>::type>::type type; }; template <typename T> struct is_any_mutable_polygon_type { typedef typename gtl_or<typename is_any_mutable_polygon_with_holes_type<T>::type, typename is_any_mutable_polygon_without_holes_type<T>::type>::type type; }; template <typename T> struct polygon_from_polygon_with_holes_type {}; template <> struct polygon_from_polygon_with_holes_type<polygon_with_holes_concept> { typedef polygon_concept type; }; template <> struct polygon_from_polygon_with_holes_type<polygon_45_with_holes_concept> { typedef polygon_45_concept type; }; template <> struct polygon_from_polygon_with_holes_type<polygon_90_with_holes_concept> { typedef polygon_90_concept type; }; template <> struct geometry_domain<polygon_45_concept> { typedef forty_five_domain type; }; template <> struct geometry_domain<polygon_45_with_holes_concept> { typedef forty_five_domain type; }; template <> struct geometry_domain<polygon_90_concept> { typedef manhattan_domain type; }; template <> struct geometry_domain<polygon_90_with_holes_concept> { typedef manhattan_domain type; }; template <typename domain_type, typename coordinate_type> struct distance_type_by_domain { typedef typename coordinate_traits<coordinate_type>::coordinate_distance type; }; template <typename coordinate_type> struct distance_type_by_domain<manhattan_domain, coordinate_type> { typedef typename coordinate_traits<coordinate_type>::coordinate_difference type; }; // \brief Sets the boundary of the polygon to the points in the iterator range // \tparam T A type that models polygon_concept // \tparam iT Iterator type over objects that model point_concept // \param t The polygon to set // \param begin_points The start of the range of points // \param end_points The end of the range of points /// \relatesalso polygon_concept template <typename T, typename iT> typename enable_if <typename is_any_mutable_polygon_type<T>::type, T>::type & set_points(T& t, iT begin_points, iT end_points) { polygon_mutable_traits<T>::set_points(t, begin_points, end_points); return t; } // \brief Sets the boundary of the polygon to the non-redundant coordinates in the iterator range // \tparam T A type that models polygon_90_concept // \tparam iT Iterator type over objects that model coordinate_concept // \param t The polygon to set // \param begin_compact_coordinates The start of the range of coordinates // \param end_compact_coordinates The end of the range of coordinates /// \relatesalso polygon_90_concept template <typename T, typename iT> typename enable_if <typename gtl_or< typename is_mutable_polygon_90_type<T>::type, typename is_mutable_polygon_90_with_holes_type<T>::type>::type, T>::type & set_compact(T& t, iT begin_compact_coordinates, iT end_compact_coordinates) { polygon_90_mutable_traits<T>::set_compact(t, begin_compact_coordinates, end_compact_coordinates); return t; } /// \relatesalso polygon_with_holes_concept template <typename T, typename iT> typename enable_if< typename gtl_and < typename is_any_mutable_polygon_with_holes_type<T>::type, typename gtl_different_type<typename geometry_domain<typename geometry_concept<T>::type>::type, manhattan_domain>::type>::type, T>::type & set_compact(T& t, iT begin_compact_coordinates, iT end_compact_coordinates) { iterator_compact_to_points<iT, point_data<typename polygon_traits<T>::coordinate_type> > itrb(begin_compact_coordinates, end_compact_coordinates), itre(end_compact_coordinates, end_compact_coordinates); return set_points(t, itrb, itre); } /// \relatesalso polygon_with_holes_concept template <typename T, typename iT> typename enable_if <typename is_any_mutable_polygon_with_holes_type<T>::type, T>::type & set_holes(T& t, iT begin_holes, iT end_holes) { polygon_with_holes_mutable_traits<T>::set_holes(t, begin_holes, end_holes); return t; } /// \relatesalso polygon_90_concept template <typename T> typename polygon_90_traits<T>::compact_iterator_type begin_compact(const T& polygon, typename enable_if< typename gtl_and <typename is_polygon_with_holes_type<T>::type, typename gtl_same_type<typename geometry_domain<typename geometry_concept<T>::type>::type, manhattan_domain>::type>::type>::type * = 0 ) { return polygon_90_traits<T>::begin_compact(polygon); } /// \relatesalso polygon_90_concept template <typename T> typename polygon_90_traits<T>::compact_iterator_type end_compact(const T& polygon, typename enable_if< typename gtl_and <typename is_polygon_with_holes_type<T>::type, typename gtl_same_type<typename geometry_domain<typename geometry_concept<T>::type>::type, manhattan_domain>::type>::type>::type * = 0 ) { return polygon_90_traits<T>::end_compact(polygon); } /// \relatesalso polygon_concept template <typename T> typename enable_if < typename gtl_if< typename is_polygon_with_holes_type<T>::type>::type, typename polygon_traits<T>::iterator_type>::type begin_points(const T& polygon) { return polygon_traits<T>::begin_points(polygon); } /// \relatesalso polygon_concept template <typename T> typename enable_if < typename gtl_if< typename is_polygon_with_holes_type<T>::type>::type, typename polygon_traits<T>::iterator_type>::type end_points(const T& polygon) { return polygon_traits<T>::end_points(polygon); } /// \relatesalso polygon_concept template <typename T> typename enable_if <typename is_polygon_with_holes_type<T>::type, std::size_t>::type size(const T& polygon) { return polygon_traits<T>::size(polygon); } /// \relatesalso polygon_with_holes_concept template <typename T> typename enable_if < typename gtl_if< typename is_polygon_with_holes_type<T>::type>::type, typename polygon_with_holes_traits<T>::iterator_holes_type>::type begin_holes(const T& polygon) { return polygon_with_holes_traits<T>::begin_holes(polygon); } /// \relatesalso polygon_with_holes_concept template <typename T> typename enable_if < typename gtl_if< typename is_polygon_with_holes_type<T>::type>::type, typename polygon_with_holes_traits<T>::iterator_holes_type>::type end_holes(const T& polygon) { return polygon_with_holes_traits<T>::end_holes(polygon); } /// \relatesalso polygon_with_holes_concept template <typename T> typename enable_if <typename is_polygon_with_holes_type<T>::type, std::size_t>::type size_holes(const T& polygon) { return polygon_with_holes_traits<T>::size_holes(polygon); } // \relatesalso polygon_concept template <typename T1, typename T2> typename enable_if< typename gtl_and< typename is_mutable_polygon_type<T1>::type, typename is_polygon_type<T2>::type>::type, T1>::type & assign(T1& lvalue, const T2& rvalue) { polygon_mutable_traits<T1>::set_points(lvalue, polygon_traits<T2>::begin_points(rvalue), polygon_traits<T2>::end_points(rvalue)); return lvalue; } // \relatesalso polygon_with_holes_concept template <typename T1, typename T2> typename enable_if< typename gtl_and< typename is_mutable_polygon_with_holes_type<T1>::type, typename is_polygon_with_holes_type<T2>::type>::type, T1>::type & assign(T1& lvalue, const T2& rvalue) { polygon_mutable_traits<T1>::set_points(lvalue, polygon_traits<T2>::begin_points(rvalue), polygon_traits<T2>::end_points(rvalue)); polygon_with_holes_mutable_traits<T1>::set_holes(lvalue, polygon_with_holes_traits<T2>::begin_holes(rvalue), polygon_with_holes_traits<T2>::end_holes(rvalue)); return lvalue; } // \relatesalso polygon_45_concept template <typename T1, typename T2> typename enable_if< typename gtl_and< typename is_mutable_polygon_45_type<T1>::type, typename is_polygon_45_type<T2>::type>::type, T1>::type & assign(T1& lvalue, const T2& rvalue) { polygon_mutable_traits<T1>::set_points(lvalue, polygon_traits<T2>::begin_points(rvalue), polygon_traits<T2>::end_points(rvalue)); return lvalue; } // \relatesalso polygon_45_with_holes_concept template <typename T1, typename T2> typename enable_if< typename gtl_and< typename is_mutable_polygon_45_with_holes_type<T1>::type, typename is_polygon_45_with_holes_type<T2>::type>::type, T1>::type & assign(T1& lvalue, const T2& rvalue) { polygon_mutable_traits<T1>::set_points(lvalue, polygon_traits<T2>::begin_points(rvalue), polygon_traits<T2>::end_points(rvalue)); polygon_with_holes_mutable_traits<T1>::set_holes(lvalue, polygon_with_holes_traits<T2>::begin_holes(rvalue), polygon_with_holes_traits<T2>::end_holes(rvalue)); return lvalue; } // \relatesalso polygon_90_concept template <typename T1, typename T2> typename enable_if< typename gtl_and< typename is_mutable_polygon_90_type<T1>::type, typename is_polygon_90_type<T2>::type>::type, T1>::type & assign(T1& lvalue, const T2& rvalue) { polygon_90_mutable_traits<T1>::set_compact(lvalue, polygon_90_traits<T2>::begin_compact(rvalue), polygon_90_traits<T2>::end_compact(rvalue)); return lvalue; } // \relatesalso polygon_90_with_holes_concept template <typename T1, typename T2> typename enable_if< typename gtl_and< typename is_mutable_polygon_90_with_holes_type<T1>::type, typename is_polygon_90_with_holes_type<T2>::type>::type, T1>::type & assign(T1& lvalue, const T2& rvalue) { polygon_90_mutable_traits<T1>::set_compact(lvalue, polygon_90_traits<T2>::begin_compact(rvalue), polygon_90_traits<T2>::end_compact(rvalue)); polygon_with_holes_mutable_traits<T1>::set_holes(lvalue, polygon_with_holes_traits<T2>::begin_holes(rvalue), polygon_with_holes_traits<T2>::end_holes(rvalue)); return lvalue; } // \relatesalso polygon_90_concept template <typename T1, typename T2> typename enable_if< typename gtl_and< typename is_any_mutable_polygon_type<T1>::type, typename is_rectangle_concept<typename geometry_concept<T2>::type>::type>::type, T1>::type & assign(T1& polygon, const T2& rect) { typedef point_data<typename polygon_traits<T1>::coordinate_type> PT; PT points[4] = {PT(xl(rect), yl(rect)), PT(xh(rect), yl(rect)), PT(xh(rect), yh(rect)), PT(xl(rect), yh(rect))}; set_points(polygon, points, points+4); return polygon; } /// \relatesalso polygon_90_concept template <typename polygon_type, typename point_type> typename enable_if< typename gtl_and< typename is_mutable_polygon_90_type<polygon_type>::type, typename is_point_concept<typename geometry_concept<point_type>::type>::type>::type, polygon_type>::type & convolve(polygon_type& polygon, const point_type& point) { std::vector<typename polygon_90_traits<polygon_type>::coordinate_type> coords; coords.reserve(::boost::polygon::size(polygon)); bool pingpong = true; for(typename polygon_90_traits<polygon_type>::compact_iterator_type iter = begin_compact(polygon); iter != end_compact(polygon); ++iter) { coords.push_back((*iter) + (pingpong ? x(point) : y(point))); pingpong = !pingpong; } polygon_90_mutable_traits<polygon_type>::set_compact(polygon, coords.begin(), coords.end()); return polygon; } /// \relatesalso polygon_concept template <typename polygon_type, typename point_type> typename enable_if< typename gtl_and< typename gtl_or< typename is_mutable_polygon_45_type<polygon_type>::type, typename is_mutable_polygon_type<polygon_type>::type>::type, typename is_point_concept<typename geometry_concept<point_type>::type>::type>::type, polygon_type>::type & convolve(polygon_type& polygon, const point_type& point) { std::vector<typename std::iterator_traits<typename polygon_traits<polygon_type>::iterator_type>::value_type> points; points.reserve(::boost::polygon::size(polygon)); for(typename polygon_traits<polygon_type>::iterator_type iter = begin_points(polygon); iter != end_points(polygon); ++iter) { points.push_back(*iter); convolve(points.back(), point); } polygon_mutable_traits<polygon_type>::set_points(polygon, points.begin(), points.end()); return polygon; } /// \relatesalso polygon_with_holes_concept template <typename polygon_type, typename point_type> typename enable_if< typename gtl_and< typename is_any_mutable_polygon_with_holes_type<polygon_type>::type, typename is_point_concept<typename geometry_concept<point_type>::type>::type>::type, polygon_type>::type & convolve(polygon_type& polygon, const point_type& point) { typedef typename polygon_with_holes_traits<polygon_type>::hole_type hole_type; hole_type h; set_points(h, begin_points(polygon), end_points(polygon)); convolve(h, point); std::vector<hole_type> holes; holes.reserve(size_holes(polygon)); for(typename polygon_with_holes_traits<polygon_type>::iterator_holes_type itr = begin_holes(polygon); itr != end_holes(polygon); ++itr) { holes.push_back(*itr); convolve(holes.back(), point); } assign(polygon, h); set_holes(polygon, holes.begin(), holes.end()); return polygon; } /// \relatesalso polygon_concept template <typename T> typename enable_if< typename is_any_mutable_polygon_type<T>::type, T>::type & move(T& polygon, orientation_2d orient, typename polygon_traits<T>::coordinate_type displacement) { typedef typename polygon_traits<T>::coordinate_type Unit; if(orient == HORIZONTAL) return convolve(polygon, point_data<Unit>(displacement, Unit(0))); return convolve(polygon, point_data<Unit>(Unit(0), displacement)); } /// \relatesalso polygon_concept /// \brief Applies a transformation to the polygon. /// \tparam polygon_type A type that models polygon_concept /// \tparam transform_type A type that may be either axis_transformation or transformation or that overloads point_concept::transform /// \param polygon The polygon to transform /// \param tr The transformation to apply template <typename polygon_type, typename transform_type> typename enable_if< typename is_any_mutable_polygon_without_holes_type<polygon_type>::type, polygon_type>::type & transform(polygon_type& polygon, const transform_type& tr) { std::vector<typename std::iterator_traits<typename polygon_traits<polygon_type>::iterator_type>::value_type> points; points.reserve(::boost::polygon::size(polygon)); for(typename polygon_traits<polygon_type>::iterator_type iter = begin_points(polygon); iter != end_points(polygon); ++iter) { points.push_back(*iter); transform(points.back(), tr); } polygon_mutable_traits<polygon_type>::set_points(polygon, points.begin(), points.end()); return polygon; } /// \relatesalso polygon_with_holes_concept template <typename T, typename transform_type> typename enable_if< typename is_any_mutable_polygon_with_holes_type<T>::type, T>::type & transform(T& polygon, const transform_type& tr) { typedef typename polygon_with_holes_traits<T>::hole_type hole_type; hole_type h; set_points(h, begin_points(polygon), end_points(polygon)); transform(h, tr); std::vector<hole_type> holes; holes.reserve(size_holes(polygon)); for(typename polygon_with_holes_traits<T>::iterator_holes_type itr = begin_holes(polygon); itr != end_holes(polygon); ++itr) { holes.push_back(*itr); transform(holes.back(), tr); } assign(polygon, h); set_holes(polygon, holes.begin(), holes.end()); return polygon; } template <typename polygon_type> typename enable_if< typename is_any_mutable_polygon_without_holes_type<polygon_type>::type, polygon_type>::type & scale_up(polygon_type& polygon, typename coordinate_traits<typename polygon_traits<polygon_type>::coordinate_type>::unsigned_area_type factor) { std::vector<typename std::iterator_traits<typename polygon_traits<polygon_type>::iterator_type>::value_type> points; points.reserve(::boost::polygon::size(polygon)); for(typename polygon_traits<polygon_type>::iterator_type iter = begin_points(polygon); iter != end_points(polygon); ++iter) { points.push_back(*iter); scale_up(points.back(), factor); } polygon_mutable_traits<polygon_type>::set_points(polygon, points.begin(), points.end()); return polygon; } template <typename T> typename enable_if< typename is_any_mutable_polygon_with_holes_type<T>::type, T>::type & scale_up(T& polygon, typename coordinate_traits<typename polygon_traits<T>::coordinate_type>::unsigned_area_type factor) { typedef typename polygon_with_holes_traits<T>::hole_type hole_type; hole_type h; set_points(h, begin_points(polygon), end_points(polygon)); scale_up(h, factor); std::vector<hole_type> holes; holes.reserve(size_holes(polygon)); for(typename polygon_with_holes_traits<T>::iterator_holes_type itr = begin_holes(polygon); itr != end_holes(polygon); ++itr) { holes.push_back(*itr); scale_up(holes.back(), factor); } assign(polygon, h); set_holes(polygon, holes.begin(), holes.end()); return polygon; } //scale non-45 down template <typename polygon_type> typename enable_if< typename gtl_and< typename is_any_mutable_polygon_without_holes_type<polygon_type>::type, typename gtl_not<typename gtl_same_type < forty_five_domain, typename geometry_domain<typename geometry_concept<polygon_type>::type>::type>::type>::type>::type, polygon_type>::type & scale_down(polygon_type& polygon, typename coordinate_traits<typename polygon_traits<polygon_type>::coordinate_type>::unsigned_area_type factor) { std::vector<typename std::iterator_traits<typename polygon_traits<polygon_type>::iterator_type>::value_type> points; points.reserve(::boost::polygon::size(polygon)); for(typename polygon_traits<polygon_type>::iterator_type iter = begin_points(polygon); iter != end_points(polygon); ++iter) { points.push_back(*iter); scale_down(points.back(), factor); } polygon_mutable_traits<polygon_type>::set_points(polygon, points.begin(), points.end()); return polygon; } template <typename Unit> Unit local_abs(Unit value) { return value < 0 ? (Unit)-value : value; } template <typename Unit> void snap_point_vector_to_45(std::vector<point_data<Unit> >& pts) { typedef point_data<Unit> Point; if(pts.size() < 3) { pts.clear(); return; } typename std::vector<point_data<Unit> >::iterator endLocation = std::unique(pts.begin(), pts.end()); if(endLocation != pts.end()){ pts.resize(endLocation - pts.begin()); } if(pts.back() == pts[0]) pts.pop_back(); //iterate over point triplets int numPts = pts.size(); bool wrap_around = false; for(int i = 0; i < numPts; ++i) { Point& pt1 = pts[i]; Point& pt2 = pts[(i + 1) % numPts]; Point& pt3 = pts[(i + 2) % numPts]; //check if non-45 edge Unit deltax = x(pt2) - x(pt1); Unit deltay = y(pt2) - y(pt1); if(deltax && deltay && local_abs(deltax) != local_abs(deltay)) { //adjust the middle point Unit ndx = x(pt3) - x(pt2); Unit ndy = y(pt3) - y(pt2); if(ndx && ndy) { Unit diff = local_abs(local_abs(deltax) - local_abs(deltay)); Unit halfdiff = diff/2; if((deltax > 0 && deltay > 0) || (deltax < 0 && deltay < 0)) { //previous edge is rising slope if(local_abs(deltax + halfdiff + (diff % 2)) == local_abs(deltay - halfdiff)) { x(pt2, x(pt2) + halfdiff + (diff % 2)); y(pt2, y(pt2) - halfdiff); } else if(local_abs(deltax - halfdiff - (diff % 2)) == local_abs(deltay + halfdiff)) { x(pt2, x(pt2) - halfdiff - (diff % 2)); y(pt2, y(pt2) + halfdiff); } else{ //std::cout << "fail1\n"; } } else { //previous edge is falling slope if(local_abs(deltax + halfdiff + (diff % 2)) == local_abs(deltay + halfdiff)) { x(pt2, x(pt2) + halfdiff + (diff % 2)); y(pt2, y(pt2) + halfdiff); } else if(local_abs(deltax - halfdiff - (diff % 2)) == local_abs(deltay - halfdiff)) { x(pt2, x(pt2) - halfdiff - (diff % 2)); y(pt2, y(pt2) - halfdiff); } else { //std::cout << "fail2\n"; } } if(i == numPts - 1 && (diff % 2)) { //we have a wrap around effect if(!wrap_around) { wrap_around = true; i = -1; } } } else if(ndx) { //next edge is horizontal //find the x value for pt1 that would make the abs(deltax) == abs(deltay) Unit newDeltaX = local_abs(deltay); if(deltax < 0) newDeltaX *= -1; x(pt2, x(pt1) + newDeltaX); } else { //ndy //next edge is vertical //find the y value for pt1 that would make the abs(deltax) == abs(deltay) Unit newDeltaY = local_abs(deltax); if(deltay < 0) newDeltaY *= -1; y(pt2, y(pt1) + newDeltaY); } } } } template <typename polygon_type> typename enable_if< typename is_any_mutable_polygon_without_holes_type<polygon_type>::type, polygon_type>::type & snap_to_45(polygon_type& polygon) { std::vector<typename std::iterator_traits<typename polygon_traits<polygon_type>::iterator_type>::value_type> points; points.reserve(::boost::polygon::size(polygon)); for(typename polygon_traits<polygon_type>::iterator_type iter = begin_points(polygon); iter != end_points(polygon); ++iter) { points.push_back(*iter); } snap_point_vector_to_45(points); polygon_mutable_traits<polygon_type>::set_points(polygon, points.begin(), points.end()); return polygon; } template <typename polygon_type> typename enable_if< typename is_any_mutable_polygon_with_holes_type<polygon_type>::type, polygon_type>::type & snap_to_45(polygon_type& polygon) { typedef typename polygon_with_holes_traits<polygon_type>::hole_type hole_type; hole_type h; set_points(h, begin_points(polygon), end_points(polygon)); snap_to_45(h); std::vector<hole_type> holes; holes.reserve(size_holes(polygon)); for(typename polygon_with_holes_traits<polygon_type>::iterator_holes_type itr = begin_holes(polygon); itr != end_holes(polygon); ++itr) { holes.push_back(*itr); snap_to_45(holes.back()); } assign(polygon, h); set_holes(polygon, holes.begin(), holes.end()); return polygon; } //scale specifically 45 down template <typename polygon_type> typename enable_if< typename gtl_and< typename is_any_mutable_polygon_without_holes_type<polygon_type>::type, typename gtl_same_type < forty_five_domain, typename geometry_domain<typename geometry_concept<polygon_type>::type>::type>::type>::type, polygon_type>::type & scale_down(polygon_type& polygon, typename coordinate_traits<typename polygon_traits<polygon_type>::coordinate_type>::unsigned_area_type factor) { std::vector<typename std::iterator_traits<typename polygon_traits<polygon_type>::iterator_type>::value_type> points; points.reserve(::boost::polygon::size(polygon)); for(typename polygon_traits<polygon_type>::iterator_type iter = begin_points(polygon); iter != end_points(polygon); ++iter) { points.push_back(*iter); scale_down(points.back(), factor); } snap_point_vector_to_45(points); polygon_mutable_traits<polygon_type>::set_points(polygon, points.begin(), points.end()); return polygon; } template <typename T> typename enable_if< typename is_any_mutable_polygon_with_holes_type<T>::type, T>::type & scale_down(T& polygon, typename coordinate_traits<typename polygon_traits<T>::coordinate_type>::unsigned_area_type factor) { typedef typename polygon_with_holes_traits<T>::hole_type hole_type; hole_type h; set_points(h, begin_points(polygon), end_points(polygon)); scale_down(h, factor); std::vector<hole_type> holes; holes.reserve(size_holes(polygon)); for(typename polygon_with_holes_traits<T>::iterator_holes_type itr = begin_holes(polygon); itr != end_holes(polygon); ++itr) { holes.push_back(*itr); scale_down(holes.back(), factor); } assign(polygon, h); set_holes(polygon, holes.begin(), holes.end()); return polygon; } //scale non-45 template <typename polygon_type> typename enable_if< typename gtl_and< typename is_any_mutable_polygon_without_holes_type<polygon_type>::type, typename gtl_not<typename gtl_same_type < forty_five_domain, typename geometry_domain<typename geometry_concept<polygon_type>::type>::type>::type>::type>::type, polygon_type>::type & scale(polygon_type& polygon, double factor) { std::vector<typename std::iterator_traits<typename polygon_traits<polygon_type>::iterator_type>::value_type> points; points.reserve(::boost::polygon::size(polygon)); for(typename polygon_traits<polygon_type>::iterator_type iter = begin_points(polygon); iter != end_points(polygon); ++iter) { points.push_back(*iter); scale(points.back(), anisotropic_scale_factor<double>(factor, factor)); } polygon_mutable_traits<polygon_type>::set_points(polygon, points.begin(), points.end()); return polygon; } //scale specifically 45 template <typename polygon_type> polygon_type& scale(polygon_type& polygon, double factor, typename enable_if< typename gtl_and< typename is_any_mutable_polygon_without_holes_type<polygon_type>::type, typename gtl_same_type < forty_five_domain, typename geometry_domain<typename geometry_concept<polygon_type>::type>::type>::type>::type>::type * = 0 ) { std::vector<typename std::iterator_traits<typename polygon_traits<polygon_type>::iterator_type>::value_type> points; points.reserve(::boost::polygon::size(polygon)); for(typename polygon_traits<polygon_type>::iterator_type iter = begin_points(polygon); iter != end_points(polygon); ++iter) { points.push_back(*iter); scale(points.back(), anisotropic_scale_factor<double>(factor, factor)); } snap_point_vector_to_45(points); polygon_mutable_traits<polygon_type>::set_points(polygon, points.begin(), points.end()); return polygon; } template <typename T> T& scale(T& polygon, double factor, typename enable_if< typename is_any_mutable_polygon_with_holes_type<T>::type>::type * = 0 ) { typedef typename polygon_with_holes_traits<T>::hole_type hole_type; hole_type h; set_points(h, begin_points(polygon), end_points(polygon)); scale(h, factor); std::vector<hole_type> holes; holes.reserve(size_holes(polygon)); for(typename polygon_with_holes_traits<T>::iterator_holes_type itr = begin_holes(polygon); itr != end_holes(polygon); ++itr) { holes.push_back(*itr); scale(holes.back(), factor); } assign(polygon, h); set_holes(polygon, holes.begin(), holes.end()); return polygon; } template <typename iterator_type, typename area_type> static area_type point_sequence_area(iterator_type begin_range, iterator_type end_range) { typedef typename std::iterator_traits<iterator_type>::value_type point_type; if(begin_range == end_range) return area_type(0); point_type first = *begin_range; point_type previous = first; ++begin_range; // Initialize trapezoid base line area_type y_base = (area_type)y(first); // Initialize area accumulator area_type area(0); while (begin_range != end_range) { area_type x1 = (area_type)x(previous); area_type x2 = (area_type)x(*begin_range); #ifdef BOOST_POLYGON_ICC #pragma warning (push) #pragma warning (disable:1572) #endif if(x1 != x2) { #ifdef BOOST_POLYGON_ICC #pragma warning (pop) #endif // do trapezoid area accumulation area += (x2 - x1) * (((area_type)y(*begin_range) - y_base) + ((area_type)y(previous) - y_base)) / 2; } previous = *begin_range; // go to next point ++begin_range; } //wrap around to evaluate the edge between first and last if not closed if(!equivalence(first, previous)) { area_type x1 = (area_type)x(previous); area_type x2 = (area_type)x(first); area += (x2 - x1) * (((area_type)y(first) - y_base) + ((area_type)y(previous) - y_base)) / 2; } return area; } template <typename T> typename enable_if< typename is_polygon_with_holes_type<T>::type, typename area_type_by_domain< typename geometry_domain<typename geometry_concept<T>::type>::type, typename polygon_traits<T>::coordinate_type>::type>::type area(const T& polygon) { typedef typename area_type_by_domain< typename geometry_domain<typename geometry_concept<T>::type>::type, typename polygon_traits<T>::coordinate_type>::type area_type; area_type retval = point_sequence_area<typename polygon_traits<T>::iterator_type, area_type> (begin_points(polygon), end_points(polygon)); if(retval < 0) retval *= -1; for(typename polygon_with_holes_traits<T>::iterator_holes_type itr = polygon_with_holes_traits<T>::begin_holes(polygon); itr != polygon_with_holes_traits<T>::end_holes(polygon); ++itr) { area_type tmp_area = point_sequence_area <typename polygon_traits<typename polygon_with_holes_traits<T>::hole_type>::iterator_type, area_type> (begin_points(*itr), end_points(*itr)); if(tmp_area < 0) tmp_area *= -1; retval -= tmp_area; } return retval; } template <typename iT> bool point_sequence_is_45(iT itr, iT itr_end) { typedef typename std::iterator_traits<iT>::value_type Point; typedef typename point_traits<Point>::coordinate_type Unit; if(itr == itr_end) return true; Point firstPt = *itr; Point prevPt = firstPt; ++itr; while(itr != itr_end) { Point pt = *itr; Unit deltax = x(pt) - x(prevPt); Unit deltay = y(pt) - y(prevPt); if(deltax && deltay && local_abs(deltax) != local_abs(deltay)) return false; prevPt = pt; ++itr; } Unit deltax = x(firstPt) - x(prevPt); Unit deltay = y(firstPt) - y(prevPt); if(deltax && deltay && local_abs(deltax) != local_abs(deltay)) return false; return true; } template <typename polygon_type> typename enable_if< typename is_polygon_with_holes_type<polygon_type>::type, bool>::type is_45(const polygon_type& polygon) { typename polygon_traits<polygon_type>::iterator_type itr = begin_points(polygon), itr_end = end_points(polygon); if(!point_sequence_is_45(itr, itr_end)) return false; typename polygon_with_holes_traits<polygon_type>::iterator_holes_type itrh = begin_holes(polygon), itrh_end = end_holes(polygon); typedef typename polygon_with_holes_traits<polygon_type>::hole_type hole_type; for(; itrh != itrh_end; ++ itrh) { typename polygon_traits<hole_type>::iterator_type itr1 = begin_points(polygon), itr1_end = end_points(polygon); if(!point_sequence_is_45(itr1, itr1_end)) return false; } return true; } template <typename distance_type, typename iterator_type> distance_type point_sequence_distance(iterator_type itr, iterator_type itr_end) { typedef distance_type Unit; typedef iterator_type iterator; typedef typename std::iterator_traits<iterator>::value_type point_type; Unit return_value = Unit(0); point_type previous_point, first_point; if(itr == itr_end) return return_value; previous_point = first_point = *itr; ++itr; for( ; itr != itr_end; ++itr) { point_type current_point = *itr; return_value += (Unit)euclidean_distance(current_point, previous_point); previous_point = current_point; } return_value += (Unit)euclidean_distance(previous_point, first_point); return return_value; } template <typename T> typename distance_type_by_domain <typename geometry_domain<typename geometry_concept<T>::type>::type, typename polygon_traits<T>::coordinate_type>::type perimeter(const T& polygon, typename enable_if< typename is_polygon_with_holes_type<T>::type>::type * = 0 ) { typedef typename distance_type_by_domain <typename geometry_domain<typename geometry_concept<T>::type>::type, typename polygon_traits<T>::coordinate_type>::type Unit; typedef typename polygon_traits<T>::iterator_type iterator; iterator itr = begin_points(polygon); iterator itr_end = end_points(polygon); Unit return_value = point_sequence_distance<Unit, iterator>(itr, itr_end); for(typename polygon_with_holes_traits<T>::iterator_holes_type itr_holes = begin_holes(polygon); itr_holes != end_holes(polygon); ++itr_holes) { typedef typename polygon_traits<typename polygon_with_holes_traits<T>::hole_type>::iterator_type hitertype; return_value += point_sequence_distance<Unit, hitertype>(begin_points(*itr_holes), end_points(*itr_holes)); } return return_value; } template <typename T> typename enable_if <typename is_polygon_with_holes_type<T>::type, direction_1d>::type winding(const T& polygon) { winding_direction wd = polygon_traits<T>::winding(polygon); if(wd != unknown_winding) { return wd == clockwise_winding ? CLOCKWISE: COUNTERCLOCKWISE; } typedef typename area_type_by_domain< typename geometry_domain<typename geometry_concept<T>::type>::type, typename polygon_traits<T>::coordinate_type>::type area_type; return point_sequence_area<typename polygon_traits<T>::iterator_type, area_type>(begin_points(polygon), end_points(polygon)) < 0 ? COUNTERCLOCKWISE : CLOCKWISE; } template <typename T, typename input_point_type> typename enable_if< typename gtl_and< typename is_polygon_90_type<T>::type, typename gtl_same_type< typename geometry_concept<input_point_type>::type, point_concept >::type >::type, bool >::type contains( const T& polygon, const input_point_type& point, bool consider_touch = true) { typedef T polygon_type; typedef typename polygon_traits<polygon_type>::coordinate_type coordinate_type; typedef typename polygon_traits<polygon_type>::iterator_type iterator; typedef typename std::iterator_traits<iterator>::value_type point_type; coordinate_type point_x = x(point); coordinate_type point_y = y(point); // Check how many intersections has the ray extended from the given // point in the x-axis negative direction with the polygon edges. // If the number is odd the point is within the polygon, otherwise not. // We can safely ignore horizontal edges, however intersections with // end points of the vertical edges require special handling. We should // add one intersection in case horizontal edges that extend vertical edge // point in the same direction. int num_full_intersections = 0; int num_half_intersections = 0; for (iterator iter = begin_points(polygon); iter != end_points(polygon);) { point_type curr_point = *iter; ++iter; point_type next_point = (iter == end_points(polygon)) ? *begin_points(polygon) : *iter; if (x(curr_point) == x(next_point)) { if (x(curr_point) > point_x) { continue; } coordinate_type min_y = (std::min)(y(curr_point), y(next_point)); coordinate_type max_y = (std::max)(y(curr_point), y(next_point)); if (point_y > min_y && point_y < max_y) { if (x(curr_point) == point_x) { return consider_touch; } ++num_full_intersections; } if (point_y == min_y || point_y == max_y) { num_half_intersections += (y(curr_point) < y(next_point) ? 1 : -1); } } else { coordinate_type min_x = (std::min)(x(curr_point), x(next_point)); coordinate_type max_x = (std::max)(x(curr_point), x(next_point)); if (point_x >= min_x && point_x <= max_x) { if (y(curr_point) == point_y) { return consider_touch; } } } } int total_intersections = num_full_intersections + (num_half_intersections >> 1); return total_intersections & 1; } //TODO: refactor to expose as user APIs template <typename Unit> struct edge_utils { typedef point_data<Unit> Point; typedef std::pair<Point, Point> half_edge; class less_point { public: typedef Point first_argument_type; typedef Point second_argument_type; typedef bool result_type; inline less_point() {} inline bool operator () (const Point& pt1, const Point& pt2) const { if(pt1.get(HORIZONTAL) < pt2.get(HORIZONTAL)) return true; if(pt1.get(HORIZONTAL) == pt2.get(HORIZONTAL)) { if(pt1.get(VERTICAL) < pt2.get(VERTICAL)) return true; } return false; } }; static inline bool between(Point pt, Point pt1, Point pt2) { less_point lp; if(lp(pt1, pt2)) return lp(pt, pt2) && lp(pt1, pt); return lp(pt, pt1) && lp(pt2, pt); } template <typename area_type> static inline bool equal_slope(area_type dx1, area_type dy1, area_type dx2, area_type dy2) { typedef typename coordinate_traits<Unit>::unsigned_area_type unsigned_product_type; unsigned_product_type cross_1 = (unsigned_product_type)(dx2 < 0 ? -dx2 :dx2) * (unsigned_product_type)(dy1 < 0 ? -dy1 : dy1); unsigned_product_type cross_2 = (unsigned_product_type)(dx1 < 0 ? -dx1 :dx1) * (unsigned_product_type)(dy2 < 0 ? -dy2 : dy2); int dx1_sign = dx1 < 0 ? -1 : 1; int dx2_sign = dx2 < 0 ? -1 : 1; int dy1_sign = dy1 < 0 ? -1 : 1; int dy2_sign = dy2 < 0 ? -1 : 1; int cross_1_sign = dx2_sign * dy1_sign; int cross_2_sign = dx1_sign * dy2_sign; return cross_1 == cross_2 && (cross_1_sign == cross_2_sign || cross_1 == 0); } static inline bool equal_slope(const Unit& x, const Unit& y, const Point& pt1, const Point& pt2) { const Point* pts[2] = {&pt1, &pt2}; typedef typename coordinate_traits<Unit>::manhattan_area_type at; at dy2 = (at)pts[1]->get(VERTICAL) - (at)y; at dy1 = (at)pts[0]->get(VERTICAL) - (at)y; at dx2 = (at)pts[1]->get(HORIZONTAL) - (at)x; at dx1 = (at)pts[0]->get(HORIZONTAL) - (at)x; return equal_slope(dx1, dy1, dx2, dy2); } template <typename area_type> static inline bool less_slope(area_type dx1, area_type dy1, area_type dx2, area_type dy2) { //reflext x and y slopes to right hand side half plane if(dx1 < 0) { dy1 *= -1; dx1 *= -1; } else if(dx1 == 0) { //if the first slope is vertical the first cannot be less return false; } if(dx2 < 0) { dy2 *= -1; dx2 *= -1; } else if(dx2 == 0) { //if the second slope is vertical the first is always less unless it is also vertical, in which case they are equal return dx1 != 0; } typedef typename coordinate_traits<Unit>::unsigned_area_type unsigned_product_type; unsigned_product_type cross_1 = (unsigned_product_type)(dx2 < 0 ? -dx2 :dx2) * (unsigned_product_type)(dy1 < 0 ? -dy1 : dy1); unsigned_product_type cross_2 = (unsigned_product_type)(dx1 < 0 ? -dx1 :dx1) * (unsigned_product_type)(dy2 < 0 ? -dy2 : dy2); int dx1_sign = dx1 < 0 ? -1 : 1; int dx2_sign = dx2 < 0 ? -1 : 1; int dy1_sign = dy1 < 0 ? -1 : 1; int dy2_sign = dy2 < 0 ? -1 : 1; int cross_1_sign = dx2_sign * dy1_sign; int cross_2_sign = dx1_sign * dy2_sign; if(cross_1_sign < cross_2_sign) return true; if(cross_2_sign < cross_1_sign) return false; if(cross_1_sign == -1) return cross_2 < cross_1; return cross_1 < cross_2; } static inline bool less_slope(const Unit& x, const Unit& y, const Point& pt1, const Point& pt2) { const Point* pts[2] = {&pt1, &pt2}; //compute y value on edge from pt_ to pts[1] at the x value of pts[0] typedef typename coordinate_traits<Unit>::manhattan_area_type at; at dy2 = (at)pts[1]->get(VERTICAL) - (at)y; at dy1 = (at)pts[0]->get(VERTICAL) - (at)y; at dx2 = (at)pts[1]->get(HORIZONTAL) - (at)x; at dx1 = (at)pts[0]->get(HORIZONTAL) - (at)x; return less_slope(dx1, dy1, dx2, dy2); } //return -1 below, 0 on and 1 above line //assumes point is on x interval of segment static inline int on_above_or_below(Point pt, const half_edge& he) { if(pt == he.first || pt == he.second) return 0; if(equal_slope(pt.get(HORIZONTAL), pt.get(VERTICAL), he.first, he.second)) return 0; bool less_result = less_slope(pt.get(HORIZONTAL), pt.get(VERTICAL), he.first, he.second); int retval = less_result ? -1 : 1; less_point lp; if(lp(he.second, he.first)) retval *= -1; if(!between(pt, he.first, he.second)) retval *= -1; return retval; } }; template <typename T, typename input_point_type> typename enable_if< typename gtl_and< typename is_any_mutable_polygon_with_holes_type<T>::type, typename gtl_same_type<typename geometry_concept<input_point_type>::type, point_concept>::type>::type, bool>::type contains(const T& polygon, const input_point_type& point, bool consider_touch = true) { typedef typename polygon_with_holes_traits<T>::iterator_holes_type holes_iterator; bool isInside = contains( view_as< typename polygon_from_polygon_with_holes_type< typename geometry_concept<T>::type>::type>( polygon ), point, consider_touch ); if(!isInside) return false; //no need to check holes holes_iterator itH = begin_holes( polygon ); while( itH != end_holes( polygon ) ) { if( contains( *itH, point, !consider_touch ) ) { isInside = false; break; } ++itH; } return isInside; } template <typename T, typename input_point_type> typename enable_if< typename gtl_and_3< typename is_polygon_type<T>::type, typename gtl_different_type<typename geometry_domain<typename geometry_concept<T>::type>::type, manhattan_domain>::type, typename gtl_same_type<typename geometry_concept<input_point_type>::type, point_concept>::type>::type, bool>::type contains(const T& polygon, const input_point_type& point, bool consider_touch = true) { typedef typename point_traits<input_point_type>::coordinate_type Unit; typedef point_data<Unit> Point; typedef std::pair<Point, Point> half_edge; typedef typename polygon_traits<T>::iterator_type iterator; iterator itr = begin_points(polygon); iterator itrEnd = end_points(polygon); half_edge he; if(itr == itrEnd) return false; assign(he.first, *itr); Point firstPt; assign(firstPt, *itr); ++itr; if(itr == itrEnd) return false; bool done = false; int above = 0; while(!done) { Point currentPt; if(itr == itrEnd) { done = true; currentPt = firstPt; } else { assign(currentPt, *itr); ++itr; } if(currentPt == he.first) { continue; } else { he.second = currentPt; if(equivalence(point, currentPt)) return consider_touch; Unit xmin = (std::min)(x(he.first), x(he.second)); Unit xmax = (std::max)(x(he.first), x(he.second)); if(x(point) >= xmin && x(point) < xmax) { //double counts if <= xmax Point tmppt; assign(tmppt, point); int oabedge = edge_utils<Unit>::on_above_or_below(tmppt, he); if(oabedge == 0) return consider_touch; if(oabedge == 1) ++above; } else if(x(point) == xmax) { if(x(point) == xmin) { Unit ymin = (std::min)(y(he.first), y(he.second)); Unit ymax = (std::max)(y(he.first), y(he.second)); Unit ypt = y(point); if(ypt <= ymax && ypt >= ymin) return consider_touch; } else { Point tmppt; assign(tmppt, point); if( edge_utils<Unit>::on_above_or_below(tmppt, he) == 0 ) { return consider_touch; } } } } he.first = he.second; } return above % 2 != 0; //if the point is above an odd number of edges is must be inside polygon } /* template <typename T, typename input_point_type> typename enable_if< typename gtl_and_3< typename is_polygon_with_holes_type<T>::type, typename gtl_different_type<typename geometry_domain<typename geometry_concept<T>::type>::type, manhattan_domain>::type, typename gtl_same_type<typename geometry_concept<input_point_type>::type, point_concept>::type>::type, bool>::type contains(const T& polygon, const input_point_type& point, bool consider_touch = true) { typedef typename point_traits<input_point_type>::coordinate_type Unit; typedef point_data<Unit> Point; typedef std::pair<Point, Point> half_edge; typedef typename polygon_traits<T>::iterator_type iterator; iterator itr = begin_points(polygon); iterator itrEnd = end_points(polygon); half_edge he; if(itr == itrEnd) return false; assign(he.first, *itr); Point firstPt; assign(firstPt, *itr); ++itr; if(itr == itrEnd) return false; bool done = false; int above = 0; while(!done) { Point currentPt; if(itr == itrEnd) { done = true; currentPt = firstPt; } else { assign(currentPt, *itr); ++itr; } if(currentPt == he.first) { continue; } else { he.second = currentPt; if(equivalence(point, currentPt)) return consider_touch; Unit xmin = (std::min)(x(he.first), x(he.second)); Unit xmax = (std::max)(x(he.first), x(he.second)); if(x(point) >= xmin && x(point) < xmax) { //double counts if <= xmax Point tmppt; assign(tmppt, point); int oabedge = edge_utils<Unit>::on_above_or_below(tmppt, he); if(oabedge == 0) return consider_touch; if(oabedge == 1) ++above; } } he.first = he.second; } return above % 2 != 0; //if the point is above an odd number of edges is must be inside polygon } */ template <typename T1, typename T2> typename enable_if< typename gtl_and< typename is_mutable_rectangle_concept<typename geometry_concept<T1>::type>::type, typename is_polygon_with_holes_type<T2>::type>::type, bool>::type extents(T1& bounding_box, const T2& polygon) { typedef typename polygon_traits<T2>::iterator_type iterator; bool first_iteration = true; iterator itr_end = end_points(polygon); for(iterator itr = begin_points(polygon); itr != itr_end; ++itr) { if(first_iteration) { set_points(bounding_box, *itr, *itr); first_iteration = false; } else { encompass(bounding_box, *itr); } } if(first_iteration) return false; return true; } template <typename T1, typename T2> typename enable_if< typename gtl_and< typename is_mutable_point_concept<typename geometry_concept<T1>::type>::type, typename is_polygon_with_holes_type<T2>::type>::type, bool>::type center(T1& center_point, const T2& polygon) { typedef typename polygon_traits<T2>::coordinate_type coordinate_type; rectangle_data<coordinate_type> bbox; extents(bbox, polygon); return center(center_point, bbox); } template <class T> template <class T2> polygon_90_data<T>& polygon_90_data<T>::operator=(const T2& rvalue) { assign(*this, rvalue); return *this; } template <class T> template <class T2> polygon_45_data<T>& polygon_45_data<T>::operator=(const T2& rvalue) { assign(*this, rvalue); return *this; } template <class T> template <class T2> polygon_data<T>& polygon_data<T>::operator=(const T2& rvalue) { assign(*this, rvalue); return *this; } template <class T> template <class T2> polygon_90_with_holes_data<T>& polygon_90_with_holes_data<T>::operator=(const T2& rvalue) { assign(*this, rvalue); return *this; } template <class T> template <class T2> polygon_45_with_holes_data<T>& polygon_45_with_holes_data<T>::operator=(const T2& rvalue) { assign(*this, rvalue); return *this; } template <class T> template <class T2> polygon_with_holes_data<T>& polygon_with_holes_data<T>::operator=(const T2& rvalue) { assign(*this, rvalue); return *this; } template <typename T> struct geometry_concept<polygon_data<T> > { typedef polygon_concept type; }; template <typename T> struct geometry_concept<polygon_45_data<T> > { typedef polygon_45_concept type; }; template <typename T> struct geometry_concept<polygon_90_data<T> > { typedef polygon_90_concept type; }; template <typename T> struct geometry_concept<polygon_with_holes_data<T> > { typedef polygon_with_holes_concept type; }; template <typename T> struct geometry_concept<polygon_45_with_holes_data<T> > { typedef polygon_45_with_holes_concept type; }; template <typename T> struct geometry_concept<polygon_90_with_holes_data<T> > { typedef polygon_90_with_holes_concept type; }; // template <typename T> struct polygon_with_holes_traits<polygon_90_data<T> > { // typedef polygon_90_data<T> hole_type; // typedef const hole_type* iterator_holes_type; // static inline iterator_holes_type begin_holes(const hole_type& t) { return &t; } // static inline iterator_holes_type end_holes(const hole_type& t) { return &t; } // static inline std::size_t size_holes(const hole_type& t) { return 0; } // }; // template <typename T> struct polygon_with_holes_traits<polygon_45_data<T> > { // typedef polygon_45_data<T> hole_type; // typedef const hole_type* iterator_holes_type; // static inline iterator_holes_type begin_holes(const hole_type& t) { return &t; } // static inline iterator_holes_type end_holes(const hole_type& t) { return &t; } // static inline std::size_t size_holes(const hole_type& t) { return 0; } // }; // template <typename T> struct polygon_with_holes_traits<polygon_data<T> > { // typedef polygon_data<T> hole_type; // typedef const hole_type* iterator_holes_type; // static inline iterator_holes_type begin_holes(const hole_type& t) { return &t; } // static inline iterator_holes_type end_holes(const hole_type& t) { return &t; } // static inline std::size_t size_holes(const hole_type& t) { return 0; } // }; template <typename T> struct get_void {}; template <> struct get_void<gtl_yes> { typedef void type; }; template <typename T> struct polygon_with_holes_traits< T, typename get_void<typename is_any_mutable_polygon_without_holes_type<T>::type>::type > { typedef T hole_type; typedef const hole_type* iterator_holes_type; static inline iterator_holes_type begin_holes(const hole_type& t) { return &t; } static inline iterator_holes_type end_holes(const hole_type& t) { return &t; } }; template <typename T> struct view_of<rectangle_concept, T> { typedef typename polygon_traits<T>::coordinate_type coordinate_type; typedef interval_data<coordinate_type> interval_type; rectangle_data<coordinate_type> rect; view_of(const T& obj) : rect() { point_data<coordinate_type> pts[2]; typename polygon_traits<T>::iterator_type itr = begin_points(obj), itre = end_points(obj); if(itr == itre) return; assign(pts[0], *itr); ++itr; if(itr == itre) return; ++itr; if(itr == itre) return; assign(pts[1], *itr); set_points(rect, pts[0], pts[1]); } inline interval_type get(orientation_2d orient) const { return rect.get(orient); } }; template <typename T> struct geometry_concept<view_of<rectangle_concept, T> > { typedef rectangle_concept type; }; template <typename T> struct view_of<polygon_45_concept, T> { const T* t; view_of(const T& obj) : t(&obj) {} typedef typename polygon_traits<T>::coordinate_type coordinate_type; typedef typename polygon_traits<T>::iterator_type iterator_type; typedef typename polygon_traits<T>::point_type point_type; /// Get the begin iterator inline iterator_type begin() const { return polygon_traits<T>::begin_points(*t); } /// Get the end iterator inline iterator_type end() const { return polygon_traits<T>::end_points(*t); } /// Get the number of sides of the polygon inline std::size_t size() const { return polygon_traits<T>::size(*t); } /// Get the winding direction of the polygon inline winding_direction winding() const { return polygon_traits<T>::winding(*t); } }; template <typename T> struct geometry_concept<view_of<polygon_45_concept, T> > { typedef polygon_45_concept type; }; template <typename T> struct view_of<polygon_90_concept, T> { const T* t; view_of(const T& obj) : t(&obj) {} typedef typename polygon_traits<T>::coordinate_type coordinate_type; typedef typename polygon_traits<T>::iterator_type iterator_type; typedef typename polygon_traits<T>::point_type point_type; typedef iterator_points_to_compact<iterator_type, point_type> compact_iterator_type; /// Get the begin iterator inline compact_iterator_type begin_compact() const { return compact_iterator_type(polygon_traits<T>::begin_points(*t), polygon_traits<T>::end_points(*t)); } /// Get the end iterator inline compact_iterator_type end_compact() const { return compact_iterator_type(polygon_traits<T>::end_points(*t), polygon_traits<T>::end_points(*t)); } /// Get the number of sides of the polygon inline std::size_t size() const { return polygon_traits<T>::size(*t); } /// Get the winding direction of the polygon inline winding_direction winding() const { return polygon_traits<T>::winding(*t); } }; template <typename T> struct geometry_concept<view_of<polygon_90_concept, T> > { typedef polygon_90_concept type; }; template <typename T> struct view_of<polygon_45_with_holes_concept, T> { const T* t; view_of(const T& obj) : t(&obj) {} typedef typename polygon_traits<T>::coordinate_type coordinate_type; typedef typename polygon_traits<T>::iterator_type iterator_type; typedef typename polygon_traits<T>::point_type point_type; typedef view_of<polygon_45_concept, typename polygon_with_holes_traits<T>::hole_type> hole_type; struct iterator_holes_type { typedef std::forward_iterator_tag iterator_category; typedef hole_type value_type; typedef std::ptrdiff_t difference_type; typedef const hole_type* pointer; //immutable typedef const hole_type& reference; //immutable typedef typename polygon_with_holes_traits<T>::iterator_holes_type iht; iht internal_itr; iterator_holes_type() : internal_itr() {} iterator_holes_type(iht iht_in) : internal_itr(iht_in) {} inline iterator_holes_type& operator++() { ++internal_itr; return *this; } inline const iterator_holes_type operator++(int) { iterator_holes_type tmp(*this); ++(*this); return tmp; } inline bool operator==(const iterator_holes_type& that) const { return (internal_itr == that.internal_itr); } inline bool operator!=(const iterator_holes_type& that) const { return (internal_itr != that.internal_itr); } inline value_type operator*() const { return view_as<polygon_45_concept>(*internal_itr); } }; /// Get the begin iterator inline iterator_type begin() const { return polygon_traits<T>::begin_points(*t); } /// Get the end iterator inline iterator_type end() const { return polygon_traits<T>::end_points(*t); } /// Get the number of sides of the polygon inline std::size_t size() const { return polygon_traits<T>::size(*t); } /// Get the winding direction of the polygon inline winding_direction winding() const { return polygon_traits<T>::winding(*t); } /// Get the begin iterator inline iterator_holes_type begin_holes() const { return polygon_with_holes_traits<T>::begin_holes(*t); } /// Get the end iterator inline iterator_holes_type end_holes() const { return polygon_with_holes_traits<T>::end_holes(*t); } /// Get the number of sides of the polygon inline std::size_t size_holes() const { return polygon_with_holes_traits<T>::size_holes(*t); } }; template <typename T> struct geometry_concept<view_of<polygon_45_with_holes_concept, T> > { typedef polygon_45_with_holes_concept type; }; template <typename T> struct view_of<polygon_90_with_holes_concept, T> { const T* t; view_of(const T& obj) : t(&obj) {} typedef typename polygon_traits<T>::coordinate_type coordinate_type; typedef typename polygon_traits<T>::iterator_type iterator_type; typedef typename polygon_traits<T>::point_type point_type; typedef iterator_points_to_compact<iterator_type, point_type> compact_iterator_type; typedef view_of<polygon_90_concept, typename polygon_with_holes_traits<T>::hole_type> hole_type; struct iterator_holes_type { typedef std::forward_iterator_tag iterator_category; typedef hole_type value_type; typedef std::ptrdiff_t difference_type; typedef const hole_type* pointer; //immutable typedef const hole_type& reference; //immutable typedef typename polygon_with_holes_traits<T>::iterator_holes_type iht; iht internal_itr; iterator_holes_type() : internal_itr() {} iterator_holes_type(iht iht_in) : internal_itr(iht_in) {} inline iterator_holes_type& operator++() { ++internal_itr; return *this; } inline const iterator_holes_type operator++(int) { iterator_holes_type tmp(*this); ++(*this); return tmp; } inline bool operator==(const iterator_holes_type& that) const { return (internal_itr == that.internal_itr); } inline bool operator!=(const iterator_holes_type& that) const { return (internal_itr != that.internal_itr); } inline value_type operator*() const { return view_as<polygon_90_concept>(*internal_itr); } }; /// Get the begin iterator inline compact_iterator_type begin_compact() const { return compact_iterator_type(polygon_traits<T>::begin_points(*t), polygon_traits<T>::end_points(*t)); } /// Get the end iterator inline compact_iterator_type end_compact() const { return compact_iterator_type(polygon_traits<T>::end_points(*t), polygon_traits<T>::end_points(*t)); } /// Get the number of sides of the polygon inline std::size_t size() const { return polygon_traits<T>::size(*t); } /// Get the winding direction of the polygon inline winding_direction winding() const { return polygon_traits<T>::winding(*t); } /// Get the begin iterator inline iterator_holes_type begin_holes() const { return polygon_with_holes_traits<T>::begin_holes(*t); } /// Get the end iterator inline iterator_holes_type end_holes() const { return polygon_with_holes_traits<T>::end_holes(*t); } /// Get the number of sides of the polygon inline std::size_t size_holes() const { return polygon_with_holes_traits<T>::size_holes(*t); } }; template <typename T> struct geometry_concept<view_of<polygon_90_with_holes_concept, T> > { typedef polygon_90_with_holes_concept type; }; template <typename T> struct view_of<polygon_concept, T> { const T* t; view_of(const T& obj) : t(&obj) {} typedef typename polygon_traits<T>::coordinate_type coordinate_type; typedef typename polygon_traits<T>::iterator_type iterator_type; typedef typename polygon_traits<T>::point_type point_type; /// Get the begin iterator inline iterator_type begin() const { return polygon_traits<T>::begin_points(*t); } /// Get the end iterator inline iterator_type end() const { return polygon_traits<T>::end_points(*t); } /// Get the number of sides of the polygon inline std::size_t size() const { return polygon_traits<T>::size(*t); } /// Get the winding direction of the polygon inline winding_direction winding() const { return polygon_traits<T>::winding(*t); } }; template <typename T> struct geometry_concept<view_of<polygon_concept, T> > { typedef polygon_concept type; }; } } #endif PK �b�[Q���/ �/ detail/rectangle_formation.hppnu �[��� /* Copyright 2008 Intel Corporation Use, modification and distribution are 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_POLYGON_RECTANGLE_FORMATION_HPP #define BOOST_POLYGON_RECTANGLE_FORMATION_HPP namespace boost { namespace polygon{ namespace rectangle_formation { template <class T> class ScanLineToRects { public: typedef T rectangle_type; typedef typename rectangle_traits<T>::coordinate_type coordinate_type; typedef rectangle_data<coordinate_type> scan_rect_type; private: typedef std::set<scan_rect_type, less_rectangle_concept<scan_rect_type, scan_rect_type> > ScanData; ScanData scanData_; bool haveCurrentRect_; scan_rect_type currentRect_; orientation_2d orient_; typename rectangle_traits<T>::coordinate_type currentCoordinate_; public: inline ScanLineToRects() : scanData_(), haveCurrentRect_(), currentRect_(), orient_(), currentCoordinate_() {} inline ScanLineToRects(orientation_2d orient, rectangle_type model) : scanData_(orientation_2d(orient.to_int() ? VERTICAL : HORIZONTAL)), haveCurrentRect_(false), currentRect_(), orient_(orient), currentCoordinate_() { assign(currentRect_, model); currentCoordinate_ = (std::numeric_limits<coordinate_type>::max)(); } template <typename CT> inline ScanLineToRects& processEdge(CT& rectangles, const interval_data<coordinate_type>& edge); inline ScanLineToRects& nextMajorCoordinate(coordinate_type currentCoordinate) { if(haveCurrentRect_) { scanData_.insert(scanData_.end(), currentRect_); haveCurrentRect_ = false; } currentCoordinate_ = currentCoordinate; return *this; } }; template <class CT, class ST, class rectangle_type, typename interval_type, typename coordinate_type> inline CT& processEdge_(CT& rectangles, ST& scanData, const interval_type& edge, bool& haveCurrentRect, rectangle_type& currentRect, coordinate_type currentCoordinate, orientation_2d orient) { typedef typename CT::value_type result_type; bool edgeProcessed = false; if(!scanData.empty()) { //process all rectangles in the scanData that touch the edge typename ST::iterator dataIter = scanData.lower_bound(rectangle_type(edge, edge)); //decrement beginIter until its low is less than edge's low while((dataIter == scanData.end() || (*dataIter).get(orient).get(LOW) > edge.get(LOW)) && dataIter != scanData.begin()) { --dataIter; } //process each rectangle until the low end of the rectangle //is greater than the high end of the edge while(dataIter != scanData.end() && (*dataIter).get(orient).get(LOW) <= edge.get(HIGH)) { const rectangle_type& rect = *dataIter; //if the rectangle data intersects the edge at all if(rect.get(orient).get(HIGH) >= edge.get(LOW)) { if(contains(rect.get(orient), edge, true)) { //this is a closing edge //we need to write out the intersecting rectangle and //insert between 0 and 2 rectangles into the scanData //write out rectangle rectangle_type tmpRect = rect; if(rect.get(orient.get_perpendicular()).get(LOW) < currentCoordinate) { //set the high coordinate perpedicular to slicing orientation //to the current coordinate of the scan event tmpRect.set(orient.get_perpendicular().get_direction(HIGH), currentCoordinate); result_type result; assign(result, tmpRect); rectangles.insert(rectangles.end(), result); } //erase the rectangle from the scan data typename ST::iterator nextIter = dataIter; ++nextIter; scanData.erase(dataIter); if(tmpRect.get(orient).get(LOW) < edge.get(LOW)) { //insert a rectangle for the overhang of the bottom //of the rectangle back into scan data rectangle_type lowRect(tmpRect); lowRect.set(orient.get_perpendicular(), interval_data<coordinate_type>(currentCoordinate, currentCoordinate)); lowRect.set(orient.get_direction(HIGH), edge.get(LOW)); scanData.insert(nextIter, lowRect); } if(tmpRect.get(orient).get(HIGH) > edge.get(HIGH)) { //insert a rectangle for the overhang of the top //of the rectangle back into scan data rectangle_type highRect(tmpRect); highRect.set(orient.get_perpendicular(), interval_data<coordinate_type>(currentCoordinate, currentCoordinate)); highRect.set(orient.get_direction(LOW), edge.get(HIGH)); scanData.insert(nextIter, highRect); } //we are done with this edge edgeProcessed = true; break; } else { //it must be an opening edge //assert that rect does not overlap the edge but only touches //write out rectangle rectangle_type tmpRect = rect; //set the high coordinate perpedicular to slicing orientation //to the current coordinate of the scan event if(tmpRect.get(orient.get_perpendicular().get_direction(LOW)) < currentCoordinate) { tmpRect.set(orient.get_perpendicular().get_direction(HIGH), currentCoordinate); result_type result; assign(result, tmpRect); rectangles.insert(rectangles.end(), result); } //erase the rectangle from the scan data typename ST::iterator nextIter = dataIter; ++nextIter; scanData.erase(dataIter); dataIter = nextIter; if(haveCurrentRect) { if(currentRect.get(orient).get(HIGH) >= edge.get(LOW)){ if(!edgeProcessed && currentRect.get(orient.get_direction(HIGH)) > edge.get(LOW)){ rectangle_type tmpRect2(currentRect); tmpRect2.set(orient.get_direction(HIGH), edge.get(LOW)); scanData.insert(nextIter, tmpRect2); if(currentRect.get(orient.get_direction(HIGH)) > edge.get(HIGH)) { currentRect.set(orient, interval_data<coordinate_type>(edge.get(HIGH), currentRect.get(orient.get_direction(HIGH)))); } else { haveCurrentRect = false; } } else { //extend the top of current rect currentRect.set(orient.get_direction(HIGH), (std::max)(edge.get(HIGH), tmpRect.get(orient.get_direction(HIGH)))); } } else { //insert current rect into the scanData scanData.insert(nextIter, currentRect); //create a new current rect currentRect.set(orient.get_perpendicular(), interval_data<coordinate_type>(currentCoordinate, currentCoordinate)); currentRect.set(orient, interval_data<coordinate_type>((std::min)(tmpRect.get(orient).get(LOW), edge.get(LOW)), (std::max)(tmpRect.get(orient).get(HIGH), edge.get(HIGH)))); } } else { haveCurrentRect = true; currentRect.set(orient.get_perpendicular(), interval_data<coordinate_type>(currentCoordinate, currentCoordinate)); currentRect.set(orient, interval_data<coordinate_type>((std::min)(tmpRect.get(orient).get(LOW), edge.get(LOW)), (std::max)(tmpRect.get(orient).get(HIGH), edge.get(HIGH)))); } //skip to nextIter position edgeProcessed = true; continue; } //edgeProcessed = true; } ++dataIter; } //end while edge intersects rectangle data } if(!edgeProcessed) { if(haveCurrentRect) { if(currentRect.get(orient.get_perpendicular().get_direction(HIGH)) == currentCoordinate && currentRect.get(orient.get_direction(HIGH)) >= edge.get(LOW)) { if(currentRect.get(orient.get_direction(HIGH)) > edge.get(LOW)){ rectangle_type tmpRect(currentRect); tmpRect.set(orient.get_direction(HIGH), edge.get(LOW)); scanData.insert(scanData.end(), tmpRect); if(currentRect.get(orient.get_direction(HIGH)) > edge.get(HIGH)) { currentRect.set(orient, interval_data<coordinate_type>(edge.get(HIGH), currentRect.get(orient.get_direction(HIGH)))); return rectangles; } else { haveCurrentRect = false; return rectangles; } } //extend current rect currentRect.set(orient.get_direction(HIGH), edge.get(HIGH)); return rectangles; } scanData.insert(scanData.end(), currentRect); haveCurrentRect = false; } rectangle_type tmpRect(currentRect); tmpRect.set(orient.get_perpendicular(), interval_data<coordinate_type>(currentCoordinate, currentCoordinate)); tmpRect.set(orient, edge); scanData.insert(tmpRect); return rectangles; } return rectangles; } template <class T> template <class CT> inline ScanLineToRects<T>& ScanLineToRects<T>::processEdge(CT& rectangles, const interval_data<coordinate_type>& edge) { processEdge_(rectangles, scanData_, edge, haveCurrentRect_, currentRect_, currentCoordinate_, orient_); return *this; } } //namespace rectangle_formation template <typename T, typename T2> struct get_coordinate_type_for_rectangles { typedef typename polygon_traits<T>::coordinate_type type; }; template <typename T> struct get_coordinate_type_for_rectangles<T, rectangle_concept> { typedef typename rectangle_traits<T>::coordinate_type type; }; template <typename output_container, typename iterator_type, typename rectangle_concept> void form_rectangles(output_container& output, iterator_type begin, iterator_type end, orientation_2d orient, rectangle_concept ) { typedef typename output_container::value_type rectangle_type; typedef typename get_coordinate_type_for_rectangles<rectangle_type, typename geometry_concept<rectangle_type>::type>::type Unit; rectangle_data<Unit> model; Unit prevPos = (std::numeric_limits<Unit>::max)(); rectangle_formation::ScanLineToRects<rectangle_data<Unit> > scanlineToRects(orient, model); for(iterator_type itr = begin; itr != end; ++ itr) { Unit pos = (*itr).first; if(pos != prevPos) { scanlineToRects.nextMajorCoordinate(pos); prevPos = pos; } Unit lowy = (*itr).second.first; iterator_type tmp_itr = itr; ++itr; Unit highy = (*itr).second.first; scanlineToRects.processEdge(output, interval_data<Unit>(lowy, highy)); if(std::abs((*itr).second.second) > 1) itr = tmp_itr; //next edge begins from this vertex } } } } #endif PK �b�[_Ϭg�D �D detail/boolean_op.hppnu �[��� /* Copyright 2008 Intel Corporation Use, modification and distribution are 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_POLYGON_BOOLEAN_OP_HPP #define BOOST_POLYGON_BOOLEAN_OP_HPP namespace boost { namespace polygon{ namespace boolean_op { //BooleanOp is the generic boolean operation scanline algorithm that provides //all the simple boolean set operations on manhattan data. By templatizing //the intersection count of the input and algorithm internals it is extensible //to multi-layer scans, properties and other advanced scanline operations above //and beyond simple booleans. //T must cast to int template <class T, typename Unit> class BooleanOp { public: typedef std::map<Unit, T> ScanData; typedef std::pair<Unit, T> ElementType; protected: ScanData scanData_; typename ScanData::iterator nextItr_; T nullT_; public: inline BooleanOp () : scanData_(), nextItr_(), nullT_() { nextItr_ = scanData_.end(); nullT_ = 0; } inline BooleanOp (T nullT) : scanData_(), nextItr_(), nullT_(nullT) { nextItr_ = scanData_.end(); } inline BooleanOp (const BooleanOp& that) : scanData_(that.scanData_), nextItr_(), nullT_(that.nullT_) { nextItr_ = scanData_.begin(); } inline BooleanOp& operator=(const BooleanOp& that); //moves scanline forward inline void advanceScan() { nextItr_ = scanData_.begin(); } //proceses the given interval and T data //appends output edges to cT template <class cT> inline void processInterval(cT& outputContainer, interval_data<Unit> ivl, T deltaCount); private: inline typename ScanData::iterator lookup_(Unit pos){ if(nextItr_ != scanData_.end() && nextItr_->first >= pos) { return nextItr_; } return nextItr_ = scanData_.lower_bound(pos); } inline typename ScanData::iterator insert_(Unit pos, T count){ return nextItr_ = scanData_.insert(nextItr_, ElementType(pos, count)); } template <class cT> inline void evaluateInterval_(cT& outputContainer, interval_data<Unit> ivl, T beforeCount, T afterCount); }; class BinaryAnd { public: inline BinaryAnd() {} inline bool operator()(int a, int b) { return (a > 0) & (b > 0); } }; class BinaryOr { public: inline BinaryOr() {} inline bool operator()(int a, int b) { return (a > 0) | (b > 0); } }; class BinaryNot { public: inline BinaryNot() {} inline bool operator()(int a, int b) { return (a > 0) & !(b > 0); } }; class BinaryXor { public: inline BinaryXor() {} inline bool operator()(int a, int b) { return (a > 0) ^ (b > 0); } }; //BinaryCount is an array of two deltaCounts coming from two different layers //of scan event data. It is the merged count of the two suitable for consumption //as the template argument of the BooleanOp algorithm because BinaryCount casts to int. //T is a binary functor object that evaluates the array of counts and returns a logical //result of some operation on those values. //BinaryCount supports many of the operators that work with int, particularly the //binary operators, but cannot support less than or increment. template <class T> class BinaryCount { public: inline BinaryCount() #ifndef BOOST_POLYGON_MSVC : counts_() #endif { counts_[0] = counts_[1] = 0; } // constructs from two integers inline BinaryCount(int countL, int countR) #ifndef BOOST_POLYGON_MSVC : counts_() #endif { counts_[0] = countL, counts_[1] = countR; } inline BinaryCount& operator=(int count) { counts_[0] = count, counts_[1] = count; return *this; } inline BinaryCount& operator=(const BinaryCount& that); inline BinaryCount(const BinaryCount& that) #ifndef BOOST_POLYGON_MSVC : counts_() #endif { *this = that; } inline bool operator==(const BinaryCount& that) const; inline bool operator!=(const BinaryCount& that) const { return !((*this) == that);} inline BinaryCount& operator+=(const BinaryCount& that); inline BinaryCount& operator-=(const BinaryCount& that); inline BinaryCount operator+(const BinaryCount& that) const; inline BinaryCount operator-(const BinaryCount& that) const; inline BinaryCount operator-() const; inline int& operator[](bool index) { return counts_[index]; } //cast to int operator evaluates data using T binary functor inline operator int() const { return T()(counts_[0], counts_[1]); } private: int counts_[2]; }; class UnaryCount { public: inline UnaryCount() : count_(0) {} // constructs from two integers inline explicit UnaryCount(int count) : count_(count) {} inline UnaryCount& operator=(int count) { count_ = count; return *this; } inline UnaryCount& operator=(const UnaryCount& that) { count_ = that.count_; return *this; } inline UnaryCount(const UnaryCount& that) : count_(that.count_) {} inline bool operator==(const UnaryCount& that) const { return count_ == that.count_; } inline bool operator!=(const UnaryCount& that) const { return !((*this) == that);} inline UnaryCount& operator+=(const UnaryCount& that) { count_ += that.count_; return *this; } inline UnaryCount& operator-=(const UnaryCount& that) { count_ -= that.count_; return *this; } inline UnaryCount operator+(const UnaryCount& that) const { UnaryCount tmp(*this); tmp += that; return tmp; } inline UnaryCount operator-(const UnaryCount& that) const { UnaryCount tmp(*this); tmp -= that; return tmp; } inline UnaryCount operator-() const { UnaryCount tmp; return tmp - *this; } //cast to int operator evaluates data using T binary functor inline operator int() const { return count_ % 2; } private: int count_; }; template <class T, typename Unit> inline BooleanOp<T, Unit>& BooleanOp<T, Unit>::operator=(const BooleanOp& that) { scanData_ = that.scanData_; nextItr_ = scanData_.begin(); nullT_ = that.nullT_; return *this; } //appends output edges to cT template <class T, typename Unit> template <class cT> inline void BooleanOp<T, Unit>::processInterval(cT& outputContainer, interval_data<Unit> ivl, T deltaCount) { typename ScanData::iterator lowItr = lookup_(ivl.low()); typename ScanData::iterator highItr = lookup_(ivl.high()); //add interval to scan data if it is past the end if(lowItr == scanData_.end()) { lowItr = insert_(ivl.low(), deltaCount); highItr = insert_(ivl.high(), nullT_); evaluateInterval_(outputContainer, ivl, nullT_, deltaCount); return; } //ensure that highItr points to the end of the ivl if(highItr == scanData_.end() || (*highItr).first > ivl.high()) { T value = nullT_; if(highItr != scanData_.begin()) { --highItr; value = highItr->second; } nextItr_ = highItr; highItr = insert_(ivl.high(), value); } //split the low interval if needed if(lowItr->first > ivl.low()) { if(lowItr != scanData_.begin()) { --lowItr; nextItr_ = lowItr; lowItr = insert_(ivl.low(), lowItr->second); } else { nextItr_ = lowItr; lowItr = insert_(ivl.low(), nullT_); } } //process scan data intersecting interval for(typename ScanData::iterator itr = lowItr; itr != highItr; ){ T beforeCount = itr->second; T afterCount = itr->second += deltaCount; Unit low = itr->first; ++itr; Unit high = itr->first; evaluateInterval_(outputContainer, interval_data<Unit>(low, high), beforeCount, afterCount); } //merge the bottom interval with the one below if they have the same count if(lowItr != scanData_.begin()){ typename ScanData::iterator belowLowItr = lowItr; --belowLowItr; if(belowLowItr->second == lowItr->second) { scanData_.erase(lowItr); } } //merge the top interval with the one above if they have the same count if(highItr != scanData_.begin()) { typename ScanData::iterator beforeHighItr = highItr; --beforeHighItr; if(beforeHighItr->second == highItr->second) { scanData_.erase(highItr); highItr = beforeHighItr; ++highItr; } } nextItr_ = highItr; } template <class T, typename Unit> template <class cT> inline void BooleanOp<T, Unit>::evaluateInterval_(cT& outputContainer, interval_data<Unit> ivl, T beforeCount, T afterCount) { bool before = (int)beforeCount > 0; bool after = (int)afterCount > 0; int value = (!before & after) - (before & !after); if(value) { outputContainer.insert(outputContainer.end(), std::pair<interval_data<Unit>, int>(ivl, value)); } } template <class T> inline BinaryCount<T>& BinaryCount<T>::operator=(const BinaryCount<T>& that) { counts_[0] = that.counts_[0]; counts_[1] = that.counts_[1]; return *this; } template <class T> inline bool BinaryCount<T>::operator==(const BinaryCount<T>& that) const { return counts_[0] == that.counts_[0] && counts_[1] == that.counts_[1]; } template <class T> inline BinaryCount<T>& BinaryCount<T>::operator+=(const BinaryCount<T>& that) { counts_[0] += that.counts_[0]; counts_[1] += that.counts_[1]; return *this; } template <class T> inline BinaryCount<T>& BinaryCount<T>::operator-=(const BinaryCount<T>& that) { counts_[0] += that.counts_[0]; counts_[1] += that.counts_[1]; return *this; } template <class T> inline BinaryCount<T> BinaryCount<T>::operator+(const BinaryCount<T>& that) const { BinaryCount retVal(*this); retVal += that; return retVal; } template <class T> inline BinaryCount<T> BinaryCount<T>::operator-(const BinaryCount<T>& that) const { BinaryCount retVal(*this); retVal -= that; return retVal; } template <class T> inline BinaryCount<T> BinaryCount<T>::operator-() const { return BinaryCount<T>() - *this; } template <class T, typename Unit, typename iterator_type_1, typename iterator_type_2> inline void applyBooleanBinaryOp(std::vector<std::pair<Unit, std::pair<Unit, int> > >& output, //const std::vector<std::pair<Unit, std::pair<Unit, int> > >& input1, //const std::vector<std::pair<Unit, std::pair<Unit, int> > >& input2, iterator_type_1 itr1, iterator_type_1 itr1_end, iterator_type_2 itr2, iterator_type_2 itr2_end, T defaultCount) { BooleanOp<T, Unit> boolean(defaultCount); //typename std::vector<std::pair<Unit, std::pair<Unit, int> > >::const_iterator itr1 = input1.begin(); //typename std::vector<std::pair<Unit, std::pair<Unit, int> > >::const_iterator itr2 = input2.begin(); std::vector<std::pair<interval_data<Unit>, int> > container; //output.reserve((std::max)(input1.size(), input2.size())); //consider eliminating dependecy on limits with bool flag for initial state Unit UnitMax = (std::numeric_limits<Unit>::max)(); Unit prevCoord = UnitMax; Unit prevPosition = UnitMax; T count(defaultCount); //define the starting point if(itr1 != itr1_end) { prevCoord = (*itr1).first; prevPosition = (*itr1).second.first; count[0] += (*itr1).second.second; } if(itr2 != itr2_end) { if((*itr2).first < prevCoord || ((*itr2).first == prevCoord && (*itr2).second.first < prevPosition)) { prevCoord = (*itr2).first; prevPosition = (*itr2).second.first; count = defaultCount; count[1] += (*itr2).second.second; ++itr2; } else if((*itr2).first == prevCoord && (*itr2).second.first == prevPosition) { count[1] += (*itr2).second.second; ++itr2; if(itr1 != itr1_end) ++itr1; } else { if(itr1 != itr1_end) ++itr1; } } else { if(itr1 != itr1_end) ++itr1; } while(itr1 != itr1_end || itr2 != itr2_end) { Unit curCoord = UnitMax; Unit curPosition = UnitMax; T curCount(defaultCount); if(itr1 != itr1_end) { curCoord = (*itr1).first; curPosition = (*itr1).second.first; curCount[0] += (*itr1).second.second; } if(itr2 != itr2_end) { if((*itr2).first < curCoord || ((*itr2).first == curCoord && (*itr2).second.first < curPosition)) { curCoord = (*itr2).first; curPosition = (*itr2).second.first; curCount = defaultCount; curCount[1] += (*itr2).second.second; ++itr2; } else if((*itr2).first == curCoord && (*itr2).second.first == curPosition) { curCount[1] += (*itr2).second.second; ++itr2; if(itr1 != itr1_end) ++itr1; } else { if(itr1 != itr1_end) ++itr1; } } else { ++itr1; } if(prevCoord != curCoord) { boolean.advanceScan(); prevCoord = curCoord; prevPosition = curPosition; count = curCount; continue; } if(curPosition != prevPosition && count != defaultCount) { interval_data<Unit> ivl(prevPosition, curPosition); container.clear(); boolean.processInterval(container, ivl, count); for(std::size_t i = 0; i < container.size(); ++i) { std::pair<interval_data<Unit>, int>& element = container[i]; if(!output.empty() && output.back().first == prevCoord && output.back().second.first == element.first.low() && output.back().second.second == element.second * -1) { output.pop_back(); } else { output.push_back(std::pair<Unit, std::pair<Unit, int> >(prevCoord, std::pair<Unit, int>(element.first.low(), element.second))); } output.push_back(std::pair<Unit, std::pair<Unit, int> >(prevCoord, std::pair<Unit, int>(element.first.high(), element.second * -1))); } } prevPosition = curPosition; count += curCount; } } template <class T, typename Unit> inline void applyBooleanBinaryOp(std::vector<std::pair<Unit, std::pair<Unit, int> > >& inputOutput, const std::vector<std::pair<Unit, std::pair<Unit, int> > >& input2, T defaultCount) { std::vector<std::pair<Unit, std::pair<Unit, int> > > output; applyBooleanBinaryOp(output, inputOutput, input2, defaultCount); if(output.size() < inputOutput.size() / 2) { inputOutput = std::vector<std::pair<Unit, std::pair<Unit, int> > >(); } else { inputOutput.clear(); } inputOutput.insert(inputOutput.end(), output.begin(), output.end()); } template <typename count_type = int> struct default_arg_workaround { template <typename Unit> static inline void applyBooleanOr(std::vector<std::pair<Unit, std::pair<Unit, int> > >& input) { BooleanOp<count_type, Unit> booleanOr; std::vector<std::pair<interval_data<Unit>, int> > container; std::vector<std::pair<Unit, std::pair<Unit, int> > > output; output.reserve(input.size()); //consider eliminating dependecy on limits with bool flag for initial state Unit UnitMax = (std::numeric_limits<Unit>::max)(); Unit prevPos = UnitMax; Unit prevY = UnitMax; int count = 0; for(typename std::vector<std::pair<Unit, std::pair<Unit, int> > >::iterator itr = input.begin(); itr != input.end(); ++itr) { Unit pos = (*itr).first; Unit y = (*itr).second.first; if(pos != prevPos) { booleanOr.advanceScan(); prevPos = pos; prevY = y; count = (*itr).second.second; continue; } if(y != prevY && count != 0) { interval_data<Unit> ivl(prevY, y); container.clear(); booleanOr.processInterval(container, ivl, count_type(count)); for(std::size_t i = 0; i < container.size(); ++i) { std::pair<interval_data<Unit>, int>& element = container[i]; if(!output.empty() && output.back().first == prevPos && output.back().second.first == element.first.low() && output.back().second.second == element.second * -1) { output.pop_back(); } else { output.push_back(std::pair<Unit, std::pair<Unit, int> >(prevPos, std::pair<Unit, int>(element.first.low(), element.second))); } output.push_back(std::pair<Unit, std::pair<Unit, int> >(prevPos, std::pair<Unit, int>(element.first.high(), element.second * -1))); } } prevY = y; count += (*itr).second.second; } if(output.size() < input.size() / 2) { input = std::vector<std::pair<Unit, std::pair<Unit, int> > >(); } else { input.clear(); } input.insert(input.end(), output.begin(), output.end()); } }; } } } #endif PK �b�[%���� � % detail/iterator_compact_to_points.hppnu �[��� /* Copyright 2008 Intel Corporation Use, modification and distribution are 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_POLYGON_ITERATOR_COMPACT_TO_POINTS_HPP #define BOOST_POLYGON_ITERATOR_COMPACT_TO_POINTS_HPP namespace boost { namespace polygon{ template <typename iterator_type, typename point_type> class iterator_compact_to_points { private: iterator_type iter_; iterator_type iter_end_; point_type pt_; typename point_traits<point_type>::coordinate_type firstX_; orientation_2d orient_; public: typedef std::forward_iterator_tag iterator_category; typedef point_type value_type; typedef std::ptrdiff_t difference_type; typedef const point_type* pointer; //immutable typedef const point_type& reference; //immutable inline iterator_compact_to_points() : iter_(), iter_end_(), pt_(), firstX_(), orient_() {} inline iterator_compact_to_points(iterator_type iter, iterator_type iter_end) : iter_(iter), iter_end_(iter_end), pt_(), firstX_(), orient_(HORIZONTAL) { if(iter_ != iter_end_) { firstX_ = *iter_; x(pt_, firstX_); ++iter_; if(iter_ != iter_end_) { y(pt_, *iter_); } } } //use bitwise copy and assign provided by the compiler inline iterator_compact_to_points& operator++() { iterator_type prev_iter = iter_; ++iter_; if(iter_ == iter_end_) { if(x(pt_) != firstX_) { iter_ = prev_iter; x(pt_, firstX_); } } else { set(pt_, orient_, *iter_); orient_.turn_90(); } return *this; } inline const iterator_compact_to_points operator++(int) { iterator_compact_to_points tmp(*this); ++(*this); return tmp; } inline bool operator==(const iterator_compact_to_points& that) const { if (iter_ == iter_end_) { return iter_ == that.iter_; } return (iter_ == that.iter_) && (x(pt_) == x(that.pt_)); } inline bool operator!=(const iterator_compact_to_points& that) const { if (iter_ == iter_end_) { return iter_ != that.iter_; } return (iter_ != that.iter_) || (x(pt_) != x(that.pt_)); } inline reference operator*() const { return pt_; } }; } } #endif PK �b�[zi�u�9 �9 detail/voronoi_robust_fpt.hppnu �[��� // Boost.Polygon library detail/voronoi_robust_fpt.hpp header file // Copyright Andrii Sydorchuk 2010-2012. // Distributed under 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) // See http://www.boost.org for updates, documentation, and revision history. #ifndef BOOST_POLYGON_DETAIL_VORONOI_ROBUST_FPT #define BOOST_POLYGON_DETAIL_VORONOI_ROBUST_FPT #include <algorithm> #include <cmath> // Geometry predicates with floating-point variables usually require // high-precision predicates to retrieve the correct result. // Epsilon robust predicates give the result within some epsilon relative // error, but are a lot faster than high-precision predicates. // To make algorithm robust and efficient epsilon robust predicates are // used at the first step. In case of the undefined result high-precision // arithmetic is used to produce required robustness. This approach // requires exact computation of epsilon intervals within which epsilon // robust predicates have undefined value. // There are two ways to measure an error of floating-point calculations: // relative error and ULPs (units in the last place). // Let EPS be machine epsilon, then next inequalities have place: // 1 EPS <= 1 ULP <= 2 EPS (1), 0.5 ULP <= 1 EPS <= 1 ULP (2). // ULPs are good for measuring rounding errors and comparing values. // Relative errors are good for computation of general relative // error of formulas or expressions. So to calculate epsilon // interval within which epsilon robust predicates have undefined result // next schema is used: // 1) Compute rounding errors of initial variables using ULPs; // 2) Transform ULPs to epsilons using upper bound of the (1); // 3) Compute relative error of the formula using epsilon arithmetic; // 4) Transform epsilon to ULPs using upper bound of the (2); // In case two values are inside undefined ULP range use high-precision // arithmetic to produce the correct result, else output the result. // Look at almost_equal function to see how two floating-point variables // are checked to fit in the ULP range. // If A has relative error of r(A) and B has relative error of r(B) then: // 1) r(A + B) <= max(r(A), r(B)), for A * B >= 0; // 2) r(A - B) <= B*r(A)+A*r(B)/(A-B), for A * B >= 0; // 2) r(A * B) <= r(A) + r(B); // 3) r(A / B) <= r(A) + r(B); // In addition rounding error should be added, that is always equal to // 0.5 ULP or at most 1 epsilon. As you might see from the above formulas // subtraction relative error may be extremely large, that's why // epsilon robust comparator class is used to store floating point values // and compute subtraction as the final step of the evaluation. // For further information about relative errors and ULPs try this link: // http://docs.sun.com/source/806-3568/ncg_goldberg.html namespace boost { namespace polygon { namespace detail { template <typename T> T get_sqrt(const T& that) { return (std::sqrt)(that); } template <typename T> bool is_pos(const T& that) { return that > 0; } template <typename T> bool is_neg(const T& that) { return that < 0; } template <typename T> bool is_zero(const T& that) { return that == 0; } template <typename _fpt> class robust_fpt { public: typedef _fpt floating_point_type; typedef _fpt relative_error_type; // Rounding error is at most 1 EPS. enum { ROUNDING_ERROR = 1 }; robust_fpt() : fpv_(0.0), re_(0.0) {} explicit robust_fpt(floating_point_type fpv) : fpv_(fpv), re_(0.0) {} robust_fpt(floating_point_type fpv, relative_error_type error) : fpv_(fpv), re_(error) {} floating_point_type fpv() const { return fpv_; } relative_error_type re() const { return re_; } relative_error_type ulp() const { return re_; } bool has_pos_value() const { return is_pos(fpv_); } bool has_neg_value() const { return is_neg(fpv_); } bool has_zero_value() const { return is_zero(fpv_); } robust_fpt operator-() const { return robust_fpt(-fpv_, re_); } robust_fpt& operator+=(const robust_fpt& that) { floating_point_type fpv = this->fpv_ + that.fpv_; if ((!is_neg(this->fpv_) && !is_neg(that.fpv_)) || (!is_pos(this->fpv_) && !is_pos(that.fpv_))) { this->re_ = (std::max)(this->re_, that.re_) + ROUNDING_ERROR; } else { floating_point_type temp = (this->fpv_ * this->re_ - that.fpv_ * that.re_) / fpv; if (is_neg(temp)) temp = -temp; this->re_ = temp + ROUNDING_ERROR; } this->fpv_ = fpv; return *this; } robust_fpt& operator-=(const robust_fpt& that) { floating_point_type fpv = this->fpv_ - that.fpv_; if ((!is_neg(this->fpv_) && !is_pos(that.fpv_)) || (!is_pos(this->fpv_) && !is_neg(that.fpv_))) { this->re_ = (std::max)(this->re_, that.re_) + ROUNDING_ERROR; } else { floating_point_type temp = (this->fpv_ * this->re_ + that.fpv_ * that.re_) / fpv; if (is_neg(temp)) temp = -temp; this->re_ = temp + ROUNDING_ERROR; } this->fpv_ = fpv; return *this; } robust_fpt& operator*=(const robust_fpt& that) { this->re_ += that.re_ + ROUNDING_ERROR; this->fpv_ *= that.fpv_; return *this; } robust_fpt& operator/=(const robust_fpt& that) { this->re_ += that.re_ + ROUNDING_ERROR; this->fpv_ /= that.fpv_; return *this; } robust_fpt operator+(const robust_fpt& that) const { floating_point_type fpv = this->fpv_ + that.fpv_; relative_error_type re; if ((!is_neg(this->fpv_) && !is_neg(that.fpv_)) || (!is_pos(this->fpv_) && !is_pos(that.fpv_))) { re = (std::max)(this->re_, that.re_) + ROUNDING_ERROR; } else { floating_point_type temp = (this->fpv_ * this->re_ - that.fpv_ * that.re_) / fpv; if (is_neg(temp)) temp = -temp; re = temp + ROUNDING_ERROR; } return robust_fpt(fpv, re); } robust_fpt operator-(const robust_fpt& that) const { floating_point_type fpv = this->fpv_ - that.fpv_; relative_error_type re; if ((!is_neg(this->fpv_) && !is_pos(that.fpv_)) || (!is_pos(this->fpv_) && !is_neg(that.fpv_))) { re = (std::max)(this->re_, that.re_) + ROUNDING_ERROR; } else { floating_point_type temp = (this->fpv_ * this->re_ + that.fpv_ * that.re_) / fpv; if (is_neg(temp)) temp = -temp; re = temp + ROUNDING_ERROR; } return robust_fpt(fpv, re); } robust_fpt operator*(const robust_fpt& that) const { floating_point_type fpv = this->fpv_ * that.fpv_; relative_error_type re = this->re_ + that.re_ + ROUNDING_ERROR; return robust_fpt(fpv, re); } robust_fpt operator/(const robust_fpt& that) const { floating_point_type fpv = this->fpv_ / that.fpv_; relative_error_type re = this->re_ + that.re_ + ROUNDING_ERROR; return robust_fpt(fpv, re); } robust_fpt sqrt() const { return robust_fpt(get_sqrt(fpv_), re_ * static_cast<relative_error_type>(0.5) + ROUNDING_ERROR); } private: floating_point_type fpv_; relative_error_type re_; }; template <typename T> robust_fpt<T> get_sqrt(const robust_fpt<T>& that) { return that.sqrt(); } template <typename T> bool is_pos(const robust_fpt<T>& that) { return that.has_pos_value(); } template <typename T> bool is_neg(const robust_fpt<T>& that) { return that.has_neg_value(); } template <typename T> bool is_zero(const robust_fpt<T>& that) { return that.has_zero_value(); } // robust_dif consists of two not negative values: value1 and value2. // The resulting expression is equal to the value1 - value2. // Subtraction of a positive value is equivalent to the addition to value2 // and subtraction of a negative value is equivalent to the addition to // value1. The structure implicitly avoids difference computation. template <typename T> class robust_dif { public: robust_dif() : positive_sum_(0), negative_sum_(0) {} explicit robust_dif(const T& value) : positive_sum_((value > 0)?value:0), negative_sum_((value < 0)?-value:0) {} robust_dif(const T& pos, const T& neg) : positive_sum_(pos), negative_sum_(neg) {} T dif() const { return positive_sum_ - negative_sum_; } T pos() const { return positive_sum_; } T neg() const { return negative_sum_; } robust_dif<T> operator-() const { return robust_dif(negative_sum_, positive_sum_); } robust_dif<T>& operator+=(const T& val) { if (!is_neg(val)) positive_sum_ += val; else negative_sum_ -= val; return *this; } robust_dif<T>& operator+=(const robust_dif<T>& that) { positive_sum_ += that.positive_sum_; negative_sum_ += that.negative_sum_; return *this; } robust_dif<T>& operator-=(const T& val) { if (!is_neg(val)) negative_sum_ += val; else positive_sum_ -= val; return *this; } robust_dif<T>& operator-=(const robust_dif<T>& that) { positive_sum_ += that.negative_sum_; negative_sum_ += that.positive_sum_; return *this; } robust_dif<T>& operator*=(const T& val) { if (!is_neg(val)) { positive_sum_ *= val; negative_sum_ *= val; } else { positive_sum_ *= -val; negative_sum_ *= -val; swap(); } return *this; } robust_dif<T>& operator*=(const robust_dif<T>& that) { T positive_sum = this->positive_sum_ * that.positive_sum_ + this->negative_sum_ * that.negative_sum_; T negative_sum = this->positive_sum_ * that.negative_sum_ + this->negative_sum_ * that.positive_sum_; positive_sum_ = positive_sum; negative_sum_ = negative_sum; return *this; } robust_dif<T>& operator/=(const T& val) { if (!is_neg(val)) { positive_sum_ /= val; negative_sum_ /= val; } else { positive_sum_ /= -val; negative_sum_ /= -val; swap(); } return *this; } private: void swap() { (std::swap)(positive_sum_, negative_sum_); } T positive_sum_; T negative_sum_; }; template<typename T> robust_dif<T> operator+(const robust_dif<T>& lhs, const robust_dif<T>& rhs) { return robust_dif<T>(lhs.pos() + rhs.pos(), lhs.neg() + rhs.neg()); } template<typename T> robust_dif<T> operator+(const robust_dif<T>& lhs, const T& rhs) { if (!is_neg(rhs)) { return robust_dif<T>(lhs.pos() + rhs, lhs.neg()); } else { return robust_dif<T>(lhs.pos(), lhs.neg() - rhs); } } template<typename T> robust_dif<T> operator+(const T& lhs, const robust_dif<T>& rhs) { if (!is_neg(lhs)) { return robust_dif<T>(lhs + rhs.pos(), rhs.neg()); } else { return robust_dif<T>(rhs.pos(), rhs.neg() - lhs); } } template<typename T> robust_dif<T> operator-(const robust_dif<T>& lhs, const robust_dif<T>& rhs) { return robust_dif<T>(lhs.pos() + rhs.neg(), lhs.neg() + rhs.pos()); } template<typename T> robust_dif<T> operator-(const robust_dif<T>& lhs, const T& rhs) { if (!is_neg(rhs)) { return robust_dif<T>(lhs.pos(), lhs.neg() + rhs); } else { return robust_dif<T>(lhs.pos() - rhs, lhs.neg()); } } template<typename T> robust_dif<T> operator-(const T& lhs, const robust_dif<T>& rhs) { if (!is_neg(lhs)) { return robust_dif<T>(lhs + rhs.neg(), rhs.pos()); } else { return robust_dif<T>(rhs.neg(), rhs.pos() - lhs); } } template<typename T> robust_dif<T> operator*(const robust_dif<T>& lhs, const robust_dif<T>& rhs) { T res_pos = lhs.pos() * rhs.pos() + lhs.neg() * rhs.neg(); T res_neg = lhs.pos() * rhs.neg() + lhs.neg() * rhs.pos(); return robust_dif<T>(res_pos, res_neg); } template<typename T> robust_dif<T> operator*(const robust_dif<T>& lhs, const T& val) { if (!is_neg(val)) { return robust_dif<T>(lhs.pos() * val, lhs.neg() * val); } else { return robust_dif<T>(-lhs.neg() * val, -lhs.pos() * val); } } template<typename T> robust_dif<T> operator*(const T& val, const robust_dif<T>& rhs) { if (!is_neg(val)) { return robust_dif<T>(val * rhs.pos(), val * rhs.neg()); } else { return robust_dif<T>(-val * rhs.neg(), -val * rhs.pos()); } } template<typename T> robust_dif<T> operator/(const robust_dif<T>& lhs, const T& val) { if (!is_neg(val)) { return robust_dif<T>(lhs.pos() / val, lhs.neg() / val); } else { return robust_dif<T>(-lhs.neg() / val, -lhs.pos() / val); } } // Used to compute expressions that operate with sqrts with predefined // relative error. Evaluates expressions of the next type: // sum(i = 1 .. n)(A[i] * sqrt(B[i])), 1 <= n <= 4. template <typename _int, typename _fpt, typename _converter> class robust_sqrt_expr { public: enum MAX_RELATIVE_ERROR { MAX_RELATIVE_ERROR_EVAL1 = 4, MAX_RELATIVE_ERROR_EVAL2 = 7, MAX_RELATIVE_ERROR_EVAL3 = 16, MAX_RELATIVE_ERROR_EVAL4 = 25 }; // Evaluates expression (re = 4 EPS): // A[0] * sqrt(B[0]). _fpt eval1(_int* A, _int* B) { _fpt a = convert(A[0]); _fpt b = convert(B[0]); return a * get_sqrt(b); } // Evaluates expression (re = 7 EPS): // A[0] * sqrt(B[0]) + A[1] * sqrt(B[1]). _fpt eval2(_int* A, _int* B) { _fpt a = eval1(A, B); _fpt b = eval1(A + 1, B + 1); if ((!is_neg(a) && !is_neg(b)) || (!is_pos(a) && !is_pos(b))) return a + b; return convert(A[0] * A[0] * B[0] - A[1] * A[1] * B[1]) / (a - b); } // Evaluates expression (re = 16 EPS): // A[0] * sqrt(B[0]) + A[1] * sqrt(B[1]) + A[2] * sqrt(B[2]). _fpt eval3(_int* A, _int* B) { _fpt a = eval2(A, B); _fpt b = eval1(A + 2, B + 2); if ((!is_neg(a) && !is_neg(b)) || (!is_pos(a) && !is_pos(b))) return a + b; tA[3] = A[0] * A[0] * B[0] + A[1] * A[1] * B[1] - A[2] * A[2] * B[2]; tB[3] = 1; tA[4] = A[0] * A[1] * 2; tB[4] = B[0] * B[1]; return eval2(tA + 3, tB + 3) / (a - b); } // Evaluates expression (re = 25 EPS): // A[0] * sqrt(B[0]) + A[1] * sqrt(B[1]) + // A[2] * sqrt(B[2]) + A[3] * sqrt(B[3]). _fpt eval4(_int* A, _int* B) { _fpt a = eval2(A, B); _fpt b = eval2(A + 2, B + 2); if ((!is_neg(a) && !is_neg(b)) || (!is_pos(a) && !is_pos(b))) return a + b; tA[0] = A[0] * A[0] * B[0] + A[1] * A[1] * B[1] - A[2] * A[2] * B[2] - A[3] * A[3] * B[3]; tB[0] = 1; tA[1] = A[0] * A[1] * 2; tB[1] = B[0] * B[1]; tA[2] = A[2] * A[3] * -2; tB[2] = B[2] * B[3]; return eval3(tA, tB) / (a - b); } private: _int tA[5]; _int tB[5]; _converter convert; }; } // detail } // polygon } // boost #endif // BOOST_POLYGON_DETAIL_VORONOI_ROBUST_FPT PK �b�[jz{D$ D$ detail/polygon_45_touch.hppnu �[��� /* Copyright 2008 Intel Corporation Use, modification and distribution are 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_POLYGON_POLYGON_45_TOUCH_HPP #define BOOST_POLYGON_POLYGON_45_TOUCH_HPP namespace boost { namespace polygon{ template <typename Unit> struct polygon_45_touch { typedef point_data<Unit> Point; typedef typename coordinate_traits<Unit>::manhattan_area_type LongUnit; template <typename property_map> static inline void merge_property_maps(property_map& mp, const property_map& mp2, bool subtract = false) { property_map newmp; newmp.reserve(mp.size() + mp2.size()); std::size_t i = 0; std::size_t j = 0; while(i != mp.size() && j != mp2.size()) { if(mp[i].first < mp2[j].first) { newmp.push_back(mp[i]); ++i; } else if(mp[i].first > mp2[j].first) { newmp.push_back(mp2[j]); if(subtract) newmp.back().second *= -1; ++j; } else { int count = mp[i].second; if(subtract) count -= mp2[j].second; else count += mp2[j].second; if(count) { newmp.push_back(mp[i]); newmp.back().second = count; } ++i; ++j; } } while(i != mp.size()) { newmp.push_back(mp[i]); ++i; } while(j != mp2.size()) { newmp.push_back(mp2[j]); if(subtract) newmp.back().second *= -1; ++j; } mp.swap(newmp); } class CountTouch { public: inline CountTouch() : counts() {} //inline CountTouch(int count) { counts[0] = counts[1] = count; } //inline CountTouch(int count1, int count2) { counts[0] = count1; counts[1] = count2; } inline CountTouch(const CountTouch& count) : counts(count.counts) {} inline bool operator==(const CountTouch& count) const { return counts == count.counts; } inline bool operator!=(const CountTouch& count) const { return !((*this) == count); } //inline CountTouch& operator=(int count) { counts[0] = counts[1] = count; return *this; } inline CountTouch& operator=(const CountTouch& count) { counts = count.counts; return *this; } inline int& operator[](int index) { std::vector<std::pair<int, int> >::iterator itr = std::lower_bound(counts.begin(), counts.end(), std::make_pair(index, int(0))); if(itr != counts.end() && itr->first == index) { return itr->second; } itr = counts.insert(itr, std::make_pair(index, int(0))); return itr->second; } // inline int operator[](int index) const { // std::vector<std::pair<int, int> >::const_iterator itr = counts.begin(); // for( ; itr != counts.end() && itr->first <= index; ++itr) { // if(itr->first == index) { // return itr->second; // } // } // return 0; // } inline CountTouch& operator+=(const CountTouch& count){ merge_property_maps(counts, count.counts, false); return *this; } inline CountTouch& operator-=(const CountTouch& count){ merge_property_maps(counts, count.counts, true); return *this; } inline CountTouch operator+(const CountTouch& count) const { return CountTouch(*this)+=count; } inline CountTouch operator-(const CountTouch& count) const { return CountTouch(*this)-=count; } inline CountTouch invert() const { CountTouch retval; retval -= *this; return retval; } std::vector<std::pair<int, int> > counts; }; typedef std::pair<std::pair<Unit, std::map<Unit, std::set<int> > >, std::map<int, std::set<int> > > map_graph_o; typedef std::pair<std::pair<Unit, std::map<Unit, std::set<int> > >, std::vector<std::set<int> > > vector_graph_o; template <typename cT> static void process_previous_x(cT& output) { std::map<Unit, std::set<int> >& y_prop_map = output.first.second; for(typename std::map<Unit, std::set<int> >::iterator itr = y_prop_map.begin(); itr != y_prop_map.end(); ++itr) { for(std::set<int>::iterator inner_itr = itr->second.begin(); inner_itr != itr->second.end(); ++inner_itr) { std::set<int>& output_edges = (*(output.second))[*inner_itr]; std::set<int>::iterator inner_inner_itr = inner_itr; ++inner_inner_itr; for( ; inner_inner_itr != itr->second.end(); ++inner_inner_itr) { output_edges.insert(output_edges.end(), *inner_inner_itr); std::set<int>& output_edges_2 = (*(output.second))[*inner_inner_itr]; output_edges_2.insert(output_edges_2.end(), *inner_itr); } } } y_prop_map.clear(); } struct touch_45_output_functor { template <typename cT> void operator()(cT& output, const CountTouch& count1, const CountTouch& count2, const Point& pt, int , direction_1d ) { Unit& x = output.first.first; std::map<Unit, std::set<int> >& y_prop_map = output.first.second; if(pt.x() != x) process_previous_x(output); x = pt.x(); std::set<int>& output_set = y_prop_map[pt.y()]; for(std::vector<std::pair<int, int> >::const_iterator itr1 = count1.counts.begin(); itr1 != count1.counts.end(); ++itr1) { if(itr1->second > 0) { output_set.insert(output_set.end(), itr1->first); } } for(std::vector<std::pair<int, int> >::const_iterator itr2 = count2.counts.begin(); itr2 != count2.counts.end(); ++itr2) { if(itr2->second > 0) { output_set.insert(output_set.end(), itr2->first); } } } }; typedef typename std::pair<Point, typename boolean_op_45<Unit>::template Scan45CountT<CountTouch> > Vertex45Compact; typedef std::vector<Vertex45Compact> TouchSetData; struct lessVertex45Compact { bool operator()(const Vertex45Compact& l, const Vertex45Compact& r) { return l.first < r.first; } }; // template <typename TSD> // static void print_tsd(TSD& tsd) { // for(std::size_t i = 0; i < tsd.size(); ++i) { // std::cout << tsd[i].first << ": "; // for(unsigned int r = 0; r < 4; ++r) { // std::cout << r << " { "; // for(std::vector<std::pair<int, int> >::iterator itr = tsd[i].second[r].counts.begin(); // itr != tsd[i].second[r].counts.end(); ++itr) { // std::cout << itr->first << "," << itr->second << " "; // } std::cout << "} "; // } // } std::cout << std::endl; // } // template <typename T> // static void print_scanline(T& t) { // for(typename T::iterator itr = t.begin(); itr != t.end(); ++itr) { // std::cout << itr->x << "," << itr->y << " " << itr->rise << " "; // for(std::vector<std::pair<int, int> >::iterator itr2 = itr->count.counts.begin(); // itr2 != itr->count.counts.end(); ++itr2) { // std::cout << itr2->first << ":" << itr2->second << " "; // } std::cout << std::endl; // } // } template <typename graph_type> static void performTouch(graph_type& graph, TouchSetData& tsd) { polygon_sort(tsd.begin(), tsd.end(), lessVertex45Compact()); typedef std::vector<std::pair<Point, typename boolean_op_45<Unit>::template Scan45CountT<CountTouch> > > TSD; TSD tsd_; tsd_.reserve(tsd.size()); for(typename TouchSetData::iterator itr = tsd.begin(); itr != tsd.end(); ) { typename TouchSetData::iterator itr2 = itr; ++itr2; for(; itr2 != tsd.end() && itr2->first == itr->first; ++itr2) { (itr->second) += (itr2->second); //accumulate } tsd_.push_back(std::make_pair(itr->first, itr->second)); itr = itr2; } std::pair<std::pair<Unit, std::map<Unit, std::set<int> > >, graph_type*> output (std::make_pair(std::make_pair((std::numeric_limits<Unit>::max)(), std::map<Unit, std::set<int> >()), &graph)); typename boolean_op_45<Unit>::template Scan45<CountTouch, touch_45_output_functor> scanline; for(typename TSD::iterator itr = tsd_.begin(); itr != tsd_.end(); ) { typename TSD::iterator itr2 = itr; ++itr2; while(itr2 != tsd_.end() && itr2->first.x() == itr->first.x()) { ++itr2; } scanline.scan(output, itr, itr2); itr = itr2; } process_previous_x(output); } template <typename iT> static void populateTouchSetData(TouchSetData& tsd, iT begin, iT end, int nodeCount) { for( ; begin != end; ++begin) { Vertex45Compact vertex; vertex.first = typename Vertex45Compact::first_type(begin->pt.x() * 2, begin->pt.y() * 2); tsd.push_back(vertex); for(unsigned int i = 0; i < 4; ++i) { if(begin->count[i]) { tsd.back().second[i][nodeCount] += begin->count[i]; } } } } }; } } #endif PK �b�[��RZ� � detail/voronoi_predicates.hppnu �[��� // Boost.Polygon library detail/voronoi_predicates.hpp header file // Copyright Andrii Sydorchuk 2010-2012. // Distributed under 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) // See http://www.boost.org for updates, documentation, and revision history. #ifndef BOOST_POLYGON_DETAIL_VORONOI_PREDICATES #define BOOST_POLYGON_DETAIL_VORONOI_PREDICATES #include <utility> #include "voronoi_robust_fpt.hpp" namespace boost { namespace polygon { namespace detail { // Predicate utilities. Operates with the coordinate types that could // be converted to the 32-bit signed integer without precision loss. template <typename CTYPE_TRAITS> class voronoi_predicates { public: typedef typename CTYPE_TRAITS::int_type int_type; typedef typename CTYPE_TRAITS::int_x2_type int_x2_type; typedef typename CTYPE_TRAITS::uint_x2_type uint_x2_type; typedef typename CTYPE_TRAITS::big_int_type big_int_type; typedef typename CTYPE_TRAITS::fpt_type fpt_type; typedef typename CTYPE_TRAITS::efpt_type efpt_type; typedef typename CTYPE_TRAITS::ulp_cmp_type ulp_cmp_type; typedef typename CTYPE_TRAITS::to_fpt_converter_type to_fpt_converter; typedef typename CTYPE_TRAITS::to_efpt_converter_type to_efpt_converter; enum { ULPS = 64, ULPSx2 = 128 }; template <typename Point> static bool is_vertical(const Point& point1, const Point& point2) { return point1.x() == point2.x(); } template <typename Site> static bool is_vertical(const Site& site) { return is_vertical(site.point0(), site.point1()); } // Compute robust cross_product: a1 * b2 - b1 * a2. // It was mathematically proven that the result is correct // with epsilon relative error equal to 1EPS. static fpt_type robust_cross_product(int_x2_type a1_, int_x2_type b1_, int_x2_type a2_, int_x2_type b2_) { static to_fpt_converter to_fpt; uint_x2_type a1 = static_cast<uint_x2_type>(is_neg(a1_) ? -a1_ : a1_); uint_x2_type b1 = static_cast<uint_x2_type>(is_neg(b1_) ? -b1_ : b1_); uint_x2_type a2 = static_cast<uint_x2_type>(is_neg(a2_) ? -a2_ : a2_); uint_x2_type b2 = static_cast<uint_x2_type>(is_neg(b2_) ? -b2_ : b2_); uint_x2_type l = a1 * b2; uint_x2_type r = b1 * a2; if (is_neg(a1_) ^ is_neg(b2_)) { if (is_neg(a2_) ^ is_neg(b1_)) return (l > r) ? -to_fpt(l - r) : to_fpt(r - l); else return -to_fpt(l + r); } else { if (is_neg(a2_) ^ is_neg(b1_)) return to_fpt(l + r); else return (l < r) ? -to_fpt(r - l) : to_fpt(l - r); } } struct orientation_test { public: // Represents orientation test result. enum Orientation { RIGHT = -1, COLLINEAR = 0, LEFT = 1 }; // Value is a determinant of two vectors (e.g. x1 * y2 - x2 * y1). // Return orientation based on the sign of the determinant. template <typename T> static Orientation eval(T value) { if (is_zero(value)) return COLLINEAR; return (is_neg(value)) ? RIGHT : LEFT; } static Orientation eval(int_x2_type dif_x1_, int_x2_type dif_y1_, int_x2_type dif_x2_, int_x2_type dif_y2_) { return eval(robust_cross_product(dif_x1_, dif_y1_, dif_x2_, dif_y2_)); } template <typename Point> static Orientation eval(const Point& point1, const Point& point2, const Point& point3) { int_x2_type dx1 = static_cast<int_x2_type>(point1.x()) - static_cast<int_x2_type>(point2.x()); int_x2_type dx2 = static_cast<int_x2_type>(point2.x()) - static_cast<int_x2_type>(point3.x()); int_x2_type dy1 = static_cast<int_x2_type>(point1.y()) - static_cast<int_x2_type>(point2.y()); int_x2_type dy2 = static_cast<int_x2_type>(point2.y()) - static_cast<int_x2_type>(point3.y()); return eval(robust_cross_product(dx1, dy1, dx2, dy2)); } }; typedef orientation_test ot; template <typename Point> class point_comparison_predicate { public: typedef Point point_type; bool operator()(const point_type& lhs, const point_type& rhs) const { if (lhs.x() == rhs.x()) return lhs.y() < rhs.y(); return lhs.x() < rhs.x(); } }; template <typename Site, typename Circle> class event_comparison_predicate { public: typedef Site site_type; typedef Circle circle_type; bool operator()(const site_type& lhs, const site_type& rhs) const { if (lhs.x0() != rhs.x0()) return lhs.x0() < rhs.x0(); if (!lhs.is_segment()) { if (!rhs.is_segment()) return lhs.y0() < rhs.y0(); if (is_vertical(rhs)) return lhs.y0() <= rhs.y0(); return true; } else { if (is_vertical(rhs)) { if (is_vertical(lhs)) return lhs.y0() < rhs.y0(); return false; } if (is_vertical(lhs)) return true; if (lhs.y0() != rhs.y0()) return lhs.y0() < rhs.y0(); return ot::eval(lhs.point1(), lhs.point0(), rhs.point1()) == ot::LEFT; } } bool operator()(const site_type& lhs, const circle_type& rhs) const { typename ulp_cmp_type::Result xCmp = ulp_cmp(to_fpt(lhs.x0()), to_fpt(rhs.lower_x()), ULPS); return xCmp == ulp_cmp_type::LESS; } bool operator()(const circle_type& lhs, const site_type& rhs) const { typename ulp_cmp_type::Result xCmp = ulp_cmp(to_fpt(lhs.lower_x()), to_fpt(rhs.x0()), ULPS); return xCmp == ulp_cmp_type::LESS; } bool operator()(const circle_type& lhs, const circle_type& rhs) const { if (lhs.lower_x() != rhs.lower_x()) { return lhs.lower_x() < rhs.lower_x(); } return lhs.y() < rhs.y(); } private: ulp_cmp_type ulp_cmp; to_fpt_converter to_fpt; }; template <typename Site> class distance_predicate { public: typedef Site site_type; typedef typename site_type::point_type point_type; // Returns true if a horizontal line going through a new site intersects // right arc at first, else returns false. If horizontal line goes // through intersection point of the given two arcs returns false also. bool operator()(const site_type& left_site, const site_type& right_site, const point_type& new_point) const { if (!left_site.is_segment()) { if (!right_site.is_segment()) { return pp(left_site, right_site, new_point); } else { return ps(left_site, right_site, new_point, false); } } else { if (!right_site.is_segment()) { return ps(right_site, left_site, new_point, true); } else { return ss(left_site, right_site, new_point); } } } private: // Represents the result of the epsilon robust predicate. If the // result is undefined some further processing is usually required. enum kPredicateResult { LESS = -1, UNDEFINED = 0, MORE = 1 }; // Robust predicate, avoids using high-precision libraries. // Returns true if a horizontal line going through the new point site // intersects right arc at first, else returns false. If horizontal line // goes through intersection point of the given two arcs returns false. bool pp(const site_type& left_site, const site_type& right_site, const point_type& new_point) const { const point_type& left_point = left_site.point0(); const point_type& right_point = right_site.point0(); if (left_point.x() > right_point.x()) { if (new_point.y() <= left_point.y()) return false; } else if (left_point.x() < right_point.x()) { if (new_point.y() >= right_point.y()) return true; } else { return static_cast<int_x2_type>(left_point.y()) + static_cast<int_x2_type>(right_point.y()) < static_cast<int_x2_type>(new_point.y()) * 2; } fpt_type dist1 = find_distance_to_point_arc(left_site, new_point); fpt_type dist2 = find_distance_to_point_arc(right_site, new_point); // The undefined ulp range is equal to 3EPS + 3EPS <= 6ULP. return dist1 < dist2; } bool ps(const site_type& left_site, const site_type& right_site, const point_type& new_point, bool reverse_order) const { kPredicateResult fast_res = fast_ps( left_site, right_site, new_point, reverse_order); if (fast_res != UNDEFINED) { return fast_res == LESS; } fpt_type dist1 = find_distance_to_point_arc(left_site, new_point); fpt_type dist2 = find_distance_to_segment_arc(right_site, new_point); // The undefined ulp range is equal to 3EPS + 7EPS <= 10ULP. return reverse_order ^ (dist1 < dist2); } bool ss(const site_type& left_site, const site_type& right_site, const point_type& new_point) const { // Handle temporary segment sites. if (left_site.sorted_index() == right_site.sorted_index()) { return ot::eval( left_site.point0(), left_site.point1(), new_point) == ot::LEFT; } fpt_type dist1 = find_distance_to_segment_arc(left_site, new_point); fpt_type dist2 = find_distance_to_segment_arc(right_site, new_point); // The undefined ulp range is equal to 7EPS + 7EPS <= 14ULP. return dist1 < dist2; } fpt_type find_distance_to_point_arc( const site_type& site, const point_type& point) const { fpt_type dx = to_fpt(site.x()) - to_fpt(point.x()); fpt_type dy = to_fpt(site.y()) - to_fpt(point.y()); // The relative error is at most 3EPS. return (dx * dx + dy * dy) / (to_fpt(2.0) * dx); } fpt_type find_distance_to_segment_arc( const site_type& site, const point_type& point) const { if (is_vertical(site)) { return (to_fpt(site.x()) - to_fpt(point.x())) * to_fpt(0.5); } else { const point_type& segment0 = site.point0(); const point_type& segment1 = site.point1(); fpt_type a1 = to_fpt(segment1.x()) - to_fpt(segment0.x()); fpt_type b1 = to_fpt(segment1.y()) - to_fpt(segment0.y()); fpt_type k = get_sqrt(a1 * a1 + b1 * b1); // Avoid subtraction while computing k. if (!is_neg(b1)) { k = to_fpt(1.0) / (b1 + k); } else { k = (k - b1) / (a1 * a1); } // The relative error is at most 7EPS. return k * robust_cross_product( static_cast<int_x2_type>(segment1.x()) - static_cast<int_x2_type>(segment0.x()), static_cast<int_x2_type>(segment1.y()) - static_cast<int_x2_type>(segment0.y()), static_cast<int_x2_type>(point.x()) - static_cast<int_x2_type>(segment0.x()), static_cast<int_x2_type>(point.y()) - static_cast<int_x2_type>(segment0.y())); } } kPredicateResult fast_ps( const site_type& left_site, const site_type& right_site, const point_type& new_point, bool reverse_order) const { const point_type& site_point = left_site.point0(); const point_type& segment_start = right_site.point0(); const point_type& segment_end = right_site.point1(); if (ot::eval(segment_start, segment_end, new_point) != ot::RIGHT) return (!right_site.is_inverse()) ? LESS : MORE; fpt_type dif_x = to_fpt(new_point.x()) - to_fpt(site_point.x()); fpt_type dif_y = to_fpt(new_point.y()) - to_fpt(site_point.y()); fpt_type a = to_fpt(segment_end.x()) - to_fpt(segment_start.x()); fpt_type b = to_fpt(segment_end.y()) - to_fpt(segment_start.y()); if (is_vertical(right_site)) { if (new_point.y() < site_point.y() && !reverse_order) return MORE; else if (new_point.y() > site_point.y() && reverse_order) return LESS; return UNDEFINED; } else { typename ot::Orientation orientation = ot::eval( static_cast<int_x2_type>(segment_end.x()) - static_cast<int_x2_type>(segment_start.x()), static_cast<int_x2_type>(segment_end.y()) - static_cast<int_x2_type>(segment_start.y()), static_cast<int_x2_type>(new_point.x()) - static_cast<int_x2_type>(site_point.x()), static_cast<int_x2_type>(new_point.y()) - static_cast<int_x2_type>(site_point.y())); if (orientation == ot::LEFT) { if (!right_site.is_inverse()) return reverse_order ? LESS : UNDEFINED; return reverse_order ? UNDEFINED : MORE; } } fpt_type fast_left_expr = a * (dif_y + dif_x) * (dif_y - dif_x); fpt_type fast_right_expr = (to_fpt(2.0) * b) * dif_x * dif_y; typename ulp_cmp_type::Result expr_cmp = ulp_cmp(fast_left_expr, fast_right_expr, 4); if (expr_cmp != ulp_cmp_type::EQUAL) { if ((expr_cmp == ulp_cmp_type::MORE) ^ reverse_order) return reverse_order ? LESS : MORE; return UNDEFINED; } return UNDEFINED; } private: ulp_cmp_type ulp_cmp; to_fpt_converter to_fpt; }; template <typename Node> class node_comparison_predicate { public: typedef Node node_type; typedef typename Node::site_type site_type; typedef typename site_type::point_type point_type; typedef typename point_type::coordinate_type coordinate_type; typedef point_comparison_predicate<point_type> point_comparison_type; typedef distance_predicate<site_type> distance_predicate_type; // Compares nodes in the balanced binary search tree. Nodes are // compared based on the y coordinates of the arcs intersection points. // Nodes with less y coordinate of the intersection point go first. // Comparison is only called during the new site events processing. // That's why one of the nodes will always lie on the sweepline and may // be represented as a straight horizontal line. bool operator() (const node_type& node1, const node_type& node2) const { // Get x coordinate of the rightmost site from both nodes. const site_type& site1 = get_comparison_site(node1); const site_type& site2 = get_comparison_site(node2); const point_type& point1 = get_comparison_point(site1); const point_type& point2 = get_comparison_point(site2); if (point1.x() < point2.x()) { // The second node contains a new site. return distance_predicate_( node1.left_site(), node1.right_site(), point2); } else if (point1.x() > point2.x()) { // The first node contains a new site. return !distance_predicate_( node2.left_site(), node2.right_site(), point1); } else { // This checks were evaluated experimentally. if (site1.sorted_index() == site2.sorted_index()) { // Both nodes are new (inserted during same site event processing). return get_comparison_y(node1) < get_comparison_y(node2); } else if (site1.sorted_index() < site2.sorted_index()) { std::pair<coordinate_type, int> y1 = get_comparison_y(node1, false); std::pair<coordinate_type, int> y2 = get_comparison_y(node2, true); if (y1.first != y2.first) return y1.first < y2.first; return (!site1.is_segment()) ? (y1.second < 0) : false; } else { std::pair<coordinate_type, int> y1 = get_comparison_y(node1, true); std::pair<coordinate_type, int> y2 = get_comparison_y(node2, false); if (y1.first != y2.first) return y1.first < y2.first; return (!site2.is_segment()) ? (y2.second > 0) : true; } } } private: // Get the newer site. const site_type& get_comparison_site(const node_type& node) const { if (node.left_site().sorted_index() > node.right_site().sorted_index()) { return node.left_site(); } return node.right_site(); } const point_type& get_comparison_point(const site_type& site) const { return point_comparison_(site.point0(), site.point1()) ? site.point0() : site.point1(); } // Get comparison pair: y coordinate and direction of the newer site. std::pair<coordinate_type, int> get_comparison_y( const node_type& node, bool is_new_node = true) const { if (node.left_site().sorted_index() == node.right_site().sorted_index()) { return std::make_pair(node.left_site().y0(), 0); } if (node.left_site().sorted_index() > node.right_site().sorted_index()) { if (!is_new_node && node.left_site().is_segment() && is_vertical(node.left_site())) { return std::make_pair(node.left_site().y0(), 1); } return std::make_pair(node.left_site().y1(), 1); } return std::make_pair(node.right_site().y0(), -1); } point_comparison_type point_comparison_; distance_predicate_type distance_predicate_; }; template <typename Site> class circle_existence_predicate { public: typedef typename Site::point_type point_type; typedef Site site_type; bool ppp(const site_type& site1, const site_type& site2, const site_type& site3) const { return ot::eval(site1.point0(), site2.point0(), site3.point0()) == ot::RIGHT; } bool pps(const site_type& site1, const site_type& site2, const site_type& site3, int segment_index) const { if (segment_index != 2) { typename ot::Orientation orient1 = ot::eval( site1.point0(), site2.point0(), site3.point0()); typename ot::Orientation orient2 = ot::eval( site1.point0(), site2.point0(), site3.point1()); if (segment_index == 1 && site1.x0() >= site2.x0()) { if (orient1 != ot::RIGHT) return false; } else if (segment_index == 3 && site2.x0() >= site1.x0()) { if (orient2 != ot::RIGHT) return false; } else if (orient1 != ot::RIGHT && orient2 != ot::RIGHT) { return false; } } else { return (site3.point0() != site1.point0()) || (site3.point1() != site2.point0()); } return true; } bool pss(const site_type& site1, const site_type& site2, const site_type& site3, int point_index) const { if (site2.sorted_index() == site3.sorted_index()) { return false; } if (point_index == 2) { if (!site2.is_inverse() && site3.is_inverse()) return false; if (site2.is_inverse() == site3.is_inverse() && ot::eval(site2.point0(), site1.point0(), site3.point1()) != ot::RIGHT) return false; } return true; } bool sss(const site_type& site1, const site_type& site2, const site_type& site3) const { return (site1.sorted_index() != site2.sorted_index()) && (site2.sorted_index() != site3.sorted_index()); } }; template <typename Site, typename Circle> class mp_circle_formation_functor { public: typedef typename Site::point_type point_type; typedef Site site_type; typedef Circle circle_type; typedef robust_sqrt_expr<big_int_type, efpt_type, to_efpt_converter> robust_sqrt_expr_type; void ppp(const site_type& site1, const site_type& site2, const site_type& site3, circle_type& circle, bool recompute_c_x = true, bool recompute_c_y = true, bool recompute_lower_x = true) { big_int_type dif_x[3], dif_y[3], sum_x[2], sum_y[2]; dif_x[0] = static_cast<int_x2_type>(site1.x()) - static_cast<int_x2_type>(site2.x()); dif_x[1] = static_cast<int_x2_type>(site2.x()) - static_cast<int_x2_type>(site3.x()); dif_x[2] = static_cast<int_x2_type>(site1.x()) - static_cast<int_x2_type>(site3.x()); dif_y[0] = static_cast<int_x2_type>(site1.y()) - static_cast<int_x2_type>(site2.y()); dif_y[1] = static_cast<int_x2_type>(site2.y()) - static_cast<int_x2_type>(site3.y()); dif_y[2] = static_cast<int_x2_type>(site1.y()) - static_cast<int_x2_type>(site3.y()); sum_x[0] = static_cast<int_x2_type>(site1.x()) + static_cast<int_x2_type>(site2.x()); sum_x[1] = static_cast<int_x2_type>(site2.x()) + static_cast<int_x2_type>(site3.x()); sum_y[0] = static_cast<int_x2_type>(site1.y()) + static_cast<int_x2_type>(site2.y()); sum_y[1] = static_cast<int_x2_type>(site2.y()) + static_cast<int_x2_type>(site3.y()); fpt_type inv_denom = to_fpt(0.5) / to_fpt(static_cast<big_int_type>( dif_x[0] * dif_y[1] - dif_x[1] * dif_y[0])); big_int_type numer1 = dif_x[0] * sum_x[0] + dif_y[0] * sum_y[0]; big_int_type numer2 = dif_x[1] * sum_x[1] + dif_y[1] * sum_y[1]; if (recompute_c_x || recompute_lower_x) { big_int_type c_x = numer1 * dif_y[1] - numer2 * dif_y[0]; circle.x(to_fpt(c_x) * inv_denom); if (recompute_lower_x) { // Evaluate radius of the circle. big_int_type sqr_r = (dif_x[0] * dif_x[0] + dif_y[0] * dif_y[0]) * (dif_x[1] * dif_x[1] + dif_y[1] * dif_y[1]) * (dif_x[2] * dif_x[2] + dif_y[2] * dif_y[2]); fpt_type r = get_sqrt(to_fpt(sqr_r)); // If c_x >= 0 then lower_x = c_x + r, // else lower_x = (c_x * c_x - r * r) / (c_x - r). // To guarantee epsilon relative error. if (!is_neg(circle.x())) { if (!is_neg(inv_denom)) { circle.lower_x(circle.x() + r * inv_denom); } else { circle.lower_x(circle.x() - r * inv_denom); } } else { big_int_type numer = c_x * c_x - sqr_r; fpt_type lower_x = to_fpt(numer) * inv_denom / (to_fpt(c_x) + r); circle.lower_x(lower_x); } } } if (recompute_c_y) { big_int_type c_y = numer2 * dif_x[0] - numer1 * dif_x[1]; circle.y(to_fpt(c_y) * inv_denom); } } // Recompute parameters of the circle event using high-precision library. void pps(const site_type& site1, const site_type& site2, const site_type& site3, int segment_index, circle_type& c_event, bool recompute_c_x = true, bool recompute_c_y = true, bool recompute_lower_x = true) { big_int_type cA[4], cB[4]; big_int_type line_a = static_cast<int_x2_type>(site3.y1()) - static_cast<int_x2_type>(site3.y0()); big_int_type line_b = static_cast<int_x2_type>(site3.x0()) - static_cast<int_x2_type>(site3.x1()); big_int_type segm_len = line_a * line_a + line_b * line_b; big_int_type vec_x = static_cast<int_x2_type>(site2.y()) - static_cast<int_x2_type>(site1.y()); big_int_type vec_y = static_cast<int_x2_type>(site1.x()) - static_cast<int_x2_type>(site2.x()); big_int_type sum_x = static_cast<int_x2_type>(site1.x()) + static_cast<int_x2_type>(site2.x()); big_int_type sum_y = static_cast<int_x2_type>(site1.y()) + static_cast<int_x2_type>(site2.y()); big_int_type teta = line_a * vec_x + line_b * vec_y; big_int_type denom = vec_x * line_b - vec_y * line_a; big_int_type dif0 = static_cast<int_x2_type>(site3.y1()) - static_cast<int_x2_type>(site1.y()); big_int_type dif1 = static_cast<int_x2_type>(site1.x()) - static_cast<int_x2_type>(site3.x1()); big_int_type A = line_a * dif1 - line_b * dif0; dif0 = static_cast<int_x2_type>(site3.y1()) - static_cast<int_x2_type>(site2.y()); dif1 = static_cast<int_x2_type>(site2.x()) - static_cast<int_x2_type>(site3.x1()); big_int_type B = line_a * dif1 - line_b * dif0; big_int_type sum_AB = A + B; if (is_zero(denom)) { big_int_type numer = teta * teta - sum_AB * sum_AB; denom = teta * sum_AB; cA[0] = denom * sum_x * 2 + numer * vec_x; cB[0] = segm_len; cA[1] = denom * sum_AB * 2 + numer * teta; cB[1] = 1; cA[2] = denom * sum_y * 2 + numer * vec_y; fpt_type inv_denom = to_fpt(1.0) / to_fpt(denom); if (recompute_c_x) c_event.x(to_fpt(0.25) * to_fpt(cA[0]) * inv_denom); if (recompute_c_y) c_event.y(to_fpt(0.25) * to_fpt(cA[2]) * inv_denom); if (recompute_lower_x) { c_event.lower_x(to_fpt(0.25) * to_fpt(sqrt_expr_.eval2(cA, cB)) * inv_denom / get_sqrt(to_fpt(segm_len))); } return; } big_int_type det = (teta * teta + denom * denom) * A * B * 4; fpt_type inv_denom_sqr = to_fpt(1.0) / to_fpt(denom); inv_denom_sqr *= inv_denom_sqr; if (recompute_c_x || recompute_lower_x) { cA[0] = sum_x * denom * denom + teta * sum_AB * vec_x; cB[0] = 1; cA[1] = (segment_index == 2) ? -vec_x : vec_x; cB[1] = det; if (recompute_c_x) { c_event.x(to_fpt(0.5) * to_fpt(sqrt_expr_.eval2(cA, cB)) * inv_denom_sqr); } } if (recompute_c_y || recompute_lower_x) { cA[2] = sum_y * denom * denom + teta * sum_AB * vec_y; cB[2] = 1; cA[3] = (segment_index == 2) ? -vec_y : vec_y; cB[3] = det; if (recompute_c_y) { c_event.y(to_fpt(0.5) * to_fpt(sqrt_expr_.eval2(&cA[2], &cB[2])) * inv_denom_sqr); } } if (recompute_lower_x) { cB[0] = cB[0] * segm_len; cB[1] = cB[1] * segm_len; cA[2] = sum_AB * (denom * denom + teta * teta); cB[2] = 1; cA[3] = (segment_index == 2) ? -teta : teta; cB[3] = det; c_event.lower_x(to_fpt(0.5) * to_fpt(sqrt_expr_.eval4(cA, cB)) * inv_denom_sqr / get_sqrt(to_fpt(segm_len))); } } // Recompute parameters of the circle event using high-precision library. void pss(const site_type& site1, const site_type& site2, const site_type& site3, int point_index, circle_type& c_event, bool recompute_c_x = true, bool recompute_c_y = true, bool recompute_lower_x = true) { big_int_type a[2], b[2], c[2], cA[4], cB[4]; const point_type& segm_start1 = site2.point1(); const point_type& segm_end1 = site2.point0(); const point_type& segm_start2 = site3.point0(); const point_type& segm_end2 = site3.point1(); a[0] = static_cast<int_x2_type>(segm_end1.x()) - static_cast<int_x2_type>(segm_start1.x()); b[0] = static_cast<int_x2_type>(segm_end1.y()) - static_cast<int_x2_type>(segm_start1.y()); a[1] = static_cast<int_x2_type>(segm_end2.x()) - static_cast<int_x2_type>(segm_start2.x()); b[1] = static_cast<int_x2_type>(segm_end2.y()) - static_cast<int_x2_type>(segm_start2.y()); big_int_type orientation = a[1] * b[0] - a[0] * b[1]; if (is_zero(orientation)) { fpt_type denom = to_fpt(2.0) * to_fpt( static_cast<big_int_type>(a[0] * a[0] + b[0] * b[0])); c[0] = b[0] * (static_cast<int_x2_type>(segm_start2.x()) - static_cast<int_x2_type>(segm_start1.x())) - a[0] * (static_cast<int_x2_type>(segm_start2.y()) - static_cast<int_x2_type>(segm_start1.y())); big_int_type dx = a[0] * (static_cast<int_x2_type>(site1.y()) - static_cast<int_x2_type>(segm_start1.y())) - b[0] * (static_cast<int_x2_type>(site1.x()) - static_cast<int_x2_type>(segm_start1.x())); big_int_type dy = b[0] * (static_cast<int_x2_type>(site1.x()) - static_cast<int_x2_type>(segm_start2.x())) - a[0] * (static_cast<int_x2_type>(site1.y()) - static_cast<int_x2_type>(segm_start2.y())); cB[0] = dx * dy; cB[1] = 1; if (recompute_c_y) { cA[0] = b[0] * ((point_index == 2) ? 2 : -2); cA[1] = a[0] * a[0] * (static_cast<int_x2_type>(segm_start1.y()) + static_cast<int_x2_type>(segm_start2.y())) - a[0] * b[0] * (static_cast<int_x2_type>(segm_start1.x()) + static_cast<int_x2_type>(segm_start2.x()) - static_cast<int_x2_type>(site1.x()) * 2) + b[0] * b[0] * (static_cast<int_x2_type>(site1.y()) * 2); fpt_type c_y = to_fpt(sqrt_expr_.eval2(cA, cB)); c_event.y(c_y / denom); } if (recompute_c_x || recompute_lower_x) { cA[0] = a[0] * ((point_index == 2) ? 2 : -2); cA[1] = b[0] * b[0] * (static_cast<int_x2_type>(segm_start1.x()) + static_cast<int_x2_type>(segm_start2.x())) - a[0] * b[0] * (static_cast<int_x2_type>(segm_start1.y()) + static_cast<int_x2_type>(segm_start2.y()) - static_cast<int_x2_type>(site1.y()) * 2) + a[0] * a[0] * (static_cast<int_x2_type>(site1.x()) * 2); if (recompute_c_x) { fpt_type c_x = to_fpt(sqrt_expr_.eval2(cA, cB)); c_event.x(c_x / denom); } if (recompute_lower_x) { cA[2] = is_neg(c[0]) ? -c[0] : c[0]; cB[2] = a[0] * a[0] + b[0] * b[0]; fpt_type lower_x = to_fpt(sqrt_expr_.eval3(cA, cB)); c_event.lower_x(lower_x / denom); } } return; } c[0] = b[0] * segm_end1.x() - a[0] * segm_end1.y(); c[1] = a[1] * segm_end2.y() - b[1] * segm_end2.x(); big_int_type ix = a[0] * c[1] + a[1] * c[0]; big_int_type iy = b[0] * c[1] + b[1] * c[0]; big_int_type dx = ix - orientation * site1.x(); big_int_type dy = iy - orientation * site1.y(); if (is_zero(dx) && is_zero(dy)) { fpt_type denom = to_fpt(orientation); fpt_type c_x = to_fpt(ix) / denom; fpt_type c_y = to_fpt(iy) / denom; c_event = circle_type(c_x, c_y, c_x); return; } big_int_type sign = ((point_index == 2) ? 1 : -1) * (is_neg(orientation) ? 1 : -1); cA[0] = a[1] * -dx + b[1] * -dy; cA[1] = a[0] * -dx + b[0] * -dy; cA[2] = sign; cA[3] = 0; cB[0] = a[0] * a[0] + b[0] * b[0]; cB[1] = a[1] * a[1] + b[1] * b[1]; cB[2] = a[0] * a[1] + b[0] * b[1]; cB[3] = (a[0] * dy - b[0] * dx) * (a[1] * dy - b[1] * dx) * -2; fpt_type temp = to_fpt( sqrt_expr_evaluator_pss4<big_int_type, efpt_type>(cA, cB)); fpt_type denom = temp * to_fpt(orientation); if (recompute_c_y) { cA[0] = b[1] * (dx * dx + dy * dy) - iy * (dx * a[1] + dy * b[1]); cA[1] = b[0] * (dx * dx + dy * dy) - iy * (dx * a[0] + dy * b[0]); cA[2] = iy * sign; fpt_type cy = to_fpt( sqrt_expr_evaluator_pss4<big_int_type, efpt_type>(cA, cB)); c_event.y(cy / denom); } if (recompute_c_x || recompute_lower_x) { cA[0] = a[1] * (dx * dx + dy * dy) - ix * (dx * a[1] + dy * b[1]); cA[1] = a[0] * (dx * dx + dy * dy) - ix * (dx * a[0] + dy * b[0]); cA[2] = ix * sign; if (recompute_c_x) { fpt_type cx = to_fpt( sqrt_expr_evaluator_pss4<big_int_type, efpt_type>(cA, cB)); c_event.x(cx / denom); } if (recompute_lower_x) { cA[3] = orientation * (dx * dx + dy * dy) * (is_neg(temp) ? -1 : 1); fpt_type lower_x = to_fpt( sqrt_expr_evaluator_pss4<big_int_type, efpt_type>(cA, cB)); c_event.lower_x(lower_x / denom); } } } // Recompute parameters of the circle event using high-precision library. void sss(const site_type& site1, const site_type& site2, const site_type& site3, circle_type& c_event, bool recompute_c_x = true, bool recompute_c_y = true, bool recompute_lower_x = true) { big_int_type a[3], b[3], c[3], cA[4], cB[4]; // cA - corresponds to the cross product. // cB - corresponds to the squared length. a[0] = static_cast<int_x2_type>(site1.x1()) - static_cast<int_x2_type>(site1.x0()); a[1] = static_cast<int_x2_type>(site2.x1()) - static_cast<int_x2_type>(site2.x0()); a[2] = static_cast<int_x2_type>(site3.x1()) - static_cast<int_x2_type>(site3.x0()); b[0] = static_cast<int_x2_type>(site1.y1()) - static_cast<int_x2_type>(site1.y0()); b[1] = static_cast<int_x2_type>(site2.y1()) - static_cast<int_x2_type>(site2.y0()); b[2] = static_cast<int_x2_type>(site3.y1()) - static_cast<int_x2_type>(site3.y0()); c[0] = static_cast<int_x2_type>(site1.x0()) * static_cast<int_x2_type>(site1.y1()) - static_cast<int_x2_type>(site1.y0()) * static_cast<int_x2_type>(site1.x1()); c[1] = static_cast<int_x2_type>(site2.x0()) * static_cast<int_x2_type>(site2.y1()) - static_cast<int_x2_type>(site2.y0()) * static_cast<int_x2_type>(site2.x1()); c[2] = static_cast<int_x2_type>(site3.x0()) * static_cast<int_x2_type>(site3.y1()) - static_cast<int_x2_type>(site3.y0()) * static_cast<int_x2_type>(site3.x1()); for (int i = 0; i < 3; ++i) cB[i] = a[i] * a[i] + b[i] * b[i]; for (int i = 0; i < 3; ++i) { int j = (i+1) % 3; int k = (i+2) % 3; cA[i] = a[j] * b[k] - a[k] * b[j]; } fpt_type denom = to_fpt(sqrt_expr_.eval3(cA, cB)); if (recompute_c_y) { for (int i = 0; i < 3; ++i) { int j = (i+1) % 3; int k = (i+2) % 3; cA[i] = b[j] * c[k] - b[k] * c[j]; } fpt_type c_y = to_fpt(sqrt_expr_.eval3(cA, cB)); c_event.y(c_y / denom); } if (recompute_c_x || recompute_lower_x) { cA[3] = 0; for (int i = 0; i < 3; ++i) { int j = (i+1) % 3; int k = (i+2) % 3; cA[i] = a[j] * c[k] - a[k] * c[j]; if (recompute_lower_x) { cA[3] = cA[3] + cA[i] * b[i]; } } if (recompute_c_x) { fpt_type c_x = to_fpt(sqrt_expr_.eval3(cA, cB)); c_event.x(c_x / denom); } if (recompute_lower_x) { cB[3] = 1; fpt_type lower_x = to_fpt(sqrt_expr_.eval4(cA, cB)); c_event.lower_x(lower_x / denom); } } } private: // Evaluates A[3] + A[0] * sqrt(B[0]) + A[1] * sqrt(B[1]) + // A[2] * sqrt(B[3] * (sqrt(B[0] * B[1]) + B[2])). template <typename _int, typename _fpt> _fpt sqrt_expr_evaluator_pss4(_int *A, _int *B) { _int cA[4], cB[4]; if (is_zero(A[3])) { _fpt lh = sqrt_expr_.eval2(A, B); cA[0] = 1; cB[0] = B[0] * B[1]; cA[1] = B[2]; cB[1] = 1; _fpt rh = sqrt_expr_.eval1(A+2, B+3) * get_sqrt(sqrt_expr_.eval2(cA, cB)); if ((!is_neg(lh) && !is_neg(rh)) || (!is_pos(lh) && !is_pos(rh))) return lh + rh; cA[0] = A[0] * A[0] * B[0] + A[1] * A[1] * B[1] - A[2] * A[2] * B[3] * B[2]; cB[0] = 1; cA[1] = A[0] * A[1] * 2 - A[2] * A[2] * B[3]; cB[1] = B[0] * B[1]; _fpt numer = sqrt_expr_.eval2(cA, cB); return numer / (lh - rh); } cA[0] = 1; cB[0] = B[0] * B[1]; cA[1] = B[2]; cB[1] = 1; _fpt rh = sqrt_expr_.eval1(A+2, B+3) * get_sqrt(sqrt_expr_.eval2(cA, cB)); cA[0] = A[0]; cB[0] = B[0]; cA[1] = A[1]; cB[1] = B[1]; cA[2] = A[3]; cB[2] = 1; _fpt lh = sqrt_expr_.eval3(cA, cB); if ((!is_neg(lh) && !is_neg(rh)) || (!is_pos(lh) && !is_pos(rh))) return lh + rh; cA[0] = A[3] * A[0] * 2; cA[1] = A[3] * A[1] * 2; cA[2] = A[0] * A[0] * B[0] + A[1] * A[1] * B[1] + A[3] * A[3] - A[2] * A[2] * B[2] * B[3]; cA[3] = A[0] * A[1] * 2 - A[2] * A[2] * B[3]; cB[3] = B[0] * B[1]; _fpt numer = sqrt_expr_evaluator_pss3<_int, _fpt>(cA, cB); return numer / (lh - rh); } template <typename _int, typename _fpt> // Evaluates A[0] * sqrt(B[0]) + A[1] * sqrt(B[1]) + // A[2] + A[3] * sqrt(B[0] * B[1]). // B[3] = B[0] * B[1]. _fpt sqrt_expr_evaluator_pss3(_int *A, _int *B) { _int cA[2], cB[2]; _fpt lh = sqrt_expr_.eval2(A, B); _fpt rh = sqrt_expr_.eval2(A+2, B+2); if ((!is_neg(lh) && !is_neg(rh)) || (!is_pos(lh) && !is_pos(rh))) return lh + rh; cA[0] = A[0] * A[0] * B[0] + A[1] * A[1] * B[1] - A[2] * A[2] - A[3] * A[3] * B[0] * B[1]; cB[0] = 1; cA[1] = (A[0] * A[1] - A[2] * A[3]) * 2; cB[1] = B[3]; _fpt numer = sqrt_expr_.eval2(cA, cB); return numer / (lh - rh); } robust_sqrt_expr_type sqrt_expr_; to_fpt_converter to_fpt; }; template <typename Site, typename Circle> class lazy_circle_formation_functor { public: typedef robust_fpt<fpt_type> robust_fpt_type; typedef robust_dif<robust_fpt_type> robust_dif_type; typedef typename Site::point_type point_type; typedef Site site_type; typedef Circle circle_type; typedef mp_circle_formation_functor<site_type, circle_type> exact_circle_formation_functor_type; void ppp(const site_type& site1, const site_type& site2, const site_type& site3, circle_type& c_event) { fpt_type dif_x1 = to_fpt(site1.x()) - to_fpt(site2.x()); fpt_type dif_x2 = to_fpt(site2.x()) - to_fpt(site3.x()); fpt_type dif_y1 = to_fpt(site1.y()) - to_fpt(site2.y()); fpt_type dif_y2 = to_fpt(site2.y()) - to_fpt(site3.y()); fpt_type orientation = robust_cross_product( static_cast<int_x2_type>(site1.x()) - static_cast<int_x2_type>(site2.x()), static_cast<int_x2_type>(site2.x()) - static_cast<int_x2_type>(site3.x()), static_cast<int_x2_type>(site1.y()) - static_cast<int_x2_type>(site2.y()), static_cast<int_x2_type>(site2.y()) - static_cast<int_x2_type>(site3.y())); robust_fpt_type inv_orientation(to_fpt(0.5) / orientation, to_fpt(2.0)); fpt_type sum_x1 = to_fpt(site1.x()) + to_fpt(site2.x()); fpt_type sum_x2 = to_fpt(site2.x()) + to_fpt(site3.x()); fpt_type sum_y1 = to_fpt(site1.y()) + to_fpt(site2.y()); fpt_type sum_y2 = to_fpt(site2.y()) + to_fpt(site3.y()); fpt_type dif_x3 = to_fpt(site1.x()) - to_fpt(site3.x()); fpt_type dif_y3 = to_fpt(site1.y()) - to_fpt(site3.y()); robust_dif_type c_x, c_y; c_x += robust_fpt_type(dif_x1 * sum_x1 * dif_y2, to_fpt(2.0)); c_x += robust_fpt_type(dif_y1 * sum_y1 * dif_y2, to_fpt(2.0)); c_x -= robust_fpt_type(dif_x2 * sum_x2 * dif_y1, to_fpt(2.0)); c_x -= robust_fpt_type(dif_y2 * sum_y2 * dif_y1, to_fpt(2.0)); c_y += robust_fpt_type(dif_x2 * sum_x2 * dif_x1, to_fpt(2.0)); c_y += robust_fpt_type(dif_y2 * sum_y2 * dif_x1, to_fpt(2.0)); c_y -= robust_fpt_type(dif_x1 * sum_x1 * dif_x2, to_fpt(2.0)); c_y -= robust_fpt_type(dif_y1 * sum_y1 * dif_x2, to_fpt(2.0)); robust_dif_type lower_x(c_x); lower_x -= robust_fpt_type(get_sqrt( (dif_x1 * dif_x1 + dif_y1 * dif_y1) * (dif_x2 * dif_x2 + dif_y2 * dif_y2) * (dif_x3 * dif_x3 + dif_y3 * dif_y3)), to_fpt(5.0)); c_event = circle_type( c_x.dif().fpv() * inv_orientation.fpv(), c_y.dif().fpv() * inv_orientation.fpv(), lower_x.dif().fpv() * inv_orientation.fpv()); bool recompute_c_x = c_x.dif().ulp() > ULPS; bool recompute_c_y = c_y.dif().ulp() > ULPS; bool recompute_lower_x = lower_x.dif().ulp() > ULPS; if (recompute_c_x || recompute_c_y || recompute_lower_x) { exact_circle_formation_functor_.ppp( site1, site2, site3, c_event, recompute_c_x, recompute_c_y, recompute_lower_x); } } void pps(const site_type& site1, const site_type& site2, const site_type& site3, int segment_index, circle_type& c_event) { fpt_type line_a = to_fpt(site3.y1()) - to_fpt(site3.y0()); fpt_type line_b = to_fpt(site3.x0()) - to_fpt(site3.x1()); fpt_type vec_x = to_fpt(site2.y()) - to_fpt(site1.y()); fpt_type vec_y = to_fpt(site1.x()) - to_fpt(site2.x()); robust_fpt_type teta(robust_cross_product( static_cast<int_x2_type>(site3.y1()) - static_cast<int_x2_type>(site3.y0()), static_cast<int_x2_type>(site3.x0()) - static_cast<int_x2_type>(site3.x1()), static_cast<int_x2_type>(site2.x()) - static_cast<int_x2_type>(site1.x()), static_cast<int_x2_type>(site2.y()) - static_cast<int_x2_type>(site1.y())), to_fpt(1.0)); robust_fpt_type A(robust_cross_product( static_cast<int_x2_type>(site3.y0()) - static_cast<int_x2_type>(site3.y1()), static_cast<int_x2_type>(site3.x0()) - static_cast<int_x2_type>(site3.x1()), static_cast<int_x2_type>(site3.y1()) - static_cast<int_x2_type>(site1.y()), static_cast<int_x2_type>(site3.x1()) - static_cast<int_x2_type>(site1.x())), to_fpt(1.0)); robust_fpt_type B(robust_cross_product( static_cast<int_x2_type>(site3.y0()) - static_cast<int_x2_type>(site3.y1()), static_cast<int_x2_type>(site3.x0()) - static_cast<int_x2_type>(site3.x1()), static_cast<int_x2_type>(site3.y1()) - static_cast<int_x2_type>(site2.y()), static_cast<int_x2_type>(site3.x1()) - static_cast<int_x2_type>(site2.x())), to_fpt(1.0)); robust_fpt_type denom(robust_cross_product( static_cast<int_x2_type>(site1.y()) - static_cast<int_x2_type>(site2.y()), static_cast<int_x2_type>(site1.x()) - static_cast<int_x2_type>(site2.x()), static_cast<int_x2_type>(site3.y1()) - static_cast<int_x2_type>(site3.y0()), static_cast<int_x2_type>(site3.x1()) - static_cast<int_x2_type>(site3.x0())), to_fpt(1.0)); robust_fpt_type inv_segm_len(to_fpt(1.0) / get_sqrt(line_a * line_a + line_b * line_b), to_fpt(3.0)); robust_dif_type t; if (ot::eval(denom) == ot::COLLINEAR) { t += teta / (robust_fpt_type(to_fpt(8.0)) * A); t -= A / (robust_fpt_type(to_fpt(2.0)) * teta); } else { robust_fpt_type det = ((teta * teta + denom * denom) * A * B).sqrt(); if (segment_index == 2) { t -= det / (denom * denom); } else { t += det / (denom * denom); } t += teta * (A + B) / (robust_fpt_type(to_fpt(2.0)) * denom * denom); } robust_dif_type c_x, c_y; c_x += robust_fpt_type(to_fpt(0.5) * (to_fpt(site1.x()) + to_fpt(site2.x()))); c_x += robust_fpt_type(vec_x) * t; c_y += robust_fpt_type(to_fpt(0.5) * (to_fpt(site1.y()) + to_fpt(site2.y()))); c_y += robust_fpt_type(vec_y) * t; robust_dif_type r, lower_x(c_x); r -= robust_fpt_type(line_a) * robust_fpt_type(site3.x0()); r -= robust_fpt_type(line_b) * robust_fpt_type(site3.y0()); r += robust_fpt_type(line_a) * c_x; r += robust_fpt_type(line_b) * c_y; if (r.pos().fpv() < r.neg().fpv()) r = -r; lower_x += r * inv_segm_len; c_event = circle_type( c_x.dif().fpv(), c_y.dif().fpv(), lower_x.dif().fpv()); bool recompute_c_x = c_x.dif().ulp() > ULPS; bool recompute_c_y = c_y.dif().ulp() > ULPS; bool recompute_lower_x = lower_x.dif().ulp() > ULPS; if (recompute_c_x || recompute_c_y || recompute_lower_x) { exact_circle_formation_functor_.pps( site1, site2, site3, segment_index, c_event, recompute_c_x, recompute_c_y, recompute_lower_x); } } void pss(const site_type& site1, const site_type& site2, const site_type& site3, int point_index, circle_type& c_event) { const point_type& segm_start1 = site2.point1(); const point_type& segm_end1 = site2.point0(); const point_type& segm_start2 = site3.point0(); const point_type& segm_end2 = site3.point1(); fpt_type a1 = to_fpt(segm_end1.x()) - to_fpt(segm_start1.x()); fpt_type b1 = to_fpt(segm_end1.y()) - to_fpt(segm_start1.y()); fpt_type a2 = to_fpt(segm_end2.x()) - to_fpt(segm_start2.x()); fpt_type b2 = to_fpt(segm_end2.y()) - to_fpt(segm_start2.y()); bool recompute_c_x, recompute_c_y, recompute_lower_x; robust_fpt_type orientation(robust_cross_product( static_cast<int_x2_type>(segm_end1.y()) - static_cast<int_x2_type>(segm_start1.y()), static_cast<int_x2_type>(segm_end1.x()) - static_cast<int_x2_type>(segm_start1.x()), static_cast<int_x2_type>(segm_end2.y()) - static_cast<int_x2_type>(segm_start2.y()), static_cast<int_x2_type>(segm_end2.x()) - static_cast<int_x2_type>(segm_start2.x())), to_fpt(1.0)); if (ot::eval(orientation) == ot::COLLINEAR) { robust_fpt_type a(a1 * a1 + b1 * b1, to_fpt(2.0)); robust_fpt_type c(robust_cross_product( static_cast<int_x2_type>(segm_end1.y()) - static_cast<int_x2_type>(segm_start1.y()), static_cast<int_x2_type>(segm_end1.x()) - static_cast<int_x2_type>(segm_start1.x()), static_cast<int_x2_type>(segm_start2.y()) - static_cast<int_x2_type>(segm_start1.y()), static_cast<int_x2_type>(segm_start2.x()) - static_cast<int_x2_type>(segm_start1.x())), to_fpt(1.0)); robust_fpt_type det( robust_cross_product( static_cast<int_x2_type>(segm_end1.x()) - static_cast<int_x2_type>(segm_start1.x()), static_cast<int_x2_type>(segm_end1.y()) - static_cast<int_x2_type>(segm_start1.y()), static_cast<int_x2_type>(site1.x()) - static_cast<int_x2_type>(segm_start1.x()), static_cast<int_x2_type>(site1.y()) - static_cast<int_x2_type>(segm_start1.y())) * robust_cross_product( static_cast<int_x2_type>(segm_end1.y()) - static_cast<int_x2_type>(segm_start1.y()), static_cast<int_x2_type>(segm_end1.x()) - static_cast<int_x2_type>(segm_start1.x()), static_cast<int_x2_type>(site1.y()) - static_cast<int_x2_type>(segm_start2.y()), static_cast<int_x2_type>(site1.x()) - static_cast<int_x2_type>(segm_start2.x())), to_fpt(3.0)); robust_dif_type t; t -= robust_fpt_type(a1) * robust_fpt_type(( to_fpt(segm_start1.x()) + to_fpt(segm_start2.x())) * to_fpt(0.5) - to_fpt(site1.x())); t -= robust_fpt_type(b1) * robust_fpt_type(( to_fpt(segm_start1.y()) + to_fpt(segm_start2.y())) * to_fpt(0.5) - to_fpt(site1.y())); if (point_index == 2) { t += det.sqrt(); } else { t -= det.sqrt(); } t /= a; robust_dif_type c_x, c_y; c_x += robust_fpt_type(to_fpt(0.5) * ( to_fpt(segm_start1.x()) + to_fpt(segm_start2.x()))); c_x += robust_fpt_type(a1) * t; c_y += robust_fpt_type(to_fpt(0.5) * ( to_fpt(segm_start1.y()) + to_fpt(segm_start2.y()))); c_y += robust_fpt_type(b1) * t; robust_dif_type lower_x(c_x); if (is_neg(c)) { lower_x -= robust_fpt_type(to_fpt(0.5)) * c / a.sqrt(); } else { lower_x += robust_fpt_type(to_fpt(0.5)) * c / a.sqrt(); } recompute_c_x = c_x.dif().ulp() > ULPS; recompute_c_y = c_y.dif().ulp() > ULPS; recompute_lower_x = lower_x.dif().ulp() > ULPS; c_event = circle_type(c_x.dif().fpv(), c_y.dif().fpv(), lower_x.dif().fpv()); } else { robust_fpt_type sqr_sum1(get_sqrt(a1 * a1 + b1 * b1), to_fpt(2.0)); robust_fpt_type sqr_sum2(get_sqrt(a2 * a2 + b2 * b2), to_fpt(2.0)); robust_fpt_type a(robust_cross_product( static_cast<int_x2_type>(segm_end1.x()) - static_cast<int_x2_type>(segm_start1.x()), static_cast<int_x2_type>(segm_end1.y()) - static_cast<int_x2_type>(segm_start1.y()), static_cast<int_x2_type>(segm_start2.y()) - static_cast<int_x2_type>(segm_end2.y()), static_cast<int_x2_type>(segm_end2.x()) - static_cast<int_x2_type>(segm_start2.x())), to_fpt(1.0)); if (!is_neg(a)) { a += sqr_sum1 * sqr_sum2; } else { a = (orientation * orientation) / (sqr_sum1 * sqr_sum2 - a); } robust_fpt_type or1(robust_cross_product( static_cast<int_x2_type>(segm_end1.y()) - static_cast<int_x2_type>(segm_start1.y()), static_cast<int_x2_type>(segm_end1.x()) - static_cast<int_x2_type>(segm_start1.x()), static_cast<int_x2_type>(segm_end1.y()) - static_cast<int_x2_type>(site1.y()), static_cast<int_x2_type>(segm_end1.x()) - static_cast<int_x2_type>(site1.x())), to_fpt(1.0)); robust_fpt_type or2(robust_cross_product( static_cast<int_x2_type>(segm_end2.x()) - static_cast<int_x2_type>(segm_start2.x()), static_cast<int_x2_type>(segm_end2.y()) - static_cast<int_x2_type>(segm_start2.y()), static_cast<int_x2_type>(segm_end2.x()) - static_cast<int_x2_type>(site1.x()), static_cast<int_x2_type>(segm_end2.y()) - static_cast<int_x2_type>(site1.y())), to_fpt(1.0)); robust_fpt_type det = robust_fpt_type(to_fpt(2.0)) * a * or1 * or2; robust_fpt_type c1(robust_cross_product( static_cast<int_x2_type>(segm_end1.y()) - static_cast<int_x2_type>(segm_start1.y()), static_cast<int_x2_type>(segm_end1.x()) - static_cast<int_x2_type>(segm_start1.x()), static_cast<int_x2_type>(segm_end1.y()), static_cast<int_x2_type>(segm_end1.x())), to_fpt(1.0)); robust_fpt_type c2(robust_cross_product( static_cast<int_x2_type>(segm_end2.x()) - static_cast<int_x2_type>(segm_start2.x()), static_cast<int_x2_type>(segm_end2.y()) - static_cast<int_x2_type>(segm_start2.y()), static_cast<int_x2_type>(segm_end2.x()), static_cast<int_x2_type>(segm_end2.y())), to_fpt(1.0)); robust_fpt_type inv_orientation = robust_fpt_type(to_fpt(1.0)) / orientation; robust_dif_type t, b, ix, iy; ix += robust_fpt_type(a2) * c1 * inv_orientation; ix += robust_fpt_type(a1) * c2 * inv_orientation; iy += robust_fpt_type(b1) * c2 * inv_orientation; iy += robust_fpt_type(b2) * c1 * inv_orientation; b += ix * (robust_fpt_type(a1) * sqr_sum2); b += ix * (robust_fpt_type(a2) * sqr_sum1); b += iy * (robust_fpt_type(b1) * sqr_sum2); b += iy * (robust_fpt_type(b2) * sqr_sum1); b -= sqr_sum1 * robust_fpt_type(robust_cross_product( static_cast<int_x2_type>(segm_end2.x()) - static_cast<int_x2_type>(segm_start2.x()), static_cast<int_x2_type>(segm_end2.y()) - static_cast<int_x2_type>(segm_start2.y()), static_cast<int_x2_type>(-site1.y()), static_cast<int_x2_type>(site1.x())), to_fpt(1.0)); b -= sqr_sum2 * robust_fpt_type(robust_cross_product( static_cast<int_x2_type>(segm_end1.x()) - static_cast<int_x2_type>(segm_start1.x()), static_cast<int_x2_type>(segm_end1.y()) - static_cast<int_x2_type>(segm_start1.y()), static_cast<int_x2_type>(-site1.y()), static_cast<int_x2_type>(site1.x())), to_fpt(1.0)); t -= b; if (point_index == 2) { t += det.sqrt(); } else { t -= det.sqrt(); } t /= (a * a); robust_dif_type c_x(ix), c_y(iy); c_x += t * (robust_fpt_type(a1) * sqr_sum2); c_x += t * (robust_fpt_type(a2) * sqr_sum1); c_y += t * (robust_fpt_type(b1) * sqr_sum2); c_y += t * (robust_fpt_type(b2) * sqr_sum1); if (t.pos().fpv() < t.neg().fpv()) { t = -t; } robust_dif_type lower_x(c_x); if (is_neg(orientation)) { lower_x -= t * orientation; } else { lower_x += t * orientation; } recompute_c_x = c_x.dif().ulp() > ULPS; recompute_c_y = c_y.dif().ulp() > ULPS; recompute_lower_x = lower_x.dif().ulp() > ULPS; c_event = circle_type( c_x.dif().fpv(), c_y.dif().fpv(), lower_x.dif().fpv()); } if (recompute_c_x || recompute_c_y || recompute_lower_x) { exact_circle_formation_functor_.pss( site1, site2, site3, point_index, c_event, recompute_c_x, recompute_c_y, recompute_lower_x); } } void sss(const site_type& site1, const site_type& site2, const site_type& site3, circle_type& c_event) { robust_fpt_type a1(to_fpt(site1.x1()) - to_fpt(site1.x0())); robust_fpt_type b1(to_fpt(site1.y1()) - to_fpt(site1.y0())); robust_fpt_type c1(robust_cross_product( site1.x0(), site1.y0(), site1.x1(), site1.y1()), to_fpt(1.0)); robust_fpt_type a2(to_fpt(site2.x1()) - to_fpt(site2.x0())); robust_fpt_type b2(to_fpt(site2.y1()) - to_fpt(site2.y0())); robust_fpt_type c2(robust_cross_product( site2.x0(), site2.y0(), site2.x1(), site2.y1()), to_fpt(1.0)); robust_fpt_type a3(to_fpt(site3.x1()) - to_fpt(site3.x0())); robust_fpt_type b3(to_fpt(site3.y1()) - to_fpt(site3.y0())); robust_fpt_type c3(robust_cross_product( site3.x0(), site3.y0(), site3.x1(), site3.y1()), to_fpt(1.0)); robust_fpt_type len1 = (a1 * a1 + b1 * b1).sqrt(); robust_fpt_type len2 = (a2 * a2 + b2 * b2).sqrt(); robust_fpt_type len3 = (a3 * a3 + b3 * b3).sqrt(); robust_fpt_type cross_12(robust_cross_product( static_cast<int_x2_type>(site1.x1()) - static_cast<int_x2_type>(site1.x0()), static_cast<int_x2_type>(site1.y1()) - static_cast<int_x2_type>(site1.y0()), static_cast<int_x2_type>(site2.x1()) - static_cast<int_x2_type>(site2.x0()), static_cast<int_x2_type>(site2.y1()) - static_cast<int_x2_type>(site2.y0())), to_fpt(1.0)); robust_fpt_type cross_23(robust_cross_product( static_cast<int_x2_type>(site2.x1()) - static_cast<int_x2_type>(site2.x0()), static_cast<int_x2_type>(site2.y1()) - static_cast<int_x2_type>(site2.y0()), static_cast<int_x2_type>(site3.x1()) - static_cast<int_x2_type>(site3.x0()), static_cast<int_x2_type>(site3.y1()) - static_cast<int_x2_type>(site3.y0())), to_fpt(1.0)); robust_fpt_type cross_31(robust_cross_product( static_cast<int_x2_type>(site3.x1()) - static_cast<int_x2_type>(site3.x0()), static_cast<int_x2_type>(site3.y1()) - static_cast<int_x2_type>(site3.y0()), static_cast<int_x2_type>(site1.x1()) - static_cast<int_x2_type>(site1.x0()), static_cast<int_x2_type>(site1.y1()) - static_cast<int_x2_type>(site1.y0())), to_fpt(1.0)); // denom = cross_12 * len3 + cross_23 * len1 + cross_31 * len2. robust_dif_type denom; denom += cross_12 * len3; denom += cross_23 * len1; denom += cross_31 * len2; // denom * r = (b2 * c_x - a2 * c_y - c2 * denom) / len2. robust_dif_type r; r -= cross_12 * c3; r -= cross_23 * c1; r -= cross_31 * c2; robust_dif_type c_x; c_x += a1 * c2 * len3; c_x -= a2 * c1 * len3; c_x += a2 * c3 * len1; c_x -= a3 * c2 * len1; c_x += a3 * c1 * len2; c_x -= a1 * c3 * len2; robust_dif_type c_y; c_y += b1 * c2 * len3; c_y -= b2 * c1 * len3; c_y += b2 * c3 * len1; c_y -= b3 * c2 * len1; c_y += b3 * c1 * len2; c_y -= b1 * c3 * len2; robust_dif_type lower_x = c_x + r; robust_fpt_type denom_dif = denom.dif(); robust_fpt_type c_x_dif = c_x.dif() / denom_dif; robust_fpt_type c_y_dif = c_y.dif() / denom_dif; robust_fpt_type lower_x_dif = lower_x.dif() / denom_dif; bool recompute_c_x = c_x_dif.ulp() > ULPS; bool recompute_c_y = c_y_dif.ulp() > ULPS; bool recompute_lower_x = lower_x_dif.ulp() > ULPS; c_event = circle_type(c_x_dif.fpv(), c_y_dif.fpv(), lower_x_dif.fpv()); if (recompute_c_x || recompute_c_y || recompute_lower_x) { exact_circle_formation_functor_.sss( site1, site2, site3, c_event, recompute_c_x, recompute_c_y, recompute_lower_x); } } private: exact_circle_formation_functor_type exact_circle_formation_functor_; to_fpt_converter to_fpt; }; template <typename Site, typename Circle, typename CEP = circle_existence_predicate<Site>, typename CFF = lazy_circle_formation_functor<Site, Circle> > class circle_formation_predicate { public: typedef Site site_type; typedef Circle circle_type; typedef CEP circle_existence_predicate_type; typedef CFF circle_formation_functor_type; // Create a circle event from the given three sites. // Returns true if the circle event exists, else false. // If exists circle event is saved into the c_event variable. bool operator()(const site_type& site1, const site_type& site2, const site_type& site3, circle_type& circle) { if (!site1.is_segment()) { if (!site2.is_segment()) { if (!site3.is_segment()) { // (point, point, point) sites. if (!circle_existence_predicate_.ppp(site1, site2, site3)) return false; circle_formation_functor_.ppp(site1, site2, site3, circle); } else { // (point, point, segment) sites. if (!circle_existence_predicate_.pps(site1, site2, site3, 3)) return false; circle_formation_functor_.pps(site1, site2, site3, 3, circle); } } else { if (!site3.is_segment()) { // (point, segment, point) sites. if (!circle_existence_predicate_.pps(site1, site3, site2, 2)) return false; circle_formation_functor_.pps(site1, site3, site2, 2, circle); } else { // (point, segment, segment) sites. if (!circle_existence_predicate_.pss(site1, site2, site3, 1)) return false; circle_formation_functor_.pss(site1, site2, site3, 1, circle); } } } else { if (!site2.is_segment()) { if (!site3.is_segment()) { // (segment, point, point) sites. if (!circle_existence_predicate_.pps(site2, site3, site1, 1)) return false; circle_formation_functor_.pps(site2, site3, site1, 1, circle); } else { // (segment, point, segment) sites. if (!circle_existence_predicate_.pss(site2, site1, site3, 2)) return false; circle_formation_functor_.pss(site2, site1, site3, 2, circle); } } else { if (!site3.is_segment()) { // (segment, segment, point) sites. if (!circle_existence_predicate_.pss(site3, site1, site2, 3)) return false; circle_formation_functor_.pss(site3, site1, site2, 3, circle); } else { // (segment, segment, segment) sites. if (!circle_existence_predicate_.sss(site1, site2, site3)) return false; circle_formation_functor_.sss(site1, site2, site3, circle); } } } if (lies_outside_vertical_segment(circle, site1) || lies_outside_vertical_segment(circle, site2) || lies_outside_vertical_segment(circle, site3)) { return false; } return true; } private: bool lies_outside_vertical_segment( const circle_type& c, const site_type& s) { if (!s.is_segment() || !is_vertical(s)) { return false; } fpt_type y0 = to_fpt(s.is_inverse() ? s.y1() : s.y0()); fpt_type y1 = to_fpt(s.is_inverse() ? s.y0() : s.y1()); return ulp_cmp(c.y(), y0, ULPS) == ulp_cmp_type::LESS || ulp_cmp(c.y(), y1, ULPS) == ulp_cmp_type::MORE; } private: to_fpt_converter to_fpt; ulp_cmp_type ulp_cmp; circle_existence_predicate_type circle_existence_predicate_; circle_formation_functor_type circle_formation_functor_; }; }; } // detail } // polygon } // boost #endif // BOOST_POLYGON_DETAIL_VORONOI_PREDICATES PK �b�[�Bʔ � detail/polygon_sort_adaptor.hppnu �[��� /* Copyright 2008 Intel Corporation Use, modification and distribution are 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_POLYGON_SORT_ADAPTOR_HPP #define BOOST_POLYGON_SORT_ADAPTOR_HPP #ifdef __ICC #pragma warning(disable:2022) #pragma warning(disable:2023) #endif #include <algorithm> //! @brief polygon_sort_adaptor default implementation that calls std::sort namespace boost { namespace polygon { template<typename iterator_type> struct dummy_to_delay_instantiation{ typedef int unit_type; // default GTL unit }; //! @brief polygon_sort_adaptor default implementation that calls std::sort template<typename T> struct polygon_sort_adaptor { //! @brief wrapper that mimics std::sort() function and takes // the same arguments template<typename RandomAccessIterator_Type> static void sort(RandomAccessIterator_Type _First, RandomAccessIterator_Type _Last) { std::sort(_First, _Last); } //! @brief wrapper that mimics std::sort() function overload and takes // the same arguments template<typename RandomAccessIterator_Type, typename Pred_Type> static void sort(RandomAccessIterator_Type _First, RandomAccessIterator_Type _Last, const Pred_Type& _Comp) { std::sort(_First, _Last, _Comp); } }; //! @brief user level wrapper for sorting quantities template <typename iter_type> void polygon_sort(iter_type _b_, iter_type _e_) { polygon_sort_adaptor<typename dummy_to_delay_instantiation<iter_type>::unit_type>::sort(_b_, _e_); } //! @brief user level wrapper for sorting quantities that takes predicate // as additional argument template <typename iter_type, typename pred_type> void polygon_sort(iter_type _b_, iter_type _e_, const pred_type& _pred_) { polygon_sort_adaptor<typename dummy_to_delay_instantiation<iter_type>::unit_type>::sort(_b_, _e_, _pred_); } } // namespace polygon } // namespace boost #endif PK �b�[ѕ��b` b` detail/polygon_45_formation.hppnu �[��� /* Copyright 2008 Intel Corporation Use, modification and distribution are 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_POLYGON_POLYGON_45_FORMATION_HPP #define BOOST_POLYGON_POLYGON_45_FORMATION_HPP namespace boost { namespace polygon{ template <typename T, typename T2> struct PolyLineByConcept {}; template <typename T> class PolyLine45PolygonData; template <typename T> class PolyLine45HoleData; //polygon45formation algorithm template <typename Unit> struct polygon_45_formation : public boolean_op_45<Unit> { typedef point_data<Unit> Point; typedef polygon_45_data<Unit> Polygon45; typedef polygon_45_with_holes_data<Unit> Polygon45WithHoles; typedef typename boolean_op_45<Unit>::Vertex45 Vertex45; typedef typename boolean_op_45<Unit>::lessVertex45 lessVertex45; typedef typename boolean_op_45<Unit>::Count2 Count2; typedef typename boolean_op_45<Unit>::Scan45Count Scan45Count; typedef std::pair<Point, Scan45Count> Scan45Vertex; typedef typename boolean_op_45<Unit>::template Scan45<Count2, typename boolean_op_45<Unit>::template boolean_op_45_output_functor<0> > Scan45; class PolyLine45 { public: typedef typename std::list<Point>::const_iterator iterator; // default constructor of point does not initialize x and y inline PolyLine45() : points() {} //do nothing default constructor // initialize a polygon from x,y values, it is assumed that the first is an x // and that the input is a well behaved polygon template<class iT> inline PolyLine45& set(iT inputBegin, iT inputEnd) { points.clear(); //just in case there was some old data there while(inputBegin != inputEnd) { points.insert(points.end(), *inputBegin); ++inputBegin; } return *this; } // copy constructor (since we have dynamic memory) inline PolyLine45(const PolyLine45& that) : points(that.points) {} // assignment operator (since we have dynamic memory do a deep copy) inline PolyLine45& operator=(const PolyLine45& that) { points = that.points; return *this; } // get begin iterator, returns a pointer to a const Unit inline iterator begin() const { return points.begin(); } // get end iterator, returns a pointer to a const Unit inline iterator end() const { return points.end(); } inline std::size_t size() const { return points.size(); } //public data member std::list<Point> points; }; class ActiveTail45 { private: //data PolyLine45* tailp_; ActiveTail45 *otherTailp_; std::list<ActiveTail45*> holesList_; bool head_; public: /** * @brief iterator over coordinates of the figure */ typedef typename PolyLine45::iterator iterator; /** * @brief iterator over holes contained within the figure */ typedef typename std::list<ActiveTail45*>::const_iterator iteratorHoles; //default constructor inline ActiveTail45() : tailp_(0), otherTailp_(0), holesList_(), head_(0) {} //constructor inline ActiveTail45(const Vertex45& vertex, ActiveTail45* otherTailp = 0) : tailp_(0), otherTailp_(0), holesList_(), head_(0) { tailp_ = new PolyLine45; tailp_->points.push_back(vertex.pt); bool headArray[4] = {false, true, true, true}; bool inverted = vertex.count == -1; head_ = headArray[vertex.rise+1] ^ inverted; otherTailp_ = otherTailp; } inline ActiveTail45(Point point, ActiveTail45* otherTailp, bool head = true) : tailp_(0), otherTailp_(0), holesList_(), head_(0) { tailp_ = new PolyLine45; tailp_->points.push_back(point); head_ = head; otherTailp_ = otherTailp; } inline ActiveTail45(ActiveTail45* otherTailp) : tailp_(0), otherTailp_(0), holesList_(), head_(0) { tailp_ = otherTailp->tailp_; otherTailp_ = otherTailp; } //copy constructor inline ActiveTail45(const ActiveTail45& that) : tailp_(0), otherTailp_(0), holesList_(), head_(0) { (*this) = that; } //destructor inline ~ActiveTail45() { destroyContents(); } //assignment operator inline ActiveTail45& operator=(const ActiveTail45& that) { tailp_ = new PolyLine45(*(that.tailp_)); head_ = that.head_; otherTailp_ = that.otherTailp_; holesList_ = that.holesList_; return *this; } //equivalence operator inline bool operator==(const ActiveTail45& b) const { return tailp_ == b.tailp_ && head_ == b.head_; } /** * @brief get the pointer to the polyline that this is an active tail of */ inline PolyLine45* getTail() const { return tailp_; } /** * @brief get the pointer to the polyline at the other end of the chain */ inline PolyLine45* getOtherTail() const { return otherTailp_->tailp_; } /** * @brief get the pointer to the activetail at the other end of the chain */ inline ActiveTail45* getOtherActiveTail() const { return otherTailp_; } /** * @brief test if another active tail is the other end of the chain */ inline bool isOtherTail(const ActiveTail45& b) const { return &b == otherTailp_; } /** * @brief update this end of chain pointer to new polyline */ inline ActiveTail45& updateTail(PolyLine45* newTail) { tailp_ = newTail; return *this; } inline bool join(ActiveTail45* tail) { if(tail == otherTailp_) { //std::cout << "joining to other tail!\n"; return false; } if(tail->head_ == head_) { //std::cout << "joining head to head!\n"; return false; } if(!tailp_) { //std::cout << "joining empty tail!\n"; return false; } if(!(otherTailp_->head_)) { otherTailp_->copyHoles(*tail); otherTailp_->copyHoles(*this); } else { tail->otherTailp_->copyHoles(*this); tail->otherTailp_->copyHoles(*tail); } PolyLine45* tail1 = tailp_; PolyLine45* tail2 = tail->tailp_; if(head_) std::swap(tail1, tail2); tail1->points.splice(tail1->points.end(), tail2->points); delete tail2; otherTailp_->tailp_ = tail1; tail->otherTailp_->tailp_ = tail1; otherTailp_->otherTailp_ = tail->otherTailp_; tail->otherTailp_->otherTailp_ = otherTailp_; tailp_ = 0; tail->tailp_ = 0; tail->otherTailp_ = 0; otherTailp_ = 0; return true; } /** * @brief associate a hole to this active tail by the specified policy */ inline ActiveTail45* addHole(ActiveTail45* hole) { holesList_.push_back(hole); copyHoles(*hole); copyHoles(*(hole->otherTailp_)); return this; } /** * @brief get the list of holes */ inline const std::list<ActiveTail45*>& getHoles() const { return holesList_; } /** * @brief copy holes from that to this */ inline void copyHoles(ActiveTail45& that) { holesList_.splice(holesList_.end(), that.holesList_); } /** * @brief find out if solid to right */ inline bool solidToRight() const { return !head_; } inline bool solidToLeft() const { return head_; } /** * @brief get vertex */ inline Point getPoint() const { if(head_) return tailp_->points.front(); return tailp_->points.back(); } /** * @brief add a coordinate to the polygon at this active tail end, properly handle degenerate edges by removing redundant coordinate */ inline void pushPoint(Point point) { if(head_) { //if(tailp_->points.size() < 2) { // tailp_->points.push_front(point); // return; //} typename std::list<Point>::iterator iter = tailp_->points.begin(); if(iter == tailp_->points.end()) { tailp_->points.push_front(point); return; } Unit firstY = (*iter).y(); Unit firstX = (*iter).x(); ++iter; if(iter == tailp_->points.end()) { tailp_->points.push_front(point); return; } if((iter->y() == point.y() && firstY == point.y()) || (iter->x() == point.x() && firstX == point.x())){ --iter; *iter = point; } else { tailp_->points.push_front(point); } return; } //if(tailp_->points.size() < 2) { // tailp_->points.push_back(point); // return; //} typename std::list<Point>::reverse_iterator iter = tailp_->points.rbegin(); if(iter == tailp_->points.rend()) { tailp_->points.push_back(point); return; } Unit firstY = (*iter).y(); Unit firstX = (*iter).x(); ++iter; if(iter == tailp_->points.rend()) { tailp_->points.push_back(point); return; } if((iter->y() == point.y() && firstY == point.y()) || (iter->x() == point.x() && firstX == point.x())){ --iter; *iter = point; } else { tailp_->points.push_back(point); } } /** * @brief joins the two chains that the two active tail tails are ends of * checks for closure of figure and writes out polygons appropriately * returns a handle to a hole if one is closed */ template <class cT> static inline ActiveTail45* joinChains(Point point, ActiveTail45* at1, ActiveTail45* at2, bool solid, cT& output) { if(at1->otherTailp_ == at2) { //if(at2->otherTailp_ != at1) std::cout << "half closed error\n"; //we are closing a figure at1->pushPoint(point); at2->pushPoint(point); if(solid) { //we are closing a solid figure, write to output //std::cout << "test1\n"; at1->copyHoles(*(at1->otherTailp_)); //std::cout << "test2\n"; //Polygon45WithHolesImpl<PolyLine45PolygonData> poly(polyData); //std::cout << poly << "\n"; //std::cout << "test3\n"; typedef typename cT::value_type pType; output.push_back(pType()); typedef typename geometry_concept<pType>::type cType; typename PolyLineByConcept<Unit, cType>::type polyData(at1); assign(output.back(), polyData); //std::cout << "test4\n"; //std::cout << "delete " << at1->otherTailp_ << "\n"; //at1->print(); //at1->otherTailp_->print(); delete at1->otherTailp_; //at1->print(); //at1->otherTailp_->print(); //std::cout << "test5\n"; //std::cout << "delete " << at1 << "\n"; delete at1; //std::cout << "test6\n"; return 0; } else { //we are closing a hole, return the tail end active tail of the figure return at1; } } //we are not closing a figure at1->pushPoint(point); at1->join(at2); delete at1; delete at2; return 0; } inline void destroyContents() { if(otherTailp_) { //std::cout << "delete p " << tailp_ << "\n"; if(tailp_) delete tailp_; tailp_ = 0; otherTailp_->otherTailp_ = 0; otherTailp_->tailp_ = 0; otherTailp_ = 0; } for(typename std::list<ActiveTail45*>::iterator itr = holesList_.begin(); itr != holesList_.end(); ++itr) { //std::cout << "delete p " << (*itr) << "\n"; if(*itr) { if((*itr)->otherTailp_) { delete (*itr)->otherTailp_; (*itr)->otherTailp_ = 0; } delete (*itr); } (*itr) = 0; } holesList_.clear(); } // inline void print() { // std::cout << this << " " << tailp_ << " " << otherTailp_ << " " << holesList_.size() << " " << head_ << "\n"; // } static inline std::pair<ActiveTail45*, ActiveTail45*> createActiveTail45sAsPair(Point point, bool solid, ActiveTail45* phole, bool fractureHoles) { ActiveTail45* at1 = 0; ActiveTail45* at2 = 0; if(phole && fractureHoles) { //std::cout << "adding hole\n"; at1 = phole; //assert solid == false, we should be creating a corner with solid below and to the left if there was a hole at2 = at1->getOtherActiveTail(); at2->pushPoint(point); at1->pushPoint(point); } else { at1 = new ActiveTail45(point, at2, solid); at2 = new ActiveTail45(at1); at1->otherTailp_ = at2; at2->head_ = !solid; if(phole) at2->addHole(phole); //assert fractureHoles == false } return std::pair<ActiveTail45*, ActiveTail45*>(at1, at2); } }; template <typename ct> class Vertex45CountT { public: typedef ct count_type; inline Vertex45CountT() #ifndef BOOST_POLYGON_MSVC : counts() #endif { counts[0] = counts[1] = counts[2] = counts[3] = 0; } //inline Vertex45CountT(ct count) { counts[0] = counts[1] = counts[2] = counts[3] = count; } inline Vertex45CountT(const ct& count1, const ct& count2, const ct& count3, const ct& count4) #ifndef BOOST_POLYGON_MSVC : counts() #endif { counts[0] = count1; counts[1] = count2; counts[2] = count3; counts[3] = count4; } inline Vertex45CountT(const Vertex45& vertex) #ifndef BOOST_POLYGON_MSVC : counts() #endif { counts[0] = counts[1] = counts[2] = counts[3] = 0; (*this) += vertex; } inline Vertex45CountT(const Vertex45CountT& count) #ifndef BOOST_POLYGON_MSVC : counts() #endif { (*this) = count; } inline bool operator==(const Vertex45CountT& count) const { for(unsigned int i = 0; i < 4; ++i) { if(counts[i] != count.counts[i]) return false; } return true; } inline bool operator!=(const Vertex45CountT& count) const { return !((*this) == count); } inline Vertex45CountT& operator=(ct count) { counts[0] = counts[1] = counts[2] = counts[3] = count; return *this; } inline Vertex45CountT& operator=(const Vertex45CountT& count) { for(unsigned int i = 0; i < 4; ++i) { counts[i] = count.counts[i]; } return *this; } inline ct& operator[](int index) { return counts[index]; } inline ct operator[](int index) const {return counts[index]; } inline Vertex45CountT& operator+=(const Vertex45CountT& count){ for(unsigned int i = 0; i < 4; ++i) { counts[i] += count.counts[i]; } return *this; } inline Vertex45CountT& operator-=(const Vertex45CountT& count){ for(unsigned int i = 0; i < 4; ++i) { counts[i] -= count.counts[i]; } return *this; } inline Vertex45CountT operator+(const Vertex45CountT& count) const { return Vertex45CountT(*this)+=count; } inline Vertex45CountT operator-(const Vertex45CountT& count) const { return Vertex45CountT(*this)-=count; } inline Vertex45CountT invert() const { return Vertex45CountT()-=(*this); } inline Vertex45CountT& operator+=(const Vertex45& element){ counts[element.rise+1] += element.count; return *this; } inline bool is_45() const { return counts[0] != 0 || counts[2] != 0; } private: ct counts[4]; }; typedef Vertex45CountT<int> Vertex45Count; // inline std::ostream& operator<< (std::ostream& o, const Vertex45Count& c) { // o << c[0] << ", " << c[1] << ", "; // o << c[2] << ", " << c[3]; // return o; // } template <typename ct> class Vertex45CompactT { public: Point pt; ct count; typedef typename boolean_op_45<Unit>::template Vertex45T<typename ct::count_type> Vertex45T; inline Vertex45CompactT() : pt(), count() {} inline Vertex45CompactT(const Point& point, int riseIn, int countIn) : pt(point), count() { count[riseIn+1] = countIn; } template <typename ct2> inline Vertex45CompactT(const typename boolean_op_45<Unit>::template Vertex45T<ct2>& vertex) : pt(vertex.pt), count() { count[vertex.rise+1] = vertex.count; } inline Vertex45CompactT(const Vertex45CompactT& vertex) : pt(vertex.pt), count(vertex.count) {} inline Vertex45CompactT& operator=(const Vertex45CompactT& vertex){ pt = vertex.pt; count = vertex.count; return *this; } inline bool operator==(const Vertex45CompactT& vertex) const { return pt == vertex.pt && count == vertex.count; } inline bool operator!=(const Vertex45CompactT& vertex) const { return !((*this) == vertex); } inline bool operator<(const Vertex45CompactT& vertex) const { if(pt.x() < vertex.pt.x()) return true; if(pt.x() == vertex.pt.x()) { return pt.y() < vertex.pt.y(); } return false; } inline bool operator>(const Vertex45CompactT& vertex) const { return vertex < (*this); } inline bool operator<=(const Vertex45CompactT& vertex) const { return !((*this) > vertex); } inline bool operator>=(const Vertex45CompactT& vertex) const { return !((*this) < vertex); } inline bool haveVertex45(int index) const { return count[index]; } inline Vertex45T operator[](int index) const { return Vertex45T(pt, index-1, count[index]); } }; typedef Vertex45CompactT<Vertex45Count> Vertex45Compact; // inline std::ostream& operator<< (std::ostream& o, const Vertex45Compact& c) { // o << c.pt << ", " << c.count; // return o; // } class Polygon45Formation { private: //definitions typedef std::map<Vertex45, ActiveTail45*, lessVertex45> Polygon45FormationData; typedef typename Polygon45FormationData::iterator iterator; typedef typename Polygon45FormationData::const_iterator const_iterator; //data Polygon45FormationData scanData_; Unit x_; int justBefore_; int fractureHoles_; public: inline Polygon45Formation() : scanData_(), x_((std::numeric_limits<Unit>::min)()), justBefore_(false), fractureHoles_(0) { lessVertex45 lessElm(&x_, &justBefore_); scanData_ = Polygon45FormationData(lessElm); } inline Polygon45Formation(bool fractureHoles) : scanData_(), x_((std::numeric_limits<Unit>::min)()), justBefore_(false), fractureHoles_(fractureHoles) { lessVertex45 lessElm(&x_, &justBefore_); scanData_ = Polygon45FormationData(lessElm); } inline Polygon45Formation(const Polygon45Formation& that) : scanData_(), x_((std::numeric_limits<Unit>::min)()), justBefore_(false), fractureHoles_(0) { (*this) = that; } inline Polygon45Formation& operator=(const Polygon45Formation& that) { x_ = that.x_; justBefore_ = that.justBefore_; fractureHoles_ = that.fractureHoles_; lessVertex45 lessElm(&x_, &justBefore_); scanData_ = Polygon45FormationData(lessElm); for(const_iterator itr = that.scanData_.begin(); itr != that.scanData_.end(); ++itr){ scanData_.insert(scanData_.end(), *itr); } return *this; } //cT is an output container of Polygon45 or Polygon45WithHoles //iT is an iterator over Vertex45 elements //inputBegin - inputEnd is a range of sorted iT that represents //one or more scanline stops worth of data template <class cT, class iT> void scan(cT& output, iT inputBegin, iT inputEnd) { //std::cout << "1\n"; while(inputBegin != inputEnd) { //std::cout << "2\n"; x_ = (*inputBegin).pt.x(); //std::cout << "SCAN FORMATION " << x_ << "\n"; //std::cout << "x_ = " << x_ << "\n"; //std::cout << "scan line size: " << scanData_.size() << "\n"; inputBegin = processEvent_(output, inputBegin, inputEnd); } } private: //functions template <class cT, class cT2> inline std::pair<int, ActiveTail45*> processPoint_(cT& output, cT2& elements, Point point, Vertex45Count& counts, ActiveTail45** tails, Vertex45Count& incoming) { //std::cout << point << "\n"; //std::cout << counts[0] << " "; //std::cout << counts[1] << " "; //std::cout << counts[2] << " "; //std::cout << counts[3] << "\n"; //std::cout << incoming[0] << " "; //std::cout << incoming[1] << " "; //std::cout << incoming[2] << " "; //std::cout << incoming[3] << "\n"; //join any closing solid corners ActiveTail45* returnValue = 0; int returnCount = 0; for(int i = 0; i < 3; ++i) { //std::cout << i << "\n"; if(counts[i] == -1) { //std::cout << "fixed i\n"; for(int j = i + 1; j < 4; ++j) { //std::cout << j << "\n"; if(counts[j]) { if(counts[j] == 1) { //std::cout << "case1: " << i << " " << j << "\n"; //if a figure is closed it will be written out by this function to output ActiveTail45::joinChains(point, tails[i], tails[j], true, output); counts[i] = 0; counts[j] = 0; tails[i] = 0; tails[j] = 0; } break; } } } } //find any pairs of incoming edges that need to create pair for leading solid //std::cout << "checking case2\n"; for(int i = 0; i < 3; ++i) { //std::cout << i << "\n"; if(incoming[i] == 1) { //std::cout << "fixed i\n"; for(int j = i + 1; j < 4; ++j) { //std::cout << j << "\n"; if(incoming[j]) { if(incoming[j] == -1) { //std::cout << "case2: " << i << " " << j << "\n"; //std::cout << "creating active tail pair\n"; std::pair<ActiveTail45*, ActiveTail45*> tailPair = ActiveTail45::createActiveTail45sAsPair(point, true, 0, fractureHoles_ != 0); //tailPair.first->print(); //tailPair.second->print(); if(j == 3) { //vertical active tail becomes return value returnValue = tailPair.first; returnCount = 1; } else { Vertex45 vertex(point, i -1, incoming[i]); //std::cout << "new element " << j-1 << " " << -1 << "\n"; elements.push_back(std::pair<Vertex45, ActiveTail45*>(Vertex45(point, j -1, -1), tailPair.first)); } //std::cout << "new element " << i-1 << " " << 1 << "\n"; elements.push_back(std::pair<Vertex45, ActiveTail45*>(Vertex45(point, i -1, 1), tailPair.second)); incoming[i] = 0; incoming[j] = 0; } break; } } } } //find any active tail that needs to pass through to an incoming edge //we expect to find no more than two pass through //find pass through with solid on top //std::cout << "checking case 3\n"; for(int i = 0; i < 4; ++i) { //std::cout << i << "\n"; if(counts[i] != 0) { if(counts[i] == 1) { //std::cout << "fixed i\n"; for(int j = 3; j >= 0; --j) { if(incoming[j] != 0) { if(incoming[j] == 1) { //std::cout << "case3: " << i << " " << j << "\n"; //tails[i]->print(); //pass through solid on top tails[i]->pushPoint(point); //std::cout << "after push\n"; if(j == 3) { returnValue = tails[i]; returnCount = -1; } else { elements.push_back(std::pair<Vertex45, ActiveTail45*>(Vertex45(point, j -1, incoming[j]), tails[i])); } tails[i] = 0; counts[i] = 0; incoming[j] = 0; } break; } } } break; } } //std::cout << "checking case 4\n"; //find pass through with solid on bottom for(int i = 3; i >= 0; --i) { if(counts[i] != 0) { if(counts[i] == -1) { for(int j = 0; j < 4; ++j) { if(incoming[j] != 0) { if(incoming[j] == -1) { //std::cout << "case4: " << i << " " << j << "\n"; //pass through solid on bottom tails[i]->pushPoint(point); if(j == 3) { returnValue = tails[i]; returnCount = 1; } else { //std::cout << "new element " << j-1 << " " << incoming[j] << "\n"; elements.push_back(std::pair<Vertex45, ActiveTail45*>(Vertex45(point, j -1, incoming[j]), tails[i])); } tails[i] = 0; counts[i] = 0; incoming[j] = 0; } break; } } } break; } } //find the end of a hole or the beginning of a hole //find end of a hole for(int i = 0; i < 3; ++i) { if(counts[i] != 0) { for(int j = i+1; j < 4; ++j) { if(counts[j] != 0) { //std::cout << "case5: " << i << " " << j << "\n"; //we are ending a hole and may potentially close a figure and have to handle the hole returnValue = ActiveTail45::joinChains(point, tails[i], tails[j], false, output); tails[i] = 0; tails[j] = 0; counts[i] = 0; counts[j] = 0; break; } } break; } } //find beginning of a hole for(int i = 0; i < 3; ++i) { if(incoming[i] != 0) { for(int j = i+1; j < 4; ++j) { if(incoming[j] != 0) { //std::cout << "case6: " << i << " " << j << "\n"; //we are beginning a empty space ActiveTail45* holep = 0; if(counts[3] == 0) holep = tails[3]; std::pair<ActiveTail45*, ActiveTail45*> tailPair = ActiveTail45::createActiveTail45sAsPair(point, false, holep, fractureHoles_ != 0); if(j == 3) { returnValue = tailPair.first; returnCount = -1; } else { //std::cout << "new element " << j-1 << " " << incoming[j] << "\n"; elements.push_back(std::pair<Vertex45, ActiveTail45*>(Vertex45(point, j -1, incoming[j]), tailPair.first)); } //std::cout << "new element " << i-1 << " " << incoming[i] << "\n"; elements.push_back(std::pair<Vertex45, ActiveTail45*>(Vertex45(point, i -1, incoming[i]), tailPair.second)); incoming[i] = 0; incoming[j] = 0; break; } } break; } } //assert that tails, counts and incoming are all null return std::pair<int, ActiveTail45*>(returnCount, returnValue); } template <class cT, class iT> inline iT processEvent_(cT& output, iT inputBegin, iT inputEnd) { //std::cout << "processEvent_\n"; justBefore_ = true; //collect up all elements from the tree that are at the y //values of events in the input queue //create vector of new elements to add into tree ActiveTail45* verticalTail = 0; int verticalCount = 0; iT currentIter = inputBegin; std::vector<iterator> elementIters; std::vector<std::pair<Vertex45, ActiveTail45*> > elements; while(currentIter != inputEnd && currentIter->pt.x() == x_) { //std::cout << "loop\n"; Unit currentY = (*currentIter).pt.y(); iterator iter = lookUp_(currentY); //int counts[4] = {0, 0, 0, 0}; Vertex45Count counts; ActiveTail45* tails[4] = {0, 0, 0, verticalTail}; //std::cout << "finding elements in tree\n"; while(iter != scanData_.end() && iter->first.evalAtX(x_) == currentY) { //std::cout << "loop2\n"; elementIters.push_back(iter); int index = iter->first.rise + 1; //std::cout << index << " " << iter->first.count << "\n"; counts[index] = iter->first.count; tails[index] = iter->second; ++iter; } //int incoming[4] = {0, 0, 0, 0}; Vertex45Count incoming; //std::cout << "aggregating\n"; do { //std::cout << "loop3\n"; Vertex45Compact currentVertex(*currentIter); incoming += currentVertex.count; ++currentIter; } while(currentIter != inputEnd && currentIter->pt.y() == currentY && currentIter->pt.x() == x_); //now counts and tails have the data from the left and //incoming has the data from the right at this point //cancel out any end points //std::cout << counts[0] << " "; //std::cout << counts[1] << " "; //std::cout << counts[2] << " "; //std::cout << counts[3] << "\n"; //std::cout << incoming[0] << " "; //std::cout << incoming[1] << " "; //std::cout << incoming[2] << " "; //std::cout << incoming[3] << "\n"; if(verticalTail) { counts[3] = -verticalCount; } incoming[3] *= -1; for(unsigned int i = 0; i < 4; ++i) incoming[i] += counts[i]; //std::cout << "calling processPoint_\n"; std::pair<int, ActiveTail45*> result = processPoint_(output, elements, Point(x_, currentY), counts, tails, incoming); verticalCount = result.first; verticalTail = result.second; //if(verticalTail) std::cout << "have vertical tail\n"; //std::cout << "verticalCount: " << verticalCount << "\n"; if(verticalTail && !verticalCount) { //we got a hole out of the point we just processed //iter is still at the next y element above the current y value in the tree //std::cout << "checking whether ot handle hole\n"; if(currentIter == inputEnd || currentIter->pt.x() != x_ || currentIter->pt.y() >= iter->first.evalAtX(x_)) { //std::cout << "handle hole here\n"; if(fractureHoles_) { //std::cout << "fracture hole here\n"; //we need to handle the hole now and not at the next input vertex ActiveTail45* at = iter->second; Point point(x_, iter->first.evalAtX(x_)); verticalTail->getOtherActiveTail()->pushPoint(point); iter->second = verticalTail->getOtherActiveTail(); at->pushPoint(point); verticalTail->join(at); delete at; delete verticalTail; verticalTail = 0; } else { //std::cout << "push hole onto list\n"; iter->second->addHole(verticalTail); verticalTail = 0; } } } } //std::cout << "erasing\n"; //erase all elements from the tree for(typename std::vector<iterator>::iterator iter = elementIters.begin(); iter != elementIters.end(); ++iter) { //std::cout << "erasing loop\n"; scanData_.erase(*iter); } //switch comparison tie breaking policy justBefore_ = false; //add new elements into tree //std::cout << "inserting\n"; for(typename std::vector<std::pair<Vertex45, ActiveTail45*> >::iterator iter = elements.begin(); iter != elements.end(); ++iter) { //std::cout << "inserting loop\n"; scanData_.insert(scanData_.end(), *iter); } //std::cout << "end processEvent\n"; return currentIter; } inline iterator lookUp_(Unit y){ //if just before then we need to look from 1 not -1 return scanData_.lower_bound(Vertex45(Point(x_, y), -1+2*justBefore_, 0)); } }; template <typename stream_type> static inline bool testPolygon45FormationRect(stream_type& stdcout) { stdcout << "testing polygon formation\n"; Polygon45Formation pf(true); std::vector<Polygon45> polys; std::vector<Vertex45> data; data.push_back(Vertex45(Point(0, 0), 0, 1)); data.push_back(Vertex45(Point(0, 0), 2, 1)); data.push_back(Vertex45(Point(0, 10), 2, -1)); data.push_back(Vertex45(Point(0, 10), 0, -1)); data.push_back(Vertex45(Point(10, 0), 0, -1)); data.push_back(Vertex45(Point(10, 0), 2, -1)); data.push_back(Vertex45(Point(10, 10), 2, 1)); data.push_back(Vertex45(Point(10, 10), 0, 1)); polygon_sort(data.begin(), data.end()); pf.scan(polys, data.begin(), data.end()); stdcout << "result size: " << polys.size() << "\n"; for(std::size_t i = 0; i < polys.size(); ++i) { stdcout << polys[i] << "\n"; } stdcout << "done testing polygon formation\n"; return true; } template <typename stream_type> static inline bool testPolygon45FormationP1(stream_type& stdcout) { stdcout << "testing polygon formation\n"; Polygon45Formation pf(true); std::vector<Polygon45> polys; std::vector<Vertex45> data; data.push_back(Vertex45(Point(0, 0), 1, 1)); data.push_back(Vertex45(Point(0, 0), 2, 1)); data.push_back(Vertex45(Point(0, 10), 2, -1)); data.push_back(Vertex45(Point(0, 10), 1, -1)); data.push_back(Vertex45(Point(10, 10), 1, -1)); data.push_back(Vertex45(Point(10, 10), 2, -1)); data.push_back(Vertex45(Point(10, 20), 2, 1)); data.push_back(Vertex45(Point(10, 20), 1, 1)); polygon_sort(data.begin(), data.end()); pf.scan(polys, data.begin(), data.end()); stdcout << "result size: " << polys.size() << "\n"; for(std::size_t i = 0; i < polys.size(); ++i) { stdcout << polys[i] << "\n"; } stdcout << "done testing polygon formation\n"; return true; } //polygon45set class template <typename stream_type> static inline bool testPolygon45FormationP2(stream_type& stdcout) { stdcout << "testing polygon formation\n"; Polygon45Formation pf(true); std::vector<Polygon45> polys; std::vector<Vertex45> data; data.push_back(Vertex45(Point(0, 0), 0, 1)); data.push_back(Vertex45(Point(0, 0), 1, -1)); data.push_back(Vertex45(Point(10, 0), 0, -1)); data.push_back(Vertex45(Point(10, 0), 1, 1)); data.push_back(Vertex45(Point(10, 10), 1, 1)); data.push_back(Vertex45(Point(10, 10), 0, -1)); data.push_back(Vertex45(Point(20, 10), 1, -1)); data.push_back(Vertex45(Point(20, 10), 0, 1)); polygon_sort(data.begin(), data.end()); pf.scan(polys, data.begin(), data.end()); stdcout << "result size: " << polys.size() << "\n"; for(std::size_t i = 0; i < polys.size(); ++i) { stdcout << polys[i] << "\n"; } stdcout << "done testing polygon formation\n"; return true; } //polygon45set class template <typename stream_type> static inline bool testPolygon45FormationStar1(stream_type& stdcout) { stdcout << "testing polygon formation\n"; Polygon45Formation pf(true); std::vector<Polygon45> polys; std::vector<Vertex45> data; // result == 0 8 -1 1 data.push_back(Vertex45(Point(0, 8), -1, 1)); // result == 0 8 1 -1 data.push_back(Vertex45(Point(0, 8), 1, -1)); // result == 4 0 1 1 data.push_back(Vertex45(Point(4, 0), 1, 1)); // result == 4 0 2 1 data.push_back(Vertex45(Point(4, 0), 2, 1)); // result == 4 4 2 -1 data.push_back(Vertex45(Point(4, 4), 2, -1)); // result == 4 4 -1 -1 data.push_back(Vertex45(Point(4, 4), -1, -1)); // result == 4 12 1 1 data.push_back(Vertex45(Point(4, 12), 1, 1)); // result == 4 12 2 1 data.push_back(Vertex45(Point(4, 12), 2, 1)); // result == 4 16 2 -1 data.push_back(Vertex45(Point(4, 16), 2, 1)); // result == 4 16 -1 -1 data.push_back(Vertex45(Point(4, 16), -1, -1)); // result == 6 2 1 -1 data.push_back(Vertex45(Point(6, 2), 1, -1)); // result == 6 14 -1 1 data.push_back(Vertex45(Point(6, 14), -1, 1)); // result == 6 2 -1 1 data.push_back(Vertex45(Point(6, 2), -1, 1)); // result == 6 14 1 -1 data.push_back(Vertex45(Point(6, 14), 1, -1)); // result == 8 0 -1 -1 data.push_back(Vertex45(Point(8, 0), -1, -1)); // result == 8 0 2 -1 data.push_back(Vertex45(Point(8, 0), 2, -1)); // result == 8 4 2 1 data.push_back(Vertex45(Point(8, 4), 2, 1)); // result == 8 4 1 1 data.push_back(Vertex45(Point(8, 4), 1, 1)); // result == 8 12 -1 -1 data.push_back(Vertex45(Point(8, 12), -1, -1)); // result == 8 12 2 -1 data.push_back(Vertex45(Point(8, 12), 2, -1)); // result == 8 16 2 1 data.push_back(Vertex45(Point(8, 16), 2, 1)); // result == 8 16 1 1 data.push_back(Vertex45(Point(8, 16), 1, 1)); // result == 12 8 1 -1 data.push_back(Vertex45(Point(12, 8), 1, -1)); // result == 12 8 -1 1 data.push_back(Vertex45(Point(12, 8), -1, 1)); polygon_sort(data.begin(), data.end()); pf.scan(polys, data.begin(), data.end()); stdcout << "result size: " << polys.size() << "\n"; for(std::size_t i = 0; i < polys.size(); ++i) { stdcout << polys[i] << "\n"; } stdcout << "done testing polygon formation\n"; return true; } template <typename stream_type> static inline bool testPolygon45FormationStar2(stream_type& stdcout) { stdcout << "testing polygon formation\n"; Polygon45Formation pf(true); std::vector<Polygon45> polys; Scan45 scan45; std::vector<Vertex45 > result; std::vector<Scan45Vertex> vertices; //is a Rectnagle(0, 0, 10, 10); Count2 count(1, 0); Count2 ncount(-1, 0); vertices.push_back(Scan45Vertex(Point(0,4), Scan45Count(Count2(0, 0), count, ncount, Count2(0, 0)))); vertices.push_back(Scan45Vertex(Point(16,4), Scan45Count(count, ncount, Count2(0, 0), Count2(0, 0)))); vertices.push_back(Scan45Vertex(Point(8,12), Scan45Count(ncount, Count2(0, 0), count, Count2(0, 0)))); count = Count2(0, 1); ncount = count.invert(); vertices.push_back(Scan45Vertex(Point(0,8), Scan45Count(count, ncount, Count2(0, 0), Count2(0, 0)))); vertices.push_back(Scan45Vertex(Point(16,8), Scan45Count(Count2(0, 0), count, ncount, Count2(0, 0)))); vertices.push_back(Scan45Vertex(Point(8,0), Scan45Count(ncount, Count2(0, 0), count, Count2(0, 0)))); sortScan45Vector(vertices); stdcout << "scanning\n"; scan45.scan(result, vertices.begin(), vertices.end()); polygon_sort(result.begin(), result.end()); pf.scan(polys, result.begin(), result.end()); stdcout << "result size: " << polys.size() << "\n"; for(std::size_t i = 0; i < polys.size(); ++i) { stdcout << polys[i] << "\n"; } stdcout << "done testing polygon formation\n"; return true; } template <typename stream_type> static inline bool testPolygon45FormationStarHole1(stream_type& stdcout) { stdcout << "testing polygon formation\n"; Polygon45Formation pf(true); std::vector<Polygon45> polys; std::vector<Vertex45> data; // result == 0 8 -1 1 data.push_back(Vertex45(Point(0, 8), -1, 1)); // result == 0 8 1 -1 data.push_back(Vertex45(Point(0, 8), 1, -1)); // result == 4 0 1 1 data.push_back(Vertex45(Point(4, 0), 1, 1)); // result == 4 0 2 1 data.push_back(Vertex45(Point(4, 0), 2, 1)); // result == 4 4 2 -1 data.push_back(Vertex45(Point(4, 4), 2, -1)); // result == 4 4 -1 -1 data.push_back(Vertex45(Point(4, 4), -1, -1)); // result == 4 12 1 1 data.push_back(Vertex45(Point(4, 12), 1, 1)); // result == 4 12 2 1 data.push_back(Vertex45(Point(4, 12), 2, 1)); // result == 4 16 2 -1 data.push_back(Vertex45(Point(4, 16), 2, 1)); // result == 4 16 -1 -1 data.push_back(Vertex45(Point(4, 16), -1, -1)); // result == 6 2 1 -1 data.push_back(Vertex45(Point(6, 2), 1, -1)); // result == 6 14 -1 1 data.push_back(Vertex45(Point(6, 14), -1, 1)); // result == 6 2 -1 1 data.push_back(Vertex45(Point(6, 2), -1, 1)); // result == 6 14 1 -1 data.push_back(Vertex45(Point(6, 14), 1, -1)); // result == 8 0 -1 -1 data.push_back(Vertex45(Point(8, 0), -1, -1)); // result == 8 0 2 -1 data.push_back(Vertex45(Point(8, 0), 2, -1)); // result == 8 4 2 1 data.push_back(Vertex45(Point(8, 4), 2, 1)); // result == 8 4 1 1 data.push_back(Vertex45(Point(8, 4), 1, 1)); // result == 8 12 -1 -1 data.push_back(Vertex45(Point(8, 12), -1, -1)); // result == 8 12 2 -1 data.push_back(Vertex45(Point(8, 12), 2, -1)); // result == 8 16 2 1 data.push_back(Vertex45(Point(8, 16), 2, 1)); // result == 8 16 1 1 data.push_back(Vertex45(Point(8, 16), 1, 1)); // result == 12 8 1 -1 data.push_back(Vertex45(Point(12, 8), 1, -1)); // result == 12 8 -1 1 data.push_back(Vertex45(Point(12, 8), -1, 1)); data.push_back(Vertex45(Point(6, 4), 1, -1)); data.push_back(Vertex45(Point(6, 4), 2, -1)); data.push_back(Vertex45(Point(6, 8), -1, 1)); data.push_back(Vertex45(Point(6, 8), 2, 1)); data.push_back(Vertex45(Point(8, 6), -1, -1)); data.push_back(Vertex45(Point(8, 6), 1, 1)); polygon_sort(data.begin(), data.end()); pf.scan(polys, data.begin(), data.end()); stdcout << "result size: " << polys.size() << "\n"; for(std::size_t i = 0; i < polys.size(); ++i) { stdcout << polys[i] << "\n"; } stdcout << "done testing polygon formation\n"; return true; } template <typename stream_type> static inline bool testPolygon45FormationStarHole2(stream_type& stdcout) { stdcout << "testing polygon formation\n"; Polygon45Formation pf(false); std::vector<Polygon45WithHoles> polys; std::vector<Vertex45> data; // result == 0 8 -1 1 data.push_back(Vertex45(Point(0, 8), -1, 1)); // result == 0 8 1 -1 data.push_back(Vertex45(Point(0, 8), 1, -1)); // result == 4 0 1 1 data.push_back(Vertex45(Point(4, 0), 1, 1)); // result == 4 0 2 1 data.push_back(Vertex45(Point(4, 0), 2, 1)); // result == 4 4 2 -1 data.push_back(Vertex45(Point(4, 4), 2, -1)); // result == 4 4 -1 -1 data.push_back(Vertex45(Point(4, 4), -1, -1)); // result == 4 12 1 1 data.push_back(Vertex45(Point(4, 12), 1, 1)); // result == 4 12 2 1 data.push_back(Vertex45(Point(4, 12), 2, 1)); // result == 4 16 2 -1 data.push_back(Vertex45(Point(4, 16), 2, 1)); // result == 4 16 -1 -1 data.push_back(Vertex45(Point(4, 16), -1, -1)); // result == 6 2 1 -1 data.push_back(Vertex45(Point(6, 2), 1, -1)); // result == 6 14 -1 1 data.push_back(Vertex45(Point(6, 14), -1, 1)); // result == 6 2 -1 1 data.push_back(Vertex45(Point(6, 2), -1, 1)); // result == 6 14 1 -1 data.push_back(Vertex45(Point(6, 14), 1, -1)); // result == 8 0 -1 -1 data.push_back(Vertex45(Point(8, 0), -1, -1)); // result == 8 0 2 -1 data.push_back(Vertex45(Point(8, 0), 2, -1)); // result == 8 4 2 1 data.push_back(Vertex45(Point(8, 4), 2, 1)); // result == 8 4 1 1 data.push_back(Vertex45(Point(8, 4), 1, 1)); // result == 8 12 -1 -1 data.push_back(Vertex45(Point(8, 12), -1, -1)); // result == 8 12 2 -1 data.push_back(Vertex45(Point(8, 12), 2, -1)); // result == 8 16 2 1 data.push_back(Vertex45(Point(8, 16), 2, 1)); // result == 8 16 1 1 data.push_back(Vertex45(Point(8, 16), 1, 1)); // result == 12 8 1 -1 data.push_back(Vertex45(Point(12, 8), 1, -1)); // result == 12 8 -1 1 data.push_back(Vertex45(Point(12, 8), -1, 1)); data.push_back(Vertex45(Point(6, 4), 1, -1)); data.push_back(Vertex45(Point(6, 4), 2, -1)); data.push_back(Vertex45(Point(6, 12), -1, 1)); data.push_back(Vertex45(Point(6, 12), 2, 1)); data.push_back(Vertex45(Point(10, 8), -1, -1)); data.push_back(Vertex45(Point(10, 8), 1, 1)); polygon_sort(data.begin(), data.end()); pf.scan(polys, data.begin(), data.end()); stdcout << "result size: " << polys.size() << "\n"; for(std::size_t i = 0; i < polys.size(); ++i) { stdcout << polys[i] << "\n"; } stdcout << "done testing polygon formation\n"; return true; } template <typename stream_type> static inline bool testPolygon45Formation(stream_type& stdcout) { stdcout << "testing polygon formation\n"; Polygon45Formation pf(false); std::vector<Polygon45WithHoles> polys; std::vector<Vertex45> data; data.push_back(Vertex45(Point(0, 0), 0, 1)); data.push_back(Vertex45(Point(0, 0), 2, 1)); data.push_back(Vertex45(Point(0, 100), 2, -1)); data.push_back(Vertex45(Point(0, 100), 0, -1)); data.push_back(Vertex45(Point(100, 0), 0, -1)); data.push_back(Vertex45(Point(100, 0), 2, -1)); data.push_back(Vertex45(Point(100, 100), 2, 1)); data.push_back(Vertex45(Point(100, 100), 0, 1)); data.push_back(Vertex45(Point(2, 2), 0, -1)); data.push_back(Vertex45(Point(2, 2), 2, -1)); data.push_back(Vertex45(Point(2, 10), 2, 1)); data.push_back(Vertex45(Point(2, 10), 0, 1)); data.push_back(Vertex45(Point(10, 2), 0, 1)); data.push_back(Vertex45(Point(10, 2), 2, 1)); data.push_back(Vertex45(Point(10, 10), 2, -1)); data.push_back(Vertex45(Point(10, 10), 0, -1)); data.push_back(Vertex45(Point(2, 12), 0, -1)); data.push_back(Vertex45(Point(2, 12), 2, -1)); data.push_back(Vertex45(Point(2, 22), 2, 1)); data.push_back(Vertex45(Point(2, 22), 0, 1)); data.push_back(Vertex45(Point(10, 12), 0, 1)); data.push_back(Vertex45(Point(10, 12), 2, 1)); data.push_back(Vertex45(Point(10, 22), 2, -1)); data.push_back(Vertex45(Point(10, 22), 0, -1)); polygon_sort(data.begin(), data.end()); pf.scan(polys, data.begin(), data.end()); stdcout << "result size: " << polys.size() << "\n"; for(std::size_t i = 0; i < polys.size(); ++i) { stdcout << polys[i] << "\n"; } stdcout << "done testing polygon formation\n"; return true; } class Polygon45Tiling { private: //definitions typedef std::map<Vertex45, ActiveTail45*, lessVertex45> Polygon45FormationData; typedef typename Polygon45FormationData::iterator iterator; typedef typename Polygon45FormationData::const_iterator const_iterator; //data Polygon45FormationData scanData_; Unit x_; int justBefore_; public: inline Polygon45Tiling() : scanData_(), x_((std::numeric_limits<Unit>::min)()), justBefore_(false) { lessVertex45 lessElm(&x_, &justBefore_); scanData_ = Polygon45FormationData(lessElm); } inline Polygon45Tiling(const Polygon45Tiling& that) : scanData_(), x_((std::numeric_limits<Unit>::min)()), justBefore_(false) { (*this) = that; } inline Polygon45Tiling& operator=(const Polygon45Tiling& that) { x_ = that.x_; justBefore_ = that.justBefore_; lessVertex45 lessElm(&x_, &justBefore_); scanData_ = Polygon45FormationData(lessElm); for(const_iterator itr = that.scanData_.begin(); itr != that.scanData_.end(); ++itr){ scanData_.insert(scanData_.end(), *itr); } return *this; } //cT is an output container of Polygon45 or Polygon45WithHoles //iT is an iterator over Vertex45 elements //inputBegin - inputEnd is a range of sorted iT that represents //one or more scanline stops worth of data template <class cT, class iT> void scan(cT& output, iT inputBegin, iT inputEnd) { //std::cout << "1\n"; while(inputBegin != inputEnd) { //std::cout << "2\n"; x_ = (*inputBegin).pt.x(); //std::cout << "SCAN FORMATION " << x_ << "\n"; //std::cout << "x_ = " << x_ << "\n"; //std::cout << "scan line size: " << scanData_.size() << "\n"; inputBegin = processEvent_(output, inputBegin, inputEnd); } } private: //functions inline void getVerticalPair_(std::pair<ActiveTail45*, ActiveTail45*>& verticalPair, iterator previter) { ActiveTail45* iterTail = (*previter).second; Point prevPoint(x_, previter->first.evalAtX(x_)); iterTail->pushPoint(prevPoint); std::pair<ActiveTail45*, ActiveTail45*> tailPair = ActiveTail45::createActiveTail45sAsPair(prevPoint, true, 0, false); verticalPair.first = iterTail; verticalPair.second = tailPair.first; (*previter).second = tailPair.second; } template <class cT, class cT2> inline std::pair<int, ActiveTail45*> processPoint_(cT& output, cT2& elements, std::pair<ActiveTail45*, ActiveTail45*>& verticalPair, iterator previter, Point point, Vertex45Count& counts, ActiveTail45** tails, Vertex45Count& incoming) { //std::cout << point << "\n"; //std::cout << counts[0] << " "; //std::cout << counts[1] << " "; //std::cout << counts[2] << " "; //std::cout << counts[3] << "\n"; //std::cout << incoming[0] << " "; //std::cout << incoming[1] << " "; //std::cout << incoming[2] << " "; //std::cout << incoming[3] << "\n"; //join any closing solid corners ActiveTail45* returnValue = 0; std::pair<ActiveTail45*, ActiveTail45*> verticalPairOut; verticalPairOut.first = 0; verticalPairOut.second = 0; int returnCount = 0; for(int i = 0; i < 3; ++i) { //std::cout << i << "\n"; if(counts[i] == -1) { //std::cout << "fixed i\n"; for(int j = i + 1; j < 4; ++j) { //std::cout << j << "\n"; if(counts[j]) { if(counts[j] == 1) { //std::cout << "case1: " << i << " " << j << "\n"; //if a figure is closed it will be written out by this function to output ActiveTail45::joinChains(point, tails[i], tails[j], true, output); counts[i] = 0; counts[j] = 0; tails[i] = 0; tails[j] = 0; } break; } } } } //find any pairs of incoming edges that need to create pair for leading solid //std::cout << "checking case2\n"; for(int i = 0; i < 3; ++i) { //std::cout << i << "\n"; if(incoming[i] == 1) { //std::cout << "fixed i\n"; for(int j = i + 1; j < 4; ++j) { //std::cout << j << "\n"; if(incoming[j]) { if(incoming[j] == -1) { //std::cout << "case2: " << i << " " << j << "\n"; //std::cout << "creating active tail pair\n"; std::pair<ActiveTail45*, ActiveTail45*> tailPair = ActiveTail45::createActiveTail45sAsPair(point, true, 0, false); //tailPair.first->print(); //tailPair.second->print(); if(j == 3) { //vertical active tail becomes return value returnValue = tailPair.first; returnCount = 1; } else { Vertex45 vertex(point, i -1, incoming[i]); //std::cout << "new element " << j-1 << " " << -1 << "\n"; elements.push_back(std::pair<Vertex45, ActiveTail45*>(Vertex45(point, j -1, -1), tailPair.first)); } //std::cout << "new element " << i-1 << " " << 1 << "\n"; elements.push_back(std::pair<Vertex45, ActiveTail45*>(Vertex45(point, i -1, 1), tailPair.second)); incoming[i] = 0; incoming[j] = 0; } break; } } } } //find any active tail that needs to pass through to an incoming edge //we expect to find no more than two pass through //find pass through with solid on top //std::cout << "checking case 3\n"; for(int i = 0; i < 4; ++i) { //std::cout << i << "\n"; if(counts[i] != 0) { if(counts[i] == 1) { //std::cout << "fixed i\n"; for(int j = 3; j >= 0; --j) { if(incoming[j] != 0) { if(incoming[j] == 1) { //std::cout << "case3: " << i << " " << j << "\n"; //tails[i]->print(); //pass through solid on top if(i != 3) tails[i]->pushPoint(point); //std::cout << "after push\n"; if(j == 3) { returnValue = tails[i]; returnCount = -1; } else { verticalPairOut.first = tails[i]; std::pair<ActiveTail45*, ActiveTail45*> tailPair = ActiveTail45::createActiveTail45sAsPair(point, true, 0, false); verticalPairOut.second = tailPair.first; elements.push_back(std::pair<Vertex45, ActiveTail45*>(Vertex45(point, j -1, incoming[j]), tailPair.second)); } tails[i] = 0; counts[i] = 0; incoming[j] = 0; } break; } } } break; } } //std::cout << "checking case 4\n"; //find pass through with solid on bottom for(int i = 3; i >= 0; --i) { if(counts[i] != 0) { if(counts[i] == -1) { for(int j = 0; j < 4; ++j) { if(incoming[j] != 0) { if(incoming[j] == -1) { //std::cout << "case4: " << i << " " << j << "\n"; //pass through solid on bottom if(i == 3) { //std::cout << "new element " << j-1 << " " << incoming[j] << "\n"; if(j == 3) { returnValue = tails[i]; returnCount = 1; } else { tails[i]->pushPoint(point); elements.push_back(std::pair<Vertex45, ActiveTail45*>(Vertex45(point, j -1, incoming[j]), tails[i])); } } else if(j == 3) { if(verticalPair.first == 0) { getVerticalPair_(verticalPair, previter); } ActiveTail45::joinChains(point, tails[i], verticalPair.first, true, output); returnValue = verticalPair.second; returnCount = 1; } else { if(verticalPair.first == 0) { getVerticalPair_(verticalPair, previter); } ActiveTail45::joinChains(point, tails[i], verticalPair.first, true, output); verticalPair.second->pushPoint(point); elements.push_back(std::pair<Vertex45, ActiveTail45*>(Vertex45(point, j -1, incoming[j]), verticalPair.second)); } tails[i] = 0; counts[i] = 0; incoming[j] = 0; } break; } } } break; } } //find the end of a hole or the beginning of a hole //find end of a hole for(int i = 0; i < 3; ++i) { if(counts[i] != 0) { for(int j = i+1; j < 4; ++j) { if(counts[j] != 0) { //std::cout << "case5: " << i << " " << j << "\n"; //we are ending a hole and may potentially close a figure and have to handle the hole tails[i]->pushPoint(point); verticalPairOut.first = tails[i]; if(j == 3) { verticalPairOut.second = tails[j]; } else { if(verticalPair.first == 0) { getVerticalPair_(verticalPair, previter); } ActiveTail45::joinChains(point, tails[j], verticalPair.first, true, output); verticalPairOut.second = verticalPair.second; } tails[i] = 0; tails[j] = 0; counts[i] = 0; counts[j] = 0; break; } } break; } } //find beginning of a hole for(int i = 0; i < 3; ++i) { if(incoming[i] != 0) { for(int j = i+1; j < 4; ++j) { if(incoming[j] != 0) { //std::cout << "case6: " << i << " " << j << "\n"; //we are beginning a empty space if(verticalPair.first == 0) { getVerticalPair_(verticalPair, previter); } verticalPair.second->pushPoint(point); if(j == 3) { returnValue = verticalPair.first; returnCount = -1; } else { std::pair<ActiveTail45*, ActiveTail45*> tailPair = ActiveTail45::createActiveTail45sAsPair(point, true, 0, false); //std::cout << "new element " << j-1 << " " << incoming[j] << "\n"; elements.push_back(std::pair<Vertex45, ActiveTail45*>(Vertex45(point, j -1, incoming[j]), tailPair.second)); verticalPairOut.second = tailPair.first; verticalPairOut.first = verticalPair.first; } //std::cout << "new element " << i-1 << " " << incoming[i] << "\n"; elements.push_back(std::pair<Vertex45, ActiveTail45*>(Vertex45(point, i -1, incoming[i]), verticalPair.second)); incoming[i] = 0; incoming[j] = 0; break; } } break; } } verticalPair = verticalPairOut; //assert that verticalPair is either both null, or neither null //assert that returnValue is null if verticalPair is not null //assert that tails, counts and incoming are all null return std::pair<int, ActiveTail45*>(returnCount, returnValue); } template <class cT, class iT> inline iT processEvent_(cT& output, iT inputBegin, iT inputEnd) { //std::cout << "processEvent_\n"; justBefore_ = true; //collect up all elements from the tree that are at the y //values of events in the input queue //create vector of new elements to add into tree ActiveTail45* verticalTail = 0; std::pair<ActiveTail45*, ActiveTail45*> verticalPair; verticalPair.first = 0; verticalPair.second = 0; int verticalCount = 0; iT currentIter = inputBegin; std::vector<iterator> elementIters; std::vector<std::pair<Vertex45, ActiveTail45*> > elements; while(currentIter != inputEnd && currentIter->pt.x() == x_) { //std::cout << "loop\n"; Unit currentY = (*currentIter).pt.y(); iterator iter = lookUp_(currentY); //int counts[4] = {0, 0, 0, 0}; Vertex45Count counts; ActiveTail45* tails[4] = {0, 0, 0, verticalTail}; //std::cout << "finding elements in tree\n"; iterator previter = iter; if(previter != scanData_.end() && previter->first.evalAtX(x_) >= currentY && previter != scanData_.begin()) --previter; while(iter != scanData_.end() && iter->first.evalAtX(x_) == currentY) { //std::cout << "loop2\n"; elementIters.push_back(iter); int index = iter->first.rise + 1; //std::cout << index << " " << iter->first.count << "\n"; counts[index] = iter->first.count; tails[index] = iter->second; ++iter; } //int incoming[4] = {0, 0, 0, 0}; Vertex45Count incoming; //std::cout << "aggregating\n"; do { //std::cout << "loop3\n"; Vertex45Compact currentVertex(*currentIter); incoming += currentVertex.count; ++currentIter; } while(currentIter != inputEnd && currentIter->pt.y() == currentY && currentIter->pt.x() == x_); //now counts and tails have the data from the left and //incoming has the data from the right at this point //cancel out any end points //std::cout << counts[0] << " "; //std::cout << counts[1] << " "; //std::cout << counts[2] << " "; //std::cout << counts[3] << "\n"; //std::cout << incoming[0] << " "; //std::cout << incoming[1] << " "; //std::cout << incoming[2] << " "; //std::cout << incoming[3] << "\n"; if(verticalTail) { counts[3] = -verticalCount; } incoming[3] *= -1; for(unsigned int i = 0; i < 4; ++i) incoming[i] += counts[i]; //std::cout << "calling processPoint_\n"; std::pair<int, ActiveTail45*> result = processPoint_(output, elements, verticalPair, previter, Point(x_, currentY), counts, tails, incoming); verticalCount = result.first; verticalTail = result.second; if(verticalPair.first != 0 && iter != scanData_.end() && (currentIter == inputEnd || currentIter->pt.x() != x_ || currentIter->pt.y() > (*iter).first.evalAtX(x_))) { //splice vertical pair into edge above ActiveTail45* tailabove = (*iter).second; Point point(x_, (*iter).first.evalAtX(x_)); verticalPair.second->pushPoint(point); ActiveTail45::joinChains(point, tailabove, verticalPair.first, true, output); (*iter).second = verticalPair.second; verticalPair.first = 0; verticalPair.second = 0; } } //std::cout << "erasing\n"; //erase all elements from the tree for(typename std::vector<iterator>::iterator iter = elementIters.begin(); iter != elementIters.end(); ++iter) { //std::cout << "erasing loop\n"; scanData_.erase(*iter); } //switch comparison tie breaking policy justBefore_ = false; //add new elements into tree //std::cout << "inserting\n"; for(typename std::vector<std::pair<Vertex45, ActiveTail45*> >::iterator iter = elements.begin(); iter != elements.end(); ++iter) { //std::cout << "inserting loop\n"; scanData_.insert(scanData_.end(), *iter); } //std::cout << "end processEvent\n"; return currentIter; } inline iterator lookUp_(Unit y){ //if just before then we need to look from 1 not -1 return scanData_.lower_bound(Vertex45(Point(x_, y), -1+2*justBefore_, 0)); } }; template <typename stream_type> static inline bool testPolygon45TilingRect(stream_type& stdcout) { stdcout << "testing polygon tiling\n"; Polygon45Tiling pf; std::vector<Polygon45> polys; std::vector<Vertex45> data; data.push_back(Vertex45(Point(0, 0), 0, 1)); data.push_back(Vertex45(Point(0, 0), 2, 1)); data.push_back(Vertex45(Point(0, 10), 2, -1)); data.push_back(Vertex45(Point(0, 10), 0, -1)); data.push_back(Vertex45(Point(10, 0), 0, -1)); data.push_back(Vertex45(Point(10, 0), 2, -1)); data.push_back(Vertex45(Point(10, 10), 2, 1)); data.push_back(Vertex45(Point(10, 10), 0, 1)); polygon_sort(data.begin(), data.end()); pf.scan(polys, data.begin(), data.end()); stdcout << "result size: " << polys.size() << "\n"; for(std::size_t i = 0; i < polys.size(); ++i) { stdcout << polys[i] << "\n"; } stdcout << "done testing polygon tiling\n"; return true; } template <typename stream_type> static inline bool testPolygon45TilingP1(stream_type& stdcout) { stdcout << "testing polygon tiling\n"; Polygon45Tiling pf; std::vector<Polygon45> polys; std::vector<Vertex45> data; data.push_back(Vertex45(Point(0, 0), 1, 1)); data.push_back(Vertex45(Point(0, 0), 2, 1)); data.push_back(Vertex45(Point(0, 10), 2, -1)); data.push_back(Vertex45(Point(0, 10), 1, -1)); data.push_back(Vertex45(Point(10, 10), 1, -1)); data.push_back(Vertex45(Point(10, 10), 2, -1)); data.push_back(Vertex45(Point(10, 20), 2, 1)); data.push_back(Vertex45(Point(10, 20), 1, 1)); polygon_sort(data.begin(), data.end()); pf.scan(polys, data.begin(), data.end()); stdcout << "result size: " << polys.size() << "\n"; for(std::size_t i = 0; i < polys.size(); ++i) { stdcout << polys[i] << "\n"; } stdcout << "done testing polygon tiling\n"; return true; } template <typename stream_type> static inline bool testPolygon45TilingP2(stream_type& stdcout) { stdcout << "testing polygon tiling\n"; Polygon45Tiling pf; std::vector<Polygon45> polys; std::vector<Vertex45> data; data.push_back(Vertex45(Point(0, 0), 0, 1)); data.push_back(Vertex45(Point(0, 0), 1, -1)); data.push_back(Vertex45(Point(10, 0), 0, -1)); data.push_back(Vertex45(Point(10, 0), 1, 1)); data.push_back(Vertex45(Point(10, 10), 1, 1)); data.push_back(Vertex45(Point(10, 10), 0, -1)); data.push_back(Vertex45(Point(20, 10), 1, -1)); data.push_back(Vertex45(Point(20, 10), 0, 1)); polygon_sort(data.begin(), data.end()); pf.scan(polys, data.begin(), data.end()); stdcout << "result size: " << polys.size() << "\n"; for(std::size_t i = 0; i < polys.size(); ++i) { stdcout << polys[i] << "\n"; } stdcout << "done testing polygon tiling\n"; return true; } template <typename stream_type> static inline bool testPolygon45TilingP3(stream_type& stdcout) { stdcout << "testing polygon tiling\n"; Polygon45Tiling pf; std::vector<Polygon45> polys; std::vector<Vertex45> data; data.push_back(Vertex45(Point(0, 0), 0, 1)); data.push_back(Vertex45(Point(0, 0), 2, 1)); data.push_back(Vertex45(Point(0, 10), 2, -1)); data.push_back(Vertex45(Point(0, 10), 0, -1)); data.push_back(Vertex45(Point(20, 0), 0, -1)); data.push_back(Vertex45(Point(20, 0), 2, -1)); data.push_back(Vertex45(Point(10, 10), 1, -1)); data.push_back(Vertex45(Point(10, 10), 0, 1)); data.push_back(Vertex45(Point(20, 20), 1, 1)); data.push_back(Vertex45(Point(20, 20), 2, 1)); polygon_sort(data.begin(), data.end()); pf.scan(polys, data.begin(), data.end()); stdcout << "result size: " << polys.size() << "\n"; for(std::size_t i = 0; i < polys.size(); ++i) { stdcout << polys[i] << "\n"; } stdcout << "done testing polygon tiling\n"; return true; } template <typename stream_type> static inline bool testPolygon45TilingP4(stream_type& stdcout) { stdcout << "testing polygon tiling p4\n"; Polygon45Tiling pf; std::vector<Polygon45> polys; std::vector<Vertex45> data; data.push_back(Vertex45(Point(0, 0), 0, 1)); data.push_back(Vertex45(Point(0, 0), 2, 1)); data.push_back(Vertex45(Point(0, 10), 2, -1)); data.push_back(Vertex45(Point(0, 10), 0, -1)); data.push_back(Vertex45(Point(10, 0), -1, 1)); data.push_back(Vertex45(Point(10, 0), 0, -1)); data.push_back(Vertex45(Point(20, 10), 2, 1)); data.push_back(Vertex45(Point(20, 10), 0, 1)); data.push_back(Vertex45(Point(20, -10), -1, -1)); data.push_back(Vertex45(Point(20, -10), 2, -1)); polygon_sort(data.begin(), data.end()); pf.scan(polys, data.begin(), data.end()); stdcout << "result size: " << polys.size() << "\n"; for(std::size_t i = 0; i < polys.size(); ++i) { stdcout << polys[i] << "\n"; } stdcout << "done testing polygon tiling\n"; return true; } template <typename stream_type> static inline bool testPolygon45TilingP5(stream_type& stdcout) { stdcout << "testing polygon tiling P5\n"; Polygon45Tiling pf; std::vector<Polygon45> polys; std::vector<Vertex45> data; data.push_back(Vertex45(Point(0, 0), 0, 1)); data.push_back(Vertex45(Point(0, 0), 2, 1)); data.push_back(Vertex45(Point(0, 10), 2, -1)); data.push_back(Vertex45(Point(0, 10), 0, -1)); data.push_back(Vertex45(Point(10, 0), 0, -1)); data.push_back(Vertex45(Point(10, 0), 2, -1)); data.push_back(Vertex45(Point(10, 10), 2, 1)); data.push_back(Vertex45(Point(10, 10), 0, 1)); data.push_back(Vertex45(Point(1, 1), 0, -1)); data.push_back(Vertex45(Point(1, 1), 1, 1)); data.push_back(Vertex45(Point(2, 1), 0, 1)); data.push_back(Vertex45(Point(2, 1), 1, -1)); data.push_back(Vertex45(Point(2, 2), 1, -1)); data.push_back(Vertex45(Point(2, 2), 0, 1)); data.push_back(Vertex45(Point(3, 2), 1, 1)); data.push_back(Vertex45(Point(3, 2), 0, -1)); polygon_sort(data.begin(), data.end()); pf.scan(polys, data.begin(), data.end()); stdcout << "result size: " << polys.size() << "\n"; for(std::size_t i = 0; i < polys.size(); ++i) { stdcout << polys[i] << "\n"; } stdcout << "done testing polygon tiling\n"; return true; } template <typename stream_type> static inline bool testPolygon45TilingP6(stream_type& stdcout) { stdcout << "testing polygon tiling P6\n"; Polygon45Tiling pf; std::vector<Polygon45> polys; std::vector<Vertex45> data; data.push_back(Vertex45(Point(0, 0), 0, 1)); data.push_back(Vertex45(Point(0, 0), 2, 1)); data.push_back(Vertex45(Point(0, 10), 2, -1)); data.push_back(Vertex45(Point(0, 10), 0, -1)); data.push_back(Vertex45(Point(10, 0), 0, -1)); data.push_back(Vertex45(Point(10, 0), 2, -1)); data.push_back(Vertex45(Point(10, 10), 2, 1)); data.push_back(Vertex45(Point(10, 10), 0, 1)); data.push_back(Vertex45(Point(1, 1), 0, -1)); data.push_back(Vertex45(Point(1, 1), 2, -1)); data.push_back(Vertex45(Point(1, 2), 2, 1)); data.push_back(Vertex45(Point(1, 2), 0, 1)); data.push_back(Vertex45(Point(2, 1), 0, 1)); data.push_back(Vertex45(Point(2, 1), 2, 1)); data.push_back(Vertex45(Point(2, 2), 2, -1)); data.push_back(Vertex45(Point(2, 2), 0, -1)); polygon_sort(data.begin(), data.end()); pf.scan(polys, data.begin(), data.end()); stdcout << "result size: " << polys.size() << "\n"; for(std::size_t i = 0; i < polys.size(); ++i) { stdcout << polys[i] << "\n"; } stdcout << "done testing polygon tiling\n"; return true; } template <typename stream_type> static inline bool testPolygon45TilingStar1(stream_type& stdcout) { stdcout << "testing polygon tiling star1\n"; Polygon45Tiling pf; std::vector<Polygon45> polys; std::vector<Vertex45> data; // result == 0 8 -1 1 data.push_back(Vertex45(Point(0, 8), -1, 1)); // result == 0 8 1 -1 data.push_back(Vertex45(Point(0, 8), 1, -1)); // result == 4 0 1 1 data.push_back(Vertex45(Point(4, 0), 1, 1)); // result == 4 0 2 1 data.push_back(Vertex45(Point(4, 0), 2, 1)); // result == 4 4 2 -1 data.push_back(Vertex45(Point(4, 4), 2, -1)); // result == 4 4 -1 -1 data.push_back(Vertex45(Point(4, 4), -1, -1)); // result == 4 12 1 1 data.push_back(Vertex45(Point(4, 12), 1, 1)); // result == 4 12 2 1 data.push_back(Vertex45(Point(4, 12), 2, 1)); // result == 4 16 2 -1 data.push_back(Vertex45(Point(4, 16), 2, 1)); // result == 4 16 -1 -1 data.push_back(Vertex45(Point(4, 16), -1, -1)); // result == 6 2 1 -1 data.push_back(Vertex45(Point(6, 2), 1, -1)); // result == 6 14 -1 1 data.push_back(Vertex45(Point(6, 14), -1, 1)); // result == 6 2 -1 1 data.push_back(Vertex45(Point(6, 2), -1, 1)); // result == 6 14 1 -1 data.push_back(Vertex45(Point(6, 14), 1, -1)); // result == 8 0 -1 -1 data.push_back(Vertex45(Point(8, 0), -1, -1)); // result == 8 0 2 -1 data.push_back(Vertex45(Point(8, 0), 2, -1)); // result == 8 4 2 1 data.push_back(Vertex45(Point(8, 4), 2, 1)); // result == 8 4 1 1 data.push_back(Vertex45(Point(8, 4), 1, 1)); // result == 8 12 -1 -1 data.push_back(Vertex45(Point(8, 12), -1, -1)); // result == 8 12 2 -1 data.push_back(Vertex45(Point(8, 12), 2, -1)); // result == 8 16 2 1 data.push_back(Vertex45(Point(8, 16), 2, 1)); // result == 8 16 1 1 data.push_back(Vertex45(Point(8, 16), 1, 1)); // result == 12 8 1 -1 data.push_back(Vertex45(Point(12, 8), 1, -1)); // result == 12 8 -1 1 data.push_back(Vertex45(Point(12, 8), -1, 1)); polygon_sort(data.begin(), data.end()); pf.scan(polys, data.begin(), data.end()); stdcout << "result size: " << polys.size() << "\n"; for(std::size_t i = 0; i < polys.size(); ++i) { stdcout << polys[i] << "\n"; } stdcout << "done testing polygon tiling\n"; return true; } template <typename stream_type> static inline bool testPolygon45TilingStar2(stream_type& stdcout) { stdcout << "testing polygon tiling\n"; Polygon45Tiling pf; std::vector<Polygon45> polys; Scan45 scan45; std::vector<Vertex45 > result; std::vector<Scan45Vertex> vertices; //is a Rectnagle(0, 0, 10, 10); Count2 count(1, 0); Count2 ncount(-1, 0); vertices.push_back(Scan45Vertex(Point(0,4), Scan45Count(Count2(0, 0), count, ncount, Count2(0, 0)))); vertices.push_back(Scan45Vertex(Point(16,4), Scan45Count(count, ncount, Count2(0, 0), Count2(0, 0)))); vertices.push_back(Scan45Vertex(Point(8,12), Scan45Count(ncount, Count2(0, 0), count, Count2(0, 0)))); count = Count2(0, 1); ncount = count.invert(); vertices.push_back(Scan45Vertex(Point(0,8), Scan45Count(count, ncount, Count2(0, 0), Count2(0, 0)))); vertices.push_back(Scan45Vertex(Point(16,8), Scan45Count(Count2(0, 0), count, ncount, Count2(0, 0)))); vertices.push_back(Scan45Vertex(Point(8,0), Scan45Count(ncount, Count2(0, 0), count, Count2(0, 0)))); sortScan45Vector(vertices); stdcout << "scanning\n"; scan45.scan(result, vertices.begin(), vertices.end()); polygon_sort(result.begin(), result.end()); pf.scan(polys, result.begin(), result.end()); stdcout << "result size: " << polys.size() << "\n"; for(std::size_t i = 0; i < polys.size(); ++i) { stdcout << polys[i] << "\n"; } stdcout << "done testing polygon tiling\n"; return true; } template <typename stream_type> static inline bool testPolygon45TilingStarHole1(stream_type& stdcout) { stdcout << "testing polygon tiling star hole 1\n"; Polygon45Tiling pf; std::vector<Polygon45> polys; std::vector<Vertex45> data; // result == 0 8 -1 1 data.push_back(Vertex45(Point(0, 8), -1, 1)); // result == 0 8 1 -1 data.push_back(Vertex45(Point(0, 8), 1, -1)); // result == 4 0 1 1 data.push_back(Vertex45(Point(4, 0), 1, 1)); // result == 4 0 2 1 data.push_back(Vertex45(Point(4, 0), 2, 1)); // result == 4 4 2 -1 data.push_back(Vertex45(Point(4, 4), 2, -1)); // result == 4 4 -1 -1 data.push_back(Vertex45(Point(4, 4), -1, -1)); // result == 4 12 1 1 data.push_back(Vertex45(Point(4, 12), 1, 1)); // result == 4 12 2 1 data.push_back(Vertex45(Point(4, 12), 2, 1)); // result == 4 16 2 -1 data.push_back(Vertex45(Point(4, 16), 2, 1)); // result == 4 16 -1 -1 data.push_back(Vertex45(Point(4, 16), -1, -1)); // result == 6 2 1 -1 data.push_back(Vertex45(Point(6, 2), 1, -1)); // result == 6 14 -1 1 data.push_back(Vertex45(Point(6, 14), -1, 1)); // result == 6 2 -1 1 data.push_back(Vertex45(Point(6, 2), -1, 1)); // result == 6 14 1 -1 data.push_back(Vertex45(Point(6, 14), 1, -1)); // result == 8 0 -1 -1 data.push_back(Vertex45(Point(8, 0), -1, -1)); // result == 8 0 2 -1 data.push_back(Vertex45(Point(8, 0), 2, -1)); // result == 8 4 2 1 data.push_back(Vertex45(Point(8, 4), 2, 1)); // result == 8 4 1 1 data.push_back(Vertex45(Point(8, 4), 1, 1)); // result == 8 12 -1 -1 data.push_back(Vertex45(Point(8, 12), -1, -1)); // result == 8 12 2 -1 data.push_back(Vertex45(Point(8, 12), 2, -1)); // result == 8 16 2 1 data.push_back(Vertex45(Point(8, 16), 2, 1)); // result == 8 16 1 1 data.push_back(Vertex45(Point(8, 16), 1, 1)); // result == 12 8 1 -1 data.push_back(Vertex45(Point(12, 8), 1, -1)); // result == 12 8 -1 1 data.push_back(Vertex45(Point(12, 8), -1, 1)); data.push_back(Vertex45(Point(6, 4), 1, -1)); data.push_back(Vertex45(Point(6, 4), 2, -1)); data.push_back(Vertex45(Point(6, 8), -1, 1)); data.push_back(Vertex45(Point(6, 8), 2, 1)); data.push_back(Vertex45(Point(8, 6), -1, -1)); data.push_back(Vertex45(Point(8, 6), 1, 1)); polygon_sort(data.begin(), data.end()); pf.scan(polys, data.begin(), data.end()); stdcout << "result size: " << polys.size() << "\n"; for(std::size_t i = 0; i < polys.size(); ++i) { stdcout << polys[i] << "\n"; } stdcout << "done testing polygon tiling\n"; return true; } template <typename stream_type> static inline bool testPolygon45TilingStarHole2(stream_type& stdcout) { stdcout << "testing polygon tiling star hole 2\n"; Polygon45Tiling pf; std::vector<Polygon45WithHoles> polys; std::vector<Vertex45> data; // result == 0 8 -1 1 data.push_back(Vertex45(Point(0, 8), -1, 1)); // result == 0 8 1 -1 data.push_back(Vertex45(Point(0, 8), 1, -1)); // result == 4 0 1 1 data.push_back(Vertex45(Point(4, 0), 1, 1)); // result == 4 0 2 1 data.push_back(Vertex45(Point(4, 0), 2, 1)); // result == 4 4 2 -1 data.push_back(Vertex45(Point(4, 4), 2, -1)); // result == 4 4 -1 -1 data.push_back(Vertex45(Point(4, 4), -1, -1)); // result == 4 12 1 1 data.push_back(Vertex45(Point(4, 12), 1, 1)); // result == 4 12 2 1 data.push_back(Vertex45(Point(4, 12), 2, 1)); // result == 4 16 2 -1 data.push_back(Vertex45(Point(4, 16), 2, 1)); // result == 4 16 -1 -1 data.push_back(Vertex45(Point(4, 16), -1, -1)); // result == 6 2 1 -1 data.push_back(Vertex45(Point(6, 2), 1, -1)); // result == 6 14 -1 1 data.push_back(Vertex45(Point(6, 14), -1, 1)); // result == 6 2 -1 1 data.push_back(Vertex45(Point(6, 2), -1, 1)); // result == 6 14 1 -1 data.push_back(Vertex45(Point(6, 14), 1, -1)); // result == 8 0 -1 -1 data.push_back(Vertex45(Point(8, 0), -1, -1)); // result == 8 0 2 -1 data.push_back(Vertex45(Point(8, 0), 2, -1)); // result == 8 4 2 1 data.push_back(Vertex45(Point(8, 4), 2, 1)); // result == 8 4 1 1 data.push_back(Vertex45(Point(8, 4), 1, 1)); // result == 8 12 -1 -1 data.push_back(Vertex45(Point(8, 12), -1, -1)); // result == 8 12 2 -1 data.push_back(Vertex45(Point(8, 12), 2, -1)); // result == 8 16 2 1 data.push_back(Vertex45(Point(8, 16), 2, 1)); // result == 8 16 1 1 data.push_back(Vertex45(Point(8, 16), 1, 1)); // result == 12 8 1 -1 data.push_back(Vertex45(Point(12, 8), 1, -1)); // result == 12 8 -1 1 data.push_back(Vertex45(Point(12, 8), -1, 1)); data.push_back(Vertex45(Point(6, 4), 1, -1)); data.push_back(Vertex45(Point(6, 4), 2, -1)); data.push_back(Vertex45(Point(6, 12), -1, 1)); data.push_back(Vertex45(Point(6, 12), 2, 1)); data.push_back(Vertex45(Point(10, 8), -1, -1)); data.push_back(Vertex45(Point(10, 8), 1, 1)); polygon_sort(data.begin(), data.end()); pf.scan(polys, data.begin(), data.end()); stdcout << "result size: " << polys.size() << "\n"; for(std::size_t i = 0; i < polys.size(); ++i) { stdcout << polys[i] << "\n"; } stdcout << "done testing polygon tiling\n"; return true; } template <typename stream_type> static inline bool testPolygon45Tiling(stream_type& stdcout) { stdcout << "testing polygon tiling\n"; Polygon45Tiling pf; std::vector<Polygon45WithHoles> polys; std::vector<Vertex45> data; data.push_back(Vertex45(Point(0, 0), 0, 1)); data.push_back(Vertex45(Point(0, 0), 2, 1)); data.push_back(Vertex45(Point(0, 100), 2, -1)); data.push_back(Vertex45(Point(0, 100), 0, -1)); data.push_back(Vertex45(Point(100, 0), 0, -1)); data.push_back(Vertex45(Point(100, 0), 2, -1)); data.push_back(Vertex45(Point(100, 100), 2, 1)); data.push_back(Vertex45(Point(100, 100), 0, 1)); data.push_back(Vertex45(Point(2, 2), 0, -1)); data.push_back(Vertex45(Point(2, 2), 2, -1)); data.push_back(Vertex45(Point(2, 10), 2, 1)); data.push_back(Vertex45(Point(2, 10), 0, 1)); data.push_back(Vertex45(Point(10, 2), 0, 1)); data.push_back(Vertex45(Point(10, 2), 2, 1)); data.push_back(Vertex45(Point(10, 10), 2, -1)); data.push_back(Vertex45(Point(10, 10), 0, -1)); data.push_back(Vertex45(Point(2, 12), 0, -1)); data.push_back(Vertex45(Point(2, 12), 2, -1)); data.push_back(Vertex45(Point(2, 22), 2, 1)); data.push_back(Vertex45(Point(2, 22), 0, 1)); data.push_back(Vertex45(Point(10, 12), 0, 1)); data.push_back(Vertex45(Point(10, 12), 2, 1)); data.push_back(Vertex45(Point(10, 22), 2, -1)); data.push_back(Vertex45(Point(10, 22), 0, -1)); polygon_sort(data.begin(), data.end()); pf.scan(polys, data.begin(), data.end()); stdcout << "result size: " << polys.size() << "\n"; for(std::size_t i = 0; i < polys.size(); ++i) { stdcout << polys[i] << "\n"; } stdcout << "done testing polygon tiling\n"; return true; } }; template <typename Unit> class PolyLine45HoleData { public: typedef typename polygon_45_formation<Unit>::ActiveTail45 ActiveTail45; typedef typename ActiveTail45::iterator iterator; typedef polygon_45_concept geometry_type; typedef Unit coordinate_type; typedef point_data<Unit> Point; typedef Point point_type; // typedef iterator_points_to_compact<iterator, Point> compact_iterator_type; typedef iterator iterator_type; typedef typename coordinate_traits<Unit>::area_type area_type; inline PolyLine45HoleData() : p_(0) {} inline PolyLine45HoleData(ActiveTail45* p) : p_(p) {} //use default copy and assign inline iterator begin() const { return p_->getTail()->begin(); } inline iterator end() const { return p_->getTail()->end(); } inline std::size_t size() const { return 0; } private: ActiveTail45* p_; }; template <typename Unit> class PolyLine45PolygonData { public: typedef typename polygon_45_formation<Unit>::ActiveTail45 ActiveTail45; typedef typename ActiveTail45::iterator iterator; typedef PolyLine45HoleData<Unit> holeType; typedef polygon_45_with_holes_concept geometry_type; typedef Unit coordinate_type; typedef point_data<Unit> Point; typedef Point point_type; // typedef iterator_points_to_compact<iterator, Point> compact_iterator_type; typedef iterator iterator_type; typedef holeType hole_type; typedef typename coordinate_traits<Unit>::area_type area_type; class iteratorHoles { private: typename ActiveTail45::iteratorHoles itr_; public: typedef PolyLine45HoleData<Unit> holeType; typedef holeType value_type; typedef std::forward_iterator_tag iterator_category; typedef std::ptrdiff_t difference_type; typedef const value_type* pointer; //immutable typedef const value_type& reference; //immutable inline iteratorHoles() : itr_() {} inline iteratorHoles(typename ActiveTail45::iteratorHoles itr) : itr_(itr) {} inline iteratorHoles(const iteratorHoles& that) : itr_(that.itr_) {} inline iteratorHoles& operator=(const iteratorHoles& that) { itr_ = that.itr_; return *this; } inline bool operator==(const iteratorHoles& that) { return itr_ == that.itr_; } inline bool operator!=(const iteratorHoles& that) { return itr_ != that.itr_; } inline iteratorHoles& operator++() { ++itr_; return *this; } inline const iteratorHoles operator++(int) { iteratorHoles tmp = *this; ++(*this); return tmp; } inline holeType operator*() { return *itr_; } }; typedef iteratorHoles iterator_holes_type; inline PolyLine45PolygonData() : p_(0) {} inline PolyLine45PolygonData(ActiveTail45* p) : p_(p) {} //use default copy and assign inline iterator begin() const { return p_->getTail()->begin(); } inline iterator end() const { return p_->getTail()->end(); } inline iteratorHoles begin_holes() const { return iteratorHoles(p_->getHoles().begin()); } inline iteratorHoles end_holes() const { return iteratorHoles(p_->getHoles().end()); } inline ActiveTail45* yield() { return p_; } //stub out these four required functions that will not be used but are needed for the interface inline std::size_t size_holes() const { return 0; } inline std::size_t size() const { return 0; } private: ActiveTail45* p_; }; template <typename T> struct PolyLineByConcept<T, polygon_45_with_holes_concept> { typedef PolyLine45PolygonData<T> type; }; template <typename T> struct PolyLineByConcept<T, polygon_with_holes_concept> { typedef PolyLine45PolygonData<T> type; }; template <typename T> struct PolyLineByConcept<T, polygon_45_concept> { typedef PolyLine45HoleData<T> type; }; template <typename T> struct PolyLineByConcept<T, polygon_concept> { typedef PolyLine45HoleData<T> type; }; template <typename T> struct geometry_concept<PolyLine45PolygonData<T> > { typedef polygon_45_with_holes_concept type; }; template <typename T> struct geometry_concept<PolyLine45HoleData<T> > { typedef polygon_45_concept type; }; } } #endif PK �b�[��j�O O detail/minkowski.hppnu �[��� /* Copyright 2008 Intel Corporation Use, modification and distribution are 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). */ namespace boost { namespace polygon { namespace detail { template <typename coordinate_type> struct minkowski_offset { typedef point_data<coordinate_type> point; typedef polygon_set_data<coordinate_type> polygon_set; typedef polygon_with_holes_data<coordinate_type> polygon; typedef std::pair<point, point> edge; static void convolve_two_segments(std::vector<point>& figure, const edge& a, const edge& b) { figure.clear(); figure.push_back(point(a.first)); figure.push_back(point(a.first)); figure.push_back(point(a.second)); figure.push_back(point(a.second)); convolve(figure[0], b.second); convolve(figure[1], b.first); convolve(figure[2], b.first); convolve(figure[3], b.second); } template <typename itrT1, typename itrT2> static void convolve_two_point_sequences(polygon_set& result, itrT1 ab, itrT1 ae, itrT2 bb, itrT2 be) { if(ab == ae || bb == be) return; point first_a = *ab; point prev_a = *ab; std::vector<point> vec; polygon poly; ++ab; for( ; ab != ae; ++ab) { point first_b = *bb; point prev_b = *bb; itrT2 tmpb = bb; ++tmpb; for( ; tmpb != be; ++tmpb) { convolve_two_segments(vec, std::make_pair(prev_b, *tmpb), std::make_pair(prev_a, *ab)); set_points(poly, vec.begin(), vec.end()); result.insert(poly); prev_b = *tmpb; } prev_a = *ab; } } template <typename itrT> static void convolve_point_sequence_with_polygons(polygon_set& result, itrT b, itrT e, const std::vector<polygon>& polygons) { for(std::size_t i = 0; i < polygons.size(); ++i) { convolve_two_point_sequences(result, b, e, begin_points(polygons[i]), end_points(polygons[i])); for(typename polygon_with_holes_traits<polygon>::iterator_holes_type itrh = begin_holes(polygons[i]); itrh != end_holes(polygons[i]); ++itrh) { convolve_two_point_sequences(result, b, e, begin_points(*itrh), end_points(*itrh)); } } } static void convolve_two_polygon_sets(polygon_set& result, const polygon_set& a, const polygon_set& b) { result.clear(); std::vector<polygon> a_polygons; std::vector<polygon> b_polygons; a.get(a_polygons); b.get(b_polygons); for(std::size_t ai = 0; ai < a_polygons.size(); ++ai) { convolve_point_sequence_with_polygons(result, begin_points(a_polygons[ai]), end_points(a_polygons[ai]), b_polygons); for(typename polygon_with_holes_traits<polygon>::iterator_holes_type itrh = begin_holes(a_polygons[ai]); itrh != end_holes(a_polygons[ai]); ++itrh) { convolve_point_sequence_with_polygons(result, begin_points(*itrh), end_points(*itrh), b_polygons); } for(std::size_t bi = 0; bi < b_polygons.size(); ++bi) { polygon tmp_poly = a_polygons[ai]; result.insert(convolve(tmp_poly, *(begin_points(b_polygons[bi])))); tmp_poly = b_polygons[bi]; result.insert(convolve(tmp_poly, *(begin_points(a_polygons[ai])))); } } } }; } template<typename T> inline polygon_set_data<T>& polygon_set_data<T>::resize(coordinate_type resizing, bool corner_fill_arc, unsigned int num_circle_segments) { using namespace ::boost::polygon::operators; if(!corner_fill_arc) { if(resizing < 0) return shrink(-resizing); if(resizing > 0) return bloat(resizing); return *this; } if(resizing == 0) return *this; if(empty()) return *this; if(num_circle_segments < 3) num_circle_segments = 4; rectangle_data<coordinate_type> rect; extents(rect); if(resizing < 0) { ::boost::polygon::bloat(rect, 10); (*this) = rect - (*this); //invert } //make_arc(std::vector<point_data< T> >& return_points, //point_data< double> start, point_data< double> end, //point_data< double> center, double r, unsigned int num_circle_segments) std::vector<point_data<coordinate_type> > circle; point_data<double> center(0.0, 0.0), start(0.0, (double)resizing); make_arc(circle, start, start, center, std::abs((double)resizing), num_circle_segments); polygon_data<coordinate_type> poly; set_points(poly, circle.begin(), circle.end()); polygon_set_data<coordinate_type> offset_set; offset_set += poly; polygon_set_data<coordinate_type> result; detail::minkowski_offset<coordinate_type>::convolve_two_polygon_sets (result, *this, offset_set); if(resizing < 0) { result = result & rect;//eliminate overhang result = result ^ rect;//invert } *this = result; return *this; } }} PK �b�[,���b b detail/polygon_simplify.hppnu �[��� // Copyright 2011, Andrew Ross // // Use, modification and distribution are 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_POLYGON_DETAIL_SIMPLIFY_HPP #define BOOST_POLYGON_DETAIL_SIMPLIFY_HPP #include <vector> namespace boost { namespace polygon { namespace detail { namespace simplify_detail { // Does a simplification/optimization pass on the polygon. If a given // vertex lies within "len" of the line segment joining its neighbor // vertices, it is removed. template <typename T> //T is a model of point concept std::size_t simplify(std::vector<T>& dst, const std::vector<T>& src, typename coordinate_traits< typename point_traits<T>::coordinate_type >::coordinate_distance len) { using namespace boost::polygon; typedef typename point_traits<T>::coordinate_type coordinate_type; typedef typename coordinate_traits<coordinate_type>::area_type ftype; typedef typename std::vector<T>::const_iterator iter; std::vector<T> out; out.reserve(src.size()); dst = src; std::size_t final_result = 0; std::size_t orig_size = src.size(); //I can't use == if T doesn't provide it, so use generic point concept compare bool closed = equivalence(src.front(), src.back()); //we need to keep smoothing until we don't find points to remove //because removing points in the first iteration through the //polygon may leave it in a state where more removal is possible bool not_done = true; while(not_done) { if(dst.size() < 3) { dst.clear(); return orig_size; } // Start with the second, test for the last point // explicitly, and exit after looping back around to the first. ftype len2 = ftype(len) * ftype(len); for(iter prev=dst.begin(), i=prev+1, next; /**/; i = next) { next = i+1; if(next == dst.end()) next = dst.begin(); // points A, B, C ftype ax = x(*prev), ay = y(*prev); ftype bx = x(*i), by = y(*i); ftype cx = x(*next), cy = y(*next); // vectors AB, BC and AC: ftype abx = bx-ax, aby = by-ay; ftype bcx = cx-bx, bcy = cy-by; ftype acx = cx-ax, acy = cy-ay; // dot products ftype ab_ab = abx*abx + aby*aby; ftype bc_bc = bcx*bcx + bcy*bcy; ftype ac_ac = acx*acx + acy*acy; ftype ab_ac = abx*acx + aby*acy; // projection of AB along AC ftype projf = ab_ac / ac_ac; ftype projx = acx * projf, projy = acy * projf; // perpendicular vector from the line AC to point B (i.e. AB - proj) ftype perpx = abx - projx, perpy = aby - projy; // Squared fractional distance of projection. FIXME: can // remove this division, the decisions below can be made with // just the sign of the quotient and a check to see if // abs(numerator) is greater than abs(divisor). ftype f2 = (projx*acx + projy*acx) / ac_ac; // Square of the relevant distance from point B: ftype dist2; if (f2 < 0) dist2 = ab_ab; else if(f2 > 1) dist2 = bc_bc; else dist2 = perpx*perpx + perpy*perpy; if(dist2 > len2) { prev = i; // bump prev, we didn't remove the segment out.push_back(*i); } if(i == dst.begin()) break; } std::size_t result = dst.size() - out.size(); if(result == 0) { not_done = false; } else { final_result += result; dst = out; out.clear(); } } //end of while loop if(closed) { //if the input was closed we want the output to be closed --final_result; dst.push_back(dst.front()); } return final_result; } }}}} #endif PK �b�[Ġ�t- t- detail/max_cover.hppnu �[��� /* Copyright 2008 Intel Corporation Use, modification and distribution are 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_POLYGON_MAX_COVER_HPP #define BOOST_POLYGON_MAX_COVER_HPP namespace boost { namespace polygon{ template <typename Unit> struct MaxCover { typedef interval_data<Unit> Interval; typedef rectangle_data<Unit> Rectangle; class Node { private: std::vector<Node*> children_; std::set<Interval> tracedPaths_; public: Rectangle rect; Node() : children_(), tracedPaths_(), rect() {} Node(const Rectangle rectIn) : children_(), tracedPaths_(), rect(rectIn) {} typedef typename std::vector<Node*>::iterator iterator; inline iterator begin() { return children_.begin(); } inline iterator end() { return children_.end(); } inline void add(Node* child) { children_.push_back(child); } inline bool tracedPath(const Interval& ivl) const { return tracedPaths_.find(ivl) != tracedPaths_.end(); } inline void addPath(const Interval& ivl) { tracedPaths_.insert(tracedPaths_.end(), ivl); } }; typedef std::pair<std::pair<Unit, Interval>, Node* > EdgeAssociation; class lessEdgeAssociation { public: typedef const EdgeAssociation& first_argument_type; typedef const EdgeAssociation& second_argument_type; typedef bool result_type; inline lessEdgeAssociation() {} inline bool operator () (const EdgeAssociation& elem1, const EdgeAssociation& elem2) const { if(elem1.first.first < elem2.first.first) return true; if(elem1.first.first > elem2.first.first) return false; return elem1.first.second < elem2.first.second; } }; template <class cT> static inline void getMaxCover(cT& outputContainer, Node* node, orientation_2d orient) { Interval rectIvl = node->rect.get(orient); if(node->tracedPath(rectIvl)) { return; } node->addPath(rectIvl); if(node->begin() == node->end()) { //std::cout << "WRITE OUT 3: " << node->rect << std::endl; outputContainer.push_back(copy_construct<typename cT::value_type, Rectangle>(node->rect)); return; } bool writeOut = true; for(typename Node::iterator itr = node->begin(); itr != node->end(); ++itr) { getMaxCover(outputContainer, *itr, orient, node->rect); //get rectangles down path Interval nodeIvl = (*itr)->rect.get(orient); if(contains(nodeIvl, rectIvl, true)) writeOut = false; } if(writeOut) { //std::cout << "WRITE OUT 2: " << node->rect << std::endl; outputContainer.push_back(copy_construct<typename cT::value_type, Rectangle>(node->rect)); } } struct stack_element { inline stack_element() : node(), rect(), itr() {} inline stack_element(Node* n, const Rectangle& r, typename Node::iterator i) : node(n), rect(r), itr(i) {} Node* node; Rectangle rect; typename Node::iterator itr; }; template <class cT> static inline void getMaxCover(cT& outputContainer, Node* node, orientation_2d orient, Rectangle rect) { //std::cout << "New Root\n"; std::vector<stack_element> stack; typename Node::iterator itr = node->begin(); do { //std::cout << "LOOP\n"; //std::cout << node->rect << std::endl; Interval rectIvl = rect.get(orient); Interval nodeIvl = node->rect.get(orient); bool iresult = intersect(rectIvl, nodeIvl, false); bool tresult = !node->tracedPath(rectIvl); //std::cout << (itr != node->end()) << " " << iresult << " " << tresult << std::endl; Rectangle nextRect1 = Rectangle(rectIvl, rectIvl); Unit low = rect.get(orient.get_perpendicular()).low(); Unit high = node->rect.get(orient.get_perpendicular()).high(); nextRect1.set(orient.get_perpendicular(), Interval(low, high)); if(iresult && tresult) { node->addPath(rectIvl); bool writeOut = true; //check further visibility beyond this node for(typename Node::iterator itr2 = node->begin(); itr2 != node->end(); ++itr2) { Interval nodeIvl3 = (*itr2)->rect.get(orient); //if a child of this node can contain the interval then we can extend through if(contains(nodeIvl3, rectIvl, true)) writeOut = false; //std::cout << "child " << (*itr2)->rect << std::endl; } Rectangle nextRect2 = Rectangle(rectIvl, rectIvl); Unit low2 = rect.get(orient.get_perpendicular()).low(); Unit high2 = node->rect.get(orient.get_perpendicular()).high(); nextRect2.set(orient.get_perpendicular(), Interval(low2, high2)); if(writeOut) { //std::cout << "write out " << nextRect << std::endl; outputContainer.push_back(copy_construct<typename cT::value_type, Rectangle>(nextRect2)); } else { //std::cout << "suppress " << nextRect << std::endl; } } if(itr != node->end() && iresult && tresult) { //std::cout << "recurse into child\n"; stack.push_back(stack_element(node, rect, itr)); rect = nextRect1; node = *itr; itr = node->begin(); } else { if(!stack.empty()) { //std::cout << "recurse out of child\n"; node = stack.back().node; rect = stack.back().rect; itr = stack.back().itr; stack.pop_back(); } else { //std::cout << "empty stack\n"; //if there were no children of the root node // Rectangle nextRect = Rectangle(rectIvl, rectIvl); // Unit low = rect.get(orient.get_perpendicular()).low(); // Unit high = node->rect.get(orient.get_perpendicular()).high(); // nextRect.set(orient.get_perpendicular(), Interval(low, high)); // outputContainer.push_back(copy_construct<typename cT::value_type, Rectangle>(nextRect)); } //std::cout << "increment " << (itr != node->end()) << std::endl; if(itr != node->end()) { ++itr; if(itr != node->end()) { //std::cout << "recurse into next child.\n"; stack.push_back(stack_element(node, rect, itr)); Interval rectIvl2 = rect.get(orient); Interval nodeIvl2 = node->rect.get(orient); /*bool iresult =*/ intersect(rectIvl2, nodeIvl2, false); Rectangle nextRect2 = Rectangle(rectIvl2, rectIvl2); Unit low2 = rect.get(orient.get_perpendicular()).low(); Unit high2 = node->rect.get(orient.get_perpendicular()).high(); nextRect2.set(orient.get_perpendicular(), Interval(low2, high2)); rect = nextRect2; //std::cout << "rect for next child" << rect << std::endl; node = *itr; itr = node->begin(); } } } } while(!stack.empty() || itr != node->end()); } /* Function recursive version of getMaxCover Because the code is so much simpler than the loop algorithm I retain it for clarity template <class cT> static inline void getMaxCover(cT& outputContainer, Node* node, orientation_2d orient, const Rectangle& rect) { Interval rectIvl = rect.get(orient); Interval nodeIvl = node->rect.get(orient); if(!intersect(rectIvl, nodeIvl, false)) { return; } if(node->tracedPath(rectIvl)) { return; } node->addPath(rectIvl); Rectangle nextRect(rectIvl, rectIvl); Unit low = rect.get(orient.get_perpendicular()).low(); Unit high = node->rect.get(orient.get_perpendicular()).high(); nextRect.set(orient.get_perpendicular(), Interval(low, high)); bool writeOut = true; rectIvl = nextRect.get(orient); for(typename Node::iterator itr = node->begin(); itr != node->end(); ++itr) { nodeIvl = (*itr)->rect.get(orient); if(contains(nodeIvl, rectIvl, true)) writeOut = false; } if(writeOut) { outputContainer.push_back(copy_construct<typename cT::value_type, Rectangle>(nextRect)); } for(typename Node::iterator itr = node->begin(); itr != node->end(); ++itr) { getMaxCover(outputContainer, *itr, orient, nextRect); } } */ //iterator range is assummed to be in topological order meaning all node's trailing //edges are in sorted order template <class iT> static inline void computeDag(iT beginNode, iT endNode, orientation_2d orient, std::size_t size) { std::vector<EdgeAssociation> leadingEdges; leadingEdges.reserve(size); for(iT iter = beginNode; iter != endNode; ++iter) { Node* nodep = &(*iter); Unit leading = nodep->rect.get(orient.get_perpendicular()).low(); Interval rectIvl = nodep->rect.get(orient); leadingEdges.push_back(EdgeAssociation(std::pair<Unit, Interval>(leading, rectIvl), nodep)); } polygon_sort(leadingEdges.begin(), leadingEdges.end(), lessEdgeAssociation()); typename std::vector<EdgeAssociation>::iterator leadingBegin = leadingEdges.begin(); iT trailingBegin = beginNode; while(leadingBegin != leadingEdges.end()) { EdgeAssociation& leadingSegment = (*leadingBegin); Unit trailing = (*trailingBegin).rect.get(orient.get_perpendicular()).high(); Interval ivl = (*trailingBegin).rect.get(orient); std::pair<Unit, Interval> trailingSegment(trailing, ivl); if(leadingSegment.first.first < trailingSegment.first) { ++leadingBegin; continue; } if(leadingSegment.first.first > trailingSegment.first) { ++trailingBegin; continue; } if(leadingSegment.first.second.high() <= trailingSegment.second.low()) { ++leadingBegin; continue; } if(trailingSegment.second.high() <= leadingSegment.first.second.low()) { ++trailingBegin; continue; } //leading segment intersects trailing segment (*trailingBegin).add((*leadingBegin).second); if(leadingSegment.first.second.high() > trailingSegment.second.high()) { ++trailingBegin; continue; } if(trailingSegment.second.high() > leadingSegment.first.second.high()) { ++leadingBegin; continue; } ++leadingBegin; ++trailingBegin; } } template <class cT> static inline void getMaxCover(cT& outputContainer, const std::vector<Rectangle>& rects, orientation_2d orient) { if(rects.empty()) return; std::vector<Node> nodes; { if(rects.size() == 1) { outputContainer.push_back(copy_construct<typename cT::value_type, Rectangle>(rects[0])); return; } nodes.reserve(rects.size()); for(std::size_t i = 0; i < rects.size(); ++i) { nodes.push_back(Node(rects[i])); } } computeDag(nodes.begin(), nodes.end(), orient, nodes.size()); for(std::size_t i = 0; i < nodes.size(); ++i) { getMaxCover(outputContainer, &(nodes[i]), orient); } } }; } } #endif PK �b�[�Ǵ� � detail/property_merge_45.hppnu �[��� /* Copyright 2008 Intel Corporation Use, modification and distribution are 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_POLYGON_PROPERTY_MERGE_45_HPP #define BOOST_POLYGON_PROPERTY_MERGE_45_HPP namespace boost { namespace polygon{ template <typename Unit, typename property_type> struct polygon_45_property_merge { typedef point_data<Unit> Point; typedef typename coordinate_traits<Unit>::manhattan_area_type LongUnit; template <typename property_map> static inline void merge_property_maps(property_map& mp, const property_map& mp2, bool subtract = false) { polygon_45_touch<Unit>::merge_property_maps(mp, mp2, subtract); } class CountMerge { public: inline CountMerge() : counts() {} //inline CountMerge(int count) { counts[0] = counts[1] = count; } //inline CountMerge(int count1, int count2) { counts[0] = count1; counts[1] = count2; } inline CountMerge(const CountMerge& count) : counts(count.counts) {} inline bool operator==(const CountMerge& count) const { return counts == count.counts; } inline bool operator!=(const CountMerge& count) const { return !((*this) == count); } //inline CountMerge& operator=(int count) { counts[0] = counts[1] = count; return *this; } inline CountMerge& operator=(const CountMerge& count) { counts = count.counts; return *this; } inline int& operator[](property_type index) { std::vector<std::pair<int, int> >::iterator itr = lower_bound(counts.begin(), counts.end(), std::make_pair(index, int(0))); if(itr != counts.end() && itr->first == index) { return itr->second; } itr = counts.insert(itr, std::make_pair(index, int(0))); return itr->second; } // inline int operator[](int index) const { // std::vector<std::pair<int, int> >::const_iterator itr = counts.begin(); // for( ; itr != counts.end() && itr->first <= index; ++itr) { // if(itr->first == index) { // return itr->second; // } // } // return 0; // } inline CountMerge& operator+=(const CountMerge& count){ merge_property_maps(counts, count.counts, false); return *this; } inline CountMerge& operator-=(const CountMerge& count){ merge_property_maps(counts, count.counts, true); return *this; } inline CountMerge operator+(const CountMerge& count) const { return CountMerge(*this)+=count; } inline CountMerge operator-(const CountMerge& count) const { return CountMerge(*this)-=count; } inline CountMerge invert() const { CountMerge retval; retval -= *this; return retval; } std::vector<std::pair<property_type, int> > counts; }; //output is a std::map<std::set<property_type>, polygon_45_set_data<Unit> > struct merge_45_output_functor { template <typename cT> void operator()(cT& output, const CountMerge& count1, const CountMerge& count2, const Point& pt, int rise, direction_1d end) { typedef typename cT::key_type keytype; keytype left; keytype right; int edgeType = end == LOW ? -1 : 1; for(typename std::vector<std::pair<property_type, int> >::const_iterator itr = count1.counts.begin(); itr != count1.counts.end(); ++itr) { left.insert(left.end(), (*itr).first); } for(typename std::vector<std::pair<property_type, int> >::const_iterator itr = count2.counts.begin(); itr != count2.counts.end(); ++itr) { right.insert(right.end(), (*itr).first); } if(left == right) return; if(!left.empty()) { //std::cout << pt.x() << " " << pt.y() << " " << rise << " " << edgeType << std::endl; output[left].insert_clean(typename boolean_op_45<Unit>::Vertex45(pt, rise, -edgeType)); } if(!right.empty()) { //std::cout << pt.x() << " " << pt.y() << " " << rise << " " << -edgeType << std::endl; output[right].insert_clean(typename boolean_op_45<Unit>::Vertex45(pt, rise, edgeType)); } } }; typedef typename std::pair<Point, typename boolean_op_45<Unit>::template Scan45CountT<CountMerge> > Vertex45Compact; typedef std::vector<Vertex45Compact> MergeSetData; struct lessVertex45Compact { bool operator()(const Vertex45Compact& l, const Vertex45Compact& r) { return l.first < r.first; } }; template <typename output_type> static void performMerge(output_type& result, MergeSetData& tsd) { polygon_sort(tsd.begin(), tsd.end(), lessVertex45Compact()); typedef std::vector<std::pair<Point, typename boolean_op_45<Unit>::template Scan45CountT<CountMerge> > > TSD; TSD tsd_; tsd_.reserve(tsd.size()); for(typename MergeSetData::iterator itr = tsd.begin(); itr != tsd.end(); ) { typename MergeSetData::iterator itr2 = itr; ++itr2; for(; itr2 != tsd.end() && itr2->first == itr->first; ++itr2) { (itr->second) += (itr2->second); //accumulate } tsd_.push_back(std::make_pair(itr->first, itr->second)); itr = itr2; } typename boolean_op_45<Unit>::template Scan45<CountMerge, merge_45_output_functor> scanline; for(typename TSD::iterator itr = tsd_.begin(); itr != tsd_.end(); ) { typename TSD::iterator itr2 = itr; ++itr2; while(itr2 != tsd_.end() && itr2->first.x() == itr->first.x()) { ++itr2; } scanline.scan(result, itr, itr2); itr = itr2; } } template <typename iT> static void populateMergeSetData(MergeSetData& tsd, iT begin, iT end, property_type property) { for( ; begin != end; ++begin) { Vertex45Compact vertex; vertex.first = typename Vertex45Compact::first_type(begin->pt.x() * 2, begin->pt.y() * 2); tsd.push_back(vertex); for(unsigned int i = 0; i < 4; ++i) { if(begin->count[i]) { tsd.back().second[i][property] += begin->count[i]; } } } } }; } } #endif PK �b�[�ǀ�W �W detail/polygon_formation.hppnu �[��� /* Copyright 2008 Intel Corporation Use, modification and distribution are 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). */ #include<iostream> #include<cassert> #ifndef BOOST_POLYGON_POLYGON_FORMATION_HPP #define BOOST_POLYGON_POLYGON_FORMATION_HPP namespace boost { namespace polygon{ namespace polygon_formation { /* * End has two states, HEAD and TAIL as is represented by a bool */ typedef bool End; /* * HEAD End is represented as false because it is the lesser state */ const End HEAD = false; /* * TAIL End is represented by true because TAIL comes after head and 1 after 0 */ const End TAIL = true; /* * 2D turning direction, left and right sides (is a boolean value since it has two states.) */ typedef bool Side; /* * LEFT Side is 0 because we inuitively think left to right; left < right */ const Side LEFT = false; /* * RIGHT Side is 1 so that right > left */ const Side RIGHT = true; /* * The PolyLine class is data storage and services for building and representing partial polygons. * As the polyline is added to it extends its storage to accomodate the data. * PolyLines can be joined head-to-head/head-to-tail when it is determined that two polylines are * part of the same polygon. * PolyLines keep state information about what orientation their incomplete head and tail geometry have, * which side of the polyline is solid and whether the polyline is joined head-to-head and tail-to-head. * PolyLines have nothing whatsoever to do with holes. * It may be valuable to collect a histogram of PolyLine lengths used by an algorithm on its typical data * sets and tune the allocation of the initial vector of coordinate data to be greater than or equal to * the mean, median, mode, or mean plus some number of standard deviation, or just generally large enough * to prevent too much unnecesary reallocations, but not too big that it wastes a lot of memory and degrades cache * performance. */ template <typename Unit> class PolyLine { private: //data /* * ptdata_ a vector of coordiantes * if VERTICAL_HEAD, first coordiante is an X * else first coordinate is a Y */ std::vector<Unit> ptdata_; /* * head and tail points to other polylines before and after this in a chain */ PolyLine* headp_; PolyLine* tailp_; /* * state bitmask * bit zero is orientation, 0 H, 1 V * bit 1 is head connectivity, 0 for head, 1 for tail * bit 2 is tail connectivity, 0 for head, 1 for tail * bit 3 is solid to left of PolyLine when 1, right when 0 */ int state_; public: /* * default constructor (for preallocation) */ PolyLine(); /* * constructor that takes the orientation, coordiante and side to which there is solid */ PolyLine(orientation_2d orient, Unit coord, Side side); //copy constructor PolyLine(const PolyLine& pline); //destructor ~PolyLine(); //assignment operator PolyLine& operator=(const PolyLine& that); //equivalence operator bool operator==(const PolyLine& b) const; /* * valid PolyLine (only default constructed polylines are invalid.) */ bool isValid() const; /* * Orientation of Head */ orientation_2d headOrient() const; /* * returns true if first coordinate is an X value (first segment is vertical) */ bool verticalHead() const; /* * returns the orientation_2d fo the tail */ orientation_2d tailOrient() const; /* * returns true if last coordinate is an X value (last segment is vertical) */ bool verticalTail() const; /* * retrun true if PolyLine has odd number of coordiantes */ bool oddLength() const; /* * retrun the End of the other polyline that the specified end of this polyline is connected to */ End endConnectivity(End end) const; /* * retrun true if the head of this polyline is connect to the tail of a polyline */ bool headToTail() const; /* * retrun true if the head of this polyline is connect to the head of a polyline */ bool headToHead() const; /* * retrun true if the tail of this polyline is connect to the tail of a polyline */ bool tailToTail() const; /* * retrun true if the tail of this polyline is connect to the head of a polyline */ bool tailToHead() const; /* * retrun the side on which there is solid for this polyline */ Side solidSide() const; /* * retrun true if there is solid to the right of this polyline */ bool solidToRight() const; /* * returns true if the polyline tail is not connected */ bool active() const; /* * adds a coordinate value to the end of the polyline changing the tail orientation */ PolyLine& pushCoordinate(Unit coord); /* * removes a coordinate value at the end of the polyline changing the tail orientation */ PolyLine& popCoordinate(); /* * extends the tail of the polyline to include the point, changing orientation if needed */ PolyLine& pushPoint(const point_data<Unit>& point); /* * changes the last coordinate of the tail of the polyline by the amount of the delta */ PolyLine& extendTail(Unit delta); /* * join thisEnd of this polyline to that polyline's end */ PolyLine& joinTo(End thisEnd, PolyLine& that, End end); /* * join an end of this polyline to the tail of that polyline */ PolyLine& joinToTail(PolyLine& that, End end); /* * join an end of this polyline to the head of that polyline */ PolyLine& joinToHead(PolyLine& that, End end); /* * join the head of this polyline to the head of that polyline */ //join this to that in the given way PolyLine& joinHeadToHead(PolyLine& that); /* * join the head of this polyline to the tail of that polyline */ PolyLine& joinHeadToTail(PolyLine& that); /* * join the tail of this polyline to the head of that polyline */ PolyLine& joinTailToHead(PolyLine& that); /* * join the tail of this polyline to the tail of that polyline */ PolyLine& joinTailToTail(PolyLine& that); /* * dissconnect the tail at the end of the polygon */ PolyLine& disconnectTails(); /* * get the coordinate at one end of this polyline, by default the tail end */ Unit getEndCoord(End end = TAIL) const; /* * get the point on the polyline at the given index (polylines have the same number of coordinates as points */ point_data<Unit> getPoint(unsigned int index) const; /* * get the point on one end of the polyline, by default the tail */ point_data<Unit> getEndPoint(End end = TAIL) const; /* * get the orientation of a segment by index */ orientation_2d segmentOrient(unsigned int index = 0) const; /* * get a coordinate by index using the square bracket operator */ Unit operator[] (unsigned int index) const; /* * get the number of segments/points/coordinates in the polyline */ unsigned int numSegments() const; /* * get the pointer to the next polyline at one end of this */ PolyLine* next(End end) const; /* * write out coordinates of this and all attached polylines to a single vector */ PolyLine* writeOut(std::vector<Unit>& outVec, End startEnd = TAIL) const; private: //methods PolyLine& joinTo_(End thisEnd, PolyLine& that, End end); }; //forward declaration template<bool orientT, typename Unit> class PolyLinePolygonData; //forward declaration template<bool orientT, typename Unit> class PolyLinePolygonWithHolesData; /* * ActiveTail represents an edge of an incomplete polygon. * * An ActiveTail object is the active tail end of a polyline object, which may (should) be the attached to * a chain of polyline objects through a pointer. The ActiveTail class provides an abstraction between * and algorithm that builds polygons and the PolyLine data representation of incomplete polygons that are * being built. It does this by providing an iterface to access the information about the last edge at the * tail of the PolyLine it is associated with. To a polygon constructing algorithm, an ActiveTail is a floating * edge of an incomplete polygon and has an orientation and coordinate value, as well as knowing which side of * that edge is supposed to be solid or space. Any incomplete polygon will have two active tails. Active tails * may be joined together to merge two incomplete polygons into a larger incomplete polygon. If two active tails * that are to be merged are the oppositve ends of the same incomplete polygon that indicates that the polygon * has been closed and is complete. The active tail keeps a pointer to the other active tail of its incomplete * polygon so that it is easy to check this condition. These pointers are updated when active tails are joined. * The active tail also keeps a list of pointers to active tail objects that serve as handles to closed holes. In * this way a hole can be associated to another incomplete polygon, which will eventually be its enclosing shell, * or reassociate the hole to another incomplete polygon in the case that it become a hole itself. Alternately, * the active tail may add a filiment to stitch a hole into a shell and "fracture" the hole out of the interior * of a polygon. The active tail maintains a static output buffer to temporarily write polygon data to when * it outputs a figure so that outputting a polygon does not require the allocation of a temporary buffer. This * static buffer should be destroyed whenever the program determines that it won't need it anymore and would prefer to * release the memory it has allocated back to the system. */ template <typename Unit> class ActiveTail { private: //data PolyLine<Unit>* tailp_; ActiveTail *otherTailp_; std::list<ActiveTail*> holesList_; //Sum of all the polylines which constitute the active tail (including holes)// size_t polyLineSize_; public: inline size_t getPolyLineSize(){ return polyLineSize_; } inline void setPolyLineSize(int delta){ polyLineSize_ = delta; } inline void addPolyLineSize(int delta){ polyLineSize_ += delta; } /* * iterator over coordinates of the figure */ class iterator { private: const PolyLine<Unit>* pLine_; const PolyLine<Unit>* pLineEnd_; unsigned int index_; unsigned int indexEnd_; End startEnd_; public: inline iterator() : pLine_(), pLineEnd_(), index_(), indexEnd_(), startEnd_() {} inline iterator(const ActiveTail* at, bool isHole, orientation_2d orient) : pLine_(), pLineEnd_(), index_(), indexEnd_(), startEnd_() { //if it is a hole and orientation is vertical or it is not a hole and orientation is horizontal //we want to use this active tail, otherwise we want to use the other active tail startEnd_ = TAIL; if(!isHole ^ (orient == HORIZONTAL)) { //switch winding direction at = at->getOtherActiveTail(); } //now we have the right winding direction //if it is horizontal we need to skip the first element pLine_ = at->getTail(); if(at->getTail()->numSegments() > 0) index_ = at->getTail()->numSegments() - 1; if((at->getOrient() == HORIZONTAL) ^ (orient == HORIZONTAL)) { pLineEnd_ = at->getTail(); indexEnd_ = pLineEnd_->numSegments() - 1; if(index_ == 0) { pLine_ = at->getTail()->next(HEAD); if(at->getTail()->endConnectivity(HEAD) == TAIL) { index_ = pLine_->numSegments() -1; } else { startEnd_ = HEAD; index_ = 0; } } else { --index_; } } else { pLineEnd_ = at->getOtherActiveTail()->getTail(); if(pLineEnd_->numSegments() > 0) indexEnd_ = pLineEnd_->numSegments() - 1; } at->getTail()->joinTailToTail(*(at->getOtherActiveTail()->getTail())); } inline size_t size(void){ size_t count = 0; End dir = startEnd_; PolyLine<Unit> const * currLine = pLine_; size_t ops = 0; while(currLine != pLineEnd_){ ops++; count += currLine->numSegments(); currLine = currLine->next(dir == HEAD ? TAIL : HEAD); dir = currLine->endConnectivity(dir == HEAD ? TAIL : HEAD); } count += pLineEnd_->numSegments(); return count; //no. of vertices } //use bitwise copy and assign provided by the compiler inline iterator& operator++() { if(pLine_ == pLineEnd_ && index_ == indexEnd_) { pLine_ = 0; index_ = 0; return *this; } if(startEnd_ == HEAD) { ++index_; if(index_ == pLine_->numSegments()) { End end = pLine_->endConnectivity(TAIL); pLine_ = pLine_->next(TAIL); if(end == TAIL) { startEnd_ = TAIL; index_ = pLine_->numSegments() -1; } else { index_ = 0; } } } else { if(index_ == 0) { End end = pLine_->endConnectivity(HEAD); pLine_ = pLine_->next(HEAD); if(end == TAIL) { index_ = pLine_->numSegments() -1; } else { startEnd_ = HEAD; index_ = 0; } } else { --index_; } } return *this; } inline const iterator operator++(int) { iterator tmp(*this); ++(*this); return tmp; } inline bool operator==(const iterator& that) const { return pLine_ == that.pLine_ && index_ == that.index_; } inline bool operator!=(const iterator& that) const { return pLine_ != that.pLine_ || index_ != that.index_; } inline Unit operator*() { return (*pLine_)[index_]; } }; /* * iterator over holes contained within the figure */ typedef typename std::list<ActiveTail*>::const_iterator iteratorHoles; //default constructor ActiveTail(); //constructor ActiveTail(orientation_2d orient, Unit coord, Side solidToRight, ActiveTail* otherTailp); //constructor ActiveTail(PolyLine<Unit>* active, ActiveTail* otherTailp); //copy constructor ActiveTail(const ActiveTail& that); //destructor ~ActiveTail(); //assignment operator ActiveTail& operator=(const ActiveTail& that); //equivalence operator bool operator==(const ActiveTail& b) const; /* * comparison operators, ActiveTail objects are sortable by geometry */ bool operator<(const ActiveTail& b) const; bool operator<=(const ActiveTail& b) const; bool operator>(const ActiveTail& b) const; bool operator>=(const ActiveTail& b) const; /* * get the pointer to the polyline that this is an active tail of */ PolyLine<Unit>* getTail() const; /* * get the pointer to the polyline at the other end of the chain */ PolyLine<Unit>* getOtherTail() const; /* * get the pointer to the activetail at the other end of the chain */ ActiveTail* getOtherActiveTail() const; /* * test if another active tail is the other end of the chain */ bool isOtherTail(const ActiveTail& b); /* * update this end of chain pointer to new polyline */ ActiveTail& updateTail(PolyLine<Unit>* newTail); /* * associate a hole to this active tail by the specified policy */ ActiveTail* addHole(ActiveTail* hole, bool fractureHoles); /* * get the list of holes */ const std::list<ActiveTail*>& getHoles() const; /* * copy holes from that to this */ void copyHoles(ActiveTail& that); /* * find out if solid to right */ bool solidToRight() const; /* * get coordinate (getCoord and getCoordinate are aliases for eachother) */ Unit getCoord() const; Unit getCoordinate() const; /* * get the tail orientation */ orientation_2d getOrient() const; /* * add a coordinate to the polygon at this active tail end, properly handle degenerate edges by removing redundant coordinate */ void pushCoordinate(Unit coord); /* * write the figure that this active tail points to out to the temp buffer */ void writeOutFigure(std::vector<Unit>& outVec, bool isHole = false) const; /* * write the figure that this active tail points to out through iterators */ void writeOutFigureItrs(iterator& beginOut, iterator& endOut, bool isHole = false, orientation_2d orient = VERTICAL) const; iterator begin(bool isHole, orientation_2d orient) const; iterator end() const; /* * write the holes that this active tail points to out through iterators */ void writeOutFigureHoleItrs(iteratorHoles& beginOut, iteratorHoles& endOut) const; iteratorHoles beginHoles() const; iteratorHoles endHoles() const; /* * joins the two chains that the two active tail tails are ends of * checks for closure of figure and writes out polygons appropriately * returns a handle to a hole if one is closed */ static ActiveTail* joinChains(ActiveTail* at1, ActiveTail* at2, bool solid, std::vector<Unit>& outBufferTmp); template <typename PolygonT> static ActiveTail* joinChains(ActiveTail* at1, ActiveTail* at2, bool solid, typename std::vector<PolygonT>& outBufferTmp); /* * deallocate temp buffer */ static void destroyOutBuffer(); /* * deallocate all polygon data this active tail points to (deep delete, call only from one of a pair of active tails) */ void destroyContents(); }; /* allocate a polyline object */ template <typename Unit> PolyLine<Unit>* createPolyLine(orientation_2d orient, Unit coord, Side side); /* deallocate a polyline object */ template <typename Unit> void destroyPolyLine(PolyLine<Unit>* pLine); /* allocate an activetail object */ template <typename Unit> ActiveTail<Unit>* createActiveTail(); /* deallocate an activetail object */ template <typename Unit> void destroyActiveTail(ActiveTail<Unit>* aTail); template<bool orientT, typename Unit> class PolyLineHoleData { private: ActiveTail<Unit>* p_; public: typedef Unit coordinate_type; typedef typename ActiveTail<Unit>::iterator compact_iterator_type; typedef iterator_compact_to_points<compact_iterator_type, point_data<coordinate_type> > iterator_type; inline PolyLineHoleData() : p_(0) {} inline PolyLineHoleData(ActiveTail<Unit>* p) : p_(p) {} //use default copy and assign inline compact_iterator_type begin_compact() const { return p_->begin(true, (orientT ? VERTICAL : HORIZONTAL)); } inline compact_iterator_type end_compact() const { return p_->end(); } inline iterator_type begin() const { return iterator_type(begin_compact(), end_compact()); } inline iterator_type end() const { return iterator_type(end_compact(), end_compact()); } inline std::size_t size() const { return p_->getPolyLineSize(); } inline ActiveTail<Unit>* yield() { return p_; } }; template<bool orientT, typename Unit> class PolyLinePolygonWithHolesData { private: ActiveTail<Unit>* p_; public: typedef Unit coordinate_type; typedef typename ActiveTail<Unit>::iterator compact_iterator_type; typedef iterator_compact_to_points<compact_iterator_type, point_data<coordinate_type> > iterator_type; typedef PolyLineHoleData<orientT, Unit> hole_type; typedef typename coordinate_traits<Unit>::area_type area_type; class iteratorHoles { private: typename ActiveTail<Unit>::iteratorHoles itr_; public: inline iteratorHoles() : itr_() {} inline iteratorHoles(typename ActiveTail<Unit>::iteratorHoles itr) : itr_(itr) {} //use bitwise copy and assign provided by the compiler inline iteratorHoles& operator++() { ++itr_; return *this; } inline const iteratorHoles operator++(int) { iteratorHoles tmp(*this); ++(*this); return tmp; } inline bool operator==(const iteratorHoles& that) const { return itr_ == that.itr_; } inline bool operator!=(const iteratorHoles& that) const { return itr_ != that.itr_; } inline PolyLineHoleData<orientT, Unit> operator*() { return PolyLineHoleData<orientT, Unit>(*itr_);} }; typedef iteratorHoles iterator_holes_type; inline PolyLinePolygonWithHolesData() : p_(0) {} inline PolyLinePolygonWithHolesData(ActiveTail<Unit>* p) : p_(p) {} //use default copy and assign inline compact_iterator_type begin_compact() const { return p_->begin(false, (orientT ? VERTICAL : HORIZONTAL)); } inline compact_iterator_type end_compact() const { return p_->end(); } inline iterator_type begin() const { return iterator_type(begin_compact(), end_compact()); } inline iterator_type end() const { return iterator_type(end_compact(), end_compact()); } inline iteratorHoles begin_holes() const { return iteratorHoles(p_->beginHoles()); } inline iteratorHoles end_holes() const { return iteratorHoles(p_->endHoles()); } inline ActiveTail<Unit>* yield() { return p_; } //stub out these four required functions that will not be used but are needed for the interface inline std::size_t size_holes() const { return 0; } inline std::size_t size() const { return 0; } }; template <bool orientT, typename Unit, typename polygon_concept_type> struct PolyLineType { }; template <bool orientT, typename Unit> struct PolyLineType<orientT, Unit, polygon_90_with_holes_concept> { typedef PolyLinePolygonWithHolesData<orientT, Unit> type; }; template <bool orientT, typename Unit> struct PolyLineType<orientT, Unit, polygon_45_with_holes_concept> { typedef PolyLinePolygonWithHolesData<orientT, Unit> type; }; template <bool orientT, typename Unit> struct PolyLineType<orientT, Unit, polygon_with_holes_concept> { typedef PolyLinePolygonWithHolesData<orientT, Unit> type; }; template <bool orientT, typename Unit> struct PolyLineType<orientT, Unit, polygon_90_concept> { typedef PolyLineHoleData<orientT, Unit> type; }; template <bool orientT, typename Unit> struct PolyLineType<orientT, Unit, polygon_45_concept> { typedef PolyLineHoleData<orientT, Unit> type; }; template <bool orientT, typename Unit> struct PolyLineType<orientT, Unit, polygon_concept> { typedef PolyLineHoleData<orientT, Unit> type; }; template <bool orientT, typename Unit, typename polygon_concept_type> class ScanLineToPolygonItrs { private: std::map<Unit, ActiveTail<Unit>*> tailMap_; typedef typename PolyLineType<orientT, Unit, polygon_concept_type>::type PolyLinePolygonData; std::vector<PolyLinePolygonData> outputPolygons_; bool fractureHoles_; public: typedef typename std::vector<PolyLinePolygonData>::iterator iterator; inline ScanLineToPolygonItrs() : tailMap_(), outputPolygons_(), fractureHoles_(false) {} /* construct a scanline with the proper offsets, protocol and options */ inline ScanLineToPolygonItrs(bool fractureHoles) : tailMap_(), outputPolygons_(), fractureHoles_(fractureHoles) {} ~ScanLineToPolygonItrs() { clearOutput_(); } /* process all vertical edges, left and right, at a unique x coordinate, edges must be sorted low to high */ void processEdges(iterator& beginOutput, iterator& endOutput, Unit currentX, std::vector<interval_data<Unit> >& leftEdges, std::vector<interval_data<Unit> >& rightEdges, size_t vertexThreshold=(std::numeric_limits<size_t>::max)() ); /********************************************************************** *methods implementing new polygon formation code * **********************************************************************/ void updatePartialSimplePolygonsWithRightEdges(Unit currentX, const std::vector<interval_data<Unit> >& leftEdges, size_t threshold); void updatePartialSimplePolygonsWithLeftEdges(Unit currentX, const std::vector<interval_data<Unit> >& leftEdges, size_t threshold); void closePartialSimplePolygon(Unit, ActiveTail<Unit>*, ActiveTail<Unit>*); void maintainPartialSimplePolygonInvariant(iterator& ,iterator& ,Unit, const std::vector<interval_data<Unit> >&, const std::vector<interval_data<Unit> >&, size_t vertexThreshold=(std::numeric_limits<size_t>::max)()); void insertNewLeftEdgeIntoTailMap(Unit, Unit, Unit, typename std::map<Unit, ActiveTail<Unit>*>::iterator &); /**********************************************************************/ inline size_t getTailMapSize(){ typename std::map<Unit, ActiveTail<Unit>* >::const_iterator itr; size_t tsize = 0; for(itr=tailMap_.begin(); itr!=tailMap_.end(); ++itr){ tsize += (itr->second)->getPolyLineSize(); } return tsize; } /*print the active tails in this map:*/ inline void print(){ typename std::map<Unit, ActiveTail<Unit>* >::const_iterator itr; printf("=========TailMap[%lu]=========\n", tailMap_.size()); for(itr=tailMap_.begin(); itr!=tailMap_.end(); ++itr){ std::cout<< "[" << itr->first << "] : " << std::endl; //print active tail// ActiveTail<Unit> const *t = (itr->second); PolyLine<Unit> const *pBegin = t->getTail(); PolyLine<Unit> const *pEnd = t->getOtherActiveTail()->getTail(); std::string sorient = pBegin->solidToRight() ? "RIGHT" : "LEFT"; std::cout<< " ActiveTail.tailp_ (solid= " << sorient ; End dir = TAIL; while(pBegin!=pEnd){ std::cout << pBegin << "={ "; for(size_t i=0; i<pBegin->numSegments(); i++){ point_data<Unit> u = pBegin->getPoint(i); std::cout << "(" << u.x() << "," << u.y() << ") "; } std::cout << "} "; pBegin = pBegin->next(dir == HEAD ? TAIL : HEAD); dir = pBegin->endConnectivity(dir == HEAD ? TAIL : HEAD); } if(pEnd){ std::cout << pEnd << "={ "; for(size_t i=0; i<pEnd->numSegments(); i++){ point_data<Unit> u = pEnd->getPoint(i); std::cout << "(" << u.x() << "," << u.y() << ") "; } std::cout << "} "; } std::cout << " end= " << pEnd << std::endl; } } private: void clearOutput_(); }; /* * ScanLine does all the work of stitching together polygons from incoming vertical edges */ // template <typename Unit, typename polygon_concept_type> // class ScanLineToPolygons { // private: // ScanLineToPolygonItrs<true, Unit> scanline_; // public: // inline ScanLineToPolygons() : scanline_() {} // /* construct a scanline with the proper offsets, protocol and options */ // inline ScanLineToPolygons(bool fractureHoles) : scanline_(fractureHoles) {} // /* process all vertical edges, left and right, at a unique x coordinate, edges must be sorted low to high */ // inline void processEdges(std::vector<Unit>& outBufferTmp, Unit currentX, std::vector<interval_data<Unit> >& leftEdges, // std::vector<interval_data<Unit> >& rightEdges) { // typename ScanLineToPolygonItrs<true, Unit>::iterator itr, endItr; // scanline_.processEdges(itr, endItr, currentX, leftEdges, rightEdges); // //copy data into outBufferTmp // while(itr != endItr) { // typename PolyLinePolygonData<true, Unit>::iterator pditr; // outBufferTmp.push_back(0); // unsigned int sizeIndex = outBufferTmp.size() - 1; // int count = 0; // for(pditr = (*itr).begin(); pditr != (*itr).end(); ++pditr) { // outBufferTmp.push_back(*pditr); // ++count; // } // outBufferTmp[sizeIndex] = count; // typename PolyLinePolygonData<true, Unit>::iteratorHoles pdHoleItr; // for(pdHoleItr = (*itr).beginHoles(); pdHoleItr != (*itr).endHoles(); ++pdHoleItr) { // outBufferTmp.push_back(0); // unsigned int sizeIndex2 = outBufferTmp.size() - 1; // int count2 = 0; // for(pditr = (*pdHoleItr).begin(); pditr != (*pdHoleItr).end(); ++pditr) { // outBufferTmp.push_back(*pditr); // ++count2; // } // outBufferTmp[sizeIndex2] = -count; // } // ++itr; // } // } // }; const int VERTICAL_HEAD = 1, HEAD_TO_TAIL = 2, TAIL_TO_TAIL = 4, SOLID_TO_RIGHT = 8; //EVERY FUNCTION in this DEF file should be explicitly defined as inline //microsoft compiler improperly warns whenever you cast an integer to bool //call this function on an integer to convert it to bool without a warning template <class T> inline bool to_bool(const T& val) { return val != 0; } //default constructor (for preallocation) template <typename Unit> inline PolyLine<Unit>::PolyLine() : ptdata_() ,headp_(0), tailp_(0), state_(-1) {} //constructor template <typename Unit> inline PolyLine<Unit>::PolyLine(orientation_2d orient, Unit coord, Side side) : ptdata_(1, coord), headp_(0), tailp_(0), state_(orient.to_int() + (side << 3)){} //copy constructor template <typename Unit> inline PolyLine<Unit>::PolyLine(const PolyLine<Unit>& pline) : ptdata_(pline.ptdata_), headp_(pline.headp_), tailp_(pline.tailp_), state_(pline.state_) {} //destructor template <typename Unit> inline PolyLine<Unit>::~PolyLine() { //clear out data just in case it is read later headp_ = tailp_ = 0; state_ = 0; } template <typename Unit> inline PolyLine<Unit>& PolyLine<Unit>::operator=(const PolyLine<Unit>& that) { if(!(this == &that)) { headp_ = that.headp_; tailp_ = that.tailp_; ptdata_ = that.ptdata_; state_ = that.state_; } return *this; } template <typename Unit> inline bool PolyLine<Unit>::operator==(const PolyLine<Unit>& b) const { return this == &b || (state_ == b.state_ && headp_ == b.headp_ && tailp_ == b.tailp_); } //valid PolyLine template <typename Unit> inline bool PolyLine<Unit>::isValid() const { return state_ > -1; } //first coordinate is an X value //first segment is vertical template <typename Unit> inline bool PolyLine<Unit>::verticalHead() const { return state_ & VERTICAL_HEAD; } //retrun true is PolyLine has odd number of coordiantes template <typename Unit> inline bool PolyLine<Unit>::oddLength() const { return to_bool((ptdata_.size()-1) % 2); } //last coordiante is an X value //last segment is vertical template <typename Unit> inline bool PolyLine<Unit>::verticalTail() const { return to_bool(verticalHead() ^ oddLength()); } template <typename Unit> inline orientation_2d PolyLine<Unit>::tailOrient() const { return (verticalTail() ? VERTICAL : HORIZONTAL); } template <typename Unit> inline orientation_2d PolyLine<Unit>::headOrient() const { return (verticalHead() ? VERTICAL : HORIZONTAL); } template <typename Unit> inline End PolyLine<Unit>::endConnectivity(End end) const { //Tail should be defined as true if(end) { return tailToTail(); } return headToTail(); } template <typename Unit> inline bool PolyLine<Unit>::headToTail() const { return to_bool(state_ & HEAD_TO_TAIL); } template <typename Unit> inline bool PolyLine<Unit>::headToHead() const { return to_bool(!headToTail()); } template <typename Unit> inline bool PolyLine<Unit>::tailToHead() const { return to_bool(!tailToTail()); } template <typename Unit> inline bool PolyLine<Unit>::tailToTail() const { return to_bool(state_ & TAIL_TO_TAIL); } template <typename Unit> inline Side PolyLine<Unit>::solidSide() const { return solidToRight(); } template <typename Unit> inline bool PolyLine<Unit>::solidToRight() const { return to_bool(state_ & SOLID_TO_RIGHT) != 0; } template <typename Unit> inline bool PolyLine<Unit>::active() const { return !to_bool(tailp_); } template <typename Unit> inline PolyLine<Unit>& PolyLine<Unit>::pushCoordinate(Unit coord) { ptdata_.push_back(coord); return *this; } template <typename Unit> inline PolyLine<Unit>& PolyLine<Unit>::popCoordinate() { ptdata_.pop_back(); return *this; } template <typename Unit> inline PolyLine<Unit>& PolyLine<Unit>::pushPoint(const point_data<Unit>& point) { if(numSegments()){ point_data<Unit> endPt = getEndPoint(); //vertical is true, horizontal is false if((tailOrient().to_int() ? point.get(VERTICAL) == endPt.get(VERTICAL) : point.get(HORIZONTAL) == endPt.get(HORIZONTAL))) { //we were pushing a colinear segment return popCoordinate(); } } return pushCoordinate(tailOrient().to_int() ? point.get(VERTICAL) : point.get(HORIZONTAL)); } template <typename Unit> inline PolyLine<Unit>& PolyLine<Unit>::extendTail(Unit delta) { ptdata_.back() += delta; return *this; } //private member function that creates a link from this PolyLine to that template <typename Unit> inline PolyLine<Unit>& PolyLine<Unit>::joinTo_(End thisEnd, PolyLine<Unit>& that, End end) { if(thisEnd){ tailp_ = &that; state_ &= ~TAIL_TO_TAIL; //clear any previous state_ of bit (for safety) state_ |= (end << 2); //place bit into mask } else { headp_ = &that; state_ &= ~HEAD_TO_TAIL; //clear any previous state_ of bit (for safety) state_ |= (end << 1); //place bit into mask } return *this; } //join two PolyLines (both ways of the association) template <typename Unit> inline PolyLine<Unit>& PolyLine<Unit>::joinTo(End thisEnd, PolyLine<Unit>& that, End end) { joinTo_(thisEnd, that, end); that.joinTo_(end, *this, thisEnd); return *this; } //convenience functions for joining PolyLines template <typename Unit> inline PolyLine<Unit>& PolyLine<Unit>::joinToTail(PolyLine<Unit>& that, End end) { return joinTo(TAIL, that, end); } template <typename Unit> inline PolyLine<Unit>& PolyLine<Unit>::joinToHead(PolyLine<Unit>& that, End end) { return joinTo(HEAD, that, end); } template <typename Unit> inline PolyLine<Unit>& PolyLine<Unit>::joinHeadToHead(PolyLine<Unit>& that) { return joinToHead(that, HEAD); } template <typename Unit> inline PolyLine<Unit>& PolyLine<Unit>::joinHeadToTail(PolyLine<Unit>& that) { return joinToHead(that, TAIL); } template <typename Unit> inline PolyLine<Unit>& PolyLine<Unit>::joinTailToHead(PolyLine<Unit>& that) { return joinToTail(that, HEAD); } template <typename Unit> inline PolyLine<Unit>& PolyLine<Unit>::joinTailToTail(PolyLine<Unit>& that) { return joinToTail(that, TAIL); } template <typename Unit> inline PolyLine<Unit>& PolyLine<Unit>::disconnectTails() { next(TAIL)->state_ &= !TAIL_TO_TAIL; next(TAIL)->tailp_ = 0; state_ &= !TAIL_TO_TAIL; tailp_ = 0; return *this; } template <typename Unit> inline Unit PolyLine<Unit>::getEndCoord(End end) const { if(end) return ptdata_.back(); return ptdata_.front(); } template <typename Unit> inline orientation_2d PolyLine<Unit>::segmentOrient(unsigned int index) const { return (to_bool((unsigned int)verticalHead() ^ (index % 2)) ? VERTICAL : HORIZONTAL); } template <typename Unit> inline point_data<Unit> PolyLine<Unit>::getPoint(unsigned int index) const { //assert(isValid() && headp_->isValid()) ("PolyLine: headp_ must be valid"); point_data<Unit> pt; pt.set(HORIZONTAL, ptdata_[index]); pt.set(VERTICAL, ptdata_[index]); Unit prevCoord; if(index == 0) { prevCoord = headp_->getEndCoord(headToTail()); } else { prevCoord = ptdata_[index-1]; } pt.set(segmentOrient(index), prevCoord); return pt; } template <typename Unit> inline point_data<Unit> PolyLine<Unit>::getEndPoint(End end) const { return getPoint((end ? numSegments() - 1 : (unsigned int)0)); } template <typename Unit> inline Unit PolyLine<Unit>::operator[] (unsigned int index) const { //assert(ptdata_.size() > index) ("PolyLine: out of bounds index"); return ptdata_[index]; } template <typename Unit> inline unsigned int PolyLine<Unit>::numSegments() const { return ptdata_.size(); } template <typename Unit> inline PolyLine<Unit>* PolyLine<Unit>::next(End end) const { return (end ? tailp_ : headp_); } template <typename Unit> inline ActiveTail<Unit>::ActiveTail() : tailp_(0), otherTailp_(0), holesList_(), polyLineSize_(0) {} template <typename Unit> inline ActiveTail<Unit>::ActiveTail(orientation_2d orient, Unit coord, Side solidToRight, ActiveTail* otherTailp) : tailp_(0), otherTailp_(0), holesList_(), polyLineSize_(0) { tailp_ = createPolyLine(orient, coord, solidToRight); otherTailp_ = otherTailp; polyLineSize_ = tailp_->numSegments(); } template <typename Unit> inline ActiveTail<Unit>::ActiveTail(PolyLine<Unit>* active, ActiveTail<Unit>* otherTailp) : tailp_(active), otherTailp_(otherTailp), holesList_(), polyLineSize_(0) {} //copy constructor template <typename Unit> inline ActiveTail<Unit>::ActiveTail(const ActiveTail<Unit>& that) : tailp_(that.tailp_), otherTailp_(that.otherTailp_), holesList_(), polyLineSize_(that.polyLineSize_) {} //destructor template <typename Unit> inline ActiveTail<Unit>::~ActiveTail() { //clear them in case the memory is read later tailp_ = 0; otherTailp_ = 0; } template <typename Unit> inline ActiveTail<Unit>& ActiveTail<Unit>::operator=(const ActiveTail<Unit>& that) { //self assignment is safe in this case tailp_ = that.tailp_; otherTailp_ = that.otherTailp_; polyLineSize_ = that.polyLineSize_; return *this; } template <typename Unit> inline bool ActiveTail<Unit>::operator==(const ActiveTail<Unit>& b) const { return tailp_ == b.tailp_ && otherTailp_ == b.otherTailp_; } template <typename Unit> inline bool ActiveTail<Unit>::operator<(const ActiveTail<Unit>& b) const { return tailp_->getEndPoint().get(VERTICAL) < b.tailp_->getEndPoint().get(VERTICAL); } template <typename Unit> inline bool ActiveTail<Unit>::operator<=(const ActiveTail<Unit>& b) const { return !(*this > b); } template <typename Unit> inline bool ActiveTail<Unit>::operator>(const ActiveTail<Unit>& b) const { return b < (*this); } template <typename Unit> inline bool ActiveTail<Unit>::operator>=(const ActiveTail<Unit>& b) const { return !(*this < b); } template <typename Unit> inline PolyLine<Unit>* ActiveTail<Unit>::getTail() const { return tailp_; } template <typename Unit> inline PolyLine<Unit>* ActiveTail<Unit>::getOtherTail() const { return otherTailp_->tailp_; } template <typename Unit> inline ActiveTail<Unit>* ActiveTail<Unit>::getOtherActiveTail() const { return otherTailp_; } template <typename Unit> inline bool ActiveTail<Unit>::isOtherTail(const ActiveTail<Unit>& b) { // assert( (tailp_ == b.getOtherTail() && getOtherTail() == b.tailp_) || // (tailp_ != b.getOtherTail() && getOtherTail() != b.tailp_)) // ("ActiveTail: Active tails out of sync"); return otherTailp_ == &b; } template <typename Unit> inline ActiveTail<Unit>& ActiveTail<Unit>::updateTail(PolyLine<Unit>* newTail) { //subtract the old size and add new size// int delta = newTail->numSegments() - tailp_->numSegments(); addPolyLineSize(delta); otherTailp_->addPolyLineSize(delta); tailp_ = newTail; return *this; } template <typename Unit> inline ActiveTail<Unit>* ActiveTail<Unit>::addHole(ActiveTail<Unit>* hole, bool fractureHoles) { if(!fractureHoles){ holesList_.push_back(hole); copyHoles(*hole); copyHoles(*(hole->getOtherActiveTail())); return this; } ActiveTail<Unit>* h, *v; ActiveTail<Unit>* other = hole->getOtherActiveTail(); if(other->getOrient() == VERTICAL) { //assert that hole.getOrient() == HORIZONTAL //this case should never happen h = hole; v = other; } else { //assert that hole.getOrient() == VERTICAL h = other; v = hole; } h->pushCoordinate(v->getCoordinate()); //assert that h->getOrient() == VERTICAL //v->pushCoordinate(getCoordinate()); //assert that v->getOrient() == VERTICAL //I can't close a figure by adding a hole, so pass zero for xMin and yMin std::vector<Unit> tmpVec; ActiveTail<Unit>::joinChains(this, h, false, tmpVec); return v; } template <typename Unit> inline const std::list<ActiveTail<Unit>*>& ActiveTail<Unit>::getHoles() const { return holesList_; } template <typename Unit> inline void ActiveTail<Unit>::copyHoles(ActiveTail<Unit>& that) { holesList_.splice(holesList_.end(), that.holesList_); //splice the two lists together } template <typename Unit> inline bool ActiveTail<Unit>::solidToRight() const { return getTail()->solidToRight(); } template <typename Unit> inline Unit ActiveTail<Unit>::getCoord() const { return getTail()->getEndCoord(); } template <typename Unit> inline Unit ActiveTail<Unit>::getCoordinate() const { return getCoord(); } template <typename Unit> inline orientation_2d ActiveTail<Unit>::getOrient() const { return getTail()->tailOrient(); } template <typename Unit> inline void ActiveTail<Unit>::pushCoordinate(Unit coord) { //appropriately handle any co-linear polyline segments by calling push point internally point_data<Unit> p; p.set(HORIZONTAL, coord); p.set(VERTICAL, coord); //if we are vertical assign the last coordinate (an X) to p.x, else to p.y p.set(getOrient().get_perpendicular(), getCoordinate()); int oldSegments = tailp_->numSegments(); tailp_->pushPoint(p); int delta = tailp_->numSegments() - oldSegments; addPolyLineSize(delta); otherTailp_->addPolyLineSize(delta); } //global utility functions template <typename Unit> inline PolyLine<Unit>* createPolyLine(orientation_2d orient, Unit coord, Side side) { return new PolyLine<Unit>(orient, coord, side); } template <typename Unit> inline void destroyPolyLine(PolyLine<Unit>* pLine) { delete pLine; } template <typename Unit> inline ActiveTail<Unit>* createActiveTail() { //consider replacing system allocator with ActiveTail memory pool return new ActiveTail<Unit>(); } template <typename Unit> inline void destroyActiveTail(ActiveTail<Unit>* aTail) { delete aTail; } //no recursion, to prevent max recursion depth errors template <typename Unit> inline void ActiveTail<Unit>::destroyContents() { tailp_->disconnectTails(); PolyLine<Unit>* nextPolyLinep = tailp_->next(HEAD); End end = tailp_->endConnectivity(HEAD); destroyPolyLine(tailp_); while(nextPolyLinep) { End nextEnd = nextPolyLinep->endConnectivity(!end); //get the direction of next polyLine PolyLine<Unit>* nextNextPolyLinep = nextPolyLinep->next(!end); //get the next polyline destroyPolyLine(nextPolyLinep); //destroy the current polyline end = nextEnd; nextPolyLinep = nextNextPolyLinep; } } template <typename Unit> inline typename ActiveTail<Unit>::iterator ActiveTail<Unit>::begin(bool isHole, orientation_2d orient) const { return iterator(this, isHole, orient); } template <typename Unit> inline typename ActiveTail<Unit>::iterator ActiveTail<Unit>::end() const { return iterator(); } template <typename Unit> inline typename ActiveTail<Unit>::iteratorHoles ActiveTail<Unit>::beginHoles() const { return holesList_.begin(); } template <typename Unit> inline typename ActiveTail<Unit>::iteratorHoles ActiveTail<Unit>::endHoles() const { return holesList_.end(); } template <typename Unit> inline void ActiveTail<Unit>::writeOutFigureItrs(iterator& beginOut, iterator& endOut, bool isHole, orientation_2d orient) const { beginOut = begin(isHole, orient); endOut = end(); } template <typename Unit> inline void ActiveTail<Unit>::writeOutFigureHoleItrs(iteratorHoles& beginOut, iteratorHoles& endOut) const { beginOut = beginHoles(); endOut = endHoles(); } template <typename Unit> inline void ActiveTail<Unit>::writeOutFigure(std::vector<Unit>& outVec, bool isHole) const { //we start writing out the polyLine that this active tail points to at its tail std::size_t size = outVec.size(); outVec.push_back(0); //place holder for size PolyLine<Unit>* nextPolyLinep = 0; if(!isHole){ nextPolyLinep = otherTailp_->tailp_->writeOut(outVec); } else { nextPolyLinep = tailp_->writeOut(outVec); } Unit firsty = outVec[size + 1]; if((getOrient() == HORIZONTAL) ^ !isHole) { //our first coordinate is a y value, so we need to rotate it to the end typename std::vector<Unit>::iterator tmpItr = outVec.begin(); tmpItr += size; outVec.erase(++tmpItr); //erase the 2nd element } End startEnd = tailp_->endConnectivity(HEAD); if(isHole) startEnd = otherTailp_->tailp_->endConnectivity(HEAD); while(nextPolyLinep) { bool nextStartEnd = nextPolyLinep->endConnectivity(!startEnd); nextPolyLinep = nextPolyLinep->writeOut(outVec, startEnd); startEnd = nextStartEnd; } if((getOrient() == HORIZONTAL) ^ !isHole) { //we want to push the y value onto the end since we ought to have ended with an x outVec.push_back(firsty); //should never be executed because we want first value to be an x } //the vector contains the coordinates of the linked list of PolyLines in the correct order //first element is supposed to be the size outVec[size] = outVec.size() - 1 - size; //number of coordinates in vector //assert outVec[size] % 2 == 0 //it should be even //make the size negative for holes outVec[size] *= (isHole ? -1 : 1); } //no recursion to prevent max recursion depth errors template <typename Unit> inline PolyLine<Unit>* PolyLine<Unit>::writeOut(std::vector<Unit>& outVec, End startEnd) const { if(startEnd == HEAD){ //forward order outVec.insert(outVec.end(), ptdata_.begin(), ptdata_.end()); return tailp_; }else{ //reverse order //do not reserve because we expect outVec to be large enough already for(int i = ptdata_.size() - 1; i >= 0; --i){ outVec.push_back(ptdata_[i]); } //NT didn't know about this version of the API.... //outVec.insert(outVec.end(), ptdata_.rbegin(), ptdata_.rend()); return headp_; } } //solid indicates if it was joined by a solit or a space template <typename Unit> inline ActiveTail<Unit>* ActiveTail<Unit>::joinChains(ActiveTail<Unit>* at1, ActiveTail<Unit>* at2, bool solid, std::vector<Unit>& outBufferTmp) { //checks to see if we closed a figure if(at1->isOtherTail(*at2)){ //value of solid tells us if we closed solid or hole //and output the solid or handle the hole appropriately //if the hole needs to fracture across horizontal partition boundary we need to notify //the calling context to do so if(solid) { //the chains are being joined because there is solid to the right //this means that if the figure is closed at this point it must be a hole //because otherwise it would have to have another vertex to the right of this one //and would not be closed at this point return at1; } else { //assert pG != 0 //the figure that was closed is a shell at1->writeOutFigure(outBufferTmp); //process holes of the polygon at1->copyHoles(*at2); //there should not be holes on at2, but if there are, copy them over const std::list<ActiveTail<Unit>*>& holes = at1->getHoles(); for(typename std::list<ActiveTail<Unit>*>::const_iterator litr = holes.begin(); litr != holes.end(); ++litr) { (*litr)->writeOutFigure(outBufferTmp, true); //delete the hole (*litr)->destroyContents(); destroyActiveTail((*litr)->getOtherActiveTail()); destroyActiveTail((*litr)); } //delete the polygon at1->destroyContents(); //at2 contents are the same as at1, so it should not destroy them destroyActiveTail(at1); destroyActiveTail(at2); } return 0; } //join the two partial polygons into one large partial polygon at1->getTail()->joinTailToTail(*(at2->getTail())); *(at1->getOtherActiveTail()) = ActiveTail(at1->getOtherTail(), at2->getOtherActiveTail()); *(at2->getOtherActiveTail()) = ActiveTail(at2->getOtherTail(), at1->getOtherActiveTail()); int accumulate = at2->getPolyLineSize() + at1->getPolyLineSize(); (at1->getOtherActiveTail())->setPolyLineSize(accumulate); (at2->getOtherActiveTail())->setPolyLineSize(accumulate); at1->getOtherActiveTail()->copyHoles(*at1); at1->getOtherActiveTail()->copyHoles(*at2); destroyActiveTail(at1); destroyActiveTail(at2); return 0; } //solid indicates if it was joined by a solit or a space template <typename Unit> template <typename PolygonT> inline ActiveTail<Unit>* ActiveTail<Unit>::joinChains(ActiveTail<Unit>* at1, ActiveTail<Unit>* at2, bool solid, std::vector<PolygonT>& outBufferTmp) { //checks to see if we closed a figure if(at1->isOtherTail(*at2)){ //value of solid tells us if we closed solid or hole //and output the solid or handle the hole appropriately //if the hole needs to fracture across horizontal partition boundary we need to notify //the calling context to do so if(solid) { //the chains are being joined because there is solid to the right //this means that if the figure is closed at this point it must be a hole //because otherwise it would have to have another vertex to the right of this one //and would not be closed at this point return at1; } else { //assert pG != 0 //the figure that was closed is a shell outBufferTmp.push_back(at1); at1->copyHoles(*at2); //there should not be holes on at2, but if there are, copy them over } return 0; } //join the two partial polygons into one large partial polygon at1->getTail()->joinTailToTail(*(at2->getTail())); *(at1->getOtherActiveTail()) = ActiveTail<Unit>(at1->getOtherTail(), at2->getOtherActiveTail()); *(at2->getOtherActiveTail()) = ActiveTail<Unit>(at2->getOtherTail(), at1->getOtherActiveTail()); int accumulate = at2->getPolyLineSize() + at1->getPolyLineSize(); (at1->getOtherActiveTail())->setPolyLineSize(accumulate); (at2->getOtherActiveTail())->setPolyLineSize(accumulate); at1->getOtherActiveTail()->copyHoles(*at1); at1->getOtherActiveTail()->copyHoles(*at2); destroyActiveTail(at1); destroyActiveTail(at2); return 0; } template <class TKey, class T> inline typename std::map<TKey, T>::iterator findAtNext(std::map<TKey, T>& theMap, typename std::map<TKey, T>::iterator pos, const TKey& key) { if(pos == theMap.end()) return theMap.find(key); //if they match the mapItr is pointing to the correct position if(pos->first < key) { return theMap.find(key); } if(pos->first > key) { return theMap.end(); } //else they are equal and no need to do anything to the iterator return pos; } // createActiveTailsAsPair is called in these two end cases of geometry // 1. lower left concave corner // ###| // ###| // ###|### // ###|### // 2. lower left convex corner // |### // |### // | // | // In case 1 there may be a hole propigated up from the bottom. If the fracture option is enabled // the two active tails that form the filament fracture line edges can become the new active tail pair // by pushing x and y onto them. Otherwise the hole simply needs to be associated to one of the new active tails // with add hole template <typename Unit> inline std::pair<ActiveTail<Unit>*, ActiveTail<Unit>*> createActiveTailsAsPair(Unit x, Unit y, bool solid, ActiveTail<Unit>* phole, bool fractureHoles) { ActiveTail<Unit>* at1 = 0; ActiveTail<Unit>* at2 = 0; if(!phole || !fractureHoles){ at1 = createActiveTail<Unit>(); at2 = createActiveTail<Unit>(); (*at1) = ActiveTail<Unit>(VERTICAL, x, solid, at2); (*at2) = ActiveTail<Unit>(HORIZONTAL, y, !solid, at1); //provide a function through activeTail class to provide this at1->getTail()->joinHeadToHead(*(at2->getTail())); at1->addPolyLineSize(1); at2->addPolyLineSize(1); if(phole) at1->addHole(phole, fractureHoles); //assert fractureHoles == false return std::pair<ActiveTail<Unit>*, ActiveTail<Unit>*>(at1, at2); } //assert phole is not null //assert fractureHoles is true if(phole->getOrient() == VERTICAL) { at2 = phole; } else { at2 = phole->getOtherActiveTail(); //should never be executed since orientation is expected to be vertical } //assert solid == false, we should be creating a corner with solid below and to the left if there was a hole at1 = at2->getOtherActiveTail(); //assert at1 is horizontal at1->pushCoordinate(x); //assert at2 is vertical at2->pushCoordinate(y); return std::pair<ActiveTail<Unit>*, ActiveTail<Unit>*>(at1, at2); } /* * | * | * = * |######## * |######## (add a new ActiveTail in the tailMap_). * |######## * |######## * |######## * = * | * | * * NOTE: Call this only if you are sure that the $ledege$ is not in the tailMap_ */ template<bool orientT, typename Unit, typename polygon_concept_type> inline void ScanLineToPolygonItrs<orientT, Unit, polygon_concept_type>:: insertNewLeftEdgeIntoTailMap(Unit currentX, Unit yBegin, Unit yEnd, typename std::map<Unit, ActiveTail<Unit> *>::iterator &hint){ ActiveTail<Unit> *currentTail = NULL; std::pair<ActiveTail<Unit>*, ActiveTail<Unit>*> tailPair = createActiveTailsAsPair(currentX, yBegin, true, currentTail, fractureHoles_); currentTail = tailPair.first; if(!tailMap_.empty()){ ++hint; } hint = tailMap_.insert(hint, std::make_pair(yBegin, tailPair.second)); currentTail->pushCoordinate(yEnd); ++hint; hint = tailMap_.insert(hint, std::make_pair(yEnd, currentTail)); } template<bool orientT, typename Unit, typename polygon_concept_type> inline void ScanLineToPolygonItrs<orientT, Unit, polygon_concept_type>:: closePartialSimplePolygon(Unit currentX, ActiveTail<Unit>*pfig, ActiveTail<Unit>*ppfig){ pfig->pushCoordinate(currentX); ActiveTail<Unit>::joinChains(pfig, ppfig, false, outputPolygons_); } /* * If the invariant is maintained correctly then left edges can do the * following. * * =### * ####### * ####### * ####### * ####### * =### * |### (input left edge) * |### * =### * ####### * ####### * =### */ template<bool orientT, typename Unit, typename polygon_concept_type> inline void ScanLineToPolygonItrs<orientT, Unit, polygon_concept_type>:: updatePartialSimplePolygonsWithLeftEdges(Unit currentX, const std::vector<interval_data<Unit> > &leftEdges, size_t vertexThreshold){ typename std::map<Unit, ActiveTail<Unit>* >::iterator succ, succ1; typename std::map<Unit, ActiveTail<Unit>* >::iterator pred, pred1, hint; Unit begin, end; ActiveTail<Unit> *pfig, *ppfig; std::pair<ActiveTail<Unit>*, ActiveTail<Unit>*> tailPair; size_t pfig_size = 0; hint = tailMap_.begin(); for(size_t i=0; i < leftEdges.size(); i++){ begin = leftEdges[i].get(LOW); end = leftEdges[i].get(HIGH); succ = findAtNext(tailMap_, hint, begin); pred = findAtNext(tailMap_, hint, end); if(succ != tailMap_.end() && pred != tailMap_.end()){ //CASE-1// //join the corresponding active tails// pfig = succ->second; ppfig = pred->second; pfig_size = pfig->getPolyLineSize() + ppfig->getPolyLineSize(); if(pfig_size >= vertexThreshold){ size_t bsize = pfig->getPolyLineSize(); size_t usize = ppfig->getPolyLineSize(); if(usize+2 < vertexThreshold){ //cut-off the lower piece (succ1, succ) join (succ1, pred)// succ1 = succ; --succ1; assert((succ1 != tailMap_.end()) && ((succ->second)->getOtherActiveTail() == succ1->second)); closePartialSimplePolygon(currentX, succ1->second, succ->second); tailPair = createActiveTailsAsPair<Unit>(currentX, succ1->first, true, NULL, fractureHoles_); //just update the succ1 with new ActiveTail<Unit>*// succ1->second = tailPair.second; ActiveTail<Unit>::joinChains(tailPair.first, pred->second, true, outputPolygons_); }else if(bsize+2 < vertexThreshold){ //cut-off the upper piece () join ()// pred1 = pred; ++pred1; assert(pred1 != tailMap_.end() && ((pred1->second)->getOtherActiveTail() == pred->second)); closePartialSimplePolygon(currentX, pred->second, pred1->second); //just update the pred1 with ActiveTail<Unit>* = pfig// pred1->second = pfig; pfig->pushCoordinate(currentX); pfig->pushCoordinate(pred1->first); }else{ //cut both and create an left edge between (pred->first, succ1)// succ1 = succ; --succ1; pred1 = pred; ++pred1; assert(pred1 != tailMap_.end() && succ1 != tailMap_.end()); assert((pred1->second)->getOtherActiveTail() == pred->second); assert((succ1->second)->getOtherActiveTail() == succ->second); closePartialSimplePolygon(currentX, succ1->second, succ->second); closePartialSimplePolygon(currentX, pred->second, pred1->second); tailPair = createActiveTailsAsPair<Unit>(currentX, succ1->first, true, NULL, fractureHoles_); succ1->second = tailPair.second; pred1->second = tailPair.first; (tailPair.first)->pushCoordinate(pred1->first); } }else{ //just join them with closing// pfig->pushCoordinate(currentX); ActiveTail<Unit>::joinChains(pfig, ppfig, true, outputPolygons_); } hint = pred; ++hint; tailMap_.erase(succ); tailMap_.erase(pred); }else if(succ == tailMap_.end() && pred != tailMap_.end()){ //CASE-2// //succ is missing in the map, first insert it into the map// tailPair = createActiveTailsAsPair<Unit>(currentX, begin, true, NULL, fractureHoles_); hint = pred; ++hint; hint = tailMap_.insert(hint, std::make_pair(begin, tailPair.second)); pfig = pred->second; pfig_size = pfig->getPolyLineSize() + 2; if(pfig_size >= vertexThreshold){ //cut-off piece from [pred, pred1] , add [begin, pred1]// pred1 = pred; ++pred1; assert((pred1 != tailMap_.end()) && ((pred1->second)->getOtherActiveTail() == pred->second)); closePartialSimplePolygon(currentX, pred->second, pred1->second); //update: we need left edge between (begin, pred1->first)// pred1->second = tailPair.first; (tailPair.first)->pushCoordinate(pred1->first); }else{ //just join// ActiveTail<Unit>::joinChains(tailPair.first, pfig, true, outputPolygons_); } tailMap_.erase(pred); }else if(succ != tailMap_.end() && pred == tailMap_.end()){ //CASE-3// //pred is missing in the map, first insert it into the map// hint = succ; ++hint; hint = tailMap_.insert(hint, std::make_pair(end, (ActiveTail<Unit> *) NULL)); pfig = succ->second; pfig_size = pfig->getPolyLineSize() + 2; if(pfig_size >= vertexThreshold){ //this figure needs cutting here// succ1 = succ; --succ1; assert((succ1 != tailMap_.end()) && (succ1->second == pfig->getOtherActiveTail())); ppfig = succ1->second; closePartialSimplePolygon(currentX, ppfig, pfig); //update: we need a left edge between (succ1->first, end)// tailPair = createActiveTailsAsPair<Unit>(currentX, succ1->first, true, NULL, fractureHoles_); succ1->second = tailPair.second; hint->second = tailPair.first; (tailPair.first)->pushCoordinate(end); }else{ //no cutting needed// hint->second = pfig; pfig->pushCoordinate(currentX); pfig->pushCoordinate(end); } tailMap_.erase(succ); }else{ //insert both pred and succ// insertNewLeftEdgeIntoTailMap(currentX, begin, end, hint); } } } template<bool orientT, typename Unit, typename polygon_concept_type> inline void ScanLineToPolygonItrs<orientT, Unit, polygon_concept_type>:: updatePartialSimplePolygonsWithRightEdges(Unit currentX, const std::vector<interval_data<Unit> > &rightEdges, size_t vertexThreshold) { typename std::map<Unit, ActiveTail<Unit>* >::iterator succ, pred, hint; std::pair<ActiveTail<Unit>*, ActiveTail<Unit>*> tailPair; Unit begin, end; size_t i = 0; //If rightEdges is non-empty Then tailMap_ is non-empty // assert(rightEdges.empty() || !tailMap_.empty() ); while( i < rightEdges.size() ){ //find the interval in the tailMap which contains this interval// pred = tailMap_.lower_bound(rightEdges[i].get(HIGH)); assert(pred != tailMap_.end()); succ = pred; --succ; assert(pred != succ); end = pred->first; begin = succ->first; //we now have a [begin, end] // bool found_solid_opening = false; bool erase_succ = true, erase_pred = true; Unit solid_opening_begin = 0; Unit solid_opening_end = 0; size_t j = i+1; ActiveTail<Unit> *pfig = succ->second; ActiveTail<Unit> *ppfig = pred->second; size_t partial_fig_size = pfig->getPolyLineSize(); //Invariant:// assert(succ->second && (pfig)->getOtherActiveTail() == ppfig); hint = succ; Unit key = rightEdges[i].get(LOW); if(begin != key){ found_solid_opening = true; solid_opening_begin = begin; solid_opening_end = key; } while(j < rightEdges.size() && rightEdges[j].get(HIGH) <= end){ if(rightEdges[j-1].get(HIGH) != rightEdges[j].get(LOW)){ if(!found_solid_opening){ found_solid_opening = true; solid_opening_begin = rightEdges[j-1].get(HIGH); solid_opening_end = rightEdges[j].get(LOW); }else{ ++hint; insertNewLeftEdgeIntoTailMap(currentX, rightEdges[j-1].get(HIGH), rightEdges[j].get(LOW), hint); } } j++; } //trailing edge// if(end != rightEdges[j-1].get(HIGH)){ if(!found_solid_opening){ found_solid_opening = true; solid_opening_begin = rightEdges[j-1].get(HIGH); solid_opening_end = end; }else{ // a solid opening has been found already, we need to insert a new left // between [rightEdges[j-1].get(HIGH), end] Unit lbegin = rightEdges[j-1].get(HIGH); tailPair = createActiveTailsAsPair<Unit>(currentX, lbegin, true, NULL, fractureHoles_); hint = tailMap_.insert(pred, std::make_pair(lbegin, tailPair.second)); pred->second = tailPair.first; (tailPair.first)->pushCoordinate(end); erase_pred = false; } } size_t vertex_delta = ((begin != solid_opening_begin) && (end != solid_opening_end)) ? 4 : 2; if(!found_solid_opening){ //just close the figure, TODO: call closePartialPolygon// pfig->pushCoordinate(currentX); ActiveTail<Unit>::joinChains(pfig, ppfig, false, outputPolygons_); hint = pred; ++hint; }else if(partial_fig_size+vertex_delta >= vertexThreshold){ //close the figure and add a pseudo left-edge// closePartialSimplePolygon(currentX, pfig, ppfig); assert(begin != solid_opening_begin || end != solid_opening_end); if(begin != solid_opening_begin && end != solid_opening_end){ insertNewLeftEdgeIntoTailMap(currentX, solid_opening_begin, solid_opening_end, hint); }else if(begin == solid_opening_begin){ //we just need to update the succ in the tailMap_// tailPair = createActiveTailsAsPair<Unit>(currentX, solid_opening_begin, true, NULL, fractureHoles_); succ->second = tailPair.second; hint = succ; ++hint; hint = tailMap_.insert(pred, std::make_pair(solid_opening_end, tailPair.first)); (tailPair.first)->pushCoordinate(solid_opening_end); erase_succ = false; }else{ //we just need to update the pred in the tailMap_// tailPair = createActiveTailsAsPair<Unit>(currentX, solid_opening_begin, true, NULL, fractureHoles_); hint = tailMap_.insert(pred, std::make_pair(solid_opening_begin, tailPair.second)); pred->second = tailPair.first; (tailPair.first)->pushCoordinate(solid_opening_end); erase_pred = false; } }else{ //continue the figure (by adding at-most two new vertices)// if(begin != solid_opening_begin){ pfig->pushCoordinate(currentX); pfig->pushCoordinate(solid_opening_begin); //insert solid_opening_begin// hint = succ; ++hint; hint = tailMap_.insert(hint, std::make_pair(solid_opening_begin, pfig)); }else{ erase_succ = false; } if(end != solid_opening_end){ std::pair<ActiveTail<Unit>*, ActiveTail<Unit>*> tailPair = createActiveTailsAsPair<Unit>(currentX, solid_opening_end, false, NULL, fractureHoles_); hint = pred; ++hint; hint = tailMap_.insert(hint, std::make_pair(solid_opening_end, tailPair.second)); ActiveTail<Unit>::joinChains(tailPair.first, ppfig, false, outputPolygons_); }else{ erase_pred = false; } } //Remove the pred and succ if necessary// if(erase_succ){ tailMap_.erase(succ); } if(erase_pred){ tailMap_.erase(pred); } i = j; } } // Maintains the following invariant: // a. All the partial polygons formed at any state can be closed // by a single edge. template<bool orientT, typename Unit, typename polygon_concept_type> inline void ScanLineToPolygonItrs<orientT, Unit, polygon_concept_type>:: maintainPartialSimplePolygonInvariant(iterator& beginOutput, iterator& endOutput, Unit currentX, const std::vector<interval_data<Unit> >& l, const std::vector<interval_data<Unit> >& r, size_t vertexThreshold) { clearOutput_(); if(!l.empty()){ updatePartialSimplePolygonsWithLeftEdges(currentX, l, vertexThreshold); } if(!r.empty()){ updatePartialSimplePolygonsWithRightEdges(currentX, r, vertexThreshold); } beginOutput = outputPolygons_.begin(); endOutput = outputPolygons_.end(); } //Process edges connects vertical input edges (right or left edges of figures) to horizontal edges stored as member //data of the scanline object. It also creates now horizontal edges as needed to construct figures from edge data. // //There are only 12 geometric end cases where the scanline intersects a horizontal edge and even fewer unique //actions to take: // 1. Solid on both sides of the vertical partition after the current position and space on both sides before // ###|### // ###|### // | // | // This case does not need to be handled because there is no vertical edge at the current x coordinate. // // 2. Solid on both sides of the vertical partition before the current position and space on both sides after // | // | // ###|### // ###|### // This case does not need to be handled because there is no vertical edge at the current x coordinate. // // 3. Solid on the left of the vertical partition after the current position and space elsewhere // ###| // ###| // | // | // The horizontal edge from the left is found and turns upward because of the vertical right edge to become // the currently active vertical edge. // // 4. Solid on the left of the vertical partion before the current position and space elsewhere // | // | // ###| // ###| // The horizontal edge from the left is found and joined to the currently active vertical edge. // // 5. Solid to the right above and below and solid to the left above current position. // ###|### // ###|### // |### // |### // The horizontal edge from the left is found and joined to the currently active vertical edge, // potentially closing a hole. // // 6. Solid on the left of the vertical partion before the current position and solid to the right above and below // |### // |### // ###|### // ###|### // The horizontal edge from the left is found and turns upward because of the vertical right edge to become // the currently active vertical edge. // // 7. Solid on the right of the vertical partition after the current position and space elsewhere // |### // |### // | // | // Create two new ActiveTails, one is added to the horizontal edges and the other becomes the vertical currentTail // // 8. Solid on the right of the vertical partion before the current position and space elsewhere // | // | // |### // |### // The currentTail vertical edge turns right and is added to the horizontal edges data // // 9. Solid to the right above and solid to the left above and below current position. // ###|### // ###|### // ###| // ###| // The currentTail vertical edge turns right and is added to the horizontal edges data // // 10. Solid on the left of the vertical partion above and below the current position and solid to the right below // ###| // ###| // ###|### // ###|### // Create two new ActiveTails, one is added to the horizontal edges data and the other becomes the vertical currentTail // // 11. Solid to the right above and solid to the left below current position. // |### // |### // ###| // ###| // The currentTail vertical edge joins the horizontal edge from the left (may close a polygon) // Create two new ActiveTails, one is added to the horizontal edges data and the other becomes the vertical currentTail // // 12. Solid on the left of the vertical partion above the current position and solid to the right below // ###| // ###| // |### // |### // The currentTail vertical edge turns right and is added to the horizontal edges data. // The horizontal edge from the left turns upward and becomes the currentTail vertical edge // template <bool orientT, typename Unit, typename polygon_concept_type> inline void ScanLineToPolygonItrs<orientT, Unit, polygon_concept_type>:: processEdges(iterator& beginOutput, iterator& endOutput, Unit currentX, std::vector<interval_data<Unit> >& leftEdges, std::vector<interval_data<Unit> >& rightEdges, size_t vertexThreshold) { clearOutput_(); typename std::map<Unit, ActiveTail<Unit>*>::iterator nextMapItr; //foreach edge unsigned int leftIndex = 0; unsigned int rightIndex = 0; bool bottomAlreadyProcessed = false; ActiveTail<Unit>* currentTail = 0; const Unit UnitMax = (std::numeric_limits<Unit>::max)(); if(vertexThreshold < (std::numeric_limits<size_t>::max)()){ maintainPartialSimplePolygonInvariant(beginOutput, endOutput, currentX, leftEdges, rightEdges, vertexThreshold); return; } nextMapItr = tailMap_.begin(); while(leftIndex < leftEdges.size() || rightIndex < rightEdges.size()) { interval_data<Unit> edges[2] = {interval_data<Unit> (UnitMax, UnitMax), interval_data<Unit> (UnitMax, UnitMax)}; bool haveNextEdge = true; if(leftIndex < leftEdges.size()) edges[0] = leftEdges[leftIndex]; else haveNextEdge = false; if(rightIndex < rightEdges.size()) edges[1] = rightEdges[rightIndex]; else haveNextEdge = false; bool trailingEdge = edges[1].get(LOW) < edges[0].get(LOW); interval_data<Unit> & edge = edges[trailingEdge]; interval_data<Unit> & nextEdge = edges[!trailingEdge]; //process this edge if(!bottomAlreadyProcessed) { //assert currentTail = 0 //process the bottom end of this edge typename std::map<Unit, ActiveTail<Unit>*>::iterator thisMapItr = findAtNext(tailMap_, nextMapItr, edge.get(LOW)); if(thisMapItr != tailMap_.end()) { //there is an edge in the map at the low end of this edge //it needs to turn upward and become the current tail ActiveTail<Unit>* tail = thisMapItr->second; if(currentTail) { //stitch currentTail into this tail currentTail = tail->addHole(currentTail, fractureHoles_); if(!fractureHoles_) currentTail->pushCoordinate(currentX); } else { currentTail = tail; currentTail->pushCoordinate(currentX); } //assert currentTail->getOrient() == VERTICAL nextMapItr = thisMapItr; //set nextMapItr to the next position after this one ++nextMapItr; //remove thisMapItr from the map tailMap_.erase(thisMapItr); } else { //there is no edge in the map at the low end of this edge //we need to create one and another one to be the current vertical tail //if this is a trailing edge then there is space to the right of the vertical edge //so pass the inverse of trailingEdge to indicate solid to the right std::pair<ActiveTail<Unit>*, ActiveTail<Unit>*> tailPair = createActiveTailsAsPair(currentX, edge.get(LOW), !trailingEdge, currentTail, fractureHoles_); currentTail = tailPair.first; tailMap_.insert(nextMapItr, std::pair<Unit, ActiveTail<Unit>*>(edge.get(LOW), tailPair.second)); // leave nextMapItr unchanged } } if(haveNextEdge && edge.get(HIGH) == nextEdge.get(LOW)) { //the top of this edge is equal to the bottom of the next edge, process them both bottomAlreadyProcessed = true; typename std::map<Unit, ActiveTail<Unit>*>::iterator thisMapItr = findAtNext(tailMap_, nextMapItr, edge.get(HIGH)); if(thisMapItr == tailMap_.end()) //assert this should never happen return; if(trailingEdge) { //geometry at this position // |## // |## // ----- // ##| // ##| //current tail should join thisMapItr tail ActiveTail<Unit>* tail = thisMapItr->second; //pass false because they are being joined because space is to the right and it will close a solid figure ActiveTail<Unit>::joinChains(currentTail, tail, false, outputPolygons_); //two new tails are created, the vertical becomes current tail, the horizontal becomes thisMapItr tail //pass true becuase they are created at the lower left corner of some solid //pass null because there is no hole pointer possible std::pair<ActiveTail<Unit>*, ActiveTail<Unit>*> tailPair = createActiveTailsAsPair<Unit>(currentX, edge.get(HIGH), true, 0, fractureHoles_); currentTail = tailPair.first; thisMapItr->second = tailPair.second; } else { //geometry at this position // ##| // ##| // ----- // |## // |## //current tail should turn right currentTail->pushCoordinate(edge.get(HIGH)); //thisMapItr tail should turn up thisMapItr->second->pushCoordinate(currentX); //thisMapItr tail becomes current tail and current tail becomes thisMapItr tail std::swap(currentTail, thisMapItr->second); } nextMapItr = thisMapItr; //set nextMapItr to the next position after this one ++nextMapItr; } else { //there is a gap between the top of this edge and the bottom of the next, process the top of this edge bottomAlreadyProcessed = false; //process the top of this edge typename std::map<Unit, ActiveTail<Unit>*>::iterator thisMapItr = findAtNext(tailMap_, nextMapItr, edge.get(HIGH)); if(thisMapItr != tailMap_.end()) { //thisMapItr is pointing to a horizontal edge in the map at the top of this vertical edge //we need to join them and potentially close a figure //assert currentTail != 0 ActiveTail<Unit>* tail = thisMapItr->second; //pass the opositve of trailing edge to mean that they are joined because of solid to the right currentTail = ActiveTail<Unit>::joinChains(currentTail, tail, !trailingEdge, outputPolygons_); nextMapItr = thisMapItr; //set nextMapItr to the next position after this one ++nextMapItr; if(currentTail) { //figure is not closed// Unit nextItrY = UnitMax; if(nextMapItr != tailMap_.end()) { nextItrY = nextMapItr->first; } //for it to be a hole this must have been a left edge Unit leftY = UnitMax; if(leftIndex + 1 < leftEdges.size()) leftY = leftEdges[leftIndex+1].get(LOW); Unit rightY = nextEdge.get(LOW); if(!haveNextEdge || (nextItrY < leftY && nextItrY < rightY)) { //we need to add it to the next edge above it in the map tail = nextMapItr->second; tail = tail->addHole(currentTail, fractureHoles_); if(fractureHoles_) { //some small additional work stitching in the filament tail->pushCoordinate(nextItrY); nextMapItr->second = tail; } //set current tail to null currentTail = 0; } } //delete thisMapItr from the map tailMap_.erase(thisMapItr); } else { //currentTail must turn right and be added into the map currentTail->pushCoordinate(edge.get(HIGH)); //assert currentTail->getOrient() == HORIZONTAL tailMap_.insert(nextMapItr, std::pair<Unit, ActiveTail<Unit>*>(edge.get(HIGH), currentTail)); //set currentTail to null currentTail = 0; //leave nextMapItr unchanged, it is still next } } //increment index leftIndex += !trailingEdge; rightIndex += trailingEdge; } //end while beginOutput = outputPolygons_.begin(); endOutput = outputPolygons_.end(); } //end function template<bool orientT, typename Unit, typename polygon_concept_type> inline void ScanLineToPolygonItrs<orientT, Unit, polygon_concept_type>::clearOutput_() { for(std::size_t i = 0; i < outputPolygons_.size(); ++i) { ActiveTail<Unit>* at1 = outputPolygons_[i].yield(); const std::list<ActiveTail<Unit>*>& holes = at1->getHoles(); for(typename std::list<ActiveTail<Unit>*>::const_iterator litr = holes.begin(); litr != holes.end(); ++litr) { //delete the hole (*litr)->destroyContents(); destroyActiveTail((*litr)->getOtherActiveTail()); destroyActiveTail((*litr)); } //delete the polygon at1->destroyContents(); //at2 contents are the same as at1, so it should not destroy them destroyActiveTail((at1)->getOtherActiveTail()); destroyActiveTail(at1); } outputPolygons_.clear(); } } //polygon_formation namespace template <bool orientT, typename Unit> struct geometry_concept<polygon_formation::PolyLinePolygonWithHolesData<orientT, Unit> > { typedef polygon_90_with_holes_concept type; }; template <bool orientT, typename Unit> struct geometry_concept<polygon_formation::PolyLineHoleData<orientT, Unit> > { typedef polygon_90_concept type; }; //public API to access polygon formation algorithm template <typename output_container, typename iterator_type, typename concept_type> unsigned int get_polygons(output_container& container, iterator_type begin, iterator_type end, orientation_2d orient, bool fracture_holes, concept_type, size_t sliceThreshold = (std::numeric_limits<size_t>::max)() ) { typedef typename output_container::value_type polygon_type; typedef typename std::iterator_traits<iterator_type>::value_type::first_type coordinate_type; polygon_type poly; unsigned int countPolygons = 0; typedef typename geometry_concept<polygon_type>::type polygon_concept_type; polygon_formation::ScanLineToPolygonItrs<true, coordinate_type, polygon_concept_type> scanlineToPolygonItrsV(fracture_holes); polygon_formation::ScanLineToPolygonItrs<false, coordinate_type, polygon_concept_type> scanlineToPolygonItrsH(fracture_holes); std::vector<interval_data<coordinate_type> > leftEdges; std::vector<interval_data<coordinate_type> > rightEdges; coordinate_type prevPos = (std::numeric_limits<coordinate_type>::max)(); coordinate_type prevY = (std::numeric_limits<coordinate_type>::max)(); int count = 0; for(iterator_type itr = begin; itr != end; ++ itr) { coordinate_type pos = (*itr).first; if(pos != prevPos) { if(orient == VERTICAL) { typename polygon_formation::ScanLineToPolygonItrs<true, coordinate_type, polygon_concept_type>::iterator itrPoly, itrPolyEnd; scanlineToPolygonItrsV.processEdges(itrPoly, itrPolyEnd, prevPos, leftEdges, rightEdges, sliceThreshold); for( ; itrPoly != itrPolyEnd; ++ itrPoly) { ++countPolygons; assign(poly, *itrPoly); container.insert(container.end(), poly); } } else { typename polygon_formation::ScanLineToPolygonItrs<false, coordinate_type, polygon_concept_type>::iterator itrPoly, itrPolyEnd; scanlineToPolygonItrsH.processEdges(itrPoly, itrPolyEnd, prevPos, leftEdges, rightEdges, sliceThreshold); for( ; itrPoly != itrPolyEnd; ++ itrPoly) { ++countPolygons; assign(poly, *itrPoly); container.insert(container.end(), poly); } } leftEdges.clear(); rightEdges.clear(); prevPos = pos; prevY = (*itr).second.first; count = (*itr).second.second; continue; } coordinate_type y = (*itr).second.first; if(count != 0 && y != prevY) { std::pair<interval_data<coordinate_type>, int> element(interval_data<coordinate_type>(prevY, y), count); if(element.second == 1) { if(leftEdges.size() && leftEdges.back().high() == element.first.low()) { encompass(leftEdges.back(), element.first); } else { leftEdges.push_back(element.first); } } else { if(rightEdges.size() && rightEdges.back().high() == element.first.low()) { encompass(rightEdges.back(), element.first); } else { rightEdges.push_back(element.first); } } } prevY = y; count += (*itr).second.second; } if(orient == VERTICAL) { typename polygon_formation::ScanLineToPolygonItrs<true, coordinate_type, polygon_concept_type>::iterator itrPoly, itrPolyEnd; scanlineToPolygonItrsV.processEdges(itrPoly, itrPolyEnd, prevPos, leftEdges, rightEdges, sliceThreshold); for( ; itrPoly != itrPolyEnd; ++ itrPoly) { ++countPolygons; assign(poly, *itrPoly); container.insert(container.end(), poly); } } else { typename polygon_formation::ScanLineToPolygonItrs<false, coordinate_type, polygon_concept_type>::iterator itrPoly, itrPolyEnd; scanlineToPolygonItrsH.processEdges(itrPoly, itrPolyEnd, prevPos, leftEdges, rightEdges, sliceThreshold); for( ; itrPoly != itrPolyEnd; ++ itrPoly) { ++countPolygons; assign(poly, *itrPoly); container.insert(container.end(), poly); } } return countPolygons; } } } #endif PK �b�[i� % detail/iterator_points_to_compact.hppnu �[��� /* Copyright 2008 Intel Corporation Use, modification and distribution are 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_POLYGON_ITERATOR_POINTS_TO_COMPACT_HPP #define BOOST_POLYGON_ITERATOR_POINTS_TO_COMPACT_HPP namespace boost { namespace polygon{ template <typename iT, typename point_type> class iterator_points_to_compact { private: iT iter_, iterEnd_; orientation_2d orient_; mutable typename point_traits<point_type>::coordinate_type coord_; public: typedef typename point_traits<point_type>::coordinate_type coordinate_type; typedef std::forward_iterator_tag iterator_category; typedef coordinate_type value_type; typedef std::ptrdiff_t difference_type; typedef const coordinate_type* pointer; //immutable typedef const coordinate_type& reference; //immutable inline iterator_points_to_compact() : iter_(), iterEnd_(), orient_(), coord_() {} inline iterator_points_to_compact(iT iter, iT iterEnd) : iter_(iter), iterEnd_(iterEnd), orient_(HORIZONTAL), coord_() {} inline iterator_points_to_compact(const iterator_points_to_compact& that) : iter_(that.iter_), iterEnd_(that.iterEnd_), orient_(that.orient_), coord_(that.coord_) {} //use bitwise copy and assign provided by the compiler inline iterator_points_to_compact& operator++() { //iT tmp = iter_; ++iter_; //iT tmp2 = iter_; orient_.turn_90(); //while(tmp2 != iterEnd_ && get(*tmp2, orient_) == get(*tmp, orient_)) { // iter_ = tmp2; // ++tmp2; //} return *this; } inline const iterator_points_to_compact operator++(int) { iT tmp(*this); ++(*this); return tmp; } inline bool operator==(const iterator_points_to_compact& that) const { return (iter_ == that.iter_); } inline bool operator!=(const iterator_points_to_compact& that) const { return (iter_ != that.iter_); } inline reference operator*() const { coord_ = get(*iter_, orient_); return coord_; } }; } } #endif PK �b�[M��2/ 2/ # detail/iterator_geometry_to_set.hppnu �[��� /* Copyright 2008 Intel Corporation Use, modification and distribution are 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_POLYGON_ITERATOR_GEOMETRY_TO_SET_HPP #define BOOST_POLYGON_ITERATOR_GEOMETRY_TO_SET_HPP namespace boost { namespace polygon{ template <typename concept_type, typename geometry_type> class iterator_geometry_to_set {}; template <typename rectangle_type> class iterator_geometry_to_set<rectangle_concept, rectangle_type> { public: typedef typename rectangle_traits<rectangle_type>::coordinate_type coordinate_type; typedef std::forward_iterator_tag iterator_category; typedef std::pair<coordinate_type, std::pair<coordinate_type, int> > value_type; typedef std::ptrdiff_t difference_type; typedef const value_type* pointer; //immutable typedef const value_type& reference; //immutable private: rectangle_data<coordinate_type> rectangle_; mutable value_type vertex_; unsigned int corner_; orientation_2d orient_; bool is_hole_; public: iterator_geometry_to_set() : rectangle_(), vertex_(), corner_(4), orient_(), is_hole_() {} iterator_geometry_to_set(const rectangle_type& rectangle, direction_1d dir, orientation_2d orient = HORIZONTAL, bool is_hole = false, bool = false, direction_1d = CLOCKWISE) : rectangle_(), vertex_(), corner_(0), orient_(orient), is_hole_(is_hole) { assign(rectangle_, rectangle); if(dir == HIGH) corner_ = 4; } inline iterator_geometry_to_set& operator++() { ++corner_; return *this; } inline const iterator_geometry_to_set operator++(int) { iterator_geometry_to_set tmp(*this); ++(*this); return tmp; } inline bool operator==(const iterator_geometry_to_set& that) const { return corner_ == that.corner_; } inline bool operator!=(const iterator_geometry_to_set& that) const { return !(*this == that); } inline reference operator*() const { if(corner_ == 0) { vertex_.first = get(get(rectangle_, orient_.get_perpendicular()), LOW); vertex_.second.first = get(get(rectangle_, orient_), LOW); vertex_.second.second = 1; if(is_hole_) vertex_.second.second *= -1; } else if(corner_ == 1) { vertex_.second.first = get(get(rectangle_, orient_), HIGH); vertex_.second.second = -1; if(is_hole_) vertex_.second.second *= -1; } else if(corner_ == 2) { vertex_.first = get(get(rectangle_, orient_.get_perpendicular()), HIGH); vertex_.second.first = get(get(rectangle_, orient_), LOW); } else { vertex_.second.first = get(get(rectangle_, orient_), HIGH); vertex_.second.second = 1; if(is_hole_) vertex_.second.second *= -1; } return vertex_; } }; template <typename polygon_type> class iterator_geometry_to_set<polygon_90_concept, polygon_type> { public: typedef typename polygon_traits<polygon_type>::coordinate_type coordinate_type; typedef std::forward_iterator_tag iterator_category; typedef std::pair<coordinate_type, std::pair<coordinate_type, int> > value_type; typedef std::ptrdiff_t difference_type; typedef const value_type* pointer; //immutable typedef const value_type& reference; //immutable typedef typename polygon_traits<polygon_type>::iterator_type coord_iterator_type; private: value_type vertex_; typename polygon_traits<polygon_type>::iterator_type itrb, itre; bool last_vertex_; bool is_hole_; int multiplier_; point_data<coordinate_type> first_pt, second_pt, pts[3]; bool use_wrap; orientation_2d orient_; int polygon_index; public: iterator_geometry_to_set() : vertex_(), itrb(), itre(), last_vertex_(), is_hole_(), multiplier_(), first_pt(), second_pt(), pts(), use_wrap(), orient_(), polygon_index(-1) {} iterator_geometry_to_set(const polygon_type& polygon, direction_1d dir, orientation_2d orient = HORIZONTAL, bool is_hole = false, bool winding_override = false, direction_1d w = CLOCKWISE) : vertex_(), itrb(), itre(), last_vertex_(), is_hole_(is_hole), multiplier_(), first_pt(), second_pt(), pts(), use_wrap(), orient_(orient), polygon_index(0) { itrb = begin_points(polygon); itre = end_points(polygon); use_wrap = false; if(itrb == itre || dir == HIGH || ::boost::polygon::size(polygon) < 4) { polygon_index = -1; } else { direction_1d wdir = w; if(!winding_override) wdir = winding(polygon); multiplier_ = wdir == LOW ? -1 : 1; if(is_hole_) multiplier_ *= -1; first_pt = pts[0] = *itrb; ++itrb; second_pt = pts[1] = *itrb; ++itrb; pts[2] = *itrb; evaluate_(); } } iterator_geometry_to_set(const iterator_geometry_to_set& that) : vertex_(), itrb(), itre(), last_vertex_(), is_hole_(), multiplier_(), first_pt(), second_pt(), pts(), use_wrap(), orient_(), polygon_index(-1) { vertex_ = that.vertex_; itrb = that.itrb; itre = that.itre; last_vertex_ = that.last_vertex_; is_hole_ = that.is_hole_; multiplier_ = that.multiplier_; first_pt = that.first_pt; second_pt = that.second_pt; pts[0] = that.pts[0]; pts[1] = that.pts[1]; pts[2] = that.pts[2]; use_wrap = that.use_wrap; orient_ = that.orient_; polygon_index = that.polygon_index; } inline iterator_geometry_to_set& operator++() { ++polygon_index; if(itrb == itre) { if(first_pt == pts[1]) polygon_index = -1; else { pts[0] = pts[1]; pts[1] = pts[2]; if(first_pt == pts[2]) { pts[2] = second_pt; } else { pts[2] = first_pt; } } } else { ++itrb; pts[0] = pts[1]; pts[1] = pts[2]; if(itrb == itre) { if(first_pt == pts[2]) { pts[2] = second_pt; } else { pts[2] = first_pt; } } else { pts[2] = *itrb; } } evaluate_(); return *this; } inline const iterator_geometry_to_set operator++(int) { iterator_geometry_to_set tmp(*this); ++(*this); return tmp; } inline bool operator==(const iterator_geometry_to_set& that) const { return polygon_index == that.polygon_index; } inline bool operator!=(const iterator_geometry_to_set& that) const { return !(*this == that); } inline reference operator*() const { return vertex_; } inline void evaluate_() { vertex_.first = pts[1].get(orient_.get_perpendicular()); vertex_.second.first =pts[1].get(orient_); if(pts[1] == pts[2]) { vertex_.second.second = 0; } else if(pts[0].get(HORIZONTAL) != pts[1].get(HORIZONTAL)) { vertex_.second.second = -1; } else if(pts[0].get(VERTICAL) != pts[1].get(VERTICAL)) { vertex_.second.second = 1; } else { vertex_.second.second = 0; } vertex_.second.second *= multiplier_; } }; template <typename polygon_with_holes_type> class iterator_geometry_to_set<polygon_90_with_holes_concept, polygon_with_holes_type> { public: typedef typename polygon_90_traits<polygon_with_holes_type>::coordinate_type coordinate_type; typedef std::forward_iterator_tag iterator_category; typedef std::pair<coordinate_type, std::pair<coordinate_type, int> > value_type; typedef std::ptrdiff_t difference_type; typedef const value_type* pointer; //immutable typedef const value_type& reference; //immutable private: iterator_geometry_to_set<polygon_90_concept, polygon_with_holes_type> itrb, itre; iterator_geometry_to_set<polygon_90_concept, typename polygon_with_holes_traits<polygon_with_holes_type>::hole_type> itrhib, itrhie; typename polygon_with_holes_traits<polygon_with_holes_type>::iterator_holes_type itrhb, itrhe; orientation_2d orient_; bool is_hole_; bool started_holes; public: iterator_geometry_to_set() : itrb(), itre(), itrhib(), itrhie(), itrhb(), itrhe(), orient_(), is_hole_(), started_holes() {} iterator_geometry_to_set(const polygon_with_holes_type& polygon, direction_1d dir, orientation_2d orient = HORIZONTAL, bool is_hole = false, bool = false, direction_1d = CLOCKWISE) : itrb(), itre(), itrhib(), itrhie(), itrhb(), itrhe(), orient_(orient), is_hole_(is_hole), started_holes() { itre = iterator_geometry_to_set<polygon_90_concept, polygon_with_holes_type>(polygon, HIGH, orient, is_hole_); itrhe = end_holes(polygon); if(dir == HIGH) { itrb = itre; itrhb = itrhe; started_holes = true; } else { itrb = iterator_geometry_to_set<polygon_90_concept, polygon_with_holes_type>(polygon, LOW, orient, is_hole_); itrhb = begin_holes(polygon); started_holes = false; } } iterator_geometry_to_set(const iterator_geometry_to_set& that) : itrb(), itre(), itrhib(), itrhie(), itrhb(), itrhe(), orient_(), is_hole_(), started_holes() { itrb = that.itrb; itre = that.itre; if(that.itrhib != that.itrhie) { itrhib = that.itrhib; itrhie = that.itrhie; } itrhb = that.itrhb; itrhe = that.itrhe; orient_ = that.orient_; is_hole_ = that.is_hole_; started_holes = that.started_holes; } inline iterator_geometry_to_set& operator++() { //this code can be folded with flow control factoring if(itrb == itre) { if(itrhib == itrhie) { if(itrhb != itrhe) { itrhib = iterator_geometry_to_set<polygon_90_concept, typename polygon_with_holes_traits<polygon_with_holes_type>::hole_type>(*itrhb, LOW, orient_, !is_hole_); itrhie = iterator_geometry_to_set<polygon_90_concept, typename polygon_with_holes_traits<polygon_with_holes_type>::hole_type>(*itrhb, HIGH, orient_, !is_hole_); ++itrhb; } else { //in this case we have no holes so we just need the iterhib == itrhie, which //is always true if they were default initialized in the initial case or //both point to end of the previous hole processed //no need to explicitly reset them, and it causes an stl debug assertion to use //the default constructed iterator this way //itrhib = itrhie = iterator_geometry_to_set<polygon_90_concept, // typename polygon_with_holes_traits<polygon_with_holes_type>::hole_type>(); } } else { ++itrhib; if(itrhib == itrhie) { if(itrhb != itrhe) { itrhib = iterator_geometry_to_set<polygon_90_concept, typename polygon_with_holes_traits<polygon_with_holes_type>::hole_type>(*itrhb, LOW, orient_, !is_hole_); itrhie = iterator_geometry_to_set<polygon_90_concept, typename polygon_with_holes_traits<polygon_with_holes_type>::hole_type>(*itrhb, HIGH, orient_, !is_hole_); ++itrhb; } else { //this is the same case as above //itrhib = itrhie = iterator_geometry_to_set<polygon_90_concept, // typename polygon_with_holes_traits<polygon_with_holes_type>::hole_type>(); } } } } else { ++itrb; if(itrb == itre) { if(itrhb != itrhe) { itrhib = iterator_geometry_to_set<polygon_90_concept, typename polygon_with_holes_traits<polygon_with_holes_type>::hole_type>(*itrhb, LOW, orient_, !is_hole_); itrhie = iterator_geometry_to_set<polygon_90_concept, typename polygon_with_holes_traits<polygon_with_holes_type>::hole_type>(*itrhb, HIGH, orient_, !is_hole_); ++itrhb; } } } return *this; } inline const iterator_geometry_to_set operator++(int) { iterator_geometry_to_set tmp(*this); ++(*this); return tmp; } inline bool operator==(const iterator_geometry_to_set& that) const { return itrb == that.itrb && itrhb == that.itrhb && itrhib == that.itrhib; } inline bool operator!=(const iterator_geometry_to_set& that) const { return !(*this == that); } inline reference operator*() const { if(itrb != itre) return *itrb; return *itrhib; } }; } } #endif PK �b�[�?Xe�"