mirror of https://github.com/CGAL/cgal
184 lines
6.9 KiB
C++
184 lines
6.9 KiB
C++
// Copyright (c) 2013-2015 The University of Western Sydney, Australia.
|
|
// 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$
|
|
//
|
|
//
|
|
// Authors: Weisheng Si, Quincy Tse
|
|
|
|
/*! \file Compute_cone_boundaries_2.h
|
|
*
|
|
* This header implements the functor for constructing theta graphs.
|
|
*/
|
|
|
|
#ifndef CGAL_COMPUTE_CONE_BOUNDARIES_2_H
|
|
#define CGAL_COMPUTE_CONE_BOUNDARIES_2_H
|
|
|
|
// if leda::real is used, pls modify the following definition
|
|
#define CGAL_USE_CORE 1
|
|
|
|
#include <iostream>
|
|
#include <cstdlib>
|
|
#include <utility>
|
|
#include <CGAL/Polynomial.h>
|
|
#include <CGAL/number_utils.h>
|
|
#include <CGAL/enum.h>
|
|
#include <CGAL/Exact_predicates_exact_constructions_kernel_with_sqrt.h>
|
|
#include <CGAL/Aff_transformation_2.h>
|
|
|
|
namespace CGAL {
|
|
|
|
/*! \ingroup PkgConeBasedSpanners
|
|
* \brief The functor for computing the directions of cone boundaries with a given
|
|
* cone number and a given initial direction. The results are stored in the vector
|
|
* \p rays.
|
|
*
|
|
* This computation can be either inexact by simply dividing an approximate Pi by the cone number
|
|
* (which is quick), or exact by using roots of polynomials (entailing number types such as `CORE::Expr` or `LEDA::Real`,
|
|
* which are slow). The inexact computation is done by the general functor definition,
|
|
* while the exact computation is done by a specialization of this functor.
|
|
* If the template parameter `Kernel_` is `Exact_predicates_exact_constructions_kernel_with_sqrt`,
|
|
* the specialization functor will be invoked.
|
|
*
|
|
* In the construction of Yao graph and Theta graph implemented by this package,
|
|
* all predicates and construction functions are from \cgal.
|
|
* Therefore, if the kernel `Exact_predicates_exact_constructions_kernel_with_sqrt` is used,
|
|
* the Yao or Theta graph will be constructed exactly, otherwise inexactly.
|
|
*
|
|
*/
|
|
template <typename Kernel_>
|
|
class Compute_cone_boundaries_2 {
|
|
public:
|
|
typedef Kernel_ kernel_type;
|
|
typedef typename Kernel_::FT FT;
|
|
typedef typename Kernel_::Direction_2 Direction_2;
|
|
typedef typename Kernel_::Aff_transformation_2 Transformation;
|
|
|
|
/* No member variables in this class, so a Constructor is not needed. */
|
|
//Compute_cone_boundaries_2() {};
|
|
|
|
/*! \brief The operator().
|
|
*
|
|
* The direction of the first ray can be specified by the parameter
|
|
* \p initial_direction, which allows the first ray to start at any direction. The remaining rays are calculated in
|
|
* counter-clockwise order.
|
|
*
|
|
* \param[in] cone_number The number of cones
|
|
* \param[in] initial_direction The direction of the first ray
|
|
* \param[out] rays The results, a vector of directions
|
|
*/
|
|
void operator()(const unsigned int cone_number,
|
|
Direction_2& initial_direction,
|
|
std::vector<Direction_2>& rays) {
|
|
if (cone_number<2) {
|
|
std::cout << "The number of cones should be larger than 1!" << std::endl;
|
|
std::exit(1);
|
|
}
|
|
|
|
if (rays.size() > 0) {
|
|
std::cout << "Initially, the vector rays must contain no elements!" << std::endl;
|
|
std::exit(1);
|
|
}
|
|
|
|
rays.push_back(initial_direction);
|
|
|
|
const double cone_angle = 2*CGAL_PI/cone_number;
|
|
double sin_value, cos_value;
|
|
for (unsigned int i = 1; i < cone_number; i++) {
|
|
sin_value = std::sin(i*cone_angle);
|
|
cos_value = std::cos(i*cone_angle);
|
|
Direction_2 ray_i = Transformation(cos_value, -sin_value, sin_value, cos_value)(initial_direction);
|
|
rays.push_back(ray_i);
|
|
}
|
|
}
|
|
|
|
};
|
|
|
|
template <>
|
|
class Compute_cone_boundaries_2<Exact_predicates_exact_constructions_kernel_with_sqrt> {
|
|
public:
|
|
typedef Exact_predicates_exact_constructions_kernel_with_sqrt kernel_type;
|
|
typedef typename Exact_predicates_exact_constructions_kernel_with_sqrt::FT FT;
|
|
typedef typename Exact_predicates_exact_constructions_kernel_with_sqrt::Direction_2 Direction_2;
|
|
typedef typename Exact_predicates_exact_constructions_kernel_with_sqrt::Aff_transformation_2 Transformation;
|
|
|
|
/*! \brief Constructor. */
|
|
Compute_cone_boundaries_2() {};
|
|
|
|
void operator()(const unsigned int cone_number,
|
|
Direction_2& initial_direction,
|
|
std::vector< Direction_2 >& rays) {
|
|
|
|
if (cone_number<2) {
|
|
std::cout << "The number of cones should be larger than 1!" << std::endl;
|
|
std::exit(1);
|
|
}
|
|
|
|
if (rays.size() > 0) {
|
|
std::cout << "Initially, the vector rays must contain no elements!" << std::endl;
|
|
std::exit(1);
|
|
}
|
|
|
|
//std::cout << "Specialization is called!" << std::endl;
|
|
|
|
// We actually use -x instead of x since CGAL::root_of() will give the k-th
|
|
// smallest root but we want the second largest one without counting.
|
|
Polynomial<FT> x(CGAL::shift(Polynomial<FT>(-1), 1));
|
|
Polynomial<FT> twox(2*x);
|
|
Polynomial<FT> a(1), b(x);
|
|
for (unsigned int i = 2; i <= cone_number; ++i) {
|
|
Polynomial<FT> c = twox*b - a;
|
|
a = b;
|
|
b = c;
|
|
}
|
|
a = b - 1;
|
|
|
|
unsigned int m, i;
|
|
if (cone_number % 2 == 0)
|
|
m = cone_number/2; // for even number of cones
|
|
else
|
|
m= cone_number/2 + 1; // for odd number of cones
|
|
|
|
FT cos_value, sin_value;
|
|
Direction_2 ray_i;
|
|
// add the first half number of rays in counter clockwise order
|
|
for (i = 1; i <= m; i++) {
|
|
cos_value = - root_of(i, a.begin(), a.end());
|
|
sin_value = sqrt(FT(1) - cos_value*cos_value);
|
|
ray_i = Transformation(cos_value, -sin_value, sin_value, cos_value)(initial_direction);
|
|
rays.push_back(ray_i);
|
|
}
|
|
|
|
// add the remaining half number of rays in ccw order
|
|
if (cone_number % 2 == 0) {
|
|
for (i = 0; i < m; i++) {
|
|
rays.push_back(-rays[i]);
|
|
}
|
|
} else {
|
|
for (i = 0; i < m-1; i++) {
|
|
cos_value = - root_of(m-i, a.begin(), a.end());
|
|
sin_value = - sqrt(FT(1) - cos_value*cos_value);
|
|
ray_i = Transformation(cos_value, -sin_value, sin_value, cos_value)(initial_direction);
|
|
rays.push_back(ray_i);
|
|
}
|
|
}
|
|
|
|
}; // end of operator()
|
|
}; // end of functor specialization: Compute_cone_..._2
|
|
|
|
} // namespace CGAL
|
|
|
|
#endif
|