Skip to content
Open
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
13 changes: 13 additions & 0 deletions implot.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4596,6 +4596,19 @@ ImVec4 SampleColormap(float t, ImPlotColormap cmap) {
return ImGui::ColorConvertU32ToFloat4(SampleColormapU32(t,cmap));
}

ImU32 ConvertValueToColor(float value, float v_min, float v_max, ImPlotColormap colormap) {
return SampleColormapU32(ImClamp(ImRemap01(value, v_min, v_max), 0.f, 1.f), colormap);
}

template <typename T>
void ConvertValueToColor(T* value, ImU32* cs, int count, float v_min, float v_max, ImPlotColormap colormap) {
for (int i = 0; i < count; i++)
cs[i] = SampleColormapU32(ImClamp(ImRemap01(static_cast<float>(value[i]), v_min, v_max), 0.f, 1.f), colormap);
}
template void ConvertValueToColor<double>(double* value, ImU32* cs, int count, float v_min, float v_max, ImPlotColormap colormap);
template void ConvertValueToColor<float>(float* value, ImU32* cs, int count, float v_min, float v_max, ImPlotColormap colormap);
template void ConvertValueToColor<int>(int* value, ImU32* cs, int count, float v_min, float v_max, ImPlotColormap colormap);

void RenderColorBar(const ImU32* colors, int size, ImDrawList& DrawList, const ImRect& bounds, bool vert, bool reversed, bool continuous) {
const int n = continuous ? size - 1 : size;
ImU32 col1, col2;
Expand Down
23 changes: 18 additions & 5 deletions implot.h
Original file line number Diff line number Diff line change
Expand Up @@ -238,12 +238,14 @@ enum ImPlotLineFlags_ {
ImPlotLineFlags_SkipNaN = 1 << 12, // NaNs values will be skipped instead of rendered as missing data
ImPlotLineFlags_NoClip = 1 << 13, // markers (if displayed) on the edge of a plot will not be clipped
ImPlotLineFlags_Shaded = 1 << 14, // a filled region between the line and horizontal origin will be rendered; use PlotShaded for more advanced cases
ImPlotLineFlags_PerPointCustomColor = 1 << 15, // each point is assigned with a specific color according to its value
};

// Flags for PlotScatter
enum ImPlotScatterFlags_ {
ImPlotScatterFlags_None = 0, // default
ImPlotScatterFlags_NoClip = 1 << 10, // markers on the edge of a plot will not be clipped
ImPlotScatterFlags_None = 0, // default
ImPlotScatterFlags_NoClip = 1 << 10, // markers on the edge of a plot will not be clipped
ImPlotScatterFlags_PerPointCustomColor = 1 << 11, // markers with multiple colors
};

// Flags for PlotStairs
Expand Down Expand Up @@ -473,9 +475,11 @@ enum ImPlotBin_ {
IM_MSVC_RUNTIME_CHECKS_OFF
struct ImPlotPoint {
double x, y;
IMPLOT_API constexpr ImPlotPoint() : x(0.0), y(0.0) { }
IMPLOT_API constexpr ImPlotPoint(double _x, double _y) : x(_x), y(_y) { }
IMPLOT_API constexpr ImPlotPoint(const ImVec2& p) : x((double)p.x), y((double)p.y) { }
ImU32 c;
IMPLOT_API constexpr ImPlotPoint() : x(0.0), y(0.0), c(ImU32()) { }
IMPLOT_API constexpr ImPlotPoint(double _x, double _y) : x(_x), y(_y), c(ImU32()) { }
IMPLOT_API constexpr ImPlotPoint(const ImVec2& p) : x((double)p.x), y((double)p.y), c(ImU32()) { }
IMPLOT_API constexpr ImPlotPoint(double _x, double _y, ImU32 _c) : x(_x), y(_y), c(_c) { }
IMPLOT_API double& operator[] (size_t idx) { IM_ASSERT(idx == 0 || idx == 1); return ((double*)(void*)(char*)this)[idx]; }
IMPLOT_API double operator[] (size_t idx) const { IM_ASSERT(idx == 0 || idx == 1); return ((const double*)(const void*)(const char*)this)[idx]; }
#ifdef IMPLOT_POINT_CLASS_EXTRA
Expand Down Expand Up @@ -861,11 +865,13 @@ IMPLOT_API void SetNextAxesToFit();
// Plots a standard 2D line plot.
IMPLOT_TMP void PlotLine(const char* label_id, const T* values, int count, double xscale=1, double xstart=0, ImPlotLineFlags flags=0, int offset=0, int stride=sizeof(T));
IMPLOT_TMP void PlotLine(const char* label_id, const T* xs, const T* ys, int count, ImPlotLineFlags flags=0, int offset=0, int stride=sizeof(T));
IMPLOT_TMP void PlotLine(const char* label_id, const T* xs, const T* ys, const ImU32* cs, int count, ImPlotLineFlags flags = 0, int offset = 0, int stride = sizeof(T));
IMPLOT_API void PlotLineG(const char* label_id, ImPlotGetter getter, void* data, int count, ImPlotLineFlags flags=0);

// Plots a standard 2D scatter plot. Default marker is ImPlotMarker_Circle.
IMPLOT_TMP void PlotScatter(const char* label_id, const T* values, int count, double xscale=1, double xstart=0, ImPlotScatterFlags flags=0, int offset=0, int stride=sizeof(T));
IMPLOT_TMP void PlotScatter(const char* label_id, const T* xs, const T* ys, int count, ImPlotScatterFlags flags=0, int offset=0, int stride=sizeof(T));
IMPLOT_TMP void PlotScatter(const char* label_id, const T* xs, const T* ys, const ImU32* cs, int count, ImPlotScatterFlags flags=0, int offset=0, int stride=sizeof(T));
IMPLOT_API void PlotScatterG(const char* label_id, ImPlotGetter getter, void* data, int count, ImPlotScatterFlags flags=0);

// Plots a a stairstep graph. The y value is continued constantly to the right from every x position, i.e. the interval [x[i], x[i+1]) has the value y[i]
Expand Down Expand Up @@ -930,6 +936,10 @@ IMPLOT_API void PlotText(const char* text, double x, double y, const ImVec2& pix
// Plots a dummy item (i.e. adds a legend entry colored by ImPlotCol_Line)
IMPLOT_API void PlotDummy(const char* label_id, ImPlotDummyFlags flags=0);

// Plots a 2D filled contour without lines, given a regular/irregular grid of data.
IMPLOT_TMP void PlotContourFill(const char* label_id, const T* xs, const T* ys, const ImU32* cs, int x_count, int y_count, const ImPlotPoint& bounds_min, const ImPlotPoint& bounds_max);


//-----------------------------------------------------------------------------
// [SECTION] Plot Tools
//-----------------------------------------------------------------------------
Expand Down Expand Up @@ -1191,6 +1201,9 @@ IMPLOT_API ImVec4 GetColormapColor(int idx, ImPlotColormap cmap = IMPLOT_AUTO);
// Sample a color from the current colormap given t between 0 and 1.
IMPLOT_API ImVec4 SampleColormap(float t, ImPlotColormap cmap = IMPLOT_AUTO);

// Convert values to colors using a specific colormap.
IMPLOT_TMP void ConvertValueToColor(T* value, ImU32* cs, int count, float v_min, float v_max, ImPlotColormap colormap);

// Shows a vertical color scale with linear spaced ticks using the specified color map. Use double hashes to hide label (e.g. "##NoLabel"). If scale_min > scale_max, the scale to color mapping will be reversed.
IMPLOT_API void ColormapScale(const char* label, double scale_min, double scale_max, const ImVec2& size = ImVec2(0,0), const char* format = "%g", ImPlotColormapScaleFlags flags = 0, ImPlotColormap cmap = IMPLOT_AUTO);
// Shows a horizontal slider with a colormap gradient background. Optionally returns the color sampled at t in [0 1].
Expand Down
135 changes: 125 additions & 10 deletions implot_demo.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -299,11 +299,50 @@ void Demo_LinePlots() {
xs2[i] = i * 1/19.0f;
ys2[i] = xs2[i] * xs2[i];
}

if (ImPlot::BeginPlot("Line Plots")) {
ImPlot::SetupAxes("x","y");
ImPlot::PlotLine("f(x)", xs1, ys1, 1001);
ImPlot::SetNextMarkerStyle(ImPlotMarker_Circle);
ImPlot::PlotLine("g(x)", xs2, ys2, 20,ImPlotLineFlags_Segments);
ImPlot::PlotLine("g(x)", xs2, ys2, 20, ImPlotLineFlags_Segments);
ImPlot::EndPlot();
}

static ImU32 colors3[150], colors4[200];
static float scale_min = FLT_MAX;
static float scale_max = -FLT_MAX;

static float xs3[150], ys3[150], zs3[150];
for (int i = 0; i < 150; i++)
{
xs3[i] = i;
ys3[i] = 1.2 * i * i;
zs3[i] = cosf(i * 0.1f);
scale_min = (scale_min > zs3[i]) ? zs3[i] : scale_min;
scale_max = (scale_max < zs3[i]) ? zs3[i] : scale_max;
}

static float xs4[200], ys4[200], zs4[200];
for (int i = 0; i < 200; i++)
{
xs4[i] = i;
ys4[i] = 0.6f * i * i * (1.f + sinf(50.f * (xs4[i] + ImGui::GetTime() / 10)));
zs4[i] = sinf(i * 0.1f);
}

const char* colormaps[] = { "Viridis", "Plasma", "Hot", "Cool", "Pink", "Jet", "Twilight", "RdBu", "BrBG", "PiYG", "Spectral", "Greys" };
static int sel_colormap = 5; // Jet by default
ImGui::Combo("Choose colormap", &sel_colormap, colormaps, IM_ARRAYSIZE(colormaps));
ImGui::DragFloatRange2("Scale Min / Max", &scale_min, &scale_max, 0.1);
ImPlotColormap cmap = GetColormapIndex(colormaps[sel_colormap]);
ImPlot::ConvertValueToColor(zs3, colors3, 150, scale_min, scale_max, cmap);
ImPlot::ConvertValueToColor(zs4, colors4, 200, scale_min, scale_max, cmap);
ImPlot::ColormapScale("##Z-Scale", floorf(scale_min), ceilf(scale_max), ImVec2(60, 300), "%.2f", 0, cmap);
ImGui::SameLine();
if (ImPlot::BeginPlot("Line Plots with Per Point Custom Colors")) {
ImPlot::SetupAxes("x", "y");
ImPlot::PlotLine("h(x)", xs3, ys3, colors3, 150, ImPlotLineFlags_Segments|ImPlotLineFlags_PerPointCustomColor);
ImPlot::PlotLine("i(x)", xs4, ys4, colors4, 200, ImPlotLineFlags_PerPointCustomColor);
ImPlot::EndPlot();
}
}
Expand Down Expand Up @@ -394,25 +433,57 @@ void Demo_ShadedPlots() {
//-----------------------------------------------------------------------------

void Demo_ScatterPlots() {
static ImU32 colors1[100], colors2[50];
static float scale_min = FLT_MAX;
static float scale_max = -FLT_MAX;
const char* colormaps[] = { "Viridis", "Plasma", "Hot", "Cool", "Pink", "Jet", "Twilight", "RdBu", "BrBG", "PiYG", "Spectral", "Greys" };
static int sel_colormap = 5; // Jet by default

srand(0);
static float xs1[100], ys1[100];
static float xs1[100], ys1[100], vs1[100];
for (int i = 0; i < 100; ++i) {
xs1[i] = i * 0.01f;
ys1[i] = xs1[i] + 0.1f * ((float)rand() / (float)RAND_MAX);
vs1[i] = sin(i * 0.1f);
scale_min = (scale_min > vs1[i]) ? vs1[i] : scale_min;
scale_max = (scale_max < vs1[i]) ? vs1[i] : scale_max;
}
static float xs2[50], ys2[50];
static float xs2[50], ys2[50], vs2[50];
for (int i = 0; i < 50; i++) {
xs2[i] = 0.25f + 0.2f * ((float)rand() / (float)RAND_MAX);
ys2[i] = 0.75f + 0.2f * ((float)rand() / (float)RAND_MAX);
vs2[i] = cos(i * 0.1f);
}

if (ImPlot::BeginPlot("Scatter Plot")) {
ImPlot::PlotScatter("Data 1", xs1, ys1, 100);
ImPlot::PushStyleVar(ImPlotStyleVar_FillAlpha, 0.25f);
ImPlot::SetNextMarkerStyle(ImPlotMarker_Square, 6, ImPlot::GetColormapColor(1), IMPLOT_AUTO, ImPlot::GetColormapColor(1));
ImPlot::PlotScatter("Data 2", xs2, ys2, 50);
ImPlot::PopStyleVar();
ImPlot::EndPlot();
static bool ppc_color = false;
ImGui::Checkbox("Per Point Custom Color", &ppc_color);
if (!ppc_color) {
if (ImPlot::BeginPlot("Scatter Plot")) {
ImPlot::PlotScatter("Data 1", xs1, ys1, 100);
ImPlot::PushStyleVar(ImPlotStyleVar_FillAlpha, 0.25f);
ImPlot::SetNextMarkerStyle(ImPlotMarker_Square, 6, ImPlot::GetColormapColor(1), IMPLOT_AUTO, ImPlot::GetColormapColor(1));
ImPlot::PlotScatter("Data 2", xs2, ys2, 50);
ImPlot::PopStyleVar();
ImPlot::EndPlot();
}
}
else {
ImGui::Combo("##ScatterColormap", &sel_colormap, colormaps, IM_ARRAYSIZE(colormaps));
ImGui::SameLine();
ImGui::Text("Choose colormap");
ImGui::DragFloatRange2("Min / Max", &scale_min, &scale_max, 0.1);
ImPlotColormap cmap = GetColormapIndex(colormaps[sel_colormap]);
ImPlot::ConvertValueToColor(vs1, colors1, 100, scale_min, scale_max, cmap);
ImPlot::ConvertValueToColor(vs2, colors2, 50, scale_min, scale_max, cmap);
ImPlot::ColormapScale("##Z-Scale", scale_min, scale_max, ImVec2(60, 300), "%.2f", 0, cmap);
ImGui::SameLine();
if (ImPlot::BeginPlot("Scatter Plot with Per Point Custom Colors")) {
ImPlot::PlotScatter("Data 1", xs1, ys1, colors1, 100, ImPlotScatterFlags_PerPointCustomColor);
ImPlot::PushStyleVar(ImPlotStyleVar_FillAlpha, 0.25f);
ImPlot::SetNextMarkerStyle(ImPlotMarker_Square, 6);
ImPlot::PlotScatter("Data 2", xs2, ys2, colors2, 50, ImPlotScatterFlags_PerPointCustomColor);
ImPlot::EndPlot();
}
}
}

Expand Down Expand Up @@ -1003,6 +1074,49 @@ void Demo_NaNValues() {
}
}

//-----------------------------------------------------------------------------
void Demo_ContourMap() {
constexpr int M = 240;
constexpr int N = 160;
static float delta = 0.025f;
static float xs[M * N];
static float ys[M * N];
static float zs[M * N];
static ImU32 colors[M * N];

static float scale_min = FLT_MAX;
static float scale_max = -FLT_MAX;
for (int i = 0; i < M; i++) {
for (int j = 0; j < N; j++) {
int idx = j * M + i;
xs[idx] = -3.f + i * delta;
ys[idx] = -2.f + j * delta;
zs[idx] = (1.f - 0.5f * xs[idx] + powf(xs[idx], 5) + powf(ys[idx], 3)) * expf(-xs[idx] * xs[idx] - ys[idx] * ys[idx]);
scale_min = (scale_min < zs[idx]) ? scale_min : zs[idx];
scale_max = (scale_max > zs[idx]) ? scale_max : zs[idx];
}
}

// Choose colormap
const char* colormaps[] = { "Viridis", "Plasma", "Hot", "Cool", "Pink", "Jet", "Twilight", "RdBu", "BrBG", "PiYG", "Spectral", "Greys" };
static int sel_colormap = 7; // RdBu by default
ImGui::SetNextItemWidth(360);
ImGui::Combo("##ContourColormap", &sel_colormap, colormaps, IM_ARRAYSIZE(colormaps));
ImGui::SameLine();
ImGui::Text("Choose colormap");
ImGui::SetNextItemWidth(360);
ImGui::DragFloatRange2("Min / Max", &scale_min, &scale_max, 0.01f, -3.f, 3.f);

ImPlotColormap cmap = ImPlot::GetColormapIndex(colormaps[sel_colormap]);
ImPlot::ConvertValueToColor(zs, colors, M * N, scale_min, scale_max, cmap);
if (ImPlot::BeginPlot("##Contour", ImVec2(M * 2, N * 2))) {
ImPlot::PlotContourFill("Contour Map", xs, ys, colors, M, N, ImPlotPoint(-3.f, -2.f), ImPlotPoint(-3.f + M * delta, -2.f + N * delta));
ImPlot::EndPlot();
}
ImGui::SameLine();
ImPlot::ColormapScale("##Z-Scale", scale_min, scale_max, ImVec2(60, N * 2), "%.2f", 0, cmap);
}

//-----------------------------------------------------------------------------

void Demo_LogScale() {
Expand Down Expand Up @@ -2264,6 +2378,7 @@ void ShowDemoWindow(bool* p_open) {
DemoHeader("Images", Demo_Images);
DemoHeader("Markers and Text", Demo_MarkersAndText);
DemoHeader("NaN Values", Demo_NaNValues);
DemoHeader("Contour Map", Demo_ContourMap);
ImGui::EndTabItem();
}
if (ImGui::BeginTabItem("Subplots")) {
Expand Down
Loading