final version
[lp74.git] / src / data.rs
blob6611bdc1a9d9b1c3c1410f803ccbb238c5b601e4
1 use std::usize;
3 use std::sync::mpsc::{Sender, Receiver};
4 use std::sync::mpsc;
5 use std::thread;
7 const SPACE_SIZE: usize = 21;
8 const NOF_DIM: usize = 3;
9 const DEFAULT_FACE_SIZE: usize = 64;
10 const NOF_THREADS: usize = 4;
12 #[derive(Clone, Copy, PartialEq, Debug)]
13 pub enum Axis {
14     X,
15     Y,
16     Z,
19 #[derive(Clone, Copy, PartialEq, Debug)]
20 pub enum Ori {
21     Top,
22     Back,
23     Side,
26 #[derive(Clone, Copy, PartialEq, Debug)]
27 pub enum Pos {
28     E(Edge),
29     F(Face),
32 #[derive(Clone, Copy, PartialEq, Debug)]
33 pub enum Change {
34     None,
35     Current,
36     Size(Edge, usize),
37     Space,
40 #[derive(Clone, Copy, PartialEq, Debug)]
41 pub enum PosKind {
42     Edge,
43     Face,
46 pub type Coord = (usize, usize, usize);
47 pub type Edge = (Coord, Axis);
48 pub type Face = (Coord, Ori);
49 pub type FaceColor = (f32, f32, f32);
50 pub type Surface = [Option<FaceColor>; NOF_DIM];
52 pub struct Space {
53     pub size: [[usize; SPACE_SIZE]; NOF_DIM],
54     pub faces: [[[Option<Surface>; SPACE_SIZE]; SPACE_SIZE]; SPACE_SIZE],
55     pub current: Pos,
56     pub change: Change,
59 impl Space {
60     fn new() -> Space {
61         let mid = SPACE_SIZE / 2;
62         let current_node = (mid, mid, mid);
63         let mut tmp = Space {
64             size: [[DEFAULT_FACE_SIZE; SPACE_SIZE]; NOF_DIM],
65             faces: [[[None; SPACE_SIZE]; SPACE_SIZE]; SPACE_SIZE],
66             current: Pos::E((current_node, Axis::X)),
67             change: Change::None,
68         };
69         tmp.add_empty_node(current_node);
70         tmp.add_face((current_node, Ori::Top));
71         tmp
72     }
74     #[inline]
75     pub fn axis_idx(a: Axis) -> usize {
76         match a {
77             Axis::X => 0,
78             Axis::Y => 1,
79             Axis::Z => 2,
80         }
81     }
83     #[inline]
84     pub fn ori_idx(o: Ori) -> usize {
85         match o {
86             Ori::Top => 0,
87             Ori::Side => 1,
88             Ori::Back => 2,
89         }
90     }
92     fn adj_faces(((x, y, z), a): Edge) -> Vec<Face> {
93         let mut faces = Vec::new();
94         match a {
95             Axis::X => {
96                 faces.push(((x, y, z), Ori::Top));
97                 faces.push(((x, y, z), Ori::Back));
98                 if y < (SPACE_SIZE - 1) {
99                     faces.push(((x, y+1, z), Ori::Top));
100                 }
101                 if z > 0 {
102                    faces.push(((x, y, z-1), Ori::Back));
103                 }
104             },
105             Axis::Y => {
106                 faces.push(((x, y, z), Ori::Top));
107                 faces.push(((x, y, z), Ori::Side));
108                 if x > 0 {
109                     faces.push(((x-1, y, z), Ori::Top));
110                 }
111                 if z > 0 {
112                     faces.push(((x, y, z-1), Ori::Side));
113                 }
114             },
115             Axis::Z => {
116                 faces.push(((x, y, z), Ori::Back));
117                 faces.push(((x, y, z), Ori::Side));
118                 if x > 0 {
119                     faces.push(((x-1, y, z), Ori::Back));
120                 }
121                 if y < (SPACE_SIZE - 1) {
122                     faces.push(((x, y+1, z), Ori::Side));
123                 }
124             },
125         }
126         faces
127     }
129     #[inline]
130     fn is_node(&self, (x, y, z): Coord) -> bool {
131         if x < SPACE_SIZE
132             && y < SPACE_SIZE
133             && z < SPACE_SIZE {
134             if let Some(_) = self.faces[x][y][z] {
135                 true
136             } else {
137                 false
138             }
139         } else {
140             false
141         }
142     }
144     #[inline]
145     fn is_face(&self, ((x, y, z), o): Face) -> bool {
146         self.is_node((x, y, z))
147             && match self.faces[x][y][z] {
148             Some(faces) => faces[Space::ori_idx(o)] != None,
149             None => false,
150         }
151     }
153     #[inline]
154     pub fn current_node_coord(&self) -> Coord {
155         match self.current {
156             Pos::E((n, _)) => n,
157             Pos::F((n, _)) => n,
158         }
159     }
161     pub fn row_size_before_current(&self, a: Axis) -> usize {
162         let (xcur, ycur, zcur) = self.current_node_coord();
163         let mut res = 0;
164         match a {
165             Axis::X => {
166                 for x in 0..xcur {
167                     res += self.size[Space::axis_idx(Axis::X)][x];
168                 }
169             },
170             Axis::Y => {
171                 for y in 0..ycur {
172                     res += self.size[Space::axis_idx(Axis::Y)][y];
173                 }
174             },
175             Axis::Z => {
176                 for z in 0..zcur {
177                     res += self.size[Space::axis_idx(Axis::Z)][z];
178                 }
179             },
180         }
181         res
182     }
184     #[inline]
185     pub fn row_size(&self, a: Axis) -> usize {
186         self.size[Space::axis_idx(a)].iter()
187             .fold(0, |row, &s| row + s)
188     }
190     #[inline]
191     pub fn get_edge_size(&self, ((x, y, z), a): Edge) -> usize {
192         self.size[Space::axis_idx(a)][match a {
193             Axis::X => x,
194             Axis::Y => y,
195             Axis::Z => z,
196         }]
197     }
199     pub fn set_current_face_color_if_any(&mut self, c: FaceColor) {
200         match self.current {
201             Pos::E(_) => panic!("current is not a face"),
202             Pos::F(((x, y, z), o)) => match self.faces[x][y][z] {
203                 Some(ref mut f) => f[Space::ori_idx(o)] = Some(c),
204                 None => panic!("no face here"),
205             },
206         }
207     }
209     fn edge_size_no_change(&mut self, ((x, y, z), a): Edge, new_size: usize) {
210         let size = &mut self.size[Space::axis_idx(a)][match a {
211             Axis::X => x,
212             Axis::Y => y,
213             Axis::Z => z,
214         }];
215         if *size != new_size {
216             *size = new_size;
217         }
218     }
220     #[inline]
221     pub fn edge_size(&mut self, e: Edge, new_size: usize) {
222         self.edge_size_no_change(e, new_size);
223         self.change = Change::Size(e, new_size);
224     }
226     pub fn inc_size(&mut self) {
227         match self.current {
228             Pos::E(e) => {
229                 let size = self.get_edge_size(e);
230                 if size < usize::MAX {
231                     self.edge_size(e, size + 1);
232                 }
233             },
234             Pos::F(_) => panic!("resize on a face"),
235         }
236     }
238     pub fn dec_size(&mut self) {
239         match self.current {
240             Pos::E(e) => {
241                 let size = self.get_edge_size(e);
242                 if size > 0 {
243                     self.edge_size(e, size - 1);
244                 }
245             },
246             Pos::F(_) => panic!("resize on a face"),
247         }
248     }
250     fn face_edges(&self, ((x, y, z), o): Face) -> Vec<Edge> {
251         let mut edges = Vec::new();
252         match o {
253             Ori::Top => {
254                 edges.push(((x, y, z), Axis::X));
255                 edges.push(((x, y, z), Axis::Y));
256                 if x < SPACE_SIZE-1 {
257                     edges.push(((x+1, y, z), Axis::Y));
258                 }
259                 if y > 0 {
260                     edges.push(((x, y-1, z), Axis::X));
261                 }
262             },
263             Ori::Back => {
264                 edges.push(((x, y, z), Axis::X));
265                 edges.push(((x, y, z), Axis::Z));
266                 if x < SPACE_SIZE-1 {
267                     edges.push(((x+1, y, z), Axis::Z));
268                 }
269                 if z < SPACE_SIZE-1 {
270                     edges.push(((x, y, z+1), Axis::X));
271                 }
272             },
273             Ori::Side => {
274                 edges.push(((x, y, z), Axis::Y));
275                 edges.push(((x, y, z), Axis::Z));
276                 if y > 0 {
277                     edges.push(((x, y-1, z), Axis::Z));
278                 }
279                 if z < SPACE_SIZE-1 {
280                     edges.push(((x, y, z+1), Axis::Y));
281                 }
282             },
283         }
284         edges
285     }
287     #[inline]
288     fn add_empty_node(&mut self, (x, y, z): Coord) {
289         assert!(!self.is_node((x, y, z)));
290         self.faces[x][y][z] = Some([None; NOF_DIM]);
291         self.change = Change::Space;
292     }
294     fn adj_available_faces(&self, e: Edge) -> Vec<Face> {
295         Space::adj_faces(e).iter()
296             .filter_map(|&adj_f| if self.is_face(adj_f) {
297                 None
298             } else {
299                 Some(adj_f)
300             }).collect::<Vec<_>>()
301     }
303     fn adj_existing_faces(&self, e: Edge) -> Vec<Face> {
304         Space::adj_faces(e).iter()
305             .filter_map(|&adj_f| if self.is_face(adj_f) {
306                 Some(adj_f)
307             } else {
308                 None
309             }).collect::<Vec<_>>()
310     }
312     pub fn dec_pos(&mut self) {
313         let tmp = match self.current {
314             Pos::E(((mut x, mut y, mut z), a)) => {
315                 match a {
316                     Axis::X => x -= 1,
317                     Axis::Y => y -= 1,
318                     Axis::Z => z -= 1,
319                 };
320                 (x, y, z)
321             },
322             Pos::F(((mut x, mut y, mut z), o)) => {
323                 match o {
324                     Ori::Top => z -= 1,
325                     Ori::Back => y -= 1,
326                     Ori::Side => x -= 1,
327                 };
328                 (x, y, z)
329             },
330         };
331         if self.is_node(tmp) {
332             self.change = Change::Current;
333             match self.current {
334                 Pos::E((ref mut n, _)) => *n = tmp,
335                 Pos::F((ref mut n, _)) => *n = tmp,
336             }
337         };
338     }
340     pub fn inc_pos(&mut self) {
341         let tmp = match self.current {
342             Pos::E(((mut x, mut y, mut z), a)) => {
343                 match a {
344                     Axis::X => x += 1,
345                     Axis::Y => y += 1,
346                     Axis::Z => z += 1,
347                 };
348                 (x, y, z)
349             },
350             Pos::F(((mut x, mut y, mut z), o)) => {
351                 match o {
352                     Ori::Top => z += 1,
353                     Ori::Back => y += 1,
354                     Ori::Side => x += 1,
355                 };
356                 (x, y, z)
357             },
358         };
359         if self.is_node(tmp) {
360             self.change = Change::Current;
361             match self.current {
362                 Pos::E((ref mut n, _)) => *n = tmp,
363                 Pos::F((ref mut n, _)) => *n = tmp,
364             }
365         };
366     }
368     pub fn rotate(&mut self) {
369         self.change = Change::Current;
370         match self.current {
371             Pos::E((_, ref mut a)) => match *a {
372                 Axis::X => *a = Axis::Y,
373                 Axis::Y => *a = Axis::Z,
374                 Axis::Z => *a = Axis::X,
375             },
376             Pos::F((_, ref mut o)) => match *o {
377                 Ori::Top => *o = Ori::Back,
378                 Ori::Back => *o = Ori::Side,
379                 Ori::Side => *o = Ori::Top,
380             },
381         }
382     }
384     pub fn set_pos_kind(&mut self, pk: PosKind) {
385         match pk {
386             PosKind::Face => if let Pos::E((c, a)) = self.current {
387                 self.change = Change::Current;
388                 self.current = Pos::F((c, match a {
389                     Axis::X => Ori::Side,
390                     Axis::Y => Ori::Back,
391                     Axis::Z => Ori::Top,
392                 }));
393             },
394             PosKind::Edge => if let Pos::F((c, o)) = self.current {
395                 self.change = Change::Current;
396                 self.current = Pos::E((c, match o {
397                     Ori::Side => Axis::X,
398                     Ori::Back => Axis::Y,
399                     Ori::Top => Axis::Z,
400                 }));
401             },
402         };
403     }
405     fn all_nodes_coord(&self) -> Vec<Coord> {
406         let mut nodes = Vec::new();
407         for x in 0..self.faces.len() {
408             for y in 0..self.faces[x].len() {
409                 for z in 0..self.faces[x][y].len() {
410                     if self.is_node((x, y, z)) {
411                         nodes.push((x, y, z));
412                     }
413                 }
414             }
415         }
416         nodes
417     }
419     fn connecting_edge(&self, f1: Face, f2: Face) -> Option<Edge> {
420         for e1 in self.face_edges(f1) {
421             for e2 in self.face_edges(f2) {
422                 if e1 == e2 {
423                     return Some(e1);
424                 }
425             }
426         }
427         None
428     }
430     fn all_faces(&self) -> Vec<Face> {
431         let mut faces = Vec::new();
432         for n in self.all_nodes_coord() {
433             for &o in [Ori::Top, Ori::Side, Ori::Back].iter() {
434                 if self.is_face((n, o)) {
435                     faces.push((n, o));
436                 }
437             }
438         }
439         faces
440     }
442     fn faces_map(&self) -> Vec<(Face, Vec<Face>)> {
443         let mut map = Vec::new();
444         for f in self.all_faces() {
445             let mut adj_faces = Vec::new();
446             for &e in self.face_edges(f).iter() {
447                 for &adj_f in self.adj_existing_faces(e).iter() {
448                     if f != adj_f {
449                         adj_faces.push(adj_f);
450                     }
451                 }
452             }
453             map.push((f, adj_faces));
454         }
455         map
456     }
458     #[inline]
459     fn face_dot_label_fmt(((x, y, z), o): Face, s: &str) -> String {
460         format!("f{0}_{1}_{2}_{3} [label=\"{0} {1} {2} {3}\" {4}]",
461                 x, y, z, Space::ori_idx(o), s)
462     }
464     #[inline]
465     fn face_dot_fmt(((x, y, z), o): Face) -> String {
466         format!("f{}_{}_{}_{}", x, y, z, Space::ori_idx(o))
467     }
469     fn dot_face_pairs(&self) -> Vec<(Face, Face)> {
470         let mut pairs = Vec::new();
471         {
472             let fmap = self.faces_map();
473             let (f_tx, f_rx): (Sender<(Face, Face)>, Receiver<(Face, Face)>) = mpsc::channel();
474             let mut nof_pairs = 0;
475             for map_chunk in fmap.chunks((fmap.len() / NOF_THREADS) + 1) {
476                 let thread_f_tx = f_tx.clone();
477                 let thread_mc = map_chunk.iter().map(|x| {
478                     nof_pairs += x.1.len();
479                     x.clone()
480                 }).collect::<Vec<(Face, Vec<Face>)>>();
481                 thread::spawn(move || {
482                     for (f, adj_fs) in thread_mc {
483                         for adj_f in adj_fs {
484                             thread_f_tx.send((f, adj_f)).unwrap();
485                         }
486                     }
487                 });
488             }
489             for _ in 0..nof_pairs {
490                 pairs.push(f_rx.recv().unwrap());
491             }
492         }
493         let mut i = 0;
494         pairs.iter().filter_map(|&(a1, b1)| {
495             i += 1;
496             if !pairs.iter().take(i-1)
497                   .any(|&(b2, a2)| a1 == a2 && b1 == b2) {
498                 Some((a1, b1))
499             } else {
500                 None
501             }
502         }).collect::<Vec<(Face, Face)>>()
503     }
505     fn dot_face_decls(&self) -> String {
506         let mut decls = String::new();
507         {
508             let faces = self.all_faces();
509             let (s_tx, s_rx): (Sender<String>, Receiver<String>) = mpsc::channel();
510             for faces_chunk in faces.chunks((faces.len() / NOF_THREADS) + 1) {
511                 let thread_s_tx = s_tx.clone();
512                 let thread_fs = faces_chunk.iter().map(|x| x.clone()).collect::<Vec<Face>>();
513                 let current = self.current;
514                 thread::spawn(move || {
515                     for f in thread_fs {
516                         thread_s_tx.send(format!("    {};\n", Space::face_dot_label_fmt(f,
517                             if Pos::F(f) == current { "color=red" } else { "" })))
518                             .unwrap();
519                     }
520                 });
521             }
522             for _ in 0..faces.len() {
523                 decls.push_str(&s_rx.recv().unwrap());
524             }
525         }
526         decls
527     }
529     pub fn dot_graph_code(&self) -> String {
530         let mut code = String::from("graph {\n");
531         code.push_str(&self.dot_face_decls());
532         for (a, b) in self.dot_face_pairs() {
533             code.push_str(&format!("    {} -- {}{};\n",
534                                    Space::face_dot_fmt(a),
535                                    Space::face_dot_fmt(b),
536                                    if let Some(e) = self.connecting_edge(a, b) {
537                                        if Pos::E(e) == self.current {
538                                            " [color=red]"
539                                        } else { "" }
540                                    } else { "" }));
541         }
542         code.push_str("}");
543         code
544     }
546     #[inline]
547     fn add_empty_node_if_none(&mut self, n: Coord) {
548         if !self.is_node(n) {
549             self.add_empty_node(n);
550         }
551     }
553     fn set_face(&mut self, ((x, y, z), o): Face, v: Option<FaceColor>) {
554         match self.faces[x][y][z] {
555             Some(ref mut f) => {
556                 if f[Space::ori_idx(o)] != v {
557                     self.change = Change::Space;
558                 }
559                 f[Space::ori_idx(o)] = v;
560             },
561             None => panic!("there is no node here"),
562         }
563     }
565     fn face_adj_available_faces(&self, f: Face) -> Vec<Face> {
566         let mut faces = Vec::new();
567         for e in self.face_edges(f) {
568             for adj_f in self.adj_available_faces(e) {
569                 if f != adj_f {
570                     faces.push(adj_f);
571                 }
572             }
573         }
574         faces
575     }
577     fn suround_with_nodes(&mut self, (n, o): Face) {
578         assert!(self.is_node(n));
579         for (nf, _) in self.face_adj_available_faces((n, o)) {
580             self.add_empty_node_if_none(nf);
581         }
582     }
584     #[inline]
585     pub fn add_face(&mut self, f: Face) {
586         self.suround_with_nodes(f);
587         self.set_face(f, Some((1.0, 1.0, 1.0)));
588     }
590     #[inline]
591     pub fn remove_face(&mut self, f: Face) {
592         assert!(self.is_face(f));
593         self.set_face(f, None);
594     }
596     pub fn set_current_face_if_none(&mut self) {
597         match self.current {
598             Pos::F(f) => if !self.is_face(f) { self.add_face(f) },
599             Pos::E(_) => {},
600         }
601     }
604 impl Clone for Space {
605     fn clone(&self) -> Space {
606         Space {
607             size: self.size,
608             faces: self.faces,
609             current: self.current,
610             change: self.change,
611         }
612     }
615 #[derive(Clone)]
616 enum Save {
617     Space(Space),
618     Current(Pos),
619     Size(Edge, usize),
622 pub struct History {
623     saves: Vec<Save>,
624     id: usize,
625     pub change: bool,
628 impl History {
629     fn new() -> History {
630         History {
631             saves: Vec::new(),
632             id: 0,
633             change: false,
634         }
635     }
637     fn add(&mut self, s: Save) {
638         if self.saves.len() > self.id {
639             while self.saves.len() > self.id {
640                 self.saves.pop();
641             }
642         }
643         self.saves.push(s);
644         self.id += 1;
645     }
647     pub fn has_prev(&self) -> bool {
648         self.id > 1
649     }
651     pub fn has_next(&self) -> bool {
652         self.saves.len() > self.id
653     }
655     fn prev(&mut self) -> Save {
656         assert!(self.has_prev());
657         self.id -= 1;
658         self.change = true;
659         self.saves[self.id-1].clone()
660     }
662     fn next(&mut self) -> Save {
663         assert!(self.has_next());
664         self.id += 1;
665         self.change = true;
666         self.saves[self.id-1].clone()
667     }
669     fn current(&self) -> Option<&Save> {
670         if self.id == 0 {
671             None
672         } else {
673             Some(&self.saves[self.id-1])
674         }
675     }
677     fn replace_current(&mut self, s: Save) {
678         assert!(self.id != 0);
679         self.saves[self.id-1] = s;
680     }
683 pub struct Data {
684     pub space: Space,
685     pub history: History,
688 impl Data {
689     pub fn new() -> Data {
690         Data { space: Space::new(), history: History::new() }
691     }
693     fn save_to_add(&self) -> Option<Save> {
694         match self.space.change {
695             Change::Space => {
696                 let mut space = self.space.clone();
697                 space.change = Change::None;
698                 Some(Save::Space(space))
699             }
700             Change::Current => Some(Save::Current(self.space.current)),
701             Change::Size(e, s) => Some(Save::Size(e, s)),
702             Change::None => None,
703         }
704     }
706     pub fn save_if_changed(&mut self) {
707         match self.save_to_add() {
708             Some(Save::Size(e, s)) =>
709                 match self.history.current() {
710                     Some(&Save::Size(e, _)) =>
711                         self.history.replace_current(Save::Size(e, s)),
712                     _ => self.history.add(Save::Size(e, s)),
713                 },
714             Some(s) => self.history.add(s),
715             None => {},
716         }
717         self.space.change = Change::None;
718     }
720     pub fn load_prev(&mut self) {
721         match self.history.prev() {
722             Save::Current(c) => self.space.current = c,
723             Save::Space(s) => self.space = s,
724             Save::Size(e, s) => self.space.edge_size_no_change(e, s),
725         }
726     }
728     pub fn load_next(&mut self) {
729         match self.history.next() {
730             Save::Current(c) => self.space.current = c,
731             Save::Space(s) => self.space = s,
732             Save::Size(e, s) => self.space.edge_size_no_change(e, s),
733         }
734     }
736     pub fn load_prev_if_any(&mut self) {
737         if self.history.has_prev() {
738             self.load_prev();
739         }
740     }
742     pub fn load_next_if_any(&mut self) {
743         if self.history.has_next() {
744             self.load_next();
745         }
746     }