BWAPI
SPAR/AIModule/BWTA/vendors/CGAL/CGAL/Polygon_2/Polygon_2_simplicity.h
Go to the documentation of this file.
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
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines