mirror of https://github.com/CGAL/cgal
Algorithms now conform to the concept.
The implementations missed const qualifiers everywhere and thus were non-conforming to the specified concept. Triangular Expansions now observes changes to the attached arrangement. Copy of the constraints on CDT initialization is now avoided with boost::transform_iterator. Fixed some bugs on Simple Polygon algorithm when the attached arrangement was changed. The compute_visibility function did not clear the given output arrangement. Added some simple test cases.
This commit is contained in:
parent
6ec47c5a8a
commit
8ea81e7515
|
|
@ -691,7 +691,7 @@ private:
|
||||||
|
|
||||||
//private methods
|
//private methods
|
||||||
private:
|
private:
|
||||||
void add_box ()
|
void add_box () const
|
||||||
{
|
{
|
||||||
std::vector<Point_2> pts;
|
std::vector<Point_2> pts;
|
||||||
pts.reserve( vs.size()+1 );
|
pts.reserve( vs.size()+1 );
|
||||||
|
|
@ -727,7 +727,7 @@ private:
|
||||||
es.back().set_index( es.back().source_index(), edge_base );
|
es.back().set_index( es.back().source_index(), edge_base );
|
||||||
}
|
}
|
||||||
|
|
||||||
void compute_shifted_source ()
|
void compute_shifted_source () const
|
||||||
{
|
{
|
||||||
if ( query_type != VERTEX_QUERY ) {
|
if ( query_type != VERTEX_QUERY ) {
|
||||||
shifted_source = query_pt;
|
shifted_source = query_pt;
|
||||||
|
|
@ -746,14 +746,15 @@ private:
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void init_quadrant_each_vertex( int i )
|
void init_quadrant_each_vertex( int i ) const
|
||||||
{ vs[i].init_quadrant( query_pt ); }
|
{ vs[i].init_quadrant( query_pt ); }
|
||||||
void init_quadrant_parallel( CGAL::Sequential_tag )
|
|
||||||
|
void init_quadrant_parallel( CGAL::Sequential_tag ) const
|
||||||
{
|
{
|
||||||
for ( int i = 0; i < vs.size(); i++ )
|
for ( int i = 0; i < vs.size(); i++ )
|
||||||
init_quadrant_each_vertex( i );
|
init_quadrant_each_vertex( i );
|
||||||
}
|
}
|
||||||
void init_quadrant_parallel( CGAL::Parallel_tag )
|
void init_quadrant_parallel( CGAL::Parallel_tag ) const
|
||||||
{
|
{
|
||||||
#ifdef CGAL_LINKED_WITH_EBB
|
#ifdef CGAL_LINKED_WITH_EBB
|
||||||
Parallel_init_quadrant init( this );
|
Parallel_init_quadrant init( this );
|
||||||
|
|
@ -763,17 +764,19 @@ private:
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
void init_orientation_each_edge( int i )
|
void init_orientation_each_edge( int i ) const
|
||||||
{
|
{
|
||||||
es[i].init_orientation( query_pt, vs[es[i].source_index()].point(),
|
es[i].init_orientation( query_pt, vs[es[i].source_index()].point(),
|
||||||
vs[es[i].target_index()].point() );
|
vs[es[i].target_index()].point() );
|
||||||
}
|
}
|
||||||
void init_orientation_parallel( CGAL::Sequential_tag )
|
|
||||||
|
void init_orientation_parallel( CGAL::Sequential_tag ) const
|
||||||
{
|
{
|
||||||
for ( int i = 0; i < es.size(); i++ )
|
for ( int i = 0; i < es.size(); i++ )
|
||||||
init_orientation_each_edge( i );
|
init_orientation_each_edge( i );
|
||||||
}
|
}
|
||||||
void init_orientation_parallel( CGAL::Parallel_tag )
|
|
||||||
|
void init_orientation_parallel( CGAL::Parallel_tag ) const
|
||||||
{
|
{
|
||||||
#ifdef CGAL_LINKED_WITH_EBB
|
#ifdef CGAL_LINKED_WITH_EBB
|
||||||
Parallel_init_orientation init( this );
|
Parallel_init_orientation init( this );
|
||||||
|
|
@ -783,13 +786,13 @@ private:
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
void sort_vertices( CGAL::Sequential_tag )
|
void sort_vertices( CGAL::Sequential_tag ) const
|
||||||
{
|
{
|
||||||
Is_swept_earlier comp ( query_pt, &vs, shifted_source, shifted_quadrant );
|
Is_swept_earlier comp ( query_pt, &vs, shifted_source, shifted_quadrant );
|
||||||
std::sort( good_vdx.begin(), good_vdx.end(), comp );
|
std::sort( good_vdx.begin(), good_vdx.end(), comp );
|
||||||
}
|
}
|
||||||
|
|
||||||
void sort_vertices( CGAL::Parallel_tag )
|
void sort_vertices( CGAL::Parallel_tag ) const
|
||||||
{
|
{
|
||||||
#ifdef CGAL_LINKED_WITH_TBB
|
#ifdef CGAL_LINKED_WITH_TBB
|
||||||
Is_swept_earlier comp ( query_pt, &vs, shifted_source, shifted_quadrant );
|
Is_swept_earlier comp ( query_pt, &vs, shifted_source, shifted_quadrant );
|
||||||
|
|
@ -799,7 +802,7 @@ private:
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
void remove_duplicated_vertices()
|
void remove_duplicated_vertices() const
|
||||||
{
|
{
|
||||||
// find duplicated vertices
|
// find duplicated vertices
|
||||||
int last = 0;
|
int last = 0;
|
||||||
|
|
@ -816,9 +819,9 @@ private:
|
||||||
good_vdx.erase( good_vdx.begin()+last+1, good_vdx.end() );
|
good_vdx.erase( good_vdx.begin()+last+1, good_vdx.end() );
|
||||||
}
|
}
|
||||||
|
|
||||||
void sort_incident ( CGAL::Sequential_tag )
|
void sort_incident ( CGAL::Sequential_tag ) const
|
||||||
{ std::sort( incident.begin(), incident.end() ); }
|
{ std::sort( incident.begin(), incident.end() ); }
|
||||||
void sort_incident ( CGAL::Parallel_tag )
|
void sort_incident ( CGAL::Parallel_tag ) const
|
||||||
{
|
{
|
||||||
#ifdef CGAL_LINKED_WITH_TBB
|
#ifdef CGAL_LINKED_WITH_TBB
|
||||||
tbb::parallel_sort( incident.begin(), incident.end() );
|
tbb::parallel_sort( incident.begin(), incident.end() );
|
||||||
|
|
@ -827,7 +830,7 @@ private:
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
void construct_incident_map()
|
void construct_incident_map() const
|
||||||
{
|
{
|
||||||
incident.clear();
|
incident.clear();
|
||||||
incident.reserve( es.size()*2 );
|
incident.reserve( es.size()*2 );
|
||||||
|
|
@ -847,7 +850,7 @@ private:
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool funnel_block_right( int v_idx, int e_idx )
|
bool funnel_block_right( int v_idx, int e_idx ) const
|
||||||
{
|
{
|
||||||
int s_idx = vs[es[e_idx].source_index()].alias_index();
|
int s_idx = vs[es[e_idx].source_index()].alias_index();
|
||||||
int t_idx = vs[es[e_idx].target_index()].alias_index();
|
int t_idx = vs[es[e_idx].target_index()].alias_index();
|
||||||
|
|
@ -865,7 +868,7 @@ private:
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool funnel_has_precedessor( int v_idx, int e_idx )
|
bool funnel_has_precedessor( int v_idx, int e_idx ) const
|
||||||
{
|
{
|
||||||
int s_idx = vs[es[e_idx].source_index()].alias_index();
|
int s_idx = vs[es[e_idx].source_index()].alias_index();
|
||||||
int t_idx = vs[es[e_idx].target_index()].alias_index();
|
int t_idx = vs[es[e_idx].target_index()].alias_index();
|
||||||
|
|
@ -876,7 +879,7 @@ private:
|
||||||
return es[e_idx].outward();
|
return es[e_idx].outward();
|
||||||
}
|
}
|
||||||
|
|
||||||
void funnel ( int first, int last )
|
void funnel ( int first, int last ) const
|
||||||
{
|
{
|
||||||
std::vector<int> left, right;
|
std::vector<int> left, right;
|
||||||
left.reserve( last - first );
|
left.reserve( last - first );
|
||||||
|
|
@ -910,7 +913,7 @@ private:
|
||||||
vs[good_vdx[i]].set_sorted_index( i );
|
vs[good_vdx[i]].set_sorted_index( i );
|
||||||
}
|
}
|
||||||
|
|
||||||
void process_funnel ()
|
void process_funnel () const
|
||||||
{
|
{
|
||||||
// TBD: future inmprovement: parallelly compute orientation
|
// TBD: future inmprovement: parallelly compute orientation
|
||||||
std::vector<CGAL::Orientation> orients( good_vdx.size()-1, CGAL::LEFT_TURN );
|
std::vector<CGAL::Orientation> orients( good_vdx.size()-1, CGAL::LEFT_TURN );
|
||||||
|
|
@ -957,7 +960,7 @@ private:
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifndef NDEBUG
|
#ifndef NDEBUG
|
||||||
void check_consistency_after_init()
|
void check_consistency_after_init() const
|
||||||
{
|
{
|
||||||
for ( int i = 0; i < vs.size(); i++ ) {
|
for ( int i = 0; i < vs.size(); i++ ) {
|
||||||
int alias = vs[i].alias_index();
|
int alias = vs[i].alias_index();
|
||||||
|
|
@ -993,7 +996,7 @@ private:
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
void keep_consistency_after_init()
|
void keep_consistency_after_init() const
|
||||||
{
|
{
|
||||||
for ( int i = 0; i < vs.size(); i++ ) {
|
for ( int i = 0; i < vs.size(); i++ ) {
|
||||||
int alias = vs[i].alias_index();
|
int alias = vs[i].alias_index();
|
||||||
|
|
@ -1010,7 +1013,7 @@ private:
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void init_vertices ( const Face_const_handle& fh )
|
void init_vertices ( const Face_const_handle& fh ) const
|
||||||
{
|
{
|
||||||
Circulator circ, curr;
|
Circulator circ, curr;
|
||||||
Hole_const_iterator hi;
|
Hole_const_iterator hi;
|
||||||
|
|
@ -1074,7 +1077,7 @@ private:
|
||||||
}
|
}
|
||||||
|
|
||||||
// Precondtion: dp != any end point of the edge.
|
// Precondtion: dp != any end point of the edge.
|
||||||
int do_intersect_edge ( const Point_2& dp, int i )
|
int do_intersect_edge ( const Point_2& dp, int i ) const
|
||||||
{
|
{
|
||||||
CGAL::Orientation orient1, orient2;
|
CGAL::Orientation orient1, orient2;
|
||||||
if ( es[i].pass_query_pt() ) // ignore bad edges
|
if ( es[i].pass_query_pt() ) // ignore bad edges
|
||||||
|
|
@ -1089,16 +1092,17 @@ private:
|
||||||
return 1;
|
return 1;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void do_intersect_parallel ( const Point_2& dp,
|
void do_intersect_parallel ( const Point_2& dp,
|
||||||
std::vector<int>& results,
|
std::vector<int>& results,
|
||||||
CGAL::Sequential_tag )
|
CGAL::Sequential_tag ) const
|
||||||
{
|
{
|
||||||
for ( int i = 0; i < es.size(); i++ )
|
for ( int i = 0; i < es.size(); i++ )
|
||||||
results[i] = do_intersect_edge( dp, i );
|
results[i] = do_intersect_edge( dp, i );
|
||||||
}
|
}
|
||||||
void do_intersect_parallel ( const Point_2& dp,
|
void do_intersect_parallel ( const Point_2& dp,
|
||||||
std::vector<int>& results,
|
std::vector<int>& results,
|
||||||
CGAL::Parallel_tag )
|
CGAL::Parallel_tag ) const
|
||||||
{
|
{
|
||||||
#ifdef CGAL_LINKED_WITH_TBB
|
#ifdef CGAL_LINKED_WITH_TBB
|
||||||
Parallel_do_intersect_edge obj( this, dp, results );
|
Parallel_do_intersect_edge obj( this, dp, results );
|
||||||
|
|
@ -1108,12 +1112,12 @@ private:
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
int default_cone_size ( CGAL::Sequential_tag )
|
int default_cone_size ( CGAL::Sequential_tag ) const
|
||||||
{ return vs.size(); }
|
{ return vs.size(); }
|
||||||
int default_cone_size ( CGAL::Parallel_tag )
|
int default_cone_size ( CGAL::Parallel_tag ) const
|
||||||
{ return 256; }
|
{ return 256; }
|
||||||
|
|
||||||
void partition_cones ()
|
void partition_cones () const
|
||||||
{
|
{
|
||||||
Intersection_edges active_edges( es.size() );
|
Intersection_edges active_edges( es.size() );
|
||||||
int curr;
|
int curr;
|
||||||
|
|
@ -1194,7 +1198,7 @@ private:
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Point_2 ray_edge_intersection( int v_idx, int e_idx )
|
Point_2 ray_edge_intersection( int v_idx, int e_idx ) const
|
||||||
{
|
{
|
||||||
const Point_2& dp = vs[v_idx].point();
|
const Point_2& dp = vs[v_idx].point();
|
||||||
const Point_2& s = vs[es[e_idx].source_index()].point();
|
const Point_2& s = vs[es[e_idx].source_index()].point();
|
||||||
|
|
@ -1219,7 +1223,7 @@ private:
|
||||||
return Point_2( ipoint->x(), ipoint->y() );
|
return Point_2( ipoint->x(), ipoint->y() );
|
||||||
}
|
}
|
||||||
|
|
||||||
void compute_visibility_partition( int cone_idx )
|
void compute_visibility_partition( int cone_idx ) const
|
||||||
{
|
{
|
||||||
const Cone& cone = cones[cone_idx];
|
const Cone& cone = cones[cone_idx];
|
||||||
Sub_region& result = sub_regions[cone_idx];
|
Sub_region& result = sub_regions[cone_idx];
|
||||||
|
|
@ -1303,13 +1307,13 @@ private:
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void compute_visibility_parallel( CGAL::Sequential_tag )
|
void compute_visibility_parallel( CGAL::Sequential_tag ) const
|
||||||
{
|
{
|
||||||
for ( int i = 0; i < cones.size(); i++ )
|
for ( int i = 0; i < cones.size(); i++ )
|
||||||
compute_visibility_partition( i );
|
compute_visibility_partition( i );
|
||||||
}
|
}
|
||||||
|
|
||||||
void compute_visibility_parallel( CGAL::Parallel_tag )
|
void compute_visibility_parallel( CGAL::Parallel_tag ) const
|
||||||
{
|
{
|
||||||
#ifdef CGAL_LINKED_WITH_TBB
|
#ifdef CGAL_LINKED_WITH_TBB
|
||||||
if ( cones.size() == 1 )
|
if ( cones.size() == 1 )
|
||||||
|
|
@ -1321,7 +1325,7 @@ private:
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
void merge_result()
|
void merge_result() const
|
||||||
{
|
{
|
||||||
polygon.clear();
|
polygon.clear();
|
||||||
cone_end_idx = cone_start_idx = -1;
|
cone_end_idx = cone_start_idx = -1;
|
||||||
|
|
@ -1342,7 +1346,7 @@ private:
|
||||||
assert( polygon.size() > 2 );
|
assert( polygon.size() > 2 );
|
||||||
}
|
}
|
||||||
|
|
||||||
void compute_visibility_impl ( const Face_const_handle& fh )
|
void compute_visibility_impl ( const Face_const_handle& fh ) const
|
||||||
{
|
{
|
||||||
assert( !fh->is_unbounded() );
|
assert( !fh->is_unbounded() );
|
||||||
|
|
||||||
|
|
@ -1365,15 +1369,15 @@ private:
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename VARR>
|
template <typename VARR>
|
||||||
void conditional_regularize( VARR& arr_out, CGAL::Tag_true )
|
void conditional_regularize( VARR& arr_out, CGAL::Tag_true ) const
|
||||||
{ regularize_output( arr_out ); }
|
{ regularize_output( arr_out ); }
|
||||||
|
|
||||||
template <typename VARR>
|
template <typename VARR>
|
||||||
void conditional_regularize( VARR& arr_out, CGAL::Tag_false )
|
void conditional_regularize( VARR& arr_out, CGAL::Tag_false ) const
|
||||||
{} // do nothing
|
{} // do nothing
|
||||||
|
|
||||||
template <typename VARR>
|
template <typename VARR>
|
||||||
void regularize_output( VARR& arr_out )
|
void regularize_output( VARR& arr_out ) const
|
||||||
{
|
{
|
||||||
typename VARR::Edge_iterator eit;
|
typename VARR::Edge_iterator eit;
|
||||||
for ( eit = arr_out.edges_begin(); eit != arr_out.edges_end(); eit++ ) {
|
for ( eit = arr_out.edges_begin(); eit != arr_out.edges_end(); eit++ ) {
|
||||||
|
|
@ -1387,7 +1391,7 @@ private:
|
||||||
// private trace mthods
|
// private trace mthods
|
||||||
private:
|
private:
|
||||||
#ifndef NDEBUG
|
#ifndef NDEBUG
|
||||||
void trace_all ( ostream& os )
|
void trace_all ( ostream& os ) const
|
||||||
{
|
{
|
||||||
os << "***********************************" << endl;
|
os << "***********************************" << endl;
|
||||||
os << " Trace All" << endl;
|
os << " Trace All" << endl;
|
||||||
|
|
@ -1457,14 +1461,14 @@ public:
|
||||||
Parallel_rotational_sweep_visibility_2 ( const Arrangement_2& arr )
|
Parallel_rotational_sweep_visibility_2 ( const Arrangement_2& arr )
|
||||||
: p_arr(&arr)
|
: p_arr(&arr)
|
||||||
{ geom_traits = p_arr->geometry_traits(); }
|
{ geom_traits = p_arr->geometry_traits(); }
|
||||||
const std::string name ()
|
const std::string name () const
|
||||||
{ return std::string("R_visibility_2"); }
|
{ return std::string("R_visibility_2"); }
|
||||||
|
|
||||||
// function to compute visibility, query point lies in the interior of a face
|
// function to compute visibility, query point lies in the interior of a face
|
||||||
template <typename VARR>
|
template <typename VARR>
|
||||||
typename VARR::Face_handle
|
typename VARR::Face_handle
|
||||||
compute_visibility( const Point_2& q, const Halfedge_const_handle& e,
|
compute_visibility( const Point_2& q, const Halfedge_const_handle& e,
|
||||||
VARR& arr_out )
|
VARR& arr_out ) const
|
||||||
{
|
{
|
||||||
if ( q == e->source()->point() )
|
if ( q == e->source()->point() )
|
||||||
return compute_visibility( q, e->prev(), arr_out );
|
return compute_visibility( q, e->prev(), arr_out );
|
||||||
|
|
@ -1556,7 +1560,7 @@ public:
|
||||||
template <typename VARR>
|
template <typename VARR>
|
||||||
typename VARR::Face_handle
|
typename VARR::Face_handle
|
||||||
compute_visibility( const Point_2& q, const Face_const_handle f,
|
compute_visibility( const Point_2& q, const Face_const_handle f,
|
||||||
VARR& arr_out )
|
VARR& arr_out ) const
|
||||||
{
|
{
|
||||||
arr_out.clear();
|
arr_out.clear();
|
||||||
query_pt = q;
|
query_pt = q;
|
||||||
|
|
@ -1583,34 +1587,35 @@ public:
|
||||||
{ p_arr = &arr; geom_traits = p_arr->geometry_traits(); }
|
{ p_arr = &arr; geom_traits = p_arr->geometry_traits(); }
|
||||||
void detach ()
|
void detach ()
|
||||||
{ p_arr = NULL; geom_traits = NULL; }
|
{ p_arr = NULL; geom_traits = NULL; }
|
||||||
const Arrangement_2& arr () const
|
const Arrangement_2& arrangement_2() const
|
||||||
{ return *p_arr; }
|
{ return *p_arr; }
|
||||||
|
|
||||||
|
|
||||||
// Private data members
|
// Private data members
|
||||||
private:
|
private:
|
||||||
const Geometry_traits_2 * geom_traits;
|
const Geometry_traits_2 * geom_traits;
|
||||||
const Arrangement_2 * p_arr;
|
const Arrangement_2 * p_arr;
|
||||||
|
|
||||||
Point_2 query_pt;
|
mutable Point_2 query_pt;
|
||||||
Halfedge_const_handle query_edge;
|
mutable Halfedge_const_handle query_edge;
|
||||||
enum { VERTEX_QUERY, EDGE_QUERY, FACE_QUERY } query_type;
|
mutable enum { VERTEX_QUERY, EDGE_QUERY, FACE_QUERY } query_type;
|
||||||
Vertex_vector vs;
|
mutable Vertex_vector vs;
|
||||||
Edge_vector es;
|
mutable Edge_vector es;
|
||||||
std::vector<int> good_vdx;
|
mutable std::vector<int> good_vdx;
|
||||||
std::vector< std::pair<int, int> > incident;
|
mutable std::vector< std::pair<int, int> > incident;
|
||||||
std::vector<Cone> cones;
|
mutable std::vector<Cone> cones;
|
||||||
std::vector<Sub_region> sub_regions;
|
mutable std::vector<Sub_region> sub_regions;
|
||||||
Point_vector polygon;
|
mutable Point_vector polygon;
|
||||||
|
|
||||||
Vertex_const_handle cone_end;
|
mutable Vertex_const_handle cone_end;
|
||||||
Vertex_const_handle cone_start;
|
mutable Vertex_const_handle cone_start;
|
||||||
int cone_end_idx;
|
mutable int cone_end_idx;
|
||||||
int cone_start_idx;
|
mutable int cone_start_idx;
|
||||||
Arrangement_2 arr_box;
|
mutable Arrangement_2 arr_box;
|
||||||
|
|
||||||
bool is_small_cone;
|
mutable bool is_small_cone;
|
||||||
Point_2 shifted_source;
|
mutable Point_2 shifted_source;
|
||||||
int shifted_quadrant;
|
mutable int shifted_quadrant;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // end namespace CGAL
|
} // end namespace CGAL
|
||||||
|
|
|
||||||
|
|
@ -1,106 +0,0 @@
|
||||||
// Copyright (c) 2013 Technical University Braunschweig (Germany).
|
|
||||||
// All rights reserved.
|
|
||||||
//
|
|
||||||
// This file is part of CGAL (www.cgal.org).
|
|
||||||
// You can redistribute it and/or modify it under the terms of the GNU
|
|
||||||
// General Public License as published by the Free Software Foundation,
|
|
||||||
// either version 3 of the License, or (at your option) any later version.
|
|
||||||
//
|
|
||||||
// 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$
|
|
||||||
// $Id$
|
|
||||||
//
|
|
||||||
//
|
|
||||||
// Author(s): Kan Huang <huangkandiy@gmail.com>
|
|
||||||
//
|
|
||||||
|
|
||||||
#ifndef CGAL_PREPROCESSED_VISIBILITY_2_H
|
|
||||||
#define CGAL_PREPROCESSED_VISIBILITY_2_H
|
|
||||||
|
|
||||||
#include <CGAL/Arrangement_2.h>
|
|
||||||
#include <CGAL/Arr_linear_traits_2.h>
|
|
||||||
#include <stack>
|
|
||||||
#include <deque>
|
|
||||||
|
|
||||||
namespace CGAL {
|
|
||||||
|
|
||||||
template<class Arrangement_2>
|
|
||||||
class Preprocessed_visibility_2 {
|
|
||||||
|
|
||||||
public:
|
|
||||||
typedef typename Arrangement_2::Geometry_traits_2 Geometry_traits_2;
|
|
||||||
// Currently only consider with same type for both
|
|
||||||
typedef Arrangement_2 Input_Arrangement_2;
|
|
||||||
typedef Arrangement_2 Output_Arrangement_2;
|
|
||||||
|
|
||||||
typedef typename Arrangement_2::Halfedge_const_handle Halfedge_const_handle;
|
|
||||||
typedef typename Arrangement_2::Ccb_halfedge_const_circulator Ccb_halfedge_const_circulator;
|
|
||||||
typedef typename Arrangement_2::Face_const_handle Face_const_handle;
|
|
||||||
typedef typename Arrangement_2::Kernel Kernel;
|
|
||||||
typedef typename CGAL::Arr_linear_traits_2<Kernel> Linear_traits_2;
|
|
||||||
|
|
||||||
typedef typename Geometry_traits_2::Point_2 Point_2;
|
|
||||||
typedef typename Geometry_traits_2::Ray_2 Ray_2;
|
|
||||||
typedef typename Geometry_traits_2::Segment_2 Segment_2;
|
|
||||||
typedef typename Geometry_traits_2::Line_2 Line_2;
|
|
||||||
typedef typename Geometry_traits_2::Vector_2 Vector_2;
|
|
||||||
typedef typename Geometry_traits_2::FT Number_type;
|
|
||||||
|
|
||||||
typedef typename CGAL::Arrangement_2<Linear_traits_2> Line_Arrangement_2;
|
|
||||||
|
|
||||||
Preprocessed_visibility_2() : p_arr(NULL) {};
|
|
||||||
|
|
||||||
/*! Constructor given an arrangement and the Regularization tag. */
|
|
||||||
Preprocessed_visibility_2(Input_Arrangement_2& arr/*, Regularization_category r_t*/): p_arr(&arr) {};
|
|
||||||
|
|
||||||
bool is_attached() {
|
|
||||||
return (p_arr != NULL);
|
|
||||||
}
|
|
||||||
|
|
||||||
void attach(Input_Arrangement_2& arr) {
|
|
||||||
p_arr = &arr;
|
|
||||||
}
|
|
||||||
|
|
||||||
void detach() {
|
|
||||||
p_arr = NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
Input_Arrangement_2 arrangement_2()() {
|
|
||||||
return *p_arr;
|
|
||||||
}
|
|
||||||
|
|
||||||
void compute_visibility(const Point_2& q,
|
|
||||||
const Face_const_handle face,
|
|
||||||
Output_Arrangement_2& out_arr
|
|
||||||
) {
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
void compute_visibility(const Point_2& q,
|
|
||||||
const Halfedge_const_handle he,
|
|
||||||
Output_Arrangement_2& out_arr
|
|
||||||
) {
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
|
||||||
Input_Arrangement_2* arr;
|
|
||||||
Line_Arrangement_2 line_arr;
|
|
||||||
void preprocess() {
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
Line_2 dual_line(const Point_2& p) {
|
|
||||||
return Line_2(p.x(), -1, -p.y());
|
|
||||||
}
|
|
||||||
|
|
||||||
};
|
|
||||||
|
|
||||||
} // namespace CGAL
|
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
@ -36,12 +36,12 @@ public:
|
||||||
typedef Arrangement_2_ Arrangement_2;
|
typedef Arrangement_2_ Arrangement_2;
|
||||||
typedef typename Arrangement_2::Traits_2 Traits_2;
|
typedef typename Arrangement_2::Traits_2 Traits_2;
|
||||||
typedef typename Arrangement_2::Geometry_traits_2 Geometry_traits_2;
|
typedef typename Arrangement_2::Geometry_traits_2 Geometry_traits_2;
|
||||||
typedef typename Arrangement_2::Vertex_const_handle Vertex_const_handle;
|
typedef typename Arrangement_2::Vertex_const_handle Vertex_const_handle;
|
||||||
typedef typename Arrangement_2::Vertex_handle Vertex_handle;
|
typedef typename Arrangement_2::Vertex_handle Vertex_handle;
|
||||||
typedef typename Arrangement_2::Halfedge_const_handle Halfedge_const_handle;
|
typedef typename Arrangement_2::Halfedge_const_handle Halfedge_const_handle;
|
||||||
typedef typename Arrangement_2::Halfedge_handle Halfedge_handle;
|
typedef typename Arrangement_2::Halfedge_handle Halfedge_handle;
|
||||||
typedef typename Arrangement_2::Ccb_halfedge_const_circulator
|
typedef typename Arrangement_2::
|
||||||
Ccb_halfedge_const_circulator;
|
Ccb_halfedge_const_circulator Ccb_halfedge_const_circulator;
|
||||||
typedef typename Arrangement_2::Face_const_handle Face_const_handle;
|
typedef typename Arrangement_2::Face_const_handle Face_const_handle;
|
||||||
typedef typename Arrangement_2::Face_handle Face_handle;
|
typedef typename Arrangement_2::Face_handle Face_handle;
|
||||||
|
|
||||||
|
|
@ -55,9 +55,9 @@ public:
|
||||||
typedef typename Geometry_traits_2::FT Number_type;
|
typedef typename Geometry_traits_2::FT Number_type;
|
||||||
typedef typename Geometry_traits_2::Object_2 Object_2;
|
typedef typename Geometry_traits_2::Object_2 Object_2;
|
||||||
|
|
||||||
typedef RegularizationCategory Regularization_category;
|
typedef RegularizationCategory Regularization_category;
|
||||||
typedef CGAL::Tag_true Supports_general_polygon_category;
|
typedef CGAL::Tag_true Supports_general_polygon_category;
|
||||||
typedef CGAL::Tag_true Supports_simple_polygon_category;
|
typedef CGAL::Tag_true Supports_simple_polygon_category;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
typedef std::vector<Point_2> Points;
|
typedef std::vector<Point_2> Points;
|
||||||
|
|
@ -76,11 +76,14 @@ private:
|
||||||
return false;
|
return false;
|
||||||
else {
|
else {
|
||||||
return &(*e1)<&(*e2);
|
return &(*e1)<&(*e2);
|
||||||
// if (e1->source() == e2->source())
|
}
|
||||||
// return Visibility_2::compare_xy_2(geom_traits, e1->target()->point(), e2->target()->point()) == SMALLER;
|
// if (e1->source() == e2->source())
|
||||||
// else
|
// return Visibility_2::compare_xy_2(geom_traits,
|
||||||
// return Visibility_2::compare_xy_2(geom_traits, e1->source()->point(), e2->source()->point()) == SMALLER;
|
// e1->target()->point(), e2->target()->point()) == SMALLER;
|
||||||
}
|
// else
|
||||||
|
// return Visibility_2::compare_xy_2(geom_traits,
|
||||||
|
// e1->source()->point(), e2->source()->point()) == SMALLER;
|
||||||
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
@ -95,7 +98,8 @@ private:
|
||||||
else
|
else
|
||||||
// I know this is dirty but it speeds up by 25%. Michael
|
// I know this is dirty but it speeds up by 25%. Michael
|
||||||
return &(*v1)<&(*v2);
|
return &(*v1)<&(*v2);
|
||||||
// return Visibility_2::compare_xy_2(geom_traits, v1->point(), v2->point()) == SMALLER;
|
// return Visibility_2::
|
||||||
|
// compare_xy_2(geom_traits, v1->point(), v2->point()) == SMALLER;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
@ -104,7 +108,8 @@ private:
|
||||||
Point_2 q;
|
Point_2 q;
|
||||||
public:
|
public:
|
||||||
Closer_edge() {}
|
Closer_edge() {}
|
||||||
Closer_edge(const Geometry_traits_2* traits, const Point_2& q):geom_traits(traits), q(q) {}
|
Closer_edge(const Geometry_traits_2* traits, const Point_2& q) :
|
||||||
|
geom_traits(traits), q(q) {}
|
||||||
|
|
||||||
int vtype(const Point_2& c, const Point_2& p) const {
|
int vtype(const Point_2& c, const Point_2& p) const {
|
||||||
switch(Visibility_2::orientation_2(geom_traits, q, c, p)) {
|
switch(Visibility_2::orientation_2(geom_traits, q, c, p)) {
|
||||||
|
|
@ -181,7 +186,7 @@ private:
|
||||||
if (Visibility_2::collinear(geom_traits, q, s2, t2)) {
|
if (Visibility_2::collinear(geom_traits, q, s2, t2)) {
|
||||||
//q is collinear with e1 and e2.
|
//q is collinear with e1 and e2.
|
||||||
return (Visibility_2::less_distance_to_point_2(geom_traits, q, s1, s2)
|
return (Visibility_2::less_distance_to_point_2(geom_traits, q, s1, s2)
|
||||||
|| Visibility_2::less_distance_to_point_2(geom_traits, q, t1, t2));
|
|| Visibility_2::less_distance_to_point_2(geom_traits, q, t1, t2));
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
//q is collinear with e1 not with e2.
|
//q is collinear with e1 not with e2.
|
||||||
|
|
@ -203,7 +208,7 @@ private:
|
||||||
else
|
else
|
||||||
return false;
|
return false;
|
||||||
case LEFT_TURN:
|
case LEFT_TURN:
|
||||||
if (Visibility_2::orientation_2(geom_traits, s1, t1, t2) == RIGHT_TURN)
|
if(Visibility_2::orientation_2(geom_traits, s1, t1, t2) == RIGHT_TURN)
|
||||||
return Visibility_2::orientation_2(geom_traits, s2, t2, q)
|
return Visibility_2::orientation_2(geom_traits, s2, t2, q)
|
||||||
== Visibility_2::orientation_2(geom_traits, s2, t2, s1);
|
== Visibility_2::orientation_2(geom_traits, s2, t2, s1);
|
||||||
else
|
else
|
||||||
|
|
@ -214,7 +219,7 @@ private:
|
||||||
case COLLINEAR:
|
case COLLINEAR:
|
||||||
return Visibility_2::orientation_2(geom_traits, s1, t1, t2)!=e1q;
|
return Visibility_2::orientation_2(geom_traits, s1, t1, t2)!=e1q;
|
||||||
case LEFT_TURN:
|
case LEFT_TURN:
|
||||||
if (Visibility_2::orientation_2(geom_traits, s1, t1, t2) == RIGHT_TURN)
|
if(Visibility_2::orientation_2(geom_traits, s1, t1, t2) == RIGHT_TURN)
|
||||||
return Visibility_2::orientation_2(geom_traits, s2, t2, q)
|
return Visibility_2::orientation_2(geom_traits, s2, t2, q)
|
||||||
== Visibility_2::orientation_2(geom_traits, s2, t2, s1);
|
== Visibility_2::orientation_2(geom_traits, s2, t2, s1);
|
||||||
else
|
else
|
||||||
|
|
@ -231,35 +236,38 @@ private:
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
// Using hash_map or edx causes a seg fault, did not have the time to see why. Michael
|
|
||||||
// class Hash_edge: public std::unary_function<VH,typename boost::hash<const typename Arrangement_2::X_monotone_curve_2*>::result_type> {
|
|
||||||
// public:
|
|
||||||
// typename boost::hash<const typename Arrangement_2::X_monotone_curve_2*>::result_type
|
|
||||||
// operator() (const EH e1) const {
|
|
||||||
// return boost::hash<const typename Arrangement_2::X_monotone_curve_2*>()(&(e1->curve()));
|
|
||||||
// }
|
|
||||||
// };
|
|
||||||
|
|
||||||
|
|
||||||
const Geometry_traits_2 *geom_traits;
|
const Geometry_traits_2 *geom_traits;
|
||||||
const Arrangement_2 *p_arr;
|
const Arrangement_2 *p_arr;
|
||||||
Point_2 q; //query point
|
|
||||||
Points polygon; //visibility polygon
|
|
||||||
std::map<VH, EHs, Less_vertex> incident_edges; //the edges that are
|
|
||||||
std::map<EH, int, Less_edge> edx; //index of active edges in the heap
|
|
||||||
// boost::unordered_map<EH,int,Hash_edge> edx; //index of active edges in the heap
|
|
||||||
std::set<EH, Closer_edge> active_edges; //a set of edges that intersect the current vision ray.
|
|
||||||
VHs vs; //angular sorted vertices
|
|
||||||
EHs bad_edges; //edges that pass the query point
|
|
||||||
VH cone_end1; //an end of visibility cone
|
|
||||||
VH cone_end2; //another end of visibility cone
|
|
||||||
int cone_end1_idx; //index of cone_end1->point() in visibility polygon
|
|
||||||
int cone_end2_idx; //index of cone_end2->point() in visibility polygon
|
|
||||||
|
|
||||||
bool is_vertex_query;
|
mutable Point_2 q; //query point
|
||||||
bool is_edge_query;
|
mutable Points polygon; //visibility polygon
|
||||||
bool is_face_query;
|
|
||||||
bool is_big_cone; //whether the angle of visibility_cone is greater than pi.
|
mutable std::map<VH, EHs, Less_vertex> incident_edges;
|
||||||
|
|
||||||
|
mutable std::map<EH, int, Less_edge> edx; //index of active edges in
|
||||||
|
//the heap
|
||||||
|
|
||||||
|
mutable std::set<EH, Closer_edge> active_edges; //a set of edges that
|
||||||
|
//intersect the current
|
||||||
|
//vision ray.
|
||||||
|
|
||||||
|
mutable VHs vs; //angular sorted vertices
|
||||||
|
mutable EHs bad_edges; //edges that pass the query point
|
||||||
|
mutable VH cone_end1; //an end of visibility cone
|
||||||
|
mutable VH cone_end2; //another end of visibility cone
|
||||||
|
|
||||||
|
mutable int cone_end1_idx; //index of cone_end1->point() in
|
||||||
|
//visibility polygon
|
||||||
|
|
||||||
|
mutable int cone_end2_idx; //index of cone_end2->point() in
|
||||||
|
//visibility polygon
|
||||||
|
|
||||||
|
mutable bool is_vertex_query;
|
||||||
|
mutable bool is_edge_query;
|
||||||
|
mutable bool is_face_query;
|
||||||
|
mutable bool is_big_cone; //whether the angle of
|
||||||
|
//visibility_cone is greater than pi.
|
||||||
|
|
||||||
public:
|
public:
|
||||||
Rotational_sweep_visibility_2(): p_arr(NULL), geom_traits(NULL) {}
|
Rotational_sweep_visibility_2(): p_arr(NULL), geom_traits(NULL) {}
|
||||||
|
|
@ -267,16 +275,19 @@ public:
|
||||||
geom_traits = p_arr->geometry_traits();
|
geom_traits = p_arr->geometry_traits();
|
||||||
}
|
}
|
||||||
|
|
||||||
const std::string name(){return std::string("R_visibility_2");}
|
const std::string name() const { return std::string("R_visibility_2"); }
|
||||||
|
|
||||||
template <typename VARR>
|
template <typename VARR>
|
||||||
typename VARR::Face_handle
|
typename VARR::Face_handle
|
||||||
compute_visibility(const Point_2& q, const Halfedge_const_handle e, VARR& arr_out) {
|
compute_visibility(
|
||||||
|
const Point_2& q, const Halfedge_const_handle e, VARR& arr_out) const
|
||||||
|
{
|
||||||
arr_out.clear();
|
arr_out.clear();
|
||||||
bad_edges.clear();
|
bad_edges.clear();
|
||||||
this->q = q;
|
this->q = q;
|
||||||
|
|
||||||
if (Visibility_2::compare_xy_2(geom_traits, q, e->target()->point())==EQUAL) {
|
if (Visibility_2::compare_xy_2(geom_traits, q, e->target()->point())==EQUAL)
|
||||||
|
{
|
||||||
is_vertex_query = true;
|
is_vertex_query = true;
|
||||||
is_edge_query = false;
|
is_edge_query = false;
|
||||||
is_face_query = false;
|
is_face_query = false;
|
||||||
|
|
@ -284,7 +295,8 @@ public:
|
||||||
cone_end2 = e->next()->target();
|
cone_end2 = e->next()->target();
|
||||||
is_big_cone = CGAL::right_turn(cone_end1->point(), q, cone_end2->point());
|
is_big_cone = CGAL::right_turn(cone_end1->point(), q, cone_end2->point());
|
||||||
|
|
||||||
typename Arrangement_2::Halfedge_around_vertex_const_circulator first, curr;
|
typename Arrangement_2::
|
||||||
|
Halfedge_around_vertex_const_circulator first, curr;
|
||||||
first = curr = e->target()->incident_halfedges();
|
first = curr = e->target()->incident_halfedges();
|
||||||
do {
|
do {
|
||||||
if (curr->face() == e->face())
|
if (curr->face() == e->face())
|
||||||
|
|
@ -316,11 +328,14 @@ public:
|
||||||
}
|
}
|
||||||
int next_idx = small_idx + 1;
|
int next_idx = small_idx + 1;
|
||||||
bool is_between;
|
bool is_between;
|
||||||
//indicate whether the shape between small_idx and big_idx is the visibility region required.
|
//indicate whether the shape between small_idx and big_idx is the visibility
|
||||||
|
//region required.
|
||||||
if (CGAL::right_turn(cone_end1->point(), q, cone_end2->point())) {
|
if (CGAL::right_turn(cone_end1->point(), q, cone_end2->point())) {
|
||||||
is_between = false;
|
is_between = false;
|
||||||
while (next_idx != big_idx) {
|
while (next_idx != big_idx) {
|
||||||
if (CGAL::left_turn(cone_end1->point(), q, polygon[next_idx]) || CGAL::left_turn(q, cone_end2->point(), polygon[next_idx])) {
|
if (CGAL::left_turn(cone_end1->point(), q, polygon[next_idx]) ||
|
||||||
|
CGAL::left_turn(q, cone_end2->point(), polygon[next_idx]))
|
||||||
|
{
|
||||||
is_between = true;
|
is_between = true;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
@ -330,7 +345,9 @@ public:
|
||||||
else {
|
else {
|
||||||
is_between = true;
|
is_between = true;
|
||||||
while (next_idx != big_idx) {
|
while (next_idx != big_idx) {
|
||||||
if (CGAL::right_turn(cone_end1->point(), q, polygon[next_idx]) || CGAL::right_turn(q, cone_end2->point(), polygon[next_idx])) {
|
if (CGAL::right_turn(cone_end1->point(), q, polygon[next_idx]) ||
|
||||||
|
CGAL::right_turn(q, cone_end2->point(), polygon[next_idx]))
|
||||||
|
{
|
||||||
is_between = false;
|
is_between = false;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
@ -367,7 +384,9 @@ public:
|
||||||
|
|
||||||
template <typename VARR>
|
template <typename VARR>
|
||||||
typename VARR::Face_handle
|
typename VARR::Face_handle
|
||||||
compute_visibility(const Point_2& q, const Face_const_handle f, VARR& arr_out) {
|
compute_visibility(
|
||||||
|
const Point_2& q, const Face_const_handle f, VARR& arr_out) const
|
||||||
|
{
|
||||||
arr_out.clear();
|
arr_out.clear();
|
||||||
this->q = q;
|
this->q = q;
|
||||||
is_vertex_query = false;
|
is_vertex_query = false;
|
||||||
|
|
@ -375,15 +394,19 @@ public:
|
||||||
is_face_query = true;
|
is_face_query = true;
|
||||||
|
|
||||||
visibility_region_impl(f, q);
|
visibility_region_impl(f, q);
|
||||||
Visibility_2::report_while_handling_needles<Rotational_sweep_visibility_2>(geom_traits, q, polygon, arr_out);
|
|
||||||
|
Visibility_2::report_while_handling_needles<Rotational_sweep_visibility_2>
|
||||||
|
(geom_traits, q, polygon, arr_out);
|
||||||
|
|
||||||
conditional_regularize(arr_out, Regularization_category());
|
conditional_regularize(arr_out, Regularization_category());
|
||||||
|
|
||||||
if (arr_out.faces_begin()->is_unbounded())
|
if (arr_out.faces_begin()->is_unbounded())
|
||||||
return ++arr_out.faces_begin();
|
return ++arr_out.faces_begin();
|
||||||
else
|
else
|
||||||
return arr_out.faces_begin();
|
return arr_out.faces_begin();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool is_attached() {
|
bool is_attached() const {
|
||||||
return (p_arr != NULL);
|
return (p_arr != NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -397,30 +420,34 @@ void detach() {
|
||||||
geom_traits = NULL;
|
geom_traits = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
const Arrangement_2& arrangement_2() {
|
const Arrangement_2& arrangement_2() const {
|
||||||
return *p_arr;
|
return *p_arr;
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
//get the neighbor of v along edge e
|
//get the neighbor of v along edge e
|
||||||
VH get_neighbor(const EH e, const VH v) {
|
VH get_neighbor(const EH e, const VH v) const {
|
||||||
if (e->source() == v)
|
if (e->source() == v)
|
||||||
return e->target();
|
return e->target();
|
||||||
else
|
else
|
||||||
return e->source();
|
return e->source();
|
||||||
}
|
}
|
||||||
|
|
||||||
//check whether ray(q->dp) intersects segment(p1, p2)
|
//check whether ray(q->dp) intersects segment(p1, p2)
|
||||||
bool do_intersect_ray(const Point_2& q,
|
bool do_intersect_ray(const Point_2& q,
|
||||||
const Point_2& dp,
|
const Point_2& dp,
|
||||||
const Point_2& p1,
|
const Point_2& p1,
|
||||||
const Point_2& p2) {
|
const Point_2& p2) const
|
||||||
return (CGAL::orientation(q, dp, p1) != CGAL::orientation(q, dp, p2) && CGAL::orientation(q, p1, dp) == CGAL::orientation(q, p1, p2));
|
{
|
||||||
|
return (CGAL::orientation(q, dp, p1) != CGAL::orientation(q, dp, p2) &&
|
||||||
|
CGAL::orientation(q, p1, dp) == CGAL::orientation(q, p1, p2));
|
||||||
}
|
}
|
||||||
|
|
||||||
//arrange vertices that on a same vision ray in a 'funnel' order
|
//arrange vertices that on a same vision ray in a 'funnel' order
|
||||||
void funnel(int i, int j) {
|
void funnel(int i, int j) const {
|
||||||
VHs right, left;
|
VHs right, left;
|
||||||
//whether the edges incident to a vertex block the left side and right side of current vision ray.
|
//whether the edges incident to a vertex block the left side and right side
|
||||||
|
//of current vision ray.
|
||||||
bool block_left(false), block_right(false);
|
bool block_left(false), block_right(false);
|
||||||
VH former = vs[i], nb;
|
VH former = vs[i], nb;
|
||||||
for (int l=i; l<j; l++) {
|
for (int l=i; l<j; l++) {
|
||||||
|
|
@ -448,7 +475,8 @@ private:
|
||||||
block_right = right_v;
|
block_right = right_v;
|
||||||
}
|
}
|
||||||
if (block_left && block_right) {
|
if (block_left && block_right) {
|
||||||
//when both sides are blocked, there is no need to change the vertex after.
|
//when both sides are blocked,
|
||||||
|
//there is no need to change the vertex after.
|
||||||
right.push_back(vs[l]);
|
right.push_back(vs[l]);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
@ -468,22 +496,25 @@ private:
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
void visibility_region_impl(const Face_const_handle f, const Point_2& q) {
|
void visibility_region_impl(const Face_const_handle f, const Point_2& q) const
|
||||||
|
{
|
||||||
vs.clear();
|
vs.clear();
|
||||||
polygon.clear();
|
polygon.clear();
|
||||||
active_edges = std::set<EH, Closer_edge>(Closer_edge(geom_traits, q));
|
active_edges = std::set<EH, Closer_edge>(Closer_edge(geom_traits, q));
|
||||||
incident_edges = std::map<VH, EHs, Less_vertex>(Less_vertex(geom_traits));
|
incident_edges = std::map<VH, EHs, Less_vertex>(Less_vertex(geom_traits));
|
||||||
edx = std::map<EH, int, Less_edge>(Less_edge(geom_traits));
|
edx = std::map<EH, int, Less_edge>(Less_edge(geom_traits));
|
||||||
|
|
||||||
EHs relevant_edges; //all edges that can affect the visibility of query point.
|
EHs relevant_edges; //edges that can affect the visibility of query point.
|
||||||
Arrangement_2 bbox;
|
Arrangement_2 bbox;
|
||||||
if (is_face_query)
|
if (is_face_query)
|
||||||
input_face(f);
|
input_face(f);
|
||||||
else
|
else
|
||||||
input_face(f, relevant_edges, bbox);
|
input_face(f, relevant_edges, bbox);
|
||||||
//the following code is the initiation of vision ray. the direction of the initial ray is between the direction
|
//the following code is the initiation of vision ray.
|
||||||
//from q to last vertex in vs and positive x-axis. By choosing this direction, we make
|
//the direction of the initial ray is between the direction from q to last
|
||||||
//sure that all plane is swept and there is not needle at the beginning of sweeping.
|
//vertex in vs and positive x-axis. By choosing this direction, we make sure
|
||||||
|
//that all plane is swept and there is not needle at the beginning of
|
||||||
|
//sweeping.
|
||||||
Vector_2 dir;
|
Vector_2 dir;
|
||||||
if (Direction_2(-1, 0) < Direction_2(Vector_2(q, vs.back()->point())))
|
if (Direction_2(-1, 0) < Direction_2(Vector_2(q, vs.back()->point())))
|
||||||
dir = Vector_2(1, 0) + Vector_2(q, vs.back()->point());
|
dir = Vector_2(1, 0) + Vector_2(q, vs.back()->point());
|
||||||
|
|
@ -491,29 +522,33 @@ private:
|
||||||
dir = Vector_2(0, -1);
|
dir = Vector_2(0, -1);
|
||||||
Point_2 dp = q + dir;
|
Point_2 dp = q + dir;
|
||||||
|
|
||||||
//initiation of active_edges. for face queries, all edges on the boundary can affect visibility.
|
//initiation of active_edges. for face queries,
|
||||||
|
//all edges on the boundary can affect visibility.
|
||||||
//for non-face queries, only relevant_edges has to be considered.
|
//for non-face queries, only relevant_edges has to be considered.
|
||||||
if (is_face_query) {
|
if (is_face_query) {
|
||||||
Ccb_halfedge_const_circulator curr = f->outer_ccb();
|
Ccb_halfedge_const_circulator curr = f->outer_ccb();
|
||||||
Ccb_halfedge_const_circulator circ = curr;
|
Ccb_halfedge_const_circulator circ = curr;
|
||||||
do {
|
do {
|
||||||
if (do_intersect_ray(q, dp, curr->target()->point(), curr->source()->point())) {
|
if (do_intersect_ray(
|
||||||
|
q, dp, curr->target()->point(), curr->source()->point()))
|
||||||
active_edges.insert(curr);
|
active_edges.insert(curr);
|
||||||
}
|
|
||||||
} while (++curr != circ);
|
} while (++curr != circ);
|
||||||
|
|
||||||
typename Arrangement_2::Hole_const_iterator hi;
|
typename Arrangement_2::Hole_const_iterator hi;
|
||||||
for (hi = f->holes_begin(); hi != f->holes_end(); ++hi) {
|
for (hi = f->holes_begin(); hi != f->holes_end(); ++hi) {
|
||||||
Ccb_halfedge_const_circulator curr = circ = *hi;
|
Ccb_halfedge_const_circulator curr = circ = *hi;
|
||||||
do {
|
do {
|
||||||
if (do_intersect_ray(q, dp, curr->target()->point(), curr->source()->point()))
|
if (do_intersect_ray(
|
||||||
|
q, dp, curr->target()->point(), curr->source()->point()))
|
||||||
active_edges.insert(curr);
|
active_edges.insert(curr);
|
||||||
} while (++curr != circ);
|
} while (++curr != circ);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
for (int i=0; i!=relevant_edges.size(); i++)
|
for (int i=0; i!=relevant_edges.size(); i++)
|
||||||
if (do_intersect_ray(q, dp, relevant_edges[i]->source()->point(), relevant_edges[i]->target()->point()))
|
if (do_intersect_ray(q, dp, relevant_edges[i]->source()->point(),
|
||||||
|
relevant_edges[i]->target()->point()))
|
||||||
active_edges.insert(relevant_edges[i]);
|
active_edges.insert(relevant_edges[i]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -549,31 +584,40 @@ private:
|
||||||
//when the closest edge changed
|
//when the closest edge changed
|
||||||
if (is_face_query) {
|
if (is_face_query) {
|
||||||
if (remove_cnt > 0 && insert_cnt > 0) {
|
if (remove_cnt > 0 && insert_cnt > 0) {
|
||||||
//some edges are added and some are deleted, which means the vertex swept is part of visibility polygon.
|
//some edges are added and some are deleted,
|
||||||
|
//which means the vertex swept is part of visibility polygon.
|
||||||
update_visibility(vh->point());
|
update_visibility(vh->point());
|
||||||
}
|
}
|
||||||
if (remove_cnt == 0 && insert_cnt > 0) {
|
if (remove_cnt == 0 && insert_cnt > 0) {
|
||||||
//only add some edges, means the view ray is blocked by new edges.
|
//only add some edges, means the view ray is blocked by new edges.
|
||||||
//therefore first add the intersection of view ray and former closet edge, then add the vertice swept.
|
//therefore first add the intersection of view ray and
|
||||||
|
//former closet edge, then add the vertice swept.
|
||||||
update_visibility(ray_seg_intersection(q,
|
update_visibility(ray_seg_intersection(q,
|
||||||
vh->point(),
|
vh->point(),
|
||||||
closest_e->target()->point(),
|
closest_e->target()->point(),
|
||||||
closest_e->source()->point()));
|
closest_e->source()->point())
|
||||||
|
);
|
||||||
update_visibility(vh->point());
|
update_visibility(vh->point());
|
||||||
}
|
}
|
||||||
if (remove_cnt > 0 && insert_cnt == 0) {
|
if (remove_cnt > 0 && insert_cnt == 0) {
|
||||||
//only delete some edges, means some block is moved and the view ray can reach the segments after the block.
|
//only delete some edges, means some block is moved and the view ray
|
||||||
|
//can reach the segments after the block.
|
||||||
update_visibility(vh->point());
|
update_visibility(vh->point());
|
||||||
update_visibility(ray_seg_intersection(q,
|
update_visibility(
|
||||||
vh->point(),
|
ray_seg_intersection(q,
|
||||||
(*active_edges.begin())->target()->point(),
|
vh->point(),
|
||||||
(*active_edges.begin())->source()->point()));
|
(*active_edges.begin())->target()->point(),
|
||||||
|
(*active_edges.begin())->source()->point()
|
||||||
|
)
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
//extra work here for edge/vertex query is the index of cone_end1 and cone_end2 will be recorded.
|
//extra work here for edge/vertex query is the index of cone_end1 and
|
||||||
|
//cone_end2 will be recorded.
|
||||||
if (remove_cnt > 0 && insert_cnt > 0) {
|
if (remove_cnt > 0 && insert_cnt > 0) {
|
||||||
//some edges are added and some are deleted, which means the vertice swept is part of visibility polygon.
|
//some edges are added and some are deleted,
|
||||||
|
//which means the vertice swept is part of visibility polygon.
|
||||||
if (update_visibility(vh->point())) {
|
if (update_visibility(vh->point())) {
|
||||||
if (vh == cone_end1)
|
if (vh == cone_end1)
|
||||||
cone_end1_idx = polygon.size()-1;
|
cone_end1_idx = polygon.size()-1;
|
||||||
|
|
@ -583,11 +627,13 @@ private:
|
||||||
}
|
}
|
||||||
if (remove_cnt == 0 && insert_cnt > 0) {
|
if (remove_cnt == 0 && insert_cnt > 0) {
|
||||||
//only add some edges, means the view ray is blocked by new edges.
|
//only add some edges, means the view ray is blocked by new edges.
|
||||||
//therefore first add the intersection of view ray and former closet edge, then add the vertice swept.
|
//therefore first add the intersection of view ray and former closet
|
||||||
|
//edge, then add the vertice swept.
|
||||||
update_visibility(ray_seg_intersection(q,
|
update_visibility(ray_seg_intersection(q,
|
||||||
vh->point(),
|
vh->point(),
|
||||||
closest_e->target()->point(),
|
closest_e->target()->point(),
|
||||||
closest_e->source()->point()));
|
closest_e->source()->point())
|
||||||
|
);
|
||||||
if (update_visibility(vh->point())) {
|
if (update_visibility(vh->point())) {
|
||||||
if (vh == cone_end1)
|
if (vh == cone_end1)
|
||||||
cone_end1_idx = polygon.size()-1;
|
cone_end1_idx = polygon.size()-1;
|
||||||
|
|
@ -596,25 +642,28 @@ private:
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (remove_cnt > 0 && insert_cnt == 0) {
|
if (remove_cnt > 0 && insert_cnt == 0) {
|
||||||
//only delete some edges, means some block is removed and the vision ray can reach the segments after the block.
|
//only delete some edges, means some block is removed and the vision
|
||||||
|
//ray can reach the segments after the block.
|
||||||
if (update_visibility(vh->point())) {
|
if (update_visibility(vh->point())) {
|
||||||
if (vh == cone_end1)
|
if (vh == cone_end1)
|
||||||
cone_end1_idx = polygon.size()-1;
|
cone_end1_idx = polygon.size()-1;
|
||||||
else if (vh == cone_end2)
|
else if (vh == cone_end2)
|
||||||
cone_end2_idx = polygon.size()-1;
|
cone_end2_idx = polygon.size()-1;
|
||||||
}
|
}
|
||||||
update_visibility(ray_seg_intersection(q,
|
update_visibility(
|
||||||
vh->point(),
|
ray_seg_intersection(q,
|
||||||
(*active_edges.begin())->target()->point(),
|
vh->point(),
|
||||||
(*active_edges.begin())->source()->point()));
|
(*active_edges.begin())->target()->point(),
|
||||||
|
(*active_edges.begin())->source()->point())
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void print_edge(const EH e) {
|
void print_edge(const EH e) const {
|
||||||
std::cout<<e->source()->point()<<"->"<<e->target()->point()<<std::endl;
|
std::cout << e->source()->point() <<"->"<< e->target()->point() <<std::endl;
|
||||||
}
|
}
|
||||||
|
|
||||||
//compute the intersection of ray(q->dp) and segment(s, t)
|
//compute the intersection of ray(q->dp) and segment(s, t)
|
||||||
|
|
@ -623,6 +672,7 @@ private:
|
||||||
Point_2 ray_seg_intersection(
|
Point_2 ray_seg_intersection(
|
||||||
const Point_2& q, const Point_2& dp, // the ray
|
const Point_2& q, const Point_2& dp, // the ray
|
||||||
const Point_2& s, const Point_2& t) // the segment
|
const Point_2& s, const Point_2& t) // the segment
|
||||||
|
const
|
||||||
{
|
{
|
||||||
if (CGAL::collinear(q, dp, s)) {
|
if (CGAL::collinear(q, dp, s)) {
|
||||||
if (CGAL::collinear(q, dp, t)) {
|
if (CGAL::collinear(q, dp, t)) {
|
||||||
|
|
@ -641,24 +691,29 @@ private:
|
||||||
}
|
}
|
||||||
|
|
||||||
//check if p has been discovered before, if not update the visibility polygon
|
//check if p has been discovered before, if not update the visibility polygon
|
||||||
bool update_visibility(const Point_2& p){
|
bool update_visibility(const Point_2& p) const {
|
||||||
if (polygon.empty()) {
|
if (polygon.empty()) {
|
||||||
polygon.push_back(p);
|
polygon.push_back(p);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
else if (Visibility_2::compare_xy_2(geom_traits, polygon.back(), p) != EQUAL) {
|
else if (Visibility_2::compare_xy_2(geom_traits, polygon.back(), p)
|
||||||
|
!= EQUAL)
|
||||||
|
{
|
||||||
polygon.push_back(p);
|
polygon.push_back(p);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
//functor to decide which vertex is swept earlier by the rotational sweeping ray
|
//functor to decide which vertex is swept earlier by the rotational sweeping
|
||||||
|
//ray
|
||||||
class Is_swept_earlier:public std::binary_function<VH, VH, bool> {
|
class Is_swept_earlier:public std::binary_function<VH, VH, bool> {
|
||||||
const Point_2& q;
|
const Point_2& q;
|
||||||
const Geometry_traits_2* geom_traits;
|
const Geometry_traits_2* geom_traits;
|
||||||
public:
|
public:
|
||||||
Is_swept_earlier(const Point_2& q, const Geometry_traits_2* traits):q(q), geom_traits(traits) {}
|
Is_swept_earlier(const Point_2& q, const Geometry_traits_2* traits) :
|
||||||
|
q(q), geom_traits(traits) {}
|
||||||
|
|
||||||
bool operator() (const VH v1, const VH v2) const {
|
bool operator() (const VH v1, const VH v2) const {
|
||||||
const Point_2& p1 = v1->point();
|
const Point_2& p1 = v1->point();
|
||||||
const Point_2& p2 = v2->point();
|
const Point_2& p2 = v2->point();
|
||||||
|
|
@ -676,8 +731,11 @@ private:
|
||||||
|
|
||||||
//return the quadrant of p with respect to o.
|
//return the quadrant of p with respect to o.
|
||||||
int quadrant(const Point_2& o, const Point_2& p) const {
|
int quadrant(const Point_2& o, const Point_2& p) const {
|
||||||
typename Geometry_traits_2::Compare_x_2 compare_x = geom_traits->compare_x_2_object();
|
typename Geometry_traits_2::Compare_x_2 compare_x =
|
||||||
typename Geometry_traits_2::Compare_y_2 compare_y = geom_traits->compare_y_2_object();
|
geom_traits->compare_x_2_object();
|
||||||
|
|
||||||
|
typename Geometry_traits_2::Compare_y_2 compare_y =
|
||||||
|
geom_traits->compare_y_2_object();
|
||||||
|
|
||||||
Comparison_result dx = compare_x(p, o);
|
Comparison_result dx = compare_x(p, o);
|
||||||
Comparison_result dy = compare_y(p, o);
|
Comparison_result dy = compare_y(p, o);
|
||||||
|
|
@ -694,7 +752,7 @@ private:
|
||||||
};
|
};
|
||||||
|
|
||||||
//when the query point is in face, every edge is good.
|
//when the query point is in face, every edge is good.
|
||||||
void input_neighbor_f( const Halfedge_const_handle e) {
|
void input_neighbor_f( const Halfedge_const_handle e) const {
|
||||||
VH v = e->target();
|
VH v = e->target();
|
||||||
if (!incident_edges.count(v))
|
if (!incident_edges.count(v))
|
||||||
vs.push_back(v);
|
vs.push_back(v);
|
||||||
|
|
@ -705,21 +763,26 @@ private:
|
||||||
//check if p is in the visibility cone
|
//check if p is in the visibility cone
|
||||||
bool is_in_cone(const Point_2& p) const{
|
bool is_in_cone(const Point_2& p) const{
|
||||||
if (is_big_cone)
|
if (is_big_cone)
|
||||||
return (!CGAL::right_turn(cone_end1->point(), q, p)) || (!CGAL::left_turn(cone_end2->point(), q, p));
|
return (!CGAL::right_turn(cone_end1->point(), q, p)) ||
|
||||||
|
(!CGAL::left_turn(cone_end2->point(), q, p));
|
||||||
else
|
else
|
||||||
return (!CGAL::right_turn(cone_end1->point(), q, p)) && (!CGAL::left_turn(cone_end2->point(), q, p));
|
return (!CGAL::right_turn(cone_end1->point(), q, p)) &&
|
||||||
|
(!CGAL::left_turn(cone_end2->point(), q, p));
|
||||||
}
|
}
|
||||||
|
|
||||||
//for vertex and edge query: the visibility is limited in a cone.
|
//for vertex and edge query: the visibility is limited in a cone.
|
||||||
void input_edge(const Halfedge_const_handle e,
|
void input_edge(const Halfedge_const_handle e,
|
||||||
EHs& good_edges) {
|
EHs& good_edges) const {
|
||||||
for (int i=0; i<bad_edges.size(); i++)
|
for (int i=0; i<bad_edges.size(); i++)
|
||||||
if (e == bad_edges[i])
|
if (e == bad_edges[i])
|
||||||
return;
|
return;
|
||||||
VH v1 = e->target();
|
VH v1 = e->target();
|
||||||
VH v2 = e->source();
|
VH v2 = e->source();
|
||||||
//an edge will affect visibility only if it has an endpoint in the visibility cone or it crosses the boundary of the cone.
|
//an edge will affect visibility only if it has an endpoint in the
|
||||||
if (is_in_cone(v1->point()) || is_in_cone(v2->point()) || do_intersect_ray(q, cone_end1->point(), v1->point(), v2->point())) {
|
//visibility cone or it crosses the boundary of the cone.
|
||||||
|
if (is_in_cone(v1->point()) || is_in_cone(v2->point()) ||
|
||||||
|
do_intersect_ray(q, cone_end1->point(), v1->point(), v2->point()))
|
||||||
|
{
|
||||||
good_edges.push_back(e);
|
good_edges.push_back(e);
|
||||||
if (!incident_edges.count(v1))
|
if (!incident_edges.count(v1))
|
||||||
vs.push_back(v1);
|
vs.push_back(v1);
|
||||||
|
|
@ -732,7 +795,7 @@ private:
|
||||||
|
|
||||||
//for face query: traverse the face to get all edges
|
//for face query: traverse the face to get all edges
|
||||||
//and sort vertices in counter-clockwise order.
|
//and sort vertices in counter-clockwise order.
|
||||||
void input_face (Face_const_handle fh)
|
void input_face (Face_const_handle fh) const
|
||||||
{
|
{
|
||||||
Ccb_halfedge_const_circulator curr = fh->outer_ccb();
|
Ccb_halfedge_const_circulator curr = fh->outer_ccb();
|
||||||
Ccb_halfedge_const_circulator circ = curr;
|
Ccb_halfedge_const_circulator circ = curr;
|
||||||
|
|
@ -768,7 +831,7 @@ private:
|
||||||
//and sort vertices in counter-clockwise order.
|
//and sort vertices in counter-clockwise order.
|
||||||
void input_face (Face_const_handle fh,
|
void input_face (Face_const_handle fh,
|
||||||
EHs& good_edges,
|
EHs& good_edges,
|
||||||
Arrangement_2& bbox)
|
Arrangement_2& bbox) const
|
||||||
{
|
{
|
||||||
Ccb_halfedge_const_circulator curr = fh->outer_ccb();
|
Ccb_halfedge_const_circulator curr = fh->outer_ccb();
|
||||||
Ccb_halfedge_const_circulator circ = curr;
|
Ccb_halfedge_const_circulator circ = curr;
|
||||||
|
|
@ -786,7 +849,8 @@ private:
|
||||||
} while (++curr != circ);
|
} while (++curr != circ);
|
||||||
}
|
}
|
||||||
|
|
||||||
//create a box that cover all vertices such that during the sweeping, the vision ray will always intersect at least an edge.
|
//create a box that cover all vertices such that during the sweeping,
|
||||||
|
//the vision ray will always intersect at least an edge.
|
||||||
//this box doesn't intersect any relevant_edge.
|
//this box doesn't intersect any relevant_edge.
|
||||||
Points points;
|
Points points;
|
||||||
for (int i=0; i<vs.size(); i++) {
|
for (int i=0; i<vs.size(); i++) {
|
||||||
|
|
@ -794,23 +858,36 @@ private:
|
||||||
}
|
}
|
||||||
points.push_back(q);
|
points.push_back(q);
|
||||||
//first get the bounding box of all relevant points.
|
//first get the bounding box of all relevant points.
|
||||||
typename Geometry_traits_2::Iso_rectangle_2 bb = bounding_box(points.begin(), points.end());
|
typename Geometry_traits_2::Iso_rectangle_2 bb =
|
||||||
|
bounding_box(points.begin(), points.end());
|
||||||
|
|
||||||
Number_type xmin, xmax, ymin, ymax;
|
Number_type xmin, xmax, ymin, ymax;
|
||||||
typename Geometry_traits_2::Compute_x_2 compute_x = geom_traits->compute_x_2_object();
|
typename Geometry_traits_2::Compute_x_2 compute_x =
|
||||||
typename Geometry_traits_2::Compute_y_2 compute_y = geom_traits->compute_y_2_object();
|
geom_traits->compute_x_2_object();
|
||||||
|
|
||||||
//make the box a little bigger than bb so that it won't intersect any relevant_edge.
|
typename Geometry_traits_2::Compute_y_2 compute_y =
|
||||||
|
geom_traits->compute_y_2_object();
|
||||||
|
|
||||||
|
//make the box a little bigger than bb so that it won't intersect any
|
||||||
|
//relevant_edge.
|
||||||
xmin = compute_x(bb.min())-1;
|
xmin = compute_x(bb.min())-1;
|
||||||
ymin = compute_y(bb.min())-1;
|
ymin = compute_y(bb.min())-1;
|
||||||
xmax = compute_x(bb.max())+1;
|
xmax = compute_x(bb.max())+1;
|
||||||
ymax = compute_y(bb.max())+1;
|
ymax = compute_y(bb.max())+1;
|
||||||
Point_2 box[4] = {Point_2(xmin, ymin), Point_2(xmax, ymin),
|
Point_2 box[4] = {Point_2(xmin, ymin), Point_2(xmax, ymin),
|
||||||
Point_2(xmax, ymax), Point_2(xmin, ymax)};
|
Point_2(xmax, ymax), Point_2(xmin, ymax)};
|
||||||
Halfedge_handle e1 = bbox.insert_in_face_interior(Segment_2(box[0], box[1]), bbox.unbounded_face());
|
|
||||||
Halfedge_handle e2 = bbox.insert_from_left_vertex(Segment_2(box[1], box[2]), e1->target());
|
Halfedge_handle e1 = bbox.insert_in_face_interior(Segment_2(box[0], box[1]),
|
||||||
Halfedge_handle e3 = bbox.insert_from_right_vertex(Segment_2(box[2], box[3]), e2->target());
|
bbox.unbounded_face());
|
||||||
bbox.insert_at_vertices(Segment_2(box[0], box[3]), e1->source(), e3->target());
|
|
||||||
|
Halfedge_handle e2 = bbox.insert_from_left_vertex(Segment_2(box[1], box[2]),
|
||||||
|
e1->target());
|
||||||
|
|
||||||
|
Halfedge_handle e3 = bbox.insert_from_right_vertex(Segment_2(box[2],box[3]),
|
||||||
|
e2->target());
|
||||||
|
|
||||||
|
bbox.insert_at_vertices(Segment_2(box[0], box[3]),
|
||||||
|
e1->source(), e3->target());
|
||||||
|
|
||||||
circ = curr = e1->face()->outer_ccb();
|
circ = curr = e1->face()->outer_ccb();
|
||||||
do {
|
do {
|
||||||
|
|
@ -837,17 +914,17 @@ private:
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename VARR>
|
template <typename VARR>
|
||||||
void conditional_regularize(VARR& arr_out, CGAL::Tag_true) {
|
void conditional_regularize(VARR& arr_out, CGAL::Tag_true) const {
|
||||||
regularize_output(arr_out);
|
regularize_output(arr_out);
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename VARR>
|
template <typename VARR>
|
||||||
void conditional_regularize(VARR& arr_out, CGAL::Tag_false) {
|
void conditional_regularize(VARR& arr_out, CGAL::Tag_false) const {
|
||||||
//do nothing
|
//do nothing
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename VARR>
|
template <typename VARR>
|
||||||
void regularize_output(VARR& arr_out) {
|
void regularize_output(VARR& arr_out) const {
|
||||||
typename VARR::Edge_iterator e_itr;
|
typename VARR::Edge_iterator e_itr;
|
||||||
for (e_itr = arr_out.edges_begin();
|
for (e_itr = arr_out.edges_begin();
|
||||||
e_itr != arr_out.edges_end();
|
e_itr != arr_out.edges_end();
|
||||||
|
|
|
||||||
|
|
@ -62,11 +62,11 @@ public:
|
||||||
typedef typename Geometry_traits_2::FT Number_type;
|
typedef typename Geometry_traits_2::FT Number_type;
|
||||||
typedef typename Geometry_traits_2::Object_2 Object_2;
|
typedef typename Geometry_traits_2::Object_2 Object_2;
|
||||||
|
|
||||||
typedef RegularizationCategory Regularization_category;
|
typedef RegularizationCategory Regularization_category;
|
||||||
typedef CGAL::Tag_false Supports_general_polygon_category;
|
typedef CGAL::Tag_false Supports_general_polygon_category;
|
||||||
typedef CGAL::Tag_true Supports_simple_polygon_category;
|
typedef CGAL::Tag_true Supports_simple_polygon_category;
|
||||||
|
|
||||||
Simple_polygon_visibility_2() : p_arr(NULL), geom_traits(NULL) {};
|
Simple_polygon_visibility_2() : p_arr(NULL), geom_traits(NULL) {}
|
||||||
|
|
||||||
/*! Constructor given an arrangement and the Regularization tag. */
|
/*! Constructor given an arrangement and the Regularization tag. */
|
||||||
Simple_polygon_visibility_2(const Arrangement_2& arr):
|
Simple_polygon_visibility_2(const Arrangement_2& arr):
|
||||||
|
|
@ -81,16 +81,17 @@ public:
|
||||||
|
|
||||||
/*! Method to check if the visibility object is attached or not to
|
/*! Method to check if the visibility object is attached or not to
|
||||||
an arrangement*/
|
an arrangement*/
|
||||||
bool is_attached() {
|
bool is_attached() const {
|
||||||
return (p_arr != NULL);
|
return (p_arr != NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*! Attaches the visibility object to the 'arr' arrangement */
|
/*! Attaches the visibility object to the 'arr' arrangement */
|
||||||
void attach(const Arrangement_2& arr) {
|
void attach(const Arrangement_2& arr) {
|
||||||
p_arr = &arr;
|
if(p_arr != &arr){
|
||||||
geom_traits = p_arr->geometry_traits();
|
detach();
|
||||||
query_pt_is_vertex = false;
|
p_arr = &arr;
|
||||||
query_pt_is_on_halfedge = false;
|
geom_traits = p_arr->geometry_traits();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/*! Detaches the visibility object from the arrangement it is
|
/*! Detaches the visibility object from the arrangement it is
|
||||||
|
|
@ -101,11 +102,11 @@ public:
|
||||||
vertices.clear();
|
vertices.clear();
|
||||||
query_pt_is_vertex = false;
|
query_pt_is_vertex = false;
|
||||||
query_pt_is_on_halfedge = false;
|
query_pt_is_on_halfedge = false;
|
||||||
p_cdt = boost::shared_ptr<CDT>();
|
p_cdt.reset();
|
||||||
}
|
}
|
||||||
|
|
||||||
/*! Getter method for the input arrangement*/
|
/*! Getter method for the input arrangement*/
|
||||||
const Arrangement_2& arrangement_2() {
|
const Arrangement_2& arrangement_2() const {
|
||||||
return *p_arr;
|
return *p_arr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -113,12 +114,17 @@ public:
|
||||||
'face' and constructs the output in 'out_arr'*/
|
'face' and constructs the output in 'out_arr'*/
|
||||||
template <typename VARR>
|
template <typename VARR>
|
||||||
typename VARR::Face_handle
|
typename VARR::Face_handle
|
||||||
compute_visibility(const Point_2& q,
|
compute_visibility(const Point_2& q, Face_const_handle face,
|
||||||
const Face_const_handle face,
|
VARR& out_arr) const {
|
||||||
VARR& out_arr) {
|
|
||||||
|
CGAL_precondition_msg(p_arr->number_of_faces() == 2,
|
||||||
|
"Only simple polygons are supported.");
|
||||||
|
|
||||||
|
out_arr.clear();
|
||||||
|
|
||||||
assert(query_pt_is_vertex == false);
|
query_pt_is_vertex = false;
|
||||||
assert(query_pt_is_on_halfedge == false);
|
query_pt_is_on_halfedge = false;
|
||||||
|
|
||||||
|
|
||||||
// Now retrieve the circulator to first visible vertex from triangulation
|
// Now retrieve the circulator to first visible vertex from triangulation
|
||||||
Ccb_halfedge_const_circulator circ = find_visible_start(face, q);
|
Ccb_halfedge_const_circulator circ = find_visible_start(face, q);
|
||||||
|
|
@ -134,31 +140,7 @@ public:
|
||||||
|
|
||||||
visibility_region_impl(q);
|
visibility_region_impl(q);
|
||||||
|
|
||||||
typename std::vector<Point_2> points;
|
return output(q, out_arr);
|
||||||
while (!s.empty()) {
|
|
||||||
Point_2 curr_point = s.top();
|
|
||||||
points.push_back(curr_point);
|
|
||||||
s.pop();
|
|
||||||
}
|
|
||||||
|
|
||||||
std::reverse(points.begin(), points.end());
|
|
||||||
|
|
||||||
CGAL::Visibility_2::report_while_handling_needles
|
|
||||||
<Simple_polygon_visibility_2>(geom_traits,
|
|
||||||
q,
|
|
||||||
points,
|
|
||||||
out_arr);
|
|
||||||
|
|
||||||
CGAL_precondition(out_arr.number_of_isolated_vertices() == 0);
|
|
||||||
CGAL_precondition(s.size() == 0);
|
|
||||||
conditional_regularize(out_arr, Regularization_category());
|
|
||||||
vertices.clear();
|
|
||||||
if (out_arr.faces_begin()->is_unbounded()) {
|
|
||||||
return ++out_arr.faces_begin();
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
return out_arr.faces_begin();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*! Computes the visibility region of the query point 'q' located on the
|
/*! Computes the visibility region of the query point 'q' located on the
|
||||||
|
|
@ -168,8 +150,14 @@ public:
|
||||||
compute_visibility(
|
compute_visibility(
|
||||||
const Point_2& q,
|
const Point_2& q,
|
||||||
const Halfedge_const_handle he,
|
const Halfedge_const_handle he,
|
||||||
VARR& out_arr )
|
VARR& out_arr ) const
|
||||||
{
|
{
|
||||||
|
|
||||||
|
CGAL_precondition_msg(p_arr->number_of_faces() == 2,
|
||||||
|
"Only simple polygons are supported.");
|
||||||
|
|
||||||
|
out_arr.clear();
|
||||||
|
|
||||||
query_pt_is_vertex = false;
|
query_pt_is_vertex = false;
|
||||||
query_pt_is_on_halfedge = false;
|
query_pt_is_on_halfedge = false;
|
||||||
bool query_on_target = false;
|
bool query_on_target = false;
|
||||||
|
|
@ -203,48 +191,34 @@ public:
|
||||||
}
|
}
|
||||||
|
|
||||||
visibility_region_impl(q);
|
visibility_region_impl(q);
|
||||||
|
|
||||||
|
return output(q, out_arr);
|
||||||
|
|
||||||
typename std::vector<Point_2> points;
|
// std::vector<Point_2> points;
|
||||||
if (!s.empty()) {
|
|
||||||
Point_2 prev_pt = s.top();
|
|
||||||
if (prev_pt != q) {
|
|
||||||
points.push_back(prev_pt);
|
|
||||||
}
|
|
||||||
else if (query_pt_is_vertex) {
|
|
||||||
points.push_back(prev_pt);
|
|
||||||
}
|
|
||||||
if (!s.empty()) {
|
|
||||||
s.pop();
|
|
||||||
}
|
|
||||||
while(!s.empty()) {
|
|
||||||
Point_2 curr_pt = s.top();
|
|
||||||
if (curr_pt != q) {
|
|
||||||
points.push_back(curr_pt);
|
|
||||||
}
|
|
||||||
else if (query_pt_is_vertex) {
|
|
||||||
points.push_back(curr_pt);
|
|
||||||
}
|
|
||||||
s.pop();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
std::reverse(points.begin(), points.end());
|
// if (!s.empty()) {
|
||||||
|
// Point_2 prev_pt = s.top();
|
||||||
|
// if (prev_pt != q) {
|
||||||
|
// points.push_back(prev_pt);
|
||||||
|
// }
|
||||||
|
// else if (query_pt_is_vertex) {
|
||||||
|
// points.push_back(prev_pt);
|
||||||
|
// }
|
||||||
|
// if (!s.empty()) {
|
||||||
|
// s.pop();
|
||||||
|
// }
|
||||||
|
// while(!s.empty()) {
|
||||||
|
// Point_2 curr_pt = s.top();
|
||||||
|
// if (curr_pt != q) {
|
||||||
|
// points.push_back(curr_pt);
|
||||||
|
// }
|
||||||
|
// else if (query_pt_is_vertex) {
|
||||||
|
// points.push_back(curr_pt);
|
||||||
|
// }
|
||||||
|
// s.pop();
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
|
||||||
CGAL::Visibility_2::report_while_handling_needles
|
|
||||||
<Simple_polygon_visibility_2>(geom_traits,
|
|
||||||
q,
|
|
||||||
points,
|
|
||||||
out_arr);
|
|
||||||
CGAL_precondition(out_arr.number_of_isolated_vertices() == 0);
|
|
||||||
CGAL_precondition(s.size() == 0);
|
|
||||||
conditional_regularize(out_arr, Regularization_category());
|
|
||||||
vertices.clear();
|
|
||||||
if (out_arr.faces_begin()->is_unbounded()) {
|
|
||||||
return ++out_arr.faces_begin();
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
return out_arr.faces_begin();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
@ -252,43 +226,43 @@ private:
|
||||||
typedef CGAL::Constrained_triangulation_face_base_2<K> Fb;
|
typedef CGAL::Constrained_triangulation_face_base_2<K> Fb;
|
||||||
typedef CGAL::Triangulation_data_structure_2<Vb,Fb> TDS;
|
typedef CGAL::Triangulation_data_structure_2<Vb,Fb> TDS;
|
||||||
typedef CGAL::No_intersection_tag Itag;
|
typedef CGAL::No_intersection_tag Itag;
|
||||||
typedef CGAL::Constrained_triangulation_2<K, TDS, Itag> CDT;
|
typedef CGAL::Constrained_triangulation_2<K, TDS, Itag> CDT;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
const Arrangement_2 *p_arr;
|
const Arrangement_2 *p_arr;
|
||||||
|
const Geometry_traits_2 *geom_traits;
|
||||||
|
|
||||||
/*! Boost pointer to the constrained Delaunay triangulation object*/
|
/*! Boost pointer to the constrained Delaunay triangulation object*/
|
||||||
boost::shared_ptr<CDT> p_cdt;
|
mutable boost::shared_ptr<CDT> p_cdt;
|
||||||
/*! Mapping of the vertices of the input to the corresponding circulator
|
/*! Mapping of the vertices of the input to the corresponding circulator
|
||||||
needed for finding the first visible vertex in case of face queries*/
|
needed for finding the first visible vertex in case of face queries*/
|
||||||
std::map<Point_2, typename Arrangement_2::Ccb_halfedge_const_circulator>
|
mutable std::map<Point_2, Ccb_halfedge_const_circulator> point_itr_map;
|
||||||
point_itr_map;
|
|
||||||
const Geometry_traits_2 *geom_traits;
|
|
||||||
/*! Stack of visibile points; manipulated when going through the sequence
|
/*! Stack of visibile points; manipulated when going through the sequence
|
||||||
of input vertices; contains the vertices of the visibility region after
|
of input vertices; contains the vertices of the visibility region after
|
||||||
the run of the algorithm*/
|
the run of the algorithm*/
|
||||||
std::stack<Point_2> s;
|
mutable std::stack<Point_2> s;
|
||||||
/*! Sequence of input vertices*/
|
/*! Sequence of input vertices*/
|
||||||
std::vector<Point_2> vertices;
|
mutable std::vector<Point_2> vertices;
|
||||||
/*! State of visibility region algorithm*/
|
/*! State of visibility region algorithm*/
|
||||||
enum {LEFT, RIGHT, SCANA, SCANB, SCANC, SCAND, FINISH} upcase;
|
mutable enum {LEFT, RIGHT, SCANA, SCANB, SCANC, SCAND, FINISH} upcase;
|
||||||
bool query_pt_is_vertex;
|
mutable bool query_pt_is_vertex;
|
||||||
bool query_pt_is_on_halfedge;
|
mutable bool query_pt_is_on_halfedge;
|
||||||
|
|
||||||
/*! Regularize output if flag is set to true*/
|
/*! Regularize output if flag is set to true*/
|
||||||
template <typename VARR>
|
template <typename VARR>
|
||||||
void conditional_regularize(VARR& out_arr, CGAL::Tag_true) {
|
void conditional_regularize(VARR& out_arr, CGAL::Tag_true) const {
|
||||||
regularize_output(out_arr);
|
regularize_output(out_arr);
|
||||||
}
|
}
|
||||||
/*! No need to regularize output if flag is set to false*/
|
/*! No need to regularize output if flag is set to false*/
|
||||||
template <typename VARR>
|
template <typename VARR>
|
||||||
void conditional_regularize(VARR& out_arr, CGAL::Tag_false) {
|
void conditional_regularize(VARR& out_arr, CGAL::Tag_false) const {
|
||||||
//do nothing
|
//do nothing
|
||||||
}
|
}
|
||||||
|
|
||||||
/*! Regularizes the output - removes edges that have the same face on both
|
/*! Regularizes the output - removes edges that have the same face on both
|
||||||
sides */
|
sides */
|
||||||
template <typename VARR>
|
template <typename VARR>
|
||||||
void regularize_output(VARR& out_arr) {
|
void regularize_output(VARR& out_arr) const {
|
||||||
typename VARR::Edge_iterator e_itr;
|
typename VARR::Edge_iterator e_itr;
|
||||||
for (e_itr = out_arr.edges_begin() ;
|
for (e_itr = out_arr.edges_begin() ;
|
||||||
e_itr != out_arr.edges_end() ; e_itr++) {
|
e_itr != out_arr.edges_end() ; e_itr++) {
|
||||||
|
|
@ -303,29 +277,61 @@ private:
|
||||||
|
|
||||||
/*! Initialized the constrained Delaunay triangulation using the edges of
|
/*! Initialized the constrained Delaunay triangulation using the edges of
|
||||||
the outer boundary of 'face' */
|
the outer boundary of 'face' */
|
||||||
void init_cdt(const Face_const_handle &face) {
|
void init_cdt(const Face_const_handle &face) const {
|
||||||
|
|
||||||
|
point_itr_map.clear();
|
||||||
|
|
||||||
std::vector<std::pair<Point_2,Point_2> > constraints;
|
std::vector<std::pair<Point_2,Point_2> > constraints;
|
||||||
typename Arrangement_2::Ccb_halfedge_const_circulator circ =
|
Ccb_halfedge_const_circulator circ = face->outer_ccb();
|
||||||
face->outer_ccb();
|
Ccb_halfedge_const_circulator curr = circ;
|
||||||
typename Arrangement_2::Ccb_halfedge_const_circulator curr = circ;
|
|
||||||
typename Arrangement_2::Halfedge_const_handle he;
|
|
||||||
|
|
||||||
do {
|
do {
|
||||||
he = curr;
|
Point_2 source = curr->source()->point();
|
||||||
Point_2 source = he->source()->point();
|
Point_2 target = curr->target()->point();
|
||||||
Point_2 target = he->target()->point();
|
|
||||||
point_itr_map.insert(std::make_pair(source, curr));
|
point_itr_map.insert(std::make_pair(source, curr));
|
||||||
constraints.push_back(std::make_pair(source,target));
|
constraints.push_back(std::make_pair(source, target));
|
||||||
} while(++curr != circ);
|
} while(++curr != circ);
|
||||||
|
|
||||||
p_cdt = boost::shared_ptr<CDT>(new CDT(constraints.begin(),constraints.end()));
|
p_cdt = boost::shared_ptr<CDT>(new CDT(constraints.begin(),
|
||||||
|
constraints.end()));
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename VARR>
|
||||||
|
typename VARR::Face_handle
|
||||||
|
output(const Point_2& q, VARR& out_arr) const {
|
||||||
|
|
||||||
|
std::vector<Point_2> points;
|
||||||
|
while (!s.empty()) {
|
||||||
|
points.push_back(s.top());
|
||||||
|
s.pop();
|
||||||
|
}
|
||||||
|
|
||||||
|
// std::reverse(points.begin(), points.end());
|
||||||
|
|
||||||
|
CGAL::Visibility_2::report_while_handling_needles
|
||||||
|
<Simple_polygon_visibility_2>(geom_traits,
|
||||||
|
q,
|
||||||
|
points,
|
||||||
|
out_arr);
|
||||||
|
|
||||||
|
CGAL_postcondition(out_arr.number_of_isolated_vertices() == 0);
|
||||||
|
CGAL_postcondition(s.empty());
|
||||||
|
|
||||||
|
conditional_regularize(out_arr, Regularization_category());
|
||||||
|
vertices.clear();
|
||||||
|
if (out_arr.faces_begin()->is_unbounded()) {
|
||||||
|
return ++out_arr.faces_begin();
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
return out_arr.faces_begin();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/*! Finds a visible vertex from the query point 'q' in 'face'
|
/*! Finds a visible vertex from the query point 'q' in 'face'
|
||||||
to start the algorithm from*/
|
to start the algorithm from*/
|
||||||
Ccb_halfedge_const_circulator find_visible_start(Face_const_handle face, const Point_2 &q) {
|
Ccb_halfedge_const_circulator find_visible_start(Face_const_handle face,
|
||||||
|
const Point_2 &q) const {
|
||||||
init_cdt(face);
|
init_cdt(face);
|
||||||
typename CDT::Face_handle fh = p_cdt->locate(q);
|
typename CDT::Face_handle fh = p_cdt->locate(q);
|
||||||
Point_2 start_point = fh->vertex(0)->point();
|
Point_2 start_point = fh->vertex(0)->point();
|
||||||
|
|
@ -334,7 +340,8 @@ private:
|
||||||
Ccb_halfedge_const_circulator circ = point_itr_map[start_point];
|
Ccb_halfedge_const_circulator circ = point_itr_map[start_point];
|
||||||
Halfedge_const_handle he_curr = circ;
|
Halfedge_const_handle he_curr = circ;
|
||||||
|
|
||||||
Halfedge_around_vertex_const_circulator incident_circ = he_curr->source()->incident_halfedges();
|
Halfedge_around_vertex_const_circulator incident_circ =
|
||||||
|
he_curr->source()->incident_halfedges();
|
||||||
Halfedge_around_vertex_const_circulator incident_curr = incident_circ;
|
Halfedge_around_vertex_const_circulator incident_curr = incident_circ;
|
||||||
|
|
||||||
do {
|
do {
|
||||||
|
|
@ -353,10 +360,9 @@ private:
|
||||||
|| CGAL::Visibility_2::orientation_2(geom_traits,
|
|| CGAL::Visibility_2::orientation_2(geom_traits,
|
||||||
he_next_inc->source()->point(),
|
he_next_inc->source()->point(),
|
||||||
he_next_inc->target()->point(),
|
he_next_inc->target()->point(),
|
||||||
q) == CGAL::LEFT_TURN) {
|
q) == CGAL::LEFT_TURN)
|
||||||
Ccb_halfedge_const_circulator result_circ = incident_next;
|
{
|
||||||
Halfedge_const_handle he_print = result_circ;
|
return incident_next;
|
||||||
return result_circ;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} while (++incident_curr != incident_circ);
|
} while (++incident_curr != incident_circ);
|
||||||
|
|
@ -367,7 +373,7 @@ private:
|
||||||
'q' - query point;
|
'q' - query point;
|
||||||
'i' - current vertex' index
|
'i' - current vertex' index
|
||||||
'w' - endpoint of ray shot from query point */
|
'w' - endpoint of ray shot from query point */
|
||||||
void visibility_region_impl(const Point_2& q) {
|
void visibility_region_impl(const Point_2& q) const {
|
||||||
int i = 0;
|
int i = 0;
|
||||||
Point_2 w;
|
Point_2 w;
|
||||||
CGAL::Orientation orient = CGAL::Visibility_2::orientation_2(geom_traits,
|
CGAL::Orientation orient = CGAL::Visibility_2::orientation_2(geom_traits,
|
||||||
|
|
@ -418,12 +424,10 @@ private:
|
||||||
( CGAL::Visibility_2::orientation_2 <Geometry_traits_2>
|
( CGAL::Visibility_2::orientation_2 <Geometry_traits_2>
|
||||||
( geom_traits, q, vertices[0],s_t ) == CGAL::LEFT_TURN ) ) {
|
( geom_traits, q, vertices[0],s_t ) == CGAL::LEFT_TURN ) ) {
|
||||||
Segment_2 seg( s.top(), s_t );
|
Segment_2 seg( s.top(), s_t );
|
||||||
if ( CGAL::Visibility_2::do_intersect_2
|
if (Visibility_2::do_intersect_2(geom_traits, seg, ray_origin ) )
|
||||||
<Geometry_traits_2, Segment_2, Ray_2>
|
{
|
||||||
( geom_traits, seg, ray_origin ) ) {
|
Object_2 result = Visibility_2::intersect_2(geom_traits,
|
||||||
Object_2 result = CGAL::Visibility_2::intersect_2
|
seg, ray_origin);
|
||||||
<Geometry_traits_2, Segment_2, Ray_2>
|
|
||||||
( geom_traits, seg, ray_origin );
|
|
||||||
const Point_2 * ipoint = CGAL::object_cast<Point_2>(&result);
|
const Point_2 * ipoint = CGAL::object_cast<Point_2>(&result);
|
||||||
assert( ipoint != NULL );
|
assert( ipoint != NULL );
|
||||||
s_t = *ipoint;
|
s_t = *ipoint;
|
||||||
|
|
@ -436,7 +440,7 @@ private:
|
||||||
}
|
}
|
||||||
|
|
||||||
/*! Method that handles the left turns in the vertex algorithm */
|
/*! Method that handles the left turns in the vertex algorithm */
|
||||||
void left(int& i, Point_2& w, const Point_2& query_pt) {
|
void left(int& i, Point_2& w, const Point_2& query_pt) const {
|
||||||
if (i >= vertices.size() - 1) {
|
if (i >= vertices.size() - 1) {
|
||||||
upcase = FINISH;
|
upcase = FINISH;
|
||||||
}
|
}
|
||||||
|
|
@ -445,8 +449,7 @@ private:
|
||||||
s.pop();
|
s.pop();
|
||||||
Point_2 s_t_prev = s.top();
|
Point_2 s_t_prev = s.top();
|
||||||
s.push( s_t );
|
s.push( s_t );
|
||||||
CGAL::Orientation orient1 = CGAL::Visibility_2::orientation_2
|
CGAL::Orientation orient1 = Visibility_2::orientation_2
|
||||||
<Geometry_traits_2>
|
|
||||||
( geom_traits,
|
( geom_traits,
|
||||||
query_pt,
|
query_pt,
|
||||||
vertices[i],
|
vertices[i],
|
||||||
|
|
@ -458,8 +461,7 @@ private:
|
||||||
w = vertices[i+1];
|
w = vertices[i+1];
|
||||||
i++;
|
i++;
|
||||||
} else {
|
} else {
|
||||||
CGAL::Orientation orient2 = CGAL::Visibility_2::orientation_2
|
CGAL::Orientation orient2 = Visibility_2::orientation_2
|
||||||
<Geometry_traits_2>
|
|
||||||
( geom_traits,
|
( geom_traits,
|
||||||
s_t_prev,
|
s_t_prev,
|
||||||
vertices[i],
|
vertices[i],
|
||||||
|
|
@ -481,7 +483,7 @@ private:
|
||||||
|
|
||||||
/*! Scans the stack such that all vertices that were pushed before to the
|
/*! Scans the stack such that all vertices that were pushed before to the
|
||||||
stack and are now not visible anymore. */
|
stack and are now not visible anymore. */
|
||||||
void right(int& i, Point_2& w, const Point_2& query_pt) {
|
void right(int& i, Point_2& w, const Point_2& query_pt) const {
|
||||||
Point_2 s_j;
|
Point_2 s_j;
|
||||||
Point_2 s_j_prev;
|
Point_2 s_j_prev;
|
||||||
Point_2 u;
|
Point_2 u;
|
||||||
|
|
@ -506,12 +508,10 @@ private:
|
||||||
|
|
||||||
Segment_2 seg2( vertices[i-1], vertices[i] );
|
Segment_2 seg2( vertices[i-1], vertices[i] );
|
||||||
Segment_2 seg( s_j_prev, s_j );
|
Segment_2 seg( s_j_prev, s_j );
|
||||||
if ( ( vertices[i-1] != s_j )
|
if ( vertices[i-1] != s_j &&
|
||||||
&& ( CGAL::Visibility_2::do_intersect_2
|
Visibility_2::do_intersect_2(geom_traits, seg, seg2) )
|
||||||
<Geometry_traits_2, Segment_2, Segment_2>
|
{
|
||||||
(geom_traits, seg, seg2) ) ) {
|
Object_2 result = Visibility_2::intersect_2(geom_traits, seg, seg2);
|
||||||
Object_2 result = CGAL::Visibility_2::intersect_2
|
|
||||||
<Geometry_traits_2, Segment_2, Segment_2>( geom_traits, seg, seg2 );
|
|
||||||
const Point_2 * ipoint = CGAL::object_cast<Point_2>(&result);
|
const Point_2 * ipoint = CGAL::object_cast<Point_2>(&result);
|
||||||
assert( ipoint != NULL );
|
assert( ipoint != NULL );
|
||||||
u = *ipoint;
|
u = *ipoint;
|
||||||
|
|
@ -579,7 +579,7 @@ private:
|
||||||
|
|
||||||
/*! Scans the vertices starting from index 'i' for the first visible vertex
|
/*! Scans the vertices starting from index 'i' for the first visible vertex
|
||||||
out of the back hidden window */
|
out of the back hidden window */
|
||||||
void scana(int& i, Point_2& w, const Point_2& query_pt) {
|
void scana(int& i, Point_2& w, const Point_2& query_pt) const {
|
||||||
// Scan v_i, v_i+1, ..., v_n for the first edge to intersect (z, s_t)
|
// Scan v_i, v_i+1, ..., v_n for the first edge to intersect (z, s_t)
|
||||||
Point_2 u;
|
Point_2 u;
|
||||||
int k = scan_edges( i, query_pt, s.top(), u, true );
|
int k = scan_edges( i, query_pt, s.top(), u, true );
|
||||||
|
|
@ -618,7 +618,7 @@ private:
|
||||||
}
|
}
|
||||||
|
|
||||||
/*! Find the first edge interecting the segment (v_0, s_t) */
|
/*! Find the first edge interecting the segment (v_0, s_t) */
|
||||||
void scanb(int& i, Point_2& w, const Point_2& query_pt) {
|
void scanb(int& i, Point_2& w, const Point_2& query_pt) const {
|
||||||
if ( i == vertices.size() - 1 ) {
|
if ( i == vertices.size() - 1 ) {
|
||||||
upcase = FINISH;
|
upcase = FINISH;
|
||||||
return;
|
return;
|
||||||
|
|
@ -639,7 +639,7 @@ private:
|
||||||
|
|
||||||
/*! Finds the exit from a general front hidden window by finding the first
|
/*! Finds the exit from a general front hidden window by finding the first
|
||||||
vertex to the right of the ray defined by the query_point and w*/
|
vertex to the right of the ray defined by the query_point and w*/
|
||||||
void scanc(int& i, Point_2& w, const Point_2& query_pt) {
|
void scanc(int& i, Point_2& w, const Point_2& query_pt) const {
|
||||||
Point_2 u;
|
Point_2 u;
|
||||||
int k = scan_edges( i, s.top(), w, u, false );
|
int k = scan_edges( i, s.top(), w, u, false );
|
||||||
upcase = RIGHT;
|
upcase = RIGHT;
|
||||||
|
|
@ -648,7 +648,7 @@ private:
|
||||||
}
|
}
|
||||||
|
|
||||||
/*! find the first edge intersecting the given window (s_t, w) */
|
/*! find the first edge intersecting the given window (s_t, w) */
|
||||||
void scand(int& i, Point_2& w, const Point_2& query_pt) {
|
void scand(int& i, Point_2& w, const Point_2& query_pt) const {
|
||||||
Point_2 u;
|
Point_2 u;
|
||||||
int k = scan_edges( i, s.top(), w, u, false );
|
int k = scan_edges( i, s.top(), w, u, false );
|
||||||
upcase = LEFT;
|
upcase = LEFT;
|
||||||
|
|
@ -663,7 +663,12 @@ private:
|
||||||
/*! Scan edges v_i,v_{i+1},...,v_n, until find an edge intersecting given ray
|
/*! Scan edges v_i,v_{i+1},...,v_n, until find an edge intersecting given ray
|
||||||
or given segment. is_ray = true -> ray, false -> segment.
|
or given segment. is_ray = true -> ray, false -> segment.
|
||||||
The intersection point is returned by u */
|
The intersection point is returned by u */
|
||||||
int scan_edges( int i, const Point_2& ray_begin, const Point_2& ray_end, Point_2& u, bool is_ray ) {
|
int scan_edges( int i,
|
||||||
|
const Point_2& ray_begin,
|
||||||
|
const Point_2& ray_end,
|
||||||
|
Point_2& u,
|
||||||
|
bool is_ray ) const
|
||||||
|
{
|
||||||
CGAL::Orientation old_orient = CGAL::RIGHT_TURN;
|
CGAL::Orientation old_orient = CGAL::RIGHT_TURN;
|
||||||
Ray_2 ray( ray_begin, ray_end );
|
Ray_2 ray( ray_begin, ray_end );
|
||||||
Segment_2 s2( ray_begin, ray_end );
|
Segment_2 s2( ray_begin, ray_end );
|
||||||
|
|
@ -679,21 +684,15 @@ private:
|
||||||
// Orientation switch, an intersection may occur
|
// Orientation switch, an intersection may occur
|
||||||
Segment_2 seg( vertices[k], vertices[k+1] );
|
Segment_2 seg( vertices[k], vertices[k+1] );
|
||||||
if ( is_ray ) {
|
if ( is_ray ) {
|
||||||
if (CGAL::Visibility_2::do_intersect_2
|
if (CGAL::Visibility_2::do_intersect_2(geom_traits, seg, ray) )
|
||||||
<Geometry_traits_2, Segment_2, Ray_2>
|
{
|
||||||
(geom_traits, seg, ray) ) {
|
result = CGAL::Visibility_2::intersect_2( geom_traits, seg, ray );
|
||||||
result = CGAL::Visibility_2::intersect_2
|
|
||||||
< Geometry_traits_2, Segment_2, Ray_2 >
|
|
||||||
( geom_traits, seg, ray );
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if (CGAL::Visibility_2::do_intersect_2
|
if (Visibility_2::do_intersect_2(geom_traits, seg, s2) )
|
||||||
<Geometry_traits_2, Segment_2, Segment_2>
|
{
|
||||||
(geom_traits, seg, s2) ) {
|
result = Visibility_2::intersect_2( geom_traits, seg, s2 );
|
||||||
result = CGAL::Visibility_2::intersect_2
|
|
||||||
< Geometry_traits_2, Segment_2, Segment_2 >
|
|
||||||
( geom_traits, seg, s2 );
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -19,12 +19,14 @@
|
||||||
// Author(s): Michael Hemmer <michael.hemmer@cgal.org>
|
// Author(s): Michael Hemmer <michael.hemmer@cgal.org>
|
||||||
//
|
//
|
||||||
|
|
||||||
#ifndef CGAL_TRIANGULAR_EXPANSION_VISIBILITY_2__H
|
#ifndef CGAL_TRIANGULAR_EXPANSION_VISIBILITY_2_H
|
||||||
#define CGAL_TRIANGULAR_EXPANSION_VISIBILITY_2__H
|
#define CGAL_TRIANGULAR_EXPANSION_VISIBILITY_2_H
|
||||||
|
|
||||||
#include <CGAL/Arrangement_2.h>
|
#include <CGAL/Arrangement_2.h>
|
||||||
#include <boost/shared_ptr.hpp>
|
#include <boost/shared_ptr.hpp>
|
||||||
|
#include <boost/iterator/transform_iterator.hpp>
|
||||||
#include <CGAL/Constrained_Delaunay_triangulation_2.h>
|
#include <CGAL/Constrained_Delaunay_triangulation_2.h>
|
||||||
|
#include <CGAL/Arr_observer.h>
|
||||||
|
|
||||||
namespace CGAL {
|
namespace CGAL {
|
||||||
|
|
||||||
|
|
@ -32,20 +34,27 @@ template<class Arrangement_2_ , class RegularizationCategory = CGAL::Tag_true >
|
||||||
class Triangular_expansion_visibility_2 {
|
class Triangular_expansion_visibility_2 {
|
||||||
typedef typename Arrangement_2_::Geometry_traits_2 Geometry_traits_2;
|
typedef typename Arrangement_2_::Geometry_traits_2 Geometry_traits_2;
|
||||||
typedef typename Geometry_traits_2::Kernel K;
|
typedef typename Geometry_traits_2::Kernel K;
|
||||||
|
|
||||||
|
typedef Triangular_expansion_visibility_2<
|
||||||
|
Arrangement_2_, RegularizationCategory> Self;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
// Currently only consider with same type for both
|
typedef Arrangement_2_ Arrangement_2;
|
||||||
typedef Arrangement_2_ Arrangement_2;
|
|
||||||
typedef typename Arrangement_2::Traits_2 Traits_2;
|
typedef typename Arrangement_2::Traits_2 Traits_2;
|
||||||
|
typedef typename Arrangement_2::Halfedge Halfedge;
|
||||||
typedef typename Arrangement_2::Halfedge_const_handle Halfedge_const_handle;
|
typedef typename Arrangement_2::Halfedge_const_handle Halfedge_const_handle;
|
||||||
typedef typename Arrangement_2::Halfedge_handle Halfedge_handle;
|
typedef typename Arrangement_2::Halfedge_handle Halfedge_handle;
|
||||||
|
typedef typename Arrangement_2::Edge_const_iterator Edge_const_iterator;
|
||||||
typedef typename Arrangement_2::Ccb_halfedge_const_circulator
|
typedef typename Arrangement_2::Ccb_halfedge_const_circulator
|
||||||
Ccb_halfedge_const_circulator;
|
Ccb_halfedge_const_circulator;
|
||||||
|
typedef typename Arrangement_2::Ccb_halfedge_circulator
|
||||||
|
Ccb_halfedge_circulator;
|
||||||
typedef typename Arrangement_2::Face_const_handle Face_const_handle;
|
typedef typename Arrangement_2::Face_const_handle Face_const_handle;
|
||||||
typedef typename Arrangement_2::Face_handle Face_handle;
|
typedef typename Arrangement_2::Face_handle Face_handle;
|
||||||
typedef typename Arrangement_2::Vertex_const_handle Vertex_const_handle;
|
typedef typename Arrangement_2::Vertex_const_handle Vertex_const_handle;
|
||||||
typedef typename Arrangement_2::Vertex_handle Vertex_handle;
|
typedef typename Arrangement_2::Vertex_handle Vertex_handle;
|
||||||
|
|
||||||
typedef typename K::Point_2 Point_2;
|
typedef typename K::Point_2 Point_2;
|
||||||
typedef typename Geometry_traits_2::Ray_2 Ray_2;
|
typedef typename Geometry_traits_2::Ray_2 Ray_2;
|
||||||
typedef typename Geometry_traits_2::Segment_2 Segment_2;
|
typedef typename Geometry_traits_2::Segment_2 Segment_2;
|
||||||
typedef typename Geometry_traits_2::Line_2 Line_2;
|
typedef typename Geometry_traits_2::Line_2 Line_2;
|
||||||
|
|
@ -54,11 +63,10 @@ public:
|
||||||
typedef typename Geometry_traits_2::FT Number_type;
|
typedef typename Geometry_traits_2::FT Number_type;
|
||||||
typedef typename Geometry_traits_2::Object_2 Object_2;
|
typedef typename Geometry_traits_2::Object_2 Object_2;
|
||||||
|
|
||||||
// TODO
|
|
||||||
typedef RegularizationCategory Regularization_category;
|
typedef RegularizationCategory Regularization_category;
|
||||||
|
|
||||||
typedef CGAL::Tag_true Supports_general_polygon_category;
|
typedef CGAL::Tag_true Supports_general_polygon_category;
|
||||||
typedef CGAL::Tag_true Supports_simple_polygon_category;
|
typedef CGAL::Tag_true Supports_simple_polygon_category;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
typedef CGAL::Triangulation_vertex_base_2<K> Vb;
|
typedef CGAL::Triangulation_vertex_base_2<K> Vb;
|
||||||
|
|
@ -66,32 +74,117 @@ private:
|
||||||
typedef CGAL::Triangulation_data_structure_2<Vb,Fb> TDS;
|
typedef CGAL::Triangulation_data_structure_2<Vb,Fb> TDS;
|
||||||
typedef CGAL::No_intersection_tag Itag;
|
typedef CGAL::No_intersection_tag Itag;
|
||||||
typedef CGAL::Constrained_Delaunay_triangulation_2<K, TDS, Itag> CDT;
|
typedef CGAL::Constrained_Delaunay_triangulation_2<K, TDS, Itag> CDT;
|
||||||
|
|
||||||
|
typedef std::pair<Point_2,Point_2> Constraint;
|
||||||
|
|
||||||
|
// Functor to create edge constraints for the CDT out of Halfedges
|
||||||
|
struct Make_constraint
|
||||||
|
{
|
||||||
|
typedef Constraint result_type;
|
||||||
|
|
||||||
|
Constraint operator()(const Halfedge& edge) const {
|
||||||
|
return std::make_pair(edge.source()->point(),
|
||||||
|
edge.target()->point());
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// Observer to track any changes of the attached arrangement.
|
||||||
|
class Observer : public Arr_observer<Arrangement_2>
|
||||||
|
{
|
||||||
|
|
||||||
|
typedef Arr_observer<Arrangement_2> Base;
|
||||||
|
typedef Observer Self;
|
||||||
|
|
||||||
|
|
||||||
|
public:
|
||||||
|
bool has_changed;
|
||||||
|
|
||||||
|
Observer() : Base(), has_changed(false)
|
||||||
|
{}
|
||||||
|
|
||||||
|
Observer(const Arrangement_2& arr)
|
||||||
|
: Base(const_cast<Arrangement_2&>(arr)), has_changed(false)
|
||||||
|
{}
|
||||||
|
|
||||||
|
// Arr_observer interface
|
||||||
|
|
||||||
|
void after_attach() { has_changed = false; }
|
||||||
|
|
||||||
|
|
||||||
|
void after_global_change() { has_changed = true; }
|
||||||
|
void after_create_vertex(Vertex_handle) { has_changed = true; }
|
||||||
|
void after_create_boundary_vertex(Vertex_handle) { has_changed = true; }
|
||||||
|
void after_create_edge(Halfedge_handle) { has_changed = true; }
|
||||||
|
void after_modify_vertex(Vertex_handle) { has_changed = true; }
|
||||||
|
void after_modify_edge(Halfedge_handle) { has_changed = true; }
|
||||||
|
void after_split_edge(Halfedge_handle, Halfedge_handle) {
|
||||||
|
has_changed = true; }
|
||||||
|
void after_split_fictitious_edge(Halfedge_handle, Halfedge_handle) {
|
||||||
|
has_changed = true; }
|
||||||
|
void after_split_face(Face_handle, Face_handle, bool) {
|
||||||
|
has_changed = true; }
|
||||||
|
void after_split_outer_ccb(Face_handle, Ccb_halfedge_circulator,
|
||||||
|
Ccb_halfedge_circulator) {
|
||||||
|
has_changed = true; }
|
||||||
|
void after_split_inner_ccb(Face_handle, Ccb_halfedge_circulator,
|
||||||
|
Ccb_halfedge_circulator) {
|
||||||
|
has_changed = true; }
|
||||||
|
void after_add_outer_ccb(Ccb_halfedge_circulator) { has_changed = true; }
|
||||||
|
void after_add_inner_ccb(Ccb_halfedge_circulator) { has_changed = true; }
|
||||||
|
void after_add_isolated_vertex(Vertex_handle) { has_changed = true; }
|
||||||
|
void after_merge_edge(Halfedge_handle) { has_changed = true; }
|
||||||
|
void after_merge_fictitious_edge(Halfedge_handle) { has_changed = true; }
|
||||||
|
void after_merge_face(Face_handle) { has_changed = true; }
|
||||||
|
void after_merge_outer_ccb(Face_handle, Ccb_halfedge_circulator) {
|
||||||
|
has_changed = true; }
|
||||||
|
void after_merge_inner_ccb(Face_handle, Ccb_halfedge_circulator) {
|
||||||
|
has_changed = true; }
|
||||||
|
void after_move_outer_ccb(Ccb_halfedge_circulator) { has_changed = true; }
|
||||||
|
void after_move_inner_ccb(Ccb_halfedge_circulator) { has_changed = true; }
|
||||||
|
void after_move_isolated_vertex(Vertex_handle) { has_changed = true; }
|
||||||
|
void after_remove_vertex() { has_changed = true; }
|
||||||
|
void after_remove_edge() { has_changed = true; }
|
||||||
|
void after_remove_outer_ccb(Face_handle) { has_changed = true; }
|
||||||
|
void after_remove_inner_ccb(Face_handle) { has_changed = true; }
|
||||||
|
};
|
||||||
|
|
||||||
public:
|
|
||||||
const std::string name(){return std::string("T_visibility_2");}
|
|
||||||
private:
|
private:
|
||||||
const Arrangement_2* p_arr;
|
const Arrangement_2* p_arr;
|
||||||
boost::shared_ptr<CDT> p_cdt;
|
|
||||||
std::vector<Segment_2> needles;
|
// May change during visibility computation
|
||||||
|
mutable Observer observer;
|
||||||
|
mutable boost::shared_ptr<CDT> p_cdt;
|
||||||
|
mutable std::vector<Segment_2> needles;
|
||||||
|
|
||||||
|
// Copy constructor and assignment not supported
|
||||||
|
Triangular_expansion_visibility_2(const Self&);
|
||||||
|
Self& operator= (const Self& );
|
||||||
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
Triangular_expansion_visibility_2() : p_arr(NULL){}
|
Triangular_expansion_visibility_2() : p_arr(NULL){}
|
||||||
|
|
||||||
/*! Constructor given an arrangement and the Regularization tag. */
|
/*! Constructor given an arrangement. */
|
||||||
Triangular_expansion_visibility_2 (const Arrangement_2& arr)
|
Triangular_expansion_visibility_2 (const Arrangement_2& arr)
|
||||||
: p_arr(&arr){
|
: p_arr(&arr), observer(arr)
|
||||||
|
{
|
||||||
init_cdt();
|
init_cdt();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool is_attached() {
|
const std::string name() const { return std::string("T_visibility_2"); }
|
||||||
|
|
||||||
|
|
||||||
|
bool is_attached() const {
|
||||||
//std::cout << "is_attached" << std::endl;
|
//std::cout << "is_attached" << std::endl;
|
||||||
return (p_arr != NULL);
|
return (p_arr != NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
void attach(const Arrangement_2& arr) {
|
void attach(const Arrangement_2& arr) {
|
||||||
// todo observe changes in arr;
|
|
||||||
if(p_arr != &arr){
|
if(p_arr != &arr){
|
||||||
p_arr = &arr;
|
p_arr = &arr;
|
||||||
|
observer.detach();
|
||||||
|
observer.attach(const_cast<Arrangement_2&>(arr));
|
||||||
init_cdt();
|
init_cdt();
|
||||||
}
|
}
|
||||||
//std::cout << "attach done" << std::endl;
|
//std::cout << "attach done" << std::endl;
|
||||||
|
|
@ -99,22 +192,209 @@ public:
|
||||||
|
|
||||||
void detach() {
|
void detach() {
|
||||||
//std::cout << "detach" << std::endl;
|
//std::cout << "detach" << std::endl;
|
||||||
|
observer.detach();
|
||||||
p_arr = NULL;
|
p_arr = NULL;
|
||||||
p_cdt = boost::shared_ptr<CDT>();
|
p_cdt.reset();
|
||||||
}
|
}
|
||||||
|
|
||||||
const Arrangement_2& arrangement_2() {
|
const Arrangement_2& arrangement_2() const {
|
||||||
return *p_arr;
|
return *p_arr;
|
||||||
}
|
}
|
||||||
|
|
||||||
typename CDT::Edge get_edge(typename CDT::Face_handle fh, int i){
|
|
||||||
|
template <typename VARR>
|
||||||
|
typename VARR::Face_handle
|
||||||
|
compute_visibility(const Point_2& q,
|
||||||
|
const Face_const_handle face,
|
||||||
|
VARR& out_arr )
|
||||||
|
const {
|
||||||
|
//std::cout << "query in face interior" << std::endl;
|
||||||
|
|
||||||
|
if(observer.has_changed) {
|
||||||
|
init_cdt();
|
||||||
|
}
|
||||||
|
|
||||||
|
out_arr.clear();
|
||||||
|
needles.clear();
|
||||||
|
assert(!face->is_unbounded());
|
||||||
|
|
||||||
|
|
||||||
|
std::vector<Point_2> raw_output;
|
||||||
|
typename CDT::Face_handle fh = p_cdt->locate(q);
|
||||||
|
|
||||||
|
raw_output.push_back(fh->vertex(1)->point());
|
||||||
|
if(!p_cdt->is_constrained(get_edge(fh,0))){
|
||||||
|
//std::cout<< "edge 0 is not constrained" << std::endl;
|
||||||
|
expand_edge(
|
||||||
|
q,
|
||||||
|
fh->vertex(2)->point(),
|
||||||
|
fh->vertex(1)->point(),
|
||||||
|
fh,0,std::back_inserter(raw_output));
|
||||||
|
}
|
||||||
|
|
||||||
|
raw_output.push_back(fh->vertex(2)->point());
|
||||||
|
if(!p_cdt->is_constrained(get_edge(fh,1))){
|
||||||
|
//std::cout << "edge 1 is not constrained" << std::endl;
|
||||||
|
expand_edge(
|
||||||
|
q,
|
||||||
|
fh->vertex(0)->point(),
|
||||||
|
fh->vertex(2)->point(),
|
||||||
|
fh,1,std::back_inserter(raw_output));
|
||||||
|
}
|
||||||
|
|
||||||
|
raw_output.push_back(fh->vertex(0)->point());
|
||||||
|
if(!p_cdt->is_constrained(get_edge(fh,2))){
|
||||||
|
//std::cout << "edge 2 is not constrained" << std::endl;
|
||||||
|
expand_edge(
|
||||||
|
q,
|
||||||
|
fh->vertex(1)->point(),
|
||||||
|
fh->vertex(0)->point(),
|
||||||
|
fh,2,std::back_inserter(raw_output));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
return output(raw_output,out_arr);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename VARR>
|
||||||
|
typename VARR::Face_handle
|
||||||
|
compute_visibility(const Point_2& q,
|
||||||
|
const Halfedge_const_handle he,
|
||||||
|
VARR& out_arr)
|
||||||
|
const {
|
||||||
|
//std::cout << "visibility_region he" << std::endl;
|
||||||
|
|
||||||
|
if(observer.has_changed) {
|
||||||
|
init_cdt();
|
||||||
|
}
|
||||||
|
|
||||||
|
assert(!he->face()->is_unbounded());
|
||||||
|
out_arr.clear();
|
||||||
|
needles.clear();
|
||||||
|
|
||||||
|
std::vector<Point_2> raw_output;
|
||||||
|
typename CDT::Locate_type location;
|
||||||
|
int index;
|
||||||
|
typename CDT::Face_handle fh = p_cdt->locate(q,location,index);
|
||||||
|
assert(location == CDT::EDGE || location == CDT::VERTEX);
|
||||||
|
//the following code tries to figure out which triangle one should start in.
|
||||||
|
|
||||||
|
|
||||||
|
if(location == CDT::EDGE){
|
||||||
|
//std::cout << "query on edge" << std::endl;
|
||||||
|
// this is the easy part, there are only two possible faces
|
||||||
|
// index indicates the edge = vertex on the other side of the edge
|
||||||
|
// the next vertex in cw order should be the target of given edge
|
||||||
|
if(fh->vertex(p_cdt->cw(index))->point() != he->target()->point()){
|
||||||
|
//std::cout << "need to swap face" << std::endl;
|
||||||
|
// take face on the other side if this is not the case
|
||||||
|
typename CDT::Face_handle nfh = fh->neighbor(index);
|
||||||
|
index = nfh->index(fh);
|
||||||
|
fh = nfh;
|
||||||
|
}
|
||||||
|
assert(fh->vertex(p_cdt->cw(index))->point() == he->target()->point());
|
||||||
|
assert(!p_cdt->is_infinite(fh->vertex(index)));
|
||||||
|
|
||||||
|
|
||||||
|
// output the edge the query lies on
|
||||||
|
raw_output.push_back(he->source()->point());
|
||||||
|
raw_output.push_back(he->target()->point());
|
||||||
|
|
||||||
|
if(!p_cdt->is_constrained(get_edge(fh,p_cdt->ccw(index)))){
|
||||||
|
expand_edge(
|
||||||
|
q,
|
||||||
|
fh->vertex(index)->point(), //left
|
||||||
|
he->target()->point() , //right
|
||||||
|
fh,
|
||||||
|
p_cdt->ccw(index),
|
||||||
|
std::back_inserter(raw_output));
|
||||||
|
}
|
||||||
|
raw_output.push_back(fh->vertex(index)->point());
|
||||||
|
|
||||||
|
if(!p_cdt->is_constrained(get_edge(fh,p_cdt->cw(index)))){
|
||||||
|
expand_edge(
|
||||||
|
q,
|
||||||
|
he->source()->point() , //left
|
||||||
|
fh->vertex(index)->point(), //right
|
||||||
|
fh,
|
||||||
|
p_cdt->cw(index),
|
||||||
|
std::back_inserter(raw_output));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if(location == CDT::VERTEX){
|
||||||
|
//std::cout << "query on vertex" << std::endl;
|
||||||
|
|
||||||
|
//bool query_point_on_vertex_is_not_working_yet = false;
|
||||||
|
//assert(query_point_on_vertex_is_not_working_yet);
|
||||||
|
|
||||||
|
assert(q == he->target()->point());
|
||||||
|
assert(fh->vertex(index)->point() == he->target()->point());
|
||||||
|
|
||||||
|
// push points that are seen anyway
|
||||||
|
// raw_output.push_back(he->source()->point()); inserted last
|
||||||
|
raw_output.push_back(he->target()->point());
|
||||||
|
raw_output.push_back(he->next()->target()->point());
|
||||||
|
|
||||||
|
// now start in the triangle that contains he->next()
|
||||||
|
while(
|
||||||
|
p_cdt->is_infinite(fh->vertex(p_cdt->ccw(index))) ||
|
||||||
|
he->next()->target()->point() !=
|
||||||
|
fh->vertex(p_cdt->ccw(index))->point()
|
||||||
|
)
|
||||||
|
{
|
||||||
|
typename CDT::Face_handle nfh = fh->neighbor(p_cdt->ccw(index));
|
||||||
|
int nindex = nfh->index(fh);
|
||||||
|
index = p_cdt->ccw(nindex);
|
||||||
|
fh = nfh;
|
||||||
|
assert(he->target()->point() == fh->vertex(index)->point());
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
assert(he->next()->source()->point() == fh->vertex(index)->point());
|
||||||
|
assert(he->next()->target()->point() ==
|
||||||
|
fh->vertex(p_cdt->ccw(index))->point());
|
||||||
|
assert(!p_cdt->is_infinite(fh));
|
||||||
|
assert(p_cdt->is_constrained(get_edge(fh,p_cdt->cw(index))));
|
||||||
|
|
||||||
|
while(he->source()->point() != fh->vertex(p_cdt->ccw(index))->point()){
|
||||||
|
|
||||||
|
if(!p_cdt->is_constrained(get_edge(fh,index))){
|
||||||
|
expand_edge(
|
||||||
|
q,
|
||||||
|
fh->vertex(p_cdt-> cw(index))->point(), //left
|
||||||
|
fh->vertex(p_cdt->ccw(index))->point(), //right
|
||||||
|
fh,
|
||||||
|
index,
|
||||||
|
std::back_inserter(raw_output));
|
||||||
|
}
|
||||||
|
// push left end point of edge into output
|
||||||
|
raw_output.push_back(fh->vertex(p_cdt-> cw(index))->point());
|
||||||
|
|
||||||
|
// take the next triangle around q in ccw order
|
||||||
|
typename CDT::Face_handle nfh = fh->neighbor(p_cdt->ccw(index));
|
||||||
|
int nindex = nfh->index(fh);
|
||||||
|
index = p_cdt->ccw(nindex);
|
||||||
|
fh = nfh;
|
||||||
|
assert(fh->vertex(index)->point() == he->target()->point());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return output(raw_output,out_arr);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
private:
|
||||||
|
|
||||||
|
typename CDT::Edge get_edge(typename CDT::Face_handle fh, int i) const {
|
||||||
return std::make_pair(fh,i);
|
return std::make_pair(fh,i);
|
||||||
}
|
}
|
||||||
|
|
||||||
Point_2 ray_seg_intersection(
|
Point_2 ray_seg_intersection(
|
||||||
const Point_2& q, const Point_2& b, // the ray
|
const Point_2& q, const Point_2& b, // the ray
|
||||||
const Point_2& s, const Point_2& t) // the segment
|
const Point_2& s, const Point_2& t // the segment
|
||||||
{
|
) const {
|
||||||
|
|
||||||
Ray_2 ray(q,b);
|
Ray_2 ray(q,b);
|
||||||
Segment_2 seg(s,t);
|
Segment_2 seg(s,t);
|
||||||
assert(typename K::Do_intersect_2()(ray,seg));
|
assert(typename K::Do_intersect_2()(ray,seg));
|
||||||
|
|
@ -127,9 +407,9 @@ public:
|
||||||
const Point_2& q,
|
const Point_2& q,
|
||||||
const typename CDT::Vertex_handle vh,
|
const typename CDT::Vertex_handle vh,
|
||||||
const typename CDT::Face_handle fh,
|
const typename CDT::Face_handle fh,
|
||||||
int index){
|
int index)
|
||||||
|
const {
|
||||||
|
|
||||||
|
|
||||||
// the expanded edge should not be constrained
|
// the expanded edge should not be constrained
|
||||||
assert(!p_cdt->is_constrained(get_edge(fh,index)));
|
assert(!p_cdt->is_constrained(get_edge(fh,index)));
|
||||||
assert(!p_cdt->is_infinite(fh));
|
assert(!p_cdt->is_infinite(fh));
|
||||||
|
|
@ -168,29 +448,30 @@ public:
|
||||||
//std::cout << "rvh->point() "<< rvh->point() << std::endl<< std::endl;
|
//std::cout << "rvh->point() "<< rvh->point() << std::endl<< std::endl;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
switch ( orient ) {
|
switch ( orient ) {
|
||||||
case CGAL::COUNTERCLOCKWISE:
|
case CGAL::COUNTERCLOCKWISE:
|
||||||
// looking on to the right edge
|
// looking on to the right edge
|
||||||
if(p_cdt->is_constrained(re)){
|
if(p_cdt->is_constrained(re)) {
|
||||||
if(vh!=rvh){
|
if(vh != rvh) {
|
||||||
Point_2 p = ray_seg_intersection(q,vh->point(),nvh->point(),rvh->point());
|
Point_2 p = ray_seg_intersection(q, vh->point(),
|
||||||
|
nvh->point(), rvh->point());
|
||||||
//std::cout << vh->point() <<" -1- "<< p <<std::endl;
|
//std::cout << vh->point() <<" -1- "<< p <<std::endl;
|
||||||
needles.push_back(Segment_2(vh->point(),p));
|
needles.push_back(Segment_2(vh->point(),p));
|
||||||
}
|
}
|
||||||
}else{
|
} else {
|
||||||
collect_needle(q,vh,nfh,rindex);
|
collect_needle(q,vh,nfh,rindex);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case CGAL::CLOCKWISE:
|
case CGAL::CLOCKWISE:
|
||||||
// looking on to the left edge
|
// looking on to the left edge
|
||||||
if(p_cdt->is_constrained(le)){
|
if(p_cdt->is_constrained(le)){
|
||||||
if(vh!=lvh){
|
if(vh != lvh){
|
||||||
Point_2 p = ray_seg_intersection(q,vh->point(),nvh->point(),lvh->point());
|
Point_2 p = ray_seg_intersection(q, vh->point(),
|
||||||
|
nvh->point(), lvh->point());
|
||||||
//std::cout << vh->point() <<" -2- "<< p <<std::endl;
|
//std::cout << vh->point() <<" -2- "<< p <<std::endl;
|
||||||
needles.push_back(Segment_2(vh->point(),p));
|
needles.push_back(Segment_2(vh->point(),p));
|
||||||
}
|
}
|
||||||
}else{
|
} else {
|
||||||
collect_needle(q,vh,nfh,lindex);
|
collect_needle(q,vh,nfh,lindex);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
@ -203,15 +484,16 @@ public:
|
||||||
needles.push_back(Segment_2(vh->point(),nvh->point()));
|
needles.push_back(Segment_2(vh->point(),nvh->point()));
|
||||||
}
|
}
|
||||||
// but we may also contiue looking along the vertex
|
// but we may also contiue looking along the vertex
|
||||||
if(!p_cdt->is_constrained(re)){
|
if(!p_cdt->is_constrained(re)) {
|
||||||
collect_needle(q,nvh,nfh,rindex);
|
collect_needle(q,nvh,nfh,rindex);
|
||||||
}
|
}
|
||||||
if(!p_cdt->is_constrained(le)){
|
if(!p_cdt->is_constrained(le)) {
|
||||||
collect_needle(q,nvh,nfh,lindex);
|
collect_needle(q,nvh,nfh,lindex);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
template<class OIT>
|
template<class OIT>
|
||||||
OIT expand_edge(
|
OIT expand_edge(
|
||||||
const Point_2& q,
|
const Point_2& q,
|
||||||
|
|
@ -219,7 +501,8 @@ public:
|
||||||
const Point_2& right,
|
const Point_2& right,
|
||||||
typename CDT::Face_handle fh,
|
typename CDT::Face_handle fh,
|
||||||
int index,
|
int index,
|
||||||
OIT oit){
|
OIT oit)
|
||||||
|
const {
|
||||||
|
|
||||||
// the expanded edge should not be constrained
|
// the expanded edge should not be constrained
|
||||||
assert(!p_cdt->is_constrained(get_edge(fh,index)));
|
assert(!p_cdt->is_constrained(get_edge(fh,index)));
|
||||||
|
|
@ -252,12 +535,13 @@ public:
|
||||||
CGAL::Orientation ro = orientation(q,right,nvh->point());
|
CGAL::Orientation ro = orientation(q,right,nvh->point());
|
||||||
CGAL::Orientation lo = orientation(q,left ,nvh->point());
|
CGAL::Orientation lo = orientation(q,left ,nvh->point());
|
||||||
|
|
||||||
assert(typename K::Orientation_2()(q,left ,lvh->point()) != CGAL::CLOCKWISE);
|
assert(typename K::Orientation_2()(q,left ,lvh->point())
|
||||||
assert(typename K::Orientation_2()(q,right,rvh->point()) != CGAL::COUNTERCLOCKWISE);
|
!= CGAL::CLOCKWISE);
|
||||||
|
assert(typename K::Orientation_2()(q,right,rvh->point())
|
||||||
|
!= CGAL::COUNTERCLOCKWISE);
|
||||||
|
|
||||||
//std::cout << (ro == CGAL::COUNTERCLOCKWISE) << " " << (lo == CGAL::CLOCKWISE) << std::endl;
|
//std::cout << (ro == CGAL::COUNTERCLOCKWISE) << " " <<
|
||||||
|
//(lo == CGAL::CLOCKWISE) << std::endl;
|
||||||
|
|
||||||
|
|
||||||
//right edge is seen if new vertex is counter clockwise of right boarder
|
//right edge is seen if new vertex is counter clockwise of right boarder
|
||||||
if(ro == CGAL::COUNTERCLOCKWISE){
|
if(ro == CGAL::COUNTERCLOCKWISE){
|
||||||
|
|
@ -306,9 +590,12 @@ public:
|
||||||
if(!Regularization_category::value){
|
if(!Regularization_category::value){
|
||||||
assert(!(ro == CGAL::COLLINEAR && lo == CGAL::COLLINEAR));
|
assert(!(ro == CGAL::COLLINEAR && lo == CGAL::COLLINEAR));
|
||||||
// we have to check whether a needle starts here.
|
// we have to check whether a needle starts here.
|
||||||
if(p_cdt->is_constrained(le) && !p_cdt->is_constrained(re) && ro == CGAL::COLLINEAR)
|
if(p_cdt->is_constrained(le) && !p_cdt->is_constrained(re)
|
||||||
collect_needle(q,nvh,nfh,rindex);
|
&& ro == CGAL::COLLINEAR)
|
||||||
if(p_cdt->is_constrained(re) && !p_cdt->is_constrained(le) && lo == CGAL::COLLINEAR)
|
collect_needle(q,nvh,nfh,rindex);
|
||||||
|
|
||||||
|
if(p_cdt->is_constrained(re) && !p_cdt->is_constrained(le)
|
||||||
|
&& lo == CGAL::COLLINEAR)
|
||||||
collect_needle(q,nvh,nfh,lindex);
|
collect_needle(q,nvh,nfh,lindex);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -347,207 +634,49 @@ public:
|
||||||
return oit;
|
return oit;
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename VARR>
|
|
||||||
typename VARR::Face_handle
|
|
||||||
compute_visibility(const Point_2& q,
|
|
||||||
const Face_const_handle face,
|
|
||||||
VARR& out_arr
|
|
||||||
){
|
|
||||||
//std::cout << "query in face interior" << std::endl;
|
|
||||||
|
|
||||||
out_arr.clear();
|
|
||||||
needles.clear();
|
|
||||||
assert(!face->is_unbounded());
|
|
||||||
|
|
||||||
|
|
||||||
std::vector<Point_2> raw_output;
|
|
||||||
typename CDT::Face_handle fh = p_cdt->locate(q);
|
|
||||||
|
|
||||||
raw_output.push_back(fh->vertex(1)->point());
|
|
||||||
if(!p_cdt->is_constrained(get_edge(fh,0))){
|
|
||||||
//std::cout<< "edge 0 is not constrained" << std::endl;
|
|
||||||
expand_edge(
|
|
||||||
q,
|
|
||||||
fh->vertex(2)->point(),
|
|
||||||
fh->vertex(1)->point(),
|
|
||||||
fh,0,std::back_inserter(raw_output));
|
|
||||||
}
|
|
||||||
|
|
||||||
raw_output.push_back(fh->vertex(2)->point());
|
|
||||||
if(!p_cdt->is_constrained(get_edge(fh,1))){
|
|
||||||
//std::cout << "edge 1 is not constrained" << std::endl;
|
|
||||||
expand_edge(
|
|
||||||
q,
|
|
||||||
fh->vertex(0)->point(),
|
|
||||||
fh->vertex(2)->point(),
|
|
||||||
fh,1,std::back_inserter(raw_output));
|
|
||||||
}
|
|
||||||
|
|
||||||
raw_output.push_back(fh->vertex(0)->point());
|
|
||||||
if(!p_cdt->is_constrained(get_edge(fh,2))){
|
|
||||||
//std::cout << "edge 2 is not constrained" << std::endl;
|
|
||||||
expand_edge(
|
|
||||||
q,
|
|
||||||
fh->vertex(1)->point(),
|
|
||||||
fh->vertex(0)->point(),
|
|
||||||
fh,2,std::back_inserter(raw_output));
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
return output(raw_output,out_arr);
|
|
||||||
}
|
|
||||||
|
|
||||||
template <typename VARR>
|
template <typename VARR>
|
||||||
typename VARR::Face_handle
|
typename VARR::Face_handle
|
||||||
compute_visibility(const Point_2& q,
|
output(std::vector<Point_2>& raw_output, VARR& out_arr) const {
|
||||||
const Halfedge_const_handle he,
|
|
||||||
VARR& out_arr) {
|
|
||||||
//std::cout << "visibility_region he" << std::endl;
|
|
||||||
|
|
||||||
assert(!he->face()->is_unbounded());
|
|
||||||
out_arr.clear();
|
|
||||||
needles.clear();
|
|
||||||
|
|
||||||
std::vector<Point_2> raw_output;
|
if(!needles.empty()){
|
||||||
typename CDT::Locate_type location;
|
|
||||||
int index;
|
|
||||||
typename CDT::Face_handle fh = p_cdt->locate(q,location,index);
|
|
||||||
assert(location == CDT::EDGE || location == CDT::VERTEX);
|
|
||||||
// the following code tries to figure out which triangle one should start in.
|
|
||||||
|
|
||||||
|
|
||||||
if(location == CDT::EDGE){
|
|
||||||
//std::cout << "query on edge" << std::endl;
|
|
||||||
// this is the easy part, there are only two possible faces
|
|
||||||
// index indicates the edge = vertex on the other side of the edge
|
|
||||||
// the next vertex in cw order should be the target of given edge
|
|
||||||
if(fh->vertex(p_cdt->cw(index))->point() != he->target()->point()){
|
|
||||||
//std::cout << "need to swap face" << std::endl;
|
|
||||||
// take face on the other side if this is not the case
|
|
||||||
typename CDT::Face_handle nfh = fh->neighbor(index);
|
|
||||||
index = nfh->index(fh);
|
|
||||||
fh = nfh;
|
|
||||||
}
|
|
||||||
assert(fh->vertex(p_cdt->cw(index))->point() == he->target()->point());
|
|
||||||
assert(!p_cdt->is_infinite(fh->vertex(index)));
|
|
||||||
|
|
||||||
|
|
||||||
// output the edge the query lies on
|
|
||||||
raw_output.push_back(he->source()->point());
|
|
||||||
raw_output.push_back(he->target()->point());
|
|
||||||
|
|
||||||
if(!p_cdt->is_constrained(get_edge(fh,p_cdt->ccw(index)))){
|
|
||||||
expand_edge(
|
|
||||||
q,
|
|
||||||
fh->vertex(index)->point(), //left
|
|
||||||
he->target()->point() , //right
|
|
||||||
fh,
|
|
||||||
p_cdt->ccw(index),
|
|
||||||
std::back_inserter(raw_output));
|
|
||||||
}
|
|
||||||
raw_output.push_back(fh->vertex(index)->point());
|
|
||||||
|
|
||||||
if(!p_cdt->is_constrained(get_edge(fh,p_cdt->cw(index)))){
|
|
||||||
expand_edge(
|
|
||||||
q,
|
|
||||||
he->source()->point() , //left
|
|
||||||
fh->vertex(index)->point(), //right
|
|
||||||
fh,
|
|
||||||
p_cdt->cw(index),
|
|
||||||
std::back_inserter(raw_output));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if(location == CDT::VERTEX){
|
|
||||||
//std::cout << "query on vertex" << std::endl;
|
|
||||||
|
|
||||||
//bool query_point_on_vertex_is_not_working_yet = false;
|
|
||||||
//assert(query_point_on_vertex_is_not_working_yet);
|
|
||||||
|
|
||||||
assert(q == he->target()->point());
|
|
||||||
assert(fh->vertex(index)->point() == he->target()->point());
|
|
||||||
|
|
||||||
// push points that are seen anyway
|
|
||||||
// raw_output.push_back(he->source()->point()); inserted last
|
|
||||||
raw_output.push_back(he->target()->point());
|
|
||||||
raw_output.push_back(he->next()->target()->point());
|
|
||||||
|
|
||||||
// now start in the triangle that contains he->next()
|
|
||||||
while(
|
|
||||||
p_cdt->is_infinite(fh->vertex(p_cdt->ccw(index))) ||
|
|
||||||
he->next()->target()->point() != fh->vertex(p_cdt->ccw(index))->point()){
|
|
||||||
typename CDT::Face_handle nfh = fh->neighbor(p_cdt->ccw(index));
|
|
||||||
int nindex = nfh->index(fh);
|
|
||||||
index = p_cdt->ccw(nindex);
|
|
||||||
fh = nfh;
|
|
||||||
assert(he->target()->point() == fh->vertex(index)->point());
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
assert(he->next()->source()->point() == fh->vertex(index)->point());
|
|
||||||
assert(he->next()->target()->point() == fh->vertex(p_cdt->ccw(index))->point());
|
|
||||||
assert(!p_cdt->is_infinite(fh));
|
|
||||||
assert(p_cdt->is_constrained(get_edge(fh,p_cdt->cw(index))));
|
|
||||||
|
|
||||||
while(he->source()->point() != fh->vertex(p_cdt->ccw(index))->point()){
|
|
||||||
|
|
||||||
if(!p_cdt->is_constrained(get_edge(fh,index))){
|
|
||||||
expand_edge(
|
|
||||||
q,
|
|
||||||
fh->vertex(p_cdt-> cw(index))->point(), //left
|
|
||||||
fh->vertex(p_cdt->ccw(index))->point(), //right
|
|
||||||
fh,
|
|
||||||
index,
|
|
||||||
std::back_inserter(raw_output));
|
|
||||||
}
|
|
||||||
// push left end point of edge into output
|
|
||||||
raw_output.push_back(fh->vertex(p_cdt-> cw(index))->point());
|
|
||||||
|
|
||||||
// take the next triangle around q in ccw order
|
|
||||||
typename CDT::Face_handle nfh = fh->neighbor(p_cdt->ccw(index));
|
|
||||||
int nindex = nfh->index(fh);
|
|
||||||
index = p_cdt->ccw(nindex);
|
|
||||||
fh = nfh;
|
|
||||||
assert(fh->vertex(index)->point() == he->target()->point());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return output(raw_output,out_arr);
|
|
||||||
}
|
|
||||||
|
|
||||||
template <typename VARR>
|
|
||||||
typename VARR::Face_handle
|
|
||||||
output(std::vector<Point_2>& raw_output, VARR& out_arr){
|
|
||||||
|
|
||||||
if(needles.size()>0){
|
|
||||||
std::vector<Segment_2> segments(needles.begin(),needles.end());
|
std::vector<Segment_2> segments(needles.begin(),needles.end());
|
||||||
for(unsigned int i = 0; i <raw_output.size();i++){
|
for(unsigned int i = 0; i < raw_output.size(); i++){
|
||||||
// //std::cout << raw_output[i] << " -- "
|
// //std::cout << raw_output[i] << " -- "
|
||||||
// << raw_output[(i+1)%raw_output.size()] << std::endl;
|
// << raw_output[(i+1)%raw_output.size()] << std::endl;
|
||||||
segments.push_back(Segment_2(raw_output[i],raw_output[(i+1)%raw_output.size()]));
|
segments.push_back(Segment_2(raw_output[i],
|
||||||
|
raw_output[(i+1) % raw_output.size()]));
|
||||||
}
|
}
|
||||||
|
|
||||||
CGAL::insert_non_intersecting_curves(out_arr,segments.begin(),segments.end());
|
CGAL::insert_non_intersecting_curves(out_arr,
|
||||||
//CGAL::insert(out_arr,segments.begin(),segments.end());
|
segments.begin(),
|
||||||
}else{
|
segments.end());
|
||||||
|
|
||||||
|
} else {
|
||||||
typename VARR::Vertex_handle v_last, v_first;
|
typename VARR::Vertex_handle v_last, v_first;
|
||||||
v_last = v_first =
|
v_last = v_first =
|
||||||
out_arr.insert_in_face_interior(raw_output[0], out_arr.unbounded_face());
|
out_arr.insert_in_face_interior(raw_output[0],out_arr.unbounded_face());
|
||||||
|
|
||||||
for(unsigned int i = 0; i <raw_output.size()-1;i++){
|
for(unsigned int i = 0; i < raw_output.size()-1; i++){
|
||||||
// //std::cout << raw_output[i] << " -- "
|
// std::cout << raw_output[i] << " -- "
|
||||||
// << raw_output[(i+1)%raw_output.size()] << std::endl;
|
// << raw_output[(i+1)%raw_output.size()] << std::endl;
|
||||||
if(raw_output[i]<raw_output[(i+1)]){
|
if(raw_output[i] < raw_output[(i+1)]){
|
||||||
v_last = out_arr.insert_from_left_vertex (Segment_2(raw_output[i], raw_output[i+1]), v_last)->target();
|
v_last = out_arr.insert_from_left_vertex (
|
||||||
}else{
|
Segment_2(raw_output[i], raw_output[i+1]), v_last
|
||||||
v_last = out_arr.insert_from_right_vertex(Segment_2(raw_output[i], raw_output[i+1]), v_last)->target();
|
)->target();
|
||||||
|
} else {
|
||||||
|
v_last = out_arr.insert_from_right_vertex(
|
||||||
|
Segment_2(raw_output[i], raw_output[i+1]), v_last
|
||||||
|
)->target();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
out_arr.insert_at_vertices(Segment_2(raw_output.front(),raw_output.back()),v_last,v_first);
|
out_arr.insert_at_vertices(
|
||||||
|
Segment_2(raw_output.front(), raw_output.back()),
|
||||||
|
v_last, v_first
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
assert(out_arr.number_of_faces()== 2);
|
assert(out_arr.number_of_faces() == 2);
|
||||||
|
|
||||||
if(out_arr.faces_begin()->is_unbounded())
|
if(out_arr.faces_begin()->is_unbounded())
|
||||||
return ++out_arr.faces_begin();
|
return ++out_arr.faces_begin();
|
||||||
|
|
@ -555,20 +684,22 @@ public:
|
||||||
return out_arr.faces_begin();
|
return out_arr.faces_begin();
|
||||||
}
|
}
|
||||||
|
|
||||||
void init_cdt(){
|
void init_cdt() const {
|
||||||
//std::cout<< "==============" <<std::endl;
|
//std::cout<< "==============" <<std::endl;
|
||||||
//std::cout<< "Input Polygon:" <<std::endl;
|
//std::cout<< "Input Polygon:" <<std::endl;
|
||||||
//todo, avoid copy by using modified iterator
|
|
||||||
std::vector<std::pair<Point_2,Point_2> > constraints;
|
typedef typename boost::transform_iterator<Make_constraint,
|
||||||
for(typename Arrangement_2::Edge_const_iterator eit = p_arr->edges_begin();
|
Edge_const_iterator> Iter;
|
||||||
eit != p_arr->edges_end(); eit++){
|
|
||||||
Point_2 source = eit->source()->point();
|
Iter begin = boost::make_transform_iterator(p_arr->edges_begin(),
|
||||||
Point_2 target = eit->target()->point();
|
Make_constraint());
|
||||||
//std::cout << source << " -- " << target << std::endl;
|
|
||||||
constraints.push_back(std::make_pair(source,target));
|
Iter end = boost::make_transform_iterator(p_arr->edges_end(),
|
||||||
}
|
Make_constraint());
|
||||||
|
|
||||||
//std::cout << "init_cdt new CDT" << std::endl;
|
//std::cout << "init_cdt new CDT" << std::endl;
|
||||||
p_cdt = boost::shared_ptr<CDT>(new CDT(constraints.begin(),constraints.end()));
|
p_cdt = boost::shared_ptr<CDT>(new CDT(begin, end));
|
||||||
|
observer.has_changed = false;
|
||||||
//std::cout << "init_cdt done" << std::endl;
|
//std::cout << "init_cdt done" << std::endl;
|
||||||
//std::cout << std::endl;
|
//std::cout << std::endl;
|
||||||
}
|
}
|
||||||
|
|
@ -576,4 +707,4 @@ public:
|
||||||
|
|
||||||
} // namespace CGAL
|
} // namespace CGAL
|
||||||
|
|
||||||
#endif //CGAL_TRIANGULAR_EXPANSION_VISIBILITY_2__H
|
#endif // CGAL_TRIANGULAR_EXPANSION_VISIBILITY_2_H
|
||||||
|
|
|
||||||
|
|
@ -333,7 +333,7 @@ bool is_regular_arr(Arrangement_2& arr){
|
||||||
|
|
||||||
|
|
||||||
template <class Visibility_2, class Visibility_arrangement_2>
|
template <class Visibility_2, class Visibility_arrangement_2>
|
||||||
bool run_test_case_from_file(Visibility_2 visibility, std::ifstream &input) {
|
bool run_test_case_from_file(Visibility_2& visibility, std::ifstream &input) {
|
||||||
typedef typename Visibility_2::Arrangement_2 Arrangement_2;
|
typedef typename Visibility_2::Arrangement_2 Arrangement_2;
|
||||||
typedef typename Arrangement_2::Geometry_traits_2 Geometry_traits_2;
|
typedef typename Arrangement_2::Geometry_traits_2 Geometry_traits_2;
|
||||||
typedef typename Geometry_traits_2::Point_2 Point_2;
|
typedef typename Geometry_traits_2::Point_2 Point_2;
|
||||||
|
|
@ -422,8 +422,178 @@ bool run_test_case_from_file(Visibility_2 visibility, std::ifstream &input) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template <class Visibility_2>
|
||||||
|
void test_interface() {
|
||||||
|
typedef typename Visibility_2::Arrangement_2 Arrangement_2;
|
||||||
|
typedef typename Arrangement_2::Geometry_traits_2 Geometry_traits_2;
|
||||||
|
typedef typename Arrangement_2::Face_const_handle Face_const_handle;
|
||||||
|
typedef typename Arrangement_2::Halfedge_const_handle Halfedge_const_handle;
|
||||||
|
typedef typename Geometry_traits_2::Segment_2 Segment_2;
|
||||||
|
typedef typename Geometry_traits_2::Point_2 Point_2;
|
||||||
|
|
||||||
|
Point_2 query(0.1, 0.1);
|
||||||
|
|
||||||
|
std::vector<Point_2> vertices;
|
||||||
|
vertices.push_back(Point_2(0, 0));
|
||||||
|
vertices.push_back(Point_2(1, 0));
|
||||||
|
vertices.push_back(Point_2(1, 1));
|
||||||
|
vertices.push_back(Point_2(0, 1));
|
||||||
|
|
||||||
|
|
||||||
|
Arrangement_2 arr_out;
|
||||||
|
Arrangement_2 square;
|
||||||
|
|
||||||
|
for(unsigned int i = 0; i < vertices.size(); ++i) {
|
||||||
|
CGAL::insert(square, Segment_2(vertices[i],
|
||||||
|
vertices[(i+1) % vertices.size()]));
|
||||||
|
}
|
||||||
|
|
||||||
|
Face_const_handle location;
|
||||||
|
CGAL::assign(location, get_location(square, query));
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
const Arrangement_2& arr = square;
|
||||||
|
|
||||||
|
// Constructor and attach method must accept a const arrangement.
|
||||||
|
Visibility_2 visibility(arr);
|
||||||
|
|
||||||
|
visibility.detach();
|
||||||
|
visibility.attach(arr);
|
||||||
|
|
||||||
|
|
||||||
|
const Visibility_2& vis = visibility;
|
||||||
|
|
||||||
|
// compute_visibility must be const
|
||||||
|
vis.compute_visibility(query, location, arr_out);
|
||||||
|
|
||||||
|
Halfedge_const_handle he = arr.edges_begin();
|
||||||
|
|
||||||
|
if(he->face()->is_unbounded())
|
||||||
|
he = he->twin();
|
||||||
|
|
||||||
|
vis.compute_visibility(he->target()->point(), he, arr_out);
|
||||||
|
|
||||||
|
// must have const arrangement_2();
|
||||||
|
const Arrangement_2& a = vis.arrangement_2();
|
||||||
|
|
||||||
|
// must have const is_attached();
|
||||||
|
vis.is_attached();
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
template <class Visibility_2>
|
||||||
|
void run_tests_with_changes_to_arr() {
|
||||||
|
|
||||||
|
std::cout << "\tTesting changes to attached arrangement:";
|
||||||
|
|
||||||
|
typedef typename Visibility_2::Arrangement_2 Arrangement_2;
|
||||||
|
typedef typename Arrangement_2::Geometry_traits_2 Geometry_traits_2;
|
||||||
|
typedef typename Arrangement_2::Face_const_handle Face_const_handle;
|
||||||
|
typedef typename Geometry_traits_2::Segment_2 Segment_2;
|
||||||
|
typedef typename Geometry_traits_2::Point_2 Point_2;
|
||||||
|
typedef typename Geometry_traits_2::FT Number_type;
|
||||||
|
|
||||||
|
bool all_passed = true;
|
||||||
|
|
||||||
|
|
||||||
|
Point_2 query(0.1, 0.1);
|
||||||
|
|
||||||
|
std::vector<Point_2> vertices;
|
||||||
|
vertices.push_back(Point_2(0, 0));
|
||||||
|
vertices.push_back(Point_2(1, 0));
|
||||||
|
vertices.push_back(Point_2(1, 1));
|
||||||
|
vertices.push_back(Point_2(0, 1));
|
||||||
|
|
||||||
|
|
||||||
|
Arrangement_2 square;
|
||||||
|
for(unsigned int i = 0; i < vertices.size(); ++i) {
|
||||||
|
CGAL::insert(square, Segment_2(vertices[i],
|
||||||
|
vertices[(i+1) % vertices.size()]));
|
||||||
|
}
|
||||||
|
|
||||||
|
Arrangement_2 lower_tri;
|
||||||
|
CGAL::insert(lower_tri, Segment_2(vertices[0], vertices[1]));
|
||||||
|
CGAL::insert(lower_tri, Segment_2(vertices[1], vertices[3]));
|
||||||
|
CGAL::insert(lower_tri, Segment_2(vertices[3], vertices[0]));
|
||||||
|
|
||||||
|
Visibility_2 visibility;
|
||||||
|
Arrangement_2 arr;
|
||||||
|
Arrangement_2 arr_out;
|
||||||
|
|
||||||
|
// Attach empty arr and fill it afterwards
|
||||||
|
visibility.attach(arr);
|
||||||
|
|
||||||
|
|
||||||
|
for(unsigned int i = 0; i < vertices.size(); ++i) {
|
||||||
|
CGAL::insert(arr, Segment_2(vertices[i],
|
||||||
|
vertices[(i+1) % vertices.size()]));
|
||||||
|
}
|
||||||
|
|
||||||
|
Face_const_handle location;
|
||||||
|
CGAL::assign(location, get_location(arr, query));
|
||||||
|
|
||||||
|
visibility.compute_visibility(query, location, arr_out);
|
||||||
|
|
||||||
|
all_passed &= test_are_equal(arr_out, square);
|
||||||
|
|
||||||
|
|
||||||
|
// Change attached arrangement and query again
|
||||||
|
|
||||||
|
arr.clear();
|
||||||
|
|
||||||
|
CGAL::insert(arr, Segment_2(vertices[0], vertices[1]));
|
||||||
|
CGAL::insert(arr, Segment_2(vertices[1], vertices[3]));
|
||||||
|
CGAL::insert(arr, Segment_2(vertices[3], vertices[0]));
|
||||||
|
|
||||||
|
CGAL::assign(location, get_location(arr, query));
|
||||||
|
|
||||||
|
visibility.compute_visibility(query, location, arr_out);
|
||||||
|
|
||||||
|
all_passed &= test_are_equal(arr_out, lower_tri);
|
||||||
|
|
||||||
|
|
||||||
|
// Detach and attach again
|
||||||
|
|
||||||
|
visibility.detach();
|
||||||
|
visibility.attach(arr);
|
||||||
|
|
||||||
|
CGAL::assign(location, get_location(arr, query));
|
||||||
|
|
||||||
|
visibility.compute_visibility(query, location, arr_out);
|
||||||
|
|
||||||
|
all_passed &= test_are_equal(arr_out, lower_tri);
|
||||||
|
|
||||||
|
|
||||||
|
// Attach another arrangement without detaching the old one first.
|
||||||
|
|
||||||
|
visibility.attach(square);
|
||||||
|
|
||||||
|
CGAL::assign(location, get_location(square, query));
|
||||||
|
|
||||||
|
visibility.compute_visibility(query, location, arr_out);
|
||||||
|
|
||||||
|
all_passed &= test_are_equal(arr_out, square);
|
||||||
|
|
||||||
|
|
||||||
|
if (!all_passed) {
|
||||||
|
std::cout << "\tFailed: Modifying attached arrangment causes wrong output.\n";
|
||||||
|
assert(false);
|
||||||
|
} else {
|
||||||
|
std::cout << "\tPassed.\n" ;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
template <class Visibility_2, class Visibility_arrangement_2>
|
template <class Visibility_2, class Visibility_arrangement_2>
|
||||||
void run_tests(int case_number_simple, int case_number_non_simple) {
|
void run_tests(int case_number_simple, int case_number_non_simple) {
|
||||||
|
|
||||||
|
// Make sure the code only compiles with a conforming interface
|
||||||
|
test_interface<Visibility_2>();
|
||||||
|
|
||||||
|
|
||||||
Visibility_2 visibility;
|
Visibility_2 visibility;
|
||||||
bool one_failed = false;
|
bool one_failed = false;
|
||||||
|
|
@ -501,8 +671,12 @@ void run_tests(int case_number_simple, int case_number_non_simple) {
|
||||||
if (one_failed) {
|
if (one_failed) {
|
||||||
assert(false);
|
assert(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
run_tests_with_changes_to_arr<Visibility_2>();
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
template <class _Arrangement_2>
|
template <class _Arrangement_2>
|
||||||
void create_arrangement_from_file(_Arrangement_2 &arr, std::ifstream& input) {
|
void create_arrangement_from_file(_Arrangement_2 &arr, std::ifstream& input) {
|
||||||
typedef _Arrangement_2 Arrangement_2;
|
typedef _Arrangement_2 Arrangement_2;
|
||||||
|
|
@ -823,8 +997,8 @@ void simple_benchmark_one_unit(
|
||||||
typename Visibility_2_fst::Arrangement_2 &arr,
|
typename Visibility_2_fst::Arrangement_2 &arr,
|
||||||
const Query_choice &choice,
|
const Query_choice &choice,
|
||||||
typename Visibility_2_fst::Arrangement_2::Face_const_handle &fit,
|
typename Visibility_2_fst::Arrangement_2::Face_const_handle &fit,
|
||||||
Visibility_2_fst visibility_fst,
|
Visibility_2_fst& visibility_fst,
|
||||||
Visibility_2_snd visibility_snd,
|
Visibility_2_snd& visibility_snd,
|
||||||
double& qtime1,
|
double& qtime1,
|
||||||
double& qtime2,
|
double& qtime2,
|
||||||
int& query_cnt) {
|
int& query_cnt) {
|
||||||
|
|
@ -1033,7 +1207,7 @@ void pure_benchmark_one_unit(
|
||||||
typename Visibility_2::Arrangement_2 &arr,
|
typename Visibility_2::Arrangement_2 &arr,
|
||||||
const Query_choice &choice,
|
const Query_choice &choice,
|
||||||
typename Visibility_2::Arrangement_2::Face_const_handle &fit,
|
typename Visibility_2::Arrangement_2::Face_const_handle &fit,
|
||||||
Visibility_2 visibility,
|
Visibility_2& visibility,
|
||||||
double& qtime,
|
double& qtime,
|
||||||
int& query_cnt) {
|
int& query_cnt) {
|
||||||
|
|
||||||
|
|
@ -1215,7 +1389,7 @@ template<class Visibility_2>
|
||||||
void test_star_shape_one_face( typename Visibility_2::Arrangement_2 &arr,
|
void test_star_shape_one_face( typename Visibility_2::Arrangement_2 &arr,
|
||||||
const Query_choice &choice,
|
const Query_choice &choice,
|
||||||
typename Visibility_2::Arrangement_2::Face_const_handle &fit,
|
typename Visibility_2::Arrangement_2::Face_const_handle &fit,
|
||||||
Visibility_2 visibility)
|
Visibility_2& visibility)
|
||||||
{
|
{
|
||||||
|
|
||||||
typedef typename Visibility_2::Arrangement_2 Arrangement_2;
|
typedef typename Visibility_2::Arrangement_2 Arrangement_2;
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue