Merge branch 'master' into BGL-Alpha_expansion_graphcut-GF

This commit is contained in:
Mael
2020-03-24 08:18:23 +01:00
committed by GitHub
805 changed files with 89808 additions and 9394 deletions
+5 -5
View File
@@ -47,11 +47,11 @@ env:
- PACKAGE='Stream_support Subdivision_method_3 Surface_mesh '
- PACKAGE='Surface_mesh_approximation Surface_mesh_deformation Surface_mesh_parameterization '
- PACKAGE='Surface_mesh_segmentation Surface_mesh_shortest_path Surface_mesh_simplification '
- PACKAGE='Surface_mesh_skeletonization Surface_mesher Surface_sweep_2 '
- PACKAGE='TDS_2 TDS_3 Testsuite '
- PACKAGE='Three Triangulation Triangulation_2 '
- PACKAGE='Triangulation_3 Union_find Visibility_2 '
- PACKAGE='Voronoi_diagram_2 wininst '
- PACKAGE='Surface_mesh_skeletonization Surface_mesh_topology Surface_mesher '
- PACKAGE='Surface_sweep_2 TDS_2 TDS_3 '
- PACKAGE='Testsuite Three Triangulation '
- PACKAGE='Triangulation_2 Triangulation_3 Union_find '
- PACKAGE='Visibility_2 Voronoi_diagram_2 wininst '
compiler: clang
install:
- echo "$PWD"
+1
View File
@@ -122,6 +122,7 @@ Surface_mesh_segmentation
Surface_mesh_shortest_path
Surface_mesh_simplification
Surface_mesh_skeletonization
Surface_mesh_topology
Surface_mesher
Surface_sweep_2
TDS_2
+10 -4
View File
@@ -5,11 +5,17 @@
DO_IGNORE=FALSE
cd $1
if [ ! -f "$2/package_info/$2/dependencies" ];then
if [ ! -d "$2" ]; then
echo "$2 : MISSING PACKAGE. Ignoring."
DO_IGNORE=TRUE
exit 1
fi
if [ ! -f "$2/package_info/$2/dependencies" ];then
echo "No dependencies found for $2"
bash Scripts/developer_scripts/cgal_check_dependencies.sh --check_headers /usr/bin/doxygen
bash Scripts/developer_scripts/cgal_check_dependencies.sh --check_headers /usr/bin/doxygen
exit 1
fi
LIST_OF_FILES=$(git diff --name-only origin/master... |cut -d/ -f1 |uniq |sort)
@@ -75,7 +75,7 @@ using Intersection_and_primitive_id = unspecified_type;
/// \name Splitting
/// During the construction of the AABB tree, the primitives are
/// splitted according to some comparison functions related to the longest axis:
/// split according to some comparison functions related to the longest axis:
/// @{
/*!
@@ -60,6 +60,8 @@ int main(int argc, char* argv[])
{
std::ifstream in((argc>1)?argv[1]:"data/half.xyz");
double per = (argc>2)?boost::lexical_cast<double>(argv[2]):0;
double radius_ratio_bound = (argc>3)?boost::lexical_cast<double>(argv[3]):5.0;
std::vector<Point_3> points;
std::vector<Facet> facets;
@@ -71,7 +73,8 @@ int main(int argc, char* argv[])
CGAL::advancing_front_surface_reconstruction(points.begin(),
points.end(),
std::back_inserter(facets),
perimeter);
perimeter,
radius_ratio_bound);
std::cout << "OFF\n" << points.size() << " " << facets.size() << " 0\n";
std::copy(points.begin(),
@@ -3,7 +3,6 @@
#include <algorithm>
#include <CGAL/Exact_predicates_inexact_constructions_kernel.h>
#include <CGAL/Point_with_normal_3.h>
#include <CGAL/Shape_detection/Efficient_RANSAC.h>
#include <CGAL/structure_point_set.h>
#include <CGAL/Delaunay_triangulation_3.h>
@@ -369,9 +369,9 @@ concept. The second template parameter is a tag that indicates what
operations are allowed in the computations that take place within the
traits class.
The two possible values of the `Method_tag` parameter are
`Ring_tag` and `Sqrt_field_tag`. When
`Ring_tag` is used, only ring operations are used during the
evaluation of the predicates, whereas if `Sqrt_field_tag` is
`Integral_domain_without_division_tag` and `Field_with_sqrt_tag`. When
`Integral_domain_without_division_tag` is used, only ring operations are used during the
evaluation of the predicates, whereas if `Field_with_sqrt_tag` is
chosen, all four field operations, as well as square roots, are used
during the predicate evaluation.
@@ -379,32 +379,22 @@ The `Apollonius_graph_traits_2<K,Method_tag>` class provides exact
predicates if the number type in the kernel `K` is an exact number
type. This is to be associated with the type of operations allowed for
the predicate evaluation. For example `MP_Float` as number
type, with `Ring_tag` as tag will give exact predicates,
whereas `MP_Float` with `Sqrt_field_tag` will give
type, with `Integral_domain_without_division_tag` as tag will give exact predicates,
whereas `MP_Float` with `Field_with_sqrt_tag` will give
inexact predicates.
Since using an exact number type may be too slow, the
`Apollonius_graph_traits_2<K,Method_tag>` class is designed to
support the dynamic filtering of \cgal through the
`Filtered_exact<CT,ET>` mechanism. In particular if `CT`
is an inexact number type that supports the operations denoted by the
tag `Method_tag` and `ET` is an exact number type for these
operations, then kernel with number type
`Filtered_exact<CT,ET>` will yield exact predicates for the
Apollonius graph traits. To give a concrete example,
`CGAL::Filtered_exact<double,CGAL::MP_Float>` with
`Ring_tag` will produce exact predicates.
Another possibility for fast and exact predicate evaluation is to use
the
`Apollonius_graph_filtered_traits_2<CK,CM,EK,EM,FK,FM>`
class. This class is the analog of a filtered kernel. It takes a
Although exact number types provide exact predicates and constructions,
their use often results in unacceptably large runtimes.
The class `Apollonius_graph_filtered_traits_2<CK,CM,EK,EM,FK,FM>`
aims to paliate this shortcoming. Similar to a filtered kernel, it takes a
constructions kernel `CK`, a filtering kernel `FK` and an
exact kernel `EK`, as well as the corresponding tags
(`CM`, `FM` and `EM`, respectively).
It evaluates the predicates by first using the filtering kernel, and
if this fails the evaluation is performed using the exact kernel. The
constructions are done using the kernel `CK`, which means that
Predicates are evaluated by first using the filtering kernel, and
if this fails the evaluation is performed using the exact kernel,
thus yielding exact predicates at a generally much cheaper cost
than directly using an exact number type. The constructions
are done using the kernel `CK`, which means that
they are not necessarily exact. All template parameters except
`CK` have default values, which are explained in the reference
manual.
@@ -20,8 +20,8 @@ This class has six template parameters. The first, third and fifth
template parameters must be a models of the `Kernel` concept. The
second, fourth and sixth template parameters correspond to how
predicates are evaluated. There are two predefined possible values for
`Method_tag`, namely `CGAL::Sqrt_field_tag` and
`CGAL::Ring_tag`. The first one must be used when the number type
`Method_tag`, namely `CGAL::Field_with_sqrt_tag` and
`CGAL::Integral_domain_without_division_tag`. The first one must be used when the number type
used in the representation supports the exact evaluation of signs of
expressions involving all four basic operations and square roots,
whereas the second one requires the exact evaluation of signs of
@@ -31,7 +31,7 @@ The way the predicates are evaluated is discussed in
\cgalCite{cgal:ke-ppawv-02}, \cgalCite{cgal:ke-rctac-03}.
The default values for the template parameters are as follows:
`CM = CGAL::Ring_tag`,
`CM = CGAL::Integral_domain_without_division_tag`,
`EK = CGAL::Simple_cartesian<CGAL::MP_Float>`,
`EM = CM`,
`FK = CGAL::Simple_cartesian<CGAL::Interval_nt<false> >`,
@@ -41,8 +41,8 @@ The default values for the template parameters are as follows:
\sa `Kernel`
\sa `ApolloniusGraphTraits_2`
\sa `CGAL::Ring_tag`
\sa `CGAL::Sqrt_field_tag`
\sa `CGAL::Integral_domain_without_division_tag`
\sa `CGAL::Field_with_sqrt_tag`
\sa `CGAL::Apollonius_graph_2<Gt,Agds>`
\sa `CGAL::Apollonius_graph_traits_2<K,Method_tag>`
@@ -10,13 +10,13 @@ This class has two template parameters. The first template parameter
must be a model of the `Kernel` concept. The second template
parameter corresponds to how predicates are evaluated. There are two
predefined possible values for `Method_tag`, namely
`CGAL::Sqrt_field_tag` and `CGAL::Ring_tag`. The first one
`CGAL::Field_with_sqrt_tag` and `CGAL::Integral_domain_without_division_tag`. The first one
must be used when the number type used in the representation supports
the exact evaluation of signs of expressions involving all four basic
operations and square roots, whereas the second one requires the exact
evaluation of signs of ring-type expressions, i.e., expressions
involving only additions, subtractions and multiplications. The
default value for `Method_tag` is `CGAL::Ring_tag`.
default value for `Method_tag` is `CGAL::Integral_domain_without_division_tag`.
The way the predicates are evaluated is discussed in
\cgalCite{cgal:ke-ppawv-02}, \cgalCite{cgal:ke-rctac-03}.
@@ -24,8 +24,8 @@ The way the predicates are evaluated is discussed in
\sa `Kernel`
\sa `ApolloniusGraphTraits_2`
\sa `CGAL::Ring_tag`
\sa `CGAL::Sqrt_field_tag`
\sa `CGAL::Integral_domain_without_division_tag`
\sa `CGAL::Field_with_sqrt_tag`
\sa `CGAL::Apollonius_graph_2<Gt,Agds>`
\sa `CGAL::Apollonius_graph_filtered_traits_2<CK,CM,EK,EM,FK,FM>`
@@ -5,5 +5,6 @@ Algebraic_foundations
Circulator
Stream_support
Voronoi_diagram_2
Number_types
TDS_2
Triangulation_2
@@ -1,38 +0,0 @@
// Copyright (c) 2003,2004 INRIA Sophia-Antipolis (France).
// All rights reserved.
//
// This file is part of CGAL (www.cgal.org).
//
// $URL$
// $Id$
// SPDX-License-Identifier: GPL-3.0-or-later OR LicenseRef-Commercial
//
//
// Author(s) : Menelaos Karavelas <mkaravel@iacm.forth.gr>
#ifndef CGAL_CHECK_FILTER_H
#define CGAL_CHECK_FILTER_H
#include <CGAL/license/Apollonius_graph_2.h>
#undef CGAL_IA_NEW_FILTERS
namespace CGAL {
template < class T>
void must_be_filtered(const T&)
{}
#if defined CGAL_ARITHMETIC_FILTER_H
template < class CT, class ET, class Type, bool Protection, class Cache>
void must_be_filtered(const Filtered_exact<CT, ET, Type, Protection,
Cache> &)
{ dont_compile(CT(), ET()); }
#endif
}
#endif
@@ -165,6 +165,7 @@ public:
//---------------------------------
typedef typename CK_traits::Construct_object_2 Construct_object_2;
typedef typename CK_traits::Assign_2 Assign_2;
typedef typename CK_traits::Construct_point_2 Construct_point_2;
// CONSTRUCTIONS
//--------------
@@ -329,6 +330,10 @@ public:
return Construct_object_2();
}
Construct_point_2
construct_point_2_object() const {
return Construct_point_2();
}
// CONSTRUCTIONS
//--------------
@@ -75,6 +75,8 @@ public:
// CONSTRUCTIONS
//--------------
typedef typename Kernel::Construct_point_2 Construct_point_2;
// vertex and dual site
typedef CGAL_APOLLONIUS_GRAPH_2_NS::Construct_Apollonius_vertex_2<Kernel>
/* */ Construct_Apollonius_vertex_2;
@@ -142,6 +144,10 @@ public:
return Construct_object_2();
}
Construct_point_2
construct_point_2_object() const {
return Construct_point_2();
}
// CONSTRUCTIONS
//--------------
@@ -83,6 +83,10 @@ public:
this->p2 = p2;
}
int compute_k(const FT tt) const {
return int(CGAL::to_double(CGAL::sqrt(tt / this->STEP)));
}
void generate_points(std::vector<Point_2>& p) const
{
if ( CGAL::is_zero(this->r) ) {
@@ -91,76 +95,70 @@ public:
return;
}
// FT STEP = W.width() / 100.0;
FT s0, s1;
s0 = t(p1);
s1 = t(p2);
if (CGAL::compare(s0, s1) == LARGER) {
if (CGAL::compare(s0, s1) == LARGER)
std::swap(s0, s1);
}
p.clear();
if ( !(CGAL::is_positive(s0)) &&
!(CGAL::is_negative(s1)) ) {
FT tt;
int k;
if ( !(CGAL::is_positive(s0)) && !(CGAL::is_negative(s1)) )
{
FT tt = FT(-this->STEP);
int k = -1;
p.push_back( this->o );
k = 1;
tt = FT(-this->STEP);
while ( CGAL::compare(tt, s0) == LARGER ) {
p.insert( p.begin(), f(tt) );
k--;
tt = -FT(k * k) * this->STEP;
while ( CGAL::compare(tt, s0) == LARGER )
{
p.insert( p.begin(), f(tt) );
--k;
tt = - FT(k * k) * this->STEP;
}
p.insert( p.begin(), f(s0) );
k = 1;
tt = FT(this->STEP);
while ( CGAL::compare(tt, s1) == SMALLER ) {
p.push_back( f(tt) );
k++;
tt = FT(k * k) * this->STEP;
while ( CGAL::compare(tt, s1) == SMALLER )
{
p.push_back( f(tt) );
++k;
tt = FT(k * k) * this->STEP;
}
p.push_back( f(s1) );
} else if ( !(CGAL::is_negative(s0)) &&
!(CGAL::is_negative(s1)) ) {
FT tt;
int k;
}
else if ( !(CGAL::is_negative(s0)) && !(CGAL::is_negative(s1)) )
{
FT tt = s0;
int k = - compute_k(-tt);
p.push_back( f(s0) );
tt = s0;
k = int(CGAL::to_double(CGAL::sqrt(tt / this->STEP)));
while ( CGAL::compare(tt, s1) == SMALLER ) {
if ( CGAL::compare(tt, s0) != SMALLER )
p.push_back( f(tt) );
k++;
tt = FT(k * k) * this->STEP;
do
{
p.push_back( f(tt) );
++k;
tt = FT(k * k) * this->STEP;
}
p.push_back( f(s1) );
} else {
FT tt;
int k;
while ( CGAL::compare(tt, s0) == LARGER && CGAL::compare(tt, s1) == SMALLER );
p.push_back( f(s1) );
}
else
{
FT tt = s1;
int k = compute_k(tt);
tt = s1;
k = int(CGAL::to_double(-CGAL::sqrt(-tt / this->STEP)));
while ( CGAL::compare(tt, s0) == LARGER ) {
if ( CGAL::compare(tt, s1) != LARGER )
p.push_back( f(tt) );
k--;
tt = -FT(k * k) * this->STEP;
do
{
p.push_back( f(tt) );
--k;
tt = - FT(k * k) * this->STEP;
}
while ( CGAL::compare(tt, s0) == LARGER && CGAL::compare(tt, s1) == SMALLER );
p.push_back( f(s0) );
}
}
@@ -62,85 +62,100 @@ public:
this->p2 = p2;
}
int compute_k(const FT& tt) const {
return int(CGAL::sqrt(CGAL::to_double(tt) / 2));
int compute_k(const FT tt, const FT STEP) const {
return int(CGAL::to_double(CGAL::sqrt(tt / STEP)));
}
// s0 and s1 define a desired drawing "range"
void generate_points(std::vector<Point_2>& p,
const FT STEP = FT(2)) const
const FT STEP,
FT s0, FT s1) const
{
FT s0, s1;
s0 = t(p1);
s1 = t(p2);
if (CGAL::compare(s0, s1) == LARGER) {
std::swap(s0, s1);
}
CGAL_precondition(STEP > 0);
p.clear();
if ( !(CGAL::is_positive(s0)) &&
!(CGAL::is_negative(s1)) ) {
FT tt;
int k;
if (CGAL::compare(s0, s1) == LARGER)
std::swap(s0, s1);
// This is a parabola segment that exists between only between p1 and p2 so we gotta crop
// the desired range to actually fit the parabola segment
FT tp1 = t(p1), tp2 = t(p2);
if (CGAL::compare(tp1, tp2) == LARGER)
std::swap(tp1, tp2);
if(tp2 < s0 || s1 < tp1) // nothing to draw because the ranges are completely disjoint
return;
s0 = (std::max)(s0, tp1);
s1 = (std::min)(s1, tp2);
if ( !(CGAL::is_positive(s0)) && !(CGAL::is_negative(s1)) )
{
FT tt = - STEP;
int k = -1;
p.push_back( this->o );
k = -1;
tt = - STEP;
while ( CGAL::compare(tt, s0) == LARGER ) {
p.insert( p.begin(), f(tt) );
k--;
tt = -FT(k * k) * STEP;
// no need to check tt < s1 since we have tt < 0, s1 >= 0 and tt is moving towards -inf
while ( CGAL::compare(tt, s0) == LARGER )
{
p.insert( p.begin(), f(tt) );
--k;
tt = - FT(k * k) * STEP;
}
p.insert( p.begin(), f(s0) );
k = 1;
tt = STEP;
while ( CGAL::compare(tt, s1) == SMALLER ) {
p.push_back( f(tt) );
k++;
tt = FT(k * k) * STEP;
// no need to check tt > s0 since we have tt > 0, s0 <= 0 and tt is moving towards +inf
while ( CGAL::compare(tt, s1) == SMALLER )
{
p.push_back( f(tt) );
++k;
tt = FT(k * k) * STEP;
}
p.push_back( f(s1) );
} else if ( !(CGAL::is_negative(s0)) &&
!(CGAL::is_negative(s1)) ) {
FT tt;
int k;
}
else if ( !(CGAL::is_negative(s0)) && !(CGAL::is_negative(s1)) )
{
FT tt = s0;
int k = compute_k(tt, STEP);
p.push_back( f(s0) );
tt = s0;
k = compute_k(tt);
while ( CGAL::compare(tt, s1) == SMALLER ) {
if ( CGAL::compare(tt, s0) != SMALLER )
p.push_back( f(tt) );
k++;
tt = FT(k * k) * STEP;
do
{
p.push_back( f(tt) );
++k;
tt = FT(k * k) * STEP;
}
p.push_back( f(s1) );
} else {
FT tt;
int k;
while ( CGAL::compare(tt, s0) == LARGER && CGAL::compare(tt, s1) == SMALLER );
p.push_back( f(s1) );
}
else
{
FT tt = s1;
int k = - compute_k(-tt, STEP);
tt = s1;
k = -compute_k(-tt);
while ( CGAL::compare(tt, s0) == LARGER ) {
if ( CGAL::compare(tt, s1) != LARGER )
p.push_back( f(tt) );
k--;
tt = -FT(k * k) * STEP;
do
{
p.push_back( f(tt) );
--k;
tt = - FT(k * k) * STEP;
}
while ( CGAL::compare(tt, s0) == LARGER && CGAL::compare(tt, s1) == SMALLER );
p.push_back( f(s0) );
}
}
void generate_points(std::vector<Point_2>& p,
const FT STEP = FT(2)) const
{
return generate_points(p, STEP, t(p1), t(p2));
}
template< class Stream >
void draw(Stream& W) const
@@ -3,76 +3,31 @@
#include <fstream>
#include <cassert>
#define DONT_USE_FILTERED_EXACT
// choose number type
#include <CGAL/MP_Float.h>
#ifndef DONT_USE_FILTERED_EXACT
# include <CGAL/Filtered_exact.h>
#endif
typedef double inexact_type;
typedef CGAL::MP_Float exact_type;
#ifndef DONT_USE_FILTERED_EXACT
typedef CGAL::Filtered_exact<inexact_type,exact_type> number_t;
#endif
#include <CGAL/Simple_cartesian.h>
#ifndef DONT_USE_FILTERED_EXACT
typedef CGAL::Simple_cartesian<number_t> Kernel;
#endif
typedef CGAL::Integral_domain_without_division_tag Method_tag;
#include "./include/test.h"
typedef CGAL::Simple_cartesian<inexact_type> CK;
typedef CGAL::Simple_cartesian<exact_type> EK;
int main()
{
#ifndef DONT_USE_FILTERED_EXACT
{
std::ifstream ifs_algo("./data/algo.dat");
std::ifstream ifs_algo("./data/algo.dat");
assert( ifs_algo );
assert( ifs_algo );
std::cout << "testing the Apollonius graph class..." << std::flush;
bool algo_ok =
CGAL::test_algo<Kernel,Method_tag,std::ifstream>(ifs_algo);
assert( algo_ok );
std::cout << " done!" << std::endl;
ifs_algo.close();
std::cout << std::endl;
}
#endif
//------------------------------------------------------------------------
{
std::ifstream ifs_algo("./data/algo.dat");
assert( ifs_algo );
std::cout << "testing the Apollonius graph class"
<< " with filtered traits..." << std::flush;
bool algo_ok =
CGAL::test_filtered_traits_algo<CK,Method_tag,EK,Method_tag,
std::ifstream>(ifs_algo);
assert( algo_ok );
std::cout << " done!" << std::endl;
ifs_algo.close();
std::cout << std::endl;
}
std::cout << "testing the Apollonius graph class" << " with filtered traits..." << std::flush;
bool algo_ok = CGAL::test_filtered_traits_algo<CK,Method_tag,EK,Method_tag,std::ifstream>(ifs_algo);
assert( algo_ok );
std::cout << " done!" << std::endl;
return 0;
}
@@ -3,79 +3,31 @@
#include <fstream>
#include <cassert>
#define DNOT_USE_FILTERED_EXACT
// choose number type
#include <CGAL/MP_Float.h>
#ifndef DNOT_USE_FILTERED_EXACT
# include <CGAL/Filtered_exact.h>
#endif
typedef double inexact_type;
typedef CGAL::MP_Float exact_type;
#ifndef DNOT_USE_FILTERED_EXACT
typedef CGAL::Filtered_exact<inexact_type,exact_type> number_t;
#endif
#include <CGAL/Simple_cartesian.h>
#ifndef DNOT_USE_FILTERED_EXACT
typedef CGAL::Simple_cartesian<number_t> K;
#endif
typedef CGAL::Integral_domain_without_division_tag Method_tag;
#include "./include/test.h"
typedef CGAL::Simple_cartesian<inexact_type> CK;
typedef CGAL::Simple_cartesian<exact_type> EK;
int main()
{
#ifndef DNOT_USE_FILTERED_EXACT
{
std::ifstream ifs_hierarchy("./data/hierarchy.dat");
std::ifstream ifs_hierarchy("./data/hierarchy.dat");
assert( ifs_hierarchy );
assert( ifs_hierarchy );
std::cout << "testing the Apollonius graph hierarchy class" << " with filtered traits..." << std::flush;
bool hierarchy_ok = CGAL::test_filtered_traits_hierarchy_algo<CK,Method_tag,EK,Method_tag,std::ifstream>(ifs_hierarchy);
std::cout << "testing the Apollonius graph hierarchy class..."
<< std::flush;
bool hierarchy_ok =
CGAL::test_hierarchy_algo<Kernel,Method_tag,
std::ifstream>(ifs_hierarchy);
assert( hierarchy_ok );
std::cout << " done!" << std::endl;
ifs_hierarchy.close();
std::cout << std::endl;
}
#endif
//------------------------------------------------------------------------
{
std::ifstream ifs_hierarchy("./data/hierarchy.dat");
assert( ifs_hierarchy );
std::cout << "testing the Apollonius graph hierarchy class"
<< " with filtered traits..." << std::flush;
bool hierarchy_ok =
CGAL::test_filtered_traits_hierarchy_algo<CK,Method_tag,EK,
Method_tag,std::ifstream>(ifs_hierarchy);
assert( hierarchy_ok );
std::cout << " done!" << std::endl;
ifs_hierarchy.close();
std::cout << std::endl;
}
assert( hierarchy_ok );
std::cout << " done!" << std::endl;
return 0;
}
@@ -2,79 +2,33 @@
#include <fstream>
#include <cassert>
#define DONT_USE_FILTERED_EXACT
// choose number type
#include <CGAL/MP_Float.h>
#ifndef DONT_USE_FILTERED_EXACT
# include <CGAL/Filtered_exact.h>
#endif
typedef double inexact_type;
typedef CGAL::MP_Float exact_type;
#ifndef DONT_USE_FILTERED_EXACT
typedef CGAL::Filtered_exact<inexact_type,exact_type> number_t;
#endif
#include <CGAL/Simple_cartesian.h>
#ifndef DONT_USE_FILTERED_EXACT
typedef CGAL::Simple_cartesian<number_t> Kernel;
#endif
typedef CGAL::Integral_domain_without_division_tag Method_tag;
#include "./include/test.h"
typedef CGAL::Simple_cartesian<double> CK;
typedef CGAL::Simple_cartesian<CGAL::MP_Float> EK;
int main()
{
#ifndef DONT_USE_FILTERED_EXACT
{
std::ifstream ifs_traits("./data/traits.dat");
std::ifstream ifs_traits("./data/traits.dat");
assert( ifs_traits );
assert( ifs_traits );
std::cout << "testing the filtered traits class..." << std::flush;
// bool is_ok =
// CGAL::test_traits<Kernel,CGAL::Integral_domain_without_division_tag,std::ifstream>(ifs_traits);
CGAL::Filtered_traits_tester<CK,Method_tag,EK,Method_tag> test_traits;
bool traits_ok = test_traits();
assert( traits_ok );
std::cout << "testing the traits class..." << std::flush;
CGAL::Traits_tester<Kernel,Method_tag> test_traits;
bool traits_ok = test_traits();
assert( traits_ok );
std::cout << " done!" << std::endl;
ifs_traits.close();
std::cout << std::endl;
}
#endif
//------------------------------------------------------------------------
{
std::ifstream ifs_traits("./data/traits.dat");
assert( ifs_traits );
std::cout << "testing the filtered traits class..." << std::flush;
CGAL::Filtered_traits_tester<CK,Method_tag,EK,Method_tag> test_traits;
bool traits_ok = test_traits();
assert( traits_ok );
std::cout << " done!" << std::endl;
ifs_traits.close();
std::cout << std::endl;
}
std::cout << " done!" << std::endl;
return 0;
}
@@ -2,7 +2,7 @@
namespace CGAL {
/*!
\ingroup PkgBGLHelper
\ingroup BGLGraphExternalIndices
The class `HalfedgeDS_face_max_base_with_id` is a model of the `HalfedgeDSFace`
concept.
@@ -2,7 +2,7 @@
namespace CGAL {
/*!
\ingroup PkgBGLHelper
\ingroup BGLGraphExternalIndices
The class `HalfedgeDS_halfedge_max_base_with_id` is a model of the `HalfedgeDSHalfedge`
concept.
@@ -2,7 +2,7 @@
namespace CGAL {
/*!
\ingroup PkgBGLHelper
\ingroup BGLGraphExternalIndices
The class `HalfedgeDS_vertex_max_base_with_id` is a model of the `HalfedgeDSVertex`
concept. It is
@@ -2,7 +2,7 @@
namespace CGAL {
/*!
\ingroup PkgBGLHelper
\ingroup BGLGraphExternalIndices
The class `Linear_cell_complex_bgl_min_items` defines `void` as the information associated with darts, darts have ids and 0- and 2-attributes are enabled and have ids.
@@ -2,7 +2,7 @@
namespace CGAL {
/*!
\ingroup PkgBGLHelper
\ingroup BGLGraphExternalIndices
The class `Linear_cell_complex_for_bgl_combinatorial_map_helper` defines a `CGAL::Linear_cell_complex_for_combinatorial_map` as inner type, named `type`, having `CGAL::Linear_cell_complex_bgl_min_items` as items class. With this item class, no information are associated with darts, darts have ids and 0- and 2-attributes are enabled and have ids.
@@ -2,7 +2,7 @@
namespace CGAL {
/*!
\ingroup PkgBGLHelper
\ingroup BGLGraphExternalIndices
The class `Polyhedron_items_with_id_3` is a model of the `PolyhedronItems_3`
concept. It provides definitions for vertices with points, halfedges,
@@ -63,7 +63,7 @@ public:
/*!
\ingroup PkgBGLHelper
\ingroup BGLGraphExternalIndices
Given a `CGAL::Polyhedron_3`,
for each simplex type (vertex, halfedge, facet) associates an index from
@@ -1,15 +1,16 @@
namespace CGAL {
/*!
\ingroup PkgBGLHelper
\ingroup BGLGraphExternalIndices
The class `Triangulation_face_base_with_id_2` is a model of the
concept `TriangulationFaceBase_2`, the base face of a
2D-triangulation. It provides an integer field that can be used to
2D-triangulation. It provides an integer field that can be used to
index faces for \sc{Bgl} algorithms.
Note that the user is in charge of setting indices correctly before
running a graph algorithm.
running a graph algorithm, by calling the function
`CGAL::set_triangulation_ids(Triangulation&)`.
\tparam TriangulationTraits_2 is the geometric traits class
and must be a model of `TriangulationTraits_2`.
@@ -42,4 +43,19 @@ int& id();
/// @}
}; /* end Triangulation_face_base_with_id_2 */
/// \ingroup BGLGraphExternalIndices
///
/// This function initializes vertex, edge, and face indices of the triangulation `tr` and must
/// be called prior to using `tr` as a BGL graph in an algorithm that requires
/// vertex, halfedge, edge, or face indices.
///
/// \tparam Triangulation a 2D triangulation of \cgal, whose combinatorial data structure
/// has been initialized with the vertex and face classes `Triangulation_vertex_base_with_id_2`
/// and `Triangulation_face_base_with_id_2`.
///
/// \sa the \ref PkgTriangulation2 package
template <typename Triangulation>
void set_triangulation_ids(Triangulation& tr);
} /* end namespace CGAL */
@@ -1,7 +1,7 @@
namespace CGAL {
/*!
\ingroup PkgBGLHelper
\ingroup BGLGraphExternalIndices
The class `Triangulation_vertex_base_with_id_2` is a model of the
concept `TriangulationVertexBase_2`, the base vertex of a
@@ -9,7 +9,8 @@ concept `TriangulationVertexBase_2`, the base vertex of a
index vertices for \sc{Bgl} algorithms.
Note that the user is in charge of setting indices correctly before
running a graph algorithm.
running a graph algorithm, by calling the function
`CGAL::set_triangulation_ids(Triangulation&)`.
\tparam TriangulationTraits_2 is the geometric traits class
and must be a model of `TriangulationTraits_2`.
+21 -12
View File
@@ -1,14 +1,9 @@
/// Boost Namespace
namespace boost {
/// CGAL Namespace
namespace CGAL {
/// \ingroup PkgBGLProperties
/// @{
/// The constant `edge_index` is a property tag which identifies the <i>index</i> property of an edge of a \sc{Bgl}
/// <a href="https://www.boost.org/libs/graph/doc/Graph.html"><code>Graph</code></a>.
/// \cgalModels <a href="https://www.boost.org/libs/graph/doc/PropertyTag.html"><code>PropertyTag</code></a>
enum edge_index_t { edge_index};
/// The constant `vertex_index` is a property tag which identifies the <i>index</i> property of a vertex of a \sc{Bgl}
/// <a href="https://www.boost.org/libs/graph/doc/Graph.html"><code>Graph</code></a>.
/// \cgalModels <a href="https://www.boost.org/libs/graph/doc/PropertyTag.html"><code>PropertyTag</code></a>
@@ -20,13 +15,17 @@ enum vertex_index_t { vertex_index };
/// \cgalModels <a href="https://www.boost.org/libs/graph/doc/PropertyTag.html"><code>PropertyTag</code></a>
enum halfedge_index_t { halfedge_index };
/// The constant `edge_index` is a property tag which identifies the <i>index</i> property of an edge of a \sc{Bgl}
/// <a href="https://www.boost.org/libs/graph/doc/Graph.html"><code>Graph</code></a>.
/// \cgalModels <a href="https://www.boost.org/libs/graph/doc/PropertyTag.html"><code>PropertyTag</code></a>
enum edge_index_t { edge_index };
/// The constant `face_index` is a property tag which identifies the <i>index</i> property of a face of a `FaceGraph`.
///
/// This is a property tag introduced by \cgal.
/// \cgalModels <a href="https://www.boost.org/libs/graph/doc/PropertyTag.html"><code>PropertyTag</code></a>
enum face_index_t { face_index };
/// The constant `vertex_point` is a property tag which refers to the geometric embedding property of
/// a vertex of a `HalfedgeGraph`.
///
@@ -34,12 +33,22 @@ enum face_index_t { face_index };
/// \cgalModels <a href="https://www.boost.org/libs/graph/doc/PropertyTag.html"><code>PropertyTag</code></a>
enum vertex_point_t { vertex_point };
/// @}
} // namespace boost
namespace CGAL {
/// \ingroup PkgBGLProperties
///
/// \brief graph_has_property is used to indicate if a model of `HalfedgeGraph` or `FaceGraph`
/// has an internal property associated with the given `PropertyTag`.
///
/// It inherits from \link Tag_true `CGAL::Tag_true` \endlink if there is a
/// default internal property map for the corresponding property tag and from
/// \link Tag_false `CGAL::Tag_false` \endlink otherwise.
///
/// \tparam Graph a model of `HalfedgeGraph` or `FaceGraph`
/// \tparam PropertyTag the type of a property tag referring to the property of interest.
///
template<typename Graph, typename PropertyTag>
struct graph_has_property;
/// @{
+24 -11
View File
@@ -38,38 +38,51 @@ a \cgal point type as value type. \n
\cgalNPEnd
\cgalNPBegin{vertex_index_map} \anchor BGL_vertex_index_map
is the property map containing the index of each vertex of the input polygon mesh.\n
is the property map associating a unique index to each vertex of a polygon mesh `g`,
between `0` and `num_vertices(g)-1`.
If this parameter is not passed, internal machinery will create and initialize a vertex index
property map, either using the internal property map if it exists or using an external map. The latter
might result in - slightly - worsened performance in case of non-constant complexity for index access.\n
<b>Type:</b> a class model of `ReadablePropertyMap` with
`boost::graph_traits<PolygonMesh>::%vertex_descriptor` as key type and the value type
\code typename boost::property_traits<typename boost::property_map<PolygonMesh, CGAL::vertex_index_t>::type>::value_type \endcode
<b>Default:</b> \code boost::get(CGAL::vertex_index, pmesh)\endcode
<b>Default:</b> an initialized vertex index property map
\cgalNPEnd
\cgalNPBegin{halfedge_index_map} \anchor BGL_halfedge_index_map
is the property map containing the index of each halfedge of the input polygon mesh.\n
is the property map associating a unique index to each halfedge of a polygon mesh,
between `0` and `num_halfedges(g)-1`.
If this parameter is not passed, internal machinery will create and initialize a halfedge index
property map, either using the internal property map if it exists or using an external map. The latter
might result in - slightly - worsened performance in case of non-constant complexity for index access.\n
<b>Type:</b> a class model of `ReadablePropertyMap` with
`boost::graph_traits<PolygonMesh>::%halfedge_descriptor` as key type and the value type:
\code typename boost::property_traits<typename boost::property_map<PolygonMesh, CGAL::halfedge_index_t>::type>::value_type \endcode
<b>Default:</b> \code boost::get(CGAL::halfedge_index, pmesh)\endcode
If this internal property map exists, its values should be initialized.
<b>Default:</b> an initialized halfedge index property map
\cgalNPEnd
\cgalNPBegin{edge_index_map} \anchor BGL_edge_index_map
is the property map containing the index of each edge of the input polygon mesh.\n
is the property map associating a unique index to each edge of a polygon mesh,
between `0` and `num_edges(g)-1`.
If this parameter is not passed, internal machinery will create and initialize a edge index
property map, either using the internal property map if it exists or using an external map. The latter
might result in - slightly - worsened performance in case of non-constant complexity for index access.\n
<b>Type:</b> a class model of `ReadablePropertyMap` with
`boost::graph_traits<PolygonMesh>::%edge_descriptor` as key type and the value type:
\code typename boost::property_traits<typename boost::property_map<PolygonMesh, CGAL::edge_index_t>::type>::value_type \endcode
<b>Default:</b> \code boost::get(CGAL::edge_index, pmesh)\endcode
If this internal property map exists, its values should be initialized.
<b>Default:</b> an initialized edge index property map
\cgalNPEnd
\cgalNPBegin{face_index_map} \anchor BGL_face_index_map
is the property map containing the index of each face of the input polygon mesh.\n
is the property map associating a unique index to each face of a polygon mesh,
between `0` and `num_faces(g)-1`.
If this parameter is not passed, internal machinery will create and initialize a face index
property map, either using the internal property map if it exists or using an external map. The latter
might result in - slightly - worsened performance in case of non-constant complexity for index access.\n
<b>Type:</b> a class model of `ReadablePropertyMap` with
`boost::graph_traits<PolygonMesh>::%face_descriptor` as key type and the value type:
\code typename boost::property_traits<typename boost::property_map<PolygonMesh, CGAL::face_index_t>::type>::value_type \endcode
<b>Default:</b> \code boost::get(CGAL::face_index, pmesh)\endcode
If this internal property map exists, its values should be initialized.
<b>Default:</b> an initialized face index property map
\cgalNPEnd
\cgalNPBegin{edge_is_constrained_map} \anchor BGL_edge_is_constrained_map
+20 -15
View File
@@ -443,7 +443,7 @@ the requirement for traversal of all faces in a graph.
/// \defgroup PkgBGLPropertiesDynamic Dynamic Properties
/// \ingroup PkgBGLRef
/// \defgroup PkgBGLHelper Helper Classes
/// \defgroup PkgBGLGraphExternalIndices External Indices
/// \ingroup PkgBGLRef
/// \defgroup PkgBGLHelperFct Helper Functions
@@ -473,8 +473,11 @@ The dynamic property tags enable to associate information to simplices of a `Fac
*/
/*!
\addtogroup PkgBGLHelper
Several classes that enable to store ids in vertices/halfedges/faces of a `CGAL::Polyhedron_3`, as well as adapters such as `CGAL::Dual`.
\addtogroup BGLGraphExternalIndices
A number of BGL and \cgal algorithms require the graph to have (initialized) integer-like indices
for its vertices, edges, or faces. However, not all graphs intrinsically offer a natural way
to attach a unique ID to each element. The following classes and functions paliate this
by attaching and initializing external IDs to the elements of the graph.
*/
/*!
@@ -575,25 +578,25 @@ Methods to read and write graphs.
- `MutableFaceGraph`
\cgalCRPSection{Properties}
- `boost::vertex_index_t`
- `boost::halfedge_index_t`
- `boost::edge_index_t`
- `boost::face_index_t`
- `boost::vertex_point_t`
- `CGAL::vertex_index_t`
- `CGAL::halfedge_index_t`
- `CGAL::edge_index_t`
- `CGAL::face_index_t`
- `CGAL::vertex_point_t`
\cgalCRPSection{%CGAL Classes Adapted for the Graph API}
Different \cgal types have been adapted as graphs for the \sc{Bgl}. All
A number of \cgal structures have been adapted as graphs for the \sc{Bgl}. All
adapted types are listed here. The pages document which concepts they
model, the properties they support, and any possible caveats that a
user might encounter.
- \link BGLSMGT `boost::graph_traits< CGAL::Surface_mesh<P> >` \endlink
- \link BGLPolyGT `boost::graph_traits< CGAL::Polyhedron_3<T> >` \endlink
- \link BGLLCCGT `boost::graph_traits< CGAL::Linear_cell_complex_for_combinatorial_map<...> >` \endlink
- \link BGLSeam_meshGT `boost::graph_traits< CGAL::Seam_mesh<T> >` \endlink
- \link BGLT2GT `boost::graph_traits< CGAL::Triangulation_2<GT, TDS> >` \endlink
- \link BGLArgtGT `boost::graph_traits< CGAL::Arrangement_2<T,DC> >` \endlink
- \link BGLSMGT `boost::graph_traits<CGAL::Surface_mesh<P> >` \endlink
- \link BGLPolyGT `boost::graph_traits<CGAL::Polyhedron_3<T> >` \endlink
- \link BGLLCCGT `boost::graph_traits<CGAL::Linear_cell_complex_for_combinatorial_map<...> >` \endlink
- \link BGLSeam_meshGT `boost::graph_traits<CGAL::Seam_mesh<T> >` \endlink
- \link BGLT2GT `boost::graph_traits<CGAL::Triangulation_2<GT, TDS> >` \endlink and other 2D triangulations
- \link BGLArgtGT `boost::graph_traits<CGAL::Arrangement_2<T, DC> >` \endlink
- \link BGLOMPAK `boost::graph_traits<OpenMesh::PolyMesh_ArrayKernelT<K> >` \endlink
- \link BGLOMTMAK `boost::graph_traits<OpenMesh::TriMesh_ArrayKernelT<K> >` \endlink
@@ -643,6 +646,8 @@ user might encounter.
- `CGAL::clear()`
- `CGAL::copy_face_graph()`
- `CGAL::set_triangulation_ids()`
\cgalCRPSection{Iterators}
- `CGAL::Halfedge_around_source_iterator`
- `CGAL::Halfedge_around_target_iterator`
+1
View File
@@ -55,6 +55,7 @@ int main(int argc, char* argv[])
CGAL::copy_face_graph(T1, S, CGAL::parameters::vertex_to_vertex_output_iterator(std::inserter(v2v, v2v.end()))
.halfedge_to_halfedge_output_iterator(std::inserter(h2h, h2h.end())));
std::ofstream out("reverse.off");
out.precision(17);
out << S;
}
return 0;
@@ -43,6 +43,7 @@ int main(int argc, char* argv[])
{
CGAL::copy_face_graph(S, T1);
std::ofstream out("sm.off");
out.precision(17);
out << T1;
}
@@ -81,6 +82,7 @@ int main(int argc, char* argv[])
boost::unordered_map<source_face_descriptor, tm_face_descriptor> f2f;
CGAL::copy_face_graph(T1, S, std::inserter(v2v, v2v.end()), std::inserter(h2h, h2h.end()));
std::ofstream out("reverse.off");
out.precision(17);
out << S;
CGAL::copy_face_graph(T1, S, CGAL::parameters::vertex_to_vertex_map(boost::make_assoc_property_map(v2v))
.halfedge_to_halfedge_output_iterator(std::inserter(h2h, h2h.end()))
@@ -20,6 +20,7 @@ int main()
CGAL::make_quad(Point(0,0,1), Point(1,0,1),Point(1,1,1),Point(0,1,1), sm);
std::ofstream out("out.inp");
out.precision(17);
CGAL::write_inp(out, sm, "out.inp", "S4R");
return 0;
}
+29 -13
View File
@@ -702,19 +702,35 @@ add_face(const VertexRange& vr, Graph& g)
break;
case 3: // both are new
if (halfedge(v, g) == boost::graph_traits<Graph>::null_halfedge())
{
set_halfedge(v, outer_prev, g);
next_cache.push_back(NextCacheEntry(outer_prev, outer_next));
// try to pick a border halfedge with v as target
halfedge_descriptor hv = halfedge(v, g);
if (hv != boost::graph_traits<Graph>::null_halfedge() && !is_border(hv, g))
{
for(halfedge_descriptor h_around_v : halfedges_around_target(hv, g))
if (is_border(h_around_v, g))
{
hv = h_around_v;
break;
}
if (!is_border(hv, g))
hv = boost::graph_traits<Graph>::null_halfedge();
}
if (hv == boost::graph_traits<Graph>::null_halfedge())
{
set_halfedge(v, outer_prev, g);
next_cache.push_back(NextCacheEntry(outer_prev, outer_next));
}
else
{
border_prev = hv;
border_next = next(border_prev, g);
next_cache.push_back(NextCacheEntry(border_prev, outer_next));
next_cache.push_back(NextCacheEntry(outer_prev, border_next));
}
break;
}
else
{
border_prev = halfedge(v, g);
border_next = next(border_prev, g);
next_cache.push_back(NextCacheEntry(border_prev, outer_next));
next_cache.push_back(NextCacheEntry(outer_prev, border_next));
}
break;
}
// set inner link
@@ -1323,7 +1339,7 @@ flip_edge(typename boost::graph_traits<Graph>::halfedge_descriptor h,
template<typename Graph>
bool
does_satisfy_link_condition(typename boost::graph_traits<Graph>::edge_descriptor e,
Graph& g)
const Graph& g)
{
typedef typename boost::graph_traits<Graph>::vertex_descriptor vertex_descriptor;
typedef typename boost::graph_traits<Graph>::halfedge_descriptor halfedge_descriptor;
@@ -1423,7 +1439,7 @@ does_satisfy_link_condition(typename boost::graph_traits<Graph>::edge_descriptor
template<typename Graph>
bool
satisfies_link_condition(typename boost::graph_traits<Graph>::edge_descriptor e,
Graph& g)
const Graph& g)
{
return does_satisfy_link_condition(e, g);
}
@@ -16,23 +16,24 @@
#include <CGAL/boost/graph/properties.h>
#include <CGAL/boost/graph/iterator.h>
#include <CGAL/boost/graph/Named_function_parameters.h>
#include <CGAL/boost/graph/named_params_helper.h>
#include <CGAL/boost/graph/helpers.h>
#include <CGAL/Dynamic_property_map.h>
#include <CGAL/assertions.h>
#include <boost/unordered_set.hpp>
#include <boost/graph/graph_traits.hpp>
#include <CGAL/boost/iterator/transform_iterator.hpp>
#include <boost/iterator/filter_iterator.hpp>
#include <CGAL/Default.h>
#include <CGAL/Dynamic_property_map.h>
#include <boost/dynamic_bitset.hpp>
#include <boost/graph/graph_traits.hpp>
#include <boost/iterator/filter_iterator.hpp>
#include <boost/range/has_range_iterator.hpp>
#include <boost/unordered_set.hpp>
#ifdef DOXYGEN_RUNNING
#define CGAL_BGL_NP_TEMPLATE_PARAMETERS NamedParameters
#define CGAL_BGL_NP_CLASS NamedParameters
#endif
namespace CGAL
{
namespace CGAL {
/*!
* \ingroup PkgBGLAdaptors
@@ -62,18 +63,18 @@ namespace CGAL
* missing if the default is fine.
*
* \tparam Graph must be a model of a `FaceListGraph`, `HalfedgeListGraph`, and \bgllink{VertexListGraph}.
* \tparam FIMap a model of `ReadablePropertyMap` with `face_descriptor` as key and `graph_traits<Graph>::%faces_size_type` as value
* \tparam VIMap a model of `ReadablePropertyMap` with `vertex_descriptor` as key and `graph_traits<Graph>::%vertices_size_type` as value
* \tparam HIMap a model of `ReadablePropertyMap` with `halfedge_descriptor` as key and `graph_traits<Graph>::%halfedges_size_type` as value
* \tparam FIMap a model of `ReadablePropertyMap` with `graph_traits<Graph>::%face_descriptor` as key and `graph_traits<Graph>::%faces_size_type` as value
* \tparam VIMap a model of `ReadablePropertyMap` with `graph_traits<Graph>::%vertex_descriptor` as key and `graph_traits<Graph>::%vertices_size_type` as value
* \tparam HIMap a model of `ReadablePropertyMap` with `graph_traits<Graph>::%halfedge_descriptor` as key and `graph_traits<Graph>::%halfedges_size_type` as value
*
* \cgalModels `FaceListGraph`
* \cgalModels `HalfedgeListGraph`
* \cgalModels \bgllink{VertexListGraph}
*/
template<typename Graph,
typename FIMap = typename boost::property_map<Graph, CGAL::face_index_t>::type,
typename VIMap = typename boost::property_map<Graph, boost::vertex_index_t>::type,
typename HIMap = typename boost::property_map<Graph, CGAL::halfedge_index_t>::type>
typename FIMap = Default,
typename VIMap = Default,
typename HIMap = Default>
struct Face_filtered_graph
{
typedef boost::graph_traits<Graph> gt;
@@ -93,10 +94,15 @@ struct Face_filtered_graph
#endif
// non documented types
typedef typename boost::property_traits< FIMap >::value_type face_index_type;
typedef typename boost::property_traits< VIMap >::value_type vertex_index_type;
typedef typename boost::property_traits< HIMap >::value_type halfedge_index_type;
typedef Face_filtered_graph<Graph, FIMap, VIMap, HIMap> Self;
typedef typename Default::Get<FIMap, typename CGAL::GetInitializedFaceIndexMap<Graph>::const_type>::type FIM;
typedef typename Default::Get<VIMap, typename CGAL::GetInitializedVertexIndexMap<Graph>::const_type>::type VIM;
typedef typename Default::Get<HIMap, typename CGAL::GetInitializedHalfedgeIndexMap<Graph>::const_type>::type HIM;
typedef typename boost::property_traits<FIM>::value_type face_index_type;
typedef typename boost::property_traits<VIM>::value_type vertex_index_type;
typedef typename boost::property_traits<HIM>::value_type halfedge_index_type;
typedef Face_filtered_graph<Graph, FIMap, VIMap, HIMap> Self;
/*!
* \brief Constructor where the set of selected faces is specified as a range of patch ids.
@@ -115,31 +121,31 @@ struct Face_filtered_graph
*
* \cgalNamedParamsBegin
* \cgalParamBegin{face_index_map}
* a property map containing an index for each face initialized from 0 to `num_vertices(graph)`
* a property map containing for each face of `graph` a unique index between `0` and `num_faces(graph)-1`
* \cgalParamEnd
* \cgalParamBegin{vertex_index_map}
* a property map containing an index for each vertex initialized 0 to `num_vertices(graph)`
* a property map containing for each vertex of `graph` a unique index between `0` and `num_vertices(graph)-1`
* \cgalParamEnd
* \cgalParamBegin{halfedge_index_map}
* a property map containing an index for each halfedge initialized 0 to `num_halfedges(graph)`
* a property map containing for each halfedge of `graph` a unique index between `0` and `num_halfedges(graph)-1`
* \cgalParamEnd
* \cgalNamedParamsEnd
*/
template <typename FacePatchIndexMap, class FacePatchIndexRange, class CGAL_BGL_NP_TEMPLATE_PARAMETERS>
Face_filtered_graph(const Graph& graph,
const FacePatchIndexRange& selected_face_patch_indices,
FacePatchIndexMap face_patch_index_map,
const CGAL_BGL_NP_CLASS& np
#ifndef DOXYGEN_RUNNING
, typename boost::enable_if<
typename boost::has_range_const_iterator<FacePatchIndexRange>::type
>::type* = 0
#endif
)
: _graph(const_cast<Graph&>(graph))
, fimap(parameters::choose_parameter(parameters::get_parameter(np, internal_np::face_index), get_const_property_map(face_index, graph)))
, vimap(parameters::choose_parameter(parameters::get_parameter(np, internal_np::vertex_index), get_const_property_map(boost::vertex_index, graph)))
, himap(parameters::choose_parameter(parameters::get_parameter(np, internal_np::halfedge_index), get_const_property_map(halfedge_index, graph)))
FacePatchIndexMap face_patch_index_map,
const CGAL_BGL_NP_CLASS& np
#ifndef DOXYGEN_RUNNING
, typename boost::enable_if<
typename boost::has_range_const_iterator<FacePatchIndexRange>::type
>::type* = 0
#endif
)
: _graph(const_cast<Graph&>(graph)),
fimap(CGAL::get_initialized_face_index_map(graph, np)),
vimap(CGAL::get_initialized_vertex_index_map(graph, np)),
himap(CGAL::get_initialized_halfedge_index_map(graph, np))
{
set_selected_faces(selected_face_patch_indices, face_patch_index_map);
}
@@ -152,10 +158,10 @@ struct Face_filtered_graph
typename boost::has_range_const_iterator<FacePatchIndexRange>::type
>::type* = 0
)
: _graph(const_cast<Graph&>(graph))
, fimap(get(CGAL::face_index, graph))
, vimap(get(boost::vertex_index, graph))
, himap(get(CGAL::halfedge_index, graph))
: _graph(const_cast<Graph&>(graph)),
fimap(CGAL::get_initialized_face_index_map(graph)),
vimap(CGAL::get_initialized_vertex_index_map(graph)),
himap(CGAL::get_initialized_halfedge_index_map(graph))
{
set_selected_faces(selected_face_patch_indices, face_patch_index_map);
}
@@ -175,38 +181,37 @@ struct Face_filtered_graph
*
* \cgalNamedParamsBegin
* \cgalParamBegin{face_index_map}
* a property map containing an index for each face initialized from 0 to `num_vertices(graph)`
* a property map containing for each face of `graph` a unique index between `0` and `num_faces(graph)-1`
* \cgalParamEnd
* \cgalParamBegin{vertex_index_map}
* a property map containing an index for each vertex initialized 0 to `num_vertices(graph)`
* a property map containing for each vertex of `graph` a unique index between `0` and `num_vertices(graph)-1`
* \cgalParamEnd
* \cgalParamBegin{halfedge_index_map}
* a property map containing an index for each halfedge initialized 0 to `num_halfedges(graph)`
* a property map containing for each halfedge of `graph` a unique index between `0` and `num_halfedges(graph)-1`
* \cgalParamEnd
* \cgalNamedParamsEnd
*/
template <typename FacePatchIndexMap, class CGAL_BGL_NP_TEMPLATE_PARAMETERS>
Face_filtered_graph(const Graph& graph,
typename boost::property_traits<FacePatchIndexMap>::value_type selected_face_patch_index,
FacePatchIndexMap face_patch_index_map,
const CGAL_BGL_NP_CLASS& np
)
: _graph(const_cast<Graph&>(graph))
, fimap(parameters::choose_parameter(parameters::get_parameter(np, internal_np::face_index), get_const_property_map(face_index, graph)))
, vimap(parameters::choose_parameter(parameters::get_parameter(np, internal_np::vertex_index), get_const_property_map(boost::vertex_index, graph)))
, himap(parameters::choose_parameter(parameters::get_parameter(np, internal_np::halfedge_index), get_const_property_map(halfedge_index, graph)))
typename boost::property_traits<FacePatchIndexMap>::value_type selected_face_patch_index,
FacePatchIndexMap face_patch_index_map,
const CGAL_BGL_NP_CLASS& np)
: _graph(const_cast<Graph&>(graph)),
fimap(CGAL::get_initialized_face_index_map(graph, np)),
vimap(CGAL::get_initialized_vertex_index_map(graph, np)),
himap(CGAL::get_initialized_halfedge_index_map(graph, np))
{
set_selected_faces(selected_face_patch_index, face_patch_index_map);
}
template <typename FacePatchIndexMap>
Face_filtered_graph(const Graph& graph,
typename boost::property_traits<FacePatchIndexMap>::value_type pid,
FacePatchIndexMap face_patch_index_map)
: _graph(const_cast<Graph&>(graph))
, fimap(get(CGAL::face_index, graph))
, vimap(get(boost::vertex_index, graph))
, himap(get(CGAL::halfedge_index, graph))
typename boost::property_traits<FacePatchIndexMap>::value_type pid,
FacePatchIndexMap face_patch_index_map)
: _graph(const_cast<Graph&>(graph)),
fimap(CGAL::get_initialized_face_index_map(graph)),
vimap(CGAL::get_initialized_vertex_index_map(graph)),
himap(CGAL::get_initialized_halfedge_index_map(graph))
{
set_selected_faces(pid, face_patch_index_map);
}
@@ -236,10 +241,10 @@ struct Face_filtered_graph
Face_filtered_graph(const Graph& graph,
const FaceRange& selected_faces,
const CGAL_BGL_NP_CLASS& np)
: _graph(const_cast<Graph&>(graph))
, fimap(parameters::choose_parameter(parameters::get_parameter(np, internal_np::face_index), get_const_property_map(face_index, graph)))
, vimap(parameters::choose_parameter(parameters::get_parameter(np, internal_np::vertex_index), get_const_property_map(boost::vertex_index, graph)))
, himap(parameters::choose_parameter(parameters::get_parameter(np, internal_np::halfedge_index), get_const_property_map(halfedge_index, graph)))
: _graph(const_cast<Graph&>(graph)),
fimap(CGAL::get_initialized_face_index_map(graph, np)),
vimap(CGAL::get_initialized_vertex_index_map(graph, np)),
himap(CGAL::get_initialized_halfedge_index_map(graph, np))
{
set_selected_faces(selected_faces);
}
@@ -247,10 +252,10 @@ struct Face_filtered_graph
template <typename FaceRange>
Face_filtered_graph(const Graph& graph,
const FaceRange& selected_faces)
: _graph(const_cast<Graph&>(graph))
, fimap(get(CGAL::face_index, graph))
, vimap(get(boost::vertex_index, graph))
, himap(get(CGAL::halfedge_index, graph))
: _graph(const_cast<Graph&>(graph)),
fimap(CGAL::get_initialized_face_index_map(graph)),
vimap(CGAL::get_initialized_vertex_index_map(graph)),
himap(CGAL::get_initialized_halfedge_index_map(graph))
{
set_selected_faces(selected_faces);
}
@@ -293,12 +298,12 @@ struct Face_filtered_graph
template<class FacePatchIndexRange, class FacePatchIndexMap>
void set_selected_faces(const FacePatchIndexRange& selected_face_patch_indices,
FacePatchIndexMap face_patch_index_map
#ifndef DOXYGEN_RUNNING
#ifndef DOXYGEN_RUNNING
, typename boost::enable_if<
typename boost::has_range_const_iterator<FacePatchIndexRange>::type
>::type* = 0
#endif
)
#endif
)
{
face_indices.clear();
vertex_indices.clear();
@@ -407,7 +412,7 @@ struct Face_filtered_graph
return selected_halfedges.count();
}
Property_map_binder< FIMap, typename Pointer_property_map< typename boost::property_traits< FIMap >::value_type >::type >
Property_map_binder<FIM, typename Pointer_property_map<typename boost::property_traits<FIM>::value_type>::type>
get_face_index_map() const
{
if (face_indices.empty())
@@ -422,7 +427,7 @@ struct Face_filtered_graph
return bind_property_maps(fimap, make_property_map(face_indices) );
}
Property_map_binder< VIMap, typename Pointer_property_map< typename boost::property_traits< VIMap >::value_type >::type >
Property_map_binder<VIM, typename Pointer_property_map<typename boost::property_traits<VIM>::value_type>::type>
get_vertex_index_map() const
{
if (vertex_indices.empty())
@@ -437,7 +442,7 @@ struct Face_filtered_graph
return bind_property_maps(vimap, make_property_map(vertex_indices) );
}
Property_map_binder< HIMap, typename Pointer_property_map< typename boost::property_traits< HIMap >::value_type >::type >
Property_map_binder<HIM, typename Pointer_property_map<typename boost::property_traits<HIM>::value_type >::type>
get_halfedge_index_map() const
{
if (halfedge_indices.empty())
@@ -510,9 +515,9 @@ struct Face_filtered_graph
private:
Graph& _graph;
FIMap fimap;
VIMap vimap;
HIMap himap;
FIM fimap;
VIM vimap;
HIM himap;
boost::dynamic_bitset<> selected_faces;
boost::dynamic_bitset<> selected_vertices;
boost::dynamic_bitset<> selected_halfedges;
@@ -1142,38 +1147,40 @@ CGAL_FILTERED_FACE_GRAPH_DYNAMIC_PMAP_SPECIALIZATION(dynamic_face_property_t)
#undef CGAL_FILTERED_FACE_GRAPH_DYNAMIC_PMAP_SPECIALIZATION
//specializations for indices
template<typename Graph,
typename FIMap,
typename VIMap,
typename HIMap>
struct property_map<CGAL::Face_filtered_graph<Graph, FIMap, VIMap, HIMap>, CGAL::face_index_t>{
typedef typename CGAL::Property_map_binder< FIMap,
typename CGAL::Pointer_property_map< typename boost::property_traits< FIMap >::value_type >::type > type;
typedef type const_type;
template<typename Graph, typename FIMap, typename VIMap, typename HIMap>
struct property_map<CGAL::Face_filtered_graph<Graph, FIMap, VIMap, HIMap>, CGAL::face_index_t>
{
typedef typename CGAL::Face_filtered_graph<Graph, FIMap, VIMap, HIMap>::FIM FIM;
typedef typename CGAL::Property_map_binder<FIM,
typename CGAL::Pointer_property_map<
typename boost::property_traits<FIM>::value_type>::type> type;
typedef type const_type;
};
template<typename Graph, typename FIMap, typename VIMap, typename HIMap>
struct property_map<CGAL::Face_filtered_graph<Graph, FIMap, VIMap, HIMap>, boost::vertex_index_t>
{
typedef typename CGAL::Face_filtered_graph<Graph, FIMap, VIMap, HIMap>::VIM VIM;
typedef typename CGAL::Property_map_binder<VIM,
typename CGAL::Pointer_property_map<
typename boost::property_traits<VIM>::value_type>::type> type;
typedef type const_type;
};
template<typename Graph,
typename FIMap,
typename VIMap,
typename HIMap>
struct property_map<CGAL::Face_filtered_graph<Graph, FIMap, VIMap, HIMap>, boost::vertex_index_t>{
typedef typename CGAL::Property_map_binder< VIMap,
typename CGAL::Pointer_property_map< typename boost::property_traits< VIMap >::value_type >::type > type;
typedef type const_type;
struct property_map<CGAL::Face_filtered_graph<Graph, FIMap, VIMap, HIMap>, CGAL::halfedge_index_t>
{
typedef typename CGAL::Face_filtered_graph<Graph, FIMap, VIMap, HIMap>::HIM HIM;
typedef typename CGAL::Property_map_binder<HIM,
typename CGAL::Pointer_property_map<
typename boost::property_traits<HIM>::value_type>::type> type;
typedef type const_type;
};
template<typename Graph,
typename FIMap,
typename VIMap,
typename HIMap>
} // namespace boost
struct property_map<CGAL::Face_filtered_graph<Graph, FIMap, VIMap, HIMap>, CGAL::halfedge_index_t>{
typedef typename CGAL::Property_map_binder< HIMap,
typename CGAL::Pointer_property_map< typename boost::property_traits< HIMap >::value_type >::type > type;
typedef type const_type;
};
}// namespace boost
#endif // CGAL_BOOST_GRAPH_FACE_FILTERED_GRAPH_H
@@ -42,17 +42,14 @@ void partition_dual_graph(const TriangleMesh& tm,
CGAL_precondition(CGAL::is_triangle_mesh(tm));
CGAL_precondition_msg(nparts > 1, ("Partitioning requires a number of parts > 1"));
using parameters::choose_parameter;
using parameters::get_parameter;
typedef typename boost::graph_traits<TriangleMesh>::vertex_descriptor vertex_descriptor;
typedef typename boost::graph_traits<TriangleMesh>::halfedge_descriptor halfedge_descriptor;
typedef typename boost::graph_traits<TriangleMesh>::face_iterator face_iterator;
// vertex index map
typedef typename CGAL::GetVertexIndexMap<TriangleMesh, NamedParameters>::type Indices;
Indices indices = choose_parameter(get_parameter(np, internal_np::vertex_index),
get_const_property_map(boost::vertex_index, tm));
typedef typename CGAL::GetInitializedVertexIndexMap<TriangleMesh, NamedParameters>::type Indices;
Indices indices = CGAL::get_initialized_vertex_index_map(tm, np);
idx_t nn = static_cast<idx_t>(num_vertices(tm));
idx_t ne = static_cast<idx_t>(num_faces(tm));
@@ -136,9 +133,6 @@ void partition_dual_graph(const TriangleMesh& tm, int nparts,
/// based on the mesh's dual graph. The resulting partition is stored in the vertex and/or face
/// property maps that are passed as parameters using \ref bgl_namedparameters "Named Parameters".
///
/// Property map for `CGAL::vertex_index_t` should be either available
/// as an internal property map to `tm` or provided as \ref bgl_namedparameters "Named Parameters".
///
/// \param tm a triangle mesh
/// \param nparts the number of parts in the final partition
/// \param np optional \ref bgl_namedparameters "Named Parameters" described below
@@ -148,7 +142,7 @@ void partition_dual_graph(const TriangleMesh& tm, int nparts,
///
/// \cgalNamedParamsBegin
/// \cgalParamBegin{vertex_index_map}
/// is a property map containing the index of each vertex of `tm` intialized from `0` to `num_vertices(tm)-1`.
/// is a property map containing for each vertex of `tm` a unique index between `0` and `num_vertices(tm)-1`.
/// \cgalParamEnd
/// \cgalParamBegin{METIS_options}
/// is a parameter used in to pass options to the METIS mesh
@@ -77,17 +77,14 @@ void partition_graph(const TriangleMesh& tm,
CGAL_precondition(CGAL::is_triangle_mesh(tm));
CGAL_precondition_msg(nparts > 1, ("Partitioning requires a number of parts > 1"));
using parameters::choose_parameter;
using parameters::get_parameter;
typedef typename boost::graph_traits<TriangleMesh>::vertex_descriptor vertex_descriptor;
typedef typename boost::graph_traits<TriangleMesh>::halfedge_descriptor halfedge_descriptor;
typedef typename boost::graph_traits<TriangleMesh>::face_iterator face_iterator;
//Vertex index map
typedef typename CGAL::GetVertexIndexMap<TriangleMesh, NamedParameters>::type Indices;
Indices indices = choose_parameter(get_parameter(np, internal_np::vertex_index),
get_const_property_map(boost::vertex_index, tm));
typedef typename CGAL::GetInitializedVertexIndexMap<TriangleMesh, NamedParameters>::type Indices;
Indices indices = CGAL::get_initialized_vertex_index_map(tm, np);
idx_t nn = static_cast<idx_t>(num_vertices(tm));
idx_t ne = static_cast<idx_t>(num_faces(tm));
@@ -168,9 +165,6 @@ void partition_graph(const TriangleMesh& tm, int nparts,
/// mesh's nodal graph. The resulting partition is stored in the vertex and/or face
/// property maps that are passed as parameters using \ref bgl_namedparameters "Named Parameters".
///
/// Property map for `CGAL::vertex_index_t` should be either available
/// as an internal property map to `tm` or provided as \ref bgl_namedparameters "Named Parameters".
///
/// \param tm a triangle mesh
/// \param nparts the number of parts in the final partition
/// \param np optional \ref bgl_namedparameters "Named Parameters" described below
@@ -180,7 +174,7 @@ void partition_graph(const TriangleMesh& tm, int nparts,
///
/// \cgalNamedParamsBegin
/// \cgalParamBegin{vertex_index_map}
/// is a property map containing the index of each vertex of `tm` intialized from `0` to `num_vertices(tm)-1`.
/// is a property map containing for each vertex of `tm` a unique index between `0` and `num_vertices(tm)-1`.
/// \cgalParamEnd
/// \cgalParamBegin{METIS_options}
/// is a parameter used in to pass options to the METIS mesh
@@ -194,6 +194,20 @@ get_parameter(const Named_function_parameters<T, Tag, Base>& np, Query_tag tag)
return internal_np::get_parameter_impl(static_cast<const internal_np::Named_params_impl<T, Tag, Base>&>(np), tag);
}
// single parameter so that we can avoid a default construction
template <typename D>
D choose_parameter(const internal_np::Param_not_found&)
{
return D();
}
template <typename D, typename T>
const T& choose_parameter(const T& t)
{
return t;
}
// Two parameters, non-trivial default value
template <typename D>
D choose_parameter(const internal_np::Param_not_found&, const D& d)
{
@@ -201,8 +215,7 @@ D choose_parameter(const internal_np::Param_not_found&, const D& d)
}
template <typename T, typename D>
const T&
choose_parameter(const T& t, const D&)
const T& choose_parameter(const T& t, const D&)
{
return t;
}
+7 -2
View File
@@ -124,8 +124,8 @@ public:
/// The type for the objects used to identify halfedges in the underlying mesh.
typedef typename boost::graph_traits<TM>::halfedge_descriptor TM_halfedge_descriptor;
/// The type for the iterators that traverse through the complete halfedge set of the underlying mesh.
typedef typename boost::graph_traits<TM>::halfedge_iterator TM_halfedge_iterator;
/// The type for the iterators that traverse through the complete halfedge set of the underlying mesh.
typedef typename boost::graph_traits<TM>::halfedge_iterator TM_halfedge_iterator;
/// The type for the objects used to identify edges in the underlying mesh.
typedef typename boost::graph_traits<TM>::edge_descriptor TM_edge_descriptor;
@@ -439,6 +439,11 @@ public:
{
return ! (e1 == e2);
}
friend std::size_t hash_value(const edge_descriptor& ed)
{
return hash_value((std::min)(ed.hd, ed.mesh_->opposite(ed.hd)));
}
};
#ifndef DOXYGEN_RUNNING
+7 -11
View File
@@ -199,13 +199,8 @@ void copy_face_graph(const SourceMesh& sm, TargetMesh& tm,
typedef typename boost::graph_traits<TargetMesh>::halfedge_descriptor tm_halfedge_descriptor;
std::vector<tm_halfedge_descriptor> hedges(num_halfedges(sm));
// init halfedge index map
/// \TODO shall we keep that?
helpers::init_halfedge_indices(const_cast<SourceMesh&>(sm),
get(boost::halfedge_index, sm));
copy_face_graph_impl(sm, tm,
bind_property_maps(get(boost::halfedge_index, sm),
bind_property_maps(get_initialized_halfedge_index_map(sm),
make_property_map(hedges)),
v2v, h2h, f2f,
sm_vpm, tm_vpm);
@@ -333,18 +328,19 @@ void copy_face_graph(const SourceMesh& sm, TargetMesh& tm,
{
using parameters::choose_parameter;
using parameters::get_parameter;
internal::copy_face_graph(sm, tm,
CGAL::graph_has_property<SourceMesh,boost::halfedge_index_t>(),
choose_parameter(get_parameter(np1, internal_np::vertex_to_vertex_output_iterator),
impl::make_functor(get_parameter(np1, internal_np::vertex_to_vertex_map))),
impl::make_functor(get_parameter(np1, internal_np::vertex_to_vertex_map))),
choose_parameter(get_parameter(np1, internal_np::halfedge_to_halfedge_output_iterator),
impl::make_functor(get_parameter(np1, internal_np::halfedge_to_halfedge_map))),
impl::make_functor(get_parameter(np1, internal_np::halfedge_to_halfedge_map))),
choose_parameter(get_parameter(np1, internal_np::face_to_face_output_iterator),
impl::make_functor(get_parameter(np1, internal_np::face_to_face_map))),
impl::make_functor(get_parameter(np1, internal_np::face_to_face_map))),
choose_parameter(get_parameter(np1, internal_np::vertex_point),
get(vertex_point, sm)),
get(vertex_point, sm)),
choose_parameter(get_parameter(np2, internal_np::vertex_point),
get(vertex_point, tm)));
get(vertex_point, tm)));
}
template <typename SourceMesh, typename TargetMesh>
@@ -0,0 +1,307 @@
// Copyright (c) 2020 GeometryFactory (France). All rights reserved.
//
// This file is part of CGAL (www.cgal.org)
//
// $URL$
// $Id$
// SPDX-License-Identifier: LGPL-3.0-or-later OR LicenseRef-Commercial
//
// Author(s) : Mael Rouxel-Labbé
// Maxime Gimeno
#ifndef CGAL_BOOST_GRAPH_INITIALIZED_INTERNAL_INDEX_MAPS_HELPERS
#define CGAL_BOOST_GRAPH_INITIALIZED_INTERNAL_INDEX_MAPS_HELPERS
#include <CGAL/assertions.h>
#include <CGAL/boost/graph/Named_function_parameters.h>
#include <CGAL/boost/graph/properties.h>
#include <CGAL/Dynamic_property_map.h>
#include <CGAL/use.h>
#include <vector>
#include <type_traits>
namespace CGAL {
namespace BGL {
namespace internal {
// Check that an index map has been correctly initialized
template <typename DescriptorRange, typename IndexMap>
bool is_index_map_valid(IndexMap idmap,
const std::size_t num_simplices,
const DescriptorRange& range)
{
typedef typename boost::property_traits<IndexMap>::value_type Id_type;
Id_type max_id = static_cast<Id_type>(num_simplices);
std::vector<bool> indices(max_id);
for(const auto& d : range)
{
const Id_type id = get(idmap, d);
if(id >= 0 && id < max_id && !indices[id])
{
indices[id] = true;
}
else
{
#ifdef CGAL_BGL_INDEX_MAP_DEBUG
std::cerr << "Invalid ID: " << id << " num_simplices: " << num_simplices << std::endl;
#endif
return false;
}
}
return true;
}
template <typename VertexIndexPropertyMap, typename Graph>
bool is_index_map_valid(const CGAL::internal_np::vertex_index_t, VertexIndexPropertyMap vertex_index_map, const Graph& g)
{
return is_index_map_valid(vertex_index_map, num_vertices(g), vertices(g));
}
template <typename HalfedgeIndexPropertyMap, typename Graph>
bool is_index_map_valid(const CGAL::internal_np::halfedge_index_t, HalfedgeIndexPropertyMap halfedge_index_map, const Graph& g)
{
return is_index_map_valid(halfedge_index_map, num_halfedges(g), halfedges(g));
}
template <typename EdgeIndexPropertyMap, typename Graph>
bool is_index_map_valid(const CGAL::internal_np::edge_index_t, EdgeIndexPropertyMap edge_index_map, const Graph& g)
{
return is_index_map_valid(edge_index_map, num_edges(g), edges(g));
}
template <typename FaceIndexPropertyMap, typename Graph>
bool is_index_map_valid(const CGAL::internal_np::face_index_t, FaceIndexPropertyMap face_index_map, const Graph& g)
{
return is_index_map_valid(face_index_map, num_faces(g), faces(g));
}
template <typename PropertyTag, typename IndexPropertyMap, typename Graph>
void initialize_index_map(const PropertyTag, IndexPropertyMap, const Graph&)
{
// Unknown parameter; should never be here.
CGAL_assertion(false);
}
template <typename IndexPropertyMap,
typename Graph,
bool is_writable = CGAL::internal::Is_writable_property_map<IndexPropertyMap>::value>
struct Index_map_initializer
{
void operator()(const CGAL::internal_np::vertex_index_t, IndexPropertyMap vertex_index_map, const Graph& g)
{
typename boost::property_traits<IndexPropertyMap>::value_type i = 0;
for(typename boost::graph_traits<Graph>::vertex_descriptor vd : vertices(g))
put(vertex_index_map, vd, i++);
}
void operator()(const CGAL::internal_np::halfedge_index_t, IndexPropertyMap halfedge_index_map, const Graph& g)
{
typename boost::property_traits<IndexPropertyMap>::value_type i = 0;
for(typename boost::graph_traits<Graph>::halfedge_descriptor hd : halfedges(g))
put(halfedge_index_map, hd, i++);
}
void operator()(const CGAL::internal_np::edge_index_t, IndexPropertyMap edge_index_map, const Graph& g)
{
typename boost::property_traits<IndexPropertyMap>::value_type i = 0;
for(typename boost::graph_traits<Graph>::edge_descriptor ed : edges(g))
put(edge_index_map, ed, i++);
}
void operator()(const CGAL::internal_np::face_index_t, IndexPropertyMap face_index_map, const Graph& g)
{
typename boost::property_traits<IndexPropertyMap>::value_type i = 0;
for(typename boost::graph_traits<Graph>::face_descriptor fd : faces(g))
put(face_index_map, fd, i++);
}
template <typename PropertyTag>
void operator()(const PropertyTag, IndexPropertyMap, const Graph&)
{
// Unknown parameter; should never be here.
CGAL_assertion(false);
}
};
template <typename IndexPropertyMap, typename Graph>
struct Index_map_initializer<IndexPropertyMap, Graph, false>
{
template <typename PropertyTag>
void operator()(const PropertyTag, IndexPropertyMap, const Graph&)
{
// The property map is not writable; should never be here.
CGAL_assertion_msg(false, "You are trying to initialize a non-writable property map");
}
};
// Just for convenience, define the following functions:
//
// BGL::internal::initialize_vertex_index_map()
// BGL::internal::initialize_halfedge_index_map()
// BGL::internal::initialize_edge_index_map()
// BGL::internal::initialize_face_index_map()
#define CGAL_DEF_INITIALIZE_ID_MAP_FUNCTION(TYPE) \
template <typename WritableIndexPropertyMap, typename Graph> \
void initialize_##TYPE##_index_map(WritableIndexPropertyMap index_map, \
const Graph& g) \
{ \
Index_map_initializer<WritableIndexPropertyMap, Graph> initializer; \
initializer(CGAL::internal_np::TYPE##_index_t{}, index_map, g); \
}
CGAL_DEF_INITIALIZE_ID_MAP_FUNCTION(vertex)
CGAL_DEF_INITIALIZE_ID_MAP_FUNCTION(halfedge)
CGAL_DEF_INITIALIZE_ID_MAP_FUNCTION(edge)
CGAL_DEF_INITIALIZE_ID_MAP_FUNCTION(face)
#undef CGAL_DEF_INITIALIZE_ID_FUCNTION
// Using the pmap passed in named parameters -------------------------------------------------------
template <typename IndexMap, typename PropertyTag, typename Tag, typename DynamicTag, typename Graph>
IndexMap get_initialized_index_map_const(const IndexMap index_map,
const PropertyTag p, Tag, DynamicTag,
const Graph& g)
{
CGAL_USE(g);
CGAL_USE(p);
// If you are passing a pmap via NPs, it must be initialized
CGAL_assertion(is_index_map_valid(p, index_map, g));
return index_map;
}
template <typename IndexMap, typename PropertyTag, typename Tag, typename DynamicTag, typename Graph>
IndexMap get_initialized_index_map(const IndexMap index_map,
const PropertyTag p, Tag, DynamicTag,
Graph& g)
{
CGAL_USE(g);
CGAL_USE(p);
// If you are passing a pmap via NPs, it must be initialized
CGAL_assertion(is_index_map_valid(p, index_map, g));
return index_map;
}
// Using the internal to the mesh ------------------------------------------------------------------
template <typename InternalIndexMap, typename PropertyTag, typename Graph>
InternalIndexMap
get_initialized_internal_index_map(InternalIndexMap index_map,
const PropertyTag p,
const Graph& g)
{
if(CGAL::internal::Is_writable_property_map<InternalIndexMap>::value)
{
if(!is_index_map_valid(p, index_map, g))
Index_map_initializer<InternalIndexMap, Graph>{}(p, index_map, g);
}
else // not writable
{
CGAL_assertion(is_index_map_valid(p, index_map, g));
}
return index_map;
}
template <typename PropertyTag, typename Tag, typename DynamicTag, typename Graph>
typename boost::property_map<Graph, Tag>::const_type
get_initialized_index_map_const(CGAL::internal_np::Param_not_found,
const PropertyTag p, const Tag tag, DynamicTag,
const Graph& g)
{
return get_initialized_internal_index_map(get(tag, g), p, g);
}
// same as above, non-const graph overload
template <typename PropertyTag, typename Tag, typename DynamicTag, typename Graph>
typename boost::property_map<Graph, Tag>::type
get_initialized_index_map(CGAL::internal_np::Param_not_found,
const PropertyTag p, const Tag tag, DynamicTag,
Graph& g)
{
// From now on the correct property map has been acquired
// and there is no need to distinguish between const and non-const mesh
return get_initialized_internal_index_map(get(tag, g), p, g);
}
// Create a dynamic property and initialize it -----------------------------------------------------
template <typename DynamicIndexMap, typename PropertyTag, typename Graph>
DynamicIndexMap
get_initialized_dynamic_index_map(DynamicIndexMap index_map,
const PropertyTag p,
const Graph& g)
{
#ifdef CGAL_PERFORMANCE_WARNINGS
std::cerr << "Warning: the automatically selected index map is a dynamic property map,"
<< " which might not have constant-time access complexity." << std::endl;
#endif
Index_map_initializer<DynamicIndexMap, Graph>{}(p, index_map, g);
return index_map;
}
template <typename PropertyTag, typename DynamicTag, typename Graph>
typename boost::property_map<Graph, DynamicTag>::const_type
get_initialized_index_map_const(CGAL::internal_np::Param_not_found,
const PropertyTag p, const DynamicTag dtag, DynamicTag,
const Graph& g)
{
return get_initialized_dynamic_index_map(get(dtag, g), p, g);
}
// same as above, non-const graph overload
template <typename PropertyTag, typename DynamicTag, typename Graph>
typename boost::property_map<Graph, DynamicTag>::type
get_initialized_index_map(CGAL::internal_np::Param_not_found,
const PropertyTag p, const DynamicTag dtag, DynamicTag,
Graph& g)
{
// From now on the correct property map has been acquired
// and there is no need to distinguish between const and non-const mesh
return get_initialized_dynamic_index_map(get(dtag, g), p, g);
}
template <typename PropertyTag, typename Tag, typename DynamicTag,
typename Graph,
typename NamedParameters = Named_function_parameters<bool, internal_np::all_default_t> >
class GetInitializedIndexMap
{
public:
// Check if there is an internal property map; if not, we must a dynamic property map
typedef typename boost::mpl::if_c<
CGAL::graph_has_property<Graph, Tag>::value, Tag, DynamicTag>::type Final_tag;
typedef typename internal_np::Lookup_named_param_def<
PropertyTag,
NamedParameters,
typename boost::property_map<Graph, Final_tag>::const_type>::type const_type;
typedef typename internal_np::Lookup_named_param_def<
PropertyTag,
NamedParameters,
typename boost::property_map<Graph, Final_tag>::type>::type type;
static const_type get_const(const PropertyTag p, const Graph& g, const NamedParameters& np)
{
return BGL::internal::get_initialized_index_map_const(parameters::get_parameter(np, p),
p, Final_tag{}, DynamicTag{}, g);
}
static type get(const PropertyTag p, Graph& g, const NamedParameters& np)
{
return BGL::internal::get_initialized_index_map(parameters::get_parameter(np, p),
p, Final_tag{}, DynamicTag{}, g);
}
};
} // namespace internal
} // namespace BGL
} // namespace CGAL
#endif // CGAL_BOOST_GRAPH_INITIALIZED_INTERNAL_INDEX_MAPS_HELPERS
+5 -14
View File
@@ -417,13 +417,9 @@ write_polys(std::ostream& os,
{
typedef typename boost::graph_traits<Mesh>::vertex_descriptor vertex_descriptor;
typedef typename boost::graph_traits<Mesh>::face_iterator face_iterator;
typedef typename CGAL::GetVertexIndexMap<Mesh, NamedParameters>::type Vimap;
using parameters::get_parameter;
using parameters::choose_parameter;
Vimap V = choose_parameter(get_parameter(np, internal_np::vertex_index),
get_const_property_map(boost::vertex_index, mesh));
typedef typename CGAL::GetInitializedVertexIndexMap<Mesh, NamedParameters>::const_type Vimap;
Vimap V = CGAL::get_initialized_vertex_index_map(mesh, np);
std::vector<std::size_t> connectivity_table;
std::vector<std::size_t> offsets;
@@ -456,13 +452,9 @@ write_polys_tag(std::ostream& os,
{
typedef typename boost::graph_traits<Mesh>::vertex_descriptor vertex_descriptor;
typedef typename boost::graph_traits<Mesh>::face_iterator face_iterator;
typedef typename CGAL::GetVertexIndexMap<Mesh, NamedParameters>::type Vimap;
using parameters::get_parameter;
using parameters::choose_parameter;
Vimap V = choose_parameter(get_parameter(np, internal_np::vertex_index),
get_const_property_map(boost::vertex_index, mesh));
typedef typename CGAL::GetInitializedVertexIndexMap<Mesh, NamedParameters>::const_type Vimap;
Vimap V = CGAL::get_initialized_vertex_index_map(mesh, np);
std::string formatattribute =
binary ? " format=\"appended\"" : " format=\"ascii\"";
@@ -638,8 +630,7 @@ write_polys_points(std::ostream& os,
* `CGAL::vertex_point_t` must be available in `TriangleMesh`.
* \cgalParamEnd
* \cgalParamBegin{vertex_index_map} the property map with the indices associated to
* the vertices of `mesh`. If this parameter is omitted, an internal property map for
* `CGAL::vertex_index_t` must be available in `TriangleMesh`.
* the vertices of `mesh`.
* \cgalParamEnd
* \cgalNamedParamsEnd
*/
@@ -19,18 +19,19 @@
#ifndef CGAL_BOOST_GRAPH_NAMED_PARAMETERS_HELPERS_H
#define CGAL_BOOST_GRAPH_NAMED_PARAMETERS_HELPERS_H
#include <CGAL/boost/graph/internal/initialized_index_maps_helpers.h>
#include <CGAL/boost/graph/Named_function_parameters.h>
#include <CGAL/boost/graph/properties.h>
#include <CGAL/Dynamic_property_map.h>
#include <CGAL/Kernel_traits.h>
#include <CGAL/Origin.h>
#include <CGAL/property_map.h>
#include <CGAL/boost/graph/properties.h>
#include <boost/mpl/if.hpp>
#include <boost/mpl/has_xxx.hpp>
#include <boost/type_traits/is_same.hpp>
#include <type_traits>
namespace CGAL {
@@ -41,8 +42,8 @@ namespace CGAL {
class Lapack_svd;
struct Alpha_expansion_boost_adjacency_list_tag;
//
//helper classes
template<typename PolygonMesh, typename PropertyTag>
class property_map_selector
@@ -105,7 +106,8 @@ namespace CGAL {
property_map_selector<PolygonMesh, PropertyTag> pms;
return pms.get_const_pmap(p, pmesh);
}
// shortcut for accessing the value type of the property map
// Shortcut for accessing the value type of the property map
template <class Graph, class Property>
class property_map_value {
typedef typename boost::property_map<Graph, Property>::const_type PMap;
@@ -113,7 +115,8 @@ namespace CGAL {
typedef typename boost::property_traits<PMap>::value_type type;
};
template<typename PolygonMesh, typename NamedParameters>
template<typename PolygonMesh,
typename NamedParameters = Named_function_parameters<bool, internal_np::all_default_t> >
class GetVertexPointMap
{
typedef typename property_map_selector<PolygonMesh, boost::vertex_point_t>::const_type
@@ -175,37 +178,105 @@ namespace CGAL {
> ::type type;
};
template<typename PolygonMesh, typename NamedParameters>
class GetFaceIndexMap
{
typedef typename property_map_selector<PolygonMesh, boost::face_index_t>::type DefaultMap;
typedef typename property_map_selector<PolygonMesh, boost::face_index_t>::const_type DefaultMap_const;
public:
typedef typename internal_np::Lookup_named_param_def <
internal_np::face_index_t,
NamedParameters,
DefaultMap
> ::type type;
typedef typename internal_np::Lookup_named_param_def <
internal_np::face_index_t,
NamedParameters,
DefaultMap_const
> ::type const_type;
typedef typename boost::is_same<type, DefaultMap>::type Is_internal_map;
typedef typename boost::is_same<const_type, DefaultMap_const>::type Is_internal_map_const;
};
// Define the following structs:
//
// GetInitializedVertexIndexMap
// GetInitializedHalfedgeIndexMap
// GetInitializedEdgeIndexMap
// GetInitializedFaceIndexMap
template<typename PolygonMesh, typename NamedParameters>
class GetVertexIndexMap
{
typedef typename property_map_selector<PolygonMesh, boost::vertex_index_t>::type DefaultMap;
public:
typedef typename internal_np::Lookup_named_param_def <
internal_np::vertex_index_t,
NamedParameters,
DefaultMap
> ::type type;
};
#define CGAL_DEF_GET_INDEX_TYPE(CTYPE, DTYPE, STYPE) \
template <typename Graph, \
typename NamedParameters = \
CGAL::Named_function_parameters<bool, CGAL::internal_np::all_default_t> > \
struct GetInitialized##CTYPE##IndexMap \
: public BGL::internal::GetInitializedIndexMap<internal_np::DTYPE##_index_t, \
boost::DTYPE##_index_t, \
CGAL::dynamic_##DTYPE##_property_t<STYPE>, \
Graph, NamedParameters> \
{ };
CGAL_DEF_GET_INDEX_TYPE(Vertex, vertex, typename boost::graph_traits<Graph>::vertices_size_type)
CGAL_DEF_GET_INDEX_TYPE(Halfedge, halfedge, typename boost::graph_traits<Graph>::halfedges_size_type)
CGAL_DEF_GET_INDEX_TYPE(Edge, edge, typename boost::graph_traits<Graph>::edges_size_type)
CGAL_DEF_GET_INDEX_TYPE(Face, face, typename boost::graph_traits<Graph>::faces_size_type)
#undef CGAL_DEF_GET_INDEX_TYPE
// Define the following functions:
//
// get_initialized_vertex_index_map()
// get_initialized_halfedge_index_map()
// get_initialized_edge_index_map()
// get_initialized_face_index_map()
//
// The function returns:
// - the index property map passed in the NPs, if passed in the NPs; it must be initialized by the user;
// - the internal index property map if it is the graph has one. It is initialized if needed and possible;
// - an initialized dynamic pmap otherwise.
#define CGAL_DEF_GET_INITIALIZED_INDEX_MAP(DTYPE, STYPE) \
template <typename Graph, \
typename NamedParameters> \
typename BGL::internal::GetInitializedIndexMap<CGAL::internal_np::DTYPE##_index_t, \
boost::DTYPE##_index_t, \
CGAL::dynamic_##DTYPE##_property_t<STYPE>, \
Graph, NamedParameters>::const_type \
get_initialized_##DTYPE##_index_map(const Graph& g, \
const NamedParameters& np) \
{ \
typedef BGL::internal::GetInitializedIndexMap<CGAL::internal_np::DTYPE##_index_t, \
boost::DTYPE##_index_t, \
CGAL::dynamic_##DTYPE##_property_t<STYPE>, \
Graph, NamedParameters> Index_map_getter; \
return Index_map_getter::get_const(CGAL::internal_np::DTYPE##_index_t{}, g, np); \
} \
template <typename Graph> \
typename BGL::internal::GetInitializedIndexMap<CGAL::internal_np::DTYPE##_index_t, \
boost::DTYPE##_index_t, \
CGAL::dynamic_##DTYPE##_property_t<STYPE>, \
Graph>::const_type \
get_initialized_##DTYPE##_index_map(const Graph& g) \
{ \
return get_initialized_##DTYPE##_index_map(g, CGAL::parameters::all_default()); \
} \
/* same as above, non-const version*/ \
template <typename Graph, \
typename NamedParameters, \
/*otherwise compilers will try to use 'Graph := const PM' and things will go badly*/ \
std::enable_if_t< \
!std::is_const<typename std::remove_reference<Graph>::type>::value, int> = 0> \
typename BGL::internal::GetInitializedIndexMap<CGAL::internal_np::DTYPE##_index_t, \
boost::DTYPE##_index_t, \
CGAL::dynamic_##DTYPE##_property_t<STYPE>, \
Graph, NamedParameters>::type \
get_initialized_##DTYPE##_index_map(Graph& g, \
const NamedParameters& np) \
{ \
typedef BGL::internal::GetInitializedIndexMap<CGAL::internal_np::DTYPE##_index_t, \
boost::DTYPE##_index_t, \
CGAL::dynamic_##DTYPE##_property_t<STYPE>, \
Graph, NamedParameters> Index_map_getter; \
return Index_map_getter::get(CGAL::internal_np::DTYPE##_index_t{}, g, np); \
} \
template <typename Graph, \
std::enable_if_t< \
!std::is_const<typename std::remove_reference<Graph>::type>::value, int> = 0> \
typename BGL::internal::GetInitializedIndexMap<CGAL::internal_np::DTYPE##_index_t, \
boost::DTYPE##_index_t, \
CGAL::dynamic_##DTYPE##_property_t<STYPE>, \
Graph>::type \
get_initialized_##DTYPE##_index_map(Graph& g) \
{ \
return get_initialized_##DTYPE##_index_map(g, CGAL::parameters::all_default()); \
}
CGAL_DEF_GET_INITIALIZED_INDEX_MAP(vertex, typename boost::graph_traits<Graph>::vertices_size_type)
CGAL_DEF_GET_INITIALIZED_INDEX_MAP(halfedge, typename boost::graph_traits<Graph>::halfedges_size_type)
CGAL_DEF_GET_INITIALIZED_INDEX_MAP(edge, typename boost::graph_traits<Graph>::edges_size_type)
CGAL_DEF_GET_INITIALIZED_INDEX_MAP(face, typename boost::graph_traits<Graph>::faces_size_type)
#undef CGAL_DEF_GET_INITIALIZED_INDEX_MAP
template<typename PolygonMesh, typename NamedParameters>
class GetFaceNormalMap
@@ -230,8 +301,45 @@ namespace CGAL {
> ::type type;
};
namespace Point_set_processing_3
namespace internal {
BOOST_MPL_HAS_XXX_TRAIT_NAMED_DEF(Has_nested_type_iterator, iterator, false)
}
template<typename PointRange,
typename NamedParameters = Named_function_parameters<bool, internal_np::all_default_t>,
bool has_nested_iterator = internal::Has_nested_type_iterator<PointRange>::value>
class GetPointMap
{
typedef typename std::iterator_traits<typename PointRange::iterator>::value_type Point;
typedef typename CGAL::Identity_property_map<Point> DefaultPMap;
public:
typedef typename internal_np::Lookup_named_param_def<
internal_np::point_t,
NamedParameters,
DefaultPMap
> ::type type;
typedef typename internal_np::Lookup_named_param_def<
internal_np::point_t,
NamedParameters,
DefaultPMap
> ::type const_type;
};
// to please compiler instantiating non valid overloads
template<typename PointRange, typename NamedParameters>
class GetPointMap<PointRange, NamedParameters, false>
{
struct Dummy_point{};
public:
typedef typename CGAL::Identity_property_map<Dummy_point> type;
typedef typename CGAL::Identity_property_map<Dummy_point> const_type;
};
namespace Point_set_processing_3 {
template <typename ValueType>
struct Fake_point_range
{
@@ -255,41 +363,6 @@ namespace CGAL {
}
}
namespace internal{
BOOST_MPL_HAS_XXX_TRAIT_NAMED_DEF(Has_nested_type_iterator, iterator, false)
}
template<typename PointRange, typename NamedParameters,
bool has_nested_iterator=internal::Has_nested_type_iterator<PointRange>::value>
class GetPointMap
{
typedef typename std::iterator_traits<typename PointRange::iterator>::value_type Point;
typedef typename CGAL::Identity_property_map<Point> DefaultPMap;
public:
typedef typename internal_np::Lookup_named_param_def<
internal_np::point_t,
NamedParameters,
DefaultPMap
> ::type type;
typedef typename internal_np::Lookup_named_param_def<
internal_np::point_t,
NamedParameters,
DefaultPMap
> ::type const_type;
};
// to please compiler instantiating non valid overloads
template<typename PointRange, typename NamedParameters>
class GetPointMap<PointRange, NamedParameters, false>
{
struct Dummy_point{};
public:
typedef typename CGAL::Identity_property_map<Dummy_point> type;
typedef typename CGAL::Identity_property_map<Dummy_point> const_type;
};
template<typename PointRange>
class GetFT
{
@@ -380,7 +453,7 @@ namespace CGAL {
DefaultPMap
> ::type const_type;
};
template<typename NamedParameters>
class GetPlaneIndexMap
{
@@ -428,7 +501,7 @@ namespace CGAL {
};
} // namespace Point_set_processing_3
template<typename NamedParameters, typename DefaultSolver>
class GetSolver
{
@@ -461,10 +534,10 @@ namespace CGAL {
typedef int Matrix;
static FT solve (const Matrix&, Vector&) { return 0.; }
};
public:
typedef DummySvdTraits NoTraits;
typedef typename internal_np::Lookup_named_param_def <
internal_np::svd_traits_t,
NamedParameters,
@@ -488,8 +561,6 @@ namespace CGAL {
DefaultImplementation
>::type type;
};
} //namespace CGAL
@@ -17,6 +17,8 @@ CGAL_add_named_parameter(face_index_t, face_index, face_index_map)
CGAL_add_named_parameter(vertex_index_t, vertex_index, vertex_index_map)
CGAL_add_named_parameter(graph_visitor_t, graph_visitor, visitor)
CGAL_add_named_parameter(point_t, point_map, point_map)
CGAL_add_named_parameter(edge_is_constrained_t, edge_is_constrained, edge_is_constrained_map)
CGAL_add_named_parameter(first_index_t, first_index, first_index)
CGAL_add_named_parameter(number_of_iterations_t, number_of_iterations, number_of_iterations)
@@ -83,6 +85,9 @@ CGAL_add_named_parameter(use_angle_smoothing_t, use_angle_smoothing, use_angle_s
CGAL_add_named_parameter(use_area_smoothing_t, use_area_smoothing, use_area_smoothing)
CGAL_add_named_parameter(use_Delaunay_flips_t, use_Delaunay_flips, use_Delaunay_flips)
CGAL_add_named_parameter(do_project_t, do_project, do_project)
CGAL_add_named_parameter(area_threshold_t, area_threshold, area_threshold)
CGAL_add_named_parameter(volume_threshold_t, volume_threshold, volume_threshold)
CGAL_add_named_parameter(dry_run_t, dry_run, dry_run)
// List of named parameters that we use in the package 'Surface Mesh Simplification'
CGAL_add_named_parameter(get_cost_policy_t, get_cost_policy, get_cost)
@@ -91,14 +96,14 @@ CGAL_add_named_parameter(get_placement_policy_t, get_placement_policy, get_place
//to be documented
CGAL_add_named_parameter(face_normal_t, face_normal, face_normal_map)
CGAL_add_named_parameter(random_seed_t, random_seed, random_seed)
CGAL_add_named_parameter(tolerance_map_t, tolerance_map, tolerance_map)
CGAL_add_named_parameter(do_lock_mesh_t, do_lock_mesh, do_lock_mesh)
CGAL_add_named_parameter(do_simplify_border_t, do_simplify_border, do_simplify_border)
//internal
CGAL_add_named_parameter(weight_calculator_t, weight_calculator, weight_calculator)
CGAL_add_named_parameter(use_bool_op_to_clip_surface_t, use_bool_op_to_clip_surface, use_bool_op_to_clip_surface)
// List of named parameters used in the Point Set Processing package
CGAL_add_named_parameter(point_t, point_map, point_map)
CGAL_add_named_parameter(query_point_t, query_point_map, query_point_map)
CGAL_add_named_parameter(normal_t, normal_map, normal_map)
CGAL_add_named_parameter(diagonalize_traits_t, diagonalize_traits, diagonalize_traits)
@@ -120,6 +125,15 @@ CGAL_add_named_parameter(plane_index_t, plane_index_map, plane_index_map)
CGAL_add_named_parameter(select_percentage_t, select_percentage, select_percentage)
CGAL_add_named_parameter(require_uniform_sampling_t, require_uniform_sampling, require_uniform_sampling)
CGAL_add_named_parameter(point_is_constrained_t, point_is_constrained, point_is_constrained_map)
CGAL_add_named_parameter(transformation_t, transformation, transformation)
CGAL_add_named_parameter(point_set_filters_t, point_set_filters, point_set_filters)
CGAL_add_named_parameter(matcher_t, matcher, matcher)
CGAL_add_named_parameter(outlier_filters_t, outlier_filters, outlier_filters)
CGAL_add_named_parameter(error_minimizer_t, error_minimizer, error_minimizer)
CGAL_add_named_parameter(transformation_checkers_t, transformation_checkers, transformation_checkers)
CGAL_add_named_parameter(inspector_t, inspector, inspector)
CGAL_add_named_parameter(logger_t, logger, logger)
CGAL_add_named_parameter(pointmatcher_config_t, pointmatcher_config, pointmatcher_config)
// List of named parameters used in Surface_mesh_approximation package
CGAL_add_named_parameter(verbose_level_t, verbose_level, verbose_level)
@@ -141,3 +155,9 @@ CGAL_add_named_parameter(proxies_t, proxies, proxies)
CGAL_add_named_parameter(anchors_t, anchors, anchors)
CGAL_add_named_parameter(triangles_t, triangles, triangles)
CGAL_add_named_parameter(number_of_samples_t, number_of_samples, number_of_samples)
CGAL_add_named_parameter(accuracy_t, accuracy, accuracy)
CGAL_add_named_parameter(maximum_running_time_t, maximum_running_time, maximum_running_time)
CGAL_add_named_parameter(overlap_t, overlap, overlap)
CGAL_add_named_parameter(maximum_normal_deviation_t, maximum_normal_deviation, maximum_normal_deviation)
+54 -172
View File
@@ -14,72 +14,45 @@
#define CGAL_BOOST_GRAPH_BGL_PROPERTIES_H
#include <CGAL/property_map.h>
#include <CGAL/Dynamic_property_map.h>
#include <CGAL/basic.h>
#include <boost/graph/properties.hpp>
#include <boost/graph/graph_traits.hpp>
#include <boost/type_traits/is_const.hpp>
#include <boost/type_traits/remove_reference.hpp>
#include <CGAL/Dynamic_property_map.h>
#include <CGAL/basic.h>
#include <string>
#include <vector>
#include <type_traits>
namespace CGAL {
namespace CGAL{
/// \ingroup PkgBGLProperties
/// \brief graph_has_property is used to indicate if
/// a model of `HalfedgeGraph` or `FaceGraph`
/// has an internal property associated with the
/// given `PropertyTag`.
///
/// It inherits from `CGAL::Tag_true` if there is a
/// default internal property map for the
/// corresponding property tag and from
/// `CGAL::Tag_false` otherwise.
///
/// \tparam Graph a model of `HalfedgeGraph` or `FaceGraph`
/// \tparam PropertyTag the type of a property tag
/// referring to the property of interest.
///
template<typename Graph, typename PropertyTag>
struct graph_has_property
#ifndef DOXYGEN_RUNNING
: CGAL::Tag_false
#endif
{};
}
/// Boost Namespace
struct graph_has_property : CGAL::Tag_false { };
} // namespace CGAL
namespace boost {
/// \ingroup PkgBGLProperties
/// @{
/// A property tag which refers to the geometric embedding property
/// of a vertex of a \ref HalfedgeGraph.
enum vertex_point_t { vertex_point };
enum vertex_external_index_t { vertex_external_index } ;
/// A property tag which refers to the property
/// of a halfedge of being a border halfedge.
enum edge_external_index_t { edge_external_index } ;
// vertex_index_t is defined in boost
enum vertex_external_index_t { vertex_external_index };
/// A property tag which identifies the *index* property of
/// a halfedge of a \ref HalfedgeGraph.
enum halfedge_index_t { halfedge_index };
enum halfedge_external_index_t { halfedge_external_index } ;
enum halfedge_index_t { halfedge_index };
enum halfedge_external_index_t { halfedge_external_index };
// edge_index_t is defined in boost
enum edge_external_index_t { edge_external_index };
/// A property tag which identifies the *index* property of
/// a face of a \ref FaceGraph.
enum face_index_t { face_index };
enum face_external_index_t { face_external_index } ;
enum face_external_index_t { face_external_index };
struct cgal_no_property
{
typedef bool type;
typedef const bool const_type;
};
/// @}
// Introduce those two tags so we can use BOOST_INSTALL_PROPERTY
// macro. This is dangerous because we now rely on implementation
// details.
@@ -97,12 +70,16 @@ BOOST_INSTALL_PROPERTY(face, external_index);
namespace CGAL {
using boost::vertex_point_t;
using boost::vertex_point;
using boost::vertex_index_t;
using boost::vertex_index;
using boost::vertex_external_index_t;
using boost::vertex_external_index;
using boost::halfedge_index_t;
using boost::halfedge_index;
using boost::halfedge_external_index_t;
using boost::halfedge_external_index;
using boost::edge_index_t;
using boost::edge_index;
using boost::edge_external_index_t;
using boost::edge_external_index;
using boost::face_index_t;
@@ -111,128 +88,7 @@ using boost::face_external_index_t;
using boost::face_external_index;
} // CGAL
namespace CGAL{
namespace helpers {
// matches read-write property maps
template <class PolygonMesh, class FaceIndexMap, class Tag>
void init_face_indices(PolygonMesh& pm,
FaceIndexMap& fid,
boost::read_write_property_map_tag,
Tag)
{
typename boost::property_traits<FaceIndexMap>::value_type i = 0;
for(typename boost::graph_traits<PolygonMesh>::face_descriptor fd :
faces(pm))
{
put(fid, fd, i);
++i;
}
}
template <class PolygonMesh, class VertexIndexMap, class Tag>
void init_vertex_indices(PolygonMesh& pm,
VertexIndexMap& vid,
boost::read_write_property_map_tag,
Tag)
{
typename boost::property_traits<VertexIndexMap>::value_type i = 0;
for(typename boost::graph_traits<PolygonMesh>::vertex_descriptor vd :
vertices(pm))
{
put(vid, vd, i);
++i;
}
}
template <class PolygonMesh, class HalfedgeIndexMap, class Tag>
void init_halfedge_indices(PolygonMesh& pm,
HalfedgeIndexMap& hid,
boost::read_write_property_map_tag,
Tag)
{
typename boost::property_traits<HalfedgeIndexMap>::value_type i = 0;
for(typename boost::graph_traits<PolygonMesh>::halfedge_descriptor hd :
halfedges(pm))
{
put(hid, hd, i);
++i;
}
}
// matches mutable Lvalue property maps
template <class PolygonMesh, class FaceIndexMap>
void init_face_indices(PolygonMesh& pm,
FaceIndexMap& fid,
boost::lvalue_property_map_tag,
boost::false_type)
{
init_face_indices(pm, fid,
boost::read_write_property_map_tag(), boost::false_type());
}
template <class PolygonMesh, class VertexIndexMap>
void init_vertex_indices(PolygonMesh& pm,
VertexIndexMap& vid,
boost::lvalue_property_map_tag,
boost::false_type)
{
init_vertex_indices(pm, vid,
boost::read_write_property_map_tag(), boost::false_type());
}
template <class PolygonMesh, class HalfedgeIndexMap>
void init_halfedge_indices(PolygonMesh& pm,
HalfedgeIndexMap& hid,
boost::lvalue_property_map_tag,
boost::false_type)
{
init_halfedge_indices(pm, hid,
boost::read_write_property_map_tag(), boost::false_type());
}
// matches all other types of property map
template <class PolygonMesh, class FaceIndexMap, class MapTag, class Tag>
void init_face_indices(PolygonMesh&, FaceIndexMap, MapTag, Tag)
{}
template <class PolygonMesh, class VertexIndexMap, class MapTag, class Tag>
void init_vertex_indices(PolygonMesh&, VertexIndexMap, MapTag, Tag)
{}
template <class PolygonMesh, class HalfedgeIndexMap, class MapTag, class Tag>
void init_halfedge_indices(PolygonMesh&, HalfedgeIndexMap, MapTag, Tag)
{}
template <class PolygonMesh, class FaceIndexMap>
void init_face_indices(PolygonMesh& pm, FaceIndexMap fid)
{
init_face_indices(pm, fid,
typename boost::property_traits<FaceIndexMap>::category(),
typename boost::is_const<
typename boost::remove_reference<
typename boost::property_traits<FaceIndexMap>::reference
>::type >::type() );
}
template <class PolygonMesh, class VertexIndexMap>
void init_vertex_indices(PolygonMesh& pm, VertexIndexMap vid)
{
init_vertex_indices(pm, vid,
typename boost::property_traits<VertexIndexMap>::category(),
typename boost::is_const<
typename boost::remove_reference<
typename boost::property_traits<VertexIndexMap>::reference
>::type >::type() );
}
template <class PolygonMesh, class HalfedgeIndexMap>
void init_halfedge_indices(PolygonMesh& pm, HalfedgeIndexMap hid)
{
init_halfedge_indices(pm, hid,
typename boost::property_traits<HalfedgeIndexMap>::category(),
typename boost::is_const<
typename boost::remove_reference<
typename boost::property_traits<HalfedgeIndexMap>::reference
>::type >::type() );
}
} //namespace helpers
namespace CGAL {
namespace internal {
template<typename Polyhedron, typename Handle>
@@ -260,8 +116,8 @@ struct Edge_index_accessor
};
template<typename Handle, typename ValueType, typename Reference,
bool is_const = boost::is_const<
typename boost::remove_reference<Reference>::type >::value>
bool is_const = std::is_const<
typename std::remove_reference<Reference>::type >::value>
struct Point_accessor
: boost::put_get_helper< Reference, Point_accessor<Handle, ValueType, Reference> >
{
@@ -293,6 +149,32 @@ struct Point_accessor<Handle, ValueType, ConstReference, true>
reference operator[](Handle h) const { return h->point(); }
};
// this one is basically 'readable_property_map_tag'
template <typename PropertyMap,
typename PropertyMapCategory = typename boost::property_traits<PropertyMap>::category>
struct Is_writable_property_map : CGAL::Tag_false { };
template <typename PropertyMap>
struct Is_writable_property_map<PropertyMap, boost::writable_property_map_tag> : CGAL::Tag_true { };
template <typename PropertyMap>
struct Is_writable_property_map<PropertyMap, boost::read_write_property_map_tag> : CGAL::Tag_true { };
// 'lvalue_pmap_tag' is annoying, because the property map is allowed to be non-mutable,
// but boost::lvalue_property_map_tag is defined as:
// struct lvalue_property_map_tag : public read_write_property_map_tag
// so we can't just check that 'writable_property_map_tag' is a base of the the lvalue tag.
//
// This checks if the reference is non-const, which is not completely correct: map[key] returning
// a non-const reference doesn't mean that 'put(map, key, val)' exists, which is what a writable
// property map must define.
template <typename PropertyMap>
struct Is_writable_property_map<PropertyMap, boost::lvalue_property_map_tag>
: boost::mpl::if_c<std::is_const<typename std::remove_reference<
typename boost::property_traits<PropertyMap>::reference>::type>::value,
CGAL::Tag_false, CGAL::Tag_true>::type
{ };
} // namespace internal
// Needed by PMP::detec_features and Mesh_3
@@ -303,12 +185,12 @@ enum vertex_time_stamp_t { vertex_time_stamp};
enum halfedge_time_stamp_t { halfedge_time_stamp};
enum face_time_stamp_t { face_time_stamp};
template <typename ID>
template<typename ID>
struct vertex_incident_patches_t {
typedef ID type;
};
template <typename ID>
template<typename ID>
struct face_patch_id_t {
typedef ID type;
};
@@ -112,6 +112,39 @@ struct property_map<CGAL::Seam_mesh<TM, SEM, SVM>, CGAL::vertex_point_t>
typedef CGAL::Seam_mesh_point_map<TM, SEM, SVM> type;
typedef type const_type;
};
template <class TM, class SEM, class SVM, typename T>
struct property_map<CGAL::Seam_mesh<TM, SEM, SVM>, CGAL::dynamic_vertex_property_t<T> >
{
typedef typename boost::graph_traits<CGAL::Seam_mesh<TM, SEM, SVM> >::vertex_descriptor vertex_descriptor;
typedef CGAL::internal::Dynamic_property_map<vertex_descriptor,T> type;
typedef type const_type;
};
template <class TM, class SEM, class SVM, typename T>
struct property_map<CGAL::Seam_mesh<TM, SEM, SVM>, CGAL::dynamic_halfedge_property_t<T> >
{
typedef typename boost::graph_traits<CGAL::Seam_mesh<TM, SEM, SVM> >::halfedge_descriptor halfedge_descriptor;
typedef CGAL::internal::Dynamic_property_map<halfedge_descriptor,T> type;
typedef type const_type;
};
template <class TM, class SEM, class SVM, typename T>
struct property_map<CGAL::Seam_mesh<TM, SEM, SVM>, CGAL::dynamic_edge_property_t<T> >
{
typedef typename boost::graph_traits<CGAL::Seam_mesh<TM, SEM, SVM> >::edge_descriptor edge_descriptor;
typedef CGAL::internal::Dynamic_property_map<edge_descriptor,T> type;
typedef type const_type;
};
template <class TM, class SEM, class SVM, typename T>
struct property_map<CGAL::Seam_mesh<TM, SEM, SVM>, CGAL::dynamic_face_property_t<T> >
{
typedef typename boost::graph_traits<CGAL::Seam_mesh<TM, SEM, SVM> >::face_descriptor face_descriptor;
typedef CGAL::internal::Dynamic_property_map<face_descriptor,T> type;
typedef type const_type;
};
} // namespace boost
namespace CGAL {
+20 -8
View File
@@ -578,32 +578,44 @@ void expand_face_selection_for_removal(const FaceRange& faces_to_be_deleted,
next_around_vertex = opposite( next(hd, tm), tm);
if (hd==start) break;
}
if ( get(is_selected, face(next_around_vertex, tm) ) ) continue; //all incident faces will be removed
if ( is_border(next_around_vertex,tm) || get(is_selected, face(next_around_vertex, tm) ) ) continue; //all incident faces will be removed
while( true )
{
// collect non-selected faces
std::vector<halfedge_descriptor> faces_traversed;
bool non_selected_face_range_has_boundary = false; // handle non-manifold situations when crossing a border
do
{
faces_traversed.push_back(next_around_vertex);
next_around_vertex = opposite( next(next_around_vertex, tm), tm);
if (is_border(next_around_vertex,tm))
{
next_around_vertex = opposite( next(next_around_vertex, tm), tm);
if (!get(is_selected, face(next_around_vertex, tm) ))
{
non_selected_face_range_has_boundary=true; // always non-manifold after removal of the selection
break;
}
}
CGAL_assertion(!is_border(next_around_vertex,tm));
}
while( !get(is_selected, face(next_around_vertex, tm) ) );
// go over the connected components of faces to remove
do{
if (!non_selected_face_range_has_boundary)
{
// go over the connected components of faces to remove
do{
if (next_around_vertex==start)
break;
next_around_vertex = opposite( next(next_around_vertex, tm), tm);
}
while(is_border(next_around_vertex,tm) || get(is_selected, face(next_around_vertex, tm) ) );
if (next_around_vertex==start)
break;
next_around_vertex = opposite( next(next_around_vertex, tm), tm);
}
while( get(is_selected, face(next_around_vertex, tm) ) );
if (next_around_vertex==start)
break;
// else we simply mark the range of traversed faces and start a new range after the border
for(halfedge_descriptor f_hd : faces_traversed)
{
@@ -0,0 +1,18 @@
OFF
9 7 0
0 0 0
1 0 0
2 0 0
2 1 0
2 2 0
1 2 0
0 2 0
0 1 0
1 1 0
3 0 1 8
3 1 2 8
3 2 3 8
3 3 4 8
3 5 6 8
3 6 7 8
3 7 0 8
+39
View File
@@ -402,6 +402,44 @@ test_swap_edges()
}
}
template <typename T>
void
add_face_bug()
{
typedef boost::graph_traits<T> GT;
typedef typename GT::vertex_descriptor vertex_descriptor;
typedef typename GT::halfedge_descriptor halfedge_descriptor;
T g;
std::vector<vertex_descriptor> vs;
vs.push_back( add_vertex(g) ); // Kernel::Point_3(0,1,0)
vs.push_back( add_vertex(g) ); // Kernel::Point_3(4,1,0)
vs.push_back( add_vertex(g) ); // Kernel::Point_3(5,2,0)
vs.push_back( add_vertex(g) ); // Kernel::Point_3(4,0,0)
CGAL::Euler::add_face(CGAL::make_array(vs[0], vs[1], vs[2]), g);
CGAL::Euler::add_face(CGAL::make_array(vs[1], vs[3], vs[2]), g);
// force vertex halfedge to not be a border halfedge
for(vertex_descriptor v : vertices(g))
{
halfedge_descriptor h = halfedge(v, g);
if ( CGAL::is_border(h, g) )
set_halfedge(v, prev(opposite(h, g), g), g);
assert(target(halfedge(v, g), g)==v);
}
vs.push_back( add_vertex(g) ); // Kernel::Point_3(0,0,0)
vs.push_back( add_vertex(g) ); // Kernel::Point_3(1,0,0)
CGAL::Euler::add_face(CGAL::make_array(vs[4],vs[5],vs[0]), g);
vs.push_back( add_vertex(g) ); // Kernel::Point_3(2,0,0)
vs.push_back( add_vertex(g) ); // Kernel::Point_3(3,0,0)
CGAL::Euler::add_face(CGAL::make_array(vs[6],vs[7],vs[1]), g);
CGAL::Euler::add_face(CGAL::make_array(vs[7],vs[3],vs[1]), g);
}
template <typename Graph>
void
test_Euler_operations()
@@ -421,6 +459,7 @@ test_Euler_operations()
join_split_inverse<Graph>();
does_satisfy_link_condition<Graph>();
test_swap_edges<Graph>();
add_face_bug<Graph>();
}
int main()
+10 -10
View File
@@ -491,13 +491,13 @@ int main()
typedef boost::graph_traits<Polyhedron> PolyTraits;
typedef boost::property_map<Polyhedron, boost::vertex_point_t>::type VPMap;
typedef boost::property_map<Polyhedron, boost::vertex_point_t>::const_type VPMap;
typedef PolyTraits::face_descriptor poly_face_descriptor;
typedef boost::associative_property_map< std::map<poly_face_descriptor,
PolyTraits::faces_size_type> > FCMap;
typedef boost::property_map<Polyhedron, CGAL::face_external_index_t>::type FIMap;
typedef boost::property_map<Polyhedron, CGAL::vertex_external_index_t>::type VIMap;
typedef boost::property_map<Polyhedron, CGAL::halfedge_external_index_t>::type HIMap;
typedef boost::property_map<Polyhedron, CGAL::face_external_index_t>::const_type FIMap;
typedef boost::property_map<Polyhedron, CGAL::vertex_external_index_t>::const_type VIMap;
typedef boost::property_map<Polyhedron, CGAL::halfedge_external_index_t>::const_type HIMap;
typedef CGAL::Face_filtered_graph<Polyhedron, FIMap, VIMap, HIMap> Poly_Adapter;
auto poly = std::make_unique<Polyhedron>();
CGAL::make_tetrahedron(
@@ -516,14 +516,14 @@ int main()
FCMap poly_fccmap(fc_map);
VPMap vpmap = get(boost::vertex_point, *poly);
CGAL::Polygon_mesh_processing::connected_components(*poly, poly_fccmap, CGAL::Polygon_mesh_processing::parameters::
edge_is_constrained_map(Constraint<Polyhedron, VPMap >(*poly, vpmap)).
face_index_map(poly_fimap));
CGAL::Polygon_mesh_processing::connected_components(*poly, poly_fccmap,
CGAL::Polygon_mesh_processing::parameters::edge_is_constrained_map(Constraint<Polyhedron, VPMap >(*poly, vpmap))
.face_index_map(poly_fimap));
Poly_Adapter poly_adapter(*poly,
pids,
poly_fccmap,
CGAL::parameters::face_index_map(poly_fimap).
vertex_index_map(poly_vimap).
halfedge_index_map(poly_himap));
CGAL::parameters::face_index_map(poly_fimap)
.vertex_index_map(poly_vimap)
.halfedge_index_map(poly_himap));
test_mesh<Polyhedron, FCMap, Poly_Adapter>(poly_adapter);
}
@@ -14,6 +14,68 @@ typedef CGAL::Exact_predicates_inexact_constructions_kernel Kernel;
typedef CGAL::Surface_mesh<Kernel::Point_3> SM;
typedef boost::graph_traits<SM>::face_descriptor face_descriptor;
void border_cases()
{
SM sm_ref;
std::ifstream input("data/nm_selection_removal.off");
input >> sm_ref;
{
SM sm = sm_ref;
std::vector<SM::Face_index> faces_to_remove;
faces_to_remove.push_back(SM::Face_index(5));
faces_to_remove.push_back(SM::Face_index(6));
SM::Property_map<SM::Face_index, bool> is_selected = sm.add_property_map<SM::Face_index, bool>("f:is_selected", false).first;
is_selected[SM::Face_index(5)]=true;
is_selected[SM::Face_index(6)]=true;
CGAL::expand_face_selection_for_removal(faces_to_remove,
sm,
is_selected);
int i=0;
for(face_descriptor fh : sm.faces())
if(!is_selected[fh]) ++i;
assert(i==4);
}
{
SM sm = sm_ref;
std::vector<SM::Face_index> faces_to_remove;
faces_to_remove.push_back(SM::Face_index(4));
faces_to_remove.push_back(SM::Face_index(6));
SM::Property_map<SM::Face_index, bool> is_selected = sm.add_property_map<SM::Face_index, bool>("f:is_selected", false).first;
is_selected[SM::Face_index(4)]=true;
is_selected[SM::Face_index(6)]=true;
CGAL::expand_face_selection_for_removal(faces_to_remove,
sm,
is_selected);
int i=0;
for(face_descriptor fh : sm.faces())
if(!is_selected[fh]) ++i;
assert(i==1 || i==4); // depends on the start point
}
{
SM sm = sm_ref;
std::vector<SM::Face_index> faces_to_remove;
faces_to_remove.push_back(SM::Face_index(4));
faces_to_remove.push_back(SM::Face_index(5));
faces_to_remove.push_back(SM::Face_index(6));
SM::Property_map<SM::Face_index, bool> is_selected = sm.add_property_map<SM::Face_index, bool>("f:is_selected", false).first;
is_selected[SM::Face_index(4)]=true;
is_selected[SM::Face_index(5)]=true;
is_selected[SM::Face_index(6)]=true;
CGAL::expand_face_selection_for_removal(faces_to_remove,
sm,
is_selected);
int i=0;
for(face_descriptor fh : sm.faces())
if(!is_selected[fh]) ++i;
assert(i==4); // depends on the start point
}
}
int main()
{
SM sm;
@@ -60,6 +122,8 @@ int main()
assert( sm.number_of_faces()+30 < nb_input_faces);
assert(is_valid_polygon_mesh(sm));
border_cases();
return 0;
}
+23 -17
View File
@@ -38,6 +38,7 @@
#include <CGAL/boost/graph/properties_Constrained_Delaunay_triangulation_2.h>
#include <CGAL/boost/graph/graph_traits_Constrained_triangulation_plus_2.h>
#include <CGAL/boost/graph/properties_Constrained_triangulation_plus_2.h>
#include <CGAL/boost/graph/Seam_mesh.h>
#include <CGAL/boost/graph/io.h>
@@ -57,6 +58,10 @@ typedef CGAL::Linear_cell_complex_for_bgl_combinatorial_map_helper
typedef CGAL::Surface_mesh<Point_3> SM;
typedef SM::Property_map<SM::Edge_index, bool> Seam_edge_pmap;
typedef SM::Property_map<SM::Vertex_index, bool> Seam_vertex_pmap;
typedef CGAL::Seam_mesh<SM, Seam_edge_pmap, Seam_vertex_pmap> Seam_mesh;
#if defined(CGAL_USE_OPENMESH)
#include <OpenMesh/Core/IO/MeshIO.hh>
@@ -73,6 +78,8 @@ typedef OpenMesh::PolyMesh_ArrayKernelT</* MyTraits*/> OMesh;
typedef CGAL::Triangulation_vertex_base_with_id_2<Kernel> Vbb;
typedef CGAL::Triangulation_face_base_with_id_2<Kernel> Fbb;
typedef CGAL::Triangulation_2<Kernel> Triangulation_no_id_2;
typedef CGAL::Triangulation_2<Kernel,
CGAL::Triangulation_data_structure_2<Vbb, Fbb> > Triangulation_2;
typedef CGAL::Delaunay_triangulation_2<Kernel,
@@ -189,8 +196,6 @@ template <typename Tr>
Tr build_dummy_triangulation()
{
typedef typename Tr::Point Point;
typedef typename boost::graph_traits<Tr>::vertex_descriptor vertex_descriptor;
typedef typename boost::graph_traits<Tr>::face_descriptor face_descriptor;
Tr t;
t.insert(Point(0.1,0));
@@ -199,24 +204,25 @@ Tr build_dummy_triangulation()
t.insert(Point(0,1));
t.insert(Point(0,2));
int id = 0;
for(vertex_descriptor vd : vertices(t))
vd->id() = id++;
id = 0;
for(face_descriptor fd : faces(t))
fd->id() = id++;
return t;
}
Triangulation_2 t2_data() { return build_dummy_triangulation<Triangulation_2>(); }
Delaunay_triangulation_2 dt2_data() { return build_dummy_triangulation<Delaunay_triangulation_2>(); }
Regular_triangulation_2 rt2_data() { return build_dummy_triangulation<Regular_triangulation_2>(); }
Constrained_triangulation_2 ct2_data() { return build_dummy_triangulation<Constrained_triangulation_2>(); }
Constrained_Delaunay_triangulation_2 cdt2_data() { return build_dummy_triangulation<Constrained_Delaunay_triangulation_2>(); }
CDT_P2 cdtp2_data() { return build_dummy_triangulation<CDT_P2>(); }
Triangulation_hierarchy_2 t2h_data() { return build_dummy_triangulation<Triangulation_hierarchy_2>(); }
template <typename Tr>
Tr build_dummy_triangulation_with_ids()
{
Tr t = build_dummy_triangulation<Tr>();
CGAL::set_triangulation_ids(t);
return t;
}
Triangulation_no_id_2 t2_no_id_data() { return build_dummy_triangulation<Triangulation_no_id_2>(); }
Triangulation_2 t2_data() { return build_dummy_triangulation_with_ids<Triangulation_2>(); }
Delaunay_triangulation_2 dt2_data() { return build_dummy_triangulation_with_ids<Delaunay_triangulation_2>(); }
Regular_triangulation_2 rt2_data() { return build_dummy_triangulation_with_ids<Regular_triangulation_2>(); }
Constrained_triangulation_2 ct2_data() { return build_dummy_triangulation_with_ids<Constrained_triangulation_2>(); }
Constrained_Delaunay_triangulation_2 cdt2_data() { return build_dummy_triangulation_with_ids<Constrained_Delaunay_triangulation_2>(); }
CDT_P2 cdtp2_data() { return build_dummy_triangulation_with_ids<CDT_P2>(); }
Triangulation_hierarchy_2 t2h_data() { return build_dummy_triangulation_with_ids<Triangulation_hierarchy_2>(); }
template <typename Graph>
struct Surface_fixture_1 {
+407 -63
View File
@@ -1,115 +1,459 @@
#include "test_Prefix.h"
#include <CGAL/boost/graph/Euler_operations.h>
#include <boost/unordered_set.hpp>
template< typename G,
typename ForwardRange,
typename IndexPropertyMap
>
void index_uniqueness(const G&,
ForwardRange range,
IndexPropertyMap pm)
// #define CGAL_TEST_PROPERTIES_DEBUG
namespace CGAL {
template <typename Key, typename Value, typename Container>
struct Non_mutable_property_map
{
typedef Key key_type;
typedef Value value_type;
typedef value_type reference;
typedef boost::readable_property_map_tag category;
Non_mutable_property_map(const Container& c) : m_c(c) { }
friend reference get(const Non_mutable_property_map<Key, Value, Container>& pmap, key_type k)
{
return pmap.m_c.at(k);
}
private:
const Container& m_c;
};
template <typename Key, typename Value, typename Container>
struct RW_property_map
{
typedef Key key_type;
typedef Value value_type;
typedef value_type& reference;
typedef boost::read_write_property_map_tag category;
RW_property_map(Container& c) : m_c(c) { }
friend void put(RW_property_map<Key, Value, Container>& pmap, const key_type& k, const value_type& val)
{
pmap.m_c[k] = val;
}
friend reference get(RW_property_map<Key, Value, Container>& pmap, const key_type& k)
{
return pmap.m_c[k];
}
private:
Container& m_c;
};
} // namespace CGAL
template<typename Graph,
typename ForwardRange,
typename IndexPropertyMap>
void test_uniqueness(const Graph&,
const ForwardRange& range,
IndexPropertyMap index_map)
{
#ifdef CGAL_TEST_PROPERTIES_DEBUG
std::cout << std::endl
<< "Checking the uniqueness of the property map of type: "
<< typeid(IndexPropertyMap).name() << std::endl;
std::cout << "Element type: " << typeid(typename boost::range_value<ForwardRange>::type).name() << std::endl;
#endif
typename boost::range_iterator<ForwardRange>::type
begin = boost::begin(range),
begin = boost::begin(range),
begin2 = boost::begin(range),
end = boost::end(range);
typedef boost::unordered_set<typename IndexPropertyMap::value_type> id_map;
typedef std::pair<typename id_map::iterator, bool> resultp;
id_map m;
while(begin != end) {
resultp r = m.insert(get(pm, *begin));
id_map m;
while(begin != end)
{
resultp r = m.insert(get(index_map, *begin));
#ifdef CGAL_TEST_PROPERTIES_DEBUG
std::cout << "id: " << get(index_map, *begin) << std::endl;
#endif
++begin;
assert(r.second);
assert(r.second); // already seen that id
}
assert(std::distance(begin2, end) == static_cast<std::ptrdiff_t>(m.size()));
}
void index_uniqueness_poly(const Polyhedron& g)
template<typename Graph,
typename NamedParameters>
void test_vertex_index_map_uniqueness(const Graph& g,
const NamedParameters& np)
{
index_uniqueness(g, edges(g) , get(boost::edge_index, g));
index_uniqueness(g, vertices(g), get(boost::vertex_index, g));
index_uniqueness(g, faces(g), get(boost::face_index, g));
index_uniqueness(g, halfedges(g), get(boost::halfedge_index, g));
typedef typename CGAL::GetInitializedVertexIndexMap<Graph, NamedParameters>::type VIM;
typedef typename CGAL::GetInitializedVertexIndexMap<Graph, NamedParameters>::const_type CVIM;
index_uniqueness(g, edges(g) , get(boost::edge_external_index, g));
index_uniqueness(g, vertices(g), get(boost::vertex_external_index, g));
index_uniqueness(g, faces(g), get(boost::face_external_index, g));
index_uniqueness(g, halfedges(g), get(boost::halfedge_external_index, g));
// in the case where the map is passed by NP, its type doesn't depend on whether the mesh is const or not
static_assert((std::is_same<VIM, CVIM>::value), "VIM, CVIM must be the same type");
VIM ivim = CGAL::get_initialized_vertex_index_map(g, np);
return test_uniqueness(g, vertices(g), ivim);
}
void index_uniqueness_lcc(const LCC& g)
template<typename Graph,
typename NamedParameters>
void test_halfedge_index_map_uniqueness(const Graph& g,
const NamedParameters& np)
{
index_uniqueness(g, edges(g) , get(boost::edge_index, g));
index_uniqueness(g, vertices(g), get(boost::vertex_index, g));
index_uniqueness(g, faces(g), get(boost::face_index, g));
index_uniqueness(g, halfedges(g), get(boost::halfedge_index, g));
typedef typename CGAL::GetInitializedHalfedgeIndexMap<Graph, NamedParameters>::type HIM;
typedef typename CGAL::GetInitializedHalfedgeIndexMap<Graph, NamedParameters>::const_type CHIM;
// in the case where the map is passed by NP, its type doesn't depend on whether the mesh is const or not
static_assert((std::is_same<HIM, CHIM>::value), "HIM, CHIM must be the same type");
HIM ihim = CGAL::get_initialized_halfedge_index_map(g, np);
return test_uniqueness(g, halfedges(g), ihim);
}
void index_uniqueness_sm(const SM& g)
template<typename Graph,
typename NamedParameters>
void test_edge_index_map_uniqueness(const Graph& g,
const NamedParameters& np)
{
index_uniqueness(g, edges(g) , get(boost::edge_index, g));
index_uniqueness(g, vertices(g), get(boost::vertex_index, g));
index_uniqueness(g, faces(g), get(boost::face_index, g));
index_uniqueness(g, halfedges(g), get(boost::halfedge_index, g));
typedef typename CGAL::GetInitializedEdgeIndexMap<Graph, NamedParameters>::type EIM;
typedef typename CGAL::GetInitializedEdgeIndexMap<Graph, NamedParameters>::const_type CEIM;
// in the case where the map is passed by NP, its type doesn't depend on whether the mesh is const or not
static_assert((std::is_same<EIM, CEIM>::value), "EIM, CEIM must be the same type");
EIM ieim = CGAL::get_initialized_edge_index_map(g, np);
return test_uniqueness(g, edges(g), ieim);
}
#if defined(CGAL_USE_OPENMESH)
void index_uniqueness_omesh(const OMesh& g)
template<typename Graph,
typename NamedParameters>
void test_face_index_map_uniqueness(const Graph& g,
const NamedParameters& np)
{
index_uniqueness(g, edges(g) , get(boost::edge_index, g));
index_uniqueness(g, vertices(g), get(boost::vertex_index, g));
index_uniqueness(g, faces(g), get(boost::face_index, g));
index_uniqueness(g, halfedges(g), get(boost::halfedge_index, g));
typedef typename CGAL::GetInitializedFaceIndexMap<Graph, NamedParameters>::type FIM;
typedef typename CGAL::GetInitializedFaceIndexMap<Graph, NamedParameters>::const_type CFIM;
// in the case where the map is passed by NP, its type doesn't depend on whether the mesh is const or not
static_assert((std::is_same<FIM, CFIM>::value), "FIM, CFIM must be the same type");
FIM ifim = CGAL::get_initialized_face_index_map(g, np);
return test_uniqueness(g, faces(g), ifim);
}
////////////////////////////////////////// const ///////////////////////////////////////////////////
template <typename Graph>
void test_internal_index_maps_const(const Graph& g)
{
test_uniqueness(g, vertices(g), get(boost::vertex_index, g));
test_uniqueness(g, halfedges(g), get(boost::halfedge_index, g));
test_uniqueness(g, edges(g) , get(boost::edge_index, g));
test_uniqueness(g, faces(g), get(boost::face_index, g));
}
template <typename Graph>
void test_initialized_index_maps_const(const Graph& g)
{
typedef typename CGAL::GetInitializedVertexIndexMap<Graph>::const_type VIM;
VIM ivim = CGAL::get_initialized_vertex_index_map(g);
test_uniqueness(g, vertices(g), ivim);
typedef typename CGAL::GetInitializedHalfedgeIndexMap<Graph>::const_type HIM;
HIM ihim = CGAL::get_initialized_halfedge_index_map(g);
test_uniqueness(g, halfedges(g), ihim);
typedef typename CGAL::GetInitializedEdgeIndexMap<Graph>::const_type EIM;
EIM ieim = CGAL::get_initialized_edge_index_map(g);
test_uniqueness(g, edges(g), ieim);
typedef typename CGAL::GetInitializedFaceIndexMap<Graph>::const_type FIM;
FIM ifim = CGAL::get_initialized_face_index_map(g);
test_uniqueness(g, faces(g), ifim);
// Passing an index map via NP
typedef typename boost::graph_traits<Graph>::vertex_descriptor vertex_descriptor;
typedef std::map<vertex_descriptor, int> VertexIndexMap;
typedef boost::associative_property_map<VertexIndexMap> VertexIdPropertyMap; // lvalue_pmap
int vi = static_cast<int>(num_vertices(g));
VertexIndexMap vim;
VertexIdPropertyMap external_vertex_index_map(vim);
for(vertex_descriptor v : vertices(g))
put(external_vertex_index_map, v, --vi);
test_vertex_index_map_uniqueness(g, CGAL::parameters::vertex_index_map(external_vertex_index_map));
// Read-only pmap
typedef typename boost::graph_traits<Graph>::halfedge_descriptor halfedge_descriptor;
typedef std::map<halfedge_descriptor, int> HalfedgeIndexMap;
typedef CGAL::Non_mutable_property_map<halfedge_descriptor, int,
HalfedgeIndexMap> HalfedgeIdPropertyMap;
int hi = 0;
HalfedgeIndexMap him;
HalfedgeIdPropertyMap external_halfedge_index_map(him);
// this should complain that the map is not writable (commented because it does assert)
// CGAL::BGL::internal::initialize_halfedge_index_map(external_halfedge_index_map, g);
// forced to initialize the underlying map
for(halfedge_descriptor h : halfedges(g))
him[h] = hi++;
test_halfedge_index_map_uniqueness(g, CGAL::parameters::halfedge_index_map(external_halfedge_index_map));
// Writable pmap
typedef typename boost::graph_traits<Graph>::edge_descriptor edge_descriptor;
typedef boost::unordered_map<edge_descriptor, int> EdgeIndexMap;
typedef CGAL::RW_property_map<edge_descriptor, int, EdgeIndexMap> EdgeIdPropertyMap;
EdgeIndexMap eim;
EdgeIdPropertyMap external_edge_index_map(eim);
CGAL::BGL::internal::initialize_edge_index_map(external_edge_index_map, g);
test_edge_index_map_uniqueness(g, CGAL::parameters::edge_index_map(external_edge_index_map));
// Just so face_index_map don't feel excluded
typedef typename boost::graph_traits<Graph>::face_descriptor face_descriptor;
typedef std::map<face_descriptor, int> FaceIndexMap;
typedef boost::const_associative_property_map<FaceIndexMap> FaceIdPropertyMap;
FaceIndexMap fim;
FaceIdPropertyMap external_face_index_map(fim);
// 'const_associative_pmap' has category 'lvalue_property_map_tag' but it's not writable
// so below should complain (commented because it does assert)
// CGAL::BGL::internal::initialize_face_index_map(external_face_index_map, g);
// gotta initialize the underlying map
int fi = 0;
for(face_descriptor f : faces(g))
fim[f] = fi++;
test_face_index_map_uniqueness(g, CGAL::parameters::face_index_map(external_face_index_map));
}
template <typename Graph>
void test_all_index_maps_const(const Graph& g)
{
#ifdef CGAL_TEST_PROPERTIES_DEBUG
std::cout << " ---------------------------- Const graph tests" << std::endl;
#endif
template <typename Triangulation>
void index_uniqueness_tr(const Triangulation& g)
{
index_uniqueness(g, edges(g) , get(boost::edge_index, g));
index_uniqueness(g, vertices(g), get(boost::vertex_index, g));
index_uniqueness(g, faces(g), get(boost::face_index, g));
index_uniqueness(g, halfedges(g), get(boost::halfedge_index, g));
test_internal_index_maps_const(g);
test_initialized_index_maps_const(g);
}
int main()
///////////////////////////////////// non-const ////////////////////////////////////////////////////
template <typename Graph>
void test_internal_index_maps(Graph& g)
{
test_uniqueness(g, vertices(g), get(boost::vertex_index, g));
test_uniqueness(g, halfedges(g), get(boost::halfedge_index, g));
test_uniqueness(g, edges(g) , get(boost::edge_index, g));
test_uniqueness(g, faces(g), get(boost::face_index, g));
}
template <typename Graph>
void test_initialized_index_maps(Graph& g)
{
typedef typename CGAL::GetInitializedVertexIndexMap<Graph>::type VIM;
VIM ivim = CGAL::get_initialized_vertex_index_map(g);
test_uniqueness(g, vertices(g), ivim);
typedef typename CGAL::GetInitializedHalfedgeIndexMap<Graph>::type HIM;
HIM ihim = CGAL::get_initialized_halfedge_index_map(g);
test_uniqueness(g, halfedges(g), ihim);
typedef typename CGAL::GetInitializedEdgeIndexMap<Graph>::type EIM;
EIM ieim = CGAL::get_initialized_edge_index_map(g);
test_uniqueness(g, edges(g), ieim);
typedef typename CGAL::GetInitializedFaceIndexMap<Graph>::type FIM;
FIM ifim = CGAL::get_initialized_face_index_map(g);
test_uniqueness(g, faces(g), ifim);
// Passing an index map via NP
typedef typename boost::graph_traits<Graph>::vertex_descriptor vertex_descriptor;
typedef std::map<vertex_descriptor, int> VertexIndexMap;
typedef boost::associative_property_map<VertexIndexMap> VertexIdPropertyMap; // lvalue_pmap
int vi = static_cast<int>(num_vertices(g));
VertexIndexMap vim;
VertexIdPropertyMap external_vertex_index_map(vim);
for(vertex_descriptor v : vertices(g))
put(external_vertex_index_map, v, --vi);
test_vertex_index_map_uniqueness(g, CGAL::parameters::vertex_index_map(external_vertex_index_map));
// Read-only pmap
typedef typename boost::graph_traits<Graph>::halfedge_descriptor halfedge_descriptor;
typedef std::map<halfedge_descriptor, int> HalfedgeIndexMap;
typedef CGAL::Non_mutable_property_map<halfedge_descriptor, int,
HalfedgeIndexMap> HalfedgeIdPropertyMap;
int hi = 0;
HalfedgeIndexMap him;
HalfedgeIdPropertyMap external_halfedge_index_map(him);
// this should complain that the map is not writable (commented because it does assert)
// CGAL::BGL::internal::initialize_halfedge_index_map(external_halfedge_index_map, g);
// forced to initialize the underlying map
for(halfedge_descriptor h : halfedges(g))
him[h] = hi++;
test_halfedge_index_map_uniqueness(g, CGAL::parameters::halfedge_index_map(external_halfedge_index_map));
// Writable pmap
typedef typename boost::graph_traits<Graph>::edge_descriptor edge_descriptor;
typedef boost::unordered_map<edge_descriptor, int> EdgeIndexMap;
typedef CGAL::RW_property_map<edge_descriptor, int, EdgeIndexMap> EdgeIdPropertyMap;
EdgeIndexMap eim;
EdgeIdPropertyMap external_edge_index_map(eim);
CGAL::BGL::internal::initialize_edge_index_map(external_edge_index_map, g);
test_edge_index_map_uniqueness(g, CGAL::parameters::edge_index_map(external_edge_index_map));
// Just so face_index_map don't feel excluded
typedef typename boost::graph_traits<Graph>::face_descriptor face_descriptor;
typedef std::map<face_descriptor, int> FaceIndexMap;
typedef boost::const_associative_property_map<FaceIndexMap> FaceIdPropertyMap;
FaceIndexMap fim;
FaceIdPropertyMap external_face_index_map(fim);
// 'const_associative_pmap' has category 'lvalue_property_map_tag' but it's not writable
// so below should complain (commented because it does assert)
// CGAL::BGL::internal::initialize_face_index_map(external_face_index_map, g);
// gotta initialize the underlying map
int fi = 0;
for(face_descriptor f : faces(g))
fim[f] = fi++;
test_face_index_map_uniqueness(g, CGAL::parameters::face_index_map(external_face_index_map));
}
template <typename Graph>
void test_all_index_maps(Graph& g)
{
#ifdef CGAL_TEST_PROPERTIES_DEBUG
std::cout << " ---------------------------- Non-const graph tests" << std::endl;
#endif
test_internal_index_maps(g);
test_initialized_index_maps(g);
}
template <typename Graph>
void test_graph(Graph& g)
{
#ifdef CGAL_TEST_PROPERTIES_DEBUG
std::cout << "Graph has:" << std::endl
<< "\t" << num_vertices(g) << " vertices (actual: " << vertices(g).size() << ")" << std::endl
<< "\t" << num_halfedges(g) << " halfedges (actual: " << halfedges(g).size() << ")" << std::endl
<< "\t" << num_edges(g) << " edges (actual: " << edges(g).size() << ")" << std::endl
<< "\t" << num_faces(g) << " faces (actual: " << faces(g).size() << ")" << std::endl;
#endif
test_all_index_maps(g);
test_all_index_maps_const(g);
}
void test_poly(Polyhedron& g)
{
test_graph(g);
test_uniqueness(g, edges(g) , get(boost::edge_external_index, g));
test_uniqueness(g, vertices(g), get(boost::vertex_external_index, g));
test_uniqueness(g, faces(g), get(boost::face_external_index, g));
test_uniqueness(g, halfedges(g), get(boost::halfedge_external_index, g));
}
int main(int, char**)
{
std::cout << "testing Polyhedron\n";
std::vector<Polyhedron> polys = poly_data();
for(Polyhedron p : polys)
index_uniqueness_poly(p);
for(Polyhedron& p : polys)
test_poly(p);
std::cout << "testing Linear_cell_complex\n";
std::vector<LCC> lccs = lcc_data();
for(LCC p : lccs)
index_uniqueness_lcc(p);
for(LCC& p : lccs)
test_graph(p);
std::cout << "testing Surface_mesh\n";
std::vector<SM> sms = sm_data();
for(SM p : sms)
index_uniqueness_sm(p);
for(SM& sm : sms)
{
assert(!CGAL::is_empty(sm));
// Add some garbage
CGAL::Euler::join_vertex(*(halfedges(sm).begin()), sm);
test_graph(sm);
// Test on a mesh with no internal index maps
Seam_edge_pmap seam_edges = sm.add_property_map<SM::Edge_index, bool>("e:on_seam", false).first;
Seam_vertex_pmap seam_vertices = sm.add_property_map<SM::Vertex_index, bool>("v:on_seam", false).first;
Seam_mesh seam_mesh(sm, seam_edges, seam_vertices);
test_initialized_index_maps(seam_mesh);
test_initialized_index_maps_const(seam_mesh);
}
#if defined(CGAL_USE_OPENMESH)
std::cout << "testing OpenMesh\n";
std::vector<OMesh> omeshs = omesh_data();
for(OMesh p : omeshs)
index_uniqueness_omesh(p);
for(OMesh& p : omeshs)
test_graph(p);
#endif
std::cout << "testing Triangulations\n";
index_uniqueness_tr(t2_data());
index_uniqueness_tr(dt2_data());
index_uniqueness_tr(rt2_data());
index_uniqueness_tr(ct2_data());
index_uniqueness_tr(cdt2_data());
index_uniqueness_tr(cdtp2_data());
index_uniqueness_tr(t2h_data());
std::cerr << "done\n";
return 0;
Triangulation_2 t2 = t2_data();
test_graph(t2);
Delaunay_triangulation_2 dt2 = dt2_data();
test_graph(dt2);
Regular_triangulation_2 rt2 = rt2_data();
test_graph(rt2);
Constrained_triangulation_2 ct2 = ct2_data();
test_graph(ct2);
Constrained_Delaunay_triangulation_2 cdt2 = cdt2_data();
test_graph(cdt2);
CDT_P2 cdtp2 = cdtp2_data();
test_graph(cdtp2);
Triangulation_hierarchy_2 t2h = t2h_data();
test_graph(t2h);
// no dynamic pmaps in triangulations (yet)
// Triangulation_no_id_2 t2_no_id = t2_no_id_data();
// test_initialized_index_maps(t2_no_id);
// test_initialized_index_maps_const(t2_no_id);
std::cout << "Done!" << std::endl;
return EXIT_SUCCESS;
}
+87 -1
View File
@@ -91,6 +91,11 @@ void test(const NamedParameters& np)
assert(get_parameter(np, CGAL::internal_np::use_area_smoothing).v == 54);
assert(get_parameter(np, CGAL::internal_np::use_Delaunay_flips).v == 55);
assert(get_parameter(np, CGAL::internal_np::use_safety_constraints).v == 56);
assert(get_parameter(np, CGAL::internal_np::area_threshold).v == 57);
assert(get_parameter(np, CGAL::internal_np::volume_threshold).v == 58);
assert(get_parameter(np, CGAL::internal_np::dry_run).v == 59);
assert(get_parameter(np, CGAL::internal_np::do_lock_mesh).v == 60);
assert(get_parameter(np, CGAL::internal_np::do_simplify_border).v == 61);
// Named parameters that we use in the package 'Surface Mesh Simplification'
assert(get_parameter(np, CGAL::internal_np::get_cost_policy).v == 34);
@@ -175,6 +180,11 @@ void test(const NamedParameters& np)
check_same_type<54>(get_parameter(np, CGAL::internal_np::use_area_smoothing));
check_same_type<55>(get_parameter(np, CGAL::internal_np::use_Delaunay_flips));
check_same_type<56>(get_parameter(np, CGAL::internal_np::use_safety_constraints));
check_same_type<57>(get_parameter(np, CGAL::internal_np::area_threshold));
check_same_type<58>(get_parameter(np, CGAL::internal_np::volume_threshold));
check_same_type<59>(get_parameter(np, CGAL::internal_np::dry_run));
check_same_type<60>(get_parameter(np, CGAL::internal_np::do_lock_mesh));
check_same_type<61>(get_parameter(np, CGAL::internal_np::do_simplify_border));
// Named parameters that we use in the package 'Surface Mesh Simplification'
check_same_type<34>(get_parameter(np, CGAL::internal_np::get_cost_policy));
@@ -193,6 +203,43 @@ void test(const NamedParameters& np)
check_same_type<42>(get_parameter(np, CGAL::internal_np::projection_functor));
check_same_type<46>(get_parameter(np, CGAL::internal_np::apply_per_connected_component));
check_same_type<47>(get_parameter(np, CGAL::internal_np::output_iterator));
// Named parameters used in the package 'Point Set Processing'
check_same_type<9000>(get_parameter(np, CGAL::internal_np::point_map));
check_same_type<9001>(get_parameter(np, CGAL::internal_np::query_point_map));
check_same_type<9002>(get_parameter(np, CGAL::internal_np::normal_map));
check_same_type<9003>(get_parameter(np, CGAL::internal_np::diagonalize_traits));
check_same_type<9004>(get_parameter(np, CGAL::internal_np::svd_traits));
check_same_type<9005>(get_parameter(np, CGAL::internal_np::callback));
check_same_type<9006>(get_parameter(np, CGAL::internal_np::sharpness_angle));
check_same_type<9007>(get_parameter(np, CGAL::internal_np::edge_sensitivity));
check_same_type<9008>(get_parameter(np, CGAL::internal_np::neighbor_radius));
check_same_type<9009>(get_parameter(np, CGAL::internal_np::number_of_output_points));
check_same_type<9010>(get_parameter(np, CGAL::internal_np::size));
check_same_type<9011>(get_parameter(np, CGAL::internal_np::maximum_variation));
check_same_type<9012>(get_parameter(np, CGAL::internal_np::degree_fitting));
check_same_type<9013>(get_parameter(np, CGAL::internal_np::degree_monge));
check_same_type<9014>(get_parameter(np, CGAL::internal_np::threshold_percent));
check_same_type<9015>(get_parameter(np, CGAL::internal_np::threshold_distance));
check_same_type<9016>(get_parameter(np, CGAL::internal_np::attraction_factor));
check_same_type<9017>(get_parameter(np, CGAL::internal_np::plane_map));
check_same_type<9018>(get_parameter(np, CGAL::internal_np::plane_index_map));
check_same_type<9019>(get_parameter(np, CGAL::internal_np::select_percentage));
check_same_type<9020>(get_parameter(np, CGAL::internal_np::require_uniform_sampling));
check_same_type<9021>(get_parameter(np, CGAL::internal_np::point_is_constrained));
check_same_type<9022>(get_parameter(np, CGAL::internal_np::number_of_samples));
check_same_type<9023>(get_parameter(np, CGAL::internal_np::accuracy));
check_same_type<9024>(get_parameter(np, CGAL::internal_np::maximum_running_time));
check_same_type<9025>(get_parameter(np, CGAL::internal_np::overlap));
check_same_type<9026>(get_parameter(np, CGAL::internal_np::transformation));
check_same_type<9027>(get_parameter(np, CGAL::internal_np::point_set_filters));
check_same_type<9028>(get_parameter(np, CGAL::internal_np::matcher));
check_same_type<9029>(get_parameter(np, CGAL::internal_np::outlier_filters));
check_same_type<9030>(get_parameter(np, CGAL::internal_np::error_minimizer));
check_same_type<9031>(get_parameter(np, CGAL::internal_np::transformation_checkers));
check_same_type<9032>(get_parameter(np, CGAL::internal_np::inspector));
check_same_type<9033>(get_parameter(np, CGAL::internal_np::logger));
check_same_type<9034>(get_parameter(np, CGAL::internal_np::maximum_normal_deviation));
}
int main()
@@ -265,7 +312,46 @@ int main()
.use_area_smoothing(A<54>(54))
.use_Delaunay_flips(A<55>(55))
.use_safety_constraints(A<56>(56))
.area_threshold(A<57>(57))
.volume_threshold(A<58>(58))
.dry_run(A<59>(59))
.do_lock_mesh(A<60>(60))
.do_simplify_border(A<61>(61))
.point_map(A<9000>(9000))
.query_point_map(A<9001>(9001))
.normal_map(A<9002>(9002))
.diagonalize_traits(A<9003>(9003))
.svd_traits(A<9004>(9004))
.callback(A<9005>(9005))
.sharpness_angle(A<9006>(9006))
.edge_sensitivity(A<9007>(9007))
.neighbor_radius(A<9008>(9008))
.number_of_output_points(A<9009>(9009))
.size(A<9010>(9010))
.maximum_variation(A<9011>(9011))
.degree_fitting(A<9012>(9012))
.degree_monge(A<9013>(9013))
.threshold_percent(A<9014>(9014))
.threshold_distance(A<9015>(9015))
.attraction_factor(A<9016>(9016))
.plane_map(A<9017>(9017))
.plane_index_map(A<9018>(9018))
.select_percentage(A<9019>(9019))
.require_uniform_sampling(A<9020>(9020))
.point_is_constrained_map(A<9021>(9021))
.number_of_samples(A<9022>(9022))
.accuracy(A<9023>(9023))
.maximum_running_time(A<9024>(9024))
.overlap(A<9025>(9025))
.transformation(A<9026>(9026))
.point_set_filters(A<9027>(9027))
.matcher(A<9028>(9028))
.outlier_filters(A<9029>(9029))
.error_minimizer(A<9030>(9030))
.transformation_checkers(A<9031>(9031))
.inspector(A<9032>(9032))
.logger(A<9033>(9033))
.maximum_normal_deviation(A<9034>(9034))
);
return EXIT_SUCCESS;
}
@@ -2,6 +2,7 @@
// We test speed of discrete harmonic coordinates on a set of automatically generated
// points inside a regular polygon with 100 vertices. We use inexact kernel.
#include <CGAL/number_type_config.h>
#include <CGAL/Real_timer.h>
#include <CGAL/Exact_predicates_inexact_constructions_kernel.h>
#include <CGAL/Barycentric_coordinates_2/Discrete_harmonic_2.h>
@@ -28,12 +29,11 @@ void generate_regular_polygon(const int number_of_vertices, const double polygon
{
const int n = number_of_vertices;
const double r = polygon_radius;
const double number_pi = 3.14159;
vertices.resize(n);
for(int i = 0; i < n; ++i)
vertices[i] = Point(Scalar(r*sin((number_pi / n) + ((i * 2.0 * number_pi) / n))), Scalar(-r*cos((number_pi / n) + ((i * 2.0 * number_pi) / n))));
vertices[i] = Point(Scalar(r*sin((CGAL_PI / n) + ((i * 2.0 * CGAL_PI) / n))), Scalar(-r*cos((CGAL_PI / n) + ((i * 2.0 * CGAL_PI) / n))));
}
int main()
@@ -2,6 +2,7 @@
// We test speed of mean value coordinates on a set of automatically generated
// points inside a regular polygon with 100 vertices. We use inexact kernel.
#include <CGAL/number_type_config.h>
#include <CGAL/Real_timer.h>
#include <CGAL/Exact_predicates_inexact_constructions_kernel.h>
#include <CGAL/Barycentric_coordinates_2/Mean_value_2.h>
@@ -28,12 +29,11 @@ void generate_regular_polygon(const int number_of_vertices, const double polygon
{
const int n = number_of_vertices;
const double r = polygon_radius;
const double number_pi = 3.14159;
vertices.resize(n);
for(int i = 0; i < n; ++i)
vertices[i] = Point(Scalar(r*sin((number_pi / n) + ((i * 2.0 * number_pi) / n))), Scalar(-r*cos((number_pi / n) + ((i * 2.0 * number_pi) / n))));
vertices[i] = Point(Scalar(r*sin((CGAL_PI / n) + ((i * 2.0 * CGAL_PI) / n))), Scalar(-r*cos((CGAL_PI / n) + ((i * 2.0 * CGAL_PI) / n))));
}
int main()
@@ -2,6 +2,7 @@
// We test speed of Wachspress coordinates on a set of automatically generated
// points inside a regular polygon with 100 vertices. We use inexact kernel.
#include <CGAL/number_type_config.h>
#include <CGAL/Real_timer.h>
#include <CGAL/Exact_predicates_inexact_constructions_kernel.h>
#include <CGAL/Barycentric_coordinates_2/Wachspress_2.h>
@@ -28,12 +29,11 @@ void generate_regular_polygon(const int number_of_vertices, const double polygon
{
const int n = number_of_vertices;
const double r = polygon_radius;
const double number_pi = 3.14159;
vertices.resize(n);
for(int i = 0; i < n; ++i)
vertices[i] = Point(Scalar(r*sin((number_pi / n) + ((i * 2.0 * number_pi) / n))), Scalar(-r*cos((number_pi / n) + ((i * 2.0 * number_pi) / n))));
vertices[i] = Point(Scalar(r*sin((CGAL_PI / n) + ((i * 2.0 * CGAL_PI) / n))), Scalar(-r*cos((CGAL_PI / n) + ((i * 2.0 * CGAL_PI) / n))));
}
int main()
@@ -8,15 +8,16 @@ if ( CGAL_FOUND )
# Use Eigen
find_package(Eigen3 3.1.0 QUIET) #(3.1.0 or greater)
if (EIGEN3_FOUND)
include( ${EIGEN3_USE_FILE} )
endif()
# create a target per cppfile
file(GLOB cppfiles RELATIVE ${CMAKE_CURRENT_SOURCE_DIR} ${CMAKE_CURRENT_SOURCE_DIR}/*.cpp)
foreach(cppfile ${cppfiles})
if(NOT (${cppfile} STREQUAL "ellipsoid.cpp") OR EIGEN3_FOUND)
create_single_source_cgal_program( "${cppfile}" )
if (EIGEN3_FOUND)
get_filename_component(target ${cppfile} NAME_WE)
CGAL_target_use_Eigen(${target})
endif()
endif()
endforeach()
@@ -14,15 +14,16 @@ if ( CGAL_FOUND )
# Use Eigen
find_package(Eigen3 3.1.0 QUIET) #(3.1.0 or greater)
if (EIGEN3_FOUND)
include( ${EIGEN3_USE_FILE} )
endif()
# create a target per cppfile
file(GLOB cppfiles RELATIVE ${CMAKE_CURRENT_SOURCE_DIR} ${CMAKE_CURRENT_SOURCE_DIR}/*.cpp)
foreach(cppfile ${cppfiles})
if(NOT (${cppfile} STREQUAL "Approximate_min_ellipsoid_d.cpp") OR EIGEN3_FOUND)
create_single_source_cgal_program( "${cppfile}" )
if (EIGEN3_FOUND)
get_filename_component(target ${cppfile} NAME_WE)
CGAL_target_use_Eigen(${target})
endif()
endif()
endforeach()
@@ -242,6 +242,29 @@ void box_intersection_all_pairs_d(
cutoff parameters are recommended. See also
Section \ref secboxintersperformance .
\cgalHeading{Concurrency}
The first template parameter of the function enables to choose whether
the algorithm is to be run in parallel, if `CGAL::Parallel_tag` is specified
and %CGAL has been linked with the Intel TBB library, or sequentially,
if `CGAL::Sequential_tag` - the default value - is specified.
The parallelization of the algorithm is based on a divide-and-conquer
approach: the two ranges are split in a number of smaller ranges, and
all combinations of subranges are treated in parallel. It is thus
recommended to use ranges of pointers to bounding boxes, to keep
these copies light.
\warning The parallel mode comes with a small overhead due to the
duplication and splitting of the input ranges. It is an improvement
for almost all inputs, but not all. A configuration where the two ranges
are small and entirely disjoint might result in a slightly worse
runtime when using the parallel version. Users should benchmark both
versions to verify that their data does not fall in this (small)
set of inputs.
\warning When using the parallel mode, the callback function must
be threadsafe.
\cgalHeading{Example}
The box implementation provided with
@@ -274,7 +297,8 @@ void box_intersection_all_pairs_d(
*/
template< class RandomAccessIterator1,
template< class ConcurrencyTag = CGAL::Sequential_tag,
class RandomAccessIterator1,
class RandomAccessIterator2,
class Callback >
void box_intersection_d(
@@ -291,7 +315,8 @@ void box_intersection_d(
Invocation with custom box traits.
*/
template< class RandomAccessIterator1,
template< class ConcurrencyTag = CGAL::Sequential_tag,
class RandomAccessIterator1,
class RandomAccessIterator2,
class Callback, class BoxTraits >
void box_intersection_d(
@@ -489,8 +514,11 @@ namespace CGAL {
\cgalHeading{Implementation}
See the implementation section of the `box_intersection_d()`
function.
See the implementation section of the `box_intersection_d()` function.
\cgalHeading{Concurrency}
See the concurrency section of the `box_intersection_d()` function.
\cgalHeading{Example}
@@ -520,7 +548,8 @@ namespace CGAL {
`RandomAccessIterator`.
*/
template< class RandomAccessIterator, class Callback >
template< class ConcurrencyTag = CGAL::Sequential_tag,
class RandomAccessIterator, class Callback >
void box_self_intersection_d(
RandomAccessIterator begin, RandomAccessIterator end,
Callback callback,
@@ -532,7 +561,8 @@ void box_self_intersection_d(
Invocation with custom box traits.
*/
template< class RandomAccessIterator,
template< class ConcurrencyTag = CGAL::Sequential_tag
class RandomAccessIterator,
class Callback, class BoxTraits >
void box_self_intersection_d(
RandomAccessIterator begin, RandomAccessIterator end,
@@ -16,34 +16,34 @@
#include <CGAL/license/Box_intersection_d.h>
#include <CGAL/basic.h>
#include <CGAL/Box_intersection_d/Box_d.h>
namespace CGAL {
namespace Box_intersection_d {
template<class NT_, int N, class Info_>
class Box_with_info_d : public Box_d< NT_, N, ID_FROM_BOX_ADDRESS> {
template<class NT_, int N, class Info_, class IdPolicy = ID_EXPLICIT>
class Box_with_info_d
: public Box_d< NT_, N, IdPolicy>
{
protected:
Info_ m_info;
public:
typedef Box_d< NT_, N, ID_FROM_BOX_ADDRESS> Base;
typedef NT_ NT;
typedef Info_ Info;
typedef Box_d< NT_, N, IdPolicy> Base;
typedef NT_ NT;
typedef Info_ Info;
Box_with_info_d() {}
Box_with_info_d( Info h) : m_info(h) {}
Box_with_info_d( bool complete, Info h): Base(complete), m_info(h) {}
Box_with_info_d(NT l[N], NT h[N], Info n) : Base( l, h), m_info(n) {}
Box_with_info_d( const Bbox_2& b, Info h) : Base( b), m_info(h) {}
Box_with_info_d( const Bbox_3& b, Info h) : Base( b), m_info(h) {}
Info info() const { return m_info; }
};
} // end namespace Box_intersection_d
} // namespace Box_intersection_d
} // namespace CGAL
} //namespace CGAL
#endif
#endif // CGAL_BOX_INTERSECTION_D_BOX_WITH_INFO_D_H
@@ -16,7 +16,6 @@
#include <CGAL/license/Box_intersection_d.h>
#include <CGAL/basic.h>
#include <CGAL/Box_intersection_d/box_limits.h>
@@ -24,7 +23,6 @@
#include <boost/random/uniform_int.hpp>
#include <boost/random/variate_generator.hpp>
#include <algorithm>
#include <iterator>
#include <functional>
@@ -93,6 +91,8 @@ void one_way_scan( RandomAccessIter1 p_begin, RandomAccessIter1 p_end,
bool in_order = true )
{
typedef typename Traits::Compare Compare;
// Putting a parallel sort here slows down the overall parallel algorithm
std::sort( p_begin, p_end, Compare( 0 ) );
std::sort( i_begin, i_end, Compare( 0 ) );
@@ -323,7 +323,7 @@ void segment_tree( RandomAccessIter1 p_begin, RandomAccessIter1 p_end,
RandomAccessIter2 i_begin, RandomAccessIter2 i_end,
T lo, T hi,
Callback callback, Predicate_traits traits,
std::ptrdiff_t cutoff, int dim, bool in_order )
std::ptrdiff_t cutoff, int dim, bool in_order)
{
typedef typename Predicate_traits::Spanning Spanning;
typedef typename Predicate_traits::Lo_less Lo_less;
@@ -6,7 +6,7 @@
// $URL$
// $Id$
// SPDX-License-Identifier: GPL-3.0-or-later OR LicenseRef-Commercial
//
//
//
// Author(s) : Lutz Kettner <kettner@mpi-sb.mpg.de>
// Andreas Meyer <ameyer@mpi-sb.mpg.de>
@@ -25,12 +25,191 @@
#include <CGAL/Box_intersection_d/Box_traits_d.h>
#include <CGAL/Box_intersection_d/box_limits.h>
#include <CGAL/use.h>
#include <CGAL/tags.h>
#ifdef CGAL_LINKED_WITH_TBB
#include <tbb/task_group.h>
#endif
#include <iterator>
#include <vector>
////////////////////////////////////////////////////////////////////////////////////////////////
/// THE CALLBACK MUST BE THREADSAFE IF YOU ARE USING THE PARALLEL MODE
////////////////////////////////////////////////////////////////////////////////////////////////
namespace CGAL {
namespace internal {
// Generic call with custom predicate traits parameter.
template< class RandomAccessIter1, class RandomAccessIter2,
template< class ConcurrencyTag,
class RandomAccessIter1, class RandomAccessIter2,
class Callback, class Traits >
void box_intersection_segment_tree_d(
RandomAccessIter1 begin1, RandomAccessIter1 end1,
RandomAccessIter2 begin2, RandomAccessIter2 end2,
Callback callback,
const Traits& traits,
const std::ptrdiff_t cutoff,
const bool in_order)
{
typedef typename Traits::NT NT;
CGAL_assertion(Traits::dimension() > 0);
const int dim = Traits::dimension() - 1;
const NT inf = Box_intersection_d::box_limits<NT>::inf();
const NT sup = Box_intersection_d::box_limits<NT>::sup();
#ifndef CGAL_LINKED_WITH_TBB
CGAL_static_assertion_msg (!(boost::is_convertible<ConcurrencyTag, Parallel_tag>::value),
"Parallel_tag is enabled but TBB is unavailable.");
#else // CGAL_LINKED_WITH_TBB
if(boost::is_convertible<ConcurrencyTag, Parallel_tag>::value)
{
// Here is an illustration for n=2.
//
// Doing a R1-R2 intersection with a 2-split is doing 4 subpairs in parallel
// a-c and b-d
// r1[0][0] --a-- r1[0][1] --b-- r1[0][2]
// r2[0][0] --c-- r2[0][1] --d-- r2[0][2]
//
// a-d and b-c
// r1[1][0] --a-- r1[1][1] --b-- r1[1][2]
// r2[1][0] --c-- r2[1][1] --d-- r2[1][2]
//
// Ranges must be duplicates since sorting is performed
typedef typename std::iterator_traits<RandomAccessIter1>::value_type val_t;
typedef typename std::iterator_traits<RandomAccessIter1>::difference_type diff_size;
typedef std::vector<val_t> val_container;
typedef typename val_container::iterator It;
static constexpr int n = 4;
const diff_size r1s = std::distance(begin1, end1);
const diff_size r2s = std::distance(begin2, end2);
val_container range_1_copies, range_2_copies;
range_1_copies.reserve(r1s * n);
range_2_copies.reserve(r2s * n);
const diff_size r1_step = r1s / n;
const diff_size r2_step = r2s / n;
for(int i=0; i<n; ++i)
{
range_1_copies.insert(range_1_copies.end(), begin1, end1);
range_2_copies.insert(range_2_copies.end(), begin2, end2);
}
// for example for n=2, there's 'begin', 'mid', and 'end' but we leave out 'end' for convenience
std::array<std::array<It, n>, n> range_1_iterators;
std::array<std::array<It, n>, n> range_2_iterators;
for(int i=0; i<n; ++i)
{
for(int j=0; j<n; ++j)
{
range_1_iterators[i][j] = range_1_copies.begin() + i * r1s + j * r1_step;
range_2_iterators[i][j] = range_2_copies.begin() + i * r2s + j * r2_step;
}
}
tbb::task_group g;
for(int i=0; i<n; ++i)
{
for(int j=0; j<n; ++j)
{
// 'j' vs 'j+i', meaning for each value of 'i' we're matching r1[i] with a shifted version of r2[i]
int r1_endi, r1_endj;
int r2_endi, r2_endj;
if(i == (n-1))
{
if(j == (n-1)) // both very last range and very last iterator
{
r1_endi = -1;
r1_endj = -1;
}
else
{
r1_endi = i;
r1_endj = j+1;
}
}
else // i != (n-1)
{
if(j == (n-1)) // end of that range, but not of the full container
{
r1_endi = i+1;
r1_endj = 0;
}
else
{
r1_endi = i;
r1_endj = j+1;
}
}
if(i == (n-1))
{
if(j+i == (n-1)) // both very last range and very last iterator
{
r2_endi = -1;
r2_endj = -1;
}
else
{
r2_endi = i;
r2_endj = (j+i+1)%n;
}
}
else // i != (n-1)
{
if(j+i == (n-1)) // end of that range, but not of the full container
{
r2_endi = i+1;
r2_endj = 0;
}
else
{
r2_endi = i;
r2_endj = (j+i+1)%n;
}
}
It r1_start = range_1_iterators[i][j];
It r1_end = (r1_endi == -1) ? range_1_copies.end() : range_1_iterators[r1_endi][r1_endj];
It r2_start = range_2_iterators[i][(j+i)%n];
It r2_end = (r2_endi == -1) ? range_2_copies.end() : range_2_iterators[r2_endi][r2_endj];
CGAL_assertion(range_1_copies.begin() <= r1_start && r1_start <= r1_end && r1_end <= range_1_copies.end());
CGAL_assertion(range_2_copies.begin() <= r2_start && r2_start <= r2_end && r2_end <= range_2_copies.end());
// Specify "copy by value" otherwise the values of iterators for next (i,j) iterations
// become shared with different lambdas being run in parallel, and things go wrong
g.run([=]{ Box_intersection_d::segment_tree( r1_start, r1_end, r2_start, r2_end,
inf, sup, callback, traits, cutoff, dim, in_order); });
}
}
g.wait();
}
else
#endif // CGAL_LINKED_WITH_TBB
{
Box_intersection_d::segment_tree(begin1, end1, begin2, end2, inf, sup, callback, traits, cutoff, dim, in_order);
}
}
} // namespace internal
// Generic call with custom predicate traits parameter.
template< class ConcurrencyTag = Sequential_tag,
class RandomAccessIter1, class RandomAccessIter2,
class Callback, class BoxPredicateTraits >
void box_intersection_custom_predicates_d(
RandomAccessIter1 begin1, RandomAccessIter1 end1,
@@ -40,23 +219,15 @@ void box_intersection_custom_predicates_d(
std::ptrdiff_t cutoff = 10,
Box_intersection_d::Setting setting = Box_intersection_d::BIPARTITE)
{
typedef BoxPredicateTraits Traits;
typedef typename Traits::NT NT;
CGAL_assertion( Traits::dimension() > 0 );
const int dim = Traits::dimension() - 1;
const NT inf = Box_intersection_d::box_limits<NT>::inf();
const NT sup = Box_intersection_d::box_limits<NT>::sup();
Box_intersection_d::segment_tree(begin1, end1, begin2, end2,
inf, sup, callback, traits, cutoff, dim, true);
if(setting == Box_intersection_d::BIPARTITE)
Box_intersection_d::segment_tree(begin2, end2, begin1, end1,
inf, sup, callback, traits, cutoff, dim, false);
internal::box_intersection_segment_tree_d<ConcurrencyTag>(begin1, end1, begin2, end2, callback, traits, cutoff, true);
if(setting == Box_intersection_d::BIPARTITE)
internal::box_intersection_segment_tree_d<ConcurrencyTag>(begin2, end2, begin1, end1, callback, traits, cutoff, false);
}
// Generic call with box traits parameter.
// - make all default parameters explicit overloads (workaround)
template< class RandomAccessIter1, class RandomAccessIter2,
template< class ConcurrencyTag = Sequential_tag,
class RandomAccessIter1, class RandomAccessIter2,
class Callback, class BoxTraits >
void box_intersection_d(
RandomAccessIter1 begin1, RandomAccessIter1 end1,
@@ -67,18 +238,19 @@ void box_intersection_d(
Box_intersection_d::Topology topology,
Box_intersection_d::Setting setting)
{
if (topology == Box_intersection_d::CLOSED) {
typedef Box_intersection_d::Predicate_traits_d<BoxTraits,true> Traits;
box_intersection_custom_predicates_d(begin1, end1, begin2, end2,
callback, Traits(), cutoff, setting);
} else {
typedef Box_intersection_d::Predicate_traits_d<BoxTraits,false> Traits;
box_intersection_custom_predicates_d(begin1, end1, begin2, end2,
callback, Traits(), cutoff, setting);
}
if (topology == Box_intersection_d::CLOSED) {
typedef Box_intersection_d::Predicate_traits_d<BoxTraits,true> Traits;
box_intersection_custom_predicates_d<ConcurrencyTag>(begin1, end1, begin2, end2,
callback, Traits(), cutoff, setting);
} else {
typedef Box_intersection_d::Predicate_traits_d<BoxTraits,false> Traits;
box_intersection_custom_predicates_d<ConcurrencyTag>(begin1, end1, begin2, end2,
callback, Traits(), cutoff, setting);
}
}
template< class RandomAccessIter1, class RandomAccessIter2,
template< class ConcurrencyTag = Sequential_tag,
class RandomAccessIter1, class RandomAccessIter2,
class Callback, class BoxTraits >
void box_intersection_d(
RandomAccessIter1 begin1, RandomAccessIter1 end1,
@@ -86,35 +258,39 @@ void box_intersection_d(
Callback callback, BoxTraits box_traits, std::ptrdiff_t cutoff,
Box_intersection_d::Topology topology)
{
box_intersection_d( begin1, end1, begin2, end2, callback, box_traits,
cutoff, topology, Box_intersection_d::BIPARTITE);
box_intersection_d<ConcurrencyTag>( begin1, end1, begin2, end2, callback, box_traits,
cutoff, topology, Box_intersection_d::BIPARTITE);
}
template< class RandomAccessIter1, class RandomAccessIter2,
template< class ConcurrencyTag = Sequential_tag,
class RandomAccessIter1, class RandomAccessIter2,
class Callback, class BoxTraits >
void box_intersection_d(
RandomAccessIter1 begin1, RandomAccessIter1 end1,
RandomAccessIter2 begin2, RandomAccessIter2 end2,
Callback callback, BoxTraits box_traits, std::ptrdiff_t cutoff)
{
box_intersection_d( begin1, end1, begin2, end2, callback, box_traits,
cutoff, Box_intersection_d::CLOSED,
Box_intersection_d::BIPARTITE);
box_intersection_d<ConcurrencyTag>( begin1, end1, begin2, end2, callback, box_traits,
cutoff, Box_intersection_d::CLOSED,
Box_intersection_d::BIPARTITE);
}
template< class RandomAccessIter1, class RandomAccessIter2,
template< class ConcurrencyTag = Sequential_tag,
class RandomAccessIter1, class RandomAccessIter2,
class Callback, class BoxTraits >
void box_intersection_d(
RandomAccessIter1 begin1, RandomAccessIter1 end1,
RandomAccessIter2 begin2, RandomAccessIter2 end2,
Callback callback, BoxTraits box_traits)
{
box_intersection_d( begin1, end1, begin2, end2, callback, box_traits,
10, Box_intersection_d::CLOSED,
Box_intersection_d::BIPARTITE);
box_intersection_d<ConcurrencyTag>( begin1, end1, begin2, end2, callback, box_traits,
10, Box_intersection_d::CLOSED,
Box_intersection_d::BIPARTITE);
}
// Specialized call with default box traits.
// - make all default parameters explicit overloads (workaround)
template< class RandomAccessIter1, class RandomAccessIter2, class Callback >
template< class ConcurrencyTag = Sequential_tag,
class RandomAccessIter1, class RandomAccessIter2, class Callback >
void box_intersection_d(
RandomAccessIter1 begin1, RandomAccessIter1 end1,
RandomAccessIter2 begin2, RandomAccessIter2 end2,
@@ -122,53 +298,58 @@ void box_intersection_d(
Box_intersection_d::Topology topology,
Box_intersection_d::Setting setting)
{
typedef typename std::iterator_traits<RandomAccessIter1>::value_type val_t;
typedef Box_intersection_d::Box_traits_d< val_t> Box_traits;
box_intersection_d( begin1, end1, begin2, end2, callback, Box_traits(),
cutoff, topology, setting);
typedef typename std::iterator_traits<RandomAccessIter1>::value_type val_t;
typedef Box_intersection_d::Box_traits_d< val_t> Box_traits;
box_intersection_d<ConcurrencyTag>( begin1, end1, begin2, end2, callback, Box_traits(),
cutoff, topology, setting);
}
template< class RandomAccessIter1, class RandomAccessIter2, class Callback >
template< class ConcurrencyTag = Sequential_tag,
class RandomAccessIter1, class RandomAccessIter2, class Callback >
void box_intersection_d(
RandomAccessIter1 begin1, RandomAccessIter1 end1,
RandomAccessIter2 begin2, RandomAccessIter2 end2,
Callback callback, std::ptrdiff_t cutoff,
Box_intersection_d::Topology topology)
{
typedef typename std::iterator_traits<RandomAccessIter1>::value_type val_t;
typedef Box_intersection_d::Box_traits_d< val_t> Box_traits;
box_intersection_d( begin1, end1, begin2, end2, callback, Box_traits(),
cutoff, topology, Box_intersection_d::BIPARTITE);
typedef typename std::iterator_traits<RandomAccessIter1>::value_type val_t;
typedef Box_intersection_d::Box_traits_d< val_t> Box_traits;
box_intersection_d<ConcurrencyTag>( begin1, end1, begin2, end2, callback, Box_traits(),
cutoff, topology, Box_intersection_d::BIPARTITE);
}
template< class RandomAccessIter1, class RandomAccessIter2, class Callback >
template< class ConcurrencyTag = Sequential_tag,
class RandomAccessIter1, class RandomAccessIter2, class Callback >
void box_intersection_d(
RandomAccessIter1 begin1, RandomAccessIter1 end1,
RandomAccessIter2 begin2, RandomAccessIter2 end2,
Callback callback, std::ptrdiff_t cutoff)
{
typedef typename std::iterator_traits<RandomAccessIter1>::value_type val_t;
typedef Box_intersection_d::Box_traits_d< val_t> Box_traits;
box_intersection_d( begin1, end1, begin2, end2, callback, Box_traits(),
cutoff, Box_intersection_d::CLOSED,
Box_intersection_d::BIPARTITE);
typedef typename std::iterator_traits<RandomAccessIter1>::value_type val_t;
typedef Box_intersection_d::Box_traits_d< val_t> Box_traits;
box_intersection_d<ConcurrencyTag>( begin1, end1, begin2, end2, callback, Box_traits(),
cutoff, Box_intersection_d::CLOSED,
Box_intersection_d::BIPARTITE);
}
template< class RandomAccessIter1, class RandomAccessIter2, class Callback >
template< class ConcurrencyTag = Sequential_tag,
class RandomAccessIter1, class RandomAccessIter2, class Callback >
void box_intersection_d(
RandomAccessIter1 begin1, RandomAccessIter1 end1,
RandomAccessIter2 begin2, RandomAccessIter2 end2,
Callback callback)
{
typedef typename std::iterator_traits<RandomAccessIter1>::value_type val_t;
typedef Box_intersection_d::Box_traits_d< val_t> Box_traits;
box_intersection_d( begin1, end1, begin2, end2, callback, Box_traits(),
10, Box_intersection_d::CLOSED,
Box_intersection_d::BIPARTITE);
typedef typename std::iterator_traits<RandomAccessIter1>::value_type val_t;
typedef Box_intersection_d::Box_traits_d< val_t> Box_traits;
box_intersection_d<ConcurrencyTag>( begin1, end1, begin2, end2, callback, Box_traits(),
10, Box_intersection_d::CLOSED,
Box_intersection_d::BIPARTITE);
}
// Generic call with box traits parameter, specialized for self-intersection.
// - make all default parameters explicit overloads (workaround)
template< class RandomAccessIter, class Callback, class BoxTraits >
template< class ConcurrencyTag = Sequential_tag,
class RandomAccessIter, class Callback, class BoxTraits >
void box_self_intersection_d(
RandomAccessIter begin, RandomAccessIter end,
Callback callback,
@@ -176,49 +357,52 @@ void box_self_intersection_d(
std::ptrdiff_t cutoff,
Box_intersection_d::Topology topology)
{
// Copying rather than calling 'box_intersection_d(begin, end, begin, end, ...'
// is necessary because the 'std::partition' and range splits on the first range
// would be messed up by sorts on the second range otherwise.
typedef typename std::iterator_traits<RandomAccessIter>::value_type val_t;
std::vector< val_t> i( begin, end);
box_intersection_d( begin, end, i.begin(), i.end(),
callback, box_traits, cutoff, topology,
Box_intersection_d::COMPLETE);
// Copying rather than calling 'box_intersection_d(begin, end, begin, end, ...'
// is necessary because the 'std::partition' and range splits on the first range
// would be messed up by sorts on the second range otherwise.
typedef typename std::iterator_traits<RandomAccessIter>::value_type val_t;
std::vector< val_t> i( begin, end);
box_intersection_d<ConcurrencyTag>( begin, end, i.begin(), i.end(),
callback, box_traits, cutoff, topology,
Box_intersection_d::COMPLETE);
}
template< class RandomAccessIter, class Callback, class BoxTraits >
template< class ConcurrencyTag = Sequential_tag,
class RandomAccessIter, class Callback, class BoxTraits >
void box_self_intersection_d(
RandomAccessIter begin, RandomAccessIter end,
Callback callback,
BoxTraits box_traits,
std::ptrdiff_t cutoff)
{
return box_self_intersection_d(begin, end, callback, box_traits, cutoff,
Box_intersection_d::CLOSED);
return box_self_intersection_d<ConcurrencyTag>(begin, end, callback, box_traits, cutoff,
Box_intersection_d::CLOSED);
}
template< class RandomAccessIter, class Callback, class BoxTraits >
template< class ConcurrencyTag = Sequential_tag,
class RandomAccessIter, class Callback, class BoxTraits >
void box_self_intersection_d(
RandomAccessIter begin, RandomAccessIter end,
Callback callback,
BoxTraits box_traits)
{
return box_self_intersection_d(begin, end, callback, box_traits, 10);
return box_self_intersection_d<ConcurrencyTag>(begin, end, callback, box_traits, 10);
}
// Specialized call with default box traits, specialized for self-intersection.
// - make all default parameters explicit overloads (workaround)
template< class RandomAccessIter, class Callback >
template< class ConcurrencyTag = Sequential_tag, class RandomAccessIter, class Callback >
void box_self_intersection_d(
RandomAccessIter begin, RandomAccessIter end,
Callback callback)
{
typedef typename std::iterator_traits<RandomAccessIter>::value_type val_t;
typedef Box_intersection_d::Box_traits_d< val_t> Box_traits;
box_self_intersection_d(begin, end, callback, Box_traits());
box_self_intersection_d<ConcurrencyTag>(begin, end, callback, Box_traits());
}
template< class RandomAccessIter, class Callback >
template< class ConcurrencyTag = Sequential_tag, class RandomAccessIter, class Callback >
void box_self_intersection_d(
RandomAccessIter begin, RandomAccessIter end,
Callback callback,
@@ -226,10 +410,10 @@ void box_self_intersection_d(
{
typedef typename std::iterator_traits<RandomAccessIter>::value_type val_t;
typedef Box_intersection_d::Box_traits_d< val_t> Box_traits;
box_self_intersection_d(begin, end, callback, Box_traits(), cutoff);
box_self_intersection_d<ConcurrencyTag>(begin, end, callback, Box_traits(), cutoff);
}
template< class RandomAccessIter, class Callback >
template< class ConcurrencyTag = Sequential_tag, class RandomAccessIter, class Callback >
void box_self_intersection_d(
RandomAccessIter begin, RandomAccessIter end,
Callback callback,
@@ -238,28 +422,27 @@ void box_self_intersection_d(
{
typedef typename std::iterator_traits<RandomAccessIter>::value_type val_t;
typedef Box_intersection_d::Box_traits_d< val_t> Box_traits;
box_self_intersection_d(begin, end, callback,
Box_traits(), cutoff, topology );
box_self_intersection_d<ConcurrencyTag>(begin, end, callback,
Box_traits(), cutoff, topology );
}
// Generic call for trivial all-pairs algorithm with box traits parameter.
// - make all default parameters explicit overloads (workaround)
template< class ForwardIter1, class ForwardIter2,
class Callback, class BoxTraits >
void box_intersection_all_pairs_d(
void box_intersection_all_pairs_d(
ForwardIter1 begin1, ForwardIter1 end1,
ForwardIter2 begin2, ForwardIter2 end2,
Callback callback, BoxTraits)
{
typedef Box_intersection_d::Predicate_traits_d<BoxTraits,true> Traits;
Box_intersection_d::all_pairs( begin1, end1, begin2, end2,
Box_intersection_d::all_pairs( begin1, end1, begin2, end2,
callback, Traits());
}
template< class ForwardIter1, class ForwardIter2,
class Callback, class BoxTraits >
void box_intersection_all_pairs_d(
void box_intersection_all_pairs_d(
ForwardIter1 begin1, ForwardIter1 end1,
ForwardIter2 begin2, ForwardIter2 end2,
Callback callback, BoxTraits,
@@ -269,18 +452,18 @@ void box_intersection_all_pairs_d(
bool complete_case = (setting != Box_intersection_d::BIPARTITE);
if (topology == Box_intersection_d::CLOSED) {
typedef Box_intersection_d::Predicate_traits_d<BoxTraits,true> Traits;
Box_intersection_d::all_pairs( begin1, end1, begin2, end2,
Box_intersection_d::all_pairs( begin1, end1, begin2, end2,
callback, Traits(), complete_case);
} else {
typedef Box_intersection_d::Predicate_traits_d<BoxTraits,false> Traits;
Box_intersection_d::all_pairs( begin1, end1, begin2, end2,
Box_intersection_d::all_pairs( begin1, end1, begin2, end2,
callback, Traits(), complete_case);
}
}
template< class ForwardIter1, class ForwardIter2,
class Callback, class BoxTraits >
void box_intersection_all_pairs_d(
void box_intersection_all_pairs_d(
ForwardIter1 begin1, ForwardIter1 end1,
ForwardIter2 begin2, ForwardIter2 end2,
Callback callback, BoxTraits traits,
@@ -293,20 +476,20 @@ void box_intersection_all_pairs_d(
// Specialized call for trivial all-pairs algorithm with default box traits.
// - make all default parameters explicit overloads (workaround)
template< class ForwardIter1, class ForwardIter2, class Callback >
void box_intersection_all_pairs_d(
void box_intersection_all_pairs_d(
ForwardIter1 begin1, ForwardIter1 end1,
ForwardIter2 begin2, ForwardIter2 end2,
Callback callback)
{
typedef typename std::iterator_traits<ForwardIter1>::value_type val_t;
typedef Box_intersection_d::Box_traits_d< val_t> Box_traits;
box_intersection_all_pairs_d( begin1, end1, begin2, end2,
callback, Box_traits(),
Box_intersection_d::CLOSED );
box_intersection_all_pairs_d( begin1, end1, begin2, end2,
callback, Box_traits(),
Box_intersection_d::CLOSED );
}
template< class ForwardIter1, class ForwardIter2, class Callback >
void box_intersection_all_pairs_d(
void box_intersection_all_pairs_d(
ForwardIter1 begin1, ForwardIter1 end1,
ForwardIter2 begin2, ForwardIter2 end2,
Callback callback,
@@ -314,12 +497,12 @@ void box_intersection_all_pairs_d(
{
typedef typename std::iterator_traits<ForwardIter1>::value_type val_t;
typedef Box_intersection_d::Box_traits_d< val_t> Box_traits;
box_intersection_all_pairs_d( begin1, end1, begin2, end2,
box_intersection_all_pairs_d( begin1, end1, begin2, end2,
callback, Box_traits(), topology);
}
template< class ForwardIter1, class ForwardIter2, class Callback >
void box_intersection_all_pairs_d(
void box_intersection_all_pairs_d(
ForwardIter1 begin1, ForwardIter1 end1,
ForwardIter2 begin2, ForwardIter2 end2,
Callback callback,
@@ -328,7 +511,7 @@ void box_intersection_all_pairs_d(
{
typedef typename std::iterator_traits<ForwardIter1>::value_type val_t;
typedef Box_intersection_d::Box_traits_d< val_t> Box_traits;
box_intersection_all_pairs_d( begin1, end1, begin2, end2,
box_intersection_all_pairs_d( begin1, end1, begin2, end2,
callback, Box_traits(), topology, setting);
}
@@ -336,7 +519,7 @@ void box_intersection_all_pairs_d(
// specialized for self-intersection test.
// - make all default parameters explicit overloads (workaround)
template< class ForwardIter, class Callback, class BoxTraits >
void box_self_intersection_all_pairs_d(
void box_self_intersection_all_pairs_d(
ForwardIter begin1, ForwardIter end1, Callback callback, BoxTraits /* traits */)
{
typedef Box_intersection_d::Predicate_traits_d<BoxTraits,true> Traits;
@@ -344,7 +527,7 @@ void box_self_intersection_all_pairs_d(
}
template< class ForwardIter, class Callback, class BoxTraits >
void box_self_intersection_all_pairs_d(
void box_self_intersection_all_pairs_d(
ForwardIter begin1, ForwardIter end1, Callback callback, BoxTraits,
Box_intersection_d::Topology topology)
{
@@ -361,17 +544,17 @@ void box_self_intersection_all_pairs_d(
// specialized for self-intersection test.
// - make all default parameters explicit overloads (workaround)
template< class ForwardIter, class Callback >
void box_self_intersection_all_pairs_d(
void box_self_intersection_all_pairs_d(
ForwardIter begin1, ForwardIter end1, Callback callback)
{
typedef typename std::iterator_traits<ForwardIter>::value_type val_t;
typedef Box_intersection_d::Box_traits_d< val_t> Box_traits;
box_self_intersection_all_pairs_d( begin1, end1, callback, Box_traits(),
Box_intersection_d::CLOSED );
box_self_intersection_all_pairs_d( begin1, end1, callback, Box_traits(),
Box_intersection_d::CLOSED );
}
template< class ForwardIter, class Callback >
void box_self_intersection_all_pairs_d(
void box_self_intersection_all_pairs_d(
ForwardIter begin1, ForwardIter end1, Callback callback,
Box_intersection_d::Topology topology)
{
@@ -5,20 +5,23 @@
cmake_minimum_required(VERSION 3.1...3.15)
project( Box_intersection_d_Tests )
find_package( CGAL QUIET )
find_package(CGAL QUIET)
find_package( TBB )
if ( CGAL_FOUND )
# create a target per cppfile
file(GLOB cppfiles RELATIVE ${CMAKE_CURRENT_SOURCE_DIR} ${CMAKE_CURRENT_SOURCE_DIR}/*.cpp)
foreach(cppfile ${cppfiles})
create_single_source_cgal_program( "${cppfile}" )
endforeach()
create_single_source_cgal_program( "automated_test.cpp" )
create_single_source_cgal_program( "benchmark_box_intersection.cpp" )
create_single_source_cgal_program( "random_set_test.cpp" )
create_single_source_cgal_program( "test_box_grid.cpp" )
if( TBB_FOUND )
CGAL_target_use_TBB( test_box_grid )
else()
message( STATUS "NOTICE: Intel TBB was not found. Sequential code will be used." )
endif()
else()
message(STATUS "This program requires the CGAL library, and will not be compiled.")
endif()
@@ -1,217 +1,297 @@
// file: test/Box_intersection_d/box_grid.C
// similar to examples/Box_intersection_d/box_grid.C but stricter in checking
// and more extensive in what is tested.
#include <CGAL/box_intersection_d.h>
#include <cassert>
#include <vector>
#include <algorithm>
#include <iterator>
typedef CGAL::Box_intersection_d::Box_d<int,2> Box;
#include <CGAL/box_intersection_d.h>
#include <CGAL/tags.h>
#include <algorithm>
#include <cassert>
#include <iterator>
#include <vector>
#ifdef CGAL_LINKED_WITH_TBB
#include <tbb/concurrent_vector.h>
#endif
typedef CGAL::Box_intersection_d::Box_d<int, 2> Box;
// coordinates for 9 boxes of a grid
int p[9*4] = { 0,0,1,1, 1,0,2,1, 2,0,3,1, // lower
0,1,1,2, 1,1,2,2, 2,1,3,2, // middle
0,2,1,3, 1,2,2,3, 2,2,3,3};// upper
// 9 boxes + 2 selected boxes as query; center and upper right
Box init_boxes[11] = { Box( p, p+ 2), Box( p+ 4, p+ 6), Box( p+ 8, p+10),
Box( p+12, p+14), Box( p+16, p+18), Box( p+20, p+22),
Box( p+24, p+26), Box( p+28, p+30), Box( p+32, p+34),
Box( p+16, p+18), Box( p+32, p+34)};
const Box init_boxes[11] = { Box( p, p+ 2), Box( p+ 4, p+ 6), Box( p+ 8, p+10),
Box( p+12, p+14), Box( p+16, p+18), Box( p+20, p+22),
Box( p+24, p+26), Box( p+28, p+30), Box( p+32, p+34),
Box( p+16, p+18), Box( p+32, p+34)};
Box boxes[11];
Box* query = boxes+9;
void init() {
for ( int i = 0; i < 11; ++i)
boxes[i] = init_boxes[i];
void init()
{
for ( int i = 0; i < 11; ++i)
boxes[i] = init_boxes[i];
}
void check_result( const char* text, std::vector<std::size_t>& result,
const std::size_t* check, std::size_t size) {
// sort, show, and check result
std::sort( result.begin(), result.end());
std::cout << text << ": got " << result.size() << " elements, expected "
<< size << " elements\n got : ";
std::copy( result.begin(), result.end(),
std::ostream_iterator<std::size_t>( std::cout, ","));
std::cout << "\n expected: ";
std::copy( check, check+size,
std::ostream_iterator<std::size_t>( std::cout, ","));
std::cout << '\n' << std::endl;
assert( result.size() == size
&& std::equal( check, check+size, result.begin()));
template <typename Vector>
void check_result( const char* text,
Vector& result,
const std::size_t* check,
std::size_t size)
{
// sort, show, and check result
std::sort( result.begin(), result.end());
std::cout << text << ": got " << result.size() << " elements, expected "
<< size << " elements\n got : ";
std::copy( result.begin(), result.end(),
std::ostream_iterator<std::size_t>( std::cout, ","));
std::cout << "\n expected: ";
std::copy( check, check+size,
std::ostream_iterator<std::size_t>( std::cout, ","));
std::cout << '\n' << std::endl;
assert( result.size() == size
&& std::equal( check, check+size, result.begin()));
}
// callback function object writing results to an output iterator
template <class OutputIterator>
struct Report {
OutputIterator it;
Report( OutputIterator i) : it(i) {} // store iterator in object
// We encode both id-numbers in a single number, a.id() + 100 * b.id(),
// and write that number to the output iterator.
void operator()( const Box& a, const Box& b) { *it++ = a.id()+100*b.id(); }
template <class Container>
struct Report
{
Container& c_;
Report(Container& c) : c_(c) {} // store iterator in object
// We encode both id-numbers in a single number, a.id() + 100 * b.id(),
// and write that number to the output iterator.
void operator()(const Box& a, const Box& b) { c_.push_back(a.id()+100*b.id()); }
void operator()(const Box* a, const Box* b) { c_.push_back(a->id()+100*b->id()); }
};
template <class Iter> // helper function to create the function object
Report<Iter> report( Iter it) { return Report<Iter>(it); }
template <class Container> // helper function to create the function object
Report<Container> report(Container& c) { return Report<Container>(c); }
// ---------------------------------------------------------------------
// box_intersection_d
// run the intersection algorithms and store results in a vector
// ---------------------------------------------------------------------
void test_box_intersection() {
// intersect 3x3 with 2 query boxes, closed boxes
init();
std::vector<std::size_t> result;
CGAL::box_intersection_d( boxes, boxes+9, query, query+2,
report( std::back_inserter( result)));
std::size_t check1[13] = {900,901,902,903,904,905,906,907,908,
1004,1005,1007,1008};
check_result( "Box inters. 3x3, 2, closed", result, check1, 13);
void test_box_intersection()
{
#ifdef CGAL_LINKED_WITH_TBB
tbb::concurrent_vector<std::size_t> result;
#else
std::vector<std::size_t> result;
#endif
// intersect 3x3 with 2 query boxes, half-open boxes and changed cutoff
init();
result.clear();
CGAL::box_intersection_d( boxes, boxes+9, query, query+2,
report( std::back_inserter( result)),
std::ptrdiff_t(1),
CGAL::Box_intersection_d::HALF_OPEN);
std::size_t check2[2] = {904,1008};
check_result( "Box inters. 3x3, 2, half-open", result, check2, 2);
// Some degenerate cases
init();
CGAL::box_intersection_d<CGAL::Parallel_if_available_tag>(boxes, boxes, boxes, boxes,
report(result));
assert(result.empty());
// self intersect 3x2, closed boxes
init();
result.clear();
CGAL::box_self_intersection_d( boxes, boxes+6,
report( std::back_inserter( result)));
std::size_t check3[11] = {1,3,4,102,103,104,105,204,205,304,405};
check_result( "Box self inters. 3x2, closed", result, check3, 11);
init();
CGAL::box_intersection_d<CGAL::Parallel_if_available_tag>(boxes, boxes, query, query + 1,
report(result));
assert(result.empty());
// self intersect 3x2, half-open boxes
init();
result.clear();
CGAL::box_self_intersection_d( boxes, boxes+6,
report( std::back_inserter( result)),
std::ptrdiff_t(1),
CGAL::Box_intersection_d::HALF_OPEN);
std::size_t check4[1] = {9999};
check_result( "Box self inters. 3x2, half-open", result, check4, 0);
init();
CGAL::box_intersection_d<CGAL::Parallel_if_available_tag>(boxes, boxes + 3, query, query,
report(result));
assert(result.empty());
// self intersect 3x3+2 query boxes, half-open boxes
init();
result.clear();
CGAL::box_self_intersection_d( boxes, boxes+11,
report( std::back_inserter( result)),
std::ptrdiff_t(1),
CGAL::Box_intersection_d::HALF_OPEN);
std::size_t check5[2] = {409,810};
check_result( "Box self inters. 3x3+2, half-open", result, check5, 2);
// With pointers
init();
std::vector<const Box*> range_1 = {{ boxes, boxes+1, boxes+2, boxes+3, boxes+4, boxes+5,
boxes+6, boxes+7, boxes+8 }};
std::vector<const Box*> range_2 = {{ query, query+1 }};
// self intersect 3x3+2 query boxes, half-open boxes, full function interf.
// tests also mixed types for the two iterator ranges
init();
result.clear();
std::vector<Box> boxes2( boxes, boxes+11);
CGAL::box_intersection_d( boxes, boxes+11, boxes2.begin(), boxes2.end(),
report( std::back_inserter( result)),
std::ptrdiff_t(1),
CGAL::Box_intersection_d::HALF_OPEN,
CGAL::Box_intersection_d::COMPLETE);
check_result( "Box inters. 3x3+2, half-open", result, check5, 2);
// compare this with the bipartite case
// self intersect 3x3+2 query boxes, half-open boxes
// tests also mixed types for the two iterator ranges
init();
result.clear();
boxes2 = std::vector<Box>( boxes, boxes+11);
CGAL::box_intersection_d( boxes, boxes+11, boxes2.begin(), boxes2.end(),
report( std::back_inserter( result)),
std::ptrdiff_t(20),
CGAL::Box_intersection_d::HALF_OPEN,
CGAL::Box_intersection_d::BIPARTITE);
std::size_t check6[4] = {409,810,904,1008};
check_result( "Box inters. 3x3+2, half-open", result, check6, 4);
CGAL::box_intersection_d<CGAL::Parallel_if_available_tag>(range_1.begin(), range_1.begin(),
range_2.begin(), range_2.end(),
report(result));
assert(result.empty());
CGAL::box_intersection_d<CGAL::Parallel_if_available_tag>(range_1.begin(), range_1.end(),
range_2.begin(), range_2.begin(),
report(result));
assert(result.empty());
CGAL::box_intersection_d<CGAL::Parallel_if_available_tag>(range_1.begin(), range_1.end(),
range_2.begin(), range_2.end(),
report(result));
std::size_t check0[13] = {900,901,902,903,904,905,906,907,908,
1004,1005,1007,1008};
check_result( "Box inters. 3x3 (ptr), 2, closed", result, check0, 13);
// intersect 3x3 with 2 query boxes, closed boxes
init();
result.clear();
CGAL::box_intersection_d<CGAL::Parallel_if_available_tag>(boxes, boxes+9, query, query+1, report(result));
std::size_t check1[13] = {900,901,902,903,904,905,906,907,908};
check_result( "Box inters. 3x3, 2, closed", result, check1, 9);
// intersect 3x3 with 2 query boxes, closed boxes
init();
result.clear();
CGAL::box_intersection_d<CGAL::Parallel_if_available_tag>(boxes, boxes+9, query, query+2, report(result));
std::size_t check1bis[13] = {900,901,902,903,904,905,906,907,908,
1004,1005,1007,1008};
check_result( "Box inters. 3x3, 2, closed", result, check1bis, 13);
// intersect 3x3 with 2 query boxes, half-open boxes and changed cutoff
init();
result.clear();
CGAL::box_intersection_d( boxes, boxes+9, query, query+2,
report(result),
std::ptrdiff_t(1),
CGAL::Box_intersection_d::HALF_OPEN);
std::size_t check2[2] = {904,1008};
check_result( "Box inters. 3x3, 2, half-open", result, check2, 2);
// intersect 3x3 with 2 query boxes, half-open boxes and changed cutoff (reversed)
init();
result.clear();
CGAL::box_intersection_d<CGAL::Parallel_if_available_tag>( query, query+2, boxes, boxes+9,
report(result),
std::ptrdiff_t(1),
CGAL::Box_intersection_d::HALF_OPEN);
std::size_t check2bis[2] = {409,810};
check_result( "Box inters. 3x3 (reversed), 2, half-open", result, check2bis, 2);
// self intersect 3x2, closed boxes
init();
result.clear();
CGAL::box_self_intersection_d( boxes, boxes+6,
report(result));
std::size_t check3[11] = {1,3,4,102,103,104,105,204,205,304,405};
check_result( "Box self inters. 3x2, closed", result, check3, 11);
// self intersect 3x2, half-open boxes
init();
result.clear();
CGAL::box_self_intersection_d( boxes, boxes+6,
report(result),
std::ptrdiff_t(1),
CGAL::Box_intersection_d::HALF_OPEN);
std::size_t check4[1] = {9999};
check_result( "Box self inters. 3x2, half-open", result, check4, 0);
// self intersect 3x3+2 query boxes, half-open boxes
init();
result.clear();
CGAL::box_self_intersection_d( boxes, boxes+11,
report(result),
std::ptrdiff_t(1),
CGAL::Box_intersection_d::HALF_OPEN);
std::size_t check5[2] = {409,810};
check_result( "Box self inters. 3x3+2, half-open", result, check5, 2);
// self intersect 3x3+2 query boxes, half-open boxes, full function interf.
// tests also mixed types for the two iterator ranges
init();
result.clear();
std::vector<Box> boxes2( boxes, boxes+11);
CGAL::box_intersection_d( boxes, boxes+11, boxes2.begin(), boxes2.end(),
report(result),
std::ptrdiff_t(1),
CGAL::Box_intersection_d::HALF_OPEN,
CGAL::Box_intersection_d::COMPLETE);
check_result( "Box inters. 3x3+2, half-open", result, check5, 2);
// compare this with the bipartite case
// self intersect 3x3+2 query boxes, half-open boxes
// tests also mixed types for the two iterator ranges
init();
result.clear();
boxes2 = std::vector<Box>( boxes, boxes+11);
CGAL::box_intersection_d( boxes, boxes+11, boxes2.begin(), boxes2.end(),
report(result),
std::ptrdiff_t(20),
CGAL::Box_intersection_d::HALF_OPEN,
CGAL::Box_intersection_d::BIPARTITE);
std::size_t check6[4] = {409,810,904,1008};
check_result( "Box inters. 3x3+2, half-open", result, check6, 4);
}
// ---------------------------------------------------------------------
// box_intersection_all_pairs_d
// run the intersection algorithms and store results in a vector
// ---------------------------------------------------------------------
void test_box_intersection_all_pairs() {
// intersect 3x3 with 2 query boxes, closed boxes
init();
std::vector<std::size_t> result;
CGAL::box_intersection_all_pairs_d( boxes, boxes+9, query, query+2,
report( std::back_inserter( result)));
std::size_t check1[13] = {900,901,902,903,904,905,906,907,908,
1004,1005,1007,1008};
check_result( "All-pairs inters. 3x3, 2, closed", result, check1, 13);
void test_box_intersection_all_pairs()
{
// intersect 3x3 with 2 query boxes, closed boxes
init();
std::vector<std::size_t> result;
CGAL::box_intersection_all_pairs_d( boxes, boxes+9, query, query+2,
report(result));
std::size_t check1[13] = {900,901,902,903,904,905,906,907,908,
1004,1005,1007,1008};
check_result( "All-pairs inters. 3x3, 2, closed", result, check1, 13);
// intersect 3x3 with 2 query boxes, half-open boxes
init();
result.clear();
CGAL::box_intersection_all_pairs_d( boxes, boxes+9, query, query+2,
report( std::back_inserter( result)),
CGAL::Box_intersection_d::HALF_OPEN);
std::size_t check2[2] = {904,1008};
check_result( "All-pairs inters. 3x3, 2, half-open", result, check2, 2);
// intersect 3x3 with 2 query boxes, half-open boxes
init();
result.clear();
CGAL::box_intersection_all_pairs_d( boxes, boxes+9, query, query+2,
report(result),
CGAL::Box_intersection_d::HALF_OPEN);
std::size_t check2[2] = {904,1008};
check_result( "All-pairs inters. 3x3, 2, half-open", result, check2, 2);
// self intersect 3x2, closed boxes
init();
result.clear();
CGAL::box_self_intersection_all_pairs_d( boxes, boxes+6,
report( std::back_inserter( result)));
std::size_t check3[11] = {100,201,300,301,400,401,402,403,501,502,504};
check_result( "All-pairs self inters. 3x2, closed", result, check3, 11);
// self intersect 3x2, closed boxes
init();
result.clear();
CGAL::box_self_intersection_all_pairs_d( boxes, boxes+6,
report(result));
std::size_t check3[11] = {100,201,300,301,400,401,402,403,501,502,504};
check_result( "All-pairs self inters. 3x2, closed", result, check3, 11);
// self intersect 3x2, half-open boxes
init();
result.clear();
CGAL::box_self_intersection_all_pairs_d( boxes, boxes+6,
report( std::back_inserter( result)),
CGAL::Box_intersection_d::HALF_OPEN);
std::size_t check4[1] = {9999};
check_result( "All-pairs self inters. 3x2, half-open", result, check4, 0);
// self intersect 3x2, half-open boxes
init();
result.clear();
CGAL::box_self_intersection_all_pairs_d( boxes, boxes+6,
report(result),
CGAL::Box_intersection_d::HALF_OPEN);
std::size_t check4[1] = {9999};
check_result( "All-pairs self inters. 3x2, half-open", result, check4, 0);
// self intersect 3x3+2 query boxes, half-open boxes
init();
result.clear();
CGAL::box_self_intersection_all_pairs_d( boxes, boxes+11,
report( std::back_inserter( result)),
CGAL::Box_intersection_d::HALF_OPEN);
std::size_t check5[2] = {904,1008};
check_result( "All-pairs self inters. 3x3+2, half-open", result, check5,2);
// self intersect 3x3+2 query boxes, half-open boxes
init();
result.clear();
CGAL::box_self_intersection_all_pairs_d( boxes, boxes+11,
report(result),
CGAL::Box_intersection_d::HALF_OPEN);
std::size_t check5[2] = {904,1008};
check_result( "All-pairs self inters. 3x3+2, half-open", result, check5,2);
// self intersect 3x3+2 query boxes, half-open boxes, full function interf.
// tests also mixed types for the two iterator ranges
init();
result.clear();
std::vector<Box> boxes2( boxes, boxes+11);
CGAL::box_intersection_all_pairs_d( boxes, boxes+11,
boxes2.begin(), boxes2.end(),
report( std::back_inserter( result)),
CGAL::Box_intersection_d::HALF_OPEN,
CGAL::Box_intersection_d::COMPLETE);
check_result( "All-pairs self inters. 3x3+2, half-open", result, check5,2);
// compare this with the bipartite case
// self intersect 3x3+2 query boxes, half-open boxes
// tests also mixed types for the two iterator ranges
init();
result.clear();
boxes2 = std::vector<Box>( boxes, boxes+11);
CGAL::box_intersection_all_pairs_d( boxes, boxes+11,
boxes2.begin(), boxes2.end(),
report( std::back_inserter( result)),
CGAL::Box_intersection_d::HALF_OPEN,
CGAL::Box_intersection_d::BIPARTITE);
std::size_t check6[4] = {409,810,904,1008};
check_result( "All-pairs inters. 3x3+2, half-open", result, check6, 4);
// self intersect 3x3+2 query boxes, half-open boxes, full function interf.
// tests also mixed types for the two iterator ranges
init();
result.clear();
std::vector<Box> boxes2( boxes, boxes+11);
CGAL::box_intersection_all_pairs_d( boxes, boxes+11,
boxes2.begin(), boxes2.end(),
report(result),
CGAL::Box_intersection_d::HALF_OPEN,
CGAL::Box_intersection_d::COMPLETE);
check_result( "All-pairs self inters. 3x3+2, half-open", result, check5,2);
// compare this with the bipartite case
// self intersect 3x3+2 query boxes, half-open boxes
// tests also mixed types for the two iterator ranges
init();
result.clear();
boxes2 = std::vector<Box>( boxes, boxes+11);
CGAL::box_intersection_all_pairs_d( boxes, boxes+11,
boxes2.begin(), boxes2.end(),
report(result),
CGAL::Box_intersection_d::HALF_OPEN,
CGAL::Box_intersection_d::BIPARTITE);
std::size_t check6[4] = {409,810,904,1008};
check_result( "All-pairs inters. 3x3+2, half-open", result, check6, 4);
}
int main()
{
test_box_intersection();
test_box_intersection_all_pairs();
int main() {
test_box_intersection();
test_box_intersection_all_pairs();
return 0;
return EXIT_SUCCESS;
}
@@ -76,6 +76,10 @@ read_vtk_image_data(vtkImageData* vtk_image, Image_3::Own owning = Image_3::OWN_
image->wdim = imageio_type.wdim;
image->wordKind = imageio_type.wordKind;
image->sign = imageio_type.sign;
if (!vtk_image->GetPointData() || !vtk_image->GetPointData()->GetScalars()) {
::_freeImage(image);
return Image_3();
}
CGAL_assertion(vtk_image->GetPointData()->GetScalars()->GetNumberOfTuples() == dims[0]*dims[1]*dims[2]);
if(owning == Image_3::OWN_THE_DATA) {
image->data = ::ImageIO_alloc(dims[0]*dims[1]*dims[2]*image->wdim);
@@ -27,9 +27,7 @@ if ( CGAL_FOUND )
include(${CGAL_USE_FILE})
find_package(Eigen3 3.1.0) #(requires 3.1.0 or greater)
if (EIGEN3_FOUND)
include( ${EIGEN3_USE_FILE} )
else()
if (NOT EIGEN3_FOUND)
message(STATUS "NOTICE: This project requires the Eigen library, and will not be compiled.")
return()
endif()
@@ -143,6 +141,7 @@ if ( CGAL_FOUND )
add_library(CGAL_${IPELET} MODULE ${IPELET}.cpp)
add_to_cached_list(CGAL_EXECUTABLE_TARGETS CGAL_${IPELET})
target_link_libraries(CGAL_${IPELET} PRIVATE CGAL::CGAL ${IPE_LIBRARIES})
CGAL_target_use_Eigen(CGAL_${IPELET})
if ( IPELET_INSTALL_DIR )
install(TARGETS CGAL_${IPELET} DESTINATION ${IPELET_INSTALL_DIR})
if (WITH_IPE_7)
@@ -153,12 +152,13 @@ if ( CGAL_FOUND )
endforeach(IPELET)
if(CGAL_Core_FOUND)
target_link_libraries(CGAL_cone_spanners PRIVATE CGAL::CGAL_Core)
CGAL_target_use_Eigen(CGAL_cone_spanners)
endif()
#example in doc not installed
add_library(simple_triangulation MODULE simple_triangulation.cpp)
add_to_cached_list(CGAL_EXECUTABLE_TARGETS simple_triangulation)
target_link_libraries(simple_triangulation ${IPE_LIBRARIES})
CGAL_target_use_Eigen(simple_triangulation)
cgal_add_compilation_test(simple_triangulation)
else()
@@ -50,6 +50,15 @@ public:
PointC2(const FT &hx, const FT &hy, const FT &hw)
: base(hx, hy, hw) {}
friend void swap(Self& a, Self& b)
#ifdef __cpp_lib_is_swappable
noexcept(std::is_nothrow_swappable_v<Vector_2_>)
#endif
{
using std::swap;
swap(a.base, b.base);
}
const FT& x() const
{
return base.x();
@@ -24,6 +24,7 @@ namespace CGAL {
template < class R_ >
class PointC3
{
typedef PointC3<R_> Self;
typedef typename R_::Vector_3 Vector_3;
typedef typename R_::Point_3 Point_3;
typedef typename R_::Aff_transformation_3 Aff_transformation_3;
@@ -47,6 +48,15 @@ public:
PointC3(const FT &x, const FT &y, const FT &z, const FT &w)
: base(x, y, z, w) {}
friend void swap(Self& a, Self& b)
#ifdef __cpp_lib_is_swappable
noexcept(std::is_nothrow_swappable_v<Vector_3>)
#endif
{
using std::swap;
swap(a.base, b.base);
}
const FT & x() const
{
return base.x();
@@ -27,6 +27,7 @@ namespace CGAL {
template < class R_ >
class VectorC2
{
typedef VectorC2<R_> Self;
typedef typename R_::FT FT;
typedef typename R_::Point_2 Point_2;
typedef typename R_::Vector_2 Vector_2;
@@ -55,6 +56,15 @@ public:
: base( hw != FT(1) ? CGAL::make_array<FT>(hx/hw, hy/hw)
: CGAL::make_array(hx, hy) ) {}
friend void swap(Self& a, Self& b)
#ifdef __cpp_lib_is_swappable
noexcept(std::is_nothrow_swappable_v<Base>)
#endif
{
using std::swap;
swap(a.base, b.base);
}
const FT & x() const
{
return CGAL::get_pointee_or_identity(base)[0];
@@ -27,6 +27,7 @@ template < class R_ >
class VectorC3
{
// https://doc.cgal.org/latest/Manual/devman_code_format.html#secprogramming_conventions
typedef VectorC3<R_> Self;
typedef typename R_::FT FT_;
typedef typename R_::Point_3 Point_3;
typedef typename R_::Vector_3 Vector_3;
@@ -70,6 +71,15 @@ public:
: base( w != FT_(1) ? CGAL::make_array<FT_>(x/w, y/w, z/w)
: CGAL::make_array(x, y, z) ) {}
friend void swap(Self& a, Self& b)
#ifdef __cpp_lib_is_swappable
noexcept(std::is_nothrow_swappable_v<Base>)
#endif
{
using std::swap;
swap(a.base, b.base);
}
const FT_ & x() const
{
return get_pointee_or_identity(base)[0];
@@ -179,7 +179,7 @@ namespace CGAL {
}
break;
case BIPOLAR:
CGAL_kernel_precondition(!"This function does not accept bipolar circle as input.");
CGAL_kernel_precondition_msg(false, "This function does not accept bipolar circle as input.");
}
return out_it;
}
@@ -516,7 +516,7 @@ namespace CGAL {
break;
}
case BIPOLAR:
CGAL_kernel_precondition(!"This function does not accept bipolar circle as input.");
CGAL_kernel_precondition_msg(false, "This function does not accept bipolar circle as input.");
}
return out_it;
@@ -5,7 +5,6 @@ cmake_minimum_required(VERSION 3.1...3.15)
project( Classification_Examples )
# CGAL and its components
find_package( CGAL QUIET COMPONENTS )
@@ -22,127 +21,73 @@ if ( NOT Boost_FOUND )
return()
endif()
find_package( Boost OPTIONAL_COMPONENTS serialization iostreams )
set(Classification_dependencies_met TRUE)
if( WIN32 )
# to avoid a warning with old cmake
set(_Boost_BZIP2_HEADERS "boost/iostreams/filter/bzip2.hpp")
set(_Boost_ZLIB_HEADERS "boost/iostreams/filter/zlib.hpp")
find_package( Boost OPTIONAL_COMPONENTS bzip2 zlib)
else()
find_package(ZLIB QUIET)
find_package( Boost OPTIONAL_COMPONENTS serialization iostreams )
if (NOT Boost_SERIALIZATION_FOUND)
message(STATUS "NOTICE: This project requires Boost Serialization, and will not be compiled.")
set(Classification_dependencies_met FALSE)
endif()
if (NOT Boost_IOSTREAMS_FOUND)
message(STATUS "NOTICE: This project requires Boost IO Streams, and will not be compiled.")
set(Classification_dependencies_met FALSE)
endif()
find_package(OpenCV QUIET COMPONENTS core ml) # Need core + machine learning
if (NOT OpenCV_FOUND)
message(STATUS "NOTICE: OpenCV was not found. OpenCV random forest predicate for classification won't be available.")
endif()
find_package(TensorFlow QUIET)
if (NOT TensorFlow_FOUND)
message(STATUS "NOTICE: TensorFlow was not found. TensorFlow neural network predicate for classification won't be available.")
endif()
find_package(Eigen3 3.1.0 REQUIRED) #(3.1.0 or greater)
if (NOT EIGEN3_FOUND)
message(STATUS "This project requires the Eigen library, and will not be compiled.")
set(Classification_dependencies_met FALSE)
endif()
find_package(TBB QUIET)
find_package(OpenCV QUIET COMPONENTS core ml) # Need core + machine learning
# Use Eigen
find_package(Eigen3 3.1.0 REQUIRED) #(3.1.0 or greater)
if (NOT EIGEN3_FOUND)
message(STATUS "This project requires the Eigen library, and will not be compiled.")
return()
else()
include( ${EIGEN3_USE_FILE} )
endif()
# Creating entries for all C++ files with "main" routine
# ##########################################################
# Classification examples
set(targets
example_classification
example_ethz_random_forest
example_feature
example_generation_and_training
example_mesh_classification
example_cluster_classification)
# Classification requires some C++11 features
set(needed_cxx_features cxx_rvalue_references cxx_variadic_templates)
# Libraries and flags
set(classification_linked_libraries)
set(classification_compile_definitions)
if (Boost_SERIALIZATION_FOUND AND Boost_IOSTREAMS_FOUND)
if(TARGET Boost::serialization AND TARGET Boost::iostreams)
set(classification_linked_libraries Boost::serialization Boost::iostreams)
else()
set(classification_linked_libraries ${classification_linked_libraries}
${Boost_SERIALIZATION_LIBRARY}
${Boost_IOSTREAMS_LIBRARY})
endif()
else()
if (NOT Boost_SERIALIZATION_FOUND)
message(STATUS "NOTICE: This project requires Boost Serialization, and will not be compiled.")
endif()
if (NOT Boost_IOSTREAMS_FOUND)
message(STATUS "NOTICE: This project requires Boost IO Streams, and will not be compiled.")
endif()
if (NOT Classification_dependencies_met)
return()
endif()
if( WIN32 )
if (Boost_ZLIB_FOUND AND Boost_BZIP2_FOUND)
set(classification_linked_libraries ${classification_linked_libraries}
${Boost_ZLIB_LIBRARY} ${Boost_BZIP2_LIBRARY})
else()
message(STATUS "NOTICE: This project requires Boost ZLIB and Boost BZIP2, and will not be compiled.")
return()
endif()
else()
if(ZLIB_FOUND)
set(classification_linked_libraries ${classification_linked_libraries} ZLIB::ZLIB)
else()
message(STATUS "NOTICE: This project requires ZLIB, and will not be compiled.")
return()
endif()
endif()
create_single_source_cgal_program( "example_classification.cpp" )
create_single_source_cgal_program( "example_ethz_random_forest.cpp" )
create_single_source_cgal_program( "example_feature.cpp" )
create_single_source_cgal_program( "example_generation_and_training.cpp" )
create_single_source_cgal_program( "example_mesh_classification.cpp" )
create_single_source_cgal_program( "example_cluster_classification.cpp" )
if (OpenCV_FOUND)
message(STATUS "Found OpenCV ${OpenCV_VERSION}")
include_directories(${OpenCV_INCLUDE_DIRS})
set(classification_linked_libraries ${classification_linked_libraries}
${OpenCV_LIBS})
set(classification_compile_definitions ${classification_compile_definitions}
"-DCGAL_LINKED_WITH_OPENCV")
set(targets ${targets} example_opencv_random_forest)
else()
message(STATUS "NOTICE: OpenCV was not found. OpenCV random forest predicate for classification won't be available.")
create_single_source_cgal_program( "example_opencv_random_forest.cpp" )
CGAL_target_use_OpenCV(example_opencv_random_forest)
endif()
find_package(TensorFlow QUIET)
if (TensorFlow_FOUND)
message(STATUS "Found TensorFlow")
include_directories( ${TensorFlow_INCLUDE_DIR} )
set(classification_linked_libraries ${classification_linked_libraries}
${TensorFlow_LIBRARY})
set(classification_compile_definitions ${classification_compile_definitions}
"-DCGAL_LINKED_WITH_TENSORFLOW")
set(targets ${targets} example_tensorflow_neural_network)
else()
message(STATUS "NOTICE: TensorFlow not found, Neural Network predicate for classification won't be available.")
create_single_source_cgal_program( "example_tensorflow_neural_network.cpp" )
CGAL_target_use_TensorFlow(example_tensorflow_neural_network)
endif()
# Creating targets with correct libraries and flags
foreach(target ${targets})
create_single_source_cgal_program( "${target}.cpp" CXX_FEATURES ${needed_cxx_features} )
foreach(target
example_classification
example_ethz_random_forest
example_feature
example_generation_and_training
example_mesh_classification
example_cluster_classification
example_opencv_random_forest
example_tensorflow_neural_network)
if(TARGET ${target})
target_link_libraries(${target} PUBLIC ${classification_linked_libraries})
target_compile_definitions(${target} PUBLIC ${classification_compile_definitions})
CGAL_target_use_Eigen(${target})
CGAL_target_use_Boost_IOStreams(${target})
CGAL_target_use_Boost_Serialization(${target})
if(TBB_FOUND)
CGAL_target_use_TBB(${target})
endif()
endif()
endforeach()
@@ -11,16 +11,12 @@
#include <CGAL/Simple_cartesian.h>
#include <CGAL/Classification.h>
#include <CGAL/bounding_box.h>
#include <CGAL/tags.h>
#include <CGAL/IO/read_ply_points.h>
#include <CGAL/Real_timer.h>
#ifdef CGAL_LINKED_WITH_TBB
typedef CGAL::Parallel_tag Concurrency_tag;
#else
typedef CGAL::Sequential_tag Concurrency_tag;
#endif
typedef CGAL::Parallel_if_available_tag Concurrency_tag;
typedef CGAL::Simple_cartesian<double> Kernel;
typedef Kernel::Point_3 Point;
@@ -18,11 +18,7 @@
#include <CGAL/Shape_detection/Region_growing.h>
#include <CGAL/Real_timer.h>
#ifdef CGAL_LINKED_WITH_TBB
typedef CGAL::Parallel_tag Concurrency_tag;
#else
typedef CGAL::Sequential_tag Concurrency_tag;
#endif
typedef CGAL::Parallel_if_available_tag Concurrency_tag;
typedef CGAL::Simple_cartesian<double> Kernel;
typedef Kernel::Point_3 Point;
@@ -127,11 +127,7 @@ public:
std::size_t num_trees = 25,
std::size_t max_depth = 20)
{
#ifdef CGAL_LINKED_WITH_TBB
train<CGAL::Parallel_tag>(ground_truth, reset_trees, num_trees, max_depth);
#else
train<CGAL::Sequential_tag>(ground_truth, reset_trees, num_trees, max_depth);
#endif
train<CGAL::Parallel_if_available_tag>(ground_truth, reset_trees, num_trees, max_depth);
}
/// \endcond
@@ -146,7 +142,7 @@ public:
label.
\tparam ConcurrencyTag enables sequential versus parallel
algorithm. Possible values are `Parallel_tag` (default value is
algorithm. Possible values are `Parallel_tag` (default value if
%CGAL is linked with TBB) or `Sequential_tag` (default value
otherwise).
@@ -38,7 +38,7 @@
#include <tbb/parallel_for.h>
#include <tbb/blocked_range.h>
#include <tbb/scalable_allocator.h>
#include <tbb/mutex.h>
#include <mutex>
#endif // CGAL_LINKED_WITH_TBB
@@ -19,7 +19,7 @@
#include <boost/make_shared.hpp>
#ifdef CGAL_LINKED_WITH_TBB
#include <tbb/mutex.h>
#include <mutex>
#include <tbb/task_group.h>
#endif // CGAL_LINKED_WITH_TBB
@@ -34,7 +34,8 @@
#include <tbb/parallel_for.h>
#include <tbb/blocked_range.h>
#include <tbb/scalable_allocator.h>
#include <tbb/mutex.h>
#include <mutex>
#endif // CGAL_LINKED_WITH_TBB
namespace CGAL {
@@ -69,7 +70,7 @@ private:
PointMap m_point_map;
const NeighborQuery& m_neighbor_query;
float& m_mean_range;
tbb::mutex& m_mutex;
std::mutex& m_mutex;
public:
@@ -78,7 +79,7 @@ private:
PointMap point_map,
const NeighborQuery& neighbor_query,
float& mean_range,
tbb::mutex& mutex)
std::mutex& mutex)
: m_eigen (eigen), m_input (input), m_point_map (point_map),
m_neighbor_query (neighbor_query), m_mean_range (mean_range), m_mutex (mutex)
{ }
@@ -120,7 +121,7 @@ private:
const FaceListGraph& m_input;
const NeighborQuery& m_neighbor_query;
float& m_mean_range;
tbb::mutex& m_mutex;
std::mutex& m_mutex;
public:
@@ -128,7 +129,7 @@ private:
const FaceListGraph& input,
const NeighborQuery& neighbor_query,
float& mean_range,
tbb::mutex& mutex)
std::mutex& mutex)
: m_eigen (eigen), m_input (input),
m_neighbor_query (neighbor_query), m_mean_range (mean_range), m_mutex (mutex)
{ }
@@ -225,7 +226,7 @@ public:
is `CGAL::Point_3`.
\tparam NeighborQuery model of `NeighborQuery`
\tparam ConcurrencyTag enables sequential versus parallel
algorithm. Possible values are `Parallel_tag` (default value is %CGAL
algorithm. Possible values are `Parallel_tag` (default value if %CGAL
is linked with TBB) or `Sequential_tag` (default value otherwise).
\tparam DiagonalizeTraits model of `DiagonalizeTraits` used for
matrix diagonalization. It can be omitted if Eigen 3 (or greater)
@@ -241,10 +242,8 @@ public:
typename NeighborQuery,
#if defined(DOXYGEN_RUNNING)
typename ConcurrencyTag,
#elif defined(CGAL_LINKED_WITH_TBB)
typename ConcurrencyTag = CGAL::Parallel_tag,
#else
typename ConcurrencyTag = CGAL::Sequential_tag,
typename ConcurrencyTag = CGAL::Parallel_if_available_tag,
#endif
#if defined(DOXYGEN_RUNNING)
typename DiagonalizeTraits>
@@ -271,7 +270,7 @@ public:
#else
if (boost::is_convertible<ConcurrencyTag,Parallel_tag>::value)
{
tbb::mutex mutex;
std::mutex mutex;
Compute_eigen_values<PointRange, PointMap, NeighborQuery, DiagonalizeTraits>
f(out, input, point_map, neighbor_query, out.m_content->mean_range, mutex);
tbb::parallel_for(tbb::blocked_range<size_t>(0, input.size ()), f);
@@ -309,7 +308,7 @@ public:
\tparam FaceListGraph model of `FaceListGraph`.
\tparam NeighborQuery model of `NeighborQuery`
\tparam ConcurrencyTag enables sequential versus parallel
algorithm. Possible values are `Parallel_tag` (default value is %CGAL
algorithm. Possible values are `Parallel_tag` (default value if %CGAL
is linked with TBB) or `Sequential_tag` (default value otherwise).
\tparam DiagonalizeTraits model of `DiagonalizeTraits` used for
matrix diagonalization. It can be omitted: if Eigen 3 (or greater)
@@ -324,10 +323,8 @@ public:
typename NeighborQuery,
#if defined(DOXYGEN_RUNNING)
typename ConcurrencyTag,
#elif defined(CGAL_LINKED_WITH_TBB)
typename ConcurrencyTag = CGAL::Parallel_tag,
#else
typename ConcurrencyTag = CGAL::Sequential_tag,
typename ConcurrencyTag = CGAL::Parallel_if_available_tag,
#endif
#if defined(DOXYGEN_RUNNING)
typename DiagonalizeTraits>
@@ -361,7 +358,7 @@ public:
#else
if (boost::is_convertible<ConcurrencyTag,Parallel_tag>::value)
{
tbb::mutex mutex;
std::mutex mutex;
Compute_eigen_values_graph<FaceListGraph, NeighborQuery, DiagonalizeTraits>
f(out, input, neighbor_query, out.m_content->mean_range, mutex);
@@ -395,7 +392,7 @@ public:
`RandomAccessIterator` and its value type is the key type of
`PointMap`.
\tparam ConcurrencyTag enables sequential versus parallel
algorithm. Possible values are `Parallel_tag` (default value is %CGAL
algorithm. Possible values are `Parallel_tag` (default value if %CGAL
is linked with TBB) or `Sequential_tag` (default value otherwise).
\tparam DiagonalizeTraits model of `DiagonalizeTraits` used for
matrix diagonalization. It can be omitted: if Eigen 3 (or greater)
@@ -408,10 +405,8 @@ public:
template <typename ClusterRange,
#if defined(DOXYGEN_RUNNING)
typename ConcurrencyTag,
#elif defined(CGAL_LINKED_WITH_TBB)
typename ConcurrencyTag = CGAL::Parallel_tag,
#else
typename ConcurrencyTag = CGAL::Sequential_tag,
typename ConcurrencyTag = CGAL::Parallel_if_available_tag,
#endif
#if defined(DOXYGEN_RUNNING)
typename DiagonalizeTraits>
@@ -45,7 +45,7 @@
#ifdef CGAL_LINKED_WITH_TBB
#include <tbb/task_group.h>
#include <tbb/mutex.h>
#include <mutex>
#endif // CGAL_LINKED_WITH_TBB
namespace CGAL {
@@ -79,7 +79,7 @@ namespace Classification {
is `GeomTraits::Point_3`.
\tparam ConcurrencyTag enables sequential versus parallel
computation of `CGAL::Classification::Local_eigen_analysis`
objects. Possible values are `Parallel_tag` (default value is %CGAL
objects. Possible values are `Parallel_tag` (default value if %CGAL
is linked with TBB) or `Sequential_tag` (default value otherwise).
\tparam DiagonalizeTraits model of `DiagonalizeTraits` used for
matrix diagonalization. It can be omitted: if Eigen 3 (or greater)
@@ -93,10 +93,8 @@ template <typename GeomTraits,
typename PointMap,
#if defined(DOXYGEN_RUNNING)
typename ConcurrencyTag,
#elif defined(CGAL_LINKED_WITH_TBB)
typename ConcurrencyTag = CGAL::Parallel_tag,
#else
typename ConcurrencyTag = CGAL::Sequential_tag,
typename ConcurrencyTag = CGAL::Parallel_if_available_tag,
#endif
typename DiagonalizeTraits = CGAL::Default_diagonalize_traits<float,3> >
class Mesh_feature_generator
@@ -90,10 +90,8 @@ template <typename GeomTraits,
typename PointMap,
#if defined(DOXYGEN_RUNNING)
typename ConcurrencyTag,
#elif defined(CGAL_LINKED_WITH_TBB)
typename ConcurrencyTag = CGAL::Parallel_tag,
#else
typename ConcurrencyTag = CGAL::Sequential_tag,
typename ConcurrencyTag = CGAL::Parallel_if_available_tag,
#endif
#if defined(DOXYGEN_RUNNING)
typename DiagonalizeTraits>
@@ -33,7 +33,7 @@
#include <tbb/parallel_for.h>
#include <tbb/blocked_range.h>
#include <tbb/scalable_allocator.h>
#include <tbb/mutex.h>
#include <mutex>
#endif // CGAL_LINKED_WITH_TBB
#define CLASSIFICATION_TRAINING_QUICK_ESTIMATION
@@ -72,9 +72,9 @@ private:
std::vector<std::size_t>& m_true_positives;
std::vector<std::size_t>& m_false_positives;
std::vector<std::size_t>& m_false_negatives;
std::vector<tbb::mutex>& m_tp_mutex;
std::vector<tbb::mutex>& m_fp_mutex;
std::vector<tbb::mutex>& m_fn_mutex;
std::vector<std::mutex>& m_tp_mutex;
std::vector<std::mutex>& m_fp_mutex;
std::vector<std::mutex>& m_fn_mutex;
public:
@@ -85,9 +85,9 @@ private:
std::vector<std::size_t>& true_positives,
std::vector<std::size_t>& false_positives,
std::vector<std::size_t>& false_negatives,
std::vector<tbb::mutex>& tp_mutex,
std::vector<tbb::mutex>& fp_mutex,
std::vector<tbb::mutex>& fn_mutex)
std::vector<std::mutex>& tp_mutex,
std::vector<std::mutex>& fp_mutex,
std::vector<std::mutex>& fn_mutex)
: m_training_set (training_set)
, m_classifier (classifier)
, m_label (label)
@@ -901,9 +901,9 @@ private:
#else
if (boost::is_convertible<ConcurrencyTag,Parallel_tag>::value)
{
std::vector<tbb::mutex> tp_mutex (m_labels.size());
std::vector<tbb::mutex> fp_mutex (m_labels.size());
std::vector<tbb::mutex> fn_mutex (m_labels.size());
std::vector<std::mutex> tp_mutex (m_labels.size());
std::vector<std::mutex> fp_mutex (m_labels.size());
std::vector<std::mutex> fn_mutex (m_labels.size());
Compute_iou f(training_sets[j], *this, j,
true_positives, false_positives, false_negatives,
tp_mutex, fp_mutex, fn_mutex);
@@ -24,7 +24,7 @@
#include <tbb/parallel_for.h>
#include <tbb/blocked_range.h>
#include <tbb/scalable_allocator.h>
#include <tbb/mutex.h>
#include <mutex>
#endif // CGAL_LINKED_WITH_TBB
namespace CGAL {
@@ -327,7 +327,7 @@ namespace internal {
suboptimal results.
\tparam ConcurrencyTag enables sequential versus parallel
algorithm. Possible values are `Parallel_tag` or `Sequential_tag`.
algorithm. Possible values are `Parallel_if_available_tag`, `Parallel_tag` or `Sequential_tag`.
\tparam ItemRange model of `ConstRange`. Its iterator type is
`RandomAccessIterator`. Its value type depends on the data that is
@@ -417,7 +417,7 @@ namespace internal {
efficiency and better quality results.
\tparam ConcurrencyTag enables sequential versus parallel
algorithm. Possible values are `Parallel_tag` or `Sequential_tag`.
algorithm. Possible values are `Parallel_if_available_tag`, `Parallel_tag` or `Sequential_tag`.
\tparam ItemRange model of `ConstRange`. Its iterator type is
`RandomAccessIterator`.
\tparam ItemMap model of `ReadablePropertyMap` whose key
@@ -495,7 +495,7 @@ namespace internal {
results.
\tparam ConcurrencyTag enables sequential versus parallel
algorithm. Possible values are `Parallel_tag` or `Sequential_tag`.
algorithm. Possible values are `Parallel_if_available_tag`, `Parallel_tag` or `Sequential_tag`.
\tparam ItemRange model of `ConstRange`. Its iterator type is
`RandomAccessIterator`.
\tparam ItemMap model of `ReadablePropertyMap` whose key
@@ -5,7 +5,6 @@ cmake_minimum_required(VERSION 3.1...3.15)
project( Classification_Tests )
# CGAL and its components
find_package( CGAL QUIET COMPONENTS )
@@ -22,88 +21,39 @@ if ( NOT Boost_FOUND )
return()
endif()
set(Classification_dependencies_met TRUE)
find_package( Boost OPTIONAL_COMPONENTS serialization iostreams )
if( WIN32 )
# to avoid a warning with old cmake
set(_Boost_BZIP2_HEADERS "boost/iostreams/filter/bzip2.hpp")
set(_Boost_ZLIB_HEADERS "boost/iostreams/filter/zlib.hpp")
find_package( Boost OPTIONAL_COMPONENTS bzip2 zlib)
else()
find_package(ZLIB QUIET)
if (NOT Boost_SERIALIZATION_FOUND)
message(STATUS "NOTICE: This project requires Boost Serialization, and will not be compiled.")
set(Classification_dependencies_met FALSE)
endif()
if (NOT Boost_IOSTREAMS_FOUND)
message(STATUS "NOTICE: This project requires Boost IO Streams, and will not be compiled.")
set(Classification_dependencies_met FALSE)
endif()
# Use Eigen
find_package(Eigen3 3.1.0) #(requires 3.1.0 or greater)
if (EIGEN3_FOUND)
include( ${EIGEN3_USE_FILE} )
find_package(Eigen3 3.1.0 REQUIRED) #(3.1.0 or greater)
if (NOT EIGEN3_FOUND)
message(STATUS "This project requires the Eigen library, and will not be compiled.")
set(Classification_dependencies_met FALSE)
endif()
find_package( TBB )
find_package(TBB QUIET)
# include for local directory
include_directories( BEFORE include )
# include for local package
# Creating entries for all C++ files with "main" routine
# ##########################################################
#add_definitions("-DCGAL_DO_NOT_USE_BOYKOV_KOLMOGOROV_MAXFLOW_SOFTWARE")
# Classification requires some C++11 features
set(needed_cxx_features cxx_rvalue_references cxx_variadic_templates)
# Libraries and flags
set(classification_linked_libraries)
if (Boost_SERIALIZATION_FOUND AND Boost_IOSTREAMS_FOUND)
if(TARGET Boost::serialization AND TARGET Boost::iostreams)
set(classification_linked_libraries Boost::serialization Boost::iostreams)
else()
set(classification_linked_libraries ${classification_linked_libraries}
${Boost_SERIALIZATION_LIBRARY}
${Boost_IOSTREAMS_LIBRARY})
endif()
else()
if (NOT Boost_SERIALIZATION_FOUND)
message(STATUS "NOTICE: This project requires Boost Serialization, and will not be compiled.")
endif()
if (NOT Boost_IOSTREAMS_FOUND)
message(STATUS "NOTICE: This project requires Boost IO Streams, and will not be compiled.")
endif()
if (NOT Classification_dependencies_met)
return()
endif()
if( WIN32 )
if (Boost_ZLIB_FOUND AND Boost_BZIP2_FOUND)
set(classification_linked_libraries ${classification_linked_libraries}
${Boost_ZLIB_LIBRARY} ${Boost_BZIP2_LIBRARY})
else()
message(STATUS "NOTICE: This project requires Boost ZLIB and Boost BZIP2, and will not be compiled.")
return()
endif()
else()
if(ZLIB_FOUND)
set(classification_linked_libraries ${classification_linked_libraries} ZLIB::ZLIB)
else()
message(STATUS "NOTICE: This project requires ZLIB, and will not be compiled.")
return()
endif()
endif()
create_single_source_cgal_program( "test_classification_point_set.cpp" )
create_single_source_cgal_program( "test_classification_io.cpp" )
create_single_source_cgal_program( "test_classification_point_set.cpp" CXX_FEATURES ${needed_cxx_features} )
if(TARGET test_classification_point_set)
target_link_libraries(test_classification_point_set PUBLIC ${classification_linked_libraries})
if (TBB_FOUND)
CGAL_target_use_TBB( test_classification_point_set )
foreach(target test_classification_point_set test_classification_io)
CGAL_target_use_Eigen(${target})
CGAL_target_use_Boost_IOStreams(${target})
CGAL_target_use_Boost_Serialization(${target})
if(TBB_FOUND)
CGAL_target_use_TBB(${target})
endif()
endif()
endforeach()
create_single_source_cgal_program( "test_classification_io.cpp" CXX_FEATURES ${needed_cxx_features} )
if(TARGET test_classification_io)
target_link_libraries(test_classification_io PUBLIC ${classification_linked_libraries})
if (TBB_FOUND)
CGAL_target_use_TBB( test_classification_io )
endif()
endif()
@@ -41,6 +41,9 @@
#include <deque>
#include <boost/type_traits/is_same.hpp>
#include <boost/unordered_map.hpp>
#include <boost/graph/graph_traits.hpp>
#include <CGAL/boost/graph/helpers.h>
#include <CGAL/config.h>
#if defined( __INTEL_COMPILER )
@@ -55,6 +58,16 @@ _Pragma("GCC diagnostic ignored \"-Warray-bounds\"")
#endif
namespace CGAL {
// functions to allow the call to next/opposite by ADL
template <typename G, typename Desc>
auto CM_ADL_next(Desc&& d, G&& g) {
return next(std::forward<Desc>(d), std::forward<G>(g));
}
template <typename G, typename Desc>
auto CM_ADL_opposite(Desc&& d, G&& g) {
return opposite(std::forward<Desc>(d), std::forward<G>(g));
}
/** @file Combinatorial_map.h
* Definition of generic dD Combinatorial map.
@@ -199,18 +212,27 @@ namespace CGAL {
CGAL_assertion(number_of_darts()==0);
}
/** Copy the given combinatorial map into *this.
/** Copy the given combinatorial map 'amap' into *this.
* Note that both CMap can have different dimensions and/or non void attributes.
* @param amap the combinatorial map to copy.
* @post *this is valid.
*/
template <typename CMap2, typename Converters, typename DartInfoConverter,
template <unsigned int d2, typename Refs2, typename Items2, typename Alloc2,
typename Storage2,
typename Converters, typename DartInfoConverter,
typename PointConverter>
void copy(const CMap2& amap, const Converters& converters,
void copy(const Combinatorial_map_base<d2, Refs2, Items2, Alloc2, Storage2>& amap,
const Converters& converters,
const DartInfoConverter& dartinfoconverter,
const PointConverter& pointconverter,
boost::unordered_map<typename CMap2::Dart_const_handle, Dart_handle>* dart_mapping=nullptr)
boost::unordered_map
<typename Combinatorial_map_base<d2, Refs2, Items2, Alloc2, Storage2>::
Dart_const_handle, Dart_handle>* origin_to_copy=NULL,
boost::unordered_map
<Dart_handle, typename Combinatorial_map_base<d2, Refs2, Items2,
Alloc2, Storage2>::Dart_const_handle>* copy_to_origin=NULL)
{
typedef Combinatorial_map_base<d2, Refs2, Items2, Alloc2, Storage2> CMap2;
this->clear();
this->mnb_used_marks = amap.mnb_used_marks;
@@ -232,81 +254,113 @@ namespace CGAL {
// Create an mapping between darts of the two maps (originals->copies).
// (here we cannot use CGAL::Unique_hash_map because it does not provide
// iterators...
boost::unordered_map<typename CMap2::Dart_const_handle, Dart_handle> local_dartmap;
if (dart_mapping==nullptr)
{ dart_mapping=&local_dartmap; }
boost::unordered_map<typename CMap2::Dart_const_handle, Dart_handle>
local_dartmap;
if (origin_to_copy==NULL) // Used local_dartmap if user does not provides its own unordered_map
{ origin_to_copy=&local_dartmap; }
Dart_handle new_dart;
for (typename CMap2::Dart_const_range::const_iterator
it=amap.darts().begin(), itend=amap.darts().end();
it!=itend; ++it)
{
(*dart_mapping)[it]=mdarts.emplace();
init_dart((*dart_mapping)[it], amap.get_marks(it));
internal::Copy_dart_info_functor<CMap2, Refs, DartInfoConverter>::run
(amap, static_cast<Refs&>(*this), it, (*dart_mapping)[it],
dartinfoconverter);
new_dart=mdarts.emplace();
init_dart(new_dart, amap.get_marks(it));
(*origin_to_copy)[it]=new_dart;
if (copy_to_origin!=NULL) { (*copy_to_origin)[new_dart]=it; }
internal::Copy_dart_info_functor<Refs2, Refs, DartInfoConverter>::run
(static_cast<const Refs2&>(amap), static_cast<Refs&>(*this),
it, new_dart, dartinfoconverter);
}
unsigned int min_dim=(dimension<amap.dimension?dimension:amap.dimension);
typename boost::unordered_map<typename CMap2::Dart_const_handle,Dart_handle>
::iterator dartmap_iter, dartmap_iter_end=dart_mapping->end();
for (dartmap_iter=dart_mapping->begin(); dartmap_iter!=dartmap_iter_end;
::iterator dartmap_iter, dartmap_iter_end=origin_to_copy->end();
for (dartmap_iter=origin_to_copy->begin(); dartmap_iter!=dartmap_iter_end;
++dartmap_iter)
{
for (unsigned int i=0; i<=min_dim; i++)
{
if (!amap.is_free(dartmap_iter->first,i) &&
(dartmap_iter->first)<(amap.beta(dartmap_iter->first,i)))
is_free(dartmap_iter->second,i))
{
basic_link_beta(dartmap_iter->second,
(*dart_mapping)[amap.beta(dartmap_iter->first,i)], i);
(*origin_to_copy)[amap.beta(dartmap_iter->first,i)], i);
}
}
}
/** Copy attributes */
for (dartmap_iter=dart_mapping->begin(); dartmap_iter!=dartmap_iter_end;
for (dartmap_iter=origin_to_copy->begin(); dartmap_iter!=dartmap_iter_end;
++dartmap_iter)
{
Helper::template Foreach_enabled_attributes
< internal::Copy_attributes_functor <CMap2, Refs, Converters,
< internal::Copy_attributes_functor <Refs2, Refs, Converters,
PointConverter> >::
run(amap, static_cast<Refs&>(*this),
run(static_cast<const Refs2&>(amap), static_cast<Refs&>(*this),
dartmap_iter->first, dartmap_iter->second,
converters, pointconverter);
}
CGAL_assertion (is_valid () == 1);
CGAL_assertion (is_valid());
}
template <typename CMap2>
void copy(const CMap2& amap,
boost::unordered_map<typename CMap2::Dart_const_handle, Dart_handle>* dart_mapping=nullptr)
template <unsigned int d2, typename Refs2, typename Items2, typename Alloc2,
typename Storage2>
void copy(const Combinatorial_map_base<d2, Refs2, Items2, Alloc2, Storage2>& amap,
boost::unordered_map
<typename Combinatorial_map_base<d2, Refs2, Items2, Alloc2,
Storage2>::Dart_const_handle, Dart_handle>* origin_to_copy=NULL,
boost::unordered_map
<Dart_handle, typename Combinatorial_map_base<d2, Refs2, Items2,
Alloc2, Storage2>::Dart_const_handle>* copy_to_origin=NULL)
{
std::tuple<> converters;
Default_converter_dart_info<CMap2, Refs> dartinfoconverter;
Default_converter_cmap_0attributes_with_point<CMap2, Refs> pointconverter;
copy(amap, converters, dartinfoconverter, pointconverter, dart_mapping);
CGAL::cpp11::tuple<> converters;
Default_converter_dart_info<Refs2, Refs> dartinfoconverter;
Default_converter_cmap_0attributes_with_point<Refs2, Refs> pointconverter;
copy(amap, converters, dartinfoconverter, pointconverter,
origin_to_copy, copy_to_origin);
}
template <typename CMap2, typename Converters>
void copy(const CMap2& amap, const Converters& converters,
boost::unordered_map<typename CMap2::Dart_const_handle, Dart_handle>* dart_mapping=nullptr)
template <unsigned int d2, typename Refs2, typename Items2, typename Alloc2,
typename Storage2, typename Converters>
void copy(const Combinatorial_map_base<d2, Refs2, Items2,
Alloc2, Storage2>& amap,
const Converters& converters,
boost::unordered_map
<typename Combinatorial_map_base<d2, Refs2, Items2, Alloc2,
Storage2>::Dart_const_handle, Dart_handle>* origin_to_copy=NULL,
boost::unordered_map
<Dart_handle, typename Combinatorial_map_base<d2, Refs2, Items2,
Alloc2, Storage2>::Dart_const_handle>* copy_to_origin=NULL)
{
Default_converter_cmap_0attributes_with_point<CMap2, Refs> pointconverter;
Default_converter_dart_info<CMap2, Refs> dartinfoconverter;
copy(amap, converters, dartinfoconverter, pointconverter, dart_mapping);
Default_converter_cmap_0attributes_with_point<Refs2, Refs> pointconverter;
Default_converter_dart_info<Refs2, Refs> dartinfoconverter;
copy(amap, converters, dartinfoconverter, pointconverter,
origin_to_copy, copy_to_origin);
}
template <typename CMap2, typename Converters, typename DartInfoConverter>
void copy(const CMap2& amap, const Converters& converters,
template <unsigned int d2, typename Refs2, typename Items2, typename Alloc2,
typename Storage2,
typename Converters, typename DartInfoConverter>
void copy(const Combinatorial_map_base<d2, Refs2, Items2,
Alloc2, Storage2>& amap,
const Converters& converters,
const DartInfoConverter& dartinfoconverter,
boost::unordered_map<typename CMap2::Dart_const_handle, Dart_handle>* dart_mapping=nullptr)
boost::unordered_map
<typename Combinatorial_map_base<d2, Refs2, Items2, Alloc2,
Storage2>::Dart_const_handle, Dart_handle>* origin_to_copy=NULL,
boost::unordered_map
<Dart_handle, typename Combinatorial_map_base<d2, Refs2, Items2,
Alloc2, Storage2>::Dart_const_handle>* copy_to_origin=NULL)
{
Default_converter_cmap_0attributes_with_point<CMap2, Refs> pointconverter;
copy(amap, converters, dartinfoconverter, pointconverter, dart_mapping);
Default_converter_cmap_0attributes_with_point<Refs2, Refs> pointconverter;
copy(amap, converters, dartinfoconverter, pointconverter,
origin_to_copy, copy_to_origin);
}
// Copy constructor from a map having exactly the same type.
@@ -314,25 +368,37 @@ namespace CGAL {
{ copy(amap); }
// "Copy constructor" from a map having different type.
template <typename CMap2>
Combinatorial_map_base(const CMap2& amap)
template <unsigned int d2, typename Refs2, typename Items2, typename Alloc2,
typename Storage2>
Combinatorial_map_base(const Combinatorial_map_base<d2, Refs2, Items2,
Alloc2, Storage2>& amap)
{ copy(amap); }
// "Copy constructor" from a map having different type.
template <typename CMap2, typename Converters>
Combinatorial_map_base(const CMap2& amap, Converters& converters)
template <unsigned int d2, typename Refs2, typename Items2, typename Alloc2,
typename Storage2, typename Converters>
Combinatorial_map_base(const Combinatorial_map_base<d2, Refs2, Items2,
Alloc2, Storage2>& amap,
const Converters& converters)
{ copy(amap, converters); }
// "Copy constructor" from a map having different type.
template <typename CMap2, typename Converters, typename DartInfoConverter>
Combinatorial_map_base(const CMap2& amap, Converters& converters,
template <unsigned int d2, typename Refs2, typename Items2, typename Alloc2,
typename Storage2, typename Converters, typename DartInfoConverter>
Combinatorial_map_base(const Combinatorial_map_base<d2, Refs2, Items2,
Alloc2, Storage2>& amap,
const Converters& converters,
const DartInfoConverter& dartinfoconverter)
{ copy(amap, converters, dartinfoconverter); }
// "Copy constructor" from a map having different type.
template <typename CMap2, typename Converters, typename DartInfoConverter,
typename PointConverter>
Combinatorial_map_base(const CMap2& amap, Converters& converters,
template <unsigned int d2, typename Refs2, typename Items2, typename Alloc2,
typename Storage2,
typename Converters, typename DartInfoConverter,
typename PointConverter>
Combinatorial_map_base(const Combinatorial_map_base<d2, Refs2, Items2,
Alloc2, Storage2>& amap,
const Converters& converters,
const DartInfoConverter& dartinfoconverter,
const PointConverter& pointconverter)
{ copy(amap, converters, dartinfoconverter, pointconverter); }
@@ -385,6 +451,62 @@ namespace CGAL {
}
}
/** Import the given hds which should be a model of an halfedge graph. */
template<class HEG>
void import_from_halfedge_graph(const HEG& heg,
boost::unordered_map
<typename boost::graph_traits<HEG>::halfedge_descriptor,
Dart_handle>* origin_to_copy=NULL,
boost::unordered_map
<Dart_handle,
typename boost::graph_traits<HEG>::halfedge_descriptor>*
copy_to_origin=NULL)
{
// Create an mapping between darts of the two maps (originals->copies).
// (here we cannot use CGAL::Unique_hash_map because it does not provide
// iterators...
boost::unordered_map
<typename boost::graph_traits<HEG>::halfedge_descriptor,
Dart_handle> local_dartmap;
if (origin_to_copy==NULL) // Used local_dartmap if user does not provides its own unordered_map
{ origin_to_copy=&local_dartmap; }
Dart_handle new_dart;
for (typename boost::graph_traits<HEG>::halfedge_iterator
it=halfedges(heg).begin(), itend=halfedges(heg).end();
it!=itend; ++it)
{
if (!CGAL::is_border(*it, heg))
{
new_dart=mdarts.emplace();
(*origin_to_copy)[*it]=new_dart;
if (copy_to_origin!=NULL) { (*copy_to_origin)[new_dart]=*it; }
}
}
typename boost::unordered_map
<typename boost::graph_traits<HEG>::halfedge_descriptor,
Dart_handle>::iterator dartmap_iter, dartmap_iter_end=origin_to_copy->end();
for (dartmap_iter=origin_to_copy->begin(); dartmap_iter!=dartmap_iter_end;
++dartmap_iter)
{
basic_link_beta(dartmap_iter->second,
(*origin_to_copy)[CM_ADL_next(dartmap_iter->first, heg)],
1);
if (!CGAL::is_border(CM_ADL_opposite(dartmap_iter->first, heg), heg) &&
(dartmap_iter->first)<CM_ADL_opposite(dartmap_iter->first, heg))
{
basic_link_beta(dartmap_iter->second,
(*origin_to_copy)
[CM_ADL_opposite(dartmap_iter->first, heg)], 2);
}
}
CGAL_assertion (is_valid());
}
/** Clear the combinatorial map. Remove all darts and all attributes.
* Note that reserved marks are not free.
*/
@@ -498,6 +620,16 @@ namespace CGAL {
{ return mdarts.iterator_to(adart); }
Dart_const_handle dart_handle(const Dart& adart) const
{ return mdarts.iterator_to(adart); }
Dart_handle dart_handle(size_type i)
{
CGAL_assertion(darts().is_used(i));
return mdarts.iterator_to(darts()[i]);
}
Dart_const_handle dart_handle(size_type i) const
{
CGAL_assertion(darts().is_used(i));
return mdarts.iterator_to(darts()[i]);
}
/** Return the highest dimension for which dh is not free.
* @param dh a dart handle
@@ -673,6 +805,11 @@ namespace CGAL {
Dart_const_handle next(Dart_const_handle ADart) const
{ return this->template beta<1>(ADart); }
Dart_handle opposite2(Dart_handle ADart)
{ return this->template beta<2>(ADart); }
Dart_const_handle opposite2(Dart_const_handle ADart) const
{ return this->template beta<2>(ADart); }
template<unsigned int dim>
Dart_handle opposite(Dart_handle ADart)
{ return this->template beta<dim>(ADart); }
@@ -950,6 +1087,27 @@ namespace CGAL {
mnb_times_reserved_marks[amark]=0;
}
template <unsigned int i, unsigned int d=dimension>
bool belong_to_same_cell(Dart_const_handle adart1,
Dart_const_handle adart2) const
{ return CGAL::belong_to_same_cell<Self, i, d>(*this, adart1, adart2); }
template <unsigned int i, unsigned int d=dimension>
bool is_whole_cell_unmarked(Dart_const_handle adart, size_type amark) const
{ return CGAL::is_whole_cell_unmarked<Self, i, d>(*this, adart, amark); }
template <unsigned int i, unsigned int d=dimension>
bool is_whole_cell_marked(Dart_const_handle adart, size_type amark) const
{ return CGAL::is_whole_cell_marked<Self, i, d>(*this, adart, amark); }
template <unsigned int i, unsigned int d=dimension>
size_type mark_cell(Dart_const_handle adart, size_type amark) const
{ return CGAL::mark_cell<Self, i, d>(*this, adart, amark); }
template <unsigned int i, unsigned int d=dimension>
size_type unmark_cell(Dart_const_handle adart, size_type amark) const
{ return CGAL::unmark_cell<Self, i, d>(*this, adart, amark); }
/** Test if this map is without boundary for a given dimension.
* @param i the dimension.
* @return true iff all the darts are not i-free.
@@ -2300,6 +2458,30 @@ namespace CGAL {
run(*this, adart, amark);
}
/// Keep the biggest connected component.
/// @return the size (in number of darts) of the biggest cc.
std::size_t keep_biggest_connected_component()
{
std::map<std::size_t, Dart_handle> ccs;
size_type treated=get_new_mark();
for (auto it=darts().begin(), itend=darts().end(); it!=itend; ++it)
{
if (!is_marked(it, treated))
{ ccs[mark_cell<dimension+1>(it, treated)]=it; }
}
if (ccs.size()>1)
{ // Here all darts are marked
this->template unmark_cell<dimension+1>(ccs.rbegin()->second, treated); // Unmark the biggest cc
erase_marked_darts(treated);
}
free_mark(treated);
return ccs.rbegin()->first;
}
/** Count the marked cells (at least one marked dart).
* @param amark the mark to consider.
* @param avector containing the dimensions of the cells to count.
@@ -2433,6 +2615,64 @@ namespace CGAL {
}
public:
/// @return the positive turn between the two given darts.
// @pre beta1(d1) and d2 must belong to the same vertex.
std::size_t positive_turn(Dart_const_handle d1, Dart_const_handle d2) const
{
CGAL_assertion((!this->template is_free<1>(d1)));
/* CGAL_assertion((belong_to_same_cell<0>(this->template beta<1>(d1),
d2))); */
if (d2==beta<2>(d1)) { return 0; }
Dart_const_handle dd1=d1;
std::size_t res=1;
while (beta<1>(dd1)!=d2)
{
if (this->template is_free<2>(beta<1>(dd1)))
{ return std::numeric_limits<std::size_t>::max(); }
++res;
dd1=beta<1, 2>(dd1);
CGAL_assertion(!this->template is_free<1>(dd1));
CGAL_assertion(beta<1>(dd1)==d2 || dd1!=d1);
}
return res;
}
/// @return the negative turn between the two given darts.
// @pre beta1(d1) and d2 must belong to the same vertex.
std::size_t negative_turn(Dart_const_handle d1, Dart_const_handle d2) const
{
CGAL_assertion((!this->template is_free<1>(d1)));
/* CGAL_assertion((belong_to_same_cell<0>(this->template beta<1>(d1),
d2))); */
if (d2==beta<2>(d1)) { return 0; }
if (this->template is_free<2>(d1) || this->template is_free<2>(d2))
{ return std::numeric_limits<std::size_t>::max(); }
d1=beta<2>(d1);
d2=beta<2>(d2);
Dart_const_handle dd1=d1;
std::size_t res=1;
while (beta<0>(dd1)!=d2)
{
if (this->template is_free<2>(beta<0>(dd1)))
{ return std::numeric_limits<std::size_t>::max(); }
++res;
dd1=beta<0, 2>(dd1);
CGAL_assertion(!this->template is_free<0>(dd1));
CGAL_assertion(beta<0>(dd1)==d2 || dd1!=d1);
}
return res;
}
/** Erase marked darts from the map.
* Marked darts are unlinked before to be removed, thus surviving darts
* are correctly linked, but the map is not necessarily valid depending
@@ -3513,12 +3753,12 @@ namespace CGAL {
!is_face_combinatorial_polygon(d4, 3) ) return false;
// TODO do better with marks (?).
if ( belong_to_same_cell<Self,2,1>(*this, d1, d2) ||
belong_to_same_cell<Self,2,1>(*this, d1, d3) ||
belong_to_same_cell<Self,2,1>(*this, d1, d4) ||
belong_to_same_cell<Self,2,1>(*this, d2, d3) ||
belong_to_same_cell<Self,2,1>(*this, d2, d4) ||
belong_to_same_cell<Self,2,1>(*this, d3, d4) ) return false;
if ( belong_to_same_cell<2,1>(d1, d2) ||
belong_to_same_cell<2,1>(d1, d3) ||
belong_to_same_cell<2,1>(d1, d4) ||
belong_to_same_cell<2,1>(d2, d3) ||
belong_to_same_cell<2,1>(d2, d4) ||
belong_to_same_cell<2,1>(d3, d4) ) return false;
if ( beta(d1,1,2)!=beta(d3,0) ||
beta(d4,0,2)!=beta(d3,1) ||
@@ -3611,21 +3851,21 @@ namespace CGAL {
!is_face_combinatorial_polygon(d6, 4) ) return false;
// TODO do better with marks.
if ( belong_to_same_cell<Self,2,1>(*this, d1, d2) ||
belong_to_same_cell<Self,2,1>(*this, d1, d3) ||
belong_to_same_cell<Self,2,1>(*this, d1, d4) ||
belong_to_same_cell<Self,2,1>(*this, d1, d5) ||
belong_to_same_cell<Self,2,1>(*this, d1, d6) ||
belong_to_same_cell<Self,2,1>(*this, d2, d3) ||
belong_to_same_cell<Self,2,1>(*this, d2, d4) ||
belong_to_same_cell<Self,2,1>(*this, d2, d5) ||
belong_to_same_cell<Self,2,1>(*this, d2, d6) ||
belong_to_same_cell<Self,2,1>(*this, d3, d4) ||
belong_to_same_cell<Self,2,1>(*this, d3, d5) ||
belong_to_same_cell<Self,2,1>(*this, d3, d6) ||
belong_to_same_cell<Self,2,1>(*this, d4, d5) ||
belong_to_same_cell<Self,2,1>(*this, d4, d6) ||
belong_to_same_cell<Self,2,1>(*this, d5, d6) )
if ( belong_to_same_cell<2,1>(d1, d2) ||
belong_to_same_cell<2,1>(d1, d3) ||
belong_to_same_cell<2,1>(d1, d4) ||
belong_to_same_cell<2,1>(d1, d5) ||
belong_to_same_cell<2,1>(d1, d6) ||
belong_to_same_cell<2,1>(d2, d3) ||
belong_to_same_cell<2,1>(d2, d4) ||
belong_to_same_cell<2,1>(d2, d5) ||
belong_to_same_cell<2,1>(d2, d6) ||
belong_to_same_cell<2,1>(d3, d4) ||
belong_to_same_cell<2,1>(d3, d5) ||
belong_to_same_cell<2,1>(d3, d6) ||
belong_to_same_cell<2,1>(d4, d5) ||
belong_to_same_cell<2,1>(d4, d6) ||
belong_to_same_cell<2,1>(d5, d6) )
return false;
if ( beta(d1,2) !=beta(d4,1,1) ||
@@ -3781,7 +4021,7 @@ namespace CGAL {
return this->template beta<1>(adart);
}
/** Insert a vertex in the given 2-cell which is splitted in triangles,
/** Insert a vertex in the given 2-cell which is split in triangles,
* once for each inital edge of the facet.
* @param adart a dart of the facet to triangulate.
* @param update_attributes a boolean to update the enabled attributes
@@ -4213,7 +4453,7 @@ namespace CGAL {
if ( od==null_handle ) return false;
// of and *it must belong to the same vertex of the same volume
if ( !belong_to_same_cell<Self, 0, 2>(*this, od, *it) )
if ( !belong_to_same_cell<0, 2>(od, *it) )
return false;
}
prec = *it;
@@ -4223,7 +4463,7 @@ namespace CGAL {
od = other_extremity(prec);
if ( od==null_handle ) return false;
if (!belong_to_same_cell<Self, 0, 2>(*this, od, *afirst))
if (!belong_to_same_cell<0, 2>(od, *afirst))
return false;
return true;
@@ -4437,24 +4677,33 @@ namespace CGAL {
Combinatorial_map(const Self & amap) : Base(amap)
{}
template < class CMap >
Combinatorial_map(const CMap & amap) : Base(amap)
template <unsigned int d2, typename Refs2, typename Items2, typename Alloc2,
typename Storage2>
Combinatorial_map(const Combinatorial_map_base<d2, Refs2, Items2, Alloc2, Storage2>&
amap) : Base(amap)
{}
template < class CMap, typename Converters >
Combinatorial_map(const CMap & amap, const Converters& converters) :
template <unsigned int d2, typename Refs2, typename Items2, typename Alloc2,
typename Storage2, typename Converters>
Combinatorial_map(const Combinatorial_map_base<d2, Refs2, Items2, Alloc2, Storage2>&
amap, const Converters& converters) :
Base(amap, converters)
{}
template < class CMap, typename Converters, typename DartInfoConverter >
Combinatorial_map(const CMap & amap, const Converters& converters,
template <unsigned int d2, typename Refs2, typename Items2, typename Alloc2,
typename Storage2, typename Converters,
typename DartInfoConverter>
Combinatorial_map(const Combinatorial_map_base<d2, Refs2, Items2, Alloc2, Storage2>&
amap, const Converters& converters,
const DartInfoConverter& dartinfoconverter) :
Base(amap, converters, dartinfoconverter)
{}
template < class CMap, typename Converters, typename DartInfoConverter,
typename PointConverter >
Combinatorial_map(const CMap & amap, const Converters& converters,
template <unsigned int d2, typename Refs2, typename Items2, typename Alloc2,
typename Storage2, typename Converters,
typename DartInfoConverter, typename PointConverter >
Combinatorial_map(const Combinatorial_map_base<d2, Refs2, Items2, Alloc2, Storage2>&
amap, const Converters& converters,
const DartInfoConverter& dartinfoconverter,
const PointConverter& pointconverter) :
Base(amap, converters, dartinfoconverter, pointconverter)
@@ -194,7 +194,7 @@ namespace CGAL
typename Map::size_type amark)
{
return CGAL::is_whole_orbit_unmarked<Map,
typename Map::template Dart_of_cell_range<i,d>::iterator>
typename Map::template Dart_of_cell_range<i,d>::const_iterator>
(amap, adart, amark);
}
@@ -39,7 +39,7 @@ insert_cell_0_in_cell_1( CMap& amap, typename CMap::Dart_handle adart,
return amap.insert_cell_0_in_cell_1(adart, ah, update_attributes);
}
/** Insert a vertex in the given 2-cell which is splitted in triangles,
/** Insert a vertex in the given 2-cell which is split in triangles,
* once for each inital edge of the facet.
* @param amap the used combinatorial map.
* @param adart a dart of the facet to triangulate.
@@ -106,7 +106,7 @@ namespace CGAL {
{
return ( ((*this==mmap->null_handle) && (aiterator==mmap->null_handle)) ||
(mfirst_dart == aiterator.mfirst_dart &&
static_cast<const Base&>(*this)==
static_cast<const Base&>(*this)==
static_cast<const Base&>(aiterator)) );
}
@@ -127,6 +127,8 @@ namespace CGAL {
CGAL_assertion(i <= dimension);
return dh->mf[i]==null_dart_handle;
}
bool is_perforated(Dart_const_handle /*dh*/) const
{ return false; }
/// Set simultaneously all the marks of this dart to a given value.
void set_dart_marks(Dart_const_handle ADart,
@@ -0,0 +1,941 @@
// Copyright (c) 2019 CNRS and LIRIS' Establishments (France).
// All rights reserved.
//
// This file is part of CGAL (www.cgal.org)
//
// $URL$
// $Id$
// SPDX-License-Identifier: LGPL-3.0-or-later OR LicenseRef-Commercial
//
// Author(s) : Guillaume Damiand <guillaume.damiand@liris.cnrs.fr>
//
#ifndef CGAL_FACE_GRAPH_WRAPPER_H
#define CGAL_FACE_GRAPH_WRAPPER_H 1
#include <CGAL/Functors_for_face_graph_wrapper.h>
#include <CGAL/Iterators_for_face_graph_wrapper.h>
#include <CGAL/internal/Combinatorial_map_internal_functors.h>
#include <CGAL/Polyhedron_3_fwd.h>
#include <CGAL/Surface_mesh/Surface_mesh_fwd.h>
#include <bitset>
namespace CGAL
{
// Forward declarations of all classes model of Face_graph
template <unsigned int d, typename Refs, typename Items, typename Alloc,
typename Storage>
class Combinatorial_map_base;
template <unsigned int d, typename Refs, typename Items, typename Alloc,
typename Storage>
class Generalized_map_base;
template <unsigned int d, unsigned int d2, typename Traits, typename Items,
typename Alloc,
template<unsigned int,class,class,class,class>
class Map, typename Refs, typename Storage>
class Linear_cell_complex_base;
template <unsigned int d, typename Items, typename Alloc,
typename Storage>
class Combinatorial_map;
template <unsigned int d, typename Items, typename Alloc,
typename Storage>
class Generalized_map;
template <unsigned int d, unsigned int d2, typename Traits, typename Items,
typename Alloc,
template<unsigned int,class,class,class,class>
class Map, typename Storage>
class Linear_cell_complex_for_combinatorial_map;
template <unsigned int d, unsigned int d2, typename Traits, typename Items,
typename Alloc,
template<unsigned int,class,class,class,class>
class Map, typename Storage>
class Linear_cell_complex_for_generalized_map;
namespace Surface_mesh_topology
{
template <typename Items, typename Alloc, typename Storage>
class Polygonal_schema_with_combinatorial_map;
template <typename Items, typename Alloc, typename Storage>
class Polygonal_schema_with_generalized_map;
}
////////////////////////////////////////////////////////////////////////////////
/** Class Face_graph_wrapper: to wrap any model of FaceGraph into a
* Combinatorial map. For now, only for const models, i.e. does not support
* modification operators.
*/
template<typename HEG_>
class Face_graph_wrapper
{
public:
typedef HEG_ HEG;
typedef Face_graph_wrapper<HEG> Self;
typedef std::size_t size_type;
struct Dart_container
{
typedef typename boost::graph_traits<HEG>::halfedge_iterator iterator;
typedef typename boost::graph_traits<HEG>::halfedge_iterator const_iterator; // TODO ?
// typedef My_halfedge_iterator<HEG> iterator;
// typedef My_halfedge_iterator<HEG> const_iterator; // TODO ?
};
typedef typename boost::graph_traits<HEG>::halfedge_descriptor Dart_handle;
typedef typename boost::graph_traits<HEG>::halfedge_descriptor Dart_const_handle;
typedef Dart_handle Null_handle_type;
// typedef CGAL::Void* Null_handle_type;
static const Null_handle_type null_handle; //=Dart_handle();
static const Null_handle_type null_dart_handle; //=Dart_handle();
/// Number of marks
static const size_type NB_MARKS = 32;
static const size_type INVALID_MARK = NB_MARKS;
/// The dimension of the combinatorial map.
static const unsigned int dimension=2;
static const unsigned int ambient_dimension=3;
typedef typename boost::graph_traits<HEG>::vertex_descriptor vertex_descriptor;
typedef typename boost::graph_traits<HEG>::edge_descriptor edge_descriptor;
typedef typename boost::graph_traits<HEG>::face_descriptor face_descriptor;
typedef boost::undirected_tag directed_category;
typedef boost::disallow_parallel_edge_tag edge_parallel_category;
struct SM_graph_traversal_category : public virtual boost::bidirectional_graph_tag,
public virtual boost::vertex_list_graph_tag,
public virtual boost::edge_list_graph_tag
{};
typedef SM_graph_traversal_category traversal_category;
Face_graph_wrapper(const HEG& f) : m_fg(f),
mdarts(*this),
m_nb_darts(0),
mnb_used_marks(0)
{
mmask_marks.reset();
for (size_type i=0; i<NB_MARKS; ++i)
{
mfree_marks_stack[i] =i;
mindex_marks[i] =i;
mnb_marked_darts[i] =0;
mnb_times_reserved_marks[i]=0;
}
// Store locally the number of darts: the HEG must not be modified
m_nb_darts=darts().size();
m_all_marks=get(CGAL::dynamic_halfedge_property_t<std::bitset<NB_MARKS> >(), m_fg);
for (typename Dart_range::const_iterator it(darts().begin()),
itend(darts().end()); it!=itend; ++it)
{ put(m_all_marks, it, std::bitset<NB_MARKS>()); }
}
const HEG& get_fg() const
{ return m_fg; }
template<unsigned int i>
bool is_free(Dart_const_handle /* dh */) const
{ return false; } // Not possible to have a free dart with an HEG.
bool is_free(Dart_const_handle /*dh*/, unsigned int /*i*/) const
{ return false; } // Not possible to have a free dart with an HEG.
bool is_perforated(Dart_const_handle dh) const
{ return is_border(dh, m_fg); }
Dart_const_handle get_beta(Dart_const_handle ADart, int B1) const
{
CGAL_assertion(B1>=0 && B1<=static_cast<int>(dimension));
if (B1==1) return Get_beta<HEG, 1>::value(m_fg, ADart);
if (B1==2) return Get_beta<HEG, 2>::value(m_fg, ADart);
return Get_beta<HEG, 0>::value(m_fg, ADart);
}
template<int B1>
Dart_const_handle get_beta(Dart_const_handle ADart) const
{
CGAL_assertion(B1>=0 && B1<=static_cast<int>(dimension));
return Get_beta<HEG, B1>::value(m_fg, ADart);
}
bool is_empty() const
{ return number_of_darts()==0; }
/* ?? bool is_dart_used(Dart_const_handle dh) const
{ return true; ?? } */
int highest_nonfree_dimension(Dart_const_handle /* dh */) const
{ return 2; }
Dart_const_handle previous(Dart_const_handle ADart) const
{ return get_beta<0>(ADart); }
Dart_const_handle next(Dart_const_handle ADart) const
{ return get_beta<1>(ADart); }
Dart_const_handle opposite(Dart_const_handle dh) const
{ return get_beta<2>(dh); }
Dart_const_handle opposite2(Dart_const_handle dh) const
{ return get_beta<2>(dh); }
Dart_const_handle other_extremity(Dart_const_handle dh) const
{ return get_beta<1>(dh); }
template<unsigned int dim>
Dart_const_handle opposite(Dart_const_handle ADart) const
{ return this->template get_beta<dim>(ADart); }
Dart_const_handle other_orientation(Dart_const_handle ADart) const
{ return ADart; }
bool is_previous_exist(Dart_const_handle) const
{ return true; }
bool is_next_exist(Dart_const_handle) const
{ return true; }
template<unsigned int dim>
bool is_opposite_exist(Dart_const_handle /* ADart */) const
{ return true; }
template<typename ...Betas>
Dart_handle beta(Dart_handle ADart, Betas... betas)
{ return CGAL::internal::Beta_functor<Self, Dart_handle, Betas...>::
run(*this, ADart, betas...); }
template<typename ...Betas>
Dart_const_handle beta(Dart_const_handle ADart, Betas... betas) const
{ return CGAL::internal::Beta_functor<const Self, Dart_const_handle, Betas...>::
run(*this, ADart, betas...); }
template<int... Betas>
Dart_handle beta(Dart_handle ADart)
{ return CGAL::internal::Beta_functor_static<Self, Dart_handle, Betas...>::
run(*this, ADart); }
template<int... Betas>
Dart_const_handle beta(Dart_const_handle ADart) const
{ return CGAL::internal::Beta_functor_static<const Self, Dart_const_handle, Betas...>::
run(*this, ADart); }
size_type number_of_darts() const
{ return m_nb_darts; }
size_type number_of_halfedges() const
{ return number_of_darts(); }
size_type number_of_used_marks() const
{ return mnb_used_marks; }
bool is_reserved(size_type amark) const
{
CGAL_assertion(amark<NB_MARKS);
return (mnb_times_reserved_marks[amark]!=0);
}
size_type number_of_marked_darts(size_type amark) const
{
CGAL_assertion( is_reserved(amark) );
return mnb_marked_darts[amark];
}
size_type number_of_unmarked_darts(size_type amark) const
{
CGAL_assertion( is_reserved(amark) );
return number_of_darts() - number_of_marked_darts(amark);
}
bool is_whole_map_unmarked(size_type amark) const
{ return number_of_marked_darts(amark)==0; }
bool is_whole_map_marked(size_type amark) const
{ return number_of_marked_darts(amark)==number_of_darts(); }
class Exception_no_more_available_mark {};
size_type get_new_mark() const
{
if (mnb_used_marks==NB_MARKS)
{
std::cerr << "Not enough Boolean marks: "
"increase NB_MARKS in item class." << std::endl;
std::cerr << " (exception launched)" << std::endl;
throw Exception_no_more_available_mark();
}
size_type m=mfree_marks_stack[mnb_used_marks];
mused_marks_stack[mnb_used_marks]=m;
mindex_marks[m]=mnb_used_marks;
mnb_times_reserved_marks[m]=1;
++mnb_used_marks;
CGAL_assertion(is_whole_map_unmarked(m));
return m;
}
void share_a_mark(size_type amark) const
{
CGAL_assertion( is_reserved(amark) );
++mnb_times_reserved_marks[amark];
}
size_type get_number_of_times_mark_reserved(size_type amark) const
{
CGAL_assertion( amark<NB_MARKS );
return mnb_times_reserved_marks[amark];
}
void negate_mark(size_type amark) const
{
CGAL_assertion(is_reserved(amark));
mnb_marked_darts[amark]=number_of_darts()-mnb_marked_darts[amark];
mmask_marks.flip(amark);
}
void mark_null_dart( size_type /*amark*/) const
{}
bool get_dart_mark(Dart_const_handle ADart, size_type amark) const
{
return get(m_all_marks, ADart)[amark];
}
void set_dart_mark(Dart_const_handle ADart, size_type amark, bool avalue) const
{
const_cast<std::bitset<NB_MARKS>& >(get(m_all_marks, ADart)).set(amark, avalue);
}
void flip_dart_mark(Dart_const_handle ADart, size_type amark) const
{ set_dart_mark(ADart, amark, !get_dart_mark(ADart, amark)); }
bool is_marked(Dart_const_handle adart, size_type amark) const
{
CGAL_assertion(is_reserved(amark));
return get_dart_mark(adart, amark)!=mmask_marks[amark];
}
void set_mark_to(Dart_const_handle adart, size_type amark,
bool astate) const
{
CGAL_assertion(is_reserved(amark));
if (is_marked(adart, amark)!=astate)
{
if (astate) ++mnb_marked_darts[amark];
else --mnb_marked_darts[amark];
flip_dart_mark(adart, amark);
}
}
void mark(Dart_const_handle adart, size_type amark) const
{
CGAL_assertion(is_reserved(amark));
if (is_marked(adart, amark)) return;
++mnb_marked_darts[amark];
flip_dart_mark(adart, amark);
}
void unmark(Dart_const_handle adart, size_type amark) const
{
CGAL_assertion( adart!=this->null_dart_handle );
CGAL_assertion( is_reserved(amark) );
if (!is_marked(adart, amark)) return;
--mnb_marked_darts[amark];
flip_dart_mark(adart, amark);
}
void unmark_all(size_type amark) const
{
CGAL_assertion( is_reserved(amark) );
if ( is_whole_map_marked(amark) )
{
negate_mark(amark);
}
else if ( !is_whole_map_unmarked(amark) )
{
for (typename Dart_range::const_iterator it(darts().begin()),
itend(darts().end()); it!=itend; ++it)
unmark(*it, amark);
}
CGAL_assertion(is_whole_map_unmarked(amark));
}
void free_mark(size_type amark) const
{
CGAL_assertion( is_reserved(amark) );
if ( mnb_times_reserved_marks[amark]>1 )
{
--mnb_times_reserved_marks[amark];
return;
}
unmark_all(amark);
// 1) We remove amark from the array mused_marks_stack by
// replacing it with the last mark in this array.
mused_marks_stack[mindex_marks[amark]] =
mused_marks_stack[--mnb_used_marks];
mindex_marks[mused_marks_stack[mnb_used_marks]] =
mindex_marks[amark];
// 2) We add amark in the array mfree_marks_stack and update its index.
mfree_marks_stack[ mnb_used_marks ]=amark;
mindex_marks[amark] = mnb_used_marks;
mnb_times_reserved_marks[amark]=0;
}
bool is_without_boundary(unsigned int i) const
{
CGAL_assertion(1<=i && i<=dimension);
if (i==1) return true;
for ( typename Dart_range::const_iterator it(darts().begin()),
itend(darts().end()); it!=itend; ++it)
{ if (is_perforated(it)) return false; }
return true;
}
bool is_without_boundary() const
{ return is_without_boundary(2); }
//**************************************************************************
// Dart_of_cell_range
template<unsigned int i>
struct Dart_of_cell_range
{
typedef CGAL::FGW_cell_iterator<Self, i> iterator;
typedef CGAL::FGW_cell_iterator<Self, i> const_iterator;
Dart_of_cell_range(const Self &amap, Dart_handle adart) : mmap(amap),
m_initdart(adart),
msize(0)
{}
const_iterator begin() const { return const_iterator(mmap, m_initdart); }
const_iterator end() const { return const_iterator(mmap, m_initdart, mmap.null_handle); }
size_type size() const
{
if (msize==0)
{
for (const_iterator it=begin(), itend=end(); it!=itend; ++it)
{ ++msize; }
}
return msize;
}
bool empty() const
{ return mmap.is_empty(); }
private:
const Self & mmap;
Dart_handle m_initdart;
mutable typename Self::size_type msize;
};
//**************************************************************************
// Dart_of_cell_const_range
/* template<unsigned int i,int dim=Self::dimension>
struct Dart_of_cell_const_range // TODO REMOVE ??
{}; */
//--------------------------------------------------------------------------
template<unsigned int i>
Dart_of_cell_range<i> darts_of_cell(Dart_handle adart)
{ return Dart_of_cell_range<i>(*this,adart); }
//--------------------------------------------------------------------------
template<unsigned int i>
Dart_of_cell_range<i> darts_of_cell(Dart_const_handle adart) const
{ return Dart_of_cell_range<i>(*this,adart); } // Before it was Dart_of_cell_const_range<i>
//**************************************************************************
// Dart_range
struct Dart_range {
typedef CGAL::FGW_dart_iterator_basic_of_all<Self> iterator;
typedef CGAL::FGW_dart_iterator_basic_of_all<Self> const_iterator;
Dart_range(const Self &amap) : mmap(amap), msize(0)
{}
iterator begin() { return iterator(mmap); }
iterator end() { return iterator(mmap,mmap.null_handle); }
const_iterator begin() const { return const_iterator(mmap); }
const_iterator end() const { return const_iterator(mmap,mmap.null_handle); }
size_type size() const
{
if (msize==0)
{ msize=halfedges(mmap.get_fg()).size(); }
return msize;
}
bool empty() const
{ return mmap.is_empty(); }
size_type capacity() const
{ return num_halfedges(mmap.get_fg()); }
bool is_used(size_type i) const
{
for (typename boost::template graph_traits<typename Self::HEG>::halfedge_iterator
it=halfedges(mmap.get_fg()).begin(),
itend=halfedges(mmap.get_fg()).end(); it!=itend; ++it)
{
if (i==0) { return !is_border(*it, mmap.get_fg()); }
--i;
}
return false;
}
private:
const Self & mmap;
mutable typename Self::size_type msize;
};
//**************************************************************************
// Dart_const_range // TODO REMOVE ?
/* struct Dart_const_range {
typedef CGAL::FGW_dart_iterator_basic_of_all<Self, true> const_iterator;
Dart_const_range(const Self &amap) : mmap(amap), msize(0)
{}
const_iterator begin() const { return const_iterator(mmap); }
const_iterator end() const { return const_iterator(mmap,mmap.null_handle); }
size_type size() const
{
if (msize==0)
{
for (const_iterator it=begin(), itend=end(); it!=itend; ++it)
{ ++msize; }
}
return msize;
}
bool empty() const
{ return mmap.is_empty(); }
private:
const Self & mmap;
mutable typename Self::size_type msize;
};*/
//**************************************************************************
Dart_range& darts()
{ return mdarts; }
//--------------------------------------------------------------------------
const Dart_range& darts() const
{ return mdarts; } // Before it was Dart_const_range(*this)
//**************************************************************************
Dart_handle dart_handle(size_type i)
{
CGAL_assertion(darts().is_used(i));
for (typename boost::template graph_traits<typename Self::HEG>::halfedge_iterator
it=halfedges(get_fg()).begin(),
itend=halfedges(get_fg()).end(); it!=itend; ++it)
{
if (i==0) { return *it; }
--i;
}
CGAL_assertion(false);
return Dart_handle();
}
Dart_const_handle dart_handle(size_type i) const
{
CGAL_assertion(darts().is_used(i));
for (typename boost::template graph_traits<typename Self::HEG>::halfedge_iterator
it=halfedges(get_fg()).begin(),
itend=halfedges(get_fg()).end(); it!=itend; ++it)
{
if (i==0) { return *it; }
--i;
}
CGAL_assertion(false);
return Dart_const_handle();
}
template <unsigned int i>
bool belong_to_same_cell(Dart_const_handle adart1,
Dart_const_handle adart2) const
{
for (typename Dart_of_cell_range<i>::iterator it=darts_of_cell<i>(adart1).begin(),
itend=darts_of_cell<i>(adart1).end(); it!=itend; ++it)
{ if (*it==adart2) { return true; } }
return false;
}
template <unsigned int i>
bool is_whole_cell_unmarked(Dart_const_handle adart, size_type amark) const
{
for (typename Dart_of_cell_range<i>::iterator it=darts_of_cell<i>(adart).begin(),
itend=darts_of_cell<i>(adart).end(); it!=itend; ++it)
{ if (is_marked(*it, amark)) { return false; } }
return true;
}
template <unsigned int i>
bool is_whole_cell_marked(Dart_const_handle adart, size_type amark) const
{
for (typename Dart_of_cell_range<i>::iterator it=darts_of_cell<i>(adart).begin(),
itend=darts_of_cell<i>(adart).end(); it!=itend; ++it)
{ if (!is_marked(*it, amark)) { return false; } }
return true;
}
template <unsigned int i>
size_type mark_cell(Dart_const_handle adart, size_type amark) const
{
size_type res=0;
for (typename Dart_of_cell_range<i>::iterator it=darts_of_cell<i>(adart).begin(),
itend=darts_of_cell<i>(adart).end(); it!=itend; ++it)
{ mark(*it, amark); ++res; }
return res;
}
size_type mark_cell(Dart_const_handle adart, unsigned int i, size_type amark) const
{
if (i==0) { return mark_cell<0>(adart, amark); }
else if (i==1) { return mark_cell<1>(adart, amark); }
else if (i==2) { return mark_cell<2>(adart, amark); }
return mark_cell<3>(adart, amark);
}
template <unsigned int i>
size_type unmark_cell(Dart_const_handle adart, size_type amark) const
{
size_type res=0;
for (typename Dart_of_cell_range<i>::iterator it=darts_of_cell<i>(adart).begin(),
itend=darts_of_cell<i>(adart).end(); it!=itend; ++it)
{ unmark(*it, amark); ++res; }
return res;
}
std::vector<unsigned int>
count_marked_cells(size_type amark, const std::vector<unsigned int>& acells) const
{
std::vector<unsigned int> res(dimension+2);
std::vector<size_type> marks(dimension+2);
// Initialization of the result
for (unsigned int i=0; i<dimension+2; ++i)
{
res[i]=0;
marks[i]=INVALID_MARK;
}
// Mark reservation
for (unsigned int i=0; i<acells.size(); ++i)
{
CGAL_assertion(acells[i]<=dimension+1);
if (marks[acells[i]]==INVALID_MARK )
{
marks[acells[i]]=get_new_mark();
assert(is_whole_map_unmarked(marks[acells[i]]));
}
}
// Counting and marking cells
for (typename Dart_range::const_iterator it(darts().begin()),
itend(darts().end()); it!=itend; ++it)
{
if (is_marked(*it, amark))
{
for (unsigned int i=0; i<acells.size(); ++i)
{
if (!is_marked(*it, marks[acells[i]]))
{
mark_cell(*it, acells[i], marks[acells[i]]);
++res[acells[i]];
}
}
}
}
// Unmarking darts
std::vector<size_type> tounmark;
for (unsigned int i=0; i<acells.size(); ++i)
{
if (is_whole_map_marked(marks[acells[i]]) ||
is_whole_map_unmarked(marks[acells[i]]))
{ free_mark(marks[acells[i]]); }
else
{ tounmark.push_back(marks[acells[i]]); }
}
if (tounmark.size()>0)
{
for (typename Dart_range::const_iterator it(darts().begin()),
itend(darts().end()); it!=itend; ++it)
{
for (unsigned int i=0; i<tounmark.size(); ++i)
{ unmark(*it, tounmark[i]); }
}
for (unsigned int i=0; i<tounmark.size(); ++i)
{
CGAL_assertion(is_whole_map_unmarked(tounmark[i]));
free_mark(tounmark[i]);
}
}
return res;
}
std::vector<unsigned int>
count_cells(const std::vector<unsigned int>& acells) const
{
std::vector<unsigned int> res;
size_type m=get_new_mark();
negate_mark(m); // We mark all the cells.
res=count_marked_cells(m, acells);
negate_mark(m); // We unmark the cells
free_mark(m);
return res;
}
std::vector<unsigned int> count_all_cells() const
{
std::vector<unsigned int> dim(dimension+2);
for ( unsigned int i=0; i<=dimension+1; ++i)
{ dim[i]=i; }
return count_cells(dim);
}
std::ostream& display_characteristics(std::ostream & os) const
{
std::vector<unsigned int> cells(dimension+2);
for ( unsigned int i=0; i<=dimension+1; ++i)
{ cells[i]=i; }
std::vector<unsigned int> res=count_cells(cells);
os<<"#Darts="<<number_of_darts();
for (unsigned int i=0; i<=dimension; ++i)
os<<", #"<<i<<"-cells="<<res[i];
os<<", #ccs="<<res[dimension+1];
return os;
}
protected:
const HEG& m_fg;
Dart_range mdarts;
std::size_t m_nb_darts;
/// Number of times each mark is reserved. 0 if the mark is free.
mutable size_type mnb_times_reserved_marks[NB_MARKS];
/// Mask marks to know the value of unmark dart, for each index i.
mutable std::bitset<NB_MARKS> mmask_marks;
/// Number of used marks.
mutable size_type mnb_used_marks;
/// Index of each mark, in mfree_marks_stack or in mfree_marks_stack.
mutable size_type mindex_marks[NB_MARKS];
/// "Stack" of free marks.
mutable size_type mfree_marks_stack[NB_MARKS];
/// "Stack" of used marks.
mutable size_type mused_marks_stack[NB_MARKS];
/// Number of marked darts for each used marks.
mutable size_type mnb_marked_darts[NB_MARKS];
/// Array of property maps; one for each reserved mark.
typedef typename boost::property_map
<HEG, CGAL::dynamic_halfedge_property_t<std::bitset<NB_MARKS> > >::const_type MarkPMap;
mutable MarkPMap m_all_marks;
};
/// null_handle
// template <typename HEG>
// const typename Face_graph_wrapper<HEG>::Null_handle_type
// Face_graph_wrapper<HEG>::null_handle=nullptr;
template <typename HEG>
const typename Face_graph_wrapper<HEG>::Null_handle_type
Face_graph_wrapper<HEG>::null_handle=typename Face_graph_wrapper<HEG>::Dart_handle();
/// null_dart_handle
// template <typename HEG>
// const typename Face_graph_wrapper<HEG>::Null_handle_type
// Face_graph_wrapper<HEG>::null_dart_handle=nullptr;
template <typename HEG>
const typename Face_graph_wrapper<HEG>::Null_handle_type
Face_graph_wrapper<HEG>::null_dart_handle=typename Face_graph_wrapper<HEG>::Dart_handle();
template<class Base, class HEG>
struct Get_map
{
typedef Face_graph_wrapper<HEG> type;
typedef const Face_graph_wrapper<HEG> storage_type;
Get_map(const HEG& heg): m_map(heg) {}
static const HEG& get_mesh(const storage_type& amap)
{ return amap.get_fg(); }
storage_type m_map;
};
template <unsigned int d, typename Refs, typename Items, typename Alloc,
typename Storage, class Map>
struct Get_map<CGAL::Combinatorial_map_base<d, Refs, Items, Alloc, Storage>, Map>
{
typedef Map type;
typedef const Map& storage_type;
Get_map(const Map& heg): m_map(heg) {}
static const Map& get_mesh(storage_type& amap)
{ return amap; }
storage_type m_map;
};
template <unsigned int d, typename Refs, typename Items, typename Alloc,
typename Storage, class Map>
struct Get_map<CGAL::Generalized_map_base<d, Refs, Items, Alloc, Storage>, Map>
{
typedef Map type;
typedef const Map& storage_type;
Get_map(const Map& heg): m_map(heg) {}
static const Map& get_mesh(storage_type& amap)
{ return amap; }
storage_type m_map;
};
template <unsigned int d, unsigned int d2, typename Traits, typename Items,
typename Alloc,
template<unsigned int,class,class,class,class>
class Map, typename Refs, typename Storage, class LCC>
struct Get_map<CGAL::Linear_cell_complex_base<d, d2, Traits, Items, Alloc,
Map, Refs, Storage>, LCC>
{
typedef LCC type;
typedef const LCC& storage_type;
Get_map(const LCC& heg): m_map(heg) {}
static const LCC& get_mesh(storage_type& amap)
{ return amap; }
storage_type m_map;
};
template <unsigned int d, typename Items, typename Alloc,
typename Storage, class Map>
struct Get_map<CGAL::Combinatorial_map<d, Items, Alloc, Storage>, Map>
{
typedef Map type;
typedef const Map& storage_type;
Get_map(const Map& heg): m_map(heg) {}
static const Map& get_mesh(storage_type& amap)
{ return amap; }
storage_type m_map;
};
template <typename Items, typename Alloc, typename Storage, class Map>
struct Get_map<CGAL::Surface_mesh_topology::
Polygonal_schema_with_combinatorial_map<Items, Alloc, Storage>, Map>
{
typedef Map type;
typedef const Map& storage_type;
Get_map(const Map& heg): m_map(heg) {}
static const Map& get_mesh(storage_type& amap)
{ return amap; }
storage_type m_map;
};
template <unsigned int d, typename Items, typename Alloc,
typename Storage, class Map>
struct Get_map<CGAL::Generalized_map<d, Items, Alloc, Storage>, Map>
{
typedef Map type;
typedef const Map& storage_type;
Get_map(const Map& heg): m_map(heg) {}
static const Map& get_mesh(storage_type& amap)
{ return amap; }
storage_type m_map;
};
template <typename Items, typename Alloc, typename Storage, class Map>
struct Get_map<CGAL::Surface_mesh_topology::
Polygonal_schema_with_generalized_map<Items, Alloc, Storage>, Map>
{
typedef Map type;
typedef const Map& storage_type;
Get_map(const Map& heg): m_map(heg) {}
static const Map& get_mesh(storage_type& amap)
{ return amap; }
storage_type m_map;
};
template <unsigned int d, unsigned int d2, typename Traits, typename Items,
typename Alloc,
template<unsigned int,class,class,class,class>
class Map, typename Storage, class LCC>
struct Get_map<CGAL::Linear_cell_complex_for_combinatorial_map
<d, d2, Traits, Items, Alloc, Map, Storage>, LCC>
{
typedef LCC type;
typedef const LCC& storage_type;
Get_map(const LCC& heg): m_map(heg) {}
static const LCC& get_mesh(storage_type& amap)
{ return amap; }
storage_type m_map;
};
template <unsigned int d, unsigned int d2, typename Traits, typename Items,
typename Alloc,
template<unsigned int,class,class,class,class>
class Map, typename Storage, class LCC>
struct Get_map<CGAL::Linear_cell_complex_for_generalized_map
<d, d2, Traits, Items, Alloc, Map, Storage>, LCC>
{
typedef LCC type;
typedef const LCC& storage_type;
Get_map(const LCC& heg): m_map(heg) {}
static const LCC& get_mesh(storage_type& amap)
{ return amap; }
storage_type m_map;
};
template<class Mesh_>
struct Get_traits
{
typedef Mesh_ Mesh;
typedef typename Mesh::Traits Kernel;
typedef typename Mesh::Point Point;
typedef typename Mesh::Vector Vector;
template<class Dart_handle>
static const Point& get_point(const Mesh& m, Dart_handle dh)
{ return m.point(dh); }
};
template<class P>
struct Get_traits<CGAL::Surface_mesh<P> >
{
typedef CGAL::Surface_mesh<P> Mesh;
typedef typename CGAL::Kernel_traits<P>::Kernel Kernel;
typedef typename Kernel::Point_3 Point;
typedef typename Kernel::Vector_3 Vector;
template<class Dart_handle>
static const Point& get_point(const Mesh& m, Dart_handle dh)
{ return m.point(m.source(dh)); }
};
template<class PolyhedronTraits_3,
class PolyhedronItems_3,
template<class T, class I, class A> class T_HDS,
class Alloc>
struct Get_traits<CGAL::Polyhedron_3<PolyhedronTraits_3,
PolyhedronItems_3, T_HDS, Alloc> >
{
typedef CGAL::Polyhedron_3<PolyhedronTraits_3, PolyhedronItems_3,
T_HDS, Alloc> Mesh;
typedef PolyhedronTraits_3 Kernel;
typedef typename Kernel::Point_3 Point;
typedef typename Kernel::Vector_3 Vector;
template<class Dart_handle>
static const Point& get_point(const Mesh& /*m*/, Dart_handle dh)
{ return dh->opposite()->vertex()->point(); }
};
} // Namespace CGAL
#endif // CGAL_FACE_GRAPH_WRAPPER_H //
// EOF //
@@ -0,0 +1,87 @@
// Copyright (c) 2019 CNRS and LIRIS' Establishments (France).
// All rights reserved.
//
// This file is part of CGAL (www.cgal.org)
//
// $URL$
// $Id$
// SPDX-License-Identifier: LGPL-3.0-or-later OR LicenseRef-Commercial
//
// Author(s) : Guillaume Damiand <guillaume.damiand@liris.cnrs.fr>
//
#ifndef CGAL_FUNCTORS_FOR_FACE_GRAPH_WRAPPER_H
#define CGAL_FUNCTORS_FOR_FACE_GRAPH_WRAPPER_H 1
#include <boost/graph/graph_traits.hpp>
#include <CGAL/boost/graph/helpers.h>
#include <CGAL/Iterators_for_face_graph_wrapper.h>
////////////////////////////////////////////////////////////////////////////////
/** This file contains the following functors for Face_graph_wrapper:
* Is_free<typename HEG, unsigned int i>::
operator() (const HEG& heg, Dart_const_handle dh)
* Get_beta<typename HEG, unsigned int i>::
operator() (const HEG& heg, Dart_const_handle dh)
*/
////////////////////////////////////////////////////////////////////////////////
namespace CGAL
{
/// Is_free
//template<typename HEG, unsigned int i>
//struct Is_free
//{
// typedef typename boost::graph_traits<HEG>::halfedge_descriptor Dart_const_handle;
// static bool value(const HEG& /*heg*/, Dart_const_handle /*dh*/)
// { CGAL_static_assertion(i==0 || i==1); return false; }
//};
//template<typename HEG>
//struct Is_free<HEG, 2>
//{
// typedef typename boost::graph_traits<HEG>::halfedge_descriptor Dart_const_handle;
// static bool value(const HEG& heg, Dart_const_handle dh)
// { return is_border(opposite(dh, heg), heg); }
//};
////////////////////////////////////////////////////////////////////////////////
/// Get_beta
template<typename HEG, unsigned int i>
struct Get_beta
{
typedef typename boost::graph_traits<HEG>::halfedge_descriptor Dart_const_handle;
static Dart_const_handle value(const HEG& /*heg*/, Dart_const_handle /*dh*/)
{ /* CGAL_static_assertion(false);*/
std::cout<<"ERROR Get_beta<HEG, "<<i<<">"<<std::endl;
CGAL_assertion(false);
return nullptr;
}
};
template<typename HEG>
struct Get_beta<HEG, 0>
{
typedef typename boost::graph_traits<HEG>::halfedge_descriptor Dart_const_handle;
static Dart_const_handle value(const HEG& heg, Dart_const_handle dh)
{ return prev(dh, heg); }
};
template<typename HEG>
struct Get_beta<HEG, 1>
{
typedef typename boost::graph_traits<HEG>::halfedge_descriptor Dart_const_handle;
static Dart_const_handle value(const HEG& heg, Dart_const_handle dh)
{ return next(dh, heg); }
};
template<typename HEG>
struct Get_beta<HEG, 2>
{
typedef typename boost::graph_traits<HEG>::halfedge_descriptor Dart_const_handle;
static Dart_const_handle value(const HEG& heg, Dart_const_handle dh)
{
//if (Is_free<HEG, 2>::value(heg, dh)) return Dart_const_handle();
return opposite(dh, heg);
}
};
////////////////////////////////////////////////////////////////////////////////
} // namespace CGAL
#endif // CGAL_FUNCTORS_FOR_FACE_GRAPH_WRAPPER_H //
// EOF //
@@ -0,0 +1,332 @@
// Copyright (c) 2019 CNRS and LIRIS' Establishments (France).
// All rights reserved.
//
// This file is part of CGAL (www.cgal.org)
//
// $URL$
// $Id$
// SPDX-License-Identifier: LGPL-3.0-or-later OR LicenseRef-Commercial
//
// Author(s) : Guillaume Damiand <guillaume.damiand@liris.cnrs.fr>
//
#ifndef CGAL_ITERATORS_FOR_FACE_GRAPH_WRAPPER_H
#define CGAL_ITERATORS_FOR_FACE_GRAPH_WRAPPER_H 1
#include <boost/graph/graph_traits.hpp>
#include <CGAL/boost/graph/helpers.h>
#include <stack>
namespace CGAL
{
//****************************************************************************
/* Class CMap_dart_iterator_basic_of_all: to iterate onto all the
* darts of the face graph.
*/
template <typename Map_,bool Const=false>
class FGW_dart_iterator_basic_of_all
{
public:
typedef FGW_dart_iterator_basic_of_all Self;
typedef Map_ Map;
typedef typename Map::Dart_handle Dart_handle;
typedef typename Map::size_type size_type;
public:
/// Main constructor.
FGW_dart_iterator_basic_of_all(const Map& amap):
mmap(amap),
m_it(halfedges(amap.get_fg()).begin())
{
/*if (m_it!=halfedges(amap.get_fg()).end() &&
is_border(*m_it, amap.get_fg()))
{ operator++(0); } */
}
/// Constructor with a dart in parameter (for end iterator).
FGW_dart_iterator_basic_of_all(const Map& amap, Dart_handle /*adart*/):
mmap(amap),
m_it(halfedges(amap.get_fg()).end())
{}
FGW_dart_iterator_basic_of_all(const FGW_dart_iterator_basic_of_all& other):
mmap(other.mmap),
m_it(other.m_it)
{}
operator Dart_handle() const
{ return operator*(); }
bool operator==(const Self& other) const
{ return &mmap==&(other.mmap) && m_it==other.m_it; }
bool operator!=(const Self& other) const
{ return !(operator==(other)); }
/// Prefix ++ operator.
Self& operator++()
{
CGAL_assertion(m_it!=halfedges(this->mmap.get_fg()).end());
//do
{
++m_it;
}
/*while(m_it!=halfedges(this->mmap.get_fg()).end() &&
is_border(*m_it, this->mmap.get_fg())); */
return *this;
}
/// Postfix ++ operator.
Self operator++(int)
{ Self res=*this; operator ++(); return res; }
Dart_handle operator*() const
{
CGAL_assertion(m_it!=halfedges(this->mmap.get_fg()).end());
return *m_it;
}
protected:
const Map& mmap;
typename boost::graph_traits<typename Map_::HEG>::halfedge_iterator m_it;
};
////////////////////////////////////////////////////////////////////////////////
template <typename Map_>
class FGW_basis_for_cell_iterator
{
public:
typedef FGW_basis_for_cell_iterator Self;
typedef Map_ Map;
typedef typename Map::Dart_handle Dart_handle;
typedef typename Map::size_type size_type;
/// Main constructor.
FGW_basis_for_cell_iterator(const Map& amap, Dart_handle adart):
mmap(amap),
m_firstdart(adart),
m_curdart(adart)
{}
/// Constructor with two darts in parameter (for end iterator).
FGW_basis_for_cell_iterator(const Map& amap, Dart_handle adart,
Dart_handle /* d2 */):
mmap(amap),
m_firstdart(adart),
m_curdart(Dart_handle())
{}
bool operator==(const Self& other) const
{ return &mmap==&(other.mmap) && m_firstdart==other.m_firstdart &&
m_curdart==other.m_curdart; }
bool operator!=(const Self& other) const
{ return !(this->operator==(other)); }
operator Dart_handle() const
{ return operator*(); }
Dart_handle operator*() const
{
CGAL_assertion(m_curdart!=Dart_handle());
return m_curdart;
}
protected:
const Map& mmap;
Dart_handle m_firstdart, m_curdart;
};
////////////////////////////////////////////////////////////////////////////////
template<typename HEG, unsigned int i>
class FGW_cell_iterator
{};
////////////////////////////////////////////////////////////////////////////////
/// Vertex iterator
template<typename Map_>
class FGW_cell_iterator<Map_, 0>: public FGW_basis_for_cell_iterator<Map_> // Vertex
{
public:
typedef FGW_cell_iterator Self;
typedef FGW_basis_for_cell_iterator<Map_> Base;
typedef Map_ Map;
typedef typename Map::Dart_handle Dart_handle;
typedef typename Map::size_type size_type;
FGW_cell_iterator(const Map& amap, Dart_handle adart) : Base(amap, adart),
m_second_way(false)
{}
/// Constructor with two darts in parameter (for end iterator).
FGW_cell_iterator(const Map& amap, Dart_handle adart,
Dart_handle d2): Base(amap, adart, d2)
{}
/// Prefix ++ operator.
Self& operator++()
{
if (!m_second_way)
{
if (this->mmap.template is_free<2>(this->m_curdart))
{
m_second_way=true;
this->m_curdart=this->mmap.template beta<0>(this->m_firstdart);
if (this->mmap.template is_free<2>(this->m_curdart))
{ this->m_curdart=Dart_handle(); }
else { this->m_curdart=this->mmap.template beta<2>(this->m_curdart); }
}
else
{
this->m_curdart=this->mmap.template beta<2, 1>(this->m_curdart);
if (this->m_curdart==this->m_firstdart)
{ this->m_curdart=Dart_handle(); }
}
}
else
{
this->m_curdart=this->mmap.template beta<0>(this->m_curdart);
if (this->mmap.template is_free<2>(this->m_curdart))
{ this->m_curdart=Dart_handle(); }
else { this->m_curdart=this->mmap.template beta<2>(this->m_curdart); }
}
return *this;
}
/// Postfix ++ operator.
Self operator++(int)
{ Self res=*this; operator ++(); return res; }
protected:
/// True if we already found a border dart, and thus turn in the second way
bool m_second_way;
};
template<typename Map_>
class FGW_cell_iterator<Map_, 1>: public FGW_basis_for_cell_iterator<Map_> // Edge
{
public:
typedef FGW_cell_iterator Self;
typedef FGW_basis_for_cell_iterator<Map_> Base;
typedef Map_ Map;
typedef typename Map::Dart_handle Dart_handle;
typedef typename Map::size_type size_type;
FGW_cell_iterator(const Map& amap, Dart_handle adart) : Base(amap, adart)
{}
/// Constructor with two darts in parameter (for end iterator).
FGW_cell_iterator(const Map& amap, Dart_handle adart,
Dart_handle d2): Base(amap, adart, d2)
{}
/// Prefix ++ operator.
Self& operator++()
{
if (this->m_curdart==this->m_firstdart)
{
if (this->mmap.template is_free<2>(this->m_curdart))
{ this->m_curdart=Dart_handle(); }
else { this->m_curdart=this->mmap.template beta<2>(this->m_curdart); }
}
else
{ this->m_curdart=Dart_handle(); }
return *this;
}
/// Postfix ++ operator.
Self operator++(int)
{ Self res=*this; operator ++(); return res; }
};
template<typename Map_>
class FGW_cell_iterator<Map_, 2>: public FGW_basis_for_cell_iterator<Map_> // Face
{
public:
typedef FGW_cell_iterator Self;
typedef FGW_basis_for_cell_iterator<Map_> Base;
typedef Map_ Map;
typedef typename Map::Dart_handle Dart_handle;
typedef typename Map::size_type size_type;
FGW_cell_iterator(const Map& amap, Dart_handle adart) : Base(amap, adart)
{}
/// Constructor with two darts in parameter (for end iterator).
FGW_cell_iterator(const Map& amap, Dart_handle adart,
Dart_handle d2): Base(amap, adart, d2)
{}
/// Prefix ++ operator.
Self& operator++()
{
this->m_curdart=this->mmap.template beta<1>(this->m_curdart);
if (this->m_curdart==this->m_firstdart)
{ this->m_curdart=Dart_handle(); }
return *this;
}
/// Postfix ++ operator.
Self operator++(int)
{ Self res=*this; operator ++(); return res; }
};
template<typename Map_>
class FGW_cell_iterator<Map_, 3>: public FGW_basis_for_cell_iterator<Map_> // CC
{
public:
typedef FGW_cell_iterator Self;
typedef FGW_basis_for_cell_iterator<Map_> Base;
typedef Map_ Map;
typedef typename Map::Dart_handle Dart_handle;
typedef typename Map::size_type size_type;
FGW_cell_iterator(const Map& amap, Dart_handle adart) : Base(amap, adart)
{ m_mark=this->mmap.get_new_mark(); }
/// Constructor with two darts in parameter (for end iterator).
FGW_cell_iterator(const Map& amap, Dart_handle adart,
Dart_handle d2): Base(amap, adart, d2)
{ m_mark=this->mmap.get_new_mark(); }
~FGW_cell_iterator()
{ this->mmap.free_mark(m_mark); }
/// Prefix ++ operator.
Self& operator++()
{
if (!this->mmap.is_marked(this->mmap.template beta<1>(this->m_curdart), m_mark))
{
m_to_treat.push(this->mmap.template beta<1>(this->m_curdart));
this->mmap.mark(this->mmap.template beta<1>(this->m_curdart), m_mark);
}
if (!this->mmap.template is_free<2>(this->m_curdart) &&
!this->mmap.is_marked(this->mmap.template beta<2>(this->m_curdart), m_mark))
{
m_to_treat.push(this->mmap.template beta<2>(this->m_curdart));
this->mmap.mark(this->mmap.template beta<2>(this->m_curdart), m_mark);
}
if (m_to_treat.empty())
{ this->m_curdart=Dart_handle(); }
else
{ this->m_curdart=m_to_treat.top(); m_to_treat.pop(); }
return *this;
}
/// Postfix ++ operator.
Self operator++(int)
{ Self res=*this; operator ++(); return res; }
protected:
typename Map_::size_type m_mark;
std::stack<Dart_handle> m_to_treat;
};
////////////////////////////////////////////////////////////////////////////////
} // namespace CGAL
#endif // CGAL_ITERATORS_FOR_FACE_GRAPH_WRAPPER_H //
// EOF //
@@ -1,5 +1,6 @@
Algebraic_foundations
Arithmetic_kernel
BGL
Cartesian_kernel
Circulator
Combinatorial_map
@@ -17,5 +18,7 @@ Kernel_d
Modular_arithmetic
Number_types
Profiling_tools
Property_map
STL_Extension
Stream_support
Random_numbers
@@ -16,6 +16,11 @@ if ( CGAL_FOUND )
create_single_source_cgal_program( "${cppfile}" )
endforeach()
find_package( OpenMesh QUIET )
if (TARGET OpenMesh::OpenMesh)
target_link_libraries(Combinatorial_map_copy_test PRIVATE OpenMesh::OpenMesh)
endif()
else()
message(STATUS "This program requires the CGAL library, and will not be compiled.")
@@ -1,6 +1,13 @@
#include <CGAL/Combinatorial_map.h>
#include <CGAL/Cell_attribute.h>
#include "Combinatorial_map_test_iterators.h"
#include <CGAL/HalfedgeDS_default.h>
#if CGAL_USE_OPENMESH
# include <OpenMesh/Core/IO/MeshIO.hh>
# include <OpenMesh/Core/Mesh/TriMesh_ArrayKernelT.hh>
# include <CGAL/boost/graph/graph_traits_TriMesh_ArrayKernelT.h>
typedef OpenMesh::TriMesh_ArrayKernelT</* MyTraits*/> OpenMesh_mesh;
#endif // CGAL_USE_OPENMESH
#include <iostream>
#include <fstream>
@@ -152,6 +159,10 @@ typedef CGAL::Combinatorial_map<4, Map_dart_items_4> Map8;
// info=char, int, int, int, int, double
typedef CGAL::Combinatorial_map<4, Map_dart_max_items_4> Map9;
struct Traits { typedef int Point_2; typedef int Point_3; };
typedef CGAL::HalfedgeDS_default<Traits> HDS;
////////////////////////////////////////////////////////////////////////////////
template<typename Map, unsigned int i, typename Attr=typename Map::
template Attribute_type<i>::type>
struct CreateAttributes
@@ -579,6 +590,31 @@ bool testCopy()
return true;
}
bool testImportFromHalfedge()
{
bool res=true;
HDS hds;
CGAL::HalfedgeDS_decorator<HDS> decorator(hds);
decorator.create_loop();
decorator.create_segment();
Map1 map1; map1.import_from_halfedge_graph(hds);
Map2 map2; map2.import_from_halfedge_graph(hds);
Map3 map3; map3.import_from_halfedge_graph(hds);
#if CGAL_USE_OPENMESH
{
// test the compilation, with an empty mesh
OpenMesh_mesh hds;
Map1 map1; map1.import_from_halfedge_graph(hds);
Map2 map2; map2.import_from_halfedge_graph(hds);
Map3 map3; map3.import_from_halfedge_graph(hds);
}
#endif // CGAL_USE_OPENMESH
return res; // TODO compare number of darts/cells
}
int main()
{
std::cout<<"Combinatorial map copy test (v1)."<<std::flush;
@@ -1,5 +1,10 @@
#include <CGAL/Combinatorial_map.h>
#include <CGAL/Cell_attribute.h>
#include <CGAL/Face_graph_wrapper.h>
#include <CGAL/Simple_cartesian.h>
#include <CGAL/Surface_mesh.h>
#include <CGAL/Polyhedron_3.h>
#include <CGAL/IO/Polyhedron_iostream.h>
#include "Combinatorial_map_2_test.h"
#include "Combinatorial_map_3_test.h"
@@ -193,8 +198,64 @@ bool test_get_new_mark()
return true;
}
bool test_face_graph_wrapper()
{
bool res=true;
typedef CGAL::Surface_mesh<CGAL::Simple_cartesian<double>::Point_3> SMesh;
SMesh m;
std::ifstream in1("data/head.off");
if (in1.fail())
{
std::cout<<"Error: impossible to open 'data/head.off'"<<std::endl;
return false;
}
in1>>m;
CGAL::Face_graph_wrapper<SMesh> fgw1(m);
std::vector<unsigned int> cells=fgw1.count_all_cells();
if (cells[0]!=1487 || cells[1]!=4406 || cells[2]!=2921 ||
fgw1.number_of_darts()!=8812)
{
std::cout<<"Error: incorrect number of cells in test_face_graph_wrapper "
<<"for Surface_mesh: "
<<cells[0]<<", "<<cells[1]<<", "<<cells[2]<<", "<<fgw1.number_of_darts()
<<std::endl;
res=false;
}
typedef CGAL::Polyhedron_3<CGAL::Simple_cartesian<double> > Polyhedron;
Polyhedron p;
std::ifstream in2("data/head.off");
if (in2.fail())
{
std::cout<<"Error: impossible to open 'data/head.off'"<<std::endl;
return false;
}
in2>>p;
CGAL::Face_graph_wrapper<Polyhedron> fgw2(p);
cells=fgw2.count_all_cells();
if (cells[0]!=1487 || cells[1]!=4406 || cells[2]!=2921 ||
fgw2.number_of_darts()!=8812)
{
std::cout<<"Error: incorrect number of cells in test_face_graph_wrapper "
<<"for Polyhedron."
<<cells[0]<<", "<<cells[1]<<", "<<cells[2]<<", "<<fgw2.number_of_darts()
<<std::endl;
res=false;
}
return res;
}
int main()
{
if (!test_face_graph_wrapper())
{
std::cout<<"ERROR during test_face_graph_wrapper."<<std::endl;
return EXIT_FAILURE;
}
if ( !test_get_new_mark() )
{
std::cout<<"ERROR during test_get_new_mark."<<std::endl;
File diff suppressed because it is too large Load Diff
@@ -12,12 +12,12 @@ cyclic sequence of extreme points is cut into a linear sequence.
\pre The source range [`first`,`beyond`) does not contain `result`.
The default traits class `Default_traits` is the kernel in which the
value type of `InputIterator` is defined.
value type of `ForwardIterator` is defined.
\cgalHeading{Requirements}
<OL>
<LI>The value type of `InputIterator` and
<LI>The value type of `ForwardIterator` and
`OutputIterator` is equivalent to `Traits::Point_2`.
<LI>`Traits` defines the following subset of types from
the concept `ConvexHullTraits_2` and their corresponding member
@@ -46,10 +46,10 @@ in the worst case for \f$ n\f$ input points with \f$ h\f$ extreme points.
*/
template <class InputIterator, class OutputIterator, class Traits>
template <class ForwardIterator, class OutputIterator, class Traits>
OutputIterator
ch_jarvis( InputIterator first,
InputIterator beyond,
ch_jarvis( ForwardIterator first,
ForwardIterator beyond,
OutputIterator result,
const Traits & ch_traits = Default_traits);
@@ -21,7 +21,7 @@ is a kernel with exact predicates but inexact constructions
(in practice we check `R::Has_filtered_predicates_tag` is `Tag_true` and `R::FT` is a floating point type),
then the default traits class of `::convex_hull_3()` is `Convex_hull_traits_3<R>`, and `R` otherwise.
\attention The user must include the header file of the `Polygon_mesh` type.
\attention The user must include the header file of the `PolygonMesh` type.
\cgalHeading{Implementation}
@@ -34,6 +34,36 @@ Barnard <I>et al.</I> \cgalCite{bdh-qach-96}.
template <class InputIterator, class PolygonMesh, class Traits>
void convex_hull_3(InputIterator first, InputIterator last, PolygonMesh& pm, const Traits& ch_traits = Default_traits);
/*!
\ingroup PkgConvexHull3Functions
* \brief computes the convex hull of the points associated to the vertices of `g`.
* The polygon mesh `pm` is cleared, then
* the convex hull is stored in `pm`. Note that the convex hull will be triangulated,
* that is `pm` will contain only triangular faces.
* if the convex hull is a point or a segment, endpoints will be added in `pm` as isolated vertices.
*
* \tparam VertexListGraph a model of `VertexListGraph`.
* \tparam PolygonMesh must be a model of `MutableFaceGraph`.
* \tparam NamedParameters a sequence of named parameters
*
* \param g the graph
* \param pm the `PolygonMesh` that will contain the convex hull
* \param np optional sequence of named parameters among the ones listed below
*
* \cgalNamedParamsBegin
* \cgalParamBegin{vertex_point_map} the property map with the points associated to the vertices of `g`.
* If this parameter is omitted, an internal property map for
* `CGAL::vertex_point_t` must be available in `VertexListGraph`
* \cgalParamEnd
* \cgalNamedParamsEnd
* \attention The user must include the header file of the `PolygonMesh` and `VertexListGraph` types.
*/
template <class VertexListGraph, class PolygonMesh, class NamedParameters>
void convex_hull_3(const VertexListGraph& g,
PolygonMesh& pm,
const NamedParameters& np);
/*!
\ingroup PkgConvexHull3Functions
@@ -47,7 +77,7 @@ that is the polygon mesh will contain only triangular facets.
\tparam Traits must be model of the concept `ConvexHullTraits_3`.
For the purposes of checking the postcondition that the convex hull
is valid, `Traits` must also be a model of the concept
`IsStronglyConvexTraits_3`. Furthermore, `Traits` must define a type `Polygon_mesh` that is a model of
`IsStronglyConvexTraits_3`. Furthermore, `Traits` must define a type `PolygonMesh` that is a model of
`MutableFaceGraph`.
If the kernel `R` of the points determined by the value type of `InputIterator`
@@ -55,7 +85,7 @@ is a kernel with exact predicates but inexact constructions
(in practice we check `R::Has_filtered_predicates_tag` is `Tag_true` and `R::FT` is a floating point type),
then the default traits class of `convex_hull_3()` is `Convex_hull_traits_3<R>`, and `R` otherwise.
\attention The user must include the header file of the `Polygon_mesh` type.
\attention The user must include the header file of the `PolygonMesh` type.
*/
template <class InputIterator, class Traits>
@@ -1,3 +1,9 @@
@INCLUDE = ${CGAL_DOC_PACKAGE_DEFAULTS}
PROJECT_NAME = "CGAL ${CGAL_DOC_VERSION} - 3D Convex Hulls"
\# macros to be used inside the code
ALIASES += "cgalNamedParamsBegin=<dl class=\"params\"><dt>Named Parameters</dt><dd> <table class=\"params\">"
ALIASES += "cgalNamedParamsEnd=</table> </dd> </dl>"
ALIASES += "cgalParamBegin{1}=<tr><td class=\"paramname\">\ref BGL_\1 \"\1\"</td><td>"
ALIASES += "cgalParamEnd=</td></tr>"

Some files were not shown because too many files have changed in this diff Show More