cgal/HalfedgeDS/include/CGAL/boost/graph/graph_traits_HalfedgeDS.h

232 lines
7.2 KiB
C++

// Copyright (c) 2007 GeometryFactory (France). All rights reserved.
//
// This file is part of CGAL (www.cgal.org)
//
// $URL$
// $Id$
// SPDX-License-Identifier: LGPL-3.0-or-later OR LicenseRef-Commercial
//
//
// Author(s) : Andreas Fabri, Fernando Cacciola
#ifndef CGAL_BOOST_GRAPH_GRAPH_TRAITS_HALFEDGEDS_H
#define CGAL_BOOST_GRAPH_GRAPH_TRAITS_HALFEDGEDS_H
#include <functional>
// include this to avoid a VC15 warning
#include <CGAL/Named_function_parameters.h>
#include <boost/config.hpp>
#include <boost/iterator/iterator_adaptor.hpp>
#include <CGAL/boost/iterator/transform_iterator.hpp>
#include <boost/graph/graph_traits.hpp>
#include <boost/graph/properties.hpp>
#include <CGAL/basic.h>
#include <CGAL/boost/graph/iterator.h>
#include <CGAL/Handle_hash_function.h>
#include <CGAL/iterator.h>
#ifndef CGAL_NO_DEPRECATED_CODE
#include <CGAL/boost/graph/halfedge_graph_traits.h>
#endif
namespace CGAL {
namespace internal {
// a HDS_halfedge pretending to be an Edge
template<typename Halfedge_handle>
struct HDS_edge {
HDS_edge() : halfedge_() { }
explicit HDS_edge(const Halfedge_handle& h) : halfedge_(h) {}
bool operator==(const HDS_edge& other) const {
// equality is tricky, we are equal when both halfedges are the
// same or when the opposite halfedge of this is the same as
// halfedge_.other but we need to be careful not to apply this
// should this be the invalid halfedge or opposite is going to
// blow up
if(halfedge_ == other.halfedge_) {
return true;
} else if(halfedge_ != Halfedge_handle()) { // not default constructed
return halfedge_->opposite() == other.halfedge_;
} else {
// this is the invalid halfedge, it can only be equal to the
// invalid halfedge and this is covered by the first case
return false;
}
}
bool operator!=(const HDS_edge& other) const {
return !(*this == other);
}
friend bool operator<(const HDS_edge& a,const HDS_edge& b)
{
if(a==b) return false;
return a.halfedge_ < b.halfedge_;
}
// forward some function to avoid boilerplate and typedefs inside
// the free functions
HDS_edge next() { return HDS_edge(halfedge_->next()); }
// this is potentially broken as it does not use the decorator to
// find prev, but we cannot instantiate the entire decorator
// without the full polyhedron type and taking all necessary
// template parameters seems overkill
HDS_edge prev() { return HDS_edge(halfedge_->prev()); }
HDS_edge opposite() { return HDS_edge(halfedge_->opposite()); }
// this is hacky, we don't know the actual type of the id and if we
// start adding decltype special cases we have to do it consistently
// up to the property map and maybe back down to Polyhedron.
std::size_t id() const { return halfedge_->id() / 2; }
Halfedge_handle halfedge() const { return halfedge_; }
// save us some work to do function chaining
HDS_edge
opposite_next() { return HDS_edge(halfedge_->opposite()->next()); }
HDS_edge
next_opposite() { return HDS_edge(halfedge_->next()->opposite()); }
HDS_edge
prev_opposite() { return HDS_edge(halfedge_->prev()->opposite()); }
HDS_edge
opposite_prev() { return HDS_edge(halfedge_->opposite()->prev()); }
friend std::size_t hash_value(const HDS_edge& i)
{
if (i.halfedge()==Halfedge_handle()) return 0;
return hash_value(i.halfedge()<i.halfedge()->opposite()?
i.halfedge():i.halfedge()->opposite());
}
private:
Halfedge_handle halfedge_;
};
// make edge_descriptor hashable by default in Unique_hash_map
namespace handle{
template<typename Halfedge_handle>
struct Hash_functor< HDS_edge<Halfedge_handle> >
{
std::size_t
operator()(const HDS_edge<Halfedge_handle>& edge)
{
Halfedge_handle he = edge.halfedge();
if (he==Halfedge_handle()) return 0;
if ( he < he->opposite() )
return Hash_functor<Halfedge_handle>()(he);
return Hash_functor<Halfedge_handle>()(he->opposite());
}
};
} //end of namespace handle
template<typename Halfedge_handle>
struct Construct_edge {
typedef HDS_edge<Halfedge_handle> result_type;
HDS_edge<Halfedge_handle> operator()(const Halfedge_handle& he) const
{ return HDS_edge<Halfedge_handle>(he); }
};
template<typename Halfedge_handle>
struct Construct_edge_opposite {
typedef HDS_edge<Halfedge_handle> result_type;
HDS_edge<Halfedge_handle> operator()(const Halfedge_handle& he) const
{ return HDS_edge<Halfedge_handle>(he->opposite()); }
};
} // internal
template <class HDS>
struct HDS_graph_traits
{
private:
struct HDS_graph_traversal_category : public virtual boost::bidirectional_graph_tag,
public virtual boost::vertex_list_graph_tag,
public virtual boost::edge_list_graph_tag,
public virtual boost::adjacency_graph_tag
{};
public:
typedef typename HDS::Vertex_handle vertex_descriptor;
typedef typename internal::HDS_edge<typename HDS::Halfedge_handle> edge_descriptor;
typedef typename HDS::Face_handle face_descriptor;
typedef typename HDS::Halfedge_handle halfedge_descriptor;
typedef CGAL::Prevent_deref<typename HDS::Vertex_iterator> vertex_iterator;
typedef CGAL::Prevent_deref<typename HDS::Face_iterator> face_iterator;
typedef CGAL::Prevent_deref<typename HDS::Edge_iterator> edge_iterator_i;
typedef CGAL::Prevent_deref<typename HDS::Halfedge_iterator> halfedge_iterator;
typedef boost::transform_iterator<
internal::Construct_edge<typename HDS::Halfedge_handle>,
edge_iterator_i,
edge_descriptor> edge_iterator;
typedef Out_edge_iterator<HDS> out_edge_iterator;
typedef In_edge_iterator<HDS> in_edge_iterator;
typedef Vertex_around_target_iterator<HDS> adjacency_iterator;
typedef boost::undirected_tag directed_category;
typedef boost::disallow_parallel_edge_tag edge_parallel_category;
typedef HDS_graph_traversal_category traversal_category;
typedef typename HDS::size_type vertices_size_type;
typedef vertices_size_type edges_size_type;
typedef vertices_size_type halfedges_size_type;
typedef vertices_size_type degree_size_type;
typedef vertices_size_type faces_size_type;
static vertex_descriptor null_vertex() { return vertex_descriptor(); }
static halfedge_descriptor null_halfedge() { return halfedge_descriptor(); }
static face_descriptor null_face() { return face_descriptor(); }
};
} //namespace CGAL
namespace std {
#if defined(BOOST_MSVC)
# pragma warning(push)
# pragma warning(disable:4099) // For VC10 it is class hash
#endif
#ifndef CGAL_CFG_NO_STD_HASH
template <typename H>
struct hash<CGAL::internal::HDS_edge<H> > {
std::size_t operator()(const CGAL::internal::HDS_edge<H>& e) const
{
std::hash<H> fct;
if (e.halfedge()==H()) return 0;
return fct(e.halfedge()<e.halfedge()->opposite()?
e.halfedge():e.halfedge()->opposite());
}
};
#endif // CGAL_CFG_NO_STD_HASH
#if defined(BOOST_MSVC)
# pragma warning(pop)
#endif
} // namespace std
#endif // CGAL_BOOST_GRAPH_GRAPH_TRAITS_HALFEDGEDS_H