2024-12-26 11:36:13 +02:00

462 lines
9.0 KiB
C++

//
// Copyright (C) 2004 Tanguy Fautré.
// For conditions of distribution and use,
// see copyright notice in tri_stripper.h
//
//////////////////////////////////////////////////////////////////////
#ifndef TRI_STRIPPER_HEADER_GUARD_GRAPH_ARRAY_H
#define TRI_STRIPPER_HEADER_GUARD_GRAPH_ARRAY_H
#include <cassert>
#include <algorithm>
#include <functional>
#include <limits>
#include <vector>
namespace triangle_stripper {
namespace detail {
// graph_array main class
template <class nodetype>
class graph_array
{
public:
class arc;
class node;
// New types
typedef size_t nodeid;
typedef nodetype value_type;
typedef std::vector<node> node_vector;
typedef typename node_vector::iterator node_iterator;
typedef typename node_vector::const_iterator const_node_iterator;
typedef typename node_vector::reverse_iterator node_reverse_iterator;
typedef typename node_vector::const_reverse_iterator const_node_reverse_iterator;
typedef graph_array<nodetype> graph_type;
// graph_array::arc class
class arc
{
public:
node_iterator terminal() const;
protected:
friend class graph_array<nodetype>;
arc(node_iterator Terminal);
node_iterator m_Terminal;
};
// New types
typedef std::vector<arc> arc_list;
typedef typename arc_list::iterator out_arc_iterator;
typedef typename arc_list::const_iterator const_out_arc_iterator;
// graph_array::node class
class node
{
public:
void mark();
void unmark();
bool marked() const;
bool out_empty() const;
size_t out_size() const;
out_arc_iterator out_begin();
out_arc_iterator out_end();
const_out_arc_iterator out_begin() const;
const_out_arc_iterator out_end() const;
value_type & operator * ();
value_type * operator -> ();
const value_type & operator * () const;
const value_type * operator -> () const;
value_type & operator = (const value_type & Elem);
protected:
friend class graph_array<nodetype>;
friend class std::vector<node>;
node(arc_list & Arcs);
arc_list & m_Arcs;
size_t m_Begin;
size_t m_End;
value_type m_Elem;
bool m_Marker;
};
graph_array();
explicit graph_array(size_t NbNodes);
// Node related member functions
bool empty() const;
size_t size() const;
node & operator [] (nodeid i);
const node & operator [] (nodeid i) const;
node_iterator begin();
node_iterator end();
const_node_iterator begin() const;
const_node_iterator end() const;
node_reverse_iterator rbegin();
node_reverse_iterator rend();
const_node_reverse_iterator rbegin() const;
const_node_reverse_iterator rend() const;
// Arc related member functions
out_arc_iterator insert_arc(nodeid Initial, nodeid Terminal);
out_arc_iterator insert_arc(node_iterator Initial, node_iterator Terminal);
// Optimized (overloaded) functions
void swap(graph_type & Right);
friend void swap(graph_type & Left, graph_type & Right) { Left.swap(Right); }
protected:
graph_array(const graph_type &);
graph_type & operator = (const graph_type &);
node_vector m_Nodes;
arc_list m_Arcs;
};
// Additional "low level", graph related, functions
template <class nodetype>
void unmark_nodes(graph_array<nodetype> & G);
//////////////////////////////////////////////////////////////////////////
// graph_array::arc inline functions
//////////////////////////////////////////////////////////////////////////
template <class N>
inline graph_array<N>::arc::arc(node_iterator Terminal)
: m_Terminal(Terminal) { }
template <class N>
inline typename graph_array<N>::node_iterator graph_array<N>::arc::terminal() const
{
return m_Terminal;
}
//////////////////////////////////////////////////////////////////////////
// graph_array::node inline functions
//////////////////////////////////////////////////////////////////////////
template <class N>
inline graph_array<N>::node::node(arc_list & Arcs)
: m_Arcs(Arcs),
m_Begin(std::numeric_limits<size_t>::max()),
m_End(std::numeric_limits<size_t>::max()),
m_Marker(false)
{
}
template <class N>
inline void graph_array<N>::node::mark()
{
m_Marker = true;
}
template <class N>
inline void graph_array<N>::node::unmark()
{
m_Marker = false;
}
template <class N>
inline bool graph_array<N>::node::marked() const
{
return m_Marker;
}
template <class N>
inline bool graph_array<N>::node::out_empty() const
{
return (m_Begin == m_End);
}
template <class N>
inline size_t graph_array<N>::node::out_size() const
{
return (m_End - m_Begin);
}
template <class N>
inline typename graph_array<N>::out_arc_iterator graph_array<N>::node::out_begin()
{
return (m_Arcs.begin() + m_Begin);
}
template <class N>
inline typename graph_array<N>::out_arc_iterator graph_array<N>::node::out_end()
{
return (m_Arcs.begin() + m_End);
}
template <class N>
inline typename graph_array<N>::const_out_arc_iterator graph_array<N>::node::out_begin() const
{
return (m_Arcs.begin() + m_Begin);
}
template <class N>
inline typename graph_array<N>::const_out_arc_iterator graph_array<N>::node::out_end() const
{
return (m_Arcs.begin() + m_End);
}
template <class N>
inline N & graph_array<N>::node::operator * ()
{
return m_Elem;
}
template <class N>
inline N * graph_array<N>::node::operator -> ()
{
return &m_Elem;
}
template <class N>
inline const N & graph_array<N>::node::operator * () const
{
return m_Elem;
}
template <class N>
inline const N * graph_array<N>::node::operator -> () const
{
return &m_Elem;
}
template <class N>
inline N & graph_array<N>::node::operator = (const N & Elem)
{
return (m_Elem = Elem);
}
//////////////////////////////////////////////////////////////////////////
// graph_array inline functions
//////////////////////////////////////////////////////////////////////////
template <class N>
inline graph_array<N>::graph_array() { }
template <class N>
inline graph_array<N>::graph_array(const size_t NbNodes)
: m_Nodes(NbNodes, node(m_Arcs))
{
// optimisation: we consider that, averagely, a triangle may have at least 2 neighbours
// otherwise we are just wasting a bit of memory, but not that much
m_Arcs.reserve(NbNodes * 2);
}
template <class N>
inline bool graph_array<N>::empty() const
{
return m_Nodes.empty();
}
template <class N>
inline size_t graph_array<N>::size() const
{
return m_Nodes.size();
}
template <class N>
inline typename graph_array<N>::node & graph_array<N>::operator [] (const nodeid i)
{
assert(i < size());
return m_Nodes[i];
}
template <class N>
inline const typename graph_array<N>::node & graph_array<N>::operator [] (const nodeid i) const
{
assert(i < size());
return m_Nodes[i];
}
template <class N>
inline typename graph_array<N>::node_iterator graph_array<N>::begin()
{
return m_Nodes.begin();
}
template <class N>
inline typename graph_array<N>::node_iterator graph_array<N>::end()
{
return m_Nodes.end();
}
template <class N>
inline typename graph_array<N>::const_node_iterator graph_array<N>::begin() const
{
return m_Nodes.begin();
}
template <class N>
inline typename graph_array<N>::const_node_iterator graph_array<N>::end() const
{
return m_Nodes.end();
}
template <class N>
inline typename graph_array<N>::node_reverse_iterator graph_array<N>::rbegin()
{
return m_Nodes.rbegin();
}
template <class N>
inline typename graph_array<N>::node_reverse_iterator graph_array<N>::rend()
{
return m_Nodes.rend();
}
template <class N>
inline typename graph_array<N>::const_node_reverse_iterator graph_array<N>::rbegin() const
{
return m_Nodes.rbegin();
}
template <class N>
inline typename graph_array<N>::const_node_reverse_iterator graph_array<N>::rend() const
{
return m_Nodes.rend();
}
template <class N>
inline typename graph_array<N>::out_arc_iterator graph_array<N>::insert_arc(const nodeid Initial, const nodeid Terminal)
{
assert(Initial < size());
assert(Terminal < size());
return insert_arc(m_Nodes.begin() + Initial, m_Nodes.begin() + Terminal);
}
template <class N>
inline typename graph_array<N>::out_arc_iterator graph_array<N>::insert_arc(const node_iterator Initial, const node_iterator Terminal)
{
assert((Initial >= begin()) && (Initial < end()));
assert((Terminal >= begin()) && (Terminal < end()));
node & Node = * Initial;
if (Node.out_empty()) {
Node.m_Begin = m_Arcs.size();
Node.m_End = m_Arcs.size() + 1;
} else {
// we optimise here for make_connectivity_graph()
// we know all the arcs for a given node are successively and sequentially added
assert(Node.m_End == m_Arcs.size());
++(Node.m_End);
}
m_Arcs.push_back(arc(Terminal));
out_arc_iterator it = m_Arcs.end();
return (--it);
}
template <class N>
inline void graph_array<N>::swap(graph_type & Right)
{
std::swap(m_Nodes, Right.m_Nodes);
std::swap(m_Arcs, Right.m_Arcs);
}
//////////////////////////////////////////////////////////////////////////
// additional functions
//////////////////////////////////////////////////////////////////////////
template <class N>
inline void unmark_nodes(graph_array<N> & G)
{
for (auto& node : G)
{
node.unmark();
}
}
} // namespace detail
} // namespace triangle_stripper
#endif // TRI_STRIPPER_HEADER_GUARD_GRAPH_ARRAY_H