mirror of
https://github.com/gwm17/implot.git
synced 2024-11-26 20:28:50 -05:00
clean up primitive rendering work, test new offset/stride and improve demo
This commit is contained in:
parent
723122211e
commit
09ef003a81
177
implot.cpp
177
implot.cpp
|
@ -514,7 +514,6 @@ inline void FitPoint(const ImPlotPoint& p) {
|
||||||
|
|
||||||
inline void UpdateTransformCache() {
|
inline void UpdateTransformCache() {
|
||||||
// get pixels for transforms
|
// get pixels for transforms
|
||||||
|
|
||||||
for (int i = 0; i < MAX_Y_AXES; i++) {
|
for (int i = 0; i < MAX_Y_AXES; i++) {
|
||||||
gp.PixelRange[i] = ImRect(HasFlag(gp.CurrentPlot->XAxis.Flags, ImPlotAxisFlags_Invert) ? gp.BB_Plot.Max.x : gp.BB_Plot.Min.x,
|
gp.PixelRange[i] = ImRect(HasFlag(gp.CurrentPlot->XAxis.Flags, ImPlotAxisFlags_Invert) ? gp.BB_Plot.Max.x : gp.BB_Plot.Min.x,
|
||||||
HasFlag(gp.CurrentPlot->YAxis[i].Flags, ImPlotAxisFlags_Invert) ? gp.BB_Plot.Min.y : gp.BB_Plot.Max.y,
|
HasFlag(gp.CurrentPlot->YAxis[i].Flags, ImPlotAxisFlags_Invert) ? gp.BB_Plot.Min.y : gp.BB_Plot.Max.y,
|
||||||
|
@ -577,60 +576,58 @@ ImVec2 PlotToPixels(const ImPlotPoint& plt, int y_axis) {
|
||||||
// Transformer functors
|
// Transformer functors
|
||||||
|
|
||||||
struct TransformerLinLin {
|
struct TransformerLinLin {
|
||||||
TransformerLinLin(int y_axis_in) : y_axis(y_axis_in) {}
|
TransformerLinLin(int y_axis) : YAxis(y_axis) {}
|
||||||
|
|
||||||
inline ImVec2 operator()(const ImPlotPoint& plt) { return (*this)(plt.x, plt.y); }
|
inline ImVec2 operator()(const ImPlotPoint& plt) { return (*this)(plt.x, plt.y); }
|
||||||
inline ImVec2 operator()(double x, double y) {
|
inline ImVec2 operator()(double x, double y) {
|
||||||
return ImVec2( (float)(gp.PixelRange[y_axis].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[y_axis].Min.y + gp.My[y_axis] * (y - gp.CurrentPlot->YAxis[y_axis].Range.Min)) );
|
(float)(gp.PixelRange[YAxis].Min.y + gp.My[YAxis] * (y - gp.CurrentPlot->YAxis[YAxis].Range.Min)) );
|
||||||
}
|
}
|
||||||
|
|
||||||
int y_axis;
|
int YAxis;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct TransformerLogLin {
|
struct TransformerLogLin {
|
||||||
TransformerLogLin(int y_axis_in) : y_axis(y_axis_in) {}
|
TransformerLogLin(int y_axis) : YAxis(y_axis) {}
|
||||||
|
|
||||||
inline ImVec2 operator()(const ImPlotPoint& plt) { return (*this)(plt.x, plt.y); }
|
inline ImVec2 operator()(const ImPlotPoint& plt) { return (*this)(plt.x, plt.y); }
|
||||||
inline ImVec2 operator()(double x, double y) {
|
inline ImVec2 operator()(double x, double y) {
|
||||||
double t = ImLog10(x / gp.CurrentPlot->XAxis.Range.Min) / gp.LogDenX;
|
double t = ImLog10(x / gp.CurrentPlot->XAxis.Range.Min) / gp.LogDenX;
|
||||||
x = ImLerp(gp.CurrentPlot->XAxis.Range.Min, gp.CurrentPlot->XAxis.Range.Max, (float)t);
|
x = ImLerp(gp.CurrentPlot->XAxis.Range.Min, gp.CurrentPlot->XAxis.Range.Max, (float)t);
|
||||||
return ImVec2( (float)(gp.PixelRange[y_axis].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[y_axis].Min.y + gp.My[y_axis] * (y - gp.CurrentPlot->YAxis[y_axis].Range.Min)) );
|
(float)(gp.PixelRange[YAxis].Min.y + gp.My[YAxis] * (y - gp.CurrentPlot->YAxis[YAxis].Range.Min)) );
|
||||||
}
|
}
|
||||||
|
|
||||||
int y_axis;
|
int YAxis;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct TransformerLinLog {
|
struct TransformerLinLog {
|
||||||
TransformerLinLog(int y_axis_in) : y_axis(y_axis_in) {}
|
TransformerLinLog(int y_axis) : YAxis(y_axis) {}
|
||||||
|
|
||||||
inline ImVec2 operator()(const ImPlotPoint& plt) { return (*this)(plt.x, plt.y); }
|
inline ImVec2 operator()(const ImPlotPoint& plt) { return (*this)(plt.x, plt.y); }
|
||||||
inline ImVec2 operator()(double x, double y) {
|
inline ImVec2 operator()(double x, double y) {
|
||||||
double t = ImLog10(y / gp.CurrentPlot->YAxis[y_axis].Range.Min) / gp.LogDenY[y_axis];
|
double t = ImLog10(y / gp.CurrentPlot->YAxis[YAxis].Range.Min) / gp.LogDenY[YAxis];
|
||||||
y = ImLerp(gp.CurrentPlot->YAxis[y_axis].Range.Min, gp.CurrentPlot->YAxis[y_axis].Range.Max, (float)t);
|
y = ImLerp(gp.CurrentPlot->YAxis[YAxis].Range.Min, gp.CurrentPlot->YAxis[YAxis].Range.Max, (float)t);
|
||||||
return ImVec2( (float)(gp.PixelRange[y_axis].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[y_axis].Min.y + gp.My[y_axis] * (y - gp.CurrentPlot->YAxis[y_axis].Range.Min)) );
|
(float)(gp.PixelRange[YAxis].Min.y + gp.My[YAxis] * (y - gp.CurrentPlot->YAxis[YAxis].Range.Min)) );
|
||||||
}
|
}
|
||||||
int y_axis;
|
int YAxis;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct TransformerLogLog {
|
struct TransformerLogLog {
|
||||||
TransformerLogLog(int y_axis_in) : y_axis(y_axis_in) {
|
TransformerLogLog(int y_axis) : YAxis(y_axis) {}
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
inline ImVec2 operator()(const ImPlotPoint& plt) { return (*this)(plt.x, plt.y); }
|
inline ImVec2 operator()(const ImPlotPoint& plt) { return (*this)(plt.x, plt.y); }
|
||||||
inline ImVec2 operator()(double x, double y) {
|
inline ImVec2 operator()(double x, double y) {
|
||||||
double t = ImLog10(x / gp.CurrentPlot->XAxis.Range.Min) / gp.LogDenX;
|
double t = ImLog10(x / gp.CurrentPlot->XAxis.Range.Min) / gp.LogDenX;
|
||||||
x = ImLerp(gp.CurrentPlot->XAxis.Range.Min, gp.CurrentPlot->XAxis.Range.Max, (float)t);
|
x = ImLerp(gp.CurrentPlot->XAxis.Range.Min, gp.CurrentPlot->XAxis.Range.Max, (float)t);
|
||||||
t = ImLog10(y / gp.CurrentPlot->YAxis[y_axis].Range.Min) / gp.LogDenY[y_axis];
|
t = ImLog10(y / gp.CurrentPlot->YAxis[YAxis].Range.Min) / gp.LogDenY[YAxis];
|
||||||
y = ImLerp(gp.CurrentPlot->YAxis[y_axis].Range.Min, gp.CurrentPlot->YAxis[y_axis].Range.Max, (float)t);
|
y = ImLerp(gp.CurrentPlot->YAxis[YAxis].Range.Min, gp.CurrentPlot->YAxis[YAxis].Range.Max, (float)t);
|
||||||
return ImVec2( (float)(gp.PixelRange[y_axis].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[y_axis].Min.y + gp.My[y_axis] * (y - gp.CurrentPlot->YAxis[y_axis].Range.Min)) );
|
(float)(gp.PixelRange[YAxis].Min.y + gp.My[YAxis] * (y - gp.CurrentPlot->YAxis[YAxis].Range.Min)) );
|
||||||
}
|
}
|
||||||
|
|
||||||
int y_axis;
|
int YAxis;
|
||||||
};
|
};
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
|
@ -731,6 +728,19 @@ inline void AddDefaultTicks(const ImPlotRange& range, int nMajor, int nMinor, bo
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
inline void AddCustomTicks(const double* values, const char** labels, int n, ImVector<ImPlotTick>& ticks, ImGuiTextBuffer& buffer) {
|
||||||
|
for (int i = 0; i < n; ++i) {
|
||||||
|
ImPlotTick tick(values[i],false);
|
||||||
|
tick.TextOffset = buffer.size();
|
||||||
|
if (labels != NULL) {
|
||||||
|
buffer.append(labels[i], labels[i] + strlen(labels[i]) + 1);
|
||||||
|
tick.Size = ImGui::CalcTextSize(labels[i]);
|
||||||
|
tick.Labeled = true;
|
||||||
|
}
|
||||||
|
ticks.push_back(tick);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
inline void LabelTicks(ImVector<ImPlotTick> &ticks, bool scientific, ImGuiTextBuffer& buffer) {
|
inline void LabelTicks(ImVector<ImPlotTick> &ticks, bool scientific, ImGuiTextBuffer& buffer) {
|
||||||
char temp[32];
|
char temp[32];
|
||||||
for (int t = 0; t < ticks.Size; t++) {
|
for (int t = 0; t < ticks.Size; t++) {
|
||||||
|
@ -748,19 +758,6 @@ inline void LabelTicks(ImVector<ImPlotTick> &ticks, bool scientific, ImGuiTextBu
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
inline void AddCustomTicks(const double* values, const char** labels, int n, ImVector<ImPlotTick>& ticks, ImGuiTextBuffer& buffer) {
|
|
||||||
for (int i = 0; i < n; ++i) {
|
|
||||||
ImPlotTick tick(values[i],false);
|
|
||||||
tick.TextOffset = buffer.size();
|
|
||||||
if (labels != NULL) {
|
|
||||||
buffer.append(labels[i], labels[i] + strlen(labels[i]) + 1);
|
|
||||||
tick.Size = ImGui::CalcTextSize(labels[i]);
|
|
||||||
tick.Labeled = true;
|
|
||||||
}
|
|
||||||
ticks.push_back(tick);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
inline float MaxTickLabelWidth(ImVector<ImPlotTick>& ticks) {
|
inline float MaxTickLabelWidth(ImVector<ImPlotTick>& ticks) {
|
||||||
float w = 0;
|
float w = 0;
|
||||||
for (int i = 0; i < ticks.Size; ++i)
|
for (int i = 0; i < ticks.Size; ++i)
|
||||||
|
@ -2356,10 +2353,10 @@ inline int PosMod(int l, int r) {
|
||||||
return (l % r + r) % r;
|
return (l % r + r) % r;
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename T>
|
// template <typename T>
|
||||||
inline T StrideIndex(const T* data, int idx, int stride) {
|
// inline T StrideIndex(const T* data, int idx, int stride) {
|
||||||
return *(const T*)(const void*)((const unsigned char*)data + (size_t)idx * stride);
|
// return *(const T*)(const void*)((const unsigned char*)data + (size_t)idx * stride);
|
||||||
}
|
// }
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
inline T OffsetAndStride(const T* data, int idx, int count, int offset, int stride) {
|
inline T OffsetAndStride(const T* data, int idx, int count, int offset, int stride) {
|
||||||
|
@ -2641,21 +2638,21 @@ void PlotScatter(const char* label_id, ImPlotPoint (*getter)(void* data, int idx
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
struct GetterBarV {
|
struct GetterBarV {
|
||||||
const T* Ys; T XShift; int Stride;
|
const T* Ys; T XShift; int Count; int Offset; int Stride;
|
||||||
GetterBarV(const T* ys, T xshift, int stride) { Ys = ys; XShift = xshift; Stride = stride; }
|
GetterBarV(const T* ys, T xshift, int count, int offset, int stride) { Ys = ys; XShift = xshift; Count = count; Offset = offset; Stride = stride; }
|
||||||
inline ImPlotPoint operator()(int idx) { return ImPlotPoint((T)idx + XShift, StrideIndex(Ys, idx, Stride)); }
|
inline ImPlotPoint operator()(int idx) { return ImPlotPoint((T)idx + XShift, OffsetAndStride(Ys, idx, Count, Offset, Stride)); }
|
||||||
};
|
};
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
struct GetterBarH {
|
struct GetterBarH {
|
||||||
const T* Xs; T YShift; int Stride;
|
const T* Xs; T YShift; int Count; int Offset; int Stride;
|
||||||
GetterBarH(const T* xs, T yshift, int stride) { Xs = xs; YShift = yshift; Stride = stride; }
|
GetterBarH(const T* xs, T yshift, int count, int offset, int stride) { Xs = xs; YShift = yshift; Count = count; Offset = offset; Stride = stride; }
|
||||||
inline ImPlotPoint operator()(int idx) { return ImPlotPoint(StrideIndex(Xs, idx, Stride), (T)idx + YShift); }
|
inline ImPlotPoint operator()(int idx) { return ImPlotPoint(OffsetAndStride(Xs, idx, Count, Offset, Stride), (T)idx + YShift); }
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
template <typename Getter, typename TWidth>
|
template <typename Getter, typename TWidth>
|
||||||
void PlotBarsEx(const char* label_id, Getter getter, int count, TWidth width, int offset) {
|
void PlotBarsEx(const char* label_id, Getter getter, TWidth width) {
|
||||||
|
|
||||||
IM_ASSERT_USER_ERROR(gp.CurrentPlot != NULL, "PlotBars() needs to be called between BeginPlot() and EndPlot()!");
|
IM_ASSERT_USER_ERROR(gp.CurrentPlot != NULL, "PlotBars() needs to be called between BeginPlot() and EndPlot()!");
|
||||||
|
|
||||||
|
@ -2683,17 +2680,15 @@ void PlotBarsEx(const char* label_id, Getter getter, int count, TWidth width, in
|
||||||
|
|
||||||
// find data extents
|
// find data extents
|
||||||
if (gp.FitThisFrame) {
|
if (gp.FitThisFrame) {
|
||||||
for (int i = 0; i < count; ++i) {
|
for (int i = 0; i < getter.Count; ++i) {
|
||||||
ImPlotPoint p = getter(i);
|
ImPlotPoint p = getter(i);
|
||||||
FitPoint(ImPlotPoint(p.x - half_width, p.y));
|
FitPoint(ImPlotPoint(p.x - half_width, p.y));
|
||||||
FitPoint(ImPlotPoint(p.x + half_width, 0));
|
FitPoint(ImPlotPoint(p.x + half_width, 0));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
int idx = offset;
|
for (int i = 0; i < getter.Count; ++i) {
|
||||||
for (int i = 0; i < count; ++i) {
|
ImPlotPoint p = getter(i);
|
||||||
ImPlotPoint p = getter(idx);
|
|
||||||
idx = (idx + 1) % count;
|
|
||||||
if (p.y == 0)
|
if (p.y == 0)
|
||||||
continue;
|
continue;
|
||||||
ImVec2 a = PlotToPixels(p.x - half_width, p.y);
|
ImVec2 a = PlotToPixels(p.x - half_width, p.y);
|
||||||
|
@ -2710,26 +2705,26 @@ void PlotBarsEx(const char* label_id, Getter getter, int count, TWidth width, in
|
||||||
// float
|
// float
|
||||||
|
|
||||||
void PlotBars(const char* label_id, const float* values, int count, float width, float shift, int offset, int stride) {
|
void PlotBars(const char* label_id, const float* values, int count, float width, float shift, int offset, int stride) {
|
||||||
GetterBarV<float> getter(values,shift,stride);
|
GetterBarV<float> getter(values,shift,count,offset,stride);
|
||||||
PlotBarsEx(label_id, getter, count, width, offset);
|
PlotBarsEx(label_id, getter, width);
|
||||||
}
|
}
|
||||||
|
|
||||||
void PlotBars(const char* label_id, const float* xs, const float* ys, int count, float width, int offset, int stride) {
|
void PlotBars(const char* label_id, const float* xs, const float* ys, int count, float width, int offset, int stride) {
|
||||||
GetterXsYs<float> getter(xs,ys,count,offset,stride);
|
GetterXsYs<float> getter(xs,ys,count,offset,stride);
|
||||||
PlotBarsEx(label_id, getter, count, width, offset);
|
PlotBarsEx(label_id, getter, width);
|
||||||
}
|
}
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
// double
|
// double
|
||||||
|
|
||||||
void PlotBars(const char* label_id, const double* values, int count, double width, double shift, int offset, int stride) {
|
void PlotBars(const char* label_id, const double* values, int count, double width, double shift, int offset, int stride) {
|
||||||
GetterBarV<double> getter(values,shift,stride);
|
GetterBarV<double> getter(values,shift,count,offset,stride);
|
||||||
PlotBarsEx(label_id, getter, count, width, offset);
|
PlotBarsEx(label_id, getter, width);
|
||||||
}
|
}
|
||||||
|
|
||||||
void PlotBars(const char* label_id, const double* xs, const double* ys, int count, double width, int offset, int stride) {
|
void PlotBars(const char* label_id, const double* xs, const double* ys, int count, double width, int offset, int stride) {
|
||||||
GetterXsYs<double> getter(xs,ys,count,offset,stride);
|
GetterXsYs<double> getter(xs,ys,count,offset,stride);
|
||||||
PlotBarsEx(label_id, getter, count, width, offset);
|
PlotBarsEx(label_id, getter, width);
|
||||||
}
|
}
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
|
@ -2737,7 +2732,7 @@ void PlotBars(const char* label_id, const double* xs, const double* ys, int coun
|
||||||
|
|
||||||
void PlotBars(const char* label_id, ImPlotPoint (*getter_func)(void* data, int idx), void* data, int count, double width, int offset) {
|
void PlotBars(const char* label_id, ImPlotPoint (*getter_func)(void* data, int idx), void* data, int count, double width, int offset) {
|
||||||
GetterFuncPtrImPlotPoint getter(getter_func, data, count, offset);
|
GetterFuncPtrImPlotPoint getter(getter_func, data, count, offset);
|
||||||
PlotBarsEx(label_id, getter, count, width, offset);
|
PlotBarsEx(label_id, getter, width);
|
||||||
}
|
}
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
|
@ -2747,7 +2742,7 @@ void PlotBars(const char* label_id, ImPlotPoint (*getter_func)(void* data, int i
|
||||||
// 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, int count, THeight height, int offset) {
|
void PlotBarsHEx(const char* label_id, Getter getter, THeight height) {
|
||||||
|
|
||||||
IM_ASSERT_USER_ERROR(gp.CurrentPlot != NULL, "PlotBarsH() needs to be called between BeginPlot() and EndPlot()!");
|
IM_ASSERT_USER_ERROR(gp.CurrentPlot != NULL, "PlotBarsH() needs to be called between BeginPlot() and EndPlot()!");
|
||||||
|
|
||||||
|
@ -2775,17 +2770,15 @@ void PlotBarsHEx(const char* label_id, Getter getter, int count, THeight height,
|
||||||
|
|
||||||
// find data extents
|
// find data extents
|
||||||
if (gp.FitThisFrame) {
|
if (gp.FitThisFrame) {
|
||||||
for (int i = 0; i < count; ++i) {
|
for (int i = 0; i < getter.Count; ++i) {
|
||||||
ImPlotPoint p = getter(i);
|
ImPlotPoint p = getter(i);
|
||||||
FitPoint(ImPlotPoint(0, p.y - half_height));
|
FitPoint(ImPlotPoint(0, p.y - half_height));
|
||||||
FitPoint(ImPlotPoint(p.x, p.y + half_height));
|
FitPoint(ImPlotPoint(p.x, p.y + half_height));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
int idx = offset;
|
for (int i = 0; i < getter.Count; ++i) {
|
||||||
for (int i = 0; i < count; ++i) {
|
ImPlotPoint p = getter(i);
|
||||||
ImPlotPoint p = getter(idx);
|
|
||||||
idx = (idx + 1) % count;
|
|
||||||
if (p.x == 0)
|
if (p.x == 0)
|
||||||
continue;
|
continue;
|
||||||
ImVec2 a = PlotToPixels(0, p.y - half_height);
|
ImVec2 a = PlotToPixels(0, p.y - half_height);
|
||||||
|
@ -2802,26 +2795,26 @@ void PlotBarsHEx(const char* label_id, Getter getter, int count, THeight height,
|
||||||
// float
|
// float
|
||||||
|
|
||||||
void PlotBarsH(const char* label_id, const float* values, int count, float height, float shift, int offset, int stride) {
|
void PlotBarsH(const char* label_id, const float* values, int count, float height, float shift, int offset, int stride) {
|
||||||
GetterBarH<float> getter(values,shift,stride);
|
GetterBarH<float> getter(values,shift,count,offset,stride);
|
||||||
PlotBarsHEx(label_id, getter, count, height, offset);
|
PlotBarsHEx(label_id, getter, height);
|
||||||
}
|
}
|
||||||
|
|
||||||
void PlotBarsH(const char* label_id, const float* xs, const float* ys, int count, float height, int offset, int stride) {
|
void PlotBarsH(const char* label_id, const float* xs, const float* ys, int count, float height, int offset, int stride) {
|
||||||
GetterXsYs<float> getter(xs,ys,count,offset,stride);
|
GetterXsYs<float> getter(xs,ys,count,offset,stride);
|
||||||
PlotBarsHEx(label_id, getter, count, height, offset);
|
PlotBarsHEx(label_id, getter, height);
|
||||||
}
|
}
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
// double
|
// double
|
||||||
|
|
||||||
void PlotBarsH(const char* label_id, const double* values, int count, double height, double shift, int offset, int stride) {
|
void PlotBarsH(const char* label_id, const double* values, int count, double height, double shift, int offset, int stride) {
|
||||||
GetterBarH<double> getter(values,shift,stride);
|
GetterBarH<double> getter(values,shift,count,offset,stride);
|
||||||
PlotBarsHEx(label_id, getter, count, height, offset);
|
PlotBarsHEx(label_id, getter, height);
|
||||||
}
|
}
|
||||||
|
|
||||||
void PlotBarsH(const char* label_id, const double* xs, const double* ys, int count, double height, int offset, int stride) {
|
void PlotBarsH(const char* label_id, const double* xs, const double* ys, int count, double height, int offset, int stride) {
|
||||||
GetterXsYs<double> getter(xs,ys,count,offset,stride);
|
GetterXsYs<double> getter(xs,ys,count,offset,stride);
|
||||||
PlotBarsHEx(label_id, getter, count, height, offset);
|
PlotBarsHEx(label_id, getter, height);
|
||||||
}
|
}
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
|
@ -2829,7 +2822,7 @@ void PlotBarsH(const char* label_id, const double* xs, const double* ys, int cou
|
||||||
|
|
||||||
void PlotBarsH(const char* label_id, ImPlotPoint (*getter_func)(void* data, int idx), void* data, int count, double height, int offset) {
|
void PlotBarsH(const char* label_id, ImPlotPoint (*getter_func)(void* data, int idx), void* data, int count, double height, int offset) {
|
||||||
GetterFuncPtrImPlotPoint getter(getter_func, data, count, offset);
|
GetterFuncPtrImPlotPoint getter(getter_func, data, count, offset);
|
||||||
PlotBarsHEx(label_id, getter, count, height, offset);
|
PlotBarsHEx(label_id, getter, height);
|
||||||
}
|
}
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
|
@ -2845,20 +2838,20 @@ struct ImPlotPointError {
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
struct GetterError {
|
struct GetterError {
|
||||||
const T* Xs; const T* Ys; const T* Neg; const T* Pos; int Stride;
|
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 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; Stride = stride;
|
Xs = xs; Ys = ys; Neg = neg; Pos = pos; Count = count; Offset = offset; Stride = stride;
|
||||||
}
|
}
|
||||||
ImPlotPointError operator()(int idx) {
|
ImPlotPointError operator()(int idx) {
|
||||||
return ImPlotPointError(StrideIndex(Xs, idx, Stride),
|
return ImPlotPointError(OffsetAndStride(Xs, idx, Count, Offset, Stride),
|
||||||
StrideIndex(Ys, idx, Stride),
|
OffsetAndStride(Ys, idx, Count, Offset, Stride),
|
||||||
StrideIndex(Neg, idx, Stride),
|
OffsetAndStride(Neg, idx, Count, Offset, Stride),
|
||||||
StrideIndex(Pos, idx, Stride));
|
OffsetAndStride(Pos, idx, Count, Offset, Stride));
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
template <typename Getter>
|
template <typename Getter>
|
||||||
void PlotErrorBarsEx(const char* label_id, Getter getter, int count, int offset) {
|
void PlotErrorBarsEx(const char* label_id, Getter getter) {
|
||||||
IM_ASSERT_USER_ERROR(gp.CurrentPlot != NULL, "PlotErrorBars() needs to be called between BeginPlot() and EndPlot()!");
|
IM_ASSERT_USER_ERROR(gp.CurrentPlot != NULL, "PlotErrorBars() needs to be called between BeginPlot() and EndPlot()!");
|
||||||
|
|
||||||
ImGuiID id = ImGui::GetID(label_id);
|
ImGuiID id = ImGui::GetID(label_id);
|
||||||
|
@ -2877,17 +2870,15 @@ void PlotErrorBarsEx(const char* label_id, Getter getter, int count, int offset)
|
||||||
|
|
||||||
// find data extents
|
// find data extents
|
||||||
if (gp.FitThisFrame) {
|
if (gp.FitThisFrame) {
|
||||||
for (int i = 0; i < count; ++i) {
|
for (int i = 0; i < getter.Count; ++i) {
|
||||||
ImPlotPointError e = getter(i);
|
ImPlotPointError e = getter(i);
|
||||||
FitPoint(ImPlotPoint(e.x , e.y - e.neg));
|
FitPoint(ImPlotPoint(e.x , e.y - e.neg));
|
||||||
FitPoint(ImPlotPoint(e.x , e.y + e.pos ));
|
FitPoint(ImPlotPoint(e.x , e.y + e.pos ));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
int idx = offset;
|
for (int i = 0; i < getter.Count; ++i) {
|
||||||
for (int i = 0; i < count; ++i) {
|
ImPlotPointError e = getter(i);
|
||||||
ImPlotPointError e = getter(idx);
|
|
||||||
idx = (idx + 1) % count;
|
|
||||||
ImVec2 p1 = PlotToPixels(e.x, e.y - e.neg);
|
ImVec2 p1 = PlotToPixels(e.x, e.y - e.neg);
|
||||||
ImVec2 p2 = PlotToPixels(e.x, e.y + e.pos);
|
ImVec2 p2 = PlotToPixels(e.x, e.y + e.pos);
|
||||||
DrawList.AddLine(p1,p2,col, gp.Style.ErrorBarWeight);
|
DrawList.AddLine(p1,p2,col, gp.Style.ErrorBarWeight);
|
||||||
|
@ -2903,26 +2894,26 @@ void PlotErrorBarsEx(const char* label_id, Getter getter, int count, int offset)
|
||||||
// float
|
// float
|
||||||
|
|
||||||
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 float* xs, const float* ys, const float* err, int count, int offset, int stride) {
|
||||||
GetterError<float> getter(xs, ys, err, err, stride);
|
GetterError<float> getter(xs, ys, err, err, count, offset, stride);
|
||||||
PlotErrorBarsEx(label_id, getter, count, offset);
|
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) {
|
void PlotErrorBars(const char* label_id, const float* xs, const float* ys, const float* neg, const float* pos, int count, int offset, int stride) {
|
||||||
GetterError<float> getter(xs, ys, neg, pos, stride);
|
GetterError<float> getter(xs, ys, neg, pos, count, offset, stride);
|
||||||
PlotErrorBarsEx(label_id, getter, count, offset);
|
PlotErrorBarsEx(label_id, getter);
|
||||||
}
|
}
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
// double
|
// double
|
||||||
|
|
||||||
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 double* xs, const double* ys, const double* err, int count, int offset, int stride) {
|
||||||
GetterError<double> getter(xs, ys, err, err, stride);
|
GetterError<double> getter(xs, ys, err, err, count, offset, stride);
|
||||||
PlotErrorBarsEx(label_id, getter, count, offset);
|
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) {
|
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, stride);
|
GetterError<double> getter(xs, ys, neg, pos, count, offset, stride);
|
||||||
PlotErrorBarsEx(label_id, getter, count, offset);
|
PlotErrorBarsEx(label_id, getter);
|
||||||
}
|
}
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
|
|
|
@ -160,6 +160,12 @@ void ShowDemoWindow(bool* p_open) {
|
||||||
ImGui::Unindent();
|
ImGui::Unindent();
|
||||||
ImGui::BulletText("Double right click to open the plot context menu.");
|
ImGui::BulletText("Double right click to open the plot context menu.");
|
||||||
ImGui::BulletText("Click legend label icons to show/hide plot items.");
|
ImGui::BulletText("Click legend label icons to show/hide plot items.");
|
||||||
|
ImGui::BulletText("IMPORTANT: By default, anti-aliased lines are turned OFF.");
|
||||||
|
ImGui::Indent();
|
||||||
|
ImGui::BulletText("Software AA can be enabled per plot with ImPlotFlags_AntiAliased.");
|
||||||
|
ImGui::BulletText("AA for demo plots can be enabled from the plot's context menu.");
|
||||||
|
ImGui::BulletText("If allowable, you are better off using hardware AA (e.g. MSAA).");
|
||||||
|
ImGui::Unindent();
|
||||||
#ifdef IMPLOT_DEMO_USE_DOUBLE
|
#ifdef IMPLOT_DEMO_USE_DOUBLE
|
||||||
ImGui::BulletText("The demo data precision is: double");
|
ImGui::BulletText("The demo data precision is: double");
|
||||||
#else
|
#else
|
||||||
|
@ -831,18 +837,37 @@ void ShowDemoWindow(bool* p_open) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
//-------------------------------------------------------------------------
|
//-------------------------------------------------------------------------
|
||||||
if (ImGui::CollapsingHeader("Offset Data")) {
|
if (ImGui::CollapsingHeader("Offset and Stride")) {
|
||||||
t_float xs[50], ys[50];
|
static const int k_circles = 11;
|
||||||
for (int i = 0; i < 50; ++i) {
|
static const int k_points_per = 50;
|
||||||
xs[i] = 0.5f + 0.4f * Cos(i/50.f * 6.28f);
|
static const int k_size = 2 * k_points_per * k_circles;
|
||||||
ys[i] = 0.5f + 0.4f * Sin(i/50.f * 6.28f);
|
static t_float interleaved_data[k_size];
|
||||||
|
for (int p = 0; p < k_points_per; ++p) {
|
||||||
|
for (int c = 0; c < k_circles; ++c) {
|
||||||
|
t_float r = (t_float)c / (k_circles - 1) * 0.2f + 0.2f;
|
||||||
|
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 + 1] = 0.5f + r * Sin((t_float)p/k_points_per * 6.28f);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
static int offset = 0;
|
static int offset = 0;
|
||||||
ImGui::SliderInt("Offset", &offset, -100, 100);
|
ImGui::BulletText("Offsetting is useful for realtime plots (see above) and circular buffers.");
|
||||||
if (ImPlot::BeginPlot("##offset")) {
|
ImGui::BulletText("Striding is useful for interleaved data (e.g. audio) or plotting structs.");
|
||||||
ImPlot::PlotLine("circle", xs, ys, 50, offset);
|
ImGui::BulletText("Here, all circle data is stored in a single interleaved buffer:");
|
||||||
|
ImGui::BulletText("[c0.x0 c0.y0 ... cn.x0 cn.y0 c0.x1 c0.y1 ... cn.x1 cn.y1 ... cn.xm cn.ym]");
|
||||||
|
ImGui::BulletText("The offset value indicates which circle point index is considered the first.");
|
||||||
|
ImGui::BulletText("Offsets can be negative and/or larger than the actual data count.");
|
||||||
|
ImGui::SliderInt("Offset", &offset, -2*k_points_per, 2*k_points_per);
|
||||||
|
if (ImPlot::BeginPlot("##strideoffset")) {
|
||||||
|
ImPlot::SetColormap(ImPlotColormap_Jet);
|
||||||
|
char buff[16];
|
||||||
|
for (int c = 0; c < k_circles; ++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::EndPlot();
|
ImPlot::EndPlot();
|
||||||
|
ImPlot::SetColormap(ImPlotColormap_Default);
|
||||||
}
|
}
|
||||||
|
// offset++; uncomment for animation!
|
||||||
}
|
}
|
||||||
//-------------------------------------------------------------------------
|
//-------------------------------------------------------------------------
|
||||||
if (ImGui::CollapsingHeader("Custom Ticks")) {
|
if (ImGui::CollapsingHeader("Custom Ticks")) {
|
||||||
|
|
Loading…
Reference in New Issue
Block a user