/* 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_INTERVAL_CONCEPT_HPP #define BOOST_POLYGON_INTERVAL_CONCEPT_HPP #include "isotropy.hpp" #include "interval_data.hpp" #include "interval_traits.hpp" namespace boost { namespace polygon{ struct interval_concept {}; template struct is_interval_concept { typedef gtl_no type; }; template <> struct is_interval_concept { typedef gtl_yes type; }; template struct is_mutable_interval_concept { typedef gtl_no type; }; template <> struct is_mutable_interval_concept { typedef gtl_yes type; }; template struct interval_coordinate_type_by_concept { typedef void type; }; template struct interval_coordinate_type_by_concept { typedef typename interval_traits::coordinate_type type; }; template struct interval_coordinate_type { typedef typename interval_coordinate_type_by_concept< T, typename is_interval_concept::type>::type>::type type; }; template struct interval_difference_type_by_concept { typedef void type; }; template struct interval_difference_type_by_concept { typedef typename coordinate_traits::coordinate_type>::coordinate_difference type; }; template struct interval_difference_type { typedef typename interval_difference_type_by_concept< T, typename is_interval_concept::type>::type>::type type; }; template typename interval_coordinate_type::type get(const T& interval, direction_1d dir, typename enable_if::type>::type>::type>::type * = 0 ) { return interval_traits::get(interval, dir); } template void set(T& interval, direction_1d dir, coordinate_type value, typename enable_if::type>::type>::type * = 0 ) { //this may need to be refined interval_mutable_traits::set(interval, dir, value); if(high(interval) < low(interval)) interval_mutable_traits::set(interval, dir.backward(), value); } template T construct(T2 low_value, T3 high_value, typename enable_if::type>::type>::type * = 0 ) { if(low_value > high_value) std::swap(low_value, high_value); return interval_mutable_traits::construct(low_value, high_value); } template T copy_construct(const T2& interval, typename enable_if< typename gtl_and::type>::type, typename is_interval_concept::type>::type>::type>::type * = 0 ) { return construct (get(interval, LOW ), get(interval, HIGH)); } template T1 & assign(T1& lvalue, const T2& rvalue, typename enable_if< typename gtl_and< typename is_mutable_interval_concept::type>::type, typename is_interval_concept::type>::type>::type>::type * = 0) { lvalue = copy_construct(rvalue); return lvalue; } template bool equivalence(const T& interval1, const T2& interval2, typename enable_if< typename gtl_and< typename is_interval_concept::type>::type, typename is_interval_concept::type>::type>::type>::type * = 0 ) { return get(interval1, LOW) == get(interval2, LOW) && get(interval1, HIGH) == get(interval2, HIGH); } struct y_i_contains : gtl_yes {}; template typename enable_if< typename gtl_and< y_i_contains, typename is_interval_concept::type>::type >::type, bool>::type contains(const interval_type& interval, typename interval_traits::coordinate_type value, bool consider_touch = true ) { if(consider_touch) { return value <= high(interval) && value >= low(interval); } else { return value < high(interval) && value > low(interval); } } template bool contains(const interval_type& interval, const interval_type_2& value, bool consider_touch = true, typename enable_if< typename gtl_and< typename is_interval_concept::type>::type, typename is_interval_concept::type>::type>::type>::type * = 0 ) { return contains(interval, get(value, LOW), consider_touch) && contains(interval, get(value, HIGH), consider_touch); } // get the low coordinate template typename interval_traits::coordinate_type low(const interval_type& interval, typename enable_if< typename is_interval_concept::type>::type>::type * = 0 ) { return get(interval, LOW); } // get the high coordinate template typename interval_traits::coordinate_type high(const interval_type& interval, typename enable_if< typename is_interval_concept::type>::type>::type * = 0 ) { return get(interval, HIGH); } // get the center coordinate template typename interval_traits::coordinate_type center(const interval_type& interval, typename enable_if< typename is_interval_concept::type>::type>::type * = 0 ) { return (high(interval) + low(interval))/2; } struct y_i_low : gtl_yes {}; // set the low coordinate to v template typename enable_if::type>::type>::type, void>::type low(interval_type& interval, typename interval_traits::coordinate_type v) { set(interval, LOW, v); } struct y_i_high : gtl_yes {}; // set the high coordinate to v template typename enable_if::type>::type>::type, void>::type high(interval_type& interval, typename interval_traits::coordinate_type v) { set(interval, HIGH, v); } // get the magnitude of the interval template typename interval_difference_type::type delta(const interval_type& interval, typename enable_if< typename is_interval_concept::type>::type>::type * = 0 ) { typedef typename coordinate_traits::coordinate_type>::coordinate_difference diffT; return (diffT)high(interval) - (diffT)low(interval); } struct y_i_flip : gtl_yes {}; // flip this about coordinate template typename enable_if::type>::type>::type, interval_type>::type & flip(interval_type& interval, typename interval_traits::coordinate_type axis = 0) { typename interval_traits::coordinate_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 {}; // scale interval by factor template typename enable_if::type>::type>::type, interval_type>::type & scale_up(interval_type& interval, typename coordinate_traits::coordinate_type>::unsigned_area_type factor) { typedef typename interval_traits::coordinate_type Unit; Unit newHigh = high(interval) * (Unit)factor; low(interval, low(interval) * (Unit)factor); high(interval, (newHigh)); return interval; } struct y_i_scale_down : gtl_yes {}; template typename enable_if::type>::type>::type, interval_type>::type & scale_down(interval_type& interval, typename coordinate_traits::coordinate_type>::unsigned_area_type factor) { typedef typename interval_traits::coordinate_type Unit; typedef typename coordinate_traits::coordinate_distance dt; Unit newHigh = scaling_policy::round((dt)(high(interval)) / (dt)factor); low(interval, scaling_policy::round((dt)(low(interval)) / (dt)factor)); high(interval, (newHigh)); return interval; } struct y_i_scale : gtl_yes {}; template typename enable_if::type>::type>::type, interval_type>::type & scale(interval_type& interval, double factor) { typedef typename interval_traits::coordinate_type Unit; Unit newHigh = scaling_policy::round((double)(high(interval)) * factor); low(interval, scaling_policy::round((double)low(interval)* factor)); high(interval, (newHigh)); return interval; } // move interval by delta template interval_type& move(interval_type& interval, typename interval_difference_type::type displacement, typename enable_if::type>::type>::type * = 0 ) { typedef typename interval_traits::coordinate_type ctype; typedef typename coordinate_traits::coordinate_difference Unit; Unit len = delta(interval); low(interval, static_cast(static_cast(low(interval)) + displacement)); high(interval, static_cast(static_cast(low(interval)) + len)); return interval; } struct y_i_convolve : gtl_yes {}; // convolve this with b template typename enable_if::type>::type>::type, interval_type>::type & convolve(interval_type& interval, typename interval_traits::coordinate_type b) { typedef typename interval_traits::coordinate_type Unit; Unit newLow = low(interval) + b; Unit newHigh = high(interval) + b; low(interval, newLow); high(interval, newHigh); return interval; } struct y_i_deconvolve : gtl_yes {}; // deconvolve this with b template typename enable_if::type>::type>::type, interval_type>::type & deconvolve(interval_type& interval, typename interval_traits::coordinate_type b) { typedef typename interval_traits::coordinate_type Unit; Unit newLow = low(interval) - b; Unit newHigh = high(interval) - b; low(interval, newLow); high(interval, newHigh); return interval; } struct y_i_convolve2 : gtl_yes {}; // convolve this with b template typename enable_if< typename gtl_and_3::type>::type, typename is_interval_concept::type>::type>::type, interval_type>::type & convolve(interval_type& interval, const interval_type_2& b) { typedef typename interval_traits::coordinate_type Unit; Unit newLow = low(interval) + low(b); Unit newHigh = high(interval) + high(b); low(interval, newLow); high(interval, newHigh); return interval; } struct y_i_deconvolve2 : gtl_yes {}; // deconvolve this with b template typename enable_if< typename gtl_and_3< y_i_deconvolve2, typename is_mutable_interval_concept::type>::type, typename is_interval_concept::type>::type>::type, interval_type>::type & deconvolve(interval_type& interval, const interval_type_2& b) { typedef typename interval_traits::coordinate_type Unit; Unit newLow = low(interval) - low(b); Unit newHigh = high(interval) - high(b); low(interval, newLow); high(interval, newHigh); return interval; } struct y_i_reconvolve : gtl_yes {}; // reflected convolve this with b template typename enable_if< typename gtl_and_3::type>::type, typename is_interval_concept::type>::type>::type, interval_type>::type & reflected_convolve(interval_type& interval, const interval_type_2& b) { typedef typename interval_traits::coordinate_type Unit; Unit newLow = low(interval) - high(b); Unit newHigh = high(interval) - low(b); low(interval, newLow); high(interval, newHigh); return interval; } struct y_i_redeconvolve : gtl_yes {}; // reflected deconvolve this with b template typename enable_if< typename gtl_and_3< y_i_redeconvolve, typename is_mutable_interval_concept::type>::type, typename is_interval_concept::type>::type>::type, interval_type>::type & reflected_deconvolve(interval_type& interval, const interval_type_2& b) { typedef typename interval_traits::coordinate_type Unit; Unit newLow = low(interval) + high(b); Unit newHigh = high(interval) + low(b); low(interval, newLow); high(interval, newHigh); return interval; } struct y_i_e_dist1 : gtl_yes {}; // distance from a coordinate to an interval template typename enable_if< typename gtl_and::type>::type>::type, typename interval_difference_type::type>::type euclidean_distance(const interval_type& interval, typename interval_traits::coordinate_type position) { typedef typename coordinate_traits::coordinate_type>::coordinate_difference 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 {}; // distance between two intervals template typename enable_if< typename gtl_and_3::type>::type, typename is_interval_concept::type>::type>::type, typename interval_difference_type::type>::type euclidean_distance(const interval_type& interval, const interval_type_2& b) { typedef typename coordinate_traits::coordinate_type>::coordinate_difference Unit; Unit dist[3] = {0, (Unit)low(interval) - (Unit)high(b), (Unit)low(b) - (Unit)high(interval)}; return dist[ (dist[1] > 0) + ((dist[2] > 0) << 1) ]; } struct y_i_e_intersects : gtl_yes {}; // check if Interval b intersects `this` Interval template typename enable_if< typename gtl_and_3::type>::type, typename is_interval_concept::type>::type>::type, bool>::type intersects(const interval_type& interval, const interval_type_2& b, bool consider_touch = true) { return consider_touch ? (low(interval) <= high(b)) & (high(interval) >= low(b)) : (low(interval) < high(b)) & (high(interval) > low(b)); } struct y_i_e_bintersect : gtl_yes {}; // check if Interval b partially overlaps `this` Interval template typename enable_if< typename gtl_and_3::type>::type, typename is_interval_concept::type>::type>::type, bool>::type boundaries_intersect(const interval_type& interval, const interval_type_2& b, bool consider_touch = true) { return (contains(interval, low(b), consider_touch) || contains(interval, high(b), consider_touch)) && (contains(b, low(interval), consider_touch) || contains(b, high(interval), consider_touch)); } struct y_i_abuts1 : gtl_yes {}; // check if they are end to end template typename enable_if< typename gtl_and_3::type>::type, typename is_interval_concept::type>::type>::type, bool>::type abuts(const interval_type& interval, const interval_type_2& b, direction_1d dir) { return dir.to_int() ? low(b) == high(interval) : low(interval) == high(b); } struct y_i_abuts2 : gtl_yes {}; // check if they are end to end template typename enable_if< typename gtl_and_3::type>::type, typename is_interval_concept::type>::type>::type, bool>::type abuts(const interval_type& interval, const interval_type_2& b) { return abuts(interval, b, HIGH) || abuts(interval, b, LOW); } struct y_i_intersect : gtl_yes {}; // set 'this' interval to the intersection of 'this' and b template typename enable_if< typename gtl_and_3::type>::type, typename is_interval_concept::type>::type>::type, bool>::type intersect(interval_type& interval, const interval_type_2& b, bool consider_touch = true) { typedef typename interval_traits::coordinate_type Unit; Unit lowVal = (std::max)(low(interval), low(b)); Unit highVal = (std::min)(high(interval), high(b)); bool valid = consider_touch ? lowVal <= highVal : lowVal < highVal; if(valid) { low(interval, lowVal); high(interval, highVal); } return valid; } struct y_i_g_intersect : gtl_yes {}; // set 'this' interval to the generalized intersection of 'this' and b template typename enable_if< typename gtl_and_3::type>::type, typename is_interval_concept::type>::type>::type, interval_type>::type & generalized_intersect(interval_type& interval, const interval_type_2& b) { typedef typename interval_traits::coordinate_type Unit; Unit coords[4] = {low(interval), high(interval), low(b), high(b)}; //consider implementing faster sorting of small fixed length range gtlsort(coords, coords+4); low(interval, coords[1]); high(interval, coords[2]); return interval; } struct y_i_bloat : gtl_yes {}; // bloat the Interval template typename enable_if< typename gtl_and::type>::type>::type, interval_type>::type & bloat(interval_type& interval, typename interval_traits::coordinate_type bloating) { low(interval, low(interval)-bloating); high(interval, high(interval)+bloating); return interval; } struct y_i_bloat2 : gtl_yes {}; // bloat the specified side of `this` Interval template typename enable_if< typename gtl_and::type>::type>::type, interval_type>::type & bloat(interval_type& interval, direction_1d dir, typename interval_traits::coordinate_type bloating) { set(interval, dir, get(interval, dir) + dir.get_sign() * bloating); return interval; } struct y_i_shrink : gtl_yes {}; // shrink the Interval template typename enable_if< typename gtl_and::type>::type>::type, interval_type>::type & shrink(interval_type& interval, typename interval_traits::coordinate_type shrinking) { return bloat(interval, -shrinking); } struct y_i_shrink2 : gtl_yes {}; // shrink the specified side of `this` Interval template typename enable_if< typename gtl_and::type>::type>::type, interval_type>::type & shrink(interval_type& interval, direction_1d dir, typename interval_traits::coordinate_type shrinking) { return bloat(interval, dir, -shrinking); } // Enlarge `this` Interval to encompass the specified Interval template bool encompass(interval_type& interval, const interval_type_2& b, typename enable_if< typename gtl_and< typename is_mutable_interval_concept::type>::type, typename is_interval_concept::type>::type>::type>::type * = 0 ) { bool retval = !contains(interval, b, true); low(interval, (std::min)(low(interval), low(b))); high(interval, (std::max)(high(interval), high(b))); return retval; } struct y_i_encompass : gtl_yes {}; // Enlarge `this` Interval to encompass the specified Interval template typename enable_if< typename gtl_and::type>::type>::type, bool>::type encompass(interval_type& interval, typename interval_traits::coordinate_type b) { bool retval = !contains(interval, b, true); low(interval, (std::min)(low(interval), b)); high(interval, (std::max)(high(interval), b)); return retval; } struct y_i_get_half : gtl_yes {}; // gets the half of the interval as an interval template typename enable_if::type>::type>::type, interval_type>::type get_half(const interval_type& interval, direction_1d d1d) { typedef typename interval_traits::coordinate_type Unit; Unit c = (get(interval, LOW) + get(interval, HIGH)) / 2; return construct((d1d == LOW) ? get(interval, LOW) : c, (d1d == LOW) ? c : get(interval, HIGH)); } struct y_i_join_with : gtl_yes {}; // returns true if the 2 intervals exactly touch at one value, like in l1 <= h1 == l2 <= h2 // sets the argument to the joined interval template typename enable_if< typename gtl_and_3::type>::type, typename is_interval_concept::type>::type>::type, bool>::type join_with(interval_type& interval, const interval_type_2& b) { if(abuts(interval, b)) { encompass(interval, b); return true; } return false; } template template interval_data& interval_data::operator=(const T2& rvalue) { assign(*this, rvalue); return *this; } template struct geometry_concept > { typedef interval_concept type; }; } } #endif