Merge pull request #4639 from janetournois/Triangulation_segment_traverser_3-tvanlank__rewrote_history-GF

Small feature - Triangulation Segment Cell/Simplex Iterator
This commit is contained in:
Laurent Rineau 2020-11-10 08:45:38 +01:00
commit d0dd5a93bf
22 changed files with 10227 additions and 1 deletions

2
.gitignore vendored
View File

@ -1,5 +1,7 @@
/*build*
/*/*/*/build
/*/*/*/VC*
/*/*/*/GCC
AABB_tree/demo/AABB_tree/AABB_demo
AABB_tree/demo/AABB_tree/Makefile
AABB_tree/examples/AABB_tree/*.kdev*

View File

@ -4,6 +4,13 @@ Release History
[Release 5.2](https://github.com/CGAL/cgal/releases/tag/v5.2)
-----------
### [3D Triangulations](https://doc.cgal.org/5.2/Manual/packages.html#PkgTriangulation3)
- Add `Segment_cell_iterator` to iterate over cells intersected by a line segment.
- Add `Segment_simplex_iterator` to iterate over simplices intersected by a line segment.
[Release 5.1](https://github.com/CGAL/cgal/releases/tag/releases%2FCGAL-5.1)
-----------
Release date: December 2020
### [CGAL and the Boost Graph Library (BGL)](https://doc.cgal.org/5.2/Manual/packages.html#PkgBGL)

View File

@ -23,6 +23,7 @@
#include <CGAL/iterator.h>
#include <boost/config.hpp>
#include <boost/iterator.hpp>
#include <functional>

View File

@ -45,6 +45,8 @@ create_single_source_cgal_program( "simple.cpp" )
create_single_source_cgal_program( "Triangulation_benchmark_3.cpp" )
create_single_source_cgal_program( "segment_traverser_benchmark.cpp" )
find_package(benchmark)
if(TARGET benchmark::benchmark)

View File

@ -0,0 +1,131 @@
// Copyright (c) 2019 GeometryFactory (France).
// All rights reserved.
//
// This file is part of CGAL (www.cgal.org).
// You can redistribute it and/or modify it under the terms of the GNU
// General Public License as published by the Free Software Foundation,
// either version 3 of the License, or (at your option) any later version.
//
// Licensees holding a valid commercial license may use this file in
// accordance with the commercial license agreement provided with the software.
//
// This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
// WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
//
// $URL$
// $Id$
//
//
#include <CGAL/Exact_predicates_exact_constructions_kernel.h>
#include <CGAL/Exact_predicates_inexact_constructions_kernel.h>
#include <CGAL/Delaunay_triangulation_3.h>
#include <CGAL/Triangulation_segment_traverser_3.h>
#include <iostream>
#include <vector>
#include <CGAL/Random.h>
#include <CGAL/Timer.h>
// Define the kernel.
typedef CGAL::Exact_predicates_exact_constructions_kernel Epeck;
typedef CGAL::Exact_predicates_inexact_constructions_kernel Epick;
template<typename Kernel>
void bench_segment_traverser(const int nb_queries,
const int nbv,
const double rad,
CGAL::Random& rng)
{
typedef CGAL::Delaunay_triangulation_3<Kernel> DT;
typedef CGAL::Triangulation_segment_simplex_iterator_3<DT> Simplex_traverser;
typedef CGAL::Triangulation_segment_cell_iterator_3<DT> Cell_traverser;
typedef typename DT::Point_3 Point_3;
typedef typename DT::Cell Cell;
std::cout << "\nBench :\t " << nb_queries << " queries," << std::endl
<< "\t in triangulation of size " << nbv << std::endl
<< "\t lying in the sphere (-" << rad << "; " << rad << ")" << std::endl
<< "\t and Kernel : " << typeid(Kernel()).name() << std::endl;
// Collect random points to build a triangulation
std::vector<Point_3> points(nbv);
int i = 0;
while (i < nbv)
{
points[i++] = Point_3(rng.get_double(-rad, rad),
rng.get_double(-rad, rad),
rng.get_double(-rad, rad));
}
// Construct the Delaunay triangulation.
DT dt(points.begin(), points.end());
assert(dt.is_valid());
// Collect random segments for queries in [-2*rad, 2*rad]
std::vector<Point_3> segments(2 * nb_queries);
i = 0;
while (i < 2 * nb_queries)
{
segments[i++] = Point_3(rng.get_double(-2 * rad, 2 * rad),
rng.get_double(-2 * rad, 2 * rad),
rng.get_double(-2 * rad, 2 * rad));
}
CGAL::Timer timer_st, timer_ct;
timer_st.reset();
timer_ct.reset();
for (i = 0; i < nb_queries; ++i)
{
//Simplex traverser
timer_st.start();
Simplex_traverser st(dt, segments[2*i], segments[2*i + 1]);
// Count the number of finite cells traversed.
unsigned int inf = 0, fin = 0;
for (; st != st.end(); ++st)
{
Cell c = st.cell();
// if (dt.is_infinite(c)) ++inf;
// else ++fin;
}
timer_st.stop();
//Cell traverser
timer_ct.start();
Cell_traverser ct(dt, segments[2*i], segments[2*i + 1]);
// Count the number of finite cells traversed.
inf = 0, fin = 0;
for (; ct != ct.end(); ++ct)
{
Cell c = ct.cell();
// if (dt.is_infinite(c)) ++inf;
// else ++fin;
}
timer_ct.stop();
}
std::cout << "Simplex traverser took " << timer_st.time() << " seconds." << std::endl;
std::cout << "Cell traverser took " << timer_ct.time() << " seconds." << std::endl;
}
int main(int argc, char* argv[])
{
CGAL::Random rng;
std::cout << "CGAL::Random seed is " << rng.get_seed() << std::endl;
//nb of segments tested
const int nb_queries = (argc > 1) ? atoi(argv[1]) : 100;
//nb of vertices in triangulation
const int nbv = (argc > 2) ? atoi(argv[2]) : 1000;
//radius of sphere including the triangulation
const double rad = (argc > 3) ? atof(argv[3]) : 10.;
// bench_segment_traverser<Epeck>(nb_queries, nbv, rad, rng);
bench_segment_traverser<Epick>(nb_queries, nbv, rad, rng);
}

View File

@ -220,6 +220,20 @@ circulator over all facets incident to a given edge
*/
typedef Triangulation_data_structure::Facet_circulator Facet_circulator;
/*!
iterator over cells intersected by a line segment.
`Segment_cell_iterator` implements the concept `ForwardIterator` and is non-mutable.
Its value type is `Cell_handle`.
*/
typedef unspecified_type Segment_cell_iterator;
/*!
iterator over simplices intersected by a line segment.
`Segment_simplex_iterator` implements the concept `ForwardIterator` and is non-mutable.
Its value type is `Triangulation_simplex_3 `.
*/
typedef unspecified_type Segment_simplex_iterator;
/// @}
/*! \name
@ -279,6 +293,17 @@ that has as value type `Vertex_handle`.
range type for iterating over the points of the finite vertices.
*/
typedef Iterator_range<unspecified_type> Points;
/*!
range type for iterating over the cells intersected by a line segment.
*/
typedef Iterator_range<unspecified_type> Segment_traverser_cell_handles;
/*!
range type for iterating over the simplices intersected by a line segment.
*/
typedef Iterator_range<Segment_simplex_iterator> Segment_traverser_simplices;
/// @}
/// \name Creation
@ -1278,6 +1303,182 @@ Finite_vertex_handles finite_vertex_handles() const;
*/
Points points() const;
/*!
returns a range of iterators over the cells intersected by a line segment
*/
Segment_traverser_cell_handles segment_traverser_cell_handles() const;
/*!
returns a range of iterators over the simplices intersected by a line segment
*/
Segment_traverser_simplices segment_traverser_simplices() const;
/// @}
/*!\name Segment Cell Iterator
The triangulation defines an iterator that visits cells intersected by a line segment.
Segment Cell Iterator iterates over a sequence of cells which union contains the segment `[s,t]`.
The sequence of cells is "minimal" (removing any cell would make the union of the
renaming cells not entirely containing `[s,t]`) and sorted along `[s,t]`.
The "minimality" of the sequence implies that in degenerate cases,
only one cell incident to the traversed simplex will be reported.
The cells visited form a facet-connected region containing both source and target points of the line segment `[s,t]`.
Each cell falls within one or more of the following categories:
1. a finite cell whose interior is intersected by `[s,t]`.
2. a finite cell with a facet `f` whose interior is intersected by `[s,t]` in a line segment.
If such a cell is visited, its neighbor incident to `f` is not visited.
3. a finite cell with an edge `e` whose interior is intersected by `[s,t]` in a line segment.
If such a cell is visited, none of the other cells incident to `e` are visited.
4. a finite cell with an edge `e` whose interior is intersected by `[s,t]` in a point.
This cell forms a connected component together with the other cells incident to `e` that are visited.
Exactly two of these visited cells also fall in category 1 or 2.
5. a finite cell with a vertex `v` that is an endpoint of `[s,t]`.
This cell also fits in either category 1 or 2.
6. a finite cell with a vertex `v` that lies in the interior of `[s,t]`.
This cell forms a connected component together with the other cells incident to `v` that are visited.
Exactly two of these cells also fall in category 1 or 2.
7. an infinite cell with a finite facet whose interior is intersected by the interior of `[s,t]`.
8. an infinite cell with a finite edge `e` whose interior is intersected by the interior of `[s,t]`.
If such a cell is visited, its infinite neighbor incident to `e` is not visited.
Among the finite cells incident to `e` that are visited,
exactly one also falls in category 1 or 2.
9. an infinite cell with a finite vertex `v` that lies in the interior of `[s,t]`.
If such a cell is visited, none of the other infinite cells incident to `v` are visited.
Among the finite cells incident to `v` that are visited,
exactly one also falls in category 1, 2, or 3.
10. an infinite cell in the special case where the segment does not intersect any finite facet.
In this case, exactly one infinite cell is visited.
This cell shares a facet `f` with a finite cell `c` such that `f` is intersected by the line through
the point `s` and the vertex of `c` opposite of `f`.
Note that for categories 4 and 6, it is not predetermined which incident cells are visited.
However, exactly two of the incident cells `c0,c1` visited also fall in category 1 or 2.
The remaining incident cells visited make a facet-connected sequence connecting `c0` to `c1`.
`Segment_cell_iterator` implements the concept `ForwardIterator` and is non-mutable.
It is invalidated by any modification of one of the cells traversed.
Its `value_type` is `Cell_handle`.
*/
/// @{
/*!
returns the iterator that allows to visit the cells intersected by the line segment `[vs,vt]`.
The initial value of the iterator is the cell containing `vs` and intersected by the
line segment `[vs,vt]` in its interior.
The first cell incident to `vt` is the last valid value of the iterator.
It is followed by `segment_traverser_cells_end()`.
\pre `vs` and `vt` must be different vertices and neither can be the infinite vertex.
\pre `triangulation.dimension() >= 2`
*/
Segment_cell_iterator segment_traverser_cells_begin(Vertex_handle vs, Vertex_handle vt) const;
/*!
returns the iterator that allows to visit the cells intersected by the line segment `[ps, pt]`.
If `[ps,pt]` entirely lies outside the convex hull, the iterator visits exactly one infinite cell.
The initial value of the iterator is the cell containing `ps`.
If more than one cell
contains `ps` (e.g. if `ps` lies on a vertex),
the initial value is the cell intersected by
the interior of the line segment `[ps,pt]`.
If `ps` lies outside the convex hull and `pt` inside the convex full,
the initial value is the infinite cell which finite facet is intersected by
the interior of `[ps,pt]`.
The first cell containing `pt` is the last valid value of the iterator.
It is followed by `segment_traverser_cells_end()`.
The optional argument `hint` can reduce the time to construct the iterator
if it is geometrically close to `ps`.
\pre `ps` and `pt` must be different points.
\pre `triangulation.dimension() >= 2`. If the dimension is 2, both `ps` and `pt` must lie in the affine hull.
*/
Segment_cell_iterator segment_traverser_cells_begin(const Point& ps, const Point& pt, Cell_handle hint = Cell_handle()) const;
/*!
returns the past-the-end iterator over the intersected cells.
This iterator cannot be dereferenced. It indicates when the `Segment_cell_iterator` has
passed the target.
\pre `triangulation.dimension() >= 2`
*/
Segment_cell_iterator segment_traverser_cells_end() const;
/// @}
/*!\name Segment Simplex Iterator
The triangulation defines an iterator that visits all the triangulation simplices
(vertices, edges, facets and cells) intersected by a line segment.
The iterator traverses a connected sequence of simplices - possibly of all dimensions -
intersected by the line segment `[s, t]`.
In the degenerate case where the query segment goes exactly through a vertex
(or along an edge, or along a facet), only one of the cells incident to that vertex
(or edge, or facet) is returned by the iterator, and not all of them.
Each simplex falls within one or more of the following categories:
1. a finite cell whose interior is intersected by `[s,t]`,
2. a facet `f` whose interior is intersected by `[s,t]` in a point,
3. a facet `f` whose interior is intersected by `[s,t]` in a line segment,
4. an edge `e` whose interior is intersected by `[s,t]` in a point,
5. an edge `e` whose interior is intersected by `[s,t]` in a line segment,
6. a vertex `v` lying on `[s,t]`,
7. an infinite cell with a finite facet whose interior is intersected by the interior of `[s,t]`,
8. an infinite cell in the special case where the segment does not intersect any finite facet.
In this case, exactly one infinite cell is visited.
This cell shares a facet `f` with a finite cell `c` such that `f` is intersected by the line through
the source of `[s,t]` and the vertex of `c` opposite of `f`.
`Segment_simplex_iterator` implements the concept `ForwardIterator` and is non-mutable.
It is invalidated by any modification of one of the cells traversed.
Its `value_type` is `Triangulation_simplex_3`.
*/
/// @{
/*!
returns the iterator that allows to visit the simplices intersected by the line segment `[vs,vt]`.
The initial value of the iterator is `vs`.
The iterator remains valid until `vt` is passed.
\pre `vs` and `vt` must be different vertices and neither can be the infinite vertex.
\pre `triangulation.dimension() >= 2`
*/
Segment_simplex_iterator segment_traverser_simplices_begin(Vertex_handle vs, Vertex_handle vt) const;
/*!
returns the iterator that allows to visit the simplices intersected by the line segment `[ps,pt]`.
If `[ps,pt]` entirely lies outside the convex hull, the iterator visits exactly one infinite cell.
The initial value of the iterator is the lowest dimension simplex containing `ps`.
The iterator remains valid until the first simplex containing `pt` is passed.
The optional argument `hint` can reduce the time to construct the iterator if it is close to `ps`.
\pre `ps` and `pt` must be different points.
\pre `triangulation.dimension() >= 2`. If the dimension is 2, both `ps` and `pt` must lie in the affine hull.
*/
Segment_simplex_iterator segment_traverser_simplices_begin(const Point& ps, const Point& pt, Cell_handle hint = Cell_handle()) const;
/*!
returns the past-the-end iterator over the intersected simplices.
This iterator cannot be dereferenced. It indicates when the `Segment_simplex_iterator` has
passed the target.
\pre `triangulation.dimension() >= 2`
*/
Segment_simplex_iterator segment_traverser_simplices_end() const;
/// @}

View File

@ -6,7 +6,6 @@
/// \defgroup PkgTriangulation3TriangulationClasses Triangulation Classes
/// \ingroup PkgTriangulation3Ref
/// \defgroup PkgTriangulation3TraitsClasses Traits Classes
/// \ingroup PkgTriangulation3Ref

View File

@ -517,6 +517,14 @@ simplices can be stored in a set.
\cgalExample{Triangulation_3/fast_location_3.cpp}
\subsection Triangulation3exsegmenttraverser Traversing the Triangulation Along a Segment
The package provides iterators that can be used to traverse the triangulation along a segment.
It is guaranteed that the input segment intersects all cells (resp. simplices) visited by this traversal iterator.
\cgalExample{Triangulation_3/segment_cell_traverser_3.cpp}
\cgalExample{Triangulation_3/segment_simplex_traverser_3.cpp}
\subsection Triangulation_3FindingtheCellsinConflict Finding the Cells in Conflict with a Point in a Delaunay Triangulation
\cgalExample{Triangulation_3/find_conflicts_3.cpp}
@ -1121,6 +1129,11 @@ Teillaud in the framework of the Google Summer of Code, 2010.
In 2013, Clément Jamin added parallel algorithms (insert, remove) to the
Delaunay and regular triangulations.
In 2014, Thijs van Lankveld implemented the segment cell traverser iterator.
In 2018, Jane Tournois introduced the segment simplex traverser iterator
and finalized both iterators that were integrated in release 5.2.
Olivier Devillers contributed to boost the performances of the cell traverser.
The authors wish to thank Lutz Kettner for inspiring discussions about
the design of \cgal. Jean-Daniel Boissonnat is also acknowledged
\cgalCite{bdty-tcgal-00}.

View File

@ -8,6 +8,8 @@
\example Triangulation_3/info_insert_with_transform_iterator.cpp
\example Triangulation_3/simplex.cpp
\example Triangulation_3/fast_location_3.cpp
\example Triangulation_3/segment_cell_traverser_3.cpp
\example Triangulation_3/segment_simplex_traverser_3.cpp
\example Triangulation_3/find_conflicts_3.cpp
\example Triangulation_3/regular_3.cpp
\example Triangulation_3/regular_with_info_3.cpp

View File

@ -17,6 +17,8 @@ if(CGAL_Qt5_FOUND)
add_definitions(-DCGAL_USE_BASIC_VIEWER -DQT_NO_KEYWORDS)
endif()
include_directories(BEFORE "../../include")
if ( CGAL_FOUND )
create_single_source_cgal_program( "for_loop.cpp" )
create_single_source_cgal_program( "adding_handles_3.cpp" )
@ -29,6 +31,8 @@ if ( CGAL_FOUND )
create_single_source_cgal_program( "info_insert_with_transform_iterator.cpp" )
create_single_source_cgal_program( "info_insert_with_zip_iterator.cpp" )
create_single_source_cgal_program( "regular_3.cpp" )
create_single_source_cgal_program( "segment_cell_traverser_3.cpp" )
create_single_source_cgal_program( "segment_simplex_traverser_3.cpp" )
create_single_source_cgal_program( "regular_with_info_3.cpp" )
create_single_source_cgal_program( "simple_triangulation_3.cpp" )
create_single_source_cgal_program( "simplex.cpp" )

View File

@ -22,6 +22,11 @@ in a triangulation, when he needs to add handles in it.
This example shows the use of the Fast_location policy to speed up
point location queries in a Delaunay triangulation.
------- segment_traverser_3 --------------------------------------------
This example shows how to use a Triangulation_segment_cell_iterator_3
to traverse the triangulation in a straight line.
------- tds --------------------------------------------------
Shows how to construct a 3D triangulation data structure by

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,109 @@
#include <CGAL/Exact_predicates_inexact_constructions_kernel.h>
#include <CGAL/Delaunay_triangulation_3.h>
#include <assert.h>
#include <iostream>
#include <fstream>
#include <string>
#include <CGAL/IO/read_xyz_points.h>
#include <CGAL/Random.h>
// Define the kernel.
typedef CGAL::Exact_predicates_inexact_constructions_kernel Kernel;
typedef Kernel::Point_3 Point_3;
// Define the structure.
typedef CGAL::Delaunay_triangulation_3< Kernel > DT;
typedef DT::Cell_handle Cell_handle;
typedef DT::Segment_cell_iterator Segment_cell_iterator;
int main(int argc, char* argv[])
{
const char* fname = (argc>1) ? argv[1] : "data/blobby.xyz";
std::vector<Point_3> points;
std::ifstream stream(fname);
if (!stream ||
!CGAL::read_xyz_points(stream, std::back_inserter(points)))
{
std::cerr << "Error: cannot read file " << fname << std::endl;
return EXIT_FAILURE;
}
//bbox
double xmin = points[0].x();
double xmax = points[0].x();
double ymin = points[0].y();
double ymax = points[0].y();
double zmin = points[0].z();
double zmax = points[0].z();
for(const Point_3& p : points)
{
xmin = (std::min)(xmin, p.x());
ymin = (std::min)(ymin, p.y());
zmin = (std::min)(zmin, p.z());
xmax = (std::max)(xmax, p.x());
ymax = (std::max)(ymax, p.y());
zmax = (std::max)(zmax, p.z());
}
// Construct the Delaunay triangulation.
DT dt( points.begin(), points.end() );
assert( dt.is_valid() );
CGAL::Random rng;
std::cout << "Random seed is " << CGAL::get_default_random().get_seed() << std::endl;
////////////////////////////////////////////////////////////
// Construct a traverser and use begin/end iterators
////////////////////////////////////////////////////////////
Point_3 p1(rng.get_double(xmin, xmax),
rng.get_double(ymin, ymax),
rng.get_double(zmin, zmax));
Point_3 p2(rng.get_double(xmin, xmax),
rng.get_double(ymin, ymax),
rng.get_double(zmin, zmax));
Segment_cell_iterator ct = dt.segment_traverser_cells_begin(p1, p2);
Segment_cell_iterator ctend = dt.segment_traverser_cells_end();
// Count the number of finite cells traversed.
unsigned int inf = 0, fin = 0;
for( ; ct != ctend; ++ct )
{
if( dt.is_infinite(ct) )
++inf;
else
++fin;
}
std::cout << "While traversing from " << p1 << " to " << p2 << std::endl;
std::cout << inf << " infinite and "
<< fin << " finite cells were visited." << std::endl;
std::cout << std::endl << std::endl;
////////////////////////////////////////////////////////////
// Construct a traverser and use range-iterator
////////////////////////////////////////////////////////////
// Count the number of finite cells traversed.
inf = 0, fin = 0;
for (const Cell_handle ch : dt.segment_traverser_cell_handles(p1, p2))
{
if (dt.is_infinite(ch))
++inf;
else
++fin;
}
std::cout << "While traversing from " << p1 << " to " << p2 << std::endl;
std::cout << inf << " infinite and "
<< fin << " finite cells were visited." << std::endl;
std::cout << std::endl << std::endl;
return 0;
}

View File

@ -0,0 +1,98 @@
#include <CGAL/Exact_predicates_inexact_constructions_kernel.h>
#include <CGAL/Delaunay_triangulation_3.h>
#include <assert.h>
#include <iostream>
#include <fstream>
#include <string>
#include <CGAL/IO/read_xyz_points.h>
#include <CGAL/Random.h>
#define CGAL_TRIANGULATION_3_VERBOSE_TRAVERSER_EXAMPLE
// Define the kernel.
typedef CGAL::Exact_predicates_inexact_constructions_kernel Kernel;
typedef Kernel::Point_3 Point_3;
// Define the structure.
typedef CGAL::Delaunay_triangulation_3<Kernel> DT;
typedef DT::Segment_simplex_iterator Segment_simplex_iterator;
typedef CGAL::Triangulation_simplex_3<DT::Triangulation_data_structure> Simplex;
int main(int argc, char* argv[])
{
const char* fname = (argc>1) ? argv[1] : "data/blobby.xyz";
std::vector<Point_3> points;
std::ifstream stream(fname);
if (!stream ||
!CGAL::read_xyz_points(stream, std::back_inserter(points)))
{
std::cerr << "Error: cannot read file " << fname << std::endl;
return EXIT_FAILURE;
}
// Construct the Delaunay triangulation.
DT dt( points.begin(), points.end() );
assert( dt.is_valid() );
CGAL::Random rng;
std::cout << "Random seed is " << CGAL::get_default_random().get_seed() << std::endl;
unsigned int nb_cells = 0, nb_facets = 0, nb_edges = 0, nb_vertex = 0;
////////////////////////////////////////////////////////////
// Construct a traverser and use begin/end iterators
////////////////////////////////////////////////////////////
Point_3 p1(rng.get_double(-0.48, 0.31),
rng.get_double(-0.22, 0.22),
rng.get_double(-0.19, 0.19));
Point_3 p2(rng.get_double(-0.48, 0.31),
rng.get_double(-0.22, 0.22),
rng.get_double(-0.19, 0.19));
Segment_simplex_iterator st = dt.segment_traverser_simplices_begin(p1, p2);
Segment_simplex_iterator stend = dt.segment_traverser_simplices_end();
for (; st != stend; ++st)
{
if (st->dimension() == 3) ++nb_cells;
else if (st->dimension() == 2) ++nb_facets;
else if (st->dimension() == 1) ++nb_edges;
else if (st->dimension() == 0) ++nb_vertex;
}
#ifdef CGAL_TRIANGULATION_3_VERBOSE_TRAVERSER_EXAMPLE
std::cout << "While traversing from " << p1 << " to " << p2 << std::endl;
std::cout << "\tcells : " << nb_cells << std::endl;
std::cout << "\tfacets : " << nb_facets << std::endl;
std::cout << "\tedges : " << nb_edges << std::endl;
std::cout << "\tvertices : " << nb_vertex << std::endl;
std::cout << std::endl << std::endl;
#endif
////////////////////////////////////////////////////////////
// Construct a traverser and use range-iterator
////////////////////////////////////////////////////////////
nb_cells = 0, nb_facets = 0, nb_edges = 0, nb_vertex = 0;
for (const Simplex& s : dt.segment_traverser_simplices(p1, p2))
{
if (s.dimension() == 3) ++nb_cells;
else if (s.dimension() == 2) ++nb_facets;
else if (s.dimension() == 1) ++nb_edges;
else if (s.dimension() == 0) ++nb_vertex;
}
#ifdef CGAL_TRIANGULATION_3_VERBOSE_TRAVERSER_EXAMPLE
std::cout << "While traversing from " << p1 << " to " << p2 << std::endl;
std::cout << "\tcells : " << nb_cells << std::endl;
std::cout << "\tfacets : " << nb_facets << std::endl;
std::cout << "\tedges : " << nb_edges << std::endl;
std::cout << "\tvertices : " << nb_vertex << std::endl;
std::cout << std::endl << std::endl;
#endif
return 0;
}

View File

@ -43,6 +43,8 @@
#include <CGAL/spatial_sort.h>
#include <CGAL/Spatial_sort_traits_adapter_3.h>
#include <CGAL/Triangulation_segment_traverser_3.h>
#include <CGAL/iterator.h>
#include <CGAL/function_objects.h>
#include <CGAL/Iterator_project.h>
@ -524,6 +526,12 @@ public:
typedef Iterator_range<Finite_edges_iterator> Finite_edges;
typedef Iterator_range<Finite_facets_iterator> Finite_facets;
typedef Triangulation_segment_cell_iterator_3<Self> Segment_cell_iterator;
typedef Triangulation_segment_simplex_iterator_3<Self> Segment_simplex_iterator;
typedef Iterator_range<Prevent_deref<Segment_cell_iterator> > Segment_traverser_cell_handles;
typedef Iterator_range<Segment_simplex_iterator> Segment_traverser_simplices;
private:
// Auxiliary iterators for convenience
// do not use default template argument to please VC++
@ -2196,6 +2204,73 @@ public:
return _tds.incident_edges_threadsafe(v, edges, Finite_filter(this));
}
//// Segment Cell Iterator
Segment_cell_iterator segment_traverser_cells_begin(Vertex_handle vs,
Vertex_handle vt) const
{
Segment_cell_iterator it(this, vs, vt);
return it;
}
Segment_cell_iterator segment_traverser_cells_begin(const Point& ps,
const Point& pt,
Cell_handle hint = Cell_handle()) const
{
Segment_cell_iterator it(this, ps, pt, hint);
return it;
}
Segment_cell_iterator segment_traverser_cells_end() const
{
Segment_cell_iterator it(this);
return it.end();
}
Segment_traverser_cell_handles segment_traverser_cell_handles(Vertex_handle vs,
Vertex_handle vt) const
{
return make_prevent_deref_range(segment_traverser_cells_begin(vs, vt),
segment_traverser_cells_end());
}
Segment_traverser_cell_handles segment_traverser_cell_handles(const Point& ps,
const Point& pt,
Cell_handle hint = Cell_handle()) const
{
return make_prevent_deref_range(segment_traverser_cells_begin(ps, pt, hint),
segment_traverser_cells_end());
}
//// Segment Simplex Iterator
Segment_simplex_iterator segment_traverser_simplices_begin(Vertex_handle vs,
Vertex_handle vt) const
{
Segment_simplex_iterator it(this, vs, vt);
return it;
}
Segment_simplex_iterator segment_traverser_simplices_begin(const Point& ps,
const Point& pt,
Cell_handle hint = Cell_handle()) const
{
Segment_simplex_iterator it(this, ps, pt, hint);
return it;
}
Segment_simplex_iterator segment_traverser_simplices_end() const
{
Segment_simplex_iterator it(this);
return it.end();
}
Segment_traverser_simplices segment_traverser_simplices(Vertex_handle vs,
Vertex_handle vt) const
{
return Segment_traverser_simplices(segment_traverser_simplices_begin(vs, vt),
segment_traverser_simplices_end());
}
Segment_traverser_simplices segment_traverser_simplices(const Point& ps,
const Point& pt,
Cell_handle hint = Cell_handle()) const
{
return Segment_traverser_simplices(segment_traverser_simplices_begin(ps, pt, hint),
segment_traverser_simplices_end());
}
size_type degree(Vertex_handle v) const
{
return _tds.degree(v);

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -27,6 +27,9 @@ if ( CGAL_FOUND )
create_single_source_cgal_program( "test_RT_cell_base_with_weighted_circumcenter_3.cpp" )
create_single_source_cgal_program( "test_robust_weighted_circumcenter.cpp" )
create_single_source_cgal_program( "test_simplex_3.cpp" )
create_single_source_cgal_program( "test_simplex_iterator_3.cpp" )
create_single_source_cgal_program( "test_segment_cell_traverser_3.cpp" )
create_single_source_cgal_program( "test_segment_simplex_traverser_3.cpp" )
create_single_source_cgal_program( "test_static_filters.cpp" )
create_single_source_cgal_program( "test_triangulation_3.cpp" )
create_single_source_cgal_program( "test_io_triangulation_3.cpp" )

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,94 @@
#include <CGAL/Exact_predicates_inexact_constructions_kernel.h>
#include <CGAL/Delaunay_triangulation_3.h>
#include <assert.h>
#include <iostream>
#include <fstream>
// Define the kernel.
typedef CGAL::Exact_predicates_inexact_constructions_kernel Kernel;
typedef Kernel::Point_3 Point_3;
// Define the structure.
typedef CGAL::Delaunay_triangulation_3< Kernel > DT;
typedef DT::Cell_handle Cell_handle;
typedef DT::Segment_cell_iterator Segment_cell_iterator;
int main()
{
const std::vector<Point_3> points = { { -2, 0, 0 },
{ 2, 0, 0 },
{ 0, 1, -1 },
{ 0, -1, -1 },
{ 0, 0, 1 },
{ -10, -10, -10 },
{ -10, 10, -10 },
{ 10, 10, -10 },
{ 10, -10, -10 },
{ -10, -10, 10 },
{ -10, 10, 10 },
{ 10, 10, 10 },
{ 10, -10, 10 },
};
std::vector<DT::Vertex_handle> vertices;
vertices.reserve(points.size());
DT dt;
for(auto p: points) vertices.push_back(dt.insert(p));
Cell_handle c;
assert( dt.is_valid() );
assert( dt.is_cell(vertices[0], vertices[2], vertices[3], vertices[4], c));
assert( dt.is_cell(vertices[1], vertices[2], vertices[3], vertices[4], c));
std::cerr << dt.number_of_finite_cells() << '\n';
Segment_cell_iterator ct = dt.segment_traverser_cells_begin(points[0], points[1]);
Segment_cell_iterator ctend = dt.segment_traverser_cells_end();
// Count the number of finite cells traversed.
unsigned int inf = 0, fin = 0;
while(ct != ctend)
{
std::cerr << "Cell ( ";
for(int i = 0; i < 4; ++i)
std::cerr << ct->vertex(i)->point() << " ";
std::cerr << " )\n";
if( dt.is_infinite(ct) )
++inf;
else
++fin;
++ct;
}
std::cout << "While traversing from " << points[0]
<< " to " << points[1] << std::endl;
std::cout << inf << " infinite and "
<< fin << " finite cells were visited." << std::endl;
inf = 0;
fin = 0;
for (Cell_handle ch : dt.segment_traverser_cell_handles(vertices[2], vertices[3]))
{
std::cerr << "Cell ( ";
for (int i = 0; i < 4; ++i)
std::cerr << ch->vertex(i)->point() << " ";
std::cerr << " )\n";
if (dt.is_infinite(ch))
++inf;
else
++fin;
}
std::cout << "While traversing from " << vertices[2]->point()
<< " to " << vertices[3]->point() << std::endl;
std::cout << inf << " infinite and "
<< fin << " finite cells were visited." << std::endl;
return 0;
}

View File

@ -0,0 +1,181 @@
#include <CGAL/Exact_predicates_inexact_constructions_kernel.h>
#include <CGAL/Delaunay_triangulation_3.h>
#include <assert.h>
#include <iostream>
#include <fstream>
#include <string>
#include <tuple>
#include <array>
#include <CGAL/Random.h>
#define CGAL_TRIANGULATION_3_VERBOSE_TRAVERSER_EXAMPLE
// Define the kernel.
typedef CGAL::Exact_predicates_inexact_constructions_kernel Kernel;
typedef Kernel::Point_3 Point_3;
// Define the structure.
typedef CGAL::Delaunay_triangulation_3<Kernel> DT;
typedef DT::Cell_handle Cell_handle;
typedef DT::Segment_simplex_iterator Segment_simplex_iterator;
bool test(const DT& dt,
const std::pair<Point_3, Point_3>& query,
const std::array<unsigned, 4>& expected_result);
int main(int, char* [])
{
const std::vector<Point_3> points = { { -2, 0, 0 },
{ 2, 0, 0 },
{ 0, 1, -1 },
{ 0, -1, -1 },
{ 0, 0, 1 },
{ -10, -10, -10 },
{ -10, 10, -10 },
{ 10, 10, -10 },
{ 10, -10, -10 },
{ -10, -10, 10 },
{ -10, 10, 10 },
{ 10, 10, 10 },
{ 10, -10, 10 },
};
std::vector<DT::Vertex_handle> vertices;
vertices.reserve(points.size());
DT dt;
for(auto p: points) vertices.push_back(dt.insert(p));
Cell_handle c;
assert(dt.is_valid());
assert(dt.is_cell(vertices[0], vertices[2], vertices[3], vertices[4], c));
assert(dt.is_cell(vertices[1], vertices[2], vertices[3], vertices[4], c));
std::cerr << dt.number_of_finite_cells() << '\n';
const std::vector < std::pair<Point_3, Point_3>> queries = {
{{-1, 0, 0}, { 1, 0, 0}}, // CFC
{{-1, 0, 0}, { 2, 0, 0}}, // CFCV
{{ 2, 0, 0}, {-1, 0, 0}}, // reverse
{{-2, 0, 0}, { 2, 0, 0}}, // VCFCV
{{ 2, 0, 0}, {-2, 0, 0}}, // reverse case: VCFCV
{{-3, 0, 0}, { 3, 0, 0}}, // FVCFCVF
{{-2, 0, 0}, { 2, 2, -2}}, // VEVF
{{ 2, 2, -2}, {-2, 0, 0}} // reverse case: FVEV
};
const std::vector< std::array<unsigned, 4> > expected_results ={
{0, 0, 1, 2}, // CFC
{1, 0, 1, 2}, // CFCV
{1, 0, 1, 2}, // reverse
{2, 0, 1, 2}, // VCFCV
{2, 0, 1, 2}, // reverse case: VCFCV
{2, 0, 3, 2}, // FVCFCVF
{2, 1, 1, 0}, // VEVF
{2, 1, 1, 0} // reverse case: FVEV
};
bool ok = true;
for(std::size_t i=0; i<queries.size(); ++i) {
if(!test(dt, queries[i], expected_results[i])) ok = false;
}
std::cout << "Done (" << queries.size() << " queries)\n";
return ok ? EXIT_SUCCESS : EXIT_FAILURE;
}
bool test(const DT& dt,
const std::pair<Point_3, Point_3>& query,
const std::array<unsigned, 4>& expected_result)
{
bool result = true;
using std::get;
const auto& p1 = query.first;
const auto& p2 = query.second;
unsigned int nb_cells = 0, nb_collinear = 0;
unsigned int nb_facets = 0, nb_edges = 0, nb_vertex = 0;
std::cout << "\n#\n# Query segment: ( " << p1 << " , "
<< p2 << " )\n#\n";
Segment_simplex_iterator st = dt.segment_traverser_simplices_begin(p1, p2);
Segment_simplex_iterator stend = dt.segment_traverser_simplices_end();
// Count the number of finite cells traversed.
unsigned int inf = 0, fin = 0;
for (; st != stend; ++st)
{
if (st->dimension() == 3
&& dt.is_infinite(Cell_handle(*st)))
++inf;
else {
++fin;
switch (st->dimension()) {
case 2: {
++nb_facets;
std::cout << "facet " << std::endl;
DT::Facet f = *st;
std::cout << " ( " << f.first->vertex((f.second + 1) & 3)->point()
<< " " << f.first->vertex((f.second + 2) & 3)->point()
<< " " << f.first->vertex((f.second + 3) & 3)->point()
<< " )\n";
break;
}
case 1: {
++nb_edges;
std::cout << "edge " << std::endl;
DT::Edge e = *st;
std::cout << " ( " << e.first->vertex(e.second)->point() << " "
<< e.first->vertex(e.third)->point() << " )\n";
break;
}
case 0: {
++nb_vertex;
std::cout << "vertex " << std::endl;
DT::Vertex_handle v = *st;
std::cout << " ( " << v->point() << " )\n";
break;
}
case 3: {
++nb_cells;
std::cout << "cell \n ( ";
DT::Cell_handle ch = *st;
for (int i = 0; i < 4; ++i)
std::cout << ch->vertex(i)->point() << " ";
std::cout << " )\n";
break;
}
default:
CGAL_assume(false);
} // end switch
}
}
#ifdef CGAL_TRIANGULATION_3_VERBOSE_TRAVERSER_EXAMPLE
std::cout << "While traversing from " << st.source()
<< " to " << st.target() << std::endl;
std::cout << "\tinfinite cells : " << inf << std::endl;
std::cout << "\tfinite cells : " << fin << std::endl;
std::cout << "\tfacets : " << nb_facets << std::endl;
std::cout << "\tedges : " << nb_edges << std::endl;
std::cout << "\tvertices : " << nb_vertex << std::endl;
std::cout << std::endl << std::endl;
#endif
auto check_expected = [](unsigned value, unsigned expected) {
if(value != expected) {
std::cout << "\t ERROR: expected " << expected << '\n';
return false;
}
return true;
};
std::cout << "\tnb cells : " << nb_cells << std::endl;
result = result && check_expected(nb_cells, expected_result[3]);
std::cout << "\tnb facets : " << nb_facets << std::endl;
result = result && check_expected(nb_facets, expected_result[2]);
std::cout << "\tnb edges : " << nb_edges << std::endl;
result = result && check_expected(nb_edges, expected_result[1]);
std::cout << "\tnb vertices : " << nb_vertex << std::endl;
result = result && check_expected(nb_vertex, expected_result[0]);
std::cout << "\tnb collinear : " << nb_collinear << std::endl;
return result;
}

View File

@ -0,0 +1,413 @@
#include <CGAL/Exact_predicates_exact_constructions_kernel.h>
#include <CGAL/Delaunay_triangulation_3.h>
#include <assert.h>
#include <iostream>
#include <fstream>
#include <string>
#include <vector>
#include <CGAL/IO/read_xyz_points.h>
#include <CGAL/Random.h>
// Define the kernel.
typedef CGAL::Exact_predicates_exact_constructions_kernel Kernel;
typedef Kernel::Point_3 Point_3;
typedef Kernel::Vector_3 Vector_3;
typedef Kernel::Segment_3 Segment_3;
// Define the structure.
typedef CGAL::Delaunay_triangulation_3< Kernel > DT;
typedef DT::Vertex_handle Vertex_handle;
typedef DT::Cell_handle Cell_handle;
typedef DT::Edge Edge;
typedef DT::Facet Facet;
typedef DT::Segment_simplex_iterator Segment_simplex_iterator;
void test_vertex_edge_vertex(const DT& dt, const std::size_t& nb_tests)
{
std::cout << "* test_vertex_edge_vertex *" << std::endl;
std::vector<Edge> edges;
for (DT::Finite_edges_iterator eit = dt.finite_edges_begin();
eit != dt.finite_edges_end() && edges.size() < nb_tests;
++eit)
{
edges.push_back(*eit);
}
for (std::size_t i = 0; i < nb_tests; ++i)
{
Vertex_handle v1 = edges[i].first->vertex(edges[i].second);
Vertex_handle v2 = edges[i].first->vertex(edges[i].third);
Vector_3 v(v1->point(), v2->point());
std::cout << "TEST " << i << " (" << v1->point()
<< " ** " << v2->point() <<")"
<< std::endl;
std::cout << "\t(";
Segment_simplex_iterator st
= dt.segment_traverser_simplices_begin((v1->point() - 2.*v),
(v2->point() + 3.*v));
Segment_simplex_iterator stend
= dt.segment_traverser_simplices_end();
for (; st != stend; ++st)
{
std::cout << st->dimension();
if(st->dimension() == 3
&& Cell_handle(*st) != Cell_handle()
&& dt.is_infinite(Cell_handle(*st)))
std::cout << "i";
std::cout << " ";
if (st->dimension() == 0 && Vertex_handle(*st) == v1)
{
++st;
std::cout << st->dimension() << " ";
assert(st->dimension() == 1);
Edge e(*st);
Vertex_handle ve1 = e.first->vertex(e.second);
Vertex_handle ve2 = e.first->vertex(e.third);
assert((ve1 == v1 && ve2 == v2)
|| (ve1 == v2 && ve2 == v1));
++st;
std::cout << st->dimension() << " ";
assert(st->dimension() == 0);
assert(Vertex_handle(*st) == v2);
}
}
std::cout << ")" << std::endl;
}
}
void test_edge_facet_edge(const DT& dt, const std::size_t& nb_tests)
{
std::cout << "* test_edge_facet_edge *" << std::endl;
std::vector<Facet> facets;
for (DT::Finite_facets_iterator fit = dt.finite_facets_begin();
fit != dt.finite_facets_end() && facets.size() < nb_tests;
++fit)
{
facets.push_back(*fit);
}
for (std::size_t i = 0; i < nb_tests; ++i)
{
const int fi = facets[i].second;
Vertex_handle v1 = facets[i].first->vertex((fi + 1) % 4);
Vertex_handle v2 = facets[i].first->vertex((fi + 2) % 4);
Vertex_handle v3 = facets[i].first->vertex((fi + 3) % 4);
Point_3 p1 = CGAL::midpoint(v1->point(), v2->point());
Point_3 p2 = CGAL::midpoint(v2->point(), v3->point());
Vector_3 v(p1, p2);
std::cout << "TEST " << i << " (" << p1 << " ** " << p2 << ")"
<< std::endl;
std::cout << "\t(";
Segment_simplex_iterator st
= dt.segment_traverser_simplices_begin((p1 - 2. * v), (p2 + 3. * v));
Segment_simplex_iterator stend
= dt.segment_traverser_simplices_end();
for (; st != stend; ++st)
{
std::cout << st->dimension();
if (st->dimension() == 3
&& Cell_handle(*st) != Cell_handle()
&& dt.is_infinite(Cell_handle(*st)))
std::cout << "i";
std::cout << " ";
if (st->dimension() == 1)
{
Edge e = *st;
Vertex_handle va = e.first->vertex(e.second);
Vertex_handle vb = e.first->vertex(e.third);
if ((va == v1 && vb == v2)
|| (va == v2 && vb == v1))
{
++st;
std::cout << st->dimension() << " ";
assert(st->dimension() == 2);
++st;
std::cout << st->dimension() << " ";
assert(st->dimension() == 1);
Edge e2 = *st;
Vertex_handle va2 = e2.first->vertex(e2.second);
Vertex_handle vb2 = e2.first->vertex(e2.third);
assert(va == va2 || va == vb2 || vb == va2 || vb == vb2);
}
}
}
std::cout << ")" << std::endl;
}
}
void test_edge_facet_vertex(const DT& dt, const std::size_t& nb_tests)
{
std::cout << "* test_edge_facet_vertex *" << std::endl;
std::vector<Facet> facets;
for (DT::Finite_facets_iterator fit = dt.finite_facets_begin();
fit != dt.finite_facets_end() && facets.size() < nb_tests;
++fit)
{
facets.push_back(*fit);
}
for (std::size_t i = 0; i < nb_tests; ++i)
{
const int fi = facets[i].second;
Vertex_handle v1 = facets[i].first->vertex((fi + 1) % 4);
Vertex_handle v2 = facets[i].first->vertex((fi + 2) % 4);
Vertex_handle v3 = facets[i].first->vertex((fi + 3) % 4);
Point_3 p1 = CGAL::midpoint(v1->point(), v2->point());
Point_3 p2 = v3->point();
Vector_3 v(p1, p2);
std::cout << "TEST " << i << " (" << p1 << " ** " << p2 << ")"
<< std::endl;
std::cout << "\t(";
Segment_simplex_iterator st
= dt.segment_traverser_simplices_begin((p1 - 2. * v), (p2 + 3. * v));
Segment_simplex_iterator stend
= dt.segment_traverser_simplices_end();
for (; st != stend; ++st)
{
std::cout << st->dimension();
if (st->dimension() == 3 && dt.is_infinite(Cell_handle(*st)))
std::cout << "i";
std::cout << " ";
if (st->dimension() == 1)
{
Edge e = *st;
Vertex_handle va = e.first->vertex(e.second);
Vertex_handle vb = e.first->vertex(e.third);
if ((va == v1 && vb == v2) || (va == v2 && vb == v1))
{
++st;
std::cout << st->dimension() << " ";
assert(st->dimension() == 2);
++st;
std::cout << st->dimension() << " ";
assert(st->dimension() == 0);
assert(Vertex_handle(*st) == v3);
}
++st;
std::cout << st->dimension() << " ";
if (st == stend)
break;
else if (st->dimension() == 3
&& Cell_handle(*st) != Cell_handle()
&& dt.is_infinite(Cell_handle(*st)))
std::cout << "i ";
assert(st->dimension() == 3);
}
}
std::cout << ")" << std::endl;
}
}
void test_vertex_facet_edge(const DT& dt, const std::size_t& nb_tests)
{
std::cout << "* test_vertex_facet_edge *" << std::endl;
std::vector<Facet> facets;
DT::Finite_facets_iterator fit = dt.finite_facets_begin();
++fit; ++fit; ++fit; //just avoid using the same faces as for test_edge_facet_vertex
for (; fit != dt.finite_facets_end() && facets.size() < nb_tests;
++fit)
{
facets.push_back(*fit);
}
for (std::size_t i = 0; i < nb_tests; ++i)
{
const int fi = facets[i].second;
Vertex_handle v1 = facets[i].first->vertex((fi + 1) % 4);
Vertex_handle v2 = facets[i].first->vertex((fi + 2) % 4);
Vertex_handle v3 = facets[i].first->vertex((fi + 3) % 4);
Point_3 p1 = v1->point();
Point_3 p2 = CGAL::midpoint(v2->point(), v3->point());
Vector_3 v(p1, p2);
std::cout << "TEST " << i << " (" << p1 << " ** " << p2 << ")"
<< std::endl;
std::cout << "\t(";
Segment_simplex_iterator st = dt.segment_traverser_simplices_begin(p1 - 2.*v, p2 + 3.*v);
Segment_simplex_iterator stend = dt.segment_traverser_simplices_begin(p1 - 2. * v, p2 + 3. * v);
for (; st != stend; ++st)
{
std::cout << st->dimension();
if (st->dimension() == 3
&& Cell_handle(*st) != Cell_handle()
&& dt.is_infinite(Cell_handle(*st)))
std::cout << "i";
std::cout << " ";
if (st->dimension() == 0 && Vertex_handle(*st) == v1)
{
++st;
std::cout << st->dimension() << " ";
assert(st->dimension() == 2);
assert(Facet(*st) == facets[i]
|| Facet(*st) == dt.mirror_facet(facets[i]));
++st;
std::cout << st->dimension() << " ";
assert(st->dimension() == 1);
Edge e(*st);
Vertex_handle va = e.first->vertex(e.second);
Vertex_handle vb = e.first->vertex(e.third);
assert((va == v2 && vb == v3) || (va == v3 && vb == v2));
}
}
std::cout << ")" << std::endl;
}
}
void test_triangulation_on_a_grid()
{
std::cout << "* test_triangulation_on_a_grid *" << std::endl;
DT dt;
for (double x = 0.; x < 11.; x = x + 1.)
for (double y = 0.; y < 11.; y = y + 1.)
for (double z = 0.; z < 11.; z = z + 1.)
dt.insert(Point_3(x, y, z));
int nb_queries = 5;
std::vector<Segment_3> queries(nb_queries);
//along an axis of the grid
queries[0] = Segment_3(Point_3(1., 1., 1.), Point_3(1., 8., 1.));
//along an axis, but between two layers
queries[1] = Segment_3(Point_3(1., 1.5, 1.), Point_3(10., 1.5, 1.));
//along a diagonal
queries[2] = Segment_3(Point_3(1., 1., 1.), Point_3(6., 6., 6.));
//along a diagonal, in the plane (y = 1)
queries[3] = Segment_3(Point_3(1., 1., 1.), Point_3(7., 1., 7.));
//along a border of the cube
queries[4] = Segment_3(Point_3(0., 0., 0.), Point_3(11., 0., 5.));
for(const Segment_3& s : queries)
{
std::cout << "Query segment : (" << s.source()
<< ") to (" << s.target() << ") [";
Segment_simplex_iterator st = dt.segment_traverser_simplices_begin(s.source(), s.target());
Segment_simplex_iterator stend = dt.segment_traverser_simplices_end();
unsigned int inf = 0, fin = 0;
unsigned int nb_facets = 0, nb_edges = 0, nb_vertex = 0;
for (; st != st.end(); ++st)
{
std::cout << st->dimension() << " ";
std::cout.flush();
if (st->dimension() == 3)
{
if (dt.is_infinite(Cell_handle(*st))) ++inf;
else ++fin;
}
if (st->dimension() == 2) ++nb_facets;
else if (st->dimension() == 1) ++nb_edges;
else if (st->dimension() == 0) ++nb_vertex;
}
std::cout << "\b]" << std::endl;
std::cout << "\tinfinite cells : " << inf << std::endl;
std::cout << "\tfinite cells : " << fin << std::endl;
std::cout << "\tfacets : " << nb_facets << std::endl;
std::cout << "\tedges : " << nb_edges << std::endl;
std::cout << "\tvertices : " << nb_vertex << std::endl;
std::cout << std::endl;
}
}
int main(int argc, char* argv[])
{
const char* fname = (argc>1) ? argv[1] : "data/blobby.xyz";
int nb_seg = (argc > 2) ? atoi(argv[2]) : 3;
// Reads a .xyz point set file in points.
// As the point is the second element of the tuple (that is with index 1)
// we use a property map that accesses the 1st element of the tuple.
std::vector<Point_3> points;
std::ifstream stream(fname);
if (!stream ||
!CGAL::read_xyz_points(stream, std::back_inserter(points)))
{
std::cerr << "Error: cannot read file " << fname << std::endl;
return EXIT_FAILURE;
}
//bbox
//min (-0.481293,-0.220929,-0.194076), max (0.311532,0.225525,0.198025)
// Construct the Delaunay triangulation.
DT dt(points.begin(), points.end());
assert(dt.is_valid());
CGAL::Random rng;
for (int i = 0; i < nb_seg; ++i)
{
// Construct a traverser.
Point_3 p1(rng.get_double(-0.48, 0.31),
rng.get_double(-0.22, 0.22),
rng.get_double(-0.19, 0.19));
Point_3 p2(rng.get_double(-0.48, 0.31),
rng.get_double(-0.22, 0.22),
rng.get_double(-0.19, 0.19));
std::cout << "Traverser " << (i + 1)
<< "\n\t(" << p1
<< ")\n\t(" << p2 << ")" << std::endl;
Segment_simplex_iterator st = dt.segment_traverser_simplices_begin(p1, p2);
Segment_simplex_iterator stend = dt.segment_traverser_simplices_end();
// Count the number of finite cells traversed.
unsigned int inf = 0, fin = 0;
unsigned int nb_facets = 0, nb_edges = 0, nb_vertex = 0;
for (; st != stend; ++st)
{
if (st->dimension() == 3)
{
if (Cell_handle(*st) != Cell_handle()
&& dt.is_infinite(Cell_handle(*st)))
++inf;
else
++fin;
}
if (st->dimension() == 2) ++nb_facets;
else if (st->dimension() == 1) ++nb_edges;
else if (st->dimension() == 0) ++nb_vertex;
}
std::cout << "While traversing from " << p1
<< " to " << p2 << std::endl;
std::cout << "\tinfinite cells : " << inf << std::endl;
std::cout << "\tfinite cells : " << fin << std::endl;
std::cout << "\tfacets : " << nb_facets << std::endl;
std::cout << "\tedges : " << nb_edges << std::endl;
std::cout << "\tvertices : " << nb_vertex << std::endl;
std::cout << std::endl << std::endl;
}
//check degenerate cases
// - along an edge
test_vertex_edge_vertex(dt, 2);
// - along a facet via edge/facet/edge
test_edge_facet_edge(dt, 3);
// - along a facet via edge/facet/vertex
test_edge_facet_vertex(dt, 3);
// - along a facet via vertex/facet/edge
test_vertex_facet_edge(dt, 3);
// - along 2 successive facets (vertex/facet/edge/facet/edge)
// - along 2 successive edges (vertex/edge/vertex/edge/vertex)
// - along a facet and an edge successively
test_triangulation_on_a_grid();
return 0;
}