File: graph_traits_HalfedgeDS.h

package info (click to toggle)
cgal 5.2-3
  • links: PTS, VCS
  • area: main
  • in suites: bullseye
  • size: 121,084 kB
  • sloc: cpp: 742,056; ansic: 182,102; sh: 647; python: 411; makefile: 280; javascript: 110
file content (229 lines) | stat: -rw-r--r-- 7,425 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
// Copyright (c) 2007  GeometryFactory (France).  All rights reserved.
//
// This file is part of CGAL (www.cgal.org)
//
// $URL: https://github.com/CGAL/cgal/blob/v5.2/HalfedgeDS/include/CGAL/boost/graph/graph_traits_HalfedgeDS.h $
// $Id: graph_traits_HalfedgeDS.h 0779373 2020-03-26T13:31:46+01:00 Sébastien Loriot
// 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/boost/graph/Named_function_parameters.h>

#include <boost/config.hpp>
#include <boost/iterator/iterator_adaptor.hpp>
#include <CGAL/boost/iterator/transform_iterator.hpp>
#include <boost/type_traits/remove_const.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:
  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 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