Skip to content

Commit 95458f7

Browse files
committed
FEATURE: vector field rendering functions
* broke API for plot/scatter rendering functions. * Added a more comprehensive and better API for plot/scatter functions. * Added API for setting 2d/3d chart axes limits and titles
1 parent 8cb8a3f commit 95458f7

File tree

1 file changed

+238
-26
lines changed

1 file changed

+238
-26
lines changed

src/graphics.rs

Lines changed: 238 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ use array::Array;
44
use defines::AfError;
55
use defines::{ColorMap, MarkerType};
66
use error::HANDLE_ERROR;
7-
use self::libc::{c_int, c_uint, c_double, c_char};
7+
use self::libc::{c_int, c_uint, c_float, c_double, c_char};
88
use std::ffi::CString;
99

1010
type MutWndHandle = *mut self::libc::c_ulonglong;
@@ -15,19 +15,49 @@ type CellPtr = *const self::libc::c_void;
1515
#[allow(dead_code)]
1616
extern {
1717
fn af_create_window(out: MutWndHandle, w: c_int, h: c_int, title: *const c_char) -> c_int;
18+
1819
fn af_set_position(wnd: WndHandle, x: c_uint, y: c_uint) -> c_int;
1920
fn af_set_title(wnd: WndHandle, title: *const c_char) -> c_int;
2021
fn af_set_size(wnd: WndHandle, w: c_uint, h: c_uint) -> c_int;
2122
fn af_set_visibility(wnd: WndHandle, is_visible: c_int) -> c_int;
23+
24+
fn af_set_axes_titles(wnd: WndHandle,
25+
xtitle: *const c_char, ytitle: *const c_char, ztitle: *const c_char,
26+
props: CellPtr) -> c_int;
27+
fn af_set_axes_limits_compute(wnd: WndHandle, x: AfArray, y: AfArray, z: AfArray,
28+
exact: c_int, props: CellPtr) -> c_int;
29+
fn af_set_axes_limits_2d(wnd: WndHandle, xmin: c_float, xmax: c_float,
30+
ymin: c_float, ymax: c_float,
31+
exact: c_int, props: CellPtr) -> c_int;
32+
fn af_set_axes_limits_3d(wnd: WndHandle, xmin: c_float, xmax: c_float,
33+
ymin: c_float, ymax: c_float,
34+
zmin: c_float, zmax: c_float,
35+
exact: c_int, props: CellPtr) -> c_int;
36+
2237
fn af_draw_image(wnd: WndHandle, arr: AfArray, props: CellPtr) -> c_int;
23-
fn af_draw_plot(wnd: WndHandle, x: AfArray, y: AfArray, props: CellPtr) -> c_int;
24-
fn af_draw_plot3(wnd: WndHandle, P: AfArray, props: CellPtr) -> c_int;
2538
fn af_draw_hist(wnd: WndHandle, x: AfArray,
2639
minval: c_double, maxval: c_double, props: CellPtr) -> c_int;
2740
fn af_draw_surface(wnd: WndHandle, xvals: AfArray, yvals: AfArray, S: AfArray,
2841
props: CellPtr) -> c_int;
29-
fn af_draw_scatter(wnd: WndHandle, x: AfArray, y: AfArray, marker: c_int, props: CellPtr) -> c_int;
30-
fn af_draw_scatter3(wnd: WndHandle, P: AfArray, marker: c_int, props: CellPtr) -> c_int;
42+
43+
fn af_draw_plot_2d(wnd: WndHandle, x: AfArray, y: AfArray, props: CellPtr) -> c_int;
44+
fn af_draw_plot_3d(wnd: WndHandle, x: AfArray, y: AfArray, z: AfArray, props: CellPtr) -> c_int;
45+
fn af_draw_plot_nd(wnd: WndHandle, P: AfArray, props: CellPtr) -> c_int;
46+
47+
fn af_draw_scatter_2d(wnd: WndHandle, x: AfArray, y: AfArray,
48+
marker: c_int, props: CellPtr) -> c_int;
49+
fn af_draw_scatter_3d(wnd: WndHandle, x: AfArray, y: AfArray, z: AfArray,
50+
marker: c_int, props: CellPtr) -> c_int;
51+
fn af_draw_scatter_nd(wnd: WndHandle, P: AfArray,
52+
marker: c_int, props: CellPtr) -> c_int;
53+
54+
fn af_draw_vector_field_2d(wnd: WndHandle, xpnts: AfArray, ypnts: AfArray,
55+
xdirs: AfArray, ydirs: AfArray, props: CellPtr) -> c_int;
56+
fn af_draw_vector_field_3d(wnd: WndHandle, xpnts: AfArray, ypnts: AfArray,
57+
xdirs: AfArray, ydirs: AfArray, zdirs: AfArray, zdirs: AfArray,
58+
props: CellPtr) -> c_int;
59+
fn af_draw_vector_field_nd(wnd: WndHandle, pnts: AfArray, dirs: AfArray, props: CellPtr) -> c_int;
60+
3161
fn af_grid(wnd: WndHandle, rows: c_int, cols: c_int) -> c_int;
3262
fn af_show(wnd: WndHandle) -> c_int;
3363
fn af_is_window_closed(out: *mut c_int, wnd: WndHandle) -> c_int;
@@ -216,6 +246,110 @@ impl Window {
216246
self.col = c;
217247
}
218248

249+
/// Set chart axes titles
250+
///
251+
/// # Parameters
252+
///
253+
/// - `xlabel` is x axis title
254+
/// - `ylabel` is y axis title
255+
/// - `zlabel` is z axis title
256+
pub fn set_axes_titles(&mut self, xlabel: String, ylabel: String, zlabel: String) {
257+
let cprops = &Cell {row: self.row, col: self.col, title: String::from(""), cmap: self.cmap};
258+
let xstr = CString::new(xlabel.as_bytes()).unwrap();
259+
let ystr = CString::new(ylabel.as_bytes()).unwrap();
260+
let zstr = CString::new(zlabel.as_bytes()).unwrap();
261+
unsafe {
262+
let err_val = af_set_axes_titles(self.handle as WndHandle,
263+
xstr.to_bytes_with_nul().as_ptr() as *const c_char,
264+
ystr.to_bytes_with_nul().as_ptr() as *const c_char,
265+
zstr.to_bytes_with_nul().as_ptr() as *const c_char,
266+
cprops as *const Cell as CellPtr);
267+
HANDLE_ERROR(AfError::from(err_val));
268+
}
269+
}
270+
271+
/// Set chart axes limits by computing limits from data
272+
///
273+
/// In multiple view (grid) mode, setting limits will effect the chart that is currently
274+
/// active via set_view call
275+
///
276+
/// # Parameters
277+
///
278+
/// - `xrange` is set of all x values to compute min/max for x axis
279+
/// - `yrange` is set of all y values to compute min/max for y axis
280+
/// - `zrange` is set of all z values to compute min/max for z axis. If None is passed to
281+
/// this paramter, 2d chart limits are set.
282+
/// - `exact` indicates if the exact min/max values from `xrange`, `yrange` and `zrange`
283+
/// are to extracted. If exact is false then the most significant digit is rounded up
284+
/// to next power of 2 and the magnitude remains the same.
285+
pub fn set_axes_limits_compute(&mut self, xrange: &Array, yrange: &Array,
286+
zrange: Option<&Array>, exact: bool) {
287+
let cprops = &Cell {row: self.row, col: self.col, title: String::from(""), cmap: self.cmap};
288+
unsafe {
289+
let err_val = af_set_axes_limits_compute(self.handle as WndHandle,
290+
xrange.get() as AfArray,
291+
yrange.get() as AfArray,
292+
match zrange {
293+
Some(z) => z.get() as AfArray,
294+
None => 0,
295+
}, exact as c_int,
296+
cprops as *const Cell as CellPtr);
297+
HANDLE_ERROR(AfError::from(err_val));
298+
}
299+
}
300+
301+
/// Set 2d chart axes limits
302+
///
303+
/// In multiple view (grid) mode, setting limits will effect the chart that is currently
304+
/// active via set_view call
305+
///
306+
/// # Parameters
307+
///
308+
/// - `xmin` is minimum value on x axis
309+
/// - `xmax` is maximum value on x axis
310+
/// - `ymin` is minimum value on y axis
311+
/// - `ymax` is maximum value on y axis
312+
/// - `exact` indicates if the exact min/max values from `xrange`, `yrange` and `zrange`
313+
/// are to extracted. If exact is false then the most significant digit is rounded up
314+
/// to next power of 2 and the magnitude remains the same.
315+
pub fn set_axes_limits_2d(&mut self, xmin: f32, xmax: f32, ymin: f32, ymax: f32, exact: bool) {
316+
let cprops = &Cell {row: self.row, col: self.col, title: String::from(""), cmap: self.cmap};
317+
unsafe {
318+
let err_val = af_set_axes_limits_2d(self.handle as WndHandle, xmin as c_float,
319+
xmax as c_float, ymin as c_float, ymax as c_float,
320+
exact as c_int, cprops as *const Cell as CellPtr);
321+
HANDLE_ERROR(AfError::from(err_val));
322+
}
323+
}
324+
325+
/// Set 3d chart axes limits
326+
///
327+
/// In multiple view (grid) mode, setting limits will effect the chart that is currently
328+
/// active via set_view call
329+
///
330+
/// # Parameters
331+
///
332+
/// - `xmin` is minimum value on x axis
333+
/// - `xmax` is maximum value on x axis
334+
/// - `ymin` is minimum value on y axis
335+
/// - `ymax` is maximum value on y axis
336+
/// - `zmin` is minimum value on z axis
337+
/// - `zmax` is maximum value on z axis
338+
/// - `exact` indicates if the exact min/max values from `xrange`, `yrange` and `zrange`
339+
/// are to extracted. If exact is false then the most significant digit is rounded up
340+
/// to next power of 2 and the magnitude remains the same.
341+
pub fn set_axes_limits_3d(&mut self, xmin: f32, xmax: f32, ymin: f32, ymax: f32,
342+
zmin: f32, zmax: f32, exact: bool) {
343+
let cprops = &Cell {row: self.row, col: self.col, title: String::from(""), cmap: self.cmap};
344+
unsafe {
345+
let err_val = af_set_axes_limits_3d(self.handle as WndHandle, xmin as c_float,
346+
xmax as c_float, ymin as c_float, ymax as c_float,
347+
zmin as c_float, zmax as c_float,
348+
exact as c_int, cprops as *const Cell as CellPtr);
349+
HANDLE_ERROR(AfError::from(err_val));
350+
}
351+
}
352+
219353
/// Render given Array as an image
220354
pub fn draw_image(&self, input: &Array, title: Option<String>) {
221355
let tstr = match title {
@@ -231,31 +365,45 @@ impl Window {
231365
}
232366

233367
/// Render given two Array's `x` and `y` as a 2d line plot
234-
pub fn draw_plot(&self, x: &Array, y: &Array, title: Option<String>) {
368+
pub fn draw_plot2(&self, x: &Array, y: &Array, title: Option<String>) {
235369
let tstr = match title {
236370
Some(s) => s,
237371
None => format!("Cell({},{}))", self.col, self.row)
238372
};
239373
let cprops = &Cell {row: self.row, col: self.col, title: tstr.clone(), cmap: self.cmap};
240374
unsafe {
241-
let err_val = af_draw_plot(self.handle as WndHandle,
242-
x.get() as AfArray,
243-
y.get() as AfArray,
244-
cprops as *const Cell as CellPtr);
375+
let err_val = af_draw_plot_2d(self.handle as WndHandle,
376+
x.get() as AfArray, y.get() as AfArray,
377+
cprops as *const Cell as CellPtr);
378+
HANDLE_ERROR(AfError::from(err_val));
379+
}
380+
}
381+
382+
/// Render given Array's `x`, `y` and `z` as a 3d line plot
383+
pub fn draw_plot3(&self, x: &Array, y: &Array, z: &Array, title: Option<String>) {
384+
let tstr = match title {
385+
Some(s) => s,
386+
None => format!("Cell({},{}))", self.col, self.row)
387+
};
388+
let cprops = &Cell {row: self.row, col: self.col, title: tstr.clone(), cmap: self.cmap};
389+
unsafe {
390+
let err_val = af_draw_plot_3d(self.handle as WndHandle,
391+
x.get() as AfArray, y.get() as AfArray, z.get() as AfArray,
392+
cprops as *const Cell as CellPtr);
245393
HANDLE_ERROR(AfError::from(err_val));
246394
}
247395
}
248396

249397
/// Render give Arrays of points as a 3d line plot
250-
pub fn draw_plot3(&self, points: &Array, title: Option<String>) {
398+
pub fn draw_plot(&self, points: &Array, title: Option<String>) {
251399
let tstr = match title {
252400
Some(s) => s,
253401
None => format!("Cell({},{}))", self.col, self.row)
254402
};
255403
let cprops = &Cell {row: self.row, col: self.col, title: tstr.clone(), cmap: self.cmap};
256404
unsafe {
257-
let err_val = af_draw_plot3(self.handle as WndHandle, points.get() as AfArray,
258-
cprops as *const Cell as CellPtr);
405+
let err_val = af_draw_plot_nd(self.handle as WndHandle, points.get() as AfArray,
406+
cprops as *const Cell as CellPtr);
259407
HANDLE_ERROR(AfError::from(err_val));
260408
}
261409
}
@@ -292,36 +440,100 @@ impl Window {
292440
}
293441
}
294442

295-
/// Render give Arrays as 2d scatter plot
296-
pub fn draw_scatter(&self, xvals: &Array, yvals: &Array, marker: MarkerType, title: Option<String>) {
443+
/// Render given Arrays as 2d scatter plot
444+
pub fn draw_scatter2(&self, xvals: &Array, yvals: &Array,
445+
marker: MarkerType, title: Option<String>) {
297446
let tstr = match title {
298447
Some(s) => s,
299448
None => format!("Cell({},{}))", self.col, self.row)
300449
};
301450
let cprops = &Cell {row: self.row, col: self.col, title: tstr.clone(), cmap: self.cmap};
302451
unsafe {
303-
let err_val = af_draw_scatter(self.handle as WndHandle,
304-
xvals.get() as AfArray,
305-
yvals.get() as AfArray,
306-
marker as c_int,
307-
cprops as *const Cell as CellPtr);
452+
let err_val = af_draw_scatter_2d(self.handle as WndHandle,
453+
xvals.get() as AfArray, yvals.get() as AfArray,
454+
marker as c_int, cprops as *const Cell as CellPtr);
455+
HANDLE_ERROR(AfError::from(err_val));
456+
}
457+
}
458+
459+
/// Render given Arrays as 3d scatter plot
460+
pub fn draw_scatter3(&self, xvals: &Array, yvals: &Array, zvals: &Array,
461+
marker: MarkerType, title: Option<String>) {
462+
let tstr = match title {
463+
Some(s) => s,
464+
None => format!("Cell({},{}))", self.col, self.row)
465+
};
466+
let cprops = &Cell {row: self.row, col: self.col, title: tstr.clone(), cmap: self.cmap};
467+
unsafe {
468+
let err_val = af_draw_scatter_3d(self.handle as WndHandle, xvals.get() as AfArray,
469+
yvals.get() as AfArray, zvals.get() as AfArray,
470+
marker as c_int, cprops as *const Cell as CellPtr);
308471
HANDLE_ERROR(AfError::from(err_val));
309472
}
310473
}
311474

312475
/// Render give Array as 3d scatter plot
313-
pub fn draw_scatter3(&self, vals: &Array, marker: MarkerType, title: Option<String>) {
476+
pub fn draw_scatter(&self, vals: &Array, marker: MarkerType, title: Option<String>) {
477+
let tstr = match title {
478+
Some(s) => s,
479+
None => format!("Cell({},{}))", self.col, self.row)
480+
};
481+
let cprops = &Cell {row: self.row, col: self.col, title: tstr.clone(), cmap: self.cmap};
482+
unsafe {
483+
let err_val = af_draw_scatter_nd(self.handle as WndHandle, vals.get() as AfArray,
484+
marker as c_int, cprops as *const Cell as CellPtr);
485+
HANDLE_ERROR(AfError::from(err_val));
486+
}
487+
}
488+
489+
/// Render given Arrays as 2d vector field
490+
pub fn draw_vector_field2(&self, xpnts: &Array, ypnts: &Array,
491+
xdirs: &Array, ydirs: &Array, title: Option<String>) {
314492
let tstr = match title {
315493
Some(s) => s,
316494
None => format!("Cell({},{}))", self.col, self.row)
317495
};
318496
let cprops = &Cell {row: self.row, col: self.col, title: tstr.clone(), cmap: self.cmap};
319497
unsafe {
320-
let err_val = af_draw_scatter3(self.handle as WndHandle,
321-
vals.get() as AfArray,
322-
marker as c_int,
323-
cprops as *const Cell as CellPtr);
498+
let err_val = af_draw_vector_field_2d(self.handle as WndHandle,
499+
xpnts.get() as AfArray, ypnts.get() as AfArray,
500+
xdirs.get() as AfArray, ydirs.get() as AfArray,
501+
cprops as *const Cell as CellPtr);
324502
HANDLE_ERROR(AfError::from(err_val));
325503
}
326504
}
327-
}
505+
506+
/// Render given Arrays as 3d vector field
507+
pub fn draw_vector_field3(&self, xpnts: &Array, ypnts: &Array, zpnts: &Array,
508+
xdirs: &Array, ydirs: &Array, zdirs: &Array,
509+
title: Option<String>) {
510+
let tstr = match title {
511+
Some(s) => s,
512+
None => format!("Cell({},{}))", self.col, self.row)
513+
};
514+
let cprops = &Cell {row: self.row, col: self.col, title: tstr.clone(), cmap: self.cmap};
515+
unsafe {
516+
let err_val = af_draw_vector_field_3d(self.handle as WndHandle, xpnts.get() as AfArray,
517+
ypnts.get() as AfArray, zpnts.get() as AfArray,
518+
xdirs.get() as AfArray, ydirs.get() as AfArray,
519+
zdirs.get() as AfArray,
520+
cprops as *const Cell as CellPtr);
521+
HANDLE_ERROR(AfError::from(err_val));
522+
}
523+
}
524+
525+
/// Render given Array as vector field
526+
pub fn draw_vector_field(&self, points: &Array, directions: &Array, title: Option<String>) {
527+
let tstr = match title {
528+
Some(s) => s,
529+
None => format!("Cell({},{}))", self.col, self.row)
530+
};
531+
let cprops = &Cell {row: self.row, col: self.col, title: tstr.clone(), cmap: self.cmap};
532+
unsafe {
533+
let err_val = af_draw_vector_field_nd(self.handle as WndHandle,
534+
points.get() as AfArray, directions.get() as AfArray,
535+
cprops as *const Cell as CellPtr);
536+
HANDLE_ERROR(AfError::from(err_val));
537+
}
538+
}
539+
}

0 commit comments

Comments
 (0)