mirror of https://github.com/CGAL/cgal
add tunnel and sweep by vertex
This commit is contained in:
parent
c0f0186c71
commit
60cc91bec4
|
|
@ -35,6 +35,7 @@ namespace CGAL {
|
|||
|
||||
template <typename Arrangement_2, typename RegularizationTag>
|
||||
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<Point_2> Pvec;
|
||||
typedef std::pair<Point_2, Point_2> Pair;
|
||||
const Input_arrangement_2 *p_arr;
|
||||
bool attach_tag;
|
||||
typedef std::vector<Point_2> Pvec;
|
||||
typedef std::pair<Point_2, Point_2> Pair;
|
||||
|
||||
Input_arrangement_2 *p_arr;
|
||||
Point_2 q;
|
||||
std::vector<Point_2> polygon; //visibility polygon
|
||||
Point_2 dp;
|
||||
Pvec polygon; //visibility polygon
|
||||
std::map<Point_2, Pvec> vmap; //vertex and two edges incident to it that might block vision
|
||||
std::map<Pair, int> edx; //index of edge in the heap
|
||||
std::vector<Pair> heap;
|
||||
std::list<Point_2> 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; l<j; l++) {
|
||||
bool left_v(false), right_v(false), has_predecessor(false);
|
||||
for (int k=0; k<vmap[vs[l]].size(); k++) {
|
||||
Point_2 temp= vmap[vs[l]][k];
|
||||
if (temp == former)
|
||||
has_predecessor = true;
|
||||
if (CGAL::left_turn(q, vs[l], temp))
|
||||
left_v = true;
|
||||
else
|
||||
right_v = CGAL::right_turn(q, vs[l], temp);
|
||||
}
|
||||
if (has_predecessor) {
|
||||
block_left = block_left || left_v;
|
||||
block_right = block_right || right_v;
|
||||
}
|
||||
else {
|
||||
block_left = left_v;
|
||||
block_right = right_v;
|
||||
}
|
||||
if (block_left && block_right) {
|
||||
right.push_back(vs[l]);
|
||||
break;
|
||||
}
|
||||
else {
|
||||
if (block_left)
|
||||
left.push_back(vs[l]);
|
||||
else
|
||||
right.push_back(vs[l]);
|
||||
}
|
||||
former = vs[l];
|
||||
}
|
||||
for (int l=0; l=right.size(); l++)
|
||||
vs[i+l] = right[l];
|
||||
for (int l=0; l=left.size(); l++)
|
||||
vs[i+l+right.size()] = left[left.size()-1-l];
|
||||
}
|
||||
|
||||
|
||||
void visibility_region_impl(Face_const_handle f, const Point_2& a, const Point_2& b) {
|
||||
input_face(f, q, a, b);
|
||||
vs.sort(compare_angle);
|
||||
|
||||
for (int i=0; i!=vs.size(); i++) {
|
||||
j = i+1;
|
||||
while (j != vs.size() && CGAL::collinear(q, vs[i], v[j]))
|
||||
j++;
|
||||
funnel(i, j);
|
||||
i = j;
|
||||
}
|
||||
|
||||
// debug
|
||||
// for (int i = 0; i<vertices.size(); i++) {
|
||||
// print(vertices[i]->point());
|
||||
|
|
@ -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<Pair> 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 "<<left_p.x()<<' '<<left_p.y()<<std::endl;
|
||||
//// std::cout<<"the right_p is "<<right_p.x()<<' '<<right_p.y()<<std::endl;
|
||||
//// std::cout<<"the front_p is "<<collinear_vertices[0].x()<<' '<<collinear_vertices[0].y()<<std::endl;
|
||||
// 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;
|
||||
// }
|
||||
// }
|
||||
// vit = end_it;
|
||||
Pair create_pair(const Point_2& p1, const Point_2& p2){
|
||||
assert(p1 != p2);
|
||||
if (p1 < p2)
|
||||
return Pair(p1, p2);
|
||||
else
|
||||
return Pair(p1, p2);
|
||||
}
|
||||
|
||||
//todo add edge location record
|
||||
void heap_insert(std::vector<Pair>& 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<Pair>& 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<Pair>& 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<Point_2>(&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<Segment_2 >(&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<Point_2>(obj);
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
//insert newly-discovered edges into active_edges according to its intersection with the view ray.
|
||||
void insert_halfedge(std::vector<Halfedge_const_handle>& 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<Halfedge_const_handle>::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<vs.size(); i++) {
|
||||
Point_2 q1 = vs[i];
|
||||
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();
|
||||
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<Point_2>& polygon){
|
||||
if (polygon.empty())
|
||||
polygon.push_back(p);
|
||||
else
|
||||
{
|
||||
if (polygon.back() != p) {
|
||||
polygon.push_back(p);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void insert_needle(const std::vector<Point_2>& points, std::vector<Point_2>& 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<Pair>& edges,
|
||||
const Point_2& dp) {
|
||||
|
||||
}
|
||||
|
||||
|
||||
//remove edges that are not active any longer
|
||||
void remove_edges(std::vector<Halfedge_const_handle>& edges, const Ray_2& r) {
|
||||
typename std::vector<Halfedge_const_handle>::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);
|
||||
|
|
|
|||
|
|
@ -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 <michael.hemmer@cgal.org>
|
||||
//
|
||||
|
||||
#ifndef CGAL_TRIANGULAR_EXPANSION_VISIBILITY_2__H
|
||||
#define CGAL_TRIANGULAR_EXPANSION_VISIBILITY_2__H
|
||||
|
||||
#include <CGAL/Arrangement_2.h>
|
||||
#include <boost/shared_ptr.hpp>
|
||||
#include <CGAL/Constrained_Delaunay_triangulation_2.h>
|
||||
|
||||
namespace CGAL {
|
||||
|
||||
template<class Arrangement_2 ,class RegularizationTag>
|
||||
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<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_Delaunay_triangulation_2<K, TDS, Itag> CDT;
|
||||
|
||||
|
||||
private:
|
||||
const Input_arrangement_2* p_arr;
|
||||
boost::shared_ptr<CDT> p_cdt;
|
||||
std::vector<Segment_2> 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<CDT>();
|
||||
}
|
||||
|
||||
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<Point_2>(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" <<std::endl;
|
||||
//std::cout << "q "<< q << std::endl ;
|
||||
//std::cout << "vh->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 <<std::endl;
|
||||
needles.push_back(Segment_2(vh->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 <<std::endl;
|
||||
needles.push_back(Segment_2(vh->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() <<std::endl;
|
||||
needles.push_back(Segment_2(vh->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<class OIT>
|
||||
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<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);
|
||||
}
|
||||
|
||||
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<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);
|
||||
}
|
||||
|
||||
Face_handle output(std::vector<Point_2>& 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<needles.size();i++){
|
||||
// //std::cout << needles[i].source() << " -- "
|
||||
// << needles[i].target() << std::endl;
|
||||
// }
|
||||
// //std::cout << raw_output.size() << std::endl;
|
||||
std::vector<Segment_2> segments(needles.begin(),needles.end());
|
||||
for(int i = 0; i <raw_output.size();i++){
|
||||
// //std::cout << raw_output[i] << " -- "
|
||||
// << raw_output[(i+1)%raw_output.size()] << std::endl;
|
||||
segments.push_back(Segment_2(raw_output[i],raw_output[(i+1)%raw_output.size()]));
|
||||
}
|
||||
|
||||
// //std::cout << " done 1 " << std::endl ;
|
||||
// use something more clever
|
||||
CGAL::insert_non_intersecting_curves(out_arr,segments.begin(),segments.end());
|
||||
//CGAL::insert(out_arr,segments.begin(),segments.end());
|
||||
|
||||
// //std::cout << " done 2 " << std::endl ;
|
||||
assert(out_arr.number_of_faces()== 2);
|
||||
|
||||
// //std::cout<< "==============" <<std::endl;
|
||||
if(out_arr.faces_begin()->is_unbounded())
|
||||
return ++out_arr.faces_begin();
|
||||
else
|
||||
return out_arr.faces_begin();
|
||||
|
||||
//std::cout<< "==============" <<std::endl;
|
||||
|
||||
}
|
||||
|
||||
void init_cdt(){
|
||||
//std::cout << "init_cdt" << std::endl;
|
||||
//std::cout<< "==============" <<std::endl;
|
||||
//std::cout<< "Input Polygon:" <<std::endl;
|
||||
//todo, avoid copy by using modified iterator
|
||||
std::vector<std::pair<Point_2,Point_2> > 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<CDT>(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
|
||||
Loading…
Reference in New Issue