diff --git a/implot.cpp b/implot.cpp index 5567c1a..80f85ef 100644 --- a/implot.cpp +++ b/implot.cpp @@ -2916,6 +2916,100 @@ void PlotErrorBars(const char* label_id, const double* xs, const double* ys, con PlotErrorBarsEx(label_id, getter); } +//----------------------------------------------------------------------------- +// PLOT ERROR BARS H +//----------------------------------------------------------------------------- + +struct ImPlotPointErrorH { + ImPlotPointErrorH(double _x, double _y, double _neg_v, double _pos_v, double _neg_h, double _pos_h) { + x = _x; y = _y; neg_v = _neg_v; pos_v = _pos_v; neg_h = _neg_h; pos_h = _pos_h; + } + double x, y, neg_v, pos_v, neg_h, pos_h; +}; + +template +struct GetterErrorH { + const T* Xs; const T* Ys; const T* Neg_v; const T* Pos_v; const T* Neg_h; const T* Pos_h; int Count; int Offset; int Stride; + GetterErrorH(const T* xs, const T* ys, const T* neg_v, const T* pos_v, const T* neg_h, const T* pos_h, int count, int offset, int stride) { + Xs = xs; Ys = ys; Neg_v = neg_v; Pos_v = pos_v; Neg_h = neg_h; Pos_h = pos_h; Count = count; Offset = offset; Stride = stride; + } + ImPlotPointErrorH operator()(int idx) { + return ImPlotPointErrorH(OffsetAndStride(Xs, idx, Count, Offset, Stride), + OffsetAndStride(Ys, idx, Count, Offset, Stride), + OffsetAndStride(Neg_v, idx, Count, Offset, Stride), + OffsetAndStride(Pos_v, idx, Count, Offset, Stride), + OffsetAndStride(Neg_h, idx, Count, Offset, Stride), + OffsetAndStride(Pos_h, idx, Count, Offset, Stride)); + } +}; + +template +void PlotErrorBarsHEx(const char* label_id, Getter getter) { + IM_ASSERT_USER_ERROR(gp.CurrentPlot != NULL, "PlotErrorBars() needs to be called between BeginPlot() and EndPlot()!"); + + ImGuiID id = ImGui::GetID(label_id); + ImPlotItem* item = gp.CurrentPlot->Items.GetByKey(id); + if (item != NULL && item->Show == false) + return; + + ImDrawList& DrawList = *ImGui::GetWindowDrawList(); + + PushPlotClipRect(); + + const ImU32 col = gp.Style.Colors[ImPlotCol_ErrorBar].w == -1 ? ImGui::GetColorU32(ImGuiCol_Text) : ImGui::GetColorU32(gp.Style.Colors[ImPlotCol_ErrorBar]); + const bool rend_whisker = gp.Style.ErrorBarSize > 0; + + const float half_whisker = gp.Style.ErrorBarSize * 0.5f; + + // find data extents + if (gp.FitThisFrame) { + for (int i = 0; i < getter.Count; ++i) { + ImPlotPointErrorH e = getter(i); + FitPoint(ImPlotPoint(e.x, e.y - e.neg_v)); + FitPoint(ImPlotPoint(e.x, e.y + e.pos_v)); + } + } + + for (int i = 0; i < getter.Count; ++i) { + ImPlotPointErrorH e = getter(i); + ImVec2 p1 = PlotToPixels(e.x, e.y - e.neg_v); + ImVec2 p2 = PlotToPixels(e.x, e.y + e.pos_v); + DrawList.AddLine(p1, p2, col, gp.Style.ErrorBarWeight); + if (rend_whisker) { + DrawList.AddLine(p1 - ImVec2(half_whisker, 0), p1 + ImVec2(half_whisker, 0), col, gp.Style.ErrorBarWeight); + DrawList.AddLine(p2 - ImVec2(half_whisker, 0), p2 + ImVec2(half_whisker, 0), col, gp.Style.ErrorBarWeight); + } + } + PopPlotClipRect(); +} + +//----------------------------------------------------------------------------- +// float + +void PlotErrorBarsH(const char* label_id, const float* xs, const float* ys, const float* err_v, const float* err_h, int count, int offset, int stride) { + GetterErrorH getter(xs, ys, err_v, err_v, err_h, err_h, count, offset, stride); + PlotErrorBarsHEx(label_id, getter); +} + +void PlotErrorBarsH(const char* label_id, const float* xs, const float* ys, const float* neg_v, const float* pos_v, const float* neg_h, const float* pos_h, int count, int offset, int stride) { + GetterErrorH getter(xs, ys, neg_v, pos_v, neg_h, pos_h, count, offset, stride); + PlotErrorBarsHEx(label_id, getter); +} + +//----------------------------------------------------------------------------- +// double + +void PlotErrorBarsH(const char* label_id, const double* xs, const double* ys, const double* err_v, const double* err_h, int count, int offset, int stride) { + GetterErrorH getter(xs, ys, err_v, err_v, err_h, err_h, count, offset, stride); + PlotErrorBarsHEx(label_id, getter); +} + +void PlotErrorBarsH(const char* label_id, const double* xs, const double* ys, const double* neg_v, const double* pos_v, const double* neg_h, const double* pos_h, int count, int offset, int stride) { + GetterErrorH getter(xs, ys, neg_v, pos_v, neg_h, pos_h, count, offset, stride); + PlotErrorBarsHEx(label_id, getter); +} + + //----------------------------------------------------------------------------- // PLOT PIE CHART //----------------------------------------------------------------------------- diff --git a/implot_demo.cpp b/implot_demo.cpp index 4256b5e..b88a4e0 100644 --- a/implot_demo.cpp +++ b/implot_demo.cpp @@ -281,6 +281,7 @@ void ShowDemoWindow(bool* p_open) { if (ImGui::CollapsingHeader("Error Bars")) { t_float xs[5] = {1,2,3,4,5}; t_float lin[5] = {8,8,9,7,8}; + t_float lin2[5] = { 6,7,6,9,6}; t_float bar[5] = {1,2,5,3,4}; t_float err1[5] = {0.2f, 0.4f, 0.2f, 0.6f, 0.4f}; t_float err2[5] = {0.4f, 0.2f, 0.4f, 0.8f, 0.6f}; @@ -295,6 +296,13 @@ void ShowDemoWindow(bool* p_open) { ImPlot::PlotLine("Line", xs, lin, 5); ImPlot::PopStyleVar(2); ImPlot::PopStyleColor(); + ImPlot::PushStyleVar(ImPlotStyleVar_Marker, ImPlotMarker_Square); + ImPlot::PushStyleVar(ImPlotStyleVar_MarkerSize, 3); + ImPlot::PushStyleColor(ImPlotCol_ErrorBar, ImVec4(0, 1, 0, 1)); + ImPlot::PlotErrorBarsH("Line##ErrorBarH", xs, lin2, err1, err2, 5); + ImPlot::PlotLine("Line##ErrorBarH", xs, lin2, 5); + ImPlot::PopStyleVar(2); + ImPlot::PopStyleColor(); ImPlot::EndPlot(); } }