mirror of https://github.com/CGAL/cgal
added Visibility_arrangement_2 as template argument to triangular_expansion
includes tests
This commit is contained in:
parent
e8f34b973d
commit
fbde0fa416
|
|
@ -16,8 +16,7 @@ typedef CGAL::Arrangement_2<Traits_2> Arrangement_2;
|
|||
typedef Arrangement_2::Vertex_const_handle Vertex_const_handle;
|
||||
typedef Arrangement_2::Halfedge_const_handle Halfedge_const_handle;
|
||||
typedef Arrangement_2::Face_handle Face_handle;
|
||||
typedef CGAL::Triangular_expansion_visibility_2<Arrangement_2, CGAL::Tag_true>
|
||||
TEV;
|
||||
typedef CGAL::Triangular_expansion_visibility_2<Arrangement_2> TEV;
|
||||
int main() {
|
||||
Point_2 p1(1, 2), p2(12, 3), p3(19, -2), p4(12, 6), p5(14, 14), p6(9, 5);
|
||||
Point_2 h1(8,3), h2(10, 3), h3(8, 4), h4(10, 6), h5(11, 6), h6(11, 7);
|
||||
|
|
|
|||
|
|
@ -1,661 +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): Francisc Bungiu <fbungiu@gmail.com>
|
||||
// Michael Hemmer <michael.hemmer@cgal.org>
|
||||
|
||||
#ifndef CGAL_SIMPLE_POLYGON_VISIBILITY_2__H
|
||||
#define CGAL_SIMPLE_POLYGON_VISIBILITY_2__H
|
||||
|
||||
#include <CGAL/Arrangement_2.h>
|
||||
#include <CGAL/rational_rotation.h>
|
||||
#include <CGAL/tags.h>
|
||||
#include <CGAL/enum.h>
|
||||
#include <CGAL/Visibility_2/visibility_utils.h>
|
||||
#include <stack>
|
||||
#include <map>
|
||||
|
||||
namespace CGAL {
|
||||
|
||||
template<class Arrangement_2, class RegularizationTag>
|
||||
class Simple_polygon_visibility_2_ {
|
||||
|
||||
public:
|
||||
// Currently only consider with same type for both
|
||||
typedef Arrangement_2 Arrangement_2;
|
||||
typedef Arrangement_2 Visibility_arrangement_2;
|
||||
typedef typename Arrangement_2::Geometry_traits_2 Geometry_traits_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 Geometry_traits_2::Point_2 Point_2;
|
||||
typedef typename Geometry_traits_2::Ray_2 Ray_2;
|
||||
typedef typename Geometry_traits_2::Segment_2 Segment_2;
|
||||
typedef typename Geometry_traits_2::Line_2 Line_2;
|
||||
typedef typename Geometry_traits_2::Vector_2 Vector_2;
|
||||
typedef typename Geometry_traits_2::Direction_2 Direction_2;
|
||||
typedef typename Geometry_traits_2::FT Number_type;
|
||||
typedef typename Geometry_traits_2::Object_2 Object_2;
|
||||
|
||||
typedef RegularizationTag Regularization_tag;
|
||||
typedef CGAL::Tag_false Supports_general_polygon_tag;
|
||||
typedef CGAL::Tag_true Supports_simple_polygon_tag;
|
||||
|
||||
Simple_polygon_visibility_2_() : p_arr(NULL), geom_traits(NULL) {};
|
||||
|
||||
/*! Constructor given an arrangement and the Regularization tag. */
|
||||
Simple_polygon_visibility_2_(const Arrangement_2& arr):
|
||||
p_arr(&arr) {
|
||||
geom_traits = p_arr->geometry_traits();
|
||||
};
|
||||
|
||||
bool is_attached() {
|
||||
return (p_arr != NULL);
|
||||
}
|
||||
|
||||
void attach(const Arrangement_2& arr) {
|
||||
p_arr = &arr;
|
||||
geom_traits = p_arr->geometry_traits();
|
||||
}
|
||||
|
||||
void detach() {
|
||||
p_arr = NULL;
|
||||
geom_traits = NULL;
|
||||
vertices.clear();
|
||||
}
|
||||
|
||||
const Arrangement_2& arr() {
|
||||
return *p_arr;
|
||||
}
|
||||
|
||||
Face_handle compute_visibility(const Point_2& q, const Face_const_handle face,
|
||||
Visibility_arrangement_2& out_arr) {
|
||||
|
||||
CGAL::Visibility_2::print_arrangement_by_face<Arrangement_2>(*p_arr);
|
||||
|
||||
typename Arrangement_2::Ccb_halfedge_const_circulator circ =
|
||||
face->outer_ccb();
|
||||
typename Arrangement_2::Ccb_halfedge_const_circulator curr = circ;
|
||||
typename Arrangement_2::Halfedge_const_handle he = curr;
|
||||
|
||||
std::vector<Point_2> temp_vertices;
|
||||
Point_2 min_intersect_pt;
|
||||
bool intersect_on_endpoint = false;
|
||||
Segment_2 curr_edge(he->source()->point(), he->target()->point());
|
||||
Segment_2 curr_min_edge(he->source()->point(), he->target()->point());
|
||||
Point_2 curr_vertex = he->target()->point();
|
||||
temp_vertices.push_back(curr_vertex);
|
||||
Number_type min_dist = CGAL::Visibility_2::Compute_squared_distance_2
|
||||
<Geometry_traits_2, Point_2, Segment_2>(geom_traits, q, curr_edge);
|
||||
int min_dist_index = 0;
|
||||
int index = 1;
|
||||
curr++;
|
||||
// Push all vertices and determine edge minimum in terms
|
||||
// of squared distance to query point
|
||||
do {
|
||||
he = curr;
|
||||
curr_edge = Segment_2(he->source()->point(), he->target()->point());
|
||||
Number_type curr_dist = CGAL::Visibility_2::Compute_squared_distance_2
|
||||
<Geometry_traits_2, Point_2, Segment_2>(geom_traits, q, curr_edge);
|
||||
|
||||
if (curr_dist < min_dist) {
|
||||
min_dist = curr_dist;
|
||||
min_dist_index = index;
|
||||
curr_min_edge = curr_edge;
|
||||
}
|
||||
temp_vertices.push_back(he->target()->point());
|
||||
index++;
|
||||
} while (++curr != circ);
|
||||
|
||||
// Only now compute the intersection point
|
||||
min_intersect_pt = CGAL::Visibility_2::Construct_projected_point_2
|
||||
<Geometry_traits_2, Segment_2, Point_2>(geom_traits, curr_min_edge, q);
|
||||
|
||||
bool intersect_pt_on_seg_endpoint = false;
|
||||
if (min_intersect_pt != curr_min_edge.source() &&
|
||||
min_intersect_pt != curr_min_edge.target()) {
|
||||
vertices.push_back(min_intersect_pt);
|
||||
}
|
||||
else {
|
||||
intersect_pt_on_seg_endpoint = true;
|
||||
}
|
||||
// Now create vector so that first vertex v0 is visible
|
||||
for (unsigned int k = min_dist_index ; k < temp_vertices.size() ; k++) {
|
||||
vertices.push_back(temp_vertices[k]);
|
||||
}
|
||||
for (unsigned int k = 0 ; k < min_dist_index ; k++) {
|
||||
vertices.push_back(temp_vertices[k]);
|
||||
}
|
||||
|
||||
// Push first vertex again to fulfill algo precondition
|
||||
if (min_intersect_pt != curr_min_edge.source() &&
|
||||
min_intersect_pt != curr_min_edge.target()) {
|
||||
vertices.push_back(min_intersect_pt);
|
||||
}
|
||||
else {
|
||||
vertices.push_back(vertices[0]);
|
||||
}
|
||||
std::cout << "******VERTICES***************\n";
|
||||
for (unsigned int i = 0 ; i < vertices.size() ; i++) {
|
||||
std::cout << vertices[i] << std::endl;
|
||||
}
|
||||
std::cout << "*********************\n";
|
||||
|
||||
compute_angular_displacement(q);
|
||||
print_angular_displacement();
|
||||
visibility_region_impl(q);
|
||||
|
||||
typename std::vector<Point_2> points;
|
||||
if (!s.empty()) {
|
||||
Point_2 prev_pt = s.top();
|
||||
if (prev_pt == min_intersect_pt) {
|
||||
if (intersect_pt_on_seg_endpoint) {
|
||||
points.push_back(prev_pt);
|
||||
}
|
||||
s.pop();
|
||||
if (!s.empty()) {
|
||||
prev_pt = s.top();
|
||||
points.push_back(prev_pt);
|
||||
}
|
||||
}
|
||||
if (!s.empty()) {
|
||||
s.pop();
|
||||
}
|
||||
while(!s.empty()) {
|
||||
Point_2 curr_pt = s.top();
|
||||
if (curr_pt == min_intersect_pt) {
|
||||
if (intersect_pt_on_seg_endpoint) {
|
||||
points.push_back(curr_pt);
|
||||
}
|
||||
s.pop();
|
||||
}
|
||||
else {
|
||||
points.push_back(curr_pt);
|
||||
prev_pt = curr_pt;
|
||||
s.pop();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
std::reverse(points.begin(), points.end());
|
||||
std::cout << "POINTS\n";
|
||||
for (unsigned int k = 0 ; k < points.size() ; k++) {
|
||||
std::cout << points[k] << std::endl;
|
||||
}
|
||||
std::cout << "END POINTS\n";
|
||||
CGAL::Visibility_2::report_while_handling_needles
|
||||
<Simple_polygon_visibility_2_>(geom_traits,
|
||||
q,
|
||||
points,
|
||||
out_arr);
|
||||
std::cout << "OUTPUT\n";
|
||||
CGAL::Visibility_2::print_arrangement_by_face<Visibility_arrangement_2>(out_arr);
|
||||
std::cout << "END OUTPUT\n";
|
||||
CGAL_precondition(out_arr.number_of_isolated_vertices() == 0);
|
||||
CGAL_precondition(s.size() == 0);
|
||||
conditional_regularize(out_arr, Regularization_tag());
|
||||
vertices.clear();
|
||||
if (out_arr.faces_begin()->is_unbounded()) {
|
||||
return ++out_arr.faces_begin();
|
||||
}
|
||||
else {
|
||||
return out_arr.faces_begin();
|
||||
}
|
||||
}
|
||||
|
||||
Face_handle compute_visibility(const Point_2& q, const Halfedge_const_handle he,
|
||||
Visibility_arrangement_2& out_arr ) {
|
||||
/*
|
||||
query_pt_is_vertex = false;
|
||||
if (q != he->source()->point()) {
|
||||
if (q != he->target()->point()) {
|
||||
vertices.push_back(q);
|
||||
vertices.push_back(he->target()->point());
|
||||
}
|
||||
else {
|
||||
vertices.push_back(q);
|
||||
query_pt_is_vertex = true;
|
||||
}
|
||||
}
|
||||
|
||||
typename Arrangement_2::Face_const_handle face = he->face();
|
||||
typename Arrangement_2::Ccb_halfedge_const_circulator circ =
|
||||
face->outer_ccb();
|
||||
typename Arrangement_2::Ccb_halfedge_const_circulator curr;
|
||||
typename Arrangement_2::Halfedge_const_handle he_handle = circ;
|
||||
|
||||
while (he_handle != he) {
|
||||
circ++;
|
||||
he_handle = circ;
|
||||
}
|
||||
circ++;
|
||||
curr = circ;
|
||||
do {
|
||||
he_handle = curr;
|
||||
Point_2 curr_vertex = he_handle->target()->point();
|
||||
vertices.push_back(curr_vertex);
|
||||
} while (++curr != circ);
|
||||
|
||||
vertices.pop_back();
|
||||
vertices.push_back(vertices[0]);
|
||||
std::cout << "******VERTICES***************\n";
|
||||
for (unsigned int i = 0 ; i < vertices.size() ; i++) {
|
||||
std::cout << vertices[i] << std::endl;
|
||||
}
|
||||
std::cout << "*********************\n";
|
||||
|
||||
visibility_region_impl(q);
|
||||
|
||||
std::cout << "STACK\n";
|
||||
while (!s.empty()) {
|
||||
std::cout << s.top() << std::endl;
|
||||
s.pop();
|
||||
}
|
||||
std::cout << "END STACK\n";
|
||||
|
||||
typename std::vector<Point_2> points;
|
||||
if (!s.empty()) {
|
||||
Point_2 prev_pt = s.top();
|
||||
if (prev_pt != q) {
|
||||
points.push_back(prev_pt);
|
||||
}
|
||||
else if (query_pt_is_vertex) {
|
||||
points.push_back(prev_pt);
|
||||
}
|
||||
if (!s.empty()) {
|
||||
s.pop();
|
||||
}
|
||||
while(!s.empty()) {
|
||||
Point_2 curr_pt = s.top();
|
||||
if (curr_pt != q) {
|
||||
points.push_back(curr_pt);
|
||||
}
|
||||
else if (query_pt_is_vertex) {
|
||||
points.push_back(curr_pt);
|
||||
}
|
||||
s.pop();
|
||||
}
|
||||
}
|
||||
|
||||
std::reverse(points.begin(), points.end());
|
||||
|
||||
std::cout << "POINTS\n";
|
||||
for (unsigned int i = 0 ; i < points.size() ; i++) {
|
||||
std::cout << points[i] << std::endl;
|
||||
}
|
||||
std::cout << "*****************\n";
|
||||
CGAL::Visibility_2::report_while_handling_needles
|
||||
<Simple_polygon_visibility_2>(geom_traits,
|
||||
q,
|
||||
points,
|
||||
out_arr);
|
||||
CGAL_precondition(out_arr.number_of_isolated_vertices() == 0);
|
||||
CGAL_precondition(s.size() == 0);
|
||||
conditional_regularize(out_arr, Regularization_tag());
|
||||
vertices.clear();
|
||||
// CGAL::Visibility_2::print_arrangement_by_face<Visibility_arrangement_2>(out_arr);
|
||||
if (out_arr.faces_begin()->is_unbounded()) {
|
||||
return ++out_arr.faces_begin();
|
||||
}
|
||||
else {
|
||||
return out_arr.faces_begin();
|
||||
}*/
|
||||
}
|
||||
|
||||
private:
|
||||
const Arrangement_2 *p_arr;
|
||||
const Geometry_traits_2 *geom_traits;
|
||||
std::stack<Point_2> s;
|
||||
std::vector<Point_2> vertices;
|
||||
std::map<Point_2, double> angular_displacement;
|
||||
std::pair<Point_2, double> angular_displacement_vn;
|
||||
enum {ADVANCE, SCAN, RETARD, FINISH} upcase;
|
||||
enum {RAY, SEGMENT} polar_mode;
|
||||
|
||||
bool do_overlap(const Point_2& a, const Point_2& b, const Point_2& c) {
|
||||
if (CGAL::Visibility_2::Collinear(geom_traits, a, b, c)) {
|
||||
Segment_2 s1(a, b);
|
||||
Segment_2 s2(a, c);
|
||||
const Segment_2 *seg_overlap;
|
||||
Object_2 result = CGAL::Visibility_2::Intersect_2
|
||||
<Geometry_traits_2, Segment_2, Segment_2>(geom_traits, s1, s2);
|
||||
if (seg_overlap = CGAL::object_cast<Segment_2>(&result)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void conditional_regularize(Visibility_arrangement_2& out_arr, CGAL::Tag_true) {
|
||||
regularize_output(out_arr);
|
||||
}
|
||||
|
||||
void conditional_regularize(Visibility_arrangement_2& out_arr, CGAL::Tag_false) {
|
||||
//do nothing
|
||||
}
|
||||
|
||||
double angle(const Point_2& r, const Point_2& p, const Point_2& q) {
|
||||
|
||||
}
|
||||
|
||||
void compute_angular_displacement(const Point_2& q) {
|
||||
|
||||
Point_2 v0 = vertices[0];
|
||||
angular_displacement.insert(std::pair<Point_2, double>(v0, 0));
|
||||
|
||||
for (unsigned int k = 1 ; k < vertices.size() ; k++) {
|
||||
Vector_2 vec1(vertices[k-1].x() - q.x(), vertices[k-1].y() - q.y());
|
||||
Vector_2 vec2(vertices[k].x() - q.x(), vertices[k].y() - q.y());
|
||||
Number_type scalar_prod = vec1*vec2;
|
||||
Number_type len1 = vec1.squared_length();
|
||||
Number_type len2 = vec2.squared_length();
|
||||
double angle = acos(CGAL::to_double(scalar_prod)/
|
||||
sqrt(CGAL::to_double(len1*len2)));
|
||||
switch(CGAL::Visibility_2::Orientation_2(geom_traits,
|
||||
q,
|
||||
vertices[k-1],
|
||||
vertices[k])) {
|
||||
case CGAL::LEFT_TURN:
|
||||
if (k == vertices.size() - 1) {
|
||||
angular_displacement_vn = std::make_pair(vertices[k],
|
||||
angular_displacement[vertices[k-1]] + angle);
|
||||
}
|
||||
else {
|
||||
angular_displacement.insert(std::pair<Point_2, double>(vertices[k],
|
||||
angular_displacement[vertices[k-1]] + angle));
|
||||
}
|
||||
break;
|
||||
case CGAL::RIGHT_TURN:
|
||||
if (k == vertices.size() - 1) {
|
||||
angular_displacement_vn = std::make_pair(vertices[k],
|
||||
angular_displacement[vertices[k-1]] - angle);
|
||||
}
|
||||
else {
|
||||
angular_displacement.insert(std::pair<Point_2, double>(vertices[k],
|
||||
angular_displacement[vertices[k-1]] - angle));
|
||||
}
|
||||
break;
|
||||
case CGAL::COLLINEAR:
|
||||
if (k == vertices.size() - 1) {
|
||||
angular_displacement_vn = std::make_pair(vertices[k],
|
||||
angular_displacement[vertices[k-1]]);
|
||||
}
|
||||
else {
|
||||
angular_displacement.insert(std::pair<Point_2, double>(vertices[k],
|
||||
angular_displacement[vertices[k-1]]));
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
double get_angular_displacement(const Point_2& pt, const int i) {
|
||||
if (i == vertices.size() - 1) {
|
||||
return angular_displacement_vn.second;
|
||||
}
|
||||
else {
|
||||
return angular_displacement[pt];
|
||||
}
|
||||
}
|
||||
|
||||
void print_angular_displacement() {
|
||||
typename std::map<Point_2, double>::iterator it = angular_displacement.begin();
|
||||
for (it ; it != angular_displacement.end() ; it++) {
|
||||
std::cout << it->first << " - " << it->second << std::endl;
|
||||
}
|
||||
std::cout << angular_displacement_vn.first << " - "
|
||||
<< angular_displacement_vn.second << std::endl;
|
||||
}
|
||||
|
||||
void regularize_output(Visibility_arrangement_2& out_arr) {
|
||||
typename Visibility_arrangement_2::Edge_iterator e_itr;
|
||||
for (e_itr = out_arr.edges_begin() ;
|
||||
e_itr != out_arr.edges_end() ; e_itr++) {
|
||||
|
||||
Halfedge_handle he = e_itr;
|
||||
Halfedge_handle he_twin = he->twin();
|
||||
if (he->face() == he_twin->face()) {
|
||||
out_arr.remove_edge(he);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void visibility_region_impl(const Point_2& q) {
|
||||
|
||||
int i = 0;
|
||||
Point_2 w;
|
||||
|
||||
bool ccw = false;
|
||||
s.push(vertices[0]);
|
||||
if (angular_displacement[vertices[1]] >= angular_displacement[vertices[0]]){
|
||||
upcase = ADVANCE;
|
||||
}
|
||||
else {
|
||||
upcase = SCAN;
|
||||
ccw = true;
|
||||
w = Point_2(vertices[0]);
|
||||
polar_mode = RAY;
|
||||
}
|
||||
while (upcase != FINISH) {
|
||||
switch(upcase) {
|
||||
case ADVANCE:
|
||||
advance(q, i, ccw, w);
|
||||
break;
|
||||
case RETARD:
|
||||
retard(q, i, ccw, w);
|
||||
break;
|
||||
case SCAN:
|
||||
scan(q, i, ccw, w);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void advance(const Point_2& q, int& i, bool& ccw, Point_2& w) {
|
||||
|
||||
while (upcase == ADVANCE) {
|
||||
|
||||
if (get_angular_displacement(vertices[i+1], i+1) <= 2*CGAL_PI) {
|
||||
i++;
|
||||
s.push(vertices[i]);
|
||||
|
||||
if (i == vertices.size()-1) {
|
||||
upcase = FINISH;
|
||||
}
|
||||
else if (get_angular_displacement(vertices[i+1], i+1) < get_angular_displacement(vertices[i], i)
|
||||
&& CGAL::Visibility_2::Orientation_2(geom_traits,
|
||||
vertices[i-1],
|
||||
vertices[i],
|
||||
vertices[i+1]) == CGAL::RIGHT_TURN) {
|
||||
upcase = SCAN;
|
||||
ccw = true;
|
||||
w = Point_2(vertices[i]);
|
||||
polar_mode = RAY;
|
||||
}
|
||||
else if (get_angular_displacement(vertices[i+1], i+1) < get_angular_displacement(vertices[i], i)
|
||||
&& CGAL::Visibility_2::Orientation_2(geom_traits,
|
||||
vertices[i-1],
|
||||
vertices[i],
|
||||
vertices[i+1]) == CGAL::LEFT_TURN) {
|
||||
upcase = RETARD;
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (angular_displacement[s.top()] < 2*CGAL_PI) {
|
||||
// Compute intersection of v[i]v[i+1] and line qv[0]
|
||||
Segment_2 seg(vertices[i], vertices[i+1]);
|
||||
Ray_2 ray(q, vertices[0]);
|
||||
Object_2 result = CGAL::Visibility_2::Intersect_2
|
||||
<Geometry_traits_2, Segment_2, Ray_2>(geom_traits, seg, ray);
|
||||
if (const Point_2 *ipoint = CGAL::object_cast<Point_2>(&result)) {
|
||||
s.push(*ipoint);
|
||||
angular_displacement.insert(std::make_pair(*ipoint, 2*CGAL_PI));
|
||||
}
|
||||
}
|
||||
upcase = SCAN;
|
||||
ccw = false;
|
||||
w = vertices[0];
|
||||
polar_mode = SEGMENT;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void retard(const Point_2& q, int& i, bool& ccw, Point_2& w) {
|
||||
|
||||
while (upcase == RETARD && !s.empty()) {
|
||||
|
||||
Point_2 s_j_prev = s.top();
|
||||
|
||||
if (!s.empty()) {
|
||||
s.pop();
|
||||
Point_2 s_j = s.top();
|
||||
|
||||
if (angular_displacement[s_j] < get_angular_displacement(vertices[i+1], i+1)
|
||||
&& get_angular_displacement(vertices[i+1], i+1) > angular_displacement[s_j]) {
|
||||
|
||||
i++;
|
||||
// Compute intersection of s[j]s[j+1] and line qv[i]
|
||||
Segment_2 seg(s_j, s_j_prev);
|
||||
Ray_2 ray(q, vertices[i]);
|
||||
Object_2 result = CGAL::Visibility_2::Intersect_2
|
||||
<Geometry_traits_2, Segment_2, Ray_2>(geom_traits, seg, ray);
|
||||
|
||||
if (const Point_2 *ipoint = CGAL::object_cast<Point_2>(&result)) {
|
||||
|
||||
angular_displacement.insert(std::pair<Point_2, double>(*ipoint, CGAL::to_double(2*CGAL_PI)));
|
||||
s.push(*ipoint);
|
||||
}
|
||||
s.push(vertices[i]);
|
||||
if (i == vertices.size() - 1) {
|
||||
upcase = FINISH;
|
||||
}
|
||||
else if (get_angular_displacement(vertices[i], i) <= get_angular_displacement(vertices[i+1], i+1)
|
||||
&& CGAL::Visibility_2::Orientation_2(geom_traits,
|
||||
vertices[i-1],
|
||||
vertices[i],
|
||||
vertices[i+1]) == CGAL::RIGHT_TURN) {
|
||||
|
||||
upcase = ADVANCE;
|
||||
}
|
||||
else if (get_angular_displacement(vertices[i], i) < get_angular_displacement(vertices[i+1], i+1)
|
||||
&& CGAL::Visibility_2::Orientation_2(geom_traits,
|
||||
vertices[i-1],
|
||||
vertices[i],
|
||||
vertices[i+1]) == CGAL::LEFT_TURN) {
|
||||
|
||||
upcase = SCAN;
|
||||
ccw = false;
|
||||
w = vertices[i];
|
||||
polar_mode = SEGMENT;
|
||||
s.pop();
|
||||
}
|
||||
else {
|
||||
s.pop();
|
||||
}
|
||||
}
|
||||
else {
|
||||
|
||||
if (get_angular_displacement(vertices[i+1], i+1) == angular_displacement[s_j]
|
||||
&& get_angular_displacement(vertices[i+2], i+2) > get_angular_displacement(vertices[i+1], i+1)
|
||||
&& CGAL::Visibility_2::Orientation_2(geom_traits,
|
||||
vertices[i],
|
||||
vertices[i+1],
|
||||
vertices[i+2]) == CGAL::RIGHT_TURN) {
|
||||
upcase = ADVANCE;
|
||||
i++;
|
||||
s.push(vertices[i]);
|
||||
}
|
||||
else {
|
||||
Segment_2 seg_fst(vertices[i], vertices[i+1]);
|
||||
Segment_2 seg_snd(s_j, s_j_prev);
|
||||
Object_2 result = CGAL::Visibility_2::Intersect_2
|
||||
<Geometry_traits_2, Segment_2, Segment_2>(geom_traits, seg_fst, seg_snd);
|
||||
|
||||
if (const Point_2 *ipoint = CGAL::object_cast<Point_2>(&result)) {
|
||||
w = *ipoint;
|
||||
polar_mode = SEGMENT;
|
||||
upcase = SCAN;
|
||||
ccw = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void scan(const Point_2& q, int& i, bool& ccw, Point_2& w) {
|
||||
|
||||
while (upcase == SCAN && i < vertices.size()-2) {
|
||||
i++;
|
||||
|
||||
if (ccw && get_angular_displacement(vertices[i+1], i+1) > angular_displacement[s.top()]
|
||||
&& angular_displacement[s.top()] >= get_angular_displacement(vertices[i], i)) {
|
||||
|
||||
Segment_2 seg(vertices[i], vertices[i+1]);
|
||||
if (polar_mode == RAY) {
|
||||
Ray_2 w_ray(q, w);
|
||||
Object_2 result = CGAL::Visibility_2::Intersect_2
|
||||
<Geometry_traits_2, Segment_2, Ray_2>(geom_traits, seg, w_ray);
|
||||
if (const Point_2 *ipoint = CGAL::object_cast<Point_2>(&result)) {
|
||||
upcase = ADVANCE;
|
||||
s.push(*ipoint);
|
||||
}
|
||||
}
|
||||
else {
|
||||
Segment_2 w_seg(s.top(), w);
|
||||
Object_2 result = CGAL::Visibility_2::Intersect_2
|
||||
<Geometry_traits_2, Segment_2, Segment_2>(geom_traits, seg, w_seg);
|
||||
if (const Point_2 *ipoint = CGAL::object_cast<Point_2>(&result)) {
|
||||
upcase = ADVANCE;
|
||||
s.push(*ipoint);
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (!ccw && get_angular_displacement(vertices[i+1], i+1) <= angular_displacement[s.top()]
|
||||
&& angular_displacement[s.top()] < get_angular_displacement(vertices[i], i)) {
|
||||
|
||||
Segment_2 seg(vertices[i], vertices[i+1]);
|
||||
if (polar_mode == RAY) {
|
||||
Ray_2 w_ray(q, w);
|
||||
Object_2 result = CGAL::Visibility_2::Intersect_2
|
||||
<Geometry_traits_2, Segment_2, Ray_2>(geom_traits, seg, w_ray);
|
||||
if (const Point_2 *ipoint = CGAL::object_cast<Point_2>(&result)) {
|
||||
upcase = RETARD;
|
||||
}
|
||||
}
|
||||
else {
|
||||
Segment_2 w_seg(s.top(), w);
|
||||
Object_2 result = CGAL::Visibility_2::Intersect_2
|
||||
<Geometry_traits_2, Segment_2, Segment_2>(geom_traits, seg, w_seg);
|
||||
if (const Point_2 *ipoint = CGAL::object_cast<Point_2>(&result)) {
|
||||
upcase = RETARD;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
} // namespace CGAL
|
||||
|
||||
#endif
|
||||
|
|
@ -28,14 +28,14 @@
|
|||
|
||||
namespace CGAL {
|
||||
|
||||
template<class Arrangement_2_ ,class RegularizationTag>
|
||||
template<class Arrangement_2_ , typename Visibility_arrangement_2_ = Arrangement_2_ ,class RegularizationTag = CGAL::Tag_true >
|
||||
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_ Arrangement_2;
|
||||
typedef Arrangement_2_ Visibility_arrangement_2;
|
||||
typedef Visibility_arrangement_2_ Visibility_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
|
||||
|
|
@ -348,7 +348,8 @@ public:
|
|||
|
||||
}
|
||||
|
||||
Face_handle compute_visibility(const Point_2& q,
|
||||
typename Visibility_arrangement_2::Face_handle
|
||||
compute_visibility(const Point_2& q,
|
||||
const Face_const_handle face,
|
||||
Visibility_arrangement_2& out_arr
|
||||
){
|
||||
|
|
@ -396,7 +397,8 @@ public:
|
|||
return output(raw_output,out_arr);
|
||||
}
|
||||
|
||||
Face_handle compute_visibility(const Point_2& q,
|
||||
typename Visibility_arrangement_2::Face_handle
|
||||
compute_visibility(const Point_2& q,
|
||||
const Halfedge_const_handle he,
|
||||
Visibility_arrangement_2& out_arr) {
|
||||
//std::cout << "visibility_region he" << std::endl;
|
||||
|
|
@ -513,7 +515,8 @@ public:
|
|||
return output(raw_output,out_arr);
|
||||
}
|
||||
|
||||
Face_handle output(std::vector<Point_2>& raw_output, Visibility_arrangement_2& out_arr){
|
||||
typename Visibility_arrangement_2::Face_handle
|
||||
output(std::vector<Point_2>& raw_output, Visibility_arrangement_2& out_arr){
|
||||
|
||||
if(needles.size()>0){
|
||||
std::vector<Segment_2> segments(needles.begin(),needles.end());
|
||||
|
|
@ -526,7 +529,7 @@ public:
|
|||
CGAL::insert_non_intersecting_curves(out_arr,segments.begin(),segments.end());
|
||||
//CGAL::insert(out_arr,segments.begin(),segments.end());
|
||||
}else{
|
||||
Vertex_handle v_last, v_first;
|
||||
typename Visibility_arrangement_2::Vertex_handle v_last, v_first;
|
||||
v_last = v_first =
|
||||
out_arr.insert_in_face_interior(raw_output[0], out_arr.unbounded_face());
|
||||
|
||||
|
|
|
|||
|
|
@ -33,12 +33,17 @@ template <class Visibility_2>
|
|||
void test_model_methods_for_arr(
|
||||
typename Visibility_2::Arrangement_2 &arr) {
|
||||
|
||||
typedef typename Visibility_2::Arrangement_2 Arrangement_2;
|
||||
typedef typename Visibility_2::Visibility_arrangement_2 Visibility_arrangement_2;
|
||||
typedef typename Arrangement_2::Point_2 Point_2;
|
||||
typedef typename Visibility_2::Arrangement_2
|
||||
Arrangement_2;
|
||||
typedef typename Visibility_2::Visibility_arrangement_2
|
||||
Visibility_arrangement_2;
|
||||
typedef typename Arrangement_2::Point_2
|
||||
Point_2;
|
||||
typedef typename Arrangement_2::Geometry_traits_2::Segment_2
|
||||
Segment_2;
|
||||
typedef typename Arrangement_2::Face_handle Face_handle;
|
||||
|
||||
typedef typename Visibility_arrangement_2::Face_handle VFH;
|
||||
|
||||
|
||||
Visibility_2 visibility;
|
||||
assert(false == visibility.is_attached());
|
||||
|
|
@ -60,8 +65,8 @@ void test_model_methods_for_arr(
|
|||
// First consider query point in the unbounded face
|
||||
const Point_2 query_pt(1, 1);
|
||||
// Check returned face_handle
|
||||
Face_handle face_check = visibility.compute_visibility(query_pt, fit, arr_out);
|
||||
Face_handle face;
|
||||
VFH face_check = visibility.compute_visibility(query_pt, fit, arr_out);
|
||||
VFH face;
|
||||
if (arr_out.faces_begin()->is_unbounded()) {
|
||||
face = ++arr_out.faces_begin();
|
||||
}
|
||||
|
|
@ -90,7 +95,7 @@ void test_model_methods_for_arr(
|
|||
const Point_2 query_pt2 = Point_2(0, 4);
|
||||
arr_out.clear();
|
||||
typename Arrangement_2::Halfedge_const_iterator hit;
|
||||
Face_handle face_check_he;
|
||||
VFH face_check_he;
|
||||
for (hit = arr.halfedges_begin();
|
||||
hit != arr.halfedges_end(); ++hit) {
|
||||
|
||||
|
|
@ -118,7 +123,7 @@ void test_model_methods_for_arr(
|
|||
for (hit_snd = arr.halfedges_begin(); hit_snd != arr.halfedges_end(); ++hit_snd) {
|
||||
if(!hit_snd->face()->is_unbounded()){
|
||||
arr_out.clear();
|
||||
Face_handle face_check_he_snd = visibility.compute_visibility(hit_snd->target()->point(), hit_snd, arr_out);
|
||||
VFH face_check_he_snd = visibility.compute_visibility(hit_snd->target()->point(), hit_snd, arr_out);
|
||||
assert(!face_check_he_snd->is_unbounded());
|
||||
if (arr_out.faces_begin()->is_unbounded()) {
|
||||
face = ++arr_out.faces_begin();
|
||||
|
|
@ -138,7 +143,10 @@ template <class Visibility_2>
|
|||
void test_model_methods() {
|
||||
|
||||
// Check concept obediance
|
||||
typedef typename Visibility_2::Arrangement_2 Arrangement_2;
|
||||
typedef typename Visibility_2::Arrangement_2
|
||||
Arrangement_2;
|
||||
typedef typename Visibility_2::Visibility_arrangement_2
|
||||
Visibility_arrangement_2;
|
||||
typedef typename Arrangement_2::Point_2 Point_2;
|
||||
typedef typename Arrangement_2::Face_handle Face_handle;
|
||||
typedef typename Arrangement_2::Halfedge_handle Halfedge_handle;
|
||||
|
|
|
|||
|
|
@ -88,18 +88,17 @@ typename Arrangement_2::Halfedge_handle get_initial_halfedge(const Arrangement_2
|
|||
* Function to compare two arrangements; first determines lowest vertex
|
||||
* from each arrangements, then it walks the edges and compares them
|
||||
*/
|
||||
template <class _Arrangement_2>
|
||||
bool test_are_equal(const _Arrangement_2 &arr1, const _Arrangement_2 &arr2) {
|
||||
template <class ARR1, class ARR2>
|
||||
bool test_are_equal(const ARR1 &arr1, const ARR2 &arr2) {
|
||||
|
||||
typedef _Arrangement_2 Arrangement_2;
|
||||
typedef typename Arrangement_2::Geometry_traits_2 Geometry_traits_2;
|
||||
typedef typename Arrangement_2::Vertex_const_iterator Vertex_const_iterator;
|
||||
typedef typename Arrangement_2::Edge_const_iterator Edge_const_iterator;
|
||||
typedef typename Arrangement_2::Halfedge Halfedge;
|
||||
typedef typename Arrangement_2::Halfedge_handle Halfedge_handle;
|
||||
typedef typename ARR1::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 ARR1::Halfedge_handle HE1;
|
||||
typedef typename ARR2::Halfedge_handle HE2;
|
||||
|
||||
|
||||
// First make sure they have the same size
|
||||
if (arr1.number_of_vertices() != arr2.number_of_vertices()) {
|
||||
return false;
|
||||
|
|
@ -119,16 +118,16 @@ bool test_are_equal(const _Arrangement_2 &arr1, const _Arrangement_2 &arr2) {
|
|||
assert(arr2.number_of_faces() == 2);
|
||||
|
||||
// get unique halfedge
|
||||
Halfedge_handle he_start_1 = get_initial_halfedge(arr1);
|
||||
Halfedge_handle he_start_2 = get_initial_halfedge(arr2);
|
||||
HE1 he_start_1 = get_initial_halfedge(arr1);
|
||||
HE2 he_start_2 = get_initial_halfedge(arr2);
|
||||
|
||||
// run on first loop and compare sources
|
||||
assert(arr1.traits()->compare_xy_2_object()(
|
||||
he_start_1->source()->point(),
|
||||
he_start_2->source()->point()) == CGAL::EQUAL);
|
||||
|
||||
Halfedge_handle he_run_1 = he_start_1->next();
|
||||
Halfedge_handle he_run_2 = he_start_2->next();
|
||||
HE1 he_run_1 = he_start_1->next();
|
||||
HE2 he_run_2 = he_start_2->next();
|
||||
|
||||
while(he_run_1 != he_start_1){
|
||||
|
||||
|
|
|
|||
|
|
@ -60,7 +60,7 @@ void define_snd_class(std::string name2, CGAL::Query_choice& qchoice, std::ifstr
|
|||
deploy_benchmark<Visibility_fst, CGAL::Naive_visibility_2<Arrangement_2, Regularization_tag> >
|
||||
(qchoice, input);
|
||||
if (name2 == "T")
|
||||
deploy_benchmark<Visibility_fst, CGAL::Triangular_expansion_visibility_2<Arrangement_2, Regularization_tag> >
|
||||
deploy_benchmark<Visibility_fst, CGAL::Triangular_expansion_visibility_2<Arrangement_2,Arrangement_2, Regularization_tag> >
|
||||
(qchoice, input);
|
||||
if (name2 == "R")
|
||||
deploy_benchmark<Visibility_fst, CGAL::Rotational_sweep_visibility_2<Arrangement_2, Regularization_tag> >
|
||||
|
|
@ -74,7 +74,7 @@ void benchmark_two_classes(std::string name1, std::string name2, CGAL::Query_cho
|
|||
if (name1 == "N")
|
||||
define_snd_class<CGAL::Naive_visibility_2<Arrangement_2, Regularization_tag>, Regularization_tag> (name2, qchoice, input);
|
||||
if (name1 == "T")
|
||||
define_snd_class<CGAL::Triangular_expansion_visibility_2<Arrangement_2, Regularization_tag>, Regularization_tag> (name2, qchoice, input);
|
||||
define_snd_class<CGAL::Triangular_expansion_visibility_2<Arrangement_2, Arrangement_2, Regularization_tag>, Regularization_tag> (name2, qchoice, input);
|
||||
if (name1 == "R")
|
||||
define_snd_class<CGAL::Rotational_sweep_visibility_2<Arrangement_2, Regularization_tag>, Regularization_tag> (name2, qchoice, input);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -48,7 +48,8 @@ int main(int argc, char* argv[]) {
|
|||
Simple_polygon_visibility_2;
|
||||
typedef CGAL::Naive_visibility_2<Arrangement_2, CGAL::Tag_false>
|
||||
Naive_visibility_2;
|
||||
typedef CGAL::Triangular_expansion_visibility_2<Arrangement_2, CGAL::Tag_false>
|
||||
typedef CGAL::Triangular_expansion_visibility_2
|
||||
<Arrangement_2, Arrangement_2, CGAL::Tag_false>
|
||||
Triangular_expansion_visibility_2;
|
||||
|
||||
if (argc == 2) {
|
||||
|
|
|
|||
|
|
@ -28,6 +28,7 @@
|
|||
#include <CGAL/test_model_methods.h>
|
||||
#include <CGAL/test_utils.h>
|
||||
#include <CGAL/Triangular_expansion_visibility_2.h>
|
||||
#include <CGAL/Arr_extended_dcel.h>
|
||||
|
||||
#include <iostream>
|
||||
#include <fstream>
|
||||
|
|
@ -39,13 +40,13 @@ int main() {
|
|||
typedef CGAL::Arr_segment_traits_2<Kernel> Traits_2;
|
||||
typedef CGAL::Arrangement_2<Traits_2> Arrangement_2;
|
||||
{
|
||||
typedef CGAL::Triangular_expansion_visibility_2<Arrangement_2, CGAL::Tag_true>
|
||||
typedef CGAL::Triangular_expansion_visibility_2<Arrangement_2 , Arrangement_2 , CGAL::Tag_true>
|
||||
Visibility_2;
|
||||
CGAL::test_model_methods<Visibility_2>();
|
||||
CGAL::run_tests<Visibility_2>(17, 2);
|
||||
}
|
||||
{
|
||||
typedef CGAL::Triangular_expansion_visibility_2<Arrangement_2 , CGAL::Tag_false>
|
||||
typedef CGAL::Triangular_expansion_visibility_2<Arrangement_2 , Arrangement_2 , CGAL::Tag_false>
|
||||
Visibility_2;
|
||||
CGAL::test_model_methods<Visibility_2>();
|
||||
CGAL::run_tests<Visibility_2>(17, 2);
|
||||
|
|
@ -56,16 +57,35 @@ int main() {
|
|||
typedef CGAL::Arr_segment_traits_2<Kernel> Traits_2;
|
||||
typedef CGAL::Arrangement_2<Traits_2> Arrangement_2;
|
||||
{
|
||||
typedef CGAL::Triangular_expansion_visibility_2<Arrangement_2 , CGAL::Tag_true>
|
||||
typedef CGAL::Triangular_expansion_visibility_2<Arrangement_2 , Arrangement_2 , CGAL::Tag_true>
|
||||
Visibility_2;
|
||||
CGAL::test_model_methods<Visibility_2>();
|
||||
CGAL::run_tests<Visibility_2>(17, 2);
|
||||
}{
|
||||
typedef CGAL::Triangular_expansion_visibility_2<Arrangement_2 , CGAL::Tag_false>
|
||||
typedef CGAL::Triangular_expansion_visibility_2<Arrangement_2 , Arrangement_2 , CGAL::Tag_false>
|
||||
Visibility_2;
|
||||
CGAL::test_model_methods<Visibility_2>();
|
||||
CGAL::run_tests<Visibility_2>(17, 2);
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
// test Visibility_arrangement_type with extended DCEL
|
||||
typedef CGAL::Exact_predicates_exact_constructions_kernel Kernel;
|
||||
typedef CGAL::Arr_segment_traits_2<Kernel> Traits_2;
|
||||
typedef CGAL::Arrangement_2<Traits_2> ARR;
|
||||
typedef CGAL::Arr_extended_dcel<Traits_2, bool, bool, bool> EDCEL;
|
||||
typedef CGAL::Arrangement_2<Traits_2, EDCEL> EARR;
|
||||
{
|
||||
typedef CGAL::Triangular_expansion_visibility_2<ARR,EARR,CGAL::Tag_true> Visibility_2;
|
||||
CGAL::test_model_methods<Visibility_2>();
|
||||
CGAL::run_tests<Visibility_2>(17, 2);
|
||||
}{
|
||||
typedef CGAL::Triangular_expansion_visibility_2<ARR,EARR,CGAL::Tag_false> Visibility_2;
|
||||
CGAL::test_model_methods<Visibility_2>();
|
||||
CGAL::run_tests<Visibility_2>(17, 2);
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
Loading…
Reference in New Issue