/* 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