use axes_common::*;
use axes2d::*;
use axes3d::*;
use std::cell::RefCell;
use std::old_io::File;
use std::old_io::BufferedWriter;
use std::old_path::Path;
use std::old_io::process::{Command, Process};
pub use self::AxesVariant::*;
enum AxesVariant
{
Axes2DType(Axes2D),
Axes3DType(Axes3D)
}
impl AxesVariant
{
fn write_out(&self, writer: &mut Writer)
{
match *self
{
Axes2DType(ref a) => a.write_out(writer),
Axes3DType(ref a) => a.write_out(writer)
}
}
fn get_common_data<'l>(&'l self) -> &'l AxesCommonData
{
match *self
{
Axes2DType(ref a) => a.get_common_data(),
Axes3DType(ref a) => a.get_common_data()
}
}
}
pub struct Figure
{
axes: Vec<AxesVariant>,
terminal: String,
output_file: String,
gnuplot: RefCell<Option<Process>>
}
impl Figure
{
pub fn new() -> Figure
{
Figure
{
axes: Vec::new(),
terminal: "".to_string(),
output_file: "".to_string(),
gnuplot: RefCell::new(None),
}
}
pub fn set_terminal<'l>(&'l mut self, terminal: &str, output_file: &str) -> &'l mut Figure
{
self.terminal = terminal.to_string();
self.output_file = output_file.to_string();
self
}
pub fn axes2d(&mut self) -> &mut Axes2D
{
self.axes.push(Axes2DType(new_axes2d()));
let l = self.axes.len();
match self.axes.as_mut_slice()[l - 1]
{
Axes2DType(ref mut a) => a,
_ => unreachable!()
}
}
pub fn axes3d(&mut self) -> &mut Axes3D
{
self.axes.push(Axes3DType(new_axes3d()));
let l = self.axes.len();
match self.axes.as_mut_slice()[l - 1]
{
Axes3DType(ref mut a) => a,
_ => unreachable!()
}
}
pub fn show(&mut self) -> &Figure
{
if self.axes.len() == 0
{
return self;
}
if self.gnuplot.borrow().is_none()
{
*self.gnuplot.borrow_mut() = Some(Command::new("gnuplot").arg("-p").spawn().ok().expect("Couldn't spawn gnuplot"));
}
self.gnuplot.borrow_mut().as_mut().map(|p|
{
self.echo(p.stdin.as_mut().unwrap());
});
self
}
pub fn clear_axes(&mut self) -> &Figure
{
self.axes.clear();
self
}
pub fn echo<'l, T: Writer>(&'l self, writer: &mut T) -> &'l Figure
{
let w = writer as &mut Writer;
if self.axes.len() == 0
{
return self;
}
if self.terminal.len() > 0
{
writeln!(w, "set terminal {}", self.terminal);
}
if self.output_file.len() > 0
{
writeln!(w, "set output \"{}\"", self.output_file);
}
writeln!(w, "set termoption dashed");
writeln!(w, "set termoption enhanced");
if self.axes.len() > 1
{
writeln!(w, "set multiplot");
}
writeln!(w, "set tics front");
for e in self.axes.iter()
{
writeln!(w, "reset");
let c = e.get_common_data();
c.grid_pos.map(|pos|
{
let width = 1.0 / (c.grid_cols as f64);
let height = 1.0 / (c.grid_rows as f64);
let x = (pos % c.grid_cols) as f64 * width;
let y = 1.0 - (1.0 + (pos / c.grid_cols) as f64) * height;
writeln!(w, "set origin {:.12e},{:.12e}", x, y);
writeln!(w, "set size {:.12e},{:.12e}", width, height);
});
e.write_out(w);
}
if self.axes.len() > 1
{
writeln!(w, "unset multiplot");
}
self
}
pub fn echo_to_file<'l>(&'l self, filename: &str) -> &'l Figure
{
if self.axes.len() == 0
{
return self;
}
let mut file = BufferedWriter::new(File::create(&Path::new(filename)).unwrap());
self.echo(&mut file);
file.flush();
self
}
}