BWAPI
|
00001 // Copyright (c) 2001 Utrecht University (The Netherlands), 00002 // ETH Zurich (Switzerland), Freie Universitaet Berlin (Germany), 00003 // INRIA Sophia-Antipolis (France), Martin-Luther-University Halle-Wittenberg 00004 // (Germany), Max-Planck-Institute Saarbruecken (Germany), RISC Linz (Austria), 00005 // and Tel-Aviv University (Israel). All rights reserved. 00006 // 00007 // This file is part of CGAL (www.cgal.org); you can redistribute it and/or 00008 // modify it under the terms of the GNU Lesser General Public License as 00009 // published by the Free Software Foundation; version 2.1 of the License. 00010 // See the file LICENSE.LGPL distributed with CGAL. 00011 // 00012 // Licensees holding a valid commercial license may use this file in 00013 // accordance with the commercial license agreement provided with the software. 00014 // 00015 // This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE 00016 // WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. 00017 // 00018 // $URL: svn+ssh://scm.gforge.inria.fr/svn/cgal/branches/CGAL-3.5-branch/Polygon/include/CGAL/Polygon_2/Polygon_2_simplicity.h $ 00019 // $Id: Polygon_2_simplicity.h 49538 2009-05-24 14:14:05Z efif $ 00020 // 00021 // 00022 // Author(s) : Geert-Jan Giezeman <geert@cs.uu.nl> 00023 00024 #ifndef CGAL_POLYGON_2_SIMPLICITY_H 00025 #define CGAL_POLYGON_2_SIMPLICITY_H 00026 00027 #include <CGAL/enum.h> 00028 #include <CGAL/Polygon_2/polygon_assertions.h> 00029 #include <set> 00030 #include <vector> 00031 #include <algorithm> 00032 00033 /* 00034 A polygon is called simple of no edges intersect each other, except 00035 consecutive edges, which intersect in their common vertex. 00036 The test for simplicity is implemented by means of a sweep line algorithm. 00037 The vertical line is swept from left to right. The edges of the polygon that 00038 are crossed by the sweep line are stored in a tree from bottom to top. 00039 00040 We discern three types of events: 00041 - insertion events. When both edges of a polygon vertex extend to the right 00042 we need to insert both edges in the tree. We need to search with the vertex 00043 to find out between which edges the new edges are to be inserted. 00044 - deletion events. When both edges extend to the left of the vertex we need 00045 to remove both edges from the tree. We have to check that the vertex lies 00046 between the edges above and below the removed edges. 00047 - replacement event. In the other case we need to replace the edge that 00048 extends to the left by the edge that extends to the right. We need to check 00049 that the vertex lies between the edges above and below the current edge. 00050 00051 We represent the tree by a std::set. This is not a perfect fit for the 00052 operations described above. In particular, the fact that we search with a 00053 VERTEX, while the set contains EDGES, is not directly supported. The 00054 insertion of edges is also complicated by the fact that we need to insert 00055 two edges starting at the same vertex. The order in which they are inserted 00056 in the tree does matter, because the edges go in separate directions. 00057 Because of this the set needs a special associated comparison function. 00058 Every edge has a flag 'is_in_tree', which is true for the edges in the tree 00059 but false for the edges when they are inserted. The comparison function 00060 treats the latter type of edge as a vertex. Another flag, is_left_to_right, 00061 tells which of the two vertices to take. The problem of the coinciding 00062 vertices is solved by the convention that the highest edges is always 00063 inserted first. The comparison function uses this fact. 00064 00065 Vertex indices of the polygon play a double role. The number v can be used to 00066 identify vertex v or the edge from vertex v to vertex v+1. 00067 00068 */ 00069 00070 namespace CGAL { 00071 00072 namespace i_polygon { 00073 // namespace CGAL::i_polygon is used for internal functions 00074 00075 typedef std::vector<int>::size_type Index_t; 00076 00077 struct Vertex_index { 00078 Vertex_index() {} 00079 explicit Vertex_index(Index_t i): m_i(i) {} 00080 Index_t as_int() const {return m_i;} 00081 Vertex_index operator++() {++m_i; return *this; } 00082 private: 00083 Index_t m_i; 00084 }; 00085 00086 struct Vertex_order { 00087 explicit Vertex_order(Index_t i): m_i(i) {} 00088 Index_t as_int() {return m_i;} 00089 private: 00090 Index_t m_i; 00091 }; 00092 00093 template <class ForwardIterator, class PolygonTraits> 00094 class Vertex_data ; 00095 00096 template <class VertexData> 00097 class Less_segments { 00098 typedef VertexData Vertex_data; 00099 Vertex_data *m_vertex_data; 00100 bool less_than_in_tree(Vertex_index i, Vertex_index j); 00101 public: 00102 Less_segments(Vertex_data *vertex_data) : m_vertex_data(vertex_data) {} 00103 bool operator()(Vertex_index i, Vertex_index j); 00104 }; 00105 00106 // The data in Edge_data is attached to an edge when it is (about to be) 00107 // inserted in the tree. 00108 // Although conceptually this data belongs in the tree, it is stored with 00109 // the vertices in the Vertex_data structure. 00110 00111 template <class LessSegments> 00112 struct Edge_data { 00113 typedef std::set<Vertex_index, LessSegments> Tree; 00114 Edge_data() : is_in_tree(false) {} 00115 Edge_data(typename Tree::iterator it) : tree_it(it), is_in_tree(false) {} 00116 typename Tree::iterator tree_it; // The iterator of the edge in the tree. 00117 // Needed for cross reference. If edge j 00118 // is in the tree: *edges[j].tree_it == j 00119 bool is_in_tree :1; // Must be set -after- inserting the edge 00120 // in the tree. Plays a role in the 00121 // comparison function of the tree. 00122 bool is_left_to_right :1; // Direction of edge from vertex v to v+1 00123 }; 00124 00125 template <class ForwardIterator, class PolygonTraits> 00126 class Vertex_data_base { 00127 public: 00128 typedef typename PolygonTraits::Point_2 Point_2; 00129 00130 // ForwardIterator points_start; 00131 std::vector<ForwardIterator> iterators; 00132 std::vector<Vertex_order> m_order_of; 00133 std::vector<Vertex_index> m_idx_at_rank; 00134 std::vector<Vertex_index>::size_type m_size; 00135 typename PolygonTraits::Orientation_2 orientation_2; 00136 typename PolygonTraits::Less_xy_2 less_xy_2; 00137 bool is_simple_result; 00138 00139 Vertex_data_base(ForwardIterator begin, ForwardIterator end, 00140 const PolygonTraits& pgnt); 00141 00142 bool ordered_left_to_right(Vertex_index v1, Vertex_index v2) 00143 { return m_order_of[v1.as_int()].as_int() < 00144 m_order_of[v2.as_int()].as_int();} 00145 Vertex_index index_at_rank(Vertex_order vo) const 00146 { return m_idx_at_rank[vo.as_int()];} 00147 Vertex_index next(Vertex_index k) const 00148 { ++k; return k.as_int() == m_size ? Vertex_index(0) : k;} 00149 Vertex_index prev(Vertex_index k) const 00150 { return k.as_int() == 0 00151 ? Vertex_index(m_size-1) 00152 : Vertex_index(k.as_int()-1); 00153 } 00154 Point_2 point(Vertex_index i) 00155 { return *iterators[i.as_int()];} 00156 // { return points_start[i.as_int()];} 00157 }; 00158 00159 template <class ForwardIterator, class PolygonTraits> 00160 class Vertex_data : public Vertex_data_base<ForwardIterator, PolygonTraits> { 00161 public: 00162 typedef Less_segments<Vertex_data> Less_segs; 00163 typedef std::set<Vertex_index, Less_segs> Tree; 00164 typedef Vertex_data_base<ForwardIterator, PolygonTraits> Base_class; 00165 00166 using Base_class::ordered_left_to_right; 00167 using Base_class::next; 00168 using Base_class::prev; 00169 using Base_class::index_at_rank; 00170 using Base_class::point; 00171 00172 std::vector<Edge_data<Less_segs> > edges; 00173 00174 Vertex_data(ForwardIterator begin, ForwardIterator end, 00175 const PolygonTraits& pgnt); 00176 00177 void init(Tree *tree); 00178 void left_and_right_index(Vertex_index &left, Vertex_index &right, 00179 Vertex_index edge); 00180 Vertex_index left_index(Vertex_index edge) 00181 { return edges[edge.as_int()].is_left_to_right ? edge : next(edge); } 00182 00183 void sweep(Tree *tree); 00184 bool insertion_event(Tree *tree, 00185 Vertex_index i, Vertex_index j, Vertex_index k); 00186 bool replacement_event(Tree *tree, 00187 Vertex_index cur, Vertex_index to_insert); 00188 bool deletion_event(Tree *tree, Vertex_index i, Vertex_index j); 00189 bool on_right_side(Vertex_index vt, Vertex_index edge, bool above); 00190 }; 00191 00192 template <class VertexData> 00193 class Less_vertex_data { 00194 VertexData *m_vertex_data; 00195 public: 00196 Less_vertex_data(VertexData *vd) 00197 : m_vertex_data(vd) {} 00198 bool operator()(Vertex_index i, Vertex_index j); 00199 }; 00200 00201 } // end of namespace i_polygon 00202 00203 // ----- implementation of i_polygon functions. ----- 00204 00205 namespace i_polygon { 00206 template <class VertexData> 00207 bool Less_segments<VertexData>:: 00208 operator()(Vertex_index i, Vertex_index j) 00209 { 00210 if (m_vertex_data->edges[j.as_int()].is_in_tree) { 00211 return less_than_in_tree(i,j); 00212 } else { 00213 return !less_than_in_tree(j,i); 00214 } 00215 } 00216 00217 template <class VertexData> 00218 bool Less_segments<VertexData>:: 00219 less_than_in_tree(Vertex_index new_edge, Vertex_index tree_edge) 00220 { 00221 CGAL_polygon_precondition( 00222 m_vertex_data->edges[tree_edge.as_int()].is_in_tree); 00223 CGAL_polygon_precondition( 00224 !m_vertex_data->edges[new_edge.as_int()].is_in_tree); 00225 Vertex_index left, mid, right; 00226 m_vertex_data->left_and_right_index(left, right, tree_edge); 00227 mid = m_vertex_data->left_index(new_edge); 00228 if (mid.as_int() == left.as_int()) { 00229 return true; 00230 } 00231 switch (m_vertex_data->orientation_2( m_vertex_data->point(left), 00232 m_vertex_data->point(mid), m_vertex_data->point(right))) { 00233 case LEFT_TURN: return true; 00234 case RIGHT_TURN: return false; 00235 case COLLINEAR: break; 00236 } 00237 m_vertex_data->is_simple_result = false; 00238 return true; 00239 } 00240 00241 template <class VertexData> 00242 bool Less_vertex_data<VertexData>:: 00243 operator()(Vertex_index i, Vertex_index j) 00244 { 00245 return m_vertex_data->less_xy_2( 00246 m_vertex_data->point(i), m_vertex_data->point(j)); 00247 } 00248 00249 template <class ForwardIterator, class PolygonTraits> 00250 Vertex_data_base<ForwardIterator, PolygonTraits>:: 00251 Vertex_data_base(ForwardIterator begin, ForwardIterator end, 00252 const PolygonTraits& pgn_traits) 00253 : orientation_2(pgn_traits.orientation_2_object()), 00254 less_xy_2(pgn_traits.less_xy_2_object()) 00255 { 00256 m_size = std::distance(begin, end); 00257 is_simple_result = true; 00258 m_idx_at_rank.reserve(m_size); 00259 iterators.reserve(m_size); 00260 m_order_of.insert(m_order_of.end(), m_size, Vertex_order(0)); 00261 for (Index_t i = 0; i< m_size; ++i, ++begin) { 00262 m_idx_at_rank.push_back(Vertex_index(i)); 00263 iterators.push_back(begin); 00264 } 00265 std::sort(m_idx_at_rank.begin(), m_idx_at_rank.end(), 00266 Less_vertex_data<Vertex_data_base>(this)); 00267 for (Index_t j = 0; j < m_size; ++j) { 00268 Vertex_order vo(j); 00269 m_order_of[index_at_rank(vo).as_int()] = vo; 00270 } 00271 } 00272 00273 template <class ForwardIterator, class PolygonTraits> 00274 void Vertex_data<ForwardIterator, PolygonTraits>:: 00275 left_and_right_index(Vertex_index &left, Vertex_index &right, 00276 Vertex_index edge) 00277 { 00278 if (edges[edge.as_int()].is_left_to_right) { 00279 left = edge; right = next(edge); 00280 } else { 00281 right = edge; left = next(edge); 00282 } 00283 } 00284 00285 template <class ForwardIterator, class PolygonTraits> 00286 Vertex_data<ForwardIterator, PolygonTraits>:: 00287 Vertex_data(ForwardIterator begin, ForwardIterator end, 00288 const PolygonTraits& pgn_traits) 00289 : Base_class(begin, end, pgn_traits) {} 00290 00291 template <class ForwardIterator, class PolygonTraits> 00292 void Vertex_data<ForwardIterator, PolygonTraits>::init(Tree *tree) 00293 { 00294 // The initialization cannot be done in the constructor, 00295 // otherwise we copy singular valued iterators. 00296 edges.insert(edges.end(), this->m_size, Edge_data<Less_segs>(tree->end())); 00297 } 00298 00299 00300 template <class ForwardIterator, class PolygonTraits> 00301 bool Vertex_data<ForwardIterator, PolygonTraits>:: 00302 insertion_event(Tree *tree, Vertex_index prev_vt, 00303 Vertex_index mid_vt, Vertex_index next_vt) 00304 { 00305 // check which endpoint is above the other 00306 bool left_turn; 00307 switch(this->orientation_2(point(prev_vt), point(mid_vt), point(next_vt))) { 00308 case LEFT_TURN: left_turn = true; break; 00309 case RIGHT_TURN: left_turn = false; break; 00310 default: return false; 00311 00312 } 00313 Edge_data<Less_segs> 00314 &td_prev = edges[prev_vt.as_int()], 00315 &td_mid = edges[mid_vt.as_int()]; 00316 td_prev.is_in_tree = false; 00317 td_prev.is_left_to_right = false; 00318 td_mid.is_in_tree = false; 00319 td_mid.is_left_to_right = true; 00320 // insert the highest chain first 00321 std::pair<typename Tree::iterator, bool> result; 00322 if (left_turn) { 00323 result = tree->insert(prev_vt); 00324 // CGAL_polygon_assertion(result.second) 00325 td_prev.tree_it = result.first; 00326 td_prev.is_in_tree = true; 00327 result = tree->insert(mid_vt); 00328 // CGAL_polygon_assertion(result.second) 00329 td_mid.tree_it = result.first; 00330 td_mid.is_in_tree = true; 00331 } else { 00332 result = tree->insert(mid_vt); 00333 // CGAL_polygon_assertion(result.second) 00334 td_mid.tree_it = result.first; 00335 td_mid.is_in_tree = true; 00336 result = tree->insert(prev_vt); 00337 // CGAL_polygon_assertion(result.second) 00338 td_prev.tree_it = result.first; 00339 td_prev.is_in_tree = true; 00340 } 00341 return true; 00342 } 00343 00344 template <class ForwardIterator, class PolygonTraits> 00345 bool Vertex_data<ForwardIterator, PolygonTraits>:: 00346 on_right_side(Vertex_index vt, Vertex_index edge_id, bool above) 00347 { 00348 Orientation turn = 00349 this->orientation_2(point(edge_id), point(vt), point(next(edge_id))); 00350 bool left_turn = edges[edge_id.as_int()].is_left_to_right ? above : !above; 00351 if (left_turn) { 00352 if (turn != RIGHT_TURN) { 00353 return false; 00354 } 00355 } else { 00356 if (turn != LEFT_TURN) { 00357 return false; 00358 } 00359 } 00360 return true; 00361 } 00362 00363 template <class ForwardIterator, class PolygonTraits> 00364 bool Vertex_data<ForwardIterator, PolygonTraits>:: 00365 replacement_event(Tree *tree, Vertex_index cur_edge, Vertex_index next_edge) 00366 { 00367 // check if continuation point is on the right side of neighbor segments 00368 typedef typename Tree::iterator It; 00369 Edge_data<Less_segs> &td = edges[cur_edge.as_int()]; 00370 CGAL_polygon_assertion(td.is_in_tree); 00371 It cur_seg = td.tree_it; 00372 Vertex_index cur_vt = (td.is_left_to_right) ? next_edge : cur_edge; 00373 if (cur_seg != tree->begin()) { 00374 It seg_below = cur_seg; 00375 --seg_below; 00376 if (!on_right_side(cur_vt, *seg_below, true)) { 00377 return false; 00378 } 00379 } 00380 It seg_above = cur_seg; 00381 ++ seg_above; 00382 if (seg_above != tree->end()) { 00383 if (!on_right_side(cur_vt, *seg_above, false)) { 00384 return false; 00385 } 00386 } 00387 // replace the segment 00388 Edge_data<Less_segs> &new_td = 00389 edges[next_edge.as_int()]; 00390 new_td.is_left_to_right = td.is_left_to_right; 00391 new_td.is_in_tree = false; 00392 tree->erase(cur_seg); 00393 td.is_in_tree = false; 00394 new_td.tree_it = tree->insert(seg_above, next_edge); 00395 new_td.is_in_tree = true; 00396 return true; 00397 } 00398 00399 template <class ForwardIterator, class PolygonTraits> 00400 bool Vertex_data<ForwardIterator, PolygonTraits>:: 00401 deletion_event(Tree *tree, Vertex_index prev_vt, Vertex_index mid_vt) 00402 { 00403 // check if continuation point is on the right side of neighbor segments 00404 typedef typename Tree::iterator It; 00405 Edge_data<Less_segs> 00406 &td_prev = edges[prev_vt.as_int()], 00407 &td_mid = edges[mid_vt.as_int()]; 00408 It prev_seg = td_prev.tree_it, mid_seg = td_mid.tree_it; 00409 Vertex_index cur_vt = (td_prev.is_left_to_right) ? mid_vt : prev_vt; 00410 It seg_above = prev_seg; 00411 ++seg_above; 00412 if (seg_above == mid_seg) { 00413 ++seg_above; 00414 } else { 00415 // mid_seg was not above prev_seg, so prev_seg should be above mid_seg 00416 // We check this to see if the edges are really neighbors in the tree. 00417 It prev_seg_copy = mid_seg; 00418 ++prev_seg_copy; 00419 if (prev_seg_copy != prev_seg) 00420 return false; 00421 } 00422 // remove the segments 00423 tree->erase(prev_seg); 00424 td_prev.is_in_tree = false; 00425 tree->erase(mid_seg); 00426 td_mid.is_in_tree = false; 00427 // Check if the vertex that is removed lies between the two tree edges. 00428 if (seg_above != tree->end()) { 00429 if (!on_right_side(cur_vt, *seg_above, false)) 00430 return false; 00431 } 00432 if (seg_above != tree->begin()) { 00433 --seg_above; // which turns it in seg_below 00434 if (!on_right_side(cur_vt, *seg_above, true)) 00435 return false; 00436 } 00437 return true; 00438 } 00439 00440 template <class ForwardIterator, class PolygonTraits> 00441 void Vertex_data<ForwardIterator, PolygonTraits>:: 00442 sweep(Tree *tree) 00443 { 00444 if (this->m_size < 3) 00445 return; 00446 bool succes = true; 00447 for (Index_t i=0; i< this->m_size; ++i) { 00448 Vertex_index cur = index_at_rank(Vertex_order(i)); 00449 Vertex_index prev_vt = prev(cur), next_vt = next(cur); 00450 if (ordered_left_to_right(cur, next_vt)) { 00451 if (ordered_left_to_right(cur, prev_vt)) 00452 succes = insertion_event(tree, prev_vt, cur, next_vt); 00453 else 00454 succes = replacement_event(tree, prev_vt, cur); 00455 } else { 00456 if (ordered_left_to_right(cur, prev_vt)) 00457 succes = replacement_event(tree, cur, prev_vt); 00458 else 00459 succes = deletion_event(tree, prev_vt, cur); 00460 } 00461 if (!succes) 00462 break; 00463 } 00464 if (!succes) 00465 this->is_simple_result = false; 00466 } 00467 } 00468 // ----- End of implementation of i_polygon functions. ----- 00469 00470 00471 template <class Iterator, class PolygonTraits> 00472 bool is_simple_polygon(Iterator points_begin, Iterator points_end, 00473 const PolygonTraits& polygon_traits) 00474 { 00475 typedef Iterator ForwardIterator; 00476 typedef i_polygon::Vertex_data<ForwardIterator, PolygonTraits> Vertex_data; 00477 typedef std::set<i_polygon::Vertex_index, 00478 i_polygon::Less_segments<Vertex_data> > Tree; 00479 00480 // A temporary fix as the sweep in some cases doesn't discover vertices with degree > 2 00481 // Todo: fix the sweep code 00482 std::vector<typename PolygonTraits::Point_2> points(points_begin,points_end); 00483 std::sort(points.begin(), points.end(), polygon_traits.less_xy_2_object()); 00484 00485 typename std::vector<typename PolygonTraits::Point_2>::iterator 00486 succ(points.begin()) , it(succ++); 00487 for(;succ != points.end(); ++it,++succ){ 00488 if(*it == *succ){ 00489 return false; 00490 } 00491 } 00492 // end of fix 00493 Vertex_data vertex_data(points_begin, points_end, polygon_traits); 00494 Tree tree(&vertex_data); 00495 vertex_data.init(&tree); 00496 vertex_data.sweep(&tree); 00497 return vertex_data.is_simple_result; 00498 } 00499 00500 } // end of namespace CGAL 00501 00502 #endif