mirror of https://github.com/CGAL/cgal
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:
commit
d0dd5a93bf
|
|
@ -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*
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -23,6 +23,7 @@
|
|||
#include <CGAL/iterator.h>
|
||||
|
||||
#include <boost/config.hpp>
|
||||
#include <boost/iterator.hpp>
|
||||
|
||||
#include <functional>
|
||||
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
|
|
@ -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;
|
||||
|
||||
/// @}
|
||||
|
||||
|
|
|
|||
|
|
@ -6,7 +6,6 @@
|
|||
/// \defgroup PkgTriangulation3TriangulationClasses Triangulation Classes
|
||||
/// \ingroup PkgTriangulation3Ref
|
||||
|
||||
|
||||
/// \defgroup PkgTriangulation3TraitsClasses Traits Classes
|
||||
/// \ingroup PkgTriangulation3Ref
|
||||
|
||||
|
|
|
|||
|
|
@ -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}.
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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" )
|
||||
|
|
|
|||
|
|
@ -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
|
|
@ -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;
|
||||
}
|
||||
|
|
@ -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;
|
||||
}
|
||||
|
|
@ -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
|
|
@ -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
|
|
@ -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;
|
||||
}
|
||||
|
|
@ -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;
|
||||
}
|
||||
|
|
@ -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;
|
||||
}
|
||||
Loading…
Reference in New Issue