Fixed performance bug.

This commit is contained in:
Andreas Haas 2015-05-18 15:16:44 +02:00
parent a4f7e1bd3f
commit ee343b0800
1 changed files with 53 additions and 74 deletions

View File

@ -26,14 +26,12 @@
#include <CGAL/tags.h> #include <CGAL/tags.h>
#include <CGAL/enum.h> #include <CGAL/enum.h>
#include <CGAL/Visibility_2/visibility_utils.h> #include <CGAL/Visibility_2/visibility_utils.h>
#include <CGAL/Constrained_Delaunay_triangulation_2.h>
#include <CGAL/Arrangement_2.h> #include <CGAL/Arrangement_2.h>
#include <CGAL/Arr_walk_along_line_point_location.h>
#include <CGAL/assertions.h> #include <CGAL/assertions.h>
#include <stack> #include <stack>
#include <map>
// TODO: // TODO:
// * rm DT = O(n^2)
// * fix handle needles = O(nlogn) // * fix handle needles = O(nlogn)
namespace CGAL { namespace CGAL {
@ -49,6 +47,7 @@ public:
typedef typename K::Intersect_2 Intersect_2; typedef typename K::Intersect_2 Intersect_2;
typedef typename Arrangement_2::Vertex_const_handle Vertex_const_handle;
typedef typename Arrangement_2::Halfedge_const_handle typedef typename Arrangement_2::Halfedge_const_handle
Halfedge_const_handle; Halfedge_const_handle;
typedef typename Arrangement_2::Halfedge_handle Halfedge_handle; typedef typename Arrangement_2::Halfedge_handle Halfedge_handle;
@ -63,9 +62,6 @@ public:
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;
typedef typename Geometry_traits_2::Vector_2 Vector_2;
typedef typename Geometry_traits_2::Direction_2 Direction_2;
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;
@ -78,8 +74,10 @@ public:
Simple_polygon_visibility_2(const Arrangement_2& arr): Simple_polygon_visibility_2(const Arrangement_2& arr):
p_arr(&arr) { p_arr(&arr) {
traits = p_arr->geometry_traits(); traits = p_arr->geometry_traits();
point_location.attach(arr);
query_pt_is_vertex = false; query_pt_is_vertex = false;
query_pt_is_on_halfedge = false; query_pt_is_on_halfedge = false;
inserted_artificial_starting_vertex = false;
} }
@ -97,18 +95,20 @@ public:
detach(); detach();
p_arr = &arr; p_arr = &arr;
traits = p_arr->geometry_traits(); traits = p_arr->geometry_traits();
point_location.attach(arr);
} }
} }
/*! Detaches the visibility object from the arrangement it is /*! Detaches the visibility object from the arrangement it is
attached to*/ attached to*/
void detach() { void detach() {
point_location.detach();
p_arr = NULL; p_arr = NULL;
traits = NULL; traits = NULL;
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.reset(); inserted_artificial_starting_vertex = false;
} }
/*! Getter method for the input arrangement*/ /*! Getter method for the input arrangement*/
@ -131,6 +131,7 @@ public:
query_pt_is_vertex = false; query_pt_is_vertex = false;
query_pt_is_on_halfedge = false; query_pt_is_on_halfedge = false;
inserted_artificial_starting_vertex = 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);
@ -197,11 +198,8 @@ public:
} }
private: private:
typedef CGAL::Triangulation_vertex_base_2<K> Vb; typedef Arr_walk_along_line_point_location<Arrangement_2> Arr_point_location;
typedef CGAL::Constrained_triangulation_face_base_2<K> Fb; typedef typename Arr_point_location::result_type Location_result;
typedef CGAL::Triangulation_data_structure_2<Vb,Fb> TDS;
typedef CGAL::No_intersection_tag Itag;
typedef CGAL::Constrained_triangulation_2<K, TDS, Itag> CDT;
typedef std::vector<Point_2> Vertex_container; typedef std::vector<Point_2> Vertex_container;
typedef typename Vertex_container::size_type Size_type; typedef typename Vertex_container::size_type Size_type;
@ -209,11 +207,8 @@ private:
const Arrangement_2 *p_arr; const Arrangement_2 *p_arr;
const Geometry_traits_2 *traits; const Geometry_traits_2 *traits;
/*! Boost pointer to the constrained Delaunay triangulation object*/ mutable Arr_point_location point_location;
mutable boost::shared_ptr<CDT> p_cdt;
/*! Mapping of the vertices of the input to the corresponding circulator
needed for finding the first visible vertex in case of face queries*/
mutable std::map<Point_2, Ccb_halfedge_const_circulator> point_itr_map;
/*! 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*/
@ -224,46 +219,30 @@ private:
mutable enum {LEFT, RIGHT, SCANA, SCANB, SCANC, SCAND, FINISH} upcase; mutable enum {LEFT, RIGHT, SCANA, SCANB, SCANC, SCAND, FINISH} upcase;
mutable bool query_pt_is_vertex; mutable bool query_pt_is_vertex;
mutable bool query_pt_is_on_halfedge; mutable bool query_pt_is_on_halfedge;
mutable bool inserted_artificial_starting_vertex;
/*! Initialized the constrained Delaunay triangulation using the edges of
the outer boundary of 'face' */
void init_cdt(const Face_const_handle &face) const {
point_itr_map.clear();
std::vector<std::pair<Point_2,Point_2> > constraints;
Ccb_halfedge_const_circulator circ = face->outer_ccb();
Ccb_halfedge_const_circulator curr = circ;
do {
const Point_2& source = curr->source()->point();
const Point_2& target = curr->target()->point();
point_itr_map.insert(std::make_pair(source, curr));
constraints.push_back(std::make_pair(source, target));
} while(++curr != circ);
p_cdt = boost::shared_ptr<CDT>(new CDT(constraints.begin(),
constraints.end()));
}
template <typename VARR> template <typename VARR>
typename VARR::Face_handle typename VARR::Face_handle
output(const Point_2& q, VARR& out_arr) const { output(const Point_2& q, VARR& out_arr) const {
if(inserted_artificial_starting_vertex)
stack.pop();
std::vector<Point_2> points; std::vector<Point_2> points;
while(!stack.empty()) { while(!stack.empty()) {
const Point_2& top = stack.top(); const Point_2& top = stack.top();
if (top != q) { if (top != q || query_pt_is_vertex) {
points.push_back(top); points.push_back(top);
}
else if (query_pt_is_vertex) {
points.push_back(top);
} }
stack.pop(); stack.pop();
} }
if(inserted_artificial_starting_vertex) {
points.back() = points[0];
inserted_artificial_starting_vertex = false;
}
// Quick fix for now. Can be done faster. // Quick fix for now. Can be done faster.
std::vector<Segment_2> segments; std::vector<Segment_2> segments;
@ -298,41 +277,41 @@ private:
/*! 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, Ccb_halfedge_const_circulator find_visible_start(Face_const_handle face,
const Point_2 &q) const { const Point_2 &q) const
init_cdt(face); {
typename CDT::Face_handle fh = p_cdt->locate(q); Location_result result = point_location.ray_shoot_up(q);
const Point_2& start_point = fh->vertex(0)->point();
// Now retrieve the circulator to first visible vertex from triangulation if(const Halfedge_const_handle* e =
Ccb_halfedge_const_circulator circ = point_itr_map[start_point]; boost::get<Halfedge_const_handle>(&(result)))
{
CGAL_assertion((*e)->face() == face);
Point_2 p(q.x(),
traits->compute_y_at_x_2_object()(
Line_2((*e)->source()->point(),
(*e)->target()->point()) ,
q.x()));
Halfedge_around_vertex_const_circulator incident_circ = vertices.push_back(p);
circ->source()->incident_halfedges(); inserted_artificial_starting_vertex = true;
Halfedge_around_vertex_const_circulator incident_curr = incident_circ;
Ccb_halfedge_const_circulator incident_next; return (*e)->next()->ccb();
do {
if (incident_curr->face() == face) {
incident_next = incident_curr;
++incident_next;
if (traits->orientation_2_object()(
incident_curr->source()->point(),
incident_curr->target()->point(),
q) == LEFT_TURN
|| traits->orientation_2_object()(
incident_next->source()->point(),
incident_next->target()->point(),
q) == LEFT_TURN)
{
break;
}
} }
} while (++incident_curr != incident_circ); else if (const Vertex_const_handle* v =
boost::get<Vertex_const_handle>(&(result)))
{
Halfedge_around_vertex_const_circulator cir =
(*v)->incident_halfedges();
return incident_next; while(face != cir->face()) {
++cir;
}
return cir->next()->ccb();
}
else
{
CGAL_assertion_msg(false, "Should not be reachable.");
return Ccb_halfedge_const_circulator();
}
} }