Add simple heatmap support
This commit is contained in:
parent
e6a6f67b4d
commit
03b356f575
4 changed files with 131 additions and 19 deletions
47
src/heatmap.rs
Normal file
47
src/heatmap.rs
Normal file
|
@ -0,0 +1,47 @@
|
|||
use sys::{ImPlotHeatmapFlags, ImPlotHeatmapFlags__ImPlotHeatmapFlags_ColMajor};
|
||||
|
||||
use crate::sys;
|
||||
use std::ffi::CString;
|
||||
use std::os::raw::c_char;
|
||||
|
||||
pub use crate::sys::ImPlotPoint;
|
||||
|
||||
pub struct PlotHeatmap {
|
||||
label: CString,
|
||||
}
|
||||
|
||||
impl PlotHeatmap {
|
||||
pub fn new(label: &str) -> Self {
|
||||
Self {
|
||||
label: CString::new(label)
|
||||
.unwrap_or_else(|_| panic!("label string has internal null bytes: {}", label)),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn plot(&self, x: &[f64], rows: i32, cols: i32) {
|
||||
if x.is_empty() {
|
||||
return;
|
||||
}
|
||||
|
||||
unsafe {
|
||||
sys::ImPlot_PlotHeatmap_doublePtr(
|
||||
self.label.as_ptr() as *const c_char,
|
||||
x.as_ptr(),
|
||||
rows,
|
||||
cols,
|
||||
0.0,
|
||||
0.0,
|
||||
"\0".as_ptr() as *const c_char,
|
||||
ImPlotPoint {
|
||||
x: 0f64,
|
||||
y: rows as f64,
|
||||
},
|
||||
ImPlotPoint {
|
||||
x: cols as f64,
|
||||
y: 0f64,
|
||||
},
|
||||
ImPlotHeatmapFlags__ImPlotHeatmapFlags_ColMajor as ImPlotHeatmapFlags,
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -24,6 +24,7 @@ use std::os::raw::c_char;
|
|||
pub use sys::{ImAxis, ImPlotPoint, ImPlotRange, ImPlotRect, ImVec2, ImVec4};
|
||||
|
||||
mod context;
|
||||
pub mod heatmap;
|
||||
pub mod lines;
|
||||
mod plot;
|
||||
mod plot_elements;
|
||||
|
@ -31,11 +32,11 @@ pub mod rect;
|
|||
|
||||
// The bindings for some reason don't contain this - it has to match the IMPLOT_AUTO from
|
||||
// the original C++ header for things to work properly.
|
||||
const IMPLOT_AUTO: i32 = -1;
|
||||
//const IMPLOT_AUTO: i32 = -1;
|
||||
|
||||
// Number of Y axes, this is used in a bunch of places for storing things like settings.
|
||||
// If this changes, also change the YAxisChoice enum.
|
||||
const NUMBER_OF_Y_AXES: usize = 3;
|
||||
//const NUMBER_OF_Y_AXES: usize = 3;
|
||||
|
||||
/// Choice of Y axis. This an enum instead of just an integer so as to make it impossible
|
||||
/// to select a Y axis that is not present - this makes it easier to avoid `Result`-type
|
||||
|
|
19
src/lines.rs
19
src/lines.rs
|
@ -16,6 +16,25 @@ impl PlotLine {
|
|||
}
|
||||
}
|
||||
|
||||
pub fn plot_with_step(&self, x: &[f64], step: f64) {
|
||||
if x.is_empty() {
|
||||
return;
|
||||
}
|
||||
|
||||
unsafe {
|
||||
sys::ImPlot_PlotLine_doublePtrInt(
|
||||
self.label.as_ptr() as *const c_char,
|
||||
x.as_ptr(),
|
||||
x.len() as i32,
|
||||
step,
|
||||
0f64,
|
||||
0,
|
||||
0,
|
||||
std::mem::size_of::<f64>() as i32,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
pub fn plot(&self, x: &[f64], y: &[f64]) {
|
||||
if x.len().min(y.len()) == 0 {
|
||||
return;
|
||||
|
|
79
src/plot.rs
79
src/plot.rs
|
@ -1,8 +1,8 @@
|
|||
use std::ffi::CString;
|
||||
use std::ffi::{c_char, CString};
|
||||
|
||||
use bitflags::bitflags;
|
||||
use implot_sys as sys;
|
||||
use sys::{ImAxis, ImVec2, *};
|
||||
use sys::{ImVec2, *};
|
||||
|
||||
use crate::{Context, PlotUi};
|
||||
|
||||
|
@ -22,17 +22,17 @@ bitflags! {
|
|||
#[repr(transparent)]
|
||||
pub struct PlotFlags: u32 {
|
||||
const NONE = ImPlotFlags__ImPlotFlags_None;
|
||||
const NOTITLE = ImPlotFlags__ImPlotFlags_NoTitle;
|
||||
const NOLEGEND = ImPlotFlags__ImPlotFlags_NoLegend;
|
||||
const NOMOUSETEXT = ImPlotFlags__ImPlotFlags_NoMouseText;
|
||||
const NOINPUTS = ImPlotFlags__ImPlotFlags_NoInputs;
|
||||
const NOMENUS = ImPlotFlags__ImPlotFlags_NoMenus;
|
||||
const NOBOXSELECT = ImPlotFlags__ImPlotFlags_NoBoxSelect;
|
||||
const NOCHILD = ImPlotFlags__ImPlotFlags_NoChild;
|
||||
const NOFRAME = ImPlotFlags__ImPlotFlags_NoFrame;
|
||||
const NO_TITLE = ImPlotFlags__ImPlotFlags_NoTitle;
|
||||
const NO_LEGEND = ImPlotFlags__ImPlotFlags_NoLegend;
|
||||
const NO_MOUSE_TEXT = ImPlotFlags__ImPlotFlags_NoMouseText;
|
||||
const NO_INPUTS = ImPlotFlags__ImPlotFlags_NoInputs;
|
||||
const NO_MENUS = ImPlotFlags__ImPlotFlags_NoMenus;
|
||||
const NO_BOX_SELECT = ImPlotFlags__ImPlotFlags_NoBoxSelect;
|
||||
const NO_CHILD = ImPlotFlags__ImPlotFlags_NoChild;
|
||||
const NO_FRAME = ImPlotFlags__ImPlotFlags_NoFrame;
|
||||
const EQUAL = ImPlotFlags__ImPlotFlags_Equal;
|
||||
const CROSSHAIRS = ImPlotFlags__ImPlotFlags_Crosshairs;
|
||||
const CANVASONLY = ImPlotFlags__ImPlotFlags_CanvasOnly;
|
||||
const CANVAS_ONLY = ImPlotFlags__ImPlotFlags_CanvasOnly;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -70,6 +70,8 @@ pub struct Plot {
|
|||
flags: ImPlotFlags,
|
||||
x_flags: ImPlotAxisFlags,
|
||||
y_flags: ImPlotAxisFlags,
|
||||
x_limit: Option<[f64; 2]>,
|
||||
y_limit: Option<[f64; 2]>,
|
||||
}
|
||||
|
||||
impl Plot {
|
||||
|
@ -83,6 +85,25 @@ impl Plot {
|
|||
flags: PlotFlags::NONE.bits() as ImPlotFlags,
|
||||
x_flags: PlotAxisFlags::NONE.bits() as ImPlotAxisFlags,
|
||||
y_flags: PlotAxisFlags::NONE.bits() as ImPlotAxisFlags,
|
||||
x_limit: None,
|
||||
y_limit: None,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn color_map_scale(title: &str, min: f64, max: f64, size: ImVec2) {
|
||||
let title = CString::new(title)
|
||||
.unwrap_or_else(|_| panic!("string contains internal null bytes: {}", title));
|
||||
|
||||
unsafe {
|
||||
sys::ImPlot_ColormapScale(
|
||||
title.as_ptr() as *const c_char,
|
||||
min,
|
||||
max,
|
||||
size,
|
||||
"%.0f\0".as_ptr() as *const c_char,
|
||||
0,
|
||||
0,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -91,21 +112,31 @@ impl Plot {
|
|||
self
|
||||
}
|
||||
|
||||
pub fn with_flags(mut self, flags: &PlotFlags) -> Self {
|
||||
pub fn with_flags(mut self, flags: PlotFlags) -> Self {
|
||||
self.flags = flags.bits() as ImPlotFlags;
|
||||
self
|
||||
}
|
||||
|
||||
pub fn with_x_flags(mut self, flags: &PlotAxisFlags) -> Self {
|
||||
pub fn with_x_flags(mut self, flags: PlotAxisFlags) -> Self {
|
||||
self.x_flags = flags.bits() as ImPlotAxisFlags;
|
||||
self
|
||||
}
|
||||
|
||||
pub fn with_y_flags(mut self, flags: &PlotAxisFlags) -> Self {
|
||||
pub fn with_y_flags(mut self, flags: PlotAxisFlags) -> Self {
|
||||
self.y_flags = flags.bits() as ImPlotAxisFlags;
|
||||
self
|
||||
}
|
||||
|
||||
pub fn with_x_limit(mut self, min: f64, max: f64) -> Self {
|
||||
self.x_limit = Some([min, max]);
|
||||
self
|
||||
}
|
||||
|
||||
pub fn with_y_limit(mut self, min: f64, max: f64) -> Self {
|
||||
self.y_limit = Some([min, max]);
|
||||
self
|
||||
}
|
||||
|
||||
pub fn x_label(mut self, label: &str) -> Self {
|
||||
self.x_label = CString::new(label)
|
||||
.unwrap_or_else(|_| panic!("string contains internal null bytes: {}", label));
|
||||
|
@ -127,15 +158,29 @@ impl Plot {
|
|||
y: self.size[1],
|
||||
};
|
||||
|
||||
let should_render = sys::ImPlot_BeginPlot(self.title.as_ptr(), size_vec, self.flags);
|
||||
|
||||
should_render
|
||||
sys::ImPlot_BeginPlot(self.title.as_ptr(), size_vec, self.flags)
|
||||
};
|
||||
|
||||
if should_render {
|
||||
unsafe {
|
||||
sys::ImPlot_SetupAxis(Axis::X1 as i32, self.x_label.as_ptr(), self.x_flags);
|
||||
sys::ImPlot_SetupAxis(Axis::Y1 as i32, self.y_label.as_ptr(), self.y_flags);
|
||||
if let Some(limit) = self.x_limit {
|
||||
sys::ImPlot_SetupAxisLimits(
|
||||
Axis::X1 as i32,
|
||||
limit[0],
|
||||
limit[1],
|
||||
ImPlotCond__ImPlotCond_Once as i32,
|
||||
);
|
||||
}
|
||||
if let Some(limit) = self.y_limit {
|
||||
sys::ImPlot_SetupAxisLimits(
|
||||
Axis::Y1 as i32,
|
||||
limit[0],
|
||||
limit[1],
|
||||
ImPlotCond__ImPlotCond_Once as i32,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
Some(PlotToken {
|
||||
|
|
Loading…
Reference in a new issue