Merge branch 'gsoc2013-Visibility_doc-hemmer' of github.com:CGAL/cgal-dev into gsoc2013-Visibility_doc-hemmer

This commit is contained in:
Michael Hemmer 2015-06-16 13:35:27 +02:00
commit e3f0b0137c
3 changed files with 104 additions and 211 deletions

View File

@ -26,6 +26,7 @@
#include <CGAL/Arrangement_2.h>
#include <CGAL/bounding_box.h>
#include <boost/unordered_map.hpp>
#include <iterator>
namespace CGAL {
@ -362,8 +363,11 @@ public:
}
}
typename Points::iterator first = polygon.begin() + small_idx;
typename Points::iterator last = polygon.begin() + big_idx;
typename Points::iterator first = polygon.begin();
std::advance(first, small_idx);
typename Points::iterator last = polygon.begin();
std::advance(last, big_idx);
if (is_between) {
Points polygon_out(first, last+1);
if (is_vertex_query)
@ -451,16 +455,16 @@ private:
}
//arrange vertices that on a same vision ray in a 'funnel' order
void funnel(int i, int j) const {
void funnel(typename VHs::size_type i, typename VHs::size_type j) const {
VHs right, left;
//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);
VH former = vs[i], nb;
for (int l=i; l<j; l++) {
for (typename VHs::size_type l=i; l<j; l++) {
bool left_v(false), right_v(false), has_predecessor(false);
EHs& edges = incident_edges[vs[l]];
for (int k=0; k<edges.size(); k++) {
for (typename EHs::size_type k=0; k<edges.size(); k++) {
nb = get_neighbor(edges[k], vs[l]);
if ( nb == former ) {
has_predecessor = true;
@ -495,9 +499,9 @@ private:
}
former = vs[l];
}
for (int l=0; l!=right.size(); l++)
for (typename VHs::size_type l=0; l!=right.size(); l++)
vs[i+l] = right[l];
for (int l=0; l!=left.size(); l++)
for (typename VHs::size_type l=0; l!=left.size(); l++)
vs[i+l+right.size()] = left[left.size()-1-l];
}
@ -553,7 +557,7 @@ private:
}
}
else {
for (int i=0; i!=relevant_edges.size(); i++)
for (typename EHs::size_type i=0; i!=relevant_edges.size(); i++)
if (do_intersect_ray(q, dp, relevant_edges[i]->source()->point(),
relevant_edges[i]->target()->point()))
active_edges.insert(relevant_edges[i]);
@ -561,12 +565,12 @@ private:
//angular sweep begins
// std::cout<<active_edges.size()<<std::endl;
for (int i=0; i!=vs.size(); i++) {
for (typename VHs::size_type i=0; i!=vs.size(); i++) {
VH vh = vs[i];
EH closest_e = *active_edges.begin();
EHs& edges = incident_edges[vh];
EHs insert_ehs, remove_ehs;
for (int j=0; j!=edges.size(); j++) {
for (typename EHs::size_type j=0; j!=edges.size(); j++) {
EH& e = edges[j];
if (active_edges.find(e) == active_edges.end())
insert_ehs.push_back(e);
@ -780,7 +784,7 @@ private:
//for vertex and edge query: the visibility is limited in a cone.
void input_edge(const Halfedge_const_handle e,
EHs& good_edges) const {
for (int i=0; i<bad_edges.size(); i++)
for (typename EHs::size_type i = 0; i < bad_edges.size(); i++)
if (e == bad_edges[i])
return;
VH v1 = e->target();
@ -822,8 +826,8 @@ private:
std::sort(vs.begin(), vs.end(), Is_swept_earlier(q, geom_traits));
for (int i=0; i!=vs.size(); i++) {
int j = i+1;
for (typename VHs::size_type i=0; i!=vs.size(); i++) {
typename VHs::size_type j = i+1;
while (j != vs.size()) {
if (!CGAL::collinear(q, vs[i]->point(), vs[j]->point()))
break;
@ -860,7 +864,7 @@ private:
//the vision ray will always intersect at least an edge.
//this box doesn't intersect any relevant_edge.
Points points;
for (int i=0; i<vs.size(); i++) {
for (typename VHs::size_type i=0; i<vs.size(); i++) {
points.push_back(vs[i]->point());
}
points.push_back(q);
@ -877,10 +881,10 @@ private:
//make the box a little bigger than bb so that it won't intersect any
//relevant_edge.
xmin = compute_x(bb.min())-1;
ymin = compute_y(bb.min())-1;
xmax = compute_x(bb.max())+1;
ymax = compute_y(bb.max())+1;
xmin = compute_x((bb.min)())-1;
ymin = compute_y((bb.min)())-1;
xmax = compute_x((bb.max)())+1;
ymax = compute_y((bb.max)())+1;
Point_2 box[4] = {Point_2(xmin, ymin), Point_2(xmax, ymin),
Point_2(xmax, ymax), Point_2(xmin, ymax)};
@ -907,8 +911,8 @@ private:
std::sort(vs.begin(), vs.end(), Is_swept_earlier(q, geom_traits));
for (int i=0; i!=vs.size(); i++) {
int j = i+1;
for (typename VHs::size_type i=0; i!=vs.size(); i++) {
typename VHs::size_type j = i+1;
while (j != vs.size()) {
if (!CGAL::collinear(q, vs[i]->point(), vs[j]->point()))
break;

View File

@ -26,14 +26,12 @@
#include <CGAL/tags.h>
#include <CGAL/enum.h>
#include <CGAL/Visibility_2/visibility_utils.h>
#include <CGAL/Constrained_Delaunay_triangulation_2.h>
#include <CGAL/Arrangement_2.h>
#include <CGAL/Arr_walk_along_line_point_location.h>
#include <CGAL/assertions.h>
#include <stack>
#include <map>
// TODO:
// * rm DT = O(n^2)
// * fix handle needles = O(nlogn)
namespace CGAL {
@ -49,6 +47,7 @@ public:
typedef typename K::Intersect_2 Intersect_2;
typedef typename Arrangement_2::Vertex_const_handle Vertex_const_handle;
typedef typename Arrangement_2::Halfedge_const_handle
Halfedge_const_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::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::Direction_2 Direction_2;
typedef typename Geometry_traits_2::FT Number_type;
typedef typename Geometry_traits_2::Object_2 Object_2;
typedef RegularizationCategory Regularization_category;
@ -78,8 +74,10 @@ public:
Simple_polygon_visibility_2(const Arrangement_2& arr):
p_arr(&arr) {
traits = p_arr->geometry_traits();
point_location.attach(arr);
query_pt_is_vertex = false;
query_pt_is_on_halfedge = false;
inserted_artificial_starting_vertex = false;
}
@ -97,18 +95,20 @@ public:
detach();
p_arr = &arr;
traits = p_arr->geometry_traits();
point_location.attach(arr);
}
}
/*! Detaches the visibility object from the arrangement it is
attached to*/
void detach() {
point_location.detach();
p_arr = NULL;
traits = NULL;
vertices.clear();
query_pt_is_vertex = false;
query_pt_is_on_halfedge = false;
p_cdt.reset();
inserted_artificial_starting_vertex = false;
}
/*! Getter method for the input arrangement*/
@ -131,6 +131,7 @@ public:
query_pt_is_vertex = false;
query_pt_is_on_halfedge = false;
inserted_artificial_starting_vertex = false;
// Now retrieve the circulator to first visible vertex from triangulation
Ccb_halfedge_const_circulator circ = find_visible_start(face, q);
@ -197,11 +198,8 @@ public:
}
private:
typedef CGAL::Triangulation_vertex_base_2<K> Vb;
typedef CGAL::Constrained_triangulation_face_base_2<K> Fb;
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 Arr_walk_along_line_point_location<Arrangement_2> Arr_point_location;
typedef typename Arr_point_location::result_type Location_result;
typedef std::vector<Point_2> Vertex_container;
typedef typename Vertex_container::size_type Size_type;
@ -209,11 +207,8 @@ private:
const Arrangement_2 *p_arr;
const Geometry_traits_2 *traits;
/*! Boost pointer to the constrained Delaunay triangulation object*/
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;
mutable Arr_point_location point_location;
/*! Stack of visibile points; manipulated when going through the sequence
of input vertices; contains the vertices of the visibility region after
the run of the algorithm*/
@ -224,46 +219,30 @@ private:
mutable enum {LEFT, RIGHT, SCANA, SCANB, SCANC, SCAND, FINISH} upcase;
mutable bool query_pt_is_vertex;
mutable bool query_pt_is_on_halfedge;
/*! 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()));
}
mutable bool inserted_artificial_starting_vertex;
template <typename VARR>
typename VARR::Face_handle
output(const Point_2& q, VARR& out_arr) const {
if(inserted_artificial_starting_vertex)
stack.pop();
std::vector<Point_2> points;
while(!stack.empty()) {
const Point_2& top = stack.top();
if (top != q) {
points.push_back(top);
}
else if (query_pt_is_vertex) {
points.push_back(top);
if (top != q || query_pt_is_vertex) {
points.push_back(top);
}
stack.pop();
}
if(inserted_artificial_starting_vertex) {
points.back() = points[0];
inserted_artificial_starting_vertex = false;
}
// Quick fix for now. Can be done faster
@ -328,41 +307,41 @@ private:
/*! Finds a visible vertex from the query point 'q' in 'face'
to start the algorithm from*/
Ccb_halfedge_const_circulator find_visible_start(Face_const_handle face,
const Point_2 &q) const {
init_cdt(face);
typename CDT::Face_handle fh = p_cdt->locate(q);
const Point_2& start_point = fh->vertex(0)->point();
const Point_2 &q) const
{
Location_result result = point_location.ray_shoot_up(q);
// Now retrieve the circulator to first visible vertex from triangulation
Ccb_halfedge_const_circulator circ = point_itr_map[start_point];
if(const Halfedge_const_handle* e =
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 =
circ->source()->incident_halfedges();
Halfedge_around_vertex_const_circulator incident_curr = incident_circ;
vertices.push_back(p);
inserted_artificial_starting_vertex = true;
Ccb_halfedge_const_circulator incident_next;
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;
}
return (*e)->next()->ccb();
}
} 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();
}
}

View File

@ -36,7 +36,6 @@
#include <vector>
#include <iostream>
#include <string>
#include <CGAL/Gmpq.h>
#include <CGAL/Timer.h>
#include <CGAL/Arr_naive_point_location.h>
#include <CGAL/Visibility_2/visibility_utils.h>
@ -151,28 +150,7 @@ bool test_are_equal(const ARR1 &arr1, const ARR2 &arr2) {
return true;
}
template<class Number_type>
Number_type string2num(const std::string& s) {
typename std::string::size_type i;
if (s.find("/") != std::string::npos) {
i = s.find("/");
std::string p = s.substr(0, i);
std::string q = s.substr(i+1);
std::stringstream convert(p);
int n, d;
convert >> n;
std::stringstream convert2(q);
convert2 >> d;
return Number_type(n)/Number_type(d);
}
else {
std::stringstream convert(s);
double n;
convert >> n;
return Number_type(n);
}
}
template<class Number_type>
std::string num2string(Number_type& n) {
@ -223,11 +201,9 @@ bool create_arrangement_from_dat_file(std::ifstream &input,
typedef typename Arrangement_2::Face_handle Face_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;
if (input) {
std::string curr_line;
std::vector<Point_2> isolated_vertices;
std::getline(input, curr_line);
std::stringstream convert(curr_line);
int number_of_isolated_vertices;
@ -236,11 +212,9 @@ bool create_arrangement_from_dat_file(std::ifstream &input,
for (int i = 0 ; i < number_of_isolated_vertices ; i++) {
std::getline(input, curr_line);
std::istringstream iss(curr_line);
std::string x, y;
iss >> x >> y;
arr.insert_in_face_interior(Point_2(string2num<Number_type>(x),
string2num<Number_type>(y)),
uface);
Point_2 p;
iss >> p;
arr.insert_in_face_interior(p, uface);
}
std::vector<Segment_2> edges;
int number_of_edges;
@ -249,13 +223,10 @@ bool create_arrangement_from_dat_file(std::ifstream &input,
convert2 >> number_of_edges;
for (int i = 0 ; i < number_of_edges ; i++) {
std::getline(input, curr_line);
std::string x1, y1, x2, y2;
std::istringstream iss(curr_line);
iss >> x1 >> y1 >> x2 >> y2;
edges.push_back(Segment_2(Point_2(string2num<Number_type>(x1),
string2num<Number_type>(y1)),
Point_2(string2num<Number_type>(x2),
string2num<Number_type>(y2))));
Segment_2 seg;
iss >> seg;
edges.push_back(seg);
}
CGAL::insert(arr, edges.begin(), edges.end());
return true;
@ -294,43 +265,12 @@ void regularize(Arrangement_2& arr){
//std::cout << "regularize done" << std::endl;
}
template <class Arrangement_2>
bool is_regular_arr(Arrangement_2& arr){
//std::cout << "\n regularize" << std::endl;
// remove all edges with the same face on both sides
typedef typename Arrangement_2::Edge_iterator EIT;
for(EIT eit = arr.edges_begin(); eit != arr.edges_end();){
if(eit->face() == eit->twin()->face()){
// arr.remove_edge(eit++,false,false); did not compile
EIT eh = eit;
++eit;
return false;
}else{
++eit;
}
}
// remove all isolated vertices (also those left from prvious step)
typedef typename Arrangement_2::Vertex_iterator VIT;
for(VIT vit = arr.vertices_begin(); vit != arr.vertices_end();){
if(vit->degree()== 0){
VIT vh = vit;
vit++;
return false;
}else{
vit++;
}
}
return true;
//std::cout << "regularize done" << std::endl;
}
template <class Visibility_2, class Visibility_arrangement_2>
bool run_test_case_from_file(Visibility_2& visibility, std::ifstream &input) {
typedef typename Visibility_2::Arrangement_2 Arrangement_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::FT Number_type;
typedef typename Arrangement_2::Halfedge_around_vertex_const_circulator
Halfedge_around_vertex_const_circulator;
typedef typename Arrangement_2::Face_const_handle Face_const_handle;
@ -346,17 +286,14 @@ bool run_test_case_from_file(Visibility_2& visibility, std::ifstream &input) {
if (curr_line[0] != '#' && curr_line[0] != '/')
break;
}
std::stringstream convert(curr_line);
std::string x, y;
convert >> x >> y;
Point_2 query_pt(string2num<Number_type>(x),
string2num<Number_type>(y));
std::stringstream ss(curr_line);
Point_2 query_pt;
ss >> query_pt;
std::getline(input, curr_line);
std::string x1, y1;
std::istringstream iss(curr_line);
iss >> x1 >> y1;
Point_2 reference_pt(string2num<Number_type>(x1),
string2num<Number_type>(y1));
Point_2 reference_pt;
iss >> reference_pt;
std::getline(input, curr_line);
if (!create_arrangement_from_dat_file<Arrangement_2>(input, arr_in)) {
@ -677,7 +614,7 @@ void create_arrangement_from_file(_Arrangement_2 &arr, std::ifstream& input) {
typedef typename Arrangement_2::Geometry_traits_2 Geometry_traits_2;
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;
if (input) {
std::string line;
while (std::getline(input, line)) {
@ -692,11 +629,10 @@ void create_arrangement_from_file(_Arrangement_2 &arr, std::ifstream& input) {
for (int i = 0; i != number_of_points; i++) {
std::getline(input, line);
std::string n1, n2;
std::istringstream iss(line);
iss>> n1 >> n2;
points.push_back(Point_2(string2num<Number_type>(n1),
string2num<Number_type>(n2)));
Point_2 p;
iss >> p;
points.push_back(p);
}
int number_of_edges;
input >> number_of_edges;
@ -719,7 +655,7 @@ void create_arrangement_from_env_file(_Arrangement_2 &arr, std::ifstream& input)
typedef typename Arrangement_2::Geometry_traits_2 Geometry_traits_2;
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;
if (input) {
std::string line;
while (std::getline(input, line)) {
@ -735,17 +671,19 @@ void create_arrangement_from_env_file(_Arrangement_2 &arr, std::ifstream& input)
std::getline(input, line);
std::stringstream convert(line);
int number_of_vertices;
typename std::vector<Point_2>::size_type number_of_vertices;
convert >> number_of_vertices;
for (int j = 0; j < number_of_vertices; j++) {
for (typename std::vector<Point_2>::size_type j = 0;
j < number_of_vertices; j++) {
std::getline(input, line);
std::string n1, n2;
std::istringstream iss(line);
iss >> n1 >> n2;
points.push_back(Point_2(string2num<Number_type>(n1),
string2num<Number_type>(n2)));
Point_2 p;
iss >> p;
points.push_back(p);
}
for (int j = 0; j < number_of_vertices-1 ; j++) {
for (typename std::vector<Point_2>::size_type j = 0;
j < number_of_vertices-1 ; j++)
{
segments.push_back(Segment_2(points[j], points[j+1]));
}
segments.push_back(Segment_2(points.front(), points.back()));
@ -965,19 +903,7 @@ typename Arrangement_2::Face_const_handle construct_biggest_arr_with_no_holes(
}
}
}
Ccb_halfedge_const_circulator circ_p = fch->outer_ccb();
Ccb_halfedge_const_circulator curr_p = circ_p;
Halfedge_const_handle he_p;/*
std::cout << "OUT FACE\n";
do {
he_p = curr_p;
Ccb_halfedge_const_circulator next = curr_p;
next++;
Halfedge_const_handle h_next = next;
assert(he_p->target() == h_next->source());
std::cout << he_p->source()->point() << std::endl;
} while(++curr_p != circ_p);
std::cout << "END\n";*/
return fch;
}
@ -1336,22 +1262,6 @@ void pure_benchmark( Visibility_2 &visibility,
// std::cout << "total time is:" << ptime + qtime << " sec" << std::endl;
}
template<class Segment_2, class Point_2>
int intersect_seg(const Segment_2& seg1, const Segment_2& seg2, Segment_2& seg_out, Point_2& p_out)
{
CGAL::Object result = CGAL::intersection(seg1, seg2);
if (const Point_2 *ipoint = CGAL::object_cast<Point_2>(&result)) {
p_out = *ipoint;
return 1;
} else
if (const Segment_2 *iseg = CGAL::object_cast<Segment_2>(&result)) {
seg_out = *iseg;
return 2;
} else {
return 0;
}
}
template<class Visibility_2>
void test_star_shape_one_face( typename Visibility_2::Arrangement_2 &arr,