From d2aadf510975fa81a95458f60d2e772d65d0aef3 Mon Sep 17 00:00:00 2001 From: Geert-Jan Giezeman Date: Thu, 21 Jun 2001 13:05:01 +0000 Subject: [PATCH] *** empty log message *** --- .../include/CGAL/Polygon_2_algorithms.C | 229 +++++++++++------- .../include/CGAL/Polygon_2_algorithms.h | 14 +- .../include/CGAL/Polygon_2_simplicity.h | 58 ++++- .../Polygon/include/CGAL/Polygon_traits_2.h | 11 +- 4 files changed, 207 insertions(+), 105 deletions(-) diff --git a/Packages/Polygon/include/CGAL/Polygon_2_algorithms.C b/Packages/Polygon/include/CGAL/Polygon_2_algorithms.C index ee499e86b8d..56240aa82c2 100644 --- a/Packages/Polygon/include/CGAL/Polygon_2_algorithms.C +++ b/Packages/Polygon/include/CGAL/Polygon_2_algorithms.C @@ -25,6 +25,7 @@ #include "CGAL/Polygon_2_simplicity.h" #include #include +#include #include #include @@ -34,82 +35,91 @@ CGAL_BEGIN_NAMESPACE //-----------------------------------------------------------------------// // is_simple_2 //-----------------------------------------------------------------------// -// uses Traits::Less_xy_2 -// Traits::less_xy_2 -// Traits::Orientation_2 -// Traits::orientation_2 -// Traits::Point_2 +// uses PolygonTraits::Less_xy_2 +// PolygonTraits::less_xy_2 +// PolygonTraits::Orientation_2 +// PolygonTraits::orientation_2 +// PolygonTraits::Point_2 -template + +template +bool is_simple_aux_2(ForwardIterator first, ForwardIterator last, + PolygonTraits const &traits, ItTag tag) +{ + std::vector data_copy(first, last); + return is_simple_polygon(data_copy.begin(), data_copy.end(), traits); +} + +template +bool is_simple_aux_2(ForwardIterator first, ForwardIterator last, + PolygonTraits const &traits, std::random_access_iterator_tag) +{ + return is_simple_polygon(first, last, traits); +} + +template bool is_simple_2(ForwardIterator first, ForwardIterator last, - const Traits& traits) + const PolygonTraits& traits) { - return is_simple_polygon(first, last, traits); + return is_simple_aux_2(first, last, traits, + std::iterator_category(first)); } //-----------------------------------------------------------------------// // left_vertex_2 //-----------------------------------------------------------------------// -// uses Traits::Less_xy +// uses PolygonTraits::Less_xy_2 and less_xy_2_object() -template +template ForwardIterator left_vertex_2(ForwardIterator first, ForwardIterator last, - const Traits&) + const PolygonTraits&traits) { - CGAL_polygon_precondition(first != last); - - typedef typename Traits::Less_xy Less_xy; - return std::min_element(first, last, Less_xy()); + CGAL_polygon_precondition(first != last); + return std::min_element(first, last, traits.less_xy_2_object()); } //-----------------------------------------------------------------------// // right_vertex_2 //-----------------------------------------------------------------------// -// uses Traits::Less_xy +// uses PolygonTraits::Less_xy_2 and less_xy_2_object() -template +template ForwardIterator right_vertex_2(ForwardIterator first, ForwardIterator last, - const Traits&) + const PolygonTraits &traits) { - CGAL_polygon_precondition(first != last); - - typedef typename Traits::Less_xy Less_xy; - return std::max_element(first, last, Less_xy()); + CGAL_polygon_precondition(first != last); + return std::max_element(first, last, traits.less_xy_2_object()); } //-----------------------------------------------------------------------// // top_vertex_2 //-----------------------------------------------------------------------// -// uses Traits::Less_yx +// uses PolygonTraits::Less_yx_2 and less_yx_2_object() -template +template ForwardIterator top_vertex_2(ForwardIterator first, ForwardIterator last, - const Traits&) + const PolygonTraits&traits) { - CGAL_polygon_precondition(first != last); - - typedef typename Traits::Less_yx Less_yx; - return std::max_element(first, last, Less_yx()); + CGAL_polygon_precondition(first != last); + return std::max_element(first, last, traits.less_yx_2_object()); } //-----------------------------------------------------------------------// // bottom_vertex_2 //-----------------------------------------------------------------------// -// uses Traits::Less_yx +// uses PolygonTraits::Less_yx_2 and less_yx_2_object() -template +template ForwardIterator bottom_vertex_2(ForwardIterator first, ForwardIterator last, - const Traits&) + const PolygonTraits&traits) { - CGAL_polygon_precondition(first != last); - - typedef typename Traits::Less_yx Less_yx; - return std::min_element(first, last, Less_yx()); + CGAL_polygon_precondition(first != last); + return std::min_element(first, last, traits.less_yx_2_object()); } //-----------------------------------------------------------------------// @@ -143,8 +153,8 @@ Bbox_2 bbox_2(InputIterator first, InputIterator last) //-----------------------------------------------------------------------// // is_convex_2 //-----------------------------------------------------------------------// -// uses Traits::lexicographically_xy_smaller -// Traits::orientation +// uses Traits::Less_xy_2 and less_xy_2_object() +// Traits::Orientation_2 and orientation_2_object() template bool is_convex_2(ForwardIterator first, @@ -160,14 +170,16 @@ bool is_convex_2(ForwardIterator first, ForwardIterator next = current; ++next; if (next == last) return true; + typename Traits::Less_xy_2 less_xy_2 = traits.less_xy_2_object(); + typename Traits::Orientation_2 orientation = traits.orientation_2_object(); // initialization bool HasClockwiseTriples = false; bool HasCounterClockwiseTriples = false; - bool Order = traits.lexicographically_xy_smaller(*previous, *current); + bool Order = less_xy_2(*previous, *current); int NumOrderChanges = 0; do { - switch (traits.orientation(*previous, *current, *next)) { + switch (orientation(*previous, *current, *next)) { case CLOCKWISE: HasClockwiseTriples = true; break; @@ -178,7 +190,7 @@ bool is_convex_2(ForwardIterator first, ; } - bool NewOrder = traits.lexicographically_xy_smaller(*current, *next); + bool NewOrder = less_xy_2(*current, *next); if (Order != NewOrder) NumOrderChanges++; if (NumOrderChanges > 2) { @@ -209,12 +221,10 @@ cout << "polygon not locally convex!" << endl; //-----------------------------------------------------------------------// // oriented_side_2 //-----------------------------------------------------------------------// -// uses Traits::Less_xy -// Traits::compare_x -// Traits::compare_y -// Traits::determinant_2 -// Traits::orientation -// Traits::sign +// uses Traits::Less_xy_2 +// Traits::Compare_x_2 compare_x_2_object() +// Traits::Compare_y_2 compare_y_2_object() +// Traits::Orientation_2 and orientation_2_object() template Oriented_side oriented_side_2(ForwardIterator first, @@ -252,13 +262,54 @@ Oriented_side oriented_side_2(ForwardIterator first, //-----------------------------------------------------------------------// // bounded_side_2 //-----------------------------------------------------------------------// -// uses Traits::compare_x -// Traits::compare_y -// Traits::determinant_2 -// Traits::sign +// uses Traits::Compare_x_2 compare_x_2_object() +// Traits::Compare_y_2 compare_y_2_object() +// Traits::Orientation_2 and orientation_2_object() // // returns ON_BOUNDED_SIDE, ON_BOUNDARY or ON_UNBOUNDED_SIDE +/* + Implementation: we shoot a horizontal ray from the point to the right + and count the number of intersections with polygon segments. + If the number of intersections is odd, the point is inside. + We don't count intersections with horizontal segments. + With non-horizontal segments, the top vertex is considered to be part of + the segment, but the bottom vertex is not. (Segments are half-closed). +*/ + +namespace i_polygon { + +template +int which_side_in_slab(Point const &point, Point const &low, Point const &high, + Orientation_2 &orientation_2, CompareX_2 &compare_x_2) +// returns -1 if point is left of segment , 0 if its on the segment +// and 1 if it is to the right +// precondition: low.y < point.y < high.y +{ + // first we try to decide on x coordinate values alone + // This is an optimisation (whether this is really faster for + // a homogeneous kernel is not clear, as comparisons can be expensive. + Comparison_result low_x_comp_res = compare_x_2(point, low); + Comparison_result high_x_comp_res = compare_x_2(point, high); + if (low_x_comp_res == SMALLER) { + if (high_x_comp_res == SMALLER) + return -1; + } else { + switch (high_x_comp_res) { + case LARGER: return 1; + case SMALLER: break; + case EQUAL: return (low_x_comp_res == EQUAL) ? 0 : 1; + } + } + switch (orientation_2(low, point, high)) { + case LEFTTURN: return 1; + case RIGHTTURN: return -1; + default: return 0; + } +} + +} // end namespace i_polygon + template Bounded_side bounded_side_2(ForwardIterator first, ForwardIterator last, @@ -271,82 +322,82 @@ Bounded_side bounded_side_2(ForwardIterator first, ForwardIterator next = current; ++next; if (next == last) return ON_UNBOUNDED_SIDE; + typename Traits::Compare_x_2 compare_x_2 = traits.compare_x_2_object(); + typename Traits::Compare_y_2 compare_y_2 = traits.compare_y_2_object(); + typename Traits::Orientation_2 orientation_2 = traits.orientation_2_object(); bool IsInside = false; - Comparison_result CompareCurrent = traits.compare_y(*current, point); + Comparison_result cur_y_comp_res = compare_y_2(*current, point); do // check if the segment (current,next) intersects // the ray { (t,y) | t >= point.x() } { - Comparison_result CompareNext = traits.compare_y(*next, point); + Comparison_result next_y_comp_res = compare_y_2(*next, point); - switch (CompareCurrent) { + switch (cur_y_comp_res) { case SMALLER: - switch (CompareNext) { + switch (next_y_comp_res) { case SMALLER: break; case EQUAL: - switch (traits.compare_x(point, *next)) { + switch (compare_x_2(point, *next)) { case SMALLER: IsInside = !IsInside; break; case EQUAL: return ON_BOUNDARY; case LARGER: break; } break; case LARGER: - if (point.x() < std::min((*current).x(), (*next).x())) { - IsInside = !IsInside; - } - else if (point.x() <= std::max((*current).x(),(*next).x())) { - switch (traits.sign(traits.determinant_2(point, - *current, - *next))) - { - case 0: return ON_BOUNDARY; - case 1: IsInside = !IsInside; break; - } - } + switch (i_polygon::which_side_in_slab(point, *current, *next, + orientation_2, compare_x_2)) { + case -1: IsInside = !IsInside; break; + case 0: return ON_BOUNDARY; + } break; } break; case EQUAL: - switch (CompareNext) { + switch (next_y_comp_res) { case SMALLER: - switch (traits.compare_x(point, *current)) { + switch (compare_x_2(point, *current)) { case SMALLER: IsInside = !IsInside; break; case EQUAL: return ON_BOUNDARY; case LARGER: break; } break; case EQUAL: + switch (compare_x_2(point, *current)) { + case SMALLER: + if (compare_x_2(point, *next) != SMALLER) + return ON_BOUNDARY; + break; + case EQUAL: return ON_BOUNDARY; + case LARGER: + if (compare_x_2(point, *next) != LARGER) + return ON_BOUNDARY; + break; + } if ( (std::min((*current).x(), (*next).x()) <= point.x()) && (point.x() <= std::max((*current).x(), (*next).x())) ) { return ON_BOUNDARY; } break; case LARGER: - if (point.x() == (*current).x()) { + if (compare_x_2(point, *current) == EQUAL) { return ON_BOUNDARY; } break; } break; case LARGER: - switch (CompareNext) { + switch (next_y_comp_res) { case SMALLER: - if (point.x() < std::min((*current).x(), (*next).x())) { - IsInside = !IsInside; - } - else if (point.x() <= std::max((*current).x(),(*next).x())) { - switch (traits.sign(traits.determinant_2(point, - *current, - *next))) - { - case -1: IsInside = !IsInside; break; - case 0: return ON_BOUNDARY; - } - } + switch (i_polygon::which_side_in_slab(point, *next, *current, + orientation_2, compare_x_2)) { + case -1: IsInside = !IsInside; break; + case 0: return ON_BOUNDARY; + } break; case EQUAL: - if (point.x() == (*next).x()) { + if (compare_x_2(point, *next) == EQUAL) { return ON_BOUNDARY; } break; @@ -357,7 +408,7 @@ Bounded_side bounded_side_2(ForwardIterator first, } current = next; - CompareCurrent = CompareNext; + cur_y_comp_res = next_y_comp_res; ++next; if (next == last) next = first; } @@ -369,8 +420,8 @@ Bounded_side bounded_side_2(ForwardIterator first, //-----------------------------------------------------------------------// // orientation_2 //-----------------------------------------------------------------------// -// uses Traits::Less_xy -// Traits::orientation +// uses Traits::Less_xy_2 (used by left_vertex_2) +// Traits::orientation_2_object() template Orientation orientation_2(ForwardIterator first, @@ -393,7 +444,7 @@ Orientation orientation_2(ForwardIterator first, // of the points (prev,i,next) will coincide // return the orientation of the triple (prev,i,next) - return traits.orientation(*prev, *i, *next); + return traits.orientation_2_object()(*prev, *i, *next); } CGAL_END_NAMESPACE diff --git a/Packages/Polygon/include/CGAL/Polygon_2_algorithms.h b/Packages/Polygon/include/CGAL/Polygon_2_algorithms.h index 5e929f41b78..052785114a7 100644 --- a/Packages/Polygon/include/CGAL/Polygon_2_algorithms.h +++ b/Packages/Polygon/include/CGAL/Polygon_2_algorithms.h @@ -68,19 +68,25 @@ Bbox_2 bbox_2(InputIterator first, InputIterator last); template void area_2( ForwardIterator first, ForwardIterator last, - typename std::iterator_traits::value_type::FT& result, + // typename std::iterator_traits::value_type::FT& result, + typename Traits::FT &result, const Traits& traits) { - typedef typename std::iterator_traits::value_type::FT FT; + typedef typename Traits::FT FT; result = FT(0); // check if the polygon is empty if (first == last) return; ForwardIterator second = first; ++second; // check if the polygon has only one point if (second == last) return; + typename Traits::Compute_area_2 compute_area_2 = + traits.compute_area_2_object(); + typename Traits::Construct_triangle_2 construct_triangle_2 = + traits.construct_triangle_2_object(); ForwardIterator third = second; while (++third != last) { - result = result + traits.determinant_2(*first, *second, *third); + result = result + compute_area_2( + construct_triangle_2(*first, *second, *third)); second = third; } result = result / FT(2); @@ -127,7 +133,7 @@ ForwardIterator left_vertex_2_aux(ForwardIterator first, ForwardIterator last, const Point_2) { - return left_vertex_2(first, last, Polygon_traits_2()); + return left_vertex_2(first, last, R()); } template diff --git a/Packages/Polygon/include/CGAL/Polygon_2_simplicity.h b/Packages/Polygon/include/CGAL/Polygon_2_simplicity.h index c11816a343d..c32234818c5 100644 --- a/Packages/Polygon/include/CGAL/Polygon_2_simplicity.h +++ b/Packages/Polygon/include/CGAL/Polygon_2_simplicity.h @@ -28,6 +28,8 @@ #include #include +// #define GJ_DEBUG_43 + namespace CGAL { namespace i_polygon { @@ -37,7 +39,7 @@ typedef std::vector::size_type Index_t; struct Vertex_index { Vertex_index() {} explicit Vertex_index(Index_t i): m_i(i) {} - Index_t as_int() {return m_i;} + Index_t as_int() const {return m_i;} Vertex_index operator++() {++m_i; return *this; } private: Index_t m_i; @@ -92,13 +94,13 @@ public: typename PolygonTraits::Less_xy_2 less_xy_2; bool is_simple_result; - Vertex_order xy_order_of(Vertex_index vi) + Vertex_order xy_order_of(Vertex_index vi) const { return m_order_of[vi.as_int()];} - Vertex_index index_at_rank(Vertex_order vo) + Vertex_index index_at_rank(Vertex_order vo) const { return m_idx_at_rank[vo.as_int()];} - Vertex_index next(Vertex_index k) + Vertex_index next(Vertex_index k) const { ++k; return k.as_int() == m_size ? Vertex_index(0) : k;} - Vertex_index prev(Vertex_index k) + Vertex_index prev(Vertex_index k) const { return k.as_int() == 0 ? Vertex_index(m_size-1) : Vertex_index(k.as_int()-1); @@ -113,8 +115,25 @@ public: bool chain_continuation(Tree *tree, Vertex_index cur, Vertex_index to_insert); bool chain_end(Tree *tree, Vertex_index i, Vertex_index j); bool on_right_side(Vertex_index vt, Vertex_index edge, bool above); +#ifdef GJ_DEBUG_43 + void print_tree(Tree *tree); +#endif }; +#ifdef GJ_DEBUG_43 +template +void Vertex_data:: +print_tree(Tree *tree) +{ + typedef Tree::iterator Tree_it; + for (Tree_it cur = tree->begin(); cur != tree->end(); ++cur) { + Vertex_index nb = next(*cur); + std::cout << (*cur).as_int() << ' ' << nb.as_int() <<'\n'; + } + std::cout << "-----\n"; +} +#endif + template class Less_vertex_data { Vertex_data *m_vertex_data; @@ -148,8 +167,19 @@ less_than_in_tree(Vertex_index new_edge, Vertex_index tree_edge) Vertex_index left, mid, right; m_vertex_data->left_and_right_index(left, right, tree_edge); mid = m_vertex_data->left_index(new_edge); - if (mid.as_int() == left.as_int()) +#ifdef GJ_DEBUG_43 +if (new_edge.as_int() == 14 || new_edge.as_int() == 15) + std::cout << "Checking "<< new_edge.as_int() << " and " + << tree_edge.as_int() <<'\n'; + std::cout<< "left: "<orientation_2( m_vertex_data->point(left), m_vertex_data->point(mid), m_vertex_data->point(right))) { case LEFTTURN: return true; @@ -219,11 +249,17 @@ chain_start(Tree *tree, Vertex_index prev_vt, &td_prev = edges[prev_vt.as_int()], &td_mid = edges[mid_vt.as_int()]; td_prev.is_in_tree = false; - td_prev.is_in_order = !left_turn; + td_prev.is_in_order = false; td_mid.is_in_tree = false; - td_mid.is_in_order = left_turn; + td_mid.is_in_order = true; // insert the highest chain first - std::pair result; +#ifdef GJ_DEBUG_43 +if (left_turn) + std::cout << "Ins " << prev_vt.as_int() << " and " << mid_vt.as_int() <<'\n'; +else + std::cout << "Ins " << mid_vt.as_int() << " and " << prev_vt.as_int() <<'\n'; +#endif + std::pair result; if (left_turn) { result = tree->insert(prev_vt); // assert(result.second) @@ -353,6 +389,10 @@ sweep(Tree *tree) else succes = chain_end(tree, prev_vt, cur); } +#ifdef GJ_DEBUG_43 + std::cout << "after treating " << cur.as_int() << ":\n"; + print_tree(tree); +#endif if (!succes) break; } diff --git a/Packages/Polygon/include/CGAL/Polygon_traits_2.h b/Packages/Polygon/include/CGAL/Polygon_traits_2.h index d551ba28217..b93d29650c6 100644 --- a/Packages/Polygon/include/CGAL/Polygon_traits_2.h +++ b/Packages/Polygon/include/CGAL/Polygon_traits_2.h @@ -24,6 +24,7 @@ #ifndef CGAL_POLYGON_TRAITS_2_H #define CGAL_POLYGON_TRAITS_2_H +/* #include #include #include @@ -35,6 +36,7 @@ #include #include #include +*/ CGAL_BEGIN_NAMESPACE @@ -46,7 +48,7 @@ CGAL_BEGIN_NAMESPACE // The template parameter _Point is added to simplify the use of points // with additional information. It is assumed that _Point inherits from // Point_2<_R>. - +/* template class Polygon_traits_2_aux : public _R { @@ -124,17 +126,20 @@ class Polygon_traits_2_aux : public _R return ::CGAL::Direction_2<_R>(v1) == ::CGAL::Direction_2<_R>(v2); } }; - +*/ //-----------------------------------------------------------------------// // Polygon_traits_2 //-----------------------------------------------------------------------// // The class Polygon_traits_2 is a traits class for Polygon_2. - +/* template class Polygon_traits_2 : public Polygon_traits_2_aux<_R, typename _R::FT, Point_2<_R> > { }; +*/ +template +class Polygon_traits_2 : public R_ {}; CGAL_END_NAMESPACE