BWAPI
SPAR/AIModule/BWTA/vendors/CGAL/CGAL/Nef_2/PM_checker.h
Go to the documentation of this file.
00001 // Copyright (c) 1997-2000  Max-Planck-Institute Saarbruecken (Germany).
00002 // All rights reserved.
00003 //
00004 // This file is part of CGAL (www.cgal.org); you may redistribute it under
00005 // the terms of the Q Public License version 1.0.
00006 // See the file LICENSE.QPL distributed with CGAL.
00007 //
00008 // Licensees holding a valid commercial license may use this file in
00009 // accordance with the commercial license agreement provided with the software.
00010 //
00011 // This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
00012 // WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
00013 //
00014 // $URL: svn+ssh://scm.gforge.inria.fr/svn/cgal/branches/CGAL-3.5-branch/Nef_2/include/CGAL/Nef_2/PM_checker.h $
00015 // $Id: PM_checker.h 40851 2007-11-09 15:27:44Z ameyer $
00016 // 
00017 //
00018 // Author(s)     : Michael Seel <seel@mpi-sb.mpg.de>
00019 
00020 #ifndef CGAL_PM_CHECKER_H
00021 #define CGAL_PM_CHECKER_H
00022 
00023 #include <CGAL/basic.h>
00024 #include <CGAL/Unique_hash_map.h>
00025 #include <CGAL/Nef_2/PM_const_decorator.h>
00026 
00027 CGAL_BEGIN_NAMESPACE
00028 
00029 /*{\Moptions outfile=PM_checker.man }*/
00030 /*{\Manpage {PM_checker}{PMCDEC,GEOM}{Plane map checking}{}}*/
00031 
00032 /*{\Mdefinition An instance |\Mvar| of the data type |\Mname| is a
00033 decorator to check the structure of a plane map. It is generic with
00034 respect to two template concepts.  |PMCDEC| has to be a decorator
00035 model of our |PM_const_decorator| concept. |GEOM| has to be a model of
00036 our geometry kernel concept.}*/
00037 
00038 /*{\Mgeneralization PM_const_decorator}*/
00039 
00040 template <typename PMCDEC, typename GEOM> 
00041 class PM_checker : public PMCDEC
00042 { typedef PMCDEC Base;
00043   const GEOM& K;
00044 public:
00045 /*{\Mtypes 3}*/
00046 typedef PMCDEC  PM_const_decorator;
00047 /*{\Mtypemember equals |PMCDEC|.}*/
00048 typedef typename PMCDEC::Plane_map Plane_map;
00049 /*{\Mtypemember equals |PMCDEC::Plane_map|, the underlying plane map type.}*/
00050 typedef GEOM Geometry;
00051 /*{\Mtypemember equals |GEOM|. Add link to GEOM concept.\\
00052 \precond |Geometry::Point_2| equals |Plane_map::Point|. }*/
00053 
00054 typedef typename GEOM::Point_2     Point;
00055 typedef typename GEOM::Direction_2 Direction;
00056 
00057   typedef typename Base::Vertex_const_handle  Vertex_const_handle;
00058   typedef typename Base::Halfedge_const_handle Halfedge_const_handle;
00059 typedef typename Base::Vertex_const_iterator Vertex_const_iterator;
00060 typedef typename Base::Halfedge_const_iterator Halfedge_const_iterator;
00061 typedef typename Base::Halfedge_around_vertex_const_circulator Halfedge_around_vertex_const_circulator;
00062 typedef typename Base::Halfedge_around_face_const_circulator Halfedge_around_face_const_circulator;
00063 
00064 
00065   using Base::clear;
00066   using Base::vertices_begin;
00067   using Base::vertices_end;
00068   using Base::halfedges_begin;
00069   using Base::halfedges_end;
00070   using Base::faces_begin;
00071   using Base::faces_end;
00072   using Base::number_of_vertices;
00073   using Base::number_of_halfedges;
00074   using Base::number_of_edges;
00075   using Base::number_of_faces;
00076   using Base::number_of_connected_components;
00077   using Base::check_integrity_and_topological_planarity;
00078 
00079 /*{\Mtext Iterators, handles, and circulators are inherited from 
00080 |PM_const_decorator|.}*/
00081 
00082 /*{\Mcreation 3}*/
00083 PM_checker(Plane_map& P, const Geometry& k = Geometry()) : 
00084   Base(P), K(k) {}
00085 /*{\Mcreate constructs a plane map checker working on |P| with
00086 geometric predicates used from |k|.}*/
00087 
00088 PM_checker(const Base& D, const Geometry& k = Geometry()) : 
00089   Base(D), K(k) {}
00090 
00091 
00092 /*{\Moperations 2 }*/
00093 Direction direction(Halfedge_const_handle e) const
00094 { return K.construct_direction(
00095     point(source(e)),point(target(e))); }
00096 
00097 bool is_forward(Halfedge_const_handle e) const
00098 { return K.compare_xy(point(source(e)),point(target(e)))<0; }
00099 
00100 void check_order_preserving_embedding(Vertex_const_handle v) const;
00101 /*{\Mop checks if the embedding of the targets of the edges in
00102 the adjacency list |A(v)| is counter-clockwise order-preserving with 
00103 respect to the order of the edges in |A(v)|.}*/
00104 
00105 void check_order_preserving_embedding() const;
00106 /*{\Mop checks if the embedding of all vertices of |P| is 
00107 counter-clockwise order-preserving with respect to the adjacency
00108 list ordering of all vertices.}*/
00109 
00110 void check_forward_prefix_condition(Vertex_const_handle v) const;
00111 /*{\Mop checks the forward-prefix property of the adjacency list of |v|.}*/
00112 
00113 Halfedge_const_iterator
00114 check_boundary_is_clockwise_weakly_polygon() const;
00115 /*{\Mop checks if the outer face cycle of |P| is a clockwise weakly polygon 
00116 and returns a halfedge on the boundary. \precond |P| is a connected graph.
00117 }*/
00118 
00119 void check_is_triangulation() const;
00120 /*{\Mop checks if |P| is a triangulation.}*/
00121 
00122 }; // PM_checker<PMCDEC,GEOM>
00123 
00124 
00125 template <typename PMCDEC, typename GEOM>
00126 void PM_checker<PMCDEC,GEOM>::
00127 check_order_preserving_embedding(Vertex_const_handle v) const
00128 {
00129   if ( is_isolated(v) ) return;
00130   std::ostringstream error_status;
00131   CGAL::set_pretty_mode ( error_status );
00132   Halfedge_const_handle ef = first_out_edge(v) ,e=ef,en,enn;
00133   error_status << "check_order_preserving_embedding\n";
00134   error_status << "vertex " << PV(v) << std::endl;
00135   error_status << "ef " << PE(ef) << std::endl;
00136   while ( true ) {
00137     en = cyclic_adj_succ(e);
00138     enn = cyclic_adj_succ(en);
00139     if (en == ef) break;
00140     error_status << "  -> " << point(target(e))
00141                  << " " << point(target(en))  
00142                  << " " << point(target(enn)) << std::endl;
00143     bool ccw1 = K.strictly_ordered_ccw(direction(e),direction(en),
00144                                        direction(enn));
00145     bool ccw2 = K.strictly_ordered_ccw(direction(e),direction(en),
00146                                        direction(ef));
00147     if ( !(ccw1 && ccw2) ) {
00148       error_status << "ccw order violate!" << std::endl << '\0';
00149       CGAL_error_msg(error_status.str().c_str());
00150     }
00151     e = en;
00152   }
00153 }
00154 
00155 template <typename PMCDEC, typename GEOM>
00156 void PM_checker<PMCDEC,GEOM>::
00157 check_forward_prefix_condition(Vertex_const_handle v) const
00158 { Halfedge_const_handle ef = first_out_edge(v);
00159   if ( ef == Halfedge_const_handle() ) return;
00160   Halfedge_const_handle el = cyclic_adj_pred(ef);
00161   bool is_left_turn = K.left_turn(point(v),
00162                                 point(target(ef)),
00163                                 point(target(el)));
00164   bool el_forward = is_forward(el);
00165   bool ef_forward = is_forward(ef);
00166   bool ef_el_eq = (ef==el);
00167   std::ostringstream error_status;
00168   error_status << "check_forward_prefix_condition: ";
00169   error_status << PV(v) << "\n";
00170   error_status << PE(ef) << "\n" << PE(el) << "\n";
00171   error_status << " ef == el = " << ef_el_eq;
00172   error_status << " ef_forward = " << ef_forward;
00173   error_status << " el_forward = " << el_forward;
00174   error_status << " is_left_turn = " << is_left_turn;
00175   CGAL_assertion_msg( (ef == el ||
00176                        ef_forward && !el_forward ||
00177                        ef_forward &&  el_forward && is_left_turn ||
00178                        !ef_forward && !el_forward && is_left_turn) ,
00179                        error_status.str().c_str());
00180 }
00181 
00182 /* We check the geometric integrity of the structure. We check
00183    + that all adjacent nodes are differently embedded
00184    + that all node lists are correctly embedded counterclockwise
00185      with winding number one.
00186    + that the convex hull of the structure has winding number one.
00187 */
00188 
00189 template <typename PMCDEC, typename GEOM>
00190 void PM_checker<PMCDEC,GEOM>::
00191 check_order_preserving_embedding() const
00192 {
00193   Vertex_const_iterator vit;
00194   for (vit = this->vertices_begin(); vit != this->vertices_end(); ++vit) {
00195     check_order_preserving_embedding(vit);
00196     check_forward_prefix_condition(vit);
00197   }
00198 }
00199 
00200 
00201 template <typename PMCDEC, typename GEOM>
00202 typename PM_checker<PMCDEC,GEOM>::Halfedge_const_iterator
00203 PM_checker<PMCDEC,GEOM>::
00204 check_boundary_is_clockwise_weakly_polygon() const
00205 {
00206   Vertex_const_iterator vit, v_min;
00207   for (vit = v_min = this->vertices_begin() ; vit != this->vertices_end(); ++vit) 
00208     if ( K.compare_xy(point(vit), point(v_min))<0 ) v_min = vit;
00209   CGAL_assertion_msg(!is_isolated(v_min),"Minimal vertex not connected.");
00210   Point p_min = point(v_min);
00211   // determine boundary edge incident to v_min: 
00212   Halfedge_const_handle e_boundary_at_v_min = first_out_edge(v_min);
00213   // all out edges are forward oriented due to minimality
00214   Halfedge_around_vertex_const_circulator 
00215     hvit(e_boundary_at_v_min), hend(hvit);
00216   do {
00217     --hvit;
00218     Point p1 = point(target(e_boundary_at_v_min));
00219     Point p2 = point(target(hvit));
00220     if ( K.orientation(p_min,p1,p2) > 0 ) { // left_turn
00221       e_boundary_at_v_min = hvit;
00222       break;
00223     }
00224   } while (hvit != hend);
00225   // now e_boundary_at_v_min is highest starting edge in bundle!!
00226 
00227   int winding_around_globally=0;
00228   Halfedge_around_face_const_circulator
00229     hfit(e_boundary_at_v_min),hstart(hfit);
00230   Halfedge_const_handle e_prev = next(e_boundary_at_v_min);
00231   /* we run counterclockwise around the outer face cycle and allow only
00232      position where the direction vector of an edge gets smaller again */
00233   Direction d_prev = direction(e_prev);
00234   CGAL_For_all_backwards(hstart,hfit) {
00235     Direction d_curr = direction(hfit);
00236     if ( d_curr < d_prev ) ++winding_around_globally;
00237     d_prev = d_curr;
00238   }
00239   CGAL_assertion(winding_around_globally == 1);
00240   return e_boundary_at_v_min;
00241 }
00242 
00243 template <typename PMCDEC, typename GEOM>
00244 void PM_checker<PMCDEC,GEOM>::
00245 check_is_triangulation() const
00246 {
00247   Halfedge_const_iterator eb;
00248   CGAL_assertion(this->number_of_connected_components() == 1);
00249   CGAL_assertion_msg(this->number_of_edges()!=this->number_of_vertices()-1,
00250     " checker checks only full dimensional complexes.");
00251   this->check_integrity_and_topological_planarity(false);
00252   check_order_preserving_embedding();
00253   eb = check_boundary_is_clockwise_weakly_polygon();
00254 
00255   CGAL::Unique_hash_map< Halfedge_const_iterator, bool> on_boundary(false);
00256   Halfedge_around_face_const_circulator hit(eb), hend(hit);
00257   std::ostringstream error_status;
00258   CGAL::set_pretty_mode ( error_status );
00259   error_status << "check_is_triangulation\n";
00260   error_status << "on boundary:\n";
00261   CGAL_For_all(hit,hend) {
00262     error_status << "  " << PE(hit) << std::endl;
00263     on_boundary[hit]=true;
00264   }
00265   Halfedge_const_iterator eit;
00266   for( eit = this->halfedges_begin(); eit != this->halfedges_end(); ++eit) {
00267     if (on_boundary[eit]) continue;
00268     hit = hend = eit; 
00269     int edges_in_face_cycle=0;
00270     CGAL_For_all(hit,hend) {
00271       error_status << PE(hit);
00272       ++edges_in_face_cycle;
00273     }
00274     CGAL_assertion_msg(edges_in_face_cycle==3,error_status.str().c_str());
00275     CGAL_assertion_msg(
00276       K.left_turn(point(source(hit)),point(target(hit)),
00277                  point(target(next(hit)))), error_status.str().c_str());
00278   }
00279 }
00280 
00281 
00282 
00283 CGAL_END_NAMESPACE
00284 
00285 
00286 #endif // CGAL_PM_CHECKER_H
00287 
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines