mirror of https://github.com/CGAL/cgal
Merge pull request #179 from afabri/CGAL-add_hash-GF
Add boost::hash and std::hash https://cgal.geometryfactory.com/CGAL/Members/wiki/Features/Small_Features/hash Conflicts: Installation/changes.html
This commit is contained in:
commit
08666dce25
|
|
@ -370,6 +370,10 @@ counterparts. `Vertex_iterator`, `Halfedge_iterator`, and
|
|||
the handles appear in function parameter lists, the respective
|
||||
iterators can be passed as well.
|
||||
|
||||
All handles are model of `LessThanComparable` and `Hashable`,
|
||||
that is they can be used as keys in containers such as `std::map`
|
||||
and `boost::unordered_map`.
|
||||
|
||||
*/
|
||||
/// @{
|
||||
|
||||
|
|
|
|||
|
|
@ -21,6 +21,8 @@
|
|||
#ifndef CGAL_ARRANGEMENT_2_ITERATORS_H
|
||||
#define CGAL_ARRANGEMENT_2_ITERATORS_H
|
||||
|
||||
#include <functional>
|
||||
|
||||
/*! \file
|
||||
* Definitions of auxiliary iterator adaptors.
|
||||
*/
|
||||
|
|
@ -340,6 +342,11 @@ public:
|
|||
return !(*this == it);
|
||||
}
|
||||
|
||||
bool operator< (const Self& it) const
|
||||
{
|
||||
return &(**this) < (&*it);
|
||||
}
|
||||
|
||||
/*! Dereferencing operators. */
|
||||
reference operator*() const
|
||||
{
|
||||
|
|
@ -495,6 +502,11 @@ public:
|
|||
return !(*this == it);
|
||||
}
|
||||
|
||||
bool operator< (const Self& it) const
|
||||
{
|
||||
return &(**this) < (&*it);
|
||||
}
|
||||
|
||||
/*! Dereferencing operators. */
|
||||
reference operator*() const
|
||||
{
|
||||
|
|
@ -545,4 +557,104 @@ public:
|
|||
|
||||
} //namespace CGAL
|
||||
|
||||
namespace std {
|
||||
|
||||
#if defined(BOOST_MSVC)
|
||||
# pragma warning(push)
|
||||
# pragma warning(disable:4099) // For VC10 it is class hash
|
||||
#endif
|
||||
|
||||
template < class T>
|
||||
struct hash;
|
||||
|
||||
template <class CIterator_, class Filter_, class MIterator_,
|
||||
class Value_, class Diff_, class Category_>
|
||||
struct hash<CGAL::I_Filtered_const_iterator<CIterator_,
|
||||
Filter_,
|
||||
MIterator_,
|
||||
Value_,
|
||||
Diff_,
|
||||
Category_> > {
|
||||
|
||||
typedef CGAL::I_Filtered_const_iterator<CIterator_,
|
||||
Filter_,
|
||||
MIterator_,
|
||||
Value_,
|
||||
Diff_,
|
||||
Category_> I;
|
||||
|
||||
std::size_t operator()(const I& i) const
|
||||
{
|
||||
return reinterpret_cast<std::size_t>(&*i) / sizeof(Value_);
|
||||
}
|
||||
};
|
||||
|
||||
template <class Iterator_, class Filter_,
|
||||
class Value_, class Diff_, class Category_>
|
||||
struct hash<CGAL::I_Filtered_iterator<Iterator_,
|
||||
Filter_,
|
||||
Value_,
|
||||
Diff_,
|
||||
Category_> > {
|
||||
typedef CGAL::I_Filtered_iterator<Iterator_,
|
||||
Filter_,
|
||||
Value_,
|
||||
Diff_,
|
||||
Category_> I;
|
||||
|
||||
std::size_t operator()(const I& i) const
|
||||
{
|
||||
return reinterpret_cast<std::size_t>(&*i) / sizeof(typename I::value_type);
|
||||
}
|
||||
};
|
||||
}
|
||||
namespace boost {
|
||||
template <typename T> struct hash;
|
||||
|
||||
template <class CIterator_, class Filter_, class MIterator_,
|
||||
class Value_, class Diff_, class Category_>
|
||||
struct hash<CGAL::I_Filtered_const_iterator<CIterator_,
|
||||
Filter_,
|
||||
MIterator_,
|
||||
Value_,
|
||||
Diff_,
|
||||
Category_> > {
|
||||
|
||||
typedef CGAL::I_Filtered_const_iterator<CIterator_,
|
||||
Filter_,
|
||||
MIterator_,
|
||||
Value_,
|
||||
Diff_,
|
||||
Category_> I;
|
||||
|
||||
std::size_t operator()(const I& i) const
|
||||
{
|
||||
return reinterpret_cast<std::size_t>(&*i) / sizeof(Value_);
|
||||
}
|
||||
};
|
||||
|
||||
template <class Iterator_, class Filter_,
|
||||
class Value_, class Diff_, class Category_>
|
||||
struct hash<CGAL::I_Filtered_iterator<Iterator_,
|
||||
Filter_,
|
||||
Value_,
|
||||
Diff_,
|
||||
Category_> > {
|
||||
typedef CGAL::I_Filtered_iterator<Iterator_,
|
||||
Filter_,
|
||||
Value_,
|
||||
Diff_,
|
||||
Category_> I;
|
||||
|
||||
std::size_t operator()(const I& i) const
|
||||
{
|
||||
return reinterpret_cast<std::size_t>(&*i) / sizeof(typename I::value_type);
|
||||
}
|
||||
};
|
||||
|
||||
#if defined(BOOST_MSVC)
|
||||
# pragma warning(pop)
|
||||
#endif
|
||||
|
||||
}
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -20,6 +20,8 @@
|
|||
#ifndef CGAL_BOOST_GRAPH_GRAPH_TRAITS_HALFEDGEDS_H
|
||||
#define CGAL_BOOST_GRAPH_GRAPH_TRAITS_HALFEDGEDS_H
|
||||
|
||||
#include <functional>
|
||||
|
||||
#include <boost/config.hpp>
|
||||
#include <boost/iterator/iterator_adaptor.hpp>
|
||||
#include <boost/iterator/transform_iterator.hpp>
|
||||
|
|
@ -30,7 +32,6 @@
|
|||
|
||||
#include <CGAL/basic.h>
|
||||
#include <CGAL/boost/graph/iterator.h>
|
||||
|
||||
#include <CGAL/Handle_hash_function.h>
|
||||
|
||||
#ifndef CGAL_NO_DEPRECATED_CODE
|
||||
|
|
@ -217,4 +218,31 @@ public:
|
|||
|
||||
} //namespace CGAL
|
||||
|
||||
|
||||
namespace std {
|
||||
|
||||
#if defined(BOOST_MSVC)
|
||||
# pragma warning(push)
|
||||
# pragma warning(disable:4099) // For VC10 it is class hash
|
||||
#endif
|
||||
|
||||
template < class T>
|
||||
struct hash;
|
||||
|
||||
template <typename H>
|
||||
struct hash<CGAL::internal::HDS_edge<H> > {
|
||||
std::size_t operator()(const CGAL::internal::HDS_edge<H>& e) const
|
||||
{
|
||||
std::cerr << "HDS_edge HashFct" << std::endl;
|
||||
std::hash<H> fct;
|
||||
return fct(e.halfedge());
|
||||
}
|
||||
};
|
||||
|
||||
#if defined(BOOST_MSVC)
|
||||
# pragma warning(pop)
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
#endif // CGAL_BOOST_GRAPH_GRAPH_TRAITS_HALFEDGEDS_H
|
||||
|
|
|
|||
|
|
@ -20,6 +20,8 @@
|
|||
#ifndef CGAL_GRAPH_TRAITS_TRIANGULATION_2_H
|
||||
#define CGAL_GRAPH_TRAITS_TRIANGULATION_2_H
|
||||
|
||||
#include <functional>
|
||||
|
||||
#include <boost/config.hpp>
|
||||
#include <boost/iterator_adaptors.hpp>
|
||||
#include <boost/graph/graph_traits.hpp>
|
||||
|
|
@ -40,8 +42,9 @@ namespace CGAL {
|
|||
|
||||
template < class T, class EdgeBase >
|
||||
class Edge : public EdgeBase {
|
||||
|
||||
public:
|
||||
typedef typename T::Face_handle Face_handle ;
|
||||
public:
|
||||
|
||||
Edge()
|
||||
{}
|
||||
|
|
@ -64,7 +67,12 @@ class Edge : public EdgeBase {
|
|||
this->first = e.first;
|
||||
this->second = e.second;
|
||||
return *this;
|
||||
}
|
||||
}
|
||||
|
||||
friend std::size_t hash_value(const Edge& e)
|
||||
{
|
||||
return hash_value(e.first);
|
||||
}
|
||||
|
||||
bool operator==(const Edge& other) const
|
||||
{
|
||||
|
|
@ -247,6 +255,49 @@ public:
|
|||
}
|
||||
};
|
||||
|
||||
|
||||
template <typename Tr>
|
||||
struct T2_halfedge_descriptor
|
||||
{
|
||||
typedef typename Tr::Face_handle face_descriptor;
|
||||
face_descriptor first;
|
||||
int second;
|
||||
operator std::pair<face_descriptor, int>() { return std::make_pair(first,second); }
|
||||
|
||||
T2_halfedge_descriptor()
|
||||
{}
|
||||
|
||||
T2_halfedge_descriptor(const typename Tr::Edge& e)
|
||||
: first(e.first), second(e.second)
|
||||
{}
|
||||
|
||||
T2_halfedge_descriptor(face_descriptor fd, int i)
|
||||
: first(fd), second(i)
|
||||
{}
|
||||
|
||||
friend std::size_t hash_value(const T2_halfedge_descriptor& h)
|
||||
{
|
||||
return hash_value(h.first);
|
||||
}
|
||||
|
||||
bool operator==(const T2_halfedge_descriptor& other) const
|
||||
{
|
||||
return (first == other.first) && (second == other.second);
|
||||
}
|
||||
|
||||
bool operator!=(const T2_halfedge_descriptor& other) const
|
||||
{
|
||||
return (first != other.first) || (second != other.second);
|
||||
}
|
||||
|
||||
bool operator<(const T2_halfedge_descriptor& other) const
|
||||
{
|
||||
if(first < other.first) return true;
|
||||
if(first > other.first) return false;
|
||||
return second < other.second;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
} // namespace detail
|
||||
} // namespace CGAL
|
||||
|
|
@ -270,41 +321,7 @@ namespace boost {
|
|||
typedef typename CGAL::Triangulation_2<GT,TDS>::All_edges_iterator edge_iterator;
|
||||
|
||||
|
||||
// with just a typedef to Edge VC++ has ambiguities for function `next()`
|
||||
struct halfedge_descriptor
|
||||
{
|
||||
face_descriptor first;
|
||||
int second;
|
||||
operator std::pair<face_descriptor, int>() { return std::make_pair(first,second); }
|
||||
|
||||
halfedge_descriptor()
|
||||
{}
|
||||
|
||||
halfedge_descriptor(const typename Triangulation::Edge& e)
|
||||
: first(e.first), second(e.second)
|
||||
{}
|
||||
|
||||
halfedge_descriptor(face_descriptor fd, int i)
|
||||
: first(fd), second(i)
|
||||
{}
|
||||
|
||||
bool operator==(const halfedge_descriptor& other) const
|
||||
{
|
||||
return (first == other.first) && (second == other.second);
|
||||
}
|
||||
|
||||
bool operator!=(const halfedge_descriptor& other) const
|
||||
{
|
||||
return (first != other.first) || (second != other.second);
|
||||
}
|
||||
|
||||
bool operator<(const halfedge_descriptor& other) const
|
||||
{
|
||||
if(first < other.first) return true;
|
||||
if(first > other.first) return false;
|
||||
return second < other.second;
|
||||
}
|
||||
};
|
||||
typedef CGAL::detail::T2_halfedge_descriptor<Triangulation> halfedge_descriptor;
|
||||
|
||||
typedef typename CGAL::Triangulation_2<GT,TDS>::All_halfedges_iterator halfedge_iterator;
|
||||
|
||||
|
|
@ -811,6 +828,42 @@ namespace boost {
|
|||
};
|
||||
} // namespace boost
|
||||
|
||||
|
||||
namespace std {
|
||||
|
||||
|
||||
#if defined(BOOST_MSVC)
|
||||
# pragma warning(push)
|
||||
# pragma warning(disable:4099) // For VC10 it is class hash
|
||||
#endif
|
||||
|
||||
template < class T>
|
||||
struct hash;
|
||||
|
||||
template < class T, class EdgeBase>
|
||||
struct hash<CGAL::detail::Edge<T,EdgeBase> > {
|
||||
std::size_t operator()(const CGAL::detail::Edge<T,EdgeBase>& e) const
|
||||
{
|
||||
std::cerr << "Triangulation_2::Edge HashFct" << std::endl;
|
||||
return hash_value(e);
|
||||
}
|
||||
};
|
||||
|
||||
template < class Tr>
|
||||
struct hash<CGAL::detail::T2_halfedge_descriptor<Tr> > {
|
||||
std::size_t operator()(const CGAL::detail::T2_halfedge_descriptor<Tr>& e) const
|
||||
{
|
||||
std::cerr << "Triangulation_2::halfedge_descriptor HashFct" << std::endl;
|
||||
return hash_value(e);
|
||||
}
|
||||
};
|
||||
|
||||
#if defined(BOOST_MSVC)
|
||||
# pragma warning(pop)
|
||||
#endif
|
||||
|
||||
} // namespace std
|
||||
|
||||
//#include <CGAL/graph_traits_Delaunay_triangulation_2.h>
|
||||
|
||||
#endif // CGAL_GRAPH_TRAITS_TRIANGULATION_2_H
|
||||
|
|
|
|||
|
|
@ -579,10 +579,15 @@ Section \ref ssecattributes "Cell Attributes").
|
|||
Users can customize a combinatorial map thanks to an items class (see
|
||||
Section \ref ssecitem "Combinatorial Map Items"), which defines the dart type and the
|
||||
attribute types. These types may be different for different
|
||||
dimensions, and they may also be void. The darts and attributes are
|
||||
dimensions, and they may also be void.
|
||||
|
||||
The darts and attributes are
|
||||
accessed through <I>handles</I>. A handle is a model of the
|
||||
`Handle` concept, thus supporting the two dereference operators
|
||||
`operator*` and `operator->`.
|
||||
All handles are model of `LessThanComparable` and `Hashable`,
|
||||
that is they can be used as keys in containers such as `std::map`
|
||||
and `boost::unordered_map`.
|
||||
|
||||
\cgalFigureBegin{figdiagram_class,Diagramme_class.png}
|
||||
UML diagram of the main classes of the package. k is the number of non void attributes.
|
||||
|
|
|
|||
|
|
@ -0,0 +1,67 @@
|
|||
# Created by the script cgal_create_CMakeLists
|
||||
# This is the CMake script for compiling a set of CGAL applications.
|
||||
|
||||
project( Hash_map )
|
||||
|
||||
|
||||
cmake_minimum_required(VERSION 2.6.2)
|
||||
if("${CMAKE_MAJOR_VERSION}.${CMAKE_MINOR_VERSION}" VERSION_GREATER 2.6)
|
||||
if("${CMAKE_MAJOR_VERSION}.${CMAKE_MINOR_VERSION}.${CMAKE_PATCH_VERSION}" VERSION_GREATER 2.8.3)
|
||||
cmake_policy(VERSION 2.8.4)
|
||||
else()
|
||||
cmake_policy(VERSION 2.6)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
set( CMAKE_ALLOW_LOOSE_LOOP_CONSTRUCTS true )
|
||||
|
||||
if ( COMMAND cmake_policy )
|
||||
|
||||
cmake_policy( SET CMP0003 NEW )
|
||||
|
||||
endif()
|
||||
|
||||
# CGAL and its components
|
||||
find_package( CGAL QUIET COMPONENTS )
|
||||
|
||||
if ( NOT CGAL_FOUND )
|
||||
|
||||
message(STATUS "This project requires the CGAL library, and will not be compiled.")
|
||||
return()
|
||||
|
||||
endif()
|
||||
|
||||
# include helper file
|
||||
include( ${CGAL_USE_FILE} )
|
||||
|
||||
|
||||
# Boost and its components
|
||||
find_package( Boost REQUIRED )
|
||||
|
||||
if ( NOT Boost_FOUND )
|
||||
|
||||
message(STATUS "This project requires the Boost library, and will not be compiled.")
|
||||
|
||||
return()
|
||||
|
||||
endif()
|
||||
|
||||
# include for local directory
|
||||
|
||||
# include for local package
|
||||
include_directories( BEFORE ../../include )
|
||||
|
||||
|
||||
# Creating entries for all .cpp/.C files with "main" routine
|
||||
# ##########################################################
|
||||
|
||||
include( CGAL_CreateSingleSourceCGALProgram )
|
||||
|
||||
create_single_source_cgal_program( "hm.cpp" )
|
||||
create_single_source_cgal_program( "foreach.cpp" )
|
||||
create_single_source_cgal_program( "triangulation.cpp" )
|
||||
create_single_source_cgal_program( "polyhedron.cpp" )
|
||||
create_single_source_cgal_program( "surface_mesh.cpp" )
|
||||
create_single_source_cgal_program( "arrangement.cpp" )
|
||||
|
||||
|
||||
|
|
@ -0,0 +1,40 @@
|
|||
#include <CGAL/Simple_cartesian.h>
|
||||
#include <CGAL/Arr_segment_traits_2.h>
|
||||
#include <CGAL/Arrangement_2.h>
|
||||
|
||||
#include <boost/unordered_map.hpp>
|
||||
#include <unordered_map>
|
||||
|
||||
|
||||
typedef int Number_type;
|
||||
typedef CGAL::Simple_cartesian<Number_type> Kernel;
|
||||
typedef CGAL::Arr_segment_traits_2<Kernel> Traits_2;
|
||||
typedef Traits_2::Point_2 Point_2;
|
||||
typedef Traits_2::X_monotone_curve_2 Segment_2;
|
||||
typedef CGAL::Arrangement_2<Traits_2> Arrangement_2;
|
||||
typedef Arrangement_2::Vertex_handle Vertex_handle;
|
||||
typedef Arrangement_2::Halfedge_handle Halfedge_handle;
|
||||
|
||||
int main()
|
||||
{
|
||||
Arrangement_2 arr;
|
||||
|
||||
Segment_2 s1(Point_2(1, 3), Point_2(3, 5));
|
||||
Segment_2 s2(Point_2(3, 5), Point_2(5, 3));
|
||||
Segment_2 s3(Point_2(5, 3), Point_2(3, 1));
|
||||
Segment_2 s4(Point_2(3, 1), Point_2(1, 3));
|
||||
Segment_2 s5(Point_2(1, 3), Point_2(5, 3));
|
||||
|
||||
Halfedge_handle e1 = arr.insert_in_face_interior(s1, arr.unbounded_face());
|
||||
Vertex_handle v1 = e1->source();
|
||||
|
||||
|
||||
|
||||
std::map<Vertex_handle,int> sm;
|
||||
sm[v1]= 1;
|
||||
std::unordered_map<Vertex_handle,int> sum;
|
||||
sum[v1]= 1;
|
||||
boost::unordered_map<Vertex_handle,int> bum;
|
||||
bum[v1]= 1;
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -0,0 +1,6 @@
|
|||
OFF
|
||||
3 1 0
|
||||
0 0 0
|
||||
1 0 0
|
||||
0 1 0
|
||||
3 0 1 2
|
||||
|
|
@ -0,0 +1,43 @@
|
|||
#include <iostream>
|
||||
#include <vector>
|
||||
|
||||
#include<boost/range/iterator_range.hpp>
|
||||
#include <boost/foreach.hpp>
|
||||
|
||||
#include <CGAL/Iterator_range.h>
|
||||
#include <CGAL/Timer.h>
|
||||
#include <CGAL/Simple_cartesian.h>
|
||||
|
||||
typedef CGAL::Timer Timer;
|
||||
|
||||
int main()
|
||||
{
|
||||
int N = 100000;
|
||||
std::vector<int> V(N), V2(N);
|
||||
|
||||
Timer t;
|
||||
|
||||
t.start();
|
||||
for(int k=0; k < N; k++){
|
||||
boost::iterator_range<std::vector<int>::iterator> bir(V.begin(), V.end());
|
||||
int j = 0;
|
||||
BOOST_FOREACH(int i, bir){
|
||||
V2[j++] = i;
|
||||
}
|
||||
}
|
||||
t.stop();
|
||||
std::cerr << "boost::iterator_range: " << t.time() << "sec.\n";
|
||||
|
||||
t.reset();
|
||||
t.start();
|
||||
for(int k=0; k < N; k++){
|
||||
int j = 0;
|
||||
BOOST_FOREACH(int i, CGAL::make_range(V.begin(), V.end())){
|
||||
V2[j++] = i;
|
||||
}
|
||||
}
|
||||
t.stop();
|
||||
std::cerr << "CGAL::iterator_range: " << t.time() << "sec.\n";
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -0,0 +1,271 @@
|
|||
#define NOHASH 1
|
||||
|
||||
#include <iostream>
|
||||
#include <fstream>
|
||||
#include <map>
|
||||
#include <algorithm>
|
||||
|
||||
#include <CGAL/Surface_mesh.h>
|
||||
#include <CGAL/Simple_cartesian.h>
|
||||
#include <CGAL/Polyhedron_3.h>
|
||||
#include <CGAL/IO/Polyhedron_iostream.h>
|
||||
|
||||
#include <CGAL/boost/graph/graph_traits_Surface_mesh.h>
|
||||
#include <CGAL/boost/graph/graph_traits_Polyhedron_3.h>
|
||||
#include <CGAL/boost/graph/properties_Polyhedron_3.h>
|
||||
#include <CGAL/boost/graph/helpers.h>
|
||||
#include <CGAL/Timer.h>
|
||||
#include<boost/range/iterator_range.hpp>
|
||||
#include <boost/unordered_map.hpp>
|
||||
#include <unordered_map>
|
||||
|
||||
#include <boost/random/random_number_generator.hpp>
|
||||
#include <boost/random/linear_congruential.hpp>
|
||||
|
||||
typedef CGAL::Simple_cartesian<double> Kernel;
|
||||
typedef Kernel::Point_3 Point_3;
|
||||
typedef Kernel::Vector_3 Vector_3;
|
||||
|
||||
typedef CGAL::Timer Timer;
|
||||
|
||||
template <typename G, typename Map>
|
||||
void
|
||||
run(const G& g)
|
||||
{
|
||||
typedef typename boost::graph_traits<G>::vertex_descriptor vertex_descriptor;
|
||||
|
||||
typedef typename boost::property_map<G,CGAL::vertex_point_t>::const_type VPM;
|
||||
VPM vpm = get(CGAL::vertex_point,g);
|
||||
|
||||
std::vector<vertex_descriptor> V, V2;
|
||||
std::vector<Point_3> P1, P2;
|
||||
|
||||
BOOST_FOREACH(vertex_descriptor vd, vertices(g)){
|
||||
V.push_back(vd);
|
||||
V2.push_back(vd);
|
||||
}
|
||||
|
||||
boost::rand48 random;
|
||||
boost::random_number_generator<boost::rand48> rng(random);
|
||||
std::random_shuffle(V.begin(), V.end(), rng);
|
||||
|
||||
Timer t;
|
||||
#if 0
|
||||
t.start();
|
||||
Map vm;
|
||||
BOOST_FOREACH(vertex_descriptor vd, V){
|
||||
vm[vd] = get(vpm,vd);
|
||||
}
|
||||
t.stop(); std::cerr << "Insertion: " << t.time() << " sec. " << std::endl;
|
||||
#endif
|
||||
|
||||
Vector_3 v(0,0,0);
|
||||
std::size_t st=0;
|
||||
|
||||
#if 0
|
||||
std::cerr << "BOOST_FOREACH std::vector<vertex_descriptor)\n";
|
||||
t.reset(); t.start();
|
||||
for(int i=0; i<100; i++){
|
||||
BOOST_FOREACH(vertex_descriptor vd, V2){
|
||||
#ifdef NOHASH
|
||||
st += std::size_t(vd);
|
||||
#else
|
||||
typename Map::iterator it = vm.find(vd);
|
||||
v = v + ((*it).second - CGAL::ORIGIN);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
t.stop(); std::cerr << " " <<t.time() << " sec. " << std::endl;
|
||||
#endif
|
||||
|
||||
#if 1
|
||||
std::cerr << "BOOST_FOREACH boost::iterator_range r = vertices(g))\n";
|
||||
|
||||
t.reset(); t.start();
|
||||
for(int i=0; i<100; i++){
|
||||
boost::iterator_range<typename boost::graph_traits<G>::vertex_iterator> r = vertices(g);
|
||||
|
||||
BOOST_FOREACH(vertex_descriptor vd, r) {
|
||||
#ifdef NOHASH
|
||||
st += std::size_t(vd);
|
||||
// v = v + (get(vpm,vd) - CGAL::ORIGIN);
|
||||
#else
|
||||
typename Map::iterator it = vm.find(vd);
|
||||
v = v + ((*it).second - CGAL::ORIGIN);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
t.stop(); std::cerr << " " <<t.time() << " sec. " << std::endl;
|
||||
#endif
|
||||
|
||||
|
||||
#if 1
|
||||
std::cerr << "BOOST_FOREACH CGAL::Iterator_range r = vertices(g))\n";
|
||||
t.reset(); t.start();
|
||||
for(int i=0; i<100; i++){
|
||||
CGAL::Iterator_range<typename boost::graph_traits<G>::vertex_iterator> ir = vertices(g);
|
||||
BOOST_FOREACH(vertex_descriptor vd, ir) {
|
||||
#ifdef NOHASH
|
||||
st += std::size_t(vd);
|
||||
//v = v + (get(vpm,vd) - CGAL::ORIGIN);
|
||||
#else
|
||||
typename Map::iterator it = vm.find(vd);
|
||||
v = v + ((*it).second - CGAL::ORIGIN);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
t.stop(); std::cerr << " " <<t.time() << " sec. " << std::endl;
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
#if 1
|
||||
std::cerr << "BOOST_FOREACH vertices(g))\n";
|
||||
t.reset(); t.start();
|
||||
for(int i=0; i<100; i++){
|
||||
BOOST_FOREACH(vertex_descriptor vd, vertices(g)) {
|
||||
#ifdef NOHASH
|
||||
st += std::size_t(vd);
|
||||
//v = v + (get(vpm,vd) - CGAL::ORIGIN);
|
||||
#else
|
||||
typename Map::iterator it = vm.find(vd);
|
||||
v = v + ((*it).second - CGAL::ORIGIN);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
t.stop(); std::cerr << " " <<t.time() << " sec. " << std::endl;
|
||||
#endif
|
||||
|
||||
|
||||
#if 1
|
||||
std::cerr << "for vertices(g))\n";
|
||||
t.reset(); t.start();
|
||||
for(int i=0; i<100; i++){
|
||||
for(vertex_descriptor vd : vertices(g)) {
|
||||
#ifdef NOHASH
|
||||
st += std::size_t(vd);
|
||||
//v = v + (get(vpm,vd) - CGAL::ORIGIN);
|
||||
#else
|
||||
typename Map::iterator it = vm.find(vd);
|
||||
v = v + ((*it).second - CGAL::ORIGIN);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
t.stop(); std::cerr << " " <<t.time() << " sec. " << std::endl;
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
#if 0
|
||||
std::cerr << "boost::tie(vb,ve) = vertices(g);\n";
|
||||
t.reset(); t.start();
|
||||
for(int i=0; i<100; i++){
|
||||
typename boost::graph_traits<G>::vertex_iterator vb, ve;
|
||||
boost::tie(vb,ve) = vertices(g);
|
||||
for(; vb != ve; ++vb) {
|
||||
vertex_descriptor vd = *vb;
|
||||
#ifdef NOHASH
|
||||
st += std::size_t(vd);
|
||||
//v = v + (get(vpm,vd) - CGAL::ORIGIN);
|
||||
#else
|
||||
typename Map::iterator it = vm.find(vd);
|
||||
v = v + ((*it).second - CGAL::ORIGIN);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
t.stop(); std::cerr << " " <<t.time() << " sec. " << std::endl;
|
||||
#endif
|
||||
|
||||
std::cerr << "v = " << v << " " << st << std::endl;
|
||||
|
||||
}
|
||||
|
||||
struct blob {
|
||||
int a, b, c, d, e, f, g;
|
||||
};
|
||||
|
||||
|
||||
int main(int , char* argv[])
|
||||
{
|
||||
|
||||
{
|
||||
typedef CGAL::Surface_mesh<Point_3> Mesh;
|
||||
typedef boost::graph_traits<Mesh>::vertex_descriptor vertex_descriptor;
|
||||
typedef std::map<vertex_descriptor,Point_3> SM;
|
||||
typedef std::unordered_map<vertex_descriptor,Point_3> SUM;
|
||||
typedef boost::unordered_map<vertex_descriptor,Point_3> BUM;
|
||||
|
||||
Mesh m;
|
||||
std::ifstream input(argv[1]);
|
||||
input >> m;
|
||||
|
||||
std::cerr << num_vertices(m) << " items\n";
|
||||
std::cerr << "\nSurface_mesh std::map"<< std::endl;
|
||||
run<Mesh,SM>(m);
|
||||
#if 0
|
||||
std::cerr << "\nSurface_mesh std::unordered_map"<< std::endl;
|
||||
run<Mesh,SUM>(m);
|
||||
std::cerr << "\nSurface_mesh boost::unordered_map"<< std::endl;
|
||||
run<Mesh,BUM>(m);
|
||||
#endif
|
||||
}
|
||||
|
||||
#if 0
|
||||
{
|
||||
typedef CGAL::Polyhedron_3<Kernel> Mesh;
|
||||
typedef boost::graph_traits<Mesh>::vertex_descriptor vertex_descriptor;
|
||||
typedef std::map<vertex_descriptor,Point_3> SM;
|
||||
typedef std::unordered_map<vertex_descriptor,Point_3> SUM;
|
||||
typedef boost::unordered_map<vertex_descriptor,Point_3> BUM;
|
||||
|
||||
Mesh m;
|
||||
std::ifstream input(argv[1]);
|
||||
input >> m;
|
||||
|
||||
std::cerr << "\nPolyhedron_3 std::map" << std::endl;
|
||||
run<Mesh,SM>(m);
|
||||
std::cerr << "\nPolyhedron_3 std::unordered_map"<< std::endl;
|
||||
run<Mesh,SUM>(m);
|
||||
std::cerr << "\nPolyhedron_3 boost::unordered_map"<< std::endl;
|
||||
run<Mesh,BUM>(m);
|
||||
}
|
||||
|
||||
{
|
||||
const int N = 3165798;
|
||||
std::cerr << "\nHashing "<< N << " pointers\n";
|
||||
std::vector<int> ints(N);
|
||||
|
||||
std::vector<blob> data(N);
|
||||
for(int i =0; i <N ; i++){
|
||||
ints[i]=i;
|
||||
}
|
||||
std::random_shuffle(ints.begin(), ints.end());
|
||||
|
||||
|
||||
{
|
||||
boost::unordered_map<blob*,int> um;
|
||||
Timer t;
|
||||
t.start();
|
||||
for(int i= 0; i < N; i++){
|
||||
um[& (data[ints[i]])] = i;
|
||||
}
|
||||
t.stop();
|
||||
std::cerr << " boost::unordered_map: " << t.time() << " sec.\n";
|
||||
}
|
||||
|
||||
{
|
||||
std::unordered_map<blob*,int> um;
|
||||
Timer t;
|
||||
t.start();
|
||||
for(int i= 0; i < N; i++){
|
||||
um[& (data[ints[i]])] = i;
|
||||
}
|
||||
t.stop();
|
||||
std::cerr << " std::unordered_map: " << t.time() << " sec.\n";
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -0,0 +1,152 @@
|
|||
#include <iostream>
|
||||
#include <fstream>
|
||||
#include <map>
|
||||
#include <algorithm>
|
||||
|
||||
#include <CGAL/Simple_cartesian.h>
|
||||
#include <CGAL/Polyhedron_3.h>
|
||||
#include <CGAL/IO/Polyhedron_iostream.h>
|
||||
#include <CGAL/boost/graph/graph_traits_Polyhedron_3.h>
|
||||
#include <CGAL/boost/graph/properties_Polyhedron_3.h>
|
||||
#include <CGAL/Unique_hash_map.h>
|
||||
|
||||
#include <CGAL/Timer.h>
|
||||
#include<boost/range/iterator_range.hpp>
|
||||
#include <boost/unordered_map.hpp>
|
||||
#include <unordered_map>
|
||||
|
||||
#include <boost/random/random_number_generator.hpp>
|
||||
#include <boost/random/linear_congruential.hpp>
|
||||
|
||||
typedef CGAL::Simple_cartesian<double> Kernel;
|
||||
typedef Kernel::Point_3 Point_3;
|
||||
typedef Kernel::Vector_3 Vector_3;
|
||||
|
||||
|
||||
typedef CGAL::Polyhedron_3<Kernel> Mesh;
|
||||
typedef boost::graph_traits<Mesh>::vertex_descriptor vertex_descriptor;
|
||||
|
||||
typedef CGAL::Timer Timer;
|
||||
|
||||
|
||||
|
||||
void fct(int ii, int jj)
|
||||
{
|
||||
typedef std::map<vertex_descriptor,Point_3> SM;
|
||||
typedef std::unordered_map<vertex_descriptor,Point_3> SUM;
|
||||
typedef boost::unordered_map<vertex_descriptor,Point_3> BUM;
|
||||
typedef CGAL::Unique_hash_map<vertex_descriptor, Point_3> UHM;
|
||||
|
||||
|
||||
Mesh mesh;
|
||||
typedef boost::property_map<Mesh,CGAL::vertex_point_t>::type VPM;
|
||||
VPM vpm = get(CGAL::vertex_point,mesh);
|
||||
|
||||
|
||||
Vector_3 v(0,0,0);
|
||||
|
||||
for(int i =0; i < ii; i++){
|
||||
vertex_descriptor vd = add_vertex(mesh);
|
||||
put(vpm,vd, Point_3(i,0,0));
|
||||
}
|
||||
|
||||
std::vector<vertex_descriptor> V;
|
||||
for(vertex_descriptor vd : vertices(mesh)){
|
||||
V.push_back(vd);
|
||||
}
|
||||
random_shuffle(V.begin(), V.end());
|
||||
|
||||
|
||||
Timer tsmc, tsumc, tbumc, tuhmc;
|
||||
Timer tsmq, tsumq, tbumq, tuhmq;
|
||||
|
||||
for(int j=0; j <jj; j++){
|
||||
|
||||
{
|
||||
tsmc.start();
|
||||
SM sm;
|
||||
for(vertex_descriptor vh : V){
|
||||
sm[vh] = get(vpm,vh);
|
||||
}
|
||||
tsmc.stop();
|
||||
|
||||
|
||||
tsmq.start();
|
||||
for(vertex_descriptor vh : V){
|
||||
v = v + (sm[vh] - CGAL::ORIGIN);
|
||||
}
|
||||
tsmq.stop();
|
||||
}
|
||||
{
|
||||
tsumc.start();
|
||||
SUM sm;
|
||||
for(vertex_descriptor vh : V){
|
||||
sm[vh] = get(vpm,vh);
|
||||
}
|
||||
tsumc.stop();
|
||||
|
||||
|
||||
tsumq.start();
|
||||
for(vertex_descriptor vh : V){
|
||||
v = v + (sm[vh] - CGAL::ORIGIN);
|
||||
}
|
||||
tsumq.stop();
|
||||
}
|
||||
{
|
||||
tbumc.start();
|
||||
BUM sm;
|
||||
for(vertex_descriptor vh : V){
|
||||
sm[vh] = get(vpm,vh);
|
||||
}
|
||||
tbumc.stop();
|
||||
|
||||
|
||||
tbumq.start();
|
||||
for(vertex_descriptor vh : V){
|
||||
v = v + (sm[vh] - CGAL::ORIGIN);
|
||||
}
|
||||
tbumq.stop();
|
||||
}
|
||||
|
||||
{
|
||||
tuhmc.start();
|
||||
UHM sm;
|
||||
for(vertex_descriptor vh : V){
|
||||
sm[vh] = get(vpm,vh);
|
||||
}
|
||||
tuhmc.stop();
|
||||
|
||||
|
||||
tuhmq.start();
|
||||
for(vertex_descriptor vh : V){
|
||||
v = v + (sm[vh] - CGAL::ORIGIN);
|
||||
}
|
||||
tuhmq.stop();
|
||||
}
|
||||
}
|
||||
std::cerr << ii << " items and queries (repeated " << jj << " times)" << std::endl;
|
||||
std::cerr << "std::map construction : "<< tsmc.time() << " sec." << std::endl;
|
||||
std::cerr << "std::map queries : "<< tsmq.time() << " sec." << std::endl;
|
||||
|
||||
std::cerr << "std::unordered_map construction : "<< tsumc.time() << " sec." << std::endl;
|
||||
std::cerr << "std::unordered_map queries : "<< tsumq.time() << " sec." << std::endl;
|
||||
|
||||
std::cerr << "boost::unordered_map construction : "<< tbumc.time() << " sec." << std::endl;
|
||||
std::cerr << "boost::unordered_map queries : "<< tbumq.time() << " sec.\n" << std::endl;
|
||||
|
||||
std::cerr << "Unique_hash_map construction : "<< tuhmc.time() << " sec." << std::endl;
|
||||
std::cerr << "Unique_hash_map queries : "<< tuhmq.time() << " sec.\n" << std::endl;
|
||||
|
||||
}
|
||||
|
||||
int main(int , char* argv[])
|
||||
{
|
||||
fct(1000000, 10);
|
||||
fct(100000, 100);
|
||||
fct(10000, 1000);
|
||||
fct(1000, 10000);
|
||||
fct(500, 20000);
|
||||
fct(250, 40000);
|
||||
fct(100, 100000);
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -0,0 +1,131 @@
|
|||
|
||||
#include <iostream>
|
||||
#include <fstream>
|
||||
#include <map>
|
||||
#include <algorithm>
|
||||
|
||||
#include <CGAL/Simple_cartesian.h>
|
||||
#include <CGAL/Surface_mesh.h>
|
||||
#include <CGAL/IO/Polyhedron_iostream.h>
|
||||
#include <CGAL/boost/graph/graph_traits_Surface_mesh.h>
|
||||
#include <CGAL/boost/graph/properties_Surface_mesh.h>
|
||||
|
||||
|
||||
#include <CGAL/Timer.h>
|
||||
#include<boost/range/iterator_range.hpp>
|
||||
#include <boost/unordered_map.hpp>
|
||||
#include <unordered_map>
|
||||
|
||||
#include <boost/random/random_number_generator.hpp>
|
||||
#include <boost/random/linear_congruential.hpp>
|
||||
|
||||
typedef CGAL::Simple_cartesian<double> Kernel;
|
||||
typedef Kernel::Point_3 Point_3;
|
||||
typedef Kernel::Vector_3 Vector_3;
|
||||
|
||||
|
||||
typedef CGAL::Surface_mesh<Point_3> Mesh;
|
||||
typedef boost::graph_traits<Mesh>::vertex_descriptor vertex_descriptor;
|
||||
|
||||
typedef CGAL::Timer Timer;
|
||||
|
||||
|
||||
|
||||
void fct(int ii, int jj)
|
||||
{
|
||||
typedef std::map<vertex_descriptor,Point_3> SM;
|
||||
typedef std::unordered_map<vertex_descriptor,Point_3> SUM;
|
||||
typedef boost::unordered_map<vertex_descriptor,Point_3> BUM;
|
||||
|
||||
Mesh mesh;
|
||||
typedef boost::property_map<Mesh,CGAL::vertex_point_t>::type VPM;
|
||||
VPM vpm = get(CGAL::vertex_point,mesh);
|
||||
|
||||
|
||||
Vector_3 v(0,0,0);
|
||||
|
||||
for(int i =0; i < ii; i++){
|
||||
vertex_descriptor vd = add_vertex(mesh);
|
||||
put(vpm,vd, Point_3(i,0,0));
|
||||
}
|
||||
|
||||
std::vector<vertex_descriptor> V;
|
||||
for(vertex_descriptor vd : vertices(mesh)){
|
||||
V.push_back(vd);
|
||||
}
|
||||
random_shuffle(V.begin(), V.end());
|
||||
|
||||
|
||||
Timer tsmc, tsumc, tbumc;
|
||||
Timer tsmq, tsumq, tbumq;
|
||||
for(int j=0; j <jj; j++){
|
||||
|
||||
{
|
||||
tsmc.start();
|
||||
SM sm;
|
||||
for(vertex_descriptor vh : V){
|
||||
sm[vh] = get(vpm,vh);
|
||||
}
|
||||
tsmc.stop();
|
||||
|
||||
|
||||
tsmq.start();
|
||||
for(vertex_descriptor vh : V){
|
||||
v = v + (sm[vh] - CGAL::ORIGIN);
|
||||
}
|
||||
tsmq.stop();
|
||||
}
|
||||
{
|
||||
tsumc.start();
|
||||
SUM sm;
|
||||
for(vertex_descriptor vh : V){
|
||||
sm[vh] = get(vpm,vh);
|
||||
}
|
||||
tsumc.stop();
|
||||
|
||||
|
||||
tsumq.start();
|
||||
for(vertex_descriptor vh : V){
|
||||
v = v + (sm[vh] - CGAL::ORIGIN);
|
||||
}
|
||||
tsumq.stop();
|
||||
}
|
||||
{
|
||||
tbumc.start();
|
||||
BUM sm;
|
||||
for(vertex_descriptor vh : V){
|
||||
sm[vh] = get(vpm,vh);
|
||||
}
|
||||
tbumc.stop();
|
||||
|
||||
|
||||
tbumq.start();
|
||||
for(vertex_descriptor vh : V){
|
||||
v = v + (sm[vh] - CGAL::ORIGIN);
|
||||
}
|
||||
tbumq.stop();
|
||||
}
|
||||
}
|
||||
std::cerr << ii << " items and queries (repeated " << jj << " times)" << std::endl;
|
||||
std::cerr << "std::map construction : "<< tsmc.time() << " sec." << std::endl;
|
||||
std::cerr << "std::map queries : "<< tsmq.time() << " sec." << std::endl;
|
||||
|
||||
std::cerr << "std::unordered_map construction : "<< tsumc.time() << " sec." << std::endl;
|
||||
std::cerr << "std::unordered_map queries : "<< tsumq.time() << " sec." << std::endl;
|
||||
|
||||
std::cerr << "boost::unordered_map construction : "<< tbumc.time() << " sec." << std::endl;
|
||||
std::cerr << "boost::unordered_map queries : "<< tbumq.time() << " sec.\n" << std::endl;
|
||||
|
||||
}
|
||||
|
||||
int main(int , char* argv[])
|
||||
{
|
||||
fct(1000000, 10);
|
||||
fct(100000, 100);
|
||||
fct(10000, 1000);
|
||||
fct(1000, 10000);
|
||||
fct(500, 20000);
|
||||
fct(250, 40000);
|
||||
fct(100, 100000);
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -0,0 +1,129 @@
|
|||
|
||||
#include <iostream>
|
||||
#include <fstream>
|
||||
#include <map>
|
||||
#include <algorithm>
|
||||
|
||||
#include <CGAL/Delaunay_triangulation_2.h>
|
||||
#include <CGAL/Simple_cartesian.h>
|
||||
#include <CGAL/point_generators_2.h>
|
||||
|
||||
#include <CGAL/Timer.h>
|
||||
#include<boost/range/iterator_range.hpp>
|
||||
#include <boost/unordered_map.hpp>
|
||||
#include <unordered_map>
|
||||
|
||||
#include <boost/random/random_number_generator.hpp>
|
||||
#include <boost/random/linear_congruential.hpp>
|
||||
|
||||
typedef CGAL::Simple_cartesian<double> Kernel;
|
||||
typedef Kernel::Point_2 Point_2;
|
||||
typedef Kernel::Vector_2 Vector_2;
|
||||
typedef CGAL::Creator_uniform_2<double,Point_2> Pt_creator;
|
||||
typedef CGAL::Random_points_in_disc_2<Point_2,Pt_creator> Random_points;;
|
||||
typedef CGAL::Delaunay_triangulation_2<Kernel> Dt;
|
||||
typedef Dt::Vertex_handle Vertex_handle;
|
||||
typedef Dt::Finite_vertices_iterator Finite_vertices_iterator;
|
||||
|
||||
typedef CGAL::Timer Timer;
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
void fct(int ii, int jj)
|
||||
{
|
||||
typedef std::map<Vertex_handle,Point_2> SM;
|
||||
typedef std::unordered_map<Vertex_handle,Point_2> SUM;
|
||||
typedef boost::unordered_map<Vertex_handle,Point_2> BUM;
|
||||
|
||||
Dt dt;
|
||||
Vector_2 v(0,0);
|
||||
Random_points rp( 250);
|
||||
std::vector<Point_2> points;
|
||||
for(int i =0; i < ii; i++){
|
||||
Point_2 p = *rp++;
|
||||
points.push_back(p);
|
||||
}
|
||||
|
||||
dt.insert(points.begin(), points.end());
|
||||
|
||||
std::vector<Vertex_handle> vertices;
|
||||
Finite_vertices_iterator b = dt.finite_vertices_begin(), e = dt.finite_vertices_end();
|
||||
for(; b!=e; ++b){
|
||||
vertices.push_back(b);
|
||||
}
|
||||
random_shuffle(vertices.begin(), vertices.end());
|
||||
|
||||
Timer tsmc, tsumc, tbumc;
|
||||
Timer tsmq, tsumq, tbumq;
|
||||
for(int j=0; j <jj; j++){
|
||||
|
||||
{
|
||||
tsmc.start();
|
||||
SM sm;
|
||||
for(Vertex_handle vh : vertices){
|
||||
sm[vh] = vh->point();
|
||||
}
|
||||
tsmc.stop();
|
||||
|
||||
|
||||
tsmq.start();
|
||||
for(Vertex_handle vh : vertices){
|
||||
v = v + (sm[vh] - CGAL::ORIGIN);
|
||||
}
|
||||
tsmq.stop();
|
||||
}
|
||||
{
|
||||
tsumc.start();
|
||||
SUM sm;
|
||||
for(Vertex_handle vh : vertices){
|
||||
sm[vh] = vh->point();
|
||||
}
|
||||
tsumc.stop();
|
||||
|
||||
|
||||
tsumq.start();
|
||||
for(Vertex_handle vh : vertices){
|
||||
v = v + (sm[vh] - CGAL::ORIGIN);
|
||||
}
|
||||
tsumq.stop();
|
||||
}
|
||||
{
|
||||
tbumc.start();
|
||||
BUM sm;
|
||||
for(Vertex_handle vh : vertices){
|
||||
sm[vh] = vh->point();
|
||||
}
|
||||
tbumc.stop();
|
||||
|
||||
|
||||
tbumq.start();
|
||||
for(Vertex_handle vh : vertices){
|
||||
v = v + (sm[vh] - CGAL::ORIGIN);
|
||||
}
|
||||
tbumq.stop();
|
||||
}
|
||||
}
|
||||
std::cerr << ii << " items and queries (repeated " << jj << " times)" << std::endl;
|
||||
std::cerr << "std::map construction : "<< tsmc.time() << " sec." << std::endl;
|
||||
std::cerr << "std::map queries : "<< tsmq.time() << " sec." << std::endl;
|
||||
|
||||
std::cerr << "std::unordered_map construction : "<< tsumc.time() << " sec." << std::endl;
|
||||
std::cerr << "std::unordered_map queries : "<< tsumq.time() << " sec." << std::endl;
|
||||
|
||||
std::cerr << "boost::unordered_map construction : "<< tbumc.time() << " sec." << std::endl;
|
||||
std::cerr << "boost::unordered_map queries : "<< tbumq.time() << " sec.\n" << std::endl;
|
||||
}
|
||||
|
||||
int main(int , char* argv[])
|
||||
{
|
||||
fct(1000000, 10);
|
||||
fct(100000, 100);
|
||||
fct(10000, 1000);
|
||||
fct(1000, 10000);
|
||||
fct(500, 20000);
|
||||
fct(250, 40000);
|
||||
fct(100, 100000);
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -0,0 +1,81 @@
|
|||
|
||||
#include <CGAL/Simple_cartesian.h>
|
||||
#include <CGAL/Arr_segment_traits_2.h>
|
||||
#include <CGAL/Arrangement_2.h>
|
||||
#include <CGAL/Polyhedron_3.h>
|
||||
#include <CGAL/Surface_mesh.h>
|
||||
#include <CGAL/Triangulation_2.h>
|
||||
#include <CGAL/Linear_cell_complex.h>
|
||||
#include <CGAL/boost/graph/graph_traits_Arrangement_2.h>
|
||||
#include <CGAL/boost/graph/graph_traits_Polyhedron_3.h>
|
||||
#include <CGAL/boost/graph/graph_traits_Triangulation_2.h>
|
||||
#include <map>
|
||||
#include <boost/unordered_map.hpp>
|
||||
|
||||
|
||||
typedef CGAL::Simple_cartesian<double> Kernel;
|
||||
typedef CGAL::Arr_segment_traits_2<Kernel> Arrangement_traits_2;
|
||||
typedef CGAL::Arrangement_2<Arrangement_traits_2> Arrangement_2;
|
||||
|
||||
typedef CGAL::Polyhedron_3<Kernel> Polyhedron;
|
||||
typedef CGAL::Surface_mesh<Kernel::Point_3> Surface_mesh;
|
||||
typedef CGAL::Triangulation_2<Kernel> Triangulation_2;
|
||||
typedef CGAL::Linear_cell_complex<3, 3> Linear_cell_complex_3;
|
||||
|
||||
|
||||
template <typename P>
|
||||
void
|
||||
fct(const P& )
|
||||
{
|
||||
typedef typename boost::graph_traits<P>::vertex_descriptor vertex_descriptor;
|
||||
|
||||
std::map<vertex_descriptor,int> M;
|
||||
vertex_descriptor vd;
|
||||
M.find(vd);
|
||||
|
||||
boost::unordered_map<vertex_descriptor, int> U;
|
||||
U[vd] = 12;
|
||||
}
|
||||
|
||||
void fct2()
|
||||
{
|
||||
typedef Linear_cell_complex_3::Dart_handle dh;
|
||||
typedef Linear_cell_complex_3::Vertex_attribute_handle vh;
|
||||
|
||||
{ // For dart handle
|
||||
std::map<dh, int> M;
|
||||
dh e;
|
||||
M.find(e);
|
||||
boost::unordered_map<dh, int> U;
|
||||
U[e] = 12;
|
||||
}
|
||||
|
||||
{ // For vertex attribute handle
|
||||
std::map<vh, int> M;
|
||||
vh e;
|
||||
M.find(e);
|
||||
boost::unordered_map<vh, int> U;
|
||||
U[e] = 12;
|
||||
}
|
||||
}
|
||||
|
||||
int main()
|
||||
{
|
||||
Arrangement_2 A;
|
||||
fct(A);
|
||||
|
||||
Polyhedron P;
|
||||
fct(P);
|
||||
|
||||
Surface_mesh S;
|
||||
fct(S);
|
||||
|
||||
Triangulation_2 T;
|
||||
fct(T);
|
||||
|
||||
fct2();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -128,6 +128,13 @@ and <code>src/</code> directories).
|
|||
<li>The code of the 3D demos now use modern OpenGL, with shaders,
|
||||
instead of the fixed pipeline API of OpenGL-1.</li>
|
||||
</ul>
|
||||
|
||||
<h3>General</h3>
|
||||
<ul>
|
||||
<li>Support for unordered sets and maps of the stdlib and of boost for
|
||||
handle and index classes.
|
||||
</li>
|
||||
</ul>
|
||||
<!-- New packages -->
|
||||
|
||||
<!-- sdglinf-philaris begin-->
|
||||
|
|
|
|||
|
|
@ -837,6 +837,11 @@ public:
|
|||
convenience, the `Point_iterator` enumerates all points in the polyhedral
|
||||
surface in the same order as the `Vertex_iterator`, but with the
|
||||
value type `Point`. Similarly, a `Plane_iterator` is provided.
|
||||
|
||||
|
||||
All handles are model of `LessThanComparable` and `Hashable`,
|
||||
that is they can be used as keys in containers such as `std::map`
|
||||
and `boost::unordered_map`.
|
||||
*/
|
||||
/// @{
|
||||
|
||||
|
|
|
|||
|
|
@ -834,4 +834,12 @@ static void * & pointer(T &t);
|
|||
|
||||
|
||||
}; /* end Compact_container_traits */
|
||||
|
||||
/*!
|
||||
returns a hash value for the pointee of `i`.
|
||||
\relates Compact_container
|
||||
*/
|
||||
template <class T, class A>
|
||||
std::size_t hash_value(const Compact_container<T,A>::iterator i);
|
||||
|
||||
} /* end namespace CGAL */
|
||||
|
|
|
|||
|
|
@ -762,4 +762,22 @@ void sort();
|
|||
|
||||
|
||||
}; /* end In_place_list */
|
||||
|
||||
/*!
|
||||
returns a hash value for the pointee of `i`.
|
||||
\relates In_place_list
|
||||
*/
|
||||
|
||||
template <class T, bool>
|
||||
std::size_t hash_value(const In_place_list<T,bool>::iterator i);
|
||||
|
||||
/*!
|
||||
returns a hash value for the pointee of `i`.
|
||||
\relates In_place_list
|
||||
*/
|
||||
|
||||
template <class T, class bool>
|
||||
std::size_t hash_value(const In_place_list<T,bool>::const_iterator i);
|
||||
|
||||
|
||||
} /* end namespace CGAL */
|
||||
|
|
|
|||
|
|
@ -0,0 +1,23 @@
|
|||
|
||||
/*!
|
||||
\ingroup PkgStlExtensionConcepts
|
||||
\cgalConcept
|
||||
|
||||
A type `Key` is a model of the concept `Hashable` if the
|
||||
specializations `boost::hash<Key>` and `std::hash<Key>` exist.
|
||||
|
||||
\cgalHasModel All handles and indices of \cgal data structures.
|
||||
|
||||
|
||||
\sa `CGAL::Unique_hash_map<Key,Mapped,Hash>`
|
||||
\sa <A HREF="http://www.cplusplus.com/reference/unordered_set/unordered_set/">`std::unordered_set`</a>
|
||||
\sa <A HREF="http://www.cplusplus.com/reference/unordered_set/unordered_map/">`std::unordered_map`</a>
|
||||
\sa <A HREF="http://www.boost.org/doc/libs/release/doc/html/boost/unordered_set.html">`boost::unordered_set`</a>
|
||||
\sa <A HREF="http://www.boost.org/doc/libs/release/doc/html/boost/unordered_map.html">`boost::unordered_map`</a>
|
||||
|
||||
*/
|
||||
|
||||
class Hashable {
|
||||
|
||||
};
|
||||
|
||||
|
|
@ -130,6 +130,13 @@ looking up keys whose type may differ from `Type`, as long as users supply
|
|||
a comparison functor `CompareKey`, between the keys and set elements;
|
||||
and catenating and splitting sets.
|
||||
|
||||
\section stl_hash Hashing
|
||||
|
||||
For handles and indices of vertices, halfedges, faces, etc., we provide specializations of `boost::hash<T>` and `std::hash<T>`, so that they can be used with classes such as `boost::unordered_map`.
|
||||
|
||||
\cgalExample{STL_Extension/unordered_map.cpp}
|
||||
|
||||
|
||||
\section stl_polyobject Polymorphic Object
|
||||
|
||||
The class `Object` can store an object of whatever other type.
|
||||
|
|
|
|||
|
|
@ -2,3 +2,5 @@ Manual
|
|||
Circulator
|
||||
Number_types
|
||||
Kernel_23
|
||||
Miscellany
|
||||
Surface_mesh
|
||||
|
|
|
|||
|
|
@ -3,4 +3,5 @@
|
|||
\example STL_Extension/in_place_list_prog.cpp
|
||||
\example STL_Extension/min_element_if_example.cpp
|
||||
\example STL_Extension/min_max_element_example.cpp
|
||||
\example STL_Extension/unordered_map.cpp
|
||||
*/
|
||||
|
|
|
|||
|
|
@ -0,0 +1,19 @@
|
|||
|
||||
#include <CGAL/Simple_cartesian.h>
|
||||
#include <CGAL/Surface_mesh.h>
|
||||
#include <boost/unordered_map.hpp>
|
||||
|
||||
|
||||
typedef CGAL::Simple_cartesian<double> Kernel;
|
||||
typedef Kernel::Point_3 Point_3;
|
||||
typedef CGAL::Surface_mesh<Point_3> Mesh;
|
||||
typedef boost::graph_traits<Mesh>::vertex_descriptor vertex_descriptor;
|
||||
|
||||
int main()
|
||||
{
|
||||
boost::unordered_map<vertex_descriptor, int> bum;
|
||||
Mesh mesh;
|
||||
vertex_descriptor vd = mesh.add_vertex();
|
||||
bum[vd] = 7812;
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -28,6 +28,7 @@
|
|||
#include <algorithm>
|
||||
#include <vector>
|
||||
#include <cstring>
|
||||
#include <functional>
|
||||
|
||||
#include <CGAL/memory.h>
|
||||
#include <CGAL/iterator.h>
|
||||
|
|
@ -1167,8 +1168,39 @@ namespace internal {
|
|||
return rhs.operator->() != NULL;
|
||||
}
|
||||
|
||||
template <class DSC, bool Const>
|
||||
std::size_t hash_value(const CC_iterator<DSC, Const>& i)
|
||||
{
|
||||
return reinterpret_cast<std::size_t>(&*i) / sizeof(typename DSC::value_type);
|
||||
}
|
||||
|
||||
} // namespace internal
|
||||
|
||||
} //namespace CGAL
|
||||
|
||||
namespace std {
|
||||
|
||||
#if defined(BOOST_MSVC)
|
||||
# pragma warning(push)
|
||||
# pragma warning(disable:4099) // For VC10 it is class hash
|
||||
#endif
|
||||
|
||||
template < class T>
|
||||
struct hash;
|
||||
|
||||
template < class DSC, bool Const >
|
||||
struct hash<CGAL::internal::CC_iterator<DSC, Const> >
|
||||
: public std::unary_function<CGAL::internal::CC_iterator<DSC, Const>, std::size_t> {
|
||||
|
||||
std::size_t operator()(const CGAL::internal::CC_iterator<DSC, Const>& i) const
|
||||
{
|
||||
return reinterpret_cast<std::size_t>(&*i) / sizeof(typename DSC::value_type);
|
||||
}
|
||||
};
|
||||
#if defined(BOOST_MSVC)
|
||||
# pragma warning(pop)
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
#endif // CGAL_COMPACT_CONTAINER_H
|
||||
|
|
|
|||
|
|
@ -33,6 +33,7 @@
|
|||
#include <functional>
|
||||
#include <algorithm>
|
||||
#include <CGAL/memory.h>
|
||||
#include <boost/functional/hash.hpp>
|
||||
|
||||
namespace CGAL {
|
||||
|
||||
|
|
@ -170,6 +171,24 @@ namespace internal {
|
|||
return In_place_list_iterator<T,Alloc>(const_cast<T*>(node));
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
|
||||
template <class T, class Alloc>
|
||||
std::size_t hash_value(const In_place_list_iterator<T,Alloc>& i)
|
||||
{
|
||||
T* ptr = &*i;
|
||||
return reinterpret_cast<std::size_t>(ptr)/ sizeof(T);
|
||||
}
|
||||
|
||||
|
||||
template <class T, class Alloc>
|
||||
std::size_t hash_value(const In_place_list_const_iterator<T,Alloc>& i)
|
||||
{
|
||||
T* ptr = &*i;
|
||||
return reinterpret_cast<std::size_t>(ptr)/ sizeof(T);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -752,4 +771,41 @@ void In_place_list<T,managed,Alloc>::sort() {
|
|||
|
||||
} //namespace CGAL
|
||||
|
||||
namespace std {
|
||||
|
||||
#if defined(BOOST_MSVC)
|
||||
# pragma warning(push)
|
||||
# pragma warning(disable:4099) // For VC10 it is class hash
|
||||
#endif
|
||||
|
||||
template < class T>
|
||||
struct hash;
|
||||
|
||||
template < class T, class Alloc >
|
||||
struct hash<CGAL::internal::In_place_list_iterator<T, Alloc> >
|
||||
: public std::unary_function<CGAL::internal::In_place_list_iterator<T, Alloc>, std::size_t> {
|
||||
|
||||
std::size_t operator()(const CGAL::internal::In_place_list_iterator<T, Alloc>& i) const
|
||||
{
|
||||
const T* ptr = &*i;
|
||||
return reinterpret_cast<std::size_t>(ptr)/ sizeof(T);
|
||||
}
|
||||
};
|
||||
|
||||
template < class T, class Alloc >
|
||||
struct hash<CGAL::internal::In_place_list_const_iterator<T, Alloc> >
|
||||
: public std::unary_function<CGAL::internal::In_place_list_const_iterator<T, Alloc>, std::size_t> {
|
||||
|
||||
std::size_t operator()(const CGAL::internal::In_place_list_const_iterator<T, Alloc>& i) const
|
||||
{
|
||||
const T* ptr = &*i;
|
||||
return reinterpret_cast<std::size_t>(ptr)/ sizeof(T);
|
||||
}
|
||||
};
|
||||
|
||||
#if defined(BOOST_MSVC)
|
||||
# pragma warning(pop)
|
||||
#endif
|
||||
|
||||
}
|
||||
#endif // CGAL_IN_PLACE_LIST_H
|
||||
|
|
|
|||
|
|
@ -22,7 +22,7 @@
|
|||
|
||||
#include <CGAL/tuple.h>
|
||||
#include <utility>
|
||||
|
||||
#include <boost/foreach.hpp>
|
||||
|
||||
namespace CGAL {
|
||||
|
||||
|
|
@ -45,6 +45,11 @@ namespace CGAL {
|
|||
: Base(b,e)
|
||||
{}
|
||||
|
||||
|
||||
// Iterator_range(const Iterator_range& ip)
|
||||
// : Base(ip)
|
||||
// {}
|
||||
|
||||
Iterator_range(const std::pair<I,I>& ip)
|
||||
: Base(ip)
|
||||
{}
|
||||
|
|
@ -74,29 +79,23 @@ namespace CGAL {
|
|||
return Iterator_range<T>(b,e);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
inline T range_begin( Iterator_range<T> & x )
|
||||
{
|
||||
return x.first;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
inline T range_end( Iterator_range<T> & x )
|
||||
{
|
||||
return x.second;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
inline T range_begin(const Iterator_range<T>& x )
|
||||
{
|
||||
return x.first;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
inline T range_end(const Iterator_range<T>& x )
|
||||
{
|
||||
return x.second;
|
||||
}
|
||||
|
||||
} // namespace CGAL
|
||||
|
||||
// At global scope...
|
||||
|
||||
template<typename T>
|
||||
inline boost::mpl::true_ *
|
||||
boost_foreach_is_lightweight_proxy( CGAL::Iterator_range<T> *&, boost::foreach::tag )
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
namespace boost { namespace foreach
|
||||
{
|
||||
template<typename T>
|
||||
struct is_lightweight_proxy< CGAL::Iterator_range<T> >
|
||||
: mpl::true_
|
||||
{
|
||||
};
|
||||
}}
|
||||
#endif // CGAL_ITERATOR_RANGE_H
|
||||
|
|
|
|||
|
|
@ -27,6 +27,7 @@
|
|||
#include <vector>
|
||||
#include <string>
|
||||
#include <typeinfo>
|
||||
#include <functional>
|
||||
|
||||
#include <boost/cstdint.hpp>
|
||||
#include <boost/array.hpp>
|
||||
|
|
@ -49,12 +50,213 @@
|
|||
#include <CGAL/boost/graph/Euler_operations.h>
|
||||
|
||||
namespace CGAL {
|
||||
|
||||
|
||||
#ifndef DOXYGEN_RUNNING
|
||||
/// Base class for vertex, halfedge, edge, and face index.
|
||||
///
|
||||
/// \attention Note that `Index` is not a model of the concept `Handle`,
|
||||
/// because it cannot be dereferenced.
|
||||
/// \sa `Vertex_index`, `Halfedge_index`, `Edge_index`, `Face_index`.
|
||||
template<typename T>
|
||||
class SM_Index
|
||||
{
|
||||
public:
|
||||
typedef boost::uint32_t size_type;
|
||||
/// Constructor. %Default construction creates an invalid index.
|
||||
/// We write -1, which is <a href="http://en.cppreference.com/w/cpp/concept/numeric_limits">
|
||||
/// <tt>std::numeric_limits<size_type>::max()</tt></a>
|
||||
/// as `size_type` is an unsigned type.
|
||||
explicit SM_Index(size_type _idx=-1) : idx_(_idx) {}
|
||||
|
||||
/// Get the underlying index of this index
|
||||
operator size_type() const { return idx_; }
|
||||
|
||||
/// reset index to be invalid (index=-1)
|
||||
void reset() { idx_=-1; }
|
||||
|
||||
/// return whether the index is valid, i.e., the index is not equal to -1.
|
||||
bool is_valid() const {
|
||||
size_type inf = -1;
|
||||
return idx_ != inf;
|
||||
}
|
||||
|
||||
/// are two indices equal?
|
||||
bool operator==(const T& _rhs) const {
|
||||
return idx_ == _rhs.idx_;
|
||||
}
|
||||
|
||||
/// are two indices different?
|
||||
bool operator!=(const T& _rhs) const {
|
||||
return idx_ != _rhs.idx_;
|
||||
}
|
||||
|
||||
/// Comparison by index.
|
||||
bool operator<(const T& _rhs) const {
|
||||
return idx_ < _rhs.idx_;
|
||||
}
|
||||
|
||||
/// increments the internal index. This operation does not
|
||||
/// guarantee that the index is valid or undeleted after the
|
||||
/// increment.
|
||||
SM_Index& operator++() { ++idx_; return *this; }
|
||||
/// decrements the internal index. This operation does not
|
||||
/// guarantee that the index is valid or undeleted after the
|
||||
/// decrement.
|
||||
SM_Index& operator--() { --idx_; return *this; }
|
||||
|
||||
/// increments the internal index. This operation does not
|
||||
/// guarantee that the index is valid or undeleted after the
|
||||
/// increment.
|
||||
SM_Index operator++(int) { SM_Index tmp(*this); ++idx_; return tmp; }
|
||||
/// decrements the internal index. This operation does not
|
||||
/// guarantee that the index is valid or undeleted after the
|
||||
/// decrement.
|
||||
SM_Index operator--(int) { SM_Index tmp(*this); --idx_; return tmp; }
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
private:
|
||||
size_type idx_;
|
||||
};
|
||||
|
||||
template <class T>
|
||||
std::size_t hash_value(const SM_Index<T>& i)
|
||||
{
|
||||
std::size_t ret = i;
|
||||
return ret;
|
||||
}
|
||||
|
||||
// Implementation for Surface_mesh::Vertex_index
|
||||
|
||||
class SM_Vertex_index
|
||||
: public SM_Index<SM_Vertex_index>
|
||||
{
|
||||
public:
|
||||
|
||||
SM_Vertex_index() : SM_Index<SM_Vertex_index>(-1) {}
|
||||
|
||||
explicit SM_Vertex_index(size_type _idx) : SM_Index<SM_Vertex_index>(_idx) {}
|
||||
|
||||
|
||||
friend std::ostream& operator<<(std::ostream& os, SM_Vertex_index const& v)
|
||||
{
|
||||
return (os << 'v' << (size_type)v );
|
||||
}
|
||||
};
|
||||
|
||||
// Implementation of Surface_mesh::Halfedge_index
|
||||
class SM_Halfedge_index
|
||||
: public SM_Index<SM_Halfedge_index>
|
||||
{
|
||||
public:
|
||||
|
||||
SM_Halfedge_index() : SM_Index<SM_Halfedge_index>(-1) {}
|
||||
|
||||
explicit SM_Halfedge_index(size_type _idx) : SM_Index<SM_Halfedge_index>(_idx) {}
|
||||
|
||||
friend std::ostream& operator<<(std::ostream& os, SM_Halfedge_index const& h)
|
||||
{
|
||||
return (os << 'h' << (size_type)h );
|
||||
}
|
||||
};
|
||||
|
||||
/// Implementation of Surfae_mesh::Face_index
|
||||
class SM_Face_index
|
||||
: public SM_Index<SM_Face_index>
|
||||
{
|
||||
public:
|
||||
|
||||
SM_Face_index() : SM_Index<SM_Face_index>(-1) {}
|
||||
|
||||
explicit SM_Face_index(size_type _idx) : SM_Index<SM_Face_index>(_idx) {}
|
||||
|
||||
|
||||
friend std::ostream& operator<<(std::ostream& os, SM_Face_index const& f)
|
||||
{
|
||||
return (os << 'f' << (size_type)f );
|
||||
}
|
||||
};
|
||||
|
||||
/// Implementation of Surface_mesh::Edge_index
|
||||
class SM_Edge_index
|
||||
{
|
||||
public:
|
||||
typedef boost::uint32_t size_type;
|
||||
|
||||
SM_Edge_index() : halfedge_(-1) { }
|
||||
|
||||
SM_Edge_index(size_type idx) : halfedge_(idx * 2) { }
|
||||
|
||||
|
||||
SM_Edge_index(SM_Halfedge_index he) : halfedge_(he) { }
|
||||
|
||||
// returns the internal halfedge.
|
||||
SM_Halfedge_index halfedge() const { return halfedge_; }
|
||||
|
||||
// returns the underlying index of this index.
|
||||
operator size_type() const { return (size_type)halfedge_ / 2; }
|
||||
|
||||
// resets index to be invalid (index=-1)
|
||||
void reset() { halfedge_.reset(); }
|
||||
|
||||
// returns whether the index is valid, i.e., the index is not equal to -1.
|
||||
bool is_valid() const { return halfedge_.is_valid(); }
|
||||
|
||||
// Are two indices equal?
|
||||
bool operator==(const SM_Edge_index& other) const { return (size_type)(*this) == (size_type)other; }
|
||||
|
||||
// Are two indices different?
|
||||
bool operator!=(const SM_Edge_index& other) const { return (size_type)(*this) != (size_type)other; }
|
||||
|
||||
// compares by index.
|
||||
bool operator<(const SM_Edge_index& other) const { return (size_type)(*this) < (size_type)other;}
|
||||
|
||||
// decrements the internal index. This operation does not
|
||||
// guarantee that the index is valid or undeleted after the
|
||||
// decrement.
|
||||
SM_Edge_index& operator--() { halfedge_ = SM_Halfedge_index((size_type)halfedge_ - 2); return *this; }
|
||||
|
||||
// increments the internal index. This operation does not
|
||||
// guarantee that the index is valid or undeleted after the
|
||||
// increment.
|
||||
SM_Edge_index& operator++() { halfedge_ = SM_Halfedge_index((size_type)halfedge_ + 2); return *this; }
|
||||
|
||||
// decrements internal index. This operation does not
|
||||
// guarantee that the index is valid or undeleted after the
|
||||
// decrement.
|
||||
SM_Edge_index operator--(int) { SM_Edge_index tmp(*this); halfedge_ = SM_Halfedge_index((size_type)halfedge_ - 2); return tmp; }
|
||||
|
||||
// increments internal index. This operation does not
|
||||
// guarantee that the index is valid or undeleted after the
|
||||
// increment.
|
||||
SM_Edge_index operator++(int) { SM_Edge_index tmp(*this); halfedge_ = SM_Halfedge_index((size_type)halfedge_ + 2); return tmp; }
|
||||
|
||||
|
||||
// prints the index and a short identification string to an ostream.
|
||||
friend std::ostream& operator<<(std::ostream& os, SM_Edge_index const& e)
|
||||
{
|
||||
return (os << 'e' << (size_type)e << " on " << e.halfedge());
|
||||
}
|
||||
|
||||
friend std::size_t hash_value(const SM_Edge_index& i)
|
||||
{
|
||||
return i;
|
||||
}
|
||||
|
||||
private:
|
||||
SM_Halfedge_index halfedge_;
|
||||
};
|
||||
#endif
|
||||
|
||||
/// \ingroup PkgSurface_mesh
|
||||
/// This class is a data structure that can be used as halfedge data structure or polyhedral
|
||||
/// surface. It is an alternative to the classes `HalfedgeDS` and `Polyhedron_3`
|
||||
/// defined in the packages \ref PkgHDSSummary and \ref PkgPolyhedronSummary.
|
||||
/// The main difference is that it is indexed based and not pointer based,
|
||||
/// and that the mechanism for adding information to vertices, halfedges,
|
||||
/// and that the mechanism for adding information to vertices, halfedges, edges,
|
||||
/// and faces is much simpler and done at runtime and not at compile time.
|
||||
/// When elements are removed, they are only marked as removed, and a garbage
|
||||
/// collection function must be called to really remove them.
|
||||
|
|
@ -575,85 +777,21 @@ private:
|
|||
///
|
||||
///@{
|
||||
|
||||
#ifndef DOXYGEN_RUNNING
|
||||
/// Base class for vertex, halfedge, edge, and face index.
|
||||
///
|
||||
/// \attention Note that `Index` is not a model of the concept `Handle`,
|
||||
/// because it cannot be dereferenced.
|
||||
/// \sa `Vertex_index`, `Halfedge_index`, `Edge_index`, `Face_index`.
|
||||
template<typename T>
|
||||
class Index
|
||||
{
|
||||
public:
|
||||
/// Constructor. %Default construction creates an invalid index.
|
||||
/// We write -1, which is <a href="http://en.cppreference.com/w/cpp/concept/numeric_limits">
|
||||
/// <tt>std::numeric_limits<size_type>::max()</tt></a>
|
||||
/// as `size_type` is an unsigned type.
|
||||
explicit Index(size_type _idx=-1) : idx_(_idx) {}
|
||||
|
||||
/// Get the underlying index of this index
|
||||
operator size_type() const { return idx_; }
|
||||
|
||||
/// reset index to be invalid (index=-1)
|
||||
void reset() { idx_=-1; }
|
||||
|
||||
/// return whether the index is valid, i.e., the index is not equal to -1.
|
||||
bool is_valid() const {
|
||||
size_type inf = -1;
|
||||
return idx_ != inf;
|
||||
}
|
||||
|
||||
/// are two indices equal?
|
||||
bool operator==(const T& _rhs) const {
|
||||
return idx_ == _rhs.idx_;
|
||||
}
|
||||
|
||||
/// are two indices different?
|
||||
bool operator!=(const T& _rhs) const {
|
||||
return idx_ != _rhs.idx_;
|
||||
}
|
||||
|
||||
/// Comparison by index.
|
||||
bool operator<(const T& _rhs) const {
|
||||
return idx_ < _rhs.idx_;
|
||||
}
|
||||
|
||||
/// increments the internal index. This operation does not
|
||||
/// guarantee that the index is valid or undeleted after the
|
||||
/// increment.
|
||||
Index& operator++() { ++idx_; return *this; }
|
||||
/// decrements the internal index. This operation does not
|
||||
/// guarantee that the index is valid or undeleted after the
|
||||
/// decrement.
|
||||
Index& operator--() { --idx_; return *this; }
|
||||
|
||||
/// increments the internal index. This operation does not
|
||||
/// guarantee that the index is valid or undeleted after the
|
||||
/// increment.
|
||||
Index operator++(int) { Index tmp(*this); ++idx_; return tmp; }
|
||||
/// decrements the internal index. This operation does not
|
||||
/// guarantee that the index is valid or undeleted after the
|
||||
/// decrement.
|
||||
Index operator--(int) { Index tmp(*this); --idx_; return tmp; }
|
||||
private:
|
||||
size_type idx_;
|
||||
};
|
||||
|
||||
#endif
|
||||
#ifdef DOXYGEN_RUNNING
|
||||
|
||||
/// This class represents a vertex.
|
||||
/// \cgalModels `Index`
|
||||
/// \cgalModels `LessThanComparable`
|
||||
/// \cgalModels `Hashable`
|
||||
/// \sa `Halfedge_index`, `Edge_index`, `Face_index`
|
||||
class Vertex_index
|
||||
#ifndef DOXYGEN_RUNNING
|
||||
: public Index<Vertex_index>
|
||||
#endif
|
||||
{
|
||||
public:
|
||||
/// %Default constructor.
|
||||
Vertex_index() : Index<Vertex_index>(-1) {}
|
||||
Vertex_index() : SM_Index<Vertex_index>(-1) {}
|
||||
|
||||
explicit Vertex_index(size_type _idx) : Index<Vertex_index>(_idx) {}
|
||||
explicit Vertex_index(size_type _idx) : SM_Index<Vertex_index>(_idx) {}
|
||||
|
||||
/// prints the index and a short identification string to an ostream.
|
||||
friend std::ostream& operator<<(std::ostream& os, typename Surface_mesh::Vertex_index const& v)
|
||||
|
|
@ -661,20 +799,24 @@ private:
|
|||
return (os << 'v' << (size_type)v );
|
||||
}
|
||||
};
|
||||
#else
|
||||
typedef SM_Vertex_index Vertex_index;
|
||||
#endif
|
||||
|
||||
#ifdef DOXYGEN_RUNNING
|
||||
|
||||
/// This class represents a halfedge.
|
||||
/// \cgalModels `Index`
|
||||
/// \cgalModels `LessThanComparable`
|
||||
/// \cgalModels `Hashable`
|
||||
/// \sa `Vertex_index`, `Edge_index`, `Face_index`
|
||||
class Halfedge_index
|
||||
#ifndef DOXYGEN_RUNNING
|
||||
: public Index<Halfedge_index>
|
||||
#endif
|
||||
{
|
||||
public:
|
||||
/// %Default constructor
|
||||
Halfedge_index() : Index<Halfedge_index>(-1) {}
|
||||
Halfedge_index() : SM_Index<Halfedge_index>(-1) {}
|
||||
|
||||
explicit Halfedge_index(size_type _idx) : Index<Halfedge_index>(_idx) {}
|
||||
explicit Halfedge_index(size_type _idx) : SM_Index<Halfedge_index>(_idx) {}
|
||||
|
||||
/// prints the index and a short identification string to an ostream.
|
||||
friend std::ostream& operator<<(std::ostream& os, typename Surface_mesh::Halfedge_index const& h)
|
||||
|
|
@ -683,20 +825,23 @@ private:
|
|||
}
|
||||
|
||||
};
|
||||
#else
|
||||
typedef SM_Halfedge_index Halfedge_index;
|
||||
#endif
|
||||
|
||||
#ifdef DOXYGEN_RUNNING
|
||||
/// This class represents a face
|
||||
/// \cgalModels `Index`
|
||||
/// \cgalModels `LessThanComparable`
|
||||
/// \cgalModels `Hashable`
|
||||
/// \sa `Vertex_index`, `Halfedge_index`, `Edge_index`
|
||||
class Face_index
|
||||
#ifndef DOXYGEN_RUNNING
|
||||
: public Index<Face_index>
|
||||
#endif
|
||||
{
|
||||
public:
|
||||
/// %Default constructor
|
||||
Face_index() : Index<Face_index>(-1) {}
|
||||
Face_index() : SM_Index<Face_index>(-1) {}
|
||||
|
||||
explicit Face_index(size_type _idx) : Index<Face_index>(_idx) {}
|
||||
explicit Face_index(size_type _idx) : SM_Index<Face_index>(_idx) {}
|
||||
|
||||
/// prints the index and a short identification string to an ostream.
|
||||
friend std::ostream& operator<<(std::ostream& os, typename Surface_mesh::Face_index const& f)
|
||||
|
|
@ -704,9 +849,15 @@ private:
|
|||
return (os << 'f' << (size_type)f );
|
||||
}
|
||||
};
|
||||
#else
|
||||
typedef SM_Face_index Face_index;
|
||||
#endif
|
||||
|
||||
#ifdef DOXYGEN_RUNNING
|
||||
/// This class represents an edge.
|
||||
/// \cgalModels `Index`
|
||||
/// \cgalModels `LessThanComparable`
|
||||
/// \cgalModels `Hashable`
|
||||
/// \sa `Vertex_index`, `Halfedge_index`, `Face_index`
|
||||
class Edge_index
|
||||
{
|
||||
|
|
@ -770,7 +921,9 @@ private:
|
|||
private:
|
||||
Halfedge_index halfedge_;
|
||||
};
|
||||
|
||||
#else
|
||||
typedef SM_Edge_index Edge_index;
|
||||
#endif
|
||||
|
||||
|
||||
///@}
|
||||
|
|
@ -824,8 +977,9 @@ private: //------------------------------------------------------ iterator types
|
|||
Index_iterator() : hnd_(), mesh_(NULL) {}
|
||||
Index_iterator(const Index_& h, const Surface_mesh* m)
|
||||
: hnd_(h), mesh_(m) {
|
||||
if (mesh_ && mesh_->has_garbage())
|
||||
if (mesh_ && mesh_->has_garbage()){
|
||||
while (mesh_->has_valid_index(hnd_) && mesh_->is_removed(hnd_)) ++hnd_;
|
||||
}
|
||||
}
|
||||
private:
|
||||
friend class boost::iterator_core_access;
|
||||
|
|
@ -833,14 +987,17 @@ private: //------------------------------------------------------ iterator types
|
|||
{
|
||||
++hnd_;
|
||||
CGAL_assertion(mesh_ != NULL);
|
||||
while (mesh_->has_garbage() && mesh_->has_valid_index(hnd_) && mesh_->is_removed(hnd_)) ++hnd_;
|
||||
}
|
||||
|
||||
if(mesh_->has_garbage())
|
||||
while ( mesh_->has_valid_index(hnd_) && mesh_->is_removed(hnd_)) ++hnd_;
|
||||
}
|
||||
|
||||
void decrement()
|
||||
{
|
||||
--hnd_;
|
||||
CGAL_assertion(mesh_ != NULL);
|
||||
while (mesh_->has_garbage() && mesh_->has_valid_index(hnd_) && mesh_->is_removed(hnd_)) --hnd_;
|
||||
if(mesh_->has_garbage())
|
||||
while ( mesh_->has_valid_index(hnd_) && mesh_->is_removed(hnd_)) --hnd_;
|
||||
}
|
||||
|
||||
bool equal(const Index_iterator& other) const
|
||||
|
|
@ -852,6 +1009,7 @@ private: //------------------------------------------------------ iterator types
|
|||
|
||||
Index_ hnd_;
|
||||
const Surface_mesh* mesh_;
|
||||
|
||||
};
|
||||
public:
|
||||
/// \name Range Types
|
||||
|
|
@ -1606,7 +1764,8 @@ public:
|
|||
bool has_valid_index(Vertex_index v) const
|
||||
{
|
||||
return ((size_type)v < num_vertices());
|
||||
}
|
||||
}
|
||||
|
||||
/// returns whether the index of halfedge `h` is valid, that is within the current array bounds.
|
||||
bool has_valid_index(Halfedge_index h) const
|
||||
{
|
||||
|
|
@ -2310,6 +2469,7 @@ private: //------------------------------------------------------- private data
|
|||
}
|
||||
|
||||
/// @cond CGAL_DOCUMENT_INTERNALS
|
||||
|
||||
inline std::istream& sm_skip_comments( std::istream& in) {
|
||||
char c;
|
||||
in >> c;
|
||||
|
|
@ -2778,7 +2938,78 @@ collect_garbage()
|
|||
garbage_ = false;
|
||||
}
|
||||
|
||||
|
||||
|
||||
} // CGAL
|
||||
|
||||
|
||||
namespace std {
|
||||
|
||||
#if defined(BOOST_MSVC)
|
||||
# pragma warning(push)
|
||||
# pragma warning(disable:4099) // For VC10 it is class hash
|
||||
#endif
|
||||
|
||||
#ifndef DOXYGEN_RUNNING
|
||||
template < class T>
|
||||
struct hash;
|
||||
#endif
|
||||
|
||||
template <>
|
||||
struct hash<CGAL::SM_Halfedge_index >
|
||||
: public std::unary_function<CGAL::SM_Halfedge_index, std::size_t> {
|
||||
|
||||
std::size_t operator()(const CGAL::SM_Halfedge_index& i) const
|
||||
{
|
||||
return i;
|
||||
}
|
||||
};
|
||||
|
||||
template <>
|
||||
struct hash<CGAL::SM_Vertex_index >
|
||||
: public std::unary_function<CGAL::SM_Vertex_index, std::size_t> {
|
||||
|
||||
std::size_t operator()(const CGAL::SM_Vertex_index& i) const
|
||||
{
|
||||
return i;
|
||||
}
|
||||
};
|
||||
|
||||
template <>
|
||||
struct hash<CGAL::SM_Face_index >
|
||||
: public std::unary_function<CGAL::SM_Face_index, std::size_t> {
|
||||
|
||||
std::size_t operator()(const CGAL::SM_Face_index& i) const
|
||||
{
|
||||
return i;
|
||||
}
|
||||
};
|
||||
|
||||
template <>
|
||||
struct hash<CGAL::SM_Edge_index >
|
||||
: public std::unary_function<CGAL::SM_Edge_index, std::size_t> {
|
||||
|
||||
std::size_t operator()(const CGAL::SM_Edge_index& i) const
|
||||
{
|
||||
return i;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
namespace boost {
|
||||
template <>
|
||||
struct hash<CGAL::SM_Vertex_index > {
|
||||
std::size_t operator()(const CGAL::SM_Vertex_index& i) const
|
||||
{
|
||||
return i;
|
||||
}
|
||||
};
|
||||
|
||||
#if defined(BOOST_MSVC)
|
||||
# pragma warning(pop)
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
#endif /* CGAL_SURFACE_MESH_H */
|
||||
|
||||
|
|
|
|||
|
|
@ -229,7 +229,10 @@ typedef Tds::difference_type difference_type;
|
|||
/// The vertices and faces of the triangulations are accessed through
|
||||
/// handles, iterators and circulators. The handles are models
|
||||
/// of the concept `Handle` which basically offers the two dereference
|
||||
/// operators and `->`. The iterators and circulators are all
|
||||
/// operators and `->`. The handles are also model of the concepts
|
||||
/// `LessThanComparable` and `Hashable`, that is they can be used as keys
|
||||
/// in containers such as `std::map` and `boost::unordered_map`.
|
||||
/// The iterators and circulators are all
|
||||
/// bidirectional and non-mutable. The circulators and iterators are
|
||||
/// convertible to handles with the same value type, so that whenever
|
||||
/// a handle appear in the parameter list of a function, an
|
||||
|
|
|
|||
|
|
@ -126,7 +126,9 @@ non-mutable. The edges and facets of the triangulation can also be
|
|||
visited through iterators and circulators which are bidirectional and
|
||||
non-mutable. Iterators and circulators are convertible to the
|
||||
corresponding handles, thus the user can pass them directly as
|
||||
arguments to the functions.
|
||||
arguments to the functions. The handles are also model of the concepts
|
||||
`LessThanComparable` and `Hashable`, that is they can be used as keys
|
||||
in containers such as `std::map` and `boost::unordered_map`.
|
||||
*/
|
||||
/// @{
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue