1pub mod geometry;
2
3use std::path::Path;
4use std::error::Error;
5use std::fs::File;
6use std::io::{Read,Write,BufWriter,BufReader};
7use serde::{Serialize,Deserialize};
8
9pub use crate::geometry::{point,rectangle,Point,Rectangle};
10
11pub type Color = u16;
12
13#[derive(Debug,Clone,Serialize,Deserialize)]
14pub enum Command {
15 Points{ color:Color,points:Vec<Point> },
16 Lines{ color:Color,lines:Vec<Vec<Point>> }
17}
18
19#[derive(Debug,Clone,Serialize,Deserialize)]
20pub struct Plot {
21 pub commands:Vec<Command>
22}
23
24#[derive(Debug,Clone,Serialize,Deserialize)]
25pub struct Page {
26 pub plots:Vec<Plot>
27}
28
29#[derive(Debug,Clone,Serialize,Deserialize)]
30pub struct Book {
31 pub pages:Vec<Page>
32}
33
34impl Command {
35 pub fn line(color:Color,p1:Point,p2:Point)->Command {
36 Self::Lines{ color,lines:vec![vec![p1,p2]] }
37 }
38
39 pub fn rectangle(color:Color,Rectangle{ a:p0,b:p1 }:Rectangle)->Command {
40 Self::Lines{ color, lines:vec![vec![p0,p0.with_x(p1),p1,p1.with_x(p0),p0]] }
41 }
42}
43
44impl Page {
45 pub fn new()->Self {
46 Self{ plots:Vec::new() }
47 }
48
49 pub fn len(&self)->usize {
50 self.plots.len()
51 }
52
53 pub fn is_empty(&self)->bool {
54 self.plots.is_empty()
55 }
56
57 pub fn plot(&mut self,pl:Plot) {
58 self.plots.push(pl);
59 }
60
61 pub fn get_plot(&self,k:isize)->Option<&Plot> {
62 let m = self.len();
63 if m == 0 {
64 None
65 } else {
66 let i = k.rem_euclid(m as isize) as usize;
67 Some(&self.plots[i])
68 }
69 }
70}
71
72impl Default for Page {
73 fn default()->Self {
74 Self::new()
75 }
76}
77
78impl Plot {
79 pub fn new()->Self {
80 Self{ commands:Vec::new() }
81 }
82
83 pub fn point(&mut self,color:Color,p:Point) {
84 self.command(Command::Points{ color,points:vec![p] });
85 }
86
87 pub fn line(&mut self,color:Color,p1:Point,p2:Point) {
88 self.command(Command::Lines{ color,lines:vec![vec![p1,p2]] });
89 }
90
91 pub fn lines(&mut self,color:Color,lines:Vec<Vec<Point>>) {
92 self.command(Command::Lines{ color,lines });
93 }
94
95 pub fn rectangle(&mut self,color:Color,Rectangle{ a:p0,b:p1 }:Rectangle) {
96 self.lines(color,vec![vec![p0,p0.with_x(p1),p1,p1.with_x(p0),p0]]);
97 }
98
99 pub fn command(&mut self,cmd:Command) {
100 self.commands.push(cmd);
101 }
102
103 pub fn bounding(&self)->Rectangle {
104 let mut r = Rectangle::empty();
105 for cmd in self.commands.iter() {
106 match cmd {
107 Command::Points{ points, .. } => {
108 for &p in points.iter() {
109 r.add_point(p);
110 }
111 },
112 Command::Lines{ lines, .. } => {
113 for line in lines.iter() {
114 for &p in line.iter() {
115 r.add_point(p);
116 }
117 }
118 }
119 }
120 }
121 r
122 }
123}
124
125impl Default for Plot {
126 fn default()->Self {
127 Self::new()
128 }
129}
130
131impl Book {
132 pub fn new()->Self {
133 Self{ pages:Vec::new() }
134 }
135
136 pub fn write<W:Write>(&self,w:&mut W)->Result<(),Box<dyn Error>> {
137 self.serialize(&mut rmp_serde::Serializer::new(w))?;
138 Ok(())
139 }
140
141 pub fn read<R:Read>(r:&mut R)->Result<Self,Box<dyn Error>> {
142 let this : Self = rmp_serde::decode::from_read(r)?;
143 Ok(this)
144 }
145
146 pub fn save_to_file<P:AsRef<Path>>(&self,path:P)->Result<(),Box<dyn Error>> {
147 let fd = File::create(path)?;
148 let mut buf = BufWriter::new(fd);
149 self.write(&mut buf)
150 }
151
152 pub fn load_from_file<P:AsRef<Path>>(path:P)->Result<Self,Box<dyn Error>> {
153 let fd = File::open(path)?;
154 let mut buf = BufReader::new(fd);
155 Self::read(&mut buf)
156 }
157
158 pub fn get_page(&self,k:isize)->Option<&Page> {
159 let m = self.pages.len();
160 if m == 0 {
161 None
162 } else {
163 let i = k.rem_euclid(m as isize) as usize;
164 Some(&self.pages[i])
165 }
166 }
167
168 pub fn page(&mut self,page:Page) {
169 self.pages.push(page);
170 }
171}
172
173impl Default for Book {
174 fn default()->Self {
175 Self::new()
176 }
177}