source: trunk/SL/TREEDISP/GroupIterator.hxx

Last change on this file was 17877, checked in by westram, 6 years ago
File size: 2.9 KB
Line 
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
18class GroupIterator {
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
46public:
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
Note: See TracBrowser for help on using the repository browser.