Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add support for multiplot options #52

Closed
wants to merge 1 commit into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -105,5 +105,10 @@ path = "examples/patterns.rs"
name = "inverse_api"
path = "examples/inverse_api.rs"

[[example]]

name = "multiplot_options"
path = "examples/multiplot_options.rs"

[dependencies]
byteorder = "1.3.1"
45 changes: 45 additions & 0 deletions examples/multiplot_options.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
// This file is released into Public Domain.
use crate::common::*;
use gnuplot::{MultiplotFillOrder::*, MultiplotFillDirection::*};

use gnuplot::*;

mod common;

fn example(c: Common)
{
let mut fg = Figure::new();
fg.set_multiplot_layout(2,2)
.set_title("Multiple parabolas")
.set_scale(0.5, 0.5)
.set_offset(0.0, 0.0)
.set_multiplot_fill_order(RowsFirst, Upwards);

fg.axes2d()
.lines(
&[-3., -2., -1., 0., 1., 2., 3.],
&[9., 4., 1., 0., 1., 4., 9.],
&[Caption("Parabola 1")],
);

fg.axes2d()
.lines(
&[-3., -2., -1., 0., 1., 2., 3.],
&[10., 5., 2., 0., 2., 5., 10.],
&[Caption("Parabola 2")],
);

fg.axes2d()
.lines(
&[-3., -2., -1., 0., 1., 2., 3.],
&[11., 6., 3., 0., 3., 6., 11.],
&[Caption("Parabola 3")],
);

c.show(&mut fg, "fg.multiplot.gnuplot");
}

fn main()
{
Common::new().map(|c| example(c));
}
128 changes: 126 additions & 2 deletions src/figure.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ use crate::axes2d::*;
use crate::axes3d::*;

use crate::axes_common::*;
use crate::options::GnuplotVersion;
use crate::options::{GnuplotVersion, MultiplotFillOrder, MultiplotFillDirection};
use crate::writer::Writer;
use std::cell::RefCell;
use std::fs::File;
Expand Down Expand Up @@ -51,6 +51,37 @@ impl AxesVariant
}
}

/// A struct that contains all the multiplot layout options
struct MultiplotOptions {
rows: usize,
columns: usize,
title: Option<String>,
scale_x: Option<f32>,
scale_y: Option<f32>,
offset_x: Option<f32>,
offset_y: Option<f32>,
fill_order: Option<MultiplotFillOrder>,
fill_direction: Option<MultiplotFillDirection>
}

impl MultiplotOptions
{
pub fn new() -> MultiplotOptions
{
MultiplotOptions {
rows: 1,
columns: 1,
title: None,
scale_x: None,
scale_y: None,
offset_x: None,
offset_y: None,
fill_order: None,
fill_direction: None
}
}
}

/// A figure that may contain multiple axes
pub struct Figure
{
Expand All @@ -63,6 +94,7 @@ pub struct Figure
// RefCell so that we can echo to it
gnuplot: RefCell<Option<Child>>,
version: Option<GnuplotVersion>,
multiplot_options: Option<MultiplotOptions>
}

impl Default for GnuplotVersion
Expand All @@ -87,6 +119,7 @@ impl Figure
post_commands: "".into(),
pre_commands: "".into(),
version: None,
multiplot_options: None
}
}

Expand Down Expand Up @@ -148,6 +181,69 @@ impl Figure
self.version.unwrap_or_default()
}

/// Define the layout for the multiple plots
/// # Arguments
/// * `rows` - Number of rows
/// * `columns` - Number of columns
pub fn set_multiplot_layout<'l>(&'l mut self, rows: usize, columns: usize) -> &'l mut Self
{
let multiplot_options = self.multiplot_options.get_or_insert(MultiplotOptions::new());
multiplot_options.rows = rows;
multiplot_options.columns = columns;

self
}

/// Set the multiplot title
/// # Arguments
/// * `title` - Name of the file
pub fn set_title<'l>(&'l mut self, title: &str) -> &'l mut Self
{
let multiplot_options = self.multiplot_options.get_or_insert(MultiplotOptions::new());
multiplot_options.title = Some(title.into());

self
}

/// Applies a horizontal and vertical scale to each plot
/// # Arguments
/// * `scale_x` - Horizonal scale applied to each plot
/// * `scale_y` - Vertical scale applied to each plot
pub fn set_scale<'l>(&'l mut self, scale_x: f32, scale_y: f32) -> &'l mut Self
{
let multiplot_options = self.multiplot_options.get_or_insert(MultiplotOptions::new());
multiplot_options.scale_x = Some(scale_x);
multiplot_options.scale_y = Some(scale_y);

self
}

/// Applies a horizontal and vertical offset to each plot
/// # Arguments
/// * `offset_x` - Horizontal offset applied to each plot
/// * `offset_y` - Horizontal offset applied to each plot
pub fn set_offset<'l>(&'l mut self, offset_x: f32, offset_y: f32) -> &'l mut Self
{
let multiplot_options = self.multiplot_options.get_or_insert(MultiplotOptions::new());
multiplot_options.offset_x = Some(offset_x);
multiplot_options.offset_y = Some(offset_y);

self
}

/// Defines the order in which plots fill the layout. Default is RowsFirst and Downwards.
/// # Arguments
/// * `order` - Options: RowsFirst, ColumnsFirst
/// * `direction` - Options: Downwards, Upwards
pub fn set_multiplot_fill_order<'l>(&'l mut self, order: MultiplotFillOrder, direction: MultiplotFillDirection) -> &'l mut Self
{
let multiplot_options = self.multiplot_options.get_or_insert(MultiplotOptions::new());
multiplot_options.fill_order = Some(order);
multiplot_options.fill_direction = Some(direction);

self
}

/// Creates a set of 2D axes
pub fn axes2d(&mut self) -> &mut Axes2D
{
Expand Down Expand Up @@ -416,8 +512,36 @@ impl Figure
);
if self.axes.len() > 1
{
writeln!(w, "set multiplot");
let mut multiplot_options_string = "".to_string();
if let Some(m) = &self.multiplot_options {
let fill_order = match m.fill_order {
None => "",
Some(fo) =>
match fo {
MultiplotFillOrder::RowsFirst => " rowsfirst",
MultiplotFillOrder::ColumnsFirst => " columnsfirst"
}
};

let fill_direction = match m.fill_direction {
None => "",
Some(fd) =>
match fd {
MultiplotFillDirection::Downwards => " downwards",
MultiplotFillDirection::Upwards => " upwards"
}
};

let title = m.title.as_ref().map_or("".to_string(), |t| format!(" title \"{}\"", t));
let scale = m.scale_x.map_or("".to_string(), |s| format!(" scale {},{}", s, m.offset_x.unwrap()));
let offset = m.offset_x.map_or("".to_string(), |o| format!(" offset {},{}", o, m.offset_y.unwrap()));

multiplot_options_string = format!(" layout {},{}{}{}{}{}{}", m.rows, m.columns, fill_order, fill_direction, title, scale, offset);
}

writeln!(w, "set multiplot{}", multiplot_options_string);
}

// TODO: Maybe add an option for this (who seriously prefers them in the back though?)
writeln!(w, "set tics front");

Expand Down
18 changes: 18 additions & 0 deletions src/options.rs
Original file line number Diff line number Diff line change
Expand Up @@ -439,3 +439,21 @@ pub enum FillPatternType
SmallForwardSlashes = 7,
Pattern8 = 8,
}

/// Multiplot Fill Order Options
#[derive(Copy, Clone, Debug, PartialOrd, Ord, PartialEq, Eq)]
pub enum MultiplotFillOrder {
/// "rowsfirst" gnuplot option.
RowsFirst,
/// "columnfirst" gnuplot option.
ColumnsFirst
}

/// Multiplot Fill Order Options
#[derive(Copy, Clone, Debug, PartialOrd, Ord, PartialEq, Eq)]
pub enum MultiplotFillDirection {
/// "downward" gnuplot option.
Downwards,
/// "upward" gnuplot option.
Upwards
}