⎇ dc8554d1231f9f351385afa13d82d56504b6309f
crates/modules/pineal/mesh/src/buffers.rs
History
Who touched what
raw
feat(pineal): cierra stub mesh — viz de grafos (núcleo)
1//! Buffers planos de nodos y aristas — `Vec` contiguos con stride fijo.
2
3/// Nodos: stride 3 = `[x, y, radius]` por nodo.
4#[derive(Debug, Clone, Default)]
5pub struct NodeBuffer {
6 data: Vec<f32>,
7}
8
9impl NodeBuffer {
10 pub fn new() -> Self {
11 Self::default()
12 }
13
14 pub fn with_capacity(n: usize) -> Self {
15 Self { data: Vec::with_capacity(n * 3) }
16 }
17
18 /// Agrega un nodo y devuelve su índice.
19 pub fn push(&mut self, x: f32, y: f32, radius: f32) -> usize {
20 let idx = self.len();
21 self.data.extend_from_slice(&[x, y, radius]);
22 idx
23 }
24
25 pub fn len(&self) -> usize {
26 self.data.len() / 3
27 }
28
29 pub fn is_empty(&self) -> bool {
30 self.data.is_empty()
31 }
32
33 pub fn pos(&self, i: usize) -> (f32, f32) {
34 (self.data[i * 3], self.data[i * 3 + 1])
35 }
36
37 pub fn radius(&self, i: usize) -> f32 {
38 self.data[i * 3 + 2]
39 }
40
41 pub fn set_pos(&mut self, i: usize, x: f32, y: f32) {
42 self.data[i * 3] = x;
43 self.data[i * 3 + 1] = y;
44 }
45
46 /// Acceso crudo al `Vec<f32>` interleaved — para subir como buffer GPU.
47 pub fn raw(&self) -> &[f32] {
48 &self.data
49 }
50}
51
52/// Aristas: stride 2 = `[from, to]` (índices de nodo).
53#[derive(Debug, Clone, Default)]
54pub struct EdgeBuffer {
55 data: Vec<u32>,
56}
57
58impl EdgeBuffer {
59 pub fn new() -> Self {
60 Self::default()
61 }
62
63 pub fn push(&mut self, from: usize, to: usize) {
64 self.data.push(from as u32);
65 self.data.push(to as u32);
66 }
67
68 pub fn len(&self) -> usize {
69 self.data.len() / 2
70 }
71
72 pub fn is_empty(&self) -> bool {
73 self.data.is_empty()
74 }
75
76 pub fn edge(&self, i: usize) -> (usize, usize) {
77 (self.data[i * 2] as usize, self.data[i * 2 + 1] as usize)
78 }
79
80 pub fn iter(&self) -> impl Iterator<Item = (usize, usize)> + '_ {
81 (0..self.len()).map(move |i| self.edge(i))
82 }
83}
84
85#[cfg(test)]
86mod tests {
87 use super::*;
88
89 #[test]
90 fn node_buffer_push_and_access() {
91 let mut nb = NodeBuffer::new();
92 let a = nb.push(1.0, 2.0, 5.0);
93 let b = nb.push(3.0, 4.0, 6.0);
94 assert_eq!((a, b), (0, 1));
95 assert_eq!(nb.len(), 2);
96 assert_eq!(nb.pos(1), (3.0, 4.0));
97 assert_eq!(nb.radius(0), 5.0);
98 nb.set_pos(0, 9.0, 9.0);
99 assert_eq!(nb.pos(0), (9.0, 9.0));
100 }
101
102 #[test]
103 fn edge_buffer_roundtrip() {
104 let mut eb = EdgeBuffer::new();
105 eb.push(0, 1);
106 eb.push(1, 2);
107 assert_eq!(eb.len(), 2);
108 assert_eq!(eb.edge(1), (1, 2));
109 assert_eq!(eb.iter().collect::<Vec<_>>(), vec![(0, 1), (1, 2)]);
110 }
111}