1
0
Fork 0
mirror of https://github.com/gwm17/implot.git synced 2024-10-09 23:57:26 -04:00

initial heatmap prototype working

This commit is contained in:
Evan Pezent 2020-06-01 22:14:22 -05:00
parent 01f033bd8a
commit 468ffe9ead
3 changed files with 213 additions and 50 deletions

View File

@ -31,6 +31,7 @@ Below is a change-log of API breaking changes only. If you are using one of the
When you are not sure about a old symbol or function name, try using the Search/Find function of your IDE to look for comments or references in all implot files.
You can read releases logs https://github.com/epezent/implot/releases for more details.
- 2020/06/01 (0.3) - SetPalette/RestorePalette were changed to SetColormap/RestoreColormap for consistency with other plotting libraries.
- 2020/05/31 (0.3) - Plot functions taking custom ImVec2* getters were removed. Use the ImPlotPoint* getter versions instead.
- 2020/05/29 (0.3) - The signature of ImPlotLimits::Contains was changed to take two doubles instead of ImVec2
- 2020/05/16 (0.2) - All plotting functions were reverted to being prefixed with "Plot" to maintain a consistent VerbNoun style. `Plot` was split into `PlotLine`
@ -152,8 +153,9 @@ inline void FlipFlag(TSet& set, TFlag flag) {
HasFlag(set, flag) ? set &= ~flag : set |= flag;
}
/// Linearly remaps float x from [x0 x1] to [y0 y1].
inline float Remap(float x, float x0, float x1, float y0, float y1) {
/// Linearly remaps x from [x0 x1] to [y0 y1].
template <typename T>
inline T Remap(T x, T x0, T x1, T y0, T y1) {
return y0 + (x - x0) * (y1 - y0) / (x1 - x0);
}
@ -334,7 +336,7 @@ struct ImPlotContext {
ImPlotContext() : RenderX(), RenderY() {
CurrentPlot = NULL;
FitThisFrame = FitX = false;
RestorePalette();
RestoreColormap();
}
/// ALl Plots
@ -385,7 +387,7 @@ struct ImPlotContext {
// Mouse pos
ImPlotPoint LastMousePos[MAX_Y_AXES];
// Style
ImVector<ImVec4> ColorMap;
ImVector<ImVec4> Colormap;
ImPlotStyle Style;
ImVector<ImGuiColorMod> ColorModifiers; // Stack for PushStyleColor()/PopStyleColor()
ImVector<ImGuiStyleMod> StyleModifiers; // Stack for PushStyleVar()/PopStyleVar()
@ -404,7 +406,7 @@ static ImPlotContext gp;
/// Returns the next unused default plot color
ImVec4 NextColor() {
ImVec4 col = gp.ColorMap[gp.CurrentPlot->ColorIdx % gp.ColorMap.size()];
ImVec4 col = gp.Colormap[gp.CurrentPlot->ColorIdx % gp.Colormap.size()];
gp.CurrentPlot->ColorIdx++;
return col;
}
@ -1078,8 +1080,8 @@ bool BeginPlot(const char* title, const char* x_label, const char* y_label, cons
float zoom_rate = 0.1f;
if (IO.MouseWheel > 0)
zoom_rate = (-zoom_rate) / (1.0f + (2.0f * zoom_rate));
float tx = Remap(IO.MousePos.x, gp.BB_Grid.Min.x, gp.BB_Grid.Max.x, 0, 1);
float ty = Remap(IO.MousePos.y, gp.BB_Grid.Min.y, gp.BB_Grid.Max.y, 0, 1);
float tx = Remap(IO.MousePos.x, gp.BB_Grid.Min.x, gp.BB_Grid.Max.x, 0.0f, 1.0f);
float ty = Remap(IO.MousePos.y, gp.BB_Grid.Min.y, gp.BB_Grid.Max.y, 0.0f, 1.0f);
if (hov_x_axis_region && !x.lock) {
ImPlotAxisScale axis_scale(0, tx, ty, zoom_rate);
const ImPlotPoint& plot_tl = axis_scale.Min;
@ -1866,17 +1868,18 @@ ImPlotStyle& GetStyle() {
return gp.Style;
}
void SetPalette(const ImVec4* colors, int num_colors) {
gp.ColorMap.shrink(0);
gp.ColorMap.reserve(num_colors);
void SetColormap(const ImVec4* colors, int num_colors) {
gp.Colormap.shrink(0);
gp.Colormap.reserve(num_colors);
for (int i = 0; i < num_colors; ++i) {
gp.ColorMap.push_back(colors[i]);
gp.Colormap.push_back(colors[i]);
}
}
/// Returns the next unused default plot color
void RestorePalette() {
static ImVec4 default_colors[10] = {
void SetColormap(ImPlotColormap colormap) {
static ImVec4 maps[ImPlotColormap_COUNT][10] {
// ImPlotColormap_Default
{
ImVec4((0.0F), (0.7490196228F), (1.0F), (1.0F)), // Blues::DeepSkyBlue,
ImVec4((1.0F), (0.0F), (0.0F), (1.0F)), // Reds::Red,
ImVec4((0.4980392158F), (1.0F), (0.0F), (1.0F)), // Greens::Chartreuse,
@ -1887,8 +1890,83 @@ void RestorePalette() {
ImVec4((0.5411764979F), (0.1686274558F), (0.8862745166F), (1.0F)), // Purples::BlueViolet,
ImVec4((0.5f), (0.5f), (0.5f), (1.0F)), // Grays::Gray50,
ImVec4((0.8235294223F), (0.7058823705F), (0.5490196347F), (1.0F)) // Browns::Tan
},
// ImPlotColormap_Viridis
{
ImVec4(0.267004f, 0.004874f, 0.329415f, 1.f),
ImVec4(0.281412f, 0.155834f, 0.469201f, 1.f),
ImVec4(0.244972f, 0.287675f, 0.53726f, 1.f),
ImVec4(0.190631f, 0.407061f, 0.556089f, 1.f),
ImVec4(0.147607f, 0.511733f, 0.557049f, 1.f),
ImVec4(0.119699f, 0.618490f, 0.536347f, 1.f),
ImVec4(0.208030f, 0.718701f, 0.472873f, 1.f),
ImVec4(0.430983f, 0.808473f, 0.346476f, 1.f),
ImVec4(0.709898f, 0.868751f, 0.169257f, 1.f),
ImVec4(0.993248f, 0.906157f, 0.143936f, 1.f )
},
// ImPlotColormap_Plasma
{
ImVec4(0.050383f, 0.029803f, 0.527975f, 1.f),
ImVec4(0.274191f, 0.012109f, 0.622722f, 1.f),
ImVec4(0.447714f, 0.002080f, 0.660240f, 1.f),
ImVec4(0.610667f, 0.090204f, 0.619951f, 1.f),
ImVec4(0.740143f, 0.213864f, 0.524216f, 1.f),
ImVec4(0.846788f, 0.342551f, 0.420579f, 1.f),
ImVec4(0.928329f, 0.472975f, 0.326067f, 1.f),
ImVec4(0.983041f, 0.624131f, 0.227937f, 1.f),
ImVec4(0.991209f, 0.790537f, 0.149377f, 1.f),
ImVec4(0.940015f, 0.975158f, 0.131326f, 1.f)
},
// ImPlotColormap_Hot
{
ImVec4(0.3333f, 0.0f, 0.0f, 1.0f),
ImVec4(0.6667f, 0.0f, 0.0f, 1.0f),
ImVec4(1.0000f, 0.0f, 0.0f, 1.0f),
ImVec4(1.0000f, 0.3333f, 0.0f, 1.0f),
ImVec4(1.0000f, 0.6667f, 0.0f, 1.0f),
ImVec4(1.0000f, 1.0000f, 0.0f, 1.0f),
ImVec4(1.0000f, 1.0000f, 0.2500f, 1.0f),
ImVec4(1.0000f, 1.0000f, 0.5000f, 1.0f),
ImVec4(1.0000f, 1.0000f, 0.7500f, 1.0f),
ImVec4(1.0000f, 1.0000f, 1.0000f, 1.0f)
},
// ImPlotColormap_Cool
{
ImVec4( 0.0f, 1.0000f, 1.0000f, 1.0f),
ImVec4(0.1111f, 0.8889f, 1.0000f, 1.0f),
ImVec4(0.2222f, 0.7778f, 1.0000f, 1.0f),
ImVec4(0.3333f, 0.6667f, 1.0000f, 1.0f),
ImVec4(0.4444f, 0.5556f, 1.0000f, 1.0f),
ImVec4(0.5556f, 0.4444f, 1.0000f, 1.0f),
ImVec4(0.6667f, 0.3333f, 1.0000f, 1.0f),
ImVec4(0.7778f, 0.2222f, 1.0000f, 1.0f),
ImVec4(0.8889f, 0.1111f, 1.0000f, 1.0f),
ImVec4(1.0000f, 0.0f, 1.0000f, 1.0f)
}
// ImPlotColormap_Spring
// ImPlotColormap_Summer
// ImPlotColormap_Autumn
// ImPlotColormap_Winter
};
SetPalette(default_colors, 10);
SetColormap(maps[colormap], 10);
}
/// Returns the next unused default plot color
void RestoreColormap() {
SetColormap(ImPlotColormap_Default);
}
ImVec4 SampleColormap(float t) {
t = ImClamp(t,0.0f,1.0f);
int i1 = (int)((gp.Colormap.Size-1) * t);
int i2 = i1 + 1;
if (i2 == gp.Colormap.Size)
return gp.Colormap[i1];
float t1 = (float)i1 / (float)gp.Colormap.Size;
float t2 = (float)i2 / (float)gp.Colormap.Size;
t = Remap(t, t1, t2, 0.0f, 1.0f);
return ImLerp(gp.Colormap[i1],gp.Colormap[i2],t);
}
void PushStyleColor(ImPlotCol idx, ImU32 col) {
@ -2515,8 +2593,7 @@ void PlotBarsEx(const char* label_id, Getter getter, int count, TWidth width, in
int idx = offset;
for (int i = 0; i < count; ++i) {
ImPlotPoint p;
p = getter(idx);
ImPlotPoint p = getter(idx);
idx = (idx + 1) % count;
if (p.y == 0)
continue;
@ -2606,8 +2683,7 @@ void PlotBarsHEx(const char* label_id, Getter getter, int count, THeight height,
int idx = offset;
for (int i = 0; i < count; ++i) {
ImPlotPoint p;
p = getter(idx);
ImPlotPoint p = getter(idx);
idx = (idx + 1) % count;
if (p.x == 0)
continue;
@ -2828,9 +2904,42 @@ void PlotPieChart(const char** label_ids, double* values, int count, double x, d
//-----------------------------------------------------------------------------
void PlotHeatmap(const char* label_id, const double* values, int rows, int cols, double scale_min, double scale_max, bool show_labels) {
IM_ASSERT_USER_ERROR(gp.CurrentPlot != NULL, "PlotHeatmap() Needs to be called between BeginPlot() and EndPlot()!");
ImPlotItem* item = RegisterItem(label_id);
if (!item->Show)
return;
if (gp.FitThisFrame) {
FitPoint(ImPlotPoint(0, 0));
FitPoint(ImPlotPoint(1, 1));
}
ImDrawList& DrawList = *ImGui::GetWindowDrawList();
double w = 1.0 / cols;
double h = 1.0 / rows;
const ImPlotPoint half_size(w*0.5,h*0.5);
ImGui::PushClipRect(gp.BB_Grid.Min, gp.BB_Grid.Max, true);
int i = 0;
for (int r = 0; r < rows; ++r) {
for (int c = 0; c < cols; ++c) {
ImPlotPoint p;
p.x = 0.5*w + c*w;
p.y = 1 - (0.5*h + r*h);
ImVec2 px = PlotToPixels(p);
ImVec2 a = PlotToPixels(p.x - half_size.x, p.y - half_size.y);
ImVec2 b = PlotToPixels(p.x + half_size.x, p.y + half_size.y);
float t = (float)Remap(values[i], scale_min, scale_max, 0.0, 1.0);
ImVec4 color = SampleColormap(t);
DrawList.AddRectFilled(a, b, ImGui::GetColorU32(color));
if (show_labels) {
char buff[32];
sprintf(buff, "%g", values[i]);
ImVec2 size = ImGui::CalcTextSize(buff);
DrawList.AddText(px - size * 0.5f, ImGui::GetColorU32(ImGuiCol_Text), buff);
}
i++;
}
}
ImGui::PopClipRect();
}
//-----------------------------------------------------------------------------

View File

@ -34,6 +34,7 @@ typedef int ImPlotAxisFlags;
typedef int ImPlotCol;
typedef int ImPlotStyleVar;
typedef int ImPlotMarker;
typedef int ImPlotColormap;
// Options for plots.
enum ImPlotFlags_ {
@ -114,7 +115,25 @@ enum ImPlotMarker_ {
ImPlotMarker_Asterisk = 1 << 10, // a asterisk marker will be rendered at each point (not filled)
};
/// Double precision version of ImVec2 used by ImPlot. Extensible by end users.
// Built-in colormaps
enum ImPlotColormap_ {
// Qualitative
ImPlotColormap_Default,
// Sequential
ImPlotColormap_Viridis,
ImPlotColormap_Plasma,
ImPlotColormap_Hot,
ImPlotColormap_Cool,
// ImPlotColormap_Spring,
// ImPlotColormap_Summer,
// ImPlotColormap_Autumn,
// ImPlotColormap_Winter,
// Diverging
// ...
ImPlotColormap_COUNT
};
// Double precision version of ImVec2 used by ImPlot. Extensible by end users.
struct ImPlotPoint {
double x, y;
ImPlotPoint() { x = y = 0.0; }
@ -226,7 +245,7 @@ void PlotErrorBars(const char* label_id, const double* xs, const double* ys, con
void PlotPieChart(const char** label_ids, float* values, int count, float x, float y, float radius, bool show_percents = true, float angle0 = 90);
void PlotPieChart(const char** label_ids, double* values, int count, double x, double y, double radius, bool show_percents = true, double angle0 = 90);
// Plots a 2D heatmap chart.
// Plots a 2D heatmap chart. Values are expected to be in row-major order.
void PlotHeatmap(const char* label_id, const double* values, int rows, int cols, double scale_min, double scale_max, bool show_labels = true);
// Plots digital data.
@ -242,15 +261,15 @@ void PlotText(const char* text, double x, double y, bool vertical = false, const
// Plot Queries
//-----------------------------------------------------------------------------
/// Returns true if the plot area in the current or most recent plot is hovered.
// Returns true if the plot area in the current or most recent plot is hovered.
bool IsPlotHovered();
/// Returns the mouse position in x,y coordinates of the current or most recent plot. A negative y_axis uses the current value of SetPlotYAxis (0 initially).
// Returns the mouse position in x,y coordinates of the current or most recent plot. A negative y_axis uses the current value of SetPlotYAxis (0 initially).
ImPlotPoint GetPlotMousePos(int y_axis = -1);
/// Returns the current or most recent plot axis range. A negative y_axis uses the current value of SetPlotYAxis (0 initially).
// Returns the current or most recent plot axis range. A negative y_axis uses the current value of SetPlotYAxis (0 initially).
ImPlotLimits GetPlotLimits(int y_axis = -1);
/// Returns true if the current or most recent plot is being queried.
// Returns true if the current or most recent plot is being queried.
bool IsPlotQueried();
/// Returns the current or most recent plot query bounds.
// Returns the current or most recent plot query bounds.
ImPlotLimits GetPlotQuery(int y_axis = -1);
//-----------------------------------------------------------------------------
@ -260,10 +279,14 @@ ImPlotLimits GetPlotQuery(int y_axis = -1);
// Provides access to plot style structure for permanant modifications to colors, sizes, etc.
ImPlotStyle& GetStyle();
// Sets the color palette to be used for plot items.
void SetPalette(const ImVec4* colors, int num_colors);
// Restores the default ImPlot color map.
void RestorePalette();
// Switch to one of the built-in colormaps for plot items.
void SetColormap(ImPlotColormap colormap);
// Sets a custom colormap to be used for plot items.
void SetColormap(const ImVec4* colors, int num_colors);
// Restores the default ImPlot colormap.
void RestoreColormap();
// Linearly interpolates a color from the current colormap/
ImVec4 SampleColormap(float t);
// Temporarily modify a plot color. Don't forget to call PopStyleColor!
void PushStyleColor(ImPlotCol idx, ImU32 col);
@ -283,14 +306,14 @@ void PopStyleVar(int count = 1);
// Plot Utils
//-----------------------------------------------------------------------------
/// Set the axes range limits of the next plot. Call right before BeginPlot(). If ImGuiCond_Always is used, the axes limits will be locked.
// Set the axes range limits of the next plot. Call right before BeginPlot(). If ImGuiCond_Always is used, the axes limits will be locked.
void SetNextPlotLimits(double x_min, double x_max, double y_min, double y_max, ImGuiCond cond = ImGuiCond_Once);
/// Set the X axis range limits of the next plot. Call right before BeginPlot(). If ImGuiCond_Always is used, the X axis limits will be locked.
// Set the X axis range limits of the next plot. Call right before BeginPlot(). If ImGuiCond_Always is used, the X axis limits will be locked.
void SetNextPlotLimitsX(double x_min, double x_max, ImGuiCond cond = ImGuiCond_Once);
/// Set the Y axis range limits of the next plot. Call right before BeginPlot(). If ImGuiCond_Always is used, the Y axis limits will be locked.
// Set the Y axis range limits of the next plot. Call right before BeginPlot(). If ImGuiCond_Always is used, the Y axis limits will be locked.
void SetNextPlotLimitsY(double y_min, double y_max, ImGuiCond cond = ImGuiCond_Once, int y_axis = 0);
/// Select which Y axis will be used for subsequent plot elements. The default is '0', or the first (left) Y axis.
// Select which Y axis will be used for subsequent plot elements. The default is '0', or the first (left) Y axis.
void SetPlotYAxis(int y_axis);
// Get the current Plot position (top-left) in pixels.

View File

@ -129,7 +129,7 @@ void ShowDemoWindow(bool* p_open) {
if (show_app_metrics) { ImGui::ShowMetricsWindow(&show_app_metrics); }
if (show_app_style_editor) { ImGui::Begin("Style Editor", &show_app_style_editor); ImGui::ShowStyleEditor(); ImGui::End(); }
ImGui::SetNextWindowPos(ImVec2(50, 50), ImGuiCond_FirstUseEver);
ImGui::SetNextWindowSize(ImVec2(520, 750), ImGuiCond_FirstUseEver);
ImGui::SetNextWindowSize(ImVec2(530, 750), ImGuiCond_FirstUseEver);
ImGui::Begin("ImPlot Demo", p_open, ImGuiWindowFlags_MenuBar);
if (ImGui::BeginMenuBar()) {
if (ImGui::BeginMenu("Tools")) {
@ -307,7 +307,7 @@ void ShowDemoWindow(bool* p_open) {
ImVec4(0.9882f, 0.3059f, 0.1647f, 1.0f),
ImVec4(0.7412f, 0.0f, 0.1490f, 1.0f),
};
ImPlot::SetPalette(YlOrRd, 5);
ImPlot::SetColormap(YlOrRd, 5);
SetNextPlotLimits(0,1,0,1,ImGuiCond_Always);
static const char* labels2[] = {"One","Two","Three","Four","Five"};
static t_float not_normalized[] = {1,2,3,4,5};
@ -315,7 +315,38 @@ void ShowDemoWindow(bool* p_open) {
ImPlot::PlotPieChart(labels2, not_normalized, 5, 0.5f, 0.5f, 0.4f);
ImPlot::EndPlot();
}
ImPlot::RestorePalette();
ImPlot::RestoreColormap();
}
//-------------------------------------------------------------------------
if (ImGui::CollapsingHeader("Heatmaps")) {
static double values1[7][7] = {{0.8, 2.4, 2.5, 3.9, 0.0, 4.0, 0.0},
{2.4, 0.0, 4.0, 1.0, 2.7, 0.0, 0.0},
{1.1, 2.4, 0.8, 4.3, 1.9, 4.4, 0.0},
{0.6, 0.0, 0.3, 0.0, 3.1, 0.0, 0.0},
{0.7, 1.7, 0.6, 2.6, 2.2, 6.2, 0.0},
{1.3, 1.2, 0.0, 0.0, 0.0, 3.2, 5.1},
{0.1, 2.0, 0.0, 1.4, 0.0, 1.9, 6.3}};
static double values2[100*100];
for (int i = 0; i < 100*100; ++i) {
values2[i] = RandomRange(0,1);
}
static ImPlotColormap map = ImPlotColormap_Viridis;
if (ImGui::Button("Cycle Colormaps"))
map = (map + 1) % ImPlotColormap_COUNT;
static ImPlotAxisFlags axes_flags = ImPlotAxisFlags_LockMin | ImPlotAxisFlags_LockMax;
if (ImPlot::BeginPlot("##Heatmap1",NULL,NULL,ImVec2(250,250),0,axes_flags,axes_flags)) {
ImPlot::SetColormap(map);
ImPlot::PlotHeatmap("heat",values1[0],7,7,0,6.3);
ImPlot::EndPlot();
ImPlot::RestoreColormap();
}
ImGui::SameLine();
if (ImPlot::BeginPlot("##Heatmap2",NULL,NULL,ImVec2(250,250),0,axes_flags,axes_flags)) {
ImPlot::SetColormap(map);
ImPlot::PlotHeatmap("heat",values2,100,100,0,1,false);
ImPlot::EndPlot();
ImPlot::RestoreColormap();
}
}
//-------------------------------------------------------------------------
if (ImGui::CollapsingHeader("Realtime Plots")) {
@ -783,12 +814,12 @@ void ShowDemoWindow(bool* p_open) {
}
//-------------------------------------------------------------------------
if (ImGui::CollapsingHeader("Custom Styles")) {
static ImVec4 my_palette[3] = {
static ImVec4 my_map[3] = {
ImVec4(0.000f, 0.980f, 0.604f, 1.0f),
ImVec4(0.996f, 0.278f, 0.380f, 1.0f),
ImVec4(0.1176470593f, 0.5647059083f, 1.0f, 1.0f),
};
ImPlot::SetPalette(my_palette, 3);
ImPlot::SetColormap(my_map, 3);
ImPlot::PushStyleColor(ImPlotCol_FrameBg, IM_COL32(32,51,77,255));
ImPlot::PushStyleColor(ImPlotCol_PlotBg, ImVec4(0,0,0,0));
ImPlot::PushStyleColor(ImPlotCol_PlotBorder, ImVec4(0,0,0,0));
@ -810,7 +841,7 @@ void ShowDemoWindow(bool* p_open) {
}
ImPlot::PopStyleColor(5);
ImPlot::PopStyleVar();
ImPlot::RestorePalette();
ImPlot::RestoreColormap();
}
//-------------------------------------------------------------------------
if (ImGui::CollapsingHeader("Custom Rendering")) {