From f2a3351f7bcfaa3656d7e8ec6afca843bd7f857b Mon Sep 17 00:00:00 2001 From: Luke Simonson Date: Mon, 25 Jul 2011 05:47:00 +0000 Subject: [PATCH] adding directed line segment concept [SVN r73349] --- .../polygon/directed_line_segment_concept.hpp | 454 ++++++++++++++++++ .../polygon/directed_line_segment_data.hpp | 69 +++ .../polygon/directed_line_segment_traits.hpp | 42 ++ include/boost/polygon/polygon.hpp | 4 + 4 files changed, 569 insertions(+) create mode 100644 include/boost/polygon/directed_line_segment_concept.hpp create mode 100644 include/boost/polygon/directed_line_segment_data.hpp create mode 100644 include/boost/polygon/directed_line_segment_traits.hpp mode change 100755 => 100644 include/boost/polygon/polygon.hpp diff --git a/include/boost/polygon/directed_line_segment_concept.hpp b/include/boost/polygon/directed_line_segment_concept.hpp new file mode 100644 index 0000000..436b928 --- /dev/null +++ b/include/boost/polygon/directed_line_segment_concept.hpp @@ -0,0 +1,454 @@ +/* + 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_DIRECTED_LINE_SEGMENT_CONCEPT_HPP +#define BOOST_POLYGON_DIRECTED_LINE_SEGMENT_CONCEPT_HPP +#include "isotropy.hpp" +#include "directed_line_segment_data.hpp" +#include "directed_line_segment_traits.hpp" +#include "rectangle_concept.hpp" +#include "detail/polygon_arbitrary_formation.hpp" + +namespace boost { namespace polygon{ + struct directed_line_segment_concept {}; + + template + struct is_directed_line_segment_concept { typedef gtl_no type; }; + template <> + struct is_directed_line_segment_concept { typedef gtl_yes type; }; + + template + struct is_mutable_directed_line_segment_concept { typedef gtl_no type; }; + template <> + struct is_mutable_directed_line_segment_concept { typedef gtl_yes type; }; + + template + struct directed_line_segment_distance_type_by_concept { typedef void type; }; + template + struct directed_line_segment_distance_type_by_concept { + typedef typename coordinate_traits::coordinate_type>::coordinate_distance type; }; + + template + struct directed_line_segment_distance_type { + typedef typename directed_line_segment_distance_type_by_concept< + T, typename is_directed_line_segment_concept::type>::type>::type type; + }; + + template + struct directed_line_segment_point_type_by_concept { typedef void type; }; + template + struct directed_line_segment_point_type_by_concept { + typedef typename directed_line_segment_traits::point_type type; }; + + template + struct directed_line_segment_point_type { + typedef typename directed_line_segment_point_type_by_concept< + T, typename is_directed_line_segment_concept::type>::type>::type type; + }; + + template + struct directed_line_segment_coordinate_type_by_concept { typedef void type; }; + template + struct directed_line_segment_coordinate_type_by_concept { + typedef typename directed_line_segment_traits::coordinate_type type; }; + + template + struct directed_line_segment_coordinate_type { + typedef typename directed_line_segment_coordinate_type_by_concept< + T, typename is_directed_line_segment_concept::type>::type>::type type; + }; + + template + typename directed_line_segment_point_type::type + get(const T& segment, direction_1d dir, + typename enable_if::type>::type>::type>::type * = 0 + ) { + return directed_line_segment_traits::get(segment, dir); + } + + template + void + set(T& segment, direction_1d dir, point_type value, + typename enable_if::type>::type>::type * = 0 + ) { + directed_line_segment_mutable_traits::set(segment, dir, value); + } + + template + T + construct(T2 low_value, T3 high_value, + typename enable_if::type>::type>::type * = 0 + ) { + return directed_line_segment_mutable_traits::construct(low_value, high_value); + } + + template + T + copy_construct(const T2& segment, + typename enable_if< typename gtl_and::type>::type, + typename is_directed_line_segment_concept::type>::type>::type>::type * = 0 + ) { + return construct + (get(segment, LOW ), + get(segment, HIGH)); + } + + template + T1 & + assign(T1& lvalue, const T2& rvalue, + typename enable_if< typename gtl_and< typename is_mutable_directed_line_segment_concept::type>::type, + typename is_directed_line_segment_concept::type>::type>::type>::type * = 0) { + lvalue = copy_construct(rvalue); + return lvalue; + } + + template + bool + equivalence(const T& segment1, const T2& segment2, + typename enable_if< typename gtl_and< typename is_directed_line_segment_concept::type>::type, + typename is_directed_line_segment_concept::type>::type>::type>::type * = 0 + ) { + return get(segment1, LOW) == + get(segment2, LOW) && + get(segment1, HIGH) == + get(segment2, HIGH); + } + + struct y_dls_on_above_or_below : gtl_yes {}; + + //-1 for below, 0 for on and 1 for above + template + typename enable_if< typename gtl_and< y_dls_on_above_or_below, typename is_directed_line_segment_concept::type>::type >::type, bool>::type + on_above_or_below(const segment_type& segment, + typename directed_line_segment_traits::point_type value) { + typedef polygon_arbitrary_formation::coordinate_type> paf; + typename paf::Point pt, l, h; + assign(pt, value); + assign(l, low(segment)); + assign(h, high(segment)); + return paf::on_above_or_below(pt, typename paf::half_edge(l, h)); + } + + struct y_dls_contains : gtl_yes {}; + + template + typename enable_if< typename gtl_and< y_dls_contains, typename is_directed_line_segment_concept::type>::type >::type, bool>::type + contains(const segment_type& segment, + typename directed_line_segment_traits::point_type value, + bool consider_touch = true ) { + if(on_above_or_below(segment, value) == 0) { + rectangle_data::coordinate_type> rect; + set_points(rect, low(segment), high(segment)); + return contains(rect, value, consider_touch); + } + return false; + } + + template + bool + contains(const segment_type& segment, + const segment_type_2& value, bool consider_touch = true, + typename enable_if< typename gtl_and< typename is_directed_line_segment_concept::type>::type, + typename is_directed_line_segment_concept::type>::type>::type>::type * = 0 + ) { + return contains(segment, get(value, LOW), consider_touch) && + contains(segment, get(value, HIGH), consider_touch); + } + + // get the low point + template + typename directed_line_segment_point_type::type + low(const segment_type& segment, + typename enable_if< typename is_directed_line_segment_concept::type>::type>::type * = 0 + ) { return get(segment, LOW); } + + // get the high point + template + typename directed_line_segment_point_type::type + high(const segment_type& segment, + typename enable_if< typename is_directed_line_segment_concept::type>::type>::type * = 0 + ) { return get(segment, HIGH); } + + // get the center point + template + typename directed_line_segment_point_type::type + center(const segment_type& segment, + typename enable_if< typename is_directed_line_segment_concept::type>::type>::type * = 0 + ) { + return construct::point_type>((x(high(segment)) + x(low(segment)))/2, + (y(high(segment)) + y(low(segment)))/2); + + } + + struct y_dls_low : gtl_yes {}; + + // set the low point to v + template + typename enable_if::type>::type>::type, void>::type + low(segment_type& segment, + typename directed_line_segment_traits::point_type v) { set(segment, LOW, v); } + + struct y_dls_high : gtl_yes {}; + + // set the high coordinate to v + template + typename enable_if::type>::type>::type, void>::type + high(segment_type& segment, + typename directed_line_segment_traits::point_type v) { set(segment, HIGH, v); } + + template + typename directed_line_segment_distance_type::type + length(const segment_type& segment, + typename enable_if< typename is_directed_line_segment_concept::type>::type>::type * = 0 + ) { return euclidean_distance(low(segment), high(segment)); } + + struct y_dls_flip : gtl_yes {}; + + struct y_dls_scale_up : gtl_yes {}; + + // scale segment by factor + template + typename enable_if::type>::type>::type, segment_type>::type & + scale_up(segment_type& segment, + typename coordinate_traits::coordinate_type>::unsigned_area_type factor) { + typename directed_line_segment_point_type::type l = low(segment), h = high(segment); + low(segment, scale_up(l, factor)); + high(segment, scale_up(h, factor)); + return segment; + } + + struct y_dls_scale_down : gtl_yes {}; + + template + typename enable_if::type>::type>::type, segment_type>::type & + scale_down(segment_type& segment, + typename coordinate_traits::coordinate_type>::unsigned_area_type factor) { + typename directed_line_segment_point_type::type l = low(segment), h = high(segment); + low(segment, scale_down(l, factor)); + high(segment, scale_down(h, factor)); + return segment; + } + + struct y_dls_scale : gtl_yes {}; + + template + typename enable_if::type>::type>::type, segment_type>::type & + scale(segment_type& segment, scaling_type factor) { + typename directed_line_segment_point_type::type l = low(segment), h = high(segment); + low(segment, scale(l, factor)); + high(segment, scale(h, factor)); + return segment; + } + + + struct y_dls_transform : gtl_yes {}; + + template + typename enable_if::type>::type>::type, segment_type>::type & + transform(segment_type& segment, const transform_type& val) { + typename directed_line_segment_point_type::type l = low(segment), h = high(segment); + low(segment, transform(l, val)); + high(segment, transform(h, val)); + return segment; + } + // move segment by delta + template + segment_type& + move(segment_type& segment, orientation_2d orient, + typename directed_line_segment_coordinate_type::type displacement, + typename enable_if::type>::type>::type * = 0 + ) { + typename directed_line_segment_point_type::type l = low(segment), h = high(segment); + low(segment, move(l, orient, displacement)); + high(segment, move(h, orient, displacement)); + return segment; + } + + struct y_dls_convolve : gtl_yes {}; + + // convolve this with b + template + typename enable_if::type>::type>::type, segment_type>::type & + convolve(segment_type& segment, + const typename directed_line_segment_traits::point_type& b) { + typename directed_line_segment_point_type::type l = low(segment), h = high(segment); + low(segment, convolve(l, b)); + high(segment, convolve(h, b)); + return segment; + } + + struct y_dls_deconvolve : gtl_yes {}; + + // deconvolve this with b + template + typename enable_if::type>::type>::type, segment_type>::type & + deconvolve(segment_type& segment, + const typename directed_line_segment_traits::point_type& b) { + typename directed_line_segment_point_type::type l = low(segment), h = high(segment); + low(segment, deconvolve(l, b)); + high(segment, deconvolve(h, b)); + return segment; + } + + struct y_dls_e_dist1 : gtl_yes {}; + + // distance from a point to a segment + template + typename enable_if< typename gtl_and::type>::type>::type, + typename directed_line_segment_distance_type::type>::type + euclidean_distance(const segment_type& segment, + typename directed_line_segment_traits::point_type position) { + typedef typename directed_line_segment_distance_type::type Unit; + Unit result1 = euclidean_distance(low(segment), high(segment)); + Unit result2 = euclidean_distance(low(segment), position); + Unit result3 = euclidean_distance(high(segment), position); + if(result2 > result1) { + if(result3*result3 < result2*result2 - result1*result1) + return result3; + } + else if(result3 > result1) { + if(result2*result2 < result3*result3 - result1*result1) + return result2; + } + if(on_above_or_below(segment, position) == 0) + return 0.0; //I don't want to return non-zero distance if the predicate returns on the line + Unit x1 = x(low(segment)); + Unit y1 = y(low(segment)); + Unit x2 = x(high(segment)); + Unit y2 = y(high(segment)); + Unit X = x(position); + Unit Y = y(position); + Unit A = X - x1; + Unit B = Y - y1; + Unit C = x2 - x1; + Unit D = y2 - y1; + Unit denom = sqrt(C * C + D * D); + if(denom == 0.0) + return 0.0; + Unit result = (A * D - C * B) / denom; + if(result < 0.0) + result *= -1; + return result; + } + + struct y_dls_e_dist2 : gtl_yes {}; + + // distance between two segments + template + typename enable_if< + typename gtl_and_3::type>::type, + typename is_directed_line_segment_concept::type>::type>::type, + typename directed_line_segment_distance_type::type>::type + euclidean_distance(const segment_type& segment, + const segment_type_2& b) { + typename directed_line_segment_distance_type::type result1 = euclidean_distance(segment, low(b)), + result2 = euclidean_distance(segment, high(b)); + if(result2 < result1) result1 = result2; + return result1; + } + + struct y_dls_e_intersects : gtl_yes {}; + + // check if Interval b intersects `this` Interval + template + typename enable_if< typename gtl_and_3::type>::type, + typename is_directed_line_segment_concept::type>::type + >::type, bool> ::type + intersects(const segment_type& segment, const segment_type_2& b, bool consider_touch = true) { + if(consider_touch) { + if(low(segment) == low(b) || low(segment) == high(b) || high(segment) == low(b) || high(segment) == high(b)) + return true; + } + typedef polygon_arbitrary_formation::coordinate_type> paf; + typename paf::Point l, h, l2, h2; + assign(l, low(segment)); + assign(h, high(segment)); + assign(l2, low(b)); + assign(h2, high(b)); + return paf::intersects(typename paf::half_edge(l, h), typename paf::half_edge(l2, h2)); + } + + struct y_dls_e_bintersect : gtl_yes {}; + + // check if Interval b partially overlaps `this` Interval + template + typename enable_if< + typename gtl_and_3::type>::type, + typename is_directed_line_segment_concept::type>::type>::type, + bool>::type + boundaries_intersect(const segment_type& segment, const segment_type_2& b, + bool consider_touch = true) { + return (contains(segment, low(b), consider_touch) || + contains(segment, high(b), consider_touch)) && + (contains(b, low(segment), consider_touch) || + contains(b, high(segment), consider_touch)); + } + + struct y_dls_abuts1 : gtl_yes {}; + + // check if they are end to end + template + typename enable_if< typename gtl_and_3::type>::type, + typename is_directed_line_segment_concept::type>::type>::type, + bool>::type + abuts(const segment_type& segment, const segment_type_2& b, direction_1d dir) { + return dir.to_int() ? equivalence(low(b) , high(segment)) : equivalence(low(segment) , high(b)); + } + + struct y_dls_abuts2 : gtl_yes {}; + + // check if they are end to end + template + typename enable_if< + typename gtl_and_3::type>::type, + typename is_directed_line_segment_concept::type>::type>::type, + bool>::type + abuts(const segment_type& segment, const segment_type_2& b) { + return abuts(segment, b, HIGH) || abuts(segment, b, LOW); + } + + struct y_dls_intersect : gtl_yes {}; + + // set point to the intersection of segment and b + template + typename enable_if< typename gtl_and_4::type>::type, + typename is_directed_line_segment_concept::type>::type, + typename is_directed_line_segment_concept::type>::type>::type, + bool>::type + intersection(point_type& intersection, const segment_type& segment, const segment_type_2& b, + bool projected = false, bool round_closest = false) { + typedef polygon_arbitrary_formation::coordinate_type> paf; + typename paf::Point pt; + typename paf::Point l, h, l2, h2; + assign(l, low(segment)); + assign(h, high(segment)); + assign(l2, low(b)); + assign(h2, high(b)); + typename paf::half_edge he1(l, h), he2(l2, h2); + typename paf::compute_intersection_pack pack; + if(pack.compute_intersection(pt, he1, he2, projected, round_closest)) { + assign(intersection, pt); + return true; + } + return false; + } + + template + template + directed_line_segment_data& directed_line_segment_data::operator=(const T2& rvalue) { + assign(*this, rvalue); + return *this; + } + + template + struct geometry_concept > { + typedef directed_line_segment_concept type; + }; +} +} +#endif diff --git a/include/boost/polygon/directed_line_segment_data.hpp b/include/boost/polygon/directed_line_segment_data.hpp new file mode 100644 index 0000000..670a6f5 --- /dev/null +++ b/include/boost/polygon/directed_line_segment_data.hpp @@ -0,0 +1,69 @@ +/* + 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_DIRECTED_LINE_SEGMENT_DATA_HPP +#define BOOST_POLYGON_DIRECTED_LINE_SEGMENT_DATA_HPP +#include "isotropy.hpp" +#include "point_data.hpp" +namespace boost { namespace polygon{ + template + class directed_line_segment_data { + public: + typedef T coordinate_type; + typedef point_data point_type; + inline directed_line_segment_data() +#ifndef BOOST_POLYGON_MSVC + :points_() +#endif + {} + inline directed_line_segment_data(point_type low, point_type high) +#ifndef BOOST_POLYGON_MSVC + :points_() +#endif + { + points_[LOW] = low; points_[HIGH] = high; + } + inline directed_line_segment_data(const directed_line_segment_data& that) +#ifndef BOOST_POLYGON_MSVC + :points_() +#endif + { + (*this) = that; + } + inline directed_line_segment_data& operator=(const directed_line_segment_data& that) { + points_[0] = that.points_[0]; points_[1] = that.points_[1]; return *this; + } + template + inline directed_line_segment_data& operator=(const T2& rvalue); + inline point_type get(direction_1d dir) const { + return points_[dir.to_int()]; + } + inline point_type low() const { return points_[0]; } + inline point_type high() const { return points_[1]; } + inline bool operator==(const directed_line_segment_data& that) const { + return low() == that.low() && high() == that.high(); } + inline bool operator!=(const directed_line_segment_data& that) const { + return low() != that.low() || high() != that.high(); } + inline bool operator<(const directed_line_segment_data& that) const { + if(points_[0] < that.points_[0]) return true; + if(points_[0] > that.points_[0]) return false; + if(points_[1] < that.points_[1]) return true; + return false; + } + inline bool operator<=(const directed_line_segment_data& that) const { return !(that < *this); } + inline bool operator>(const directed_line_segment_data& that) const { return that < *this; } + inline bool operator>=(const directed_line_segment_data& that) const { return !((*this) < that); } + inline void set(direction_1d dir, point_type value) { + points_[dir.to_int()] = value; + } +private: + point_type points_[2]; +}; + +} +} +#endif diff --git a/include/boost/polygon/directed_line_segment_traits.hpp b/include/boost/polygon/directed_line_segment_traits.hpp new file mode 100644 index 0000000..56fc077 --- /dev/null +++ b/include/boost/polygon/directed_line_segment_traits.hpp @@ -0,0 +1,42 @@ +/* + 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_DIRECTED_LINE_SEGMENT_TRAITS_HPP +#define BOOST_POLYGON_DIRECTED_LINE_SEGMENT_TRAITS_HPP +namespace boost { namespace polygon{ + template + struct directed_line_segment_traits { + typedef typename T::coordinate_type coordinate_type; + typedef typename T::point_type point_type; + + static inline point_type get(const T& segment, direction_1d dir) { + return segment.get(dir); + } + }; + + template + struct directed_line_segment_mutable_traits { + template + static inline void set(T& segment, direction_1d dir, const Point1& value) { + typename directed_line_segment_traits::point_type p1; + assign(p1, value); + segment.set(dir, value); + } + + template + static inline T construct(const Point1& low_value, + const Point2& high_value) { + typename directed_line_segment_traits::point_type p1, p2; + assign(p1, low_value); + assign(p2, high_value); + return T(p1, p2); + } + }; +} +} +#endif + diff --git a/include/boost/polygon/polygon.hpp b/include/boost/polygon/polygon.hpp old mode 100755 new mode 100644 index 4c3e43a..d4048e7 --- a/include/boost/polygon/polygon.hpp +++ b/include/boost/polygon/polygon.hpp @@ -88,4 +88,8 @@ #include "polygon_set_concept.hpp" +#include "directed_line_segment_data.hpp" +#include "directed_line_segment_traits.hpp" +#include "directed_line_segment_concept.hpp" + #endif