// Copyright (c) 2000 Max-Planck-Institute Saarbruecken (Germany). // All rights reserved. // // This file is part of CGAL (www.cgal.org); you may redistribute it under // the terms of the Q Public License version 1.0. // See the file LICENSE.QPL distributed with CGAL. // // Licensees holding a valid commercial license may use this file in // accordance with the commercial license agreement provided with the software. // // This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE // WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. // // $Source$ // $Revision$ $Date$ // $Name$ // // Author(s) : Susan Hert #ifndef CGAL_PARTITION_APPROX_CONVEX_H #define CGAL_PARTITION_APPROX_CONVEX_H #include #include #include #include #include #include #include #include #include #include namespace CGAL { template< class Point_2, class Traits > bool partition_appx_cvx_is_edge_through_interior(const Point_2& before_s, const Point_2& source, const Point_2& after_s, const Point_2& target, const Traits& traits ) { // determine if the edge goes through the interior of the polygon or not typedef typename Traits::Left_turn_2 Left_turn_2; Left_turn_2 left_turn = traits.left_turn_2_object(); Turn_reverser right_turn(left_turn); if (right_turn(before_s, source, after_s)) // concave angle { if (right_turn(before_s, source, target) && right_turn(target, source, after_s)) return false; } else // left turn or straight if (right_turn(before_s, source, target) || right_turn(target, source, after_s)) return false; return true; } // e_circ is a circulator for the edges incident to the point referred to by // v_ref, which is a circualtor around the vertices of the original polygon template bool partition_appx_cvx_cuts_nonconvex_angle( Edge_circulator e_circ, Circulator v_ref, const Triangulation& triangles, const Traits& traits) { typedef typename Triangulation::Segment Segment_2; #ifdef CGAL_PARTITION_APPROX_CONVEX_DEBUG Segment_2 edge = triangles.segment((*e_circ).first, (*e_circ).second); std::cout << "edge: " << *edge.source() << " " << *edge.target() << std::endl; #endif typename Triangulation::Point next_ccw_pt_ref, prev_ccw_pt_ref; // the next and previous edges in the ccw ordering of edges around v_ref Edge_circulator next_e = e_circ; next_e++; Edge_circulator prev_e = e_circ; prev_e--; // find the first edge before this one that has been included in the // partition polygon (and is thus marked as constrained in triangulation) while (prev_e != e_circ && (triangles.is_infinite(*prev_e) || !(*prev_e).first->is_constrained((*prev_e).second))) prev_e--; Segment_2 next_edge = triangles.segment((*next_e).first,(*next_e).second); Segment_2 prev_edge = triangles.segment((*prev_e).first,(*prev_e).second); #ifdef CGAL_PARTITION_APPROX_CONVEX_DEBUG std::cout << "next_edge: " << *next_edge.source() << " " << *next_edge.target() < right_turn(left_turn); return right_turn(*next_ccw_pt_ref, *v_ref, *prev_ccw_pt_ref); } template OutputIterator partition_approx_convex_2(InputIterator first, InputIterator beyond, OutputIterator result, const Traits& traits) { if (first == beyond) return result; typedef Partitioned_polygon_2< Traits > P_Polygon_2; typedef typename P_Polygon_2::iterator I; typedef Circulator_from_iterator Circulator; typedef Triangulation_indirect_traits_2 Gt; typedef Constrained_triangulation_2 Constrained_tri_2; typedef typename Constrained_tri_2::Edge_iterator Edge_iterator; typedef typename Constrained_tri_2::Edge_circulator Edge_circulator; typedef typename Constrained_tri_2::Vertex_iterator Tri_vertex_iterator; typedef typename Constrained_tri_2::Vertex_handle Vertex_handle; typedef typename Gt::Segment_2 Segment_2; P_Polygon_2 polygon(first, beyond); CGAL_partition_precondition( orientation_2(polygon.begin(), polygon.end(), traits) == COUNTERCLOCKWISE); Circulator first_c(polygon.begin(), polygon.end(), polygon.begin()); Circulator c(polygon.begin(), polygon.end()); Circulator next(polygon.begin(), polygon.end()); Constrained_tri_2 triangles; do { next = c; next++; triangles.insert(c, next); } while (++c != first_c); Segment_2 edge; Circulator source, target, before_s, after_s; #ifdef CGAL_PARTITION_APPROX_CONVEX_DEBUG std::cout << "Inserting diagonals: " << std::endl; #endif Edge_circulator e_circ, first_e; Tri_vertex_iterator v_it; for (v_it = triangles.vertices_begin(); v_it != triangles.vertices_end(); v_it++) { first_e = triangles.incident_edges(Vertex_handle(v_it)); // find the constrained edge attached to this vertex that is first // when going CW from the first edge returned above. while (triangles.is_infinite(*first_e) || !(*first_e).first->is_constrained((*first_e).second)) { first_e--; } e_circ = first_e; do { if ((*e_circ).first->is_constrained((*e_circ).second)) { edge = triangles.segment((*e_circ).first, (*e_circ).second); #ifdef CGAL_PARTITION_APPROX_CONVEX_DEBUG std::cout << "edge " << *edge.source() << " " << *edge.target() << " is constrained " << std::endl; #endif } else { if (!triangles.is_infinite(*e_circ)) { edge = triangles.segment((*e_circ).first, (*e_circ).second); source = edge.source(); target = edge.target(); before_s = source; before_s--; after_s = source; after_s++; #ifdef CGAL_PARTITION_APPROX_CONVEX_DEBUG std::cout << "considering " << *source << " " << *target << "..."; #endif if (partition_appx_cvx_is_edge_through_interior(*before_s, *source, *after_s, *target, traits)) { if (partition_appx_cvx_cuts_nonconvex_angle(e_circ, (*v_it).point(), triangles, traits)) { #ifdef CGAL_PARTITION_APPROX_CONVEX_DEBUG std::cout << "inserting" << std::endl; #endif polygon.insert_diagonal(source, target); triangles.insert(source, target); } #ifdef CGAL_PARTITION_APPROX_CONVEX_DEBUG else std::cout << "doesn't cut reflex angle" << std::endl; #endif } #ifdef CGAL_PARTITION_APPROX_CONVEX_DEBUG else std::cout << "not an edge through the interior" << std::endl; #endif } #ifdef CGAL_PARTITION_APPROX_CONVEX_DEBUG std::cout << "edge is infinite " << std::endl; #endif } } while (++e_circ != first_e); } #if defined(CGAL_PARTITION_NO_POSTCONDITIONS) || \ defined(CGAL_NO_POSTCONDITIONS) || defined(NDEBUG) OutputIterator res(result); #else typedef typename Traits::Polygon_2 Polygon_2; Tee_for_output_iterator res(result); #endif // no postconditions polygon.partition(res, 0); CGAL_partition_postcondition( convex_partition_is_valid_2(polygon.begin(), polygon.end(), res.output_so_far_begin(), res.output_so_far_end(), traits)); #if defined(CGAL_PARTITION_NO_POSTCONDITIONS) || \ defined(CGAL_NO_POSTCONDITIONS) || defined(NDEBUG) return res; #else return res.to_output_iterator(); #endif // no postconditions } template inline OutputIterator partition_approx_convex_2(InputIterator first, InputIterator beyond, OutputIterator result) { typedef typename std::iterator_traits::value_type Point_2; typedef typename Kernel_traits::Kernel K; return partition_approx_convex_2(first, beyond, result, Partition_traits_2()); } } #endif // CGAL_PARTITION_APPROX_CONVEX_H