mirror of https://github.com/CGAL/cgal
Merge remote-tracking branch 'cgal/master' into Polyhedron-demo__add_qtscript_support_to_Mesh_3_plugin-GF
This commit is contained in:
commit
f17d903d75
|
|
@ -1,6 +1,6 @@
|
|||
name: CMake all CGAL
|
||||
|
||||
on: [push]
|
||||
on: [push, pull_request]
|
||||
|
||||
jobs:
|
||||
build:
|
||||
|
|
@ -8,9 +8,7 @@ jobs:
|
|||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v1
|
||||
with:
|
||||
fetch-depth: 0
|
||||
- uses: actions/checkout@v2.0.0
|
||||
- name: install dependencies
|
||||
run: sudo apt-get install -y libboost-dev libboost-program-options-dev libmpfr-dev libeigen3-dev
|
||||
- name: configure all
|
||||
|
|
|
|||
10
.travis.yml
10
.travis.yml
|
|
@ -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"
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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:
|
||||
/// @{
|
||||
|
||||
/*!
|
||||
|
|
|
|||
|
|
@ -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 ) {
|
||||
|
||||
while ( CGAL::compare(tt, s0) == LARGER )
|
||||
{
|
||||
p.insert( p.begin(), f(tt) );
|
||||
k--;
|
||||
--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 ) {
|
||||
while ( CGAL::compare(tt, s1) == SMALLER )
|
||||
{
|
||||
p.push_back( f(tt) );
|
||||
k++;
|
||||
++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 )
|
||||
do
|
||||
{
|
||||
p.push_back( f(tt) );
|
||||
k++;
|
||||
++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 )
|
||||
do
|
||||
{
|
||||
p.push_back( f(tt) );
|
||||
k--;
|
||||
--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,101 @@ 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);
|
||||
CGAL_precondition(s0 < s1);
|
||||
|
||||
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 ) {
|
||||
// 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--;
|
||||
--k;
|
||||
tt = - FT(k * k) * STEP;
|
||||
}
|
||||
p.insert( p.begin(), f(s0) );
|
||||
|
||||
k = 1;
|
||||
tt = STEP;
|
||||
while ( CGAL::compare(tt, s1) == SMALLER ) {
|
||||
|
||||
// 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++;
|
||||
++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 )
|
||||
do
|
||||
{
|
||||
p.push_back( f(tt) );
|
||||
k++;
|
||||
++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 )
|
||||
do
|
||||
{
|
||||
p.push_back( f(tt) );
|
||||
k--;
|
||||
--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
|
||||
|
|
|
|||
|
|
@ -112,7 +112,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
|
||||
|
|
|
|||
|
|
@ -82,6 +82,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)
|
||||
|
|
|
|||
|
|
@ -578,7 +578,7 @@ 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 )
|
||||
{
|
||||
|
|
@ -600,7 +600,7 @@ void expand_face_selection_for_removal(const FaceRange& faces_to_be_deleted,
|
|||
break;
|
||||
next_around_vertex = opposite( next(next_around_vertex, tm), tm);
|
||||
}
|
||||
while( get(is_selected, face(next_around_vertex, tm) ) );
|
||||
while(is_border(next_around_vertex,tm) || get(is_selected, face(next_around_vertex, tm) ) );
|
||||
|
||||
if (next_around_vertex==start)
|
||||
break;
|
||||
|
|
|
|||
|
|
@ -91,6 +91,9 @@ 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);
|
||||
|
||||
// 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 +178,9 @@ 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));
|
||||
|
||||
// Named parameters that we use in the package 'Surface Mesh Simplification'
|
||||
check_same_type<34>(get_parameter(np, CGAL::internal_np::get_cost_policy));
|
||||
|
|
@ -265,6 +271,9 @@ 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))
|
||||
);
|
||||
|
||||
return EXIT_SUCCESS;
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
template <unsigned int d2, typename Refs2, typename Items2, typename Alloc2,
|
||||
typename Storage2,
|
||||
typename Converters, typename DartInfoConverter,
|
||||
typename PointConverter>
|
||||
Combinatorial_map_base(const CMap2& amap, Converters& converters,
|
||||
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.
|
||||
|
|
|
|||
|
|
@ -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
|
|
@ -102,3 +102,5 @@ Classification
|
|||
Hyperbolic_triangulation_2
|
||||
Periodic_4_hyperbolic_triangulation_2
|
||||
Surface_mesh_approximation
|
||||
Surface_mesh_topology
|
||||
|
||||
|
|
|
|||
|
|
@ -119,6 +119,7 @@
|
|||
\package_listing{Stream_lines_2}
|
||||
\package_listing{Classification}
|
||||
\package_listing{Heat_method_3}
|
||||
\package_listing{Surface_mesh_topology}
|
||||
|
||||
\cgalPackageSection{PartSearchStructures,Spatial Searching and Sorting}
|
||||
|
||||
|
|
|
|||
|
|
@ -152023,3 +152023,21 @@ pages = {179--189}
|
|||
HAL_ID = {inria-00412437},
|
||||
HAL_VERSION = {v1},
|
||||
}
|
||||
|
||||
@InProceedings{ew-tcsr-13,
|
||||
Title = {Transforming curves on surfaces redux},
|
||||
Author = {Erickson, Jeff and Whittelsey, Kim},
|
||||
Booktitle = {24rd Annual ACM-SIAM Symposium on Discrete Algorithms (SODA)},
|
||||
Year = {2013},
|
||||
Pages = {1646--1655},
|
||||
Url = {http://jeffe.cs.illinois.edu/pubs/pdf/dehn.pdf}
|
||||
}
|
||||
|
||||
@InProceedings{lr-hts-12,
|
||||
Title = {On the homotopy test on surfaces},
|
||||
Author = {Lazarus, Francis and Rivaud, Julien},
|
||||
Booktitle = {53rd Annual IEEE Symposium on Foundations of Computer Science (FOCS)},
|
||||
Year = {2012},
|
||||
Pages = {440-449},
|
||||
Url = {http://arxiv.org/abs/1110.4573}
|
||||
}
|
||||
|
|
@ -339,3 +339,9 @@ div.fragment {
|
|||
padding: 4px;
|
||||
margin: 1em 4px 1em 4px;
|
||||
}
|
||||
|
||||
/* Make summary smaller to avoid wrapping of classes and concepts */
|
||||
div.summary
|
||||
{
|
||||
width: auto;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -339,3 +339,9 @@ div.fragment {
|
|||
padding: 4px;
|
||||
margin: 1em 4px 1em 4px;
|
||||
}
|
||||
|
||||
/* Make summary smaller to avoid wrapping of classes and concepts */
|
||||
div.summary
|
||||
{
|
||||
width: auto;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -329,3 +329,10 @@ div.fragment {
|
|||
padding: 4px;
|
||||
margin: 1em 4px 1em 4px;
|
||||
}
|
||||
|
||||
|
||||
/* Make summary smaller to avoid wrapping of classes and concepts */
|
||||
div.summary
|
||||
{
|
||||
width: auto;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -181,13 +181,22 @@ namespace CGAL {
|
|||
* @param amap the generalized map to copy.
|
||||
* @post *this is valid.
|
||||
*/
|
||||
template <typename GMap2, 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 GMap2& amap, const Converters& converters,
|
||||
void copy(const Generalized_map_base<d2, Refs2, Items2, Alloc2, Storage2>& amap,
|
||||
const Converters& converters,
|
||||
const DartInfoConverter& dartinfoconverter,
|
||||
const PointConverter& pointconverter,
|
||||
boost::unordered_map<typename GMap2::Dart_const_handle, Dart_handle>* dart_mapping=nullptr)
|
||||
boost::unordered_map
|
||||
<typename Generalized_map_base<d2, Refs2, Items2, Alloc2, Storage2>::
|
||||
Dart_const_handle, Dart_handle>* origin_to_copy=NULL,
|
||||
boost::unordered_map
|
||||
<Dart_handle, typename Generalized_map_base<d2, Refs2, Items2,
|
||||
Alloc2, Storage2>::Dart_const_handle>* copy_to_origin=NULL)
|
||||
{
|
||||
typedef Generalized_map_base<d2, Refs2, Items2, Alloc2, Storage2> GMap2;
|
||||
this->clear();
|
||||
|
||||
this->mnb_used_marks = amap.mnb_used_marks;
|
||||
|
|
@ -207,107 +216,145 @@ 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 GMap2::Dart_const_handle, Dart_handle> local_dartmap;
|
||||
if (dart_mapping==nullptr)
|
||||
{ dart_mapping=&local_dartmap; }
|
||||
|
||||
boost::unordered_map<typename GMap2::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 GMap2::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<GMap2, 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 GMap2::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.alpha(dartmap_iter->first,i)))
|
||||
is_free(dartmap_iter->second,i))
|
||||
{
|
||||
basic_link_alpha(dartmap_iter->second,
|
||||
(*dart_mapping)[amap.alpha(dartmap_iter->first,i)], i);
|
||||
(*origin_to_copy)[amap.alpha(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 <GMap2, 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 GMap2>
|
||||
void copy(const GMap2& amap,
|
||||
boost::unordered_map<typename GMap2::Dart_const_handle, Dart_handle>* dart_mapping=nullptr)
|
||||
template <unsigned int d2, typename Refs2, typename Items2, typename Alloc2,
|
||||
typename Storage2>
|
||||
void copy(const Generalized_map_base<d2, Refs2, Items2, Alloc2, Storage2>& amap,
|
||||
boost::unordered_map
|
||||
<typename Generalized_map_base<d2, Refs2, Items2, Alloc2, Storage2>::
|
||||
Dart_const_handle, Dart_handle>* origin_to_copy=NULL,
|
||||
boost::unordered_map
|
||||
<Dart_handle, typename Generalized_map_base<d2, Refs2, Items2,
|
||||
Alloc2, Storage2>::Dart_const_handle>* copy_to_origin=NULL)
|
||||
{
|
||||
std::tuple<> converters;
|
||||
Default_converter_dart_info<GMap2, Refs> dartinfoconverter;
|
||||
Default_converter_cmap_0attributes_with_point<GMap2, 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 GMap2, typename Converters>
|
||||
void copy(const GMap2& amap, const Converters& converters,
|
||||
boost::unordered_map<typename GMap2::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 Generalized_map_base<d2, Refs2, Items2, Alloc2, Storage2>& amap,
|
||||
const Converters& converters,
|
||||
boost::unordered_map
|
||||
<typename Generalized_map_base<d2, Refs2, Items2, Alloc2, Storage2>::
|
||||
Dart_const_handle, Dart_handle>* origin_to_copy=NULL,
|
||||
boost::unordered_map
|
||||
<Dart_handle, typename Generalized_map_base<d2, Refs2, Items2,
|
||||
Alloc2, Storage2>::Dart_const_handle>* copy_to_origin=NULL)
|
||||
{
|
||||
Default_converter_cmap_0attributes_with_point<GMap2, Refs> pointconverter;
|
||||
Default_converter_dart_info<GMap2, 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 GMap2, typename Converters, typename DartInfoConverter>
|
||||
void copy(const GMap2& amap, const Converters& converters,
|
||||
template <unsigned int d2, typename Refs2, typename Items2, typename Alloc2,
|
||||
typename Storage2,
|
||||
typename Converters, typename DartInfoConverter>
|
||||
void copy(const Generalized_map_base<d2, Refs2, Items2, Alloc2, Storage2>& amap,
|
||||
const Converters& converters,
|
||||
const DartInfoConverter& dartinfoconverter,
|
||||
boost::unordered_map<typename GMap2::Dart_const_handle, Dart_handle>* dart_mapping=nullptr)
|
||||
boost::unordered_map
|
||||
<typename Generalized_map_base<d2, Refs2, Items2, Alloc2, Storage2>::
|
||||
Dart_const_handle, Dart_handle>* origin_to_copy=NULL,
|
||||
boost::unordered_map
|
||||
<Dart_handle, typename Generalized_map_base<d2, Refs2, Items2,
|
||||
Alloc2, Storage2>::Dart_const_handle>* copy_to_origin=NULL)
|
||||
{
|
||||
Default_converter_cmap_0attributes_with_point<GMap2, 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.
|
||||
Generalized_map_base (const Self & amap)
|
||||
{ copy<Self>(amap); }
|
||||
|
||||
// "Copy constructor" from a map having different type.
|
||||
template <typename GMap2>
|
||||
Generalized_map_base(const GMap2& amap)
|
||||
{ copy(amap); }
|
||||
|
||||
// "Copy constructor" from a map having different type.
|
||||
template <typename GMap2, typename Converters>
|
||||
Generalized_map_base(const GMap2& amap, Converters& converters)
|
||||
template <unsigned int d2, typename Refs2, typename Items2, typename Alloc2,
|
||||
typename Storage2>
|
||||
Generalized_map_base(const Generalized_map_base<d2, Refs2, Items2, Alloc2, Storage2>& amap)
|
||||
{ copy(amap); }
|
||||
|
||||
// "Copy constructor" from a map having different type.
|
||||
template <unsigned int d2, typename Refs2, typename Items2, typename Alloc2,
|
||||
typename Storage2, typename Converters>
|
||||
Generalized_map_base(const Generalized_map_base<d2, Refs2, Items2, Alloc2, Storage2>& amap,
|
||||
const Converters& converters)
|
||||
{ copy(amap, converters); }
|
||||
|
||||
// "Copy constructor" from a map having different type.
|
||||
template <typename GMap2, typename Converters, typename DartInfoConverter>
|
||||
Generalized_map_base(const GMap2& amap, Converters& converters,
|
||||
template <unsigned int d2, typename Refs2, typename Items2, typename Alloc2,
|
||||
typename Storage2,
|
||||
typename Converters, typename DartInfoConverter>
|
||||
Generalized_map_base(const Generalized_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 GMap2, typename Converters, typename DartInfoConverter,
|
||||
template <unsigned int d2, typename Refs2, typename Items2, typename Alloc2,
|
||||
typename Storage2,
|
||||
typename Converters, typename DartInfoConverter,
|
||||
typename PointConverter>
|
||||
Generalized_map_base(const GMap2& amap, Converters& converters,
|
||||
Generalized_map_base(const Generalized_map_base<d2, Refs2, Items2, Alloc2, Storage2>& amap,
|
||||
const Converters& converters,
|
||||
const DartInfoConverter& dartinfoconverter,
|
||||
const PointConverter& pointconverter)
|
||||
{ copy(amap, converters, dartinfoconverter, pointconverter); }
|
||||
|
|
@ -579,6 +626,11 @@ namespace CGAL {
|
|||
Dart_const_handle next(Dart_const_handle ADart) const
|
||||
{ return this->template alpha<0, 1>(ADart); }
|
||||
|
||||
Dart_handle opposite2(Dart_handle ADart)
|
||||
{ return this->template alpha<0, 2>(ADart); }
|
||||
Dart_const_handle opposite2(Dart_const_handle ADart) const
|
||||
{ return this->template alpha<0, 2>(ADart); }
|
||||
|
||||
template<unsigned int dim>
|
||||
Dart_handle opposite(Dart_handle ADart)
|
||||
{ return this->template alpha<0, dim>(ADart); }
|
||||
|
|
@ -849,6 +901,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.
|
||||
|
|
@ -1647,6 +1720,61 @@ namespace CGAL {
|
|||
}
|
||||
|
||||
public:
|
||||
/// @return the positive turn between the two given darts.
|
||||
// @pre next(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->next(d1), d2))); */
|
||||
|
||||
if (d2==opposite2(d1)) { return 0; }
|
||||
|
||||
Dart_const_handle dd1=d1;
|
||||
std::size_t res=1;
|
||||
while (next(dd1)!=d2)
|
||||
{
|
||||
if (this->template is_free<2>(next(dd1)))
|
||||
{ return std::numeric_limits<std::size_t>::max(); }
|
||||
|
||||
++res;
|
||||
dd1=opposite2(next(dd1));
|
||||
|
||||
CGAL_assertion(!this->template is_free<1>(dd1));
|
||||
CGAL_assertion(next(dd1)==d2 || dd1!=d1);
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
/// @return the negative turn between the two given darts.
|
||||
// @pre next(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->next(d1), d2))); */
|
||||
|
||||
if (d2==opposite2(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=opposite2(d1);
|
||||
d2=opposite2(d2);
|
||||
Dart_const_handle dd1=d1;
|
||||
std::size_t res=1;
|
||||
while (previous(dd1)!=d2)
|
||||
{
|
||||
if (this->template is_free<2>(previous(dd1)))
|
||||
{ return std::numeric_limits<std::size_t>::max(); }
|
||||
|
||||
++res;
|
||||
dd1=opposite2(previous(dd1));
|
||||
|
||||
CGAL_assertion(!this->template is_free<0>(dd1));
|
||||
CGAL_assertion(previous(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
|
||||
|
|
@ -1666,7 +1794,7 @@ namespace CGAL {
|
|||
if (is_marked(d, amark))
|
||||
{
|
||||
for ( i = 0; i <= dimension; ++i)
|
||||
{ if (!is_free(d, i)) unlink_beta(d, i); }
|
||||
{ if (!is_free(d, i)) topo_unsew(d, i); }
|
||||
erase_dart(d); ++res;
|
||||
}
|
||||
}
|
||||
|
|
@ -2766,12 +2894,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 ( alpha(d1, 0,1,2)!=alpha(d3,1) ||
|
||||
alpha(d4, 1,2)!=alpha(d3,0,1) ||
|
||||
|
|
@ -2847,21 +2975,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 ( alpha(d1,2) !=alpha(d4,1,0,1) ||
|
||||
|
|
@ -3020,7 +3148,7 @@ namespace CGAL {
|
|||
return alpha<0, 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.
|
||||
* @return A dart incident to the new vertex.
|
||||
|
|
@ -3341,14 +3469,14 @@ namespace CGAL {
|
|||
if (prec!=null_handle)
|
||||
{
|
||||
// prec and *it must belong to the same vertex of the same volume
|
||||
if ( !CGAL::belong_to_same_cell<Self, 0, 2>(*this, prec, *it) )
|
||||
if ( !belong_to_same_cell<0, 2>(prec, *it) )
|
||||
return false;
|
||||
}
|
||||
prec = this->template alpha<0>(*it);
|
||||
}
|
||||
|
||||
// The path must be closed.
|
||||
if (!CGAL::belong_to_same_cell<Self, 0, 2>(*this, prec, *afirst))
|
||||
if (!belong_to_same_cell<0, 2>(prec, *afirst))
|
||||
return false;
|
||||
|
||||
return true;
|
||||
|
|
@ -3589,24 +3717,34 @@ namespace CGAL {
|
|||
Generalized_map(const Self & amap) : Base(amap)
|
||||
{}
|
||||
|
||||
template < class Gmap >
|
||||
Generalized_map(const Gmap & amap) : Base(amap)
|
||||
template <unsigned int d2, typename Refs2, typename Items2, typename Alloc2,
|
||||
typename Storage2>
|
||||
Generalized_map(const Generalized_map_base<d2, Refs2, Items2, Alloc2, Storage2>& amap) :
|
||||
Base(amap)
|
||||
{}
|
||||
|
||||
template < class Gmap, typename Converters >
|
||||
Generalized_map(const Gmap & amap, const Converters& converters) :
|
||||
template <unsigned int d2, typename Refs2, typename Items2, typename Alloc2,
|
||||
typename Storage2, typename Converters>
|
||||
Generalized_map(const Generalized_map_base<d2, Refs2, Items2, Alloc2, Storage2>& amap,
|
||||
const Converters& converters) :
|
||||
Base(amap, converters)
|
||||
{}
|
||||
|
||||
template < class Gmap, typename Converters, typename DartInfoConverter >
|
||||
Generalized_map(const Gmap & amap, const Converters& converters,
|
||||
template <unsigned int d2, typename Refs2, typename Items2, typename Alloc2,
|
||||
typename Storage2,
|
||||
typename Converters, typename DartInfoConverter>
|
||||
Generalized_map(const Generalized_map_base<d2, Refs2, Items2, Alloc2, Storage2>& amap,
|
||||
const Converters& converters,
|
||||
const DartInfoConverter& dartinfoconverter) :
|
||||
Base(amap, converters, dartinfoconverter)
|
||||
{}
|
||||
|
||||
template < class Gmap, typename Converters, typename DartInfoConverter,
|
||||
template <unsigned int d2, typename Refs2, typename Items2, typename Alloc2,
|
||||
typename Storage2,
|
||||
typename Converters, typename DartInfoConverter,
|
||||
typename PointConverter >
|
||||
Generalized_map(const Gmap & amap, const Converters& converters,
|
||||
Generalized_map(const Generalized_map_base<d2, Refs2, Items2, Alloc2, Storage2>& amap,
|
||||
const Converters& converters,
|
||||
const DartInfoConverter& dartinfoconverter,
|
||||
const PointConverter& pointconverter) :
|
||||
Base(amap, converters, dartinfoconverter, pointconverter)
|
||||
|
|
|
|||
|
|
@ -123,6 +123,8 @@ namespace CGAL {
|
|||
CGAL_assertion(i <= dimension);
|
||||
return dh->mf[i]==dh;
|
||||
}
|
||||
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,
|
||||
|
|
|
|||
|
|
@ -406,8 +406,8 @@ public:
|
|||
|
||||
if (m_points_of_face.size()<3)
|
||||
{
|
||||
std::cerr<<"PB: you try to triangulate a face with "<<m_points_of_face.size()<<" vertices."
|
||||
<<std::endl;
|
||||
/* std::cerr<<"PB: you try to triangulate a face with "<<m_points_of_face.size()<<" vertices."
|
||||
<<std::endl; */
|
||||
|
||||
m_face_started=false;
|
||||
m_points_of_face.clear();
|
||||
|
|
@ -526,6 +526,7 @@ public:
|
|||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
CGAL::Bbox_3 *bb() const { return m_bb; }
|
||||
|
||||
protected:
|
||||
|
|
|
|||
|
|
@ -1223,6 +1223,7 @@ protected:
|
|||
setKeyDescription(::Qt::Key_M, "Toggles mono color");
|
||||
setKeyDescription(::Qt::Key_N, "Inverse direction of normals");
|
||||
setKeyDescription(::Qt::Key_T, "Toggles text display");
|
||||
setKeyDescription(::Qt::Key_U, "Move camera direction upside down");
|
||||
setKeyDescription(::Qt::Key_V, "Toggles vertices display");
|
||||
setKeyDescription(::Qt::Key_Plus, "Increase size of edges");
|
||||
setKeyDescription(::Qt::Key_Minus, "Decrease size of edges");
|
||||
|
|
@ -1305,6 +1306,30 @@ protected:
|
|||
negate_all_normals();
|
||||
redraw();
|
||||
}
|
||||
else if ((e->key()==::Qt::Key_U) && (modifiers==::Qt::NoButton))
|
||||
{
|
||||
if (is_two_dimensional())
|
||||
{
|
||||
displayMessage(QString("Move camera direction upside down."));
|
||||
/* CGAL::qglviewer::Vec cur=camera()->viewDirection();
|
||||
double cx=cur.x, cy=cur.y, cz=cur.z;
|
||||
if (has_zero_x()) { cx=-cx; }
|
||||
else if (has_zero_y()) { cy=-cy; }
|
||||
else { cz=-cz; }
|
||||
double cx=0., cy=0., cz=0.;
|
||||
if (has_zero_x()) { cx=(cur.x<0?-1.:1); }
|
||||
else if (has_zero_y()) { cy=(cur.y<0?-1.:1); }
|
||||
else { cz=(cur.z<0?-1.:1); }*/
|
||||
|
||||
camera()->setUpVector(-camera()->upVector());
|
||||
//camera()->frame()->setConstraint(NULL);
|
||||
// camera()->setViewDirection(CGAL::qglviewer::Vec(-cx,-cy,-cz));
|
||||
//constraint.setRotationConstraintDirection(CGAL::qglviewer::Vec(cx, cy, cz));
|
||||
//camera()->frame()->setConstraint(&constraint);
|
||||
//update();
|
||||
redraw();
|
||||
}
|
||||
}
|
||||
else if ((e->key()==::Qt::Key_T) && (modifiers==::Qt::NoButton))
|
||||
{
|
||||
m_draw_text=!m_draw_text;
|
||||
|
|
|
|||
|
|
@ -195,7 +195,6 @@ void
|
|||
DemosMainWindow::setUseAntialiasing(bool checked)
|
||||
{
|
||||
view->setRenderHint(QPainter::Antialiasing, checked);
|
||||
view->setRenderHint(QPainter::HighQualityAntialiasing, checked);
|
||||
|
||||
statusBar()->showMessage(tr("Antialiasing %1activated").arg(checked?"":"de-"),
|
||||
1000);
|
||||
|
|
|
|||
|
|
@ -21,6 +21,7 @@
|
|||
#include <QDateTime>
|
||||
#include <QString>
|
||||
#include <QTimer>
|
||||
#include <QElapsedTimer>
|
||||
|
||||
namespace CGAL{
|
||||
namespace qglviewer {
|
||||
|
|
@ -348,7 +349,7 @@ private:
|
|||
qreal zoomSensitivity_;
|
||||
|
||||
// Mouse speed and spinning
|
||||
QTime last_move_time;
|
||||
QElapsedTimer last_move_time;
|
||||
qreal mouseSpeed_;
|
||||
int delay_;
|
||||
bool isSpinning_;
|
||||
|
|
|
|||
|
|
@ -28,7 +28,7 @@
|
|||
#include <QOpenGLBuffer>
|
||||
#include <QMap>
|
||||
#include <QVector>
|
||||
#include <QTime>
|
||||
#include <QElapsedTimer>
|
||||
#include <QTimer>
|
||||
#include <QGLContext>
|
||||
#include <QOpenGLWidget>
|
||||
|
|
@ -1038,7 +1038,7 @@ protected:
|
|||
int animationTimerId_;
|
||||
|
||||
// F P S d i s p l a y
|
||||
QTime fpsTime_;
|
||||
QElapsedTimer fpsTime_;
|
||||
unsigned int fpsCounter_;
|
||||
QString fpsString_;
|
||||
qreal f_p_s_;
|
||||
|
|
|
|||
|
|
@ -46,6 +46,7 @@
|
|||
#include <QColorDialog>
|
||||
#include <QOpenGLFramebufferObject>
|
||||
#include <QFileDialog>
|
||||
#include <QElapsedTimer>
|
||||
|
||||
namespace CGAL{
|
||||
// Static private variable
|
||||
|
|
@ -2244,7 +2245,7 @@ void CGAL::QGLViewer::keyPressEvent(QKeyEvent *e) {
|
|||
unsigned int index = pathIndex_[::Qt::Key(key)];
|
||||
|
||||
// not safe, but try to double press on two viewers at the same time !
|
||||
static QTime doublePress;
|
||||
static QElapsedTimer doublePress;
|
||||
|
||||
if (modifiers == playPathKeyboardModifiers()) {
|
||||
int elapsed = doublePress.restart();
|
||||
|
|
|
|||
|
|
@ -1,17 +1,31 @@
|
|||
Release History
|
||||
===============
|
||||
|
||||
Release 5.1
|
||||
[Release 5.1] (https://github.com/CGAL/cgal/releases/tag/releases%2FCGAL-5.1)
|
||||
-----------
|
||||
|
||||
Release date: June 2020
|
||||
|
||||
### Surface Mesh Topology (new package)
|
||||
|
||||
- This package allows to compute some topological invariants of
|
||||
surfaces. For now, it is possible to test if two (closed) curves
|
||||
on a combinatorial surface are homotopic. The user can choose
|
||||
between free homotopy and homotopy with fixed endpoints.
|
||||
A contractibility test is also provided.
|
||||
|
||||
### 3D Fast Intersection and Distance Computation
|
||||
- **Breaking change**: the internal search tree is now lazily constructed. To disable it, one must call
|
||||
the new function `do_not_accelerate_distance_queries()` before the first distance query.
|
||||
|
||||
### Polygon Mesh Processing
|
||||
|
||||
- Introduced a new function, `CGAL::Polygon_mesh_processing::remove_connected_components_of_negligible_size()`,
|
||||
which can be used to remove connected components whose area or volume is under a certain threshold.
|
||||
Area and volume thresholds are either specified by the user or deduced from the bounding box of the mesh.
|
||||
- Added a new named parameter for `keep_large_connected_components()` and `remove_connected_components_of_negligible_size`
|
||||
that can be used to perform a dry run of the operation, meaning that the function will return the number of connected
|
||||
components that would be removed with the specified threshold, but without actually removing them.
|
||||
- The function `CGAL::Polygon_mesh_processing::stitch_borders()` now returns the number
|
||||
of halfedge pairs that were stitched.
|
||||
|
||||
|
|
|
|||
|
|
@ -55,7 +55,7 @@ set(CGAL_ImageIO_USE_ZLIB "@CGAL_ImageIO_USE_ZLIB@" )
|
|||
set(CGAL_VERSION "${CGAL_MAJOR_VERSION}.${CGAL_MINOR_VERSION}.${CGAL_BUGFIX_VERSION}")
|
||||
|
||||
set(CGAL_USE_FILE "${CGAL_MODULES_DIR}/UseCGAL.cmake" )
|
||||
set(CGAL_GRAPHICSVIEW_PACKAGE_DIR "${CGAL_INCLUDE_DIRS}/CGAL/" CACHE INTERNAL "Directory containing the GraphicsView package")
|
||||
set(CGAL_GRAPHICSVIEW_PACKAGE_DIR "${CGAL_INSTALL_PREFIX}" CACHE INTERNAL "Directory containing the GraphicsView package")
|
||||
|
||||
if ( CGAL_FIND_REQUIRED )
|
||||
set( CHECK_CGAL_COMPONENT_MSG_ON_ERROR TRUE )
|
||||
|
|
|
|||
|
|
@ -15,7 +15,7 @@ if (NOT GLPK_FOUND)
|
|||
)
|
||||
|
||||
find_library(GLPK_LIBRARIES
|
||||
NAMES libglpk
|
||||
NAMES libglpk glpk
|
||||
PATHS ENV LD_LIBRARY_PATH
|
||||
ENV LIBRARY_PATH
|
||||
/usr/local/lib
|
||||
|
|
|
|||
|
|
@ -6,6 +6,8 @@
|
|||
# OPENMESH_LIBRARIES - OpenMesh libraries
|
||||
#
|
||||
|
||||
find_package(OpenMesh NO_MODULE QUIET)
|
||||
|
||||
# Is it already configured?
|
||||
if (NOT OpenMesh_FOUND)
|
||||
|
||||
|
|
@ -44,7 +46,34 @@ endif()
|
|||
|
||||
include( FindPackageHandleStandardArgs )
|
||||
|
||||
FIND_PACKAGE_HANDLE_STANDARD_ARGS(OpenMesh
|
||||
find_package_handle_standard_args(OpenMesh
|
||||
REQUIRED_VARS OPENMESH_INCLUDE_DIR OPENMESH_LIBRARIES
|
||||
FOUND_VAR OpenMesh_FOUND
|
||||
)
|
||||
|
||||
if(OpenMesh_FOUND AND NOT TARGET OpenMesh::OpenMesh)
|
||||
add_library(OpenMesh::OpenMesh UNKNOWN IMPORTED)
|
||||
|
||||
if(TARGET OpenMeshCore)
|
||||
target_link_libraries(OpenMesh::OpenMesh PUBLIC OpenMeshCore)
|
||||
return()
|
||||
endif()
|
||||
|
||||
set_target_properties(OpenMesh::OpenMesh PROPERTIES
|
||||
INTERFACE_COMPILE_DEFINITIONS "CGAL_USE_OPENMESH;NOMINMAX;_USE_MATH_DEFINES"
|
||||
INTERFACE_INCLUDE_DIRECTORIES "${OPENMESH_INCLUDE_DIR}")
|
||||
|
||||
if(OPENMESH_LIBRARY_RELEASE)
|
||||
set_property(TARGET OpenMesh::OpenMesh APPEND PROPERTY
|
||||
IMPORTED_CONFIGURATIONS RELEASE)
|
||||
set_target_properties(OpenMesh::OpenMesh PROPERTIES
|
||||
IMPORTED_LOCATION_RELEASE "${OPENMESH_LIBRARY_RELEASE}")
|
||||
endif()
|
||||
|
||||
if(OPENMESH_LIBRARY_DEBUG)
|
||||
set_property(TARGET OpenMesh::OpenMesh APPEND PROPERTY
|
||||
IMPORTED_CONFIGURATIONS DEBUG)
|
||||
set_target_properties(OpenMesh::OpenMesh PROPERTIES
|
||||
IMPORTED_LOCATION_DEBUG "${OPENMESH_LIBRARY_DEBUG}")
|
||||
endif()
|
||||
endif()
|
||||
|
|
|
|||
|
|
@ -0,0 +1,54 @@
|
|||
// Copyright (c) 2016 GeometryFactory SARL (France).
|
||||
// All rights reserved.
|
||||
//
|
||||
// This file is part of CGAL (www.cgal.org)
|
||||
//
|
||||
// $URL$
|
||||
// $Id$
|
||||
// SPDX-License-Identifier: LGPL-3.0-or-later OR LicenseRef-Commercial
|
||||
//
|
||||
// Author(s) : Andreas Fabri
|
||||
//
|
||||
// Warning: this file is generated, see include/CGAL/licence/README.md
|
||||
|
||||
#ifndef CGAL_LICENSE_SURFACE_MESH_TOPOLOGY_H
|
||||
#define CGAL_LICENSE_SURFACE_MESH_TOPOLOGY_H
|
||||
|
||||
#include <CGAL/config.h>
|
||||
#include <CGAL/license.h>
|
||||
|
||||
#ifdef CGAL_SURFACE_MESH_TOPOLOGY_COMMERCIAL_LICENSE
|
||||
|
||||
# if CGAL_SURFACE_MESH_TOPOLOGY_COMMERCIAL_LICENSE < CGAL_RELEASE_DATE
|
||||
|
||||
# if defined(CGAL_LICENSE_WARNING)
|
||||
|
||||
CGAL_pragma_warning("Your commercial license for CGAL does not cover "
|
||||
"this release of the Surface Mesh Topology package.")
|
||||
# endif
|
||||
|
||||
# ifdef CGAL_LICENSE_ERROR
|
||||
# error "Your commercial license for CGAL does not cover this release \
|
||||
of the Surface Mesh Topology package. \
|
||||
You get this error, as you defined CGAL_LICENSE_ERROR."
|
||||
# endif // CGAL_LICENSE_ERROR
|
||||
|
||||
# endif // CGAL_SURFACE_MESH_TOPOLOGY_COMMERCIAL_LICENSE < CGAL_RELEASE_DATE
|
||||
|
||||
#else // no CGAL_SURFACE_MESH_TOPOLOGY_COMMERCIAL_LICENSE
|
||||
|
||||
# if defined(CGAL_LICENSE_WARNING)
|
||||
CGAL_pragma_warning("\nThe macro CGAL_SURFACE_MESH_TOPOLOGY_COMMERCIAL_LICENSE is not defined."
|
||||
"\nYou use the CGAL Surface Mesh Topology package under "
|
||||
"the terms of the GPLv3+.")
|
||||
# endif // CGAL_LICENSE_WARNING
|
||||
|
||||
# ifdef CGAL_LICENSE_ERROR
|
||||
# error "The macro CGAL_SURFACE_MESH_TOPOLOGY_COMMERCIAL_LICENSE is not defined.\
|
||||
You use the CGAL Surface Mesh Topology package under the terms of \
|
||||
the GPLv3+. You get this error, as you defined CGAL_LICENSE_ERROR."
|
||||
# endif // CGAL_LICENSE_ERROR
|
||||
|
||||
#endif // no CGAL_SURFACE_MESH_TOPOLOGY_COMMERCIAL_LICENSE
|
||||
|
||||
#endif // CGAL_LICENSE_SURFACE_MESH_TOPOLOGY_H
|
||||
|
|
@ -82,6 +82,7 @@ Surface_mesh_segmentation Triangulated Surface Mesh Segmentation
|
|||
Surface_mesh_shortest_path Triangulated Surface Mesh Shortest Paths
|
||||
Surface_mesh_simplification Triangulated Surface Mesh Simplification
|
||||
Surface_mesh_skeletonization Triangulated Surface Mesh Skeletonization
|
||||
Surface_mesh_topology Surface Mesh Topology
|
||||
Surface_sweep_2 2D Intersection of Curves
|
||||
TDS_2 2D Triangulation Data Structure
|
||||
TDS_3 3D Triangulation Data Structure
|
||||
|
|
|
|||
|
|
@ -89,6 +89,7 @@ template <class R,int dim>
|
|||
class Construct_bbox_projected_2 {
|
||||
public:
|
||||
typedef typename R::Point_3 Point;
|
||||
typedef Bbox_2 result_type;
|
||||
|
||||
Bbox_2 operator()(const Point& p) const { typename R::Construct_bbox_3 bb; return Projector<R, dim>::bbox(bb(p)); }
|
||||
};
|
||||
|
|
|
|||
|
|
@ -24,7 +24,7 @@ endif()
|
|||
# set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -pg")
|
||||
|
||||
# To use valgrind, we must disable rounding math ckeck.
|
||||
# add_definition(-DCGAL_DISABLE_ROUNDING_MATH_CHECK)
|
||||
# add_definitions(-DCGAL_DISABLE_ROUNDING_MATH_CHECK)
|
||||
|
||||
if (CGAL_FOUND)
|
||||
|
||||
|
|
|
|||
|
|
@ -150,6 +150,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,
|
||||
|
|
|
|||
|
|
@ -142,6 +142,8 @@ namespace CGAL {
|
|||
CGAL_assertion(i <= dimension);
|
||||
return dh->mf[i]==dh;
|
||||
}
|
||||
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,
|
||||
|
|
|
|||
|
|
@ -147,24 +147,46 @@ namespace CGAL {
|
|||
Linear_cell_complex_base(const Self& alcc) : Base(alcc)
|
||||
{}
|
||||
|
||||
template < class LCC2 >
|
||||
Linear_cell_complex_base(const LCC2& alcc) : Base(alcc)
|
||||
template <unsigned int d2, unsigned int ambient_dim2, class Traits2,
|
||||
class Items2, class Alloc2,
|
||||
template<unsigned int,class,class,class,class> class CMap2,
|
||||
class Refs2, class Storage2>
|
||||
Linear_cell_complex_base
|
||||
(const Linear_cell_complex_base<d2, ambient_dim2,
|
||||
Traits2, Items2, Alloc2, CMap2, Refs2, Storage2>& alcc) : Base(alcc)
|
||||
{}
|
||||
|
||||
template < class LCC2, typename Converters >
|
||||
Linear_cell_complex_base(const LCC2& alcc, Converters& converters) :
|
||||
template <unsigned int d2, unsigned int ambient_dim2, class Traits2,
|
||||
class Items2, class Alloc2,
|
||||
template<unsigned int,class,class,class,class> class CMap2,
|
||||
class Refs2,
|
||||
class Storage2, typename Converters>
|
||||
Linear_cell_complex_base
|
||||
(const Linear_cell_complex_base<d2, ambient_dim2, Traits2, Items2,
|
||||
Alloc2, CMap2, Refs2, Storage2>& alcc, Converters& converters) :
|
||||
Base(alcc, converters)
|
||||
{}
|
||||
|
||||
template < class LCC2, typename Converters, typename DartInfoConverter >
|
||||
Linear_cell_complex_base(const LCC2& alcc, Converters& converters,
|
||||
template <unsigned int d2, unsigned int ambient_dim2, class Traits2,
|
||||
class Items2, class Alloc2,
|
||||
template<unsigned int,class,class,class,class> class CMap2,
|
||||
class Refs2, class Storage2, typename Converters,
|
||||
typename DartInfoConverter>
|
||||
Linear_cell_complex_base
|
||||
(const Linear_cell_complex_base<d2, ambient_dim2, Traits2, Items2,
|
||||
Alloc2, CMap2, Refs2, Storage2>& alcc, Converters& converters,
|
||||
const DartInfoConverter& dartinfoconverter) :
|
||||
Base(alcc, converters, dartinfoconverter)
|
||||
{}
|
||||
|
||||
template < class LCC2, typename Converters, typename DartInfoConverter,
|
||||
typename Pointconverter >
|
||||
Linear_cell_complex_base(const LCC2& alcc, Converters& converters,
|
||||
template <unsigned int d2, unsigned int ambient_dim2, class Traits2,
|
||||
class Items2, class Alloc2,
|
||||
template<unsigned int,class,class,class,class> class CMap2,
|
||||
class Refs2, class Storage2, typename Converters,
|
||||
typename DartInfoConverter, typename Pointconverter>
|
||||
Linear_cell_complex_base
|
||||
(const Linear_cell_complex_base<d2, ambient_dim2, Traits2, Items2,
|
||||
Alloc2, CMap2, Refs2, Storage2>& alcc, Converters& converters,
|
||||
const DartInfoConverter& dartinfoconverter,
|
||||
const Pointconverter& pointconverter) :
|
||||
Base(alcc, converters, dartinfoconverter, pointconverter)
|
||||
|
|
|
|||
|
|
@ -17,6 +17,7 @@
|
|||
#include <CGAL/Linear_cell_complex_min_items.h>
|
||||
#include <CGAL/Combinatorial_map.h>
|
||||
#include <CGAL/CMap_linear_cell_complex_storages.h>
|
||||
#include <CGAL/boost/graph/properties.h>
|
||||
|
||||
namespace CGAL {
|
||||
|
||||
|
|
@ -100,40 +101,119 @@ namespace CGAL {
|
|||
* @param alcc the linear cell complex to copy.
|
||||
* @post *this is valid.
|
||||
*/
|
||||
#ifdef DOXYGEN_RUNNING
|
||||
Linear_cell_complex_for_combinatorial_map(const Self& alcc) : Base(alcc)
|
||||
{}
|
||||
#endif
|
||||
|
||||
template < class LCC2 >
|
||||
Linear_cell_complex_for_combinatorial_map(const LCC2& alcc) : Base(alcc)
|
||||
template <unsigned int d2, unsigned int ambient_dim2, class Traits2,
|
||||
class Items2, class Alloc2,
|
||||
template<unsigned int,class,class,class,class> class CMap2,
|
||||
class Storage2>
|
||||
Linear_cell_complex_for_combinatorial_map
|
||||
(const Linear_cell_complex_for_combinatorial_map<d2, ambient_dim2,
|
||||
Traits2, Items2, Alloc2, CMap2, Storage2>& alcc) : Base(alcc)
|
||||
{}
|
||||
|
||||
template < class LCC2, typename Converters >
|
||||
Linear_cell_complex_for_combinatorial_map(const LCC2& alcc,
|
||||
Converters& converters) :
|
||||
Base(alcc, converters)
|
||||
template <unsigned int d2, unsigned int ambient_dim2, class Traits2,
|
||||
class Items2, class Alloc2,
|
||||
template<unsigned int,class,class,class,class> class CMap2,
|
||||
class Storage2, typename Converters>
|
||||
Linear_cell_complex_for_combinatorial_map
|
||||
(const Linear_cell_complex_for_combinatorial_map<d2, ambient_dim2,
|
||||
Traits2, Items2, Alloc2, CMap2, Storage2>& alcc,
|
||||
const Converters& converters) : Base(alcc, converters)
|
||||
{}
|
||||
|
||||
template < class LCC2, typename Converters, typename DartInfoConverter >
|
||||
Linear_cell_complex_for_combinatorial_map(const LCC2& alcc,
|
||||
Converters& converters,
|
||||
const DartInfoConverter&
|
||||
dartinfoconverter) :
|
||||
template <unsigned int d2, unsigned int ambient_dim2, class Traits2,
|
||||
class Items2, class Alloc2,
|
||||
template<unsigned int,class,class,class,class> class CMap2,
|
||||
class Storage2, typename Converters, typename DartInfoConverter>
|
||||
Linear_cell_complex_for_combinatorial_map
|
||||
(const Linear_cell_complex_for_combinatorial_map<d2, ambient_dim2,
|
||||
Traits2, Items2, Alloc2, CMap2, Storage2>& alcc,
|
||||
const Converters& converters,
|
||||
const DartInfoConverter& dartinfoconverter) :
|
||||
Base(alcc, converters, dartinfoconverter)
|
||||
{}
|
||||
|
||||
template < class LCC2, typename Converters, typename DartInfoConverter,
|
||||
typename PointConverter >
|
||||
Linear_cell_complex_for_combinatorial_map(const LCC2& alcc,
|
||||
Converters& converters,
|
||||
const DartInfoConverter&
|
||||
dartinfoconverter,
|
||||
const PointConverter&
|
||||
pointconverter) :
|
||||
template <unsigned int d2, unsigned int ambient_dim2, class Traits2,
|
||||
class Items2, class Alloc2,
|
||||
template<unsigned int,class,class,class,class> class CMap2,
|
||||
class Storage2, typename Converters,
|
||||
typename DartInfoConverter, typename PointConverter>
|
||||
Linear_cell_complex_for_combinatorial_map
|
||||
(const Linear_cell_complex_for_combinatorial_map<d2, ambient_dim2,
|
||||
Traits2, Items2, Alloc2, CMap2, Storage2>& alcc,
|
||||
const Converters& converters, const DartInfoConverter& dartinfoconverter,
|
||||
const PointConverter& pointconverter) :
|
||||
Base(alcc, converters, dartinfoconverter, pointconverter)
|
||||
{}
|
||||
|
||||
Self & operator= (const Self & alcc)
|
||||
{
|
||||
Base::operator=(alcc);
|
||||
return *this;
|
||||
}
|
||||
|
||||
/** Import the given hds which should be a model of an halfedge graph. */
|
||||
template<class HEG, class PointConverter>
|
||||
void import_from_halfedge_graph(const HEG& heg ,
|
||||
const PointConverter& pointconverter,
|
||||
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)
|
||||
|
||||
{
|
||||
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; }
|
||||
|
||||
Base::import_from_halfedge_graph(heg, origin_to_copy, copy_to_origin);
|
||||
|
||||
typedef typename boost::property_map<HEG,vertex_point_t>::const_type
|
||||
Point_property_map;
|
||||
Point_property_map ppmap = get(CGAL::vertex_point, heg);
|
||||
|
||||
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)
|
||||
{
|
||||
if (this->vertex_attribute(dartmap_iter->second)==NULL)
|
||||
{
|
||||
this->set_vertex_attribute(dartmap_iter->second,
|
||||
this->create_vertex_attribute());
|
||||
pointconverter.run(ppmap[source(dartmap_iter->first, heg)],
|
||||
this->point(dartmap_iter->second));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/** 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)
|
||||
{
|
||||
typedef typename boost::property_traits<typename boost::property_map
|
||||
<HEG, vertex_point_t>::type>::value_type HEG_point;
|
||||
|
||||
CGAL::internal::Set_point_if_possible_cmap<HEG_point, Point> default_point_converter;
|
||||
import_from_halfedge_graph(heg, default_point_converter,
|
||||
origin_to_copy, copy_to_origin);
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
} // namespace CGAL
|
||||
|
|
|
|||
|
|
@ -96,40 +96,59 @@ namespace CGAL {
|
|||
* @param alcc the linear cell complex to copy.
|
||||
* @post *this is valid.
|
||||
*/
|
||||
#ifdef DOXYGEN_RUNNING
|
||||
Linear_cell_complex_for_generalized_map(const Self & alcc) : Base(alcc)
|
||||
{}
|
||||
#endif
|
||||
|
||||
template < class LCC2 >
|
||||
Linear_cell_complex_for_generalized_map(const LCC2& alcc) : Base(alcc)
|
||||
template <unsigned int d2, unsigned int ambient_dim2, class Traits2,
|
||||
class Items2, class Alloc2,
|
||||
template<unsigned int,class,class,class,class> class CMap2,
|
||||
class Storage2>
|
||||
Linear_cell_complex_for_generalized_map
|
||||
(const Linear_cell_complex_for_generalized_map<d2, ambient_dim2,
|
||||
Traits2, Items2, Alloc2, CMap2, Storage2>& alcc) : Base(alcc)
|
||||
{}
|
||||
|
||||
template < class LCC2, typename Converters >
|
||||
Linear_cell_complex_for_generalized_map(const LCC2& alcc,
|
||||
Converters& converters) :
|
||||
Base(alcc, converters)
|
||||
template <unsigned int d2, unsigned int ambient_dim2, class Traits2,
|
||||
class Items2, class Alloc2,
|
||||
template<unsigned int,class,class,class,class> class CMap2,
|
||||
class Storage2, typename Converters>
|
||||
Linear_cell_complex_for_generalized_map
|
||||
(const Linear_cell_complex_for_generalized_map<d2, ambient_dim2,
|
||||
Traits2, Items2, Alloc2, CMap2, Storage2>& alcc,
|
||||
const Converters& converters) : Base(alcc, converters)
|
||||
{}
|
||||
|
||||
template < class LCC2, typename Converters, typename DartInfoConverter >
|
||||
Linear_cell_complex_for_generalized_map(const LCC2& alcc,
|
||||
Converters& converters,
|
||||
const DartInfoConverter&
|
||||
dartinfoconverter) :
|
||||
template <unsigned int d2, unsigned int ambient_dim2, class Traits2,
|
||||
class Items2, class Alloc2,
|
||||
template<unsigned int,class,class,class,class> class CMap2,
|
||||
class Storage2, typename Converters, typename DartInfoConverter>
|
||||
Linear_cell_complex_for_generalized_map
|
||||
(const Linear_cell_complex_for_generalized_map<d2, ambient_dim2,
|
||||
Traits2, Items2, Alloc2, CMap2, Storage2>& alcc,
|
||||
const Converters& converters,
|
||||
const DartInfoConverter& dartinfoconverter) :
|
||||
Base(alcc, converters, dartinfoconverter)
|
||||
{}
|
||||
|
||||
template < class LCC2, typename Converters, typename DartInfoConverter,
|
||||
template <unsigned int d2, unsigned int ambient_dim2, class Traits2,
|
||||
class Items2, class Alloc2,
|
||||
template<unsigned int,class,class,class,class> class CMap2,
|
||||
class Storage2, typename Converters, typename DartInfoConverter,
|
||||
typename PointConverter>
|
||||
Linear_cell_complex_for_generalized_map(const LCC2& alcc,
|
||||
Converters& converters,
|
||||
const DartInfoConverter&
|
||||
dartinfoconverter,
|
||||
const PointConverter&
|
||||
pointconverter) :
|
||||
Linear_cell_complex_for_generalized_map
|
||||
(const Linear_cell_complex_for_generalized_map<d2, ambient_dim2,
|
||||
Traits2, Items2, Alloc2, CMap2, Storage2>& alcc,
|
||||
const Converters& converters,
|
||||
const DartInfoConverter& dartinfoconverter,
|
||||
const PointConverter& pointconverter) :
|
||||
Base(alcc, converters, dartinfoconverter, pointconverter)
|
||||
{}
|
||||
|
||||
Self & operator= (const Self & alcc)
|
||||
{
|
||||
Base::operator=(alcc);
|
||||
return *this;
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace CGAL
|
||||
|
|
|
|||
|
|
@ -16,7 +16,7 @@
|
|||
|
||||
#ifdef CGAL_USE_BASIC_VIEWER
|
||||
|
||||
#include <CGAL/Linear_cell_complex_base.h>
|
||||
#include <CGAL/Linear_cell_complex_operations.h>
|
||||
#include <CGAL/Random.h>
|
||||
|
||||
namespace CGAL
|
||||
|
|
|
|||
|
|
@ -27,7 +27,7 @@ LC_CTYPE=en_US.UTF-8
|
|||
# "integration"
|
||||
0 21 * * Mon,Tue,Wed,Thu cd $HOME/CGAL/create_internal_release && /usr/bin/time scl enable rh-git29 -- $HOME/bin/create_release $HOME/CGAL/branches/integration.git $HOME/CGAL/branches/empty-dir --do-it --public || echo ERROR
|
||||
# from branch 5.0
|
||||
0 21 * * fri cd $HOME/CGAL/create_internal_release-5.0-branch && /usr/bin/time scl enable rh-git29 -- $HOME/bin/create_release $HOME/CGAL/branches/CGAL-4.14-branch.git --public --do-it || echo ERROR
|
||||
0 21 * * Fri cd $HOME/CGAL/create_internal_release-5.0-branch && /usr/bin/time scl enable rh-git29 -- $HOME/bin/create_release $HOME/CGAL/branches/CGAL-5.0-branch.git --public --do-it || echo ERROR
|
||||
# from branch 4.14
|
||||
0 21 * * Sat cd $HOME/CGAL/create_internal_release-4.14-branch && /usr/bin/time scl enable rh-git29 -- $HOME/bin/create_release $HOME/CGAL/branches/CGAL-4.14-branch.git --public --do-it || echo ERROR
|
||||
|
||||
|
|
|
|||
|
|
@ -0,0 +1,136 @@
|
|||
<!doctype html>
|
||||
<html style='height: 100%'>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>Diff of Testsuites</title>
|
||||
<script type="text/javascript" src="difflib.js"></script>
|
||||
<script type="text/javascript" src="fill_empty_lines.js"></script>
|
||||
<script type="text/javascript" src="print_diff.js"></script>
|
||||
<script type="text/javascript" src="diff_testsuites.js"></script>
|
||||
<script type="text/javascript" src="worker.js"></script>
|
||||
</head>
|
||||
<body style='background-color: #C0C0D0; min-height: 100%;'>
|
||||
|
||||
<p><input type='text' id='baseInput'/>
|
||||
<select id='baselist'></select>
|
||||
|
||||
<input type='text' id='newInput'/>
|
||||
<select id='newlist'></select>
|
||||
|
||||
<button type="button" id='button'>Compare</button><br>
|
||||
I = Master<br>
|
||||
Ic = integration
|
||||
</p>
|
||||
<p>
|
||||
<table id=namesTable border="1" cellspacing="2" cellpadding="5"></table>
|
||||
<table id=diffPlatforms border="1" cellspacing="2" cellpadding="5"></table>
|
||||
<table id=testTable border="1" cellspacing="2" cellpadding="5"></table>
|
||||
<table id=namesTableBis border="1" cellspacing="2" cellpadding="5"></table>
|
||||
</p>
|
||||
|
||||
<script type="text/javascript">
|
||||
//get list of existing testsuites
|
||||
var xhr = new XMLHttpRequest();
|
||||
xhr.open('GET', 'https://cgal.geometryfactory.com/~mgimeno/testsuite_comparison/list_of_testsuites.txt', false);
|
||||
xhr.send(null);
|
||||
if (xhr.status !== 200) {
|
||||
alert("Couldn't find the list of testsuites.");
|
||||
throw new Error("Couldn't find the list of testsuites.");
|
||||
}
|
||||
var tmp=xhr.responseText;
|
||||
var testsuites=tmp.split("\n");
|
||||
testsuites.sort();
|
||||
testsuites.reverse();
|
||||
var sorted_testsuites = testsuites;
|
||||
var base = document.getElementById('baselist');
|
||||
var newlist = document.getElementById('newlist');
|
||||
var baseinput = document.getElementById('baseInput');
|
||||
baseinput.oninput=function(){
|
||||
var length = base.length;
|
||||
for(i=0; i<length; i++)
|
||||
{
|
||||
base.removeChild(base.options[0]);
|
||||
}
|
||||
sorted_testsuites=testsuites.filter(word=>word.includes(baseinput.value));
|
||||
for(var i = 0; i < sorted_testsuites.length; i++) {
|
||||
var opt1 = document.createElement('option');
|
||||
opt1.innerHTML = sorted_testsuites[i];
|
||||
opt1.value = sorted_testsuites[i];
|
||||
base.appendChild(opt1);
|
||||
}
|
||||
}
|
||||
var newinput = document.getElementById('newInput');
|
||||
newinput.oninput=function(){
|
||||
var length = newlist.length;
|
||||
for(i=0; i<length; i++)
|
||||
{
|
||||
newlist.removeChild(newlist.options[0]);
|
||||
}
|
||||
sorted_testsuites=testsuites.filter(word=>word.includes(newinput.value));
|
||||
for(var i = 0; i < sorted_testsuites.length; i++) {
|
||||
var opt1 = document.createElement('option');
|
||||
opt1.innerHTML = sorted_testsuites[i];
|
||||
opt1.value = sorted_testsuites[i];
|
||||
newlist.appendChild(opt1);
|
||||
}
|
||||
}
|
||||
|
||||
for(var i = 0; i < sorted_testsuites.length; i++) {
|
||||
var opt1 = document.createElement('option');
|
||||
var opt2 = document.createElement('option');
|
||||
opt1.innerHTML = sorted_testsuites[i];
|
||||
opt2.innerHTML = sorted_testsuites[i];
|
||||
opt1.value = sorted_testsuites[i];
|
||||
opt2.value = sorted_testsuites[i];
|
||||
base.appendChild(opt1);
|
||||
newlist.appendChild(opt2);
|
||||
}
|
||||
var button = document.getElementById('button');
|
||||
button.onclick=function(){
|
||||
var baselist = document.getElementById("baselist");
|
||||
var newlist = document.getElementById("newlist")
|
||||
if(baselist.length==0 || newlist.length==0){
|
||||
alert("You need two valid testsuites to diff.");
|
||||
throw new Error("You need two valid testsuites to diff.");
|
||||
}
|
||||
var baseId = baselist.selectedIndex;
|
||||
var newId = newlist.selectedIndex;
|
||||
var baseTest = base.options[base.selectedIndex].value;
|
||||
var newTest = newlist.options[newlist.selectedIndex].value;
|
||||
document.body.style.cursor = 'wait';
|
||||
if(baseTest === newTest){
|
||||
alert("You chose the same testsuite twice, so no diff is expected !");
|
||||
}
|
||||
var namesTable = document.getElementById("namesTable");
|
||||
var diffPlatforms = document.getElementById("diffPlatforms");
|
||||
var namesTableBis = document.getElementById("namesTableBis");
|
||||
var names = "<table id=table border=\"1\" cellspacing=\"2\" cellpadding=\"5\">";
|
||||
var diff_platforms = "<table id=table border=\"1\" cellspacing=\"2\" cellpadding=\"5\">";
|
||||
var tests = "<table id=table border=\"1\" cellspacing=\"2\" cellpadding=\"5\">";
|
||||
tests+="<caption>TESTSUITE1: <a href=\"https://cgal.geometryfactory.com/CGAL/testsuite/"+baseTest.replace('CGAL','results')+".shtml\">"+baseTest+"</a> | TESTSUITE2: <a href=\"https://cgal.geometryfactory.com/CGAL/testsuite/"+newTest.replace('CGAL','results')+".shtml\">"+newTest+"</a></caption>";
|
||||
|
||||
var testTable =document.getElementById("testTable");
|
||||
|
||||
var message = [baseTest, newTest];
|
||||
var w = new Worker("worker.js");
|
||||
w.addEventListener('message', function(e) {
|
||||
console.log(e.data[0]);
|
||||
if(e.data[0] === "finished"){
|
||||
namesTable.innerHTML=names;
|
||||
diffPlatforms.innerHTML=diff_platforms;
|
||||
testTable.innerHTML=tests;
|
||||
namesTableBis.innerHTML=names;
|
||||
document.body.style.cursor = 'default';
|
||||
} else if(e.data[0] === "diffPlatforms"){
|
||||
diff_platforms+= e.data[1];
|
||||
}else if(e.data[0] === "namesTable"){
|
||||
names+= e.data[1];
|
||||
} else if(e.data[0] === "testTable"){
|
||||
tests+= e.data[1];
|
||||
}
|
||||
}, false);
|
||||
w.postMessage(message);
|
||||
};
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
|
|
@ -0,0 +1,148 @@
|
|||
/* Author: Maxime Gimeno <maxime.gimeno@gmail.com> */
|
||||
|
||||
/***
|
||||
Needs difflib.js, fill_empty_lines.js and print_diff.js to work.
|
||||
|
||||
Input : 2 strings of the form "CGAL-M.m.mm-I[c]-XXX"
|
||||
|
||||
Output: the list of differences between the testsuites.
|
||||
|
||||
***/
|
||||
|
||||
//v1.7
|
||||
function diff_testsuites(baseTest, newTest){
|
||||
var URL_suff='https://cgal.geometryfactory.com/~mgimeno/testsuite_comparison/list_of_suffixes.txt';
|
||||
var URL_testsuite='https://cgal.geometryfactory.com/CGAL/Members/testsuite/';
|
||||
//get the list of suffixes
|
||||
var xhr = new XMLHttpRequest();
|
||||
xhr.open('GET', URL_suff, false);
|
||||
xhr.send(null);
|
||||
var tmp=xhr.responseText;
|
||||
var suffixes=tmp.split("\n");
|
||||
suffixes.sort();
|
||||
suffixes.reverse();
|
||||
var myArray = new Array();
|
||||
|
||||
//contains the diff of existing platforms.
|
||||
|
||||
var diffArray = new Array();
|
||||
|
||||
var init = false;
|
||||
for(s = 0; s < suffixes.length; s++) {
|
||||
var new_column = new Array();
|
||||
xhr.open('GET', URL_testsuite+baseTest+'/'+suffixes[s], false);
|
||||
xhr.send(null);
|
||||
var base_exists = (xhr.status === 200);
|
||||
var base=xhr.responseText;
|
||||
xhr.open('GET', URL_testsuite+newTest+'/'+suffixes[s], false);
|
||||
xhr.send(null);
|
||||
var new_exists = (xhr.status === 200)
|
||||
|
||||
if(base_exists && !new_exists)
|
||||
{
|
||||
diffArray.push("-"+suffixes[s]);
|
||||
continue;
|
||||
}
|
||||
if(!base_exists && new_exists)
|
||||
{
|
||||
diffArray.push("+"+suffixes[s]);
|
||||
continue;
|
||||
}
|
||||
if(!base_exists && !new_exists)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
var newtext=xhr.responseText;
|
||||
var sp_base=base.split("\n");
|
||||
sp_base.sort();
|
||||
var sp_newtext=newtext.split("\n");
|
||||
sp_newtext.sort();
|
||||
addMissingLines(sp_base, sp_newtext);
|
||||
if(!init)
|
||||
{
|
||||
var first_column = new Array();
|
||||
first_column.push("Platform")
|
||||
for(i=0; i< sp_base.length; i++){
|
||||
if(sp_base[i] !== ""){
|
||||
first_column.push(sp_base[i].substr(0, sp_base[i].length-2));
|
||||
} else {
|
||||
first_column.push(sp_newtext[i].substr(0, sp_newtext[i].length-2));
|
||||
}
|
||||
}
|
||||
myArray.push(first_column);
|
||||
init = true;
|
||||
}
|
||||
var fragments = suffixes[s].split("_");
|
||||
fragments.shift();
|
||||
var name = fragments.join("_");
|
||||
name = name.replace('.txt', '');
|
||||
if(name !== ""){
|
||||
new_column.push(name.replace(fragments[0]+"_", ''));
|
||||
for(i=0; i< sp_base.length; i++){
|
||||
var broken = false;
|
||||
var res = print_diff(sp_base[i], sp_newtext[i]);
|
||||
var compensator=0;
|
||||
if(sp_base[i] !== ""){
|
||||
while(sp_base[i].substr(0, sp_base[i].length-2) !== first_column[i+compensator]){
|
||||
if(compensator >10){
|
||||
broken=true;
|
||||
break;
|
||||
}
|
||||
compensator++;
|
||||
}
|
||||
}
|
||||
else{
|
||||
while(sp_newtext[i].substr(0, sp_newtext[i].length-2) !== first_column[i+compensator]){
|
||||
if(compensator >10){
|
||||
broken=true;
|
||||
break;
|
||||
}
|
||||
compensator++;
|
||||
}
|
||||
}
|
||||
if(broken)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
var new_line=first_column[i+compensator]+"||"+"<td style='width: 25px; text-align: right;";
|
||||
var result="";
|
||||
if(res[0]===""){
|
||||
if(res[1] !==""){
|
||||
result+="+";
|
||||
}
|
||||
}
|
||||
else {
|
||||
result+="<a href=\""+URL_testsuite+baseTest+"/"+first_column[i+compensator]+"/TestReport_"+name+".gz\">"+res[0]+"</a>\/";
|
||||
}
|
||||
|
||||
if(res[1]===""){
|
||||
if(res[0]!==""){
|
||||
result+="-";
|
||||
}
|
||||
}
|
||||
else {
|
||||
result+="<a href=\""+URL_testsuite+newTest+"/"+first_column[i+compensator]+"/TestReport_"+name+".gz\">"+res[1]+"</a>";
|
||||
}
|
||||
if(res[1] === "w"){
|
||||
new_line+=" background-color: rgb(100%,100%,50%)'> "+result;
|
||||
} else if(res[1]=== "r"){
|
||||
new_line+=" background-color: rgb(65%,65%,100%)'> "+result;
|
||||
} else if(res[1]=== "n"){
|
||||
new_line+=" background-color: rgb(100%,50%,50%)'> "+result;
|
||||
}
|
||||
else if(res[1]==="" && res[0]!==""){
|
||||
new_line+=" background-color: rgb(50%,25%,75%)'>"+result;
|
||||
}
|
||||
else{
|
||||
new_line+="'>";
|
||||
}
|
||||
new_line+="</td>";
|
||||
new_column.push(new_line);
|
||||
}
|
||||
myArray.push(new_column);
|
||||
}
|
||||
}
|
||||
|
||||
return [myArray, diffArray];
|
||||
}
|
||||
|
|
@ -0,0 +1,409 @@
|
|||
/***
|
||||
This is part of jsdifflib v1.0. <http://snowtide.com/jsdifflib>
|
||||
Copyright (c) 2007, Snowtide Informatics Systems, Inc.
|
||||
All rights reserved.
|
||||
Redistribution and use in source and binary forms, with or without modification,
|
||||
are permitted provided that the following conditions are met:
|
||||
* Redistributions of source code must retain the above copyright notice, this
|
||||
list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above copyright notice,
|
||||
this list of conditions and the following disclaimer in the documentation
|
||||
and/or other materials provided with the distribution.
|
||||
* Neither the name of the Snowtide Informatics Systems nor the names of its
|
||||
contributors may be used to endorse or promote products derived from this
|
||||
software without specific prior written permission.
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
|
||||
EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
|
||||
SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
|
||||
TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
|
||||
BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
|
||||
ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
|
||||
DAMAGE.
|
||||
***/
|
||||
/* Author: Chas Emerick <cemerick@snowtide.com> */
|
||||
var __whitespace = {" ":true, "\t":true, "\n":true, "\f":true, "\r":true};
|
||||
|
||||
var difflib = {
|
||||
defaultJunkFunction: function (c) {
|
||||
return __whitespace.hasOwnProperty(c);
|
||||
},
|
||||
|
||||
stripLinebreaks: function (str) { return str.replace(/^[\n\r]*|[\n\r]*$/g, ""); },
|
||||
|
||||
stringAsLines: function (str) {
|
||||
var lfpos = str.indexOf("\n");
|
||||
var crpos = str.indexOf("\r");
|
||||
var linebreak = ((lfpos > -1 && crpos > -1) || crpos < 0) ? "\n" : "\r";
|
||||
|
||||
var lines = str.split(linebreak);
|
||||
for (var i = 0; i < lines.length; i++) {
|
||||
lines[i] = difflib.stripLinebreaks(lines[i]);
|
||||
}
|
||||
|
||||
return lines;
|
||||
},
|
||||
|
||||
// iteration-based reduce implementation
|
||||
__reduce: function (func, list, initial) {
|
||||
if (initial != null) {
|
||||
var value = initial;
|
||||
var idx = 0;
|
||||
} else if (list) {
|
||||
var value = list[0];
|
||||
var idx = 1;
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
|
||||
for (; idx < list.length; idx++) {
|
||||
value = func(value, list[idx]);
|
||||
}
|
||||
|
||||
return value;
|
||||
},
|
||||
|
||||
// comparison function for sorting lists of numeric tuples
|
||||
__ntuplecomp: function (a, b) {
|
||||
var mlen = Math.max(a.length, b.length);
|
||||
for (var i = 0; i < mlen; i++) {
|
||||
if (a[i] < b[i]) return -1;
|
||||
if (a[i] > b[i]) return 1;
|
||||
}
|
||||
|
||||
return a.length == b.length ? 0 : (a.length < b.length ? -1 : 1);
|
||||
},
|
||||
|
||||
__calculate_ratio: function (matches, length) {
|
||||
return length ? 2.0 * matches / length : 1.0;
|
||||
},
|
||||
|
||||
// returns a function that returns true if a key passed to the returned function
|
||||
// is in the dict (js object) provided to this function; replaces being able to
|
||||
// carry around dict.has_key in python...
|
||||
__isindict: function (dict) {
|
||||
return function (key) { return dict.hasOwnProperty(key); };
|
||||
},
|
||||
|
||||
// replacement for python's dict.get function -- need easy default values
|
||||
__dictget: function (dict, key, defaultValue) {
|
||||
return dict.hasOwnProperty(key) ? dict[key] : defaultValue;
|
||||
},
|
||||
|
||||
SequenceMatcher: function (a, b, isjunk) {
|
||||
this.set_seqs = function (a, b) {
|
||||
this.set_seq1(a);
|
||||
this.set_seq2(b);
|
||||
}
|
||||
|
||||
this.set_seq1 = function (a) {
|
||||
if (a == this.a) return;
|
||||
this.a = a;
|
||||
this.matching_blocks = this.opcodes = null;
|
||||
}
|
||||
|
||||
this.set_seq2 = function (b) {
|
||||
if (b == this.b) return;
|
||||
this.b = b;
|
||||
this.matching_blocks = this.opcodes = this.fullbcount = null;
|
||||
this.__chain_b();
|
||||
}
|
||||
|
||||
this.__chain_b = function () {
|
||||
var b = this.b;
|
||||
var n = b.length;
|
||||
var b2j = this.b2j = {};
|
||||
var populardict = {};
|
||||
for (var i = 0; i < b.length; i++) {
|
||||
var elt = b[i];
|
||||
if (b2j.hasOwnProperty(elt)) {
|
||||
var indices = b2j[elt];
|
||||
if (n >= 200 && indices.length * 100 > n) {
|
||||
populardict[elt] = 1;
|
||||
delete b2j[elt];
|
||||
} else {
|
||||
indices.push(i);
|
||||
}
|
||||
} else {
|
||||
b2j[elt] = [i];
|
||||
}
|
||||
}
|
||||
|
||||
for (var elt in populardict) {
|
||||
if (populardict.hasOwnProperty(elt)) {
|
||||
delete b2j[elt];
|
||||
}
|
||||
}
|
||||
|
||||
var isjunk = this.isjunk;
|
||||
var junkdict = {};
|
||||
if (isjunk) {
|
||||
for (var elt in populardict) {
|
||||
if (populardict.hasOwnProperty(elt) && isjunk(elt)) {
|
||||
junkdict[elt] = 1;
|
||||
delete populardict[elt];
|
||||
}
|
||||
}
|
||||
for (var elt in b2j) {
|
||||
if (b2j.hasOwnProperty(elt) && isjunk(elt)) {
|
||||
junkdict[elt] = 1;
|
||||
delete b2j[elt];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
this.isbjunk = difflib.__isindict(junkdict);
|
||||
this.isbpopular = difflib.__isindict(populardict);
|
||||
}
|
||||
|
||||
this.find_longest_match = function (alo, ahi, blo, bhi) {
|
||||
var a = this.a;
|
||||
var b = this.b;
|
||||
var b2j = this.b2j;
|
||||
var isbjunk = this.isbjunk;
|
||||
var besti = alo;
|
||||
var bestj = blo;
|
||||
var bestsize = 0;
|
||||
var j = null;
|
||||
var k;
|
||||
|
||||
var j2len = {};
|
||||
var nothing = [];
|
||||
for (var i = alo; i < ahi; i++) {
|
||||
var newj2len = {};
|
||||
var jdict = difflib.__dictget(b2j, a[i], nothing);
|
||||
for (var jkey in jdict) {
|
||||
if (jdict.hasOwnProperty(jkey)) {
|
||||
j = jdict[jkey];
|
||||
if (j < blo) continue;
|
||||
if (j >= bhi) break;
|
||||
newj2len[j] = k = difflib.__dictget(j2len, j - 1, 0) + 1;
|
||||
if (k > bestsize) {
|
||||
besti = i - k + 1;
|
||||
bestj = j - k + 1;
|
||||
bestsize = k;
|
||||
}
|
||||
}
|
||||
}
|
||||
j2len = newj2len;
|
||||
}
|
||||
|
||||
while (besti > alo && bestj > blo && !isbjunk(b[bestj - 1]) && a[besti - 1] == b[bestj - 1]) {
|
||||
besti--;
|
||||
bestj--;
|
||||
bestsize++;
|
||||
}
|
||||
|
||||
while (besti + bestsize < ahi && bestj + bestsize < bhi &&
|
||||
!isbjunk(b[bestj + bestsize]) &&
|
||||
a[besti + bestsize] == b[bestj + bestsize]) {
|
||||
bestsize++;
|
||||
}
|
||||
|
||||
while (besti > alo && bestj > blo && isbjunk(b[bestj - 1]) && a[besti - 1] == b[bestj - 1]) {
|
||||
besti--;
|
||||
bestj--;
|
||||
bestsize++;
|
||||
}
|
||||
|
||||
while (besti + bestsize < ahi && bestj + bestsize < bhi && isbjunk(b[bestj + bestsize]) &&
|
||||
a[besti + bestsize] == b[bestj + bestsize]) {
|
||||
bestsize++;
|
||||
}
|
||||
|
||||
return [besti, bestj, bestsize];
|
||||
}
|
||||
|
||||
this.get_matching_blocks = function () {
|
||||
if (this.matching_blocks != null) return this.matching_blocks;
|
||||
var la = this.a.length;
|
||||
var lb = this.b.length;
|
||||
|
||||
var queue = [[0, la, 0, lb]];
|
||||
var matching_blocks = [];
|
||||
var alo, ahi, blo, bhi, qi, i, j, k, x;
|
||||
while (queue.length) {
|
||||
qi = queue.pop();
|
||||
alo = qi[0];
|
||||
ahi = qi[1];
|
||||
blo = qi[2];
|
||||
bhi = qi[3];
|
||||
x = this.find_longest_match(alo, ahi, blo, bhi);
|
||||
i = x[0];
|
||||
j = x[1];
|
||||
k = x[2];
|
||||
|
||||
if (k) {
|
||||
matching_blocks.push(x);
|
||||
if (alo < i && blo < j)
|
||||
queue.push([alo, i, blo, j]);
|
||||
if (i+k < ahi && j+k < bhi)
|
||||
queue.push([i + k, ahi, j + k, bhi]);
|
||||
}
|
||||
}
|
||||
|
||||
matching_blocks.sort(difflib.__ntuplecomp);
|
||||
|
||||
var i1 = 0, j1 = 0, k1 = 0, block = 0;
|
||||
var i2, j2, k2;
|
||||
var non_adjacent = [];
|
||||
for (var idx in matching_blocks) {
|
||||
if (matching_blocks.hasOwnProperty(idx)) {
|
||||
block = matching_blocks[idx];
|
||||
i2 = block[0];
|
||||
j2 = block[1];
|
||||
k2 = block[2];
|
||||
if (i1 + k1 == i2 && j1 + k1 == j2) {
|
||||
k1 += k2;
|
||||
} else {
|
||||
if (k1) non_adjacent.push([i1, j1, k1]);
|
||||
i1 = i2;
|
||||
j1 = j2;
|
||||
k1 = k2;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (k1) non_adjacent.push([i1, j1, k1]);
|
||||
|
||||
non_adjacent.push([la, lb, 0]);
|
||||
this.matching_blocks = non_adjacent;
|
||||
return this.matching_blocks;
|
||||
}
|
||||
|
||||
this.get_opcodes = function () {
|
||||
if (this.opcodes != null) return this.opcodes;
|
||||
var i = 0;
|
||||
var j = 0;
|
||||
var answer = [];
|
||||
this.opcodes = answer;
|
||||
var block, ai, bj, size, tag;
|
||||
var blocks = this.get_matching_blocks();
|
||||
for (var idx in blocks) {
|
||||
if (blocks.hasOwnProperty(idx)) {
|
||||
block = blocks[idx];
|
||||
ai = block[0];
|
||||
bj = block[1];
|
||||
size = block[2];
|
||||
tag = '';
|
||||
if (i < ai && j < bj) {
|
||||
tag = 'replace';
|
||||
} else if (i < ai) {
|
||||
tag = 'delete';
|
||||
} else if (j < bj) {
|
||||
tag = 'insert';
|
||||
}
|
||||
if (tag) answer.push([tag, i, ai, j, bj]);
|
||||
i = ai + size;
|
||||
j = bj + size;
|
||||
|
||||
if (size) answer.push(['equal', ai, i, bj, j]);
|
||||
}
|
||||
}
|
||||
|
||||
return answer;
|
||||
}
|
||||
|
||||
// this is a generator function in the python lib, which of course is not supported in javascript
|
||||
// the reimplementation builds up the grouped opcodes into a list in their entirety and returns that.
|
||||
this.get_grouped_opcodes = function (n) {
|
||||
if (!n) n = 3;
|
||||
var codes = this.get_opcodes();
|
||||
if (!codes) codes = [["equal", 0, 1, 0, 1]];
|
||||
var code, tag, i1, i2, j1, j2;
|
||||
if (codes[0][0] == 'equal') {
|
||||
code = codes[0];
|
||||
tag = code[0];
|
||||
i1 = code[1];
|
||||
i2 = code[2];
|
||||
j1 = code[3];
|
||||
j2 = code[4];
|
||||
codes[0] = [tag, Math.max(i1, i2 - n), i2, Math.max(j1, j2 - n), j2];
|
||||
}
|
||||
if (codes[codes.length - 1][0] == 'equal') {
|
||||
code = codes[codes.length - 1];
|
||||
tag = code[0];
|
||||
i1 = code[1];
|
||||
i2 = code[2];
|
||||
j1 = code[3];
|
||||
j2 = code[4];
|
||||
codes[codes.length - 1] = [tag, i1, Math.min(i2, i1 + n), j1, Math.min(j2, j1 + n)];
|
||||
}
|
||||
|
||||
var nn = n + n;
|
||||
var group = [];
|
||||
var groups = [];
|
||||
for (var idx in codes) {
|
||||
if (codes.hasOwnProperty(idx)) {
|
||||
code = codes[idx];
|
||||
tag = code[0];
|
||||
i1 = code[1];
|
||||
i2 = code[2];
|
||||
j1 = code[3];
|
||||
j2 = code[4];
|
||||
if (tag == 'equal' && i2 - i1 > nn) {
|
||||
group.push([tag, i1, Math.min(i2, i1 + n), j1, Math.min(j2, j1 + n)]);
|
||||
groups.push(group);
|
||||
group = [];
|
||||
i1 = Math.max(i1, i2-n);
|
||||
j1 = Math.max(j1, j2-n);
|
||||
}
|
||||
|
||||
group.push([tag, i1, i2, j1, j2]);
|
||||
}
|
||||
}
|
||||
|
||||
if (group && !(group.length == 1 && group[0][0] == 'equal')) groups.push(group)
|
||||
|
||||
return groups;
|
||||
}
|
||||
|
||||
this.ratio = function () {
|
||||
matches = difflib.__reduce(
|
||||
function (sum, triple) { return sum + triple[triple.length - 1]; },
|
||||
this.get_matching_blocks(), 0);
|
||||
return difflib.__calculate_ratio(matches, this.a.length + this.b.length);
|
||||
}
|
||||
|
||||
this.quick_ratio = function () {
|
||||
var fullbcount, elt;
|
||||
if (this.fullbcount == null) {
|
||||
this.fullbcount = fullbcount = {};
|
||||
for (var i = 0; i < this.b.length; i++) {
|
||||
elt = this.b[i];
|
||||
fullbcount[elt] = difflib.__dictget(fullbcount, elt, 0) + 1;
|
||||
}
|
||||
}
|
||||
fullbcount = this.fullbcount;
|
||||
|
||||
var avail = {};
|
||||
var availhas = difflib.__isindict(avail);
|
||||
var matches = numb = 0;
|
||||
for (var i = 0; i < this.a.length; i++) {
|
||||
elt = this.a[i];
|
||||
if (availhas(elt)) {
|
||||
numb = avail[elt];
|
||||
} else {
|
||||
numb = difflib.__dictget(fullbcount, elt, 0);
|
||||
}
|
||||
avail[elt] = numb - 1;
|
||||
if (numb > 0) matches++;
|
||||
}
|
||||
|
||||
return difflib.__calculate_ratio(matches, this.a.length + this.b.length);
|
||||
}
|
||||
|
||||
this.real_quick_ratio = function () {
|
||||
var la = this.a.length;
|
||||
var lb = this.b.length;
|
||||
return _calculate_ratio(Math.min(la, lb), la + lb);
|
||||
}
|
||||
|
||||
this.isjunk = isjunk ? isjunk : difflib.defaultJunkFunction;
|
||||
this.a = this.b = null;
|
||||
this.set_seqs(a, b);
|
||||
}
|
||||
};
|
||||
|
||||
|
|
@ -0,0 +1,47 @@
|
|||
/* Author: Maxime Gimeno <maxime.gimeno@gmail.com> */
|
||||
|
||||
/***
|
||||
This is designed to treat lines from CGAL testsuites results files,
|
||||
of the form Package_name [r/y/w/n].
|
||||
|
||||
Input : 2 arrays of string, sorted by alphabetical order.
|
||||
|
||||
Output: the arrays, alphabetically sorted, of the same size, filled with
|
||||
empty strings.
|
||||
|
||||
Short: Equalizes the sizes of the two inpu arrays by adding empty strings.
|
||||
|
||||
Detailed: for each element of the smaller input,
|
||||
if base[i] != newtest[i] (not taking the last char into account),
|
||||
adds an empty string in the input that is missing this entry,
|
||||
based on the alphabetical order. Once it is done, will fill the smaller array
|
||||
with empty strings if necessary.
|
||||
|
||||
|
||||
***/
|
||||
function addMissingLines(base, newtext){
|
||||
for(i=0, j=0; i<Math.min(base.length, newtext.length); i++, j++)
|
||||
{
|
||||
if(base[i].substr(0, base[i].length-2) != newtext[i].substr(0,newtext[i].length-2) ) {
|
||||
var tmp = [base[i], newtext[i]];
|
||||
tmp.sort();
|
||||
if(tmp[0] == base[i]){
|
||||
newtext.splice(i, 0, "");
|
||||
} else {
|
||||
base.splice(i, 0, "");
|
||||
}
|
||||
}
|
||||
}
|
||||
var minsize = base.length;
|
||||
var maxsize = newtext.length;
|
||||
var to_fill = base;
|
||||
if(base.length>newtext.length){
|
||||
minsize = newtext.length;
|
||||
maxsize = base.length;
|
||||
to_fill = newtext;
|
||||
}
|
||||
for(i = minsize; i < maxsize; i++)
|
||||
{
|
||||
to_fill.push("");
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,44 @@
|
|||
/* Author: Maxime Gimeno <maxime.gimeno@gmail.com> */
|
||||
/***
|
||||
Need difflib.js
|
||||
|
||||
Input : 2 strings
|
||||
|
||||
Output: res. Contains the difference between the two input strings.
|
||||
|
||||
According to the result of difflib, will output :
|
||||
- replace : -base, +newtext (the two input differs, but none are empty)
|
||||
- insert: +newtext (the first input is empty)
|
||||
- delete: -base (the second input is empty)
|
||||
***/
|
||||
|
||||
function print_diff(base, newtext){
|
||||
// create a SequenceMatcher instance that diffs the two sets of lines
|
||||
var sm = new difflib.SequenceMatcher(base, newtext);
|
||||
// get the opcodes from the SequenceMatcher instance
|
||||
// opcodes is a list of 3-tuples describing what changes should be made to the base text
|
||||
// in order to yield the new text
|
||||
var opcodes = sm.get_opcodes();
|
||||
var res=["",""];
|
||||
for (var idx = 0; idx < opcodes.length; idx++) {
|
||||
code = opcodes[idx];
|
||||
change = code[0];
|
||||
var b = code[1];
|
||||
var be = code[2];
|
||||
var n = code[3];
|
||||
var ne = code[4];
|
||||
if(newtext.charAt(newtext.length-1) !== "y"
|
||||
&& change != "equal"){
|
||||
res[0]=base.charAt(base.length-1);
|
||||
res[1]=newtext.charAt(newtext.length-1);
|
||||
}
|
||||
//else if(change == "insert") {
|
||||
// res=newtext.charAt(newtext.length-1);
|
||||
//}
|
||||
//else if(change == "delete") {
|
||||
// res="-";
|
||||
//}
|
||||
//}
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
|
@ -0,0 +1,51 @@
|
|||
<!doctype html>
|
||||
<html style='height: 100%'>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>Combo Box Test</title>
|
||||
<script type="text/javascript" src="diff_testsuites.js"></script>
|
||||
|
||||
<body style='background-color: #C0C0D0; min-height: 100%;'>
|
||||
|
||||
<button type="button" id='button'>
|
||||
Wait 1s.
|
||||
</button>
|
||||
|
||||
<script type="text/javascript">
|
||||
|
||||
|
||||
function prendDuTemps(onSuccess) {
|
||||
setTimeout(
|
||||
function() {
|
||||
if(onSuccess) {
|
||||
onSuccess()
|
||||
}
|
||||
},
|
||||
100);
|
||||
}
|
||||
|
||||
function boucleSynchrone(i) {
|
||||
if(i<10) {
|
||||
prendDuTemps(
|
||||
function(){
|
||||
console.log("blah"+i);
|
||||
boucleSynchrone(i+1);
|
||||
}
|
||||
);
|
||||
}
|
||||
else
|
||||
{
|
||||
document.body.style.cursor = 'default';
|
||||
}
|
||||
|
||||
}
|
||||
function clickDiv() {
|
||||
document.body.style.cursor = 'wait';
|
||||
boucleSynchrone(0);
|
||||
}
|
||||
|
||||
var button = document.getElementById('button');
|
||||
button.onclick=clickDiv;
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
|
|
@ -0,0 +1,62 @@
|
|||
|
||||
|
||||
onmessage=function(e){
|
||||
importScripts('difflib.js', 'diff_testsuites.js');
|
||||
importScripts('fill_empty_lines.js','print_diff.js');
|
||||
var res_arrays = diff_testsuites(e.data[0],e.data[1]);
|
||||
var myArray = res_arrays[0];
|
||||
var diffArray = res_arrays[1];
|
||||
for(var i=0; i<diffArray.length; i++){
|
||||
postMessage(["diffPlatforms","<tr><td>"+ diffArray[i]+"</td></tr>"]);
|
||||
}
|
||||
postMessage(["diffPlatforms", "</table>"]);
|
||||
//pass over My Array to equalize columns length
|
||||
|
||||
var max_length=myArray[0].length;
|
||||
for( i = 1; i< myArray.length; ++i){
|
||||
var length = myArray[i].length;
|
||||
if(length === max_length){ continue; }
|
||||
for(var j=2; j<length;j++){
|
||||
var base_line = myArray[i][j];
|
||||
var max_line = myArray[0][j];
|
||||
var base_identifier=base_line.split("||")[0];
|
||||
var max_identifier=max_line.split("||")[0];
|
||||
if(base_identifier !== max_identifier) {
|
||||
myArray[i].splice(j, 0, "<td></td>");
|
||||
}
|
||||
}
|
||||
var minsize = myArray[i].length;
|
||||
|
||||
for(k = minsize; k < myArray[0].length; k++)
|
||||
{
|
||||
myArray[i].push("<td></td>");
|
||||
}
|
||||
}
|
||||
|
||||
for(i=1; i<myArray.length; i++){
|
||||
postMessage(["namesTable","<tr><td>"+i+": </td><td>"+ myArray[i][0]+"</td></tr>"]);
|
||||
}
|
||||
postMessage(["namesTable", "</table>"]);
|
||||
|
||||
postMessage(["testTable", "<tr><td style='width: 25px;'>Platform: </td>"]);
|
||||
for(i=1; i<myArray.length; i++)
|
||||
{
|
||||
postMessage(["testTable", "<td style='width: 25px; text-align: right;'>" + i + "</td>"]);
|
||||
}
|
||||
postMessage(["testTable", "</tr>"]);
|
||||
for (var j=2; j<myArray[0].length; j++) {
|
||||
postMessage(["testTable", "<tr><td style='width: 25px;'>"+ myArray[0][j]+": </td>"]);
|
||||
for(i=1; i<myArray.length; i++)
|
||||
{
|
||||
var sp = myArray[i][j].split("||");
|
||||
if(sp.length === 1){
|
||||
postMessage(["testTable", myArray[i][j]]);
|
||||
} else{
|
||||
postMessage(["testTable", sp[1]]);
|
||||
}
|
||||
}
|
||||
postMessage(["testTable", "</tr>"]);
|
||||
}
|
||||
postMessage(["testTable", "</table></body>"]);
|
||||
postMessage(["finished"]);
|
||||
}
|
||||
|
|
@ -89,7 +89,7 @@ public:
|
|||
|
||||
/**
|
||||
* The following map tells what vertices are in the cluster and if
|
||||
* the corresponding segment has been splitted once.
|
||||
* the corresponding segment has been split once.
|
||||
*/
|
||||
typedef std::map<Vertex_handle, bool> Vertices_map;
|
||||
Vertices_map vertices;
|
||||
|
|
|
|||
|
|
@ -493,7 +493,7 @@ public:
|
|||
/** This version computes the refinement point without handling
|
||||
clusters. The refinement point of an edge is just the middle point of
|
||||
the segment.
|
||||
Saves the handles of the edge that will be splitted.
|
||||
Saves the handles of the edge that will be split.
|
||||
This function is overridden in class Refine_edge_with_clusters.
|
||||
*/
|
||||
Point refinement_point_impl(const Edge& edge)
|
||||
|
|
|
|||
|
|
@ -106,9 +106,8 @@ public Q_SLOTS:
|
|||
|
||||
void insert_mp() {
|
||||
insert_point(moving_point);
|
||||
QString str;
|
||||
ui->viewer->displayMessage(str.sprintf("Added point (%f, %f, %f)",
|
||||
moving_point.x(),moving_point.y(),moving_point.z()));
|
||||
ui->viewer->displayMessage(QString("Added point (%1, %2, %3)").arg(
|
||||
moving_point.x()).arg(moving_point.y()).arg(moving_point.z()));
|
||||
changed();
|
||||
}
|
||||
|
||||
|
|
@ -117,9 +116,8 @@ public Q_SLOTS:
|
|||
Point pt = *rp+Vector(0.5,0.5,0.5);
|
||||
rp++;
|
||||
insert_point(Point(pt.x(),pt.y(),(in_plane? 0.0:pt.z())));
|
||||
QString str;
|
||||
ui->viewer->displayMessage(str.sprintf("Added point (%f, %f, %f)",
|
||||
pt.x(),pt.y(),(in_plane? 0.0:pt.z())));
|
||||
ui->viewer->displayMessage(QString("Added point (%1, %2, %3)").arg(
|
||||
pt.x()).arg(pt.y()).arg((in_plane? 0.0:pt.z())));
|
||||
changed();
|
||||
}
|
||||
void insert_point(Point p) {
|
||||
|
|
|
|||
|
|
@ -231,6 +231,18 @@ public:
|
|||
return *this;
|
||||
}
|
||||
|
||||
/// \cond SKIP_IN_MANUAL
|
||||
// copy constructor (same as assignment)
|
||||
Point_set_3 (const Point_set_3& ps)
|
||||
{
|
||||
m_base = ps.m_base;
|
||||
m_indices = this->property_map<Index> ("index").first;
|
||||
m_points = this->property_map<Point> ("point").first;
|
||||
m_normals = this->property_map<Vector> ("normal").first;
|
||||
m_nb_removed = ps.m_nb_removed;
|
||||
}
|
||||
/// \endcond
|
||||
|
||||
/// @}
|
||||
|
||||
/// \cond SKIP_IN_MANUAL
|
||||
|
|
|
|||
|
|
@ -404,31 +404,28 @@ still ensuring that the total sum of the coordinates is `1`.
|
|||
<b>Default:</b> `0`
|
||||
\cgalNPEnd
|
||||
|
||||
\cgalNPBegin{use_angle_smoothing_t} \anchor PMP_use_angle_smoothing
|
||||
\cgalNPBegin{use_angle_smoothing} \anchor PMP_use_angle_smoothing
|
||||
Parameter used in the function `smooth_mesh()` to indicate if angle-based smoothing should be used.
|
||||
When this type of smoothing is used, the algorithm attempts to equalize angles incident to each vertex.
|
||||
|
||||
\n
|
||||
<b>Type:</b> `bool` \n
|
||||
<b>Default:</b> `true`
|
||||
\cgalNPEnd
|
||||
|
||||
\cgalNPBegin{use_area_smoothing_t} \anchor PMP_use_area_smoothing
|
||||
\cgalNPBegin{use_area_smoothing} \anchor PMP_use_area_smoothing
|
||||
Parameter used in the function `smooth_mesh()` to indicate if area-based smoothing should be used.
|
||||
When this type of smoothing is used, the algorithm attempts to equalize the areas of the triangles
|
||||
incident to each vertex. Since this can create elongated triangles, a second phase uses Delaunay-based
|
||||
flips to recover good shapes, unless specified otherwise (see below).
|
||||
|
||||
\n
|
||||
<b>Type:</b> `bool` \n
|
||||
<b>Default:</b> `true`
|
||||
\cgalNPEnd
|
||||
|
||||
\cgalNPBegin{use_Delaunay_flips_t} \anchor PMP_use_Delaunay_flips
|
||||
\cgalNPBegin{use_Delaunay_flips} \anchor PMP_use_Delaunay_flips
|
||||
Parameter used in the function `smooth_mesh()` to indicate if Delaunay-based flips should be used
|
||||
after area-based smoothing has been performed. A user wishing to preserve combinatorial information
|
||||
can set this parameter to `false`, but the mesh might have elongated elements.
|
||||
|
||||
\n
|
||||
<b>Type:</b> `bool` \n
|
||||
<b>Default:</b> `true`
|
||||
|
|
@ -439,7 +436,6 @@ Parameter used in the function `smooth_mesh()` to indicate if some sanity checks
|
|||
if the move of a vertex should be applied or rejected. These sanity checks consists of checking that
|
||||
no face incident to the vertex becomes inverted and that the minimum angle of the incident faces
|
||||
is not decreased by the move.
|
||||
|
||||
\n
|
||||
<b>Type:</b> `bool` \n
|
||||
<b>Default:</b> `true`
|
||||
|
|
@ -449,7 +445,6 @@ is not decreased by the move.
|
|||
Parameter used in the functions `keep_large_connected_components()` and
|
||||
`keep_largest_connected_components()` to pass a property map that gives the size of a face when
|
||||
evaluating the size of a connected component (which is defined as the sum of the sizes of its faces).
|
||||
|
||||
\n
|
||||
<b>Type:</b> a class model of `ReadablePropertyMap` with
|
||||
`boost::graph_traits<PolygonMesh>::%face_descriptor` as key type and
|
||||
|
|
@ -457,6 +452,33 @@ a value type supporting construction from `0`, `operator+=()`, and comparison op
|
|||
<b>Default:</b> `CGAL::Constant_property_map<face_descriptor, std::size_t>` with value `1`
|
||||
\cgalNPEnd
|
||||
|
||||
\cgalNPBegin{area_threshold} \anchor PMP_area_threshold
|
||||
Parameter used in the function `remove_connected_components_of_negligible_size()`
|
||||
to pass a threshold value such that all connected components with an area smaller
|
||||
than this value are removed from the mesh.
|
||||
\n
|
||||
<b>Type:</b> `Kernel::FT` \n
|
||||
<b>Default:</b> The square of one percent of the length of the diagonal of the bounding box of the mesh.
|
||||
\cgalNPEnd
|
||||
|
||||
\cgalNPBegin{volume_threshold} \anchor PMP_volume_threshold
|
||||
Parameter used in the function `remove_connected_components_of_negligible_size()`
|
||||
to pass a threshold value such that all (closed) connected components with a volume smaller
|
||||
than this value are removed from the mesh.
|
||||
\n
|
||||
<b>Type:</b> `Kernel::FT` \n
|
||||
<b>Default:</b> The third power of one percent of the length of the diagonal of the bounding box of the mesh.
|
||||
\cgalNPEnd
|
||||
|
||||
|
||||
\cgalNPBegin{dry_run} \anchor PMP_dry_run
|
||||
Parameter that tells a function not to alter the input, but rather to only return the expected result.
|
||||
It is for example used in the fucntion `keep_large_connected_components()`.
|
||||
\n
|
||||
<b>Type:</b> `bool` \n
|
||||
<b>Default:</b> `false`
|
||||
\cgalNPEnd
|
||||
|
||||
\cgalNPTableEnd
|
||||
|
||||
*/
|
||||
|
|
|
|||
|
|
@ -155,6 +155,7 @@ and provides a list of the parameters that are used in this package.
|
|||
- `CGAL::Polygon_mesh_processing::duplicate_non_manifold_vertices()`
|
||||
- `CGAL::Polygon_mesh_processing::merge_duplicated_vertices_in_boundary_cycle()`
|
||||
- `CGAL::Polygon_mesh_processing::merge_duplicated_vertices_in_boundary_cycles()`
|
||||
- `CGAL::Polygon_mesh_processing::remove_connected_components_of_negligible_size()`
|
||||
|
||||
\cgalCRPSection{Normal Computation Functions}
|
||||
- `CGAL::Polygon_mesh_processing::compute_face_normal()`
|
||||
|
|
|
|||
|
|
@ -6,7 +6,10 @@
|
|||
#include <iostream>
|
||||
#include <fstream>
|
||||
|
||||
namespace PMP = CGAL::Polygon_mesh_processing;
|
||||
|
||||
typedef CGAL::Exact_predicates_inexact_constructions_kernel K;
|
||||
|
||||
typedef K::Point_3 Point;
|
||||
typedef K::Vector_3 Vector;
|
||||
|
||||
|
|
@ -25,24 +28,18 @@ int main(int argc, char* argv[])
|
|||
return 1;
|
||||
}
|
||||
|
||||
auto fnormals = mesh.add_property_map<face_descriptor, Vector>
|
||||
("f:normals", CGAL::NULL_VECTOR).first;
|
||||
auto vnormals = mesh.add_property_map<vertex_descriptor, Vector>
|
||||
("v:normals", CGAL::NULL_VECTOR).first;
|
||||
auto vnormals = mesh.add_property_map<vertex_descriptor, Vector>("v:normals", CGAL::NULL_VECTOR).first;
|
||||
auto fnormals = mesh.add_property_map<face_descriptor, Vector>("f:normals", CGAL::NULL_VECTOR).first;
|
||||
|
||||
CGAL::Polygon_mesh_processing::compute_normals(mesh,
|
||||
vnormals,
|
||||
fnormals,
|
||||
CGAL::Polygon_mesh_processing::parameters::vertex_point_map(mesh.points()).
|
||||
geom_traits(K()));
|
||||
PMP::compute_normals(mesh, vnormals, fnormals);
|
||||
|
||||
std::cout << "Vertex normals :" << std::endl;
|
||||
for(vertex_descriptor vd: vertices(mesh))
|
||||
std::cout << vnormals[vd] << std::endl;
|
||||
|
||||
std::cout << "Face normals :" << std::endl;
|
||||
for(face_descriptor fd: faces(mesh)){
|
||||
for(face_descriptor fd: faces(mesh))
|
||||
std::cout << fnormals[fd] << std::endl;
|
||||
}
|
||||
std::cout << "Vertex normals :" << std::endl;
|
||||
for(vertex_descriptor vd: vertices(mesh)){
|
||||
std::cout << vnormals[vd] << std::endl;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
// Copyright (c) 2015 GeometryFactory (France).
|
||||
// Copyright (c) 2015-2019 GeometryFactory (France).
|
||||
// All rights reserved.
|
||||
//
|
||||
// This file is part of CGAL (www.cgal.org).
|
||||
|
|
@ -9,51 +9,62 @@
|
|||
//
|
||||
//
|
||||
// Author(s) : Jane Tournois
|
||||
|
||||
// Mael Rouxel-Labbé
|
||||
|
||||
#ifndef CGAL_POLYGON_MESH_PROCESSING_COMPUTE_NORMAL_H
|
||||
#define CGAL_POLYGON_MESH_PROCESSING_COMPUTE_NORMAL_H
|
||||
|
||||
#include <CGAL/license/Polygon_mesh_processing/Compute_normal.h>
|
||||
|
||||
|
||||
#include <CGAL/boost/graph/helpers.h>
|
||||
#include <CGAL/boost/graph/properties.h>
|
||||
#include <boost/graph/graph_traits.hpp>
|
||||
#include <CGAL/Origin.h>
|
||||
#include <CGAL/Kernel/global_functions_3.h>
|
||||
#include <CGAL/Kernel_traits.h>
|
||||
|
||||
#include <CGAL/Polygon_mesh_processing/internal/named_function_params.h>
|
||||
#include <CGAL/Polygon_mesh_processing/internal/named_params_helper.h>
|
||||
|
||||
#include <boost/type_traits.hpp>
|
||||
#include <CGAL/boost/graph/helpers.h>
|
||||
#include <CGAL/boost/graph/properties.h>
|
||||
#include <CGAL/Dynamic_property_map.h>
|
||||
#include <CGAL/Origin.h>
|
||||
|
||||
#include <boost/graph/graph_traits.hpp>
|
||||
|
||||
#include <iostream>
|
||||
#include <utility>
|
||||
#include <vector>
|
||||
|
||||
#ifdef CGAL_PMP_COMPUTE_NORMAL_DEBUG_PP
|
||||
# ifndef CGAL_PMP_COMPUTE_NORMAL_DEBUG
|
||||
# define CGAL_PMP_COMPUTE_NORMAL_DEBUG
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#ifdef CGAL_PMP_COMPUTE_NORMAL_DEBUG
|
||||
#include <fstream>
|
||||
#include <CGAL/Polygon_mesh_processing/bbox.h>
|
||||
#endif
|
||||
|
||||
namespace CGAL {
|
||||
|
||||
namespace Polygon_mesh_processing {
|
||||
|
||||
namespace internal {
|
||||
|
||||
template <class GT>
|
||||
void normalize(typename GT::Vector_3& v, const GT& traits)
|
||||
{
|
||||
typename GT::FT norm = CGAL::approximate_sqrt(
|
||||
traits.compute_squared_length_3_object()(v));
|
||||
typedef typename GT::FT FT;
|
||||
|
||||
//If the vector is small enough, approx_sqrt might return 0, and then we get nan values.
|
||||
//To avoid that, we check the resulted norm. If it is 0, we don't normalize.
|
||||
if(norm != 0)
|
||||
const FT norm = CGAL::approximate_sqrt(traits.compute_squared_length_3_object()(v));
|
||||
if(norm != FT(0))
|
||||
{
|
||||
v = traits.construct_divided_vector_3_object()(v, norm);
|
||||
}
|
||||
}
|
||||
|
||||
template<typename Point
|
||||
, typename GT>
|
||||
template<typename Point, typename GT>
|
||||
typename GT::Vector_3
|
||||
triangle_normal(const Point& p0, const Point& p1, const Point& p2
|
||||
, const GT& traits)
|
||||
triangle_normal(const Point& p0, const Point& p1, const Point& p2, const GT& traits)
|
||||
{
|
||||
typedef typename GT::FT FT;
|
||||
|
||||
typename GT::Vector_3 n = traits.construct_cross_product_vector_3_object()(
|
||||
traits.construct_vector_3_object()(p1, p2),
|
||||
traits.construct_vector_3_object()(p1, p0));
|
||||
|
|
@ -61,12 +72,10 @@ namespace internal {
|
|||
//cross-product(AB, AC)'s norm is the area of the parallelogram
|
||||
//formed by these 2 vectors.
|
||||
//the triangle's area is half of it
|
||||
return traits.construct_scaled_vector_3_object()(n, 0.5);
|
||||
}
|
||||
return traits.construct_scaled_vector_3_object()(n, FT(1)/FT(2));
|
||||
}
|
||||
|
||||
template<typename Point, typename PM, typename VertexPointMap, typename Vector
|
||||
, typename GT>
|
||||
template<typename Point, typename PM, typename VertexPointMap, typename Vector, typename GT>
|
||||
void sum_normals(const PM& pmesh,
|
||||
typename boost::graph_traits<PM>::face_descriptor f,
|
||||
VertexPointMap vpmap,
|
||||
|
|
@ -76,21 +85,25 @@ void sum_normals(const PM& pmesh,
|
|||
typedef typename boost::graph_traits<PM>::vertex_descriptor vertex_descriptor;
|
||||
typedef typename boost::graph_traits<PM>::halfedge_descriptor halfedge_descriptor;
|
||||
|
||||
typedef typename boost::property_traits<VertexPointMap>::reference Point_ref;
|
||||
|
||||
halfedge_descriptor he = halfedge(f, pmesh);
|
||||
vertex_descriptor v = source(he, pmesh);
|
||||
const Point& pv = get(vpmap, v);
|
||||
const Point_ref pv = get(vpmap, v);
|
||||
|
||||
while(v != target(next(he, pmesh), pmesh))
|
||||
{
|
||||
const Point& pvn = get(vpmap, target(he, pmesh));
|
||||
const Point& pvnn = get(vpmap, target(next(he, pmesh), pmesh));
|
||||
const Point_ref pvn = get(vpmap, target(he, pmesh));
|
||||
const Point_ref pvnn = get(vpmap, target(next(he, pmesh), pmesh));
|
||||
|
||||
Vector n = internal::triangle_normal(pv, pvn, pvnn, traits);
|
||||
const Vector n = internal::triangle_normal(pv, pvn, pvnn, traits);
|
||||
sum = traits.construct_sum_of_vectors_3_object()(sum, n);
|
||||
|
||||
he = next(he, pmesh);
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace internal
|
||||
|
||||
/**
|
||||
* \ingroup PMP_normal_grp
|
||||
|
|
@ -124,9 +137,9 @@ Vector_3
|
|||
#else
|
||||
typename GetGeomTraits<PolygonMesh, NamedParameters>::type::Vector_3
|
||||
#endif
|
||||
compute_face_normal(typename boost::graph_traits<PolygonMesh>::face_descriptor f
|
||||
, const PolygonMesh& pmesh
|
||||
, const NamedParameters& np)
|
||||
compute_face_normal(typename boost::graph_traits<PolygonMesh>::face_descriptor f,
|
||||
const PolygonMesh& pmesh,
|
||||
const NamedParameters& np)
|
||||
{
|
||||
using parameters::choose_parameter;
|
||||
using parameters::get_parameter;
|
||||
|
|
@ -139,10 +152,10 @@ compute_face_normal(typename boost::graph_traits<PolygonMesh>::face_descriptor f
|
|||
get_const_property_map(vertex_point, pmesh));
|
||||
|
||||
typedef typename GT::Point_3 Point;
|
||||
typedef typename GT::Vector_3 Vector;
|
||||
typedef typename GT::Vector_3 Vector_3;
|
||||
|
||||
Vector normal = traits.construct_vector_3_object()(CGAL::NULL_VECTOR);
|
||||
sum_normals<Point>(pmesh, f, vpmap, normal, traits);
|
||||
Vector_3 normal = traits.construct_vector_3_object()(CGAL::NULL_VECTOR);
|
||||
internal::sum_normals<Point>(pmesh, f, vpmap, normal, traits);
|
||||
|
||||
if(!traits.equal_3_object()(normal, CGAL::NULL_VECTOR))
|
||||
internal::normalize(normal, traits);
|
||||
|
|
@ -150,16 +163,24 @@ compute_face_normal(typename boost::graph_traits<PolygonMesh>::face_descriptor f
|
|||
return normal;
|
||||
}
|
||||
|
||||
template <typename PolygonMesh>
|
||||
typename GetGeomTraits<PolygonMesh>::type::Vector_3
|
||||
compute_face_normal(typename boost::graph_traits<PolygonMesh>::face_descriptor f,
|
||||
const PolygonMesh& pmesh)
|
||||
{
|
||||
return compute_face_normal(f, pmesh, CGAL::parameters::all_default());
|
||||
}
|
||||
|
||||
/**
|
||||
* \ingroup PMP_normal_grp
|
||||
* computes the outward unit vector normal for all faces of the polygon mesh.
|
||||
* @tparam PolygonMesh a model of `FaceGraph`
|
||||
* @tparam FaceNormalMap a model of `WritablePropertyMap` with
|
||||
* @tparam Face_normal_map a model of `WritablePropertyMap` with
|
||||
`boost::graph_traits<PolygonMesh>::%face_descriptor` as key type and
|
||||
`Kernel::Vector_3` as value type.
|
||||
*
|
||||
* @param pmesh the polygon mesh
|
||||
* @param fnm the property map in which the normals are written
|
||||
* @param face_normals the property map in which the normals are written
|
||||
* @param np optional sequence of \ref pmp_namedparameters "Named Parameters" among the ones listed below
|
||||
*
|
||||
* \cgalNamedParamsBegin
|
||||
|
|
@ -173,22 +194,366 @@ compute_face_normal(typename boost::graph_traits<PolygonMesh>::face_descriptor f
|
|||
* If `Kernel::FT` does not have a `sqrt()` operation, the square root computation
|
||||
* will be done approximately.
|
||||
*/
|
||||
template <typename PolygonMesh
|
||||
, typename FaceNormalMap
|
||||
, typename NamedParameters>
|
||||
void
|
||||
compute_face_normals(const PolygonMesh& pmesh
|
||||
, FaceNormalMap fnm
|
||||
, const NamedParameters& np)
|
||||
template <typename PolygonMesh, typename Face_normal_map, typename NamedParameters>
|
||||
void compute_face_normals(const PolygonMesh& pmesh,
|
||||
Face_normal_map face_normals,
|
||||
const NamedParameters& np)
|
||||
{
|
||||
typedef typename GetGeomTraits<PolygonMesh,NamedParameters>::type Kernel;
|
||||
|
||||
for(typename boost::graph_traits<PolygonMesh>::face_descriptor f : faces(pmesh)){
|
||||
for(typename boost::graph_traits<PolygonMesh>::face_descriptor f : faces(pmesh))
|
||||
{
|
||||
typename Kernel::Vector_3 vec = compute_face_normal(f, pmesh, np);
|
||||
put(fnm, f, vec);
|
||||
put(face_normals, f, vec);
|
||||
#ifdef CGAL_PMP_COMPUTE_NORMAL_DEBUG
|
||||
std::cout << "normal at face " << f << " is " << get(face_normals, f) << std::endl;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
template <typename PolygonMesh, typename Face_normal_map>
|
||||
void compute_face_normals(const PolygonMesh& pmesh, Face_normal_map face_normals)
|
||||
{
|
||||
compute_face_normals(pmesh, face_normals, CGAL::parameters::all_default());
|
||||
}
|
||||
|
||||
namespace internal {
|
||||
|
||||
enum Vertex_normal_type {
|
||||
NO_WEIGHT = 0,
|
||||
SIN_WEIGHT,
|
||||
MOST_VISIBLE
|
||||
};
|
||||
|
||||
template <typename GT>
|
||||
bool almost_equal(const typename GT::Vector_3& v1, const typename GT::Vector_3& v2,
|
||||
const GT& traits)
|
||||
{
|
||||
typedef typename GT::FT FT;
|
||||
|
||||
// We are doing a lot of likely inexact constructions to compute min circles on the sphere and
|
||||
// these degenerate cases often happen (e.g. almost flat surfaces), so we don't want to to the usual
|
||||
// "switch to the exact kernel" in degenerate cases robustness trick. Rather, use a fixed tolerance
|
||||
// to assimilate vectors and scalar products.
|
||||
//
|
||||
// Tolerance is (arbitrarily) chosen as theta := 0.01°, thus we want sp(v1,v2) >= cos(theta)
|
||||
const FT cos_theta = 0.99999998476912910;
|
||||
return traits.compute_scalar_product_3_object()(v1, v2) >= cos_theta;
|
||||
}
|
||||
|
||||
template <typename PolygonMesh, typename FaceNormalVector, typename K>
|
||||
bool does_enclose_other_normals(const std::size_t i, const std::size_t j, const std::size_t k,
|
||||
const typename K::Vector_3& nb,
|
||||
const typename K::FT sp_bi,
|
||||
const std::vector<typename boost::graph_traits<PolygonMesh>::face_descriptor>& incident_faces,
|
||||
const FaceNormalVector& face_normals,
|
||||
const K& traits)
|
||||
{
|
||||
typedef typename K::FT FT;
|
||||
typedef typename boost::property_traits<FaceNormalVector>::reference Vector_ref;
|
||||
|
||||
typename K::Compute_scalar_product_3 sp = traits.compute_scalar_product_3_object();
|
||||
|
||||
const FT nbn = CGAL::approximate_sqrt(traits.compute_squared_length_3_object()(nb));
|
||||
|
||||
// check that this min circle defined by the diameter contains the other points
|
||||
const std::size_t nif = incident_faces.size();
|
||||
for(std::size_t l=0; l<nif; ++l)
|
||||
{
|
||||
if(l == i || l == j || l == k)
|
||||
continue;
|
||||
|
||||
const Vector_ref nl = get(face_normals, incident_faces[l]);
|
||||
|
||||
// this is a bound on how much the scalar product between (v1,v2) and (v1, v3) can change
|
||||
// when the angle changes theta_bound := 0.01°
|
||||
// The weird number is thus := max_(theta_i, theta_j)[abs(std::cos(theta_i), std::cos(theta_j))]
|
||||
// with theta_j - theta_i = theta_bound
|
||||
const FT sp_diff_bound = nbn * 0.00017453292431333;
|
||||
const FT sp_bl = sp(nb, nl);
|
||||
if(CGAL::abs(sp_bi - sp_bl) <= sp_diff_bound)
|
||||
continue;
|
||||
|
||||
if(sp_bl < sp_bi)
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
template <typename GT>
|
||||
typename GT::Vector_3 compute_normals_bisector(const typename GT::Vector_3& ni,
|
||||
const typename GT::Vector_3& nj,
|
||||
const GT& traits)
|
||||
{
|
||||
if(traits.equal_3_object()(ni, nj))
|
||||
return ni;
|
||||
|
||||
return traits.construct_sum_of_vectors_3_object()(ni, nj); // not normalized
|
||||
}
|
||||
|
||||
template <typename GT>
|
||||
typename GT::Vector_3 compute_normals_bisector(const typename GT::Vector_3& ni,
|
||||
const typename GT::Vector_3& nj,
|
||||
const typename GT::Vector_3& nk,
|
||||
const GT& traits)
|
||||
{
|
||||
typedef typename GT::FT FT;
|
||||
typedef typename GT::Point_3 Point_3;
|
||||
typedef typename GT::Vector_3 Vector_3;
|
||||
|
||||
typename GT::Construct_scaled_vector_3 cslv_3 = traits.construct_scaled_vector_3_object();
|
||||
typename GT::Construct_sum_of_vectors_3 csv_3 = traits.construct_sum_of_vectors_3_object();
|
||||
typename GT::Construct_vector_3 cv_3 = traits.construct_vector_3_object();
|
||||
|
||||
Vector_3 nb = cv_3(CGAL::NULL_VECTOR);
|
||||
|
||||
if(almost_equal(ni, nj, traits))
|
||||
{
|
||||
if(almost_equal(nj, nk, traits))
|
||||
nb = ni;
|
||||
else // ni == nj, but nij != nk
|
||||
nb = compute_normals_bisector(nj, nk, traits);
|
||||
}
|
||||
else if(almost_equal(ni, nk, traits)) // ni != nj
|
||||
{
|
||||
nb = compute_normals_bisector(nj, nk, traits);
|
||||
}
|
||||
else if(almost_equal(nj, nk, traits)) // ni != nj, ni != nk
|
||||
{
|
||||
nb = compute_normals_bisector(ni, nk, traits);
|
||||
}
|
||||
else
|
||||
{
|
||||
CGAL_assertion(ni != nj);
|
||||
CGAL_assertion(ni != nk);
|
||||
CGAL_assertion(nj != nk);
|
||||
CGAL_assertion(!traits.collinear_3_object()(CGAL::ORIGIN + ni, CGAL::ORIGIN + nj, CGAL::ORIGIN + nk));
|
||||
|
||||
#ifdef CGAL_PMP_COMPUTE_NORMAL_DEBUG_PP
|
||||
std::cout << "Triplet: ni[" << ni << "] nj[" << nj << "] nk[" << nk << "]" << std::endl;
|
||||
#endif
|
||||
|
||||
const Point_3 c = traits.construct_circumcenter_3_object()(CGAL::ORIGIN + ni, CGAL::ORIGIN + nj, CGAL::ORIGIN + nk);
|
||||
if(c == CGAL::ORIGIN)
|
||||
{
|
||||
// will happen if the three vectors live in the same plan, return some weighted sum
|
||||
const FT third = FT(1)/FT(3);
|
||||
return csv_3(csv_3(cslv_3(ni, third), cslv_3(nj, third)), cslv_3(nk, third));
|
||||
}
|
||||
|
||||
nb = cv_3(CGAL::ORIGIN, c); // note that this isn't normalized
|
||||
}
|
||||
|
||||
return nb;
|
||||
}
|
||||
|
||||
template <typename PolygonMesh, typename FaceNormalVector, typename GT>
|
||||
typename GT::Vector_3
|
||||
compute_most_visible_normal_2_points(std::vector<typename boost::graph_traits<PolygonMesh>::face_descriptor>& incident_faces,
|
||||
const FaceNormalVector& face_normals,
|
||||
const GT& traits)
|
||||
{
|
||||
typedef typename GT::FT FT;
|
||||
typedef typename GT::Vector_3 Vector_3;
|
||||
typedef typename boost::property_traits<FaceNormalVector>::reference Vector_ref;
|
||||
|
||||
typename GT::Compute_scalar_product_3 sp_3 = traits.compute_scalar_product_3_object();
|
||||
typename GT::Construct_vector_3 cv_3 = traits.construct_vector_3_object();
|
||||
|
||||
#ifdef CGAL_PMP_COMPUTE_NORMAL_DEBUG_PP
|
||||
std::cout << "Trying to find enclosing normal with 2 normals" << std::endl;
|
||||
#endif
|
||||
|
||||
FT min_sp = -1;
|
||||
Vector_3 n = cv_3(CGAL::NULL_VECTOR);
|
||||
|
||||
const std::size_t nif = incident_faces.size();
|
||||
for(std::size_t i=0; i<nif; ++i)
|
||||
{
|
||||
for(std::size_t j=i+1; j<nif; ++j)
|
||||
{
|
||||
const Vector_ref ni = get(face_normals, incident_faces[i]);
|
||||
const Vector_ref nj = get(face_normals, incident_faces[j]);
|
||||
|
||||
const Vector_3 nb = compute_normals_bisector(ni, nj, traits);
|
||||
|
||||
// Degeneracies like ni == -nj or a numerical error in the construction of 'nb' can happen.
|
||||
if(traits.equal_3_object()(nb, CGAL::NULL_VECTOR))
|
||||
return CGAL::NULL_VECTOR;
|
||||
|
||||
const FT sp_bi = sp_3(nb, ni);
|
||||
|
||||
CGAL_assertion(sp_bi >= 0);
|
||||
if(sp_bi <= min_sp)
|
||||
continue;
|
||||
|
||||
if(!does_enclose_other_normals<PolygonMesh>(i, j, -1 /*NA*/, nb, sp_bi, incident_faces, face_normals, traits))
|
||||
continue;
|
||||
|
||||
min_sp = sp_bi;
|
||||
n = nb;
|
||||
}
|
||||
}
|
||||
|
||||
return n;
|
||||
}
|
||||
|
||||
template <typename PolygonMesh, typename FaceNormalVector, typename GT>
|
||||
typename GT::Vector_3
|
||||
compute_most_visible_normal_3_points(const std::vector<typename boost::graph_traits<PolygonMesh>::face_descriptor>& incident_faces,
|
||||
const FaceNormalVector& face_normals,
|
||||
const GT& traits)
|
||||
{
|
||||
typedef typename GT::FT FT;
|
||||
typedef typename GT::Vector_3 Vector_3;
|
||||
typedef typename boost::property_traits<FaceNormalVector>::reference Vector_ref;
|
||||
|
||||
#ifdef CGAL_PMP_COMPUTE_NORMAL_DEBUG_PP
|
||||
std::cout << "Trying to find enclosing normal with 3 normals" << std::endl;
|
||||
#endif
|
||||
|
||||
FT min_sp = -1;
|
||||
|
||||
Vector_3 n = traits.construct_vector_3_object()(CGAL::NULL_VECTOR);
|
||||
|
||||
const std::size_t nif = incident_faces.size();
|
||||
for(std::size_t i=0; i<nif; ++i)
|
||||
{
|
||||
for(std::size_t j=i+1; j<nif; ++j)
|
||||
{
|
||||
for(std::size_t k=j+1; k<nif; ++k)
|
||||
{
|
||||
const Vector_ref ni = get(face_normals, incident_faces[i]);
|
||||
const Vector_ref nj = get(face_normals, incident_faces[j]);
|
||||
const Vector_ref nk = get(face_normals, incident_faces[k]);
|
||||
|
||||
Vector_3 nb = compute_normals_bisector(ni, nj, nk, traits);
|
||||
if(traits.equal_3_object()(nb, CGAL::NULL_VECTOR))
|
||||
return nb;
|
||||
|
||||
FT sp_bi = traits.compute_scalar_product_3_object()(nb, ni);
|
||||
if(sp_bi < FT(0))
|
||||
{
|
||||
nb = traits.construct_opposite_vector_3_object()(nb);
|
||||
sp_bi = - sp_bi;
|
||||
}
|
||||
|
||||
if(sp_bi <= min_sp)
|
||||
continue;
|
||||
|
||||
if(!does_enclose_other_normals<PolygonMesh>(i, j, k, nb, sp_bi, incident_faces, face_normals, traits))
|
||||
continue;
|
||||
|
||||
min_sp = sp_bi;
|
||||
n = nb;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef CGAL_PMP_COMPUTE_NORMAL_DEBUG_PP
|
||||
std::cout << "Best normal from 3-normals-approach: " << n << std::endl;
|
||||
#endif
|
||||
|
||||
return n;
|
||||
}
|
||||
|
||||
// Inspired by Aubry et al. On the most 'normal' normal
|
||||
template <typename PolygonMesh, typename FaceNormalVector, typename GT>
|
||||
typename GT::Vector_3
|
||||
compute_vertex_normal_most_visible_min_circle(typename boost::graph_traits<PolygonMesh>::vertex_descriptor v,
|
||||
const FaceNormalVector& face_normals,
|
||||
const PolygonMesh& pmesh,
|
||||
const GT& traits)
|
||||
{
|
||||
typedef typename boost::graph_traits<PolygonMesh>::face_descriptor face_descriptor;
|
||||
|
||||
typedef typename GT::Vector_3 Vector_3;
|
||||
|
||||
std::vector<face_descriptor> incident_faces;
|
||||
for(face_descriptor f : CGAL::faces_around_target(halfedge(v, pmesh), pmesh))
|
||||
{
|
||||
if(f == boost::graph_traits<PolygonMesh>::null_face())
|
||||
continue;
|
||||
|
||||
incident_faces.push_back(f);
|
||||
}
|
||||
|
||||
if(incident_faces.size() == 1)
|
||||
return get(face_normals, incident_faces.front());
|
||||
|
||||
Vector_3 res = compute_most_visible_normal_2_points<PolygonMesh>(incident_faces, face_normals, traits);
|
||||
|
||||
if(res != CGAL::NULL_VECTOR) // found a valid normal through 2 point min circle
|
||||
return res;
|
||||
|
||||
CGAL_assertion(incident_faces.size() > 2);
|
||||
|
||||
return compute_most_visible_normal_3_points<PolygonMesh>(incident_faces, face_normals, traits);
|
||||
}
|
||||
|
||||
template <typename PolygonMesh, typename FaceNormalVector, typename VertexPointMap, typename GT>
|
||||
typename GT::Vector_3
|
||||
compute_vertex_normal_as_sum_of_weighted_normals(typename boost::graph_traits<PolygonMesh>::vertex_descriptor v,
|
||||
const Vertex_normal_type& vn_type,
|
||||
const FaceNormalVector& face_normals,
|
||||
const VertexPointMap& vpmap,
|
||||
const PolygonMesh& pmesh,
|
||||
const GT& traits)
|
||||
{
|
||||
typedef typename boost::graph_traits<PolygonMesh>::halfedge_descriptor halfedge_descriptor;
|
||||
|
||||
typedef typename GT::FT FT;
|
||||
typedef typename GT::Vector_3 Vector_3;
|
||||
typedef typename boost::property_traits<FaceNormalVector>::reference Vector_ref;
|
||||
|
||||
typename GT::Construct_vector_3 cv_3 = traits.construct_vector_3_object();
|
||||
typename GT::Compute_squared_length_3 csl_3 = traits.compute_squared_length_3_object();
|
||||
|
||||
Vector_3 normal = cv_3(CGAL::NULL_VECTOR);
|
||||
|
||||
halfedge_descriptor h = halfedge(v, pmesh);
|
||||
if(h == boost::graph_traits<PolygonMesh>::null_halfedge())
|
||||
return normal;
|
||||
|
||||
halfedge_descriptor end = h;
|
||||
do
|
||||
{
|
||||
if(!is_border(h, pmesh))
|
||||
{
|
||||
if(vn_type == NO_WEIGHT)
|
||||
{
|
||||
const Vector_ref n = get(face_normals, face(h, pmesh));
|
||||
normal = traits.construct_sum_of_vectors_3_object()(normal, n);
|
||||
}
|
||||
else if(vn_type == SIN_WEIGHT)
|
||||
{
|
||||
const Vector_3 v1 = cv_3(get(vpmap, v), get(vpmap, source(h, pmesh)));
|
||||
const Vector_3 v2 = cv_3(get(vpmap, v), get(vpmap, target(next(h, pmesh), pmesh)));
|
||||
|
||||
//v(i) and v(i+1) must me seen in ccw order, from v, so we reverse v1 and v2
|
||||
Vector_3 n = traits.construct_cross_product_vector_3_object()(v2, v1);
|
||||
n = traits.construct_scaled_vector_3_object()(n, CGAL::approximate_sqrt(FT(1)/(csl_3(v1) * csl_3(v2))));
|
||||
|
||||
normal = traits.construct_sum_of_vectors_3_object()(normal, n);
|
||||
}
|
||||
else
|
||||
{
|
||||
std::cerr << "Error: unknown vertex normal type" << std::endl;
|
||||
CGAL_assertion(false);
|
||||
return CGAL::NULL_VECTOR;
|
||||
}
|
||||
}
|
||||
|
||||
h = opposite(next(h, pmesh), pmesh);
|
||||
}
|
||||
while(h != end);
|
||||
|
||||
return normal;
|
||||
}
|
||||
|
||||
} // end namespace internal
|
||||
|
||||
/**
|
||||
* \ingroup PMP_normal_grp
|
||||
* computes the unit normal at vertex `v` as the average of the normals of incident faces.
|
||||
|
|
@ -222,61 +587,101 @@ typename GetGeomTraits<PolygonMesh, NamedParameters>::type::Vector_3
|
|||
#endif
|
||||
compute_vertex_normal(typename boost::graph_traits<PolygonMesh>::vertex_descriptor v,
|
||||
const PolygonMesh& pmesh,
|
||||
const NamedParameters& np
|
||||
)
|
||||
const NamedParameters& np)
|
||||
{
|
||||
using parameters::choose_parameter;
|
||||
using parameters::is_default_parameter;
|
||||
using parameters::get_parameter;
|
||||
|
||||
typedef typename boost::graph_traits<PolygonMesh>::halfedge_descriptor halfedge_descriptor;
|
||||
typedef typename boost::graph_traits<PolygonMesh>::face_descriptor face_descriptor;
|
||||
|
||||
typedef typename GetGeomTraits<PolygonMesh, NamedParameters>::type GT;
|
||||
typedef typename GT::Vector_3 Vector;
|
||||
typedef typename GT::Vector_3 Vector_3;
|
||||
GT traits = choose_parameter(get_parameter(np, internal_np::geom_traits), GT());
|
||||
|
||||
typedef typename GetFaceNormalMap<PolygonMesh, NamedParameters>::NoMap DefaultMap;
|
||||
typedef typename internal_np::Lookup_named_param_def <
|
||||
internal_np::face_normal_t,
|
||||
typedef typename GetVertexPointMap<PolygonMesh, NamedParameters>::const_type VPMap;
|
||||
VPMap vpmap = choose_parameter(get_parameter(np, internal_np::vertex_point),
|
||||
get_const_property_map(vertex_point, pmesh));
|
||||
|
||||
typedef std::map<face_descriptor, Vector_3> Face_vector_map;
|
||||
typedef boost::associative_property_map<Face_vector_map> Default_map;
|
||||
|
||||
typedef typename internal_np::Lookup_named_param_def<internal_np::face_normal_t,
|
||||
NamedParameters,
|
||||
DefaultMap> ::type FaceNormalMap;
|
||||
FaceNormalMap fnmap = choose_parameter(get_parameter(np, internal_np::face_normal), DefaultMap());
|
||||
bool fnmap_valid
|
||||
= !boost::is_same<FaceNormalMap,
|
||||
DefaultMap
|
||||
>::value;
|
||||
Default_map>::type Face_normal_map;
|
||||
Face_vector_map default_fvmap;
|
||||
Face_normal_map face_normals = choose_parameter(get_parameter(np, internal_np::face_normal),
|
||||
Default_map(default_fvmap));
|
||||
const bool must_compute_face_normals = is_default_parameter(get_parameter(np, internal_np::face_normal));
|
||||
|
||||
typedef typename boost::graph_traits<PolygonMesh>::halfedge_descriptor halfedge_descriptor;
|
||||
#ifdef CGAL_PMP_COMPUTE_NORMAL_DEBUG_PP
|
||||
std::cout << std::endl << std::endl;
|
||||
std::cout << "----------------------------------------------------------------------" << std::endl;
|
||||
std::cout << "compute vertex at " << get(vpmap, v)
|
||||
<< ", must compute face normals? " << must_compute_face_normals << std::endl;
|
||||
#endif
|
||||
|
||||
Vector normal = traits.construct_vector_3_object()(CGAL::NULL_VECTOR);
|
||||
|
||||
halfedge_descriptor he = halfedge(v, pmesh);
|
||||
// handle isolated vertices
|
||||
if (he==boost::graph_traits<PolygonMesh>::null_halfedge()) return normal;
|
||||
halfedge_descriptor end = he;
|
||||
do
|
||||
halfedge_descriptor he = halfedge(v, pmesh);
|
||||
if(he == boost::graph_traits<PolygonMesh>::null_halfedge())
|
||||
return CGAL::NULL_VECTOR;
|
||||
|
||||
if(must_compute_face_normals)
|
||||
{
|
||||
if (!is_border(he, pmesh))
|
||||
for(face_descriptor f : CGAL::faces_around_target(halfedge(v, pmesh), pmesh))
|
||||
{
|
||||
Vector n = fnmap_valid ? get(fnmap, face(he, pmesh))
|
||||
: compute_face_normal(face(he, pmesh), pmesh, np);
|
||||
normal = traits.construct_sum_of_vectors_3_object()(normal, n);
|
||||
if(f == boost::graph_traits<PolygonMesh>::null_face())
|
||||
continue;
|
||||
|
||||
put(face_normals, f, compute_face_normal(f, pmesh, np));
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef CGAL_PMP_COMPUTE_NORMAL_DEBUG
|
||||
std::cout << "Incident face normals:" << std::endl;
|
||||
for(halfedge_descriptor h : CGAL::halfedges_around_target(v, pmesh))
|
||||
{
|
||||
if(!is_border(h, pmesh))
|
||||
std::cout << "get normal at f " << face(h, pmesh) << " : " << get(face_normals, face(h, pmesh)) << std::endl;
|
||||
}
|
||||
#endif
|
||||
|
||||
Vector_3 normal = internal::compute_vertex_normal_most_visible_min_circle(v, face_normals, pmesh, traits);
|
||||
if(traits.equal_3_object()(normal, CGAL::NULL_VECTOR)) // can't always find a most visible normal
|
||||
{
|
||||
#ifdef CGAL_PMP_COMPUTE_NORMAL_DEBUG_PP
|
||||
std::cout << "Failed to find most visible normal, use weighted sum of normals" << std::endl;
|
||||
#endif
|
||||
normal = internal::compute_vertex_normal_as_sum_of_weighted_normals(
|
||||
v, internal::SIN_WEIGHT, face_normals, vpmap, pmesh, traits);
|
||||
}
|
||||
he = opposite(next(he, pmesh), pmesh);
|
||||
} while (he != end);
|
||||
|
||||
if(!traits.equal_3_object()(normal, CGAL::NULL_VECTOR))
|
||||
internal::normalize(normal, traits);
|
||||
|
||||
return normal;
|
||||
}
|
||||
|
||||
template <typename PolygonMesh>
|
||||
typename GetGeomTraits<PolygonMesh>::type::Vector_3
|
||||
compute_vertex_normal(typename boost::graph_traits<PolygonMesh>::vertex_descriptor v,
|
||||
const PolygonMesh& pmesh)
|
||||
{
|
||||
return compute_vertex_normal(v, pmesh, CGAL::parameters::all_default());
|
||||
}
|
||||
|
||||
/**
|
||||
* \ingroup PMP_normal_grp
|
||||
* computes the outward unit vector normal for all vertices of the polygon mesh.
|
||||
*
|
||||
* @tparam PolygonMesh a model of `FaceListGraph`
|
||||
* @tparam VertexNormalMap a model of `WritablePropertyMap` with
|
||||
`boost::graph_traits<PolygonMesh>::%vertex_descriptor` as key type and
|
||||
the return type of `compute_vertex_normal()` as value type.
|
||||
* `boost::graph_traits<PolygonMesh>::%vertex_descriptor` as key type and
|
||||
* the return type of `compute_vertex_normal()` as value type.
|
||||
*
|
||||
* @param pmesh the polygon mesh
|
||||
* @param vnm the property map in which the normals are written
|
||||
* @param vertex_normals the property map in which the normals are written
|
||||
* @param np optional sequence of \ref pmp_namedparameters "Named Parameters" among the ones listed below
|
||||
*
|
||||
* \cgalNamedParamsBegin
|
||||
|
|
@ -290,38 +695,82 @@ compute_vertex_normal(typename boost::graph_traits<PolygonMesh>::vertex_descript
|
|||
* If `Kernel::FT` does not have a `sqrt()` operation, the square root computation
|
||||
* will be done approximately.
|
||||
*/
|
||||
template <typename PolygonMesh
|
||||
, typename VertexNormalMap
|
||||
, typename NamedParameters
|
||||
>
|
||||
void
|
||||
compute_vertex_normals(const PolygonMesh& pmesh
|
||||
, VertexNormalMap vnm
|
||||
, const NamedParameters& np
|
||||
)
|
||||
template <typename PolygonMesh, typename VertexNormalMap, typename NamedParameters>
|
||||
void compute_vertex_normals(const PolygonMesh& pmesh,
|
||||
VertexNormalMap vertex_normals,
|
||||
const NamedParameters& np)
|
||||
{
|
||||
typedef typename GetGeomTraits<PolygonMesh,NamedParameters>::type Kernel;
|
||||
using parameters::choose_parameter;
|
||||
using parameters::is_default_parameter;
|
||||
using parameters::get_parameter;
|
||||
|
||||
for(typename boost::graph_traits<PolygonMesh>::vertex_descriptor v : vertices(pmesh)){
|
||||
typename Kernel::Vector_3 vec = compute_vertex_normal(v, pmesh, np);
|
||||
put(vnm, v, vec);
|
||||
typedef typename boost::graph_traits<PolygonMesh>::vertex_descriptor vertex_descriptor;
|
||||
|
||||
typedef typename GetGeomTraits<PolygonMesh,NamedParameters>::type GT;
|
||||
typedef typename GT::Vector_3 Vector_3;
|
||||
|
||||
typedef CGAL::dynamic_face_property_t<Vector_3> Face_normal_tag;
|
||||
typedef typename boost::property_map<PolygonMesh, Face_normal_tag>::const_type Face_normal_dmap;
|
||||
|
||||
#ifdef CGAL_PMP_COMPUTE_NORMAL_DEBUG_PP
|
||||
GT traits = choose_parameter(get_parameter(np, internal_np::geom_traits), GT());
|
||||
|
||||
typedef typename GetVertexPointMap<PolygonMesh, NamedParameters>::const_type VPMap;
|
||||
VPMap vpmap = choose_parameter(get_parameter(np, internal_np::vertex_point),
|
||||
get_const_property_map(vertex_point, pmesh));
|
||||
#endif
|
||||
|
||||
typedef typename internal_np::Lookup_named_param_def<internal_np::face_normal_t,
|
||||
NamedParameters,
|
||||
Face_normal_dmap>::type Face_normal_map;
|
||||
Face_normal_map face_normals = choose_parameter(get_parameter(np, internal_np::face_normal),
|
||||
get(Face_normal_tag(), pmesh));
|
||||
const bool must_compute_face_normals = is_default_parameter(get_parameter(np, internal_np::face_normal));
|
||||
|
||||
if(must_compute_face_normals)
|
||||
compute_face_normals(pmesh, face_normals, np);
|
||||
|
||||
#ifdef CGAL_PMP_COMPUTE_NORMAL_DEBUG_PP
|
||||
std::ofstream out("computed_normals.cgal.polylines.txt");
|
||||
const Bbox_3 bb = bbox(pmesh, np);
|
||||
const typename GT::FT bbox_diagonal = CGAL::sqrt(CGAL::square(bb.xmax() - bb.xmin()) +
|
||||
CGAL::square(bb.ymax() - bb.ymin()) +
|
||||
CGAL::square(bb.zmax() - bb.zmin()));
|
||||
#endif
|
||||
|
||||
for(vertex_descriptor v : vertices(pmesh))
|
||||
{
|
||||
const Vector_3 n = compute_vertex_normal(v, pmesh, np.face_normal_map(face_normals));
|
||||
put(vertex_normals, v, n);
|
||||
|
||||
#ifdef CGAL_PMP_COMPUTE_NORMAL_DEBUG_PP
|
||||
out << "2 " << get(vpmap, v) << " "
|
||||
<< get(vpmap, v) + traits.construct_scaled_vector_3_object()(n, 0.1 * bbox_diagonal) << "\n";
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
template <typename PolygonMesh, typename VertexNormalMap>
|
||||
void compute_vertex_normals(const PolygonMesh& pmesh, VertexNormalMap vertex_normals)
|
||||
{
|
||||
compute_vertex_normals(pmesh, vertex_normals, CGAL::parameters::all_default());
|
||||
}
|
||||
|
||||
/**
|
||||
* \ingroup PMP_normal_grp
|
||||
* computes the outward unit vector normal for all vertices and faces of the polygon mesh.
|
||||
*
|
||||
* @tparam PolygonMesh a model of `FaceListGraph`
|
||||
* @tparam VertexNormalMap a model of `WritablePropertyMap` with
|
||||
`boost::graph_traits<PolygonMesh>::%vertex_descriptor` as key type and
|
||||
`Kernel::Vector_3` as value type.
|
||||
* `boost::graph_traits<PolygonMesh>::%vertex_descriptor` as key type and
|
||||
* `Kernel::Vector_3` as value type.
|
||||
* @tparam FaceNormalMap a model of `ReadWritePropertyMap` with
|
||||
`boost::graph_traits<PolygonMesh>::%face_descriptor` as key type and
|
||||
`Kernel::Vector_3` as value type.
|
||||
* `boost::graph_traits<PolygonMesh>::%face_descriptor` as key type and
|
||||
* `Kernel::Vector_3` as value type.
|
||||
*
|
||||
* @param pmesh the polygon mesh
|
||||
* @param vnm the property map in which the vertex normals are written
|
||||
* @param fnm the property map in which the face normals are written
|
||||
* @param vertex_normals the property map in which the vertex normals are written
|
||||
* @param face_normals the property map in which the face normals are written
|
||||
* @param np optional sequence of \ref pmp_namedparameters "Named Parameters" among the ones listed below
|
||||
*
|
||||
* \cgalNamedParamsBegin
|
||||
|
|
@ -335,79 +784,27 @@ compute_vertex_normals(const PolygonMesh& pmesh
|
|||
* If `Kernel::FT` does not have a `sqrt()` operation, the square root computation
|
||||
* will be done approximately.
|
||||
*/
|
||||
template <typename PolygonMesh
|
||||
, typename VertexNormalMap
|
||||
, typename FaceNormalMap
|
||||
, typename NamedParameters
|
||||
>
|
||||
void
|
||||
compute_normals(const PolygonMesh& pmesh
|
||||
, VertexNormalMap vnm
|
||||
, FaceNormalMap fnm
|
||||
, const NamedParameters& np
|
||||
)
|
||||
template <typename PolygonMesh,
|
||||
typename VertexNormalMap, typename FaceNormalMap,
|
||||
typename NamedParameters>
|
||||
void compute_normals(const PolygonMesh& pmesh,
|
||||
VertexNormalMap vertex_normals,
|
||||
FaceNormalMap face_normals,
|
||||
const NamedParameters& np)
|
||||
{
|
||||
compute_face_normals(pmesh, fnm, np);
|
||||
compute_vertex_normals(pmesh, vnm, np.face_normal_map(fnm));
|
||||
compute_face_normals(pmesh, face_normals, np);
|
||||
compute_vertex_normals(pmesh, vertex_normals, np.face_normal_map(face_normals));
|
||||
}
|
||||
|
||||
///\cond SKIP_IN_MANUAL
|
||||
// compute_vertex_normal overloads
|
||||
template <typename PolygonMesh>
|
||||
typename CGAL::Kernel_traits< typename property_map_value<PolygonMesh, CGAL::vertex_point_t>::type>::Kernel::Vector_3
|
||||
compute_vertex_normal(
|
||||
typename boost::graph_traits<PolygonMesh>::vertex_descriptor v,
|
||||
const PolygonMesh& pmesh)
|
||||
{
|
||||
return compute_vertex_normal(v, pmesh,
|
||||
CGAL::Polygon_mesh_processing::parameters::all_default());
|
||||
}
|
||||
|
||||
// compute_vertex_normals overloads
|
||||
template <typename PolygonMesh, typename VertexNormalMap>
|
||||
void
|
||||
compute_vertex_normals(const PolygonMesh& pmesh,
|
||||
VertexNormalMap vnm)
|
||||
{
|
||||
compute_vertex_normals(pmesh, vnm,
|
||||
CGAL::Polygon_mesh_processing::parameters::all_default());
|
||||
}
|
||||
|
||||
// compute_face_normal overload
|
||||
template <typename PolygonMesh>
|
||||
typename CGAL::Kernel_traits < typename property_map_value<PolygonMesh, CGAL::vertex_point_t>::type>::Kernel::Vector_3
|
||||
compute_face_normal(
|
||||
typename boost::graph_traits<PolygonMesh>::face_descriptor f,
|
||||
const PolygonMesh& pmesh)
|
||||
{
|
||||
return compute_face_normal(f, pmesh,
|
||||
CGAL::Polygon_mesh_processing::parameters::all_default());
|
||||
}
|
||||
|
||||
// compute_face_normals overload
|
||||
template <typename PolygonMesh, typename FaceNormalMap>
|
||||
void
|
||||
compute_face_normals(const PolygonMesh& pmesh, FaceNormalMap fnm)
|
||||
{
|
||||
compute_face_normals(pmesh, fnm,
|
||||
CGAL::Polygon_mesh_processing::parameters::all_default());
|
||||
}
|
||||
|
||||
// compute_normals overload
|
||||
template <typename PolygonMesh, typename VertexNormalMap, typename FaceNormalMap>
|
||||
void
|
||||
compute_normals(const PolygonMesh& pmesh,
|
||||
VertexNormalMap vnm,
|
||||
FaceNormalMap fnm)
|
||||
void compute_normals(const PolygonMesh& pmesh,
|
||||
VertexNormalMap vertex_normals,
|
||||
FaceNormalMap face_normals)
|
||||
{
|
||||
compute_normals(pmesh, vnm, fnm,
|
||||
CGAL::Polygon_mesh_processing::parameters::all_default());
|
||||
compute_normals(pmesh, vertex_normals, face_normals, CGAL::parameters::all_default());
|
||||
}
|
||||
|
||||
/// \endcond
|
||||
|
||||
}
|
||||
|
||||
} // end of namespace CGAL::Polygon_mesh_processing
|
||||
} // namespace Polygon_mesh_processing
|
||||
} // namespace CGAL
|
||||
|
||||
#endif // CGAL_POLYGON_MESH_PROCESSING_COMPUTE_NORMAL_H
|
||||
|
|
|
|||
|
|
@ -27,14 +27,14 @@
|
|||
#include <boost/graph/connected_components.hpp>
|
||||
#include <boost/property_map/vector_property_map.hpp>
|
||||
|
||||
#include <CGAL/assertions.h>
|
||||
#include <CGAL/boost/graph/iterator.h>
|
||||
#include <CGAL/boost/graph/helpers.h>
|
||||
|
||||
#include <CGAL/assertions.h>
|
||||
#include <CGAL/tuple.h>
|
||||
#include <CGAL/boost/graph/Dual.h>
|
||||
#include <CGAL/boost/graph/helpers.h>
|
||||
#include <CGAL/Default.h>
|
||||
#include <CGAL/Dynamic_property_map.h>
|
||||
#include <CGAL/iterator.h>
|
||||
#include <CGAL/tuple.h>
|
||||
|
||||
#include <CGAL/Polygon_mesh_processing/internal/named_function_params.h>
|
||||
#include <CGAL/Polygon_mesh_processing/internal/named_params_helper.h>
|
||||
|
|
@ -238,12 +238,9 @@ typename boost::property_traits<FaceComponentMap>::value_type
|
|||
connected_components(const PolygonMesh& pmesh,
|
||||
FaceComponentMap fcm)
|
||||
{
|
||||
|
||||
return CGAL::Polygon_mesh_processing::connected_components(pmesh, fcm,
|
||||
CGAL::Polygon_mesh_processing::parameters::all_default());
|
||||
return CGAL::Polygon_mesh_processing::connected_components(pmesh, fcm, CGAL::parameters::all_default());
|
||||
}
|
||||
|
||||
|
||||
template <typename PolygonMesh
|
||||
, typename ComponentRange
|
||||
, typename FaceComponentMap
|
||||
|
|
@ -253,6 +250,50 @@ void keep_connected_components(PolygonMesh& pmesh
|
|||
, const FaceComponentMap& fcm
|
||||
, const NamedParameters& np);
|
||||
|
||||
namespace internal {
|
||||
|
||||
// /*!
|
||||
// * \ingroup keep_connected_components_grp
|
||||
// * returns the number of connected components in the mesh.
|
||||
// *
|
||||
// * A property map for `CGAL::face_index_t` must be either available as an internal property map
|
||||
// * to `pmesh` or provided as one of the \ref pmp_namedparameters "Named Parameters".
|
||||
// *
|
||||
// * \tparam PolygonMesh a model of `FaceGraph`
|
||||
// * \tparam NamedParameters a sequence of \ref pmp_namedparameters "Named Parameters"
|
||||
// *
|
||||
// * \param pmesh the polygon mesh
|
||||
// * \param np optional \ref pmp_namedparameters "Named Parameters" described below
|
||||
// *
|
||||
// * \cgalNamedParamsBegin
|
||||
// * \cgalParamBegin{edge_is_constrained_map} a property map containing the constrained-or-not status of each edge of `pmesh` \cgalParamEnd
|
||||
// * \cgalParamBegin{face_index_map} a property map containing the index of each face of `pmesh` \cgalParamEnd
|
||||
// * \cgalNamedParamsEnd
|
||||
// *
|
||||
// * \returns the output iterator.
|
||||
// *
|
||||
// */
|
||||
template <typename PolygonMesh,
|
||||
typename CGAL_PMP_NP_TEMPLATE_PARAMETERS>
|
||||
std::size_t number_of_connected_components(const PolygonMesh& pmesh,
|
||||
const CGAL_PMP_NP_CLASS& np)
|
||||
{
|
||||
typedef CGAL::dynamic_face_property_t<std::size_t> Face_property_tag;
|
||||
typedef typename boost::property_map<PolygonMesh, Face_property_tag >::const_type Patch_ids_map;
|
||||
|
||||
Patch_ids_map patch_ids_map = get(Face_property_tag(), pmesh);
|
||||
|
||||
return CGAL::Polygon_mesh_processing::connected_components(pmesh, patch_ids_map, np);
|
||||
}
|
||||
|
||||
template <typename PolygonMesh>
|
||||
std::size_t number_of_connected_components(const PolygonMesh& pmesh)
|
||||
{
|
||||
return internal::number_of_connected_components(pmesh, CGAL::parameters::all_default());
|
||||
}
|
||||
|
||||
} // end namespace internal
|
||||
|
||||
/*!
|
||||
* \ingroup keep_connected_components_grp
|
||||
*
|
||||
|
|
@ -270,7 +311,8 @@ void keep_connected_components(PolygonMesh& pmesh
|
|||
* \tparam NamedParameters a sequence of \ref pmp_namedparameters "Named Parameters"
|
||||
*
|
||||
* \param pmesh the polygon mesh
|
||||
* \param nb_components_to_keep the number of components to be kept
|
||||
* \param nb_components_to_keep the number of components to be kept. If this number is larger than
|
||||
* the number of components in the mesh, all components are kept.
|
||||
* \param np optional \ref pmp_namedparameters "Named Parameters", amongst those described below
|
||||
*
|
||||
* \cgalNamedParamsBegin
|
||||
|
|
@ -282,6 +324,14 @@ void keep_connected_components(PolygonMesh& pmesh
|
|||
* is chosen by the user, but must be constructible from `0` and support `operator+=()` and
|
||||
* comparisons.
|
||||
* \cgalParamEnd
|
||||
* \cgalParamBegin{dry_run}
|
||||
* a Boolean parameter. If set to `true`, the mesh will not be altered, but the number
|
||||
* of components that would be removed is returned. The default value is `false`.
|
||||
* \cgalParamEnd
|
||||
* \cgalParamBegin{output_iterator} a model of `OutputIterator` with value type `face_descriptor`.
|
||||
* When using the "dry run" mode (see parameter `dry_run`), faces that would be removed by the
|
||||
* algorithm can be collected with this output iterator.
|
||||
* \cgalParamEnd
|
||||
* \cgalNamedParamsEnd
|
||||
*
|
||||
* \return the number of connected components removed (ignoring isolated vertices).
|
||||
|
|
@ -313,6 +363,13 @@ std::size_t keep_largest_connected_components(PolygonMesh& pmesh,
|
|||
FaceSizeMap face_size_pmap = choose_parameter(get_parameter(np, internal_np::face_size_map),
|
||||
Constant_property_map<face_descriptor, std::size_t>(1));
|
||||
|
||||
const bool dry_run = choose_parameter(get_parameter(np, internal_np::dry_run), false);
|
||||
|
||||
typedef typename internal_np::Lookup_named_param_def<internal_np::output_iterator_t,
|
||||
NamedParameters,
|
||||
Emptyset_iterator>::type Output_iterator;
|
||||
Output_iterator out = choose_parameter(get_parameter(np, internal_np::output_iterator), Emptyset_iterator());
|
||||
|
||||
// vector_property_map
|
||||
boost::vector_property_map<std::size_t, FaceIndexMap> face_cc(fimap);
|
||||
std::size_t num = connected_components(pmesh, face_cc, np);
|
||||
|
|
@ -320,12 +377,13 @@ std::size_t keep_largest_connected_components(PolygonMesh& pmesh,
|
|||
// Even if we do not want to keep anything we need to first
|
||||
// calculate the number of existing connected_components to get the
|
||||
// correct return value.
|
||||
if(nb_components_to_keep == 0) {
|
||||
if(nb_components_to_keep == 0)
|
||||
{
|
||||
CGAL::clear(pmesh);
|
||||
return num;
|
||||
}
|
||||
|
||||
if((num == 1)|| (nb_components_to_keep > num) )
|
||||
if(nb_components_to_keep >= num)
|
||||
return 0;
|
||||
|
||||
std::vector<std::pair<std::size_t, Face_size> > component_size(num);
|
||||
|
|
@ -338,11 +396,25 @@ std::size_t keep_largest_connected_components(PolygonMesh& pmesh,
|
|||
|
||||
// we sort the range [0, num) by component size
|
||||
std::sort(component_size.begin(), component_size.end(), internal::MoreSecond());
|
||||
|
||||
if(dry_run)
|
||||
{
|
||||
std::vector<bool> is_to_be_removed(num, false);
|
||||
for(std::size_t i=0; i<nb_components_to_keep; ++i)
|
||||
is_to_be_removed[component_size[i].first] = true;
|
||||
|
||||
for(face_descriptor f : faces(pmesh))
|
||||
if(is_to_be_removed[face_cc[f]])
|
||||
*out++ = f;
|
||||
}
|
||||
else
|
||||
{
|
||||
std::vector<std::size_t> cc_to_keep;
|
||||
for(std::size_t i=0; i<nb_components_to_keep; ++i)
|
||||
cc_to_keep.push_back(component_size[i].first);
|
||||
|
||||
keep_connected_components(pmesh, cc_to_keep, face_cc, np);
|
||||
}
|
||||
|
||||
return num - nb_components_to_keep;
|
||||
}
|
||||
|
|
@ -385,6 +457,14 @@ std::size_t keep_largest_connected_components(PolygonMesh& pmesh,
|
|||
* is chosen by the user, but must be constructible from `0` and support `operator+=()` and
|
||||
* comparisons.
|
||||
* \cgalParamEnd
|
||||
* \cgalParamBegin{dry_run}
|
||||
* a Boolean parameter. If set to `true`, the mesh will not be altered, but the number
|
||||
* of components that would be removed is returned. The default value is `false`.
|
||||
* \cgalParamEnd
|
||||
* \cgalParamBegin{output_iterator} a model of `OutputIterator` with value type `face_descriptor`.
|
||||
* When using the "dry run" mode (see parameter `dry_run`), faces that would be removed by the
|
||||
* algorithm can be collected with this output iterator.
|
||||
* \cgalParamEnd
|
||||
* \cgalNamedParamsEnd
|
||||
*
|
||||
* \pre If a face size property map is passed by the user, `ThresholdValueType` must be the same
|
||||
|
|
@ -418,34 +498,54 @@ std::size_t keep_large_connected_components(PolygonMesh& pmesh,
|
|||
|
||||
CGAL_static_assertion((std::is_convertible<ThresholdValueType, Face_size>::value));
|
||||
|
||||
typedef typename internal_np::Lookup_named_param_def<internal_np::output_iterator_t,
|
||||
NamedParameters,
|
||||
Emptyset_iterator>::type Output_iterator;
|
||||
|
||||
FaceSizeMap face_size_pmap = choose_parameter(get_parameter(np, internal_np::face_size_map),
|
||||
Constant_property_map<face_descriptor, std::size_t>(1));
|
||||
const bool dry_run = choose_parameter(get_parameter(np, internal_np::dry_run), false);
|
||||
Output_iterator out = choose_parameter(get_parameter(np, internal_np::output_iterator), Emptyset_iterator());
|
||||
|
||||
// vector_property_map
|
||||
boost::vector_property_map<std::size_t, FaceIndexMap> face_cc(fim);
|
||||
std::size_t num = connected_components(pmesh, face_cc, np);
|
||||
std::vector<Face_size> component_size(num);
|
||||
|
||||
for(std::size_t i=0; i<num; ++i)
|
||||
component_size[i] = Face_size(0);
|
||||
std::vector<Face_size> component_size(num, 0);
|
||||
|
||||
for(face_descriptor f : faces(pmesh))
|
||||
component_size[face_cc[f]] += get(face_size_pmap, f);
|
||||
|
||||
const Face_size thresh = threshold_value;
|
||||
std::vector<bool> is_to_be_kept(num, false);
|
||||
std::size_t res = 0;
|
||||
|
||||
std::vector<std::size_t> cc_to_keep;
|
||||
for(std::size_t i=0; i<num; ++i)
|
||||
{
|
||||
if(component_size[i] >= thresh)
|
||||
cc_to_keep.push_back(i);
|
||||
{
|
||||
is_to_be_kept[i] = true;
|
||||
++res;
|
||||
}
|
||||
}
|
||||
|
||||
keep_connected_components(pmesh, cc_to_keep, face_cc, np);
|
||||
if(dry_run)
|
||||
{
|
||||
for(face_descriptor f : faces(pmesh))
|
||||
if(!is_to_be_kept[face_cc[f]])
|
||||
*out++ = f;
|
||||
}
|
||||
else
|
||||
{
|
||||
std::vector<std::size_t> ccs_to_keep;
|
||||
for(std::size_t i=0; i<num; ++i)
|
||||
if(is_to_be_kept[i])
|
||||
ccs_to_keep.push_back(i);
|
||||
|
||||
return num - cc_to_keep.size();
|
||||
keep_connected_components(pmesh, ccs_to_keep, face_cc, np);
|
||||
}
|
||||
|
||||
return num - res;
|
||||
}
|
||||
|
||||
template <typename PolygonMesh>
|
||||
std::size_t keep_large_connected_components(PolygonMesh& pmesh,
|
||||
|
|
|
|||
|
|
@ -326,7 +326,8 @@ face_area(typename boost::graph_traits<TriangleMesh>::face_descriptor f,
|
|||
halfedge_descriptor hd = halfedge(f, tmesh);
|
||||
halfedge_descriptor nhd = next(hd, tmesh);
|
||||
|
||||
typename GetGeomTraits<TriangleMesh, CGAL_PMP_NP_CLASS>::type traits;
|
||||
typedef typename GetGeomTraits<TriangleMesh, CGAL_PMP_NP_CLASS>::type GT;
|
||||
GT traits = choose_parameter(get_parameter(np, internal_np::geom_traits), GT());
|
||||
|
||||
return approximate_sqrt(traits.compute_squared_area_3_object()(get(vpm, source(hd, tmesh)),
|
||||
get(vpm, target(hd, tmesh)),
|
||||
|
|
|
|||
|
|
@ -29,8 +29,10 @@
|
|||
#include <CGAL/boost/graph/selection.h>
|
||||
|
||||
#include <CGAL/Polygon_mesh_processing/connected_components.h>
|
||||
#include <CGAL/Polygon_mesh_processing/bbox.h>
|
||||
#include <CGAL/Polygon_mesh_processing/border.h>
|
||||
#include <CGAL/Polygon_mesh_processing/shape_predicates.h>
|
||||
#include <CGAL/Polygon_mesh_processing/measure.h>
|
||||
|
||||
#include <CGAL/Polygon_mesh_processing/internal/named_function_params.h>
|
||||
#include <CGAL/Polygon_mesh_processing/internal/named_params_helper.h>
|
||||
|
|
@ -60,6 +62,284 @@
|
|||
|
||||
namespace CGAL {
|
||||
namespace Polygon_mesh_processing {
|
||||
|
||||
/// \ingroup PMP_repairing_grp
|
||||
/// removes the isolated vertices from any polygon mesh.
|
||||
/// A vertex is considered isolated if it is not incident to any simplex
|
||||
/// of higher dimension.
|
||||
///
|
||||
/// @tparam PolygonMesh a model of `FaceListGraph` and `MutableFaceGraph`
|
||||
///
|
||||
/// @param pmesh the polygon mesh to be repaired
|
||||
///
|
||||
/// @return number of removed isolated vertices
|
||||
///
|
||||
template <class PolygonMesh>
|
||||
std::size_t remove_isolated_vertices(PolygonMesh& pmesh)
|
||||
{
|
||||
typedef typename boost::graph_traits<PolygonMesh>::vertex_descriptor vertex_descriptor;
|
||||
std::vector<vertex_descriptor> to_be_removed;
|
||||
|
||||
for(vertex_descriptor v : vertices(pmesh))
|
||||
{
|
||||
if (CGAL::halfedges_around_target(v, pmesh).first
|
||||
== CGAL::halfedges_around_target(v, pmesh).second)
|
||||
to_be_removed.push_back(v);
|
||||
}
|
||||
std::size_t nb_removed = to_be_removed.size();
|
||||
for(vertex_descriptor v : to_be_removed)
|
||||
{
|
||||
remove_vertex(v, pmesh);
|
||||
}
|
||||
return nb_removed;
|
||||
}
|
||||
|
||||
/// \ingroup PMP_repairing_grp
|
||||
///
|
||||
/// removes connected components whose area or volume is under a certain threshold value.
|
||||
///
|
||||
/// Thresholds are provided via \ref pmp_namedparameters "Named Parameters". (see below).
|
||||
/// If thresholds are not provided by the user, default values are computed as follows:
|
||||
/// - the area threshold is taken as the square of one percent of the length of the diagonal
|
||||
/// of the bounding box of the mesh.
|
||||
/// - the volume threshold is taken as the third power of one percent of the length of the diagonal
|
||||
/// of the bounding box of the mesh.
|
||||
///
|
||||
/// The area and volume of a connected component will always be positive values (regardless
|
||||
/// of the orientation of the mesh).
|
||||
///
|
||||
/// As a consequence of the last sentence, the area or volume criteria can be disabled
|
||||
/// by passing zero (`0`) as threshold value.
|
||||
///
|
||||
/// Property maps for `CGAL::face_index_t` and `CGAL::vertex_index_t`
|
||||
/// must be either available as internal property maps
|
||||
/// to `tmesh` or provided as \ref pmp_namedparameters "Named Parameters".
|
||||
///
|
||||
/// \tparam TriangleMesh a model of `FaceListGraph` and `MutableFaceGraph`
|
||||
/// \tparam NamedParameters a sequence of \ref pmp_namedparameters "Named Parameters"
|
||||
///
|
||||
/// \param tmesh the triangulated polygon mesh
|
||||
/// \param np optional \ref pmp_namedparameters "Named Parameters", amongst those described below
|
||||
///
|
||||
/// \cgalNamedParamsBegin
|
||||
/// \cgalParamBegin{area_threshold} a fixed value such that only connected components whose area is
|
||||
/// larger than this value are kept \cgalParamEnd
|
||||
/// \cgalParamBegin{volume_threshold} a fixed value such that only connected components whose volume is
|
||||
/// larger than this value are kept (only applies to closed connected components) \cgalParamEnd
|
||||
/// \cgalParamBegin{edge_is_constrained_map} a property map containing the constrained-or-not status of each edge of `pmesh` \cgalParamEnd
|
||||
/// \cgalParamBegin{face_index_map} a property map containing the index of each face of `tmesh` \cgalParamEnd
|
||||
/// \cgalParamBegin{vertex_point_map} the property map with the points associated to the vertices of `tmesh`.
|
||||
/// If this parameter is omitted, an internal property map for
|
||||
/// `CGAL::vertex_point_t` should be available in `TriangleMesh` \cgalParamEnd
|
||||
/// \cgalParamBegin{geom_traits} an instance of a geometric traits class, model of `Kernel` \cgalParamEnd
|
||||
/// \cgalParamBegin{dry_run} a Boolean parameter. If set to `true`, the mesh will not be altered,
|
||||
/// but the number of components that would be removed is returned. The default value is `false`.\cgalParamEnd
|
||||
/// \cgalParamBegin{output_iterator} a model of `OutputIterator` with value type `face_descriptor`.
|
||||
/// When using the "dry run" mode (see parameter `dry_run`), faces
|
||||
/// that would be removed by the algorithm can be collected with this output iterator. \cgalParamEnd
|
||||
/// \cgalNamedParamsEnd
|
||||
///
|
||||
/// \return the number of connected components removed (ignoring isolated vertices).
|
||||
///
|
||||
template <typename TriangleMesh,
|
||||
typename NamedParameters>
|
||||
std::size_t remove_connected_components_of_negligible_size(TriangleMesh& tmesh,
|
||||
const NamedParameters& np)
|
||||
{
|
||||
using parameters::choose_parameter;
|
||||
using parameters::is_default_parameter;
|
||||
using parameters::get_parameter;
|
||||
|
||||
typedef typename boost::graph_traits<TriangleMesh>::halfedge_descriptor halfedge_descriptor;
|
||||
typedef typename boost::graph_traits<TriangleMesh>::face_descriptor face_descriptor;
|
||||
|
||||
typedef typename GetGeomTraits<TriangleMesh, NamedParameters>::type GT;
|
||||
typedef typename GT::FT FT;
|
||||
const GT traits = choose_parameter(get_parameter(np, internal_np::vertex_point), GT());
|
||||
|
||||
typedef typename GetVertexPointMap<TriangleMesh, NamedParameters>::const_type VPM;
|
||||
typedef typename boost::property_traits<VPM>::value_type Point_3;
|
||||
const VPM vpm = choose_parameter(get_parameter(np, internal_np::vertex_point),
|
||||
get_const_property_map(CGAL::vertex_point, tmesh));
|
||||
|
||||
typedef typename GetFaceIndexMap<TriangleMesh, NamedParameters>::type FaceIndexMap;
|
||||
FaceIndexMap fim = choose_parameter(get_parameter(np, internal_np::face_index),
|
||||
get_property_map(boost::face_index, tmesh));
|
||||
|
||||
FT area_threshold = choose_parameter(get_parameter(np, internal_np::area_threshold), FT(-1));
|
||||
FT volume_threshold = choose_parameter(get_parameter(np, internal_np::volume_threshold), FT(-1));
|
||||
|
||||
// If no threshold is provided, compute it as a % of the bbox
|
||||
const bool is_default_area_threshold = is_default_parameter(get_parameter(np, internal_np::area_threshold));
|
||||
const bool is_default_volume_threshold = is_default_parameter(get_parameter(np, internal_np::volume_threshold));
|
||||
|
||||
const bool dry_run = choose_parameter(get_parameter(np, internal_np::dry_run), false);
|
||||
|
||||
typedef typename internal_np::Lookup_named_param_def<internal_np::output_iterator_t,
|
||||
NamedParameters,
|
||||
Emptyset_iterator>::type Output_iterator;
|
||||
Output_iterator out = choose_parameter(get_parameter(np, internal_np::output_iterator), Emptyset_iterator());
|
||||
|
||||
#ifdef CGAL_PMP_DEBUG_SMALL_CC_REMOVAL
|
||||
std::cout << "default threshold? " << is_default_area_threshold << " " << is_default_volume_threshold << std::endl;
|
||||
#endif
|
||||
|
||||
FT bbox_diagonal = FT(0), threshold_value = FT(0);
|
||||
|
||||
if(is_default_area_threshold || is_default_volume_threshold)
|
||||
{
|
||||
if(is_empty(tmesh))
|
||||
return 0;
|
||||
|
||||
const Bbox_3 bb = bbox(tmesh, np);
|
||||
|
||||
bbox_diagonal = FT(CGAL::sqrt(CGAL::square(bb.xmax() - bb.xmin()) +
|
||||
CGAL::square(bb.ymax() - bb.ymin()) +
|
||||
CGAL::square(bb.zmax() - bb.zmin())));
|
||||
threshold_value = bbox_diagonal / FT(100); // default filter is 1%
|
||||
|
||||
#ifdef CGAL_PMP_DEBUG_SMALL_CC_REMOVAL
|
||||
std::cout << "bb xmin xmax: " << bb.xmin() << " " << bb.xmax() << std::endl;
|
||||
std::cout << "bb ymin ymax: " << bb.ymin() << " " << bb.ymax() << std::endl;
|
||||
std::cout << "bb zmin zmax: " << bb.zmin() << " " << bb.zmax() << std::endl;
|
||||
std::cout << "bbox_diagonal: " << bbox_diagonal << std::endl;
|
||||
std::cout << "threshold_value: " << threshold_value << std::endl;
|
||||
#endif
|
||||
}
|
||||
|
||||
if(is_default_area_threshold)
|
||||
area_threshold = CGAL::square(threshold_value);
|
||||
|
||||
if(is_default_volume_threshold)
|
||||
volume_threshold = CGAL::square(threshold_value);
|
||||
|
||||
const bool use_areas = (is_default_area_threshold || area_threshold > 0);
|
||||
const bool use_volumes = (is_default_volume_threshold || volume_threshold > 0);
|
||||
|
||||
if(!use_areas && !use_volumes)
|
||||
return 0;
|
||||
|
||||
// Compute the connected components only once
|
||||
boost::vector_property_map<std::size_t, FaceIndexMap> face_cc(fim);
|
||||
std::size_t num = connected_components(tmesh, face_cc, np);
|
||||
|
||||
#ifdef CGAL_PMP_DEBUG_SMALL_CC_REMOVAL
|
||||
std::cout << num << " different connected components" << std::endl;
|
||||
#endif
|
||||
|
||||
if(!dry_run)
|
||||
CGAL::Polygon_mesh_processing::remove_isolated_vertices(tmesh);
|
||||
|
||||
// Compute CC-wide and total areas/volumes
|
||||
FT total_area = 0;
|
||||
std::vector<FT> component_areas(num, 0);
|
||||
|
||||
if(use_areas)
|
||||
{
|
||||
for(face_descriptor f : faces(tmesh))
|
||||
{
|
||||
const FT fa = face_area(f, tmesh, np);
|
||||
component_areas[face_cc[f]] += fa;
|
||||
total_area += fa;
|
||||
}
|
||||
|
||||
#ifdef CGAL_PMP_DEBUG_SMALL_CC_REMOVAL
|
||||
std::cout << "area threshold: " << area_threshold << std::endl;
|
||||
std::cout << "total area: " << total_area << std::endl;
|
||||
#endif
|
||||
}
|
||||
|
||||
// Volumes make no sense for CCs that are not closed
|
||||
std::vector<bool> cc_closeness(num, true);
|
||||
std::vector<FT> component_volumes(num);
|
||||
|
||||
if(use_volumes)
|
||||
{
|
||||
for(halfedge_descriptor h : halfedges(tmesh))
|
||||
{
|
||||
if(is_border(h, tmesh))
|
||||
cc_closeness[face_cc[face(opposite(h, tmesh), tmesh)]] = false;
|
||||
}
|
||||
|
||||
typename GT::Compute_volume_3 cv3 = traits.compute_volume_3_object();
|
||||
Point_3 origin(0, 0, 0);
|
||||
|
||||
for(face_descriptor f : faces(tmesh))
|
||||
{
|
||||
const std::size_t i = face_cc[f];
|
||||
if(!cc_closeness[i])
|
||||
continue;
|
||||
|
||||
const FT fv = cv3(origin,
|
||||
get(vpm, target(halfedge(f, tmesh), tmesh)),
|
||||
get(vpm, target(next(halfedge(f, tmesh), tmesh), tmesh)),
|
||||
get(vpm, target(prev(halfedge(f, tmesh), tmesh), tmesh)));
|
||||
|
||||
component_volumes[i] += fv;
|
||||
}
|
||||
|
||||
// negative volume means the CC was oriented inward
|
||||
FT total_volume = 0;
|
||||
for(std::size_t i=0; i<num; ++i)
|
||||
{
|
||||
component_volumes[i] = CGAL::abs(component_volumes[i]);
|
||||
total_volume += component_volumes[i];
|
||||
}
|
||||
|
||||
#ifdef CGAL_PMP_DEBUG_SMALL_CC_REMOVAL
|
||||
std::cout << "volume threshold: " << volume_threshold << std::endl;
|
||||
std::cout << "total volume: " << total_volume << std::endl;
|
||||
#endif
|
||||
}
|
||||
|
||||
std::size_t res = 0;
|
||||
std::vector<bool> is_to_be_removed(num, false);
|
||||
|
||||
for(std::size_t i=0; i<num; ++i)
|
||||
{
|
||||
#ifdef CGAL_PMP_DEBUG_SMALL_CC_REMOVAL
|
||||
std::cout << "CC " << i << " has area: " << component_areas[i]
|
||||
<< " and volume: " << component_volumes[i] << std::endl;
|
||||
#endif
|
||||
|
||||
if((use_volumes && cc_closeness[i] && component_volumes[i] <= volume_threshold) ||
|
||||
(use_areas && component_areas[i] <= area_threshold))
|
||||
{
|
||||
is_to_be_removed[i] = true;
|
||||
++res;
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef CGAL_PMP_DEBUG_SMALL_CC_REMOVAL
|
||||
std::cout << "Removing " << res << " CCs" << std::endl;
|
||||
#endif
|
||||
|
||||
if(dry_run)
|
||||
{
|
||||
for(face_descriptor f : faces(tmesh))
|
||||
if(is_to_be_removed[face_cc[f]])
|
||||
*out++ = f;
|
||||
}
|
||||
else
|
||||
{
|
||||
std::vector<std::size_t> ccs_to_remove;
|
||||
for(std::size_t i=0; i<num; ++i)
|
||||
if(is_to_be_removed[i])
|
||||
ccs_to_remove.push_back(i);
|
||||
|
||||
remove_connected_components(tmesh, ccs_to_remove, face_cc, np);
|
||||
CGAL_expensive_postcondition(is_valid_polygon_mesh(tmesh));
|
||||
}
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
template <typename TriangleMesh>
|
||||
std::size_t remove_connected_components_of_negligible_size(TriangleMesh& tmesh)
|
||||
{
|
||||
return remove_connected_components_of_negligible_size(tmesh, parameters::all_default());
|
||||
}
|
||||
|
||||
namespace debug{
|
||||
|
||||
template <class TriangleMesh, class VertexPointMap>
|
||||
|
|
@ -2368,37 +2648,6 @@ std::size_t duplicate_non_manifold_vertices(PolygonMesh& pm)
|
|||
return duplicate_non_manifold_vertices(pm, parameters::all_default());
|
||||
}
|
||||
|
||||
/// \ingroup PMP_repairing_grp
|
||||
/// removes the isolated vertices from any polygon mesh.
|
||||
/// A vertex is considered isolated if it is not incident to any simplex
|
||||
/// of higher dimension.
|
||||
///
|
||||
/// @tparam PolygonMesh a model of `FaceListGraph` and `MutableFaceGraph`
|
||||
///
|
||||
/// @param pmesh the polygon mesh to be repaired
|
||||
///
|
||||
/// @return number of removed isolated vertices
|
||||
///
|
||||
template <class PolygonMesh>
|
||||
std::size_t remove_isolated_vertices(PolygonMesh& pmesh)
|
||||
{
|
||||
typedef typename boost::graph_traits<PolygonMesh>::vertex_descriptor vertex_descriptor;
|
||||
std::vector<vertex_descriptor> to_be_removed;
|
||||
|
||||
for(vertex_descriptor v : vertices(pmesh))
|
||||
{
|
||||
if (CGAL::halfedges_around_target(v, pmesh).first
|
||||
== CGAL::halfedges_around_target(v, pmesh).second)
|
||||
to_be_removed.push_back(v);
|
||||
}
|
||||
std::size_t nb_removed = to_be_removed.size();
|
||||
for(vertex_descriptor v : to_be_removed)
|
||||
{
|
||||
remove_vertex(v, pmesh);
|
||||
}
|
||||
return nb_removed;
|
||||
}
|
||||
|
||||
/// \cond SKIP_IN_MANUAL
|
||||
template <class TriangleMesh, class face_descriptor, class VertexPointMap>
|
||||
std::pair< bool, bool >
|
||||
|
|
|
|||
|
|
@ -5,7 +5,7 @@ cmake_minimum_required(VERSION 3.1...3.15)
|
|||
project( Polygon_mesh_processing_Tests )
|
||||
|
||||
# CGAL and its components
|
||||
find_package( CGAL QUIET COMPONENTS )
|
||||
find_package( CGAL QUIET COMPONENTS Core)
|
||||
|
||||
if ( NOT CGAL_FOUND )
|
||||
|
||||
|
|
@ -14,6 +14,8 @@ if ( NOT CGAL_FOUND )
|
|||
|
||||
endif()
|
||||
|
||||
include(${CGAL_USE_FILE})
|
||||
|
||||
# Boost and its components
|
||||
find_package( Boost REQUIRED )
|
||||
|
||||
|
|
|
|||
|
|
@ -45,6 +45,19 @@ void mesh_with_id(const char* argv1, const bool save_output)
|
|||
assert(num == 3);
|
||||
|
||||
std::cerr << "The graph has " << num << " connected components (face connectivity)" << std::endl;
|
||||
std::size_t nb_faces = num_faces(sm);
|
||||
std::vector<face_descriptor> faces_to_remove; // faces that would be removed but are not because we're doing a dry run
|
||||
std::size_t nb_to_remove = PMP::keep_large_connected_components(sm, 1000,
|
||||
CGAL::parameters::face_size_map(
|
||||
CGAL::Constant_property_map<face_descriptor, std::size_t>(1))
|
||||
.dry_run(true)
|
||||
.output_iterator(std::back_inserter(faces_to_remove)));
|
||||
assert(!faces_to_remove.empty());
|
||||
if (strcmp(argv1, "data/blobby_3cc.off") == 0)
|
||||
{
|
||||
assert(nb_to_remove == 1);
|
||||
assert(num_faces(sm) == nb_faces);
|
||||
}
|
||||
|
||||
PMP::keep_largest_connected_components(sm, 2,
|
||||
CGAL::parameters::face_size_map(
|
||||
|
|
|
|||
|
|
@ -161,8 +161,26 @@ void test_CC_with_area_size_map(Mesh sm,
|
|||
typedef boost::graph_traits<Mesh>::face_descriptor face_descriptor;
|
||||
|
||||
Face_descriptor_area_functor<Mesh, Kernel> f(sm, k);
|
||||
std::vector<face_descriptor> faces_to_remove; // faces that would be removed but are not because we're doing a dry run
|
||||
std::size_t nv = num_vertices(sm);
|
||||
std::size_t num = PMP::internal::number_of_connected_components(sm);
|
||||
|
||||
std::cout << "We keep the " << 2 << " largest components" << std::endl;
|
||||
std::size_t res = PMP::keep_largest_connected_components(sm, 2,
|
||||
PMP::parameters::face_size_map(CGAL::internal::boost_::make_function_property_map<face_descriptor>(f))
|
||||
.dry_run(true)
|
||||
.output_iterator(std::back_inserter(faces_to_remove)));
|
||||
|
||||
// didn't actually remove anything
|
||||
assert(PMP::internal::number_of_connected_components(sm) == num);
|
||||
assert(num_vertices(sm) == nv);
|
||||
|
||||
if(num > 2)
|
||||
{
|
||||
assert(res == num - 2);
|
||||
assert(!faces_to_remove.empty());
|
||||
}
|
||||
|
||||
PMP::keep_largest_connected_components(sm, 2,
|
||||
PMP::parameters::face_size_map(
|
||||
CGAL::internal::boost_::make_function_property_map<face_descriptor>(f)));
|
||||
|
|
@ -183,6 +201,12 @@ void test_CC_with_area_size_map(Mesh sm,
|
|||
CGAL::parameters::face_size_map(
|
||||
CGAL::internal::boost_::make_function_property_map<face_descriptor>(f)));
|
||||
assert(vertices(m).size() == 3);
|
||||
|
||||
PMP::keep_largest_connected_components(m, 1);
|
||||
assert(PMP::internal::number_of_connected_components(m) == 1);
|
||||
PMP::keep_largest_connected_components(m, 0);
|
||||
assert(is_empty(m));
|
||||
assert(PMP::internal::number_of_connected_components(m) == 0);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -0,0 +1,15 @@
|
|||
OFF
|
||||
7 6 0
|
||||
0.50085999554530469 0.98935974982034269 0.054777016186685679
|
||||
0.51086414037695982 0.0074532224578913869 0.0098759303387234813
|
||||
0.23667027533904861 -0.19236191791372245 0.078118737677961653
|
||||
0.49890739640011506 0.47147692553082188 0.51901846156493603
|
||||
0.5 0.5 0
|
||||
0.8400145559724278 0.28990007922508693 -0.53104077094013602
|
||||
-0.011501240589425327 0.99837637926383715 0.011228717925938695
|
||||
3 4 5 0
|
||||
3 1 4 3
|
||||
3 3 4 6
|
||||
3 4 0 6
|
||||
3 1 2 4
|
||||
3 2 5 4
|
||||
|
|
@ -0,0 +1,371 @@
|
|||
OFF
|
||||
141 228 0
|
||||
-1 -1 1
|
||||
1 -1 1
|
||||
1 -1 -1
|
||||
-1 -1 -1
|
||||
-1 1 -1
|
||||
-1 1 1
|
||||
1 1 1
|
||||
1 1 -1
|
||||
-2 1 0
|
||||
-2 0 -1.0000000000000001e-05
|
||||
-2.0000100000000001 0 -1.2246467991473532e-21
|
||||
-2 0 1.0000000000000001e-05
|
||||
-1.9999899999999999 0 0
|
||||
-2 0 0
|
||||
0.066195740892434629 9.7645929666223047e-06 3.4984150593572543
|
||||
6.123233995736766e-17 0 2
|
||||
-1 0 3
|
||||
-1.8369701987210297e-16 0 4
|
||||
1 0 3
|
||||
0 0 3
|
||||
0 4 0
|
||||
0 4.0000001000000003 0
|
||||
0 4.0000001999999997 0
|
||||
1.0000000000000002e-06 4.0000001000000003 0
|
||||
0 4.0000003 0
|
||||
1.0000000000000002e-06 4.0000001999999997 0
|
||||
0 4.0000004000000002 0
|
||||
1.0000000000000002e-06 4.0000003 0
|
||||
0 4.0000005000000005 0
|
||||
1.0000000000000002e-06 4.0000004000000002 0
|
||||
0 4.0000005999999999 0
|
||||
1.0000000000000002e-06 4.0000005000000005 0
|
||||
0 4.0000007000000002 0
|
||||
1.0000000000000002e-06 4.0000005999999999 0
|
||||
0 4.0000008000000005 0
|
||||
1.0000000000000002e-06 4.0000007000000002 0
|
||||
0 4.0000008999999999 0
|
||||
1.0000000000000002e-06 4.0000008000000005 0
|
||||
0 4.0000010000000001 0
|
||||
1.0000000000000002e-06 4.0000008999999999 0
|
||||
1.0000000000000002e-06 4.0000010000000001 0
|
||||
1.0000000000000002e-06 4 0
|
||||
2.0000000000000003e-06 4.0000001000000003 0
|
||||
2.0000000000000003e-06 4.0000001999999997 0
|
||||
2.0000000000000003e-06 4.0000003 0
|
||||
2.0000000000000003e-06 4.0000004000000002 0
|
||||
2.0000000000000003e-06 4.0000005000000005 0
|
||||
2.0000000000000003e-06 4.0000005999999999 0
|
||||
2.0000000000000003e-06 4.0000007000000002 0
|
||||
2.0000000000000003e-06 4.0000008000000005 0
|
||||
2.0000000000000003e-06 4.0000008999999999 0
|
||||
2.0000000000000003e-06 4.0000010000000001 0
|
||||
2.0000000000000003e-06 4 0
|
||||
3.0000000000000005e-06 4.0000001000000003 0
|
||||
3.0000000000000005e-06 4.0000001999999997 0
|
||||
3.0000000000000005e-06 4.0000003 0
|
||||
3.0000000000000005e-06 4.0000004000000002 0
|
||||
3.0000000000000005e-06 4.0000005000000005 0
|
||||
3.0000000000000005e-06 4.0000005999999999 0
|
||||
3.0000000000000005e-06 4.0000007000000002 0
|
||||
3.0000000000000005e-06 4.0000008000000005 0
|
||||
3.0000000000000005e-06 4.0000008999999999 0
|
||||
3.0000000000000005e-06 4.0000010000000001 0
|
||||
3.0000000000000005e-06 4 0
|
||||
4.0000000000000007e-06 4.0000001000000003 0
|
||||
4.0000000000000007e-06 4.0000001999999997 0
|
||||
4.0000000000000007e-06 4.0000003 0
|
||||
4.0000000000000007e-06 4.0000004000000002 0
|
||||
4.0000000000000007e-06 4.0000005000000005 0
|
||||
4.0000000000000007e-06 4.0000005999999999 0
|
||||
4.0000000000000007e-06 4.0000007000000002 0
|
||||
4.0000000000000007e-06 4.0000008000000005 0
|
||||
4.0000000000000007e-06 4.0000008999999999 0
|
||||
4.0000000000000007e-06 4.0000010000000001 0
|
||||
4.0000000000000007e-06 4 0
|
||||
5.0000000000000004e-06 4.0000001000000003 0
|
||||
5.0000000000000004e-06 4.0000001999999997 0
|
||||
5.0000000000000004e-06 4.0000003 0
|
||||
5.0000000000000004e-06 4.0000004000000002 0
|
||||
5.0000000000000004e-06 4.0000005000000005 0
|
||||
5.0000000000000004e-06 4.0000005999999999 0
|
||||
5.0000000000000004e-06 4.0000007000000002 0
|
||||
5.0000000000000004e-06 4.0000008000000005 0
|
||||
5.0000000000000004e-06 4.0000008999999999 0
|
||||
5.0000000000000004e-06 4.0000010000000001 0
|
||||
5.0000000000000004e-06 4 0
|
||||
6.000000000000001e-06 4.0000001000000003 0
|
||||
6.000000000000001e-06 4.0000001999999997 0
|
||||
6.000000000000001e-06 4.0000003 0
|
||||
6.000000000000001e-06 4.0000004000000002 0
|
||||
6.000000000000001e-06 4.0000005000000005 0
|
||||
6.000000000000001e-06 4.0000005999999999 0
|
||||
6.000000000000001e-06 4.0000007000000002 0
|
||||
6.000000000000001e-06 4.0000008000000005 0
|
||||
6.000000000000001e-06 4.0000008999999999 0
|
||||
6.000000000000001e-06 4.0000010000000001 0
|
||||
6.000000000000001e-06 4 0
|
||||
7.0000000000000007e-06 4.0000001000000003 0
|
||||
7.0000000000000007e-06 4.0000001999999997 0
|
||||
7.0000000000000007e-06 4.0000003 0
|
||||
7.0000000000000007e-06 4.0000004000000002 0
|
||||
7.0000000000000007e-06 4.0000005000000005 0
|
||||
7.0000000000000007e-06 4.0000005999999999 0
|
||||
7.0000000000000007e-06 4.0000007000000002 0
|
||||
7.0000000000000007e-06 4.0000008000000005 0
|
||||
7.0000000000000007e-06 4.0000008999999999 0
|
||||
7.0000000000000007e-06 4.0000010000000001 0
|
||||
7.0000000000000007e-06 4 0
|
||||
8.0000000000000013e-06 4.0000001000000003 0
|
||||
8.0000000000000013e-06 4.0000001999999997 0
|
||||
8.0000000000000013e-06 4.0000003 0
|
||||
8.0000000000000013e-06 4.0000004000000002 0
|
||||
8.0000000000000013e-06 4.0000005000000005 0
|
||||
8.0000000000000013e-06 4.0000005999999999 0
|
||||
8.0000000000000013e-06 4.0000007000000002 0
|
||||
8.0000000000000013e-06 4.0000008000000005 0
|
||||
8.0000000000000013e-06 4.0000008999999999 0
|
||||
8.0000000000000013e-06 4.0000010000000001 0
|
||||
8.0000000000000013e-06 4 0
|
||||
9.0000000000000002e-06 4.0000001000000003 0
|
||||
9.0000000000000002e-06 4.0000001999999997 0
|
||||
9.0000000000000002e-06 4.0000003 0
|
||||
9.0000000000000002e-06 4.0000004000000002 0
|
||||
9.0000000000000002e-06 4.0000005000000005 0
|
||||
9.0000000000000002e-06 4.0000005999999999 0
|
||||
9.0000000000000002e-06 4.0000007000000002 0
|
||||
9.0000000000000002e-06 4.0000008000000005 0
|
||||
9.0000000000000002e-06 4.0000008999999999 0
|
||||
9.0000000000000002e-06 4.0000010000000001 0
|
||||
9.0000000000000002e-06 4 0
|
||||
1.0000000000000001e-05 4 0
|
||||
1.0000000000000001e-05 4.0000001000000003 0
|
||||
1.0000000000000001e-05 4.0000001999999997 0
|
||||
1.0000000000000001e-05 4.0000003 0
|
||||
1.0000000000000001e-05 4.0000004000000002 0
|
||||
1.0000000000000001e-05 4.0000005000000005 0
|
||||
1.0000000000000001e-05 4.0000005999999999 0
|
||||
1.0000000000000001e-05 4.0000007000000002 0
|
||||
1.0000000000000001e-05 4.0000008000000005 0
|
||||
1.0000000000000001e-05 4.0000008999999999 0
|
||||
1.0000000000000001e-05 4.0000010000000001 0
|
||||
3 4 5 6
|
||||
3 0 3 2
|
||||
3 1 2 7
|
||||
3 0 1 6
|
||||
3 3 0 5
|
||||
3 2 3 4
|
||||
3 6 7 4
|
||||
3 2 1 0
|
||||
3 7 6 1
|
||||
3 6 5 0
|
||||
3 5 4 3
|
||||
3 4 7 2
|
||||
3 9 8 12
|
||||
3 10 8 9
|
||||
3 11 8 10
|
||||
3 12 8 11
|
||||
3 12 13 9
|
||||
3 9 13 10
|
||||
3 10 13 11
|
||||
3 11 13 12
|
||||
3 15 14 18
|
||||
3 16 14 15
|
||||
3 17 14 16
|
||||
3 18 14 17
|
||||
3 18 19 15
|
||||
3 15 19 16
|
||||
3 16 19 17
|
||||
3 17 19 18
|
||||
3 21 20 41
|
||||
3 21 41 23
|
||||
3 22 21 23
|
||||
3 22 23 25
|
||||
3 24 22 25
|
||||
3 24 25 27
|
||||
3 26 24 27
|
||||
3 26 27 29
|
||||
3 28 26 29
|
||||
3 28 29 31
|
||||
3 30 28 31
|
||||
3 30 31 33
|
||||
3 32 30 33
|
||||
3 32 33 35
|
||||
3 34 32 35
|
||||
3 34 35 37
|
||||
3 36 34 37
|
||||
3 36 37 39
|
||||
3 38 36 39
|
||||
3 38 39 40
|
||||
3 23 41 52
|
||||
3 23 52 42
|
||||
3 25 23 42
|
||||
3 25 42 43
|
||||
3 27 25 43
|
||||
3 27 43 44
|
||||
3 29 27 44
|
||||
3 29 44 45
|
||||
3 31 29 45
|
||||
3 31 45 46
|
||||
3 33 31 46
|
||||
3 33 46 47
|
||||
3 35 33 47
|
||||
3 35 47 48
|
||||
3 37 35 48
|
||||
3 37 48 49
|
||||
3 39 37 49
|
||||
3 39 49 50
|
||||
3 40 39 50
|
||||
3 40 50 51
|
||||
3 42 52 63
|
||||
3 42 63 53
|
||||
3 43 42 53
|
||||
3 43 53 54
|
||||
3 44 43 54
|
||||
3 44 54 55
|
||||
3 45 44 55
|
||||
3 45 55 56
|
||||
3 46 45 56
|
||||
3 46 56 57
|
||||
3 47 46 57
|
||||
3 47 57 58
|
||||
3 48 47 58
|
||||
3 48 58 59
|
||||
3 49 48 59
|
||||
3 49 59 60
|
||||
3 50 49 60
|
||||
3 50 60 61
|
||||
3 51 50 61
|
||||
3 51 61 62
|
||||
3 53 63 74
|
||||
3 53 74 64
|
||||
3 54 53 64
|
||||
3 54 64 65
|
||||
3 55 54 65
|
||||
3 55 65 66
|
||||
3 56 55 66
|
||||
3 56 66 67
|
||||
3 57 56 67
|
||||
3 57 67 68
|
||||
3 58 57 68
|
||||
3 58 68 69
|
||||
3 59 58 69
|
||||
3 59 69 70
|
||||
3 60 59 70
|
||||
3 60 70 71
|
||||
3 61 60 71
|
||||
3 61 71 72
|
||||
3 62 61 72
|
||||
3 62 72 73
|
||||
3 64 74 85
|
||||
3 64 85 75
|
||||
3 65 64 75
|
||||
3 65 75 76
|
||||
3 66 65 76
|
||||
3 66 76 77
|
||||
3 67 66 77
|
||||
3 67 77 78
|
||||
3 68 67 78
|
||||
3 68 78 79
|
||||
3 69 68 79
|
||||
3 69 79 80
|
||||
3 70 69 80
|
||||
3 70 80 81
|
||||
3 71 70 81
|
||||
3 71 81 82
|
||||
3 72 71 82
|
||||
3 72 82 83
|
||||
3 73 72 83
|
||||
3 73 83 84
|
||||
3 75 85 96
|
||||
3 75 96 86
|
||||
3 76 75 86
|
||||
3 76 86 87
|
||||
3 77 76 87
|
||||
3 77 87 88
|
||||
3 78 77 88
|
||||
3 78 88 89
|
||||
3 79 78 89
|
||||
3 79 89 90
|
||||
3 80 79 90
|
||||
3 80 90 91
|
||||
3 81 80 91
|
||||
3 81 91 92
|
||||
3 82 81 92
|
||||
3 82 92 93
|
||||
3 83 82 93
|
||||
3 83 93 94
|
||||
3 84 83 94
|
||||
3 84 94 95
|
||||
3 86 96 107
|
||||
3 86 107 97
|
||||
3 87 86 97
|
||||
3 87 97 98
|
||||
3 88 87 98
|
||||
3 88 98 99
|
||||
3 89 88 99
|
||||
3 89 99 100
|
||||
3 90 89 100
|
||||
3 90 100 101
|
||||
3 91 90 101
|
||||
3 91 101 102
|
||||
3 92 91 102
|
||||
3 92 102 103
|
||||
3 93 92 103
|
||||
3 93 103 104
|
||||
3 94 93 104
|
||||
3 94 104 105
|
||||
3 95 94 105
|
||||
3 95 105 106
|
||||
3 97 107 118
|
||||
3 97 118 108
|
||||
3 98 97 108
|
||||
3 98 108 109
|
||||
3 99 98 109
|
||||
3 99 109 110
|
||||
3 100 99 110
|
||||
3 100 110 111
|
||||
3 101 100 111
|
||||
3 101 111 112
|
||||
3 102 101 112
|
||||
3 102 112 113
|
||||
3 103 102 113
|
||||
3 103 113 114
|
||||
3 104 103 114
|
||||
3 104 114 115
|
||||
3 105 104 115
|
||||
3 105 115 116
|
||||
3 106 105 116
|
||||
3 106 116 117
|
||||
3 108 118 129
|
||||
3 108 129 119
|
||||
3 109 108 119
|
||||
3 109 119 120
|
||||
3 110 109 120
|
||||
3 110 120 121
|
||||
3 111 110 121
|
||||
3 111 121 122
|
||||
3 112 111 122
|
||||
3 112 122 123
|
||||
3 113 112 123
|
||||
3 113 123 124
|
||||
3 114 113 124
|
||||
3 114 124 125
|
||||
3 115 114 125
|
||||
3 115 125 126
|
||||
3 116 115 126
|
||||
3 116 126 127
|
||||
3 117 116 127
|
||||
3 117 127 128
|
||||
3 119 129 130
|
||||
3 119 130 131
|
||||
3 120 119 131
|
||||
3 120 131 132
|
||||
3 121 120 132
|
||||
3 121 132 133
|
||||
3 122 121 133
|
||||
3 122 133 134
|
||||
3 123 122 134
|
||||
3 123 134 135
|
||||
3 124 123 135
|
||||
3 124 135 136
|
||||
3 125 124 136
|
||||
3 125 136 137
|
||||
3 126 125 137
|
||||
3 126 137 138
|
||||
3 127 126 138
|
||||
3 127 138 139
|
||||
3 128 127 139
|
||||
3 128 139 140
|
||||
|
|
@ -1,62 +1,165 @@
|
|||
#include <CGAL/Exact_predicates_inexact_constructions_kernel.h>
|
||||
#include <CGAL/Exact_predicates_exact_constructions_kernel.h>
|
||||
#include <CGAL/Surface_mesh.h>
|
||||
#include <CGAL/Polygon_mesh_processing/compute_normal.h>
|
||||
// #define CGAL_PMP_COMPUTE_NORMAL_DEBUG
|
||||
|
||||
#include <CGAL/Timer.h>
|
||||
#include <CGAL/Exact_predicates_inexact_constructions_kernel.h>
|
||||
#include <CGAL/Exact_predicates_exact_constructions_kernel_with_sqrt.h>
|
||||
|
||||
#include <CGAL/Surface_mesh.h>
|
||||
#include <CGAL/Polyhedron_3.h>
|
||||
|
||||
#include <CGAL/Polygon_mesh_processing/compute_normal.h>
|
||||
|
||||
#include <iostream>
|
||||
#include <fstream>
|
||||
|
||||
typedef CGAL::Exact_predicates_inexact_constructions_kernel Epic;
|
||||
typedef CGAL::Exact_predicates_exact_constructions_kernel Epec;
|
||||
typedef CGAL::Exact_predicates_inexact_constructions_kernel EPICK;
|
||||
typedef CGAL::Exact_predicates_exact_constructions_kernel_with_sqrt EPECK;
|
||||
|
||||
typedef CGAL::Surface_mesh<EPICK::Point_3> EPICK_SM;
|
||||
typedef CGAL::Surface_mesh<EPECK::Point_3> EPECK_SM;
|
||||
|
||||
namespace PMP = CGAL::Polygon_mesh_processing;
|
||||
|
||||
template <typename K, typename Mesh, typename VertexNormalPmap, typename FaceNormalPmap>
|
||||
void test(const Mesh& mesh,
|
||||
const VertexNormalPmap& vnormals,
|
||||
const FaceNormalPmap& fnormals)
|
||||
{
|
||||
typedef typename K::Vector_3 Vector;
|
||||
|
||||
typedef typename boost::graph_traits<Mesh>::vertex_descriptor vertex_descriptor;
|
||||
typedef typename boost::graph_traits<Mesh>::face_descriptor face_descriptor;
|
||||
|
||||
typedef typename CGAL::GetVertexPointMap<Mesh>::const_type VPMap;
|
||||
VPMap vpmap = get_const_property_map(CGAL::vertex_point, mesh);
|
||||
|
||||
assert(!is_empty(mesh));
|
||||
|
||||
const vertex_descriptor first_vertex = *(vertices(mesh).begin());
|
||||
const face_descriptor first_face = *(faces(mesh).begin());
|
||||
|
||||
PMP::compute_face_normals(mesh, fnormals);
|
||||
PMP::compute_face_normals(mesh, fnormals, PMP::parameters::vertex_point_map(vpmap));
|
||||
PMP::compute_face_normals(mesh, fnormals, CGAL::parameters::vertex_point_map(vpmap)
|
||||
.geom_traits(K()));
|
||||
|
||||
Vector f0n = PMP::compute_face_normal(first_face, mesh);
|
||||
assert(f0n == get(fnormals, first_face));
|
||||
PMP::compute_face_normal(first_face, mesh, PMP::parameters::vertex_point_map(vpmap));
|
||||
|
||||
PMP::compute_vertex_normals(mesh, vnormals);
|
||||
PMP::compute_vertex_normals(mesh, vnormals, PMP::parameters::vertex_point_map(vpmap));
|
||||
PMP::compute_vertex_normals(mesh, vnormals, CGAL::parameters::vertex_point_map(vpmap)
|
||||
.geom_traits(K()));
|
||||
|
||||
Vector v0n = PMP::compute_vertex_normal(first_vertex, mesh);
|
||||
assert(v0n == get(vnormals, first_vertex));
|
||||
v0n = PMP::compute_vertex_normal(first_vertex, mesh, PMP::parameters::vertex_point_map(vpmap)
|
||||
.face_normal_map(fnormals));
|
||||
std::cout.precision(17);
|
||||
assert(v0n == get(vnormals, first_vertex));
|
||||
|
||||
PMP::compute_normals(mesh, vnormals, fnormals);
|
||||
PMP::compute_normals(mesh, vnormals, fnormals, PMP::parameters::vertex_point_map(vpmap));
|
||||
PMP::compute_normals(mesh, vnormals, fnormals, CGAL::parameters::vertex_point_map(vpmap)
|
||||
.geom_traits(K()));
|
||||
|
||||
for(vertex_descriptor v : vertices(mesh)) {
|
||||
assert(get(vnormals, v) != CGAL::NULL_VECTOR);
|
||||
}
|
||||
|
||||
for(face_descriptor f : faces(mesh)) {
|
||||
assert(get(fnormals, f) != CGAL::NULL_VECTOR);
|
||||
}
|
||||
}
|
||||
|
||||
template<typename K>
|
||||
void test_normals(const char* file_name)
|
||||
void test_SM(const char* file_name)
|
||||
{
|
||||
typedef typename K::Point_3 Point;
|
||||
typedef typename K::Vector_3 Vector;
|
||||
typedef CGAL::Surface_mesh<Point> Surface_mesh;
|
||||
typedef typename boost::graph_traits<Surface_mesh>::vertex_descriptor vertex_descriptor;
|
||||
typedef typename boost::graph_traits<Surface_mesh>::face_descriptor face_descriptor;
|
||||
typedef CGAL::Surface_mesh<typename K::Point_3> SM;
|
||||
typedef typename boost::graph_traits<SM>::vertex_descriptor vertex_descriptor;
|
||||
typedef typename boost::graph_traits<SM>::face_descriptor face_descriptor;
|
||||
|
||||
Surface_mesh mesh;
|
||||
typedef typename K::Vector_3 Vector;
|
||||
|
||||
std::cout << "Test with Surface_mesh, and kernel: " << typeid(K).name() << std::endl;
|
||||
|
||||
SM mesh;
|
||||
std::ifstream input(file_name);
|
||||
if (!(input >> mesh)){
|
||||
std::cerr << "Error: cannot read Surface_mesh : " << file_name << "\n";
|
||||
if(!(input >> mesh))
|
||||
{
|
||||
std::cerr << "Error: cannot read " << file_name << " as a Surface_mesh\n";
|
||||
assert(false);
|
||||
}
|
||||
|
||||
typename Surface_mesh::template Property_map<face_descriptor, Vector> fnormals;
|
||||
bool created;
|
||||
boost::tie(fnormals, created) = mesh.template add_property_map<face_descriptor,Vector>("f:normals",Vector(0,0,0));
|
||||
CGAL::Polygon_mesh_processing::compute_face_normals(mesh, fnormals);
|
||||
CGAL::Polygon_mesh_processing::compute_face_normals(mesh, fnormals,
|
||||
CGAL::Polygon_mesh_processing::parameters::vertex_point_map(mesh.points()));
|
||||
CGAL::Polygon_mesh_processing::compute_face_normals(mesh, fnormals,
|
||||
CGAL::Polygon_mesh_processing::parameters::vertex_point_map(mesh.points()).geom_traits(K()));
|
||||
typename SM::template Property_map<vertex_descriptor, Vector> vnormals;
|
||||
vnormals = mesh.template add_property_map<vertex_descriptor, Vector>("v:normals", CGAL::NULL_VECTOR).first;
|
||||
typename SM::template Property_map<face_descriptor, Vector> fnormals;
|
||||
fnormals = mesh.template add_property_map<face_descriptor, Vector>("f:normals", CGAL::NULL_VECTOR).first;
|
||||
|
||||
typename Surface_mesh:: template Property_map<vertex_descriptor,Vector> vnormals;
|
||||
test<K>(mesh, vnormals, fnormals);
|
||||
}
|
||||
|
||||
boost::tie(vnormals, created) = mesh.template add_property_map<vertex_descriptor,Vector>("v:normals",Vector(0,0,0));
|
||||
CGAL::Polygon_mesh_processing::compute_vertex_normals(mesh, vnormals);
|
||||
CGAL::Polygon_mesh_processing::compute_vertex_normals(mesh, vnormals,
|
||||
CGAL::Polygon_mesh_processing::parameters::vertex_point_map(mesh.points()));
|
||||
CGAL::Polygon_mesh_processing::compute_vertex_normals(mesh, vnormals,
|
||||
CGAL::Polygon_mesh_processing::parameters::vertex_point_map(mesh.points()).geom_traits(K()));
|
||||
template<typename K>
|
||||
void test_Polyhedron(const char* file_name)
|
||||
{
|
||||
typedef CGAL::Polyhedron_3<K> Polyhedron;
|
||||
typedef typename boost::graph_traits<Polyhedron>::vertex_descriptor vertex_descriptor;
|
||||
typedef typename boost::graph_traits<Polyhedron>::face_descriptor face_descriptor;
|
||||
|
||||
CGAL::Polygon_mesh_processing::compute_normals(mesh, vnormals, fnormals);
|
||||
CGAL::Polygon_mesh_processing::compute_normals(mesh, vnormals, fnormals,
|
||||
CGAL::Polygon_mesh_processing::parameters::vertex_point_map(mesh.points()));
|
||||
CGAL::Polygon_mesh_processing::compute_normals(mesh, vnormals, fnormals,
|
||||
CGAL::Polygon_mesh_processing::parameters::vertex_point_map(mesh.points()).geom_traits(K()));
|
||||
typedef typename K::Vector_3 Vector;
|
||||
|
||||
std::cout << "Test with Polyhedron, and kernel: " << typeid(K).name() << std::endl;
|
||||
|
||||
Polyhedron mesh;
|
||||
std::ifstream input(file_name);
|
||||
if(!(input >> mesh))
|
||||
{
|
||||
std::cerr << "Error: cannot read " << file_name << " as a Polyhedron\n";
|
||||
assert(false);
|
||||
}
|
||||
|
||||
typedef std::map<vertex_descriptor, Vector> VertexNormalMap;
|
||||
typedef boost::associative_property_map<VertexNormalMap> VertexNormalPMap;
|
||||
typedef std::map<face_descriptor, Vector> FaceNormalMap;
|
||||
typedef boost::associative_property_map<FaceNormalMap> FaceNormalPMap;
|
||||
|
||||
VertexNormalMap vn_map;
|
||||
FaceNormalMap fn_map;
|
||||
|
||||
for(vertex_descriptor v : vertices(mesh))
|
||||
vn_map[v] = CGAL::NULL_VECTOR;
|
||||
for(face_descriptor f : faces(mesh))
|
||||
fn_map[f] = CGAL::NULL_VECTOR;
|
||||
|
||||
VertexNormalPMap vnormals(vn_map);
|
||||
FaceNormalPMap fnormals(fn_map);
|
||||
|
||||
test<K>(mesh, vnormals, fnormals);
|
||||
}
|
||||
|
||||
void test(const char* filename)
|
||||
{
|
||||
std::cout << "test " << filename << "..." << std::endl;
|
||||
|
||||
// EPECK disabled because it takes too long for the testsuite due to sq roots comparisons,
|
||||
// but it passed.
|
||||
test_SM<EPICK>(filename);
|
||||
// test_SM<EPECK>(filename);
|
||||
test_Polyhedron<EPICK>(filename);
|
||||
// test_Polyhedron<EPECK>(filename);
|
||||
}
|
||||
|
||||
int main()
|
||||
{
|
||||
test_normals<Epic>("data/elephant.off");
|
||||
test_normals<Epec>("data/elephant.off");
|
||||
std::cout.precision(17);
|
||||
|
||||
CGAL::Set_ieee_double_precision pfr;
|
||||
|
||||
test("data/elephant.off");
|
||||
test("data/folded_star.off");
|
||||
test("data/joint_refined.off");
|
||||
test("data/mannequin-devil.off");
|
||||
test("data/U.off");
|
||||
|
||||
std::cerr << "All done." << std::endl;
|
||||
return EXIT_SUCCESS;
|
||||
|
|
|
|||
|
|
@ -1,8 +1,12 @@
|
|||
#define CGAL_PMP_DEBUG_SMALL_CC_REMOVAL
|
||||
|
||||
#include <CGAL/Exact_predicates_inexact_constructions_kernel.h>
|
||||
|
||||
#include <CGAL/Surface_mesh.h>
|
||||
#include <CGAL/Polyhedron_3.h>
|
||||
#include <CGAL/Polyhedron_items_with_id_3.h>
|
||||
|
||||
#include <CGAL/Polygon_mesh_processing/connected_components.h>
|
||||
#include <CGAL/Polygon_mesh_processing/repair.h>
|
||||
|
||||
#include <iostream>
|
||||
|
|
@ -14,12 +18,10 @@
|
|||
//
|
||||
|
||||
namespace PMP = CGAL::Polygon_mesh_processing;
|
||||
namespace CP = CGAL::parameters;
|
||||
|
||||
typedef CGAL::Exact_predicates_inexact_constructions_kernel EPICK;
|
||||
|
||||
typedef CGAL::Surface_mesh<EPICK::Point_3> Surface_mesh;
|
||||
typedef CGAL::Polyhedron_3<EPICK> Polyhedron;
|
||||
|
||||
template <typename K, typename EdgeRange, typename FaceRange, typename Mesh>
|
||||
void detect_degeneracies(const EdgeRange& edge_range,
|
||||
const FaceRange& face_range,
|
||||
|
|
@ -34,10 +36,10 @@ void detect_degeneracies(const EdgeRange& edge_range,
|
|||
std::set<edge_descriptor> dedges;
|
||||
PMP::degenerate_edges(mesh, std::inserter(dedges, dedges.end()));
|
||||
PMP::degenerate_edges(edge_range, mesh, std::inserter(dedges, dedges.begin()));
|
||||
PMP::degenerate_edges(mesh, std::inserter(dedges, dedges.end()), CGAL::parameters::all_default());
|
||||
PMP::degenerate_edges(mesh, std::inserter(dedges, dedges.end()), CP::all_default());
|
||||
|
||||
dedges.clear();
|
||||
PMP::degenerate_edges(edge_range, mesh, std::inserter(dedges, dedges.begin()), CGAL::parameters::all_default());
|
||||
PMP::degenerate_edges(edge_range, mesh, std::inserter(dedges, dedges.begin()), CP::all_default());
|
||||
std::cout << "\t" << dedges.size() << " degenerate edges vs " << expected_dedges_n << std::endl;
|
||||
assert(dedges.size() == expected_dedges_n);
|
||||
|
||||
|
|
@ -45,10 +47,10 @@ void detect_degeneracies(const EdgeRange& edge_range,
|
|||
std::vector<face_descriptor> dfaces;
|
||||
PMP::degenerate_faces(mesh, std::back_inserter(dfaces));
|
||||
PMP::degenerate_faces(face_range, mesh, std::back_inserter(dfaces));
|
||||
PMP::degenerate_faces(mesh, std::back_inserter(dfaces), CGAL::parameters::all_default());
|
||||
PMP::degenerate_faces(mesh, std::back_inserter(dfaces), CP::all_default());
|
||||
|
||||
dfaces.clear();
|
||||
PMP::degenerate_faces(face_range, mesh, std::back_inserter(dfaces), CGAL::parameters::all_default());
|
||||
PMP::degenerate_faces(face_range, mesh, std::back_inserter(dfaces), CP::all_default());
|
||||
std::cout << "\t" << dfaces.size() << " degenerate faces vs " << expected_dfaces_n << std::endl;
|
||||
assert(dfaces.size() == expected_dfaces_n);
|
||||
}
|
||||
|
|
@ -99,7 +101,7 @@ bool remove_dedges(const std::vector<std::size_t>& edges_selection_ids,
|
|||
for(std::size_t edge_id : edges_selection_ids)
|
||||
edge_range.push_back(all_edges[edge_id]);
|
||||
|
||||
return CGAL::Polygon_mesh_processing::remove_degenerate_edges(edge_range, mesh, CGAL::parameters::all_default());
|
||||
return CGAL::Polygon_mesh_processing::remove_degenerate_edges(edge_range, mesh, CP::all_default());
|
||||
}
|
||||
|
||||
template <typename Mesh>
|
||||
|
|
@ -115,11 +117,11 @@ bool remove_dfaces(const std::vector<std::size_t>& faces_selection_ids,
|
|||
for(std::size_t face_id : faces_selection_ids)
|
||||
face_range.push_back(all_faces[face_id]);
|
||||
|
||||
return CGAL::Polygon_mesh_processing::remove_degenerate_faces(face_range, mesh, CGAL::parameters::all_default());
|
||||
return CGAL::Polygon_mesh_processing::remove_degenerate_faces(face_range, mesh, CP::all_default());
|
||||
}
|
||||
|
||||
template <typename K, typename Mesh>
|
||||
void test(const char* filename,
|
||||
void remove_degeneracies(const char* filename,
|
||||
const std::vector<std::size_t>& edges_selection_ids,
|
||||
const std::vector<std::size_t>& faces_selection_ids,
|
||||
const std::size_t expected_all_degen_edges_n,
|
||||
|
|
@ -129,7 +131,7 @@ void test(const char* filename,
|
|||
const std::size_t expected_post_removal_degen_edges_n,
|
||||
const std::size_t expected_post_removal_degen_faces_n)
|
||||
{
|
||||
std::cout << " test file: " << filename << std::endl;
|
||||
std::cout << " remove_degeneracies, file: " << filename << std::endl;
|
||||
|
||||
std::ifstream input(filename);
|
||||
Mesh mesh;
|
||||
|
|
@ -149,12 +151,12 @@ void test(const char* filename,
|
|||
// Complete remove
|
||||
std::cout << " Remove all..." << std::endl;
|
||||
mesh = mesh_cpy;
|
||||
/* bool all_removed = */ CGAL::Polygon_mesh_processing::remove_degenerate_edges(mesh, CGAL::parameters::all_default());
|
||||
/* bool all_removed = */ CGAL::Polygon_mesh_processing::remove_degenerate_edges(mesh, CP::all_default());
|
||||
//assert(all_removed);
|
||||
assert(CGAL::is_valid_polygon_mesh(mesh));
|
||||
|
||||
mesh = mesh_cpy;
|
||||
/* all_removed = */ CGAL::Polygon_mesh_processing::remove_degenerate_faces(mesh, CGAL::parameters::all_default());
|
||||
/* all_removed = */ CGAL::Polygon_mesh_processing::remove_degenerate_faces(mesh, CP::all_default());
|
||||
// assert(all_removed);
|
||||
assert(CGAL::is_valid_polygon_mesh(mesh));
|
||||
|
||||
|
|
@ -179,69 +181,177 @@ void test(const char* filename,
|
|||
std::cout << " Done" << std::endl;
|
||||
}
|
||||
|
||||
template <typename Mesh>
|
||||
void initialize_IDs(const Mesh&) { }
|
||||
|
||||
template <typename Kernel>
|
||||
void initialize_IDs(const CGAL::Polyhedron_3<Kernel, CGAL::Polyhedron_items_with_id_3>& mesh)
|
||||
{
|
||||
typedef CGAL::Polyhedron_3<Kernel, CGAL::Polyhedron_items_with_id_3> Mesh;
|
||||
typedef typename boost::graph_traits<Mesh>::vertex_descriptor vertex_descriptor;
|
||||
typedef typename boost::graph_traits<Mesh>::face_descriptor face_descriptor;
|
||||
|
||||
int i=0;
|
||||
for(vertex_descriptor v : vertices(mesh))
|
||||
v->id() = i++;
|
||||
|
||||
i=0;
|
||||
for(face_descriptor f : faces(mesh))
|
||||
f->id() = i++;
|
||||
}
|
||||
|
||||
template <typename K, typename Mesh>
|
||||
void remove_negligible_connected_components(const char* filename)
|
||||
{
|
||||
typedef typename boost::graph_traits<Mesh>::face_descriptor face_descriptor;
|
||||
|
||||
std::cout << " remove negligible CCs, file: " << filename << std::endl;
|
||||
|
||||
std::ifstream input(filename);
|
||||
Mesh mesh, mesh_cpy;
|
||||
if (!input || !(input >> mesh) || mesh.is_empty())
|
||||
{
|
||||
std::cerr << filename << " is not a valid off file.\n";
|
||||
exit(1);
|
||||
}
|
||||
|
||||
mesh_cpy = mesh;
|
||||
|
||||
initialize_IDs(mesh);
|
||||
initialize_IDs(mesh_cpy);
|
||||
|
||||
std::size_t ini_nv = num_vertices(mesh);
|
||||
std::size_t ini_nf = num_faces(mesh);
|
||||
|
||||
std::cout << "before: " << ini_nv << " nv & " << ini_nf << " nf" << std::endl;
|
||||
|
||||
// negative thresholds --> doesn't remove anything
|
||||
std::cout << "---------\nnull or negative threshold, nothing happens..." << std::endl;
|
||||
std::size_t res = PMP::remove_connected_components_of_negligible_size(mesh, CP::area_threshold(-1e15)
|
||||
.volume_threshold(0));
|
||||
assert(PMP::internal::number_of_connected_components(mesh) == 4);
|
||||
assert(num_vertices(mesh) == ini_nv);
|
||||
assert(num_faces(mesh) == ini_nf);
|
||||
|
||||
// threshold too small, doesn't remove anything
|
||||
std::cout << "---------\ntiny threshold, nothing happens..." << std::endl;
|
||||
PMP::remove_connected_components_of_negligible_size(mesh, CP::area_threshold(1e-15)
|
||||
.volume_threshold(1e-15));
|
||||
assert(PMP::internal::number_of_connected_components(mesh) == 4);
|
||||
assert(num_vertices(mesh) == ini_nv);
|
||||
assert(num_faces(mesh) == ini_nf);
|
||||
|
||||
// that removes the CCs with small volumes
|
||||
std::cout << "---------\nremove small volumes..." << std::endl;
|
||||
res = PMP::remove_connected_components_of_negligible_size(mesh, CP::area_threshold(1e-15)
|
||||
.volume_threshold(0.1));
|
||||
std::cout << "res: " << res << std::endl;
|
||||
initialize_IDs(mesh);
|
||||
assert(PMP::internal::number_of_connected_components(mesh) == 2);
|
||||
|
||||
// that removes the open CC with a small area
|
||||
std::cout << "---------\nremove small areas..." << std::endl;
|
||||
PMP::remove_connected_components_of_negligible_size(mesh, CP::area_threshold(20));
|
||||
initialize_IDs(mesh);
|
||||
assert(PMP::internal::number_of_connected_components(mesh) == 1);
|
||||
|
||||
// Remove everything with a too-large value
|
||||
std::cout << "---------\nremove everything..." << std::endl;
|
||||
PMP::remove_connected_components_of_negligible_size(mesh, CP::area_threshold(1e15));
|
||||
assert(is_empty(mesh));
|
||||
|
||||
// Could also have used default paramaters, which does the job by itself
|
||||
std::cout << "---------\ndefault values..." << std::endl;
|
||||
|
||||
std::vector<face_descriptor> faces_to_be_removed;
|
||||
std::size_t nb_to_be_rm = PMP::remove_connected_components_of_negligible_size(
|
||||
mesh_cpy, CP::dry_run(true)
|
||||
.output_iterator(std::back_inserter(faces_to_be_removed)));
|
||||
assert(nb_to_be_rm == 3);
|
||||
assert(PMP::internal::number_of_connected_components(mesh_cpy) == 4); // a dry run does not remove anything
|
||||
assert(faces_to_be_removed.size() == 216); // sum of #faces of the small CCs
|
||||
|
||||
assert(nb_to_be_rm == PMP::remove_connected_components_of_negligible_size(mesh_cpy));
|
||||
assert(PMP::internal::number_of_connected_components(mesh_cpy) == 1);
|
||||
}
|
||||
|
||||
template <typename K, typename Mesh>
|
||||
void test()
|
||||
{
|
||||
test<K, Mesh>("data_degeneracies/degtri_2dt_1edge_split_twice.off",
|
||||
remove_degeneracies<K, Mesh>("data_degeneracies/degtri_2dt_1edge_split_twice.off",
|
||||
std::initializer_list<std::size_t>({0, 1, 4, 3}), // edge selection
|
||||
std::initializer_list<std::size_t>({0}), // face selection
|
||||
0, 2, // expected number of degenerate edges/faces in the complete mesh
|
||||
0, 1, // expected number of degenerate edges/faces in the selection
|
||||
0, 0); // expected number of degenerate edges/faces in the mesh after partial removal
|
||||
|
||||
test<K, Mesh>("data_degeneracies/degtri_four.off",
|
||||
remove_degeneracies<K, Mesh>("data_degeneracies/degtri_four.off",
|
||||
std::initializer_list<std::size_t>({1}),
|
||||
std::initializer_list<std::size_t>({3}),
|
||||
0, 1, 0, 0, 0, 1);
|
||||
|
||||
test<K, Mesh>("data_degeneracies/degtri_four-2.off",
|
||||
remove_degeneracies<K, Mesh>("data_degeneracies/degtri_four-2.off",
|
||||
std::initializer_list<std::size_t>({2}),
|
||||
std::initializer_list<std::size_t>({3}),
|
||||
0, 1, 0, 0, 0, 1);
|
||||
|
||||
test<K, Mesh>("data_degeneracies/degtri_on_border.off",
|
||||
remove_degeneracies<K, Mesh>("data_degeneracies/degtri_on_border.off",
|
||||
std::initializer_list<std::size_t>({2}),
|
||||
std::initializer_list<std::size_t>({0}),
|
||||
0, 1, 0, 1, 0, 0);
|
||||
|
||||
test<K, Mesh>("data_degeneracies/degtri_three.off",
|
||||
remove_degeneracies<K, Mesh>("data_degeneracies/degtri_three.off",
|
||||
std::initializer_list<std::size_t>({2}),
|
||||
std::initializer_list<std::size_t>({1}),
|
||||
0, 1, 0, 0, 0, 1);
|
||||
|
||||
test<K, Mesh>("data_degeneracies/degtri_single.off",
|
||||
remove_degeneracies<K, Mesh>("data_degeneracies/degtri_single.off",
|
||||
std::initializer_list<std::size_t>({0, 1, 2}),
|
||||
std::initializer_list<std::size_t>({0}),
|
||||
0, 1, 0, 1, 0, 0);
|
||||
|
||||
test<K, Mesh>("data_degeneracies/degtri_nullface.off",
|
||||
remove_degeneracies<K, Mesh>("data_degeneracies/degtri_nullface.off",
|
||||
std::initializer_list<std::size_t>({3, 6, 7}),
|
||||
std::initializer_list<std::size_t>({0, 1, 2}),
|
||||
3, 4, 1, 2, 0, 0);
|
||||
|
||||
test<K, Mesh>("data_degeneracies/trihole.off",
|
||||
remove_degeneracies<K, Mesh>("data_degeneracies/trihole.off",
|
||||
std::initializer_list<std::size_t>({12}),
|
||||
std::initializer_list<std::size_t>({4, 5}),
|
||||
1, 3, 1, 2, 0, 0);
|
||||
|
||||
test<K, Mesh>("data_degeneracies/degtri_sliding.off",
|
||||
remove_degeneracies<K, Mesh>("data_degeneracies/degtri_sliding.off",
|
||||
std::initializer_list<std::size_t>({2}),
|
||||
std::initializer_list<std::size_t>({2, 4}),
|
||||
0, 4, 0, 2, 0, 0);
|
||||
|
||||
test<K, Mesh>("data_degeneracies/fused_vertices.off",
|
||||
remove_degeneracies<K, Mesh>("data_degeneracies/fused_vertices.off",
|
||||
std::initializer_list<std::size_t>({5, 10, 13, 15, 27, 45}),
|
||||
std::initializer_list<std::size_t>({1, 3, 5, 10, 19}),
|
||||
6, 7, 2, 4, 3, 3);
|
||||
|
||||
remove_negligible_connected_components<K, Mesh>("data_degeneracies/small_ccs.off");
|
||||
}
|
||||
|
||||
int main()
|
||||
template <typename Kernel>
|
||||
void test()
|
||||
{
|
||||
typedef typename Kernel::Point_3 Point_3;
|
||||
typedef CGAL::Surface_mesh<Point_3> Surface_mesh;
|
||||
typedef CGAL::Polyhedron_3<Kernel, CGAL::Polyhedron_items_with_id_3> Polyhedron_with_ID;
|
||||
|
||||
std::cout << "EPICK SM TESTS" << std::endl;
|
||||
test<EPICK, Surface_mesh>();
|
||||
test<Kernel, Surface_mesh>();
|
||||
|
||||
std::cout << "EPICK POLYHEDRON TESTS" << std::endl;
|
||||
test<EPICK, Polyhedron>();
|
||||
test<Kernel, Polyhedron_with_ID>();
|
||||
}
|
||||
|
||||
int main(int /*argc*/, char** /*argv*/)
|
||||
{
|
||||
test<EPICK>();
|
||||
|
||||
std::cout << "Done" << std::endl;
|
||||
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -38,7 +38,7 @@
|
|||
#include <QSpinBox>
|
||||
#include <stdexcept>
|
||||
#include <fstream>
|
||||
#include <QTime>
|
||||
#include <QElapsedTimer>
|
||||
#include <QWidgetAction>
|
||||
#include <QJsonArray>
|
||||
#include <QSequentialIterable>
|
||||
|
|
@ -451,7 +451,7 @@ void filterMenuOperations(QMenu* menu, QString filter, bool keep_from_here)
|
|||
action->setVisible(!(submenu->isEmpty()));
|
||||
|
||||
}
|
||||
else if(action->text().contains(filter, Qt::CaseInsensitive)){
|
||||
else if(action->text().remove("&").contains(filter, Qt::CaseInsensitive)){
|
||||
//menu->addAction(action);
|
||||
addActionToMenu(action, menu);
|
||||
}
|
||||
|
|
@ -491,7 +491,7 @@ void MainWindow::filterOperations(bool)
|
|||
Q_FOREACH(const PluginNamePair& p, plugins) {
|
||||
Q_FOREACH(QAction* action, p.first->actions()) {
|
||||
action->setVisible( p.first->applicable(action)
|
||||
&& (action->text().contains(filter, Qt::CaseInsensitive)
|
||||
&& (action->text().remove("&").contains(filter, Qt::CaseInsensitive)
|
||||
|| action->property("subMenuName")
|
||||
.toString().contains(filter, Qt::CaseInsensitive)));
|
||||
}
|
||||
|
|
@ -1197,6 +1197,10 @@ void MainWindow::open(QString filename)
|
|||
selected_items << io_plugin->name();
|
||||
}
|
||||
}
|
||||
//if no plugin is correct, offer them all.
|
||||
for(CGAL::Three::Polyhedron_demo_io_plugin_interface* io_plugin : io_plugins) {
|
||||
all_items << io_plugin->name();
|
||||
}
|
||||
}
|
||||
else
|
||||
selected_items << *dfs_it;
|
||||
|
|
@ -1477,11 +1481,11 @@ void MainWindow::showSceneContextMenu(int selectedItemIndex,
|
|||
this, SLOT(reloadItem()));
|
||||
}
|
||||
QAction* saveas = menu->addAction(tr("&Save as..."));
|
||||
saveas->setData(qVariantFromValue((void*)item));
|
||||
saveas->setData(QVariant::fromValue((void*)item));
|
||||
connect(saveas, SIGNAL(triggered()),
|
||||
this, SLOT(on_actionSaveAs_triggered()));
|
||||
QAction* showobject = menu->addAction(tr("&Zoom to this Object"));
|
||||
showobject->setData(qVariantFromValue((void*)item));
|
||||
showobject->setData(QVariant::fromValue((void*)item));
|
||||
connect(showobject, SIGNAL(triggered()),
|
||||
this, SLOT(viewerShowObject()));
|
||||
|
||||
|
|
@ -1804,7 +1808,12 @@ void MainWindow::readSettings()
|
|||
viewer->setFastDrawing(settings.value("quick_camera_mode", true).toBool());
|
||||
scene->enableVisibilityRecentering(settings.value("offset_update", false).toBool());
|
||||
viewer->textRenderer()->setMax(settings.value("max_text_items", 10000).toInt());
|
||||
viewer->setTotalPass(settings.value("transparency_pass_number", 4).toInt());
|
||||
int val = settings.value("transparency_pass_number", 4).toInt();
|
||||
if (val < 4 ) {
|
||||
val = 4;
|
||||
settings.setValue("transparency_pass_number", 4);
|
||||
}
|
||||
viewer->setTotalPass(val);
|
||||
CGAL::Three::Three::s_defaultSMRM = CGAL::Three::Three::modeFromName(
|
||||
settings.value("default_sm_rm", "flat+edges").toString());
|
||||
CGAL::Three::Three::s_defaultPSRM = CGAL::Three::Three::modeFromName(
|
||||
|
|
@ -3173,9 +3182,9 @@ void SubViewer::lookat()
|
|||
if (viewer->camera()->frame()->isSpinning())
|
||||
viewer->camera()->frame()->stopSpinning();
|
||||
mw->viewerShow(viewer,
|
||||
(float)dialog.get_x(),
|
||||
(float)dialog.get_y(),
|
||||
(float)dialog.get_z());
|
||||
(float)dialog.get_x() + viewer->offset().x,
|
||||
(float)dialog.get_y() + viewer->offset().y,
|
||||
(float)dialog.get_z() + viewer->offset().z);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -27,7 +27,7 @@
|
|||
|
||||
#include <CGAL/bounding_box.h>
|
||||
|
||||
#include <QTime>
|
||||
#include <QElapsedTimer>
|
||||
|
||||
#include <QAction>
|
||||
#include <QMainWindow>
|
||||
|
|
@ -1241,7 +1241,7 @@ void Polyhedron_demo_cut_plugin::computeIntersection()
|
|||
Simple_kernel::Plane_3 plane(n[0], n[1], n[2], - n * pos);
|
||||
//std::cerr << plane << std::endl;
|
||||
edges_item->edges.clear();
|
||||
QTime time;
|
||||
QElapsedTimer time;
|
||||
time.start();
|
||||
bool does_intersect = false;
|
||||
for(Facet_sm_trees::iterator it = facet_sm_trees.begin(); it != facet_sm_trees.end(); ++it)
|
||||
|
|
|
|||
|
|
@ -8,7 +8,7 @@
|
|||
#include <QMenu>
|
||||
#include <QMainWindow>
|
||||
#include <QApplication>
|
||||
#include <QTime>
|
||||
#include <QElapsedTimer>
|
||||
#include <QMessageBox>
|
||||
using namespace CGAL::Three;
|
||||
class Polyhedron_demo_nef_plugin :
|
||||
|
|
@ -115,7 +115,7 @@ Polyhedron_demo_nef_plugin::on_actionToNef_triggered()
|
|||
}
|
||||
|
||||
QApplication::setOverrideCursor(Qt::WaitCursor);
|
||||
QTime time;
|
||||
QElapsedTimer time;
|
||||
time.start();
|
||||
std::cerr << "Convert facegraph to nef polyhedron...";
|
||||
|
||||
|
|
@ -146,7 +146,7 @@ Polyhedron_demo_nef_plugin::on_actionConvexDecomposition_triggered()
|
|||
: qobject_cast<Scene_nef_polyhedron_item*>(scene->item(index));
|
||||
QApplication::restoreOverrideCursor();
|
||||
if(item) {
|
||||
QTime time;
|
||||
QElapsedTimer time;
|
||||
time.start();
|
||||
std::cerr << "Convex decomposition...";
|
||||
|
||||
|
|
@ -188,7 +188,7 @@ Polyhedron_demo_nef_plugin::on_actionToPoly_triggered()
|
|||
if(item)
|
||||
{
|
||||
QApplication::setOverrideCursor(Qt::WaitCursor);
|
||||
QTime time;
|
||||
QElapsedTimer time;
|
||||
time.start();
|
||||
std::cerr << "Convert nef polyhedron to facegraph...";
|
||||
|
||||
|
|
@ -277,7 +277,7 @@ void Polyhedron_demo_nef_plugin::boolean_operation(const Boolean_operation opera
|
|||
|
||||
// perform Boolean operation
|
||||
std::cout << "Boolean operation...";
|
||||
QTime time;
|
||||
QElapsedTimer time;
|
||||
time.start();
|
||||
switch(operation)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
#include <QTime>
|
||||
#include <QElapsedTimer>
|
||||
#include <QApplication>
|
||||
#include <QAction>
|
||||
#include <QMainWindow>
|
||||
|
|
@ -74,7 +74,7 @@ void Polyhedron_demo_convex_hull_plugin::on_actionConvexHull_triggered()
|
|||
// wait cursor
|
||||
QApplication::setOverrideCursor(Qt::WaitCursor);
|
||||
|
||||
QTime time;
|
||||
QElapsedTimer time;
|
||||
time.start();
|
||||
std::cout << "Convex hull...";
|
||||
|
||||
|
|
|
|||
|
|
@ -80,6 +80,7 @@ endif()
|
|||
|
||||
find_path(3MF_INCLUDE_DIR
|
||||
NAMES Model/COM/NMR_DLLInterfaces.h
|
||||
PATH_SUFFIXES lib3mf
|
||||
DOC "Path to lib3MF headers"
|
||||
)
|
||||
find_library(3MF_LIBRARIES NAMES 3MF DOC "Path to the lib3MF library")
|
||||
|
|
|
|||
|
|
@ -35,7 +35,7 @@
|
|||
|
||||
#include <CGAL/boost/graph/Euler_operations.h>
|
||||
|
||||
#include <QTime>
|
||||
#include <QElapsedTimer>
|
||||
#include <QAction>
|
||||
#include <QMainWindow>
|
||||
#include <QApplication>
|
||||
|
|
@ -264,14 +264,14 @@ private:
|
|||
typedef CGAL::Delaunay_mesh_size_criteria_2<CDT> Criteria;
|
||||
typedef CGAL::Delaunay_mesher_2<CDT, Criteria> Mesher;
|
||||
|
||||
QTime time; // global timer
|
||||
QElapsedTimer time; // global timer
|
||||
time.start();
|
||||
|
||||
std::cout << " Building Constrained_Delaunay_triangulation_2..."
|
||||
<< std::flush;
|
||||
CDT cdt;
|
||||
|
||||
QTime ltime; //local timer
|
||||
QElapsedTimer ltime; //local timer
|
||||
ltime.start();
|
||||
double constant_coordinate =
|
||||
polylines_items.back()->polylines.back().back()[constant_coordinate_index];
|
||||
|
|
|
|||
|
|
@ -708,9 +708,9 @@ private:
|
|||
Volume_plane<y_tag> *y_item = new Volume_plane<y_tag>(img->image()->tx,img->image()->ty, img->image()->tz);
|
||||
Volume_plane<z_tag> *z_item = new Volume_plane<z_tag>(img->image()->tx,img->image()->ty, img->image()->tz);
|
||||
|
||||
x_item->setProperty("img",qVariantFromValue((void*)seg_img));
|
||||
y_item->setProperty("img",qVariantFromValue((void*)seg_img));
|
||||
z_item->setProperty("img",qVariantFromValue((void*)seg_img));
|
||||
x_item->setProperty("img",QVariant::fromValue((void*)seg_img));
|
||||
y_item->setProperty("img",QVariant::fromValue((void*)seg_img));
|
||||
z_item->setProperty("img",QVariant::fromValue((void*)seg_img));
|
||||
|
||||
x_item->setColor(QColor("red"));
|
||||
y_item->setColor(QColor("green"));
|
||||
|
|
|
|||
|
|
@ -16,7 +16,7 @@
|
|||
|
||||
#include "config.h"
|
||||
|
||||
#include <QTime>
|
||||
#include <QElapsedTimer>
|
||||
#include <QApplication>
|
||||
|
||||
#include "Meshing_thread.h"
|
||||
|
|
@ -52,7 +52,7 @@ void
|
|||
Meshing_thread::
|
||||
run()
|
||||
{
|
||||
QTime timer;
|
||||
QElapsedTimer timer;
|
||||
timer.start();
|
||||
CGAL::Three::Three::CursorScopeGuard guard(Qt::BusyCursor);
|
||||
f_->launch();
|
||||
|
|
|
|||
|
|
@ -16,7 +16,7 @@
|
|||
|
||||
#include "config_mesh_3.h"
|
||||
|
||||
#include <QTime>
|
||||
#include <QElapsedTimer>
|
||||
#include <QTimer>
|
||||
#include "Optimizer_thread.h"
|
||||
#include "Scene_c3t3_item.h"
|
||||
|
|
@ -47,7 +47,7 @@ void
|
|||
Optimizer_thread::
|
||||
run()
|
||||
{
|
||||
QTime timer;
|
||||
QElapsedTimer timer;
|
||||
timer.start();
|
||||
//SEGFAULT
|
||||
rc_ = f_->launch();
|
||||
|
|
|
|||
|
|
@ -91,7 +91,8 @@ public :
|
|||
//get the references
|
||||
this->scene = scene_interface;
|
||||
this->messages = mi;
|
||||
plane = NULL;
|
||||
plane = nullptr;
|
||||
clipper_item = nullptr;
|
||||
//creates and link the actions
|
||||
actionClipPolyhedra = new QAction("Clip Polyhedra With Plane", mw);
|
||||
actionClipPolyhedra->setProperty("subMenuName","Polygon Mesh Processing/Corefinement");
|
||||
|
|
|
|||
|
|
@ -14,7 +14,7 @@
|
|||
#include <QMenu>
|
||||
#include <QMainWindow>
|
||||
#include <QApplication>
|
||||
#include <QTime>
|
||||
#include <QElapsedTimer>
|
||||
#include <QMessageBox>
|
||||
|
||||
typedef Scene_surface_mesh_item Scene_facegraph_item;
|
||||
|
|
|
|||
|
|
@ -21,7 +21,7 @@
|
|||
#include <QDockWidget>
|
||||
#include <QDialog>
|
||||
#include <QApplication>
|
||||
#include <QTime>
|
||||
#include <QElapsedTimer>
|
||||
#include <QMessageBox>
|
||||
|
||||
#include "ui_Transformation_widget.h"
|
||||
|
|
|
|||
|
|
@ -14,7 +14,7 @@ typedef Scene_surface_mesh_item Scene_facegraph_item;
|
|||
#include <CGAL/Polygon_mesh_processing/fair.h>
|
||||
#include <CGAL/Polygon_mesh_processing/refine.h>
|
||||
|
||||
#include <QTime>
|
||||
#include <QElapsedTimer>
|
||||
#include <QAction>
|
||||
#include <QMainWindow>
|
||||
#include <QApplication>
|
||||
|
|
|
|||
|
|
@ -18,7 +18,7 @@
|
|||
#include <CGAL/Timer.h>
|
||||
#include <CGAL/iterator.h>
|
||||
|
||||
#include <QTime>
|
||||
#include <QElapsedTimer>
|
||||
#include <QAction>
|
||||
#include <QMainWindow>
|
||||
#include <QApplication>
|
||||
|
|
|
|||
|
|
@ -23,7 +23,7 @@
|
|||
#include <boost/unordered_set.hpp>
|
||||
#include <CGAL/property_map.h>
|
||||
|
||||
#include <QTime>
|
||||
#include <QElapsedTimer>
|
||||
#include <QAction>
|
||||
#include <QMainWindow>
|
||||
#include <QApplication>
|
||||
|
|
@ -341,7 +341,7 @@ public Q_SLOTS:
|
|||
// wait cursor
|
||||
QApplication::setOverrideCursor(Qt::WaitCursor);
|
||||
|
||||
QTime time;
|
||||
QElapsedTimer time;
|
||||
time.start();
|
||||
|
||||
typedef boost::graph_traits<FaceGraph>::edge_descriptor edge_descriptor;
|
||||
|
|
@ -699,7 +699,7 @@ public Q_SLOTS:
|
|||
detect_and_split_duplicates(selection, edges_to_protect, target_length);
|
||||
|
||||
#ifdef CGAL_LINKED_WITH_TBB
|
||||
QTime time;
|
||||
QElapsedTimer time;
|
||||
time.start();
|
||||
|
||||
tbb::parallel_for(
|
||||
|
|
@ -715,7 +715,7 @@ public Q_SLOTS:
|
|||
target_length, nb_iter, protect, smooth_features);
|
||||
for(Scene_facegraph_item* poly_item : selection)
|
||||
{
|
||||
QTime time;
|
||||
QElapsedTimer time;
|
||||
time.start();
|
||||
|
||||
remesher(poly_item, edges_to_protect[poly_item->polyhedron()]);
|
||||
|
|
|
|||
|
|
@ -14,7 +14,7 @@
|
|||
#include <QApplication>
|
||||
#include <QMainWindow>
|
||||
#include <QInputDialog>
|
||||
#include <QTime>
|
||||
#include <QElapsedTimer>
|
||||
#include <QMessageBox>
|
||||
|
||||
#include <Eigen/Sparse>
|
||||
|
|
@ -360,7 +360,7 @@ void Polyhedron_demo_mean_curvature_flow_skeleton_plugin::on_actionSegment()
|
|||
if (num_vertices(item->skeleton_curve)==0 ) { QApplication::restoreOverrideCursor(); return;}
|
||||
QApplication::setOverrideCursor(Qt::WaitCursor);
|
||||
|
||||
QTime time;
|
||||
QElapsedTimer time;
|
||||
time.start();
|
||||
|
||||
// init the polyhedron simplex indices
|
||||
|
|
@ -453,7 +453,7 @@ void Polyhedron_demo_mean_curvature_flow_skeleton_plugin::on_actionConvert_to_me
|
|||
|
||||
if ( !is_mesh_valid(pMesh) ) return;
|
||||
|
||||
QTime time;
|
||||
QElapsedTimer time;
|
||||
time.start();
|
||||
QApplication::setOverrideCursor(Qt::WaitCursor);
|
||||
|
||||
|
|
@ -491,7 +491,7 @@ void Polyhedron_demo_mean_curvature_flow_skeleton_plugin::on_actionContract()
|
|||
return;
|
||||
}
|
||||
|
||||
QTime time;
|
||||
QElapsedTimer time;
|
||||
time.start();
|
||||
std::cout << "Contract...\n";
|
||||
QApplication::setOverrideCursor(Qt::WaitCursor);
|
||||
|
|
@ -516,7 +516,7 @@ void Polyhedron_demo_mean_curvature_flow_skeleton_plugin::on_actionCollapse()
|
|||
return;
|
||||
}
|
||||
|
||||
QTime time;
|
||||
QElapsedTimer time;
|
||||
time.start();
|
||||
std::cout << "Collapse...\n";
|
||||
QApplication::setOverrideCursor(Qt::WaitCursor);
|
||||
|
|
@ -542,7 +542,7 @@ void Polyhedron_demo_mean_curvature_flow_skeleton_plugin::on_actionSplit()
|
|||
return;
|
||||
}
|
||||
|
||||
QTime time;
|
||||
QElapsedTimer time;
|
||||
time.start();
|
||||
std::cout << "Split...\n";
|
||||
QApplication::setOverrideCursor(Qt::WaitCursor);
|
||||
|
|
@ -567,7 +567,7 @@ void Polyhedron_demo_mean_curvature_flow_skeleton_plugin::on_actionDegeneracy()
|
|||
return;
|
||||
}
|
||||
|
||||
QTime time;
|
||||
QElapsedTimer time;
|
||||
time.start();
|
||||
std::cout << "Detect degeneracy...\n";
|
||||
QApplication::setOverrideCursor(Qt::WaitCursor);
|
||||
|
|
@ -618,7 +618,7 @@ void Polyhedron_demo_mean_curvature_flow_skeleton_plugin::on_actionRun()
|
|||
return;
|
||||
}
|
||||
|
||||
QTime time;
|
||||
QElapsedTimer time;
|
||||
time.start();
|
||||
QApplication::setOverrideCursor(Qt::WaitCursor);
|
||||
|
||||
|
|
@ -741,7 +741,7 @@ void Polyhedron_demo_mean_curvature_flow_skeleton_plugin::on_actionSkeletonize()
|
|||
return;
|
||||
}
|
||||
|
||||
QTime time;
|
||||
QElapsedTimer time;
|
||||
time.start();
|
||||
QApplication::setOverrideCursor(Qt::WaitCursor);
|
||||
|
||||
|
|
@ -802,7 +802,7 @@ void Polyhedron_demo_mean_curvature_flow_skeleton_plugin::on_actionConverge()
|
|||
return;
|
||||
}
|
||||
|
||||
QTime time;
|
||||
QElapsedTimer time;
|
||||
time.start();
|
||||
QApplication::setOverrideCursor(Qt::WaitCursor);
|
||||
|
||||
|
|
|
|||
|
|
@ -16,7 +16,7 @@
|
|||
#include <CGAL/bounding_box.h>
|
||||
#include <CGAL/Polygon_mesh_slicer.h>
|
||||
|
||||
#include <QTime>
|
||||
#include <QElapsedTimer>
|
||||
#include <QAction>
|
||||
#include <QMainWindow>
|
||||
#include <QApplication>
|
||||
|
|
@ -287,7 +287,7 @@ void Polyhedron_demo_polyhedron_slicer_plugin::on_Generate_button_clicked()
|
|||
if(!new_polyline_item_for_polylines)
|
||||
{
|
||||
Scene_polylines_item* new_polylines_item = new Scene_polylines_item();
|
||||
QTime time; time.start();
|
||||
QElapsedTimer time; time.start();
|
||||
// call algorithm and fill polylines in polylines_item
|
||||
intersection_of_plane_Polyhedra_3_using_AABB_wrapper(*smesh, planes, plane_positions, new_polylines_item->polylines);
|
||||
// set names etc and print timing
|
||||
|
|
@ -301,7 +301,7 @@ void Polyhedron_demo_polyhedron_slicer_plugin::on_Generate_button_clicked()
|
|||
scene->addItem(new_polylines_item);
|
||||
}
|
||||
else {
|
||||
QTime time; time.start();
|
||||
QElapsedTimer time; time.start();
|
||||
std::list<std::vector<Epic_kernel::Point_3> > polylines;
|
||||
// call algorithm and fill polylines in polylines_item
|
||||
intersection_of_plane_Polyhedra_3_using_AABB_wrapper(*smesh, planes, plane_positions, polylines);
|
||||
|
|
|
|||
|
|
@ -16,7 +16,7 @@
|
|||
#include <boost/graph/graph_traits.hpp>
|
||||
#include <CGAL/property_map.h>
|
||||
|
||||
#include <QTime>
|
||||
#include <QElapsedTimer>
|
||||
#include <QAction>
|
||||
#include <QMainWindow>
|
||||
#include <QApplication>
|
||||
|
|
@ -94,7 +94,7 @@ public Q_SLOTS:
|
|||
|
||||
// wait cursor
|
||||
QApplication::setOverrideCursor(Qt::WaitCursor);
|
||||
QTime time;
|
||||
QElapsedTimer time;
|
||||
time.start();
|
||||
|
||||
std::cout << "Perturbation..." << std::endl;
|
||||
|
|
|
|||
|
|
@ -17,7 +17,7 @@
|
|||
|
||||
#include "ui_Smoothing_plugin.h"
|
||||
|
||||
#include <QTime>
|
||||
#include <QElapsedTimer>
|
||||
#include <QAction>
|
||||
#include <QMainWindow>
|
||||
#include <QApplication>
|
||||
|
|
|
|||
|
|
@ -15,7 +15,7 @@
|
|||
#include <QMenu>
|
||||
#include <QMainWindow>
|
||||
#include <QApplication>
|
||||
#include <QTime>
|
||||
#include <QElapsedTimer>
|
||||
#include <QMessageBox>
|
||||
|
||||
typedef Scene_surface_mesh_item Scene_face_graph_item;
|
||||
|
|
@ -130,7 +130,7 @@ void Polyhedron_demo_intersection_plugin::intersectionSurfaces()
|
|||
|
||||
Scene_polylines_item* new_item = new Scene_polylines_item();
|
||||
// perform Boolean operation
|
||||
QTime time;
|
||||
QElapsedTimer time;
|
||||
time.start();
|
||||
|
||||
try{
|
||||
|
|
@ -193,7 +193,7 @@ void Polyhedron_demo_intersection_plugin::intersectionPolylines()
|
|||
Scene_points_with_normal_item* new_point_item = new Scene_points_with_normal_item();
|
||||
Scene_polylines_item* new_pol_item = new Scene_polylines_item();
|
||||
// perform Boolean operation
|
||||
QTime time;
|
||||
QElapsedTimer time;
|
||||
time.start();
|
||||
std::vector<Polyline_3> polyA, polyB;
|
||||
Q_FOREACH(const Polyline_3& poly, itemA->polylines)
|
||||
|
|
@ -289,7 +289,7 @@ void Polyhedron_demo_intersection_plugin::intersectionSurfacePolyline()
|
|||
Scene_points_with_normal_item* new_point_item = new Scene_points_with_normal_item();
|
||||
Scene_polylines_item* new_pol_item = new Scene_polylines_item();
|
||||
// perform Boolean operation
|
||||
QTime time;
|
||||
QElapsedTimer time;
|
||||
time.start();
|
||||
Scene_face_graph_item::Face_graph tm = *itemA->face_graph();
|
||||
std::vector<face_descriptor> Afaces;
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
#include <QTime>
|
||||
#include <QElapsedTimer>
|
||||
#include <QApplication>
|
||||
#include <QAction>
|
||||
#include <QList>
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
#include <QTime>
|
||||
#include <QElapsedTimer>
|
||||
#include <QApplication>
|
||||
#include <QMainWindow>
|
||||
#include <QAction>
|
||||
|
|
@ -81,7 +81,7 @@ template<class FaceGraphItem>
|
|||
void Polyhedron_demo_subdivision_methods_plugin::apply_loop(FaceGraphItem* item, int nb_steps)
|
||||
{
|
||||
typename FaceGraphItem::Face_graph* graph = item->face_graph();
|
||||
QTime time;
|
||||
QElapsedTimer time;
|
||||
time.start();
|
||||
CGAL::Three::Three::information("Loop subdivision...");
|
||||
QApplication::setOverrideCursor(Qt::WaitCursor);
|
||||
|
|
@ -113,7 +113,7 @@ void Polyhedron_demo_subdivision_methods_plugin::apply_catmullclark(FaceGraphIte
|
|||
{
|
||||
typename FaceGraphItem::Face_graph* graph = item->face_graph();
|
||||
if(!graph) return;
|
||||
QTime time;
|
||||
QElapsedTimer time;
|
||||
time.start();
|
||||
CGAL::Three::Three::information("Catmull-Clark subdivision...");
|
||||
QApplication::setOverrideCursor(Qt::WaitCursor);
|
||||
|
|
@ -143,7 +143,7 @@ void Polyhedron_demo_subdivision_methods_plugin::apply_sqrt3(FaceGraphItem* item
|
|||
{
|
||||
typename FaceGraphItem::Face_graph* graph = item->face_graph();
|
||||
if(!graph) return;
|
||||
QTime time;
|
||||
QElapsedTimer time;
|
||||
time.start();
|
||||
CGAL::Three::Three::information("Sqrt-3 subdivision...");
|
||||
QApplication::setOverrideCursor(Qt::WaitCursor);
|
||||
|
|
@ -175,7 +175,7 @@ void Polyhedron_demo_subdivision_methods_plugin::apply_doosabin(FaceGraphItem* i
|
|||
{
|
||||
typename FaceGraphItem::Face_graph* graph = item->face_graph();
|
||||
if(!graph) return;
|
||||
QTime time;
|
||||
QElapsedTimer time;
|
||||
time.start();
|
||||
CGAL::Three::Three::information("Doo-Sabin subdivision...");
|
||||
QApplication::setOverrideCursor(Qt::WaitCursor);
|
||||
|
|
|
|||
|
|
@ -9,7 +9,7 @@
|
|||
#include <QApplication>
|
||||
#include <QMainWindow>
|
||||
#include <QInputDialog>
|
||||
#include <QTime>
|
||||
#include <QElapsedTimer>
|
||||
#include <QAction>
|
||||
#include <QDebug>
|
||||
#include <QObject>
|
||||
|
|
@ -196,7 +196,7 @@ void Polyhedron_demo_mesh_plane_detection_plugin::on_actionPlaneDetection_trigge
|
|||
if(dialog.exec() == QDialog::Rejected)
|
||||
return;
|
||||
|
||||
QTime time;
|
||||
QElapsedTimer time;
|
||||
time.start();
|
||||
std::cerr << "Detecting planes... ";
|
||||
QApplication::setOverrideCursor(Qt::WaitCursor);
|
||||
|
|
|
|||
|
|
@ -10,7 +10,7 @@
|
|||
#include <QApplication>
|
||||
#include <QMainWindow>
|
||||
#include <QInputDialog>
|
||||
#include <QTime>
|
||||
#include <QElapsedTimer>
|
||||
#include <QAction>
|
||||
#include <QDebug>
|
||||
#include <QObject>
|
||||
|
|
@ -211,7 +211,7 @@ void Polyhedron_demo_mesh_segmentation_plugin::apply_SDF_button_clicked(Facegrap
|
|||
typename boost::property_map<Facegraph, CGAL::face_index_t>::type fidmap =
|
||||
get(CGAL::face_index, *pair->first->face_graph());
|
||||
FaceGraph_with_id_to_vector_property_map<Facegraph, double> sdf_pmap(&pair->second, fidmap);
|
||||
QTime time;
|
||||
QElapsedTimer time;
|
||||
time.start();
|
||||
std::pair<double, double> min_max_sdf = sdf_values(*(pair->first->face_graph()), sdf_pmap, cone_angle, number_of_rays);
|
||||
std::cout << "ok (" << time.elapsed() << " ms)" << std::endl;
|
||||
|
|
@ -284,7 +284,7 @@ void Polyhedron_demo_mesh_segmentation_plugin::apply_Partition_button_clicked(Fa
|
|||
QApplication::setOverrideCursor(Qt::WaitCursor);
|
||||
}
|
||||
check_and_set_ids(pair->first->face_graph());
|
||||
QTime time;
|
||||
QElapsedTimer time;
|
||||
time.start();
|
||||
typename boost::property_map<Facegraph, CGAL::face_index_t>::type fidmap =
|
||||
get(CGAL::face_index, *pair->first->face_graph());
|
||||
|
|
|
|||
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue