extern crate libc;
use self::libc::{c_char, c_double, c_float, c_int, c_uint};
use crate::array::Array;
use crate::defines::AfError;
use crate::defines::{ColorMap, MarkerType};
use crate::error::HANDLE_ERROR;
use crate::util::{AfArray, CellPtr, HasAfEnum, MutWndHandle, WndHandle};
use std::ffi::CString;
use std::ptr;
#[allow(dead_code)]
extern "C" {
fn af_create_window(out: MutWndHandle, w: c_int, h: c_int, title: *const c_char) -> c_int;
fn af_set_position(wnd: WndHandle, x: c_uint, y: c_uint) -> c_int;
fn af_set_title(wnd: WndHandle, title: *const c_char) -> c_int;
fn af_set_size(wnd: WndHandle, w: c_uint, h: c_uint) -> c_int;
fn af_set_visibility(wnd: WndHandle, is_visible: c_int) -> c_int;
fn af_set_axes_titles(
wnd: WndHandle,
xtitle: *const c_char,
ytitle: *const c_char,
ztitle: *const c_char,
props: CellPtr,
) -> c_int;
fn af_set_axes_limits_compute(
wnd: WndHandle,
x: AfArray,
y: AfArray,
z: AfArray,
exact: c_int,
props: CellPtr,
) -> c_int;
fn af_set_axes_limits_2d(
wnd: WndHandle,
xmin: c_float,
xmax: c_float,
ymin: c_float,
ymax: c_float,
exact: c_int,
props: CellPtr,
) -> c_int;
fn af_set_axes_limits_3d(
wnd: WndHandle,
xmin: c_float,
xmax: c_float,
ymin: c_float,
ymax: c_float,
zmin: c_float,
zmax: c_float,
exact: c_int,
props: CellPtr,
) -> c_int;
fn af_draw_image(wnd: WndHandle, arr: AfArray, props: CellPtr) -> c_int;
fn af_draw_hist(
wnd: WndHandle,
x: AfArray,
minval: c_double,
maxval: c_double,
props: CellPtr,
) -> c_int;
fn af_draw_surface(
wnd: WndHandle,
xvals: AfArray,
yvals: AfArray,
S: AfArray,
props: CellPtr,
) -> c_int;
fn af_draw_plot_2d(wnd: WndHandle, x: AfArray, y: AfArray, props: CellPtr) -> c_int;
fn af_draw_plot_3d(wnd: WndHandle, x: AfArray, y: AfArray, z: AfArray, props: CellPtr)
-> c_int;
fn af_draw_plot_nd(wnd: WndHandle, P: AfArray, props: CellPtr) -> c_int;
fn af_draw_scatter_2d(
wnd: WndHandle,
x: AfArray,
y: AfArray,
marker: c_int,
props: CellPtr,
) -> c_int;
fn af_draw_scatter_3d(
wnd: WndHandle,
x: AfArray,
y: AfArray,
z: AfArray,
marker: c_int,
props: CellPtr,
) -> c_int;
fn af_draw_scatter_nd(wnd: WndHandle, P: AfArray, marker: c_int, props: CellPtr) -> c_int;
fn af_draw_vector_field_2d(
wnd: WndHandle,
xpnts: AfArray,
ypnts: AfArray,
xdirs: AfArray,
ydirs: AfArray,
props: CellPtr,
) -> c_int;
fn af_draw_vector_field_3d(
wnd: WndHandle,
xpnts: AfArray,
ypnts: AfArray,
xdirs: AfArray,
ydirs: AfArray,
zdirs: AfArray,
zdirs: AfArray,
props: CellPtr,
) -> c_int;
fn af_draw_vector_field_nd(
wnd: WndHandle,
pnts: AfArray,
dirs: AfArray,
props: CellPtr,
) -> c_int;
fn af_grid(wnd: WndHandle, rows: c_int, cols: c_int) -> c_int;
fn af_show(wnd: WndHandle) -> c_int;
fn af_is_window_closed(out: *mut c_int, wnd: WndHandle) -> c_int;
fn af_destroy_window(wnd: WndHandle) -> c_int;
}
#[repr(C)]
pub struct Cell {
pub row: i32,
pub col: i32,
pub title: *const c_char,
pub cmap: ColorMap,
}
#[derive(Clone)]
pub struct Window {
handle: u64,
row: i32,
col: i32,
cmap: ColorMap,
}
impl From<u64> for Window {
fn from(t: u64) -> Self {
Self {
handle: t,
row: -1,
col: -1,
cmap: ColorMap::DEFAULT,
}
}
}
impl Drop for Window {
fn drop(&mut self) {
unsafe {
let err_val = af_destroy_window(self.handle);
match err_val {
0 => (),
_ => panic!(
"Window object destruction failed with error code: {}",
err_val
),
}
}
}
}
impl Window {
#[allow(unused_mut)]
pub fn new(width: i32, height: i32, title: String) -> Self {
unsafe {
let mut temp: u64 = 0;
let cstr_ret = CString::new(title);
match cstr_ret {
Ok(cstr) => {
let err_val = af_create_window(
&mut temp as MutWndHandle,
width as c_int,
height as c_int,
cstr.as_ptr(),
);
HANDLE_ERROR(AfError::from(err_val));
Self::from(temp)
}
Err(_) => {
panic!("String creation failed while prepping params for window creation.")
}
}
}
}
pub fn set_position(&self, x: u32, y: u32) {
unsafe {
let err_val = af_set_position(self.handle as WndHandle, x as c_uint, y as c_uint);
HANDLE_ERROR(AfError::from(err_val));
}
}
pub fn set_title(&self, title: String) {
unsafe {
let cstr_ret = CString::new(title);
match cstr_ret {
Ok(cstr) => {
let err_val = af_set_title(self.handle as WndHandle, cstr.as_ptr());
HANDLE_ERROR(AfError::from(err_val));
}
Err(_) => HANDLE_ERROR(AfError::ERR_INTERNAL),
}
}
}
pub fn set_visibility(&self, is_visible: bool) {
unsafe {
let err_val = af_set_visibility(self.handle as WndHandle, is_visible as c_int);
HANDLE_ERROR(AfError::from(err_val));
}
}
pub fn set_size(&self, w: u32, h: u32) {
unsafe {
let err_val = af_set_size(self.handle as WndHandle, w as c_uint, h as c_uint);
HANDLE_ERROR(AfError::from(err_val));
}
}
pub fn set_colormap(&mut self, cmap: ColorMap) {
self.cmap = cmap;
}
pub fn is_closed(&self) -> bool {
unsafe {
let mut temp: i32 = 1;
let err_val = af_is_window_closed(&mut temp as *mut c_int, self.handle as WndHandle);
HANDLE_ERROR(AfError::from(err_val));
temp > 0
}
}
pub fn grid(&self, rows: i32, cols: i32) {
unsafe {
let err_val = af_grid(self.handle as WndHandle, rows as c_int, cols as c_int);
HANDLE_ERROR(AfError::from(err_val));
}
}
pub fn show(&mut self) {
unsafe {
let err_val = af_show(self.handle as WndHandle);
HANDLE_ERROR(AfError::from(err_val));
self.row = -1;
self.col = -1;
}
}
pub fn set_view(&mut self, r: i32, c: i32) {
self.row = r;
self.col = c;
}
pub fn set_axes_titles(&mut self, xlabel: String, ylabel: String, zlabel: String) {
let cprops = &Cell {
row: self.row,
col: self.col,
title: ptr::null(),
cmap: self.cmap,
};
let xstr = CString::new(xlabel).unwrap();
let ystr = CString::new(ylabel).unwrap();
let zstr = CString::new(zlabel).unwrap();
unsafe {
let err_val = af_set_axes_titles(
self.handle as WndHandle,
xstr.as_ptr(),
ystr.as_ptr(),
zstr.as_ptr(),
cprops as *const Cell as CellPtr,
);
HANDLE_ERROR(AfError::from(err_val));
}
}
pub fn set_axes_limits_compute<T>(
&mut self,
xrange: &Array<T>,
yrange: &Array<T>,
zrange: Option<&Array<T>>,
exact: bool,
) where
T: HasAfEnum,
{
let cprops = &Cell {
row: self.row,
col: self.col,
title: ptr::null(),
cmap: self.cmap,
};
unsafe {
let err_val = af_set_axes_limits_compute(
self.handle as WndHandle,
xrange.get() as AfArray,
yrange.get() as AfArray,
match zrange {
Some(z) => z.get() as AfArray,
None => 0,
},
exact as c_int,
cprops as *const Cell as CellPtr,
);
HANDLE_ERROR(AfError::from(err_val));
}
}
pub fn set_axes_limits_2d(&mut self, xmin: f32, xmax: f32, ymin: f32, ymax: f32, exact: bool) {
let cprops = &Cell {
row: self.row,
col: self.col,
title: ptr::null(),
cmap: self.cmap,
};
unsafe {
let err_val = af_set_axes_limits_2d(
self.handle as WndHandle,
xmin as c_float,
xmax as c_float,
ymin as c_float,
ymax as c_float,
exact as c_int,
cprops as *const Cell as CellPtr,
);
HANDLE_ERROR(AfError::from(err_val));
}
}
pub fn set_axes_limits_3d(
&mut self,
xmin: f32,
xmax: f32,
ymin: f32,
ymax: f32,
zmin: f32,
zmax: f32,
exact: bool,
) {
let cprops = &Cell {
row: self.row,
col: self.col,
title: ptr::null(),
cmap: self.cmap,
};
unsafe {
let err_val = af_set_axes_limits_3d(
self.handle as WndHandle,
xmin as c_float,
xmax as c_float,
ymin as c_float,
ymax as c_float,
zmin as c_float,
zmax as c_float,
exact as c_int,
cprops as *const Cell as CellPtr,
);
HANDLE_ERROR(AfError::from(err_val));
}
}
pub fn draw_image<T>(&self, input: &Array<T>, title: Option<String>)
where
T: HasAfEnum,
{
let tstr = match title {
Some(s) => s,
None => format!("Cell({},{}))", self.col, self.row),
};
let tstr = CString::new(tstr).unwrap();
let cprops = &Cell {
row: self.row,
col: self.col,
title: tstr.as_ptr(),
cmap: self.cmap,
};
unsafe {
let err_val = af_draw_image(
self.handle as WndHandle,
input.get() as AfArray,
cprops as *const Cell as CellPtr,
);
HANDLE_ERROR(AfError::from(err_val));
}
}
pub fn draw_plot2<T>(&self, x: &Array<T>, y: &Array<T>, title: Option<String>)
where
T: HasAfEnum,
{
let tstr = match title {
Some(s) => s,
None => format!("Cell({},{}))", self.col, self.row),
};
let tstr = CString::new(tstr).unwrap();
let cprops = &Cell {
row: self.row,
col: self.col,
title: tstr.as_ptr(),
cmap: self.cmap,
};
unsafe {
let err_val = af_draw_plot_2d(
self.handle as WndHandle,
x.get() as AfArray,
y.get() as AfArray,
cprops as *const Cell as CellPtr,
);
HANDLE_ERROR(AfError::from(err_val));
}
}
pub fn draw_plot3<T>(&self, x: &Array<T>, y: &Array<T>, z: &Array<T>, title: Option<String>)
where
T: HasAfEnum,
{
let tstr = match title {
Some(s) => s,
None => format!("Cell({},{}))", self.col, self.row),
};
let tstr = CString::new(tstr).unwrap();
let cprops = &Cell {
row: self.row,
col: self.col,
title: tstr.as_ptr(),
cmap: self.cmap,
};
unsafe {
let err_val = af_draw_plot_3d(
self.handle as WndHandle,
x.get() as AfArray,
y.get() as AfArray,
z.get() as AfArray,
cprops as *const Cell as CellPtr,
);
HANDLE_ERROR(AfError::from(err_val));
}
}
pub fn draw_plot<T>(&self, points: &Array<T>, title: Option<String>)
where
T: HasAfEnum,
{
let tstr = match title {
Some(s) => s,
None => format!("Cell({},{}))", self.col, self.row),
};
let tstr = CString::new(tstr).unwrap();
let cprops = &Cell {
row: self.row,
col: self.col,
title: tstr.as_ptr(),
cmap: self.cmap,
};
unsafe {
let err_val = af_draw_plot_nd(
self.handle as WndHandle,
points.get() as AfArray,
cprops as *const Cell as CellPtr,
);
HANDLE_ERROR(AfError::from(err_val));
}
}
pub fn draw_hist<T>(&self, hst: &Array<T>, minval: f64, maxval: f64, title: Option<String>)
where
T: HasAfEnum,
{
let tstr = match title {
Some(s) => s,
None => format!("Cell({},{}))", self.col, self.row),
};
let tstr = CString::new(tstr).unwrap();
let cprops = &Cell {
row: self.row,
col: self.col,
title: tstr.as_ptr(),
cmap: self.cmap,
};
unsafe {
let err_val = af_draw_hist(
self.handle as WndHandle,
hst.get() as AfArray,
minval as c_double,
maxval as c_double,
cprops as *const Cell as CellPtr,
);
HANDLE_ERROR(AfError::from(err_val));
}
}
pub fn draw_surface<T>(
&self,
xvals: &Array<T>,
yvals: &Array<T>,
zvals: &Array<T>,
title: Option<String>,
) where
T: HasAfEnum,
{
let tstr = match title {
Some(s) => s,
None => format!("Cell({},{}))", self.col, self.row),
};
let tstr = CString::new(tstr).unwrap();
let cprops = &Cell {
row: self.row,
col: self.col,
title: tstr.as_ptr(),
cmap: self.cmap,
};
unsafe {
let err_val = af_draw_surface(
self.handle as WndHandle,
xvals.get() as AfArray,
yvals.get() as AfArray,
zvals.get() as AfArray,
cprops as *const Cell as CellPtr,
);
HANDLE_ERROR(AfError::from(err_val));
}
}
pub fn draw_scatter2<T>(
&self,
xvals: &Array<T>,
yvals: &Array<T>,
marker: MarkerType,
title: Option<String>,
) where
T: HasAfEnum,
{
let tstr = match title {
Some(s) => s,
None => format!("Cell({},{}))", self.col, self.row),
};
let tstr = CString::new(tstr).unwrap();
let cprops = &Cell {
row: self.row,
col: self.col,
title: tstr.as_ptr(),
cmap: self.cmap,
};
unsafe {
let err_val = af_draw_scatter_2d(
self.handle as WndHandle,
xvals.get() as AfArray,
yvals.get() as AfArray,
marker as c_int,
cprops as *const Cell as CellPtr,
);
HANDLE_ERROR(AfError::from(err_val));
}
}
pub fn draw_scatter3<T>(
&self,
xvals: &Array<T>,
yvals: &Array<T>,
zvals: &Array<T>,
marker: MarkerType,
title: Option<String>,
) where
T: HasAfEnum,
{
let tstr = match title {
Some(s) => s,
None => format!("Cell({},{}))", self.col, self.row),
};
let tstr = CString::new(tstr).unwrap();
let cprops = &Cell {
row: self.row,
col: self.col,
title: tstr.as_ptr(),
cmap: self.cmap,
};
unsafe {
let err_val = af_draw_scatter_3d(
self.handle as WndHandle,
xvals.get() as AfArray,
yvals.get() as AfArray,
zvals.get() as AfArray,
marker as c_int,
cprops as *const Cell as CellPtr,
);
HANDLE_ERROR(AfError::from(err_val));
}
}
pub fn draw_scatter<T>(&self, vals: &Array<T>, marker: MarkerType, title: Option<String>)
where
T: HasAfEnum,
{
let tstr = match title {
Some(s) => s,
None => format!("Cell({},{}))", self.col, self.row),
};
let tstr = CString::new(tstr).unwrap();
let cprops = &Cell {
row: self.row,
col: self.col,
title: tstr.as_ptr(),
cmap: self.cmap,
};
unsafe {
let err_val = af_draw_scatter_nd(
self.handle as WndHandle,
vals.get() as AfArray,
marker as c_int,
cprops as *const Cell as CellPtr,
);
HANDLE_ERROR(AfError::from(err_val));
}
}
pub fn draw_vector_field2<T>(
&self,
xpnts: &Array<T>,
ypnts: &Array<T>,
xdirs: &Array<T>,
ydirs: &Array<T>,
title: Option<String>,
) where
T: HasAfEnum,
{
let tstr = match title {
Some(s) => s,
None => format!("Cell({},{}))", self.col, self.row),
};
let tstr = CString::new(tstr).unwrap();
let cprops = &Cell {
row: self.row,
col: self.col,
title: tstr.as_ptr(),
cmap: self.cmap,
};
unsafe {
let err_val = af_draw_vector_field_2d(
self.handle as WndHandle,
xpnts.get() as AfArray,
ypnts.get() as AfArray,
xdirs.get() as AfArray,
ydirs.get() as AfArray,
cprops as *const Cell as CellPtr,
);
HANDLE_ERROR(AfError::from(err_val));
}
}
pub fn draw_vector_field3<T>(
&self,
xpnts: &Array<T>,
ypnts: &Array<T>,
zpnts: &Array<T>,
xdirs: &Array<T>,
ydirs: &Array<T>,
zdirs: &Array<T>,
title: Option<String>,
) where
T: HasAfEnum,
{
let tstr = match title {
Some(s) => s,
None => format!("Cell({},{}))", self.col, self.row),
};
let tstr = CString::new(tstr).unwrap();
let cprops = &Cell {
row: self.row,
col: self.col,
title: tstr.as_ptr(),
cmap: self.cmap,
};
unsafe {
let err_val = af_draw_vector_field_3d(
self.handle as WndHandle,
xpnts.get() as AfArray,
ypnts.get() as AfArray,
zpnts.get() as AfArray,
xdirs.get() as AfArray,
ydirs.get() as AfArray,
zdirs.get() as AfArray,
cprops as *const Cell as CellPtr,
);
HANDLE_ERROR(AfError::from(err_val));
}
}
pub fn draw_vector_field<T>(
&self,
points: &Array<T>,
directions: &Array<T>,
title: Option<String>,
) where
T: HasAfEnum,
{
let tstr = match title {
Some(s) => s,
None => format!("Cell({},{}))", self.col, self.row),
};
let tstr = CString::new(tstr).unwrap();
let cprops = &Cell {
row: self.row,
col: self.col,
title: tstr.as_ptr(),
cmap: self.cmap,
};
unsafe {
let err_val = af_draw_vector_field_nd(
self.handle as WndHandle,
points.get() as AfArray,
directions.get() as AfArray,
cprops as *const Cell as CellPtr,
);
HANDLE_ERROR(AfError::from(err_val));
}
}
}