File: partition_approx_convex_2.h

package info (click to toggle)
cgal 3.2.1-2
  • links: PTS
  • area: non-free
  • in suites: etch, etch-m68k
  • size: 47,752 kB
  • ctags: 72,510
  • sloc: cpp: 397,707; ansic: 10,393; sh: 4,232; makefile: 3,713; perl: 394; sed: 9
file content (271 lines) | stat: -rw-r--r-- 10,500 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
// 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.
//
// $URL: svn+ssh://scm.gforge.inria.fr/svn/cgal/branches/CGAL-3.2-branch/Partition_2/include/CGAL/partition_approx_convex_2.h $
// $Id: partition_approx_convex_2.h 28567 2006-02-16 14:30:13Z lsaboret $
// 
//
// Author(s)     : Susan Hert <hert@mpi-sb.mpg.de>

#ifndef CGAL_PARTITION_APPROX_CONVEX_H
#define CGAL_PARTITION_APPROX_CONVEX_H

#include <CGAL/Constrained_triangulation_2.h>
#include <CGAL/Triangulation_indirect_traits_2.h>
#include <CGAL/Turn_reverser.h>
#include <CGAL/Partitioned_polygon_2.h>
#include <CGAL/IO/Tee_for_output_iterator.h>
#include <CGAL/Partition_traits_2.h>
#include <CGAL/partition_is_valid_2.h>
#include <CGAL/partition_assertions.h>
#include <utility>
#include <iterator>

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<Point_2, Left_turn_2> 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 <class Edge_circulator, class Circulator, class Triangulation, 
          class Traits>
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() <<std::endl;
   std::cout << "prev_edge: " << *prev_edge.source() << " " 
             << *prev_edge.target() <<std::endl;
#endif
   // find which endpoint is shared by the two edges
   if (next_edge.source() == v_ref)
      next_ccw_pt_ref = next_edge.target();
   else
      next_ccw_pt_ref = next_edge.source();
   if (prev_edge.source() == v_ref)
      prev_ccw_pt_ref = prev_edge.target();
   else
      prev_ccw_pt_ref = prev_edge.source();

#ifdef CGAL_PARTITION_APPROX_CONVEX_DEBUG
   std::cout << "partition_appx_cvx_cuts_nonconvex_angle: next_ccw_pt " 
             << *next_ccw_pt_ref << " v_ref " << *v_ref << " prev_ccw_pt_ref " 
             << *prev_ccw_pt_ref << std::endl;
#endif

   typedef typename Traits::Left_turn_2    Left_turn_2;
   typedef typename Traits::Point_2     Point_2;
   Left_turn_2 left_turn = traits.left_turn_2_object();
   Turn_reverser<Point_2, Left_turn_2>  right_turn(left_turn);
   return right_turn(*next_ccw_pt_ref, *v_ref, *prev_ccw_pt_ref); 
}


template<class InputIterator, class Traits, class OutputIterator>
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<I>                 Circulator;
   typedef Triangulation_indirect_traits_2<Circulator, Traits>  Gt;

   typedef Constrained_triangulation_2<Gt>             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<OutputIterator, Polygon_2>  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 <class InputIterator, class OutputIterator>
inline
OutputIterator partition_approx_convex_2(InputIterator first, 
                                         InputIterator beyond,
                                         OutputIterator result)
{
   typedef typename std::iterator_traits<InputIterator>::value_type Point_2;
   typedef typename Kernel_traits<Point_2>::Kernel K;
   return partition_approx_convex_2(first, beyond, result,  
                                    Partition_traits_2<K>());
}

}

#endif // CGAL_PARTITION_APPROX_CONVEX_H