segment_delaunay_graph_nearest_site_2.h

来自「很多二维 三维几何计算算法 C++ 类库」· C头文件 代码 · 共 301 行

H
301
字号
// Copyright (c) 2006 Foundation for Research and Technology-Hellas (Greece).// 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.3-branch/Voronoi_diagram_2/include/CGAL/Voronoi_diagram_2/Segment_Delaunay_graph_nearest_site_2.h $// $Id: Segment_Delaunay_graph_nearest_site_2.h 29163 2006-03-07 23:41:02Z mkaravel $// //// Author(s)     : Menelaos Karavelas <mkaravel@iacm.forth.gr>#ifndef CGAL_VORONOI_DIAGRAM_2_SEGMENT_DELAUNAY_GRAPH_NEAREST_SITE_2_H#define CGAL_VORONOI_DIAGRAM_2_SEGMENT_DELAUNAY_GRAPH_NEAREST_SITE_2_H 1#include <CGAL/Voronoi_diagram_2/basic.h>#include <CGAL/Triangulation_utils_2.h>#include <boost/variant.hpp>CGAL_BEGIN_NAMESPACECGAL_VORONOI_DIAGRAM_2_BEGIN_NAMESPACE//=========================================================================//=========================================================================template<class DG>class Segment_Delaunay_graph_nearest_site_2{public:  typedef DG                                          Delaunay_graph;  typedef typename Delaunay_graph::Point_2            Point_2;  typedef Arity_tag<2>                                Arity;private:  typedef Triangulation_cw_ccw_2                      CW_CCW_2;  typedef typename Delaunay_graph::Site_2             Site_2;  typedef typename Delaunay_graph::Vertex_handle      Vertex_handle;  typedef typename Delaunay_graph::Face_handle        Face_handle;  typedef typename Delaunay_graph::Face_circulator    Face_circulator;  typedef typename Delaunay_graph::Edge_circulator    Edge_circulator;  typedef typename Delaunay_graph::Edge               Edge;  typedef typename Delaunay_graph::Geom_traits        Geom_traits;  typedef typename Geom_traits::Equal_2               Equal_2;  typedef typename Geom_traits::Orientation_2         Orientation_2;  typedef typename Geom_traits::Oriented_side_2       Oriented_side_2;  typedef typename Geom_traits::Oriented_side_of_bisector_2  Oriented_side_of_bisector_2;private:  static Site_2 opposite(const Site_2& t) {    CGAL_precondition( t.is_segment() );    if ( t.is_input() ) {      return Site_2::construct_site_2(t.target_of_supporting_site(),				      t.source_of_supporting_site());    } else {      if ( t.is_input(0) ) {	return Site_2::construct_site_2(t.target_of_supporting_site(),					t.source_of_supporting_site(),					t.target_of_crossing_site(1),					t.source_of_crossing_site(1),					false);      } else if ( t.is_input(1) ) {	return Site_2::construct_site_2(t.target_of_supporting_site(),					t.source_of_supporting_site(),					t.target_of_crossing_site(0),					t.source_of_crossing_site(0),					true);      } else {	return Site_2::construct_site_2(t.target_of_supporting_site(),					t.source_of_supporting_site(),					t.target_of_crossing_site(1),					t.source_of_crossing_site(1),					t.target_of_crossing_site(0),					t.source_of_crossing_site(0));      }    }  }  Site_2 orient_segment(const Site_2& s, const Site_2& p,			const Orientation_2& orientation) const  {    CGAL_precondition( s.is_segment() );    CGAL_precondition( p.is_point() );    Orientation o = orientation(s.source_site(), s.target_site(), p);    CGAL_assertion( o != COLLINEAR );    if ( o == LEFT_TURN ) { return s; }    return opposite(s);  }public:  typedef boost::variant<Vertex_handle,Edge,Face_handle>  result_type;  result_type operator()(const Delaunay_graph& dg, const Point_2& p) const {    CGAL_precondition( dg.dimension() >= 0 );    Oriented_side_of_bisector_2 side_of_bisector =      dg.geom_traits().oriented_side_of_bisector_2_object();    Equal_2 equal = dg.geom_traits().equal_2_object();    Site_2 sp = Site_2::construct_site_2(p);    Vertex_handle v = dg.nearest_neighbor(p);    if ( dg.dimension() == 0 ) {      return v;    }    if ( dg.dimension() == 1 ) {      Edge e = *dg.finite_edges_begin();      Vertex_handle v1 = e.first->vertex(CW_CCW_2::ccw(e.second));      Vertex_handle v2 = e.first->vertex(CW_CCW_2::cw(e.second) );      Oriented_side os = side_of_bisector(v1->site(), v2->site(), sp);            if ( os == ON_ORIENTED_BOUNDARY ) {	return e;      } else {	return v;      }    }    CGAL_assertion( dg.dimension() == 2 );    Site_2 sv = v->site();    Face_circulator fc_start = dg.incident_faces(v);    Face_circulator fc = fc_start;    // first check if the point lies on a Voronoi vertex    do {      int index = fc->index(v);      Vertex_handle v1 = fc->vertex(CW_CCW_2::ccw(index));      Vertex_handle v2 = fc->vertex(CW_CCW_2::cw(index) );      Oriented_side os1 = ON_POSITIVE_SIDE, os2 = ON_POSITIVE_SIDE;      // check if the query point is identical to an endpoint of a      // segment that has a Voronoi face with zero area.      if ( !dg.is_infinite(v1) && !dg.is_infinite(v2) ) {	Site_2 s1 = v1->site();	Site_2 s2 = v2->site();	if ( sv.is_point() && equal(sv, sp) &&	     s1.is_segment() && s2.is_segment() ) {	  bool b1 = equal(sv, s1.source_site()) || equal(sv, s1.target_site());	  bool b2 = equal(sv, s2.source_site()) || equal(sv, s2.target_site());	  if ( b1 && b2 ) { return Face_handle(fc); }	}      }      // do the generic check now      if ( !dg.is_infinite(v1) ) {	os1 = side_of_bisector(sv, v1->site(), sp);      }      if ( !dg.is_infinite(v2) ) {	os2 = side_of_bisector(sv, v2->site(), sp);      }      CGAL_assertion( os1 != ON_NEGATIVE_SIDE );      CGAL_assertion( os2 != ON_NEGATIVE_SIDE );      if ( os1 == ON_ORIENTED_BOUNDARY && os2 == ON_ORIENTED_BOUNDARY ) {	return fc;      }      ++fc;    } while ( fc != fc_start );    // now check if the point lies on a Voronoi edge    Edge_circulator ec_start = dg.incident_edges(v);    Edge_circulator ec = ec_start;    do {      Face_handle f = ec->first;      int idx = ec->second;      CGAL_assertion( f->vertex(CW_CCW_2::cw(idx)) == v );      Vertex_handle v1 = f->vertex(CW_CCW_2::ccw(idx));      // check if the query point is lies on the bisector between a      // segment and its endpoint      if ( !dg.is_infinite(v1) ) {	Site_2 s1 = v1->site();	if ( sv.is_point() &&  s1.is_segment() ) {	  bool b = equal(sv, s1.source_site()) || equal(sv, s1.target_site());	  if ( b && equal(sv, sp) ) { return *ec; }	  Oriented_side os = side_of_bisector(sv, s1, sp);	  if ( b && os == ON_ORIENTED_BOUNDARY ) { return *ec; }	}	if ( sv.is_segment() && s1.is_point() ) {	  bool b = equal(sv.source_site(), s1) || equal(sv.target_site(), s1);	  if ( b && equal(s1, sp) ) { return *ec; }	  Oriented_side os = side_of_bisector(sv, s1, sp);	  if ( b && os == ON_ORIENTED_BOUNDARY ) { return *ec; }	}      }      Oriented_side os1 = ON_POSITIVE_SIDE;      // do the generic check now      if ( !dg.is_infinite(v1) ) {	os1 = side_of_bisector(sv, v1->site(), sp);      }      CGAL_assertion( os1 != ON_NEGATIVE_SIDE );      if ( os1 != ON_ORIENTED_BOUNDARY ) {	++ec;	continue;      }      // now find the correct part of the bisector on which the query      // point lies; this part is essential when the two sites have      // more than one Voronoi edge between them      CGAL_assertion( !dg.is_infinite(v1) );      Site_2 s1 = v1->site();      // if both v and v1 are points there is no need to check for      // other Voronoi edges; there is only one.      if ( sv.is_point() && s1.is_point() ) {	return *ec;      }      // the vertices v2 and v3 can only be infinite in two cases:      // 1. when both v and v1 are points      // 2. when v and v1 are a point and a segment and the point is      //    an endpoint of the segment      // none of the two cases can happen at this point in the code,      // since we already have treated these two cases above.      Vertex_handle v2 = f->vertex(idx);      Vertex_handle v3 = dg.tds().mirror_vertex(f, idx);      CGAL_assertion( !dg.is_infinite(v2) && !dg.is_infinite(v3) );      Oriented_side_2 vv_oriented_side =	dg.geom_traits().oriented_side_2_object();      Orientation_2 orientation = dg.geom_traits().orientation_2_object();      Oriented_side o2 = ON_POSITIVE_SIDE, o3 = ON_NEGATIVE_SIDE;      Site_2 sp = Site_2::construct_site_2(p);      if ( sv.is_segment() ) {	Site_2 svo = orient_segment(sv, sp, orientation);	o2 = vv_oriented_side(sv, v2->site(), s1, svo, sp);	o3 = vv_oriented_side(sv, s1, v3->site(), svo, sp);	CGAL_assertion( o2 != ON_ORIENTED_BOUNDARY );	CGAL_assertion( o3 != ON_ORIENTED_BOUNDARY );	if ( o2 == ON_NEGATIVE_SIDE && o3 == ON_POSITIVE_SIDE ) {	  return *ec;	}      } else {	CGAL_assertion( s1.is_segment() );	Site_2 s1o = orient_segment(s1, sp, orientation);	o2 = vv_oriented_side(sv, v2->site(), s1, s1o, sp);	o3 = vv_oriented_side(sv, s1, v3->site(), s1o, sp);	CGAL_assertion( o2 != ON_ORIENTED_BOUNDARY );	CGAL_assertion( o3 != ON_ORIENTED_BOUNDARY );	if ( o2 == ON_POSITIVE_SIDE && o3 == ON_NEGATIVE_SIDE ) {	  return *ec;	}      }      ++ec;          } while ( ec != ec_start );    // the point lies in a Voronoi face    return v;  }};//=========================================================================//=========================================================================CGAL_VORONOI_DIAGRAM_2_END_NAMESPACECGAL_END_NAMESPACE#endif // CGAL_VORONOI_DIAGRAM_2_SEGMENT_DELAUNAY_GRAPH_NEAREST_SITE_2_H

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?