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