Move TDS2's graph traits into the TDS2 package

This commit is contained in:
Mael Rouxel-Labbé 2021-12-16 13:48:01 +01:00
parent 62a646ecf3
commit 129f427d93
5 changed files with 344 additions and 307 deletions

View File

@ -12,11 +12,9 @@
#ifndef CGAL_GRAPH_TRAITS_TRIANGULATION_DATA_STRUCTURE_2_H
#define CGAL_GRAPH_TRAITS_TRIANGULATION_DATA_STRUCTURE_2_H
#include <functional>
// include this to avoid a VC15 warning
#include <CGAL/boost/graph/Named_function_parameters.h>
#include <CGAL/boost/graph/internal/graph_traits_2D_triangulation_helper.h>
#include <CGAL/boost/graph/internal/graph_traits_2D_TDS_helper.h>
#include <CGAL/boost/graph/properties_Triangulation_data_structure_2.h>
#include <CGAL/Triangulation_data_structure_2.h>
@ -46,14 +44,14 @@ struct graph_traits<CGAL::Triangulation_data_structure_2<VB, FB> >
typedef CGAL::Triangulation_data_structure_2<VB,FB> Triangulation_data_structure;
typedef typename Triangulation_data_structure::Vertex_handle vertex_descriptor;
typedef CGAL::internal::T2_halfedge_descriptor<Triangulation_data_structure> halfedge_descriptor;
typedef CGAL::internal::T2_edge_descriptor<Triangulation_data_structure> edge_descriptor;
typedef CGAL::internal::TDS2_halfedge_descriptor<Triangulation_data_structure> halfedge_descriptor;
typedef CGAL::internal::TDS2_edge_descriptor<Triangulation_data_structure> edge_descriptor;
typedef typename Triangulation_data_structure::Face_handle face_descriptor;
typedef CGAL::Prevent_deref<typename Triangulation_data_structure::Vertex_iterator> vertex_iterator;
typedef CGAL::internal::T2_halfedge_iterator<Triangulation_data_structure,
typedef CGAL::internal::TDS2_halfedge_iterator<Triangulation_data_structure,
typename Triangulation_data_structure::Edge_iterator> halfedge_iterator;
typedef CGAL::internal::T2_edge_iterator<Triangulation_data_structure,
typedef CGAL::internal::TDS2_edge_iterator<Triangulation_data_structure,
typename Triangulation_data_structure::Edge_iterator> edge_iterator;
typedef CGAL::Prevent_deref<typename Triangulation_data_structure::Face_iterator> face_iterator;

View File

@ -0,0 +1,322 @@
// Copyright (c) 2019 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) : Mael Rouxel-Labbé
#include <CGAL/Iterator_range.h>
#include <CGAL/iterator.h>
#include <CGAL/use.h>
#include <boost/config.hpp>
#include <boost/iterator_adaptors.hpp>
#include <boost/graph/graph_traits.hpp>
#include <iterator>
#include <utility>
#ifndef CGAL_GRAPH_TRAITS_2D_TDS_HELPERS
#define CGAL_GRAPH_TRAITS_2D_TDS_HELPERS
namespace CGAL {
namespace internal {
// A triangulation edge is a face handle + an int, and is thus actually a halfedge...
template <class TDS>
struct TDS2_halfedge_descriptor
: public TDS::Edge
{
typedef typename TDS::Edge Base;
typedef typename TDS::Face_handle Face_handle;
TDS2_halfedge_descriptor() {}
TDS2_halfedge_descriptor(Face_handle fh, int i) : Base(fh, i) { }
explicit TDS2_halfedge_descriptor(const Base& e) : Base(e) { }
TDS2_halfedge_descriptor(const TDS2_halfedge_descriptor& h) : Base(h) { }
const Base& base() const { return static_cast<const Base&>(*this); }
TDS2_halfedge_descriptor& operator=(const TDS2_halfedge_descriptor& h)
{
this->first = h.first;
this->second = h.second;
return *this;
}
friend std::size_t hash_value(const TDS2_halfedge_descriptor& e) {
return hash_value(e.first);
}
};
// An edge is just a halfedge, but we give it a complete structure to distinguish it from Tr::Edge
template <typename TDS>
struct TDS2_edge_descriptor
{
typedef typename TDS::Face_handle Face_handle;
TDS2_edge_descriptor() : first(), second(0) { }
explicit TDS2_edge_descriptor(const typename TDS::Edge& e) : first(e.first), second(e.second) { }
TDS2_edge_descriptor(Face_handle fd, int i) : first(fd), second(i) { }
// so that we can still do stuff like tr.is_finite(edge_descriptor) without any hassle
operator std::pair<Face_handle, int>() const { return std::make_pair(first, second); }
friend std::size_t hash_value(const TDS2_edge_descriptor& h)
{
if(h.first == Face_handle())
return 0;
return hash_value(h.first < h.first->neighbor(h.second) ? h.first
: h.first->neighbor(h.second));
}
bool operator==(const TDS2_edge_descriptor& other) const
{
if((first == other.first) && (second == other.second))
return true;
Face_handle fh = first->neighbor(second);
if(other.first != fh)
return false;
int i = fh->index(first);
return (other.second == i);
}
bool operator!=(TDS2_edge_descriptor& other) const { return ! (*this == other); }
void get_canonical_edge_representation(Face_handle& fh, int& i) const
{
Face_handle neigh_fh = fh->neighbor(i);
Face_handle canonical_fh = (fh < neigh_fh) ? fh : neigh_fh;
int canonical_i = (fh < neigh_fh) ? i : neigh_fh->index(fh);
fh = canonical_fh;
i = canonical_i;
}
bool operator<(const TDS2_edge_descriptor& other) const
{
if(*this == other)
return false;
Face_handle tfh = first;
int ti = second;
get_canonical_edge_representation(tfh, ti);
Face_handle ofh = other.first;
int oi = other.second;
get_canonical_edge_representation(ofh, oi);
if(tfh < ofh) return true;
if(tfh > ofh) return false;
return ti < oi;
}
Face_handle first;
int second;
};
// A halfedge iterator is just an edge iterator that duplicates everything twice,
// to see the edge from either side.
// Could probably be factorized with TDS2_edge_iterator, but it's clearer this way.
template <typename TDS, typename EdgeIterator>
struct TDS2_halfedge_iterator
{
private:
typedef TDS2_halfedge_iterator<TDS, EdgeIterator> Self;
typedef EdgeIterator Edge_iterator;
typedef TDS2_halfedge_descriptor<TDS> Descriptor;
typedef typename TDS::Face_handle Face_handle;
public:
typedef Descriptor value_type;
typedef value_type* pointer;
typedef value_type& reference;
typedef std::size_t size_type;
typedef std::ptrdiff_t difference_type;
typedef std::bidirectional_iterator_tag iterator_category;
TDS2_halfedge_iterator() { }
TDS2_halfedge_iterator(const Edge_iterator& feit) : it(feit), on_adjacent_face(false) { }
Self& operator++()
{
// If we are on the first face, move to the opposite face. If we are already on the opposite face,
// then it's time to move on the next edge
if(on_adjacent_face) {
++it;
on_adjacent_face = false;
} else {
on_adjacent_face = true;
}
return *this;
}
Self& operator--()
{
// Note that while decreasing, we start from the opposite face
if(on_adjacent_face) {
on_adjacent_face = false;
} else {
--it;
on_adjacent_face = true;
}
return *this;
}
Self operator++(int) { Self tmp = *this; operator++(); return tmp; }
Self operator--(int) { Self tmp = *this; operator--(); return tmp; }
bool operator==(const Self& other) const { return it == other.it; }
bool operator!=(const Self& other) const { return !(*this == other); }
reference operator*() const
{
if(on_adjacent_face)
{
Face_handle neigh_f = it->first->neighbor(it->second);
hd = Descriptor(neigh_f, neigh_f->index(it->first));
return hd;
} else {
hd = Descriptor(it->first, it->second);
return hd;
}
}
private:
Edge_iterator it;
bool on_adjacent_face;
mutable Descriptor hd;
};
template <typename TDS, typename EdgeIterator>
struct TDS2_edge_iterator
{
private:
typedef TDS2_edge_iterator<TDS, EdgeIterator> Self;
typedef EdgeIterator Edge_iterator;
typedef TDS2_edge_descriptor<TDS> Descriptor;
public:
typedef Descriptor value_type;
typedef value_type* pointer;
typedef value_type& reference;
typedef std::size_t size_type;
typedef std::ptrdiff_t difference_type;
typedef std::bidirectional_iterator_tag iterator_category;
TDS2_edge_iterator() { }
TDS2_edge_iterator(const Edge_iterator& feit) : it(feit) { }
bool operator==(const Self& other) const { return it == other.it; }
bool operator!=(const Self& other) const { return !(*this == other); }
Self& operator++() { ++it; return *this; }
Self& operator--() { --it; return *this; }
Self operator++(int) { Self tmp = *this; operator++(); return tmp; }
Self operator--(int) { Self tmp = *this; operator--(); return tmp; }
reference operator*() const
{
ed = Descriptor(*it);
return ed;
}
private:
Edge_iterator it;
mutable Descriptor ed;
};
// Must distinguish TDS and triangulations circulators (later are filtered)
template <class Circ, class E>
class TDS2_Out_edge_circulator
: public Circ
{
private:
mutable E e;
public:
typedef E value_type;
typedef E* pointer;
typedef E& reference;
TDS2_Out_edge_circulator() : Circ() {}
TDS2_Out_edge_circulator(Circ c) : Circ(c) {}
const E& operator*() const
{
E ed = static_cast<const Circ*>(this)->operator*();
e = E(ed.first->neighbor(ed.second), ed.first->neighbor(ed.second)->index(ed.first));
return e;
}
};
template <class Circ, class E>
class TDS2_In_edge_circulator
: public Circ
{
private:
mutable E e;
public:
typedef E value_type;
typedef E* pointer;
typedef E& reference;
TDS2_In_edge_circulator() : Circ() {}
TDS2_In_edge_circulator(Circ c) : Circ(c) {}
const E& operator*() const
{
typename Circ::value_type ed = static_cast<const Circ*>(this)->operator*();
e = E(ed);
return e;
}
};
} // namespace internal
} // namespace CGAL
namespace std {
// workaround a bug detected on at least g++ 4.4 where boost::next(Iterator)
// is picked as a candidate for next(h,g)
template <typename TDS>
struct iterator_traits< CGAL::internal::TDS2_halfedge_descriptor<TDS> >
{
typedef void* iterator_category;
typedef void* difference_type;
typedef void* value_type;
typedef void* reference;
};
#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 <class TDS>
struct hash<CGAL::internal::TDS2_halfedge_descriptor<TDS> >
{
std::size_t operator()(const CGAL::internal::TDS2_halfedge_descriptor<TDS>& e) const {
return hash_value(e);
}
};
#endif // CGAL_CFG_NO_STD_HASH
#if defined(BOOST_MSVC)
# pragma warning(pop)
#endif
} // namespace std
#endif // CGAL_GRAPH_TRAITS_2D_TDS_HELPERS

View File

@ -12,7 +12,7 @@
#define CGAL_PROPERTIES_TRIANGULATION_DATA_STRUCTURE_2_H
#include <CGAL/Triangulation_data_structure_2.h>
#include <CGAL/boost/graph/internal/graph_traits_2D_triangulation_helper.h>
#include <CGAL/boost/graph/internal/graph_traits_2D_TDS_helper.h>
#include <CGAL/boost/graph/internal/Has_member_id.h>
#include <CGAL/boost/graph/Named_function_parameters.h>
@ -81,7 +81,7 @@ public:
typedef boost::readable_property_map_tag category;
typedef int value_type;
typedef int reference;
typedef CGAL::internal::T2_halfedge_descriptor<TDS> key_type;
typedef CGAL::internal::TDS2_halfedge_descriptor<TDS> key_type;
typedef typename TDS::Face_handle face_descriptor;
@ -112,7 +112,7 @@ public:
typedef boost::readable_property_map_tag category;
typedef int value_type;
typedef int reference;
typedef CGAL::internal::T2_edge_descriptor<TDS> key_type;
typedef CGAL::internal::TDS2_edge_descriptor<TDS> key_type;
typedef typename TDS::Face_handle Face_handle;

View File

@ -8,12 +8,11 @@
//
// Author(s) : Mael Rouxel-Labbé
#include <CGAL/boost/graph/internal/graph_traits_2D_TDS_helper.h>
#include <CGAL/Iterator_range.h>
#include <CGAL/iterator.h>
#include <CGAL/use.h>
#include <boost/config.hpp>
#include <boost/iterator_adaptors.hpp>
#include <boost/graph/graph_traits.hpp>
#include <utility>
@ -24,260 +23,19 @@
namespace CGAL {
namespace internal {
// A triangulation edge is a face handle + an int, and is thus actually a halfedge...
template <class Tr>
struct T2_halfedge_descriptor
: public Tr::Edge
{
typedef typename Tr::Edge Base;
typedef typename Tr::Face_handle Face_handle;
// just for clarity
template <typename T>
using T2_halfedge_descriptor = TDS2_halfedge_descriptor<T>;
T2_halfedge_descriptor() {}
T2_halfedge_descriptor(Face_handle fh, int i) : Base(fh, i) { }
explicit T2_halfedge_descriptor(const Base& e) : Base(e) { }
T2_halfedge_descriptor(const T2_halfedge_descriptor& h) : Base(h) { }
template <typename T, typename EI>
using T2_halfedge_iterator = TDS2_halfedge_iterator<T, EI>;
const Base& base() const { return static_cast<const Base&>(*this); }
template <typename T>
using T2_edge_descriptor = TDS2_edge_descriptor<T>;
T2_halfedge_descriptor& operator=(const T2_halfedge_descriptor& h)
{
this->first = h.first;
this->second = h.second;
return *this;
}
template <typename T, typename EI>
using T2_edge_iterator = TDS2_edge_iterator<T, EI>;
friend std::size_t hash_value(const T2_halfedge_descriptor& e) {
return hash_value(e.first);
}
};
// An edge is just a halfedge, but we give it a complete structure to distinguish it from Tr::Edge
template <typename Tr>
struct T2_edge_descriptor
{
typedef typename Tr::Face_handle Face_handle;
T2_edge_descriptor() : first(), second(0) { }
explicit T2_edge_descriptor(const typename Tr::Edge& e) : first(e.first), second(e.second) { }
T2_edge_descriptor(Face_handle fd, int i) : first(fd), second(i) { }
// so that we can still do stuff like tr.is_finite(edge_descriptor) without any hassle
operator std::pair<Face_handle, int>() const { return std::make_pair(first, second); }
friend std::size_t hash_value(const T2_edge_descriptor& h)
{
if(h.first == Face_handle())
return 0;
return hash_value(h.first < h.first->neighbor(h.second) ? h.first
: h.first->neighbor(h.second));
}
bool operator==(const T2_edge_descriptor& other) const
{
if((first == other.first) && (second == other.second))
return true;
Face_handle fh = first->neighbor(second);
if(other.first != fh)
return false;
int i = fh->index(first);
return (other.second == i);
}
bool operator!=(T2_edge_descriptor& other) const { return ! (*this == other); }
void get_canonical_edge_representation(Face_handle& fh, int& i) const
{
Face_handle neigh_fh = fh->neighbor(i);
Face_handle canonical_fh = (fh < neigh_fh) ? fh : neigh_fh;
int canonical_i = (fh < neigh_fh) ? i : neigh_fh->index(fh);
fh = canonical_fh;
i = canonical_i;
}
bool operator<(const T2_edge_descriptor& other) const
{
if(*this == other)
return false;
Face_handle tfh = first;
int ti = second;
get_canonical_edge_representation(tfh, ti);
Face_handle ofh = other.first;
int oi = other.second;
get_canonical_edge_representation(ofh, oi);
if(tfh < ofh) return true;
if(tfh > ofh) return false;
return ti < oi;
}
Face_handle first;
int second;
};
// A halfedge iterator is just an edge iterator that duplicates everything twice,
// to see the edge from either side.
// Could probably be factorized with T2_edge_iterator, but it's clearer this way.
template <typename Tr, typename EdgeIterator>
struct T2_halfedge_iterator
{
private:
typedef T2_halfedge_iterator<Tr, EdgeIterator> Self;
typedef EdgeIterator Edge_iterator;
typedef T2_halfedge_descriptor<Tr> Descriptor;
typedef typename Tr::Face_handle Face_handle;
public:
typedef Descriptor value_type;
typedef value_type* pointer;
typedef value_type& reference;
typedef std::size_t size_type;
typedef std::ptrdiff_t difference_type;
typedef std::bidirectional_iterator_tag iterator_category;
T2_halfedge_iterator() { }
T2_halfedge_iterator(const Edge_iterator& feit) : it(feit), on_adjacent_face(false) { }
Self& operator++()
{
// If we are on the first face, move to the opposite face. If we are already on the opposite face,
// then it's time to move on the next edge
if(on_adjacent_face) {
++it;
on_adjacent_face = false;
} else {
on_adjacent_face = true;
}
return *this;
}
Self& operator--()
{
// Note that while decreasing, we start from the opposite face
if(on_adjacent_face) {
on_adjacent_face = false;
} else {
--it;
on_adjacent_face = true;
}
return *this;
}
Self operator++(int) { Self tmp = *this; operator++(); return tmp; }
Self operator--(int) { Self tmp = *this; operator--(); return tmp; }
bool operator==(const Self& other) const { return it == other.it; }
bool operator!=(const Self& other) const { return !(*this == other); }
reference operator*() const
{
if(on_adjacent_face)
{
Face_handle neigh_f = it->first->neighbor(it->second);
hd = Descriptor(neigh_f, neigh_f->index(it->first));
return hd;
} else {
hd = Descriptor(it->first, it->second);
return hd;
}
}
private:
Edge_iterator it;
bool on_adjacent_face;
mutable Descriptor hd;
};
template <typename Tr, typename EdgeIterator>
struct T2_edge_iterator
{
private:
typedef T2_edge_iterator<Tr, EdgeIterator> Self;
typedef EdgeIterator Edge_iterator;
typedef T2_edge_descriptor<Tr> Descriptor;
public:
typedef Descriptor value_type;
typedef value_type* pointer;
typedef value_type& reference;
typedef std::size_t size_type;
typedef std::ptrdiff_t difference_type;
typedef std::bidirectional_iterator_tag iterator_category;
T2_edge_iterator() { }
T2_edge_iterator(const Edge_iterator& feit) : it(feit) { }
bool operator==(const Self& other) const { return it == other.it; }
bool operator!=(const Self& other) const { return !(*this == other); }
Self& operator++() { ++it; return *this; }
Self& operator--() { --it; return *this; }
Self operator++(int) { Self tmp = *this; operator++(); return tmp; }
Self operator--(int) { Self tmp = *this; operator--(); return tmp; }
reference operator*() const
{
ed = Descriptor(*it);
return ed;
}
private:
Edge_iterator it;
mutable Descriptor ed;
};
// Must distinguish TDS and triangulations circulators (later are filtered)
template <class Circ, class E>
class TDS2_Out_edge_circulator
: public Circ
{
private:
mutable E e;
public:
typedef E value_type;
typedef E* pointer;
typedef E& reference;
TDS2_Out_edge_circulator() : Circ() {}
TDS2_Out_edge_circulator(Circ c) : Circ(c) {}
const E& operator*() const
{
E ed = static_cast<const Circ*>(this)->operator*();
e = E(ed.first->neighbor(ed.second), ed.first->neighbor(ed.second)->index(ed.first));
return e;
}
};
template <class Circ, class E>
class TDS2_In_edge_circulator
: public Circ
{
private:
mutable E e;
public:
typedef E value_type;
typedef E* pointer;
typedef E& reference;
TDS2_In_edge_circulator() : Circ() {}
TDS2_In_edge_circulator(Circ c) : Circ(c) {}
const E& operator*() const
{
typename Circ::value_type ed = static_cast<const Circ*>(this)->operator*();
e = E(ed);
return e;
}
};
template <typename Tr>
struct T2_edge_circulator
@ -422,40 +180,4 @@ private:
} // namespace internal
} // namespace CGAL
namespace std {
// workaround a bug detected on at least g++ 4.4 where boost::next(Iterator)
// is picked as a candidate for next(h,g)
template <typename Tr>
struct iterator_traits< CGAL::internal::T2_halfedge_descriptor<Tr> >
{
typedef void* iterator_category;
typedef void* difference_type;
typedef void* value_type;
typedef void* reference;
};
#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 < class Tr>
struct hash<CGAL::internal::T2_halfedge_descriptor<Tr> >
{
std::size_t operator()(const CGAL::internal::T2_halfedge_descriptor<Tr>& e) const {
return hash_value(e);
}
};
#endif // CGAL_CFG_NO_STD_HASH
#if defined(BOOST_MSVC)
# pragma warning(pop)
#endif
} // namespace std
#endif // CGAL_GRAPH_TRAITS_2D_TRIANGULATION_HELPERS

View File

@ -9,6 +9,7 @@
// Author(s) : Mael Rouxel-Labbé
#include <CGAL/assertions.h>
#include <CGAL/boost/graph/internal/graph_traits_2D_triangulation_helper.h>
#include <CGAL/boost/graph/internal/Has_member_id.h>
#include <CGAL/boost/graph/properties.h>
@ -20,7 +21,7 @@
#error CGAL_2D_TRIANGULATION is not defined
#endif
// note only the properties below are protected by the macro,
// note that only the properties below are protected by the macro,
// the rest of the file is the shared implementation of properties for all 2D triangulations
#ifndef CGAL_BOOST_GRAPH_PROPERTIES_2D_TRIANGULATION_H
#define CGAL_BOOST_GRAPH_PROPERTIES_2D_TRIANGULATION_H
@ -28,12 +29,6 @@
namespace CGAL {
namespace internal {
template <class Tr>
struct T2_halfedge_descriptor;
template <class Tr>
struct T2_edge_descriptor;
template <typename Tr>
class T2_vertex_point_map
{