934 lines
30 KiB
C++
934 lines
30 KiB
C++
// Copyright (c) 2019 CNRS and LIRIS' Establishments (France).
|
|
// All rights reserved.
|
|
//
|
|
// This file is part of CGAL (www.cgal.org)
|
|
//
|
|
// $URL: https://github.com/CGAL/cgal/blob/v5.1/Surface_mesh_topology/include/CGAL/Face_graph_wrapper.h $
|
|
// $Id: Face_graph_wrapper.h 52186a0 2020-05-14T11:38:15+02:00 Guillaume Damiand
|
|
// SPDX-License-Identifier: GPL-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/license/Surface_mesh_topology.h>
|
|
|
|
#include <CGAL/Surface_mesh_topology/internal/Functors_for_face_graph_wrapper.h>
|
|
#include <CGAL/Surface_mesh_topology/internal/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 <CGAL/Combinatorial_map_fwd.h>
|
|
#include <CGAL/Generalized_map_fwd.h>
|
|
#include <CGAL/Linear_cell_complex_fwd.h>
|
|
#include <CGAL/Polygonal_schema_fwd.h>
|
|
#include <bitset>
|
|
|
|
namespace CGAL
|
|
{
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
/** 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 boost::uint32_t /*std::size_t*/ size_type;
|
|
typedef Self Refs;
|
|
|
|
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),
|
|
m_marks_initialized(false),
|
|
mnb_used_marks(0)
|
|
|
|
{
|
|
// Store locally the number of darts: the HEG must not be modified
|
|
m_nb_darts=darts().size();
|
|
}
|
|
|
|
void initialize_marks() const
|
|
{
|
|
if (m_marks_initialized) return;
|
|
|
|
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;
|
|
}
|
|
|
|
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>()); }
|
|
|
|
m_marks_initialized=true;
|
|
}
|
|
|
|
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 internal::Get_beta<HEG, 1>::value(m_fg, ADart);
|
|
if (B1==2) return internal::Get_beta<HEG, 2>::value(m_fg, ADart);
|
|
return internal::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 internal::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 (m_marks_initialized && 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
|
|
{
|
|
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
|
|
{
|
|
initialize_marks();
|
|
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( is_reserved(amark) );
|
|
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
|
|
{
|
|
CGAL_assertion(is_reserved(amark));
|
|
return get(m_all_marks, ADart)[amark];
|
|
}
|
|
void set_dart_mark(Dart_const_handle ADart, size_type amark, bool avalue) const
|
|
{
|
|
CGAL_assertion(is_reserved(amark));
|
|
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::internal::FGW_cell_iterator<Self, i> iterator;
|
|
typedef CGAL::internal::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::internal::FGW_dart_iterator_basic_of_all<Self> iterator;
|
|
typedef CGAL::internal::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=static_cast<size_type>(halfedges(mmap.get_fg()).size()); }
|
|
return msize;
|
|
}
|
|
bool empty() const
|
|
{ return mmap.is_empty(); }
|
|
|
|
size_type capacity() const
|
|
{ return static_cast<size_type>(num_halfedges(mmap.get_fg())); }
|
|
|
|
bool is_used(size_type i) const
|
|
{ return internal::Is_index_used<HEG>::run(mmap.get_fg(), i); }
|
|
|
|
size_type index(const_iterator it) const
|
|
{
|
|
return internal::Index_from_halfedge_descriptor<HEG>::
|
|
run(mmap.get_fg(), *it);
|
|
}
|
|
|
|
size_type index(Dart_const_handle it) const
|
|
{
|
|
return internal::Index_from_halfedge_descriptor<HEG>::
|
|
run(mmap.get_fg(), it);
|
|
}
|
|
|
|
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));
|
|
return internal::Halfedge_descriptor_from_index<HEG>::run(get_fg(), i);
|
|
}
|
|
Dart_const_handle dart_handle(size_type i) const
|
|
{
|
|
CGAL_assertion(darts().is_used(i));
|
|
return internal::Halfedge_descriptor_from_index<HEG>::run(get_fg(), i);
|
|
}
|
|
|
|
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;
|
|
}
|
|
|
|
template <unsigned int i>
|
|
size_type mark_oriented_cell(Dart_const_handle adart, size_type amark,
|
|
size_type amark2=INVALID_MARK) 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;
|
|
if (amark2!=INVALID_MARK) { mark(*it, amark2); }
|
|
}
|
|
return res;
|
|
}
|
|
|
|
template <unsigned int i>
|
|
size_type unmark_oriented_cell(Dart_const_handle adart, size_type amark,
|
|
size_type amark2=INVALID_MARK) 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;
|
|
if (amark2!=INVALID_MARK) { unmark(*it, amark2); }
|
|
}
|
|
return res;
|
|
}
|
|
|
|
std::size_t orient(size_type amark) const
|
|
{ negate_mark(amark); return number_of_darts(); }
|
|
|
|
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;
|
|
size_type m_nb_darts;
|
|
mutable bool m_marks_initialized; /// True iff marks are initialized (we use lazy initialization)
|
|
|
|
/// 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 //
|