linnet/half_edge/
tree.rs

1use std::{cmp::Ordering, collections::VecDeque};
2
3use bitvec::vec::BitVec;
4use itertools::Itertools;
5
6use crate::tree::{
7    parent_pointer::ParentPointerStore, Forest, ForestNodeStore, ForestNodeStoreBfs,
8    ForestNodeStoreDown, ForestNodeStorePreorder, RootId,
9};
10
11use super::{
12    involution::{Hedge, Involution},
13    subgraph::{Cycle, Inclusion, InternalSubGraph, ModifySubgraph, SubGraph, SubGraphOps},
14    HedgeGraph, HedgeGraphError, NodeIndex, NodeStorageOps,
15};
16
17// pub struct HedgeTree<V, P: ForestNodeStore<NodeData = ()>, E> {
18//     graph: HedgeGraph<E, V, Forest<V, P>>,
19//     tree_subgraph: InternalSubGraph,
20//     covers: BitVec,
21// }
22
23// impl<V, P: ForestNodeStore<NodeData = ()>, E> HedgeTree<V, P, E> {
24//     pub fn ancestor_nodes(&self,) {
25//         self.
26//     }
27// }
28
29// #[derive(Debug, Clone)]
30// pub struct TraversalTreeRef<
31//     'a,
32//     E,
33//     V,
34//     N: NodeStorage<NodeData = V>,
35//     P: ForestNodeStore<NodeData = ()>,
36// > {
37//     graph: &'a HedgeGraph<E, V, N>,
38//     simple: SimpleTraversalTree<P>,
39//     tree_subgraph: InternalSubGraph,
40// }
41
42#[derive(Debug, Clone, Copy, Hash, PartialEq, Eq, PartialOrd, Ord)]
43#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
44#[cfg_attr(feature = "bincode", derive(bincode::Encode, bincode::Decode))]
45/// Represents the role of a graph node within a [`SimpleTraversalTree`].
46///
47/// When a traversal (like DFS or BFS) is performed on a graph, each node
48/// of the graph can be classified based on its position and discovery time
49/// within that traversal. This enum is typically used as the root data in the
50/// `Forest` underlying a `SimpleTraversalTree`.
51pub enum TTRoot {
52    /// The node is a child of another node in the traversal tree.
53    /// The `usize` value might represent discovery order or depth, depending on context.
54    Child(usize),
55    /// The node is the root of this specific traversal tree.
56    Root,
57    /// The node is not part of this traversal tree (e.g., it was not visited).
58    None,
59}
60
61impl TTRoot {
62    pub fn includes(&self) -> bool {
63        match self {
64            TTRoot::Child(_) => true,
65            TTRoot::Root => true,
66            TTRoot::None => false,
67        }
68    }
69
70    pub fn is_root(&self) -> bool {
71        match self {
72            TTRoot::Child(_) => false,
73            TTRoot::Root => true,
74            TTRoot::None => false,
75        }
76    }
77
78    pub fn is_child(&self) -> bool {
79        match self {
80            TTRoot::Child(_) => true,
81            TTRoot::Root => false,
82            TTRoot::None => false,
83        }
84    }
85}
86
87#[derive(Debug, Clone)]
88#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
89// #[cfg_attr(feature = "bincode", derive(bincode::Encode, bincode::Decode))] // Manual Bincode implemented
90/// Represents a traversal tree (e.g., DFS or BFS tree) derived from a [`HedgeGraph`].
91///
92/// This structure uses a generic [`Forest`] to store the tree topology. Each "root" in the
93/// `Forest` corresponds to a node in the original `HedgeGraph`, and its data is a [`TTRoot`]
94/// enum indicating its role (Root, Child, or None) in this specific traversal. The nodes
95/// within each tree of the `Forest` typically represent the half-edges that form the
96/// traversal path.
97///
98/// # Type Parameters
99///
100/// - `P`: The type of [`ForestNodeStore`] used by the underlying `Forest`.
101///   It stores `()` as `NodeData` because the tree nodes (representing half-edges)
102///   don't need additional data beyond their structural role in the traversal tree.
103///   Defaults to [`ParentPointerStore<()>`].
104pub struct SimpleTraversalTree<P: ForestNodeStore<NodeData = ()> = ParentPointerStore<()>> {
105    /// The underlying forest structure representing the traversal tree(s).
106    /// Each root in this forest is a graph node, and its data is its [`TTRoot`] status.
107    /// Nodes within each tree of this forest represent half-edges.
108    forest: Forest<TTRoot, P>,
109    /// A bitmask representing the set of half-edges that constitute the actual
110    /// edges of this traversal tree.
111    // #[cfg_attr(feature = "bincode", bincode(with_serde))] // Handled by manual impl
112    pub tree_subgraph: BitVec,
113}
114#[cfg(feature = "bincode")]
115impl<P: ForestNodeStore<NodeData = ()>> ::bincode::Encode for SimpleTraversalTree<P>
116where
117    P: ::bincode::Encode,
118{
119    fn encode<__E: ::bincode::enc::Encoder>(
120        &self,
121        encoder: &mut __E,
122    ) -> core::result::Result<(), ::bincode::error::EncodeError> {
123        ::bincode::Encode::encode(&self.forest, encoder)?;
124        ::bincode::Encode::encode(&::bincode::serde::Compat(&self.tree_subgraph), encoder)?;
125        core::result::Result::Ok(())
126    }
127}
128
129#[cfg(feature = "bincode")]
130impl<P: ForestNodeStore<NodeData = ()>, __Context> ::bincode::Decode<__Context>
131    for SimpleTraversalTree<P>
132where
133    P: ::bincode::Decode<__Context>,
134{
135    fn decode<__D: ::bincode::de::Decoder<Context = __Context>>(
136        decoder: &mut __D,
137    ) -> core::result::Result<Self, ::bincode::error::DecodeError> {
138        core::result::Result::Ok(Self {
139            forest: ::bincode::Decode::decode(decoder)?,
140            tree_subgraph: (<::bincode::serde::Compat<_> as ::bincode::Decode<__Context>>::decode(
141                decoder,
142            )?)
143            .0,
144        })
145    }
146}
147
148#[cfg(feature = "bincode")]
149impl<'__de, P: ForestNodeStore<NodeData = ()>, __Context> ::bincode::BorrowDecode<'__de, __Context>
150    for SimpleTraversalTree<P>
151where
152    P: ::bincode::de::BorrowDecode<'__de, __Context>,
153{
154    fn borrow_decode<__D: ::bincode::de::BorrowDecoder<'__de, Context = __Context>>(
155        decoder: &mut __D,
156    ) -> core::result::Result<Self, ::bincode::error::DecodeError> {
157        core::result::Result::Ok(Self {
158            forest: ::bincode::BorrowDecode::<'_, __Context>::borrow_decode(decoder)?,
159            tree_subgraph: (<::bincode::serde::BorrowCompat<_> as ::bincode::BorrowDecode<
160                '_,
161                __Context,
162            >>::borrow_decode(decoder)?)
163            .0,
164        })
165    }
166}
167impl<P: ForestNodeStore<NodeData = ()>> SimpleTraversalTree<P> {
168    pub fn cast<P2: ForestNodeStore<NodeData = ()>>(self) -> SimpleTraversalTree<P2>
169    where
170        Forest<TTRoot, P2>: From<Forest<TTRoot, P>>,
171    {
172        SimpleTraversalTree {
173            forest: self.forest.into(),
174            tree_subgraph: self.tree_subgraph,
175        }
176    }
177}
178
179impl<P: ForestNodeStore<NodeData = ()>> SimpleTraversalTree<P> {
180    pub fn node_order(&self) -> Vec<NodeIndex> {
181        self.forest
182            .iter_roots()
183            .enumerate()
184            .filter_map(|(i, (a, _))| match a {
185                TTRoot::Root => Some((0, i)),
186                TTRoot::Child(a) => Some((*a, i)),
187                _ => None,
188            })
189            .sorted_by(|a, b| a.0.cmp(&b.0))
190            .map(|a| NodeIndex(a.1))
191            .collect()
192    }
193    pub fn covers<S: SubGraph>(&self, subgraph: &S) -> BitVec {
194        // println!("calculating covers..");
195        let mut covers = BitVec::empty(self.tree_subgraph.len());
196
197        // self.tree_subgraph.covers(graph)
198
199        for i in 0..self.tree_subgraph.len() {
200            if self.node_data(self.node_id(Hedge(i))).includes() && subgraph.includes(&Hedge(i)) {
201                covers.set(i, true);
202            }
203        }
204
205        covers
206    }
207
208    // fn root_hedge(&self, node: NodeIndex) -> Hedge {
209    //     self.forest[&RootId(node.0)].into()
210    // }
211
212    pub fn node_data(&self, node: NodeIndex) -> &TTRoot {
213        &self.forest[RootId(node.0)]
214    }
215
216    pub fn internal<I: AsRef<Involution>>(&self, hedge: Hedge, _inv: I) -> bool {
217        self.tree_subgraph.includes(&hedge)
218    }
219
220    pub fn tree_subgraph<I: AsRef<Involution>>(&self, inv: I) -> InternalSubGraph {
221        let mut tree = BitVec::empty(self.tree_subgraph.len());
222        let inv = inv.as_ref();
223
224        for (r, h) in self.forest.iter_roots() {
225            let h: Hedge = (*h).into();
226            if r.is_child() {
227                tree.add(h);
228                tree.add(inv.inv(h))
229            }
230        }
231
232        unsafe { InternalSubGraph::new_unchecked(tree) }
233    }
234
235    pub fn get_cycle<I: AsRef<Involution>>(&self, cut: Hedge, inv: &I) -> Option<Cycle> {
236        if self.internal(cut, inv) {
237            return None;
238        }
239        let mut cycle = self.path_to_root(cut, inv);
240        cycle.sym_diff_with(&self.path_to_root(inv.as_ref().inv(cut), inv));
241        let mut cycle = Cycle::new_unchecked(cycle);
242        cycle.loop_count = Some(1);
243
244        Some(cycle)
245    }
246
247    pub fn node_id(&self, hedge: Hedge) -> NodeIndex {
248        NodeIndex::from(self.forest.root(hedge.into()))
249    }
250
251    /// get the parent node of the current node
252    pub fn node_parent<I: AsRef<Involution>>(&self, from: NodeIndex, inv: I) -> Option<NodeIndex> {
253        let root = RootId::from(from);
254
255        if self.forest[root].is_child() {
256            // if the current node is in the forest
257            // get the involved hedge connected to the root pointing hedge of the current node
258            let involved = inv.as_ref().inv(self.forest[&root].into());
259            Some(self.node_id(involved))
260        } else {
261            None
262        }
263    }
264
265    fn path_to_root<I: AsRef<Involution>>(&self, start: Hedge, inv: I) -> BitVec {
266        let mut path = BitVec::empty(self.tree_subgraph.len());
267
268        self.ancestor_iter_hedge(start, inv.as_ref())
269            .for_each(|a| path.set(a.0, true));
270        path
271    }
272
273    /// among the hedges of the same node get the one pointing to the root node.
274    /// if the from hedge is that pointing to the root node, go to the involved hedge.
275    pub fn hedge_parent<I: AsRef<Involution>>(&self, from: Hedge, inv: I) -> Option<Hedge> {
276        let root = self.forest.root(from.into()); //Get "NodeId/RootId"
277
278        match self.forest[root] {
279            TTRoot::Child(_) => {
280                let roothedge = self.forest[&root].into(); //Get "chosen" root among node hairs
281
282                if from == roothedge {
283                    //if it is the same as the input, go to the involved hedge
284                    Some(inv.as_ref().inv(from))
285                } else {
286                    // else go to the "chosen" hedge
287                    Some(roothedge)
288                }
289            }
290            TTRoot::None => {
291                // println!("None");
292                None
293            }
294            TTRoot::Root => {
295                // println!("Root");
296                None
297            } // if it is attached to the root node, it has no parent
298        }
299    }
300}
301
302/// An iterator that traverses upwards from a given starting half-edge to the root
303/// of its traversal tree, yielding each [`Hedge`] along the path.
304///
305/// # Type Parameters
306///
307/// - `'a`: The lifetime of the borrowed [`SimpleTraversalTree`] and [`Involution`].
308/// - `P`: The type of [`ForestNodeStore`] used by the `SimpleTraversalTree`.
309pub struct TraversalTreeAncestorHedgeIterator<'a, P: ForestNodeStore<NodeData = ()>> {
310    /// A reference to the traversal tree being traversed.
311    tt: &'a SimpleTraversalTree<P>,
312    /// A reference to the graph's involution, needed to find opposite half-edges.
313    inv: &'a Involution,
314    /// The current [`Hedge`] in the traversal, or `None` if iteration is finished.
315    current: Option<Hedge>,
316}
317
318impl<P: ForestNodeStore<NodeData = ()>> Iterator for TraversalTreeAncestorHedgeIterator<'_, P> {
319    type Item = Hedge;
320
321    fn next(&mut self) -> Option<Self::Item> {
322        if let Some(c) = self.current {
323            self.current = self.tt.hedge_parent(c, self.inv);
324            Some(c)
325        } else {
326            None
327        }
328    }
329}
330
331#[derive(Clone)]
332/// An iterator that performs a pre-order traversal of the nodes in a [`SimpleTraversalTree`].
333///
334/// Starting from a given graph node, it visits the node itself and then recursively
335/// visits its children in the traversal tree.
336///
337/// # Type Parameters
338///
339/// - `'a`: The lifetime of the borrowed [`SimpleTraversalTree`] and [`Involution`].
340/// - `S`: The type of [`ForestNodeStore`] used by the `SimpleTraversalTree`, which
341///   must also implement [`ForestNodeStoreDown`] to allow child iteration.
342pub struct PreorderTraversalIter<'a, S: ForestNodeStore<NodeData = ()>>
343where
344    S: ForestNodeStoreBfs,
345{
346    /// A reference to the traversal tree being traversed.
347    store: &'a SimpleTraversalTree<S>,
348    /// A reference to the graph's involution, used for navigating child relationships.
349    inv: &'a Involution,
350    /// A stack to keep track of nodes to visit during the pre-order traversal.
351    stack: Vec<NodeIndex>,
352}
353
354impl<'a, S: ForestNodeStoreBfs + ForestNodeStore<NodeData = ()>> PreorderTraversalIter<'a, S> {
355    /// Create a new pre-order iterator starting at `start`.
356    pub fn new(
357        store: &'a SimpleTraversalTree<S>,
358        inv: &'a impl AsRef<Involution>,
359        start: NodeIndex,
360    ) -> Self {
361        PreorderTraversalIter {
362            inv: inv.as_ref(),
363            store,
364            stack: vec![start],
365        }
366    }
367}
368
369impl<S: ForestNodeStoreBfs + ForestNodeStore<NodeData = ()>> Iterator
370    for PreorderTraversalIter<'_, S>
371{
372    type Item = NodeIndex;
373    fn next(&mut self) -> Option<Self::Item> {
374        // Pop the next node from the stack
375        let node = self.stack.pop()?;
376
377        // Push children onto the stack in reverse order so the first child is processed next
378        // (This assumes iter_children returns them in the desired forward order)
379        for child in self
380            .store
381            .iter_children(node, &self.inv)
382            .collect::<Vec<_>>()
383            .into_iter()
384            .rev()
385        {
386            self.stack.push(child);
387        }
388
389        Some(node)
390    }
391}
392
393impl<P: ForestNodeStore<NodeData = ()>> SimpleTraversalTree<P> {
394    pub fn debug_draw<FR>(
395        &self,
396        format_root: FR, // Closure to format root data (&R) -> String
397    ) -> String
398    where
399        FR: FnMut(&TTRoot) -> String,
400
401        P: ForestNodeStoreDown,
402    {
403        self.forest.debug_draw(format_root, |_| "".into())
404    }
405    pub fn iter_children<'a, I: AsRef<Involution>>(
406        &'a self,
407        node_id: NodeIndex,
408        inv: &'a I,
409    ) -> impl Iterator<Item = NodeIndex> + 'a
410    where
411        P: ForestNodeStoreBfs,
412    {
413        let root_node = self.forest[&RootId::from(node_id)];
414
415        let root_node_data = self.forest[RootId::from(node_id)];
416
417        // println!("{:?}", root_node);
418        self.forest.iter_bfs(root_node).filter_map(move |a| {
419            if root_node == a && !root_node_data.is_root() {
420                return None;
421            }
422            let h = Hedge::from(a);
423            // println!("Hedge:{h}");
424            if self.tree_subgraph.includes(&h) {
425                let invh = inv.as_ref().inv(a.into());
426                // println!("Included");
427                if invh != h {
428                    // println!("Hi");
429                    if self.tree_subgraph.includes(&invh) {
430                        let child = self.node_id(invh);
431                        // println!("Node:{child}");
432
433                        let root = RootId::from(child);
434
435                        if self.forest[root].is_child() {
436                            Some(child)
437                        } else {
438                            None
439                        }
440                    } else {
441                        None
442                    }
443                } else {
444                    None
445                }
446            } else {
447                None
448            }
449        })
450    }
451
452    // pub fn iter_descendents<'a, I: AsRef<Involution>>(
453    //     &'a self,
454    //     node_id: NodeIndex,
455    //     inv: &'a I,
456    // ) -> impl Iterator<Item = NodeIndex> + 'a
457    // where
458    //     P: ForestNodeStoreDown,
459    // {
460    //     self.iter_children(node_id, inv)
461    //         .map(|n| self.iter_descendents(n, inv))
462    //         .flatten()
463    // }
464    /// Returns a pre-order iterator over the hedges *within* the traversal tree.
465    /// Requires the underlying Forest store `P` to support pre-order traversal.
466    pub fn iter_preorder_tree_nodes<'a>(
467        &'a self,
468        inv: &'a impl AsRef<Involution>,
469        start: NodeIndex,
470    ) -> PreorderTraversalIter<'a, P>
471    where
472        P: ForestNodeStorePreorder<NodeData = ()> + ForestNodeStoreBfs,
473    {
474        PreorderTraversalIter::new(self, inv, start)
475    }
476
477    pub fn ancestor_iter_hedge<'a>(
478        &'a self,
479        start: Hedge,
480        inv: &'a Involution,
481    ) -> impl Iterator<Item = Hedge> + 'a {
482        TraversalTreeAncestorHedgeIterator {
483            tt: self,
484            inv,
485            current: Some(start),
486        }
487    }
488
489    pub fn dot<E, V, H, N: NodeStorageOps<NodeData = V>>(
490        &self,
491        graph: &HedgeGraph<E, V, H, N>,
492    ) -> String {
493        let mut structure = graph.just_structure();
494        structure.align_superficial_to_tree(self);
495
496        structure.base_dot()
497    }
498
499    pub fn tree_order<I: AsRef<Involution>>(
500        &self,
501        left: NodeIndex,
502        right: NodeIndex,
503        inv: I,
504    ) -> Option<Ordering> {
505        if left == right {
506            return Some(Ordering::Equal);
507        }
508
509        let left_to_root_passes_through_right = self
510            .ancestor_iter_node(left, inv.as_ref())
511            .any(|a| a == right);
512        if left_to_root_passes_through_right {
513            return Some(Ordering::Less);
514        }
515
516        let right_to_root_passes_through_left = self
517            .ancestor_iter_node(right, inv.as_ref())
518            .any(|a| a == left);
519        if right_to_root_passes_through_left {
520            return Some(Ordering::Greater);
521        }
522
523        None
524    }
525
526    /// Iterate over all half-edges in the tree.
527    ///
528    /// Each iteration yields a three-tuple:
529    ///
530    /// - the half-edge
531    /// - whether it is part of a child, or root node, or outside of the tree
532    /// - the root-pointing half-edge if it is actually part of the tree
533    ///
534    pub fn iter_hedges(&self) -> impl Iterator<Item = (Hedge, TTRoot, Option<Hedge>)> + '_ {
535        self.forest.iter_node_ids().map(|a| {
536            let root = self.forest.root(a); //Get "NodeId/RootId"
537            let hedge: Hedge = a.into();
538            let ttype = self.forest[root];
539            let root_among_hedges = if self.tree_subgraph.includes(&hedge) {
540                Some(self.forest[&root].into())
541            } else {
542                None
543            };
544
545            (hedge, ttype, root_among_hedges)
546        })
547    }
548}
549
550pub struct TraversalTreeAncestorNodeIterator<'a, P: ForestNodeStore<NodeData = ()>> {
551    tt: &'a SimpleTraversalTree<P>,
552    inv: &'a Involution,
553    current: Option<NodeIndex>,
554}
555
556impl<P: ForestNodeStore<NodeData = ()>> Iterator for TraversalTreeAncestorNodeIterator<'_, P> {
557    type Item = NodeIndex;
558
559    fn next(&mut self) -> Option<Self::Item> {
560        if let Some(c) = self.current {
561            self.current = self.tt.node_parent(c, self.inv);
562            Some(c)
563        } else {
564            None
565        }
566    }
567}
568
569impl<P: ForestNodeStore<NodeData = ()>> SimpleTraversalTree<P> {
570    pub fn ancestor_iter_node<'a>(
571        &'a self,
572        from: NodeIndex,
573        inv: &'a Involution,
574    ) -> impl Iterator<Item = NodeIndex> + 'a {
575        TraversalTreeAncestorNodeIterator {
576            tt: self,
577            inv,
578            current: Some(from),
579        }
580    }
581}
582
583impl SimpleTraversalTree {
584    pub fn empty<E, V, H, N: NodeStorageOps<NodeData = V>>(graph: &HedgeGraph<E, V, H, N>) -> Self {
585        let forest = graph.node_store.to_forest(|_| TTRoot::None);
586        SimpleTraversalTree {
587            forest,
588            tree_subgraph: graph.empty_subgraph(),
589        }
590    }
591
592    // pub fn root(&self,Hedge) -> Hedge {
593    //     self.forest.root()
594    // }
595
596    pub fn depth_first_traverse<S: SubGraph, E, V, H, N: NodeStorageOps<NodeData = V>>(
597        graph: &HedgeGraph<E, V, H, N>,
598        subgraph: &S,
599        root_node: &NodeIndex,
600        include_hedge: Option<Hedge>,
601    ) -> Result<Self, HedgeGraphError> {
602        let mut seen = subgraph.hairs(graph.iter_crown(*root_node));
603
604        if seen.count_ones() == 0 {
605            // if the root node is not in the subgraph
606            return Err(HedgeGraphError::RootNodeNotInSubgraph(*root_node));
607        }
608
609        let mut stack = seen.included_iter().collect::<Vec<_>>();
610        if let Some(r) = include_hedge {
611            if graph.inv(r) == r {
612                return Err(HedgeGraphError::ExternalHedgeIncluded(r)); //cannot include an external hedge in the traversal
613            }
614
615            let pos = stack.iter().find_position(|a| **a == r).map(|a| a.0);
616
617            let last = stack.len() - 1;
618            if let Some(pos) = pos {
619                stack.swap(pos, last);
620            } else {
621                return Err(HedgeGraphError::NotInNode(r, *root_node));
622            }
623        }
624
625        let mut init = Self::empty(graph);
626        init.forest[RootId(root_node.0)] = TTRoot::Root;
627
628        let mut iter_order = 0;
629
630        while let Some(hedge) = stack.pop() {
631            // if the hedge is not external get the neighbors of the paired hedge
632            if let Some(cn) = graph.involved_node_crown(hedge) {
633                let connected = graph.inv(hedge);
634
635                if !seen.includes(&connected) && subgraph.includes(&connected) {
636                    // if this new hedge hasn't been seen before, it means the node it belongs to
637                    // is a new node in the traversal
638                    init.tree_subgraph.set(connected.0, true);
639                    init.tree_subgraph.set(hedge.0, true);
640                    let node_id = init.forest.change_to_root(connected.into());
641                    iter_order += 1;
642                    init.forest[node_id] = TTRoot::Child(iter_order);
643                } else {
644                    continue;
645                }
646
647                // mark the new node as seen
648                // seen.union_with(&cn.hairs);
649
650                for i in cn {
651                    if subgraph.includes(&i) {
652                        seen.set(i.0, true);
653                        if !seen.includes(&graph.inv(i)) {
654                            stack.push(i);
655                        }
656                    }
657                }
658            }
659        }
660
661        // init.tree_subgraph = tree_subgraph;
662        Ok(init)
663    }
664
665    pub fn breadth_first_traverse<S: SubGraph, E, V, H, N: NodeStorageOps<NodeData = V>>(
666        graph: &HedgeGraph<E, V, H, N>,
667        subgraph: &S,
668        root_node: &NodeIndex,
669        include_hedge: Option<Hedge>,
670    ) -> Result<Self, HedgeGraphError> {
671        let mut seen = subgraph.hairs(graph.iter_crown(*root_node));
672
673        if seen.count_ones() == 0 {
674            // if the root node is not in the subgraph
675            return Err(HedgeGraphError::InvalidNode(*root_node));
676        }
677
678        let mut queue = seen.included_iter().collect::<VecDeque<_>>();
679        if let Some(r) = include_hedge {
680            if graph.inv(r) == r {
681                return Err(HedgeGraphError::InvalidHedge(r)); //cannot include an external hedge in the traversal
682            }
683            let pos = queue.iter().find_position(|a| **a == r).map(|a| a.0);
684            if let Some(pos) = pos {
685                queue.swap(pos, 0);
686            } else {
687                return Err(HedgeGraphError::InvalidHedge(r));
688            }
689        }
690
691        let mut init = Self::empty(graph);
692
693        let mut iter_order = 0;
694        init.forest[RootId(root_node.0)] = TTRoot::Root;
695        while let Some(hedge) = queue.pop_front() {
696            // if the hedge is not external get the neighbors of the paired hedge
697            if let Some(cn) = graph.connected_neighbors(subgraph, hedge) {
698                let connected = graph.inv(hedge);
699
700                if !seen.includes(&connected) && subgraph.includes(&connected) {
701                    // if this new hedge hasn't been seen before, it means the node it belongs to
702                    //  a new node in the traversal
703                    //
704                    init.tree_subgraph.set(connected.0, true);
705                    init.tree_subgraph.set(hedge.0, true);
706                    let node_id = init.forest.change_to_root(connected.into());
707                    iter_order += 1;
708                    init.forest[node_id] = TTRoot::Child(iter_order);
709                } else {
710                    continue;
711                }
712                // mark the new node as seen
713                seen.union_with(&cn);
714
715                // for all hedges in this new node, they have a parent, the initial hedge
716                for i in cn.included_iter() {
717                    // if they lead to a new node, they are potential branches, add them to the queue
718                    if !seen.includes(&graph.inv(i)) && subgraph.includes(&i) {
719                        queue.push_back(i);
720                    }
721                }
722            }
723        }
724        Ok(init)
725    }
726}
727
728#[derive(Debug, Clone)]
729#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
730// #[cfg_attr(feature = "bincode", derive(bincode::Encode, bincode::Decode))]
731/// Represents a traversal tree that owns its graph representation, typically simplified.
732///
733/// This structure might be used for scenarios where a traversal tree needs to be
734/// stored or manipulated independently of the original, more complex graph from
735/// which it was derived. The graph it owns might store simplified data (e.g., `()` for
736/// edge data, `bool` for node data indicating inclusion).
737///
738/// # Type Parameters
739///
740/// - `P`: The type of [`ForestNodeStore`] used by the underlying `Forest` within the
741///   owned `HedgeGraph`. `P` must also implement `Clone` and [`ForestNodeStorePreorder`].
742pub struct OwnedTraversalTree<P: ForestNodeStore<NodeData = ()> + Clone + ForestNodeStorePreorder> {
743    /// The graph representation owned by this traversal tree.
744    /// Edge data is `()`, and node data is `bool` (likely indicating tree membership or similar).
745    /// The node storage of this graph is a `Forest<bool, P>`.
746    pub graph: HedgeGraph<(), bool, (), Forest<bool, P>>,
747    /// An [`InternalSubGraph`] representing the edges that form this traversal tree
748    /// within the context of its owned `graph`.
749    pub tree_subgraph: InternalSubGraph,
750    /// A bitmask indicating the set of half-edges covered by this traversal tree,
751    /// potentially in the context of a larger original graph.
752    // #[cfg_attr(feature = "bincode", bincode(with_serde))]
753    pub covers: BitVec,
754}
755
756// impl TraversalTree {
757//     pub fn children(&self, hedge: Hedge) -> BitVec {
758//         let mut children = <BitVec as SubGraph>::empty(self.inv.inv.len());
759
760//         for (i, m) in self.parents.iter().enumerate() {
761//             if let Parent::Hedge { hedge_to_root, .. } = m {
762//                 if *hedge_to_root == hedge {
763//                     children.set(i, true);
764//                 }
765//             }
766//         }
767
768//         children.set(hedge.0, false);
769
770//         children
771//     }
772
773//     pub fn leaf_edges(&self) -> BitVec {
774//         let mut leaves = <BitVec as SubGraph>::empty(self.inv.inv.len());
775//         for hedge in self.covers().included_iter() {
776//             let is_not_parent = !self.parent_iter().any(|(_, p)| {
777//                 if let Parent::Hedge { hedge_to_root, .. } = p {
778//                     *hedge_to_root == hedge
779//                 } else {
780//                     false
781//                 }
782//             });
783//             if is_not_parent {
784//                 leaves.set(hedge.0, true);
785//             }
786//         }
787//         leaves
788//     }
789
790//     pub fn leaf_nodes<V, N: NodeStorageOps<NodeData = V>, E>(
791//         &self,
792//         graph: &HedgeGraph<E, V, N>,
793//     ) -> Vec<NodeIndex> {
794//         let mut leaves = IndexSet::new();
795
796//         for hedge in self.covers().included_iter() {
797//             if let Parent::Hedge { hedge_to_root, .. } = self.parent(hedge) {
798//                 if *hedge_to_root == hedge {
799//                     let mut sect = self
800//                         .tree
801//                         .filter
802//                         .intersection(&graph.node_hairs(hedge).hairs);
803
804//                     sect.set(hedge.0, false);
805
806//                     if sect.count_ones() == 0 {
807//                         leaves.insert(graph.node_id(hedge));
808//                     }
809//                 }
810//             }
811//         }
812
813//         leaves.into_iter().collect()
814//     }
815
816//     pub fn child_nodes<V, N: NodeStorageOps<NodeData = V>, E>(
817//         &self,
818//         parent: NodeIndex,
819//         graph: &HedgeGraph<E, V, N>,
820//     ) -> Vec<NodeIndex> {
821//         let mut children = IndexSet::new();
822
823//         for h in graph.hairs_from_id(parent).hairs.included_iter() {
824//             if let Parent::Hedge { hedge_to_root, .. } = self.parent(h) {
825//                 if *hedge_to_root != h {
826//                     if let Some(c) = graph.involved_node_id(h) {
827//                         children.insert(c);
828//                     }
829//                 }
830//             }
831//         }
832
833//         children.into_iter().collect()
834//     }
835// }
836#[cfg(test)]
837pub mod tests {
838    use crate::{dot, half_edge::involution::Orientation, parser::DotGraph};
839
840    use super::*;
841
842    #[test]
843    fn double_pentagon_tree() {
844        let mut graph: DotGraph = dot!(
845            digraph {
846        node [shape=circle,height=0.1,label=""];  overlap="scale"; layout="neato";
847        00 -> 07[ dir=none,label="a"];
848        00 -> 12[ dir=forward,label="d"];
849        01 -> 00[ dir=forward,label="d"];
850        05 -> 02[ dir=forward,label="d"];
851        02 -> 01[ dir=forward,label="d"];
852        09 -> 04[ dir=forward,label="d"];
853        02 -> 06[ dir=none,label="a"];
854        01 -> 03[ dir=none,label="a"];
855        03 -> 13[ dir=forward,label="d"];
856        04 -> 03[ dir=forward,label="d"];
857        04 -> 05[ dir=none,label="g"];
858        06 -> 07[ dir=forward,label="e-"];
859        07 -> 11[ dir=forward,label="e-"];
860        08 -> 06[ dir=forward,label="e-"];
861        10 -> 05[ dir=forward,label="d"];
862        }
863        )
864        .unwrap();
865
866        // println!("{}", graph.dot_display(&graph.full_filter()));
867
868        let tree = SimpleTraversalTree::depth_first_traverse(
869            &graph,
870            &graph.full_filter(),
871            &NodeIndex(0),
872            None,
873        )
874        .unwrap();
875        // println!("{}", tree.dot(&graph));
876
877        graph.align_underlying_to_tree(&tree);
878        graph.align_superficial_to_tree(&tree);
879        assert!(graph
880            .iter_edges()
881            .all(|(_, _, d)| !matches!(d.orientation, Orientation::Reversed)));
882        // println!("{}", tree.dot(&graph))
883        // Test implementation
884    }
885}