diff --git a/Visibility_2/include/CGAL/Rotational_sweep_visibility_2.h b/Visibility_2/include/CGAL/Rotational_sweep_visibility_2.h index 01cfdfa7b81..2ea55889afb 100644 --- a/Visibility_2/include/CGAL/Rotational_sweep_visibility_2.h +++ b/Visibility_2/include/CGAL/Rotational_sweep_visibility_2.h @@ -35,6 +35,7 @@ namespace CGAL { template class Rotational_sweep_visibility_2 { + public: typedef Arrangement_2 Input_arrangement_2; typedef Arrangement_2 Output_arrangement_2; @@ -48,6 +49,7 @@ public: typedef typename Arrangement_2::Face_const_handle Face_const_handle; typedef typename Arrangement_2::Face_handle Face_handle; + typedef typename Geometry_traits_2::Kernel K; 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; @@ -61,7 +63,7 @@ public: typedef CGAL::Tag_true Supports_general_polygon_tag; typedef CGAL::Tag_true Supports_simple_polygon_tag; - enum Intersection_type { UNBOUNDED, CORNER, INNER }; + Rotational_sweep_visibility_2(): p_arr(NULL) {} Rotational_sweep_visibility_2(Input_arrangement_2& arr): p_arr(&arr) {} @@ -189,13 +191,16 @@ const Input_arrangement_2& arr() { private: //members - typedef std::vector Pvec; - typedef std::pair Pair; - const Input_arrangement_2 *p_arr; - bool attach_tag; + typedef std::vector Pvec; + typedef std::pair Pair; + + Input_arrangement_2 *p_arr; Point_2 q; - std::vector polygon; //visibility polygon + Point_2 dp; + Pvec polygon; //visibility polygon std::map vmap; //vertex and two edges incident to it that might block vision + std::map edx; //index of edge in the heap + std::vector heap; std::list vs; //angular sorted vertices bool is_vertex_query; bool is_edge_query; @@ -213,24 +218,73 @@ private: } bool if_intersect(const Point_2& q, - const Point_2& d_p, + const Point_2& dp, const Point_2& p1, const Point_2& p2) { - if (CGAL::collinear(q, d_p, p1)) - return (quadrant(p1.x()-q.x(), p1.y()-q.y()) == quadrant((d_p.x()-q.x(), d_p.y()-q.y()))); + if (CGAL::collinear(q, dp, p1)) + return (quadrant(p1.x()-q.x(), p1.y()-q.y()) == quadrant((dp.x()-q.x(), dp.y()-q.y()))); - if (CGAL::collinear(q, d_p, p2)) - return (quadrant(p2.x()-q.x(), p2.y()-q.y()) == quadrant((d_p.x()-q.x(), d_p.y()-q.y()))); + if (CGAL::collinear(q, dp, p2)) + return (quadrant(p2.x()-q.x(), p2.y()-q.y()) == quadrant((dp.x()-q.x(), dp.y()-q.y()))); - return (CGAL::orientation(q, d_p, p1) != CGAL::orientation(q, d_p, p2) && CGAL::orientation(q, p1, d_p) == 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)); } - //compute visibility region between qa and qb - void visibility_region_impl(Face_const_handle f, const Point_2& q, const Point_2& a, const Point_2& b) { + void funnel(int i, int j) { + Pvec right, left; + bool block_left(false), block_right(false); + Point_2 former = vs[i]; + for (int l=i; lpoint()); @@ -246,7 +300,8 @@ private: dir = Vector_2(0, -1); } - Point_2 direct_p(q.x()+dir.x(), q.y()+dir.y()); + dp = Point_2(q.x()+dir.x(), q.y()+dir.y()); + //initiation of active_edges std::vector active_edges; Ccb_halfedge_const_circulator curr = f->outer_ccb(); @@ -254,8 +309,8 @@ private: do { Point_2 p1 = curr->target()->point(); Point_2 p2 = curr->source()->point(); - if (q != p1 && q != p2 && if_intersect(q, direct_p, p1, p2)) - active_edges.push_back(create_pair(p1, p2)); + if (q != p1 && q != p2 && if_intersect(q, dp, p1, p2)) + heap_insert(create_pair(p1, p2)); } while (++curr != circ); typename Arrangement_2::Hole_const_iterator hi; @@ -264,183 +319,134 @@ private: do { Point_2 p1 = c1->target()->point(); Point_2 p2 = c1->source()->point(); - if (q != p1 && q != p2 && if_intersect(q, direct_p, p1, p2)) - active_edges.push_back(create_pair(p1, p2)); + if (q != p1 && q != p2 && if_intersect(q, dp, p1, p2)) + heap_insert(create_pair(p1, p2)); } while (++c1 != c2); } //angular sweep begins -// typename Pvec::iterator vit = vs.begin(), begin_it, end_it; + //todo should edx be cleaned. + for (int i=0; i!=vs.size(); i++) { + dp = vs[i]; + Point_2 v = dp; + Pair ce = heap.front(); //save closest edge; + int insert_cnt(0), remove_cnt(0); + for (int j=0; j!=vmap[v].size(); j++) { + Pair e = create_pair(v, vmap[v][j]); + if (edx.count(e)) { + heap_remove(edx[e]); + remove_cnt++; + } + else { + heap_insert(e); + insert_cnt++; + } + } + if (ce != heap.front()) { + //when the closest edge changed + if (remove_cnt > 0 && insert_cnt > 0) { + //some edges are added and some are deleted, which means the vertice sweeped is a vertice of visibility polygon. + update_visibility(v); + } + if (remove_cnt == 0 && insert_cnt > 0) { + //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 sweeped. + update_visibility(intersection_point(ray, halfedge2seg(old_closet_edge))); + update_visibility(v); + } + 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. + update_visibility(v); + update_visibility(intersection_point(ray, halfedge2seg(active_edges[0]))); + } -// while (vit != vs.end()) -// { -// Point_2 right_p, left_p, mid_p; -// begin_it = vit; -// end_it = vit + 1; -// right_p = intersection_point(direct_p, active_edges[0]); + } + } + } -// //find end_it such that all vertices between begin_it and end_it(not included) are collinear with query point. -// while (end_it != vs.end()) { -// if (!CGAL::collinear(q, *begin_it, *end_it)) -// break; -// insert_edge(*end_it, active_edges, direct_p); -// end_it++; -// } - -//// std::cout<<"after adding\n"; -//// print_edges(active_edges); -// mid_p = intersection_point(direct_p, active_edges[0]); -// Pvec collinear_vertices; -// Intersection_type i_type = needle(active_edges, direct_p, collinear_vertices); -// switch (i_type) { -// case UNBOUNDED : -// //todo:this part is not finished. -// //remove right and collinear; -// remove_edges(active_edges, direct_p); -// update_visibility(right_p, polygon); -// update_visibility(mid_p, polygon); -// //todo CGAL::insert_curve(); -// if (!active_edges.empty()) { -// left_p = intersection_point(direct_p, active_edges[0]); -// update_visibility(left_p, polygon); -// } -// break; -// case CORNER : -// //remove right and collinear; -// remove_edges(active_edges, direct_p); - -//// std::cout<<"after removing\n"; -//// print_edges(active_edges); - -// left_p = intersection_point(direct_p, active_edges[0]); -// update_visibility(right_p, polygon); -// if (right_p == collinear_vertices[0]) { -// insert_needle(collinear_vertices, polygon, true); -// } -// else if (left_p == collinear_vertices[0]) { -// insert_needle(collinear_vertices, polygon, false); -// } -// update_visibility(left_p, polygon); -// break; -// case INNER : -// //remove right and collinear; -// remove_edges(active_edges, direct_p); -// if (collinear_vertices.size() < 2) { -// //this means mid_p = left_p = right_p = furthest_p. no new vertex is found. -// } -// else { -// //debug -//// std::cout<<"print a needle:\n"; -//// print(collinear_vertices); -//// std::cout<<"the left_p is "<& heap, const Pair& e, const Point_2& dp) { + void heap_insert(const Pair& e) { heap.push_back(e); int i = heap.size()-1; + edx[e] = i; int parent = (i-1)/2; - while (i!=0 && is_closer(heap[i], heap[parent], dp)){ - heap_swap(heap, i, parent); + while (i!=0 && is_closer(heap[i], heap[parent])){ + heap_swap(i, parent); i = parent; parent = (i-1)/2; } } - void heap_remove(std::vector& heap, int i, const Point_2& dp) { + void heap_remove(int i) { + edx.erase(heap[i]); heap[i] = heap.back(); + edx[heap[i]] = i; heap.pop_back(); - bool swapped; + bool need_swap; do { int left_son = i*2+1; int right_son = i*2+2; int closest = i; - if (left_son < heap.size() && is_closer(heap[left_son], heap[i], dp)) { + if (left_son < heap.size() && is_closer(heap[left_son], heap[i])) { closest = left_son; } - if (right_son < heap.size() && is_closer(heap[right_son], heap[closest], dp)) { + if (right_son < heap.size() && is_closer(heap[right_son], heap[closest])) { closest = right_son; } - swapped = false; + need_swap = false; if (closest != i) { - heap_swap(heap, i, closest); + heap_swap(i, closest); i = closest; - swapped = true; + need_swap = true; } - } while(swapped); + } while(need_swap); } - void heap_swap(std::vector& heap, int i, int j) { + void heap_swap(int i, int j) { + edx[heap[i]] = j; + edx[heap[j]] = i; + Pair temp = heap[i]; + heap[i] = heap[j]; + heap[j] = temp; + } + + bool is_closer(Pair e1, Pair e2) { } - bool is_closer(Pair e1, Pair e2, Point_2 dp) { - - } - - Point_2 intersection_point(Ray_2 ray, Segment_2 seg ) + Point_2 ray_seg_intersection( + const Point_2& q, const Point_2& dp, // the ray + const Point_2& s, const Point_2& t) // the segment { - - CGAL::Object result = CGAL::intersection(ray, seg); - if (const Point_2 *ipoint = CGAL::object_cast(&result)) { - return *ipoint; - } else - //if result is a segment, return the end closer to the source of ray. - if (const Segment_2 *iseg = CGAL::object_cast(&result)) { - switch (CGAL::compare_distance_to_point(ray.source(), iseg->source(), iseg->target())) { - case (CGAL::SMALLER): - return iseg->source(); - break; - case (CGAL::LARGER) : - return iseg->target(); - break; - } - - } else { - // if no intersection, return the source of ray. - return ray.source(); - } + Ray_2 ray(q,dp); + Segment_2 seg(s,t); + assert(typename K::Do_intersect_2()(ray,seg)); + CGAL::Object obj = typename K::Intersect_2()(ray,seg); + Point_2 result = object_cast(obj); + return result; } - - //insert newly-discovered edges into active_edges according to its intersection with the view ray. - void insert_halfedge(std::vector& active_edges, const Ray_2& ray, Halfedge_const_handle edge) - { - Point_2 cross_of_e = intersection_point(ray, edge); - if (cross_of_e != ray.source()) - { - typename std::vector::iterator curr = active_edges.begin(); - while (curr != active_edges.end()) - { - - Point_2 cross_of_curr = intersection_point(ray, *curr); - if (CGAL::compare_distance_to_point(ray.source(), cross_of_e, cross_of_curr) == CGAL::SMALLER) - break; - if (cross_of_curr == cross_of_e && is_closer(ray, edge, *curr)) - break; - ++curr; - } - active_edges.insert(curr, edge); + void update_visibility(const Point_2& p){ + if (polygon.empty()) + polygon.push_back(p); + else + { + if (polygon.back() != p){ + polygon.push_back(p); } + } } + bool compare_angle(const Point_2& p1, const Point_2& p2) { Direction_2 d1(Ray_2(q, p1)); @@ -476,7 +482,7 @@ private: typename Arrangement_2::Hole_const_iterator hi; for (hi = fh->holes_begin(); hi != fh->holes_end(); ++hi) { - typename Arrangement_2::Ccb_halfedge_const_circulator c1 = *hi, c2 = *hi; + Ccb_halfedge_const_circulator c1 = *hi, c2 = *hi; do { Point_2 v = curr->target()->point(); if (v == q) @@ -497,20 +503,17 @@ private: ymin = ymax = q1.y(); for (int i=0; i xmax) - xmax = q1.x(); - if (q1.y() < ymin) - ymin = q1.y(); - if (q1.y() > ymax) - ymax = q1.y(); + if (q1.x() < xmin) xmin = q1.x(); + if (q1.x() > xmax) xmax = q1.x(); + if (q1.y() < ymin) ymin = q1.y(); + if (q1.y() > ymax) ymax = q1.y(); } xmin -= 10; xmax += 10; ymin -= 10; ymax += 10; - Point_2 box[4] = {Point_2(xmin, ymin), Point_2(xmax, ymin), Point_2(xmax, ymax), Point_2(xmin, ymax)}; + Point_2 box[4] = {Point_2(xmin, ymin), Point_2(xmax, ymin), + Point_2(xmax, ymax), Point_2(xmin, ymax)}; for (int i=0; i<4; i++) { vs.push_back(box[i]); Pvec pvec; @@ -524,67 +527,8 @@ private: - //insert new vertice to polygon. before insertion, check if this vertice has been added before. - void update_visibility(const Point_2 p, std::vector& polygon){ - if (polygon.empty()) - polygon.push_back(p); - else - { - if (polygon.back() != p) { - polygon.push_back(p); - } - } - } - - void insert_needle(const std::vector& points, std::vector& polygon, bool is_right_close){ - if (is_right_close) { - for (int i = 0; i != points.size(); i++) { - update_visibility(points[i], polygon); - } - } - else { - for (int i = points.size()-1; i != -1; i--) { - update_visibility(points[i], polygon); - } - } - } - //add a new edge when vision ray passes a vertex - void insert_edge(const Point_2& p, - std::vector& edges, - const Point_2& dp) { - - } - - - //remove edges that are not active any longer - void remove_edges(std::vector& edges, const Ray_2& r) { - typename std::vector::iterator eit = edges.begin(); - while (eit != edges.end()) { - Point_2 p1 = (*eit)->target()->point(); - Point_2 p2 = (*eit)->source()->point(); - bool is_incident(false); - if (is_on_ray(r, p1)) { - is_incident = true; - } - else if (is_on_ray(r, p2)) { - Point_2 tmp = p1; - p1 = p2; - p2 = tmp; - is_incident = true; - } - if ( (is_incident && !CGAL::left_turn(r.source(), p1, p2)) || intersection_point(r, *eit) == r.source() ) - { - eit = edges.erase(eit); - continue; - } - - else { - eit++; - } - } - } bool is_on_ray(const Ray_2& r, const Point_2& p) { return Direction_2(Vector_2(r.source(), p)) == Direction_2(r); diff --git a/Visibility_2/include/CGAL/Triangular_expansion_visibility_2_.h b/Visibility_2/include/CGAL/Triangular_expansion_visibility_2_.h deleted file mode 100644 index 73717481188..00000000000 --- a/Visibility_2/include/CGAL/Triangular_expansion_visibility_2_.h +++ /dev/null @@ -1,571 +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): Michael Hemmer -// - -#ifndef CGAL_TRIANGULAR_EXPANSION_VISIBILITY_2__H -#define CGAL_TRIANGULAR_EXPANSION_VISIBILITY_2__H - -#include -#include -#include - -namespace CGAL { - -template -class Triangular_expansion_visibility_2 { - typedef typename Arrangement_2::Geometry_traits_2 Geometry_traits_2; - typedef typename Geometry_traits_2::Kernel K; -public: - // 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::Halfedge_handle Halfedge_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::Face_handle Face_handle; - typedef typename Arrangement_2::Vertex_const_handle Vertex_const_handle; - typedef typename Arrangement_2::Vertex_handle Vertex_handle; - - typedef typename K::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::Direction_2 Direction_2; - typedef typename Geometry_traits_2::FT Number_type; - typedef typename Geometry_traits_2::Object_2 Object_2; - - // TODO - typedef RegularizationTag Regularization_tag; - - typedef CGAL::Tag_true Supports_general_polygon_tag; - typedef CGAL::Tag_true Supports_simple_polygon_tag; - -private: - typedef CGAL::Triangulation_vertex_base_2 Vb; - typedef CGAL::Constrained_triangulation_face_base_2 Fb; - typedef CGAL::Triangulation_data_structure_2 TDS; - typedef CGAL::No_intersection_tag Itag; - typedef CGAL::Constrained_Delaunay_triangulation_2 CDT; - - -private: - const Input_arrangement_2* p_arr; - boost::shared_ptr p_cdt; - std::vector needles; - -public: - Triangular_expansion_visibility_2() : p_arr(NULL){} - - /*! Constructor given an arrangement and the Regularization tag. */ - Triangular_expansion_visibility_2 (Input_arrangement_2& arr) - : p_arr(&arr){ - //std::cout << "Triangular_expansion_visibility_2" << std::endl; - init_cdt(); - } - - bool is_attached() { - //std::cout << "is_attached" << std::endl; - return (p_arr != NULL); - } - - void attach(Input_arrangement_2& arr) { - //std::cout << "attach" << std::endl; - // todo observe changes in arr; - p_arr = &arr; - init_cdt(); - //std::cout << "attach done" << std::endl; - } - - void detach() { - //std::cout << "detach" << std::endl; - p_arr = NULL; - p_cdt = boost::shared_ptr(); - } - - const Input_arrangement_2& arr() { - return *p_arr; - } - - typename CDT::Edge get_edge(typename CDT::Face_handle fh, int i){ - return std::make_pair(fh,i); - } - - Point_2 ray_seg_intersection( - const Point_2& q, const Point_2& b, // the ray - const Point_2& s, const Point_2& t) // the segment - { - Ray_2 ray(q,b); - Segment_2 seg(s,t); - assert(typename K::Do_intersect_2()(ray,seg)); - CGAL::Object obj = typename K::Intersect_2()(ray,seg); - Point_2 result = object_cast(obj); - return result; - } - - void collect_needle( - const Point_2& q, - const typename CDT::Vertex_handle vh, - const typename CDT::Face_handle fh, - int index){ - - - // the expanded edge should not be constrained - assert(!p_cdt->is_constrained(get_edge(fh,index))); - assert(!p_cdt->is_infinite(fh)); - // go into the new face - const typename CDT::Face_handle nfh(fh->neighbor(index)); - assert(!p_cdt->is_infinite(nfh)); - - // get indices of neighbors - int nindex = nfh->index(fh); // index of new vertex and old face - int rindex = p_cdt->ccw(nindex); // index of face behind right edge - int lindex = p_cdt-> cw(nindex); // index of face behind left edge - - // get vertices seen from entering edge - const typename CDT::Vertex_handle nvh(nfh->vertex(nindex)); - const typename CDT::Vertex_handle rvh(nfh->vertex(p_cdt->cw (nindex))); - const typename CDT::Vertex_handle lvh(nfh->vertex(p_cdt->ccw(nindex))); - assert(!p_cdt->is_infinite(nvh)); - assert(!p_cdt->is_infinite(lvh)); - assert(!p_cdt->is_infinite(rvh)); - - // get edges seen from entering edge - typename CDT::Edge re = get_edge(nfh,p_cdt->ccw(nindex)); - typename CDT::Edge le = get_edge(nfh,p_cdt-> cw(nindex)); - - // do orientation computation once for new vertex - typename K::Orientation_2 orientation = - p_cdt->geom_traits().orientation_2_object(); - CGAL::Orientation orient = orientation(q,vh->point(),nvh->point()); - - - //std::cout << "\n collect_needle" <point() "<< vh->point() << std::endl; - //std::cout << "lvh->point() "<< lvh->point() << std::endl ; - //std::cout << "nvh->point() "<< nvh->point() << std::endl ; - //std::cout << "rvh->point() "<< rvh->point() << std::endl<< std::endl; - - - - switch ( orient ) { - case CGAL::COUNTERCLOCKWISE: - // looking on to the right edge - if(p_cdt->is_constrained(re)){ - if(vh!=rvh){ - Point_2 p = ray_seg_intersection(q,vh->point(),nvh->point(),rvh->point()); - //std::cout << vh->point() <<" -1- "<< p <point(),p)); - } - }else{ - collect_needle(q,vh,nfh,rindex); - } - break; - case CGAL::CLOCKWISE: - // looking on to the left edge - if(p_cdt->is_constrained(le)){ - if(vh!=lvh){ - Point_2 p = ray_seg_intersection(q,vh->point(),nvh->point(),lvh->point()); - //std::cout << vh->point() <<" -2- "<< p <point(),p)); - } - }else{ - collect_needle(q,vh,nfh,lindex); - } - break; - default: - assert(orient == CGAL::COLLINEAR); - // looking on nvh, so it must be reported - // if it wasn't already (triangles rotate around vh) - if(vh != nvh){ - //std::cout << vh->point() <<" -3- "<< nvh->point() <point(),nvh->point())); - } - // but we may also contiue looking along the vertex - if(!p_cdt->is_constrained(re)){ - collect_needle(q,nvh,nfh,rindex); - } - if(!p_cdt->is_constrained(le)){ - collect_needle(q,nvh,nfh,lindex); - } - break; - } - } - template - OIT expand_edge( - const Point_2& q, - const Point_2& left, - const Point_2& right, - typename CDT::Face_handle fh, - int index, - OIT oit){ - - // the expanded edge should not be constrained - assert(!p_cdt->is_constrained(get_edge(fh,index))); - assert(!p_cdt->is_infinite(fh)); - - // go into the new face - const typename CDT::Face_handle nfh(fh->neighbor(index)); - assert(!p_cdt->is_infinite(nfh)); - - // get indices of neighbors - int nindex = nfh->index(fh); // index of new vertex and old face - int rindex = p_cdt->ccw(nindex); // index of face behind right edge - int lindex = p_cdt-> cw(nindex); // index of face behind left edge - - // get vertices seen from entering edge - const typename CDT::Vertex_handle nvh(nfh->vertex(nindex)); - const typename CDT::Vertex_handle rvh(nfh->vertex(p_cdt->cw (nindex))); - const typename CDT::Vertex_handle lvh(nfh->vertex(p_cdt->ccw(nindex))); - assert(!p_cdt->is_infinite(nvh)); - assert(!p_cdt->is_infinite(lvh)); - assert(!p_cdt->is_infinite(rvh)); - - // get edges seen from entering edge - typename CDT::Edge re = get_edge(nfh,p_cdt->ccw(nindex)); - typename CDT::Edge le = get_edge(nfh,p_cdt-> cw(nindex)); - - // do orientation computation once for new vertex - typename K::Orientation_2 orientation = - p_cdt->geom_traits().orientation_2_object(); - CGAL::Orientation ro = orientation(q,right,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,right,rvh->point()) != CGAL::COUNTERCLOCKWISE); - - //std::cout << (ro == CGAL::COUNTERCLOCKWISE) << " " << (lo == CGAL::CLOCKWISE) << std::endl; - - - - //right edge is seen if new vertex is counter clockwise of right boarder - if(ro == CGAL::COUNTERCLOCKWISE){ - if(p_cdt->is_constrained(re)){ - // the edge is constrained - // report intersection with right boarder ray - // if it is not already the right vertex (already reported) - if(right != rvh->point()){ - *oit++ = ray_seg_intersection(q,right,nvh->point(),rvh->point()); - } - - // then report intersection with left boarder if it exists - if(lo == CGAL::COUNTERCLOCKWISE){ - *oit++ = ray_seg_intersection(q,left,nvh->point(),rvh->point()); - } - }else{ - // the edge is not a constrained - if(lo == CGAL::COUNTERCLOCKWISE){ - // no split needed and return - //std::cout<< "h1"<< std::endl; - oit = expand_edge(q,left,right,nfh,rindex,oit); - //std::cout<< "h1 done"<< std::endl; - return oit; - }else{ - // spliting at new vertex - //std::cout<< "h2"<< std::endl; - *oit++ = expand_edge(q,nvh->point(),right,nfh,rindex,oit); - //std::cout<< "h2 done"<< std::endl; - } - } - } - - - //std::cout << "q "<< q << std::endl ; - //std::cout << "lvh->point() "<< lvh->point() << std::endl; - //std::cout << "left "<< left << std::endl ; - //std::cout << "nvh->point() "<< nvh->point() << std::endl ; - //std::cout << "right "<< right << std::endl ; - //std::cout << "rvh->point() "<< rvh->point() << std::endl<< std::endl; - - - // determin whether new vertex needs to be reported - if(ro != CGAL::CLOCKWISE && lo != CGAL::COUNTERCLOCKWISE){ - *oit++ = nvh->point(); - } - if(!Regularization_tag::value){ - assert(!(ro == CGAL::COLLINEAR && lo == CGAL::COLLINEAR)); - // we have to check whether a needle starts here. - if(p_cdt->is_constrained(le) && !p_cdt->is_constrained(re) && ro == 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); - } - - //left edge is seen if new vertex is clockwise of left boarder - if(lo == CGAL::CLOCKWISE){ - if(p_cdt->is_constrained(le)){ - // the edge is constrained - // report interesection with right boarder if exists - if(ro == CGAL::CLOCKWISE){ - *oit++ = ray_seg_intersection(q,right,nvh->point(),lvh->point()); - } - // then report intersection with left boarder ray - // if it is not already the left vertex (already reported) - if(left != lvh->point()){ - *oit++ = ray_seg_intersection(q,left,nvh->point(),lvh->point()); - } - return oit; - }else{ - // the edge is not a constrained - if(ro == CGAL::CLOCKWISE){ - // no split needed and return - //std::cout<< "h3"<< std::endl; - oit = expand_edge(q,left,right,nfh,lindex,oit); - //std::cout<< "h3 done"<< std::endl; - return oit; - }else{ - // spliting at new vertex - //std::cout<< "h4"<< std::endl; - oit = expand_edge(q,left,nvh->point(),nfh,lindex,oit); - //std::cout<< "h4 done"<< std::endl; - return oit; - } - } - } - - // never reached ;) - // assert(false); - - } - - Face_handle compute_visibility(const Point_2& q, - const Face_const_handle face, - Output_arrangement_2& out_arr - ){ - //std::cout << "query in face interior" << std::endl; - - out_arr.clear(); - needles.clear(); - assert(!face->is_unbounded()); - - - std::vector 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); - } - - Face_handle compute_visibility(const Point_2& q, - const Halfedge_const_handle he, - Output_arrangement_2& out_arr) { - //std::cout << "visibility_region he" << std::endl; - - assert(!he->face()->is_unbounded()); - out_arr.clear(); - needles.clear(); - - std::vector 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); - } - - Face_handle output(std::vector& raw_output, Output_arrangement_2& out_arr){ -// //std::cout << "\n Output Polygon" << std::endl; -// //std::cout << needles.size() << std::endl; -// for (int i = 0; i segments(needles.begin(),needles.end()); - for(int i = 0; i is_unbounded()) - return ++out_arr.faces_begin(); - else - return out_arr.faces_begin(); - - //std::cout<< "==============" < > constraints; - for(typename Input_arrangement_2::Edge_const_iterator eit = p_arr->edges_begin(); - eit != p_arr->edges_end(); eit++){ - Point_2 source = eit->source()->point(); - Point_2 target = eit->target()->point(); - //std::cout << source << " -- " << target << std::endl; - constraints.push_back(std::make_pair(source,target)); - } - //std::cout << "init_cdt new CDT" << std::endl; - p_cdt = boost::shared_ptr(new CDT(constraints.begin(),constraints.end())); - //std::cout << "init_cdt done" << std::endl; - //std::cout << std::endl; - } -}; - -} // namespace CGAL - -#endif //CGAL_TRIANGULAR_EXPANSION_VISIBILITY_2__H