1use ahash::AHashMap;
2use itertools::Itertools;
3use linnet::half_edge::{
4 HedgeGraph, HedgeGraphError, NoData, NodeIndex,
5 builder::HedgeGraphBuilder,
6 involution::{HedgePair, Orientation},
7 nodestore::NodeStorageOps,
8};
9use symbolica::graph::Graph as SymbolicaGraph;
10
11pub trait HedgeGraphExt<N, E> {
12 type Error;
13 fn from_sym(graph: SymbolicaGraph<N, E>) -> Self;
14
15 fn to_sym(graph: &Self) -> Result<SymbolicaGraph<&N, &E>, Self::Error>;
16}
17
18impl<N: Clone, E: Clone, S: NodeStorageOps<NodeData = N>> HedgeGraphExt<N, E>
19 for HedgeGraph<E, N, NoData, S>
20{
21 fn from_sym(graph: SymbolicaGraph<N, E>) -> Self {
22 let mut builder = HedgeGraphBuilder::new();
23 let mut map = AHashMap::new();
24
25 for (i, node) in graph.nodes().iter().enumerate() {
26 map.insert(i, builder.add_node(node.data.clone()));
27 }
28
29 for edge in graph
33 .edges()
34 .iter()
35 .sorted_by(|a, b| a.vertices.cmp(&b.vertices))
36 {
37 let vertices = edge.vertices;
38 let source = map[&vertices.0];
39 let sink = map[&vertices.1];
40 builder.add_edge(source, sink, edge.data.clone(), edge.directed);
41 }
42
43 builder.into()
44 }
45
46 type Error = HedgeGraphError;
47
48 fn to_sym(value: &HedgeGraph<E, N, NoData, S>) -> Result<SymbolicaGraph<&N, &E>, Self::Error> {
49 let mut graph = SymbolicaGraph::new();
50 let mut map = AHashMap::new();
51
52 for (n, (_, _, node)) in value.iter_nodes().enumerate() {
53 map.insert(NodeIndex(n), graph.add_node(node));
54 }
55
56 for (i, _, d) in value.iter_edges() {
57 if let HedgePair::Paired { source, sink } = i {
58 let source = map[&value.node_id(source)];
59 let sink = map[&value.node_id(sink)];
60
61 let data = d.data;
62 let orientation = d.orientation;
63
64 match orientation {
65 Orientation::Default => {
66 graph
67 .add_edge(source, sink, true, data)
68 .map_err(HedgeGraphError::SymbolicaError)?;
69 }
70 Orientation::Reversed => {
71 graph
72 .add_edge(sink, source, true, data)
73 .map_err(HedgeGraphError::SymbolicaError)?;
74 }
75 Orientation::Undirected => {
76 graph
77 .add_edge(source, sink, false, data)
78 .map_err(HedgeGraphError::SymbolicaError)?;
79 }
80 }
81 } else {
82 return Err(HedgeGraphError::HasIdentityHedge);
83 }
84 }
85
86 Ok(graph)
87 }
88}