mirror of https://github.com/CGAL/cgal
Merge pull request #4421 from MaelRL/Triangulation_on_sphere_2-GF
new package: Triangulation on the sphere
This commit is contained in:
commit
b8bc56ca12
|
|
@ -39,7 +39,6 @@ CGAL_add_named_parameter(face_to_face_map_t, face_to_face_map, face_to_face_map)
|
|||
CGAL_add_named_parameter(implementation_tag_t, implementation_tag, implementation_tag)
|
||||
CGAL_add_named_parameter(prevent_unselection_t, prevent_unselection, prevent_unselection)
|
||||
|
||||
CGAL_add_named_parameter(stream_precision_t, stream_precision, stream_precision)
|
||||
CGAL_add_named_parameter(verbose_t, verbose, verbose)
|
||||
|
||||
// List of named parameters used for IO
|
||||
|
|
@ -52,6 +51,8 @@ CGAL_add_named_parameter(vertex_color_map_t, vertex_color_map, vertex_color_map)
|
|||
CGAL_add_named_parameter(vertex_texture_map_t, vertex_texture_map, vertex_texture_map)
|
||||
CGAL_add_named_parameter(face_color_map_t, face_color_map, face_color_map)
|
||||
CGAL_add_named_parameter(repair_polygon_soup_t, repair_polygon_soup, repair_polygon_soup)
|
||||
CGAL_add_named_parameter(output_color_t, output_color, output_color)
|
||||
CGAL_add_named_parameter(stream_precision_t, stream_precision, stream_precision)
|
||||
|
||||
// List of named parameters that we use in the package 'Mesh_3'
|
||||
CGAL_add_named_parameter(vertex_feature_degree_t, vertex_feature_degree, vertex_feature_degree_map)
|
||||
|
|
|
|||
|
|
@ -3692,9 +3692,9 @@ namespace CartesianKernelFunctors {
|
|||
// p,q,r supposed to be non collinear
|
||||
// tests whether s is on the same side of p,q as r
|
||||
// returns :
|
||||
// COLLINEAR if pqr collinear
|
||||
// POSITIVE if qrp and qrs have the same orientation
|
||||
// NEGATIVE if qrp and qrs have opposite orientations
|
||||
// COLLINEAR if qps collinear
|
||||
// POSITIVE if qpr and qps have the same orientation
|
||||
// NEGATIVE if qpr and qps have opposite orientations
|
||||
CGAL_kernel_exactness_precondition( ! cl(p, q, r) );
|
||||
CGAL_kernel_exactness_precondition( cp(p, q, r, s) );
|
||||
return coplanar_orientationC3(p.x(), p.y(), p.z(),
|
||||
|
|
|
|||
|
|
@ -295,9 +295,6 @@ void Viewer::initialize_buffers()
|
|||
buffers[6].release();
|
||||
}
|
||||
vao[2].release();
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
void Viewer::compute_elements()
|
||||
|
|
@ -841,7 +838,6 @@ void Viewer::draw()
|
|||
rendering_program.release();
|
||||
vao[1].release();
|
||||
|
||||
|
||||
}
|
||||
|
||||
void Viewer::init()
|
||||
|
|
|
|||
|
|
@ -73,8 +73,8 @@ namespace CGAL {
|
|||
: _full(false)
|
||||
{
|
||||
// l must pass through s and t, and s != t
|
||||
CGAL_kernel_precondition(SK().has_on_3_object()(c,s));
|
||||
CGAL_kernel_precondition(SK().has_on_3_object()(c,t));
|
||||
// CGAL_kernel_precondition(SK().has_on_3_object()(c,s));
|
||||
// CGAL_kernel_precondition(SK().has_on_3_object()(c,t));
|
||||
CGAL_kernel_precondition(s != t);
|
||||
base = Rep(c,s,t);
|
||||
// we can optimize the computations of the sign (for the has_on functor),
|
||||
|
|
|
|||
|
|
@ -67,6 +67,7 @@
|
|||
|
||||
\package_listing{Triangulation_2}
|
||||
\package_listing{TDS_2}
|
||||
\package_listing{Triangulation_on_sphere_2}
|
||||
\package_listing{Periodic_2_triangulation_2}
|
||||
\package_listing{Hyperbolic_triangulation_2}
|
||||
\package_listing{Periodic_4_hyperbolic_triangulation_2}
|
||||
|
|
|
|||
|
|
@ -353,6 +353,15 @@ Boissonnat}
|
|||
,url = "https://tel.archives-ouvertes.fr/tel-00552215/"
|
||||
}
|
||||
|
||||
@inproceedings{cgal:ccplr-redtp-10,
|
||||
title={Robust and efficient {Delaunay} triangulations of points on or close to a sphere},
|
||||
author={Caroli, Manuel and de Castro, Pedro MM and Loriot, S{\'e}bastien and Rouiller, Olivier and Teillaud, Monique and Wormser, Camille},
|
||||
booktitle={International Symposium on Experimental Algorithms},
|
||||
pages={462--473},
|
||||
year={2010},
|
||||
organization={Springer}
|
||||
}
|
||||
|
||||
@article{cgal:cc-rgbss-78
|
||||
,author = {E.~Catmull and J.~Clark}
|
||||
,title = {Recursively generated {B}-spline surfaces
|
||||
|
|
|
|||
|
|
@ -3837,9 +3837,9 @@ namespace HomogeneousKernelFunctors {
|
|||
// p,q,r supposed to be non collinear
|
||||
// tests whether s is on the same side of p,q as r
|
||||
// returns :
|
||||
// COLLINEAR if pqr collinear
|
||||
// POSITIVE if qrp and qrs have the same orientation
|
||||
// NEGATIVE if qrp and qrs have opposite orientations
|
||||
// COLLINEAR if qps collinear
|
||||
// POSITIVE if qpr and qps have the same orientation
|
||||
// NEGATIVE if qpr and qps have opposite orientations
|
||||
CGAL_kernel_exactness_precondition( ! cl(p, q, r) );
|
||||
CGAL_kernel_exactness_precondition( cp(p, q, r, s) );
|
||||
|
||||
|
|
|
|||
|
|
@ -6,8 +6,18 @@ Release History
|
|||
|
||||
Release date: June 2021
|
||||
|
||||
### Triangulations on the Sphere (new package)
|
||||
|
||||
- This package enables the construction and manipulation of Delaunay triangulations on the 2-sphere.
|
||||
Triangulations are built incrementally and can be modified by insertion or removal of vertices.
|
||||
Point location querying and primitives to build the dual Voronoi diagram are provided.
|
||||
|
||||
### General
|
||||
- Cmake minimal version is now 3.14
|
||||
|
||||
- Cmake minimal version is now `3.14`.
|
||||
|
||||
### File Input / Output
|
||||
|
||||
- Point set, polygon soup, and polygon mesh file I/O functions have been harmonized and documented:
|
||||
- Point set I/O functions can be found in the packages [Point_set_processing_3](https://doc.cgal.org/5.3/Manual/packages.html#PkgPolygonMeshProcessing), and [Point_set_3](https://doc.cgal.org/5.3/Manual/packages.html#PkgPointSet3).
|
||||
- Polygon mesh I/O functions can be found in the package [BGL](https://doc.cgal.org/5.3/Manual/packages.html#PkgBGL).
|
||||
|
|
|
|||
|
|
@ -0,0 +1,54 @@
|
|||
// Copyright (c) 2016 GeometryFactory SARL (France).
|
||||
// All rights reserved.
|
||||
//
|
||||
// This file is part of CGAL (www.cgal.org)
|
||||
//
|
||||
// $URL$
|
||||
// $Id$
|
||||
// SPDX-License-Identifier: LGPL-3.0-or-later OR LicenseRef-Commercial
|
||||
//
|
||||
// Author(s) : Andreas Fabri
|
||||
//
|
||||
// Warning: this file is generated, see include/CGAL/licence/README.md
|
||||
|
||||
#ifndef CGAL_LICENSE_TRIANGULATION_ON_SPHERE_2_H
|
||||
#define CGAL_LICENSE_TRIANGULATION_ON_SPHERE_2_H
|
||||
|
||||
#include <CGAL/config.h>
|
||||
#include <CGAL/license.h>
|
||||
|
||||
#ifdef CGAL_TRIANGULATION_ON_SPHERE_2_COMMERCIAL_LICENSE
|
||||
|
||||
# if CGAL_TRIANGULATION_ON_SPHERE_2_COMMERCIAL_LICENSE < CGAL_RELEASE_DATE
|
||||
|
||||
# if defined(CGAL_LICENSE_WARNING)
|
||||
|
||||
CGAL_pragma_warning("Your commercial license for CGAL does not cover "
|
||||
"this release of the 2D Triangulations on Sphere package.")
|
||||
# endif
|
||||
|
||||
# ifdef CGAL_LICENSE_ERROR
|
||||
# error "Your commercial license for CGAL does not cover this release \
|
||||
of the 2D Triangulations on Sphere package. \
|
||||
You get this error, as you defined CGAL_LICENSE_ERROR."
|
||||
# endif // CGAL_LICENSE_ERROR
|
||||
|
||||
# endif // CGAL_TRIANGULATION_ON_SPHERE_2_COMMERCIAL_LICENSE < CGAL_RELEASE_DATE
|
||||
|
||||
#else // no CGAL_TRIANGULATION_ON_SPHERE_2_COMMERCIAL_LICENSE
|
||||
|
||||
# if defined(CGAL_LICENSE_WARNING)
|
||||
CGAL_pragma_warning("\nThe macro CGAL_TRIANGULATION_ON_SPHERE_2_COMMERCIAL_LICENSE is not defined."
|
||||
"\nYou use the CGAL 2D Triangulations on Sphere package under "
|
||||
"the terms of the GPLv3+.")
|
||||
# endif // CGAL_LICENSE_WARNING
|
||||
|
||||
# ifdef CGAL_LICENSE_ERROR
|
||||
# error "The macro CGAL_TRIANGULATION_ON_SPHERE_2_COMMERCIAL_LICENSE is not defined.\
|
||||
You use the CGAL 2D Triangulations on Sphere package under the terms of \
|
||||
the GPLv3+. You get this error, as you defined CGAL_LICENSE_ERROR."
|
||||
# endif // CGAL_LICENSE_ERROR
|
||||
|
||||
#endif // no CGAL_TRIANGULATION_ON_SPHERE_2_COMMERCIAL_LICENSE
|
||||
|
||||
#endif // CGAL_LICENSE_TRIANGULATION_ON_SPHERE_2_H
|
||||
|
|
@ -90,6 +90,7 @@ TDS_2 2D Triangulation Data Structure
|
|||
TDS_3 3D Triangulation Data Structure
|
||||
Three Three
|
||||
Triangulation_2 2D Triangulation
|
||||
Triangulation_on_sphere_2 2D Triangulation on Sphere
|
||||
Triangulation_3 3D Triangulations
|
||||
Triangulation dD Triangulations
|
||||
Visibility_2 2D Visibility Computation
|
||||
|
|
|
|||
|
|
@ -77,42 +77,42 @@ template <class K>
|
|||
inline
|
||||
typename K::Boolean
|
||||
do_intersect(const typename K::Sphere_3 &sp,
|
||||
const typename K::Ray_3 &lin,
|
||||
const typename K::Ray_3 &ray,
|
||||
const K & /* k */)
|
||||
{
|
||||
return squared_distance(sp.center(), lin) <= sp.squared_radius();
|
||||
return squared_distance(sp.center(), ray) <= sp.squared_radius();
|
||||
}
|
||||
|
||||
|
||||
template <class K>
|
||||
inline
|
||||
typename K::Boolean
|
||||
do_intersect(const typename K::Ray_3 &lin,
|
||||
do_intersect(const typename K::Ray_3 &ray,
|
||||
const typename K::Sphere_3 &sp,
|
||||
const K & /* k */)
|
||||
{
|
||||
return squared_distance(sp.center(), lin) <= sp.squared_radius();
|
||||
return squared_distance(sp.center(), ray) <= sp.squared_radius();
|
||||
}
|
||||
|
||||
template <class K>
|
||||
inline
|
||||
typename K::Boolean
|
||||
do_intersect(const typename K::Sphere_3 &sp,
|
||||
const typename K::Segment_3 &lin,
|
||||
const typename K::Segment_3 &seg,
|
||||
const K & /* k */)
|
||||
{
|
||||
return squared_distance(sp.center(), lin) <= sp.squared_radius();
|
||||
return squared_distance(sp.center(), seg) <= sp.squared_radius();
|
||||
}
|
||||
|
||||
|
||||
template <class K>
|
||||
inline
|
||||
typename K::Boolean
|
||||
do_intersect(const typename K::Segment_3 &lin,
|
||||
do_intersect(const typename K::Segment_3 &seg,
|
||||
const typename K::Sphere_3 &sp,
|
||||
const K & /* k */)
|
||||
{
|
||||
return squared_distance(sp.center(), lin) <= sp.squared_radius();
|
||||
return squared_distance(sp.center(), seg) <= sp.squared_radius();
|
||||
}
|
||||
|
||||
} // namespace internal
|
||||
|
|
|
|||
|
|
@ -6905,7 +6905,7 @@ public:
|
|||
/// @{
|
||||
|
||||
/*!
|
||||
computes the unit normal of the vectors`q-p` and `r-p`.
|
||||
computes the unit normal of the vectors `q-p` and `r-p`.
|
||||
This requires that `Kernel::FT` supports the `sqrt` operation.
|
||||
*/
|
||||
Kernel::Vector_3 operator()(const Kernel::Point_3& p,
|
||||
|
|
|
|||
|
|
@ -12,7 +12,7 @@ location queries.
|
|||
implementation, only `Periodic_3_Delaunay_triangulation_3` is supported for.</I>
|
||||
|
||||
`PTr::Vertex` has to be a model of the concept
|
||||
`Periodic_3TriangulationHierarchyVertexBase_3`.
|
||||
`Periodic_3TriangulationDSVertexBase_3`.
|
||||
|
||||
`PTr::Geom_traits` has to be a model of the concept
|
||||
`Periodic_3DelaunayTriangulationTraits_3`.
|
||||
|
|
|
|||
|
|
@ -22,6 +22,7 @@
|
|||
#include <CGAL/basic.h>
|
||||
|
||||
#include <CGAL/internal/Periodic_3_triangulation_iterators_3.h>
|
||||
#include <CGAL/result_of.h>
|
||||
#include <CGAL/Periodic_3_triangulation_ds_cell_base_3.h>
|
||||
#include <CGAL/Periodic_3_triangulation_ds_vertex_base_3.h>
|
||||
#include <CGAL/Periodic_3_triangulation_traits_3.h>
|
||||
|
|
|
|||
|
|
@ -22,11 +22,13 @@
|
|||
|
||||
namespace CGAL {
|
||||
|
||||
template <class K, class Hilbert_policy >
|
||||
class Hilbert_sort_on_sphere_3 {
|
||||
typedef typename K::Point_3 Point_3;
|
||||
|
||||
static const double _sqrt_of_one_over_three;
|
||||
template <class K,
|
||||
class Hilbert_policy,
|
||||
class P = typename K::Point_3>
|
||||
class Hilbert_sort_on_sphere_3
|
||||
{
|
||||
typedef P Point_3;
|
||||
typedef typename K::FT FT;
|
||||
|
||||
// Face 1, x > sqrt(1/3)
|
||||
// Face 2, y > sqrt(1/3)
|
||||
|
|
@ -42,28 +44,33 @@ class Hilbert_sort_on_sphere_3 {
|
|||
typedef internal::Transform_coordinates_traits_3<K,-1,0,1,1> Face_5_traits_3; // -z +x
|
||||
typedef internal::Transform_coordinates_traits_3<K,1,1,0,0> Face_6_traits_3; // +x +y
|
||||
|
||||
|
||||
|
||||
Hilbert_sort_2<Face_1_traits_3, Hilbert_policy > _hs_1_object;
|
||||
Hilbert_sort_2<Face_2_traits_3, Hilbert_policy > _hs_2_object;
|
||||
Hilbert_sort_2<Face_3_traits_3, Hilbert_policy > _hs_3_object;
|
||||
Hilbert_sort_2<Face_4_traits_3, Hilbert_policy > _hs_4_object;
|
||||
Hilbert_sort_2<Face_5_traits_3, Hilbert_policy > _hs_5_object;
|
||||
Hilbert_sort_2<Face_6_traits_3, Hilbert_policy > _hs_6_object;
|
||||
|
||||
K _k;
|
||||
Point_3 _p;
|
||||
double _sq_r;
|
||||
FT _sq_r;
|
||||
const FT _sqrt_of_one_over_three;
|
||||
|
||||
public:
|
||||
Hilbert_sort_on_sphere_3 (const K &k=K(),
|
||||
double sq_r = 1.0,
|
||||
const Point_3 &p = Point_3(0,0,0),
|
||||
std::ptrdiff_t limit=1)
|
||||
Hilbert_sort_on_sphere_3 (const K &k = K(),
|
||||
FT sq_r = 1.0,
|
||||
const Point_3 &p = Point_3(0,0,0),
|
||||
std::ptrdiff_t limit=1)
|
||||
: _hs_1_object(Face_1_traits_3(),limit),
|
||||
_hs_2_object(Face_2_traits_3(),limit),
|
||||
_hs_3_object(Face_3_traits_3(),limit),
|
||||
_hs_4_object(Face_4_traits_3(),limit),
|
||||
_hs_5_object(Face_5_traits_3(),limit),
|
||||
_hs_6_object(Face_6_traits_3(),limit),
|
||||
_k(k), _p(p), _sq_r(sq_r)
|
||||
_k(k), _p(p), _sq_r(sq_r),
|
||||
_sqrt_of_one_over_three(CGAL_NTS sqrt(FT(1)/FT(3)))
|
||||
{
|
||||
CGAL_precondition( sq_r > 0 );
|
||||
}
|
||||
|
|
@ -74,10 +81,10 @@ public:
|
|||
typedef typename std::iterator_traits<RandomAccessIterator>::value_type Point;
|
||||
std::vector< Point > vec[6];
|
||||
|
||||
const double mulcte = _sqrt_of_one_over_three * CGAL_NTS sqrt(_sq_r);
|
||||
const double lxi = _p.x() - mulcte, lxs = _p.x() + mulcte;
|
||||
const double lyi = _p.y() - mulcte, lys = _p.y() + mulcte;
|
||||
const double lzs = _p.z() + mulcte;
|
||||
const FT mulcte = _sqrt_of_one_over_three * CGAL_NTS sqrt(_sq_r);
|
||||
const FT lxi = _p.x() - mulcte, lxs = _p.x() + mulcte;
|
||||
const FT lyi = _p.y() - mulcte, lys = _p.y() + mulcte;
|
||||
const FT lzs = _p.z() + mulcte;
|
||||
|
||||
for(RandomAccessIterator i = begin; i != end; ++i) {
|
||||
const Point &p = *i;
|
||||
|
|
@ -105,8 +112,6 @@ public:
|
|||
*begin++ = vec[i][j];
|
||||
}
|
||||
};
|
||||
template <class K, class Hilbert_policy >
|
||||
const double Hilbert_sort_on_sphere_3<K,Hilbert_policy>::_sqrt_of_one_over_three = 0.57735026919;
|
||||
|
||||
} // namespace CGAL
|
||||
|
||||
|
|
|
|||
|
|
@ -36,6 +36,39 @@ public:
|
|||
typedef typename boost::property_traits<PointPropertyMap>::key_type Point_3;
|
||||
typedef typename boost::call_traits<Point_3>::param_type Arg_type;
|
||||
|
||||
struct Compute_x_3
|
||||
: public Base_traits::Compute_x_3
|
||||
{
|
||||
Compute_x_3(const PointPropertyMap& ppmap, const typename Base_traits::Compute_x_3& base):
|
||||
Base_traits::Compute_x_3(base), ppmap_(ppmap){}
|
||||
const PointPropertyMap& ppmap_;
|
||||
bool operator()(Arg_type p) const {
|
||||
return static_cast<const typename Base_traits::Compute_x_3*>(this)->operator()(get(ppmap_,p));
|
||||
}
|
||||
};
|
||||
|
||||
struct Compute_y_3
|
||||
: public Base_traits::Compute_y_3
|
||||
{
|
||||
Compute_y_3(const PointPropertyMap& ppmap, const typename Base_traits::Compute_y_3& base):
|
||||
Base_traits::Compute_y_3(base), ppmap_(ppmap){}
|
||||
const PointPropertyMap& ppmap_;
|
||||
bool operator()(Arg_type p) const {
|
||||
return static_cast<const typename Base_traits::Compute_y_3*>(this)->operator()(get(ppmap_,p));
|
||||
}
|
||||
};
|
||||
|
||||
struct Compute_z_3
|
||||
: public Base_traits::Compute_z_3
|
||||
{
|
||||
Compute_z_3(const PointPropertyMap& ppmap, const typename Base_traits::Compute_z_3& base):
|
||||
Base_traits::Compute_z_3(base), ppmap_(ppmap){}
|
||||
const PointPropertyMap& ppmap_;
|
||||
bool operator()(Arg_type p) const {
|
||||
return static_cast<const typename Base_traits::Compute_z_3*>(this)->operator()(get(ppmap_,p));
|
||||
}
|
||||
};
|
||||
|
||||
struct Less_x_3
|
||||
: public Base_traits::Less_x_3
|
||||
{
|
||||
|
|
@ -69,6 +102,10 @@ public:
|
|||
}
|
||||
};
|
||||
|
||||
Compute_x_3 compute_x_3_object () const {return Compute_x_3(ppmap_, static_cast<const Gt*>(this)->compute_x_3_object() );}
|
||||
Compute_y_3 compute_y_3_object () const {return Compute_y_3(ppmap_, static_cast<const Gt*>(this)->compute_y_3_object() );}
|
||||
Compute_z_3 compute_z_3_object () const {return Compute_z_3(ppmap_, static_cast<const Gt*>(this)->compute_z_3_object() );}
|
||||
|
||||
Less_x_3 less_x_3_object () const {return Less_x_3(ppmap_, static_cast<const Gt*>(this)->less_x_3_object() );}
|
||||
Less_y_3 less_y_3_object () const {return Less_y_3(ppmap_, static_cast<const Gt*>(this)->less_y_3_object() );}
|
||||
Less_z_3 less_z_3_object () const {return Less_z_3(ppmap_, static_cast<const Gt*>(this)->less_z_3_object() );}
|
||||
|
|
|
|||
|
|
@ -16,29 +16,31 @@
|
|||
|
||||
#include <CGAL/spatial_sort.h>
|
||||
#include <CGAL/hilbert_sort_on_sphere.h>
|
||||
#include <CGAL/Hilbert_policy_tags.h>
|
||||
|
||||
namespace CGAL {
|
||||
|
||||
namespace internal {
|
||||
|
||||
template <class RandomAccessIterator, class Policy, class Kernel>
|
||||
template <class RandomAccessIterator, class PolicyTag, class Kernel,
|
||||
class FT = typename Kernel::FT,
|
||||
class Point = typename Kernel::Point_3>
|
||||
void spatial_sort_on_sphere (RandomAccessIterator begin, RandomAccessIterator end,
|
||||
const Kernel &k,
|
||||
Policy /*policy*/,
|
||||
typename Kernel::Point_3 *,
|
||||
double sq_r,
|
||||
const typename Kernel::Point_3 &p,
|
||||
const Hilbert_policy<PolicyTag> /*policy*/,
|
||||
const FT sq_r,
|
||||
const Point &p,
|
||||
std::ptrdiff_t threshold_hilbert,
|
||||
std::ptrdiff_t threshold_multiscale,
|
||||
double ratio)
|
||||
{
|
||||
typedef Hilbert_sort_on_sphere_3<Kernel, Policy> Sort;
|
||||
typedef Hilbert_sort_on_sphere_3<Kernel, Hilbert_policy<PolicyTag>, Point> Sort;
|
||||
typedef std::iterator_traits<RandomAccessIterator> ITraits;
|
||||
typedef typename ITraits::difference_type Diff_t;
|
||||
|
||||
boost::rand48 random;
|
||||
boost::random_number_generator<boost::rand48, Diff_t> rng(random);
|
||||
CGAL::cpp98::random_shuffle(begin,end, rng);
|
||||
CGAL::cpp98::random_shuffle(begin, end, rng);
|
||||
|
||||
if (threshold_hilbert==0) threshold_hilbert=4;
|
||||
if (threshold_multiscale==0) threshold_multiscale=16;
|
||||
|
|
@ -50,87 +52,52 @@ void spatial_sort_on_sphere (RandomAccessIterator begin, RandomAccessIterator en
|
|||
|
||||
} // end of namespace internal
|
||||
|
||||
template <class RandomAccessIterator, class Policy, class Kernel>
|
||||
template <class RandomAccessIterator, class PolicyTag,
|
||||
class Kernel = typename CGAL::Kernel_traits<typename std::iterator_traits<RandomAccessIterator>::value_type>::Kernel,
|
||||
class FT = typename Kernel::FT,
|
||||
class Point = typename Kernel::Point_3>
|
||||
void spatial_sort_on_sphere (RandomAccessIterator begin, RandomAccessIterator end,
|
||||
const Hilbert_policy<PolicyTag> policy,
|
||||
const FT sq_r = FT(1),
|
||||
const Point &p = Point(0,0,0),
|
||||
std::ptrdiff_t threshold_hilbert = 0,
|
||||
std::ptrdiff_t threshold_multiscale = 0,
|
||||
const double ratio = 0.)
|
||||
{
|
||||
internal::spatial_sort_on_sphere (begin, end, Kernel(), policy, sq_r, p,
|
||||
threshold_hilbert, threshold_multiscale, ratio);
|
||||
}
|
||||
|
||||
template <class RandomAccessIterator, class Kernel,
|
||||
class FT = typename Kernel::FT,
|
||||
class Point = typename Kernel::Point_3>
|
||||
void spatial_sort_on_sphere (RandomAccessIterator begin, RandomAccessIterator end,
|
||||
const Kernel &k,
|
||||
Policy policy,
|
||||
double sq_r=1.0,
|
||||
const typename Kernel::Point_3 &p = typename Kernel::Point_3(0,0,0),
|
||||
std::ptrdiff_t threshold_hilbert=0,
|
||||
std::ptrdiff_t threshold_multiscale=0,
|
||||
double ratio=0.0)
|
||||
const FT sq_r = FT(1),
|
||||
const Point &p = Point(0,0,0),
|
||||
std::ptrdiff_t threshold_hilbert = 0,
|
||||
std::ptrdiff_t threshold_multiscale = 0,
|
||||
const double ratio = 0.)
|
||||
{
|
||||
typedef std::iterator_traits<RandomAccessIterator> ITraits;
|
||||
typedef typename ITraits::value_type value_type;
|
||||
|
||||
internal::spatial_sort_on_sphere(begin, end, k, policy, static_cast<value_type *> (0),
|
||||
sq_r,p, threshold_hilbert,threshold_multiscale,ratio);
|
||||
internal::spatial_sort_on_sphere (begin, end, k,
|
||||
Hilbert_sort_median_policy(), sq_r, p,
|
||||
threshold_hilbert, threshold_multiscale, ratio);
|
||||
}
|
||||
|
||||
template <class RandomAccessIterator>
|
||||
template <class RandomAccessIterator,
|
||||
class Kernel = typename CGAL::Kernel_traits<typename std::iterator_traits<RandomAccessIterator>::value_type>::Kernel,
|
||||
class FT = typename Kernel::FT,
|
||||
class Point = typename Kernel::Point_3>
|
||||
void spatial_sort_on_sphere (RandomAccessIterator begin, RandomAccessIterator end,
|
||||
Hilbert_sort_median_policy policy,
|
||||
double sq_r=1.0,
|
||||
const typename CGAL::Kernel_traits<typename std::iterator_traits<RandomAccessIterator>::value_type>::Kernel::Point_3 &p =
|
||||
typename CGAL::Kernel_traits<typename std::iterator_traits<RandomAccessIterator>::value_type>::Kernel::Point_3(0,0,0),
|
||||
std::ptrdiff_t threshold_hilbert=0,
|
||||
std::ptrdiff_t threshold_multiscale=0,
|
||||
double ratio=0.0)
|
||||
const FT sq_r = FT(1),
|
||||
const Point &p = Point(0,0,0),
|
||||
std::ptrdiff_t threshold_hilbert = 0,
|
||||
std::ptrdiff_t threshold_multiscale = 0,
|
||||
const double ratio = 0.)
|
||||
{
|
||||
typedef std::iterator_traits<RandomAccessIterator> ITraits;
|
||||
typedef typename ITraits::value_type value_type;
|
||||
typedef CGAL::Kernel_traits<value_type> KTraits;
|
||||
typedef typename KTraits::Kernel Kernel;
|
||||
|
||||
spatial_sort_on_sphere (begin, end, Kernel(), policy, sq_r, p,
|
||||
threshold_hilbert,threshold_multiscale,ratio);
|
||||
}
|
||||
template <class RandomAccessIterator>
|
||||
void spatial_sort_on_sphere (RandomAccessIterator begin, RandomAccessIterator end,
|
||||
Hilbert_sort_middle_policy policy,
|
||||
double sq_r=1.0,
|
||||
const typename CGAL::Kernel_traits<typename std::iterator_traits<RandomAccessIterator>::value_type>::Kernel::Point_3 &p =
|
||||
typename CGAL::Kernel_traits<typename std::iterator_traits<RandomAccessIterator>::value_type>::Kernel::Point_3(0,0,0),
|
||||
std::ptrdiff_t threshold_hilbert=0,
|
||||
std::ptrdiff_t threshold_multiscale=0,
|
||||
double ratio=0.0)
|
||||
{
|
||||
typedef std::iterator_traits<RandomAccessIterator> ITraits;
|
||||
typedef typename ITraits::value_type value_type;
|
||||
typedef CGAL::Kernel_traits<value_type> KTraits;
|
||||
typedef typename KTraits::Kernel Kernel;
|
||||
|
||||
spatial_sort_on_sphere (begin, end, Kernel(), policy, sq_r,p,
|
||||
threshold_hilbert,threshold_multiscale,ratio);
|
||||
}
|
||||
|
||||
|
||||
template <class RandomAccessIterator, class Kernel>
|
||||
void spatial_sort_on_sphere (RandomAccessIterator begin, RandomAccessIterator end,
|
||||
const Kernel &k,
|
||||
double sq_r = 1.0,
|
||||
const typename Kernel::Point_3 &p = typename Kernel::Point_3(0,0,0),
|
||||
std::ptrdiff_t threshold_hilbert=0,
|
||||
std::ptrdiff_t threshold_multiscale=0,
|
||||
double ratio=0.0)
|
||||
{
|
||||
spatial_sort_on_sphere (begin, end, k,
|
||||
Hilbert_sort_median_policy(), sq_r, p,
|
||||
threshold_hilbert,threshold_multiscale,ratio);
|
||||
}
|
||||
|
||||
template <class RandomAccessIterator>
|
||||
void spatial_sort_on_sphere (RandomAccessIterator begin, RandomAccessIterator end,
|
||||
double sq_r = 1.0,
|
||||
const typename CGAL::Kernel_traits<typename std::iterator_traits<RandomAccessIterator>::value_type>::Kernel::Point_3 &p =
|
||||
typename CGAL::Kernel_traits<typename std::iterator_traits<RandomAccessIterator>::value_type>::Kernel::Point_3(0,0,0),
|
||||
std::ptrdiff_t threshold_hilbert=0,
|
||||
std::ptrdiff_t threshold_multiscale=0,
|
||||
double ratio=0.0)
|
||||
{
|
||||
spatial_sort_on_sphere (begin, end,
|
||||
Hilbert_sort_median_policy(), sq_r,p,
|
||||
threshold_hilbert,threshold_multiscale,ratio);
|
||||
internal::spatial_sort_on_sphere (begin, end, Kernel(),
|
||||
Hilbert_sort_median_policy(), sq_r, p,
|
||||
threshold_hilbert, threshold_multiscale, ratio);
|
||||
}
|
||||
|
||||
} // end of namespace CGAL
|
||||
|
|
|
|||
|
|
@ -91,6 +91,11 @@ typedef TriangulationDataStructure_2::Vertex_handle Vertex_handle;
|
|||
*/
|
||||
typedef TriangulationDataStructure_2::Face_handle Face_handle;
|
||||
|
||||
/*!
|
||||
|
||||
*/
|
||||
typedef TriangulationDataStructure_2::Face_data TDS_data;
|
||||
|
||||
/// @}
|
||||
|
||||
/// \name Creation
|
||||
|
|
@ -187,5 +192,25 @@ void for_compact_container(void *p);
|
|||
|
||||
/// @}
|
||||
|
||||
/// \name Internal
|
||||
/// \cgalAdvancedBegin
|
||||
/// These functions are used internally by the triangulation data
|
||||
/// structure. The user is not encouraged to use them directly as they
|
||||
/// may change in the future.
|
||||
/// \cgalAdvancedEnd
|
||||
/// @{
|
||||
|
||||
/*!
|
||||
|
||||
*/
|
||||
TDS_data& tds_data();
|
||||
|
||||
/*!
|
||||
|
||||
*/
|
||||
const TDS_data& tds_data() const;
|
||||
|
||||
/// @}
|
||||
|
||||
}; /* end TriangulationDSFaceBase_2 */
|
||||
|
||||
|
|
|
|||
|
|
@ -98,6 +98,11 @@ The face type, requirements for this type are described in concept `Triangulatio
|
|||
*/
|
||||
typedef unspecified_type Face;
|
||||
|
||||
/*!
|
||||
%Face data type, requirements are described in `TriangulationDataStructure_2::Face_data`.
|
||||
*/
|
||||
typedef unspecified_type Face_data;
|
||||
|
||||
/*!
|
||||
Handle to a vertex.
|
||||
\cgalModels `Handle`
|
||||
|
|
@ -689,12 +694,12 @@ Vertex_handle file_input( istream& is, bool skip_first=false);
|
|||
/*!
|
||||
reads a combinatorial triangulation data structure from `is` and assigns it to tthe triangulation data structure.
|
||||
*/
|
||||
istream& operator>> (istream& is, TriangulationDataStructure_3 & tds);
|
||||
istream& operator>> (istream& is, TriangulationDataStructure_2 & tds);
|
||||
|
||||
/*!
|
||||
writes `tds` into the stream `os`.
|
||||
*/
|
||||
ostream& operator<< (ostream& os, const TriangulationDataStructure_3 & tds);
|
||||
ostream& operator<< (ostream& os, const TriangulationDataStructure_2 & tds);
|
||||
|
||||
/// @}
|
||||
|
||||
|
|
@ -992,3 +997,66 @@ std::ostream& operator<< (std::ostream& os, const TriangulationDataStructure_2::
|
|||
/// @}
|
||||
|
||||
}; /* end TriangulationDataStructure_2::Face */
|
||||
|
||||
/*!
|
||||
\ingroup PkgTDS2Concepts
|
||||
\cgalConcept
|
||||
|
||||
Various algorithms using a triangulation data structure, such as Delaunay triangulations
|
||||
or Alpha Shapes, must be able to associate a state to a face elemental.
|
||||
For efficiency, this information must be stored directly within the face.
|
||||
|
||||
This class is only meant to store a state (Boolean). Consequently, the state must be the default
|
||||
value (i.e. `false`) unless a setting function (`mark_in_conflict()`, etc.) has been called.
|
||||
|
||||
The three states are "in conflict", "on boundary", and "processed".
|
||||
By default, a face is not in conflict, not on boundary, and not processed.
|
||||
|
||||
\sa `TriangulationDataStructure_2::Face`
|
||||
|
||||
*/
|
||||
|
||||
class TriangulationDataStructure_2::Face_data
|
||||
{
|
||||
public:
|
||||
/// \name Setting
|
||||
/// @{
|
||||
|
||||
/// Clears all flags: the face is neither in conflict, nor on the boundary, nor processed.
|
||||
void clear();
|
||||
|
||||
/// Sets the "in conflict" state to `true`.
|
||||
///
|
||||
/// \post `is_in_conflict()` returns `true`
|
||||
void mark_in_conflict();
|
||||
|
||||
/// Sets the "on boundary" state to `true`.
|
||||
///
|
||||
/// \post `is_on_boundary()` returns `true`
|
||||
void mark_on_boundary();
|
||||
|
||||
/// Sets the "processed" state to `true`.
|
||||
///
|
||||
/// \post `processed()` returns `true`
|
||||
void mark_processed();
|
||||
|
||||
/// @}
|
||||
|
||||
/// \name Access Functions
|
||||
/// @{
|
||||
|
||||
/// Checks whether the face has default state (not in conflict, not on boundary, not processed).
|
||||
bool is_clear();
|
||||
|
||||
/// Returns whether the face has been marked as "in conflict".
|
||||
bool is_in_conflict();
|
||||
|
||||
/// Returns whether the face has been marked as "on boundary".
|
||||
bool is_on_boundary();
|
||||
|
||||
/// Returns whether the face has been marked as "processed".
|
||||
bool processed();
|
||||
|
||||
/// @}
|
||||
|
||||
}; /* end Face_data */
|
||||
|
|
|
|||
|
|
@ -52,6 +52,7 @@ These refining concepts and their models are described in Chapter
|
|||
\cgalCRPSection{Concepts}
|
||||
- `TriangulationDataStructure_2`
|
||||
- `TriangulationDataStructure_2::Face`
|
||||
- `TriangulationDataStructure_2::Face_data`
|
||||
- `TriangulationDataStructure_2::Vertex`
|
||||
|
||||
- `TriangulationDSFaceBase_2`
|
||||
|
|
|
|||
|
|
@ -67,6 +67,22 @@ public:
|
|||
typedef Triangulation_data_structure_2<Vb, Fb2> Other;
|
||||
};
|
||||
|
||||
class Face_data {
|
||||
unsigned char conflict_state;
|
||||
public:
|
||||
Face_data() : conflict_state(0) {}
|
||||
|
||||
void clear() { conflict_state = 0; }
|
||||
void mark_in_conflict() { conflict_state = 1; }
|
||||
void mark_on_boundary() { conflict_state = 2; }
|
||||
void mark_processed() { conflict_state = 1; }
|
||||
|
||||
bool is_clear() const { return conflict_state == 0; }
|
||||
bool is_in_conflict() const { return conflict_state == 1; }
|
||||
bool is_on_boundary() const { return conflict_state == 2; }
|
||||
bool processed() const { return conflict_state == 1; }
|
||||
};
|
||||
|
||||
typedef Vertex_base Vertex;
|
||||
typedef Face_base Face;
|
||||
|
||||
|
|
|
|||
|
|
@ -30,6 +30,7 @@ public:
|
|||
typedef TDS Triangulation_data_structure;
|
||||
typedef typename TDS::Vertex_handle Vertex_handle;
|
||||
typedef typename TDS::Face_handle Face_handle;
|
||||
typedef typename TDS::Face_data TDS_data;
|
||||
|
||||
template <typename TDS2>
|
||||
struct Rebind_TDS { typedef Triangulation_ds_face_base_2<TDS2> Other; };
|
||||
|
|
@ -37,6 +38,7 @@ public:
|
|||
private:
|
||||
Vertex_handle V[3];
|
||||
Face_handle N[3];
|
||||
TDS_data _tds_data;
|
||||
|
||||
public:
|
||||
Triangulation_ds_face_base_2();
|
||||
|
|
@ -81,6 +83,9 @@ public:
|
|||
void * for_compact_container() const {return N[0].for_compact_container(); }
|
||||
void for_compact_container(void* p) { N[0].for_compact_container(p);}
|
||||
|
||||
// TDS internal data access functions.
|
||||
TDS_data& tds_data() { return _tds_data; }
|
||||
const TDS_data& tds_data() const { return _tds_data; }
|
||||
|
||||
static int ccw(int i) {return Triangulation_cw_ccw_2::ccw(i);}
|
||||
static int cw(int i) {return Triangulation_cw_ccw_2::cw(i);}
|
||||
|
|
|
|||
|
|
@ -49,7 +49,6 @@ Section \ref TDS3secintro.)
|
|||
\cgalClassifedRefPages
|
||||
|
||||
\cgalCRPSection{Concepts}
|
||||
|
||||
- `TriangulationDataStructure_3`
|
||||
- `TriangulationDataStructure_3::Cell`
|
||||
- `TriangulationDataStructure_3::Cell_data`
|
||||
|
|
|
|||
|
|
@ -330,8 +330,7 @@ Oriented_side side_of_oriented_circle(Face_handle f, const Point& p) const;
|
|||
/*!
|
||||
tests the validity of the triangulation as a
|
||||
`Triangulation_2` and additionally tests the Delaunay property. This
|
||||
method is mainly useful for debugging Delaunay triangulation
|
||||
algorithms designed by the user.
|
||||
method is mainly useful for debugging Delaunay triangulation algorithms.
|
||||
*/
|
||||
bool is_valid(bool verbose = false, int level = 0) const;
|
||||
|
||||
|
|
|
|||
|
|
@ -297,7 +297,7 @@ iterator over finite vertices.
|
|||
typedef unspecified_type Finite_vertices_iterator;
|
||||
|
||||
/*!
|
||||
iterator over the points corresponding the
|
||||
iterator over the points corresponding to the
|
||||
finite vertices of the triangulation.
|
||||
*/
|
||||
typedef unspecified_type Point_iterator;
|
||||
|
|
@ -305,7 +305,7 @@ typedef unspecified_type Point_iterator;
|
|||
|
||||
/*!
|
||||
range type for iterating over all faces (including infinite faces), with a nested
|
||||
type `iterator` that has as value type `Face_handle`
|
||||
type `iterator` that has as value type `Face_handle`.
|
||||
*/
|
||||
typedef Iterator_range<unspecified_type> All_face_handles;
|
||||
|
||||
|
|
@ -317,14 +317,14 @@ typedef Iterator_range<All_edges_iterator> All_edges;
|
|||
|
||||
/*!
|
||||
range type for iterating over all vertices (including the infinite vertex), with a nested
|
||||
type `iterator` that has as value type `Vertex_handle`
|
||||
type `iterator` that has as value type `Vertex_handle`.
|
||||
*/
|
||||
typedef Iterator_range<unspecified_type> All_vertex_handles;
|
||||
|
||||
|
||||
/*!
|
||||
range type for iterating over finite faces, with a nested
|
||||
type `iterator` that has as value type `Face_handle`
|
||||
type `iterator` that has as value type `Face_handle`.
|
||||
*/
|
||||
typedef Iterator_range<unspecified_type> Finite_face_handles;
|
||||
|
||||
|
|
@ -336,7 +336,7 @@ typedef Iterator_range<Finite_edges_iterator> Finite_edges;
|
|||
|
||||
/*!
|
||||
range type for iterating over finite vertices, with a nested
|
||||
type `iterator` that has as value type `Vertex_handle`
|
||||
type `iterator` that has as value type `Vertex_handle`.
|
||||
*/
|
||||
typedef Iterator_range<unspecified_type> Finite_vertex_handles;
|
||||
|
||||
|
|
@ -929,7 +929,7 @@ Point_iterator points_end() const;
|
|||
/*!
|
||||
returns a range of iterators over finite vertices.
|
||||
\note While the value type of `Finite_vertices_iterator` is `Vertex`, the value type of
|
||||
`Finite_vertex_handles::iterator` is `Vertex_handle`
|
||||
`Finite_vertex_handles::iterator` is `Vertex_handle`.
|
||||
*/
|
||||
Finite_vertex_handles finite_vertex_handles() const;
|
||||
|
||||
|
|
@ -941,7 +941,7 @@ Finite_edges finite_edges() const;
|
|||
/*!
|
||||
returns a range of iterators over finite faces.
|
||||
\note While the value type of `Finite_faces_iterator` is `Face`, the value type of
|
||||
`Finite_face_handles::iterator` is `Face_handle`
|
||||
`Finite_face_handles::iterator` is `Face_handle`.
|
||||
*/
|
||||
Finite_face_handles finite_face_handles() const;
|
||||
|
||||
|
|
@ -995,7 +995,7 @@ All_faces_iterator all_faces_end() const;
|
|||
/*!
|
||||
returns a range of iterators over all vertices.
|
||||
\note While the value type of `All_vertices_iterator` is `Vertex`, the value type of
|
||||
`All_vertex_handles::iterator` is `Vertex_handle`
|
||||
`All_vertex_handles::iterator` is `Vertex_handle`.
|
||||
*/
|
||||
All_vertex_handles all_vertex_handles() const;
|
||||
|
||||
|
|
@ -1007,7 +1007,7 @@ All_edges all_edges() const;
|
|||
/*!
|
||||
returns a range of iterators over all faces.
|
||||
\note While the value type of `All_faces_iterator` is `Face`, the value type of
|
||||
`All_face_handles::iterator` is `Face_handle`
|
||||
`All_face_handles::iterator` is `Face_handle`.
|
||||
*/
|
||||
All_face_handles all_face_handles() const;
|
||||
|
||||
|
|
|
|||
|
|
@ -10,7 +10,7 @@ namespace CGAL {
|
|||
\image html tr1dt1.svg
|
||||
\image latex tr1dt1.png
|
||||
|
||||
This chapter describes the two dimensional triangulations
|
||||
This chapter describes the two-dimensional triangulations
|
||||
of \cgal.
|
||||
Section \ref Section_2D_Triangulations_Definitions recalls the
|
||||
main definitions about triangulations.
|
||||
|
|
@ -46,7 +46,7 @@ and vertices.
|
|||
|
||||
\section Section_2D_Triangulations_Definitions Definitions
|
||||
|
||||
A two dimensional triangulation can be roughly described as a set \f$ T\f$
|
||||
A two-dimensional triangulation can be roughly described as a set \f$ T\f$
|
||||
of triangular facets such that:
|
||||
|
||||
- two facets either are disjoint or share a lower dimensional
|
||||
|
|
@ -85,8 +85,8 @@ A point \f$ p\f$ in the domain of \f$ T\f$ is said to singular
|
|||
if its surrounding in \f$ U_T\f$
|
||||
is neither a topological ball nor a topological disc.
|
||||
|
||||
Then, a two dimensional triangulation can be described as a
|
||||
two dimensional simplicial complex that is pure,
|
||||
Then, a two-dimensional triangulation can be described as a
|
||||
two-dimensional simplicial complex that is pure,
|
||||
connected and without singularity.
|
||||
|
||||
Each facet of a triangulation can be given an orientation
|
||||
|
|
@ -100,7 +100,7 @@ that all pairs of incident facets have consistent orientations.
|
|||
|
||||
The data structure underlying \cgal triangulations
|
||||
allows the user to represent the combinatorics of
|
||||
any orientable two dimensional triangulations
|
||||
any orientable two-dimensional triangulations
|
||||
without boundaries.
|
||||
On top of this data structure, the 2D triangulations classes
|
||||
take care of the geometric embedding of the triangulation
|
||||
|
|
@ -126,7 +126,7 @@ to design a face of any dimension,
|
|||
and the two-dimensional faces of a triangulation
|
||||
should be properly called <I>facets</I>.
|
||||
However, following a common usage, we hereafter often call <I>faces</I>, the facets
|
||||
of a two dimensional triangulation.
|
||||
of a two-dimensional triangulation.
|
||||
|
||||
\section Section_2D_Triangulations_Representation Representation
|
||||
|
||||
|
|
@ -731,7 +731,7 @@ regular triangulation of \f$ { PW}\f$.
|
|||
Alternatively, the regular triangulation
|
||||
of the weighted points set \f$ { PW}\f$
|
||||
can be obtained as the projection
|
||||
on the two dimensional plane of the convex hull of the set of three
|
||||
on the two-dimensional plane of the convex hull of the set of three
|
||||
dimensional points
|
||||
\f$ { P'}= \{ (p_i,p_i ^2 - w_i ) | i = 1, \ldots , n \}\f$.
|
||||
|
||||
|
|
@ -759,7 +759,7 @@ they have to be stored somewhere.
|
|||
The regular triangulation store those points in special vertices, called
|
||||
hidden vertices.
|
||||
A hidden point can reappear as vertex of the triangulation
|
||||
only when the two dimensional face that hides it
|
||||
only when the two-dimensional face that hides it
|
||||
is removed from the triangulation. To deal with this feature,
|
||||
each face of a regular triangulation stores a list of hidden vertices.
|
||||
The points in those vertices
|
||||
|
|
|
|||
|
|
@ -44,6 +44,7 @@
|
|||
#include <boost/random/variate_generator.hpp>
|
||||
#include <CGAL/boost/iterator/transform_iterator.hpp>
|
||||
#include <boost/iterator/zip_iterator.hpp>
|
||||
#include <boost/utility/result_of.hpp>
|
||||
|
||||
#ifndef CGAL_TRIANGULATION_2_DONT_INSERT_RANGE_OF_POINTS_WITH_INFO
|
||||
#include <CGAL/internal/info_check.h>
|
||||
|
|
@ -304,8 +305,10 @@ public:
|
|||
typename boost::result_of<const Construct_point_2(const Point&)>::type
|
||||
construct_point(const Point& p) const { return geom_traits().construct_point_2_object()(p); }
|
||||
|
||||
const Point& point(Face_handle c, int i) const;
|
||||
|
||||
const Point& point(Face_handle f, int i) const;
|
||||
const Point& point(Vertex_handle v) const;
|
||||
|
||||
Segment segment(Face_handle f, int i) const;
|
||||
Segment segment(const Edge& e) const;
|
||||
Segment segment(const Edge_circulator& ec) const;
|
||||
|
|
|
|||
|
|
@ -0,0 +1,20 @@
|
|||
# Created by the script cgal_create_cmake_script
|
||||
# This is the CMake script for compiling a CGAL application.
|
||||
|
||||
project( Triangulation_on_sphere_2_Benchmarks )
|
||||
|
||||
cmake_minimum_required(VERSION 3.1...3.15)
|
||||
|
||||
find_package(CGAL REQUIRED COMPONENTS Core )
|
||||
|
||||
if ( CGAL_FOUND )
|
||||
|
||||
create_single_source_cgal_program( "bench_dtos2.cpp" )
|
||||
create_single_source_cgal_program( "generate_points.cpp" )
|
||||
|
||||
else()
|
||||
|
||||
message(STATUS "This program requires the CGAL library, and will not be compiled.")
|
||||
|
||||
endif()
|
||||
|
||||
|
|
@ -0,0 +1,107 @@
|
|||
#include <CGAL/Exact_predicates_inexact_constructions_kernel.h>
|
||||
|
||||
#include <CGAL/Delaunay_triangulation_on_sphere_traits_2.h>
|
||||
#include <CGAL/Delaunay_triangulation_on_sphere_2.h>
|
||||
#include <CGAL/Projection_on_sphere_traits_3.h>
|
||||
|
||||
#include <CGAL/algorithm.h>
|
||||
#include <CGAL/convex_hull_3.h>
|
||||
#include <CGAL/Delaunay_triangulation_3.h>
|
||||
#include <CGAL/point_generators_2.h>
|
||||
#include <CGAL/point_generators_3.h>
|
||||
#include <CGAL/Surface_mesh.h>
|
||||
#include <CGAL/squared_distance_3.h>
|
||||
#include <CGAL/Timer.h>
|
||||
|
||||
#include <boost/iterator/transform_iterator.hpp>
|
||||
|
||||
#include <cmath>
|
||||
#include <fstream>
|
||||
#include <vector>
|
||||
|
||||
typedef CGAL::Exact_predicates_inexact_constructions_kernel K;
|
||||
typedef CGAL::Surface_mesh<K> Surface_mesh;
|
||||
|
||||
typedef K::Segment_3 Segment_3;
|
||||
typedef CGAL::Delaunay_triangulation_3<K> Delaunay;
|
||||
|
||||
typedef CGAL::Delaunay_triangulation_on_sphere_traits_2<K> Gt;
|
||||
typedef CGAL::Projection_on_sphere_traits_3<K> Gt2;
|
||||
typedef CGAL::Delaunay_triangulation_on_sphere_2<Gt> DTOS;
|
||||
typedef CGAL::Delaunay_triangulation_on_sphere_2<Gt2> DTOS2;
|
||||
typedef K::Point_3 Point;
|
||||
|
||||
typedef CGAL::Delaunay_triangulation_3<K, CGAL::Fast_location> Delaunay_fast;
|
||||
typedef CGAL::Creator_uniform_3<double, Point> Creator;
|
||||
|
||||
int main(int, char**)
|
||||
{
|
||||
CGAL::Timer time;
|
||||
|
||||
const std::size_t nu_of_pts = 1e7;
|
||||
const double radius = 5184.152;
|
||||
|
||||
CGAL::Random random;
|
||||
std::cout << "Seed is " << random.get_seed() << std::endl;
|
||||
|
||||
CGAL::Random_points_on_sphere_3<Point, Creator> on_sphere(radius, random);
|
||||
|
||||
std::vector<Point> points;
|
||||
points.reserve(nu_of_pts);
|
||||
|
||||
for(std::size_t count=0; count<nu_of_pts; ++count)
|
||||
points.push_back(*on_sphere++);
|
||||
std::cout << points.size() << " points" << std::endl;
|
||||
|
||||
// Delaunay_traits
|
||||
DTOS dtos;
|
||||
dtos.set_radius(radius);
|
||||
|
||||
std::cout << " ***STARTING***" << std::endl;
|
||||
time.start();
|
||||
dtos.insert(points.begin(), points.end());
|
||||
time.stop();
|
||||
assert(dtos.number_of_vertices() == nu_of_pts);
|
||||
std::cout << "Triangulation sphere: "
|
||||
<< dtos.number_of_vertices() << " vertices in " << time.time() << " sec" << std::endl;
|
||||
|
||||
//Triangulation with points on the sphere (projection_traits)
|
||||
Gt2 traits(K::Point_3(0, 0, 0), radius);
|
||||
DTOS2 dtos2(traits);
|
||||
Gt2::Construct_point_on_sphere_2 cst = traits.construct_point_on_sphere_2_object();
|
||||
|
||||
time.reset();
|
||||
time.start();
|
||||
dtos2.insert(boost::make_transform_iterator(points.begin(), cst),
|
||||
boost::make_transform_iterator(points.end(), cst));
|
||||
time.stop();
|
||||
std::cout << "Triangulation w/ sphere projection traits: "
|
||||
<< dtos2.number_of_vertices() << " vertices in " << time.time() << " sec" << std::endl;
|
||||
|
||||
// Surface_mesh sm;
|
||||
|
||||
// time.reset();
|
||||
// time.start();
|
||||
// CGAL::convex_hull_3(points.begin(), points.end(), sm);
|
||||
// time.stop();
|
||||
// std::cout << "Convex hull 3D: " << time.time() << " " << std::endl;
|
||||
|
||||
time.reset();
|
||||
time.start();
|
||||
Delaunay T;
|
||||
T.insert(Point(0, 0, 0));
|
||||
T.insert(points.begin(), points.end());
|
||||
time.stop();
|
||||
std::cout << "Delaunay 3D with origin: "
|
||||
<< T.number_of_vertices() << " vertices in " << time.time() << " sec" << std::endl;
|
||||
|
||||
time.reset();
|
||||
time.start();
|
||||
Delaunay_fast T_fast_on2;
|
||||
T_fast_on2.insert(Point(0, 0, 0));
|
||||
T_fast_on2.insert(points.begin(), points.end());
|
||||
time.stop();
|
||||
std::cout << "Delaunay 3D with origin, fast location: " << time.time() << std::endl;
|
||||
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
|
|
@ -0,0 +1,38 @@
|
|||
#include <CGAL/Exact_predicates_inexact_constructions_kernel.h>
|
||||
|
||||
#include <CGAL/Random.h>
|
||||
#include <CGAL/point_generators_3.h>
|
||||
|
||||
typedef CGAL::Exact_predicates_inexact_constructions_kernel K;
|
||||
|
||||
int main(int argc, char* argv[])
|
||||
{
|
||||
int no_of_pts;
|
||||
double radius;
|
||||
if(argc > 1)
|
||||
{
|
||||
no_of_pts = pow(10, atoi(argv[1]));
|
||||
radius = atoi(argv[2]);
|
||||
}
|
||||
else
|
||||
{
|
||||
no_of_pts = 1000000;
|
||||
radius = 1;
|
||||
}
|
||||
|
||||
CGAL::Random random(7);
|
||||
typedef CGAL::Creator_uniform_3<double, K::Point_3> Creator;
|
||||
|
||||
std::cout << no_of_pts << std::endl;
|
||||
|
||||
CGAL::Random_points_on_sphere_3<K::Point_3, Creator> on_sphere(radius, random);
|
||||
for(int count=0; count<no_of_pts; ++count)
|
||||
{
|
||||
K::Point_3 p = *on_sphere;
|
||||
++on_sphere;
|
||||
|
||||
std::cout << p << std::endl;
|
||||
}
|
||||
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
|
|
@ -0,0 +1,49 @@
|
|||
# Created by the script cgal_create_cmake_script
|
||||
# This is the CMake script for compiling a CGAL application.
|
||||
|
||||
cmake_minimum_required(VERSION 3.1...3.15)
|
||||
|
||||
project (Triangulation_on_sphere_2_Demo)
|
||||
|
||||
set(CMAKE_ALLOW_LOOSE_LOOP_CONSTRUCTS true)
|
||||
|
||||
# Find includes in corresponding build directories
|
||||
set(CMAKE_INCLUDE_CURRENT_DIR ON)
|
||||
# Instruct CMake to run moc automatically when needed.
|
||||
set(CMAKE_AUTOMOC ON)
|
||||
if(NOT POLICY CMP0070 AND POLICY CMP0053)
|
||||
# Only set CMP0053 to OLD with CMake<3.10, otherwise there is a warning.
|
||||
cmake_policy(SET CMP0053 OLD)
|
||||
endif()
|
||||
|
||||
if(POLICY CMP0071)
|
||||
cmake_policy(SET CMP0071 NEW)
|
||||
endif()
|
||||
|
||||
|
||||
# Find CGAL and CGAL Qt5
|
||||
find_package(CGAL REQUIRED OPTIONAL_COMPONENTS Qt5)
|
||||
|
||||
# Find Qt5 itself
|
||||
find_package(Qt5 QUIET COMPONENTS Script OpenGL Gui Svg)
|
||||
|
||||
find_package(Eigen3 3.1.0) #(requires 3.1.0 or greater)
|
||||
include(CGAL_Eigen3_support)
|
||||
|
||||
if(CGAL_Qt5_FOUND AND Qt5_FOUND AND TARGET CGAL::Eigen3_support)
|
||||
# Include this package's headers first
|
||||
|
||||
include_directories(BEFORE ./ ./include)
|
||||
# ui file, created wih Qt Designer
|
||||
qt5_wrap_ui( uis Mainwindow.ui )
|
||||
|
||||
#qt5_generate_moc( main.cpp Mainwindow.moc)
|
||||
|
||||
add_executable ( Triangulation_on_sphere_2_Demo main.cpp Viewer.cpp ${uis})
|
||||
|
||||
add_to_cached_list( CGAL_EXECUTABLE_TARGETS Triangulation_on_sphere_2_Demo )
|
||||
|
||||
target_link_libraries( Triangulation_on_sphere_2_Demo PRIVATE CGAL::CGAL CGAL::CGAL_Qt5 CGAL::Eigen3_support)
|
||||
else()
|
||||
message(STATUS "NOTICE: This demo requires CGAL, the QGLViewer, OpenGL and Qt4, and will not be compiled.")
|
||||
endif()
|
||||
|
|
@ -0,0 +1,68 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<ui version="4.0">
|
||||
<class>MainWindow</class>
|
||||
<widget class="QMainWindow" name="MainWindow">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>800</width>
|
||||
<height>600</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
<string>2D Triangulation on 3D Sphere</string>
|
||||
</property>
|
||||
<widget class="QWidget" name="centralwidget">
|
||||
<layout class="QGridLayout" name="gridLayout">
|
||||
<item row="0" column="0">
|
||||
<widget class="Viewer" name="viewer" native="true"/>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<widget class="QMenuBar" name="menubar">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>800</width>
|
||||
<height>20</height>
|
||||
</rect>
|
||||
</property>
|
||||
<widget class="QMenu" name="menu_File">
|
||||
<property name="title">
|
||||
<string>&File</string>
|
||||
</property>
|
||||
<addaction name="action_Open"/>
|
||||
<addaction name="action_Quit"/>
|
||||
</widget>
|
||||
<addaction name="menu_File"/>
|
||||
</widget>
|
||||
<widget class="QStatusBar" name="statusbar"/>
|
||||
<action name="action_Quit">
|
||||
<property name="text">
|
||||
<string>&Quit</string>
|
||||
</property>
|
||||
<property name="shortcut">
|
||||
<string>Ctrl+Q</string>
|
||||
</property>
|
||||
</action>
|
||||
<action name="action_Open">
|
||||
<property name="text">
|
||||
<string>&Open</string>
|
||||
</property>
|
||||
<property name="shortcut">
|
||||
<string>Ctrl+O</string>
|
||||
</property>
|
||||
</action>
|
||||
</widget>
|
||||
<customwidgets>
|
||||
<customwidget>
|
||||
<class>Viewer</class>
|
||||
<extends>QWidget</extends>
|
||||
<header>Viewer.h</header>
|
||||
</customwidget>
|
||||
</customwidgets>
|
||||
<resources/>
|
||||
<connections/>
|
||||
</ui>
|
||||
|
|
@ -0,0 +1,448 @@
|
|||
#include "Viewer.h"
|
||||
|
||||
#include <CGAL/point_generators_3.h>
|
||||
#include <CGAL/squared_distance_3.h>
|
||||
#include <CGAL/Exact_spherical_kernel_3.h>
|
||||
|
||||
#include <CGAL/Qt/CreateOpenGLContext.h>
|
||||
#include "create_sphere.h"
|
||||
|
||||
#include <vector>
|
||||
|
||||
Viewer::Viewer(QWidget* parent )
|
||||
: CGAL::QGLViewer(parent)
|
||||
{
|
||||
draw_balls = true;
|
||||
draw_inputs = false;
|
||||
trivial_center.push_back(0.);
|
||||
trivial_center.push_back(0.);
|
||||
trivial_center.push_back(0.);
|
||||
radius_ = 1.0;
|
||||
center_ = Point_3(0,0,0);
|
||||
}
|
||||
|
||||
void Viewer::compile_shaders()
|
||||
{
|
||||
initializeOpenGLFunctions();
|
||||
for(int i = 0; i<SIZE_OF_VBO; ++i)
|
||||
if(! buffers[i].create())
|
||||
{
|
||||
std::cerr<<"VBO Creation FAILED"<<std::endl;
|
||||
return;
|
||||
}
|
||||
for(int i = 0; i<SIZE_OF_VAO; ++i)
|
||||
if(!vao[i].create())
|
||||
{
|
||||
std::cerr<<"VAO Creation FAILED"<<std::endl;
|
||||
return;
|
||||
}
|
||||
|
||||
//The sphere
|
||||
|
||||
//Vertex source code
|
||||
const char vertex_source[] =
|
||||
{
|
||||
"#version 120 \n"
|
||||
"attribute highp vec4 vertex;\n"
|
||||
"attribute highp vec3 normal;\n"
|
||||
"attribute highp vec4 center;\n"
|
||||
|
||||
"uniform highp mat4 mvp_matrix;\n"
|
||||
"uniform highp mat4 mv_matrix; \n"
|
||||
|
||||
"varying highp vec4 fP; \n"
|
||||
"varying highp vec3 fN; \n"
|
||||
"void main(void)\n"
|
||||
"{\n"
|
||||
" fP = mv_matrix * (vertex+vec4(center.xyz, 0.0)); \n"
|
||||
" fN = mat3(mv_matrix)* normal; \n"
|
||||
" gl_Position = mvp_matrix * (vertex+vec4(center.xyz, 0.0));\n"
|
||||
"}"
|
||||
};
|
||||
//Vertex source code
|
||||
const char fragment_source[] =
|
||||
{
|
||||
"#version 120 \n"
|
||||
"varying highp vec4 fP; \n"
|
||||
"varying highp vec3 fN; \n"
|
||||
"uniform highp vec4 color; \n"
|
||||
"uniform highp vec4 light_pos; \n"
|
||||
"uniform highp vec4 light_diff; \n"
|
||||
"uniform highp vec4 light_spec; \n"
|
||||
"uniform highp vec4 light_amb; \n"
|
||||
"uniform float spec_power ; \n"
|
||||
|
||||
"void main(void) { \n"
|
||||
|
||||
" highp vec3 L = light_pos.xyz - fP.xyz; \n"
|
||||
" highp vec3 V = -fP.xyz; \n"
|
||||
|
||||
" highp vec3 N = normalize(fN); \n"
|
||||
" L = normalize(L); \n"
|
||||
" V = normalize(V); \n"
|
||||
|
||||
" highp vec3 R = reflect(-L, N); \n"
|
||||
" highp vec4 diffuse = max(dot(N,L), 0.0) * light_diff * color; \n"
|
||||
" highp vec4 specular = pow(max(dot(R,V), 0.0), spec_power) * light_spec; \n"
|
||||
|
||||
"gl_FragColor = light_amb*color + diffuse ; \n"
|
||||
"} \n"
|
||||
"\n"
|
||||
};
|
||||
QOpenGLShader *vertex_shader = new QOpenGLShader(QOpenGLShader::Vertex);
|
||||
if(!vertex_shader->compileSourceCode(vertex_source))
|
||||
{
|
||||
std::cerr<<"Compiling vertex source FAILED"<<std::endl;
|
||||
}
|
||||
|
||||
QOpenGLShader *fragment_shader= new QOpenGLShader(QOpenGLShader::Fragment);
|
||||
if(!fragment_shader->compileSourceCode(fragment_source))
|
||||
{
|
||||
std::cerr<<"Compiling fragmentsource FAILED"<<std::endl;
|
||||
}
|
||||
|
||||
if(!rendering_program.addShader(vertex_shader))
|
||||
{
|
||||
std::cerr<<"adding vertex shader FAILED"<<std::endl;
|
||||
}
|
||||
if(!rendering_program.addShader(fragment_shader))
|
||||
{
|
||||
std::cerr<<"adding fragment shader FAILED"<<std::endl;
|
||||
}
|
||||
if(!rendering_program.link())
|
||||
{
|
||||
std::cerr<<"linking Program FAILED"<<std::endl;
|
||||
}
|
||||
|
||||
//The edges
|
||||
|
||||
//Vertex source code
|
||||
const char vertex_source_edges[] =
|
||||
{
|
||||
"#version 120 \n"
|
||||
"attribute highp vec4 vertex;\n"
|
||||
"uniform highp mat4 mvp_matrix;\n"
|
||||
"void main(void)\n"
|
||||
"{\n"
|
||||
" gl_Position = mvp_matrix * vertex;\n"
|
||||
"}"
|
||||
};
|
||||
//Vertex source code
|
||||
const char fragment_source_edges[] =
|
||||
{
|
||||
"#version 120 \n"
|
||||
"void main(void) { \n"
|
||||
"gl_FragColor = vec4(0.0, 0.0, 0.0, 1.0); \n"
|
||||
"} \n"
|
||||
"\n"
|
||||
};
|
||||
QOpenGLShader *vertex_shader_edges = new QOpenGLShader(QOpenGLShader::Vertex);
|
||||
if(!vertex_shader_edges->compileSourceCode(vertex_source_edges))
|
||||
{
|
||||
std::cerr<<"Compiling vertex source FAILED"<<std::endl;
|
||||
}
|
||||
|
||||
QOpenGLShader *fragment_shader_edges = new QOpenGLShader(QOpenGLShader::Fragment);
|
||||
if(!fragment_shader_edges->compileSourceCode(fragment_source_edges))
|
||||
{
|
||||
std::cerr<<"Compiling fragmentsource FAILED"<<std::endl;
|
||||
}
|
||||
|
||||
if(!rendering_program_edges.addShader(vertex_shader_edges))
|
||||
{
|
||||
std::cerr<<"adding vertex shader FAILED"<<std::endl;
|
||||
}
|
||||
if(!rendering_program_edges.addShader(fragment_shader_edges))
|
||||
{
|
||||
std::cerr<<"adding fragment shader FAILED"<<std::endl;
|
||||
}
|
||||
if(!rendering_program_edges.link())
|
||||
{
|
||||
std::cerr<<"linking Program FAILED"<<std::endl;
|
||||
}
|
||||
}
|
||||
|
||||
void Viewer::initialize_buffers()
|
||||
{
|
||||
rendering_program.bind();
|
||||
//The big white sphere
|
||||
vao[SPHERE_VAO].bind();
|
||||
|
||||
//points of the sphere
|
||||
buffers[SPHERE_POINTS].bind();
|
||||
buffers[SPHERE_POINTS].allocate(pos_sphere.data(),
|
||||
static_cast<int>(pos_sphere.size()*sizeof(float)));
|
||||
vertexLocation[0] = rendering_program.attributeLocation("vertex");
|
||||
rendering_program.enableAttributeArray(vertexLocation[0]);
|
||||
rendering_program.setAttributeBuffer(vertexLocation[0],GL_FLOAT,0,3);
|
||||
buffers[SPHERE_POINTS].release();
|
||||
|
||||
//normals of the sphere
|
||||
buffers[SPHERE_NORMALS].bind();
|
||||
buffers[SPHERE_NORMALS].allocate(normals.data(),
|
||||
static_cast<int>(normals.size()*sizeof(float)));
|
||||
normalsLocation[0] = rendering_program.attributeLocation("normal");
|
||||
rendering_program.enableAttributeArray(normalsLocation[0]);
|
||||
rendering_program.setAttributeBuffer(normalsLocation[0],GL_FLOAT,0,3);
|
||||
buffers[SPHERE_NORMALS].release();
|
||||
|
||||
//center of the sphere
|
||||
buffers[SPHERE_CENTER].bind();
|
||||
buffers[SPHERE_CENTER].allocate(trivial_center.data(),
|
||||
static_cast<int>(trivial_center.size()*sizeof(float)));
|
||||
trivialCenterLocation = rendering_program.attributeLocation("center");
|
||||
rendering_program.enableAttributeArray(trivialCenterLocation);
|
||||
rendering_program.setAttributeBuffer(trivialCenterLocation,GL_FLOAT,0,3);
|
||||
buffers[SPHERE_CENTER].release();
|
||||
|
||||
glVertexAttribDivisor(trivialCenterLocation, 1);
|
||||
glVertexAttribDivisor(normalsLocation[0], 0);
|
||||
vao[SPHERE_VAO].release();
|
||||
|
||||
//The little green spheres
|
||||
vao[POINTS_VAO].bind();
|
||||
|
||||
//points of the spheres
|
||||
buffers[POINTS_POINTS].bind();
|
||||
buffers[POINTS_POINTS].allocate(pos_sphere_inter.data(),
|
||||
static_cast<int>(pos_sphere_inter.size()*sizeof(float)));
|
||||
vertexLocation[2] = rendering_program.attributeLocation("vertex");
|
||||
rendering_program.enableAttributeArray(vertexLocation[2]);
|
||||
rendering_program.setAttributeBuffer(vertexLocation[2],GL_FLOAT,0,3);
|
||||
buffers[POINTS_POINTS].release();
|
||||
|
||||
//normals of the sphere
|
||||
buffers[POINTS_NORMALS].bind();
|
||||
buffers[POINTS_NORMALS].allocate(normals_inter.data(),
|
||||
static_cast<int>(normals_inter.size()*sizeof(float)));
|
||||
normalsLocation[2] = rendering_program.attributeLocation("normal");
|
||||
rendering_program.enableAttributeArray(normalsLocation[2]);
|
||||
rendering_program.setAttributeBuffer(normalsLocation[2],GL_FLOAT,0,3);
|
||||
buffers[POINTS_NORMALS].release();
|
||||
|
||||
//center of the sphere
|
||||
buffers[POINTS_CENTERS].bind();
|
||||
buffers[POINTS_CENTERS].allocate(pos_points.data(),
|
||||
static_cast<int>(pos_points.size()*sizeof(float)));
|
||||
centerLocation = rendering_program.attributeLocation("center");
|
||||
rendering_program.enableAttributeArray(centerLocation);
|
||||
rendering_program.setAttributeBuffer(centerLocation,GL_FLOAT,0,3);
|
||||
buffers[POINTS_CENTERS].release();
|
||||
|
||||
glVertexAttribDivisor(centerLocation, 1);
|
||||
glVertexAttribDivisor(normalsLocation[2], 0);
|
||||
vao[POINTS_VAO].release();
|
||||
rendering_program.release();
|
||||
|
||||
//The circles
|
||||
rendering_program_edges.bind();
|
||||
vao[EDGES_VAO].bind();
|
||||
buffers[EDGES_POINTS].bind();
|
||||
buffers[EDGES_POINTS].allocate(pos_lines.data(),
|
||||
static_cast<int>(pos_lines.size()*sizeof(float)));
|
||||
vertexLocation[1] = rendering_program_edges.attributeLocation("vertex");
|
||||
rendering_program_edges.enableAttributeArray(vertexLocation[1]);
|
||||
rendering_program_edges.setAttributeBuffer(vertexLocation[1],GL_FLOAT,0,3);
|
||||
buffers[EDGES_POINTS].release();
|
||||
vao[EDGES_VAO].release();
|
||||
rendering_program_edges.release();
|
||||
}
|
||||
|
||||
void Viewer::compute_elements()
|
||||
{
|
||||
pos_sphere_inter.clear();
|
||||
normals_inter.clear();
|
||||
pos_sphere.clear();
|
||||
normals.clear();
|
||||
trivial_center.clear();
|
||||
trivial_center.push_back(static_cast<float>(center_.x()));
|
||||
trivial_center.push_back(static_cast<float>(center_.y()));
|
||||
trivial_center.push_back(static_cast<float>(center_.z()));
|
||||
create_flat_sphere(static_cast<float>(radius_), pos_sphere, normals, 9);
|
||||
create_flat_sphere(0.001f*static_cast<float>(radius_), pos_sphere_inter, normals_inter, 36);
|
||||
|
||||
pos_points.resize(0);
|
||||
pos_lines.resize(0);
|
||||
|
||||
std::cout << inputs.size() << " inputs to points" << std::endl;
|
||||
// draw points as small spheres
|
||||
for(const auto& p : inputs)
|
||||
{
|
||||
pos_points.push_back(p.x());
|
||||
pos_points.push_back(p.y());
|
||||
pos_points.push_back(p.z());
|
||||
}
|
||||
|
||||
std::cout << subsampled_arcs.size() << " edge arcs" << std::endl;
|
||||
|
||||
// draw the primal edges
|
||||
std::size_t tot_size = 0;
|
||||
for(const auto& arc : subsampled_arcs)
|
||||
tot_size += arc.size();
|
||||
pos_lines.reserve(2 * 3 * tot_size);
|
||||
|
||||
for(const auto& arc : subsampled_arcs)
|
||||
{
|
||||
for(std::size_t i=0; i<arc.size()-1; ++i)
|
||||
{
|
||||
pos_lines.push_back(arc[i].x());
|
||||
pos_lines.push_back(arc[i].y());
|
||||
pos_lines.push_back(arc[i].z());
|
||||
pos_lines.push_back(arc[i+1].x());
|
||||
pos_lines.push_back(arc[i+1].y());
|
||||
pos_lines.push_back(arc[i+1].z());
|
||||
}
|
||||
}
|
||||
setSceneRadius(radius_*1.3);
|
||||
setSceneCenter({center_.x(), center_.y(), center_.z()});
|
||||
showEntireScene();
|
||||
}
|
||||
|
||||
void Viewer::attrib_buffers(CGAL::QGLViewer* viewer)
|
||||
{
|
||||
QMatrix4x4 mvpMatrix;
|
||||
QMatrix4x4 mvMatrix;
|
||||
double mat[16];
|
||||
|
||||
viewer->camera()->getModelViewProjectionMatrix(mat);
|
||||
for(int i=0; i < 16; i++)
|
||||
mvpMatrix.data()[i] = (float)mat[i];
|
||||
|
||||
viewer->camera()->getModelViewMatrix(mat);
|
||||
|
||||
for(int i=0; i < 16; i++)
|
||||
mvMatrix.data()[i] = (float)mat[i];
|
||||
|
||||
// define material
|
||||
QVector4D ambient(0.1f, 0.1f, 0.1f, 1.0f);
|
||||
QVector4D diffuse( 0.9f,
|
||||
0.9f,
|
||||
0.9f,
|
||||
0.0f );
|
||||
|
||||
QVector4D specular( 0.0f,
|
||||
0.0f,
|
||||
0.0f,
|
||||
0.0f );
|
||||
|
||||
QVector4D position( -1.2f, 1.2f, .9797958971f, 1.0f );
|
||||
GLfloat shininess = 1.0f;
|
||||
|
||||
|
||||
mvpLocation = rendering_program.uniformLocation("mvp_matrix");
|
||||
mvLocation = rendering_program.uniformLocation("mv_matrix");
|
||||
colorLocation = rendering_program.uniformLocation("color");
|
||||
lightLocation[0] = rendering_program.uniformLocation("light_pos");
|
||||
lightLocation[1] = rendering_program.uniformLocation("light_diff");
|
||||
lightLocation[2] = rendering_program.uniformLocation("light_spec");
|
||||
lightLocation[3] = rendering_program.uniformLocation("light_amb");
|
||||
lightLocation[4] = rendering_program.uniformLocation("spec_power");
|
||||
|
||||
rendering_program.setUniformValue(lightLocation[0], position);
|
||||
rendering_program.setUniformValue(lightLocation[1], diffuse);
|
||||
rendering_program.setUniformValue(lightLocation[2], specular);
|
||||
rendering_program.setUniformValue(lightLocation[3], ambient);
|
||||
rendering_program.setUniformValue(lightLocation[4], shininess);
|
||||
rendering_program.setUniformValue(mvpLocation, mvpMatrix);
|
||||
rendering_program.setUniformValue(mvLocation, mvMatrix);
|
||||
rendering_program_edges.setUniformValue("mvp_matrix", mvpMatrix);
|
||||
|
||||
}
|
||||
|
||||
void Viewer::draw()
|
||||
{
|
||||
glEnable(GL_DEPTH_TEST);
|
||||
QColor color;
|
||||
rendering_program.bind();
|
||||
|
||||
if(draw_balls)
|
||||
{
|
||||
vao[SPHERE_VAO].bind();
|
||||
attrib_buffers(this);
|
||||
color.setRgbF(1.0f, 1.0f, 1.0f);
|
||||
rendering_program.setUniformValue(colorLocation, color);
|
||||
glDrawArraysInstanced(GL_TRIANGLES, 0, static_cast<GLsizei>(pos_sphere.size()/3), 1);
|
||||
vao[SPHERE_VAO].release();
|
||||
}
|
||||
|
||||
if(draw_inputs)
|
||||
{
|
||||
vao[POINTS_VAO].bind();
|
||||
attrib_buffers(this);
|
||||
color.setRgbF(0.0f, 1.0f, 0.0f);
|
||||
rendering_program.setUniformValue(colorLocation, color);
|
||||
|
||||
glDrawArraysInstanced(GL_TRIANGLES, 0,
|
||||
static_cast<GLsizei>(pos_sphere_inter.size()/3),
|
||||
static_cast<GLsizei>(pos_points.size()/3));
|
||||
vao[POINTS_VAO].release();
|
||||
}
|
||||
rendering_program.release();
|
||||
rendering_program_edges.bind();
|
||||
vao[EDGES_VAO].bind();
|
||||
attrib_buffers(this);
|
||||
glDrawArrays(GL_LINES, 0, static_cast<GLsizei>(pos_lines.size()/3));
|
||||
vao[EDGES_VAO].release();
|
||||
rendering_program_edges.release();
|
||||
}
|
||||
|
||||
void Viewer::init()
|
||||
{
|
||||
glDrawArraysInstanced = (PFNGLDRAWARRAYSINSTANCEDARBPROC)this->context()->getProcAddress("glDrawArraysInstancedARB");
|
||||
glVertexAttribDivisor = (PFNGLVERTEXATTRIBDIVISORARBPROC)this->context()->getProcAddress("glVertexAttribDivisorARB");
|
||||
if(!glDrawArraysInstanced || !glDrawArraysInstanced)
|
||||
{
|
||||
qDebug()<<"Missing OpenGL extensions. Demo not available.";
|
||||
return;
|
||||
}
|
||||
|
||||
compile_shaders();
|
||||
compute_elements();
|
||||
|
||||
initialize_buffers();
|
||||
glEnable(GL_BLEND);
|
||||
|
||||
glHint(GL_LINE_SMOOTH_HINT, GL_NICEST);
|
||||
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
|
||||
glEnable(GL_POINT_SMOOTH);
|
||||
glEnable(GL_LINE_SMOOTH);
|
||||
}
|
||||
|
||||
QString Viewer::helpString() const
|
||||
{
|
||||
QString text("<h2>S i m p l e V i e w e r</h2>");
|
||||
text += "Use the mouse to move the camera around the object. ";
|
||||
text += "You can respectively revolve around, zoom and translate with the three mouse buttons. ";
|
||||
text += "Left and middle buttons pressed together rotate around the camera view direction axis<br><br>";
|
||||
text += "Pressing <b>Alt</b> and one of the function keys (<b>F1</b>..<b>F12</b>) defines a camera keyFrame. ";
|
||||
text += "Simply press the function key again to restore it. Several keyFrames define a ";
|
||||
text += "camera path. Paths are saved when you quit the application and restored at next start.<br><br>";
|
||||
text += "Press <b>F</b> to display the frame rate, <b>A</b> for the world axis, ";
|
||||
text += "<b>Alt+Return</b> for full screen mode and <b>Control+S</b> to save a snapshot. ";
|
||||
text += "See the <b>Keyboard</b> tab in this window for a complete shortcut list.<br><br>";
|
||||
text += "Double clicks automates single click actions: A left button double click aligns the closer axis with the camera (if close enough). ";
|
||||
text += "A middle button double click fits the zoom of the camera and the right button re-centers the scene.<br><br>";
|
||||
text += "A left button double click while holding right button pressed defines the camera <i>Revolve Around Point</i>. ";
|
||||
text += "See the <b>Mouse</b> tab and the documentation web pages for details.<br><br>";
|
||||
text += "Press <b>Escape</b> to exit the viewer.";
|
||||
return text;
|
||||
}
|
||||
|
||||
void Viewer::keyPressEvent(QKeyEvent *e)
|
||||
{
|
||||
if(e->key() == Qt::Key_P)
|
||||
{
|
||||
draw_inputs = !draw_inputs;
|
||||
update();
|
||||
return;
|
||||
}
|
||||
|
||||
if(e->key() == Qt::Key_S)
|
||||
{
|
||||
draw_balls = !draw_balls;
|
||||
update();
|
||||
return;
|
||||
}
|
||||
|
||||
QGLViewer::keyPressEvent(e);
|
||||
}
|
||||
|
|
@ -0,0 +1,173 @@
|
|||
#ifndef TRIANGULATION_ON_SPHERE_2_VIEWER_H
|
||||
#define TRIANGULATION_ON_SPHERE_2_VIEWER_H
|
||||
|
||||
#include <QMap>
|
||||
#include <CGAL/Qt/qglviewer.h>
|
||||
|
||||
#include <QOpenGLFunctions_2_1>
|
||||
#include <QOpenGLVertexArrayObject>
|
||||
#include <QOpenGLBuffer>
|
||||
#include <QOpenGLShaderProgram>
|
||||
|
||||
#include <CGAL/Exact_predicates_inexact_constructions_kernel.h>
|
||||
#include <CGAL/Delaunay_triangulation_on_sphere_traits_2.h>
|
||||
#include <CGAL/Projection_on_sphere_traits_3.h>
|
||||
#include <CGAL/Delaunay_triangulation_on_sphere_2.h>
|
||||
|
||||
#include <list>
|
||||
#include <vector>
|
||||
|
||||
class Viewer
|
||||
: public CGAL::QGLViewer
|
||||
{
|
||||
typedef CGAL::Exact_predicates_inexact_constructions_kernel Kernel;
|
||||
typedef Kernel::FT FT;
|
||||
typedef Kernel::Point_3 Point_3;
|
||||
typedef Kernel::Segment_3 Segment_3;
|
||||
|
||||
typedef CGAL::Projection_on_sphere_traits_3<Kernel> Projection_traits;
|
||||
typedef CGAL::Delaunay_triangulation_on_sphere_2<Projection_traits> Projected_DToS2;
|
||||
|
||||
typedef std::list<std::vector<Point_3> > Subsampled_arcs;
|
||||
|
||||
template <class TOS>
|
||||
void build_the_boundary(const TOS& tos)
|
||||
{
|
||||
typedef typename TOS::Geom_traits::SK Spherical_kernel;
|
||||
|
||||
if(tos.dimension() < 2)
|
||||
return;
|
||||
|
||||
typename TOS::Solid_edges_iterator it = tos.solid_edges_begin();
|
||||
for (; it != tos.solid_edges_end(); ++it)
|
||||
{
|
||||
typename TOS::Edge e = *it;
|
||||
|
||||
const bool diametral_edge = CGAL::collinear(tos.construct_point(tos.point(e.first, (e.second+1)%3)),
|
||||
tos.construct_point(tos.point(e.first, (e.second+2)%3)),
|
||||
tos.geom_traits().center());
|
||||
|
||||
subsampled_arcs.emplace_front();
|
||||
|
||||
// primal
|
||||
if(!diametral_edge)
|
||||
{
|
||||
typename TOS::Arc_on_sphere_2 as = tos.segment_on_sphere(e);
|
||||
std::vector<typename Spherical_kernel::Point_3> discretization_points;
|
||||
CGAL::Triangulations_on_sphere_2::internal::subsample_arc_on_sphere_2<Spherical_kernel>(
|
||||
as, std::back_inserter(discretization_points), min_edge_size);
|
||||
|
||||
subsampled_arcs.begin()->reserve(discretization_points.size());
|
||||
for(const typename Spherical_kernel::Point_3& spt : discretization_points)
|
||||
subsampled_arcs.begin()->push_back(Point_3(spt.x(), spt.y(), spt.z()));
|
||||
}
|
||||
else
|
||||
{
|
||||
const Segment_3 s = tos.segment(e);
|
||||
subsampled_arcs.begin()->push_back(s.source());
|
||||
subsampled_arcs.begin()->push_back(s.target());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public:
|
||||
Viewer(QWidget* parent = 0);
|
||||
|
||||
template <typename TOS, typename Iterator>
|
||||
void open(Iterator begin, Iterator end,
|
||||
const TOS& tos)
|
||||
{
|
||||
draw_balls = true;
|
||||
draw_inputs = false;
|
||||
|
||||
subsampled_arcs.clear();
|
||||
inputs.clear();
|
||||
|
||||
pos_points.clear();
|
||||
pos_lines.clear();
|
||||
pos_sphere_inter.clear();
|
||||
normals_inter.clear();
|
||||
normals_lines.clear();
|
||||
|
||||
radius_ = tos.geom_traits().radius();
|
||||
center_ = tos.geom_traits().center();
|
||||
min_edge_size = 0.01 * radius_;
|
||||
|
||||
std::copy(begin, end, std::back_inserter(inputs));
|
||||
build_the_boundary(tos);
|
||||
compute_elements();
|
||||
initialize_buffers();
|
||||
|
||||
qDebug() << "Finished loading";
|
||||
}
|
||||
|
||||
GLuint dl_nb;
|
||||
|
||||
protected :
|
||||
virtual void draw();
|
||||
virtual void init();
|
||||
virtual QString helpString() const;
|
||||
virtual void keyPressEvent(QKeyEvent *e);
|
||||
|
||||
private:
|
||||
//Shaders elements
|
||||
int vertexLocation[3];
|
||||
int normalsLocation[3];
|
||||
int centerLocation;
|
||||
int trivialCenterLocation;
|
||||
int mvpLocation;
|
||||
int mvLocation;
|
||||
int colorLocation;
|
||||
int lightLocation[5];
|
||||
|
||||
std::vector<float> pos_points;
|
||||
std::vector<float> pos_lines;
|
||||
std::vector<float> pos_sphere;
|
||||
std::vector<float> pos_sphere_inter;
|
||||
std::vector<float> normals;
|
||||
std::vector<float> normals_inter;
|
||||
std::vector<float> trivial_center;
|
||||
std::vector<float> normals_lines;
|
||||
|
||||
double min_edge_size;
|
||||
Subsampled_arcs subsampled_arcs;
|
||||
std::vector<Point_3> inputs;
|
||||
|
||||
bool draw_inputs;
|
||||
bool draw_balls;
|
||||
|
||||
enum VBO {
|
||||
SPHERE_POINTS =0,
|
||||
SPHERE_NORMALS,
|
||||
SPHERE_CENTER,
|
||||
POINTS_POINTS,
|
||||
POINTS_NORMALS,
|
||||
POINTS_CENTERS,
|
||||
EDGES_POINTS,
|
||||
SIZE_OF_VBO
|
||||
};
|
||||
|
||||
enum VAO {
|
||||
SPHERE_VAO = 0,
|
||||
POINTS_VAO,
|
||||
EDGES_VAO,
|
||||
SIZE_OF_VAO
|
||||
};
|
||||
|
||||
QOpenGLBuffer buffers[SIZE_OF_VBO];
|
||||
QOpenGLVertexArrayObject vao[SIZE_OF_VAO];
|
||||
QOpenGLShaderProgram rendering_program;
|
||||
QOpenGLShaderProgram rendering_program_edges;
|
||||
typedef void (APIENTRYP PFNGLDRAWARRAYSINSTANCEDARBPROC) (GLenum mode, GLint first, GLsizei count, GLsizei primcount);
|
||||
typedef void (APIENTRYP PFNGLVERTEXATTRIBDIVISORARBPROC) (GLuint index, GLuint divisor);
|
||||
PFNGLDRAWARRAYSINSTANCEDARBPROC glDrawArraysInstanced;
|
||||
PFNGLVERTEXATTRIBDIVISORARBPROC glVertexAttribDivisor;
|
||||
double radius_;
|
||||
Point_3 center_;
|
||||
void initialize_buffers();
|
||||
void compute_elements();
|
||||
void attrib_buffers(CGAL::QGLViewer*);
|
||||
void compile_shaders();
|
||||
};
|
||||
|
||||
#endif // TRIANGULATION_ON_SPHERE_2_VIEWER_H
|
||||
|
|
@ -0,0 +1,355 @@
|
|||
#ifndef POLYHEDRON_DEMO_CREATE_SPHERE_H
|
||||
#define POLYHEDRON_DEMO_CREATE_SPHERE_H
|
||||
|
||||
#include <CGAL/number_type_config.h>
|
||||
|
||||
#include <cmath>
|
||||
#include <vector>
|
||||
|
||||
template <class FLOAT>
|
||||
void create_flat_sphere(FLOAT R,
|
||||
std::vector<FLOAT>& positions_spheres,
|
||||
std::vector<FLOAT>& normals_spheres,
|
||||
int prec = 36)
|
||||
{
|
||||
// The smaller they are, the more precise the sphere will be
|
||||
|
||||
// Must be divisors of 180 and 360
|
||||
const float rings = float(prec) / 2;
|
||||
const float sectors = float(prec);
|
||||
const float to_rad = static_cast<float>(CGAL_PI / 180.);
|
||||
|
||||
float T, P;
|
||||
float x[4],y[4],z[4];
|
||||
|
||||
//Top of the sphere
|
||||
for(float t=0; t<360.f; t+=sectors)
|
||||
{
|
||||
positions_spheres.push_back(0);
|
||||
positions_spheres.push_back(0);
|
||||
positions_spheres.push_back(R);
|
||||
|
||||
normals_spheres.push_back(0);
|
||||
normals_spheres.push_back(0);
|
||||
normals_spheres.push_back(1);
|
||||
|
||||
P = rings*to_rad;
|
||||
T = t*to_rad;
|
||||
x[1] = sin(P) * cos(T);
|
||||
y[1] = sin(P) * sin(T);
|
||||
z[1] = cos(P);
|
||||
positions_spheres.push_back(R * x[1]);
|
||||
positions_spheres.push_back(R * y[1]);
|
||||
positions_spheres.push_back(R * z[1]);
|
||||
|
||||
normals_spheres.push_back(x[1]);
|
||||
normals_spheres.push_back(y[1]);
|
||||
normals_spheres.push_back(z[1]);
|
||||
|
||||
//
|
||||
P = rings*to_rad;
|
||||
T = (t+sectors)*to_rad;
|
||||
x[2] = sin(P) * cos(T);
|
||||
y[2] = sin(P) * sin(T);
|
||||
z[2] = cos(P);
|
||||
positions_spheres.push_back(R * x[2]);
|
||||
positions_spheres.push_back(R * y[2]);
|
||||
positions_spheres.push_back(R * z[2]);
|
||||
|
||||
normals_spheres.push_back(x[2]);
|
||||
normals_spheres.push_back(y[2]);
|
||||
normals_spheres.push_back(z[2]);
|
||||
}
|
||||
|
||||
//Body of the sphere
|
||||
for(float p=rings; p<180.f-rings; p+=rings)
|
||||
{
|
||||
for(float t=0; t<360.f; t+=sectors)
|
||||
{
|
||||
//A
|
||||
P = p*to_rad;
|
||||
T = t*to_rad;
|
||||
x[0] = sin(P) * cos(T);
|
||||
y[0] = sin(P) * sin(T);
|
||||
z[0] = cos(P);
|
||||
|
||||
positions_spheres.push_back(R * x[0]);
|
||||
positions_spheres.push_back(R * y[0]);
|
||||
positions_spheres.push_back(R * z[0]);
|
||||
|
||||
normals_spheres.push_back(x[0]);
|
||||
normals_spheres.push_back(y[0]);
|
||||
normals_spheres.push_back(z[0]);
|
||||
|
||||
//B
|
||||
P = (p+rings)*to_rad;
|
||||
T = t*to_rad;
|
||||
x[1] = sin(P) * cos(T);
|
||||
y[1] = sin(P) * sin(T);
|
||||
z[1] = cos(P);
|
||||
positions_spheres.push_back(R * x[1]);
|
||||
positions_spheres.push_back(R * y[1]);
|
||||
positions_spheres.push_back(R * z[1]);
|
||||
|
||||
normals_spheres.push_back(x[1]);
|
||||
normals_spheres.push_back(y[1]);
|
||||
normals_spheres.push_back(z[1]);
|
||||
|
||||
//C
|
||||
P = p*to_rad;
|
||||
T = (t+sectors)*to_rad;
|
||||
x[2] = sin(P) * cos(T);
|
||||
y[2] = sin(P) * sin(T);
|
||||
z[2] = cos(P);
|
||||
positions_spheres.push_back(R * x[2]);
|
||||
positions_spheres.push_back(R * y[2]);
|
||||
positions_spheres.push_back(R * z[2]);
|
||||
|
||||
normals_spheres.push_back(x[2]);
|
||||
normals_spheres.push_back(y[2]);
|
||||
normals_spheres.push_back(z[2]);
|
||||
|
||||
//D
|
||||
P = (p+rings)*to_rad;
|
||||
T = (t+sectors)*to_rad;
|
||||
x[3] = sin(P) * cos(T);
|
||||
y[3] = sin(P) * sin(T);
|
||||
z[3] = cos(P);
|
||||
positions_spheres.push_back(R * x[3]);
|
||||
positions_spheres.push_back(R * y[3]);
|
||||
positions_spheres.push_back(R * z[3]);
|
||||
|
||||
normals_spheres.push_back(x[3]);
|
||||
normals_spheres.push_back(y[3]);
|
||||
normals_spheres.push_back(z[3]);
|
||||
|
||||
positions_spheres.push_back(R * x[1]);
|
||||
positions_spheres.push_back(R * y[1]);
|
||||
positions_spheres.push_back(R * z[1]);
|
||||
|
||||
normals_spheres.push_back(x[1]);
|
||||
normals_spheres.push_back(y[1]);
|
||||
normals_spheres.push_back(z[1]);
|
||||
|
||||
positions_spheres.push_back(R * x[2]);
|
||||
positions_spheres.push_back(R * y[2]);
|
||||
positions_spheres.push_back(R * z[2]);
|
||||
|
||||
normals_spheres.push_back(x[2]);
|
||||
normals_spheres.push_back(y[2]);
|
||||
normals_spheres.push_back(z[2]);
|
||||
}
|
||||
}
|
||||
|
||||
//Bottom of the sphere
|
||||
for(float t=0; t<360.f; t+=sectors)
|
||||
{
|
||||
positions_spheres.push_back(0);
|
||||
positions_spheres.push_back(0);
|
||||
positions_spheres.push_back(-R);
|
||||
|
||||
normals_spheres.push_back(0);
|
||||
normals_spheres.push_back(0);
|
||||
normals_spheres.push_back(-1);
|
||||
|
||||
P = (180-rings)*to_rad;
|
||||
T = t*to_rad;
|
||||
x[1] = sin(P) * cos(T);
|
||||
y[1] = sin(P) * sin(T);
|
||||
z[1] = cos(P);
|
||||
positions_spheres.push_back(R * x[1]);
|
||||
positions_spheres.push_back(R * y[1]);
|
||||
positions_spheres.push_back(R * z[1]);
|
||||
|
||||
normals_spheres.push_back(x[1]);
|
||||
normals_spheres.push_back(y[1]);
|
||||
normals_spheres.push_back(z[1]);
|
||||
|
||||
P = (180-rings)*to_rad;
|
||||
T = (t+sectors)*to_rad;
|
||||
x[2] = sin(P) * cos(T);
|
||||
y[2] = sin(P) * sin(T);
|
||||
z[2] = cos(P);
|
||||
positions_spheres.push_back(R * x[2]);
|
||||
positions_spheres.push_back(R * y[2]);
|
||||
positions_spheres.push_back(R * z[2]);
|
||||
|
||||
normals_spheres.push_back(x[2]);
|
||||
normals_spheres.push_back(y[2]);
|
||||
normals_spheres.push_back(z[2]);
|
||||
}
|
||||
}
|
||||
|
||||
template <class FLOAT>
|
||||
void create_flat_and_wire_sphere(FLOAT R,
|
||||
std::vector<FLOAT>& positions_spheres,
|
||||
std::vector<FLOAT>& normals_spheres,
|
||||
std::vector<FLOAT>& positions_wire_spheres,
|
||||
int prec = 36)
|
||||
{
|
||||
// The smaller they are, the more precise the sphere will be
|
||||
|
||||
// Must be a divisor of 360 and 180.
|
||||
const float rings = float(prec)/2;
|
||||
const float sectors = float(prec);
|
||||
const float to_rad = static_cast<float>(CGAL_PI / 180.0);
|
||||
|
||||
create_flat_sphere(R, positions_spheres, normals_spheres);
|
||||
|
||||
float T, P;
|
||||
float x[4],y[4],z[4];
|
||||
|
||||
//Top of the sphere
|
||||
for(float t=0; t<360; t+=sectors)
|
||||
{
|
||||
positions_wire_spheres.push_back(0);
|
||||
positions_wire_spheres.push_back(0);
|
||||
positions_wire_spheres.push_back(R);
|
||||
|
||||
P = rings*to_rad;
|
||||
T = t*to_rad;
|
||||
x[1] = sin(P) * cos(T);
|
||||
y[1] = sin(P) * sin(T);
|
||||
z[1] = cos(P);
|
||||
|
||||
positions_wire_spheres.push_back(R * x[1]);
|
||||
positions_wire_spheres.push_back(R * y[1]);
|
||||
positions_wire_spheres.push_back(R * z[1]);
|
||||
|
||||
positions_wire_spheres.push_back(R * x[1]);
|
||||
positions_wire_spheres.push_back(R * y[1]);
|
||||
positions_wire_spheres.push_back(R * z[1]);
|
||||
|
||||
//
|
||||
P = rings*to_rad;
|
||||
T = (t+sectors)*to_rad;
|
||||
x[2] = sin(P) * cos(T);
|
||||
y[2] = sin(P) * sin(T);
|
||||
z[2] = cos(P);
|
||||
positions_wire_spheres.push_back(R * x[2]);
|
||||
positions_wire_spheres.push_back(R * y[2]);
|
||||
positions_wire_spheres.push_back(R * z[2]);
|
||||
|
||||
positions_wire_spheres.push_back(R * x[2]);
|
||||
positions_wire_spheres.push_back(R * y[2]);
|
||||
positions_wire_spheres.push_back(R * z[2]);
|
||||
|
||||
positions_wire_spheres.push_back(0);
|
||||
positions_wire_spheres.push_back(0);
|
||||
positions_wire_spheres.push_back(R);
|
||||
}
|
||||
|
||||
//Body of the sphere
|
||||
for(float p=rings; p<180.f-rings; p+=rings)
|
||||
{
|
||||
for(float t=0; t<360.f; t+=sectors)
|
||||
{
|
||||
//A
|
||||
P = p*to_rad;
|
||||
T = t*to_rad;
|
||||
x[0] = sin(P) * cos(T);
|
||||
y[0] = sin(P) * sin(T);
|
||||
z[0] = cos(P);
|
||||
|
||||
//B
|
||||
P = (p+rings)*to_rad;
|
||||
T = t*to_rad;
|
||||
x[1] = sin(P) * cos(T);
|
||||
y[1] = sin(P) * sin(T);
|
||||
z[1] = cos(P);
|
||||
|
||||
//C
|
||||
P = p*to_rad;
|
||||
T = (t+sectors)*to_rad;
|
||||
x[2] = sin(P) * cos(T);
|
||||
y[2] = sin(P) * sin(T);
|
||||
z[2] = cos(P);
|
||||
|
||||
//D
|
||||
P = (p+rings)*to_rad;
|
||||
T = (t+sectors)*to_rad;
|
||||
x[3] = sin(P) * cos(T);
|
||||
y[3] = sin(P) * sin(T);
|
||||
z[3] = cos(P);
|
||||
|
||||
positions_wire_spheres.push_back(R * x[0]);
|
||||
positions_wire_spheres.push_back(R * y[0]);
|
||||
positions_wire_spheres.push_back(R * z[0]);
|
||||
|
||||
positions_wire_spheres.push_back(R * x[1]);
|
||||
positions_wire_spheres.push_back(R * y[1]);
|
||||
positions_wire_spheres.push_back(R * z[1]);
|
||||
|
||||
|
||||
positions_wire_spheres.push_back(R * x[1]);
|
||||
positions_wire_spheres.push_back(R * y[1]);
|
||||
positions_wire_spheres.push_back(R * z[1]);
|
||||
|
||||
positions_wire_spheres.push_back(R * x[3]);
|
||||
positions_wire_spheres.push_back(R * y[3]);
|
||||
positions_wire_spheres.push_back(R * z[3]);
|
||||
|
||||
|
||||
positions_wire_spheres.push_back(R * x[3]);
|
||||
positions_wire_spheres.push_back(R * y[3]);
|
||||
positions_wire_spheres.push_back(R * z[3]);
|
||||
|
||||
positions_wire_spheres.push_back(R * x[2]);
|
||||
positions_wire_spheres.push_back(R * y[2]);
|
||||
positions_wire_spheres.push_back(R * z[2]);
|
||||
|
||||
|
||||
positions_wire_spheres.push_back(R * x[2]);
|
||||
positions_wire_spheres.push_back(R * y[2]);
|
||||
positions_wire_spheres.push_back(R * z[2]);
|
||||
|
||||
positions_wire_spheres.push_back(R * x[0]);
|
||||
positions_wire_spheres.push_back(R * y[0]);
|
||||
positions_wire_spheres.push_back(R * z[0]);
|
||||
}
|
||||
}
|
||||
|
||||
//Bottom of the sphere
|
||||
for(float t=0; t<360.f; t+=sectors)
|
||||
{
|
||||
P = (180-rings)*to_rad;
|
||||
T = t*to_rad;
|
||||
x[1] = sin(P) * cos(T);
|
||||
y[1] = sin(P) * sin(T);
|
||||
z[1] = cos(P);
|
||||
|
||||
P = (180-rings)*to_rad;
|
||||
T = (t+sectors)*to_rad;
|
||||
x[2] = sin(P) * cos(T);
|
||||
y[2] = sin(P) * sin(T);
|
||||
z[2] = cos(P);
|
||||
|
||||
positions_wire_spheres.push_back(0);
|
||||
positions_wire_spheres.push_back(0);
|
||||
positions_wire_spheres.push_back(-R);
|
||||
|
||||
positions_wire_spheres.push_back(R * x[1]);
|
||||
positions_wire_spheres.push_back(R * y[1]);
|
||||
positions_wire_spheres.push_back(R * z[1]);
|
||||
|
||||
|
||||
positions_wire_spheres.push_back(R * x[1]);
|
||||
positions_wire_spheres.push_back(R * y[1]);
|
||||
positions_wire_spheres.push_back(R * z[1]);
|
||||
|
||||
positions_wire_spheres.push_back(R * x[2]);
|
||||
positions_wire_spheres.push_back(R * y[2]);
|
||||
positions_wire_spheres.push_back(R * z[2]);
|
||||
|
||||
|
||||
positions_wire_spheres.push_back(R * x[2]);
|
||||
positions_wire_spheres.push_back(R * y[2]);
|
||||
positions_wire_spheres.push_back(R * z[2]);
|
||||
|
||||
positions_wire_spheres.push_back(0);
|
||||
positions_wire_spheres.push_back(0);
|
||||
positions_wire_spheres.push_back(-R);
|
||||
}
|
||||
}
|
||||
|
||||
#endif //POLYHEDRON_DEMO_DRAW_SPHERE_H
|
||||
|
|
@ -0,0 +1,127 @@
|
|||
#include <CGAL/Exact_predicates_inexact_constructions_kernel.h>
|
||||
|
||||
#include <CGAL/Delaunay_triangulation_on_sphere_traits_2.h>
|
||||
#include <CGAL/Projection_on_sphere_traits_3.h>
|
||||
#include <CGAL/Delaunay_triangulation_on_sphere_2.h>
|
||||
|
||||
#include <CGAL/utility.h>
|
||||
#include <CGAL/Qt/DemosMainWindow.h>
|
||||
|
||||
#include <QApplication>
|
||||
#include <QMainWindow>
|
||||
#include <QFileDialog>
|
||||
#include <QInputDialog>
|
||||
#include <CGAL/Three/Three.h>
|
||||
|
||||
#include <boost/iterator/transform_iterator.hpp>
|
||||
|
||||
#include <list>
|
||||
#include <fstream>
|
||||
|
||||
typedef CGAL::Exact_predicates_inexact_constructions_kernel Kernel;
|
||||
typedef Kernel::FT FT;
|
||||
typedef Kernel::Point_3 Point_3;
|
||||
typedef Kernel::Segment_3 Segment_3;
|
||||
|
||||
typedef CGAL::Projection_on_sphere_traits_3<Kernel> Projection_traits;
|
||||
typedef CGAL::Delaunay_triangulation_on_sphere_2<Projection_traits> Projected_DToS2;
|
||||
|
||||
typedef std::list<std::vector<Point_3> > Subsampled_arcs;
|
||||
|
||||
#include "Viewer.h"
|
||||
#include "ui_Mainwindow.h"
|
||||
|
||||
template <class Output_iterator>
|
||||
void read_points(const char* file_path, Output_iterator out)
|
||||
{
|
||||
std::ifstream input(file_path);
|
||||
if(!input)
|
||||
{
|
||||
std::cerr << "Error while reading " << file_path << std::endl;
|
||||
std::exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
double x,y,z;
|
||||
while(input >> x >> y >> z)
|
||||
*out++ = Point_3(x, y, z);
|
||||
}
|
||||
|
||||
class MainWindow
|
||||
: public CGAL::Qt::DemosMainWindow,
|
||||
public Ui::MainWindow
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
MainWindow()
|
||||
{
|
||||
setupUi(this);
|
||||
}
|
||||
|
||||
public slots:
|
||||
void open(QString filename)
|
||||
{
|
||||
std::vector<Point_3> lst_pt;
|
||||
read_points(filename.toUtf8().data(), std::back_inserter(lst_pt));
|
||||
|
||||
const Point_3 center(0,0,0);
|
||||
const QString infos = QInputDialog::getText(nullptr, "Sphere", "Enter the sphere's information : (Radius center.x center.y center.z):",
|
||||
QLineEdit::Normal,"100.0 0.0 0.0 0.0");
|
||||
QStringList list = infos.split(QRegExp("\\s+"), CGAL_QT_SKIP_EMPTY_PARTS);
|
||||
if (list.isEmpty()) return;
|
||||
if (list.size()!=4){
|
||||
QMessageBox *msgBox = new QMessageBox;
|
||||
msgBox->setWindowTitle("Error");
|
||||
msgBox->setText("ERROR : Input should consists of 4 doubles: The radius first, then the coordinates of the center.");
|
||||
msgBox->exec();
|
||||
return;
|
||||
}
|
||||
|
||||
double coords[4];
|
||||
for(int j=0; j<4; ++j)
|
||||
{
|
||||
bool ok;
|
||||
coords[j] = list.at(j).toDouble(&ok);
|
||||
if(!ok)
|
||||
{
|
||||
QMessageBox *msgBox = new QMessageBox;
|
||||
msgBox->setWindowTitle("Error");
|
||||
msgBox->setText("ERROR : Input is invalid.");
|
||||
msgBox->exec();
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
Projection_traits traits(Point_3(coords[1], coords[2], coords[3]), coords[0]);
|
||||
Projected_DToS2 dtos(lst_pt.begin(), lst_pt.end(), traits);
|
||||
|
||||
std::cout << dtos.number_of_vertices() << " vertices" << std::endl;
|
||||
|
||||
// Instantiate the viewer
|
||||
viewer->open(lst_pt.begin(), lst_pt.end(), dtos);
|
||||
}
|
||||
|
||||
void on_action_Quit_triggered()
|
||||
{
|
||||
close();
|
||||
}
|
||||
|
||||
void on_action_Open_triggered()
|
||||
{
|
||||
QString filename = QFileDialog::getOpenFileName(this);
|
||||
if(!filename.isNull())
|
||||
open(filename);
|
||||
}
|
||||
};
|
||||
|
||||
int main(int argc, char** argv)
|
||||
{
|
||||
// Read command lines arguments
|
||||
QApplication application(argc,argv);
|
||||
MainWindow mainWindow;
|
||||
mainWindow.show();
|
||||
|
||||
// Run main loop
|
||||
return application.exec();
|
||||
}
|
||||
|
||||
#include "main.moc"
|
||||
|
|
@ -0,0 +1,260 @@
|
|||
namespace CGAL {
|
||||
|
||||
/*!
|
||||
\ingroup PkgTriangulationOnSphere2TriangulationClasses
|
||||
|
||||
The class `Delaunay_triangulation_on_sphere_2` is designed to represent
|
||||
the Delaunay triangulation of a set of points on the 2-sphere.
|
||||
|
||||
A Delaunay triangulation of a set of points is a triangulation of the set of points that fulfills
|
||||
the following <I>empty circle property</I> (also called <I>Delaunay property</I>): the circumscribing
|
||||
sphere of any simplex of the triangulation contains no point of the set in its interior.
|
||||
For a point set with no case of co-circularity of more than three points,
|
||||
the Delaunay triangulation is unique, and defined as the dual of the Voronoi diagram of the points.
|
||||
|
||||
The setting of 3D points on the 2-sphere is particular in that the empty circle property
|
||||
can be reduced to a single 3D orientation test \cgalCite{cgal:ccplr-redtp-10}.
|
||||
|
||||
\tparam Traits is the geometric traits; it must be a model of `DelaunayTriangulationOnSphereTraits_2`.
|
||||
|
||||
\tparam TDS is the triangulation data structure, which must be a model of `TriangulationDataStructure_2`
|
||||
whose vertex base must be a model of `TriangulationOnSphereVertexBase_2` and whose face base
|
||||
must be a model of `TriangulationOnSphereFaceBase_2`. \cgal provides a default instantiation
|
||||
for this parameter, which is the class
|
||||
`CGAL::Triangulation_data_structure_2 < CGAL::Triangulation_on_sphere_vertex_base_2<Traits>,
|
||||
CGAL::Triangulation_on_sphere_face_base_2<Traits> >`.
|
||||
|
||||
\sa `CGAL::Triangulation_on_sphere_2<Traits, TDS>`
|
||||
*/
|
||||
template< typename Traits, typename TDS >
|
||||
class Delaunay_triangulation_on_sphere_2
|
||||
: public Triangulation_on_sphere_2<Traits, TDS>
|
||||
{
|
||||
public:
|
||||
/// \name Types
|
||||
/// @{
|
||||
|
||||
/*!
|
||||
The traits class.
|
||||
*/
|
||||
typedef Traits Geom_traits;
|
||||
|
||||
/*!
|
||||
The point type representing a point on the sphere.
|
||||
*/
|
||||
typedef Traits::Point_on_sphere_2 Point;
|
||||
|
||||
/// @}
|
||||
|
||||
/// \name Creation
|
||||
/// @{
|
||||
|
||||
/*!
|
||||
introduces an empty triangulation and sets the center and radius of the sphere to `c` and `r` respectively.
|
||||
*/
|
||||
Delaunay_triangulation_on_sphere_2(const Point_3& c, const FT r);
|
||||
|
||||
/*!
|
||||
introduces an empty triangulation.
|
||||
|
||||
\note The values for the center and radius must be either already set in the traits
|
||||
(if `gt` is provided) or must be set after the construction, using the function `set_center_and_radius()`.
|
||||
*/
|
||||
Delaunay_triangulation_on_sphere_2(const Geom_traits& gt = Geom_traits());
|
||||
|
||||
/*!
|
||||
introduces an empty triangulation, sets the center and radius of the sphere to `c` and `r` respectively,
|
||||
and inserts the point range `[first; beyond[`.
|
||||
|
||||
\tparam PointOnSphereIterator must be a model of `InputIterator` with value type `Point_on_sphere_2` or `Point_3`.
|
||||
*/
|
||||
template <typename PointOnSphereIterator>
|
||||
Delaunay_triangulation_on_sphere_2(PointOnSphereIterator first, PointOnSphereIterator beyond,
|
||||
const Point_3& center, const FT radius);
|
||||
|
||||
/*!
|
||||
introduces an empty triangulation whose center and radius are set according to values within the traits
|
||||
and inserts the point range `[first;beyond[`.
|
||||
|
||||
\warning It is the user's responsability to ensure that the center and radius are set as intended in `gt`.
|
||||
|
||||
\tparam PointOnSphereIterator must be a model of `InputIterator` with value type `Point_on_sphere_2` or `Point_3`.
|
||||
*/
|
||||
template <typename PointOnSphereIterator>
|
||||
Delaunay_triangulation_on_sphere_2(PointOnSphereIterator first, PointOnSphereIterator beyond,
|
||||
const Geom_traits& gt = Geom_traits());
|
||||
|
||||
/*!
|
||||
Copy constructor. All the vertices and faces are duplicated.
|
||||
*/
|
||||
Delaunay_triangulation_on_sphere_2(const Delaunay_triangulation_on_sphere_2<Traits,TDS> &tr);
|
||||
|
||||
/// @}
|
||||
|
||||
public:
|
||||
/// \name Predicates
|
||||
///
|
||||
/// @{
|
||||
|
||||
/*!
|
||||
returns the side of `p` with respect to the circle circumscribing the triangle associated with `f`.
|
||||
*/
|
||||
Oriented_side side_of_oriented_circle(Face_handle f, const Point& p) const;
|
||||
|
||||
/// @}
|
||||
|
||||
public:
|
||||
/// \name Insertion and Removal
|
||||
///
|
||||
/// Methods for the insertion and removal of points on the sphere.
|
||||
/// In the degenerate setting of co-circular points, the Delaunay triangulation is known
|
||||
/// not to be uniquely defined. In this case, \cgal chooses a particular Delaunay triangulation
|
||||
/// using a symbolic perturbation scheme \cgalCite{cgal:dt-pvr3d-03}.
|
||||
///
|
||||
/// @{
|
||||
|
||||
/*!
|
||||
inserts the point `p`.
|
||||
If the point `p` coincides with an already existing vertex, this vertex is returned
|
||||
and the triangulation remains unchanged.
|
||||
The optional parameter `f` is used to give a hint about the location of `p`.
|
||||
*/
|
||||
Vertex_handle insert(const Point& p, Face_handle f = Face_handle());
|
||||
|
||||
/*!
|
||||
inserts the point `p` at the location given by `(lt, loc, li)`.
|
||||
|
||||
\sa `Triangulation_on_sphere_2::locate()`
|
||||
*/
|
||||
Vertex_handle insert(const Point& p, Locate_type& lt, Face_handle loc, int li );
|
||||
|
||||
/*!
|
||||
Equivalent to `insert(p)`.
|
||||
*/
|
||||
Vertex_handle push_back(const Point& p);
|
||||
|
||||
/*!
|
||||
inserts the points in the range `[first, beyond)` and returns the number of inserted points.
|
||||
|
||||
\tparam PointOnSphereIterator must be a model of `InputIterator` with value type `Point`.
|
||||
*/
|
||||
template <class PointOnSphereIterator>
|
||||
size_type insert(PointOnSphereIterator first, PointOnSphereIterator beyond);
|
||||
|
||||
/*!
|
||||
removes the vertex `v` from the triangulation.
|
||||
*/
|
||||
void remove(Vertex_handle v);
|
||||
|
||||
/// @}
|
||||
|
||||
/// \name Queries
|
||||
/// @{
|
||||
|
||||
/*!
|
||||
outputs the faces and boundary edges of the conflict zone of point `p` into output iterators.
|
||||
|
||||
This function outputs in the container pointed to by `fit` the faces which are in conflict with point `p`,
|
||||
i. e., the faces whose circumcircle contains `p`. It outputs in the container pointed to by `eit`
|
||||
the boundary of the zone in conflict with `p`. The boundary edges of the conflict zone
|
||||
are output in counter-clockwise order and each edge is described through its incident face
|
||||
which is not in conflict with `p`. The function returns in a `std::pair` the resulting output iterators.
|
||||
|
||||
\tparam OutItFaces is an output iterator with `Face_handle` as value type.
|
||||
\tparam OutItBoundaryEdges is an output iterator with `Edge` as value type.
|
||||
|
||||
\warning This function makes uses of the member `tds_data` (see the concept `TriangulationDSFaceBase_2`)
|
||||
of the face to mark faces in conflict. It is the responsability of the user to make sure the flags are cleared.
|
||||
|
||||
\pre `dimension() == 2`.
|
||||
*/
|
||||
template <typename OutputItFaces, typename OutputItBoundaryEdges>
|
||||
std::pair<OutputItFaces, OutputItBoundaryEdges>
|
||||
get_conflicts_and_boundary(const Point& p,
|
||||
OutputItFaces fit,
|
||||
OutputItBoundaryEdges eit,
|
||||
Face_handle start) const;
|
||||
|
||||
/// @}
|
||||
|
||||
/// \name Voronoi Diagram
|
||||
///
|
||||
/// The following member functions provide the elements of the dual Voronoi diagram.
|
||||
/// Two different embeddings are possible: a "straight" embedding, using line segments living
|
||||
/// in Euclidean 3D sphere, and a "curved" embedding, using arc segments on the sphere.
|
||||
///
|
||||
/// Note that the following operations are constructions, which should be kept in mind in the choice
|
||||
/// of the underlying kernel.
|
||||
///
|
||||
/// @{
|
||||
|
||||
// Straight
|
||||
|
||||
/*!
|
||||
returns the center of the circle circumscribed to face `f`
|
||||
*/
|
||||
Point_3 dual(const Face_handle f) const;
|
||||
|
||||
/*!
|
||||
returns the line segment with endpoints the circumcenters of the faces incident to the edge `e`.
|
||||
*/
|
||||
Segment_3 dual(const Edge& e) const;
|
||||
|
||||
/*!
|
||||
returns the line segment with endpoints the circumcenters of the faces incident to the edge `*ec`.
|
||||
*/
|
||||
Segment_3 dual(const Edge_circulator ec) const;
|
||||
|
||||
/*!
|
||||
returns the line segment with endpoints the circumcenters of the faces incident to the edge `*ei`.
|
||||
*/
|
||||
Segment_3 dual(const All_edges_iterator ei) const;
|
||||
|
||||
// Curved
|
||||
|
||||
/*!
|
||||
returns the intersection of the dual of the face `f` and the sphere.
|
||||
|
||||
\pre `dimension() == 2` and `f` is a solid face.
|
||||
*/
|
||||
Point dual_on_sphere(const Face_handle f) const;
|
||||
|
||||
/*!
|
||||
returns the arc of great circle with endpoints the circumcenters of the faces incident to the edge `e`.
|
||||
|
||||
\pre `dimension() == 2` and `e` is not a ghost edge.
|
||||
*/
|
||||
Arc_on_sphere_2 dual_on_sphere(const Edge& e) const;
|
||||
|
||||
/*!
|
||||
returns the arc of great circle with endpoints the circumcenters of the faces incident to the edge `*ec`.
|
||||
|
||||
\pre `dimension() == 2` and `*ec` is not a ghost edge.
|
||||
*/
|
||||
Arc_on_sphere_2 dual_on_sphere(const Edge_circulator ec) const;
|
||||
|
||||
/*!
|
||||
returns the arc of great circle with endpoints the circumcenters of the faces incident to the edge `*ei`.
|
||||
|
||||
\pre `dimension() == 2` and `*ei` is not a ghost edge.
|
||||
*/
|
||||
Arc_on_sphere_2 dual_on_sphere(const All_edges_iterator ei) const;
|
||||
|
||||
/// @}
|
||||
|
||||
/// \name Miscellaneous
|
||||
///
|
||||
/// @{
|
||||
|
||||
/*!
|
||||
tests the validity of the triangulation as a `Triangulation_on_sphere_2`
|
||||
and additionally tests the Delaunay property. This method is mainly useful
|
||||
for debugging Delaunay triangulation algorithms.
|
||||
*/
|
||||
bool is_valid(bool verbose = false, int level = 0) const;
|
||||
|
||||
/// @}
|
||||
|
||||
};
|
||||
|
||||
} // namespace CGAL
|
||||
|
|
@ -0,0 +1,119 @@
|
|||
namespace CGAL {
|
||||
|
||||
/*!
|
||||
\ingroup PkgTriangulationOnSphere2TriangulationClasses
|
||||
|
||||
The class `Delaunay_triangulation_on_sphere_traits_2` is a model
|
||||
of the concept `DelaunayTriangulationOnSphereTraits_2`.
|
||||
|
||||
The `Point_on_sphere_2` type is implemented as a kernel `Point_3` type.
|
||||
|
||||
If the kernel template parameter `LK` does not enable exact representation of points on sphere
|
||||
(i.e., at least a mean to represent algebraic coordinates), then it cannot be guaranteed
|
||||
that all points on the sphere are in a convex position and thus some points might be hidden upon insertion.
|
||||
It is possible to ensure that no point can be hidden by enforcing a tiny gap between points \cgalCite{cgal:ccplr-redtp-10}.
|
||||
In Lemma 4.1 of this publication, it is in particular proven that if points lie within a distance
|
||||
\f$ \delta \f$ of the sphere, no point is hidden as long as points are separated by at least \f$ 2 \sqrt{R\delta} \f$
|
||||
with \f$ R \f$ the radius of the sphere.
|
||||
|
||||
Thus, if `LK` offers exact representation, then \f$ \delta \f$ is set to \f$ 0 \f$.
|
||||
Otherwise, \f$ \delta \f$ is set to the maximal distance between two consecutive `LK::FT`
|
||||
for the coordinates of a point that is (theoretically) on the sphere.
|
||||
This bound \f$ \delta \f$ is then used in the functions `is_on_sphere()` and `are_points_too_close()`
|
||||
using the relation above to ensure that a point being inserted is either marked as "too close"
|
||||
(see \link CGAL::Triangulation_on_sphere_2::Locate_type `CGAL::Triangulation_on_sphere_2<Traits,TDS>::Locate_type` \endlink)
|
||||
and thus not inserted, or guaranteed to not be hidden upon insertion.
|
||||
|
||||
\tparam LK a linear kernel type; it must be a model of `Kernel`.
|
||||
\tparam SK a spherical kernel type; it must be a model of `SphericalKernel` refining `LK`.
|
||||
|
||||
\cgalModels `DelaunayTriangulationOnSphereTraits_2`
|
||||
|
||||
\sa `CGAL::Projection_on_sphere_traits_3`
|
||||
*/
|
||||
template <typename LK,
|
||||
typename SK = CGAL::Spherical_kernel_3<
|
||||
LK, CGAL::Algebraic_kernel_for_spheres_2_3<typename LK::FT> > >
|
||||
class Delaunay_triangulation_on_sphere_traits_2
|
||||
{
|
||||
public:
|
||||
/// The field number type
|
||||
typedef typename LK::FT FT;
|
||||
|
||||
///
|
||||
typedef typename LK::Point_3 Point_on_sphere_2;
|
||||
|
||||
/// An arc of a great circle, used to represent a curved segment on the sphere (Voronoi or Delaunay edge).
|
||||
typedef typename SK::Circular_arc_3 Arc_on_sphere_2;
|
||||
|
||||
///
|
||||
typedef typename LK::Point_3 Point_3;
|
||||
|
||||
///
|
||||
typedef typename LK::Segment_3 Segment_3;
|
||||
|
||||
///
|
||||
typedef typename LK::Triangle_3 Triangle_3;
|
||||
|
||||
/// \name Predicates
|
||||
///
|
||||
/// @{
|
||||
|
||||
/// Internally uses `LK::Coplanar_orientation_3`
|
||||
typedef unspecified_type Collinear_are_strictly_ordered_on_great_circle_2;
|
||||
|
||||
///
|
||||
typedef typename LK::Compare_xyz_3 Compare_on_sphere_2;
|
||||
|
||||
/// If the kernel cannot represent algebraic coordinates exactly, there is a tolerance
|
||||
/// around the sphere, and thus different points of \f$ \mathbb{R}^3\f$ can actually
|
||||
/// correspond to the same point on the sphere.
|
||||
/// This functor checks if two points project onto the same point on the sphere.
|
||||
typedef unspecified_type Equal_on_sphere_2;
|
||||
|
||||
///
|
||||
typedef typename LK::Orientation_3 Side_of_oriented_circle_on_sphere_2;
|
||||
|
||||
/// Internally uses `LK::Orientation_3`
|
||||
typedef unspecified_type Orientation_on_sphere_2;
|
||||
|
||||
/// @}
|
||||
|
||||
/// \name Constructions
|
||||
///
|
||||
/// @{
|
||||
|
||||
/// Internally uses `SK::Construct_circular_arc_3`
|
||||
typedef typename unspecified_type Construct_arc_on_sphere_2;
|
||||
|
||||
///
|
||||
typedef typename LK::Construct_circumcenter_3 Construct_circumcenter_3;
|
||||
|
||||
///
|
||||
typedef typename LK::Construct_point_3 Construct_point_3;
|
||||
|
||||
///
|
||||
typedef typename LK::Construct_segment_3 Construct_segment_3;
|
||||
|
||||
///
|
||||
typedef typename LK::Construct_triangle_3 Construct_triangle_3;
|
||||
|
||||
/// @}
|
||||
|
||||
public:
|
||||
/// \name Precision predicates
|
||||
///
|
||||
/// @{
|
||||
|
||||
/// returns whether `p` is exactly on the sphere if `LK` can represent algebraic coordinates,
|
||||
/// or whether `p` is within an automatically computed small distance otherwise.
|
||||
bool is_on_sphere(const Point_on_sphere_2& p) const;
|
||||
|
||||
/// returns `false` if `LK` can represent algebraic coordinates, or whether the distance
|
||||
/// between `p` and `q` is lower than \f$ 2 \sqrt{R\delta} \f$ otherwise.
|
||||
bool are_points_too_close(const Point_on_sphere_2& p, const Point_on_sphere_2& q) const;
|
||||
|
||||
/// @}
|
||||
};
|
||||
|
||||
} // namespace CGAL
|
||||
|
|
@ -0,0 +1,69 @@
|
|||
namespace CGAL {
|
||||
|
||||
/*!
|
||||
\ingroup PkgTriangulationOnSphere2TriangulationClasses
|
||||
|
||||
The class `Projection_on_sphere_traits_3` is a model of the concept `DelaunayTriangulationOnSphereTraits_2`.
|
||||
|
||||
It implements the `Point_on_sphere_2` type as a custom point type which represents the projection
|
||||
of a point living in the 3D Euclidean space onto the sphere along the segment between said point
|
||||
and the center of the sphere.
|
||||
|
||||
\tparam LK a linear kernel type; must be a model of `Kernel`.
|
||||
\tparam SK a spherical kernel type; must be a model of `SphericalKernel`.
|
||||
|
||||
\cgalModels `DelaunayTriangulationOnSphereTraits_2`
|
||||
|
||||
\sa `CGAL::Delaunay_triangulation_on_sphere_traits_2`
|
||||
*/
|
||||
template <typename LK,
|
||||
typename SK = CGAL::Spherical_kernel_3<
|
||||
LK, CGAL::Algebraic_kernel_for_spheres_2_3<typename LK::FT> > >
|
||||
class Projection_on_sphere_traits_3
|
||||
{
|
||||
public:
|
||||
/// The field number type
|
||||
typedef typename LK::FT FT;
|
||||
|
||||
/// The point on the sphere type
|
||||
typedef unspecified_type Point_on_sphere_2;
|
||||
|
||||
///
|
||||
typedef typename SK::Circular_arc_3 Arc_on_sphere_2;
|
||||
|
||||
///
|
||||
typedef typename LK::Point_3 Point_3;
|
||||
|
||||
///
|
||||
typedef typename LK::Segment_3 Segment_3;
|
||||
|
||||
///
|
||||
typedef typename LK::Triangle_3 Triangle_3;
|
||||
|
||||
/// \name Predicates
|
||||
///
|
||||
/// @{
|
||||
|
||||
/// Points are equal if they have the same projection onto the sphere.
|
||||
typedef unspecified_type Equal_on_sphere_2;
|
||||
|
||||
/// @}
|
||||
|
||||
public:
|
||||
/// \name Precision predicates
|
||||
///
|
||||
/// @{
|
||||
|
||||
/// Due to the chosen point representation, any point is theoretically on the sphere, and this function
|
||||
/// always returns `true`.
|
||||
bool is_on_sphere(const Point_on_sphere_2& p) const;
|
||||
|
||||
/// returns `false` if `LK` can represent algebraic coordinates, or whether the distance
|
||||
/// between `p` and `q` is lower than \f$ 2 \sqrt{R\delta} \f$ otherwise (see the traits class
|
||||
/// `CGAL::Delaunay_triangulation_on_sphere_traits_2`).
|
||||
bool are_points_too_close(const Point_on_sphere_2& p, const Point_on_sphere_2& q) const;
|
||||
|
||||
/// @}
|
||||
};
|
||||
|
||||
} // namespace CGAL
|
||||
|
|
@ -0,0 +1,634 @@
|
|||
namespace CGAL {
|
||||
|
||||
/*!
|
||||
\ingroup PkgTriangulationOnSphere2TriangulationClasses
|
||||
|
||||
The class `Triangulation_on_sphere_2` is the basic class designed to represent a triangulation
|
||||
of a point set on a sphere: its vertices coincide with the points of the set.
|
||||
|
||||
\warning This triangulation supports neither the insertion nor the removal of vertices,
|
||||
see `CGAL::Delaunay_triangulation_on_sphere_2` for such purposes.
|
||||
|
||||
This triangulation class is very similar to `CGAL::Triangulation_2` as both classes represent
|
||||
triangulations of a 2-manifold domain without boundary. A significant difference is that
|
||||
in the case of Euclidean 2D triangulation, it is necessary to introduce so-called <i>infinite
|
||||
faces</i> to complete the convex hull into an actual 2-manifold without boundary that the triangulation
|
||||
data structure can represent. This is not necessary for triangulations on the sphere,
|
||||
which are already perfectly adapted to the triangulation data structure.
|
||||
|
||||
There is an exception to the previous statement: in the degenerate configuration
|
||||
where all points lie on the same hemisphere, the triangulation has a border.
|
||||
Internally, the triangulation data structure must however remain a 2-manifold at all time,
|
||||
and to ensure this property, fictitious faces called <i>ghost faces</i> are added. We call faces that
|
||||
are not ghost faces <em>solid faces</em>, and edges of such faces <em>solid edges</em>.
|
||||
|
||||
\tparam Traits is the geometric traits; it must be a model of the concept `TriangulationOnSphereTraits_2`.
|
||||
|
||||
\tparam TDS is the triangulation data structure; it must be a model of the concept `TriangulationDataStructure_2`,
|
||||
whose vertex base must be a model of `TriangulationOnSphereVertexBase_2` and whose face base
|
||||
must be a model of `TriangulationOnSphereFaceBase_2`. By default, the triangulation data structure
|
||||
is instantiated by `Triangulation_data_structure_2<Triangulation_on_sphere_vertex_base_2<Gt>, Triangulation_on_sphere_face_base_2<Gt> >`.
|
||||
|
||||
\sa `CGAL::Delaunay_triangulation_on_sphere_2<Traits, TDS>`
|
||||
*/
|
||||
template <typename Traits, typename TDS>
|
||||
class Triangulation_on_sphere_2
|
||||
: public Triangulation_cw_ccw_2
|
||||
{
|
||||
public:
|
||||
|
||||
/// \name Types
|
||||
/// @{
|
||||
|
||||
/*!
|
||||
The traits class.
|
||||
*/
|
||||
typedef Traits Geom_traits;
|
||||
|
||||
/*!
|
||||
The triangulation data structure type.
|
||||
*/
|
||||
typedef TDS Triangulation_data_structure;
|
||||
|
||||
/*!
|
||||
Size type (an unsigned integral type).
|
||||
*/
|
||||
typedef Triangulation_data_structure::size_type size_type;
|
||||
|
||||
/*!
|
||||
The number type.
|
||||
*/
|
||||
typedef Traits::FT FT;
|
||||
|
||||
/*!
|
||||
The point type representing a point on the sphere.
|
||||
*/
|
||||
typedef Traits::Point_on_sphere_2 Point;
|
||||
|
||||
/*!
|
||||
The 3D point type.
|
||||
*/
|
||||
typedef Traits::Point_3 Point_3;
|
||||
|
||||
/*!
|
||||
The 3D segment type.
|
||||
*/
|
||||
typedef Traits::Segment_3 Segment_3;
|
||||
|
||||
/*!
|
||||
The 3D triangle type.
|
||||
*/
|
||||
typedef Traits::Triangle_3 Triangle_3;
|
||||
|
||||
/*!
|
||||
An arc of a great circle, used to represent a curved segment (Voronoi or Delaunay edge).
|
||||
*/
|
||||
typedef Traits::Arc_on_sphere_2 Arc_on_sphere_2;
|
||||
|
||||
public:
|
||||
/*!
|
||||
The vertex type.
|
||||
*/
|
||||
typedef TDS::Vertex Vertex;
|
||||
|
||||
/*!
|
||||
The edge type.
|
||||
*/
|
||||
typedef TDS::Edge Edge;
|
||||
|
||||
/*!
|
||||
The face type.
|
||||
*/
|
||||
typedef TDS::Face Face;
|
||||
|
||||
public:
|
||||
/// \name Handles, Iterators, and Circulators
|
||||
///
|
||||
/// The vertices and faces of the triangulation are accessed through
|
||||
/// handles, iterators and circulators. The handles are models
|
||||
/// of the concept `Handle` which basically offers the two dereference
|
||||
/// operators `*` and `->`. The handles are also model of the concepts
|
||||
/// `LessThanComparable` and `Hashable`, that is they can be used as keys
|
||||
/// in containers such as `std::map` and `std::unordered_map`.
|
||||
/// The iterators and circulators are all bidirectional and non-mutable.
|
||||
/// The circulators and iterators are convertible to handles with the same value type,
|
||||
/// so that whenever a handle appear in the parameter list of a function,
|
||||
/// an appropriate iterator or circulator can be passed as well.
|
||||
///
|
||||
/// The edges of the triangulation can also be visited through
|
||||
/// iterators and circulators, the edge circulators and iterators are
|
||||
/// also bidirectional and non mutable.
|
||||
///
|
||||
|
||||
/*!
|
||||
Handle to a vertex.
|
||||
*/
|
||||
typedef TDS::Vertex_handle Vertex_handle;
|
||||
|
||||
/*!
|
||||
Handle to a face.
|
||||
*/
|
||||
typedef TDS::Face_handle Face_handle;
|
||||
|
||||
/*!
|
||||
Iterator over all vertices.
|
||||
*/
|
||||
typedef TDS::Vertex_iterator Vertices_iterator;
|
||||
|
||||
/*!
|
||||
Range type for iterating over all vertices, with a nested
|
||||
type `iterator` that has as value type `Vertex_handle`.
|
||||
*/
|
||||
typedef Iterator_range<unspecified_type> Vertex_handles;
|
||||
|
||||
/*!
|
||||
Iterator over all edges.
|
||||
*/
|
||||
typedef TDS::Edge_iterator All_edges_iterator;
|
||||
|
||||
/*!
|
||||
Range type for iterating over all edges (including non-solid ones).
|
||||
*/
|
||||
typedef Iterator_range<All_edges_iterator> All_edges;
|
||||
|
||||
/*!
|
||||
Iterator over all faces.
|
||||
*/
|
||||
typedef TDS::Face_iterator All_faces_iterator;
|
||||
|
||||
/*!
|
||||
Range type for iterating over all faces (including ghost faces), with a nested
|
||||
type `iterator` that has as value type `Face_handle`.
|
||||
*/
|
||||
typedef Iterator_range<All_faces_iterator> All_face_handles;
|
||||
|
||||
/*!
|
||||
Iterator over all solid edges.
|
||||
*/
|
||||
typedef unspecified_type Solid_edges_iterator;
|
||||
|
||||
/*!
|
||||
Range type for iterating over all solid edges.
|
||||
*/
|
||||
typedef Iterator_range<Solid_edges_iterator> Solid_edges;
|
||||
|
||||
/*!
|
||||
Iterator over all solid faces.
|
||||
*/
|
||||
typedef unspecified_type Solid_faces_iterator;
|
||||
|
||||
/*!
|
||||
Range type for iterating over solid faces, with a nested
|
||||
type `iterator` that has as value type `Face_handle`.
|
||||
*/
|
||||
typedef Iterator_range<unspecified_type> Solid_face_handles;
|
||||
|
||||
/*!
|
||||
Circulator over all vertices incident to a given vertex.
|
||||
*/
|
||||
typedef unspecified_type Vertex_circulator;
|
||||
|
||||
/*!
|
||||
Circulator over all edges incident to a given vertex.
|
||||
*/
|
||||
typedef unspecified_type Edge_circulator;
|
||||
|
||||
/*!
|
||||
Circulator over all faces incident to a given vertex.
|
||||
*/
|
||||
typedef unspecified_type Face_circulator;
|
||||
|
||||
/*!
|
||||
Iterator over the points corresponding the vertices of the triangulation.
|
||||
*/
|
||||
typedef unspecified_type Point_iterator;
|
||||
|
||||
/*!
|
||||
Range type for iterating over the points of the finite vertices.
|
||||
*/
|
||||
typedef Iterator_range<Point_iterator> Points;
|
||||
|
||||
|
||||
/// @}
|
||||
|
||||
public:
|
||||
/// \name Creation
|
||||
/// @{
|
||||
|
||||
/*!
|
||||
constructs an empty triangulation.
|
||||
|
||||
\note The values for the center and radius must be either already set in the traits
|
||||
(if `gt` is passed) or must be set after the construction, using the function `set_center_and_radius()`.
|
||||
*/
|
||||
Triangulation_on_sphere_2(const Traits& gt = Traits());
|
||||
|
||||
/*!
|
||||
constructs an empty triangulation and sets the center and radius to `c` and `r` respectively.
|
||||
*/
|
||||
Triangulation_on_sphere_2(const Point_3& c, const FT r);
|
||||
|
||||
/*!
|
||||
Copy constructor. All the vertices and faces are duplicated.
|
||||
After the copy, `*this` and `tr` refer to different triangulations:
|
||||
if `tr` is modified, `*this` is not.
|
||||
*/
|
||||
Triangulation_on_sphere_2(const Triangulation_on_sphere_2& tr);
|
||||
|
||||
/*!
|
||||
Assignment operator. This performs a deep copy of the triangulation, duplicating both vertices and faces.
|
||||
*/
|
||||
Triangulation_on_sphere_2& operator=(Triangulation_on_sphere_2<Traits,TDS> tr);
|
||||
|
||||
/*!
|
||||
The triangulations `tr` and `*this` are swapped.
|
||||
*/
|
||||
void swap(Triangulation_on_sphere_2& tr);
|
||||
|
||||
/*!
|
||||
deletes all faces and vertices, resulting in an empty triangulation.
|
||||
*/
|
||||
void clear();
|
||||
|
||||
/// @}
|
||||
|
||||
public:
|
||||
/// \name Ghost Predicates
|
||||
/// @{
|
||||
|
||||
/*!
|
||||
returns `true` if `f` is a ghost face, and `false` otherwise.
|
||||
|
||||
\pre `dimension() == 2`
|
||||
*/
|
||||
bool is_ghost(const Face_handle f) const;
|
||||
|
||||
/*!
|
||||
returns `true` if `e` is a ghost edge, that is if both its incident faces are ghost faces,
|
||||
and `false` otherwise.
|
||||
|
||||
\pre `dimension() == 2`
|
||||
*/
|
||||
bool is_ghost(const Edge& e) const;
|
||||
|
||||
/// @}
|
||||
|
||||
public:
|
||||
/// \name Modifying the domain
|
||||
///
|
||||
/// The following functions can be used to modify the geometry of the spherical domain.
|
||||
///
|
||||
/// \warning The triangulation is cleared in the process.
|
||||
///
|
||||
/// @{
|
||||
|
||||
/*! */
|
||||
void set_center(const Point_3& c);
|
||||
|
||||
/*! */
|
||||
void set_radius(const FT radius);
|
||||
|
||||
/*! */
|
||||
void set_center_and_radius(const Point_3& c, const FT radius);
|
||||
|
||||
/// @}
|
||||
|
||||
public:
|
||||
/// \name Access Functions
|
||||
/// @{
|
||||
|
||||
/*!
|
||||
returns:
|
||||
- `-2` if the triangulation is empty
|
||||
- `-1` if the triangulation contains a single vertex
|
||||
- `0` if the triangulation contains exactly two vertices
|
||||
- `1` if the triangulation contains three (or more) coplanar vertices
|
||||
- `2` if the triangulation contains at least four non-coplanar vertices
|
||||
|
||||
Note that a triangulation of dimension `1` is just a polygon drawn on a circle. The polygon is
|
||||
not triangulated itself. Thus the triangulation of dimension one consists of one polygon and
|
||||
has no faces.
|
||||
*/
|
||||
int dimension() const;
|
||||
|
||||
/*!
|
||||
returns a const reference to the triangulation traits object.
|
||||
*/
|
||||
const Geom_traits& geom_traits() const;
|
||||
|
||||
/*!
|
||||
returns a const reference to the triangulation data structure.
|
||||
*/
|
||||
const Triangulation_data_structure& tds() const;
|
||||
|
||||
/*!
|
||||
returns the number of vertices.
|
||||
*/
|
||||
size_type number_of_vertices() const;
|
||||
|
||||
/*!
|
||||
returns the number of faces. Note that this includes ghost faces.
|
||||
*/
|
||||
size_type number_of_faces() const;
|
||||
|
||||
/*!
|
||||
returns the number of ghost faces.
|
||||
*/
|
||||
size_type number_of_ghost_faces() const;
|
||||
|
||||
/*!
|
||||
returns the number of solid faces.
|
||||
*/
|
||||
size_type number_of_solid_faces() const;
|
||||
|
||||
/// @}
|
||||
|
||||
/// \name Geometric Access Functions
|
||||
/// @{
|
||||
|
||||
/*!
|
||||
returns the geometric position of the vertex `v`.
|
||||
*/
|
||||
const Point& point(const Vertex_handle v);
|
||||
|
||||
/*!
|
||||
returns the geometric position of the `i`-th vertex of the face `f`.
|
||||
*/
|
||||
const Point& point(const Face_handle f, const int i);
|
||||
|
||||
/*!
|
||||
returns the 3D line segment formed by the vertices of the edge `e`.
|
||||
\pre `t.dimension()` \f$ \geq1\f$.
|
||||
*/
|
||||
Segment_3 segment(const Edge& e) const;
|
||||
|
||||
/*!
|
||||
returns the 3D line segment formed by the vertices of the edge `(f, i)`.
|
||||
\pre `t.dimension()` \f$ \geq1\f$.
|
||||
*/
|
||||
Segment_3 segment(const Face_handle f, int i) const;
|
||||
|
||||
/*!
|
||||
returns the great circle arc formed by the vertices of the edge `e`.
|
||||
\pre `t.dimension()` \f$ \geq1\f$.
|
||||
*/
|
||||
Arc_on_sphere_2 segment_on_sphere(const Edge& e) const;
|
||||
|
||||
/*!
|
||||
returns the great circle arc formed by the vertices of the edge `(f, i)`.
|
||||
\pre `t.dimension()` \f$ \geq1\f$.
|
||||
*/
|
||||
Arc_on_sphere_2 segment_on_sphere(const Face_handle f, int i) const;
|
||||
|
||||
/*!
|
||||
returns the 3D triangle formed by the three vertices of the face `f`.
|
||||
\pre `t.dimension()` \f$ \geq2\f$.
|
||||
*/
|
||||
Triangle_3 triangle(const Face_handle f) const;
|
||||
|
||||
/// @}
|
||||
|
||||
/// \name All Face, Edge and Vertex Iterators
|
||||
///
|
||||
/// The following iterators allow respectively to visit all faces, edges and
|
||||
/// vertices of the triangulation. These iterators are non mutable,
|
||||
/// bidirectional and their value types are respectively `Face`,
|
||||
/// `Edge` and `Vertex`. They are all invalidated by any change in the triangulation.
|
||||
///
|
||||
/// @{
|
||||
|
||||
/*!
|
||||
Starts at an arbitrary vertex.
|
||||
*/
|
||||
Vertices_iterator vertices_begin() const;
|
||||
|
||||
/*!
|
||||
Past-the-end iterator
|
||||
*/
|
||||
Vertices_iterator vertices_end() const;
|
||||
|
||||
/*!
|
||||
returns a range of iterators over all vertices.
|
||||
\note While the value type of `Vertices_iterator` is `Vertex`, the value type of
|
||||
`Vertex_handles::iterator` is `Vertex_handle`.
|
||||
*/
|
||||
Vertex_handles vertex_handles() const;
|
||||
|
||||
/*!
|
||||
Starts at an arbitrary edge.
|
||||
*/
|
||||
All_edges_iterator all_edges_begin() const;
|
||||
|
||||
/*!
|
||||
Past-the-end iterator
|
||||
*/
|
||||
All_edges_iterator all_edges_end() const;
|
||||
|
||||
/*!
|
||||
returns a range of iterators over all edges.
|
||||
*/
|
||||
All_edges all_edges() const;
|
||||
|
||||
/*!
|
||||
Starts at an arbitrary face.
|
||||
*/
|
||||
All_faces_iterator all_faces_begin() const;
|
||||
|
||||
/*!
|
||||
Past-the-end iterator
|
||||
*/
|
||||
All_faces_iterator all_faces_end() const;
|
||||
|
||||
/*!
|
||||
returns a range of iterators over all faces.
|
||||
\note While the value type of `All_faces_iterator` is `Face`, the value type of
|
||||
`All_face_handles::iterator` is `Face_handle`.
|
||||
*/
|
||||
All_face_handles all_face_handles() const;
|
||||
|
||||
/*!
|
||||
Starts at an arbitrary face.
|
||||
*/
|
||||
Solid_faces_iterator solid_faces_begin() const;
|
||||
|
||||
/*!
|
||||
Past-the-end iterator
|
||||
*/
|
||||
Solid_faces_iterator solid_faces_end() const;
|
||||
|
||||
/*!
|
||||
returns a range of iterators over all solid faces.
|
||||
\note While the value type of `Solid_faces_iterator` is `Face`, the value type of
|
||||
`Solid_face_handles::iterator` is `Face_handle`.
|
||||
*/
|
||||
Solid_face_handles solid_face_handles() const;
|
||||
|
||||
/*!
|
||||
Starts at an arbitrary face.
|
||||
*/
|
||||
Solid_edges_iterator solid_edges_begin() const;
|
||||
|
||||
/*!
|
||||
Past-the-end iterator
|
||||
*/
|
||||
Solid_edges_iterator solid_edges_end() const;
|
||||
|
||||
/*!
|
||||
returns a range of iterators over all solid edges.
|
||||
*/
|
||||
Solid_edges solid_edges() const;
|
||||
|
||||
/*!
|
||||
returns a range of iterators over all the points of the triangulations.
|
||||
*/
|
||||
Points points() const;
|
||||
|
||||
/// @}
|
||||
|
||||
/// \name Face, Edge and Vertex Circulators
|
||||
///
|
||||
/// The triangulation also provides circulators that allows to visit respectively
|
||||
/// all faces or edges incident to a given vertex or all vertices adjacent to a given vertex.
|
||||
/// These circulators are non-mutable and bidirectional. The `operator++` moves the
|
||||
/// circulator counterclockwise around the vertex while the `operator-` moves clockwise.
|
||||
/// A face circulator is invalidated by any modification of the face pointed to.
|
||||
/// An edge or a vertex circulator are invalidated by any modification of one of the two
|
||||
/// faces incident to the edge pointed to.
|
||||
///
|
||||
/// @{
|
||||
|
||||
/*!
|
||||
Starts at an arbitrary vertex adjacent to the vertex `v`.
|
||||
*/
|
||||
Vertex_circulator adjacent_vertices(Vertex_handle v) const;
|
||||
|
||||
/*!
|
||||
Starts at the first vertex of `f` adjacent to `v` in counterclockwise order around `v`.
|
||||
\pre The face `f` is incident to the vertex `v`.
|
||||
*/
|
||||
Vertex_circulator adjacent_vertices(Vertex_handle v, Face_handle f);
|
||||
|
||||
/*!
|
||||
Starts at an arbitrary edge incident to the vertex `v`.
|
||||
*/
|
||||
Edge_circulator incident_edges(Vertex_handle v) const;
|
||||
|
||||
/*!
|
||||
Starts at the first edge of `f` incident to `v`, in counterclockwise order around `v`.
|
||||
\pre The face `f` is incident to the vertex `v`.
|
||||
*/
|
||||
Edge_circulator incident_edges(Vertex_handle v, Face_handle f) const;
|
||||
|
||||
/*!
|
||||
Starts at an arbitrary face incident to the vertex `v`.
|
||||
|
||||
Note that this may contain ghost faces.
|
||||
*/
|
||||
Face_circulator incident_faces(Vertex_handle v) const;
|
||||
|
||||
/*!
|
||||
Starts at face `f`.
|
||||
\pre The face `f` is incident to the vertex `v`.
|
||||
*/
|
||||
Face_circulator incident_faces(Vertex_handle v, Face_handle f) const;
|
||||
|
||||
/// @}
|
||||
|
||||
/// \name Combinatorial Predicates
|
||||
///
|
||||
/// The class `Triangulation_on_sphere_2` provides methods to test the
|
||||
/// presence of a particular feature (edge or face) in the triangulation.
|
||||
///
|
||||
/// @{
|
||||
|
||||
/*!
|
||||
returns `true` if there exists an edge (ghost or solid) having `va` and `vb` as vertices.
|
||||
*/
|
||||
bool is_edge(Vertex_handle va, Vertex_handle vb);
|
||||
|
||||
/*!
|
||||
returns `true` if there exists an edge (ghost or solid) having `va` and `vb` as vertices.
|
||||
If `true` is returned, the edge with vertices `va` and `vb` is the edge `e=(fr,i)`
|
||||
where `fr` is a handle to the face incident to `e` and on the right side of `e` oriented from `va` to `vb`.
|
||||
*/
|
||||
bool is_edge(Vertex_handle va, Vertex_handle vb, Face_handle& fr, int& i);
|
||||
|
||||
/*!
|
||||
returns `true` if there exists a face (ghost or solid) having `v1`, `v2` and `v3` as vertices.
|
||||
*/
|
||||
bool is_face(Vertex_handle v1, Vertex_handle v2, Vertex_handle v3);
|
||||
|
||||
/*!
|
||||
returns `true` if there exists a face (ghost or solid) having `v1`, `v2` and `v3` as vertices.
|
||||
If `true` is returned, `fr` is a handle to the face with `v1`, `v2` and `v3` as vertices.
|
||||
*/
|
||||
bool is_face(Vertex_handle v1, Vertex_handle v2, Vertex_handle v3, Face_handle& fr);
|
||||
|
||||
/// @}
|
||||
|
||||
/// \name Queries
|
||||
///
|
||||
/// The class `Triangulation_on_sphere_2` provides methods to locate a given
|
||||
/// point with respect to a triangulation. It also provides methods to locate
|
||||
/// a point with respect to a given face of the triangulation.
|
||||
///
|
||||
/// @{
|
||||
|
||||
/*!
|
||||
specifies which case occurs when locating a query point in the triangulation.
|
||||
*/
|
||||
enum Locate_type { VERTEX=0, /*!< when the point coincides with a vertex of the triangulation */
|
||||
EDGE, /*!< when the point is in the relative interior of an edge */
|
||||
FACE, /*!< when the point is in the interior of a face */
|
||||
OUTSIDE_CONVEX_HULL, /*!< when the point is on the same 3D plane as the existing vertices, but not on an existing edge */
|
||||
OUTSIDE_AFFINE_HULL, /*!< when the insertion of the point would increase the dimension of the triangulation. */
|
||||
NOT_ON_SPHERE, /*!< when the point is not on the sphere */
|
||||
TOO_CLOSE /*!< when the point is too close to a vertex of the triangulation (see `TriangulationOnSphereTraits_2` for more details) */
|
||||
};
|
||||
|
||||
/*!
|
||||
locates the point `query` in the triangulation, and returns information on this location.
|
||||
|
||||
If the point is (according to the traits) not on the sphere or is too close to an existing vertex,
|
||||
or if the dimension of the triangulation is not 2, or if the point is outside the affine hull,
|
||||
then the returned `Face_handle` is `nullptr`.
|
||||
|
||||
Otherwise, a face intersected by the ray spawned from the center of the sphere
|
||||
and passing through the point is returned.
|
||||
|
||||
The optional `Face_handle` argument, if provided, is used as a hint
|
||||
of where the locate process should start its search.
|
||||
*/
|
||||
Face_handle locate(const Point& query, Face_handle f = Face_handle()) const;
|
||||
|
||||
/*!
|
||||
Same as above. Additionally, the parameters `lt` and `li` describe where the query point is located.
|
||||
The variable `lt` is set to the locate type of the query.
|
||||
If `lt==VERTEX`, the variable `li` is set to the index of the vertex,
|
||||
and if `lt==EDGE` `li` is set to the index of the vertex opposite to the edge.
|
||||
Note that `li` has no meaning when the query type is `FACE`, `OUTSIDE_CONVEX_HULL`,
|
||||
or `OUTSIDE_AFFINE_HULL`.
|
||||
*/
|
||||
Face_handle locate(const Point& query, Locate_type& lt, int& li, Face_handle h = Face_handle()) const;
|
||||
|
||||
/// @}
|
||||
|
||||
/// \name Miscellaneous
|
||||
///
|
||||
/// @{
|
||||
|
||||
/*!
|
||||
tests the validity of the triangulation as a `Triangulation_on_sphere_2`.
|
||||
|
||||
This function tests the validity of the underlying data structure (using the function
|
||||
`TriangulationDataStructure_2::is_valid()`), and the validity of the triangulation itself
|
||||
(consistency between the dimension and the number of simplices, face orientation checks, etc.).
|
||||
|
||||
This method is mainly useful for debugging Delaunay triangulation algorithms.
|
||||
*/
|
||||
bool is_valid(bool verbose = false, int level = 0) const;
|
||||
|
||||
/// @}
|
||||
};
|
||||
|
||||
} // namespace CGAL
|
||||
|
|
@ -0,0 +1,36 @@
|
|||
namespace CGAL {
|
||||
|
||||
/*!
|
||||
\ingroup PkgTriangulationOnSphere2VertexFaceClasses
|
||||
|
||||
\cgalModels `TriangulationOnSphereFaceBase_2`
|
||||
|
||||
The class `Triangulation_on_sphere_face_base_2` is a model for the concept
|
||||
`TriangulationOnSphereFaceBase_2`. It is the default face base class
|
||||
for triangulations on the sphere.
|
||||
|
||||
`Triangulation_on_sphere_face_base_2` can be simply plugged into the triangulation data
|
||||
structure of a triangulation, or used as a base class to derive
|
||||
other base face classes tuned for specific applications.
|
||||
|
||||
\tparam Traits must be a geometric traits class.
|
||||
The geometric traits is actually not used by the class.
|
||||
|
||||
\tparam Fb has to be a model of the concept `TriangulationDSFaceBase_2`
|
||||
and will serve as a base class for `Triangulation_on_sphere_face_base_2`.
|
||||
By default this parameter is instantiated by `Triangulation_ds_face_base_2<>`.
|
||||
|
||||
\sa `CGAL::Triangulation_ds_face_base_2<Tds>`
|
||||
\sa `CGAL::Triangulation_face_base_with_info_2<Traits,Tds>`
|
||||
\sa `CGAL::Triangulation_on_sphere_vertex_base_2<Traits,Vb>`
|
||||
\sa `CGAL::Triangulation_on_sphere_2<Traits,Tds>`
|
||||
*/
|
||||
template< typename Traits, typename Fb >
|
||||
class Triangulation_on_sphere_face_base_2
|
||||
: public Fb
|
||||
{
|
||||
public:
|
||||
|
||||
};
|
||||
|
||||
} // namespace CGAL
|
||||
|
|
@ -0,0 +1,47 @@
|
|||
namespace CGAL {
|
||||
|
||||
/*!
|
||||
\ingroup PkgTriangulationOnSphere2VertexFaceClasses
|
||||
|
||||
\cgalModels `TriangulationOnSphereVertexBase_2`
|
||||
|
||||
The class `Triangulation_on_sphere_vertex_base_2` is the default model
|
||||
for the concept `TriangulationOnSphereVertexBase_2` and
|
||||
the default vertex base class for triangulations on the sphere.
|
||||
|
||||
`Triangulation_on_sphere_vertex_base_2` can be simply plugged into the triangulation data
|
||||
structure of a triangulation, or used as a base class to derive
|
||||
other base vertex classes tuned for specific applications.
|
||||
|
||||
\tparam Traits must be a geometric traits class which provides the type `Point_on_sphere_2`.
|
||||
It is strongly recommended to instantiate this traits class with the model used
|
||||
for the triangulation traits class. This ensures that the point type defined by
|
||||
`Triangulation_on_sphere_vertex_base_2` is the same as the point type defined by
|
||||
the triangulation.
|
||||
|
||||
\tparam Vb must be a model of the concept `TriangulationDSVertexBase_2`.
|
||||
By default this parameter is instantiated by `Triangulation_ds_vertex_base_2<>`.
|
||||
|
||||
\sa `CGAL::Triangulation_ds_vertex_base_2<Tds>`
|
||||
\sa `CGAL::Triangulation_on_sphere_face_base_2<Traits,Fb>`
|
||||
\sa `CGAL::Triangulation_vertex_base_with_info_2<Info,Traits,Vb>`
|
||||
\sa `CGAL::Triangulation_on_sphere_2<Traits,Tds>`
|
||||
*/
|
||||
template< typename Traits, typename Vb >
|
||||
class Triangulation_on_sphere_vertex_base_2
|
||||
: public Vb
|
||||
{
|
||||
public:
|
||||
|
||||
/// \name Types
|
||||
/// @{
|
||||
|
||||
/*!
|
||||
|
||||
*/
|
||||
typedef Traits::Point_on_sphere_2 Point;
|
||||
|
||||
/// @}
|
||||
};
|
||||
|
||||
} // namespace CGAL
|
||||
|
|
@ -0,0 +1,65 @@
|
|||
/*!
|
||||
\ingroup PkgTriangulationOnSphere2Concepts
|
||||
\cgalConcept
|
||||
|
||||
\cgalRefines TriangulationOnSphereTraits_2
|
||||
|
||||
The concept `DelaunayTriangulationOnSphereTraits_2` describes the set of requirements
|
||||
to be fulfilled by any class used to instantiate the first template
|
||||
parameter of the class `CGAL::Delaunay_triangulation_on_sphere_2<Traits, Tds>`.
|
||||
|
||||
To the requirements listed within the concept `TriangulationOnSphereTraits_2`,
|
||||
this concept adds types and functors requirements related to build the dual on the sphere.
|
||||
|
||||
\cgalHasModel `CGAL::Delaunay_triangulation_on_sphere_traits_2`
|
||||
\cgalHasModel `CGAL::Projection_on_sphere_traits_3`
|
||||
*/
|
||||
class DelaunayTriangulationOnSphereTraits_2
|
||||
{
|
||||
public:
|
||||
/// \name Constructions
|
||||
///
|
||||
/// @{
|
||||
|
||||
/// Construction object type. Must provide the operator:
|
||||
///
|
||||
/// `Point_on_sphere_2 operator()(Point_on_sphere_2 p, Point_on_sphere_2 q, Point_on_sphere_2 r)`
|
||||
///
|
||||
/// which returns the intersection of the dual of the face defined by the three points `p`, `q`, and `r`,
|
||||
/// and the sphere, on the positive side of the plane defined by `p`, `q`, and `r`. The dual of the face
|
||||
/// is the line orthogonal to the face, passing through the center of the smallest circumscribing sphere
|
||||
/// of the face.
|
||||
///
|
||||
/// \pre the center of the sphere is on the negative side of the plane defined by `p`, `q`, and `r`.
|
||||
///
|
||||
/// \note This type is only required for the computation of dual objects (Voronoi vertices and edges)
|
||||
/// and a dummy type can be used otherwise.
|
||||
typedef unspecified_type Construct_circumcenter_on_sphere_2;
|
||||
|
||||
/// Construction object type. Must provide the operator:
|
||||
///
|
||||
/// `Point_3 operator()(Point_3 p, Point_3 q, Point_3 r)`
|
||||
///
|
||||
/// which returns the center of the circle circumscribed to the face with vertices `p`, `q`, and `r`.
|
||||
///
|
||||
/// \note This type is only required for the computation of dual objects (Voronoi vertices and edges)
|
||||
/// and a dummy type can be used otherwise.
|
||||
typedef unspecified_type Construct_circumcenter_3;
|
||||
|
||||
/// @}
|
||||
|
||||
public:
|
||||
/// \name Operations
|
||||
///
|
||||
/// The following functions give access to the predicate and constructor objects.
|
||||
///
|
||||
/// @{
|
||||
|
||||
///
|
||||
Construct_circumcenter_on_sphere_2 construct_circumcenter_on_sphere_2_object();
|
||||
|
||||
///
|
||||
Construct_circumcenter_3 construct_circumcenter_3_object();
|
||||
|
||||
/// @}
|
||||
};
|
||||
|
|
@ -0,0 +1,35 @@
|
|||
/*!
|
||||
\ingroup PkgTriangulationOnSphere2Concepts
|
||||
\cgalConcept
|
||||
|
||||
\cgalRefines `TriangulationDSFaceBase_2`
|
||||
|
||||
The concept `TriangulationOnSphereFaceBase_2` describes the requirements for a face class
|
||||
of a triangulation data structure that is itself plugged into a triangulation on the sphere.
|
||||
|
||||
The data structure concept `TriangulationDataStructure_2` was primarily designed
|
||||
to serve as a data structure for the 2D triangulation classes of \cgal, which are triangulations
|
||||
embedded in the 2D Euclidean plane.
|
||||
However, its genericity makes it usable for any orientable triangulated surface without boundary
|
||||
regardless of the dimensionality of the space the triangulation is embedded in, and thus
|
||||
it is a valid data structure for the triangulations on the sphere of this package.
|
||||
|
||||
A departing feature is that if the vertices of the triangulation are all lying on one hemisphere,
|
||||
then the triangulation is not an orientable triangulated surface without boundary.
|
||||
In this case, fictitious faces are added to the triangulation, called <i>ghost faces</i>,
|
||||
such that the triangulation is a topological sphere.
|
||||
|
||||
\cgalHasModel `CGAL::Triangulation_on_sphere_face_base_2<Traits, Fb>`
|
||||
|
||||
\sa `TriangulationDataStructure_2`
|
||||
\sa `TriangulationOnSphereVertexBase_2`
|
||||
*/
|
||||
class TriangulationOnSphereFaceBase_2
|
||||
{
|
||||
public:
|
||||
/// provides read access to a Boolean used to indicate if the face is a ghost face.
|
||||
bool is_ghost();
|
||||
|
||||
/// provides write access to a Boolean used to indicate if the face is a ghost face.
|
||||
void set_ghost(const bool b);
|
||||
};
|
||||
|
|
@ -0,0 +1,267 @@
|
|||
/*!
|
||||
\ingroup PkgTriangulationOnSphere2Concepts
|
||||
\cgalConcept
|
||||
|
||||
\cgalRefines SpatialSortingTraits_3
|
||||
|
||||
The concept `TriangulationOnSphereTraits_2` describes the set of requirements
|
||||
to be fulfilled by any class used to instantiate the first template
|
||||
parameter of the class `CGAL::Triangulation_on_sphere_2<Traits, Tds>`.
|
||||
This concept provides the types of the geometric primitives used in the
|
||||
triangulation and the function object types for the required predicates on those primitives.
|
||||
|
||||
In particular, the traits class is expected to contain information about the sphere (center and radius)
|
||||
on which the points of the triangulation lie, as well as to provide means to change this information.
|
||||
|
||||
\cgalHasModel `CGAL::Delaunay_triangulation_on_sphere_traits_2`
|
||||
\cgalHasModel `CGAL::Projection_on_sphere_traits_3`
|
||||
|
||||
\sa `DelaunayTriangulationOnSphereTraits_2`
|
||||
*/
|
||||
class TriangulationOnSphereTraits_2
|
||||
{
|
||||
public:
|
||||
/// \name Types
|
||||
/// @{
|
||||
|
||||
/*!
|
||||
The number type; must be a model of `FieldNumberType`.
|
||||
*/
|
||||
typedef unspecified_type FT;
|
||||
|
||||
/*!
|
||||
The point type of the triangulation, representing a point on the sphere.
|
||||
*/
|
||||
typedef unspecified_type Point_on_sphere_2;
|
||||
|
||||
/*!
|
||||
An arc of a great circle, used to represent a curved segment (a Voronoi or a Delaunay edge).
|
||||
*/
|
||||
typedef unspecified_type Arc_on_sphere_2;
|
||||
|
||||
/*!
|
||||
The 3D point type.
|
||||
*/
|
||||
typedef unspecified_type Point_3;
|
||||
|
||||
/*!
|
||||
The 3D segment type.
|
||||
*/
|
||||
typedef unspecified_type Segment_3;
|
||||
|
||||
/*!
|
||||
The 3D triangle type.
|
||||
*/
|
||||
typedef unspecified_type Triangle_3;
|
||||
|
||||
/// @}
|
||||
|
||||
public:
|
||||
/// \name Predicates
|
||||
/// @{
|
||||
|
||||
/// Predicate object type. Must provide the operator:
|
||||
///
|
||||
/// `bool operator()(Point_on_sphere_2 p, Point_on_sphere_2 q, Point_on_sphere_2 r)`
|
||||
///
|
||||
/// which returns `true` if `r` strictly lies on the shortest path between `p` and `q`
|
||||
/// on the great circle passing through `p` and `q`.
|
||||
///
|
||||
/// If `p` and `q` are diametrically opposed, `true` is returned.
|
||||
typedef unspecified_type Collinear_are_strictly_ordered_on_great_circle_2;
|
||||
|
||||
/// Predicate object type. Must provide the operator:
|
||||
///
|
||||
/// `bool operator()(Point_on_sphere_2 p, Point_on_sphere_2 q)`
|
||||
///
|
||||
/// which returns `true` or `false` based on a consistent, user-defined strict total order of points.
|
||||
typedef unspecified_type Compare_on_sphere_2;
|
||||
|
||||
/// Predicate object type. Must provide the operator:
|
||||
///
|
||||
/// `bool operator()(Point_on_sphere_2 p, Point_on_sphere_2 q)`
|
||||
///
|
||||
/// which returns `true` if, and only if, `p` and `q` are equal.
|
||||
typedef unspecified_type Equal_on_sphere_2;
|
||||
|
||||
/// Predicate object type. Must provide the operator:
|
||||
///
|
||||
/// `Orientation operator()(Point_on_sphere_2 p, Point_on_sphere_2 q, Point_on_sphere_2 r)`
|
||||
///
|
||||
/// which returns `CGAL::POSITIVE`, if `r` lies on the left hemisphere while walking
|
||||
/// the shortest path between `p` and `q` on the great circle defined by `p` and `q`;
|
||||
/// returns `CGAL::NEGATIVE` if `r` lies on the right hemisphere; and returns `CGAL::COPLANAR`
|
||||
/// if `r` lies on the great circle.
|
||||
///
|
||||
/// If `p` and `q` are diametrically opposed, `CGAL::COPLANAR` is returned.
|
||||
typedef unspecified_type Orientation_on_sphere_2;
|
||||
|
||||
/// Predicate object type. Must provide the operator:
|
||||
///
|
||||
/// `bool operator()(Point_on_sphere_2 p, Point_on_sphere_2 q, Point_on_sphere_2 r, Point_on_sphere_2 s)`
|
||||
///
|
||||
/// which returns `CGAL::POSITIVE`, if `s` lies on the positive side of the oriented plane `h`
|
||||
/// defined by `p`, `q`, and `r`; returns `CGAL::NEGATIVE` if `s` lies on the negative side of `h`;
|
||||
/// and returns `CGAL::COPLANAR` if `s` lies on `h`.
|
||||
typedef unspecified_type Side_of_oriented_circle_on_sphere_2;
|
||||
|
||||
/// @}
|
||||
|
||||
/// \name Constructions
|
||||
///
|
||||
/// @{
|
||||
|
||||
/// Construction object. Must provide the operator:
|
||||
///
|
||||
/// `Arc_on_sphere_2 operator()(Point_on_sphere_2 p, Point_on_sphere_2 q)`
|
||||
///
|
||||
/// which introduces an arc of great circle, with source `p` and target `q`.
|
||||
///
|
||||
/// The circular arc constructed from a source, and a target, is defined as the set of points
|
||||
/// of the great circle that lie between the source `p` and the target `q`,
|
||||
/// when traversing the great circle counterclockwise seen from the side of the plane
|
||||
/// of the great circle pointed by its <I>positive</I> normal vectors.
|
||||
///
|
||||
/// In this definition, we say that a normal vector \f$ (a,b,c)\f$ is <I>positive</I> if
|
||||
/// \f$ (a,b,c)>(0,0,0)\f$ (i.e.\ \f$ (a>0) || (a==0) \&\& (b>0) || (a==0)\&\&(b==0)\&\&(c>0)\f$).
|
||||
///
|
||||
/// \pre `p` and `q` are not diametrically opposed.
|
||||
typedef unspecified_type Construct_arc_on_sphere_2;
|
||||
|
||||
/// Construction object. Must provide the operator:
|
||||
///
|
||||
/// `Point_on_sphere_2 operator()(Point_3 p)`,
|
||||
///
|
||||
/// which expresses the point `p`, a 3D point living on the sphere,
|
||||
/// using the (user-defined) point-on-sphere representation.
|
||||
typedef unspecified_type Construct_point_on_sphere_2;
|
||||
|
||||
/// Construction object. Must provide the operator:
|
||||
///
|
||||
/// `Point_3 operator()(Point_on_sphere_2 p)`,
|
||||
///
|
||||
/// which expresses the point `p` on the sphere as a point in the embedding 3D space.
|
||||
typedef unspecified_type Construct_point_3;
|
||||
|
||||
/// Construction object. Must provide the operator:
|
||||
///
|
||||
/// `Segment_3 operator()(Point_3 p, Point_3 q)`,
|
||||
///
|
||||
/// which constructs a segment from two 3D points.
|
||||
typedef unspecified_type Construct_segment_3;
|
||||
|
||||
/// Construction object. Must provide the operator:
|
||||
///
|
||||
/// `Triangle_3 operator()(Point_3 p, Point_3 q, Point_3 r)`,
|
||||
///
|
||||
/// which constructs a triangle from three 3D points.
|
||||
typedef unspecified_type Construct_triangle_3;
|
||||
|
||||
/// @}
|
||||
|
||||
public:
|
||||
/// \name Operations
|
||||
///
|
||||
/// The following functions provide access to the predicate and constructor objects.
|
||||
///
|
||||
/// @{
|
||||
|
||||
// Predicates
|
||||
|
||||
///
|
||||
Compare_on_sphere_2 compare_on_sphere_2_object();
|
||||
|
||||
///
|
||||
Equal_on_sphere_2 equal_on_sphere_2_object();
|
||||
|
||||
///
|
||||
Orientation_on_sphere_2 orientation_on_sphere_2_object();
|
||||
|
||||
///
|
||||
Side_of_oriented_circle_on_sphere_2 side_of_oriented_circle_on_sphere_2_object();
|
||||
|
||||
///
|
||||
Collinear_are_strictly_ordered_on_great_circle_2 collinear_are_strictly_ordered_on_great_circle_2_object();
|
||||
|
||||
// Constructions
|
||||
|
||||
///
|
||||
Construct_arc_on_sphere_2 construct_arc_on_sphere_2_object();
|
||||
|
||||
///
|
||||
Construct_point_on_sphere_2 construct_point_on_sphere_2_object();
|
||||
|
||||
///
|
||||
Construct_point_3 construct_point_3_object();
|
||||
|
||||
///
|
||||
Construct_segment_3 construct_segment_3_object();
|
||||
|
||||
///
|
||||
Construct_triangle_3 construct_triangle_3_object();
|
||||
|
||||
/// @}
|
||||
|
||||
public:
|
||||
/// \name Configuration of the spherical domain
|
||||
///
|
||||
/// @{
|
||||
|
||||
/// sets the center of the sphere.
|
||||
///
|
||||
/// \note This function is meant to be used only by the triangulation class as modifying the domain
|
||||
/// requires clearing the triangulation. Users can change the domain using
|
||||
/// `CGAL::Triangulation_on_sphere_2::set_center_and_radius()`.
|
||||
void set_center(Point_3 center);
|
||||
|
||||
/// returns the center of the sphere.
|
||||
Point_3 center() const;
|
||||
|
||||
/// sets the radius of the sphere.
|
||||
///
|
||||
/// \note This function is meant to be used only by the triangulation class as modifying the domain
|
||||
/// requires clearing the triangulation. Users can change the domain using
|
||||
/// `CGAL::Triangulation_on_sphere_2::set_center_and_radius()`.
|
||||
void set_radius(FT radius);
|
||||
|
||||
/// returns the radius of the sphere.
|
||||
FT radius() const;
|
||||
|
||||
/// @}
|
||||
|
||||
public:
|
||||
/// \name Precision predicates
|
||||
///
|
||||
/// When a kernel does not offer arbitrary precision - or at least an exact representation of
|
||||
/// algebraic coordinates, which is usually the case for the sake of computational speed,
|
||||
/// then most points that are theoretically on the sphere are not in practice exactly on the sphere.
|
||||
/// When this is the case, it cannot be guaranteed that all points are in a convex position,
|
||||
/// which can then result in points being hidden upon insertion, see \cgalCite{cgal:ccplr-redtp-10}.
|
||||
/// To ensure that no point is hidden, a trick is to enforce a gap between points (\cgalCite{cgal:ccplr-redtp-10},
|
||||
/// Lemma 4.1). This gap is based on a fixed maximal allowed distance \f$ \delta \f$ between a point
|
||||
/// and the theoretical sphere. The gap must then be at least \f$ 2 \sqrt{R\delta} \f$, where \f$ R \f$
|
||||
/// is the radius of the sphere.
|
||||
///
|
||||
/// The following two predicates serve to check if the point is on the sphere, that is
|
||||
/// if for a model-defined \f$ \delta \f$ the distance to the sphere is smaller
|
||||
/// than \f$ \delta \f$ and if the distance between two points is greater than \f$ 2 \sqrt{R\delta} \f$.
|
||||
/// It is also of course possible to construct traits classes with arbitrary precision or
|
||||
/// with a representation that ensures that points are exactly on the sphere and in this case,
|
||||
/// \f$ \delta = 0 \f$ can be chosen and the predicates below are trivial.
|
||||
///
|
||||
/// \sa `CGAL::Delaunay_triangulation_on_sphere_traits_2`
|
||||
///
|
||||
/// @{
|
||||
|
||||
/// returns whether the point `p` is on the sphere or not.
|
||||
///
|
||||
/// \note A point that is not on the sphere will not be inserted in the triangulation.
|
||||
bool is_on_sphere(Point_on_sphere_2 p);
|
||||
|
||||
/// returns whether the points `p` and `q` are too close (see
|
||||
/// <a href="https://doc.cgal.org/latest/Triangulation_on_sphere_2/classTriangulationOnSphereTraits__2.html#amgrpbc40b59d2ea2be0fc60516e5f7bb0f92">
|
||||
/// Precision predicates</a>).
|
||||
bool are_points_too_close(Point_on_sphere_2 p, Point_on_sphere_2 q);
|
||||
|
||||
/// @}
|
||||
};
|
||||
|
|
@ -0,0 +1,83 @@
|
|||
/*!
|
||||
\ingroup PkgTriangulationOnSphere2Concepts
|
||||
\cgalConcept
|
||||
|
||||
\cgalRefines `TriangulationDSVertexBase_2`
|
||||
|
||||
The concept `TriangulationOnSphereVertexBase_2` describes the requirements for the vertex base class
|
||||
of a triangulation data structure to be plugged in a triangulation on the sphere.
|
||||
It refines the concept `TriangulationDSVertexBase_2`, adding geometric information:
|
||||
the vertex base of a triangulation stores a point.
|
||||
|
||||
\cgalHasModel `CGAL::Triangulation_on_sphere_vertex_base_2<Traits,Vb>`
|
||||
|
||||
\sa `TriangulationDataStructure_2`
|
||||
\sa `TriangulationOnSphereFaceBase_2`
|
||||
*/
|
||||
class TriangulationOnSphereVertexBase_2
|
||||
{
|
||||
public:
|
||||
/// \name Types
|
||||
/// @{
|
||||
|
||||
/*!
|
||||
Must be the equivalent to the point type `Point_on_sphere_2` of the concept `TriangulationOnSphereTraits_2`.
|
||||
*/
|
||||
typedef unspecified_type Point;
|
||||
|
||||
/*!
|
||||
Must be the equivalent to the point type `Face_handle` of the triangulation.
|
||||
*/
|
||||
typedef unspecified_type Face_handle;
|
||||
|
||||
/// @}
|
||||
|
||||
/// \name Creation
|
||||
/// @{
|
||||
|
||||
/*!
|
||||
constructs a vertex whose geometric embedding is the point `p`.
|
||||
*/
|
||||
TriangulationOnSphereVertexBase_2(Point p);
|
||||
|
||||
/*!
|
||||
constructs a vertex whose geometric embedding is the point `p` and pointing to face `f`.
|
||||
`Face_handle` is the type defined the triangulation data structure used in the Delaunay triangulation
|
||||
on the sphere.
|
||||
*/
|
||||
TriangulationOnSphereVertexBase_2(Point p, Face_handle f);
|
||||
|
||||
/// @}
|
||||
|
||||
/// \name Access Functions
|
||||
/// @{
|
||||
|
||||
/*!
|
||||
returns the point.
|
||||
*/
|
||||
Point point() const;
|
||||
|
||||
/// @}
|
||||
|
||||
/// \name Setting
|
||||
/// @{
|
||||
|
||||
/*!
|
||||
sets the point.
|
||||
*/
|
||||
void set_point(Point p);
|
||||
|
||||
/*!
|
||||
inputs the non-combinatorial information given by the vertex:
|
||||
the point and other possible information.
|
||||
*/
|
||||
std::istream& operator>>(std::istream& is, TriangulationOnSphereVertexBase_2& v);
|
||||
|
||||
/*!
|
||||
outputs the non combinatorial operation given by the vertex: the
|
||||
point and other possible information.
|
||||
*/
|
||||
std::ostream& operator<<(std::ostream& os, const TriangulationOnSphereVertexBase_2& v);
|
||||
|
||||
/// @}
|
||||
};
|
||||
|
|
@ -0,0 +1,7 @@
|
|||
@INCLUDE = ${CGAL_DOC_PACKAGE_DEFAULTS}
|
||||
|
||||
PROJECT_NAME = "CGAL ${CGAL_DOC_VERSION} - 2D Triangulations on the Sphere"
|
||||
|
||||
HTML_EXTRA_FILES = ${CGAL_PACKAGE_DOC_DIR}/fig/geometric_embedding.png \
|
||||
${CGAL_PACKAGE_DOC_DIR}/fig/ghost_faces.png \
|
||||
${CGAL_PACKAGE_DOC_DIR}/fig/header.png
|
||||
|
|
@ -0,0 +1,81 @@
|
|||
/// \defgroup PkgTriangulationOnSphere2Ref 2D Triangulation on Sphere Reference
|
||||
|
||||
/// \defgroup PkgTriangulationOnSphere2Concepts Concepts
|
||||
/// \ingroup PkgTriangulationOnSphere2Ref
|
||||
|
||||
/// \defgroup PkgTriangulationOnSphere2TriangulationClasses Triangulation Classes
|
||||
/// \ingroup PkgTriangulationOnSphere2Ref
|
||||
|
||||
/// \defgroup PkgTriangulationOnSphere2VertexFaceClasses Vertex and Face Classes
|
||||
/// \ingroup PkgTriangulationOnSphere2Ref
|
||||
|
||||
/*!
|
||||
\addtogroup PkgTriangulationOnSphere2Ref
|
||||
|
||||
\cgalPkgDescriptionBegin{2D Triangulations on Sphere,PkgTriangulationOnSphere2}
|
||||
\cgalPkgPicture{triangulation_on_sphere.png}
|
||||
\cgalPkgSummaryBegin
|
||||
\cgalPkgAuthors{Mael Rouxel-Labbé, Monique Teillaud, and Claudia Werner}
|
||||
\cgalPkgDesc{This package enables the construction and manipulation of Delaunay triangulations on the 2-sphere.
|
||||
Triangulations are built incrementally and can be modified by insertion or removal of vertices.
|
||||
Point location querying and primitives to build the dual Voronoi diagram are provided.}
|
||||
\cgalPkgManuals{Chapter_2D_Triangulations_on_sphere,PkgTriangulationOnSphere2Ref}
|
||||
\cgalPkgSummaryEnd
|
||||
\cgalPkgShortInfoBegin
|
||||
\cgalPkgSince{5.3}
|
||||
\cgalPkgDependsOn{\ref PkgTDS2}
|
||||
\cgalPkgBib{cgal:rtw-tos2}
|
||||
\cgalPkgLicense{\ref licensesGPL "GPL"}
|
||||
\cgalPkgDemo{Delaunay Triangulation, delaunay_Triangulation_on_sphere_2.zip}
|
||||
\cgalPkgShortInfoEnd
|
||||
\cgalPkgDescriptionEnd
|
||||
|
||||
A triangulation is a 2-dimensional simplicial complex that is pure,
|
||||
connected, and without singularities. It can be viewed as a collection of triangular faces,
|
||||
such that two faces either have an empty intersection or share an edge or a vertex.
|
||||
|
||||
This package handles triangulations of points on the 2-sphere, and is thus tightly linked
|
||||
to the package \ref PkgTriangulation2, which handles triangulations of points in Euclidean 2D space,
|
||||
since both domains are 2-manifolds. Concepts and classes are therefore similar
|
||||
to those of the package \ref PkgTriangulation2.
|
||||
|
||||
The basic elements of the representation are vertices and faces.
|
||||
Each triangular face gives access to its three incident vertices
|
||||
and to its three adjacent faces.
|
||||
Each vertex gives access to one of its incident faces
|
||||
and, through that face, to the circular list of its incident faces.
|
||||
The edges are not explicitly represented, they are only represented
|
||||
through the adjacency relations of two faces.
|
||||
|
||||
The triangulation classes of \cgal depend on two template parameters.
|
||||
The first template parameter stands for a geometric traits class which is assumed to provide
|
||||
the geometric objects (points, segments, ...) forming the triangulation
|
||||
and the geometric predicates on those objects.
|
||||
The second template parameter stands for a model of triangulation data structure
|
||||
acting as a container for faces and vertices while taking care
|
||||
of the combinatorial aspects of the triangulation.
|
||||
The concepts and models relative to the triangulation data structure
|
||||
are described in Chapter \ref PkgTDS2Ref "2D Triangulation Data Structure".
|
||||
|
||||
\cgalClassifedRefPages
|
||||
|
||||
\cgalCRPSection{Concepts}
|
||||
- `TriangulationOnSphereTraits_2`
|
||||
- `DelaunayTriangulationOnSphereTraits_2`
|
||||
- `TriangulationOnSphereFaceBase_2`
|
||||
- `TriangulationOnSphereVertexBase_2`
|
||||
|
||||
\cgalCRPSection{Traits Classes}
|
||||
- `CGAL::Delaunay_triangulation_on_sphere_traits_2<LK, SK>`
|
||||
- `CGAL::Projection_on_sphere_traits_3<LK, SK>`
|
||||
|
||||
\cgalCRPSection{Triangulation Classes}
|
||||
- `CGAL::Triangulation_on_sphere_face_base_2<Traits, Fb>`
|
||||
- `CGAL::Triangulation_on_sphere_vertex_base_2<Traits, Vb>`
|
||||
- `CGAL::Triangulation_on_sphere_2<Traits, TDS>`
|
||||
- `CGAL::Delaunay_triangulation_on_sphere_2<Traits, TDS>`
|
||||
|
||||
\cgalCRPSection{Enum}
|
||||
- \link CGAL::Triangulation_on_sphere_2::Locate_type `CGAL::Triangulation_on_sphere_2<Traits,TDS>::Locate_type` \endlink
|
||||
|
||||
*/
|
||||
|
|
@ -0,0 +1,241 @@
|
|||
namespace CGAL {
|
||||
/*!
|
||||
|
||||
\mainpage User Manual
|
||||
\anchor Chapter_2D_Triangulations_on_sphere
|
||||
|
||||
\cgalAutoToc
|
||||
\author Mael Rouxel-Labbé, Monique Teillaud, and Claudia Werner
|
||||
|
||||
\cgalFigureAnchor{fig_TOS2_header}
|
||||
<center>
|
||||
<img src="header.png" style="max-width:70%;"/>
|
||||
</center>
|
||||
|
||||
This chapter describes two-dimensional triangulations on the sphere of \cgal. It is organized as follows:
|
||||
<ul>
|
||||
<li>Section \ref Section_2D_ToS_Definitions introduces the main definitions about triangulations on the sphere.</li>
|
||||
<li>Section \ref Section_2D_ToS_Implementation details the way two-dimensional triangulations on the sphere
|
||||
are implemented and represented in \cgal.</li>
|
||||
<li>Section \ref Section_2D_ToS_Examples lists a few basic examples to illustrate the capabilities
|
||||
of the package.</li>
|
||||
</ul>
|
||||
|
||||
\section Section_2D_ToS_Definitions Definitions
|
||||
|
||||
Denote by \f$ \mathbb{S(c, r)}\f$ the two-dimensional sphere embedded in the Euclidean space \f$ \mathbb{R}^3\f$,
|
||||
with center `c` and radius `r`, that is
|
||||
\f$ \mathbb{S(c, r)} = \left\{ x \in \mathbf{R}^3 : \left\| x - c \right\| = r \right\} \f$.
|
||||
When the parameters `c` and `r` are not important, they will be omitted and \f$ \mathbb{S}\f$
|
||||
will be used directly.
|
||||
Given a set \f$ \mathcal{P}\f$ of points on \f$ \mathbb{S(c, r)}\f$, a <em>two-dimension triangulation</em>
|
||||
of \f$ \mathcal{P}\f$ can be described as a two-dimensional simplicial complex that is pure,
|
||||
connected, and without singularity whose vertices are exactly the points in \f$ \mathcal{P}\f$
|
||||
(see the complete definition in the package
|
||||
\link Section_2D_Triangulations_Definitions 2D Triangulations\endlink).
|
||||
|
||||
In \f$ \mathbb{R}^2\f$, a <em>Delaunay</em> triangulation is a two-dimension triangulation
|
||||
that satisfies the <em>empty circle property</em> (also called <em>Delaunay property</em>):
|
||||
the circumscribing circle of any facet of the triangulation contains no point in its interior.
|
||||
This definition naturally extends to the two-dimensional sphere, as illustrated in the figure below.
|
||||
|
||||
\cgalFigureBegin{fig_del_def, delaunay_on_sphere_def.svg}
|
||||
Delaunay property: the circumscribing circle (in green) on the sphere
|
||||
of the Delaunay face \f$ p_1 p_2 p_3\f$ is empty.
|
||||
\cgalFigureEnd
|
||||
|
||||
A particularity of Delaunay triangulations on \f$ \mathbb{S}\f$ is that the Delaunay property
|
||||
test can be reduced to a simple orientation test in the three-dimensional space: indeed, the circumscribing
|
||||
circle of a Delaunay face is the intersection of the plane passing through the three vertices
|
||||
of the face with \f$ \mathbb{S}\f$, and determining whether a fourth point `q` is within the
|
||||
circumscribing circle or not is equivalent to checking whether `q` is above or below the said supporting plane.
|
||||
|
||||
\subsection Section_2D_ToS_Imprecision Representation of a Point on the Sphere
|
||||
|
||||
The theoretical definition of Delaunay triangulations in the previous section assumes that points
|
||||
in \f$ \mathcal{P}\f$ lie exactly on the sphere. In a real world however, one usually does not
|
||||
manipulate points that lie exactly on \f$ \mathbb{S}\f$ because the chosen number type
|
||||
is not able to represent square roots exactly, such as \f$ \mathtt{float}\f$, or \f$ \mathtt{double}\f$.
|
||||
Some specific number types are able to represent exactly all points on the sphere, for example
|
||||
the class `CORE::Expr`, but this comes with the drawback of a substantially higher computational cost.
|
||||
|
||||
This lack of exact representation is an obvious problem as the interpretation of the Delaunay property
|
||||
as an orientation test does not stand if points do not lie in a convex position.
|
||||
|
||||
This gap between the theoretical and the practical settings was addressed by Caroli et al. \cgalCite{cgal:ccplr-redtp-10} :
|
||||
the solution is to use a <em>regular</em> triangulation, which is a generalization of the Delaunay triangulation
|
||||
to sets of <em>weighted points</em>
|
||||
(see \link Section_2D_Triangulations_Regular 2D Regular Triangulations\endlink for more information).
|
||||
A weighted point \f$(p,w)\f$ of \f$ \mathbb{R}^2\f$ can naturally be seen as as a circle with center \f$ p\f$
|
||||
and radius \f$ r\f$ such that \f$ r^2 = w\f$ and similarly to Delaunay triangulations and the definition
|
||||
of regular triangulations in \f$ \mathbb{R}^2\f$ can be naturally extended to circles on \f$ \mathbb{S}\f$.
|
||||
Given a set of points \f$ \mathcal{P}_3\f$ living in \f$ \mathbb{R}^3\f$, Caroli et al. compute
|
||||
a regular triangulation of the set of weighted points \f$ \mathcal{P}_w\f$ where the weighted
|
||||
points of \f$ \mathcal{P}_w\f$ are the projection of the points of \f$ \mathcal{P}_3\f$ onto \f$ \mathbb{S}\f$,
|
||||
and whose weights are based on the projection distance. Furthermore, they show that if the Euclidean distance
|
||||
between the points of \f$ \mathcal{P}_w\f$ is sufficiently large, and if the points are sufficiently
|
||||
close to the sphere, then the Delaunay triangulation of the Delaunay triangulation of \f$ \mathcal{P}_3\f$
|
||||
is exactly the regular triangulation of \f$ \mathcal{P}_w\f$.
|
||||
As a consequence is that one can manipulate 3D points that are not exactly on the sphere,
|
||||
and it possible to build the Delaunay triangulation without taking the weights into account, as long as the
|
||||
points are sufficiently far from each other.
|
||||
|
||||
Caroli et al. et provide bounds on this separation criterion for the case of the \f$ \mathtt{double}\f$
|
||||
number type: two points must be at least \f$ 2^{-25}r\f$ apart. This is a condition that
|
||||
is generally satisfied for most inputs: if \f$ r\f$ were for example the radius of the Earth,
|
||||
roughly 6300 kms, then the point separation requirement would be of the order of 1 meter.
|
||||
|
||||
\section Section_2D_ToS_Implementation Implementation
|
||||
|
||||
The main class of this package is the class `CGAL::Delaunay_triangulation_on_sphere_2`;
|
||||
it represents a Delaunay triangulation on the sphere, and provides insertion and removal of vertices,
|
||||
as well as tools to draw the triangulation and its dual, the Voronoi diagram.
|
||||
The base of `CGAL::Delaunay_triangulation_on_sphere_2` is the class `CGAL::Triangulation_on_sphere_2`.
|
||||
It represents a triangulation on the sphere, but does <em>not</em> support insertion or removal
|
||||
of vertices. Both classes are built on top of a data structure called the triangulation data structure.
|
||||
The triangulation data structure can be thought of as a container for the faces and vertices
|
||||
of the triangulation. This data structure also takes care of all the combinatorial aspects of the triangulation.
|
||||
|
||||
These triangulation classes are intentionally very similar to `CGAL::Delaunay_triangulation_2` and
|
||||
`CGAL::Triangulation_2` as both classes represent triangulations of a 2-manifold domain without boundary.
|
||||
As such, many details about the implementation are not repeated here, and complementary information
|
||||
can be found in the Sections \ref Section_2D_Triangulations_Representation,
|
||||
\ref Section_2D_Triangulations_Software_Design, and \ref Section_2D_Triangulations_Basic
|
||||
of the package \ref PkgTriangulation2.
|
||||
|
||||
However, a significant departure from Euclidean 2D triangulations is the following: since
|
||||
the triangulation data structure represents a 2-manifold without boundary, it is necessary
|
||||
for 2D triangulations to introduce so-called <i>infinite faces</i> to complete the "real"
|
||||
triangulation (see \ref Triangulation_2TheSetofFaces).
|
||||
On the sphere, this trick is not necessary as the triangulation itself is already a 2-manifold
|
||||
without boundary.
|
||||
|
||||
\subsection Section_2D_ToS_Ghost Ghost Faces
|
||||
|
||||
There is an exception to the previous statement: in degenerate configurations where all points
|
||||
lie on the same hemisphere, the Delaunay triangulation on the sphere theoretically has a border.
|
||||
Internally however, the triangulation data structure must remain a 2-manifold at all time.
|
||||
To ensure this property, fictitious faces referred to as <i>ghost faces</i> are added.
|
||||
These faces are characterized by the fact that the center of the sphere does not (strictly) lie
|
||||
on the positive side of the supporting plane of the face. Conversely, faces that
|
||||
are not ghost faces are called <em>solid faces</em>, and edges of such faces are <em>solid edges</em>.
|
||||
|
||||
\cgalFigureAnchor{fig_TOS2_ghost}
|
||||
<center>
|
||||
<img src="ghost_faces.png" style="max-width:70%;"/>
|
||||
</center>
|
||||
\cgalFigureCaptionBegin{fig_TOS2_ghost}
|
||||
Solid (blue) and ghost (orange) faces of a Delaunay triangulation on the sphere. View from above (leftmost),
|
||||
and below (middle and rightmost).
|
||||
\cgalFigureCaptionEnd
|
||||
|
||||
\subsection Section_2D_ToS_Traits Traits Classes and Choice of Kernel
|
||||
|
||||
Two traits classes are offered with this package as models of the concept `DelaunayTriangulationOnSphereTraits_2`:
|
||||
<ul>
|
||||
<li>`CGAL::Delaunay_triangulation_on_sphere_traits_2`: This is the simplest possible traits,
|
||||
which represents points on sphere directly as 3D points. If its kernel template parameter
|
||||
cannot represent all points on the sphere exactly, it employs the solution
|
||||
described in Section \ref Section_2D_ToS_Imprecision to determine whether a point
|
||||
should be considered on the sphere, or too close to an existing vertex.
|
||||
</li>
|
||||
<li>`CGAL::Projection_on_sphere_traits_3`: This traits class utilizes a custom internal point type
|
||||
for points on the sphere: given a point `p` in 3D space, this traits class manipulates directly
|
||||
its projection on the sphere (that is, the intersection of the sphere and the segment with endpoints
|
||||
`p` and the center of the sphere). Consequently, all points to be inserted are on the sphere.
|
||||
This traits enable manipulating points that are not on the sphere, but whose triangulation
|
||||
on the sphere is still interesting, such as geographical coordinates with altitude.
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
Both these classes are templated by a kernel. The choice of this kernel is important to ensure
|
||||
a correct result: for the construction of triangulations to be safe, the kernel should provide
|
||||
exact predicates (for example, `CGAL::Exact_predicates_inexact_constructions_kernel`). In addition,
|
||||
some auxiliary functions such as those used in the construction of the Voronoi diagram require creating
|
||||
new geometric points; as such, a kernel offering an exact representation of points on the sphere
|
||||
and exact constructions (for example, `CGAL::Exact_predicates_exact_constructions_kernel_with_sqrt`)
|
||||
should be used if one wants to avoid otherwise inevitable numerical approximations.
|
||||
|
||||
\subsection Section_2D_ToS_Lowdim Dimension of a Triangulation on the Sphere
|
||||
|
||||
Mostly by convention with other triangulations, the dimension of a triangulation on the sphere
|
||||
is defined as follows:
|
||||
<ul>
|
||||
<li>`-2`, if the triangulation is empty;</li>
|
||||
<li>`-1`, if the triangulation contains a single vertex;</li>
|
||||
<li>`0`, if the triangulation contains exactly two vertices;</li>
|
||||
<li>`1`, if the triangulation contains at least three coplanar vertices (which do not necessarily
|
||||
lie on a great circle);</li>
|
||||
<li>`2`, if the triangulation contains at least four non-coplanar vertices.</li>
|
||||
</ul>
|
||||
|
||||
Note that a triangulation of dimension `1` is just a polygon drawn on a circle. The polygon is
|
||||
not triangulated itself. Thus the triangulation of dimension `1` consists of a planar polygon and
|
||||
has no faces.
|
||||
|
||||
\subsection Section_2D_ToS_Embedding Geometric Embeddings
|
||||
|
||||
The descriptions of Delaunay (and regular) triangulations over \f$ \mathbb{S}\f$ have so far been mostly
|
||||
combinatorial. The question of the geometrical embedding of the simplices of the triangulation
|
||||
is also interesting. The two natural embedding of edges and faces of a triangulation of a set
|
||||
of points on \f$ \mathbb{S}\f$ are to use either <em>straight</em> simplex, that is using
|
||||
three-dimensional segments and triangles for the edges and faces of the triangulation, or
|
||||
to use a <em>curved</em> embedding, where the edges are arc segments of great circles over \f$ \mathbb{S}\f$.
|
||||
In the latter choice, the geometrical embedding of the face is defined implicitely by its three edges.
|
||||
|
||||
Both choices are available to users, for example using either `Triangulation_on_sphere_2::segment()`
|
||||
or `Triangulation_on_sphere_2::segment_on_sphere()`. Similar choices are available in the construction
|
||||
of the dual, the Voronoi diagram.
|
||||
|
||||
\cgalFigureAnchor{fig_TOS2_embedding}
|
||||
<center>
|
||||
<img src="geometric_embedding.png" style="max-width:70%;"/>
|
||||
</center>
|
||||
\cgalFigureCaptionBegin{fig_TOS2_embedding}
|
||||
Curved (left) and straight (right) geometric embeddings of the edges of the Delaunay triangulation
|
||||
of the French (including overseas territories) post offices.
|
||||
\cgalFigureCaptionEnd
|
||||
|
||||
\section Section_2D_ToS_Examples Examples
|
||||
|
||||
\subsection Section_2D_ToS_Ex_Basic Basic Example
|
||||
|
||||
The following example uses the simplest traits class provided in this package. It demonstrates
|
||||
how to iteratively insert a few points, and how the dimension and the data structure
|
||||
of the triangulation evolve with these insertions.
|
||||
|
||||
\cgalExample{Triangulation_on_sphere_2/triang_on_sphere.cpp}
|
||||
|
||||
\subsection Section_2D_ToS_Ex_Exact Using an Exact Kernel
|
||||
|
||||
The following example illustrates the limitation of using a kernel with inexact representation
|
||||
of points on the sphere and the rejection of a point for being too close to an already existing
|
||||
vertex. A kernel providing exact representation is also shown to be able to insert
|
||||
these two extremely close points.
|
||||
|
||||
\cgalExample{Triangulation_on_sphere_2/triang_on_sphere_exact.cpp}
|
||||
|
||||
\subsection Section_2D_ToS_Ex_Project Using the Projection Traits Class
|
||||
|
||||
In this example, the use of the projection traits class is illustrated.
|
||||
|
||||
\cgalExample{Triangulation_on_sphere_2/triang_on_sphere_proj.cpp}
|
||||
|
||||
\subsection Section_2D_ToS_Ex_Range Insertion of a Range and Spatial Sorting
|
||||
|
||||
The following example demonstrates how to insert a range of points at once. This enables
|
||||
an internal algorithm to sort the set of points to ensure locality when inserting points,
|
||||
which greatly speeds up the insertion.
|
||||
|
||||
\cgalExample{Triangulation_on_sphere_2/triang_on_sphere_range.cpp}
|
||||
|
||||
\section Section_2D_ToS_Design Design and Implementation History
|
||||
|
||||
Prototype code implementing the publication of Caroli et al. \cgalCite{cgal:ccplr-redtp-10}
|
||||
was developed over the two internships of Oliver Rouiller and Claudia Werner at Inria,
|
||||
under the supervision of Monique Teillaud and with the help of Sébastien Loriot.
|
||||
Based on this prototype, Mael Rouxel-Labbé developed the initial version of this package.
|
||||
|
||||
*/
|
||||
} /* namespace CGAL */
|
||||
|
||||
|
|
@ -0,0 +1,11 @@
|
|||
Manual
|
||||
Kernel_23
|
||||
Circular_kernel_3
|
||||
STL_Extension
|
||||
Algebraic_foundations
|
||||
Circulator
|
||||
Spatial_sorting
|
||||
Stream_support
|
||||
TDS_2
|
||||
Triangulation_2
|
||||
Number_types
|
||||
|
|
@ -0,0 +1,6 @@
|
|||
/*!
|
||||
\example Triangulation_on_sphere_2/triang_on_sphere.cpp
|
||||
\example Triangulation_on_sphere_2/triang_on_sphere_exact.cpp
|
||||
\example Triangulation_on_sphere_2/triang_on_sphere_proj.cpp
|
||||
\example Triangulation_on_sphere_2/triang_on_sphere_range.cpp
|
||||
*/
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 46 KiB |
|
|
@ -0,0 +1,86 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="294pt" height="284pt" viewBox="0 0 294 284" version="1.1">
|
||||
<defs>
|
||||
<g>
|
||||
<symbol overflow="visible" id="glyph0-0">
|
||||
<path style="stroke:none;" d=""/>
|
||||
</symbol>
|
||||
<symbol overflow="visible" id="glyph0-1">
|
||||
<path style="stroke:none;" d="M 9.109375 -9.96875 C 9.109375 -10.09375 9.015625 -10.09375 8.984375 -10.09375 C 8.921875 -10.09375 8.90625 -10.078125 8.734375 -9.875 C 8.65625 -9.765625 8.0625 -9.015625 8.046875 -9.015625 C 7.578125 -9.9375 6.625 -10.09375 6.03125 -10.09375 C 4.203125 -10.09375 2.546875 -8.4375 2.546875 -6.8125 C 2.546875 -5.734375 3.203125 -5.109375 3.90625 -4.859375 C 4.0625 -4.8125 4.90625 -4.578125 5.328125 -4.46875 C 6.0625 -4.28125 6.25 -4.21875 6.5625 -3.90625 C 6.609375 -3.828125 6.90625 -3.5 6.90625 -2.828125 C 6.90625 -1.484375 5.671875 -0.109375 4.234375 -0.109375 C 3.0625 -0.109375 1.75 -0.609375 1.75 -2.21875 C 1.75 -2.5 1.8125 -2.84375 1.84375 -2.984375 C 1.84375 -3.03125 1.859375 -3.09375 1.859375 -3.125 C 1.859375 -3.1875 1.84375 -3.25 1.71875 -3.25 C 1.59375 -3.25 1.578125 -3.234375 1.515625 -2.984375 L 0.78125 -0.046875 C 0.78125 -0.03125 0.734375 0.15625 0.734375 0.171875 C 0.734375 0.296875 0.84375 0.296875 0.875 0.296875 C 0.9375 0.296875 0.953125 0.28125 1.125 0.078125 L 1.78125 -0.78125 C 2.125 -0.265625 2.875 0.296875 4.203125 0.296875 C 6.046875 0.296875 7.75 -1.484375 7.75 -3.28125 C 7.75 -3.890625 7.609375 -4.421875 7.0625 -4.953125 C 6.75 -5.25 6.5 -5.328125 5.171875 -5.671875 C 4.21875 -5.921875 4.09375 -5.96875 3.828125 -6.203125 C 3.578125 -6.4375 3.40625 -6.78125 3.40625 -7.265625 C 3.40625 -8.484375 4.625 -9.703125 5.984375 -9.703125 C 7.390625 -9.703125 8.046875 -8.84375 8.046875 -7.484375 C 8.046875 -7.109375 7.96875 -6.734375 7.96875 -6.671875 C 7.96875 -6.546875 8.09375 -6.546875 8.140625 -6.546875 C 8.265625 -6.546875 8.28125 -6.578125 8.328125 -6.8125 Z M 9.109375 -9.96875 "/>
|
||||
</symbol>
|
||||
<symbol overflow="visible" id="glyph1-0">
|
||||
<path style="stroke:none;" d=""/>
|
||||
</symbol>
|
||||
<symbol overflow="visible" id="glyph1-1">
|
||||
<path style="stroke:none;" d="M 5.609375 -5.390625 C 5.328125 -5.390625 5.203125 -5.390625 5 -5.21875 C 4.921875 -5.15625 4.765625 -4.9375 4.765625 -4.703125 C 4.765625 -4.421875 4.984375 -4.25 5.25 -4.25 C 5.59375 -4.25 5.984375 -4.53125 5.984375 -5.109375 C 5.984375 -5.796875 5.328125 -6.328125 4.328125 -6.328125 C 2.453125 -6.328125 0.578125 -4.28125 0.578125 -2.234375 C 0.578125 -0.984375 1.34375 0.140625 2.8125 0.140625 C 4.765625 0.140625 6 -1.375 6 -1.5625 C 6 -1.65625 5.90625 -1.71875 5.859375 -1.71875 C 5.8125 -1.71875 5.796875 -1.703125 5.671875 -1.578125 C 4.75 -0.359375 3.390625 -0.140625 2.84375 -0.140625 C 1.84375 -0.140625 1.53125 -1 1.53125 -1.71875 C 1.53125 -2.21875 1.78125 -3.609375 2.296875 -4.59375 C 2.671875 -5.265625 3.4375 -6.03125 4.34375 -6.03125 C 4.53125 -6.03125 5.328125 -6.015625 5.609375 -5.390625 Z M 5.609375 -5.390625 "/>
|
||||
</symbol>
|
||||
<symbol overflow="visible" id="glyph2-0">
|
||||
<path style="stroke:none;" d=""/>
|
||||
</symbol>
|
||||
<symbol overflow="visible" id="glyph2-1">
|
||||
<path style="stroke:none;" d="M 0.609375 1.828125 C 0.515625 2.25 0.453125 2.359375 -0.125 2.359375 C -0.296875 2.359375 -0.4375 2.359375 -0.4375 2.640625 C -0.4375 2.671875 -0.4375 2.78125 -0.265625 2.78125 C -0.09375 2.78125 0.109375 2.75 0.296875 2.75 L 0.921875 2.75 C 1.21875 2.75 1.953125 2.78125 2.25 2.78125 C 2.34375 2.78125 2.515625 2.78125 2.515625 2.53125 C 2.515625 2.359375 2.40625 2.359375 2.171875 2.359375 C 1.5 2.359375 1.46875 2.265625 1.46875 2.15625 C 1.46875 1.984375 2.109375 -0.484375 2.1875 -0.8125 C 2.359375 -0.421875 2.734375 0.140625 3.484375 0.140625 C 5.109375 0.140625 6.859375 -1.96875 6.859375 -4.078125 C 6.859375 -5.390625 6.109375 -6.328125 5.03125 -6.328125 C 4.109375 -6.328125 3.34375 -5.4375 3.1875 -5.234375 C 3.0625 -5.953125 2.515625 -6.328125 1.9375 -6.328125 C 1.515625 -6.328125 1.1875 -6.125 0.921875 -5.578125 C 0.65625 -5.0625 0.453125 -4.1875 0.453125 -4.125 C 0.453125 -4.078125 0.515625 -4 0.609375 -4 C 0.734375 -4 0.75 -4.015625 0.828125 -4.34375 C 1.046875 -5.1875 1.3125 -6.03125 1.890625 -6.03125 C 2.21875 -6.03125 2.34375 -5.8125 2.34375 -5.375 C 2.34375 -5.03125 2.296875 -4.890625 2.234375 -4.640625 Z M 3.09375 -4.46875 C 3.203125 -4.875 3.59375 -5.296875 3.828125 -5.5 C 3.984375 -5.640625 4.453125 -6.03125 5 -6.03125 C 5.640625 -6.03125 5.921875 -5.40625 5.921875 -4.65625 C 5.921875 -3.96875 5.515625 -2.359375 5.15625 -1.609375 C 4.8125 -0.828125 4.140625 -0.140625 3.484375 -0.140625 C 2.515625 -0.140625 2.359375 -1.375 2.359375 -1.4375 C 2.359375 -1.484375 2.375 -1.59375 2.390625 -1.65625 Z M 3.09375 -4.46875 "/>
|
||||
</symbol>
|
||||
<symbol overflow="visible" id="glyph3-0">
|
||||
<path style="stroke:none;" d=""/>
|
||||
</symbol>
|
||||
<symbol overflow="visible" id="glyph3-1">
|
||||
<path style="stroke:none;" d="M 2.9375 -1.640625 L 2.9375 -0.78125 C 2.9375 -0.421875 2.90625 -0.3125 2.171875 -0.3125 L 1.96875 -0.3125 L 1.96875 0 C 2.375 -0.03125 2.890625 -0.03125 3.3125 -0.03125 C 3.734375 -0.03125 4.25 -0.03125 4.671875 0 L 4.671875 -0.3125 L 4.453125 -0.3125 C 3.71875 -0.3125 3.703125 -0.421875 3.703125 -0.78125 L 3.703125 -1.640625 L 4.6875 -1.640625 L 4.6875 -1.953125 L 3.703125 -1.953125 L 3.703125 -6.484375 C 3.703125 -6.6875 3.703125 -6.75 3.53125 -6.75 C 3.453125 -6.75 3.421875 -6.75 3.34375 -6.625 L 0.28125 -1.953125 L 0.28125 -1.640625 Z M 2.984375 -1.953125 L 0.5625 -1.953125 L 2.984375 -5.671875 Z M 2.984375 -1.953125 "/>
|
||||
</symbol>
|
||||
<symbol overflow="visible" id="glyph3-2">
|
||||
<path style="stroke:none;" d="M 2.890625 -3.515625 C 3.703125 -3.78125 4.28125 -4.46875 4.28125 -5.265625 C 4.28125 -6.078125 3.40625 -6.640625 2.453125 -6.640625 C 1.453125 -6.640625 0.6875 -6.046875 0.6875 -5.28125 C 0.6875 -4.953125 0.90625 -4.765625 1.203125 -4.765625 C 1.5 -4.765625 1.703125 -4.984375 1.703125 -5.28125 C 1.703125 -5.765625 1.234375 -5.765625 1.09375 -5.765625 C 1.390625 -6.265625 2.046875 -6.390625 2.40625 -6.390625 C 2.828125 -6.390625 3.375 -6.171875 3.375 -5.28125 C 3.375 -5.15625 3.34375 -4.578125 3.09375 -4.140625 C 2.796875 -3.65625 2.453125 -3.625 2.203125 -3.625 C 2.125 -3.609375 1.890625 -3.59375 1.8125 -3.59375 C 1.734375 -3.578125 1.671875 -3.5625 1.671875 -3.46875 C 1.671875 -3.359375 1.734375 -3.359375 1.90625 -3.359375 L 2.34375 -3.359375 C 3.15625 -3.359375 3.53125 -2.6875 3.53125 -1.703125 C 3.53125 -0.34375 2.84375 -0.0625 2.40625 -0.0625 C 1.96875 -0.0625 1.21875 -0.234375 0.875 -0.8125 C 1.21875 -0.765625 1.53125 -0.984375 1.53125 -1.359375 C 1.53125 -1.71875 1.265625 -1.921875 0.984375 -1.921875 C 0.734375 -1.921875 0.421875 -1.78125 0.421875 -1.34375 C 0.421875 -0.4375 1.34375 0.21875 2.4375 0.21875 C 3.65625 0.21875 4.5625 -0.6875 4.5625 -1.703125 C 4.5625 -2.515625 3.921875 -3.296875 2.890625 -3.515625 Z M 2.890625 -3.515625 "/>
|
||||
</symbol>
|
||||
<symbol overflow="visible" id="glyph3-3">
|
||||
<path style="stroke:none;" d="M 1.265625 -0.765625 L 2.328125 -1.796875 C 3.875 -3.171875 4.46875 -3.703125 4.46875 -4.703125 C 4.46875 -5.84375 3.578125 -6.640625 2.359375 -6.640625 C 1.234375 -6.640625 0.5 -5.71875 0.5 -4.828125 C 0.5 -4.28125 1 -4.28125 1.03125 -4.28125 C 1.203125 -4.28125 1.546875 -4.390625 1.546875 -4.8125 C 1.546875 -5.0625 1.359375 -5.328125 1.015625 -5.328125 C 0.9375 -5.328125 0.921875 -5.328125 0.890625 -5.3125 C 1.109375 -5.96875 1.65625 -6.328125 2.234375 -6.328125 C 3.140625 -6.328125 3.5625 -5.515625 3.5625 -4.703125 C 3.5625 -3.90625 3.078125 -3.125 2.515625 -2.5 L 0.609375 -0.375 C 0.5 -0.265625 0.5 -0.234375 0.5 0 L 4.203125 0 L 4.46875 -1.734375 L 4.234375 -1.734375 C 4.171875 -1.4375 4.109375 -1 4 -0.84375 C 3.9375 -0.765625 3.28125 -0.765625 3.0625 -0.765625 Z M 1.265625 -0.765625 "/>
|
||||
</symbol>
|
||||
<symbol overflow="visible" id="glyph3-4">
|
||||
<path style="stroke:none;" d="M 2.9375 -6.375 C 2.9375 -6.625 2.9375 -6.640625 2.703125 -6.640625 C 2.078125 -6 1.203125 -6 0.890625 -6 L 0.890625 -5.6875 C 1.09375 -5.6875 1.671875 -5.6875 2.1875 -5.953125 L 2.1875 -0.78125 C 2.1875 -0.421875 2.15625 -0.3125 1.265625 -0.3125 L 0.953125 -0.3125 L 0.953125 0 C 1.296875 -0.03125 2.15625 -0.03125 2.5625 -0.03125 C 2.953125 -0.03125 3.828125 -0.03125 4.171875 0 L 4.171875 -0.3125 L 3.859375 -0.3125 C 2.953125 -0.3125 2.9375 -0.421875 2.9375 -0.78125 Z M 2.9375 -6.375 "/>
|
||||
</symbol>
|
||||
</g>
|
||||
</defs>
|
||||
<g id="surface10774">
|
||||
<path style="fill:none;stroke-width:0.8;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(0%,0%,0%);stroke-opacity:1;stroke-miterlimit:10;" d="M 435.953125 421.160156 C 435.953125 498.929688 372.910156 561.972656 295.144531 561.972656 C 217.375 561.972656 154.332031 498.929688 154.332031 421.160156 C 154.332031 343.394531 217.375 280.351562 295.144531 280.351562 C 372.910156 280.351562 435.953125 343.394531 435.953125 421.160156 Z M 435.953125 421.160156 " transform="matrix(1,0,0,-1,-153,563)"/>
|
||||
<path style=" stroke:none;fill-rule:evenodd;fill:rgb(0%,0%,0%);fill-opacity:1;" d="M 143.796875 141.847656 C 143.796875 139.449219 140.195312 139.449219 140.195312 141.847656 C 140.195312 144.25 143.796875 144.25 143.796875 141.847656 Z M 143.796875 141.847656 "/>
|
||||
<g style="fill:rgb(0%,0%,0%);fill-opacity:1;">
|
||||
<use xlink:href="#glyph0-1" x="283.177808" y="199.223094"/>
|
||||
</g>
|
||||
<g style="fill:rgb(0%,0%,0%);fill-opacity:1;">
|
||||
<use xlink:href="#glyph1-1" x="148.795439" y="151.211264"/>
|
||||
</g>
|
||||
<g style="fill:rgb(0%,0%,0%);fill-opacity:1;">
|
||||
<use xlink:href="#glyph2-1" x="72.319298" y="182.176426"/>
|
||||
</g>
|
||||
<g style="fill:rgb(0%,0%,0%);fill-opacity:1;">
|
||||
<use xlink:href="#glyph3-1" x="79.369298" y="184.328426"/>
|
||||
</g>
|
||||
<g style="fill:rgb(0%,0%,0%);fill-opacity:1;">
|
||||
<use xlink:href="#glyph2-1" x="61.102381" y="97.365032"/>
|
||||
</g>
|
||||
<g style="fill:rgb(0%,0%,0%);fill-opacity:1;">
|
||||
<use xlink:href="#glyph3-2" x="68.152381" y="99.517032"/>
|
||||
</g>
|
||||
<g style="fill:rgb(0%,0%,0%);fill-opacity:1;">
|
||||
<use xlink:href="#glyph2-1" x="232.164693" y="67.862648"/>
|
||||
</g>
|
||||
<g style="fill:rgb(0%,0%,0%);fill-opacity:1;">
|
||||
<use xlink:href="#glyph3-3" x="239.214693" y="70.014648"/>
|
||||
</g>
|
||||
<g style="fill:rgb(0%,0%,0%);fill-opacity:1;">
|
||||
<use xlink:href="#glyph2-1" x="226.685146" y="44.49094"/>
|
||||
</g>
|
||||
<g style="fill:rgb(0%,0%,0%);fill-opacity:1;">
|
||||
<use xlink:href="#glyph3-4" x="233.735146" y="46.64294"/>
|
||||
</g>
|
||||
<path style="fill:none;stroke-width:0.8;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(100%,0%,0%);stroke-opacity:1;stroke-miterlimit:10;" d="M 230.960938 392.6875 C 275.921875 433.171875 325.492188 468.226562 378.644531 497.132812 " transform="matrix(1,0,0,-1,-153,563)"/>
|
||||
<path style="fill:none;stroke-width:0.8;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(100%,0%,0%);stroke-opacity:1;stroke-miterlimit:10;" d="M 230.960938 392.6875 C 227.496094 419.308594 227.441406 446.261719 230.796875 472.894531 " transform="matrix(1,0,0,-1,-153,563)"/>
|
||||
<path style="fill:none;stroke-width:0.8;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(100%,0%,0%);stroke-opacity:1;stroke-miterlimit:10;" d="M 230.796875 472.894531 C 271 507.796875 323.949219 524.339844 376.871094 518.535156 " transform="matrix(1,0,0,-1,-153,563)"/>
|
||||
<path style="fill:none;stroke-width:0.8;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(100%,0%,0%);stroke-opacity:1;stroke-miterlimit:10;" d="M 230.796875 472.894531 C 276.140625 496.8125 328.039062 505.320312 378.644531 497.132812 " transform="matrix(1,0,0,-1,-153,563)"/>
|
||||
<path style="fill:none;stroke-width:0.8;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(0%,0%,0%);stroke-opacity:1;stroke-dasharray:4;stroke-miterlimit:10;" d="M 435.957031 420.902344 C 435.066406 470.46875 372.523438 510.960938 295.578125 511.789062 C 218.632812 512.613281 155.835938 473.46875 154.632812 423.925781 " transform="matrix(1,0,0,-1,-153,563)"/>
|
||||
<path style="fill:none;stroke-width:0.8;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(0%,100%,0%);stroke-opacity:1;stroke-miterlimit:10;" d="M 379.625 506.074219 C 378.8125 535.113281 340.398438 558.65625 293.824219 558.65625 C 247.246094 558.65625 210.148438 535.113281 210.960938 506.074219 C 211.769531 477.035156 250.183594 453.492188 296.761719 453.492188 C 343.335938 453.492188 380.433594 477.035156 379.625 506.074219 Z M 379.625 506.074219 " transform="matrix(1,0,0,-1,-153,563)"/>
|
||||
<path style="fill:none;stroke-width:0.8;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(100%,0%,0%);stroke-opacity:1;stroke-miterlimit:10;" d="M 376.871094 518.535156 C 378.171875 511.476562 378.765625 504.308594 378.644531 497.132812 " transform="matrix(1,0,0,-1,-153,563)"/>
|
||||
<path style=" stroke:none;fill-rule:evenodd;fill:rgb(0%,0%,0%);fill-opacity:1;" d="M 225.671875 44.464844 C 225.671875 42.0625 222.074219 42.0625 222.074219 44.464844 C 222.074219 46.863281 225.671875 46.863281 225.671875 44.464844 Z M 225.671875 44.464844 "/>
|
||||
<path style=" stroke:none;fill-rule:evenodd;fill:rgb(0%,0%,0%);fill-opacity:1;" d="M 227.445312 65.867188 C 227.445312 63.46875 223.84375 63.46875 223.84375 65.867188 C 223.84375 68.269531 227.445312 68.269531 227.445312 65.867188 Z M 227.445312 65.867188 "/>
|
||||
<path style=" stroke:none;fill-rule:evenodd;fill:rgb(0%,0%,0%);fill-opacity:1;" d="M 79.597656 90.105469 C 79.597656 87.707031 75.996094 87.707031 75.996094 90.105469 C 75.996094 92.503906 79.597656 92.503906 79.597656 90.105469 Z M 79.597656 90.105469 "/>
|
||||
<path style="fill:none;stroke-width:0.8;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(0%,0%,0%);stroke-opacity:1;stroke-miterlimit:10;" d="M 154.632812 423.925781 C 154.3125 399.796875 168.953125 376.445312 195.304688 359.042969 C 221.65625 341.640625 257.542969 331.628906 295.007812 331.226562 C 332.472656 330.824219 368.417969 340.066406 394.878906 356.898438 C 421.339844 373.734375 436.125 396.769531 435.957031 420.902344 " transform="matrix(1,0,0,-1,-153,563)"/>
|
||||
<path style=" stroke:none;fill-rule:evenodd;fill:rgb(0%,0%,0%);fill-opacity:1;" d="M 79.761719 170.3125 C 79.761719 167.914062 76.160156 167.914062 76.160156 170.3125 C 76.160156 172.710938 79.761719 172.710938 79.761719 170.3125 Z M 79.761719 170.3125 "/>
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 14 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 488 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 236 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 570 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 16 KiB |
|
|
@ -0,0 +1,19 @@
|
|||
cmake_minimum_required(VERSION 3.1...3.15)
|
||||
|
||||
project( Triangulation_on_sphere_2_Examples )
|
||||
|
||||
find_package(CGAL REQUIRED COMPONENTS Core)
|
||||
|
||||
if ( CGAL_FOUND )
|
||||
|
||||
create_single_source_cgal_program( "triang_on_sphere.cpp" )
|
||||
create_single_source_cgal_program( "triang_on_sphere_range.cpp" )
|
||||
create_single_source_cgal_program( "triang_on_sphere_exact.cpp" )
|
||||
create_single_source_cgal_program( "triang_on_sphere_proj.cpp" )
|
||||
create_single_source_cgal_program( "triang_on_sphere_geo.cpp" )
|
||||
|
||||
else()
|
||||
|
||||
message(STATUS "This program requires the CGAL library, and will not be compiled.")
|
||||
|
||||
endif()
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
|
|
@ -0,0 +1,46 @@
|
|||
#include <CGAL/Exact_predicates_inexact_constructions_kernel.h>
|
||||
|
||||
#include <CGAL/Delaunay_triangulation_on_sphere_traits_2.h>
|
||||
#include <CGAL/Delaunay_triangulation_on_sphere_2.h>
|
||||
|
||||
typedef CGAL::Exact_predicates_inexact_constructions_kernel K;
|
||||
|
||||
typedef CGAL::Delaunay_triangulation_on_sphere_traits_2<K> Traits;
|
||||
typedef CGAL::Delaunay_triangulation_on_sphere_2<Traits> DToS2;
|
||||
|
||||
typedef Traits::Point_3 Point_3;
|
||||
|
||||
int main(int, char**)
|
||||
{
|
||||
std::vector<Point_3> points;
|
||||
points.emplace_back( 2, 1, 1);
|
||||
points.emplace_back(-2, 1, 1); // not on the sphere
|
||||
points.emplace_back( 0, 1, 1);
|
||||
points.emplace_back( 1, 2, 1);
|
||||
points.emplace_back( 0, 1, 1); // duplicate of #3
|
||||
points.emplace_back( 1, 0, 1);
|
||||
points.emplace_back( 1, 1, 2);
|
||||
|
||||
Traits traits(Point_3(1, 1, 1), 1); // sphere center on (1,1,1), with radius 1
|
||||
DToS2 dtos(traits);
|
||||
|
||||
for(const Point_3& pt : points)
|
||||
{
|
||||
std::cout << "Inserting (" << pt
|
||||
<< ") at squared distance " << CGAL::squared_distance(pt, traits.center())
|
||||
<< " from the center of the sphere; is it on there sphere? "
|
||||
<< (traits.is_on_sphere(pt) ? "yes" : "no") << std::endl;
|
||||
dtos.insert(pt);
|
||||
|
||||
std::cout << "After insertion, the dimension of the triangulation is: " << dtos.dimension() << "\n";
|
||||
std::cout << "It has:\n";
|
||||
std::cout << dtos.number_of_vertices() << " vertices\n";
|
||||
std::cout << dtos.number_of_edges() << " edges\n";
|
||||
std::cout << dtos.number_of_faces() << " solid faces\n";
|
||||
std::cout << dtos.number_of_ghost_faces() << " ghost faces\n" << std::endl;
|
||||
}
|
||||
|
||||
CGAL::write_OFF("result.off", dtos, CGAL::parameters::stream_precision(17));
|
||||
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
|
|
@ -0,0 +1,68 @@
|
|||
#include <CGAL/Exact_predicates_exact_constructions_kernel_with_sqrt.h>
|
||||
#include <CGAL/Exact_predicates_inexact_constructions_kernel.h>
|
||||
|
||||
#include <CGAL/Delaunay_triangulation_on_sphere_2.h>
|
||||
#include <CGAL/Projection_on_sphere_traits_3.h>
|
||||
|
||||
#include <iostream>
|
||||
#include <fstream>
|
||||
|
||||
template <typename Kernel>
|
||||
void create_triangulation(const char* filename)
|
||||
{
|
||||
typedef typename Kernel::FT FT;
|
||||
|
||||
typedef CGAL::Projection_on_sphere_traits_3<Kernel> Traits;
|
||||
typedef CGAL::Delaunay_triangulation_on_sphere_2<Traits> DToS2;
|
||||
|
||||
typedef typename Traits::Point_3 Point_3;
|
||||
|
||||
std::cout << "\n-- Constructing triangulation with Kernel: " << typeid(Kernel).name() << " --" << std::endl;
|
||||
|
||||
std::vector<Point_3> points;
|
||||
double x, y, z;
|
||||
|
||||
std::ifstream in(filename);
|
||||
if(!in)
|
||||
{
|
||||
std::cerr << "Invalid input file: " << filename << std::endl;
|
||||
return;
|
||||
}
|
||||
|
||||
while(in >> x >> y >> z)
|
||||
points.emplace_back(x, y, z);
|
||||
|
||||
// Add an extra point that would be too close to 'p' with a basic kernel such as CGAL::EPICK,
|
||||
const Point_3& p = points.back();
|
||||
const FT tiny = 100 * std::numeric_limits<double>::epsilon();
|
||||
points.emplace_back(p.x() + tiny, p.y() - tiny, p.z() + tiny);
|
||||
|
||||
std::cout << "Adding point " << points.back() << "\nvery close to " << p << std::endl;
|
||||
std::cout << "Squared distance between points " << CGAL::squared_distance(points.back(), p) << std::endl;
|
||||
std::cout << points.size() << " points in input" << std::endl;
|
||||
|
||||
Traits traits(Point_3(0, 0, 0), 100); // centered on (0,0,0), with radius 100
|
||||
DToS2 dtos(points.begin(), points.end(), traits);
|
||||
|
||||
std::cout << dtos.number_of_vertices() << " vertices" << std::endl;
|
||||
std::cout << dtos.number_of_faces() << " faces" << std::endl;
|
||||
}
|
||||
|
||||
int main(int argc, char** argv)
|
||||
{
|
||||
std::cout.precision(17);
|
||||
|
||||
// This kernel CAN represent exactly all points of the sphere
|
||||
typedef CGAL::Exact_predicates_exact_constructions_kernel_with_sqrt EPECK_w_SQRT;
|
||||
|
||||
// This kernel CANNOT represent exactly all points of the sphere
|
||||
// and thus a separation mechanism is needed to ensure that no points are hidden
|
||||
typedef CGAL::Exact_predicates_inexact_constructions_kernel EPICK;
|
||||
|
||||
const char* filename = (argc > 1) ? argv[1] : "data/poste_france.xyz";
|
||||
|
||||
create_triangulation<EPICK>(filename);
|
||||
create_triangulation<EPECK_w_SQRT>(filename);
|
||||
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
|
|
@ -0,0 +1,63 @@
|
|||
#include <CGAL/Exact_predicates_inexact_constructions_kernel.h>
|
||||
|
||||
#include <CGAL/Delaunay_triangulation_on_sphere_2.h>
|
||||
#include <CGAL/Geographical_coordinates_traits_2.h>
|
||||
|
||||
#include <iostream>
|
||||
#include <fstream>
|
||||
|
||||
typedef CGAL::Exact_predicates_inexact_constructions_kernel K;
|
||||
|
||||
typedef CGAL::Geographical_coordinates_traits_2<K> Traits;
|
||||
typedef CGAL::Delaunay_triangulation_on_sphere_2<Traits> DToS2;
|
||||
|
||||
typedef Traits::Point_3 Point_3;
|
||||
typedef Traits::Point_on_sphere_2 Point;
|
||||
|
||||
// Note: Geographical_coordinates_traits_2 are currently undocumented because they use
|
||||
// a conversion to the Cartesian domain R^3 to perform predicates and constructions,
|
||||
// losing the benefit of the exact representation on the way.
|
||||
// It can be useful on its own (especially since it contains code
|
||||
// to handle generic convex domains), but hidden points are possible
|
||||
// and are not handled properly.
|
||||
|
||||
int main(int argc, char** argv)
|
||||
{
|
||||
std::cout.precision(17);
|
||||
|
||||
const char* filename = (argc > 1) ? argv[1] : "data/poste_france.xyz";
|
||||
|
||||
Traits traits(Point_3(0, 0, 0), 100);
|
||||
|
||||
std::ifstream in(filename);
|
||||
if(!in)
|
||||
{
|
||||
std::cerr << "Invalid input file: " << filename << std::endl;
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
typename Traits::Construct_point_on_sphere_2 cps2 = traits.construct_point_on_sphere_2_object();
|
||||
|
||||
std::vector<Point> points;
|
||||
double x, y, z;
|
||||
|
||||
while(in >> x >> y >> z)
|
||||
{
|
||||
Point_3 cp(x, y, z);
|
||||
Point ps = cps2(cp);
|
||||
std::cout << "Cartesian point: " << cp << " Coordinates on the sphere: " << ps << std::endl;
|
||||
points.push_back(ps);
|
||||
}
|
||||
|
||||
std::cout << points.size() << " points in input" << std::endl;
|
||||
|
||||
DToS2 dtos(points.begin(), points.end(), traits);
|
||||
|
||||
std::cout << dtos.number_of_vertices() << " vertices" << std::endl;
|
||||
std::cout << dtos.number_of_faces() << " solid faces" << std::endl;
|
||||
std::cout << dtos.number_of_ghost_faces() << " ghost faces" << std::endl;
|
||||
|
||||
CGAL::write_OFF("result.off", dtos, CGAL::parameters::stream_precision(17));
|
||||
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
|
|
@ -0,0 +1,46 @@
|
|||
#include <CGAL/Exact_predicates_inexact_constructions_kernel.h>
|
||||
|
||||
#include <CGAL/Delaunay_triangulation_on_sphere_2.h>
|
||||
#include <CGAL/Projection_on_sphere_traits_3.h>
|
||||
|
||||
#include <boost/iterator/transform_iterator.hpp>
|
||||
|
||||
typedef CGAL::Exact_predicates_inexact_constructions_kernel K;
|
||||
|
||||
typedef CGAL::Projection_on_sphere_traits_3<K> Traits;
|
||||
typedef CGAL::Delaunay_triangulation_on_sphere_2<Traits> DToS2;
|
||||
|
||||
typedef Traits::Point_3 Point_3;
|
||||
|
||||
int main(int, char**)
|
||||
{
|
||||
std::vector<Point_3> points;
|
||||
points.emplace_back( 3, 1, 1);
|
||||
points.emplace_back(-8, 1, 1);
|
||||
points.emplace_back( 1, 2, 1);
|
||||
points.emplace_back( 1, -2, 1);
|
||||
points.emplace_back( 1, 1, 10);
|
||||
|
||||
Traits traits(Point_3(1,1,1)); // radius is 1 by default
|
||||
DToS2 dtos(traits);
|
||||
|
||||
Traits::Construct_point_on_sphere_2 cst = traits.construct_point_on_sphere_2_object();
|
||||
|
||||
for(const auto& pt : points)
|
||||
{
|
||||
std::cout << "----- Inserting (" << pt
|
||||
<< ") at squared distance " << CGAL::squared_distance(pt, traits.center())
|
||||
<< " from the center of the sphere" << std::endl;
|
||||
dtos.insert(cst(pt));
|
||||
|
||||
std::cout << "The triangulation now has dimension: " << dtos.dimension() << " and\n";
|
||||
std::cout << dtos.number_of_vertices() << " vertices" << std::endl;
|
||||
std::cout << dtos.number_of_edges() << " edges" << std::endl;
|
||||
std::cout << dtos.number_of_faces() << " solid faces" << std::endl;
|
||||
std::cout << dtos.number_of_ghost_faces() << " ghost faces" << std::endl;
|
||||
}
|
||||
|
||||
CGAL::write_OFF("result.off", dtos, CGAL::parameters::stream_precision(17));
|
||||
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
|
|
@ -0,0 +1,46 @@
|
|||
#include <CGAL/Exact_predicates_inexact_constructions_kernel.h>
|
||||
|
||||
#include <CGAL/Delaunay_triangulation_on_sphere_2.h>
|
||||
#include <CGAL/Projection_on_sphere_traits_3.h>
|
||||
|
||||
#include <iostream>
|
||||
#include <fstream>
|
||||
|
||||
typedef CGAL::Exact_predicates_inexact_constructions_kernel K;
|
||||
|
||||
typedef CGAL::Projection_on_sphere_traits_3<K> Traits;
|
||||
typedef CGAL::Delaunay_triangulation_on_sphere_2<Traits> DToS2;
|
||||
|
||||
typedef DToS2::Point_3 Point;
|
||||
|
||||
int main(int argc, char** argv)
|
||||
{
|
||||
std::cout.precision(17);
|
||||
|
||||
const char* filename = (argc > 1) ? argv[1] : "data/radar.xyz";
|
||||
|
||||
std::vector<Point> points;
|
||||
double x, y, z;
|
||||
|
||||
std::ifstream in(filename);
|
||||
if(!in)
|
||||
{
|
||||
std::cerr << "Invalid input file: " << filename << std::endl;
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
while(in >> x >> y >> z)
|
||||
points.emplace_back(x, y, z);
|
||||
|
||||
std::cout << points.size() << " points in input" << std::endl;
|
||||
|
||||
Traits traits(Point(0, 0, 0), 100);
|
||||
DToS2 dtos(points.begin(), points.end(), traits);
|
||||
|
||||
std::cout << dtos.number_of_vertices() << " vertices" << std::endl;
|
||||
std::cout << dtos.number_of_faces() << " solid faces" << std::endl;
|
||||
|
||||
CGAL::write_OFF("result.off", dtos, CGAL::parameters::stream_precision(17));
|
||||
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
|
|
@ -0,0 +1,411 @@
|
|||
// Copyright (c) 1997, 2012, 2019 INRIA Sophia-Antipolis (France).
|
||||
// All rights reserved.
|
||||
//
|
||||
// This file is part of CGAL (www.cgal.org).
|
||||
//
|
||||
// $URL$
|
||||
// $Id$
|
||||
// SPDX-License-Identifier: GPL-3.0-or-later OR LicenseRef-Commercial
|
||||
//
|
||||
// Author(s) : Mariette Yvinec,
|
||||
// Claudia Werner,
|
||||
// Mael Rouxel-Labbé
|
||||
|
||||
#ifndef CGAL_DELAUNAY_TRIANGULATION_SPHERE_TRAITS_2_H
|
||||
#define CGAL_DELAUNAY_TRIANGULATION_SPHERE_TRAITS_2_H
|
||||
|
||||
#include <CGAL/license/Triangulation_on_sphere_2.h>
|
||||
|
||||
#include <CGAL/Triangulation_on_sphere_2/internal/get_precision_bounds.h>
|
||||
|
||||
#include <CGAL/Algebraic_kernel_for_spheres_2_3.h>
|
||||
#include <CGAL/Has_conversion.h>
|
||||
#include <CGAL/Spherical_kernel_3.h>
|
||||
#include <CGAL/squared_distance_3.h>
|
||||
#include <CGAL/triangulation_assertions.h>
|
||||
|
||||
#include <CGAL/enum.h>
|
||||
|
||||
namespace CGAL {
|
||||
namespace internal {
|
||||
|
||||
template <typename LK>
|
||||
class Orientation_on_sphere_2
|
||||
{
|
||||
public:
|
||||
typedef typename LK::Point_3 Point_3;
|
||||
typedef typename LK::Point_3 Point_on_sphere_2;
|
||||
typedef Comparison_result result_type;
|
||||
|
||||
Orientation_on_sphere_2(const Point_3& center, const LK& lk)
|
||||
: _center(center), _lk(lk)
|
||||
{ }
|
||||
|
||||
Comparison_result operator()(const Point_on_sphere_2& p, const Point_on_sphere_2& q, const Point_on_sphere_2& r) const
|
||||
{ return _lk.orientation_3_object()(_center, p, q, r); }
|
||||
|
||||
protected:
|
||||
const Point_3& _center;
|
||||
const LK& _lk;
|
||||
};
|
||||
|
||||
template <typename LK>
|
||||
class Equal_on_sphere_2
|
||||
{
|
||||
public:
|
||||
typedef typename LK::Point_3 Point_3;
|
||||
typedef typename LK::Point_3 Point_on_sphere_2;
|
||||
typedef bool result_type;
|
||||
|
||||
Equal_on_sphere_2(const Point_3& center, const LK& lk)
|
||||
: _center(center), _lk(lk)
|
||||
{ }
|
||||
|
||||
bool operator()(const Point_on_sphere_2& p, const Point_on_sphere_2& q) const
|
||||
{
|
||||
return _lk.collinear_3_object()(_center, p, q) &&
|
||||
!_lk.collinear_are_strictly_ordered_along_line_3_object()(p, _center, q);
|
||||
}
|
||||
|
||||
protected:
|
||||
const Point_3& _center;
|
||||
const LK& _lk;
|
||||
};
|
||||
|
||||
template <typename LK>
|
||||
class Inside_cone_2
|
||||
{
|
||||
public:
|
||||
typedef typename LK::Point_3 Point_3;
|
||||
typedef typename LK::Point_3 Point_on_sphere_2;
|
||||
typedef bool result_type;
|
||||
|
||||
Inside_cone_2(const Point_3& center, const LK& lk)
|
||||
: _center(center), _lk(lk)
|
||||
{ }
|
||||
|
||||
bool operator()(const Point_on_sphere_2& p, const Point_on_sphere_2& q, const Point_on_sphere_2& r) const
|
||||
{
|
||||
// @todo first two checks might be unnecessary because we should always have r != p|q (using equal_on_sphere)
|
||||
if(_lk.collinear_3_object()(_center, p, r) ||
|
||||
_lk.collinear_3_object()(_center, q, r) ||
|
||||
_lk.orientation_3_object()(_center, p, q, r) != COLLINEAR)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
// @todo also useless?
|
||||
if(collinear(_center, p, q))
|
||||
return true;
|
||||
|
||||
// Check if r is on the same side of the plane orthogonal to the plane (c,p,q)
|
||||
// and going through c and p as q
|
||||
const Orientation op = _lk.coplanar_orientation_3_object()(_center, p, q, r);
|
||||
CGAL_triangulation_assertion(op != COLLINEAR);
|
||||
if(op == NEGATIVE)
|
||||
return false;
|
||||
|
||||
// Check if r is on the same side of the plane orthogonal to the plane (c,p,q)
|
||||
// and going through c and q as p
|
||||
const Orientation oq = _lk.coplanar_orientation_3_object()(_center, q, p, r);
|
||||
CGAL_triangulation_assertion(oq != COLLINEAR);
|
||||
if(oq == NEGATIVE)
|
||||
return false;
|
||||
|
||||
return true; // both true
|
||||
}
|
||||
|
||||
protected:
|
||||
const Point_3& _center;
|
||||
const LK& _lk;
|
||||
};
|
||||
|
||||
template <typename LK>
|
||||
typename LK::Point_3
|
||||
ray_sphere_intersection(const typename LK::Point_3 o, // origin of the ray
|
||||
const typename LK::Vector_3 dir, // direction of the ray
|
||||
const typename LK::Point_3 sc, // center of the sphere
|
||||
const typename LK::FT r, // radius of the sphere
|
||||
const LK& lk)
|
||||
{
|
||||
typedef typename LK::FT FT;
|
||||
typedef typename LK::Vector_3 Vector_3;
|
||||
|
||||
// Line-Sphere intersection is:
|
||||
//
|
||||
// || x - c ||^2 = r^2 // sphere
|
||||
// x = o + t * d // ray
|
||||
//
|
||||
// thus || o + t*d - c ||^2 = r^2
|
||||
//
|
||||
// so a*t^2 + b*t + c = 0 with
|
||||
//
|
||||
// a := || d ||^2
|
||||
// b := 2 * d * (o - c)
|
||||
// c := || o - c||^2 - r^2
|
||||
|
||||
const Vector_3 sco = lk.construct_vector_3_object()(sc, o);
|
||||
const FT a = lk.compute_squared_length_3_object()(dir);
|
||||
const FT b = 2 * lk.compute_scalar_product_3_object()(dir, sco);
|
||||
const FT c = lk.compute_squared_length_3_object()(sco) - r*r;
|
||||
|
||||
FT d = b*b - 4*a*c;
|
||||
// by construction d > 0 is expected, but just to be safe
|
||||
if(d < 0)
|
||||
d = 0;
|
||||
|
||||
const FT dr = CGAL::sqrt(d);
|
||||
const FT det = FT(0.5) / a;
|
||||
|
||||
// care only about the positive value, and we know det > 0 && dr > 0
|
||||
const FT t0 = det * (-b + dr);
|
||||
|
||||
return lk.construct_translated_point_3_object()(o, lk.construct_scaled_vector_3_object()(dir, t0));
|
||||
}
|
||||
|
||||
template <typename LK>
|
||||
class Construct_circumcenter_on_sphere_2
|
||||
{
|
||||
public:
|
||||
typedef typename LK::FT FT;
|
||||
typedef typename LK::Point_3 Point_3;
|
||||
typedef typename LK::Point_3 Point_on_sphere_2;
|
||||
typedef typename LK::Vector_3 Vector_3;
|
||||
typedef Point_on_sphere_2 result_type;
|
||||
|
||||
Construct_circumcenter_on_sphere_2(const Point_3& center, const FT radius, const LK& lk)
|
||||
: _center(center), _radius(radius), _lk(lk)
|
||||
{ }
|
||||
|
||||
result_type operator()(const Point_on_sphere_2& p, const Point_on_sphere_2& q, const Point_on_sphere_2& r) const
|
||||
{
|
||||
const Point_3 c = _lk.construct_circumcenter_3_object()(p, q, r);
|
||||
const Vector_3 n = _lk.construct_normal_3_object()(p, q, r);
|
||||
return ray_sphere_intersection(c, n, _center, _radius, _lk);
|
||||
}
|
||||
|
||||
protected:
|
||||
const Point_3& _center;
|
||||
const FT _radius;
|
||||
const LK& _lk;
|
||||
};
|
||||
|
||||
template <typename LK, typename SK>
|
||||
class Construct_arc_on_sphere_2
|
||||
{
|
||||
public:
|
||||
typedef typename LK::FT FT;
|
||||
typedef typename LK::Point_3 Point_3;
|
||||
typedef typename LK::Point_3 Point_on_sphere_2;
|
||||
typedef typename SK::Circular_arc_3 result_type;
|
||||
|
||||
Construct_arc_on_sphere_2(const Point_3& center, const FT radius, const LK& lk, const SK& sk)
|
||||
: _center(center), _radius(radius), _lk(lk), _sk(sk)
|
||||
{ }
|
||||
|
||||
result_type operator()(const Point_on_sphere_2& p, const Point_on_sphere_2& q) const
|
||||
{
|
||||
typedef typename CGAL::internal::Converter_selector<LK, SK>::type Converter;
|
||||
Converter cv;
|
||||
|
||||
typename SK::Point_3 sc = cv(_center); // @tmp cache that
|
||||
typename SK::Point_3 sp = cv(p);
|
||||
typename SK::Point_3 sq = cv(q);
|
||||
|
||||
CGAL_precondition(!_sk.collinear_3_object()(sc, sp, sq));
|
||||
|
||||
typename SK::Plane_3 pl = _sk.construct_plane_3_object()(sc, sp, sq);
|
||||
CGAL_assertion(is_valid(pl));
|
||||
|
||||
// CircleC3 has an annoying assertion to check pl.has_on(sc) that has no chance to
|
||||
// pass with a non-exact kernel, so dodging it by passing the plane's normal,
|
||||
//despite this creating internally another plane...
|
||||
typename SK::Circle_3 c = _sk.construct_circle_3_object()(
|
||||
sc, square(_radius), _sk.construct_orthogonal_vector_3_object()(pl));
|
||||
|
||||
typename SK::Circular_arc_point_3 cp = _sk.construct_circular_arc_point_3_object()(sp);
|
||||
typename SK::Circular_arc_point_3 cq = _sk.construct_circular_arc_point_3_object()(sq);
|
||||
|
||||
return _sk.construct_circular_arc_3_object()(c, cp, cq);
|
||||
}
|
||||
|
||||
protected:
|
||||
const Point_3& _center;
|
||||
const FT _radius;
|
||||
const LK& _lk;
|
||||
const SK& _sk;
|
||||
};
|
||||
|
||||
} // namespace internal
|
||||
|
||||
template <typename LK_,
|
||||
typename SK_ = CGAL::Spherical_kernel_3<
|
||||
LK_, CGAL::Algebraic_kernel_for_spheres_2_3<typename LK_::FT> > >
|
||||
class Delaunay_triangulation_on_sphere_traits_2
|
||||
: public LK_, SK_
|
||||
{
|
||||
public:
|
||||
typedef LK_ LK;
|
||||
typedef SK_ SK;
|
||||
|
||||
private:
|
||||
typedef Delaunay_triangulation_on_sphere_traits_2<LK> Self;
|
||||
|
||||
public:
|
||||
typedef typename LK::FT FT;
|
||||
typedef typename LK::Point_3 Point_on_sphere_2;
|
||||
typedef typename LK::Point_3 Point_3;
|
||||
typedef typename LK::Segment_3 Segment_3;
|
||||
typedef typename LK::Triangle_3 Triangle_3;
|
||||
|
||||
typedef typename SK::Circular_arc_3 Arc_on_sphere_2;
|
||||
|
||||
// predicates
|
||||
typedef internal::Inside_cone_2<LK> Collinear_are_strictly_ordered_on_great_circle_2;
|
||||
typedef typename LK::Compare_xyz_3 Compare_on_sphere_2;
|
||||
typedef internal::Equal_on_sphere_2<LK> Equal_on_sphere_2;
|
||||
typedef internal::Orientation_on_sphere_2<LK> Orientation_on_sphere_2;
|
||||
typedef typename LK::Orientation_3 Side_of_oriented_circle_on_sphere_2;
|
||||
|
||||
// constructions
|
||||
typedef typename LK::Construct_point_3 Construct_point_on_sphere_2;
|
||||
typedef typename LK::Construct_point_3 Construct_point_3;
|
||||
typedef typename LK::Construct_segment_3 Construct_segment_3;
|
||||
typedef typename LK::Construct_triangle_3 Construct_triangle_3;
|
||||
|
||||
// For the hilbert sort
|
||||
typedef typename LK::Compute_x_3 Compute_x_3;
|
||||
typedef typename LK::Compute_y_3 Compute_y_3;
|
||||
typedef typename LK::Compute_z_3 Compute_z_3;
|
||||
|
||||
typedef internal::Construct_circumcenter_on_sphere_2<LK> Construct_circumcenter_on_sphere_2;
|
||||
typedef internal::Construct_arc_on_sphere_2<LK, SK> Construct_arc_on_sphere_2;
|
||||
typedef typename LK::Construct_circumcenter_3 Construct_circumcenter_3;
|
||||
|
||||
protected:
|
||||
Point_3 _center;
|
||||
FT _radius;
|
||||
|
||||
FT _minDistSquared; // minimal distance of two points to each other
|
||||
FT _minRadiusSquared; // minimal distance of a point from center of the sphere
|
||||
FT _maxRadiusSquared; // maximal distance of a point from center of the sphere
|
||||
|
||||
static constexpr bool _has_exact_rep =
|
||||
is_same_or_derived<Field_with_sqrt_tag,
|
||||
typename Algebraic_structure_traits<FT>::Algebraic_category>::value &&
|
||||
!std::is_floating_point<FT>::value;
|
||||
|
||||
public:
|
||||
Delaunay_triangulation_on_sphere_traits_2(const Point_3& center = CGAL::ORIGIN,
|
||||
const FT radius = 1,
|
||||
const LK& k = LK(),
|
||||
const SK& sk = SK())
|
||||
: LK(k), SK(sk), _center(center), _radius(radius)
|
||||
{
|
||||
initialize_bounds();
|
||||
}
|
||||
|
||||
public:
|
||||
const LK& lk() const { return static_cast<const LK&>(*this); }
|
||||
const SK& sk() const { return static_cast<const SK&>(*this); }
|
||||
|
||||
void set_center(const Point_3& center) { _center = center; }
|
||||
const Point_3& center() const { return _center; }
|
||||
void set_radius(const FT radius) { _radius = radius; initialize_bounds(); }
|
||||
FT radius() const { return _radius; }
|
||||
|
||||
private:
|
||||
void initialize_bounds()
|
||||
{
|
||||
Triangulations_on_sphere_2::internal::ToS2_precision_bound<FT, _has_exact_rep> bound_getter(_radius);
|
||||
|
||||
_minDistSquared = bound_getter.get_squared_min_dist();
|
||||
_minRadiusSquared = bound_getter.get_squared_min_radius();
|
||||
_maxRadiusSquared = bound_getter.get_squared_max_radius();
|
||||
}
|
||||
|
||||
public:
|
||||
Collinear_are_strictly_ordered_on_great_circle_2
|
||||
collinear_are_strictly_ordered_on_great_circle_2_object() const
|
||||
{ return Collinear_are_strictly_ordered_on_great_circle_2(center(), lk()); }
|
||||
|
||||
Compare_on_sphere_2
|
||||
compare_on_sphere_2_object() const
|
||||
{ return lk().compare_xyz_3_object(); }
|
||||
|
||||
Equal_on_sphere_2
|
||||
equal_on_sphere_2_object() const
|
||||
{ return Equal_on_sphere_2(center(), lk()); }
|
||||
|
||||
Orientation_on_sphere_2
|
||||
orientation_on_sphere_2_object() const
|
||||
{ return Orientation_on_sphere_2(center(), lk()); }
|
||||
|
||||
Side_of_oriented_circle_on_sphere_2
|
||||
side_of_oriented_circle_on_sphere_2_object() const
|
||||
{ return lk().orientation_3_object(); }
|
||||
|
||||
public:
|
||||
Compute_x_3
|
||||
compute_x_3_object() const
|
||||
{ return lk().compute_x_3_object(); }
|
||||
|
||||
Compute_y_3
|
||||
compute_y_3_object() const
|
||||
{ return lk().compute_y_3_object(); }
|
||||
|
||||
Compute_z_3
|
||||
compute_z_3_object() const
|
||||
{ return lk().compute_z_3_object(); }
|
||||
|
||||
Construct_point_on_sphere_2
|
||||
construct_point_on_sphere_2_object() const
|
||||
{ return lk().construct_point_on_sphere_2_object(); }
|
||||
|
||||
Construct_point_3
|
||||
construct_point_3_object() const
|
||||
{ return lk().construct_point_3_object(); }
|
||||
|
||||
Construct_segment_3
|
||||
construct_segment_3_object() const
|
||||
{ return lk().construct_segment_3_object(); }
|
||||
|
||||
Construct_triangle_3
|
||||
construct_triangle_3_object() const
|
||||
{ return lk().construct_triangle_3_object(); }
|
||||
|
||||
Construct_arc_on_sphere_2
|
||||
construct_arc_on_sphere_2_object() const
|
||||
{ return Construct_arc_on_sphere_2(center(), radius(), lk(), sk()); }
|
||||
|
||||
Construct_circumcenter_on_sphere_2
|
||||
construct_circumcenter_on_sphere_2_object() const
|
||||
{ return Construct_circumcenter_on_sphere_2(center(), radius(), lk()); }
|
||||
|
||||
Construct_circumcenter_3
|
||||
construct_circumcenter_3_object() const
|
||||
{ return lk().construct_circumcenter_3_object(); }
|
||||
|
||||
public:
|
||||
bool is_on_sphere(const Point_on_sphere_2& p) const
|
||||
{
|
||||
const FT sq_dist = lk().compute_squared_distance_3_object()(p, _center);
|
||||
|
||||
if(_has_exact_rep)
|
||||
return (sq_dist == _minRadiusSquared);
|
||||
else
|
||||
return (_minRadiusSquared <= sq_dist && sq_dist < _maxRadiusSquared);
|
||||
}
|
||||
|
||||
bool are_points_too_close(const Point_on_sphere_2& p, const Point_on_sphere_2& q) const
|
||||
{
|
||||
if(_has_exact_rep)
|
||||
return false;
|
||||
else
|
||||
return (CGAL::squared_distance(p, q) <= _minDistSquared);
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace CGAL
|
||||
|
||||
#endif // CGAL_DELAUNAY_TRIANGULATION_SPHERE_TRAITS_2_H
|
||||
|
|
@ -0,0 +1,307 @@
|
|||
// Copyright (c) 1997, 2012, 2019 INRIA Sophia-Antipolis (France).
|
||||
// All rights reserved.
|
||||
//
|
||||
// This file is part of CGAL (www.cgal.org).
|
||||
//
|
||||
// $URL$
|
||||
// $Id$
|
||||
// SPDX-License-Identifier: GPL-3.0-or-later OR LicenseRef-Commercial
|
||||
//
|
||||
// Author(s) : Mael Rouxel-Labbé
|
||||
|
||||
#ifndef CGAL_TRIANGULATION_ON_SPHERE_GEOGRAPHICAL_COORDINATES_TRAITS_2_H
|
||||
#define CGAL_TRIANGULATION_ON_SPHERE_GEOGRAPHICAL_COORDINATES_TRAITS_2_H
|
||||
|
||||
#include <CGAL/license/Triangulation_on_sphere_2.h>
|
||||
|
||||
#include <CGAL/Delaunay_triangulation_on_sphere_traits_2.h>
|
||||
|
||||
#include <CGAL/triangulation_assertions.h>
|
||||
#include <CGAL/number_utils_classes.h>
|
||||
|
||||
#include <cmath>
|
||||
#include <fstream>
|
||||
#include <iostream>
|
||||
|
||||
// @todo
|
||||
// Note: this is currently undocumented because it uses a conversion to
|
||||
// the Cartesian domain R^3 to perform predicates and constructions,
|
||||
// losing the benefit of the exact representation on the way.
|
||||
// It can be useful on its own (especially since it contains code
|
||||
// to handle generic convex domains), but hidden points are possible
|
||||
// and are not handled properly.
|
||||
|
||||
namespace CGAL {
|
||||
|
||||
template <typename LK>
|
||||
struct Geographical_coordinates
|
||||
{
|
||||
typedef typename LK::FT FT;
|
||||
typedef FT Latitude;
|
||||
typedef FT Longitude;
|
||||
|
||||
Geographical_coordinates() : _la(360), _lo(360) { }
|
||||
Geographical_coordinates(const FT la, const FT lo) : _la(la), _lo(lo) { }
|
||||
|
||||
Latitude latitude() const { return _la; }
|
||||
Longitude longitude() const { return _lo; }
|
||||
|
||||
friend std::ostream& operator<<(std::ostream& os, const Geographical_coordinates& l)
|
||||
{
|
||||
os << l._la << " " << l._lo;
|
||||
return os;
|
||||
}
|
||||
|
||||
private:
|
||||
FT _la;
|
||||
FT _lo;
|
||||
};
|
||||
|
||||
namespace internal {
|
||||
|
||||
template <typename LK>
|
||||
struct Construct_geographical_coordinates
|
||||
: public CGAL::cpp98::unary_function<typename LK::Point_3, CGAL::Geographical_coordinates<LK> >
|
||||
{
|
||||
typedef typename LK::FT FT;
|
||||
typedef typename LK::Point_3 Point_3;
|
||||
typedef CGAL::Geographical_coordinates<LK> result_type;
|
||||
|
||||
Construct_geographical_coordinates(const Point_3& center, const FT radius)
|
||||
: _center(center), _radius(radius)
|
||||
{ }
|
||||
|
||||
result_type operator()(const Point_3& pt) const
|
||||
{
|
||||
CGAL_assertion(pt != _center);
|
||||
|
||||
const FT la = 180. * std::asin((pt.z() - _center.z()) / _radius) / CGAL_PI;
|
||||
const FT lo = 180. * std::atan2((pt.y() - _center.y()), (pt.x() - _center.x())) / CGAL_PI;
|
||||
|
||||
return result_type(la, lo);
|
||||
}
|
||||
|
||||
private:
|
||||
const Point_3& _center;
|
||||
const FT _radius;
|
||||
};
|
||||
|
||||
template <typename LK>
|
||||
struct Construct_Cartesian_coordinates
|
||||
: public CGAL::cpp98::unary_function<typename LK::Point_3, CGAL::Geographical_coordinates<LK> >
|
||||
{
|
||||
typedef typename LK::FT FT;
|
||||
typedef typename LK::Point_3 Point_3;
|
||||
typedef CGAL::Geographical_coordinates<LK> Coordinates;
|
||||
|
||||
Construct_Cartesian_coordinates(const Point_3& center, const FT radius)
|
||||
: _center(center), _radius(radius)
|
||||
{ }
|
||||
|
||||
Point_3 operator()(const Coordinates& l) const
|
||||
{
|
||||
#if 1
|
||||
const FT rla = CGAL_PI * l.latitude() / 180.;
|
||||
const FT rlo = CGAL_PI * l.longitude() / 180.;
|
||||
const FT x = _center.x() + _radius * std::cos(rla) * std::cos(rlo);
|
||||
const FT y = _center.y() + _radius * std::cos(rla) * std::sin(rlo);
|
||||
const FT z = _center.z() + _radius * std::sin(rla);
|
||||
#else
|
||||
const FT rla = CGAL_PI * l.latitude() / 180.;
|
||||
const FT rlo = CGAL_PI * l.longitude() / 180.;
|
||||
|
||||
// Quoting wikipedia:
|
||||
// - The Earth's equatorial radius a, or semi-major axis, is the distance from its center
|
||||
// to the equator and equals 6,378.1370 km (3,963.1906 mi)
|
||||
// - The Earth's polar radius b, or semi-minor axis, is the distance from its center to the North
|
||||
// and South Poles, and equals 6,356.7523 km (3,949.9028 mi).
|
||||
const FT equ_radius = 6378.1370;
|
||||
const FT pol_radius = 6356.7523;
|
||||
FT radius_ratio = equ_radius / pol_radius;
|
||||
|
||||
const FT a2 = square(_radius * radius_ratio);
|
||||
const FT b2 = square(_radius);
|
||||
|
||||
// Using https://en.wikipedia.org/wiki/Geographic_coordinate_conversion#From_geodetic_to_ECEF_coordinates
|
||||
const FT N = a2 / sqrt(a2 * square(std::cos(rla)) + b2 * square(std::sin(rla)));
|
||||
const FT h = 0;
|
||||
const FT x = _center.x() + (N + h) * std::cos(rla) * std::cos(rlo);
|
||||
const FT y = _center.y() + (N + h) * std::cos(rla) * std::sin(rlo);
|
||||
const FT z = _center.z() + (b2 * N / a2 + h) * std::sin(rla);
|
||||
#endif
|
||||
|
||||
return Point_3(x, y, z);
|
||||
}
|
||||
|
||||
private:
|
||||
const Point_3& _center;
|
||||
const FT _radius;
|
||||
};
|
||||
|
||||
template <typename LK, typename Base_functor_>
|
||||
struct Construct_circumcenter_on_geo_sphere_2
|
||||
{
|
||||
public:
|
||||
typedef typename LK::FT FT;
|
||||
typedef typename LK::Point_3 Point_3;
|
||||
typedef typename LK::Vector_3 Vector_3;
|
||||
typedef Geographical_coordinates<LK> Point_on_sphere_2;
|
||||
typedef Geographical_coordinates<LK> result_type;
|
||||
|
||||
Construct_circumcenter_on_geo_sphere_2( const Base_functor_ f, const Point_3& center, const FT radius)
|
||||
: _center(center), _radius(radius), _f(f)
|
||||
{ }
|
||||
|
||||
result_type operator()(const Point_on_sphere_2& p, const Point_on_sphere_2& q, const Point_on_sphere_2& r) const
|
||||
{
|
||||
Construct_Cartesian_coordinates<LK> to_P3(_center, _radius);
|
||||
Construct_geographical_coordinates<LK> to_PoS2(_center, _radius);
|
||||
|
||||
return to_PoS2(_f(to_P3(p), to_P3(q), to_P3(r)));
|
||||
}
|
||||
|
||||
private:
|
||||
const Base_functor_ _f;
|
||||
const Point_3& _center;
|
||||
const FT _radius;
|
||||
};
|
||||
|
||||
// Adaptor for calling the functors with the points projected on the sphere
|
||||
template <typename LK, typename Functor_>
|
||||
class Functor_geo_projection_adaptor
|
||||
: public Functor_
|
||||
{
|
||||
typedef Functor_ Functor;
|
||||
typedef Functor_ Base;
|
||||
|
||||
typedef typename LK::FT FT;
|
||||
typedef typename LK::Point_3 Point_3;
|
||||
typedef Geographical_coordinates<LK> Point;
|
||||
|
||||
typedef Construct_Cartesian_coordinates<LK> To_Point_3;
|
||||
|
||||
public:
|
||||
Functor_geo_projection_adaptor(const Functor& f, const Point_3& center, const FT radius)
|
||||
: Base(f), to_p3(center, radius)
|
||||
{ }
|
||||
|
||||
public:
|
||||
using Base::operator();
|
||||
|
||||
decltype(auto) operator()(const Point& p0, const Point& p1)
|
||||
{ return Base::operator()(to_p3(p0), to_p3(p1)); }
|
||||
|
||||
decltype(auto) operator()(const Point& p0, const Point& p1, const Point& p2)
|
||||
{ return Base::operator()(to_p3(p0), to_p3(p1), to_p3(p2)); }
|
||||
|
||||
decltype(auto) operator ()(const Point& p0, const Point& p1, const Point& p2, const Point& p3)
|
||||
{ return Base::operator()(to_p3(p0), to_p3(p1), to_p3(p2), to_p3(p3)); }
|
||||
|
||||
decltype(auto) operator()(const Point& p0, const Point& p1, const Point& p2, const Point& p3, const Point& p4)
|
||||
{ return Base::operator()(to_p3(p0), to_p3(p1), to_p3(p2), to_p3(p3), to_p3(p4)); }
|
||||
|
||||
private:
|
||||
const To_Point_3 to_p3;
|
||||
};
|
||||
|
||||
} // namespace internal
|
||||
|
||||
template <typename LK>
|
||||
class Geographical_coordinates_traits_2
|
||||
: public Delaunay_triangulation_on_sphere_traits_2<LK>
|
||||
{
|
||||
protected:
|
||||
typedef Delaunay_triangulation_on_sphere_traits_2<LK> Base;
|
||||
typedef Geographical_coordinates_traits_2<LK> Self;
|
||||
|
||||
public:
|
||||
typedef typename LK::FT FT;
|
||||
typedef typename LK::Point_3 Point_3;
|
||||
typedef Geographical_coordinates<LK> Point_on_sphere_2;
|
||||
|
||||
// predicates
|
||||
typedef internal::Functor_geo_projection_adaptor<LK, typename Base::Collinear_are_strictly_ordered_on_great_circle_2> Collinear_are_strictly_ordered_on_great_circle_2;
|
||||
typedef internal::Functor_geo_projection_adaptor<LK, typename Base::Compare_on_sphere_2> Compare_on_sphere_2;
|
||||
typedef internal::Functor_geo_projection_adaptor<LK, typename Base::Equal_on_sphere_2> Equal_on_sphere_2;
|
||||
typedef internal::Functor_geo_projection_adaptor<LK, typename Base::Orientation_on_sphere_2> Orientation_on_sphere_2;
|
||||
typedef internal::Functor_geo_projection_adaptor<LK, typename Base::Side_of_oriented_circle_on_sphere_2> Side_of_oriented_circle_on_sphere_2;
|
||||
|
||||
// constructions
|
||||
typedef internal::Construct_geographical_coordinates<LK> Construct_point_on_sphere_2;
|
||||
typedef internal::Construct_Cartesian_coordinates<LK> Construct_point_3;
|
||||
typedef internal::Functor_geo_projection_adaptor<LK, typename Base::Construct_segment_3> Construct_segment_3;
|
||||
typedef internal::Functor_geo_projection_adaptor<LK, typename Base::Construct_triangle_3> Construct_triangle_3;
|
||||
|
||||
typedef internal::Functor_geo_projection_adaptor<LK, typename Base::Construct_arc_on_sphere_2> Construct_arc_on_sphere_2;
|
||||
typedef internal::Construct_circumcenter_on_geo_sphere_2<LK, typename Base::Construct_circumcenter_on_sphere_2> Construct_circumcenter_on_sphere_2;
|
||||
|
||||
public:
|
||||
Geographical_coordinates_traits_2(const Point_3& sphere = CGAL::ORIGIN,
|
||||
const FT radius = 1,
|
||||
const LK& lk = LK())
|
||||
: Base(sphere, radius, lk)
|
||||
{ }
|
||||
|
||||
// predicates
|
||||
public:
|
||||
Collinear_are_strictly_ordered_on_great_circle_2
|
||||
collinear_are_strictly_ordered_on_great_circle_2_object() const
|
||||
{ return Collinear_are_strictly_ordered_on_great_circle_2(
|
||||
Base::collinear_are_strictly_ordered_on_great_circle_2_object(),
|
||||
Base::center(), Base::radius()); }
|
||||
|
||||
Compare_on_sphere_2
|
||||
compare_on_sphere_2_object() const
|
||||
{ return Compare_on_sphere_2(Base::compare_on_sphere_2_object(),
|
||||
Base::center(), Base::radius()); }
|
||||
|
||||
Equal_on_sphere_2
|
||||
equal_on_sphere_2_object() const
|
||||
{ return Equal_on_sphere_2(Base::equal_on_sphere_2_object(),
|
||||
Base::center(), Base::radius()); }
|
||||
|
||||
Orientation_on_sphere_2
|
||||
orientation_on_sphere_2_object() const
|
||||
{ return Orientation_on_sphere_2(Base::orientation_on_sphere_2_object(),
|
||||
Base::center(), Base::radius()); }
|
||||
|
||||
Side_of_oriented_circle_on_sphere_2
|
||||
side_of_oriented_circle_on_sphere_2_object() const
|
||||
{ return Side_of_oriented_circle_on_sphere_2(Base::side_of_oriented_circle_on_sphere_2_object(),
|
||||
Base::center(), Base::radius()); }
|
||||
|
||||
// constructions
|
||||
public:
|
||||
Construct_point_on_sphere_2
|
||||
construct_point_on_sphere_2_object() const
|
||||
{ return Construct_point_on_sphere_2(Base::center(), Base::radius()); }
|
||||
|
||||
Construct_point_3
|
||||
construct_point_3_object() const
|
||||
{ return Construct_point_3(Base::center(), Base::radius()); }
|
||||
|
||||
Construct_arc_on_sphere_2
|
||||
construct_arc_on_sphere_2_object() const
|
||||
{ return Construct_arc_on_sphere_2(Base::construct_arc_on_sphere_2_object(),
|
||||
Base::center(), Base::radius()); }
|
||||
|
||||
Construct_circumcenter_on_sphere_2
|
||||
construct_circumcenter_on_sphere_2_object() const
|
||||
{ return Construct_circumcenter_on_sphere_2(Base::construct_circumcenter_on_sphere_2_object(),
|
||||
Base::center(), Base::radius()); }
|
||||
|
||||
public:
|
||||
bool is_on_sphere(const Point_on_sphere_2& /*p*/) const
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
bool are_points_too_close(const Point_on_sphere_2& p, const Point_on_sphere_2& q) const
|
||||
{
|
||||
return Base::are_points_too_close(construct_point_3_object()(p), construct_point_3_object()(q));
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace CGAL
|
||||
|
||||
#endif // CGAL_TRIANGULATION_ON_SPHERE_GEOGRAPHICAL_COORDINATES_TRAITS_2_H
|
||||
|
|
@ -0,0 +1,236 @@
|
|||
// Copyright (c) 1997, 2012, 2019 INRIA Sophia-Antipolis (France).
|
||||
// All rights reserved.
|
||||
//
|
||||
// This file is part of CGAL (www.cgal.org).
|
||||
//
|
||||
// $URL$
|
||||
// $Id$
|
||||
// SPDX-License-Identifier: GPL-3.0-or-later OR LicenseRef-Commercial
|
||||
//
|
||||
// Author(s) : Mariette Yvinec,
|
||||
// Claudia Werner
|
||||
// Mael Rouxel-Labbé
|
||||
|
||||
#ifndef CGAL_TRIANGULATION_ON_SPHERE_PROJECTION_SPHERE_TRAITS_3_H
|
||||
#define CGAL_TRIANGULATION_ON_SPHERE_PROJECTION_SPHERE_TRAITS_3_H
|
||||
|
||||
#include <CGAL/license/Triangulation_on_sphere_2.h>
|
||||
|
||||
#include <CGAL/Delaunay_triangulation_on_sphere_traits_2.h>
|
||||
|
||||
#include <CGAL/triangulation_assertions.h>
|
||||
#include <CGAL/number_utils_classes.h>
|
||||
|
||||
namespace CGAL {
|
||||
namespace internal {
|
||||
|
||||
template <typename LK>
|
||||
class Point_with_scale
|
||||
: public LK::Point_3
|
||||
{
|
||||
public:
|
||||
typedef typename LK::FT FT;
|
||||
typedef typename LK::Point_3 Base_point;
|
||||
typedef typename LK::Vector_3 Vector_3;
|
||||
|
||||
private:
|
||||
mutable bool cached;
|
||||
mutable Base_point proj_pt;
|
||||
|
||||
public:
|
||||
Point_with_scale() : Base_point() { } // vertex base wants a default constructor
|
||||
Point_with_scale(const Base_point& p) : Base_point(p), cached(false) { }
|
||||
|
||||
const Base_point& get_projection(const Base_point& center,
|
||||
const FT radius,
|
||||
const LK& lk) const
|
||||
{
|
||||
if(!cached)
|
||||
compute_projection(center, radius, lk);
|
||||
|
||||
return proj_pt;
|
||||
}
|
||||
|
||||
const Base_point& get_projection(const Base_point& center,
|
||||
const FT radius) const
|
||||
{
|
||||
return get_projection(center, radius, LK());
|
||||
}
|
||||
|
||||
private:
|
||||
void compute_projection(const Base_point& center,
|
||||
const FT radius,
|
||||
const LK& lk) const
|
||||
{
|
||||
CGAL_precondition(static_cast<const Base_point&>(*this) != center);
|
||||
|
||||
Vector_3 v = lk.construct_vector_3_object()(center, static_cast<const Base_point&>(*this));
|
||||
FT n = lk.compute_squared_length_3_object()(v);
|
||||
CGAL_assertion(n > 0);
|
||||
n = CGAL::sqrt(n);
|
||||
v = lk.construct_scaled_vector_3_object()(v, radius / n);
|
||||
|
||||
proj_pt = lk.construct_translated_point_3_object()(center, v);
|
||||
cached = true;
|
||||
}
|
||||
};
|
||||
|
||||
template <typename P3, typename PoS2>
|
||||
struct Construct_point_with_scale
|
||||
: public CGAL::cpp98::unary_function<P3, PoS2>
|
||||
{
|
||||
PoS2 operator()(const P3& pt) const { return PoS2(pt); }
|
||||
};
|
||||
|
||||
// Adaptor for calling the functors with the points projected on the sphere
|
||||
template <typename LK, typename Functor_>
|
||||
class Functor_projection_adaptor
|
||||
: public Functor_
|
||||
{
|
||||
typedef Functor_ Functor;
|
||||
typedef Functor_ Base;
|
||||
|
||||
typedef typename LK::FT FT;
|
||||
typedef typename LK::Point_3 Point_3;
|
||||
typedef internal::Point_with_scale<LK> Point;
|
||||
|
||||
public:
|
||||
Functor_projection_adaptor(const Functor& f, const Point_3& center, const FT radius)
|
||||
: Base(f), _c(center), _r(radius)
|
||||
{ }
|
||||
|
||||
public:
|
||||
using Base::operator();
|
||||
|
||||
decltype(auto) operator()(const Point& p0, const Point& p1)
|
||||
{
|
||||
return Base::operator()(p0.get_projection(_c, _r), p1.get_projection(_c, _r));
|
||||
}
|
||||
|
||||
decltype(auto) operator()(const Point& p0, const Point& p1, const Point& p2)
|
||||
{
|
||||
return Base::operator()(p0.get_projection(_c, _r), p1.get_projection(_c, _r),
|
||||
p2.get_projection(_c, _r));
|
||||
}
|
||||
|
||||
decltype(auto) operator ()(const Point& p0, const Point& p1, const Point& p2, const Point& p3)
|
||||
{
|
||||
return Base::operator()(p0.get_projection(_c, _r), p1.get_projection(_c, _r),
|
||||
p2.get_projection(_c, _r), p3.get_projection(_c, _r));
|
||||
}
|
||||
|
||||
decltype(auto) operator()(const Point& p0, const Point& p1, const Point& p2,
|
||||
const Point& p3, const Point& p4)
|
||||
{
|
||||
return Base::operator()(p0.get_projection(_c, _r), p1.get_projection(_c, _r),
|
||||
p2.get_projection(_c, _r), p3.get_projection(_c, _r),
|
||||
p4.get_projection(_c, _r));
|
||||
}
|
||||
|
||||
private:
|
||||
const Point_3& _c;
|
||||
const FT _r;
|
||||
};
|
||||
|
||||
} // namespace internal
|
||||
|
||||
template <typename LK>
|
||||
class Projection_on_sphere_traits_3
|
||||
: public Delaunay_triangulation_on_sphere_traits_2<LK>
|
||||
{
|
||||
protected:
|
||||
typedef Delaunay_triangulation_on_sphere_traits_2<LK> Base;
|
||||
typedef Projection_on_sphere_traits_3<LK> Self;
|
||||
|
||||
public:
|
||||
typedef typename LK::FT FT;
|
||||
typedef typename LK::Point_3 Point_3;
|
||||
typedef internal::Point_with_scale<LK> Point_on_sphere_2;
|
||||
|
||||
// predicates
|
||||
typedef internal::Functor_projection_adaptor<LK, typename Base::Collinear_are_strictly_ordered_on_great_circle_2> Collinear_are_strictly_ordered_on_great_circle_2;
|
||||
typedef internal::Functor_projection_adaptor<LK, typename Base::Compare_on_sphere_2> Compare_on_sphere_2;
|
||||
typedef internal::Functor_projection_adaptor<LK, typename Base::Equal_on_sphere_2> Equal_on_sphere_2;
|
||||
typedef internal::Functor_projection_adaptor<LK, typename Base::Orientation_on_sphere_2> Orientation_on_sphere_2;
|
||||
typedef internal::Functor_projection_adaptor<LK, typename Base::Side_of_oriented_circle_on_sphere_2> Side_of_oriented_circle_on_sphere_2;
|
||||
|
||||
// constructions
|
||||
typedef internal::Construct_point_with_scale<Point_3, Point_on_sphere_2> Construct_point_on_sphere_2;
|
||||
typedef internal::Functor_projection_adaptor<LK, typename Base::Construct_point_3> Construct_point_3;
|
||||
typedef internal::Functor_projection_adaptor<LK, typename Base::Construct_segment_3> Construct_segment_3;
|
||||
typedef internal::Functor_projection_adaptor<LK, typename Base::Construct_triangle_3> Construct_triangle_3;
|
||||
|
||||
typedef internal::Functor_projection_adaptor<LK, typename Base::Construct_arc_on_sphere_2> Construct_arc_on_sphere_2;
|
||||
typedef internal::Functor_projection_adaptor<LK, typename Base::Construct_circumcenter_on_sphere_2> Construct_circumcenter_on_sphere_2;
|
||||
|
||||
public:
|
||||
Projection_on_sphere_traits_3(const Point_3& sphere = CGAL::ORIGIN,
|
||||
const FT radius = 1,
|
||||
const LK& lk = LK())
|
||||
: Base(sphere, radius, lk)
|
||||
{ }
|
||||
|
||||
// predicates
|
||||
public:
|
||||
Collinear_are_strictly_ordered_on_great_circle_2
|
||||
collinear_are_strictly_ordered_on_great_circle_2_object() const
|
||||
{ return Collinear_are_strictly_ordered_on_great_circle_2(
|
||||
Base::collinear_are_strictly_ordered_on_great_circle_2_object(),
|
||||
Base::center(), Base::radius()); }
|
||||
|
||||
Compare_on_sphere_2
|
||||
compare_on_sphere_2_object() const
|
||||
{ return Compare_on_sphere_2(Base::compare_on_sphere_2_object(),
|
||||
Base::center(), Base::radius()); }
|
||||
|
||||
Equal_on_sphere_2
|
||||
equal_on_sphere_2_object() const
|
||||
{ return Equal_on_sphere_2(Base::equal_on_sphere_2_object(),
|
||||
Base::center(), Base::radius()); }
|
||||
|
||||
Orientation_on_sphere_2
|
||||
orientation_on_sphere_2_object() const
|
||||
{ return Orientation_on_sphere_2(Base::orientation_on_sphere_2_object(),
|
||||
Base::center(), Base::radius()); }
|
||||
|
||||
Side_of_oriented_circle_on_sphere_2
|
||||
side_of_oriented_circle_on_sphere_2_object() const
|
||||
{ return Side_of_oriented_circle_on_sphere_2(Base::side_of_oriented_circle_on_sphere_2_object(),
|
||||
Base::center(), Base::radius()); }
|
||||
|
||||
// constructions
|
||||
public:
|
||||
Construct_point_on_sphere_2
|
||||
construct_point_on_sphere_2_object() const
|
||||
{ return Construct_point_on_sphere_2(); }
|
||||
|
||||
Construct_arc_on_sphere_2
|
||||
construct_arc_on_sphere_2_object() const
|
||||
{ return Construct_arc_on_sphere_2(Base::construct_arc_on_sphere_2_object(),
|
||||
Base::center(), Base::radius()); }
|
||||
|
||||
Construct_circumcenter_on_sphere_2
|
||||
construct_circumcenter_on_sphere_2_object() const
|
||||
{ return Construct_circumcenter_on_sphere_2(Base::construct_circumcenter_on_sphere_2_object(),
|
||||
Base::center(), Base::radius()); }
|
||||
|
||||
Construct_point_3
|
||||
construct_point_3_object() const
|
||||
{ return Construct_point_3(Base::construct_point_3_object(), Base::center(), Base::radius()); }
|
||||
|
||||
public:
|
||||
bool is_on_sphere(const Point_on_sphere_2& /*p*/) const
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
bool are_points_too_close(const Point_on_sphere_2& p, const Point_on_sphere_2& q) const
|
||||
{
|
||||
return Base::are_points_too_close(p.get_projection(Base::center(), Base::radius(), Base::lk()),
|
||||
q.get_projection(Base::center(), Base::radius(), Base::lk()));
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace CGAL
|
||||
|
||||
#endif // CGAL_TRIANGULATION_ON_SPHERE_PROJECTION_SPHERE_TRAITS_3_H
|
||||
File diff suppressed because it is too large
Load Diff
|
|
@ -0,0 +1,192 @@
|
|||
// Copyright (c) 1997-2021 INRIA Sophia-Antipolis (France).
|
||||
// All rights reserved.
|
||||
//
|
||||
// This file is part of CGAL (www.cgal.org)
|
||||
//
|
||||
// $URL$
|
||||
// $Id$
|
||||
// SPDX-License-Identifier: GPL-3.0-or-later OR LicenseRef-Commercial
|
||||
//
|
||||
// Author(s) : Mael Rouxel-Labbé
|
||||
|
||||
#ifndef CGAL_TOS2_IO_OFF_H
|
||||
#define CGAL_TOS2_IO_OFF_H
|
||||
|
||||
#include <CGAL/license/Triangulation_on_sphere_2.h>
|
||||
|
||||
#include <CGAL/triangulation_assertions.h>
|
||||
|
||||
#include <CGAL/boost/graph/Named_function_parameters.h>
|
||||
#include <CGAL/boost/graph/named_params_helper.h>
|
||||
#include <CGAL/IO/helpers.h>
|
||||
|
||||
#include <fstream>
|
||||
#include <string>
|
||||
#include <unordered_map>
|
||||
|
||||
#ifdef DOXYGEN_RUNNING
|
||||
#define CGAL_BGL_NP_TEMPLATE_PARAMETERS NamedParameters
|
||||
#define CGAL_BGL_NP_CLASS NamedParameters
|
||||
#define CGAL_DEPRECATED
|
||||
#endif
|
||||
|
||||
namespace CGAL {
|
||||
|
||||
template <typename Gt, typename Tds>
|
||||
class Triangulation_on_sphere_2;
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// Read
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// Write
|
||||
|
||||
/*!
|
||||
\ingroup PkgPointSet3IOOFF
|
||||
|
||||
\brief writes the content of a triangulation on the sphere into an output stream in the \ref IOStreamOFF.
|
||||
|
||||
\tparam Gt the geometric traits type of the triangulation
|
||||
\tparam Tds the triangulation data structure type of the triangulation
|
||||
\tparam NamedParameters a sequence of \ref bgl_namedparameters "Named Parameters"
|
||||
|
||||
\param os the output stream
|
||||
\param dt the triangulation
|
||||
\param np an optional sequence of \ref bgl_namedparameters "Named Parameters" among the ones listed below
|
||||
|
||||
\cgalNamedParamsBegin
|
||||
\cgalParamNBegin{stream_precision}
|
||||
\cgalParamDescription{a parameter used to set the precision (i.e., how many digits are generated) of the output stream}
|
||||
\cgalParamType{int}
|
||||
\cgalParamDefault{the precision of the stream `os`}
|
||||
\cgalParamNEnd
|
||||
\cgalNamedParamsEnd
|
||||
|
||||
\return `true` if the writing was successful, `false` otherwise.
|
||||
*/
|
||||
template <typename Gt, typename Tds, typename CGAL_BGL_NP_TEMPLATE_PARAMETERS>
|
||||
bool write_OFF(std::ostream& os,
|
||||
const CGAL::Triangulation_on_sphere_2<Gt, Tds>& dt,
|
||||
const CGAL_BGL_NP_CLASS& np)
|
||||
{
|
||||
typedef Triangulation_on_sphere_2<Gt,Tds> Tr;
|
||||
typedef typename Tr::Vertex_handle Vertex_handle;
|
||||
typedef typename Tr::Vertices_iterator Vertex_iterator;
|
||||
typedef typename Tr::All_faces_iterator Face_iterator;
|
||||
typedef typename Tr::size_type size_type;
|
||||
|
||||
set_stream_precision_from_NP(os, np);
|
||||
|
||||
const bool use_colors = parameters::choose_parameter(parameters::get_parameter(np, internal_np::output_color), true);
|
||||
|
||||
typename Gt::Construct_point_3 cp3 = dt.geom_traits().construct_point_3_object();
|
||||
|
||||
const size_type n = dt.number_of_vertices();
|
||||
|
||||
std::stringstream output;
|
||||
set_stream_precision_from_NP(output, np);
|
||||
|
||||
// write the vertices
|
||||
std::unordered_map<Vertex_handle, size_type> index_of_vertex;
|
||||
size_type i = 0;
|
||||
for(Vertex_iterator it = dt.vertices_begin(); it != dt.vertices_end(); ++it, ++i)
|
||||
{
|
||||
Vertex_handle vh = it;
|
||||
output << cp3(vh->point()) << " 0 0 0 \n"; // '0 0 0' for colors
|
||||
index_of_vertex[vh] = i;
|
||||
}
|
||||
|
||||
CGAL_triangulation_assertion(i == n);
|
||||
|
||||
size_type number_of_triangles = 0;
|
||||
for(Face_iterator fit = dt.all_faces_begin() ; fit != dt.all_faces_end() ; ++fit)
|
||||
{
|
||||
output << "3 "
|
||||
<< index_of_vertex[fit->vertex(0)] << " "
|
||||
<< index_of_vertex[fit->vertex(1)] << " "
|
||||
<< index_of_vertex[fit->vertex(2)];
|
||||
if(use_colors)
|
||||
{
|
||||
if(fit->is_ghost())
|
||||
output << " 229 117 0\n";
|
||||
else
|
||||
output << " 0 117 229\n";
|
||||
}
|
||||
else
|
||||
{
|
||||
output << "\n";
|
||||
}
|
||||
|
||||
++number_of_triangles;
|
||||
}
|
||||
|
||||
if(use_colors)
|
||||
os << "COFF \n";
|
||||
else
|
||||
os << "OFF \n";
|
||||
|
||||
os << n << " "
|
||||
<< number_of_triangles << " 0\n"
|
||||
<< output.str();
|
||||
|
||||
return !os.fail();
|
||||
}
|
||||
|
||||
/// \cond SKIP_IN_MANUAL
|
||||
|
||||
template <typename Gt, typename Tds>
|
||||
bool write_OFF(std::ostream& os, const CGAL::Triangulation_on_sphere_2<Gt, Tds>& dt)
|
||||
{
|
||||
return write_OFF(os, dt, parameters::all_default());
|
||||
}
|
||||
|
||||
/// \endcond
|
||||
|
||||
/*!
|
||||
\ingroup PkgPointSet3IOOFF
|
||||
|
||||
\brief writes the content of a triangulation on the sphere into an output file in the \ref IOStreamOFF.
|
||||
|
||||
\tparam Gt the geometric traits type of the triangulation
|
||||
\tparam Tds the triangulation data structure type of the triangulation
|
||||
\tparam NamedParameters a sequence of \ref bgl_namedparameters "Named Parameters"
|
||||
|
||||
\param fname the path to the output file
|
||||
\param point_set the point set
|
||||
\param np an optional sequence of \ref bgl_namedparameters "Named Parameters" among the ones listed below
|
||||
|
||||
\cgalNamedParamsBegin
|
||||
\cgalParamNBegin{stream_precision}
|
||||
\cgalParamDescription{a parameter used to set the precision (i.e., how many digits are generated) of the output stream}
|
||||
\cgalParamType{int}
|
||||
\cgalParamDefault{`6`}
|
||||
\cgalParamNEnd
|
||||
\cgalNamedParamsEnd
|
||||
|
||||
\return `true` if the writing was successful, `false` otherwise.
|
||||
*/
|
||||
template <typename Gt, typename Tds, typename CGAL_BGL_NP_TEMPLATE_PARAMETERS>
|
||||
bool write_OFF(const std::string& fname,
|
||||
const CGAL::Triangulation_on_sphere_2<Gt, Tds>& dt,
|
||||
const CGAL_BGL_NP_CLASS& np)
|
||||
{
|
||||
std::ofstream os(fname); // stream precision will be set in the ostream overload
|
||||
return write_OFF(os, dt, np);
|
||||
}
|
||||
|
||||
/// \cond SKIP_IN_MANUAL
|
||||
|
||||
template <typename Gt, typename Tds>
|
||||
bool write_OFF(const std::string& fname, const CGAL::Triangulation_on_sphere_2<Gt, Tds>& dt)
|
||||
{
|
||||
std::ofstream os(fname);
|
||||
return write_OFF(os, dt, parameters::all_default());
|
||||
}
|
||||
|
||||
/// \endcond
|
||||
|
||||
} // namespace CGAL
|
||||
|
||||
#endif // CGAL_TOS2_IO_OFF_H
|
||||
|
|
@ -0,0 +1,159 @@
|
|||
// Copyright (c) 1997-2021 INRIA Sophia-Antipolis (France).
|
||||
// All rights reserved.
|
||||
//
|
||||
// This file is part of CGAL (www.cgal.org).
|
||||
//
|
||||
// $URL$
|
||||
// $Id$
|
||||
// SPDX-License-Identifier: GPL-3.0-or-later OR LicenseRef-Commercial
|
||||
//
|
||||
// Author(s) : Sébastien Loriot
|
||||
// Mael Rouxel-Labbé
|
||||
//
|
||||
#ifndef CGAL_TOS2_INTERNAL_ARC_ON_SPHERE_SUBSAMPLING_H
|
||||
#define CGAL_TOS2_INTERNAL_ARC_ON_SPHERE_SUBSAMPLING_H
|
||||
|
||||
#include <CGAL/license/Triangulation_on_sphere_2.h>
|
||||
|
||||
#ifdef CGAL_EIGEN3_ENABLED
|
||||
|
||||
#include <CGAL/Eigen_solver_traits.h>
|
||||
|
||||
#include <cmath>
|
||||
#include <list>
|
||||
|
||||
namespace CGAL {
|
||||
namespace Triangulations_on_sphere_2 {
|
||||
namespace internal {
|
||||
|
||||
template <class Kernel>
|
||||
double get_theta( typename Kernel::Point_3& pt,
|
||||
typename Kernel::Vector_3& V1,
|
||||
typename Kernel::Vector_3& V2,
|
||||
typename Kernel::Vector_3& V3)
|
||||
{
|
||||
typedef typename Kernel::FT FT;
|
||||
|
||||
typedef Eigen::Matrix<FT, 3, 3, Eigen::DontAlign> Matrix;
|
||||
typedef Eigen::Matrix<FT, 3, 1> Col;
|
||||
|
||||
auto V1c = V1.cartesian_begin(), V2c = V2.cartesian_begin(), V3c = V3.cartesian_begin();
|
||||
|
||||
Matrix M;
|
||||
M(0, 0) = *V1c++; M(0, 1) = *V2c++; M(0, 2) = *V3c++;
|
||||
M(1, 0) = *V1c++; M(1, 1) = *V2c++; M(1, 2) = *V3c++;
|
||||
M(2, 0) = *V1c++; M(2, 1) = *V2c++; M(2, 2) = *V3c++;
|
||||
|
||||
Col pt_in_vect;
|
||||
auto ptc = pt.cartesian_begin();
|
||||
pt_in_vect(0) = *ptc++; pt_in_vect(1) = *ptc++; pt_in_vect(2) = *ptc++;
|
||||
|
||||
Matrix inverse = M.inverse();
|
||||
FT X = inverse.row(0) * pt_in_vect;
|
||||
FT Y = inverse.row(1) * pt_in_vect;
|
||||
|
||||
double angle = atan2(Y*sqrt(V2.squared_length()), X*sqrt(V1.squared_length()));
|
||||
|
||||
return angle;
|
||||
}
|
||||
|
||||
template <class Kernel>
|
||||
inline typename Kernel::Point_3 compute_point(const typename Kernel::Point_3& center,
|
||||
double radius,
|
||||
double theta,
|
||||
const typename Kernel::Vector_3& b1,
|
||||
const typename Kernel::Vector_3& b2)
|
||||
{
|
||||
return center +
|
||||
radius * cos(theta) * b1 / sqrt(b1.squared_length()) +
|
||||
radius * sin(theta) * b2 / sqrt(b2.squared_length());
|
||||
}
|
||||
|
||||
template <class Kernel, class Output_iterator>
|
||||
void subsample_arc_on_sphere_2(const typename Kernel::Circle_3& circle,
|
||||
double source,
|
||||
double target,
|
||||
const typename Kernel::Vector_3& b1,
|
||||
const typename Kernel::Vector_3& b2,
|
||||
Output_iterator out_pts,
|
||||
double min_edge_size)
|
||||
{
|
||||
if(source > target)
|
||||
target += 2*CGAL_PI;
|
||||
|
||||
CGAL_triangulation_assertion(target > source);
|
||||
|
||||
const double radius = sqrt(circle.squared_radius());
|
||||
const double edge_len = (target - source) * radius;
|
||||
const int nb_of_segments = static_cast<int>(floor(edge_len / min_edge_size));
|
||||
|
||||
*out_pts++ = compute_point<Kernel>(circle.center(), radius, source, b1, b2);
|
||||
const double step_size = (target - source) / static_cast<double>(nb_of_segments);
|
||||
double current_theta = source;
|
||||
for(int i=0; i<nb_of_segments-1; ++i)
|
||||
{
|
||||
current_theta += step_size;
|
||||
CGAL_triangulation_assertion(current_theta <= target);
|
||||
*out_pts++ = compute_point<Kernel>(circle.center(), radius, current_theta, b1, b2);
|
||||
}
|
||||
*out_pts++ = compute_point<Kernel>(circle.center(), radius, target, b1, b2);
|
||||
}
|
||||
|
||||
//Subsample from source to target seen ccw from the side of plane pointed by its orthogonal_vector()
|
||||
template <class Kernel,class Output_iterator>
|
||||
void subsample_circle_3(const typename Kernel::Circle_3& circle,
|
||||
Output_iterator out_pts,
|
||||
double min_edge_size)
|
||||
{
|
||||
typename Kernel::Vector_3 b1 = circle.supporting_plane().base1();
|
||||
typename Kernel::Vector_3 b2 = circle.supporting_plane().base2();
|
||||
|
||||
subsample_arc_on_sphere_2<Kernel>(circle, 0, 2*CGAL_PI, b1, b2, out_pts, min_edge_size);
|
||||
}
|
||||
|
||||
//Subsample from source to target seen ccw from the side of plane pointed by its orthogonal_vector()
|
||||
template <class Kernel,class Output_iterator>
|
||||
void subsample_arc_on_sphere_2(const typename Kernel::Circle_3& circle,
|
||||
const typename Kernel::Plane_3& plane,
|
||||
const typename Kernel::Circular_arc_point_3& source,
|
||||
const typename Kernel::Circular_arc_point_3& target,
|
||||
Output_iterator out_pts,
|
||||
double min_edge_size)
|
||||
{
|
||||
typename Kernel::Vector_3 b1 = plane.base1();
|
||||
typename Kernel::Vector_3 b2 = plane.base2();
|
||||
typename Kernel::Vector_3 b3 = plane.orthogonal_vector();
|
||||
|
||||
typename Kernel::Point_3 tmp = typename Kernel::Point_3(source.x() - circle.center().x(),
|
||||
source.y() - circle.center().y(),
|
||||
source.z() - circle.center().z());
|
||||
const double theta_source = get_theta<Kernel>(tmp, b1, b2, b3);
|
||||
|
||||
tmp = typename Kernel::Point_3(target.x() - circle.center().x(),
|
||||
target.y() - circle.center().y(),
|
||||
target.z() - circle.center().z());
|
||||
const double theta_target = get_theta<Kernel>(tmp, b1, b2, b3);
|
||||
|
||||
subsample_arc_on_sphere_2<Kernel>(circle, theta_source, theta_target, b1, b2, out_pts, min_edge_size);
|
||||
}
|
||||
|
||||
template <class Kernel, class ArcOnSphere, class Output_iterator>
|
||||
void subsample_arc_on_sphere_2(const ArcOnSphere& arc,
|
||||
Output_iterator out_pts,
|
||||
double min_edge_size = 0.01)
|
||||
{
|
||||
subsample_arc_on_sphere_2<Kernel>(arc.supporting_circle(),
|
||||
arc.supporting_circle().supporting_plane(),
|
||||
arc.source(),
|
||||
arc.target(),
|
||||
out_pts,
|
||||
min_edge_size);
|
||||
}
|
||||
|
||||
} // namespace internal
|
||||
} // namespace Triangulations_on_sphere_2
|
||||
} // namespace CGAL
|
||||
|
||||
#endif // CGAL_EIGEN3_ENABLED
|
||||
|
||||
#endif // CGAL_TOS2_INTERNAL_ARC_ON_SPHERE_SUBSAMPLING_H
|
||||
|
|
@ -0,0 +1,76 @@
|
|||
// Copyright (c) 1997-2021 INRIA Sophia-Antipolis (France).
|
||||
// All rights reserved.
|
||||
//
|
||||
// This file is part of CGAL (www.cgal.org).
|
||||
//
|
||||
// $URL$
|
||||
// $Id$
|
||||
// SPDX-License-Identifier: GPL-3.0-or-later OR LicenseRef-Commercial
|
||||
//
|
||||
// Author(s) : Mael Rouxel-Labbé
|
||||
// Sébastien Loriot
|
||||
|
||||
#ifndef CGAL_TRIANGULATION_ON_SPHERE_GET_PRECISION_BOUNDS_H
|
||||
#define CGAL_TRIANGULATION_ON_SPHERE_GET_PRECISION_BOUNDS_H
|
||||
|
||||
#include <CGAL/license/Triangulation_on_sphere_2.h>
|
||||
|
||||
#include <CGAL/double.h>
|
||||
#include <CGAL/Algebraic_structure_traits.h>
|
||||
#include <CGAL/number_utils.h>
|
||||
|
||||
#include <type_traits>
|
||||
|
||||
namespace CGAL {
|
||||
namespace Triangulations_on_sphere_2 {
|
||||
namespace internal {
|
||||
|
||||
// @todo could do something more suble than requiring exact SQRT representation (Root_of_2 etc.)
|
||||
template <typename FT,
|
||||
bool has_exact_rep =
|
||||
is_same_or_derived<
|
||||
Field_with_sqrt_tag,
|
||||
typename Algebraic_structure_traits<FT>::Algebraic_category>::value &&
|
||||
!std::is_floating_point<FT>::value>
|
||||
struct ToS2_precision_bound
|
||||
{
|
||||
ToS2_precision_bound(const FT /*radius*/) { }
|
||||
|
||||
// If you get a link error here, your number type is not supported and needs to implement its own specific values.
|
||||
// See the manual of the package for more information: https://doc.cgal.org/latest/Triangulation_on_sphere_2/
|
||||
FT get_squared_min_dist() const;
|
||||
FT get_squared_min_radius() const;
|
||||
FT get_squared_max_radius() const;
|
||||
};
|
||||
|
||||
template <typename FT>
|
||||
struct ToS2_precision_bound<FT, true> // exact representation of points on the sphere
|
||||
{
|
||||
ToS2_precision_bound(const FT radius) : _sq_radius(CGAL::square(radius)) { }
|
||||
|
||||
FT get_squared_min_dist() const { return 0; }
|
||||
FT get_squared_min_radius() const { return _sq_radius; }
|
||||
FT get_squared_max_radius() const { return _sq_radius; }
|
||||
|
||||
private:
|
||||
FT _sq_radius;
|
||||
};
|
||||
|
||||
template <>
|
||||
struct ToS2_precision_bound<double, false>
|
||||
{
|
||||
ToS2_precision_bound(const double radius) : _radius(radius) { }
|
||||
|
||||
double get_squared_min_dist() const { return CGAL::square(_radius * std::pow(2, -23)); }
|
||||
double get_squared_min_radius() const { return CGAL::square(_radius * (1 - std::pow(2, -50))); }
|
||||
double get_squared_max_radius() const { return CGAL::square(_radius * (1 + std::pow(2, -50))); }
|
||||
|
||||
private:
|
||||
double _radius;
|
||||
};
|
||||
|
||||
} // namespace internal
|
||||
} // namespace Triangulations_on_sphere_2
|
||||
} // namespace CGAL
|
||||
|
||||
#endif // CGAL_TRIANGULATION_ON_SPHERE_GET_PRECISION_BOUNDS_H
|
||||
|
|
@ -0,0 +1,69 @@
|
|||
// Copyright (c) 1997, 2012, 2019 INRIA Sophia-Antipolis (France).
|
||||
// All rights reserved.
|
||||
//
|
||||
// This file is part of CGAL (www.cgal.org).
|
||||
//
|
||||
// $URL$
|
||||
// $Id$
|
||||
// SPDX-License-Identifier: GPL-3.0-or-later OR LicenseRef-Commercial
|
||||
//
|
||||
// Author(s) : Mariette Yvinec,
|
||||
// Claudia Werner
|
||||
// Mael Rouxel-Labbé
|
||||
|
||||
#ifndef CGAL_TRIANGULATION_ON_SPHERE_FACE_BASE_2_H
|
||||
#define CGAL_TRIANGULATION_ON_SPHERE_FACE_BASE_2_H
|
||||
|
||||
#include <CGAL/license/Triangulation_on_sphere_2.h>
|
||||
|
||||
#include <CGAL/Triangulation_ds_face_base_2.h>
|
||||
|
||||
namespace CGAL {
|
||||
|
||||
template <typename Gt,
|
||||
typename Fb = Triangulation_ds_face_base_2<> >
|
||||
class Triangulation_on_sphere_face_base_2
|
||||
: public Fb
|
||||
{
|
||||
public:
|
||||
typedef Gt Geom_traits;
|
||||
typedef typename Fb::Vertex_handle Vertex_handle;
|
||||
typedef typename Fb::Face_handle Face_handle;
|
||||
|
||||
template < typename TDS2 >
|
||||
struct Rebind_TDS {
|
||||
typedef typename Fb::template Rebind_TDS<TDS2>::Other Fb2;
|
||||
typedef Triangulation_on_sphere_face_base_2<Gt, Fb2> Other;
|
||||
};
|
||||
|
||||
public:
|
||||
void set_ghost(const bool b) { _ghost_flag = b; }
|
||||
bool is_ghost() const { return _ghost_flag; }
|
||||
|
||||
public:
|
||||
Triangulation_on_sphere_face_base_2()
|
||||
: Fb(), _ghost_flag(false)
|
||||
{ }
|
||||
|
||||
Triangulation_on_sphere_face_base_2(Vertex_handle v0,
|
||||
Vertex_handle v1,
|
||||
Vertex_handle v2)
|
||||
: Fb(v0, v1, v2), _ghost_flag(false)
|
||||
{ }
|
||||
|
||||
Triangulation_on_sphere_face_base_2(Vertex_handle v0,
|
||||
Vertex_handle v1,
|
||||
Vertex_handle v2,
|
||||
Face_handle n0,
|
||||
Face_handle n1,
|
||||
Face_handle n2)
|
||||
: Fb(v0, v1, v2, n0, n1, n2), _ghost_flag(false)
|
||||
{ }
|
||||
|
||||
protected:
|
||||
bool _ghost_flag;
|
||||
};
|
||||
|
||||
} // namespace CGAL
|
||||
|
||||
#endif //CGAL_TRIANGULATION_ON_SPHERE_FACE_BASE_2_H
|
||||
|
|
@ -0,0 +1,80 @@
|
|||
// Copyright (c) 1997 INRIA Sophia-Antipolis (France).
|
||||
// All rights reserved.
|
||||
//
|
||||
// This file is part of CGAL (www.cgal.org).
|
||||
//
|
||||
// $URL$
|
||||
// $Id$
|
||||
// SPDX-License-Identifier: GPL-3.0-or-later OR LicenseRef-Commercial
|
||||
//
|
||||
//
|
||||
// Author(s) : Mariette Yvinec
|
||||
|
||||
#ifndef CGAL_TRIANGULATION_ON_SPHERE_VERTEX_BASE_2_H
|
||||
#define CGAL_TRIANGULATION_ON_SPHERE_VERTEX_BASE_2_H
|
||||
|
||||
#include <CGAL/license/Triangulation_on_sphere_2.h>
|
||||
|
||||
#include <CGAL/Triangulation_ds_vertex_base_2.h>
|
||||
|
||||
namespace CGAL {
|
||||
|
||||
template <typename GT,
|
||||
typename Vb = Triangulation_ds_vertex_base_2<> >
|
||||
class Triangulation_on_sphere_vertex_base_2
|
||||
: public Vb
|
||||
{
|
||||
typedef typename Vb::Triangulation_data_structure Tds;
|
||||
public:
|
||||
typedef GT Geom_traits;
|
||||
typedef typename GT::Point_on_sphere_2 Point;
|
||||
typedef Tds Triangulation_data_structure;
|
||||
typedef typename Tds::Face_handle Face_handle;
|
||||
typedef typename Tds::Vertex_handle Vertex_handle;
|
||||
|
||||
template < typename TDS2 >
|
||||
struct Rebind_TDS {
|
||||
typedef typename Vb::template Rebind_TDS<TDS2>::Other Vb2;
|
||||
typedef Triangulation_on_sphere_vertex_base_2<GT, Vb2> Other;
|
||||
};
|
||||
|
||||
private:
|
||||
Point _p;
|
||||
|
||||
public:
|
||||
Triangulation_on_sphere_vertex_base_2 () : Vb(), _p() { }
|
||||
Triangulation_on_sphere_vertex_base_2(const Point & p) : Vb(), _p(p) { }
|
||||
Triangulation_on_sphere_vertex_base_2(const Point & p, Face_handle f) : Vb(f), _p(p) { }
|
||||
Triangulation_on_sphere_vertex_base_2(Face_handle f) : Vb(f) { }
|
||||
|
||||
void set_point(const Point & p) { _p = p; }
|
||||
const Point& point() const { return _p; }
|
||||
|
||||
// the non-const version of point() is undocument but needed to make the point iterator works
|
||||
// using Lutz projection scheme
|
||||
Point& point() { return _p; }
|
||||
|
||||
// the following trivial is_valid to allow the user of derived face base classes
|
||||
// to add their own purpose checking
|
||||
bool is_valid(bool /* verbose */ = false, int /* level */ = 0) const {return true;}
|
||||
};
|
||||
|
||||
template < class GT, class Vb >
|
||||
std::istream&
|
||||
operator>>(std::istream &is, Triangulation_on_sphere_vertex_base_2<GT, Vb> &v)
|
||||
{
|
||||
// non combinatorial information. Default = point
|
||||
return is >> static_cast<Vb&>(v) >> v.point();
|
||||
}
|
||||
|
||||
template < class GT, class Vb >
|
||||
std::ostream&
|
||||
operator<<(std::ostream &os, const Triangulation_on_sphere_vertex_base_2<GT, Vb> &v)
|
||||
{
|
||||
// non combinatorial information. Default = point
|
||||
return os << static_cast<const Vb&>(v) << v.point();
|
||||
}
|
||||
|
||||
} // namespace CGAL
|
||||
|
||||
#endif //CGAL_TRIANGULATION_ON_SPHERE_VERTEX_BASE_2_H
|
||||
|
|
@ -0,0 +1,365 @@
|
|||
// Copyright (c) 1997, 2O12, 2019 INRIA Sophia-Antipolis (France).
|
||||
// All rights reserved.
|
||||
//
|
||||
// This file is part of CGAL (www.cgal.org).
|
||||
//
|
||||
// $URL$
|
||||
// $Id$
|
||||
// SPDX-License-Identifier: GPL-3.0-or-later OR LicenseRef-Commercial
|
||||
//
|
||||
// Author(s) : Claudia Werner, Mariette Yvinec
|
||||
|
||||
#ifndef CGAL_TRIANGULATION_SPHERE_LINE_FACE_CIRCULATOR_2_H
|
||||
#define CGAL_TRIANGULATION_SPHERE_LINE_FACE_CIRCULATOR_2_H
|
||||
|
||||
#include <CGAL/license/Triangulation_on_sphere_2.h>
|
||||
|
||||
#include <CGAL/triangulation_assertions.h>
|
||||
|
||||
namespace CGAL {
|
||||
|
||||
template <class Triangulation_>
|
||||
class Triangulation_sphere_line_face_circulator_2
|
||||
: public Bidirectional_circulator_base<typename Triangulation_::Triangulation_data_structure::Face,
|
||||
std::size_t>,
|
||||
public Triangulation_cw_ccw_2
|
||||
{
|
||||
public:
|
||||
typedef Triangulation_sphere_line_face_circulator_2<Triangulation_> Line_face_circulator;
|
||||
typedef Triangulation_ Triangulation;
|
||||
|
||||
typedef typename Triangulation::Geom_traits Gt;
|
||||
typedef typename Triangulation_::Triangulation_data_structure Tds;
|
||||
|
||||
typedef typename Tds::Vertex Vertex;
|
||||
typedef typename Tds::Edge Edge;
|
||||
typedef typename Tds::Face Face;
|
||||
typedef typename Tds::Vertex_handle Vertex_handle;
|
||||
typedef typename Tds::Face_handle Face_handle;
|
||||
typedef typename Tds::Face_circulator Face_circulator;
|
||||
|
||||
typedef typename Gt::Point_2 Point;
|
||||
typedef typename Triangulation::Locate_type Locate_type;
|
||||
|
||||
enum State {undefined = -1,
|
||||
vertex_vertex,
|
||||
vertex_edge,
|
||||
edge_vertex,
|
||||
edge_edge};
|
||||
|
||||
private:
|
||||
Face_handle pos;
|
||||
const Triangulation* _tr;
|
||||
State s;
|
||||
int i;
|
||||
Point p, q;
|
||||
|
||||
public:
|
||||
Triangulation_sphere_line_face_circulator_2()
|
||||
: pos(), _tr(NULL), s(undefined), i(-1)
|
||||
{ }
|
||||
|
||||
Triangulation_sphere_line_face_circulator_2(Vertex_handle v,
|
||||
const Triangulation* tr,
|
||||
const Point& dir);
|
||||
|
||||
Line_face_circulator& operator++();
|
||||
Line_face_circulator& operator--();
|
||||
Line_face_circulator operator++(int);
|
||||
Line_face_circulator operator--(int);
|
||||
Face* operator->() { return &*pos; }
|
||||
Face& operator*() { return *pos; }
|
||||
Face_handle handle() { return pos; }
|
||||
|
||||
operator const Face_handle() const { return pos; }
|
||||
bool operator==(const Line_face_circulator& lfc) const;
|
||||
bool operator!=(const Line_face_circulator& lfc) const;
|
||||
|
||||
bool operator==(const Face_handle& fh) const { return fh == pos; }
|
||||
bool operator!=(const Face_handle& fh) const { return fh != pos; }
|
||||
|
||||
bool operator==(Nullptr_t CGAL_assertion_code(n)) const;
|
||||
bool operator!=(Nullptr_t n) const;
|
||||
bool is_empty() const;
|
||||
bool locate(const Point& t, Locate_type <, int &li);
|
||||
|
||||
//private:
|
||||
Triangulation_sphere_line_face_circulator_2(const Face_handle& face,
|
||||
int index,
|
||||
State state,
|
||||
const Triangulation * t,
|
||||
const Point& pp,
|
||||
const Point& qq);
|
||||
private:
|
||||
void increment();
|
||||
void decrement();
|
||||
};
|
||||
|
||||
template <typename Triangulation>
|
||||
inline
|
||||
bool
|
||||
operator==(typename Triangulation::Triangulation_data_structure::Face_handle fh,
|
||||
Triangulation_sphere_line_face_circulator_2<Triangulation> fc)
|
||||
{
|
||||
return (fc == fh);
|
||||
}
|
||||
|
||||
template <typename Triangulation>
|
||||
inline
|
||||
bool
|
||||
operator!=(typename Triangulation::Triangulation_data_structure::Face_handle fh,
|
||||
Triangulation_sphere_line_face_circulator_2<Triangulation> fc)
|
||||
{
|
||||
return (fc != fh);
|
||||
}
|
||||
|
||||
template <typename Triangulation>
|
||||
Triangulation_sphere_line_face_circulator_2<Triangulation>::
|
||||
Triangulation_sphere_line_face_circulator_2(Vertex_handle v,
|
||||
const Triangulation* tr,
|
||||
const Point& dir)
|
||||
: pos(), _tr(tr), s(undefined)
|
||||
// begin at the face incident to v, traversed by the ray from v to dir
|
||||
// or null iterator
|
||||
{
|
||||
CGAL_precondition((_tr->dimension() == 2) &&
|
||||
(! _tr->xy_equal(v->point(), dir)));
|
||||
p = v->point();
|
||||
q = dir;
|
||||
|
||||
// find a vertex to the left of pq
|
||||
// if there is no, the line_face_circulator is null
|
||||
Face_circulator fc = _tr->incident_faces(v);
|
||||
Face_circulator done(fc);
|
||||
int ic = fc->index(v);
|
||||
Vertex_handle vt = fc->vertex(cw(ic));
|
||||
//Orientation o = _tr->orientation(p, q, vt->point());
|
||||
while( _tr->orientation(p, q, vt->point()) != LEFT_TURN)
|
||||
{
|
||||
++fc;
|
||||
ic = fc->index(v);
|
||||
vt= fc->vertex(cw(ic));
|
||||
|
||||
if(fc == done)
|
||||
{
|
||||
*this = Line_face_circulator();
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
Vertex_handle vr = fc-> vertex(ccw(ic));
|
||||
Orientation pqr = RIGHT_TURN; // warning "pqr might be used uninitialized"
|
||||
while((pqr = _tr->orientation(p, q, vr->point())) == LEFT_TURN)
|
||||
{
|
||||
--fc;
|
||||
ic = fc->index(v);
|
||||
vr = fc-> vertex(ccw(ic));
|
||||
}
|
||||
|
||||
// first intersected face found
|
||||
// [pqr] is COLLINEAR or RIGHT_TURN
|
||||
ic = fc->index(v);
|
||||
vt= fc->vertex(cw(ic));
|
||||
CGAL_assertion (_tr->orientation(p, q, vt->point()) == LEFT_TURN);
|
||||
|
||||
if(pqr == COLLINEAR)
|
||||
{
|
||||
pos = fc;
|
||||
s = vertex_vertex;
|
||||
i = ccw(ic);
|
||||
}
|
||||
else // pqr == RIGHT_TURN
|
||||
{
|
||||
pos = fc;
|
||||
s = vertex_edge;
|
||||
i = ic ;
|
||||
}
|
||||
}
|
||||
|
||||
template <typename Triangulation>
|
||||
inline
|
||||
void
|
||||
Triangulation_sphere_line_face_circulator_2<Triangulation>::
|
||||
increment()
|
||||
{
|
||||
CGAL_precondition(pos != Face_handle());
|
||||
if(s == vertex_vertex || s == edge_vertex)
|
||||
{
|
||||
Orientation o;
|
||||
do
|
||||
{
|
||||
Face_handle n = pos->neighbor(cw(i));
|
||||
i = n->index(pos);
|
||||
pos = n;
|
||||
|
||||
o = _tr->orientation(p, q, pos->vertex(i)->point());
|
||||
i = cw(i);
|
||||
} while(o == LEFT_TURN);
|
||||
|
||||
if(o == COLLINEAR)
|
||||
{
|
||||
s = vertex_vertex;
|
||||
i = ccw(i);
|
||||
}
|
||||
else
|
||||
{
|
||||
s = vertex_edge;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
Face_handle n = pos->neighbor(i);
|
||||
int ni = n->index(pos);
|
||||
pos = n ;
|
||||
Orientation o = _tr->orientation(p, q, pos->vertex(ni)->point());
|
||||
|
||||
switch(o)
|
||||
{
|
||||
case LEFT_TURN:
|
||||
s = edge_edge;
|
||||
i = ccw(ni);
|
||||
break;
|
||||
case RIGHT_TURN:
|
||||
s = edge_edge;
|
||||
i = cw(ni);
|
||||
break;
|
||||
default:
|
||||
s = edge_vertex;
|
||||
i = ni;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
template <typename Triangulation>
|
||||
void
|
||||
Triangulation_sphere_line_face_circulator_2<Triangulation>::
|
||||
decrement()
|
||||
{
|
||||
CGAL_precondition(pos != Face_handle());
|
||||
if(s == vertex_vertex || s == vertex_edge)
|
||||
{
|
||||
if(s == vertex_vertex)
|
||||
i = cw(i);
|
||||
|
||||
Orientation o;
|
||||
do
|
||||
{
|
||||
Face_handle n = pos->neighbor(ccw(i));
|
||||
i = n->index(pos);
|
||||
pos = n;
|
||||
|
||||
o = _tr->orientation(p, q, pos->vertex(i)->point());
|
||||
i = ccw(i);
|
||||
}
|
||||
while(o == LEFT_TURN);
|
||||
|
||||
s = (o == COLLINEAR) ? vertex_vertex : edge_vertex;
|
||||
|
||||
}
|
||||
else // s == edge_edge || s == edge_vertex
|
||||
{
|
||||
// the following is not nice. A better solution is to say
|
||||
// that index i is at the vertex that is alone on one side of l(p, q)
|
||||
if(s == edge_edge)
|
||||
i = (_tr->orientation(p, q, pos->vertex(i)->point()) == LEFT_TURN) ? cw(i) : ccw(i);
|
||||
|
||||
Face_handle n = pos->neighbor(i);
|
||||
i = n->index(pos);
|
||||
pos = n;
|
||||
Orientation o = _tr->orientation(p, q, pos->vertex(i)->point());
|
||||
|
||||
s = (o == COLLINEAR) ? vertex_edge : edge_edge;
|
||||
}
|
||||
}
|
||||
|
||||
template <typename Triangulation>
|
||||
inline
|
||||
Triangulation_sphere_line_face_circulator_2<Triangulation>&
|
||||
Triangulation_sphere_line_face_circulator_2<Triangulation>::
|
||||
operator++()
|
||||
{
|
||||
CGAL_precondition(pos != Face_handle()) ;
|
||||
increment();
|
||||
return *this;
|
||||
}
|
||||
|
||||
template <typename Triangulation>
|
||||
inline
|
||||
Triangulation_sphere_line_face_circulator_2<Triangulation>&
|
||||
Triangulation_sphere_line_face_circulator_2<Triangulation>::
|
||||
operator--()
|
||||
{
|
||||
CGAL_precondition(pos != Face_handle()) ;
|
||||
decrement();
|
||||
return *this;
|
||||
}
|
||||
|
||||
template <typename Triangulation>
|
||||
inline
|
||||
Triangulation_sphere_line_face_circulator_2<Triangulation>
|
||||
Triangulation_sphere_line_face_circulator_2<Triangulation>::
|
||||
operator++(int)
|
||||
{
|
||||
Line_face_circulator tmp(*this);
|
||||
++(*this);
|
||||
return tmp;
|
||||
}
|
||||
|
||||
template <typename Triangulation>
|
||||
inline
|
||||
Triangulation_sphere_line_face_circulator_2<Triangulation>
|
||||
Triangulation_sphere_line_face_circulator_2<Triangulation>::
|
||||
operator--(int)
|
||||
{
|
||||
Line_face_circulator tmp(*this);
|
||||
--(*this);
|
||||
return tmp;
|
||||
}
|
||||
|
||||
template <typename Triangulation>
|
||||
inline bool
|
||||
Triangulation_sphere_line_face_circulator_2<Triangulation>::
|
||||
operator==(const Line_face_circulator& lfc) const
|
||||
{
|
||||
CGAL_precondition(pos != Face_handle() && lfc.pos != Face_handle());
|
||||
return (pos == lfc.pos && _tr == lfc._tr &&
|
||||
s == lfc.s && p==lfc.p && q==lfc.q);
|
||||
}
|
||||
|
||||
template <typename Triangulation>
|
||||
inline bool
|
||||
Triangulation_sphere_line_face_circulator_2<Triangulation>::
|
||||
operator!=(const Line_face_circulator& lfc) const
|
||||
{
|
||||
return !(*this == lfc);
|
||||
}
|
||||
|
||||
template <typename Triangulation>
|
||||
inline bool
|
||||
Triangulation_sphere_line_face_circulator_2<Triangulation>::
|
||||
is_empty() const
|
||||
{
|
||||
return pos == Face_handle();
|
||||
}
|
||||
|
||||
template <typename Triangulation>
|
||||
inline bool
|
||||
Triangulation_sphere_line_face_circulator_2<Triangulation>::
|
||||
operator==(Nullptr_t CGAL_assertion_code(n)) const
|
||||
{
|
||||
CGAL_triangulation_assertion(n == NULL);
|
||||
return pos == Face_handle();
|
||||
}
|
||||
|
||||
template <typename Triangulation>
|
||||
inline bool
|
||||
Triangulation_sphere_line_face_circulator_2<Triangulation>::
|
||||
operator!=(Nullptr_t n) const
|
||||
{
|
||||
CGAL_triangulation_assertion(n == NULL);
|
||||
return !(*this == n);
|
||||
}
|
||||
|
||||
} // end namespace CGAL
|
||||
|
||||
#endif // CGAL_TRIANGULATION_SPHERE_LINE_FACE_CIRCULATOR_2_H
|
||||
|
|
@ -0,0 +1 @@
|
|||
INRIA (France)
|
||||
|
|
@ -0,0 +1,27 @@
|
|||
Algebraic_foundations
|
||||
Algebraic_kernel_for_spheres
|
||||
Arithmetic_kernel
|
||||
BGL
|
||||
Cartesian_kernel
|
||||
Circular_kernel_3
|
||||
Circulator
|
||||
Distance_2
|
||||
Distance_3
|
||||
Filtered_kernel
|
||||
Hash_map
|
||||
Homogeneous_kernel
|
||||
Installation
|
||||
Intersections_2
|
||||
Interval_support
|
||||
Kernel_23
|
||||
Modular_arithmetic
|
||||
Number_types
|
||||
Polygon
|
||||
Profiling_tools
|
||||
Property_map
|
||||
STL_Extension
|
||||
Solver_interface
|
||||
Spatial_sorting
|
||||
Stream_support
|
||||
TDS_2
|
||||
Triangulation_on_sphere_2
|
||||
|
|
@ -0,0 +1 @@
|
|||
GPL (v3 or later)
|
||||
|
|
@ -0,0 +1,28 @@
|
|||
cmake_minimum_required(VERSION 3.1...3.15)
|
||||
|
||||
project( Triangulation_on_sphere_2_Tests )
|
||||
|
||||
find_package(CGAL REQUIRED COMPONENTS Core)
|
||||
|
||||
find_package(Eigen3 3.1.0) #(requires 3.1.0 or greater)
|
||||
include(CGAL_Eigen3_support)
|
||||
|
||||
if ( CGAL_FOUND )
|
||||
|
||||
create_single_source_cgal_program( "test_dtos.cpp" )
|
||||
create_single_source_cgal_program( "test_dtos2_remove.cpp" )
|
||||
create_single_source_cgal_program( "test_dtos_degenerate_cases.cpp" )
|
||||
create_single_source_cgal_program( "test_dtos_illegal_points.cpp" )
|
||||
create_single_source_cgal_program( "test_dtos_projection_traits.cpp" )
|
||||
create_single_source_cgal_program( "test_dtos_traits.cpp" )
|
||||
|
||||
if(TARGET CGAL::Eigen3_support)
|
||||
create_single_source_cgal_program( "test_dtos_dual.cpp" )
|
||||
target_link_libraries(test_dtos_dual PUBLIC CGAL::Eigen3_support)
|
||||
endif()
|
||||
|
||||
else()
|
||||
|
||||
message(STATUS "This program requires the CGAL library, and will not be compiled.")
|
||||
|
||||
endif()
|
||||
|
|
@ -0,0 +1,189 @@
|
|||
#include <CGAL/Exact_predicates_inexact_constructions_kernel.h>
|
||||
|
||||
#include <CGAL/Delaunay_triangulation_on_sphere_traits_2.h>
|
||||
#include <CGAL/Delaunay_triangulation_on_sphere_2.h>
|
||||
|
||||
#include <CGAL/enum.h>
|
||||
|
||||
#include <iostream>
|
||||
|
||||
typedef CGAL::Exact_predicates_inexact_constructions_kernel K;
|
||||
typedef K::Point_3 Point;
|
||||
|
||||
typedef CGAL::Delaunay_triangulation_on_sphere_traits_2<K> Gt;
|
||||
typedef CGAL::Delaunay_triangulation_on_sphere_2<Gt> Tr;
|
||||
|
||||
int main(int, char**)
|
||||
{
|
||||
Gt traits(Point(1, 2, 3), 5);
|
||||
|
||||
std::vector<Point> points;
|
||||
points.emplace_back( 2, 1, 1);
|
||||
points.emplace_back(-2, 1, 1); // not on the sphere
|
||||
points.emplace_back( 0, 1, 1);
|
||||
points.emplace_back( 1, 2, 1);
|
||||
points.emplace_back( 0, 1, 1); // duplicate
|
||||
points.emplace_back( 1, 0, 1);
|
||||
points.emplace_back( 1, 1, 2);
|
||||
|
||||
// test constructors
|
||||
Tr tr0;
|
||||
assert(tr0.geom_traits().center() == Point(0, 0, 0));
|
||||
assert(tr0.geom_traits().radius() == 1);
|
||||
|
||||
Tr tr(traits);
|
||||
assert(tr.geom_traits().center() == Point(1, 2, 3));
|
||||
assert(tr.geom_traits().radius() == 5);
|
||||
|
||||
Tr trbis(tr);
|
||||
assert(trbis.geom_traits().center() == tr.geom_traits().center());
|
||||
assert(trbis.geom_traits().radius() == tr.geom_traits().radius());
|
||||
assert(trbis.number_of_vertices() == tr.number_of_vertices());
|
||||
assert(trbis.number_of_edges() == tr.number_of_edges());
|
||||
assert(trbis.number_of_solid_faces() == tr.number_of_solid_faces());
|
||||
assert(trbis.number_of_ghost_faces() == tr.number_of_ghost_faces());
|
||||
|
||||
Tr tr2(tr);
|
||||
assert(tr2.geom_traits().center() == tr.geom_traits().center());
|
||||
assert(tr2.geom_traits().radius() == tr.geom_traits().radius());
|
||||
|
||||
Tr tr3 = tr2;
|
||||
assert(tr3.geom_traits().center() == tr2.geom_traits().center());
|
||||
assert(tr3.geom_traits().radius() == tr2.geom_traits().radius());
|
||||
|
||||
Tr tr4(points.begin(), points.end(), Point(1, 1, 1), 1);
|
||||
assert(tr4.number_of_vertices() == 5);
|
||||
|
||||
tr4.set_radius(0.123);
|
||||
assert(tr4.number_of_vertices() == 0);
|
||||
|
||||
Tr tr5(points.begin(), points.end());
|
||||
assert(tr5.geom_traits().center() == Point(0, 0, 0));
|
||||
assert(tr5.geom_traits().radius() == 1);
|
||||
assert(tr5.number_of_vertices() == 0);
|
||||
|
||||
Gt traits2(Point(1, 1, 1), 1);
|
||||
Tr tr6(points.begin(), points.end(), traits2);
|
||||
assert(tr6.number_of_vertices() == 5);
|
||||
|
||||
tr6.set_center(Point(1,2,3));
|
||||
assert(tr6.number_of_vertices() == 0);
|
||||
|
||||
// center / radius setting
|
||||
tr.insert(Point(6, 2, 3));
|
||||
assert(tr.number_of_vertices() == 1);
|
||||
|
||||
tr.set_center_and_radius(Point(1, 1, 1), 1);
|
||||
assert(tr3.number_of_vertices() == 0);
|
||||
assert(tr.geom_traits().center() == Point(1, 1, 1));
|
||||
assert(tr.geom_traits().radius() == 1);
|
||||
|
||||
tr.insert(points.begin(), points.end());
|
||||
write_OFF("test_dtos.off", tr);
|
||||
assert(tr.is_valid());
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// test ranges
|
||||
Tr::Vertex_handles vs = tr.vertex_handles();
|
||||
assert(vs.size() == tr.number_of_vertices() && vs.size() == 5);
|
||||
|
||||
Tr::All_edges es = tr.all_edges();
|
||||
Tr::Solid_edges ses = tr.solid_edges();
|
||||
assert(es.size() == 9 && ses.size() == 8);
|
||||
|
||||
Tr::All_face_handles afs = tr.all_face_handles();
|
||||
assert(afs.size() == tr.number_of_faces() && afs.size() == 6);
|
||||
|
||||
Tr::Solid_face_handles sfs = tr.solid_faces();
|
||||
assert(sfs.size() == 4);
|
||||
assert(tr.number_of_solid_faces() + tr.number_of_ghost_faces() == tr.number_of_faces());
|
||||
|
||||
Tr::Points pts = tr.points();
|
||||
assert(pts.size() == tr.number_of_vertices() && pts.size() == 5);
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// test iterators
|
||||
|
||||
// All vertices iterator
|
||||
Tr::Vertices_iterator vit = tr.vertices_begin(), vend = tr.vertices_end();
|
||||
assert(std::distance(vit, vend) == 5);
|
||||
|
||||
const Tr::Point& p0 = tr.point(vit);
|
||||
++vit;
|
||||
const Tr::Point& p1 = tr.point(vit++);
|
||||
assert(p0 != p1);
|
||||
std::advance(vit, -2);
|
||||
assert(p0 == vit->point());
|
||||
|
||||
// All edges iterator
|
||||
Tr::All_edges_iterator eit = tr.all_edges_begin(), eend = tr.all_edges_end();
|
||||
assert(std::distance(eit, eend) == 9);
|
||||
|
||||
Tr::Edge e0 = *eit;
|
||||
++eit;
|
||||
Tr::Edge e1 = *eit++;
|
||||
assert(e0 != e1);
|
||||
std::advance(eit, -2);
|
||||
assert(e0 == *eit);
|
||||
|
||||
// Solid edges iterator
|
||||
Tr::Solid_edges_iterator seit = tr.solid_edges_begin(), seend = tr.solid_edges_end();
|
||||
assert(std::distance(seit, seend) == 8);
|
||||
|
||||
Tr::Edge se0 = *seit;
|
||||
++seit;
|
||||
Tr::Edge se1 = *seit++;
|
||||
assert(se0 != se1);
|
||||
std::advance(seit, -2);
|
||||
assert(se0 == *seit);
|
||||
|
||||
// Contour edges iterator
|
||||
Tr::Contour_edges_iterator ceit=tr.contour_edges_begin(), ceend=tr.contour_edges_end();
|
||||
assert(std::distance(ceit, ceend) == 4);
|
||||
|
||||
std::set<Tr::Edge> unique_edges;
|
||||
while(ceit != ceend)
|
||||
{
|
||||
const Tr::Edge& e = *ceit;
|
||||
unique_edges.insert(e);
|
||||
assert(tr.is_ghost(e.first) != tr.is_ghost(tr.mirror_edge(e).first)); // xor
|
||||
++ceit;
|
||||
}
|
||||
|
||||
assert(unique_edges.size() == 4);
|
||||
std::advance(ceit, -4);
|
||||
assert(ceit == tr.contour_edges_begin());
|
||||
|
||||
// All faces iterator
|
||||
Tr::All_faces_iterator fit = tr.all_faces_begin(), fend = tr.all_faces_end();
|
||||
assert(std::distance(fit, fend) == 6);
|
||||
|
||||
Tr::Face_handle f0 = fit;
|
||||
++fit;
|
||||
Tr::Face_handle f1 = fit++;
|
||||
assert(f0 != f1);
|
||||
std::advance(fit, -2);
|
||||
assert(f0 == fit);
|
||||
|
||||
// Solid faces iterator
|
||||
Tr::Solid_faces_iterator sfit = tr.solid_faces_begin(), sfend = tr.solid_faces_end();
|
||||
assert(std::distance(sfit, sfend) == 4);
|
||||
|
||||
Tr::Face_handle sf0 = sfit;
|
||||
++sfit;
|
||||
Tr::Face_handle sf1 = sfit++;
|
||||
assert(sf0 != sf1);
|
||||
std::advance(sfit, -2);
|
||||
Tr::Face_handle sf2 = sfit;
|
||||
assert(sf0 == sf2);
|
||||
|
||||
// Face Circulator
|
||||
vit = tr.vertices_begin();
|
||||
std::advance(vit, 3); // top of the pyramid
|
||||
Tr::Face_circulator fc = tr.incident_faces(vit), end = fc;
|
||||
assert(std::distance(++fc, end) + 1 == 4);
|
||||
|
||||
std::cout << "Done!" << std::endl;
|
||||
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
|
|
@ -0,0 +1,88 @@
|
|||
#include <CGAL/Exact_predicates_inexact_constructions_kernel.h>
|
||||
|
||||
#include <CGAL/Delaunay_triangulation_on_sphere_traits_2.h>
|
||||
#include <CGAL/Projection_on_sphere_traits_3.h>
|
||||
#include <CGAL/Delaunay_triangulation_on_sphere_2.h>
|
||||
|
||||
#include <cmath>
|
||||
#include <fstream>
|
||||
|
||||
typedef CGAL::Exact_predicates_inexact_constructions_kernel K;
|
||||
typedef K::Point_3 Point;
|
||||
|
||||
typedef CGAL::Delaunay_triangulation_on_sphere_traits_2<K> Gt;
|
||||
typedef CGAL::Projection_on_sphere_traits_3<K> Gt2;
|
||||
typedef CGAL::Delaunay_triangulation_on_sphere_2<Gt> DTOS;
|
||||
typedef CGAL::Delaunay_triangulation_on_sphere_2<Gt2> DTOS2;
|
||||
|
||||
void test1()
|
||||
{
|
||||
DTOS dtos;
|
||||
dtos.set_radius(10);
|
||||
|
||||
Point a( 0, 0, 10);
|
||||
Point b(-10/sqrt(3), -10/sqrt(3), 10/sqrt(3));
|
||||
Point c( 10/sqrt(3), 10/sqrt(3), 10/sqrt(3));
|
||||
Point d( 10/sqrt(3), -10/sqrt(3), 10/sqrt(3));
|
||||
Point e(-10/sqrt(3), 10/sqrt(3), 10/sqrt(3));
|
||||
|
||||
DTOS::Vertex_handle v1 = dtos.insert(a);
|
||||
DTOS::Vertex_handle v2 = dtos.insert(b);
|
||||
DTOS::Vertex_handle v3 = dtos.insert(c);
|
||||
DTOS::Vertex_handle v4 = dtos.insert(d);
|
||||
DTOS::Vertex_handle v5 = dtos.insert(e);
|
||||
|
||||
assert(dtos.number_of_ghost_faces() == 2);
|
||||
assert(dtos.dimension() == 2);
|
||||
|
||||
dtos.remove(v1);
|
||||
assert(dtos.dimension() == 1);
|
||||
|
||||
dtos.remove(v2);
|
||||
assert(dtos.dimension() == 1);
|
||||
|
||||
dtos.remove(v3);
|
||||
assert(dtos.dimension() == 0);
|
||||
|
||||
dtos.remove(v4);
|
||||
assert(dtos.dimension() == -1);
|
||||
|
||||
dtos.remove(v5);
|
||||
assert(dtos.dimension() == -2);
|
||||
}
|
||||
|
||||
void test2()
|
||||
{
|
||||
DTOS2 dtos;
|
||||
dtos.set_radius(10);
|
||||
|
||||
Point a( 0, 0, 10);
|
||||
Point b(-10/sqrt(3), -10/sqrt(3), 10/sqrt(3));
|
||||
Point c( 10/sqrt(3), 10/sqrt(3), 10/sqrt(3));
|
||||
Point d( 10/sqrt(3), -10/sqrt(3), 10/sqrt(3));
|
||||
Point e(-10/sqrt(3), 10/sqrt(3), 10/sqrt(3));
|
||||
Point f( 0, 0, -10);
|
||||
|
||||
/*DTOS2::Vertex_handle v1 = */dtos.insert(a);
|
||||
/*DTOS2::Vertex_handle v2 = */dtos.insert(b);
|
||||
/*DTOS2::Vertex_handle v3 = */dtos.insert(c);
|
||||
/*DTOS2::Vertex_handle v4 = */dtos.insert(d);
|
||||
/*DTOS2::Vertex_handle v5 = */dtos.insert(e);
|
||||
DTOS2::Vertex_handle v6 = dtos.insert(f);
|
||||
|
||||
assert(dtos.number_of_ghost_faces() == 0);
|
||||
dtos.remove(v6);
|
||||
|
||||
assert(dtos.number_of_ghost_faces() == 2);
|
||||
assert(dtos.dimension() == 2);
|
||||
}
|
||||
|
||||
int main(int, char**)
|
||||
{
|
||||
test1();
|
||||
test2();
|
||||
|
||||
std::cout << "Done" << std::endl;
|
||||
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
|
|
@ -0,0 +1,225 @@
|
|||
#include <CGAL/Exact_predicates_inexact_constructions_kernel.h>
|
||||
#include <CGAL/Exact_predicates_exact_constructions_kernel_with_sqrt.h>
|
||||
|
||||
#include <CGAL/Delaunay_triangulation_on_sphere_traits_2.h>
|
||||
#include <CGAL/Projection_on_sphere_traits_3.h>
|
||||
#include <CGAL/Triangulation_on_sphere_2.h>
|
||||
#include <CGAL/Delaunay_triangulation_on_sphere_2.h>
|
||||
|
||||
#include <algorithm>
|
||||
#include <iostream>
|
||||
#include <vector>
|
||||
|
||||
template <class Vertex_handle, class Face_handle>
|
||||
bool has_face(const Face_handle fh,
|
||||
const Vertex_handle v0,
|
||||
const Vertex_handle v1,
|
||||
const Vertex_handle v2)
|
||||
{
|
||||
bool test1, test2, test3;
|
||||
|
||||
for(int i=0; i<=2; ++i)
|
||||
{
|
||||
test1 = (v0->point() == fh->vertex(i)->point());
|
||||
if(test1)
|
||||
break;
|
||||
}
|
||||
|
||||
if(!test1)
|
||||
return false;
|
||||
|
||||
for(int i=0; i<=2; ++i)
|
||||
{
|
||||
test2 = (v1->point() == fh->vertex(i)->point());
|
||||
if(test2)
|
||||
break;
|
||||
}
|
||||
|
||||
if(!test2)
|
||||
return false;
|
||||
|
||||
for(int i=0; i<=2; ++i)
|
||||
{
|
||||
test3 = (v2->point() == fh->vertex(i)->point());
|
||||
if(test3)
|
||||
break;
|
||||
}
|
||||
|
||||
if(!test3)
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
template <class Triangul>
|
||||
bool are_equal(const Triangul& triA, const Triangul& triB)
|
||||
{
|
||||
typedef typename Triangul::Vertex_handle Vertex_handle;
|
||||
typedef typename Triangul::Face_handle Face_handle;
|
||||
typedef typename Triangul::All_faces_iterator Face_iterator;
|
||||
|
||||
std::cout << "First triangulation:" << std::endl;
|
||||
std::cout << "dimension: " << triA.dimension() << std::endl;
|
||||
std::cout << triA.number_of_vertices() << " nv" << std::endl;
|
||||
std::cout << triA.number_of_faces() << " nf" << std::endl;
|
||||
std::cout << triA.number_of_ghost_faces() << " gf" << std::endl;
|
||||
|
||||
std::cout << "Second triangulation:" << std::endl;
|
||||
std::cout << "dimension: " << triB.dimension() << std::endl;
|
||||
std::cout << triB.number_of_vertices() << " nv" << std::endl;
|
||||
std::cout << triB.number_of_faces() << " nf" << std::endl;
|
||||
std::cout << triB.number_of_ghost_faces() << " gf" << std::endl;
|
||||
|
||||
if (triA.number_of_vertices()!= triB.number_of_vertices())
|
||||
return false;
|
||||
if (triA.number_of_faces()!= triB.number_of_faces())
|
||||
return false;
|
||||
if(triA.number_of_ghost_faces()!=triB.number_of_ghost_faces())
|
||||
return false;
|
||||
|
||||
bool found = true;
|
||||
for(Face_iterator fiA = triA.all_faces_begin(); fiA != triA.all_faces_end(); ++fiA)
|
||||
{
|
||||
found = false;
|
||||
for(Face_iterator fiB=triB.all_faces_begin(); fiB!=triB.all_faces_end(); ++fiB)
|
||||
{
|
||||
Face_handle fb = Face_handle(fiB);
|
||||
Face_handle fa = Face_handle(fiA);
|
||||
Vertex_handle v0 = fa->vertex(0);
|
||||
Vertex_handle v1 = fa->vertex(1);
|
||||
Vertex_handle v2 = fa->vertex(2);
|
||||
if(has_face(fb, v0, v1, v2))
|
||||
{
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
assert(found);
|
||||
}
|
||||
|
||||
return found;
|
||||
}
|
||||
|
||||
// tests whether it is possible to insert points in degenerated positions
|
||||
// and whether the result is uniquely defined after this.
|
||||
|
||||
template <typename DTOS, typename FT, typename PointContainer>
|
||||
void test(const FT radius,
|
||||
PointContainer coplanar_points)
|
||||
{
|
||||
std::cout << coplanar_points.size() << " input points" << std::endl;
|
||||
|
||||
DTOS dtos(CGAL::ORIGIN, radius);
|
||||
for(const auto& p : coplanar_points) // to avoid Hilbert sort
|
||||
dtos.insert(p);
|
||||
|
||||
assert(dtos.is_valid());
|
||||
|
||||
std::cout << "Triangulation:" << std::endl;
|
||||
std::cout << "dimension: " << dtos.dimension() << std::endl;
|
||||
std::cout << dtos.number_of_vertices() << " nv" << std::endl;
|
||||
std::cout << dtos.number_of_edges() << " ne" << std::endl;
|
||||
std::cout << dtos.number_of_faces() << " nf" << std::endl;
|
||||
std::cout << dtos.number_of_ghost_faces() << " gf" << std::endl;
|
||||
|
||||
for(int i=0; i<10; ++i)
|
||||
{
|
||||
CGAL::cpp98::random_shuffle(coplanar_points.begin(), coplanar_points.end());
|
||||
|
||||
DTOS dtos2(CGAL::ORIGIN, radius);
|
||||
for(const auto& p : coplanar_points) // to avoid Hilbert sort
|
||||
dtos2.insert(p);
|
||||
|
||||
assert(dtos2.is_valid());
|
||||
assert(are_equal(dtos, dtos2));
|
||||
|
||||
std::cout << dtos2.number_of_vertices() << " nv and " << dtos2.number_of_faces() << " nf" << std::endl;
|
||||
}
|
||||
}
|
||||
|
||||
template <typename K>
|
||||
void test_kernel()
|
||||
{
|
||||
std::cout << "Test: " << typeid(K).name() << std::endl;
|
||||
|
||||
typedef typename K::FT FT;
|
||||
typedef typename K::Point_3 Point_3;
|
||||
|
||||
typedef CGAL::Delaunay_triangulation_on_sphere_traits_2<K> Gt;
|
||||
typedef CGAL::Delaunay_triangulation_on_sphere_2<Gt> DTOS;
|
||||
|
||||
typedef CGAL::Projection_on_sphere_traits_3<K> PGt;
|
||||
typedef CGAL::Delaunay_triangulation_on_sphere_2<PGt> PDTOS;
|
||||
|
||||
const FT radius = 100;
|
||||
const FT radius2 = CGAL::square(radius);
|
||||
|
||||
const FT denom = FT(1) / CGAL::sqrt(FT(2));
|
||||
const FT z = CGAL::sqrt(radius2 - 1);
|
||||
|
||||
std::vector<Point_3> coplanar_low_dim { Point_3(0,0,radius), Point_3(radius,0,0), Point_3(0,radius,0)
|
||||
// , Point_3(0,0,-radius)
|
||||
};
|
||||
|
||||
// Points are coplanar and coplanar with the center of the sphere
|
||||
std::vector<Point_3> coplanar_points { Point_3( radius*denom, radius*denom, 0),
|
||||
Point_3(- radius*denom, radius*denom, 0),
|
||||
Point_3(- radius*denom, - radius*denom, 0),
|
||||
Point_3( radius*denom, - radius*denom, 0),
|
||||
Point_3( radius, 0, 0),
|
||||
Point_3( 0, 0, radius) };
|
||||
|
||||
std::vector<Point_3> coplanar_points_on_great_circle { Point_3( 0, 0, radius),
|
||||
Point_3( denom, denom, z),
|
||||
Point_3(-denom, -denom, z),
|
||||
Point_3( denom, denom, -z),
|
||||
Point_3(-denom, -denom, -z),
|
||||
Point_3( 0, 0,-radius) };
|
||||
|
||||
std::vector<Point_3> coplanar_points_on_circle { Point_3( denom, denom, z),
|
||||
Point_3(-denom, -denom, z),
|
||||
Point_3( 0, 1, z)/*,
|
||||
Point_3( 1, 0, z),
|
||||
Point_3(-denom, denom, z),
|
||||
Point_3( denom, -denom, z)*/ };
|
||||
|
||||
// -----------------------------------------------------------------------------------------------
|
||||
std::cout << "Testing with Delaunay_triangulation_sphere_traits:" << std::endl;
|
||||
test<DTOS>(radius, coplanar_low_dim);
|
||||
test<DTOS>(radius, coplanar_points);
|
||||
test<DTOS>(radius, coplanar_points_on_great_circle);
|
||||
test<DTOS>(radius, coplanar_points_on_circle);
|
||||
return;
|
||||
|
||||
// -----------------------------------------------------------------------------------------------
|
||||
std::cout << "Testing with projection: " << std::endl;
|
||||
PGt traits(CGAL::ORIGIN, radius);
|
||||
typename PGt::Construct_point_on_sphere_2 to_s2 = traits.construct_point_on_sphere_2_object();
|
||||
|
||||
std::vector<typename PGt::Point_on_sphere_2> coplanar_ppoints;
|
||||
std::vector<typename PGt::Point_on_sphere_2> coplanar_ppoints_on_great_circle;
|
||||
|
||||
std::transform(coplanar_points.begin(), coplanar_points.end(), std::back_inserter(coplanar_ppoints), to_s2);
|
||||
|
||||
test<PDTOS>(radius, coplanar_ppoints);
|
||||
|
||||
// tests the convenience API (passing P3)
|
||||
test<PDTOS>(radius, coplanar_low_dim);
|
||||
test<PDTOS>(radius, coplanar_points_on_circle);
|
||||
test<PDTOS>(radius, coplanar_points_on_great_circle);
|
||||
test<PDTOS>(radius, coplanar_points_on_circle);
|
||||
}
|
||||
|
||||
int main(int, char**)
|
||||
{
|
||||
typedef CGAL::Exact_predicates_exact_constructions_kernel_with_sqrt EPECK_w_SQRT;
|
||||
typedef CGAL::Exact_predicates_inexact_constructions_kernel EPICK;
|
||||
|
||||
test_kernel<EPICK>();
|
||||
test_kernel<EPECK_w_SQRT>();
|
||||
|
||||
std::cout << "Done" << std::endl;
|
||||
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
|
|
@ -0,0 +1,164 @@
|
|||
#include <CGAL/Exact_predicates_inexact_constructions_kernel.h>
|
||||
|
||||
#include <CGAL/Geographical_coordinates_traits_2.h>
|
||||
#include <CGAL/Delaunay_triangulation_on_sphere_traits_2.h>
|
||||
#include <CGAL/Projection_on_sphere_traits_3.h>
|
||||
#include <CGAL/Delaunay_triangulation_on_sphere_2.h>
|
||||
|
||||
#include <CGAL/enum.h>
|
||||
#include <CGAL/point_generators_3.h>
|
||||
|
||||
#include <iostream>
|
||||
#include <fstream>
|
||||
|
||||
typedef CGAL::Exact_predicates_inexact_constructions_kernel EPICK;
|
||||
|
||||
template <typename K, typename PointRange>
|
||||
void test(const PointRange& points)
|
||||
{
|
||||
// typedef CGAL::Geographical_coordinates_traits_2<K> Gt;
|
||||
typedef CGAL::Projection_on_sphere_traits_3<K> Gt;
|
||||
typedef CGAL::Delaunay_triangulation_on_sphere_2<Gt> Dt;
|
||||
|
||||
typedef typename Gt::SK SK;
|
||||
|
||||
typedef typename Dt::FT FT;
|
||||
typedef typename Dt::Point_3 Point_3;
|
||||
typedef typename Dt::Point Point_on_sphere_2;
|
||||
typedef typename Dt::Segment_3 Segment_3;
|
||||
typedef typename Dt::Arc_on_sphere_2 Arc_on_sphere_2;
|
||||
typedef typename Dt::Face_handle Face_handle;
|
||||
|
||||
Dt dt;
|
||||
dt.insert(points.begin(), points.end());
|
||||
|
||||
// The triangulation, using straight edges
|
||||
write_OFF("result.off", dt, CGAL::parameters::stream_precision(17));
|
||||
|
||||
std::ofstream out_primal("edges_primal.polylines.cgal");
|
||||
out_primal.precision(17);
|
||||
std::ofstream out_dual("edges_dual.polylines.cgal");
|
||||
out_dual.precision(17);
|
||||
|
||||
for(typename Dt::Solid_faces_iterator fit = dt.solid_faces_begin(); fit!=dt.solid_faces_end(); ++fit)
|
||||
{
|
||||
Face_handle fh = fit;
|
||||
|
||||
const Point_3 c = dt.dual(fh);
|
||||
CGAL_USE(c);
|
||||
|
||||
const Point_on_sphere_2 cs = dt.dual_on_sphere(fh);
|
||||
const FT r = dt.geom_traits().radius();
|
||||
assert(CGAL::abs(CGAL::squared_distance(dt.construct_point(cs),
|
||||
dt.geom_traits().center()) - r*r) <= 1e-10);
|
||||
|
||||
for(int i=0; i<3; ++i)
|
||||
{
|
||||
Face_handle nfh = fh->neighbor(i);
|
||||
if(!dt.is_ghost(nfh) && fh < nfh)
|
||||
continue;
|
||||
|
||||
typename Dt::Edge e(fh, i);
|
||||
const bool diametral_edge = CGAL::collinear(dt.construct_point(dt.point(fh, (i+1)%3)),
|
||||
dt.construct_point(dt.point(fh, (i+2)%3)),
|
||||
dt.geom_traits().center());
|
||||
|
||||
// primal
|
||||
if(!diametral_edge)
|
||||
{
|
||||
Arc_on_sphere_2 as = dt.segment_on_sphere(e);
|
||||
std::vector<typename SK::Point_3> discretization_points;
|
||||
CGAL::Triangulations_on_sphere_2::internal::subsample_arc_on_sphere_2<SK>(as, std::back_inserter(discretization_points));
|
||||
assert(discretization_points.size() >= 2);
|
||||
|
||||
for(std::size_t i=0; i<discretization_points.size()-1; ++i)
|
||||
out_primal << "2 " << discretization_points[i] << " " << discretization_points[i+1] << "\n";
|
||||
}
|
||||
else
|
||||
{
|
||||
Segment_3 s = dt.segment(e);
|
||||
out_primal << "2 " << s.source() << " " << s.target() << "\n";
|
||||
}
|
||||
|
||||
// Dual
|
||||
if(dt.is_contour(e))
|
||||
continue;
|
||||
|
||||
const Point_on_sphere_2 c1 = dt.circumcenter_on_sphere(e.first);
|
||||
const Point_on_sphere_2 c2 = dt.circumcenter_on_sphere(dt.mirror_edge(e).first);
|
||||
|
||||
// That should never be possible, but with constructions...
|
||||
const bool diametral_dual = CGAL::collinear(dt.construct_point(c1),
|
||||
dt.construct_point(c2),
|
||||
dt.geom_traits().center());
|
||||
|
||||
if(!diametral_dual)
|
||||
{
|
||||
Arc_on_sphere_2 ad = dt.dual_on_sphere(e);
|
||||
std::vector<typename SK::Point_3> discretization_points;
|
||||
CGAL::Triangulations_on_sphere_2::internal::subsample_arc_on_sphere_2<SK>(ad, std::back_inserter(discretization_points));
|
||||
assert(discretization_points.size() >= 2);
|
||||
|
||||
for(std::size_t i=0; i<discretization_points.size()-1; ++i)
|
||||
out_dual << "2 " << discretization_points[i] << " " << discretization_points[i+1] << "\n";
|
||||
}
|
||||
else
|
||||
{
|
||||
Segment_3 d = dt.dual(e);
|
||||
out_dual << "2 " << d.source() << " " << d.target() << "\n";
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
template <typename K>
|
||||
void test_with_ghost_faces()
|
||||
{
|
||||
std::vector<typename K::Point_3> points;
|
||||
points.emplace_back( 1, 0, 0);
|
||||
points.emplace_back( 0, 1, 0);
|
||||
points.emplace_back( 1, 1, 1);
|
||||
points.emplace_back( -1, -1, -1);
|
||||
points.emplace_back( 0.5, 0.5, 0);
|
||||
points.emplace_back( 1, 1, 0);
|
||||
points.emplace_back(0.25, 0.25, 0);
|
||||
// points.emplace_back( 0, 0, 1);
|
||||
// points.emplace_back( 2, 0, 0);
|
||||
// points.emplace_back( 0.5, 0, 0);
|
||||
// points.emplace_back( 0.5, 0, 0.5);
|
||||
// points.emplace_back( 0.5, 0, -0.5);
|
||||
// points.emplace_back( 0, 0, 0.5);
|
||||
// points.emplace_back( -1, 0, 0);
|
||||
|
||||
return test<K>(points);
|
||||
}
|
||||
|
||||
template <typename K>
|
||||
void test_random_data(const std::size_t num_of_pts)
|
||||
{
|
||||
typedef typename K::Point_3 Point_3;
|
||||
typedef CGAL::Creator_uniform_3<double, Point_3> Creator;
|
||||
|
||||
CGAL::Random r;
|
||||
std::cout << "Seed is " << r.get_seed() << std::endl;
|
||||
CGAL::Random_points_on_sphere_3<Point_3, Creator> on_sphere(1 /*radius*/, r);
|
||||
|
||||
std::vector<Point_3> points;
|
||||
points.reserve(num_of_pts);
|
||||
|
||||
for(std::size_t c=0; c<num_of_pts; ++c)
|
||||
points.push_back(*on_sphere++);
|
||||
|
||||
return test<K>(points);
|
||||
}
|
||||
|
||||
int main(int argc, char** argv)
|
||||
{
|
||||
const std::size_t num_pts = (argc > 1) ? std::atoi(argv[1]) : 100;
|
||||
|
||||
test_with_ghost_faces<EPICK>();
|
||||
test_random_data<EPICK>(num_pts);
|
||||
|
||||
std::cout << "Done!" << std::endl;
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
|
|
@ -0,0 +1,141 @@
|
|||
#include <CGAL/Exact_predicates_inexact_constructions_kernel.h>
|
||||
|
||||
#include <CGAL/Delaunay_triangulation_on_sphere_traits_2.h>
|
||||
#include <CGAL/Projection_on_sphere_traits_3.h>
|
||||
#include <CGAL/Delaunay_triangulation_on_sphere_2.h>
|
||||
|
||||
#include <iostream>
|
||||
#include <vector>
|
||||
|
||||
typedef CGAL::Exact_predicates_inexact_constructions_kernel K;
|
||||
typedef CGAL::Delaunay_triangulation_on_sphere_traits_2<K> Gt;
|
||||
typedef CGAL::Projection_on_sphere_traits_3<K> Pgt;
|
||||
typedef CGAL::Delaunay_triangulation_on_sphere_2<Gt> DTOS;
|
||||
typedef CGAL::Delaunay_triangulation_on_sphere_2<Pgt> PDTOS;
|
||||
|
||||
typedef K::Point_3 Point;
|
||||
|
||||
void test_projection_traits()
|
||||
{
|
||||
const Point center = Point(0,0,0);
|
||||
const double radius = 1000;
|
||||
Pgt traits(center, radius);
|
||||
PDTOS pdtos(traits);
|
||||
|
||||
std::vector<Point> points;
|
||||
|
||||
// legal points
|
||||
Point p1( radius/sqrt(2), 0, radius/sqrt(2));
|
||||
Point p2(-radius/sqrt(3), radius/sqrt(3), -radius/sqrt(3));
|
||||
Point p3( radius, 0, 0);
|
||||
Point p4(-radius/sqrt(2), -radius/sqrt(2), 0);
|
||||
|
||||
points.push_back(p1);
|
||||
points.push_back(p2);
|
||||
points.push_back(p3);
|
||||
points.push_back(p4);
|
||||
|
||||
// points original not on sphere
|
||||
Point p5(radius, 0, -0.5*radius);
|
||||
points.push_back(p5);
|
||||
|
||||
// Points too close
|
||||
Point p6( 5*radius, std::pow(2, -25), 0);
|
||||
Point p7(-7*radius/sqrt(3), 7*radius/sqrt(3), -7*radius/sqrt(3) + std::pow(2,-35));
|
||||
|
||||
points.push_back(p6);
|
||||
points.push_back(p7);
|
||||
|
||||
pdtos.insert(points.begin(), points.end());
|
||||
|
||||
assert(pdtos.number_of_vertices() == 5);
|
||||
assert(pdtos.is_valid());
|
||||
}
|
||||
|
||||
void test_Delaunay_traits()
|
||||
{
|
||||
typedef DTOS::Point Point;
|
||||
|
||||
const double radius = 1000;
|
||||
DTOS dtos;
|
||||
dtos.set_radius(radius);
|
||||
|
||||
std::vector<Point> points;
|
||||
|
||||
// legal points
|
||||
Point p1( radius/sqrt(2), 0, radius/sqrt(2));
|
||||
Point p2(-radius/sqrt(3), radius/sqrt(3), -radius/sqrt(3));
|
||||
Point p3( radius, 0, 0);
|
||||
Point p4(-radius/sqrt(2), -radius/sqrt(2), 0);
|
||||
|
||||
points.push_back(p1);
|
||||
points.push_back(p2);
|
||||
points.push_back(p3);
|
||||
points.push_back(p4);
|
||||
|
||||
// points not on sphere
|
||||
Point p5(-1.5*radius, 0, 0);
|
||||
Point p6( radius, 0, -0.5*radius);
|
||||
points.push_back(p5);
|
||||
points.push_back(p6);
|
||||
|
||||
// points to close
|
||||
Point p7(radius/sqrt(2), radius*std::pow(2, -15), radius/sqrt(2));
|
||||
Point p8( radius, 0, radius*std::pow(2, -14));
|
||||
|
||||
points.push_back(p7);
|
||||
points.push_back(p8);
|
||||
|
||||
dtos.insert(points.begin(), points.end());
|
||||
assert(dtos.is_valid());
|
||||
assert(dtos.number_of_vertices() == 4);
|
||||
|
||||
dtos.clear();
|
||||
dtos.set_radius(radius);
|
||||
|
||||
dtos.insert(p1);
|
||||
assert(dtos.number_of_vertices() == 1);
|
||||
dtos.insert(p1);
|
||||
assert(dtos.number_of_vertices() == 1);
|
||||
|
||||
dtos.insert(p2);
|
||||
assert(dtos.number_of_vertices() == 2);
|
||||
dtos.insert(p2);
|
||||
assert(dtos.number_of_vertices() == 2);
|
||||
|
||||
dtos.insert(p3);
|
||||
assert(dtos.number_of_vertices() == 3);
|
||||
dtos.insert(p3);
|
||||
assert(dtos.number_of_vertices() == 3);
|
||||
|
||||
dtos.insert(p4);
|
||||
assert(dtos.number_of_vertices() == 4);
|
||||
dtos.insert(p4);
|
||||
assert(dtos.number_of_vertices() == 4);
|
||||
|
||||
dtos.insert(p5);
|
||||
assert(dtos.number_of_vertices() == 4);
|
||||
dtos.insert(p6);
|
||||
assert(dtos.number_of_vertices() == 4);
|
||||
|
||||
dtos.insert(p7);
|
||||
assert(dtos.number_of_vertices() == 4);
|
||||
|
||||
dtos.insert(p8);
|
||||
assert(dtos.number_of_vertices() == 4);
|
||||
dtos.insert(p8);
|
||||
assert(dtos.number_of_vertices() == 4);
|
||||
}
|
||||
|
||||
int main()
|
||||
{
|
||||
std::cout << "Test inserting illegal points with Delaunay_traits" << std::endl;
|
||||
test_Delaunay_traits();
|
||||
|
||||
std::cout << "Test inserting illegal points with Projection_traits" << std::endl;
|
||||
test_projection_traits();
|
||||
|
||||
std::cout << "Done" << std::endl;
|
||||
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
|
|
@ -0,0 +1,121 @@
|
|||
#include <CGAL/Exact_predicates_inexact_constructions_kernel.h>
|
||||
|
||||
#include <CGAL/Projection_on_sphere_traits_3.h>
|
||||
|
||||
#include <CGAL/enum.h>
|
||||
|
||||
#include <iostream>
|
||||
|
||||
typedef CGAL::Exact_predicates_inexact_constructions_kernel K;
|
||||
|
||||
typedef CGAL::Projection_on_sphere_traits_3<K> Gt;
|
||||
|
||||
typedef Gt::Point_3 Point_3;
|
||||
typedef Gt::Point_on_sphere_2 Point_on_sphere_2;
|
||||
typedef Gt::Construct_point_on_sphere_2 Construct_point_on_sphere_2;
|
||||
|
||||
typedef Gt::Compare_on_sphere_2 Compare_on_sphere_2;
|
||||
typedef Gt::Equal_on_sphere_2 Equal_on_sphere_2;
|
||||
typedef Gt::Collinear_are_strictly_ordered_on_great_circle_2 Collinear_are_strictly_ordered_on_great_circle_2;
|
||||
typedef Gt::Orientation_on_sphere_2 Orientation_on_sphere_2;
|
||||
typedef Gt::Side_of_oriented_circle_on_sphere_2 Side_of_oriented_circle_on_sphere_2;
|
||||
|
||||
typedef Gt::Compare_on_sphere_2 Compare_on_sphere_2;
|
||||
|
||||
int main(int, char**)
|
||||
{
|
||||
Point_3 c(0, 0, 0);
|
||||
|
||||
Gt traits(c, 10);
|
||||
|
||||
Equal_on_sphere_2 equal_on_sphere = traits.equal_on_sphere_2_object();
|
||||
Compare_on_sphere_2 compare_on_sphere = traits.compare_on_sphere_2_object();
|
||||
Collinear_are_strictly_ordered_on_great_circle_2 inside_cone = traits.collinear_are_strictly_ordered_on_great_circle_2_object();
|
||||
Orientation_on_sphere_2 orientation = traits.orientation_on_sphere_2_object();
|
||||
Side_of_oriented_circle_on_sphere_2 side_of_oriented_circle = traits.side_of_oriented_circle_on_sphere_2_object();
|
||||
|
||||
Construct_point_on_sphere_2 cst = traits.construct_point_on_sphere_2_object();
|
||||
|
||||
// Testing with Points projected on unit sphere
|
||||
Point_3 p11(1.5, 1.5, 1.5);
|
||||
Point_3 p12( -1, 1, 1);
|
||||
Point_3 p13( 0, 0.7, 0);
|
||||
Point_3 p14( 0, -2, 0);
|
||||
|
||||
Point_3 p21( 2, 0, -1);
|
||||
Point_3 p22(-1.8, 0, -0.7);
|
||||
Point_3 p23( 0, 0, 2.6);
|
||||
|
||||
// Points with same coordinates
|
||||
Point_3 p31(0.6, 0.3, -1);
|
||||
Point_3 p32(0.6, 0.3, -1);
|
||||
Point_3 p33(0.6, 0.3, 1);
|
||||
|
||||
// Equal points
|
||||
Point_3 p41( 1, 1, 1);
|
||||
Point_3 p42(0.7, 0.7, 0.7);
|
||||
Point_3 p43(0.3, 0.6, -2.4);
|
||||
Point_3 p44(0.6, 1.2, -4.8);
|
||||
|
||||
// Inside Cone
|
||||
Point_3 p51( 1, 1, 1);
|
||||
Point_3 p52( -1, 1, 1);
|
||||
Point_3 p53( 1, 3, 3); // inside
|
||||
Point_3 p54(0.8, 0.8, 0.8); // boundary
|
||||
Point_3 p55( 0, -2, -2); // outside
|
||||
|
||||
//distance
|
||||
Point_3 p61( 1, 1, 0);
|
||||
Point_3 p62( -1, 1, 0);
|
||||
|
||||
// transform to projected points
|
||||
Point_on_sphere_2 pp11 = cst(p11);
|
||||
Point_on_sphere_2 pp12 = cst(p12);
|
||||
Point_on_sphere_2 pp13 = cst(p13);
|
||||
Point_on_sphere_2 pp14 = cst(p14);
|
||||
Point_on_sphere_2 pp21 = cst(p21);
|
||||
Point_on_sphere_2 pp22 = cst(p22);
|
||||
Point_on_sphere_2 pp23 = cst(p23);
|
||||
Point_on_sphere_2 pp31 = cst(p31);
|
||||
Point_on_sphere_2 pp32 = cst(p32);
|
||||
Point_on_sphere_2 pp33 = cst(p33);
|
||||
Point_on_sphere_2 pp41 = cst(p41);
|
||||
Point_on_sphere_2 pp42 = cst(p42);
|
||||
Point_on_sphere_2 pp43 = cst(p43);
|
||||
Point_on_sphere_2 pp44 = cst(p44);
|
||||
Point_on_sphere_2 pp51 = cst(p51);
|
||||
Point_on_sphere_2 pp52 = cst(p52);
|
||||
Point_on_sphere_2 pp53 = cst(p53);
|
||||
Point_on_sphere_2 pp54 = cst(p54);
|
||||
Point_on_sphere_2 pp55 = cst(p55);
|
||||
|
||||
std::cout << "Test Orientation" << std::endl;
|
||||
assert(orientation(pp11, pp12, pp13) == CGAL::NEGATIVE);
|
||||
assert(orientation(pp13, pp12, pp11) == CGAL::POSITIVE);
|
||||
assert(orientation(pp21, pp22, pp23) == CGAL::ON_ORIENTED_BOUNDARY);
|
||||
|
||||
std::cout << "Test Side_of_oriented_circle_on_sphere_2" << std::endl;
|
||||
assert(side_of_oriented_circle(pp11, pp12, pp13, pp14) == CGAL::POSITIVE);
|
||||
assert(side_of_oriented_circle(pp14, pp11, pp12, pp13) == CGAL::NEGATIVE);
|
||||
assert(side_of_oriented_circle(pp21, pp22, pp23, pp11) == CGAL::POSITIVE);
|
||||
|
||||
std::cout << "Test Equal_on_sphere_2" << std::endl;
|
||||
assert(equal_on_sphere(pp41, pp41));
|
||||
assert(equal_on_sphere(pp41, pp42));
|
||||
assert(equal_on_sphere(pp43, pp44));
|
||||
|
||||
std::cout << "Test Inside_cone_sphere_2" << std::endl;
|
||||
assert(inside_cone(pp51, pp52, pp53));
|
||||
assert(!inside_cone(pp51, pp52, pp54));
|
||||
assert(!inside_cone(pp51, pp52, pp55));
|
||||
|
||||
std::cout << "Test Compare_on_sphere_2" << std::endl;
|
||||
assert(compare_on_sphere(pp31, pp31) == CGAL::EQUAL);
|
||||
assert(compare_on_sphere(pp31, pp32) == CGAL::EQUAL);
|
||||
assert(compare_on_sphere(pp31, pp33) == CGAL::SMALLER);
|
||||
assert(compare_on_sphere(pp33, pp31) == CGAL::LARGER);
|
||||
|
||||
std::cout << "Done" << std::endl;
|
||||
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
|
|
@ -0,0 +1,162 @@
|
|||
#include <CGAL/Exact_predicates_inexact_constructions_kernel.h>
|
||||
|
||||
#include <CGAL/Delaunay_triangulation_on_sphere_traits_2.h>
|
||||
|
||||
#include <CGAL/enum.h>
|
||||
#include <CGAL/Origin.h>
|
||||
|
||||
#include <iostream>
|
||||
|
||||
typedef CGAL::Exact_predicates_inexact_constructions_kernel K;
|
||||
typedef K::Point_3 Point;
|
||||
|
||||
typedef CGAL::Delaunay_triangulation_on_sphere_traits_2<K> Gt;
|
||||
|
||||
typedef Gt::Orientation_on_sphere_2 Orientation_on_sphere_2;
|
||||
typedef Gt::Side_of_oriented_circle_on_sphere_2 Side_of_oriented_circle_on_sphere_2;
|
||||
|
||||
// This only tests non-trivial functions (a lot of functors are just calls to some functors
|
||||
// of the 3D linear kernel, such as:
|
||||
// typedef typename LK::Compare_xyz_3 Compare_on_sphere_2;
|
||||
|
||||
int main(int, char**)
|
||||
{
|
||||
Point P0 ( 0, 0, 0);
|
||||
Point P1 ( 1, 0, 0);
|
||||
Point P2 ( 0, 1, 0);
|
||||
Point P3 ( 0, 0, 1);
|
||||
Point P4 ( 1, 1, 1);
|
||||
Point P5 ( -1, -1, -1);
|
||||
Point P6 ( 0.5, 0.5, 0);
|
||||
Point P7 ( 2, 0, 0);
|
||||
Point P8 ( 0.5, 0, 0);
|
||||
Point P9 ( 1, 1, 0);
|
||||
Point P10(0.25, 0.25, 0);
|
||||
Point P11( 0.5, 0, 0.5);
|
||||
Point P12( 0.5, 0, -0.5);
|
||||
Point P13( 0, 0, 0.5);
|
||||
Point P14( -1, 0, 0);
|
||||
|
||||
Gt traits;
|
||||
Gt traits_2(CGAL::ORIGIN);
|
||||
Gt traits_3(Point(1, 2, 3), 15);
|
||||
|
||||
Gt traits_4(traits_3);
|
||||
assert(traits_4.radius() == traits_3.radius());
|
||||
assert(traits_4.center() == traits_3.center());
|
||||
|
||||
Gt traits_5 = traits_4;
|
||||
assert(traits_4.radius() == traits_5.radius());
|
||||
assert(traits_4.center() == traits_5.center());
|
||||
|
||||
std::cout << "Test Side_of_oriented_circle_on_sphere_2" << std::endl;
|
||||
CGAL::Oriented_side result;
|
||||
result = traits.side_of_oriented_circle_on_sphere_2_object()(P1, P2, P3, P4);
|
||||
assert(result == CGAL::ON_POSITIVE_SIDE);
|
||||
result = traits.side_of_oriented_circle_on_sphere_2_object()(P1, P2, P3, P5);
|
||||
assert(result == CGAL::ON_NEGATIVE_SIDE);
|
||||
result = traits.side_of_oriented_circle_on_sphere_2_object()(P1, P2, P3, P6);
|
||||
assert(result == CGAL::ON_ORIENTED_BOUNDARY);
|
||||
|
||||
// Former tests for the degenerate cases,
|
||||
// https://github.com/MaelRL/cgal/blob/Triangulation_on_sphere_2-GF-old/
|
||||
// Triangulation_on_sphere_2/include/CGAL/Delaunay_triangulation_sphere_traits_2.h#L29
|
||||
//
|
||||
// power_test_2(p,q,r) where p,q and r are coplanar points with the center of the sphere
|
||||
// result = traits.power_test_2_object()(P1, P2, P9);
|
||||
// assert(result == CGAL::ON_POSITIVE_SIDE);
|
||||
// result = traits.power_test_2_object()(P2, P1, P9);
|
||||
// assert(result == CGAL::ON_POSITIVE_SIDE);
|
||||
// result = traits.power_test_2_object()(P1, P2, P6);
|
||||
// assert(result == CGAL::ON_ORIENTED_BOUNDARY);
|
||||
// result = traits.power_test_2_object()(P1, P2, P10);
|
||||
// assert(result == CGAL::ON_NEGATIVE_SIDE);
|
||||
// result = traits.power_test_2_object()(P2, P1, P10);
|
||||
// assert(result == CGAL::ON_NEGATIVE_SIDE);
|
||||
|
||||
// power_test_2(p,q) where p, q, and the center of the sphere are colinear
|
||||
// result = traits.power_test_2_object()(P1, P7);
|
||||
// assert(result == CGAL::ON_POSITIVE_SIDE);
|
||||
// result = traits.power_test_2_object()(P1, P1);
|
||||
// assert(result == CGAL::ON_ORIENTED_BOUNDARY);
|
||||
// result = traits.power_test_2_object()(P1, P8);
|
||||
// assert(result == CGAL::ON_NEGATIVE_SIDE);
|
||||
|
||||
// With a center different from the origin
|
||||
Gt traits_6(Point(0,0,1));
|
||||
|
||||
// power_test_2(p,q,r,s)
|
||||
result = traits_6.side_of_oriented_circle_on_sphere_2_object()(P0, P2, P1, P5);
|
||||
assert(result == CGAL::ON_POSITIVE_SIDE);
|
||||
result = traits_6.side_of_oriented_circle_on_sphere_2_object()(P0, P2, P1, P4);
|
||||
assert(result == CGAL::ON_NEGATIVE_SIDE);
|
||||
result = traits_6.side_of_oriented_circle_on_sphere_2_object()(P0, P1, P1, P10);
|
||||
assert(result == CGAL::ON_ORIENTED_BOUNDARY);
|
||||
|
||||
// power_test_2(p,q,r) where p,q and r are coplanar points
|
||||
// result = traits_6.power_test_2_object()(P14, P1, P12);
|
||||
// assert(result == CGAL::ON_POSITIVE_SIDE);
|
||||
// result = traits_6.power_test_2_object()(P1, P2, P6);
|
||||
// assert(result == CGAL::ON_ORIENTED_BOUNDARY);
|
||||
// result = traits_6.power_test_2_object()(P14, P1, P11);
|
||||
// assert(result == CGAL::ON_NEGATIVE_SIDE);
|
||||
|
||||
// power_test_2(p,q) where p, q and sphere are colinear
|
||||
// result = traits_6.power_test_2_object()(P13, P0);
|
||||
// assert(result == CGAL::ON_POSITIVE_SIDE);
|
||||
// result = traits_6.power_test_2_object()(P13, P13);
|
||||
// assert(result == CGAL::ON_ORIENTED_BOUNDARY);
|
||||
// result = traits_6.power_test_2_object()(P0, P13);
|
||||
// assert(result == CGAL::ON_NEGATIVE_SIDE);
|
||||
|
||||
std::cout << "Test Orientation_on_sphere_2" << std::endl;
|
||||
Point p21( 0.5, 0.5, sqrt(0.75));
|
||||
Point p22(-0.5, 0.5, sqrt(0.75));
|
||||
Point p23( 0, -1, sqrt(0.75));
|
||||
Point p24( 0, 0, -1);
|
||||
Point p25( 0, 0, -1.5);
|
||||
Point p26( 1, 1, 2*sqrt(0.75));
|
||||
|
||||
result = traits.orientation_on_sphere_2_object()(p21, p22, p23);
|
||||
assert(result == CGAL::ON_POSITIVE_SIDE);
|
||||
result = traits.orientation_on_sphere_2_object()(p23, p22, p21);
|
||||
assert(result == CGAL::ON_NEGATIVE_SIDE);
|
||||
|
||||
result = traits.side_of_oriented_circle_on_sphere_2_object()(p24, p21, p22, p23);
|
||||
assert(result == CGAL::ON_POSITIVE_SIDE);
|
||||
|
||||
std::cout << "Test Equal_on_sphere_2" << std::endl;
|
||||
bool coradial;
|
||||
coradial = traits.equal_on_sphere_2_object()(p24, p25);
|
||||
assert(coradial);
|
||||
coradial = traits.equal_on_sphere_2_object()(p25, p24);
|
||||
assert(coradial);
|
||||
coradial = traits.equal_on_sphere_2_object()(p21, p26);
|
||||
assert(coradial);
|
||||
coradial = traits.equal_on_sphere_2_object()(p22, p26);
|
||||
assert(!coradial);
|
||||
|
||||
std::cout << "Test Collinear_are_strictly_ordered_on_great_circle_2" << std::endl;
|
||||
Point p31(1,1,1);
|
||||
Point p32(-1,1,1);
|
||||
Point p33(0, sqrt(1.5),sqrt(1.5));
|
||||
Point p34(0, -sqrt(2),-1);
|
||||
Point p35(0.9,0.9,0.9);
|
||||
Point p36(0, sqrt(2.5),0);
|
||||
|
||||
bool inside;
|
||||
// cone defined by 0, p31 and p32
|
||||
inside = traits.collinear_are_strictly_ordered_on_great_circle_2_object()(p31, p32, p33);
|
||||
assert(inside);
|
||||
inside = traits.collinear_are_strictly_ordered_on_great_circle_2_object()(p31, p32, p34);
|
||||
assert(!inside);
|
||||
inside = traits.collinear_are_strictly_ordered_on_great_circle_2_object()(p31, p32, p35);
|
||||
assert(!inside);
|
||||
//not coplanar
|
||||
inside = traits.collinear_are_strictly_ordered_on_great_circle_2_object()(p31, p32, p36);
|
||||
assert(!inside);
|
||||
|
||||
std::cout << "Done" << std::endl;
|
||||
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
Loading…
Reference in New Issue