1
0
Fork 0
mirror of https://github.com/gwm17/implot.git synced 2024-11-23 02:38:53 -05:00

finish templetizing API, several optimizations to plotting pipeline, remmove t_float etc from demo

This commit is contained in:
epezent 2020-09-07 16:08:59 -05:00
parent 48cc6e15d6
commit 75e779c931
4 changed files with 458 additions and 400 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. 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. You can read releases logs https://github.com/epezent/implot/releases for more details.
- 2020/09/07 (0.8) - Plotting functions which accept a custom getter function pointer have been post-fixed with a G (e.g. PlotLineG)
- 2020/09/06 (0.7) - Several flags under ImPlotFlags and ImPlotAxisFlags were inverted (e.g. ImPlotFlags_Legend -> ImPlotFlags_NoLegend) so that the default flagset - 2020/09/06 (0.7) - Several flags under ImPlotFlags and ImPlotAxisFlags were inverted (e.g. ImPlotFlags_Legend -> ImPlotFlags_NoLegend) so that the default flagset
is simply 0. This more closely matches ImGui's style and makes it easier to enable non-default but commonly used flags (e.g. ImPlotAxisFlags_Time). is simply 0. This more closely matches ImGui's style and makes it easier to enable non-default but commonly used flags (e.g. ImPlotAxisFlags_Time).
- 2020/08/28 (0.5) - ImPlotMarker_ can no longer be combined with bitwise OR, |. This features caused unecessary slow-down, and almost no one used it. - 2020/08/28 (0.5) - ImPlotMarker_ can no longer be combined with bitwise OR, |. This features caused unecessary slow-down, and almost no one used it.

View File

@ -301,8 +301,40 @@ void EndPlot();
// Plot Items // Plot Items
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
// Supported Types for T* // The template functions below are explicitly instantiated in implot_items.cpp.
// They are not intended to be used generically with custom types. You will get
// a linker error if you try! All functions support the following scalar types:
//
// float, double, ImS8, ImU8, ImS16, ImU16, ImS32, ImU32, ImS64, ImU64 // float, double, ImS8, ImU8, ImS16, ImU16, ImS32, ImU32, ImS64, ImU64
//
//
// If you need to plot custom or non-homogenous data you have a few options:
//
// 1. If your data is a simple struct/class (e.g. Vector2f), you can use striding.
// This is the most performant option if applicable.
//
// struct Vector2f { float X, Y; };
// ...
// Vector2f data[42];
// ImPlot::PlotLine("line", &data[0].x, &data[0].y, 42, 0, sizeof(Vector2f)); // or sizeof(float)*2
//
// 2. Write a custom getter function or C++ lambda and pass it and your data to
// an ImPlot function post-fixed with a G (e.g. PlotScatterG). This has a
// slight performance cost, but probably not enough to worry about.
//
// ImPlotPoint MyDataGetter(void* data, int idx) {
// MyData* my_data = (MyData*)data;
// ImPlotPoint p;
// p.X = my_data->GetTime(idx);
// p.Y = my_data->GetValue(idx);
// return p
// }
// ...
// MyData my_data;
// ImPlot::PlotScatterG("scatter", MyDataGetter, &my_data, my_data.Size());
//
// NB: All types are converted to double before plotting. You may loose information
// if you try plotting extremely large 64-bit integral types. Proceed with caution!
// Plots a standard 2D line plot. // Plots a standard 2D line plot.
template <typename T> void PlotLine(const char* label_id, const T* values, int count, int offset = 0, int stride = sizeof(T)); template <typename T> void PlotLine(const char* label_id, const T* values, int count, int offset = 0, int stride = sizeof(T));
@ -330,41 +362,29 @@ template <typename T> void PlotBarsH(const char* label_id, const T* values, int
template <typename T> void PlotBarsH(const char* label_id, const T* xs, const T* ys, int count, double height, int offset = 0, int stride = sizeof(T)); template <typename T> void PlotBarsH(const char* label_id, const T* xs, const T* ys, int count, double height, int offset = 0, int stride = sizeof(T));
void PlotBarsHG(const char* label_id, ImPlotPoint (*getter)(void* data, int idx), void* data, int count, double height, int offset = 0); void PlotBarsHG(const char* label_id, ImPlotPoint (*getter)(void* data, int idx), void* data, int count, double height, int offset = 0);
// TODO ...
// Plots vertical error bar. The label_id should be the same as the label_id of the associated line or bar plot. // Plots vertical error bar. The label_id should be the same as the label_id of the associated line or bar plot.
void PlotErrorBars(const char* label_id, const float* xs, const float* ys, const float* err, int count, int offset = 0, int stride = sizeof(float)); template <typename T> void PlotErrorBars(const char* label_id, const T* xs, const T* ys, const T* err, int count, int offset = 0, int stride = sizeof(T));
void PlotErrorBars(const char* label_id, const double* xs, const double* ys, const double* err, int count, int offset = 0, int stride = sizeof(double)); template <typename T> void PlotErrorBars(const char* label_id, const T* xs, const T* ys, const T* neg, const T* pos, int count, int offset = 0, int stride = sizeof(T));
void PlotErrorBars(const char* label_id, const float* xs, const float* ys, const float* neg, const float* pos, int count, int offset = 0, int stride = sizeof(float));
void PlotErrorBars(const char* label_id, const double* xs, const double* ys, const double* neg, const double* pos, int count, int offset = 0, int stride = sizeof(double));
// Plots horizontal error bars. The label_id should be the same as the label_id of the associated line or bar plot. // Plots horizontal error bars. The label_id should be the same as the label_id of the associated line or bar plot.
void PlotErrorBarsH(const char* label_id, const float* xs, const float* ys, const float* err, int count, int offset = 0, int stride = sizeof(float)); template <typename T> void PlotErrorBarsH(const char* label_id, const T* xs, const T* ys, const T* err, int count, int offset = 0, int stride = sizeof(T));
void PlotErrorBarsH(const char* label_id, const double* xs, const double* ys, const double* err, int count, int offset = 0, int stride = sizeof(double)); template <typename T> void PlotErrorBarsH(const char* label_id, const T* xs, const T* ys, const T* neg, const T* pos, int count, int offset = 0, int stride = sizeof(T));
void PlotErrorBarsH(const char* label_id, const float* xs, const float* ys, const float* neg, const float* pos, int count, int offset = 0, int stride = sizeof(float));
void PlotErrorBarsH(const char* label_id, const double* xs, const double* ys, const double* neg, const double* pos, int count, int offset = 0, int stride = sizeof(double));
/// Plots vertical stems. /// Plots vertical stems.
void PlotStems(const char* label_id, const float* values, int count, float y_ref = 0, int offset = 0, int stride = sizeof(float)); template <typename T> void PlotStems(const char* label_id, const T* values, int count, double y_ref = 0, int offset = 0, int stride = sizeof(T));
void PlotStems(const char* label_id, const double* values, int count, double y_ref = 0, int offset = 0, int stride = sizeof(double)); template <typename T> void PlotStems(const char* label_id, const T* xs, const T* ys, int count, double y_ref = 0, int offset = 0, int stride = sizeof(T));
void PlotStems(const char* label_id, const float* xs, const float* ys, int count, float y_ref = 0, int offset = 0, int stride = sizeof(float));
void PlotStems(const char* label_id, const double* xs, const double* ys, int count, double y_ref = 0, int offset = 0, int stride = sizeof(double));
// Plots a pie chart. If the sum of values > 1 or normalize is true, each value will be normalized. Center and radius are in plot units. #label_fmt can be set to NULL for no labels. // Plots a pie chart. If the sum of values > 1 or normalize is true, each value will be normalized. Center and radius are in plot units. #label_fmt can be set to NULL for no labels.
void PlotPieChart(const char* const label_ids[], const float* values, int count, float x, float y, float radius, bool normalize = false, const char* label_fmt = "%.1f", float angle0 = 90); template <typename T> void PlotPieChart(const char* const label_ids[], const T* values, int count, double x, double y, double radius, bool normalize = false, const char* label_fmt = "%.1f", double angle0 = 90);
void PlotPieChart(const char* const label_ids[], const double* values, int count, double x, double y, double radius, bool normalize = false, const char* label_fmt = "%.1f", double angle0 = 90);
// Plots a 2D heatmap chart. Values are expected to be in row-major order. #label_fmt can be set to NULL for no labels. // Plots a 2D heatmap chart. Values are expected to be in row-major order. #label_fmt can be set to NULL for no labels.
void PlotHeatmap(const char* label_id, const float* values, int rows, int cols, float scale_min, float scale_max, const char* label_fmt = "%.1f", const ImPlotPoint& bounds_min = ImPlotPoint(0,0), const ImPlotPoint& bounds_max = ImPlotPoint(1,1)); template <typename T> void PlotHeatmap(const char* label_id, const T* values, int rows, int cols, double scale_min, double scale_max, const char* label_fmt = "%.1f", const ImPlotPoint& bounds_min = ImPlotPoint(0,0), const ImPlotPoint& bounds_max = ImPlotPoint(1,1));
void PlotHeatmap(const char* label_id, const double* values, int rows, int cols, double scale_min, double scale_max, const char* label_fmt = "%.1f", const ImPlotPoint& bounds_min = ImPlotPoint(0,0), const ImPlotPoint& bounds_max = ImPlotPoint(1,1));
// Plots digital data. Digital plots do not respond to y drag or zoom, and are always referenced to the bottom of the plot. // Plots digital data. Digital plots do not respond to y drag or zoom, and are always referenced to the bottom of the plot.
void PlotDigital(const char* label_id, const float* xs, const float* ys, int count, int offset = 0, int stride = sizeof(float)); template <typename T> void PlotDigital(const char* label_id, const T* xs, const T* ys, int count, int offset = 0, int stride = sizeof(T));
void PlotDigital(const char* label_id, const double* xs, const double* ys, int count, int offset = 0, int stride = sizeof(double)); void PlotDigitalG(const char* label_id, ImPlotPoint (*getter)(void* data, int idx), void* data, int count, int offset = 0);
void PlotDigital(const char* label_id, ImPlotPoint (*getter)(void* data, int idx), void* data, int count, int offset = 0);
// Plots a centered text label at point x,y with optional pixel offset. Text color can be changed with ImPlot::PushStyleColor(ImPlotCol_InlayText, ...). // Plots a centered text label at point x,y with optional pixel offset. Text color can be changed with ImPlot::PushStyleColor(ImPlotCol_InlayText, ...).
void PlotText(const char* text, float x, float y, bool vertical = false, const ImVec2& pixel_offset = ImVec2(0,0));
void PlotText(const char* text, double x, double y, bool vertical = false, const ImVec2& pixel_offset = ImVec2(0,0)); void PlotText(const char* text, double x, double y, bool vertical = false, const ImVec2& pixel_offset = ImVec2(0,0));
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------

View File

@ -32,9 +32,16 @@
#define sprintf sprintf_s #define sprintf sprintf_s
#endif #endif
// Encapsulates examples for customizing ImPlot.
namespace MyImPlot { namespace MyImPlot {
// Examples for passing custom function pointers to ImPlot in Custom Getters section. // Example for Custom Data and Getters section.
struct Vector2f {
Vector2f(float _x, float _y) { x = _x; y = _y; }
float x, y;
};
// Example for Custom Data and Getters section.
struct WaveData { struct WaveData {
double X, Amp, Freq, Offset; double X, Amp, Freq, Offset;
WaveData(double x, double amp, double freq, double offset) { X = x; Amp = amp; Freq = freq; Offset = offset; } WaveData(double x, double amp, double freq, double offset) { X = x; Amp = amp; Freq = freq; Offset = offset; }
@ -42,44 +49,25 @@ struct WaveData {
ImPlotPoint SineWave(void* wave_data, int idx); ImPlotPoint SineWave(void* wave_data, int idx);
ImPlotPoint SawWave(void* wave_data, int idx); ImPlotPoint SawWave(void* wave_data, int idx);
ImPlotPoint Spiral(void*, int idx); ImPlotPoint Spiral(void*, int idx);
// Example for Tables section. Generates a quick and simple shaded line plot. See implementation at bottom.
// Example for Tables section.
void Sparkline(const char* id, const float* values, int count, float min_v, float max_v, int offset, const ImVec4& col, const ImVec2& size); void Sparkline(const char* id, const float* values, int count, float min_v, float max_v, int offset, const ImVec4& col, const ImVec2& size);
// Example for Custom Plotters and Tooltips section. Plots a candlestick chart for financial data. See implementation at bottom.
// Example for Custom Plotters and Tooltips section.
void PlotCandlestick(const char* label_id, const double* xs, const double* opens, const double* closes, const double* lows, const double* highs, int count, bool tooltip = true, float width_percent = 0.25f, ImVec4 bullCol = ImVec4(0,1,0,1), ImVec4 bearCol = ImVec4(1,0,0,1)); void PlotCandlestick(const char* label_id, const double* xs, const double* opens, const double* closes, const double* lows, const double* highs, int count, bool tooltip = true, float width_percent = 0.25f, ImVec4 bullCol = ImVec4(0,1,0,1), ImVec4 bearCol = ImVec4(1,0,0,1));
// Sets style to mimic Seaborn
// Example for Custom Styles section.
void StyleSeaborn(); void StyleSeaborn();
} // namespace MyImPlot } // namespace MyImPlot
namespace ImPlot { namespace ImPlot {
/// Choose whether the demo uses double or float versions of the ImPlot API.
/// NB: You don't ever need to typdef of define values for ImPlot. This
/// is only being done here for the sake of demoing both precision types.
// #define IMPLOT_DEMO_USE_DOUBLE
#ifdef IMPLOT_DEMO_USE_DOUBLE
typedef double t_float;
typedef ImPlotPoint t_float2;
#define Sin sin
#define Cos cos
#define Pow pow
#define Log log
#define Fmod fmod
#else
typedef float t_float;
typedef ImVec2 t_float2;
#define Sin sinf
#define Cos cosf
#define Pow powf
#define Log logf
#define Fmod fmodf
#endif
void ShowBenchmarkTool(); void ShowBenchmarkTool();
inline t_float RandomRange(t_float min, t_float max) { template <typename T>
t_float scale = rand() / (t_float) RAND_MAX; inline T RandomRange(T min, T max) {
T scale = rand() / (T) RAND_MAX;
return min + scale * ( max - min ); return min + scale * ( max - min );
} }
@ -87,17 +75,17 @@ inline t_float RandomRange(t_float min, t_float max) {
struct ScrollingBuffer { struct ScrollingBuffer {
int MaxSize; int MaxSize;
int Offset; int Offset;
ImVector<t_float2> Data; ImVector<ImVec2> Data;
ScrollingBuffer() { ScrollingBuffer() {
MaxSize = 2000; MaxSize = 2000;
Offset = 0; Offset = 0;
Data.reserve(MaxSize); Data.reserve(MaxSize);
} }
void AddPoint(t_float x, t_float y) { void AddPoint(float x, float y) {
if (Data.size() < MaxSize) if (Data.size() < MaxSize)
Data.push_back(t_float2(x,y)); Data.push_back(ImVec2(x,y));
else { else {
Data[Offset] = t_float2(x,y); Data[Offset] = ImVec2(x,y);
Offset = (Offset + 1) % MaxSize; Offset = (Offset + 1) % MaxSize;
} }
} }
@ -111,17 +99,17 @@ struct ScrollingBuffer {
// utility structure for realtime plot // utility structure for realtime plot
struct RollingBuffer { struct RollingBuffer {
t_float Span; float Span;
ImVector<t_float2> Data; ImVector<ImVec2> Data;
RollingBuffer() { RollingBuffer() {
Span = 10.0f; Span = 10.0f;
Data.reserve(2000); Data.reserve(2000);
} }
void AddPoint(t_float x, t_float y) { void AddPoint(float x, float y) {
t_float xmod = Fmod(x, Span); float xmod = fmodf(x, Span);
if (!Data.empty() && xmod < Data.back().x) if (!Data.empty() && xmod < Data.back().x)
Data.shrink(0); Data.shrink(0);
Data.push_back(t_float2(xmod, y)); Data.push_back(ImVec2(xmod, y));
} }
}; };
@ -145,7 +133,7 @@ struct HugeTimeData {
}; };
void ShowDemoWindow(bool* p_open) { void ShowDemoWindow(bool* p_open) {
t_float DEMO_TIME = (t_float)ImGui::GetTime(); double DEMO_TIME = ImGui::GetTime();
static bool show_imgui_metrics = false; static bool show_imgui_metrics = false;
static bool show_imgui_style_editor = false; static bool show_imgui_style_editor = false;
static bool show_implot_style_editor = false; static bool show_implot_style_editor = false;
@ -249,7 +237,7 @@ void ShowDemoWindow(bool* p_open) {
static float xs1[1001], ys1[1001]; static float xs1[1001], ys1[1001];
for (int i = 0; i < 1001; ++i) { for (int i = 0; i < 1001; ++i) {
xs1[i] = i * 0.001f; xs1[i] = i * 0.001f;
ys1[i] = 0.5f + 0.5f * sinf(50 * (xs1[i] + DEMO_TIME / 10)); ys1[i] = 0.5f + 0.5f * sinf(50 * (xs1[i] + (float)DEMO_TIME / 10));
} }
static double xs2[11], ys2[11]; static double xs2[11], ys2[11];
for (int i = 0; i < 11; ++i) { for (int i = 0; i < 11; ++i) {
@ -266,13 +254,13 @@ void ShowDemoWindow(bool* p_open) {
} }
//------------------------------------------------------------------------- //-------------------------------------------------------------------------
if (ImGui::CollapsingHeader("Filled Line Plots")) { if (ImGui::CollapsingHeader("Filled Line Plots")) {
static t_float xs1[101], ys1[101], ys2[101], ys3[101]; static double xs1[101], ys1[101], ys2[101], ys3[101];
srand(0); srand(0);
for (int i = 0; i < 101; ++i) { for (int i = 0; i < 101; ++i) {
xs1[i] = (float)i; xs1[i] = (float)i;
ys1[i] = RandomRange(400,450); ys1[i] = RandomRange(400.0,450.0);
ys2[i] = RandomRange(275,350); ys2[i] = RandomRange(275.0,350.0);
ys3[i] = RandomRange(150,225); ys3[i] = RandomRange(150.0,225.0);
} }
static bool show_lines = true; static bool show_lines = true;
static bool show_fills = true; static bool show_fills = true;
@ -300,15 +288,15 @@ void ShowDemoWindow(bool* p_open) {
} }
//------------------------------------------------------------------------- //-------------------------------------------------------------------------
if (ImGui::CollapsingHeader("Shaded Plots")) { if (ImGui::CollapsingHeader("Shaded Plots")) {
static t_float xs[1001], ys[1001], ys1[1001], ys2[1001], ys3[1001], ys4[1001]; static float xs[1001], ys[1001], ys1[1001], ys2[1001], ys3[1001], ys4[1001];
srand(0); srand(0);
for (int i = 0; i < 1001; ++i) { for (int i = 0; i < 1001; ++i) {
xs[i] = i * 0.001f; xs[i] = i * 0.001f;
ys[i] = 0.25f + 0.25f * Sin(25 * xs[i]) * Sin(5 * xs[i]) + RandomRange(-0.01f, 0.01f); ys[i] = 0.25f + 0.25f * sinf(25 * xs[i]) * sinf(5 * xs[i]) + RandomRange(-0.01f, 0.01f);
ys1[i] = ys[i] + RandomRange(0.1f, 0.12f); ys1[i] = ys[i] + RandomRange(0.1f, 0.12f);
ys2[i] = ys[i] - RandomRange(0.1f, 0.12f); ys2[i] = ys[i] - RandomRange(0.1f, 0.12f);
ys3[i] = 0.75f + 0.2f * Sin(25 * xs[i]); ys3[i] = 0.75f + 0.2f * sinf(25 * xs[i]);
ys4[i] = 0.75f + 0.1f * Cos(25 * xs[i]); ys4[i] = 0.75f + 0.1f * cosf(25 * xs[i]);
} }
static float alpha = 0.25f; static float alpha = 0.25f;
ImGui::DragFloat("Alpha",&alpha,0.01f,0,1); ImGui::DragFloat("Alpha",&alpha,0.01f,0,1);
@ -327,15 +315,15 @@ void ShowDemoWindow(bool* p_open) {
//------------------------------------------------------------------------- //-------------------------------------------------------------------------
if (ImGui::CollapsingHeader("Scatter Plots")) { if (ImGui::CollapsingHeader("Scatter Plots")) {
srand(0); srand(0);
static t_float xs1[100], ys1[100]; static float xs1[100], ys1[100];
for (int i = 0; i < 100; ++i) { for (int i = 0; i < 100; ++i) {
xs1[i] = i * 0.01f; xs1[i] = i * 0.01f;
ys1[i] = xs1[i] + 0.1f * ((t_float)rand() / (t_float)RAND_MAX); ys1[i] = xs1[i] + 0.1f * ((float)rand() / (float)RAND_MAX);
} }
static t_float xs2[50], ys2[50]; static float xs2[50], ys2[50];
for (int i = 0; i < 50; i++) { for (int i = 0; i < 50; i++) {
xs2[i] = 0.25f + 0.2f * ((t_float)rand() / (t_float)RAND_MAX); xs2[i] = 0.25f + 0.2f * ((float)rand() / (float)RAND_MAX);
ys2[i] = 0.75f + 0.2f * ((t_float)rand() / (t_float)RAND_MAX); ys2[i] = 0.75f + 0.2f * ((float)rand() / (float)RAND_MAX);
} }
if (ImPlot::BeginPlot("Scatter Plot", NULL, NULL)) { if (ImPlot::BeginPlot("Scatter Plot", NULL, NULL)) {
@ -386,14 +374,14 @@ void ShowDemoWindow(bool* p_open) {
} }
//------------------------------------------------------------------------- //-------------------------------------------------------------------------
if (ImGui::CollapsingHeader("Error Bars")) { if (ImGui::CollapsingHeader("Error Bars")) {
static t_float xs[5] = {1,2,3,4,5}; static float xs[5] = {1,2,3,4,5};
static t_float bar[5] = {1,2,5,3,4}; static float bar[5] = {1,2,5,3,4};
static t_float lin1[5] = {8,8,9,7,8}; static float lin1[5] = {8,8,9,7,8};
static t_float lin2[5] = {6,7,6,9,6}; static float lin2[5] = {6,7,6,9,6};
static t_float err1[5] = {0.2f, 0.4f, 0.2f, 0.6f, 0.4f}; static float err1[5] = {0.2f, 0.4f, 0.2f, 0.6f, 0.4f};
static t_float err2[5] = {0.4f, 0.2f, 0.4f, 0.8f, 0.6f}; static float err2[5] = {0.4f, 0.2f, 0.4f, 0.8f, 0.6f};
static t_float err3[5] = {0.09f, 0.14f, 0.09f, 0.12f, 0.16f}; static float err3[5] = {0.09f, 0.14f, 0.09f, 0.12f, 0.16f};
static t_float err4[5] = {0.02f, 0.08f, 0.15f, 0.05f, 0.2f}; static float err4[5] = {0.02f, 0.08f, 0.15f, 0.05f, 0.2f};
ImPlot::SetNextPlotLimits(0, 6, 0, 10); ImPlot::SetNextPlotLimits(0, 6, 0, 10);
@ -417,11 +405,11 @@ void ShowDemoWindow(bool* p_open) {
} }
} }
if (ImGui::CollapsingHeader("Stem Plots")) { if (ImGui::CollapsingHeader("Stem Plots")) {
static t_float xs[51], ys1[51], ys2[51]; static double xs[51], ys1[51], ys2[51];
for (int i = 0; i < 51; ++i) { for (int i = 0; i < 51; ++i) {
xs[i] = i * 0.02f; xs[i] = i * 0.02;
ys1[i] = 1.0f + 0.5f * Sin(25*xs[i])*Cos(2*xs[i]); ys1[i] = 1.0 + 0.5 * sin(25*xs[i])*cos(2*xs[i]);
ys2[i] = 0.5f + 0.25f * Sin(10*xs[i]) * Sin(xs[i]); ys2[i] = 0.5 + 0.25 * sin(10*xs[i]) * sin(xs[i]);
} }
ImPlot::SetNextPlotLimits(0,1,0,1.6); ImPlot::SetNextPlotLimits(0,1,0,1.6);
if (ImPlot::BeginPlot("Stem Plots")) { if (ImPlot::BeginPlot("Stem Plots")) {
@ -449,26 +437,26 @@ void ShowDemoWindow(bool* p_open) {
ImPlot::SetNextPlotLimits(0,1,0,1,ImGuiCond_Always); ImPlot::SetNextPlotLimits(0,1,0,1,ImGuiCond_Always);
if (ImPlot::BeginPlot("##Pie1", NULL, NULL, ImVec2(250,250), ImPlotFlags_NoMousePos, ImPlotAxisFlags_NoDecorations, ImPlotAxisFlags_NoDecorations)) { if (ImPlot::BeginPlot("##Pie1", NULL, NULL, ImVec2(250,250), ImPlotFlags_NoMousePos, ImPlotAxisFlags_NoDecorations, ImPlotAxisFlags_NoDecorations)) {
ImPlot::PlotPieChart(labels1, data1, 4, 0.5f, 0.5f, 0.4f, normalize, "%.2f"); ImPlot::PlotPieChart(labels1, data1, 4, 0.5, 0.5, 0.4, normalize, "%.2f");
ImPlot::EndPlot(); ImPlot::EndPlot();
} }
ImGui::SameLine(); ImGui::SameLine();
static const char* labels2[] = {"A","B","C","D","E"}; static const char* labels2[] = {"A","B","C","D","E"};
static t_float data2[] = {1,1,2,3,5}; static int data2[] = {1,1,2,3,5};
ImPlot::PushColormap(ImPlotColormap_Pastel); ImPlot::PushColormap(ImPlotColormap_Pastel);
ImPlot::SetNextPlotLimits(0,1,0,1,ImGuiCond_Always); ImPlot::SetNextPlotLimits(0,1,0,1,ImGuiCond_Always);
if (ImPlot::BeginPlot("##Pie2", NULL, NULL, ImVec2(250,250), ImPlotFlags_NoMousePos, ImPlotAxisFlags_NoDecorations, ImPlotAxisFlags_NoDecorations)) { if (ImPlot::BeginPlot("##Pie2", NULL, NULL, ImVec2(250,250), ImPlotFlags_NoMousePos, ImPlotAxisFlags_NoDecorations, ImPlotAxisFlags_NoDecorations)) {
ImPlot::PlotPieChart(labels2, data2, 5, 0.5f, 0.5f, 0.4f, true, "%.0f", 180); ImPlot::PlotPieChart(labels2, data2, 5, 0.5, 0.5, 0.4, true, "%.0f", 180);
ImPlot::EndPlot(); ImPlot::EndPlot();
} }
ImPlot::PopColormap(); ImPlot::PopColormap();
} }
//------------------------------------------------------------------------- //-------------------------------------------------------------------------
if (ImGui::CollapsingHeader("Heatmaps")) { if (ImGui::CollapsingHeader("Heatmaps")) {
static t_float values1[7][7] = {{0.8f, 2.4f, 2.5f, 3.9f, 0.0f, 4.0f, 0.0f}, static float values1[7][7] = {{0.8f, 2.4f, 2.5f, 3.9f, 0.0f, 4.0f, 0.0f},
{2.4f, 0.0f, 4.0f, 1.0f, 2.7f, 0.0f, 0.0f}, {2.4f, 0.0f, 4.0f, 1.0f, 2.7f, 0.0f, 0.0f},
{1.1f, 2.4f, 0.8f, 4.3f, 1.9f, 4.4f, 0.0f}, {1.1f, 2.4f, 0.8f, 4.3f, 1.9f, 4.4f, 0.0f},
{0.6f, 0.0f, 0.3f, 0.0f, 3.1f, 0.0f, 0.0f}, {0.6f, 0.0f, 0.3f, 0.0f, 3.1f, 0.0f, 0.0f},
@ -477,10 +465,6 @@ void ShowDemoWindow(bool* p_open) {
{0.1f, 2.0f, 0.0f, 1.4f, 0.0f, 1.9f, 6.3f}}; {0.1f, 2.0f, 0.0f, 1.4f, 0.0f, 1.9f, 6.3f}};
static float scale_min = 0; static float scale_min = 0;
static float scale_max = 6.3f; static float scale_max = 6.3f;
static t_float values2[100*100];
srand((unsigned int)(DEMO_TIME*1000000));
for (int i = 0; i < 100*100; ++i)
values2[i] = RandomRange(0,1);
static const char* xlabels[] = {"C1","C2","C3","C4","C5","C6","C7"}; static const char* xlabels[] = {"C1","C2","C3","C4","C5","C6","C7"};
static const char* ylabels[] = {"R1","R2","R3","R4","R5","R6","R7"}; static const char* ylabels[] = {"R1","R2","R3","R4","R5","R6","R7"};
@ -507,6 +491,11 @@ void ShowDemoWindow(bool* p_open) {
ImGui::SameLine(); ImGui::SameLine();
static double values2[100*100];
srand((unsigned int)(DEMO_TIME*1000000));
for (int i = 0; i < 100*100; ++i)
values2[i] = RandomRange(0.0,1.0);
static ImVec4 gray[2] = {ImVec4(0,0,0,1), ImVec4(1,1,1,1)}; static ImVec4 gray[2] = {ImVec4(0,0,0,1), ImVec4(1,1,1,1)};
ImPlot::PushColormap(gray, 2); ImPlot::PushColormap(gray, 2);
ImPlot::SetNextPlotLimits(-1,1,-1,1); ImPlot::SetNextPlotLimits(-1,1,-1,1);
@ -524,7 +513,7 @@ void ShowDemoWindow(bool* p_open) {
static ScrollingBuffer sdata1, sdata2; static ScrollingBuffer sdata1, sdata2;
static RollingBuffer rdata1, rdata2; static RollingBuffer rdata1, rdata2;
ImVec2 mouse = ImGui::GetMousePos(); ImVec2 mouse = ImGui::GetMousePos();
static t_float t = 0; static float t = 0;
t += ImGui::GetIO().DeltaTime; t += ImGui::GetIO().DeltaTime;
sdata1.AddPoint(t, mouse.x * 0.0005f); sdata1.AddPoint(t, mouse.x * 0.0005f);
rdata1.AddPoint(t, mouse.x * 0.0005f); rdata1.AddPoint(t, mouse.x * 0.0005f);
@ -539,7 +528,7 @@ void ShowDemoWindow(bool* p_open) {
static ImPlotAxisFlags rt_axis = ImPlotAxisFlags_NoTickLabels; static ImPlotAxisFlags rt_axis = ImPlotAxisFlags_NoTickLabels;
ImPlot::SetNextPlotLimitsX(t - history, t, ImGuiCond_Always); ImPlot::SetNextPlotLimitsX(t - history, t, ImGuiCond_Always);
if (ImPlot::BeginPlot("##Scrolling", NULL, NULL, ImVec2(-1,150), 0, rt_axis, rt_axis | ImPlotAxisFlags_LockMin)) { if (ImPlot::BeginPlot("##Scrolling", NULL, NULL, ImVec2(-1,150), 0, rt_axis, rt_axis | ImPlotAxisFlags_LockMin)) {
ImPlot::PlotShaded("Data 1", &sdata1.Data[0].x, &sdata1.Data[0].y, sdata1.Data.size(), 0, sdata1.Offset, 2 * sizeof(t_float)); ImPlot::PlotShaded("Data 1", &sdata1.Data[0].x, &sdata1.Data[0].y, sdata1.Data.size(), 0, sdata1.Offset, 2 * sizeof(float));
ImPlot::PlotLine("Data 2", &sdata2.Data[0], sdata2.Data.size(), sdata2.Offset); ImPlot::PlotLine("Data 2", &sdata2.Data[0], sdata2.Data.size(), sdata2.Offset);
ImPlot::EndPlot(); ImPlot::EndPlot();
} }
@ -549,7 +538,7 @@ void ShowDemoWindow(bool* p_open) {
// as ImVec2* (or ImPlot*): // as ImVec2* (or ImPlot*):
ImPlot::PlotLine("Data 1", &rdata1.Data[0], rdata1.Data.size()); ImPlot::PlotLine("Data 1", &rdata1.Data[0], rdata1.Data.size());
// as float*, float* (or double*, double*) with stride of 2 * sizeof // as float*, float* (or double*, double*) with stride of 2 * sizeof
ImPlot::PlotLine("Data 2", &rdata2.Data[0].x, &rdata2.Data[0].y, rdata2.Data.size(), 0, 2 * sizeof(t_float)); ImPlot::PlotLine("Data 2", &rdata2.Data[0].x, &rdata2.Data[0].y, rdata2.Data.size(), 0, 2 * sizeof(float));
ImPlot::EndPlot(); ImPlot::EndPlot();
} }
} }
@ -562,8 +551,8 @@ void ShowDemoWindow(bool* p_open) {
ImPlot::SetNextPlotLimits(0, 10, 0, 12); ImPlot::SetNextPlotLimits(0, 10, 0, 12);
if (ImPlot::BeginPlot("##MarkerStyles", NULL, NULL, ImVec2(-1,0), ImPlotFlags_CanvasOnly, ImPlotAxisFlags_NoDecorations, ImPlotAxisFlags_NoDecorations)) { if (ImPlot::BeginPlot("##MarkerStyles", NULL, NULL, ImVec2(-1,0), ImPlotFlags_CanvasOnly, ImPlotAxisFlags_NoDecorations, ImPlotAxisFlags_NoDecorations)) {
t_float xs[2] = {1,4}; ImS8 xs[2] = {1,4};
t_float ys[2] = {10,11}; ImS8 ys[2] = {10,11};
// filled markers // filled markers
for (int m = 1; m < ImPlotMarker_COUNT; ++m) { for (int m = 1; m < ImPlotMarker_COUNT; ++m) {
@ -595,12 +584,12 @@ void ShowDemoWindow(bool* p_open) {
} }
//------------------------------------------------------------------------- //-------------------------------------------------------------------------
if (ImGui::CollapsingHeader("Log Scale")) { if (ImGui::CollapsingHeader("Log Scale")) {
static t_float xs[1001], ys1[1001], ys2[1001], ys3[1001]; static double xs[1001], ys1[1001], ys2[1001], ys3[1001];
for (int i = 0; i < 1001; ++i) { for (int i = 0; i < 1001; ++i) {
xs[i] = i*0.1f; xs[i] = i*0.1f;
ys1[i] = Sin(xs[i]) + 1; ys1[i] = sin(xs[i]) + 1;
ys2[i] = Log(xs[i]); ys2[i] = log(xs[i]);
ys3[i] = Pow(10.0f, xs[i]); ys3[i] = pow(10.0, xs[i]);
} }
ImGui::BulletText("Open the plot context menu (double right click) to change scales."); ImGui::BulletText("Open the plot context menu (double right click) to change scales.");
@ -655,12 +644,12 @@ void ShowDemoWindow(bool* p_open) {
} }
//------------------------------------------------------------------------- //-------------------------------------------------------------------------
if (ImGui::CollapsingHeader("Multiple Y-Axes")) { if (ImGui::CollapsingHeader("Multiple Y-Axes")) {
static t_float xs[1001], xs2[1001], ys1[1001], ys2[1001], ys3[1001]; static float xs[1001], xs2[1001], ys1[1001], ys2[1001], ys3[1001];
for (int i = 0; i < 1001; ++i) { for (int i = 0; i < 1001; ++i) {
xs[i] = (i*0.1f); xs[i] = (i*0.1f);
ys1[i] = Sin(xs[i]) * 3 + 1; ys1[i] = sinf(xs[i]) * 3 + 1;
ys2[i] = Cos(xs[i]) * 0.2f + 0.5f; ys2[i] = cosf(xs[i]) * 0.2f + 0.5f;
ys3[i] = Sin(xs[i]+0.5f) * 100 + 200; ys3[i] = sinf(xs[i]+0.5f) * 100 + 200;
xs2[i] = xs[i] + 10.0f; xs2[i] = xs[i] + 10.0f;
} }
static bool y2_axis = true; static bool y2_axis = true;
@ -699,7 +688,7 @@ void ShowDemoWindow(bool* p_open) {
if (ImGui::CollapsingHeader("Linked Axes")) { if (ImGui::CollapsingHeader("Linked Axes")) {
static double xmin = 0, xmax = 1, ymin = 0, ymax = 1; static double xmin = 0, xmax = 1, ymin = 0, ymax = 1;
static bool linkx = true, linky = true; static bool linkx = true, linky = true;
t_float data[2] = {0,1}; int data[2] = {0,1};
ImGui::Checkbox("Link X", &linkx); ImGui::Checkbox("Link X", &linkx);
ImGui::SameLine(); ImGui::SameLine();
ImGui::Checkbox("Link Y", &linky); ImGui::Checkbox("Link Y", &linky);
@ -716,7 +705,7 @@ void ShowDemoWindow(bool* p_open) {
} }
//------------------------------------------------------------------------- //-------------------------------------------------------------------------
if (ImGui::CollapsingHeader("Querying")) { if (ImGui::CollapsingHeader("Querying")) {
static ImVector<t_float2> data; static ImVector<ImPlotPoint> data;
static ImPlotLimits range, query; static ImPlotLimits range, query;
ImGui::BulletText("Ctrl + click in the plot area to draw points."); ImGui::BulletText("Ctrl + click in the plot area to draw points.");
@ -730,14 +719,14 @@ void ShowDemoWindow(bool* p_open) {
if (ImPlot::BeginPlot("##Drawing", NULL, NULL, ImVec2(-1,0), ImPlotFlags_Query, ImPlotAxisFlags_NoDecorations, ImPlotAxisFlags_NoDecorations)) { if (ImPlot::BeginPlot("##Drawing", NULL, NULL, ImVec2(-1,0), ImPlotFlags_Query, ImPlotAxisFlags_NoDecorations, ImPlotAxisFlags_NoDecorations)) {
if (ImPlot::IsPlotHovered() && ImGui::IsMouseClicked(0) && ImGui::GetIO().KeyCtrl) { if (ImPlot::IsPlotHovered() && ImGui::IsMouseClicked(0) && ImGui::GetIO().KeyCtrl) {
ImPlotPoint pt = ImPlot::GetPlotMousePos(); ImPlotPoint pt = ImPlot::GetPlotMousePos();
data.push_back(t_float2((t_float)pt.x, (t_float)pt.y)); data.push_back(pt);
} }
if (data.size() > 0) if (data.size() > 0)
ImPlot::PlotScatter("Points", &data[0].x, &data[0].y, data.size(), 0, 2 * sizeof(t_float)); ImPlot::PlotScatter("Points", &data[0].x, &data[0].y, data.size(), 0, 2 * sizeof(double));
if (ImPlot::IsPlotQueried() && data.size() > 0) { if (ImPlot::IsPlotQueried() && data.size() > 0) {
ImPlotLimits range2 = ImPlot::GetPlotQuery(); ImPlotLimits range2 = ImPlot::GetPlotQuery();
int cnt = 0; int cnt = 0;
t_float2 avg; ImPlotPoint avg;
for (int i = 0; i < data.size(); ++i) { for (int i = 0; i < data.size(); ++i) {
if (range2.Contains(data[i].x, data[i].y)) { if (range2.Contains(data[i].x, data[i].y)) {
avg.x += data[i].x; avg.x += data[i].x;
@ -762,19 +751,19 @@ void ShowDemoWindow(bool* p_open) {
//------------------------------------------------------------------------- //-------------------------------------------------------------------------
if (ImGui::CollapsingHeader("Views")) { if (ImGui::CollapsingHeader("Views")) {
// mimic's soulthread's imgui_plot demo // mimic's soulthread's imgui_plot demo
static t_float x_data[512]; static float x_data[512];
static t_float y_data1[512]; static float y_data1[512];
static t_float y_data2[512]; static float y_data2[512];
static t_float y_data3[512]; static float y_data3[512];
static t_float sampling_freq = 44100; static float sampling_freq = 44100;
static t_float freq = 500; static float freq = 500;
for (size_t i = 0; i < 512; ++i) { for (size_t i = 0; i < 512; ++i) {
const t_float t = i / sampling_freq; const float t = i / sampling_freq;
x_data[i] = t; x_data[i] = t;
const t_float arg = 2 * 3.14f * freq * t; const float arg = 2 * 3.14f * freq * t;
y_data1[i] = Sin(arg); y_data1[i] = sinf(arg);
y_data2[i] = y_data1[i] * -0.6f + Sin(2 * arg) * 0.4f; y_data2[i] = y_data1[i] * -0.6f + sinf(2 * arg) * 0.4f;
y_data3[i] = y_data2[i] * -0.6f + Sin(3 * arg) * 0.4f; y_data3[i] = y_data2[i] * -0.6f + sinf(3 * arg) * 0.4f;
} }
ImGui::BulletText("Query the first plot to render a subview in the second plot (see above for controls)."); ImGui::BulletText("Query the first plot to render a subview in the second plot (see above for controls).");
ImPlot::SetNextPlotLimits(0,0.01,-1,1); ImPlot::SetNextPlotLimits(0,0.01,-1,1);
@ -836,7 +825,7 @@ void ShowDemoWindow(bool* p_open) {
ImGui::EndGroup(); ImGui::EndGroup();
ImGui::SameLine(); ImGui::SameLine();
srand((unsigned int)DEMO_TIME*10000000); srand((unsigned int)DEMO_TIME*10000000);
static t_float t = 0; static float t = 0;
if (!paused) { if (!paused) {
t += ImGui::GetIO().DeltaTime; t += ImGui::GetIO().DeltaTime;
for (int i = 0; i < K_CHANNELS; ++i) { for (int i = 0; i < K_CHANNELS; ++i) {
@ -851,7 +840,7 @@ void ShowDemoWindow(bool* p_open) {
char label[K_CHANNELS]; char label[K_CHANNELS];
sprintf(label, "data_%d", i); sprintf(label, "data_%d", i);
ImPlot::SetPlotYAxis(yAxis[i]); ImPlot::SetPlotYAxis(yAxis[i]);
ImPlot::PlotLine(label, &data[i].Data[0].x, &data[i].Data[0].y, data[i].Data.size(), data[i].Offset, 2 * sizeof(t_float)); ImPlot::PlotLine(label, &data[i].Data[0].x, &data[i].Data[0].y, data[i].Data.size(), data[i].Offset, 2 * sizeof(float));
// allow legend labels to be dragged and dropped // allow legend labels to be dragged and dropped
if (ImPlot::BeginLegendDragDropSource(label)) { if (ImPlot::BeginLegendDragDropSource(label)) {
ImGui::SetDragDropPayload("DND_PLOT", &i, sizeof(int)); ImGui::SetDragDropPayload("DND_PLOT", &i, sizeof(int));
@ -923,35 +912,35 @@ void ShowDemoWindow(bool* p_open) {
} }
ImGui::EndGroup(); ImGui::EndGroup();
ImGui::SameLine(); ImGui::SameLine();
static t_float t = 0; static float t = 0;
if (!paused) { if (!paused) {
t += ImGui::GetIO().DeltaTime; t += ImGui::GetIO().DeltaTime;
//digital signal values //digital signal values
int i = 0; int i = 0;
if (showDigital[i]) if (showDigital[i])
dataDigital[i].AddPoint(t, Sin(2*t) > 0.45); dataDigital[i].AddPoint(t, sinf(2*t) > 0.45);
i++; i++;
if (showDigital[i]) if (showDigital[i])
dataDigital[i].AddPoint(t, Sin(2*t) < 0.45); dataDigital[i].AddPoint(t, sinf(2*t) < 0.45);
i++; i++;
if (showDigital[i]) if (showDigital[i])
dataDigital[i].AddPoint(t, Fmod(t,5.0f)); dataDigital[i].AddPoint(t, fmodf(t,5.0f));
i++; i++;
if (showDigital[i]) if (showDigital[i])
dataDigital[i].AddPoint(t, Sin(2*t) < 0.17); dataDigital[i].AddPoint(t, sinf(2*t) < 0.17);
//Analog signal values //Analog signal values
i = 0; i = 0;
if (showAnalog[i]) if (showAnalog[i])
dataAnalog[i].AddPoint(t, Sin(2*t)); dataAnalog[i].AddPoint(t, sinf(2*t));
i++; i++;
if (showAnalog[i]) if (showAnalog[i])
dataAnalog[i].AddPoint(t, Cos(2*t)); dataAnalog[i].AddPoint(t, cosf(2*t));
i++; i++;
if (showAnalog[i]) if (showAnalog[i])
dataAnalog[i].AddPoint(t, Sin(2*t) * Cos(2*t)); dataAnalog[i].AddPoint(t, sinf(2*t) * cosf(2*t));
i++; i++;
if (showAnalog[i]) if (showAnalog[i])
dataAnalog[i].AddPoint(t, Sin(2*t) - Cos(2*t)); dataAnalog[i].AddPoint(t, sinf(2*t) - cosf(2*t));
} }
ImPlot::SetNextPlotLimitsY(-1, 1); ImPlot::SetNextPlotLimitsY(-1, 1);
ImPlot::SetNextPlotLimitsX(t - 10.0, t, paused ? ImGuiCond_Once : ImGuiCond_Always); ImPlot::SetNextPlotLimitsX(t - 10.0, t, paused ? ImGuiCond_Once : ImGuiCond_Always);
@ -960,7 +949,7 @@ void ShowDemoWindow(bool* p_open) {
if (showDigital[i] && dataDigital[i].Data.size() > 0) { if (showDigital[i] && dataDigital[i].Data.size() > 0) {
char label[32]; char label[32];
sprintf(label, "digital_%d", i); sprintf(label, "digital_%d", i);
ImPlot::PlotDigital(label, &dataDigital[i].Data[0].x, &dataDigital[i].Data[0].y, dataDigital[i].Data.size(), dataDigital[i].Offset, 2 * sizeof(t_float)); ImPlot::PlotDigital(label, &dataDigital[i].Data[0].x, &dataDigital[i].Data[0].y, dataDigital[i].Data.size(), dataDigital[i].Offset, 2 * sizeof(float));
} }
} }
for (int i = 0; i < K_PLOT_ANALOG_CH_COUNT; ++i) { for (int i = 0; i < K_PLOT_ANALOG_CH_COUNT; ++i) {
@ -968,7 +957,7 @@ void ShowDemoWindow(bool* p_open) {
char label[32]; char label[32];
sprintf(label, "analog_%d", i); sprintf(label, "analog_%d", i);
if (dataAnalog[i].Data.size() > 0) if (dataAnalog[i].Data.size() > 0)
ImPlot::PlotLine(label, &dataAnalog[i].Data[0].x, &dataAnalog[i].Data[0].y, dataAnalog[i].Data.size(), dataAnalog[i].Offset, 2 * sizeof(t_float)); ImPlot::PlotLine(label, &dataAnalog[i].Data[0].x, &dataAnalog[i].Data[0].y, dataAnalog[i].Data.size(), dataAnalog[i].Offset, 2 * sizeof(float));
} }
} }
ImPlot::EndPlot(); ImPlot::EndPlot();
@ -1010,7 +999,7 @@ void ShowDemoWindow(bool* p_open) {
static float data[100]; static float data[100];
srand(row); srand(row);
for (int i = 0; i < 100; ++i) for (int i = 0; i < 100; ++i)
data[i] = (float)RandomRange(0,10); data[i] = RandomRange(0.0f,10.0f);
ImGui::TableSetColumnIndex(0); ImGui::TableSetColumnIndex(0);
ImGui::Text("EMG %d", row); ImGui::Text("EMG %d", row);
ImGui::TableSetColumnIndex(1); ImGui::TableSetColumnIndex(1);
@ -1032,12 +1021,12 @@ void ShowDemoWindow(bool* p_open) {
static const int k_circles = 11; static const int k_circles = 11;
static const int k_points_per = 50; static const int k_points_per = 50;
static const int k_size = 2 * k_points_per * k_circles; static const int k_size = 2 * k_points_per * k_circles;
static t_float interleaved_data[k_size]; static double interleaved_data[k_size];
for (int p = 0; p < k_points_per; ++p) { for (int p = 0; p < k_points_per; ++p) {
for (int c = 0; c < k_circles; ++c) { for (int c = 0; c < k_circles; ++c) {
t_float r = (t_float)c / (k_circles - 1) * 0.2f + 0.2f; double r = (double)c / (k_circles - 1) * 0.2 + 0.2;
interleaved_data[p*2*k_circles + 2*c + 0] = 0.5f + r * Cos((t_float)p/k_points_per * 6.28f); interleaved_data[p*2*k_circles + 2*c + 0] = 0.5 + r * cos((double)p/k_points_per * 6.28);
interleaved_data[p*2*k_circles + 2*c + 1] = 0.5f + r * Sin((t_float)p/k_points_per * 6.28f); interleaved_data[p*2*k_circles + 2*c + 1] = 0.5 + r * sin((double)p/k_points_per * 6.28);
} }
} }
static int offset = 0; static int offset = 0;
@ -1053,7 +1042,7 @@ void ShowDemoWindow(bool* p_open) {
char buff[16]; char buff[16];
for (int c = 0; c < k_circles; ++c) { for (int c = 0; c < k_circles; ++c) {
sprintf(buff, "Circle %d", c); sprintf(buff, "Circle %d", c);
ImPlot::PlotLine(buff, &interleaved_data[c*2 + 0], &interleaved_data[c*2 + 1], k_points_per, offset, 2*k_circles*sizeof(t_float)); ImPlot::PlotLine(buff, &interleaved_data[c*2 + 0], &interleaved_data[c*2 + 1], k_points_per, offset, 2*k_circles*sizeof(double));
} }
ImPlot::EndPlot(); ImPlot::EndPlot();
ImPlot::PopColormap(); ImPlot::PopColormap();
@ -1061,12 +1050,25 @@ void ShowDemoWindow(bool* p_open) {
// offset++; uncomment for animation! // offset++; uncomment for animation!
} }
//------------------------------------------------------------------------- //-------------------------------------------------------------------------
if (ImGui::CollapsingHeader("Custom Getters")) { if (ImGui::CollapsingHeader("Custom Data and Getters")) {
ImGui::BulletText("Most plotters can be passed a function pointer for getting data."); ImGui::BulletText("You can plot custom structs using the stride feature.");
ImGui::BulletText("You can optionally pass user data to be given to your getter."); ImGui::BulletText("Most plotters can also be passed a function pointer for getting data.");
ImGui::BulletText("C++ lambdas can be passed as function pointers as well."); ImGui::Indent();
if (ImPlot::BeginPlot("##Custom Getters")) { ImGui::BulletText("You can optionally pass user data to be given to your getter function.");
ImGui::BulletText("C++ lambdas can be passed as function pointers as well!");
ImGui::Unindent();
MyImPlot::Vector2f vec2_data[2] = { MyImPlot::Vector2f(0,0), MyImPlot::Vector2f(1,1) };
if (ImPlot::BeginPlot("##Custom Data")) {
// custom structs using stride example:
ImPlot::PlotLine("Vector2f", &vec2_data[0].x, &vec2_data[0].y, 2, 0, sizeof(MyImPlot::Vector2f) /* or sizeof(float) * 2 */);
// custom getter example 1:
ImPlot::PlotLineG("Spiral", MyImPlot::Spiral, NULL, 1000); ImPlot::PlotLineG("Spiral", MyImPlot::Spiral, NULL, 1000);
// custom getter example 2:
static MyImPlot::WaveData data1(0.001, 0.2, 2, 0.75); static MyImPlot::WaveData data1(0.001, 0.2, 2, 0.75);
static MyImPlot::WaveData data2(0.001, 0.2, 4, 0.25); static MyImPlot::WaveData data2(0.001, 0.2, 4, 0.25);
ImPlot::PlotLineG("Waves", MyImPlot::SineWave, &data1, 1000); ImPlot::PlotLineG("Waves", MyImPlot::SineWave, &data1, 1000);
@ -1074,9 +1076,11 @@ void ShowDemoWindow(bool* p_open) {
ImPlot::PushStyleVar(ImPlotStyleVar_FillAlpha, 0.25f); ImPlot::PushStyleVar(ImPlotStyleVar_FillAlpha, 0.25f);
ImPlot::PlotShadedG("Waves", MyImPlot::SineWave, &data1, MyImPlot::SawWave, &data2, 1000); ImPlot::PlotShadedG("Waves", MyImPlot::SineWave, &data1, MyImPlot::SawWave, &data2, 1000);
ImPlot::PopStyleVar(); ImPlot::PopStyleVar();
// you can also pass C++ lambdas: // you can also pass C++ lambdas:
// auto lamda = [](void* data, int idx) { ... return ImPlotPoint(x,y); }; // auto lamda = [](void* data, int idx) { ... return ImPlotPoint(x,y); };
// ImPlot::PlotLine("My Lambda", lambda, data, 1000); // ImPlot::PlotLine("My Lambda", lambda, data, 1000);
ImPlot::EndPlot(); ImPlot::EndPlot();
} }
} }
@ -1115,9 +1119,9 @@ void ShowDemoWindow(bool* p_open) {
MyImPlot::StyleSeaborn(); MyImPlot::StyleSeaborn();
ImPlot::SetNextPlotLimits(-0.5f, 9.5f, 0, 10); ImPlot::SetNextPlotLimits(-0.5f, 9.5f, 0, 10);
if (ImPlot::BeginPlot("seaborn style", "x-axis", "y-axis")) { if (ImPlot::BeginPlot("seaborn style", "x-axis", "y-axis")) {
t_float lin[10] = {8,8,9,7,8,8,8,9,7,8}; unsigned int lin[10] = {8,8,9,7,8,8,8,9,7,8};
t_float bar[10] = {1,2,5,3,4,1,2,5,3,4}; unsigned int bar[10] = {1,2,5,3,4,1,2,5,3,4};
t_float dot[10] = {7,6,6,7,8,5,6,5,8,7}; unsigned int dot[10] = {7,6,6,7,8,5,6,5,8,7};
ImPlot::PlotBars("Bars", bar, 10, 0.5f); ImPlot::PlotBars("Bars", bar, 10, 0.5f);
ImPlot::PlotLine("Line", lin, 10); ImPlot::PlotLine("Line", lin, 10);
ImPlot::NextColormapColor(); // skip green ImPlot::NextColormapColor(); // skip green
@ -1154,9 +1158,9 @@ void ShowDemoWindow(bool* p_open) {
static bool markers = false; static bool markers = false;
static bool shaded = false; static bool shaded = false;
static t_float vals[101]; static float vals[101];
for (int i = 0; i < 101; ++i) for (int i = 0; i < 101; ++i)
vals[i] = amplitude * Sin(frequency * i); vals[i] = amplitude * sinf(frequency * i);
ImPlot::SetNextPlotLimits(0,100,-1,1); ImPlot::SetNextPlotLimits(0,100,-1,1);
if (ImPlot::BeginPlot("Right Click the Legend")) { if (ImPlot::BeginPlot("Right Click the Legend")) {
@ -1240,8 +1244,8 @@ ImPlotPoint Spiral(void*, int idx) {
float n = (r - a) / b; // number of revolutions float n = (r - a) / b; // number of revolutions
double th = 2 * n * 3.14; // angle double th = 2 * n * 3.14; // angle
float Th = float(th * idx / (1000 - 1)); float Th = float(th * idx / (1000 - 1));
return ImPlotPoint(0.5f+(a + b*Th / (2.0f * (float) 3.14))*Cos(Th), return ImPlotPoint(0.5f+(a + b*Th / (2.0f * (float) 3.14))*cos(Th),
0.5f + (a + b*Th / (2.0f * (float)3.14))*Sin(Th)); 0.5f + (a + b*Th / (2.0f * (float)3.14))*sin(Th));
} }
// Example for Tables section. Generates a quick and simple shaded line plot. See implementation at bottom. // Example for Tables section. Generates a quick and simple shaded line plot. See implementation at bottom.
@ -1412,12 +1416,12 @@ namespace ImPlot {
struct BenchData { struct BenchData {
BenchData() { BenchData() {
float y = (float)RandomRange(0,1); float y = RandomRange(0.0f,1.0f);
Data = new float[1000]; Data = new float[1000];
for (int i = 0; i < 1000; ++i) { for (int i = 0; i < 1000; ++i) {
Data[i] = y + (float)RandomRange(-0.01f,0.01f); Data[i] = y + RandomRange(-0.01f,0.01f);
} }
Col = ImVec4((float)RandomRange(0,1),(float)RandomRange(0,1),(float)RandomRange(0,1),1); Col = ImVec4(RandomRange(0.0f,1.0f),RandomRange(0.0f,1.0f),RandomRange(0.0f,1.0f),0.5f);
} }
~BenchData() { delete[] Data; } ~BenchData() { delete[] Data; }
float* Data; float* Data;

View File

@ -95,6 +95,34 @@ ImPlotItem* GetCurrentItem() {
return gp.CurrentItem; return gp.CurrentItem;
} }
void SetNextLineStyle(const ImVec4& col, float weight) {
ImPlotContext& gp = *GImPlot;
gp.NextItemStyle.Colors[ImPlotCol_Line] = col;
gp.NextItemStyle.LineWeight = weight;
}
void SetNextFillStyle(const ImVec4& col, float alpha) {
ImPlotContext& gp = *GImPlot;
gp.NextItemStyle.Colors[ImPlotCol_Fill] = col;
gp.NextItemStyle.FillAlpha = alpha;
}
void SetNextMarkerStyle(ImPlotMarker marker, float size, const ImVec4& fill, float weight, const ImVec4& outline) {
ImPlotContext& gp = *GImPlot;
gp.NextItemStyle.Marker = marker;
gp.NextItemStyle.Colors[ImPlotCol_MarkerFill] = fill;
gp.NextItemStyle.MarkerSize = size;
gp.NextItemStyle.Colors[ImPlotCol_MarkerOutline] = outline;
gp.NextItemStyle.MarkerWeight = weight;
}
void SetNextErrorBarStyle(const ImVec4& col, float size, float weight) {
ImPlotContext& gp = *GImPlot;
gp.NextItemStyle.Colors[ImPlotCol_ErrorBar] = col;
gp.NextItemStyle.ErrorBarSize = size;
gp.NextItemStyle.ErrorBarWeight = weight;
}
void BustItemCache() { void BustItemCache() {
ImPlotContext& gp = *GImPlot; ImPlotContext& gp = *GImPlot;
for (int p = 0; p < gp.Plots.GetSize(); ++p) { for (int p = 0; p < gp.Plots.GetSize(); ++p) {
@ -104,6 +132,10 @@ void BustItemCache() {
} }
} }
//-----------------------------------------------------------------------------
// Begin/EndItem
//-----------------------------------------------------------------------------
// Begins a new item. Returns false if the item should not be plotted. // Begins a new item. Returns false if the item should not be plotted.
bool BeginItem(const char* label_id, ImPlotCol recolor_from) { bool BeginItem(const char* label_id, ImPlotCol recolor_from) {
ImPlotContext& gp = *GImPlot; ImPlotContext& gp = *GImPlot;
@ -172,35 +204,6 @@ void EndItem() {
gp.CurrentItem = NULL; gp.CurrentItem = NULL;
} }
void SetNextLineStyle(const ImVec4& col, float weight) {
ImPlotContext& gp = *GImPlot;
gp.NextItemStyle.Colors[ImPlotCol_Line] = col;
gp.NextItemStyle.LineWeight = weight;
}
void SetNextFillStyle(const ImVec4& col, float alpha) {
ImPlotContext& gp = *GImPlot;
gp.NextItemStyle.Colors[ImPlotCol_Fill] = col;
gp.NextItemStyle.FillAlpha = alpha;
}
void SetNextMarkerStyle(ImPlotMarker marker, float size, const ImVec4& fill, float weight, const ImVec4& outline) {
ImPlotContext& gp = *GImPlot;
gp.NextItemStyle.Marker = marker;
gp.NextItemStyle.Colors[ImPlotCol_MarkerFill] = fill;
gp.NextItemStyle.MarkerSize = size;
gp.NextItemStyle.Colors[ImPlotCol_MarkerOutline] = outline;
gp.NextItemStyle.MarkerWeight = weight;
}
void SetNextErrorBarStyle(const ImVec4& col, float size, float weight) {
ImPlotContext& gp = *GImPlot;
gp.NextItemStyle.Colors[ImPlotCol_ErrorBar] = col;
gp.NextItemStyle.ErrorBarSize = size;
gp.NextItemStyle.ErrorBarWeight = weight;
}
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
// GETTERS // GETTERS
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
@ -208,6 +211,8 @@ void SetNextErrorBarStyle(const ImVec4& col, float size, float weight) {
// Getters can be thought of as iterators that convert user data (e.g. raw arrays) // Getters can be thought of as iterators that convert user data (e.g. raw arrays)
// to ImPlotPoints // to ImPlotPoints
// TODO: Make members const
// Interprets an array of Y points as ImPlotPoints where the X value is the index // Interprets an array of Y points as ImPlotPoints where the X value is the index
template <typename T> template <typename T>
struct GetterYs { struct GetterYs {
@ -221,7 +226,7 @@ struct GetterYs {
int Count; int Count;
int Offset; int Offset;
int Stride; int Stride;
inline ImPlotPoint operator()(int idx) { inline ImPlotPoint operator()(int idx) const {
return ImPlotPoint((double)idx, (double)OffsetAndStride(Ys, idx, Count, Offset, Stride)); return ImPlotPoint((double)idx, (double)OffsetAndStride(Ys, idx, Count, Offset, Stride));
} }
}; };
@ -240,7 +245,7 @@ struct GetterXsYs {
int Count; int Count;
int Offset; int Offset;
int Stride; int Stride;
inline ImPlotPoint operator()(int idx) { inline ImPlotPoint operator()(int idx) const {
return ImPlotPoint((double)OffsetAndStride(Xs, idx, Count, Offset, Stride), (double)OffsetAndStride(Ys, idx, Count, Offset, Stride)); return ImPlotPoint((double)OffsetAndStride(Xs, idx, Count, Offset, Stride), (double)OffsetAndStride(Ys, idx, Count, Offset, Stride));
} }
}; };
@ -249,7 +254,7 @@ struct GetterXsYs {
template <typename T> template <typename T>
struct GetterYRef { struct GetterYRef {
GetterYRef(T y_ref, int count) { YRef = y_ref; Count = count; } GetterYRef(T y_ref, int count) { YRef = y_ref; Count = count; }
inline ImPlotPoint operator()(int idx) { inline ImPlotPoint operator()(int idx) const {
return ImPlotPoint((double)idx, (double)YRef); return ImPlotPoint((double)idx, (double)YRef);
} }
T YRef; T YRef;
@ -271,7 +276,7 @@ struct GetterXsYRef {
int Count; int Count;
int Offset; int Offset;
int Stride; int Stride;
inline ImPlotPoint operator()(int idx) { inline ImPlotPoint operator()(int idx) const {
return ImPlotPoint((double)OffsetAndStride(Xs, idx, Count, Offset, Stride), (double)YRef); return ImPlotPoint((double)OffsetAndStride(Xs, idx, Count, Offset, Stride), (double)YRef);
} }
}; };
@ -283,7 +288,7 @@ struct GetterImVec2 {
Count = count; Count = count;
Offset = count ? ImPosMod(offset, count) : 0; Offset = count ? ImPosMod(offset, count) : 0;
} }
inline ImPlotPoint operator()(int idx) { inline ImPlotPoint operator()(int idx) const {
idx = ImPosMod(Offset + idx, Count); idx = ImPosMod(Offset + idx, Count);
return ImPlotPoint((double)Data[idx].x, (double)Data[idx].y); return ImPlotPoint((double)Data[idx].x, (double)Data[idx].y);
} }
@ -299,7 +304,7 @@ struct GetterImPlotPoint {
Count = count; Count = count;
Offset = count ? ImPosMod(offset, count) : 0; Offset = count ? ImPosMod(offset, count) : 0;
} }
inline ImPlotPoint operator()(int idx) { inline ImPlotPoint operator()(int idx) const {
idx = ImPosMod(Offset + idx, Count); idx = ImPosMod(Offset + idx, Count);
return Data[idx]; return Data[idx];
} }
@ -316,7 +321,7 @@ struct GetterFuncPtrImPlotPoint {
Count = count; Count = count;
Offset = count ? ImPosMod(offset, count) : 0; Offset = count ? ImPosMod(offset, count) : 0;
} }
inline ImPlotPoint operator()(int idx) { inline ImPlotPoint operator()(int idx) const {
idx = ImPosMod(Offset + idx, Count); idx = ImPosMod(Offset + idx, Count);
return getter(Data, idx); return getter(Data, idx);
} }
@ -330,14 +335,14 @@ template <typename T>
struct GetterBarV { struct GetterBarV {
const T* Ys; double XShift; int Count; int Offset; int Stride; const T* Ys; double XShift; int Count; int Offset; int Stride;
GetterBarV(const T* ys, double xshift, int count, int offset, int stride) { Ys = ys; XShift = xshift; Count = count; Offset = offset; Stride = stride; } GetterBarV(const T* ys, double xshift, int count, int offset, int stride) { Ys = ys; XShift = xshift; Count = count; Offset = offset; Stride = stride; }
inline ImPlotPoint operator()(int idx) { return ImPlotPoint((double)idx + (double)XShift, (double)OffsetAndStride(Ys, idx, Count, Offset, Stride)); } inline ImPlotPoint operator()(int idx) const { return ImPlotPoint((double)idx + (double)XShift, (double)OffsetAndStride(Ys, idx, Count, Offset, Stride)); }
}; };
template <typename T> template <typename T>
struct GetterBarH { struct GetterBarH {
const T* Xs; double YShift; int Count; int Offset; int Stride; const T* Xs; double YShift; int Count; int Offset; int Stride;
GetterBarH(const T* xs, double yshift, int count, int offset, int stride) { Xs = xs; YShift = yshift; Count = count; Offset = offset; Stride = stride; } GetterBarH(const T* xs, double yshift, int count, int offset, int stride) { Xs = xs; YShift = yshift; Count = count; Offset = offset; Stride = stride; }
inline ImPlotPoint operator()(int idx) { return ImPlotPoint((double)OffsetAndStride(Xs, idx, Count, Offset, Stride), (double)idx + (double)YShift); } inline ImPlotPoint operator()(int idx) const { return ImPlotPoint((double)OffsetAndStride(Xs, idx, Count, Offset, Stride), (double)idx + (double)YShift); }
}; };
template <typename T> template <typename T>
@ -346,7 +351,7 @@ struct GetterError {
GetterError(const T* xs, const T* ys, const T* neg, const T* pos, int count, int offset, int stride) { GetterError(const T* xs, const T* ys, const T* neg, const T* pos, int count, int offset, int stride) {
Xs = xs; Ys = ys; Neg = neg; Pos = pos; Count = count; Offset = offset; Stride = stride; Xs = xs; Ys = ys; Neg = neg; Pos = pos; Count = count; Offset = offset; Stride = stride;
} }
ImPlotPointError operator()(int idx) { ImPlotPointError operator()(int idx) const {
return ImPlotPointError((double)OffsetAndStride(Xs, idx, Count, Offset, Stride), return ImPlotPointError((double)OffsetAndStride(Xs, idx, Count, Offset, Stride),
(double)OffsetAndStride(Ys, idx, Count, Offset, Stride), (double)OffsetAndStride(Ys, idx, Count, Offset, Stride),
(double)OffsetAndStride(Neg, idx, Count, Offset, Stride), (double)OffsetAndStride(Neg, idx, Count, Offset, Stride),
@ -363,62 +368,54 @@ struct GetterError {
// Transforms points for linear x and linear y space // Transforms points for linear x and linear y space
struct TransformerLinLin { struct TransformerLinLin {
TransformerLinLin() : YAxis(GetCurrentYAxis()) {} TransformerLinLin() : YAxis(GetCurrentYAxis()) {}
// inline ImVec2 operator()(const ImPlotPoint& plt) const { return (*this)(plt.x, plt.y); }
inline ImVec2 operator()(const ImPlotPoint& plt) { return (*this)(plt.x, plt.y); } inline ImVec2 operator()(const ImPlotPoint& plt) const {
inline ImVec2 operator()(double x, double y) {
ImPlotContext& gp = *GImPlot; ImPlotContext& gp = *GImPlot;
return ImVec2( (float)(gp.PixelRange[YAxis].Min.x + gp.Mx * (x - gp.CurrentPlot->XAxis.Range.Min)), return ImVec2( (float)(gp.PixelRange[YAxis].Min.x + gp.Mx * (plt.x - gp.CurrentPlot->XAxis.Range.Min)),
(float)(gp.PixelRange[YAxis].Min.y + gp.My[YAxis] * (y - gp.CurrentPlot->YAxis[YAxis].Range.Min)) ); (float)(gp.PixelRange[YAxis].Min.y + gp.My[YAxis] * (plt.y - gp.CurrentPlot->YAxis[YAxis].Range.Min)) );
} }
int YAxis; const int YAxis;
}; };
// Transforms points for log x and linear y space // Transforms points for log x and linear y space
struct TransformerLogLin { struct TransformerLogLin {
TransformerLogLin() : YAxis(GetCurrentYAxis()) {} TransformerLogLin() : YAxis(GetCurrentYAxis()) {}
inline ImVec2 operator()(const ImPlotPoint& plt) const {
inline ImVec2 operator()(const ImPlotPoint& plt) { return (*this)(plt.x, plt.y); }
inline ImVec2 operator()(double x, double y) {
ImPlotContext& gp = *GImPlot; ImPlotContext& gp = *GImPlot;
double t = ImLog10(x / gp.CurrentPlot->XAxis.Range.Min) / gp.LogDenX; double t = ImLog10(plt.x / gp.CurrentPlot->XAxis.Range.Min) / gp.LogDenX;
x = ImLerp(gp.CurrentPlot->XAxis.Range.Min, gp.CurrentPlot->XAxis.Range.Max, (float)t); double x = ImLerp(gp.CurrentPlot->XAxis.Range.Min, gp.CurrentPlot->XAxis.Range.Max, (float)t);
return ImVec2( (float)(gp.PixelRange[YAxis].Min.x + gp.Mx * (x - gp.CurrentPlot->XAxis.Range.Min)), return ImVec2( (float)(gp.PixelRange[YAxis].Min.x + gp.Mx * (x - gp.CurrentPlot->XAxis.Range.Min)),
(float)(gp.PixelRange[YAxis].Min.y + gp.My[YAxis] * (y - gp.CurrentPlot->YAxis[YAxis].Range.Min)) ); (float)(gp.PixelRange[YAxis].Min.y + gp.My[YAxis] * (plt.y - gp.CurrentPlot->YAxis[YAxis].Range.Min)) );
} }
const int YAxis;
int YAxis;
}; };
// Transforms points for linear x and log y space // Transforms points for linear x and log y space
struct TransformerLinLog { struct TransformerLinLog {
TransformerLinLog() : YAxis(GetCurrentYAxis()) {} TransformerLinLog() : YAxis(GetCurrentYAxis()) {}
inline ImVec2 operator()(const ImPlotPoint& plt) const {
inline ImVec2 operator()(const ImPlotPoint& plt) { return (*this)(plt.x, plt.y); }
inline ImVec2 operator()(double x, double y) {
ImPlotContext& gp = *GImPlot; ImPlotContext& gp = *GImPlot;
double t = ImLog10(y / gp.CurrentPlot->YAxis[YAxis].Range.Min) / gp.LogDenY[YAxis]; double t = ImLog10(plt.y / gp.CurrentPlot->YAxis[YAxis].Range.Min) / gp.LogDenY[YAxis];
y = ImLerp(gp.CurrentPlot->YAxis[YAxis].Range.Min, gp.CurrentPlot->YAxis[YAxis].Range.Max, (float)t); double y = ImLerp(gp.CurrentPlot->YAxis[YAxis].Range.Min, gp.CurrentPlot->YAxis[YAxis].Range.Max, (float)t);
return ImVec2( (float)(gp.PixelRange[YAxis].Min.x + gp.Mx * (x - gp.CurrentPlot->XAxis.Range.Min)), return ImVec2( (float)(gp.PixelRange[YAxis].Min.x + gp.Mx * (plt.x - gp.CurrentPlot->XAxis.Range.Min)),
(float)(gp.PixelRange[YAxis].Min.y + gp.My[YAxis] * (y - gp.CurrentPlot->YAxis[YAxis].Range.Min)) ); (float)(gp.PixelRange[YAxis].Min.y + gp.My[YAxis] * (y - gp.CurrentPlot->YAxis[YAxis].Range.Min)) );
} }
int YAxis; const int YAxis;
}; };
// Transforms points for log x and log y space // Transforms points for log x and log y space
struct TransformerLogLog { struct TransformerLogLog {
TransformerLogLog() : YAxis(GetCurrentYAxis()) {} TransformerLogLog() : YAxis(GetCurrentYAxis()) {}
inline ImVec2 operator()(const ImPlotPoint& plt) const {
inline ImVec2 operator()(const ImPlotPoint& plt) { return (*this)(plt.x, plt.y); }
inline ImVec2 operator()(double x, double y) {
ImPlotContext& gp = *GImPlot; ImPlotContext& gp = *GImPlot;
double t = ImLog10(x / gp.CurrentPlot->XAxis.Range.Min) / gp.LogDenX; double t = ImLog10(plt.x / gp.CurrentPlot->XAxis.Range.Min) / gp.LogDenX;
x = ImLerp(gp.CurrentPlot->XAxis.Range.Min, gp.CurrentPlot->XAxis.Range.Max, (float)t); double x = ImLerp(gp.CurrentPlot->XAxis.Range.Min, gp.CurrentPlot->XAxis.Range.Max, (float)t);
t = ImLog10(y / gp.CurrentPlot->YAxis[YAxis].Range.Min) / gp.LogDenY[YAxis]; t = ImLog10(plt.y / gp.CurrentPlot->YAxis[YAxis].Range.Min) / gp.LogDenY[YAxis];
y = ImLerp(gp.CurrentPlot->YAxis[YAxis].Range.Min, gp.CurrentPlot->YAxis[YAxis].Range.Max, (float)t); double y = ImLerp(gp.CurrentPlot->YAxis[YAxis].Range.Min, gp.CurrentPlot->YAxis[YAxis].Range.Max, (float)t);
return ImVec2( (float)(gp.PixelRange[YAxis].Min.x + gp.Mx * (x - gp.CurrentPlot->XAxis.Range.Min)), return ImVec2( (float)(gp.PixelRange[YAxis].Min.x + gp.Mx * (x - gp.CurrentPlot->XAxis.Range.Min)),
(float)(gp.PixelRange[YAxis].Min.y + gp.My[YAxis] * (y - gp.CurrentPlot->YAxis[YAxis].Range.Min)) ); (float)(gp.PixelRange[YAxis].Min.y + gp.My[YAxis] * (y - gp.CurrentPlot->YAxis[YAxis].Range.Min)) );
} }
int YAxis; const int YAxis;
}; };
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
@ -460,16 +457,16 @@ inline void AddLine(const ImVec2& P1, const ImVec2& P2, float weight, ImU32 col,
template <typename TGetter, typename TTransformer> template <typename TGetter, typename TTransformer>
struct LineStripRenderer { struct LineStripRenderer {
inline LineStripRenderer(TGetter getter, TTransformer transformer, ImU32 col, float weight) : inline LineStripRenderer(const TGetter& getter, const TTransformer& transformer, ImU32 col, float weight) :
Getter(getter), Getter(getter),
Transformer(transformer) Transformer(transformer),
Prims(Getter.Count - 1),
Col(col),
Weight(weight)
{ {
Prims = Getter.Count - 1;
Col = col;
Weight = weight;
P1 = Transformer(Getter(0)); P1 = Transformer(Getter(0));
} }
inline bool operator()(ImDrawList& DrawList, const ImRect& cull_rect, const ImVec2& uv, int prim) { inline bool operator()(ImDrawList& DrawList, const ImRect& cull_rect, const ImVec2& uv, int prim) const {
ImVec2 P2 = Transformer(Getter(prim + 1)); ImVec2 P2 = Transformer(Getter(prim + 1));
if (!cull_rect.Overlaps(ImRect(ImMin(P1, P2), ImMax(P1, P2)))) { if (!cull_rect.Overlaps(ImRect(ImMin(P1, P2), ImMax(P1, P2)))) {
P1 = P2; P1 = P2;
@ -479,29 +476,27 @@ struct LineStripRenderer {
P1 = P2; P1 = P2;
return true; return true;
} }
TGetter Getter; const TGetter& Getter;
TTransformer Transformer; const TTransformer& Transformer;
int Prims; const int Prims;
ImU32 Col; const ImU32 Col;
float Weight; const float Weight;
ImVec2 P1; mutable ImVec2 P1;
static const int IdxConsumed = 6; static const int IdxConsumed = 6;
static const int VtxConsumed = 4; static const int VtxConsumed = 4;
}; };
template <typename TGetter1, typename TGetter2, typename TTransformer> template <typename TGetter1, typename TGetter2, typename TTransformer>
struct LineSegmentsRenderer { struct LineSegmentsRenderer {
inline LineSegmentsRenderer(TGetter1 getter1, TGetter2 getter2, TTransformer transformer, ImU32 col, float weight) : inline LineSegmentsRenderer(const TGetter1& getter1, const TGetter2& getter2, const TTransformer& transformer, ImU32 col, float weight) :
Getter1(getter1), Getter1(getter1),
Getter2(getter2), Getter2(getter2),
Transformer(transformer) Transformer(transformer),
{ Prims(ImMin(Getter1.Count, Getter2.Count)),
Col(col),
Prims = ImMin(Getter1.Count, Getter2.Count); Weight(weight)
Col = col; {}
Weight = weight; inline bool operator()(ImDrawList& DrawList, const ImRect& cull_rect, const ImVec2& uv, int prim) const {
}
inline bool operator()(ImDrawList& DrawList, const ImRect& cull_rect, const ImVec2& uv, int prim) {
ImVec2 P1 = Transformer(Getter1(prim)); ImVec2 P1 = Transformer(Getter1(prim));
ImVec2 P2 = Transformer(Getter2(prim)); ImVec2 P2 = Transformer(Getter2(prim));
if (!cull_rect.Overlaps(ImRect(ImMin(P1, P2), ImMax(P1, P2)))) if (!cull_rect.Overlaps(ImRect(ImMin(P1, P2), ImMax(P1, P2))))
@ -509,30 +504,30 @@ struct LineSegmentsRenderer {
AddLine(P1,P2,Weight,Col,DrawList,uv); AddLine(P1,P2,Weight,Col,DrawList,uv);
return true; return true;
} }
TGetter1 Getter1; const TGetter1& Getter1;
TGetter2 Getter2; const TGetter2& Getter2;
TTransformer Transformer; const TTransformer& Transformer;
int Prims; const int Prims;
ImU32 Col; const ImU32 Col;
float Weight; const float Weight;
static const int IdxConsumed = 6; static const int IdxConsumed = 6;
static const int VtxConsumed = 4; static const int VtxConsumed = 4;
}; };
template <typename TGetter1, typename TGetter2, typename TTransformer> template <typename TGetter1, typename TGetter2, typename TTransformer>
struct ShadedRenderer { struct ShadedRenderer {
ShadedRenderer(TGetter1 getter1, TGetter2 getter2, TTransformer transformer, ImU32 col) : ShadedRenderer(const TGetter1& getter1, const TGetter2& getter2, const TTransformer& transformer, ImU32 col) :
Getter1(getter1), Getter1(getter1),
Getter2(getter2), Getter2(getter2),
Transformer(transformer), Transformer(transformer),
Prims(ImMin(Getter1.Count, Getter2.Count) - 1),
Col(col) Col(col)
{ {
Prims = ImMin(Getter1.Count, Getter2.Count) - 1;
P11 = Transformer(Getter1(0)); P11 = Transformer(Getter1(0));
P12 = Transformer(Getter2(0)); P12 = Transformer(Getter2(0));
} }
inline bool operator()(ImDrawList& DrawList, const ImRect& /*cull_rect*/, const ImVec2& uv, int prim) { inline bool operator()(ImDrawList& DrawList, const ImRect& /*cull_rect*/, const ImVec2& uv, int prim) const {
// TODO: Culling // TODO: Culling
ImVec2 P21 = Transformer(Getter1(prim+1)); ImVec2 P21 = Transformer(Getter1(prim+1));
ImVec2 P22 = Transformer(Getter2(prim+1)); ImVec2 P22 = Transformer(Getter2(prim+1));
@ -566,26 +561,26 @@ struct ShadedRenderer {
P12 = P22; P12 = P22;
return true; return true;
} }
TGetter1 Getter1; const TGetter1& Getter1;
TGetter2 Getter2; const TGetter2& Getter2;
TTransformer Transformer; const TTransformer& Transformer;
int Prims; const int Prims;
ImU32 Col; const ImU32 Col;
ImVec2 P11, P12; mutable ImVec2 P11;
mutable ImVec2 P12;
static const int IdxConsumed = 6; static const int IdxConsumed = 6;
static const int VtxConsumed = 5; static const int VtxConsumed = 5;
}; };
template <typename TGetter, typename TTransformer> template <typename TGetter, typename TTransformer>
struct RectRenderer { struct RectRenderer {
inline RectRenderer(TGetter getter, TTransformer transformer, ImU32 col) : inline RectRenderer(const TGetter& getter, const TTransformer& transformer, ImU32 col) :
Getter(getter), Getter(getter),
Transformer(transformer) Transformer(transformer),
{ Prims(Getter.Count / 2),
Prims = Getter.Count / 2; Col(col)
Col = col; {}
} inline bool operator()(ImDrawList& DrawList, const ImRect& /*cull_rect*/, const ImVec2& uv, int prim) const {
inline bool operator()(ImDrawList& DrawList, const ImRect& /*cull_rect*/, const ImVec2& uv, int prim) {
// TODO: Culling // TODO: Culling
ImVec2 P1 = Transformer(Getter(2*prim)); ImVec2 P1 = Transformer(Getter(2*prim));
ImVec2 P2 = Transformer(Getter(2*prim+1)); ImVec2 P2 = Transformer(Getter(2*prim+1));
@ -614,10 +609,10 @@ struct RectRenderer {
DrawList._VtxCurrentIdx += 4; DrawList._VtxCurrentIdx += 4;
return true; return true;
} }
TGetter Getter; const TGetter& Getter;
TTransformer Transformer; const TTransformer& Transformer;
int Prims; const int Prims;
ImU32 Col; const ImU32 Col;
static const int IdxConsumed = 6; static const int IdxConsumed = 6;
static const int VtxConsumed = 4; static const int VtxConsumed = 4;
}; };
@ -630,7 +625,7 @@ template <> const unsigned int MaxIdx<unsigned int>::Value = 4294967295;
/// Renders primitive shapes in bulk as efficiently as possible. /// Renders primitive shapes in bulk as efficiently as possible.
template <typename Renderer> template <typename Renderer>
inline void RenderPrimitives(Renderer renderer, ImDrawList& DrawList, const ImRect& cull_rect) { inline void RenderPrimitives(const Renderer& renderer, ImDrawList& DrawList, const ImRect& cull_rect) {
unsigned int prims = renderer.Prims; unsigned int prims = renderer.Prims;
unsigned int prims_culled = 0; unsigned int prims_culled = 0;
unsigned int idx = 0; unsigned int idx = 0;
@ -667,7 +662,7 @@ inline void RenderPrimitives(Renderer renderer, ImDrawList& DrawList, const ImRe
} }
template <typename Getter, typename Transformer> template <typename Getter, typename Transformer>
inline void RenderLineStrip(Getter getter, Transformer transformer, ImDrawList& DrawList, float line_weight, ImU32 col) { inline void RenderLineStrip(const Getter& getter, const Transformer& transformer, ImDrawList& DrawList, float line_weight, ImU32 col) {
ImPlotContext& gp = *GImPlot; ImPlotContext& gp = *GImPlot;
if (ImHasFlag(gp.CurrentPlot->Flags, ImPlotFlags_AntiAliased) || gp.Style.AntiAliasedLines) { if (ImHasFlag(gp.CurrentPlot->Flags, ImPlotFlags_AntiAliased) || gp.Style.AntiAliasedLines) {
ImVec2 p1 = transformer(getter(0)); ImVec2 p1 = transformer(getter(0));
@ -684,7 +679,7 @@ inline void RenderLineStrip(Getter getter, Transformer transformer, ImDrawList&
} }
template <typename Getter1, typename Getter2, typename Transformer> template <typename Getter1, typename Getter2, typename Transformer>
inline void RenderLineSegments(Getter1 getter1, Getter2 getter2, Transformer transformer, ImDrawList& DrawList, float line_weight, ImU32 col) { inline void RenderLineSegments(const Getter1& getter1, const Getter2& getter2, const Transformer& transformer, ImDrawList& DrawList, float line_weight, ImU32 col) {
ImPlotContext& gp = *GImPlot; ImPlotContext& gp = *GImPlot;
if (ImHasFlag(gp.CurrentPlot->Flags, ImPlotFlags_AntiAliased) || gp.Style.AntiAliasedLines) { if (ImHasFlag(gp.CurrentPlot->Flags, ImPlotFlags_AntiAliased) || gp.Style.AntiAliasedLines) {
int I = ImMin(getter1.Count, getter2.Count); int I = ImMin(getter1.Count, getter2.Count);
@ -810,11 +805,11 @@ inline void RenderMarkers(Getter getter, Transformer transformer, ImDrawList& Dr
} }
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
// PLOT LINES // PLOT LINE
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
template <typename Getter> template <typename Getter>
inline void PlotLineEx(const char* label_id, Getter getter) { inline void PlotLineEx(const char* label_id, const Getter& getter) {
if (BeginItem(label_id, ImPlotCol_Line)) { if (BeginItem(label_id, ImPlotCol_Line)) {
if (FitThisFrame()) { if (FitThisFrame()) {
for (int i = 0; i < getter.Count; ++i) { for (int i = 0; i < getter.Count; ++i) {
@ -906,7 +901,7 @@ void PlotLineG(const char* label_id, ImPlotPoint (*getter_func)(void* data, int
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
template <typename Getter> template <typename Getter>
inline void PlotScatterEx(const char* label_id, Getter getter) { inline void PlotScatterEx(const char* label_id, const Getter& getter) {
if (BeginItem(label_id, ImPlotCol_MarkerOutline)) { if (BeginItem(label_id, ImPlotCol_MarkerOutline)) {
if (FitThisFrame()) { if (FitThisFrame()) {
for (int i = 0; i < getter.Count; ++i) { for (int i = 0; i < getter.Count; ++i) {
@ -990,7 +985,7 @@ void PlotScatterG(const char* label_id, ImPlotPoint (*getter_func)(void* data, i
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
template <typename Getter1, typename Getter2> template <typename Getter1, typename Getter2>
inline void PlotShadedEx(const char* label_id, Getter1 getter1, Getter2 getter2) { inline void PlotShadedEx(const char* label_id, const Getter1& getter1, const Getter2& getter2) {
if (BeginItem(label_id, ImPlotCol_Fill)) { if (BeginItem(label_id, ImPlotCol_Fill)) {
if (FitThisFrame()) { if (FitThisFrame()) {
for (int i = 0; i < ImMin(getter1.Count, getter2.Count); ++i) { for (int i = 0; i < ImMin(getter1.Count, getter2.Count); ++i) {
@ -1082,10 +1077,10 @@ void PlotShadedG(const char* label_id, ImPlotPoint (*g1)(void* data, int idx), v
// TODO: Migrate to RenderPrimitives // TODO: Migrate to RenderPrimitives
template <typename Getter, typename TWidth> template <typename Getter>
void PlotBarsEx(const char* label_id, Getter getter, TWidth width) { void PlotBarsEx(const char* label_id, const Getter& getter, double width) {
if (BeginItem(label_id, ImPlotCol_Fill)) { if (BeginItem(label_id, ImPlotCol_Fill)) {
const TWidth half_width = width / 2; const double half_width = width / 2;
if (FitThisFrame()) { if (FitThisFrame()) {
for (int i = 0; i < getter.Count; ++i) { for (int i = 0; i < getter.Count; ++i) {
ImPlotPoint p = getter(i); ImPlotPoint p = getter(i);
@ -1162,7 +1157,7 @@ void PlotBarsG(const char* label_id, ImPlotPoint (*getter_func)(void* data, int
// TODO: Migrate to RenderPrimitives // TODO: Migrate to RenderPrimitives
template <typename Getter, typename THeight> template <typename Getter, typename THeight>
void PlotBarsHEx(const char* label_id, Getter getter, THeight height) { void PlotBarsHEx(const char* label_id, const Getter& getter, THeight height) {
if (BeginItem(label_id, ImPlotCol_Fill)) { if (BeginItem(label_id, ImPlotCol_Fill)) {
const THeight half_height = height / 2; const THeight half_height = height / 2;
if (FitThisFrame()) { if (FitThisFrame()) {
@ -1239,7 +1234,7 @@ void PlotBarsHG(const char* label_id, ImPlotPoint (*getter_func)(void* data, int
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
template <typename Getter> template <typename Getter>
void PlotErrorBarsEx(const char* label_id, Getter getter) { void PlotErrorBarsEx(const char* label_id, const Getter& getter) {
if (BeginItem(label_id)) { if (BeginItem(label_id)) {
if (FitThisFrame()) { if (FitThisFrame()) {
for (int i = 0; i < getter.Count; ++i) { for (int i = 0; i < getter.Count; ++i) {
@ -1267,34 +1262,45 @@ void PlotErrorBarsEx(const char* label_id, Getter getter) {
} }
} }
// float template <typename T>
void PlotErrorBars(const char* label_id, const float* xs, const float* ys, const float* err, int count, int offset, int stride) { void PlotErrorBars(const char* label_id, const T* xs, const T* ys, const T* err, int count, int offset, int stride) {
GetterError<float> getter(xs, ys, err, err, count, offset, stride); GetterError<T> getter(xs, ys, err, err, count, offset, stride);
PlotErrorBarsEx(label_id, getter); PlotErrorBarsEx(label_id, getter);
} }
void PlotErrorBars(const char* label_id, const float* xs, const float* ys, const float* neg, const float* pos, int count, int offset, int stride) { template void PlotErrorBars<ImS8>(const char* label_id, const ImS8* xs, const ImS8* ys, const ImS8* err, int count, int offset, int stride);
GetterError<float> getter(xs, ys, neg, pos, count, offset, stride); template void PlotErrorBars<ImU8>(const char* label_id, const ImU8* xs, const ImU8* ys, const ImU8* err, int count, int offset, int stride);
PlotErrorBarsEx(label_id, getter); template void PlotErrorBars<ImS16>(const char* label_id, const ImS16* xs, const ImS16* ys, const ImS16* err, int count, int offset, int stride);
} template void PlotErrorBars<ImU16>(const char* label_id, const ImU16* xs, const ImU16* ys, const ImU16* err, int count, int offset, int stride);
template void PlotErrorBars<ImS32>(const char* label_id, const ImS32* xs, const ImS32* ys, const ImS32* err, int count, int offset, int stride);
template void PlotErrorBars<ImU32>(const char* label_id, const ImU32* xs, const ImU32* ys, const ImU32* err, int count, int offset, int stride);
template void PlotErrorBars<ImS64>(const char* label_id, const ImS64* xs, const ImS64* ys, const ImS64* err, int count, int offset, int stride);
template void PlotErrorBars<ImU64>(const char* label_id, const ImU64* xs, const ImU64* ys, const ImU64* err, int count, int offset, int stride);
template void PlotErrorBars<float>(const char* label_id, const float* xs, const float* ys, const float* err, int count, int offset, int stride);
template void PlotErrorBars<double>(const char* label_id, const double* xs, const double* ys, const double* err, int count, int offset, int stride);
// double template <typename T>
void PlotErrorBars(const char* label_id, const double* xs, const double* ys, const double* err, int count, int offset, int stride) { void PlotErrorBars(const char* label_id, const T* xs, const T* ys, const T* neg, const T* pos, int count, int offset, int stride) {
GetterError<double> getter(xs, ys, err, err, count, offset, stride); GetterError<T> getter(xs, ys, neg, pos, count, offset, stride);
PlotErrorBarsEx(label_id, getter);
}
void PlotErrorBars(const char* label_id, const double* xs, const double* ys, const double* neg, const double* pos, int count, int offset, int stride) {
GetterError<double> getter(xs, ys, neg, pos, count, offset, stride);
PlotErrorBarsEx(label_id, getter); PlotErrorBarsEx(label_id, getter);
} }
template void PlotErrorBars<ImS8>(const char* label_id, const ImS8* xs, const ImS8* ys, const ImS8* neg, const ImS8* pos, int count, int offset, int stride);
template void PlotErrorBars<ImU8>(const char* label_id, const ImU8* xs, const ImU8* ys, const ImU8* neg, const ImU8* pos, int count, int offset, int stride);
template void PlotErrorBars<ImS16>(const char* label_id, const ImS16* xs, const ImS16* ys, const ImS16* neg, const ImS16* pos, int count, int offset, int stride);
template void PlotErrorBars<ImU16>(const char* label_id, const ImU16* xs, const ImU16* ys, const ImU16* neg, const ImU16* pos, int count, int offset, int stride);
template void PlotErrorBars<ImS32>(const char* label_id, const ImS32* xs, const ImS32* ys, const ImS32* neg, const ImS32* pos, int count, int offset, int stride);
template void PlotErrorBars<ImU32>(const char* label_id, const ImU32* xs, const ImU32* ys, const ImU32* neg, const ImU32* pos, int count, int offset, int stride);
template void PlotErrorBars<ImS64>(const char* label_id, const ImS64* xs, const ImS64* ys, const ImS64* neg, const ImS64* pos, int count, int offset, int stride);
template void PlotErrorBars<ImU64>(const char* label_id, const ImU64* xs, const ImU64* ys, const ImU64* neg, const ImU64* pos, int count, int offset, int stride);
template void PlotErrorBars<float>(const char* label_id, const float* xs, const float* ys, const float* neg, const float* pos, int count, int offset, int stride);
template void PlotErrorBars<double>(const char* label_id, const double* xs, const double* ys, const double* neg, const double* pos, int count, int offset, int stride);
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
// PLOT ERROR BARS H // PLOT ERROR BARS H
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
template <typename Getter> template <typename Getter>
void PlotErrorBarsHEx(const char* label_id, Getter getter) { void PlotErrorBarsHEx(const char* label_id, const Getter& getter) {
if (BeginItem(label_id)) { if (BeginItem(label_id)) {
if (FitThisFrame()) { if (FitThisFrame()) {
for (int i = 0; i < getter.Count; ++i) { for (int i = 0; i < getter.Count; ++i) {
@ -1322,34 +1328,46 @@ void PlotErrorBarsHEx(const char* label_id, Getter getter) {
} }
} }
// float template <typename T>
void PlotErrorBarsH(const char* label_id, const float* xs, const float* ys, const float* err, int count, int offset, int stride) { void PlotErrorBarsH(const char* label_id, const T* xs, const T* ys, const T* err, int count, int offset, int stride) {
GetterError<float> getter(xs, ys, err, err, count, offset, stride); GetterError<T> getter(xs, ys, err, err, count, offset, stride);
PlotErrorBarsHEx(label_id, getter); PlotErrorBarsHEx(label_id, getter);
} }
void PlotErrorBarsH(const char* label_id, const float* xs, const float* ys, const float* neg, const float* pos, int count, int offset, int stride) { template void PlotErrorBarsH<ImS8>(const char* label_id, const ImS8* xs, const ImS8* ys, const ImS8* err, int count, int offset, int stride);
GetterError<float> getter(xs, ys, neg, pos, count, offset, stride); template void PlotErrorBarsH<ImU8>(const char* label_id, const ImU8* xs, const ImU8* ys, const ImU8* err, int count, int offset, int stride);
template void PlotErrorBarsH<ImS16>(const char* label_id, const ImS16* xs, const ImS16* ys, const ImS16* err, int count, int offset, int stride);
template void PlotErrorBarsH<ImU16>(const char* label_id, const ImU16* xs, const ImU16* ys, const ImU16* err, int count, int offset, int stride);
template void PlotErrorBarsH<ImS32>(const char* label_id, const ImS32* xs, const ImS32* ys, const ImS32* err, int count, int offset, int stride);
template void PlotErrorBarsH<ImU32>(const char* label_id, const ImU32* xs, const ImU32* ys, const ImU32* err, int count, int offset, int stride);
template void PlotErrorBarsH<ImS64>(const char* label_id, const ImS64* xs, const ImS64* ys, const ImS64* err, int count, int offset, int stride);
template void PlotErrorBarsH<ImU64>(const char* label_id, const ImU64* xs, const ImU64* ys, const ImU64* err, int count, int offset, int stride);
template void PlotErrorBarsH<float>(const char* label_id, const float* xs, const float* ys, const float* err, int count, int offset, int stride);
template void PlotErrorBarsH<double>(const char* label_id, const double* xs, const double* ys, const double* err, int count, int offset, int stride);
template <typename T>
void PlotErrorBarsH(const char* label_id, const T* xs, const T* ys, const T* neg, const T* pos, int count, int offset, int stride) {
GetterError<T> getter(xs, ys, neg, pos, count, offset, stride);
PlotErrorBarsHEx(label_id, getter); PlotErrorBarsHEx(label_id, getter);
} }
// double template void PlotErrorBarsH<ImS8>(const char* label_id, const ImS8* xs, const ImS8* ys, const ImS8* neg, const ImS8* pos, int count, int offset, int stride);
void PlotErrorBarsH(const char* label_id, const double* xs, const double* ys, const double* err, int count, int offset, int stride) { template void PlotErrorBarsH<ImU8>(const char* label_id, const ImU8* xs, const ImU8* ys, const ImU8* neg, const ImU8* pos, int count, int offset, int stride);
GetterError<double> getter(xs, ys, err, err, count, offset, stride); template void PlotErrorBarsH<ImS16>(const char* label_id, const ImS16* xs, const ImS16* ys, const ImS16* neg, const ImS16* pos, int count, int offset, int stride);
PlotErrorBarsHEx(label_id, getter); template void PlotErrorBarsH<ImU16>(const char* label_id, const ImU16* xs, const ImU16* ys, const ImU16* neg, const ImU16* pos, int count, int offset, int stride);
} template void PlotErrorBarsH<ImS32>(const char* label_id, const ImS32* xs, const ImS32* ys, const ImS32* neg, const ImS32* pos, int count, int offset, int stride);
template void PlotErrorBarsH<ImU32>(const char* label_id, const ImU32* xs, const ImU32* ys, const ImU32* neg, const ImU32* pos, int count, int offset, int stride);
void PlotErrorBarsH(const char* label_id, const double* xs, const double* ys, const double* neg, const double* pos, int count, int offset, int stride) { template void PlotErrorBarsH<ImS64>(const char* label_id, const ImS64* xs, const ImS64* ys, const ImS64* neg, const ImS64* pos, int count, int offset, int stride);
GetterError<double> getter(xs, ys, neg, pos, count, offset, stride); template void PlotErrorBarsH<ImU64>(const char* label_id, const ImU64* xs, const ImU64* ys, const ImU64* neg, const ImU64* pos, int count, int offset, int stride);
PlotErrorBarsHEx(label_id, getter); template void PlotErrorBarsH<float>(const char* label_id, const float* xs, const float* ys, const float* neg, const float* pos, int count, int offset, int stride);
} template void PlotErrorBarsH<double>(const char* label_id, const double* xs, const double* ys, const double* neg, const double* pos, int count, int offset, int stride);
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
// PLOT STEMS // PLOT STEMS
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
template <typename GetterM, typename GetterB> template <typename GetterM, typename GetterB>
inline void PlotStemsEx(const char* label_id, GetterM get_mark, GetterB get_base) { inline void PlotStemsEx(const char* label_id, const GetterM& get_mark, const GetterB& get_base) {
if (BeginItem(label_id, ImPlotCol_Line)) { if (BeginItem(label_id, ImPlotCol_Line)) {
if (FitThisFrame()) { if (FitThisFrame()) {
for (int i = 0; i < get_base.Count; ++i) { for (int i = 0; i < get_base.Count; ++i) {
@ -1385,29 +1403,41 @@ inline void PlotStemsEx(const char* label_id, GetterM get_mark, GetterB get_base
} }
} }
void PlotStems(const char* label_id, const float* values, int count, float y_ref, int offset, int stride) { template <typename T>
GetterYs<float> get_mark(values,count,offset,stride); void PlotStems(const char* label_id, const T* values, int count, double y_ref, int offset, int stride) {
GetterYRef<float> get_base(y_ref,count); GetterYs<T> get_mark(values,count,offset,stride);
PlotStemsEx(label_id, get_mark, get_base);
}
void PlotStems(const char* label_id, const double* values, int count, double y_ref, int offset, int stride) {
GetterYs<double> get_mark(values,count,offset,stride);
GetterYRef<double> get_base(y_ref,count); GetterYRef<double> get_base(y_ref,count);
PlotStemsEx(label_id, get_mark, get_base); PlotStemsEx(label_id, get_mark, get_base);
} }
void PlotStems(const char* label_id, const float* xs, const float* ys, int count, float y_ref, int offset, int stride) { template void PlotStems<ImS8>(const char* label_id, const ImS8* values, int count, double y_ref, int offset, int stride);
GetterXsYs<float> get_mark(xs,ys,count,offset,stride); template void PlotStems<ImU8>(const char* label_id, const ImU8* values, int count, double y_ref, int offset, int stride);
GetterXsYRef<float,float> get_base(xs,y_ref,count,offset,stride); template void PlotStems<ImS16>(const char* label_id, const ImS16* values, int count, double y_ref, int offset, int stride);
template void PlotStems<ImU16>(const char* label_id, const ImU16* values, int count, double y_ref, int offset, int stride);
template void PlotStems<ImS32>(const char* label_id, const ImS32* values, int count, double y_ref, int offset, int stride);
template void PlotStems<ImU32>(const char* label_id, const ImU32* values, int count, double y_ref, int offset, int stride);
template void PlotStems<ImS64>(const char* label_id, const ImS64* values, int count, double y_ref, int offset, int stride);
template void PlotStems<ImU64>(const char* label_id, const ImU64* values, int count, double y_ref, int offset, int stride);
template void PlotStems<float>(const char* label_id, const float* values, int count, double y_ref, int offset, int stride);
template void PlotStems<double>(const char* label_id, const double* values, int count, double y_ref, int offset, int stride);
template <typename T>
void PlotStems(const char* label_id, const T* xs, const T* ys, int count, double y_ref, int offset, int stride) {
GetterXsYs<T> get_mark(xs,ys,count,offset,stride);
GetterXsYRef<T,double> get_base(xs,y_ref,count,offset,stride);
PlotStemsEx(label_id, get_mark, get_base); PlotStemsEx(label_id, get_mark, get_base);
} }
void PlotStems(const char* label_id, const double* xs, const double* ys, int count, double y_ref, int offset, int stride) { template void PlotStems<ImS8>(const char* label_id, const ImS8* xs, const ImS8* ys, int count, double y_ref, int offset, int stride);
GetterXsYs<double> get_mark(xs,ys,count,offset,stride); template void PlotStems<ImU8>(const char* label_id, const ImU8* xs, const ImU8* ys, int count, double y_ref, int offset, int stride);
GetterXsYRef<double,double> get_base(xs,y_ref,count,offset,stride); template void PlotStems<ImS16>(const char* label_id, const ImS16* xs, const ImS16* ys, int count, double y_ref, int offset, int stride);
PlotStemsEx(label_id, get_mark, get_base); template void PlotStems<ImU16>(const char* label_id, const ImU16* xs, const ImU16* ys, int count, double y_ref, int offset, int stride);
} template void PlotStems<ImS32>(const char* label_id, const ImS32* xs, const ImS32* ys, int count, double y_ref, int offset, int stride);
template void PlotStems<ImU32>(const char* label_id, const ImU32* xs, const ImU32* ys, int count, double y_ref, int offset, int stride);
template void PlotStems<ImS64>(const char* label_id, const ImS64* xs, const ImS64* ys, int count, double y_ref, int offset, int stride);
template void PlotStems<ImU64>(const char* label_id, const ImU64* xs, const ImU64* ys, int count, double y_ref, int offset, int stride);
template void PlotStems<float>(const char* label_id, const float* xs, const float* ys, int count, double y_ref, int offset, int stride);
template void PlotStems<double>(const char* label_id, const double* xs, const double* ys, int count, double y_ref, int offset, int stride);
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
// PLOT PIE CHART // PLOT PIE CHART
@ -1427,19 +1457,19 @@ inline void RenderPieSlice(ImDrawList& DrawList, const ImPlotPoint& center, doub
} }
template <typename T> template <typename T>
void PlotPieChartEx(const char* const label_ids[], const T* values, int count, T x, T y, T radius, bool normalize, const char* fmt, T angle0) { void PlotPieChart(const char* const label_ids[], const T* values, int count, double x, double y, double radius, bool normalize, const char* fmt, double angle0) {
IM_ASSERT_USER_ERROR(GImPlot->CurrentPlot != NULL, "PlotPieChart() needs to be called between BeginPlot() and EndPlot()!"); IM_ASSERT_USER_ERROR(GImPlot->CurrentPlot != NULL, "PlotPieChart() needs to be called between BeginPlot() and EndPlot()!");
ImDrawList & DrawList = *GetPlotDrawList(); ImDrawList & DrawList = *GetPlotDrawList();
T sum = 0; double sum = 0;
for (int i = 0; i < count; ++i) for (int i = 0; i < count; ++i)
sum += values[i]; sum += (double)values[i];
normalize = normalize || sum > 1.0f; normalize = normalize || sum > 1.0;
ImPlotPoint center(x,y); ImPlotPoint center(x,y);
PushPlotClipRect(); PushPlotClipRect();
T a0 = angle0 * 2 * IM_PI / 360.0f; double a0 = angle0 * 2 * IM_PI / 360.0;
T a1 = angle0 * 2 * IM_PI / 360.0f; double a1 = angle0 * 2 * IM_PI / 360.0;
for (int i = 0; i < count; ++i) { for (int i = 0; i < count; ++i) {
T percent = normalize ? values[i] / sum : values[i]; double percent = normalize ? (double)values[i] / sum : (double)values[i];
a1 = a0 + 2 * IM_PI * percent; a1 = a0 + 2 * IM_PI * percent;
if (BeginItem(label_ids[i])) { if (BeginItem(label_ids[i])) {
ImU32 col = ImGui::GetColorU32(GetCurrentItem()->Color); ImU32 col = ImGui::GetColorU32(GetCurrentItem()->Color);
@ -1447,26 +1477,26 @@ void PlotPieChartEx(const char* const label_ids[], const T* values, int count, T
RenderPieSlice(DrawList, center, radius, a0, a1, col); RenderPieSlice(DrawList, center, radius, a0, a1, col);
} }
else { else {
RenderPieSlice(DrawList, center, radius, a0, a0 + (a1 - a0) * 0.5f, col); RenderPieSlice(DrawList, center, radius, a0, a0 + (a1 - a0) * 0.5, col);
RenderPieSlice(DrawList, center, radius, a0 + (a1 - a0) * 0.5f, a1, col); RenderPieSlice(DrawList, center, radius, a0 + (a1 - a0) * 0.5, a1, col);
} }
EndItem(); EndItem();
} }
a0 = a1; a0 = a1;
} }
if (fmt != NULL) { if (fmt != NULL) {
a0 = angle0 * 2 * IM_PI / 360.0f; a0 = angle0 * 2 * IM_PI / 360.0;
a1 = angle0 * 2 * IM_PI / 360.0f; a1 = angle0 * 2 * IM_PI / 360.0;
char buffer[32]; char buffer[32];
for (int i = 0; i < count; ++i) { for (int i = 0; i < count; ++i) {
ImPlotItem* item = GetItem(label_ids[i]); ImPlotItem* item = GetItem(label_ids[i]);
T percent = normalize ? values[i] / sum : values[i]; double percent = normalize ? (double)values[i] / sum : (double)values[i];
a1 = a0 + 2 * IM_PI * percent; a1 = a0 + 2 * IM_PI * percent;
if (item->Show) { if (item->Show) {
sprintf(buffer, fmt, values[i]); sprintf(buffer, fmt, (double)values[i]);
ImVec2 size = ImGui::CalcTextSize(buffer); ImVec2 size = ImGui::CalcTextSize(buffer);
T angle = a0 + (a1 - a0) * 0.5f; double angle = a0 + (a1 - a0) * 0.5;
ImVec2 pos = PlotToPixels(center.x + 0.5f * radius * cos(angle), center.y + 0.5f * radius * sin(angle)); ImVec2 pos = PlotToPixels(center.x + 0.5 * radius * cos(angle), center.y + 0.5 * radius * sin(angle));
ImU32 col = CalcTextColor(item->Color); ImU32 col = CalcTextColor(item->Color);
DrawList.AddText(pos - size * 0.5f, col, buffer); DrawList.AddText(pos - size * 0.5f, col, buffer);
} }
@ -1476,22 +1506,23 @@ void PlotPieChartEx(const char* const label_ids[], const T* values, int count, T
PopPlotClipRect(); PopPlotClipRect();
} }
// float template void PlotPieChart<ImS8>(const char* const label_ids[], const ImS8* values, int count, double x, double y, double radius, bool normalize, const char* fmt, double angle0);
void PlotPieChart(const char* const label_ids[], const float* values, int count, float x, float y, float radius, bool normalize, const char* fmt, float angle0) { template void PlotPieChart<ImU8>(const char* const label_ids[], const ImU8* values, int count, double x, double y, double radius, bool normalize, const char* fmt, double angle0);
return PlotPieChartEx(label_ids, values, count, x, y, radius, normalize, fmt, angle0); template void PlotPieChart<ImS16>(const char* const label_ids[], const ImS16* values, int count, double x, double y, double radius, bool normalize, const char* fmt, double angle0);
} template void PlotPieChart<ImU16>(const char* const label_ids[], const ImU16* values, int count, double x, double y, double radius, bool normalize, const char* fmt, double angle0);
template void PlotPieChart<ImS32>(const char* const label_ids[], const ImS32* values, int count, double x, double y, double radius, bool normalize, const char* fmt, double angle0);
// double template void PlotPieChart<ImU32>(const char* const label_ids[], const ImU32* values, int count, double x, double y, double radius, bool normalize, const char* fmt, double angle0);
void PlotPieChart(const char* const label_ids[], const double* values, int count, double x, double y, double radius, bool normalize, const char* fmt, double angle0) { template void PlotPieChart<ImS64>(const char* const label_ids[], const ImS64* values, int count, double x, double y, double radius, bool normalize, const char* fmt, double angle0);
return PlotPieChartEx(label_ids, values, count, x, y, radius, normalize, fmt, angle0); template void PlotPieChart<ImU64>(const char* const label_ids[], const ImU64* values, int count, double x, double y, double radius, bool normalize, const char* fmt, double angle0);
} template void PlotPieChart<float>(const char* const label_ids[], const float* values, int count, double x, double y, double radius, bool normalize, const char* fmt, double angle0);
template void PlotPieChart<double>(const char* const label_ids[], const double* values, int count, double x, double y, double radius, bool normalize, const char* fmt, double angle0);
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
// PLOT HEATMAP // PLOT HEATMAP
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
template <typename T, typename Transformer> template <typename T, typename Transformer>
void RenderHeatmap(Transformer transformer, ImDrawList& DrawList, const T* values, int rows, int cols, T scale_min, T scale_max, const char* fmt, const ImPlotPoint& bounds_min, const ImPlotPoint& bounds_max) { void RenderHeatmap(Transformer transformer, ImDrawList& DrawList, const T* values, int rows, int cols, double scale_min, double scale_max, const char* fmt, const ImPlotPoint& bounds_min, const ImPlotPoint& bounds_max) {
ImPlotContext& gp = *GImPlot; ImPlotContext& gp = *GImPlot;
const double w = (bounds_max.x - bounds_min.x) / cols; const double w = (bounds_max.x - bounds_min.x) / cols;
const double h = (bounds_max.y - bounds_min.y) / rows; const double h = (bounds_max.y - bounds_min.y) / rows;
@ -1502,10 +1533,10 @@ void RenderHeatmap(Transformer transformer, ImDrawList& DrawList, const T* value
ImPlotPoint p; ImPlotPoint p;
p.x = bounds_min.x + 0.5*w + c*w; p.x = bounds_min.x + 0.5*w + c*w;
p.y = bounds_max.y - (0.5*h + r*h); p.y = bounds_max.y - (0.5*h + r*h);
ImVec2 a = transformer(p.x - half_size.x, p.y - half_size.y); ImVec2 a = transformer(ImPlotPoint(p.x - half_size.x, p.y - half_size.y));
ImVec2 b = transformer(p.x + half_size.x, p.y + half_size.y); ImVec2 b = transformer(ImPlotPoint(p.x + half_size.x, p.y + half_size.y));
float t = (float)ImRemap(values[i], scale_min, scale_max, T(0), T(1)); double t = ImRemap((double)values[i], scale_min, scale_max, 0.0, 1.0);
ImVec4 color = LerpColormap(t); ImVec4 color = LerpColormap((float)t);
color.w *= gp.Style.FillAlpha; color.w *= gp.Style.FillAlpha;
ImU32 col = ImGui::GetColorU32(color); ImU32 col = ImGui::GetColorU32(color);
DrawList.AddRectFilled(a, b, col); DrawList.AddRectFilled(a, b, col);
@ -1523,8 +1554,8 @@ void RenderHeatmap(Transformer transformer, ImDrawList& DrawList, const T* value
char buff[32]; char buff[32];
sprintf(buff, fmt, values[i]); sprintf(buff, fmt, values[i]);
ImVec2 size = ImGui::CalcTextSize(buff); ImVec2 size = ImGui::CalcTextSize(buff);
float t = (float)ImRemap(values[i], scale_min, scale_max, T(0), T(1)); double t = ImRemap((double)values[i], scale_min, scale_max, 0.0, 1.0);
ImVec4 color = LerpColormap(t); ImVec4 color = LerpColormap((float)t);
ImU32 col = CalcTextColor(color); ImU32 col = CalcTextColor(color);
DrawList.AddText(px - size * 0.5f, col, buff); DrawList.AddText(px - size * 0.5f, col, buff);
i++; i++;
@ -1534,7 +1565,7 @@ void RenderHeatmap(Transformer transformer, ImDrawList& DrawList, const T* value
} }
template <typename T> template <typename T>
void PlotHeatmapEx(const char* label_id, const T* values, int rows, int cols, T scale_min, T scale_max, const char* fmt, const ImPlotPoint& bounds_min, const ImPlotPoint& bounds_max) { void PlotHeatmap(const char* label_id, const T* values, int rows, int cols, double scale_min, double scale_max, const char* fmt, const ImPlotPoint& bounds_min, const ImPlotPoint& bounds_max) {
IM_ASSERT_USER_ERROR(scale_min != scale_max, "Scale values must be different!"); IM_ASSERT_USER_ERROR(scale_min != scale_max, "Scale values must be different!");
if (BeginItem(label_id)) { if (BeginItem(label_id)) {
if (FitThisFrame()) { if (FitThisFrame()) {
@ -1552,21 +1583,22 @@ void PlotHeatmapEx(const char* label_id, const T* values, int rows, int cols, T
} }
} }
// float template void PlotHeatmap<ImS8>(const char* label_id, const ImS8* values, int rows, int cols, double scale_min, double scale_max, const char* fmt, const ImPlotPoint& bounds_min, const ImPlotPoint& bounds_max);
void PlotHeatmap(const char* label_id, const float* values, int rows, int cols, float scale_min, float scale_max, const char* fmt, const ImPlotPoint& bounds_min, const ImPlotPoint& bounds_max) { template void PlotHeatmap<ImU8>(const char* label_id, const ImU8* values, int rows, int cols, double scale_min, double scale_max, const char* fmt, const ImPlotPoint& bounds_min, const ImPlotPoint& bounds_max);
return PlotHeatmapEx(label_id, values, rows, cols, scale_min, scale_max, fmt, bounds_min, bounds_max); template void PlotHeatmap<ImS16>(const char* label_id, const ImS16* values, int rows, int cols, double scale_min, double scale_max, const char* fmt, const ImPlotPoint& bounds_min, const ImPlotPoint& bounds_max);
} template void PlotHeatmap<ImU16>(const char* label_id, const ImU16* values, int rows, int cols, double scale_min, double scale_max, const char* fmt, const ImPlotPoint& bounds_min, const ImPlotPoint& bounds_max);
template void PlotHeatmap<ImS32>(const char* label_id, const ImS32* values, int rows, int cols, double scale_min, double scale_max, const char* fmt, const ImPlotPoint& bounds_min, const ImPlotPoint& bounds_max);
// double template void PlotHeatmap<ImU32>(const char* label_id, const ImU32* values, int rows, int cols, double scale_min, double scale_max, const char* fmt, const ImPlotPoint& bounds_min, const ImPlotPoint& bounds_max);
void PlotHeatmap(const char* label_id, const double* values, int rows, int cols, double scale_min, double scale_max, const char* fmt, const ImPlotPoint& bounds_min, const ImPlotPoint& bounds_max) { template void PlotHeatmap<ImS64>(const char* label_id, const ImS64* values, int rows, int cols, double scale_min, double scale_max, const char* fmt, const ImPlotPoint& bounds_min, const ImPlotPoint& bounds_max);
return PlotHeatmapEx(label_id, values, rows, cols, scale_min, scale_max, fmt, bounds_min, bounds_max); template void PlotHeatmap<ImU64>(const char* label_id, const ImU64* values, int rows, int cols, double scale_min, double scale_max, const char* fmt, const ImPlotPoint& bounds_min, const ImPlotPoint& bounds_max);
} template void PlotHeatmap<float>(const char* label_id, const float* values, int rows, int cols, double scale_min, double scale_max, const char* fmt, const ImPlotPoint& bounds_min, const ImPlotPoint& bounds_max);
template void PlotHeatmap<double>(const char* label_id, const double* values, int rows, int cols, double scale_min, double scale_max, const char* fmt, const ImPlotPoint& bounds_min, const ImPlotPoint& bounds_max);
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
// PLOT DIGITAL // PLOT DIGITAL
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
// TODO: Make this behave like all the other plot types // TODO: Make this behave like all the other plot types (.e. not fixed in y axis)
template <typename Getter> template <typename Getter>
inline void PlotDigitalEx(const char* label_id, Getter getter) { inline void PlotDigitalEx(const char* label_id, Getter getter) {
@ -1624,20 +1656,26 @@ inline void PlotDigitalEx(const char* label_id, Getter getter) {
} }
} }
// float
void PlotDigital(const char* label_id, const float* xs, const float* ys, int count, int offset, int stride) { template <typename T>
GetterXsYs<float> getter(xs,ys,count,offset,stride); void PlotDigital(const char* label_id, const T* xs, const T* ys, int count, int offset, int stride) {
GetterXsYs<T> getter(xs,ys,count,offset,stride);
return PlotDigitalEx(label_id, getter); return PlotDigitalEx(label_id, getter);
} }
// double template void PlotDigital<ImS8>(const char* label_id, const ImS8* xs, const ImS8* ys, int count, int offset, int stride);
void PlotDigital(const char* label_id, const double* xs, const double* ys, int count, int offset, int stride) { template void PlotDigital<ImU8>(const char* label_id, const ImU8* xs, const ImU8* ys, int count, int offset, int stride);
GetterXsYs<double> getter(xs,ys,count,offset,stride); template void PlotDigital<ImS16>(const char* label_id, const ImS16* xs, const ImS16* ys, int count, int offset, int stride);
return PlotDigitalEx(label_id, getter); template void PlotDigital<ImU16>(const char* label_id, const ImU16* xs, const ImU16* ys, int count, int offset, int stride);
} template void PlotDigital<ImS32>(const char* label_id, const ImS32* xs, const ImS32* ys, int count, int offset, int stride);
template void PlotDigital<ImU32>(const char* label_id, const ImU32* xs, const ImU32* ys, int count, int offset, int stride);
template void PlotDigital<ImS64>(const char* label_id, const ImS64* xs, const ImS64* ys, int count, int offset, int stride);
template void PlotDigital<ImU64>(const char* label_id, const ImU64* xs, const ImU64* ys, int count, int offset, int stride);
template void PlotDigital<float>(const char* label_id, const float* xs, const float* ys, int count, int offset, int stride);
template void PlotDigital<double>(const char* label_id, const double* xs, const double* ys, int count, int offset, int stride);
// custom // custom
void PlotDigital(const char* label_id, ImPlotPoint (*getter_func)(void* data, int idx), void* data, int count, int offset) { void PlotDigitalG(const char* label_id, ImPlotPoint (*getter_func)(void* data, int idx), void* data, int count, int offset) {
GetterFuncPtrImPlotPoint getter(getter_func,data,count,offset); GetterFuncPtrImPlotPoint getter(getter_func,data,count,offset);
return PlotDigitalEx(label_id, getter); return PlotDigitalEx(label_id, getter);
} }
@ -1646,7 +1684,7 @@ void PlotDigital(const char* label_id, ImPlotPoint (*getter_func)(void* data, in
// PLOT RECTS // PLOT RECTS
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
template <typename Getter> template <typename Getter>
void PlotRectsEx(const char* label_id, Getter getter) { void PlotRectsEx(const char* label_id, const Getter& getter) {
if (BeginItem(label_id, ImPlotCol_Fill)) { if (BeginItem(label_id, ImPlotCol_Fill)) {
if (FitThisFrame()) { if (FitThisFrame()) {
for (int i = 0; i < getter.Count; ++i) { for (int i = 0; i < getter.Count; ++i) {
@ -1691,11 +1729,6 @@ void PlotRects(const char* label_id, ImPlotPoint (*getter_func)(void* data, int
// PLOT TEXT // PLOT TEXT
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
// float
void PlotText(const char* text, float x, float y, bool vertical, const ImVec2& pixel_offset) {
return PlotText(text, (double)x, (double)y, vertical, pixel_offset);
}
// double // double
void PlotText(const char* text, double x, double y, bool vertical, const ImVec2& pixel_offset) { void PlotText(const char* text, double x, double y, bool vertical, const ImVec2& pixel_offset) {
IM_ASSERT_USER_ERROR(GImPlot->CurrentPlot != NULL, "PlotText() needs to be called between BeginPlot() and EndPlot()!"); IM_ASSERT_USER_ERROR(GImPlot->CurrentPlot != NULL, "PlotText() needs to be called between BeginPlot() and EndPlot()!");