ARB
GroupIterator.hxx
Go to the documentation of this file.
1 // ============================================================= //
2 // //
3 // File : GroupIterator.hxx //
4 // Purpose : Iterate over all groups of a tree //
5 // //
6 // Coded by Ralf Westram (coder@reallysoft.de) in March 2017 //
7 // http://www.arb-home.de/ //
8 // //
9 // ============================================================= //
10 
11 #ifndef GROUPITERATOR_HXX
12 #define GROUPITERATOR_HXX
13 
14 #ifndef TREENODE_H
15 #include <TreeNode.h>
16 #endif
17 
19  // This iterates over all clades shown in a tree.
20  // i.e. if a normal and a keeled group fall together, the iterator only stops once!
21  //
22  // Bug?: does not stop at keeled leaf groups
23  // (better leave as is: currently only stops at inner nodes)
24 
25  ARB_edge edge;
26  bool reverse;
27 
28  inline bool at_group() const {
29  return
30  edge.get_type() != EDGE_TO_ROOT &&
31  !edge.dest()->is_leaf() &&
32  edge.dest()->is_clade();
33  }
34 
35  void inc() {
36  ARB_edge start(edge);
37  do edge = edge.counter_previous();
38  while (!at_group() && start != edge);
39  }
40  void dec() {
41  ARB_edge start(edge);
42  do edge = edge.counter_next();
43  while (!at_group() && start != edge);
44  }
45 
46 public:
47  // forward iterator
48  // * starts with topmost and "rootmost" groups (i.e. child groups follow parent groups)
49  //
50  // reverse iterator
51  // * start with lowermost and "leafmost" groups (i.e. parent groups follow child groups)
52  //
53  // if 'start' node is a group => iterator will point to that group (after construction).
54  // Otherwise the iterator automatically increments to the "next" group.
55 
56  GroupIterator(AP_tree *start, bool forward = true) :
57  edge(start->father
58  ? parentEdge(start).inverse()
59  : ARB_edge(start->get_rightson(), start->get_leftson(), ROOT_EDGE)),
60  reverse(!forward)
61  {
62  td_assert(implicated(!start->is_leaf() && start->is_clade(),
63  at_group() && node() == start));
64  if (!at_group()) next();
65  }
66 
67  GroupIterator& next() { reverse ? inc() : dec(); return *this; }
68  GroupIterator& previous() { reverse ? dec() : inc(); return *this; }
69 
70  bool valid() const { return at_group(); } // false if GroupIterator created on tree w/o groups
71 
72  AP_tree *node() const {
73  td_assert(valid());
74  return DOWNCAST(AP_tree*, edge.dest());
75  }
76 
77  int get_clade_level() const {
78  td_assert(valid());
79  return node()->calc_clade_level(); // brute-force (maintain inside GroupIterator?)
80  }
81 };
82 
83 
84 #else
85 #error GroupIterator.hxx included twice
86 #endif // GROUPITERATOR_HXX
bool valid() const
#define implicated(hypothesis, conclusion)
Definition: arb_assert.h:289
int calc_clade_level() const
Definition: TreeNode.h:544
AP_tree * node() const
#define td_assert(cond)
Definition: Group.hxx:18
bool is_clade() const
Definition: TreeNode.h:480
ARB_edge_type get_type() const
Definition: TreeNode.h:766
#define DOWNCAST(totype, expr)
Definition: downcast.h:141
static HelixNrInfo * start
ARB_edge parentEdge(TreeNode *son)
Definition: TreeNode.h:883
POS_TREE1 * father
Definition: probe_tree.h:39
ARB_edge counter_previous() const
Definition: TreeNode.h:838
int get_clade_level() const
TreeNode * dest() const
Definition: TreeNode.h:768
bool is_leaf() const
Definition: TreeNode.h:211
GroupIterator(AP_tree *start, bool forward=true)
ARB_edge counter_next() const
Definition: TreeNode.h:827
GroupIterator & next()
GroupIterator & previous()