libcarla/include/system/boost/graph/detail/self_avoiding_walk.hpp

484 lines
16 KiB
C++
Raw Normal View History

2024-10-18 13:19:59 +08:00
//=======================================================================
// Copyright 1997, 1998, 1999, 2000 University of Notre Dame.
// Authors: Andrew Lumsdaine, Lie-Quan Lee, Jeremy G. Siek
//
// Distributed under the Boost Software License, Version 1.0. (See
// accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
//=======================================================================
#ifndef BOOST_SELF_AVOIDING_WALK_HPP
#define BOOST_SELF_AVOIDING_WALK_HPP
/*
This file defines necessary components for SAW.
mesh language: (defined by myself to clearify what is what)
A triangle in mesh is called an triangle.
An edge in mesh is called an line.
A vertex in mesh is called a point.
A triangular mesh corresponds to a graph in which a vertex is a
triangle and an edge(u, v) stands for triangle u and triangle v
share an line.
After this point, a vertex always refers to vertex in graph,
therefore it is a traingle in mesh.
*/
#include <utility>
#include <boost/config.hpp>
#include <boost/graph/graph_traits.hpp>
#include <boost/property_map/property_map.hpp>
#define SAW_SENTINAL -1
namespace boost
{
template < class T1, class T2, class T3 > struct triple
{
T1 first;
T2 second;
T3 third;
triple(const T1& a, const T2& b, const T3& c)
: first(a), second(b), third(c)
{
}
triple() : first(SAW_SENTINAL), second(SAW_SENTINAL), third(SAW_SENTINAL) {}
};
typedef triple< int, int, int > Triple;
/* Define a vertex property which has a triangle inside. Triangle is
represented by a triple. */
struct triangle_tag
{
enum
{
num = 100
};
};
typedef property< triangle_tag, Triple > triangle_property;
/* Define an edge property with a line. A line is represented by a
pair. This is not required for SAW though.
*/
struct line_tag
{
enum
{
num = 101
};
};
template < class T >
struct line_property : public property< line_tag, std::pair< T, T > >
{
};
/*Precondition: Points in a Triangle are in order */
template < class Triangle, class Line >
inline void get_sharing(const Triangle& a, const Triangle& b, Line& l)
{
l.first = SAW_SENTINAL;
l.second = SAW_SENTINAL;
if (a.first == b.first)
{
l.first = a.first;
if (a.second == b.second || a.second == b.third)
l.second = a.second;
else if (a.third == b.second || a.third == b.third)
l.second = a.third;
}
else if (a.first == b.second)
{
l.first = a.first;
if (a.second == b.third)
l.second = a.second;
else if (a.third == b.third)
l.second = a.third;
}
else if (a.first == b.third)
{
l.first = a.first;
}
else if (a.second == b.first)
{
l.first = a.second;
if (a.third == b.second || a.third == b.third)
l.second = a.third;
}
else if (a.second == b.second)
{
l.first = a.second;
if (a.third == b.third)
l.second = a.third;
}
else if (a.second == b.third)
{
l.first = a.second;
}
else if (a.third == b.first || a.third == b.second || a.third == b.third)
l.first = a.third;
/*Make it in order*/
if (l.first > l.second)
{
typename Line::first_type i = l.first;
l.first = l.second;
l.second = i;
}
}
template < class TriangleDecorator, class Vertex, class Line >
struct get_vertex_sharing
{
typedef std::pair< Vertex, Line > Pair;
get_vertex_sharing(const TriangleDecorator& _td) : td(_td) {}
inline Line operator()(const Vertex& u, const Vertex& v) const
{
Line l;
get_sharing(td[u], td[v], l);
return l;
}
inline Line operator()(const Pair& u, const Vertex& v) const
{
Line l;
get_sharing(td[u.first], td[v], l);
return l;
}
inline Line operator()(const Pair& u, const Pair& v) const
{
Line l;
get_sharing(td[u.first], td[v.first], l);
return l;
}
TriangleDecorator td;
};
/* HList has to be a handle of data holder so that pass-by-value is
* in right logic.
*
* The element of HList is a pair of vertex and line. (remember a
* line is a pair of two ints.). That indicates the walk w from
* current vertex is across line. (If the first of line is -1, it is
* a point though.
*/
template < class TriangleDecorator, class HList, class IteratorD >
class SAW_visitor : public bfs_visitor<>, public dfs_visitor<>
{
typedef typename boost::property_traits< IteratorD >::value_type iter;
/*use boost shared_ptr*/
typedef typename HList::element_type::value_type::second_type Line;
public:
typedef tree_edge_tag category;
inline SAW_visitor(TriangleDecorator _td, HList _hlist, IteratorD ia)
: td(_td), hlist(_hlist), iter_d(ia)
{
}
template < class Vertex, class Graph >
inline void start_vertex(Vertex v, Graph&)
{
Line l1;
l1.first = SAW_SENTINAL;
l1.second = SAW_SENTINAL;
hlist->push_front(std::make_pair(v, l1));
iter_d[v] = hlist->begin();
}
/*Several symbols:
w(i): i-th triangle in walk w
w(i) |- w(i+1): w enter w(i+1) from w(i) over a line
w(i) ~> w(i+1): w enter w(i+1) from w(i) over a point
w(i) -> w(i+1): w enter w(i+1) from w(i)
w(i) ^ w(i+1): the line or point w go over from w(i) to w(i+1)
*/
template < class Edge, class Graph > bool tree_edge(Edge e, Graph& G)
{
using std::make_pair;
typedef typename boost::graph_traits< Graph >::vertex_descriptor Vertex;
Vertex tau = target(e, G);
Vertex i = source(e, G);
get_vertex_sharing< TriangleDecorator, Vertex, Line > get_sharing_line(
td);
Line tau_i = get_sharing_line(tau, i);
iter w_end = hlist->end();
iter w_i = iter_d[i];
iter w_i_m_1 = w_i;
iter w_i_p_1 = w_i;
/*----------------------------------------------------------
* true false
*==========================================================
*a w(i-1) |- w(i) w(i-1) ~> w(i) or w(i-1) is null
*----------------------------------------------------------
*b w(i) |- w(i+1) w(i) ~> w(i+1) or no w(i+1) yet
*----------------------------------------------------------
*/
bool a = false, b = false;
--w_i_m_1;
++w_i_p_1;
b = (w_i->second.first != SAW_SENTINAL);
if (w_i_m_1 != w_end)
{
a = (w_i_m_1->second.first != SAW_SENTINAL);
}
if (a)
{
if (b)
{
/*Case 1:
w(i-1) |- w(i) |- w(i+1)
*/
Line l1 = get_sharing_line(*w_i_m_1, tau);
iter w_i_m_2 = w_i_m_1;
--w_i_m_2;
bool c = true;
if (w_i_m_2 != w_end)
{
c = w_i_m_2->second != l1;
}
if (c)
{ /* w(i-1) ^ tau != w(i-2) ^ w(i-1) */
/*extension: w(i-1) -> tau |- w(i) */
w_i_m_1->second = l1;
/*insert(pos, const T&) is to insert before pos*/
iter_d[tau] = hlist->insert(w_i, make_pair(tau, tau_i));
}
else
{ /* w(i-1) ^ tau == w(i-2) ^ w(i-1) */
/*must be w(i-2) ~> w(i-1) */
bool d = true;
// need to handle the case when w_i_p_1 is null
Line l3 = get_sharing_line(*w_i_p_1, tau);
if (w_i_p_1 != w_end)
d = w_i_p_1->second != l3;
if (d)
{ /* w(i+1) ^ tau != w(i+1) ^ w(i+2) */
/*extension: w(i) |- tau -> w(i+1) */
w_i->second = tau_i;
iter_d[tau]
= hlist->insert(w_i_p_1, make_pair(tau, l3));
}
else
{ /* w(i+1) ^ tau == w(i+1) ^ w(i+2) */
/*must be w(1+1) ~> w(i+2) */
Line l5 = get_sharing_line(*w_i_m_1, *w_i_p_1);
if (l5 != w_i_p_1->second)
{ /* w(i-1) ^ w(i+1) != w(i+1) ^ w(i+2) */
/*extension: w(i-2) -> tau |- w(i) |- w(i-1) ->
* w(i+1) */
w_i_m_2->second = get_sharing_line(*w_i_m_2, tau);
iter_d[tau]
= hlist->insert(w_i, make_pair(tau, tau_i));
w_i->second = w_i_m_1->second;
w_i_m_1->second = l5;
iter_d[w_i_m_1->first]
= hlist->insert(w_i_p_1, *w_i_m_1);
hlist->erase(w_i_m_1);
}
else
{
/*mesh is tetrahedral*/
// dont know what that means.
;
}
}
}
}
else
{
/*Case 2:
w(i-1) |- w(i) ~> w(1+1)
*/
if (w_i->second.second == tau_i.first
|| w_i->second.second == tau_i.second)
{ /*w(i) ^ w(i+1) < w(i) ^ tau*/
/*extension: w(i) |- tau -> w(i+1) */
w_i->second = tau_i;
Line l1 = get_sharing_line(*w_i_p_1, tau);
iter_d[tau] = hlist->insert(w_i_p_1, make_pair(tau, l1));
}
else
{ /*w(i) ^ w(i+1) !< w(i) ^ tau*/
Line l1 = get_sharing_line(*w_i_m_1, tau);
bool c = true;
iter w_i_m_2 = w_i_m_1;
--w_i_m_2;
if (w_i_m_2 != w_end)
c = l1 != w_i_m_2->second;
if (c)
{ /*w(i-1) ^ tau != w(i-2) ^ w(i-1)*/
/*extension: w(i-1) -> tau |- w(i)*/
w_i_m_1->second = l1;
iter_d[tau] = hlist->insert(w_i, make_pair(tau, tau_i));
}
else
{ /*w(i-1) ^ tau == w(i-2) ^ w(i-1)*/
/*must be w(i-2)~>w(i-1)*/
/*extension: w(i-2) -> tau |- w(i) |- w(i-1) -> w(i+1)*/
w_i_m_2->second = get_sharing_line(*w_i_m_2, tau);
iter_d[tau] = hlist->insert(w_i, make_pair(tau, tau_i));
w_i->second = w_i_m_1->second;
w_i_m_1->second = get_sharing_line(*w_i_m_1, *w_i_p_1);
iter_d[w_i_m_1->first]
= hlist->insert(w_i_p_1, *w_i_m_1);
hlist->erase(w_i_m_1);
}
}
}
}
else
{
if (b)
{
/*Case 3:
w(i-1) ~> w(i) |- w(i+1)
*/
bool c = false;
if (w_i_m_1 != w_end)
c = (w_i_m_1->second.second == tau_i.first)
|| (w_i_m_1->second.second == tau_i.second);
if (c)
{ /*w(i-1) ^ w(i) < w(i) ^ tau*/
/* extension: w(i-1) -> tau |- w(i) */
if (w_i_m_1 != w_end)
w_i_m_1->second = get_sharing_line(*w_i_m_1, tau);
iter_d[tau] = hlist->insert(w_i, make_pair(tau, tau_i));
}
else
{
bool d = true;
Line l1;
l1.first = SAW_SENTINAL;
l1.second = SAW_SENTINAL;
if (w_i_p_1 != w_end)
{
l1 = get_sharing_line(*w_i_p_1, tau);
d = l1 != w_i_p_1->second;
}
if (d)
{ /*w(i+1) ^ tau != w(i+1) ^ w(i+2)*/
/*extension: w(i) |- tau -> w(i+1) */
w_i->second = tau_i;
iter_d[tau]
= hlist->insert(w_i_p_1, make_pair(tau, l1));
}
else
{
/*must be w(i+1) ~> w(i+2)*/
/*extension: w(i-1) -> w(i+1) |- w(i) |- tau -> w(i+2)
*/
iter w_i_p_2 = w_i_p_1;
++w_i_p_2;
w_i_p_1->second = w_i->second;
iter_d[i] = hlist->insert(w_i_p_2, make_pair(i, tau_i));
hlist->erase(w_i);
Line l2 = get_sharing_line(*w_i_p_2, tau);
iter_d[tau]
= hlist->insert(w_i_p_2, make_pair(tau, l2));
}
}
}
else
{
/*Case 4:
w(i-1) ~> w(i) ~> w(i+1)
*/
bool c = false;
if (w_i_m_1 != w_end)
{
c = (w_i_m_1->second.second == tau_i.first)
|| (w_i_m_1->second.second == tau_i.second);
}
if (c)
{ /*w(i-1) ^ w(i) < w(i) ^ tau */
/*extension: w(i-1) -> tau |- w(i) */
if (w_i_m_1 != w_end)
w_i_m_1->second = get_sharing_line(*w_i_m_1, tau);
iter_d[tau] = hlist->insert(w_i, make_pair(tau, tau_i));
}
else
{
/*extension: w(i) |- tau -> w(i+1) */
w_i->second = tau_i;
Line l1;
l1.first = SAW_SENTINAL;
l1.second = SAW_SENTINAL;
if (w_i_p_1 != w_end)
l1 = get_sharing_line(*w_i_p_1, tau);
iter_d[tau] = hlist->insert(w_i_p_1, make_pair(tau, l1));
}
}
}
return true;
}
protected:
TriangleDecorator td; /*a decorator for vertex*/
HList hlist;
/*This must be a handle of list to record the SAW
The element type of the list is pair<Vertex, Line>
*/
IteratorD iter_d;
/*Problem statement: Need a fast access to w for triangle i.
*Possible solution: mantain an array to record.
iter_d[i] will return an iterator
which points to w(i), where i is a vertex
representing triangle i.
*/
};
template < class Triangle, class HList, class Iterator >
inline SAW_visitor< Triangle, HList, Iterator > visit_SAW(
Triangle t, HList hl, Iterator i)
{
return SAW_visitor< Triangle, HList, Iterator >(t, hl, i);
}
template < class Tri, class HList, class Iter >
inline SAW_visitor< random_access_iterator_property_map< Tri*, Tri, Tri& >,
HList, random_access_iterator_property_map< Iter*, Iter, Iter& > >
visit_SAW_ptr(Tri* t, HList hl, Iter* i)
{
typedef random_access_iterator_property_map< Tri*, Tri, Tri& > TriD;
typedef random_access_iterator_property_map< Iter*, Iter, Iter& > IterD;
return SAW_visitor< TriD, HList, IterD >(t, hl, i);
}
// should also have combo's of pointers, and also const :(
}
#endif /*BOOST_SAW_H*/