Skip to main content

linnet/half_edge/
tree.rs

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