add DropDownList for color selection
[lp74.git] / src / data.rs
blob3fd35491d6ab725c95d8b06c95b8ad071a1e969d
1 use std::usize;
3 const SPACE_SIZE: usize = 11;
4 const NOF_DIM: usize = 3;
5 const DEFAULT_FACE_SIZE: usize = 64;
7 #[derive(Clone, Copy, PartialEq, Debug)]
8 pub enum Axis {
9     X,
10     Y,
11     Z,
14 #[derive(Clone, Copy, PartialEq, Debug)]
15 pub enum Ori {
16     Top,
17     Back,
18     Side,
21 #[derive(Clone, Copy, PartialEq, Debug)]
22 pub enum Pos {
23     E(Edge),
24     F(Face),
27 #[derive(Clone, Copy, PartialEq, Debug)]
28 pub enum Change {
29     None,
30     Current,
31     Size(Edge, usize),
32     Space,
35 #[derive(Clone, Copy, PartialEq, Debug)]
36 pub enum PosKind {
37     Edge,
38     Face,
41 pub type Coord = (usize, usize, usize);
42 pub type Edge = (Coord, Axis);
43 pub type Face = (Coord, Ori);
44 pub type FaceColor = (f32, f32, f32);
45 pub type Surface = [Option<FaceColor>; NOF_DIM];
47 pub struct Space {
48     pub size: [[usize; SPACE_SIZE]; NOF_DIM],
49     pub faces: [[[Option<Surface>; SPACE_SIZE]; SPACE_SIZE]; SPACE_SIZE],
50     pub current: Pos,
51     pub change: Change,
54 impl Space {
55     fn new() -> Space {
56         let mid = SPACE_SIZE / 2;
57         let current_node = (mid, mid, mid);
58         let mut tmp = Space {
59             size: [[DEFAULT_FACE_SIZE; SPACE_SIZE]; NOF_DIM],
60             faces: [[[None; SPACE_SIZE]; SPACE_SIZE]; SPACE_SIZE],
61             current: Pos::E((current_node, Axis::X)),
62             change: Change::None,
63         };
64         tmp.add_empty_node(current_node);
65         tmp.add_face((current_node, Ori::Top));
66         tmp
67     }
69     pub fn axis_idx(a: Axis) -> usize {
70         match a {
71             Axis::X => 0,
72             Axis::Y => 1,
73             Axis::Z => 2,
74         }
75     }
77     pub fn ori_idx(o: Ori) -> usize {
78         match o {
79             Ori::Top => 0,
80             Ori::Side => 1,
81             Ori::Back => 2,
82         }
83     }
85     fn adj_faces(((x, y, z), a): Edge) -> Vec<Face> {
86         let mut faces = Vec::new();
87         match a {
88             Axis::X => {
89                 faces.push(((x, y, z), Ori::Top));
90                 faces.push(((x, y, z), Ori::Back));
91                 if y < (SPACE_SIZE - 1) {
92                     faces.push(((x, y+1, z), Ori::Top));
93                 }
94                 if z > 0 {
95                    faces.push(((x, y, z-1), Ori::Back));
96                 }
97             },
98             Axis::Y => {
99                 faces.push(((x, y, z), Ori::Top));
100                 faces.push(((x, y, z), Ori::Side));
101                 if x > 0 {
102                     faces.push(((x-1, y, z), Ori::Top));
103                 }
104                 if z > 0 {
105                     faces.push(((x, y, z-1), Ori::Side));
106                 }
107             },
108             Axis::Z => {
109                 faces.push(((x, y, z), Ori::Back));
110                 faces.push(((x, y, z), Ori::Side));
111                 if x > 0 {
112                     faces.push(((x-1, y, z), Ori::Back));
113                 }
114                 if y < (SPACE_SIZE - 1) {
115                     faces.push(((x, y+1, z), Ori::Side));
116                 }
117             },
118         }
119         faces
120     }
122     fn is_node(&self, (x, y, z): Coord) -> bool {
123         if x < SPACE_SIZE
124             && y < SPACE_SIZE
125             && z < SPACE_SIZE {
126             if let Some(_) = self.faces[x][y][z] {
127                 true
128             } else {
129                 false
130             }
131         } else {
132             false
133         }
134     }
136     fn is_face(&self, ((x, y, z), o): Face) -> bool {
137         self.is_node((x, y, z))
138             && match self.faces[x][y][z] {
139             Some(faces) => faces[Space::ori_idx(o)] != None,
140             None => false,
141         }
142     }
144     pub fn current_node_coord(&self) -> Coord {
145         match self.current {
146             Pos::E((n, _)) => n,
147             Pos::F((n, _)) => n,
148         }
149     }
151     pub fn row_size_before_current(&self, a: Axis) -> usize {
152         let (xcur, ycur, zcur) = self.current_node_coord();
153         let mut res = 0;
154         match a {
155             Axis::X => {
156                 for x in 0..xcur {
157                     res += self.size[Space::axis_idx(Axis::X)][x];
158                 }
159             },
160             Axis::Y => {
161                 for y in 0..ycur {
162                     res += self.size[Space::axis_idx(Axis::Y)][y];
163                 }
164             },
165             Axis::Z => {
166                 for z in 0..zcur {
167                     res += self.size[Space::axis_idx(Axis::Z)][z];
168                 }
169             },
170         }
171         res
172     }
174     pub fn row_size(&self, a: Axis) -> usize {
175         self.size[Space::axis_idx(a)].iter()
176             .fold(0, |row, &s| row + s)
177     }
179     pub fn get_edge_size(&self, ((x, y, z), a): Edge) -> usize {
180         //assert!(self.is_edge(((x, y, z), a)));
181         self.size[Space::axis_idx(a)][match a {
182             Axis::X => x,
183             Axis::Y => y,
184             Axis::Z => z,
185         }]
186     }
188     pub fn set_current_face_color_if_any(&mut self, c: FaceColor) {
189         match self.current {
190             Pos::E(_) => panic!("current is not a face"),
191             Pos::F(((x, y, z), o)) => match self.faces[x][y][z] {
192                 Some(ref mut f) => f[Space::ori_idx(o)] = Some(c),
193                 None => panic!("no face here"),
194             },
195         }
196     }
198     fn edge_size_no_change(&mut self, ((x, y, z), a): Edge, new_size: usize) {
199         //assert!(self.is_edge(((x, y, z), a)));
200         let size = &mut self.size[Space::axis_idx(a)][match a {
201             Axis::X => x,
202             Axis::Y => y,
203             Axis::Z => z,
204         }];
205         if *size != new_size {
206             *size = new_size;
207         }
208     }
210     pub fn edge_size(&mut self, e: Edge, new_size: usize) {
211         self.edge_size_no_change(e, new_size);
212         self.change = Change::Size(e, new_size);
213     }
215     pub fn inc_size(&mut self) {
216         match self.current {
217             Pos::E(e) => {
218                 let size = self.get_edge_size(e);
219                 if size < usize::MAX {
220                     self.edge_size(e, size + 1);
221                 }
222             },
223             Pos::F(_) => panic!("resize on a face"),
224         }
225     }
227     pub fn dec_size(&mut self) {
228         match self.current {
229             Pos::E(e) => {
230                 let size = self.get_edge_size(e);
231                 if size > 0 {
232                     self.edge_size(e, size - 1);
233                 }
234             },
235             Pos::F(_) => panic!("resize on a face"),
236         }
237     }
239     fn face_edges(&self, ((x, y, z), o): Face) -> Vec<Edge> {
240         let mut edges = Vec::new();
241         match o {
242             Ori::Top => {
243                 edges.push(((x, y, z), Axis::X));
244                 edges.push(((x, y, z), Axis::Y));
245                 if x < SPACE_SIZE-1 {
246                     edges.push(((x+1, y, z), Axis::Y));
247                 }
248                 if y > 0 {
249                     edges.push(((x, y-1, z), Axis::X));
250                 }
251             },
252             Ori::Back => {
253                 edges.push(((x, y, z), Axis::X));
254                 edges.push(((x, y, z), Axis::Z));
255                 if x < SPACE_SIZE-1 {
256                     edges.push(((x+1, y, z), Axis::Z));
257                 }
258                 if z < SPACE_SIZE-1 {
259                     edges.push(((x, y, z+1), Axis::X));
260                 }
261             },
262             Ori::Side => {
263                 edges.push(((x, y, z), Axis::Y));
264                 edges.push(((x, y, z), Axis::Z));
265                 if y > 0 {
266                     edges.push(((x, y-1, z), Axis::Z));
267                 }
268                 if z < SPACE_SIZE-1 {
269                     edges.push(((x, y, z+1), Axis::Y));
270                 }
271             },
272         }
273         edges
274     }
276     fn add_empty_node(&mut self, (x, y, z): Coord) {
277         assert!(!self.is_node((x, y, z)));
278         self.faces[x][y][z] = Some([None; NOF_DIM]);
279         println!("empty node change");
280         self.change = Change::Space;
281     }
283     fn adj_available_faces(&self, e: Edge) -> Vec<Face> {
284         Space::adj_faces(e).iter()
285             .filter_map(|&adj_f| if self.is_face(adj_f) {
286                 None
287             } else {
288                 Some(adj_f)
289             }).collect::<Vec<_>>()
290     }
292     fn adj_existing_faces(&self, e: Edge) -> Vec<Face> {
293         Space::adj_faces(e).iter()
294             .filter_map(|&adj_f| if self.is_face(adj_f) {
295                 Some(adj_f)
296             } else {
297                 None
298             }).collect::<Vec<_>>()
299     }
301     pub fn dec_pos(&mut self) {
302         let tmp = match self.current {
303             Pos::E(((mut x, mut y, mut z), a)) => {
304                 match a {
305                     Axis::X => x -= 1,
306                     Axis::Y => y -= 1,
307                     Axis::Z => z -= 1,
308                 };
309                 (x, y, z)
310             },
311             Pos::F(((mut x, mut y, mut z), o)) => {
312                 match o {
313                     Ori::Top => z -= 1,
314                     Ori::Back => y -= 1,
315                     Ori::Side => x -= 1,
316                 };
317                 (x, y, z)
318             },
319         };
320         if self.is_node(tmp) {
321             println!("pos change");
322             self.change = Change::Current;
323             match self.current {
324                 Pos::E((ref mut n, _)) => *n = tmp,
325                 Pos::F((ref mut n, _)) => *n = tmp,
326             }
327         };
328     }
330     pub fn inc_pos(&mut self) {
331         let tmp = match self.current {
332             Pos::E(((mut x, mut y, mut z), a)) => {
333                 match a {
334                     Axis::X => x += 1,
335                     Axis::Y => y += 1,
336                     Axis::Z => z += 1,
337                 };
338                 (x, y, z)
339             },
340             Pos::F(((mut x, mut y, mut z), o)) => {
341                 match o {
342                     Ori::Top => z += 1,
343                     Ori::Back => y += 1,
344                     Ori::Side => x += 1,
345                 };
346                 (x, y, z)
347             },
348         };
349         if self.is_node(tmp) {
350             println!("pos change");
351             self.change = Change::Current;
352             match self.current {
353                 Pos::E((ref mut n, _)) => *n = tmp,
354                 Pos::F((ref mut n, _)) => *n = tmp,
355             }
356         };
357     }
359     pub fn rotate(&mut self) {
360         println!("rotate change");
361         self.change = Change::Current;
362         match self.current {
363             Pos::E((_, ref mut a)) => match *a {
364                 Axis::X => *a = Axis::Y,
365                 Axis::Y => *a = Axis::Z,
366                 Axis::Z => *a = Axis::X,
367             },
368             Pos::F((_, ref mut o)) => match *o {
369                 Ori::Top => *o = Ori::Back,
370                 Ori::Back => *o = Ori::Side,
371                 Ori::Side => *o = Ori::Top,
372             },
373         }
374     }
376     pub fn set_pos_kind(&mut self, pk: PosKind) {
377         match pk {
378             PosKind::Face => if let Pos::E((c, a)) = self.current {
379                 self.change = Change::Current;
380                 self.current = Pos::F((c, match a {
381                     Axis::X => Ori::Side,
382                     Axis::Y => Ori::Back,
383                     Axis::Z => Ori::Top,
384                 }));
385             },
386             PosKind::Edge => if let Pos::F((c, o)) = self.current {
387                 self.change = Change::Current;
388                 self.current = Pos::E((c, match o {
389                     Ori::Side => Axis::X,
390                     Ori::Back => Axis::Y,
391                     Ori::Top => Axis::Z,
392                 }));
393             },
394         };
395     }
397     pub fn switch_pos_type(&mut self) {
398         println!("switch change");
399         match self.current {
400             Pos::E(_) => self.set_pos_kind(PosKind::Face),
401             Pos::F(_) => self.set_pos_kind(PosKind::Edge),
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     fn face_dot_label_fmt(((x, y, z), o): Face, s: &str) -> String {
459         format!("f{0}_{1}_{2}_{3} [label=\"{0} {1} {2} {3}\" {4}]",
460                 x, y, z, Space::ori_idx(o), s)
461     }
463     fn face_dot_fmt(((x, y, z), o): Face) -> String {
464         format!("f{}_{}_{}_{}", x, y, z, Space::ori_idx(o))
465     }
467     pub fn dot_graph_code(&self) -> String {
468         let mut code = String::from("graph {\n");
469         let mut pairs = Vec::new();
470         for (f, adj_fs) in self.faces_map() {
471             code.push_str(&format!("    {};\n", Space::face_dot_label_fmt(f,
472                 if Pos::F(f) == self.current { "color=red" } else { "" })));
473             for adj_f in adj_fs {
474                 pairs.push((f, adj_f));
475             }
476         }
477         let mut i = 0;
478         let pairs_clean = pairs.iter().filter(|&&(a1, b1)| {
479             i += 1;
480             !pairs.iter().take(i-1)
481                   .any(|&(b2, a2)| a1 == a2 && b1 == b2)
482         }).collect::<Vec<_>>();
483         for &(a, b) in pairs_clean {
484             code.push_str(&format!("    {} -- {} {};\n",
485                                    Space::face_dot_fmt(a),
486                                    Space::face_dot_fmt(b),
487                                    if let Some(e) = self.connecting_edge(a, b) {
488                                        if Pos::E(e) == self.current {
489                                            "[color=red]"
490                                        } else { "" }
491                                    } else { "" }));
492         }
493         code.push_str("}");
494         println!("{}", code);
495         code
496     }
498     fn add_empty_node_if_none(&mut self, n: Coord) {
499         if !self.is_node(n) {
500             self.add_empty_node(n);
501         }
502     }
504     fn set_face(&mut self, ((x, y, z), o): Face, v: Option<FaceColor>) {
505         match self.faces[x][y][z] {
506             Some(ref mut f) => {
507                 if f[Space::ori_idx(o)] != v {
508                     println!("face change");
509                     self.change = Change::Space;
510                 }
511                 f[Space::ori_idx(o)] = v;
512             },
513             None => panic!("there is no node here"),
514         }
515     }
517     fn face_adj_available_faces(&self, f: Face) -> Vec<Face> {
518         let mut faces = Vec::new();
519         for e in self.face_edges(f) {
520             for adj_f in self.adj_available_faces(e) {
521                 if f != adj_f {
522                     faces.push(adj_f);
523                 }
524             }
525         }
526         faces
527     }
529     fn suround_with_nodes(&mut self, (n, o): Face) {
530         assert!(self.is_node(n));
531         for (nf, _) in self.face_adj_available_faces((n, o)) {
532             self.add_empty_node_if_none(nf);
533         }
534     }
536     pub fn add_face(&mut self, f: Face) {
537         self.suround_with_nodes(f);
538         self.set_face(f, Some((1.0, 1.0, 1.0)));
539     }
541     pub fn remove_face(&mut self, f: Face) {
542         assert!(self.is_face(f));
543         //panic!("not yet implemented");
544         self.set_face(f, None);
545     }
547     pub fn set_current_face_if_none(&mut self) {
548         match self.current {
549             Pos::F(f) => if !self.is_face(f) { self.add_face(f) },
550             Pos::E(_) => {},
551         }
552     }
554     //fn is_edge(&self, (c, a): Edge) -> bool {
555     //    assert!(self.is_node(c));
556     //    self.is_adj_existing_faces((c, a))
557     //}
559     //pub fn row_size_after_current(&self, a: Axis) -> usize {
560     //    let (xcur, ycur, zcur) = self.current_node_coord();
561     //    let mut res = 0;
562     //    match a {
563     //        Axis::X => {
564     //            let xidx = Space::axis_idx(Axis::X);
565     //            for x in xcur..self.size[xidx].len() {
566     //                res += self.size[xidx][x];
567     //            }
568     //        },
569     //        Axis::Y => {
570     //            let yidx = Space::axis_idx(Axis::Y);
571     //            for y in ycur..self.size[yidx].len() {
572     //                res += self.size[yidx][y];
573     //            }
574     //        },
575     //        Axis::Z => {
576     //            let zidx = Space::axis_idx(Axis::Z);
577     //            for z in zcur..self.size[zidx].len() {
578     //                res += self.size[zidx][z];
579     //            }
580     //        },
581     //    }
582     //    res
583     //}
585     //pub fn get_current_face_color_if_any(&self) -> Option<FaceColor> {
586     //    match self.current {
587     //        Pos::E(_) => None,
588     //        Pos::F(((x, y, z), o)) => match self.faces[x][y][z] {
589     //            Some(ref f) => f[Space::ori_idx(o)],
590     //            None => None,
591     //        },
592     //    }
593     //}
595     //fn is_adj_existing_faces(&self, e: Edge) -> bool {
596     //    for f in Space::adj_faces(e).iter() {
597     //        if self.is_face(*f) {
598     //            return true;
599     //        }
600     //    }
601     //    false
602     //}
604     //fn remove_node(&mut self, (x, y, z): Coord) {
605     //    assert!(self.is_node((x, y, z)));
606     //    panic!("nothing here");
607     //}
609     //fn remove_node_if_any(&mut self, n: Coord) {
610     //    if self.is_node(n) {
611     //        self.remove_node(n);
612     //    }
613     //}
615     //fn face_adj_existing_faces(&self, f: Face) -> Vec<Face> {
616     //    let mut faces = Vec::new();
617     //    for e in self.face_edges(f) {
618     //        for adj_f in self.adj_existing_faces(e) {
619     //            if f != adj_f {
620     //                faces.push(adj_f);
621     //            }
622     //        }
623     //    }
624     //    faces
625     //}
628 impl Clone for Space {
629     fn clone(&self) -> Space {
630         Space {
631             size: self.size,
632             faces: self.faces,
633             current: self.current,
634             change: self.change,
635         }
636     }
639 #[derive(Clone)]
640 enum Save {
641     Space(Space),
642     Current(Pos),
643     Size(Edge, usize),
646 pub struct History {
647     saves: Vec<Save>,
648     id: usize,
649     pub change: bool,
652 impl History {
653     fn new() -> History {
654         History {
655             saves: Vec::new(),
656             id: 0,
657             change: false,
658         }
659     }
661     fn add(&mut self, s: Save) {
662         if self.saves.len() > self.id {
663             println!("clear next saves");
664             while self.saves.len() > self.id {
665                 self.saves.pop();
666             }
667         }
668         self.saves.push(s);
669         self.id += 1;
670     }
672     pub fn has_prev(&self) -> bool {
673         self.id > 1
674     }
676     pub fn has_next(&self) -> bool {
677         self.saves.len() > self.id
678     }
680     fn prev(&mut self) -> Save {
681         assert!(self.has_prev());
682         self.id -= 1;
683         self.change = true;
684         self.saves[self.id-1].clone()
685     }
687     fn next(&mut self) -> Save {
688         assert!(self.has_next());
689         self.id += 1;
690         self.change = true;
691         self.saves[self.id-1].clone()
692     }
694     fn current(&self) -> Option<&Save> {
695         if self.id == 0 {
696             None
697         } else {
698             Some(&self.saves[self.id-1])
699         }
700     }
702     fn replace_current(&mut self, s: Save) {
703         assert!(self.id != 0);
704         self.saves[self.id-1] = s;
705     }
708 pub struct Data {
709     pub space: Space,
710     pub history: History,
713 impl Data {
714     pub fn new() -> Data {
715         Data { space: Space::new(), history: History::new() }
716     }
718     fn save_to_add(&self) -> Option<Save> {
719         match self.space.change {
720             Change::Space => {
721                 let mut space = self.space.clone();
722                 space.change = Change::None;
723                 Some(Save::Space(space))
724             }
725             Change::Current => Some(Save::Current(self.space.current)),
726             Change::Size(e, s) => Some(Save::Size(e, s)),
727             Change::None => None,
728         }
729     }
731     pub fn save_if_changed(&mut self) {
732         match self.save_to_add() {
733             Some(Save::Size(e, s)) =>
734                 match self.history.current() {
735                     Some(&Save::Size(e, _)) =>
736                         self.history.replace_current(Save::Size(e, s)),
737                     _ => self.history.add(Save::Size(e, s)),
738                 },
739             Some(s) => self.history.add(s),
740             None => {},
741         }
742         self.space.change = Change::None;
743     }
745     pub fn load_prev(&mut self) {
746         println!("load prev");
747         match self.history.prev() {
748             Save::Current(c) => self.space.current = c,
749             Save::Space(s) => self.space = s,
750             Save::Size(e, s) => self.space.edge_size_no_change(e, s),
751         }
752     }
754     pub fn load_next(&mut self) {
755         println!("load next");
756         match self.history.next() {
757             Save::Current(c) => self.space.current = c,
758             Save::Space(s) => self.space = s,
759             Save::Size(e, s) => self.space.edge_size_no_change(e, s),
760         }
761     }
763     pub fn load_prev_if_any(&mut self) {
764         if self.history.has_prev() {
765             self.load_prev();
766         }
767     }
769     pub fn load_next_if_any(&mut self) {
770         if self.history.has_next() {
771             self.load_next();
772         }
773     }