Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add PlotShadedClip, fills region only if the second line is higher than the first one. #161

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions implot.h
Original file line number Diff line number Diff line change
Expand Up @@ -871,6 +871,12 @@ IMPLOT_TMP void PlotShaded(const char* label_id, const T* xs, const T* ys, int c
IMPLOT_TMP void PlotShaded(const char* label_id, const T* xs, const T* ys1, const T* ys2, int count, ImPlotShadedFlags flags=0, int offset=0, int stride=sizeof(T));
IMPLOT_API void PlotShadedG(const char* label_id, ImPlotGetter getter1, void* data1, ImPlotGetter getter2, void* data2, int count, ImPlotShadedFlags flags=0);

// Plots a shaded (filled) region between two lines, only if the second line is higher than the first one
IMPLOT_TMP void PlotShadedClip(const char* label_id, const T* values, int count, double yref=0, double xscale=1, double xstart=0, ImPlotShadedFlags flags=0, int offset=0, int stride=sizeof(T));
IMPLOT_TMP void PlotShadedClip(const char* label_id, const T* xs, const T* ys, int count, double yref=0, ImPlotShadedFlags flags=0, int offset=0, int stride=sizeof(T));
IMPLOT_TMP void PlotShadedClip(const char* label_id, const T* xs, const T* ys1, const T* ys2, int count, ImPlotShadedFlags flags=0, int offset=0, int stride=sizeof(T));
IMPLOT_API void PlotShadedClipG(const char* label_id, ImPlotGetter getter1, void* data1, ImPlotGetter getter2, void* data2, int count, ImPlotShadedFlags flags=0);

// Plots a bar graph. Vertical by default. #bar_size and #shift are in plot units.
IMPLOT_TMP void PlotBars(const char* label_id, const T* values, int count, double bar_size=0.67, double shift=0, ImPlotBarsFlags flags=0, int offset=0, int stride=sizeof(T));
IMPLOT_TMP void PlotBars(const char* label_id, const T* xs, const T* ys, int count, double bar_size, ImPlotBarsFlags flags=0, int offset=0, int stride=sizeof(T));
Expand Down
13 changes: 13 additions & 0 deletions implot_demo.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -384,6 +384,19 @@ void Demo_ShadedPlots() {
ImPlot::PopStyleVar();
ImPlot::EndPlot();
}
if (ImPlot::BeginPlot("Shaded Clip Plots")) {
ImPlot::PushStyleVar(ImPlotStyleVar_FillAlpha, alpha);
ImPlot::SetNextLineStyle(ImVec4(0.0f,1.0f,0.0f,0.25f));
ImPlot::SetNextFillStyle(ImVec4(0.0f,1.0f,0.0f,0.25f));
ImPlot::PlotLine("Overlapping",xs,ys4,1001);
ImPlot::PlotShadedClip("Overlapping",xs,ys3,ys4,1001);
ImPlot::SetNextLineStyle(ImVec4(1.0f,0.0f,0.0f,0.25f));
ImPlot::SetNextFillStyle(ImVec4(1.0f,0.0f,0.0f,0.25f));
ImPlot::PlotLine("Overlapping",xs,ys3,1001);
ImPlot::PlotShadedClip("Overlapping",xs,ys4,ys3,1001);
ImPlot::PopStyleVar();
ImPlot::EndPlot();
}
}

//-----------------------------------------------------------------------------
Expand Down
108 changes: 108 additions & 0 deletions implot_items.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1351,6 +1351,53 @@ struct RendererRectC : RendererBase {
mutable ImVec2 UV;
};

template <class _Getter1, class _Getter2>
struct RendererShadedClip : RendererShaded<_Getter1, _Getter2> {
RendererShadedClip(const _Getter1& getter1, const _Getter2& getter2, ImU32 col) :
RendererShaded<_Getter1, _Getter2>(getter1, getter2, col)
{}

IMPLOT_INLINE bool Render(ImDrawList& draw_list, const ImRect& cull_rect, int prim) const {
ImVec2 P21 = this->Transformer(this->Getter1(prim+1));
ImVec2 P22 = this->Transformer(this->Getter2(prim+1));
ImRect rect(ImMin(ImMin(ImMin(this->P11,this->P12),P21),P22), ImMax(ImMax(ImMax(this->P11,this->P12),P21),P22));
if (!cull_rect.Overlaps(rect)) {
this->P11 = P21;
this->P12 = P22;
return false;
}
const int intersect = (this->P11.y > this->P12.y && P22.y > P21.y) || (this->P12.y > this->P11.y && P21.y > P22.y);
ImVec2 intersection = Intersection(this->P11,P21,this->P12,P22);
draw_list._VtxWritePtr[0].pos = this->P11;
draw_list._VtxWritePtr[0].uv = this->UV;
draw_list._VtxWritePtr[0].col = this->Col;
draw_list._VtxWritePtr[1].pos = P21;
draw_list._VtxWritePtr[1].uv = this->UV;
draw_list._VtxWritePtr[1].col = this->Col;
draw_list._VtxWritePtr[2].pos = intersection;
draw_list._VtxWritePtr[2].uv = this->UV;
draw_list._VtxWritePtr[2].col = this->Col;
draw_list._VtxWritePtr[3].pos = this->P12;
draw_list._VtxWritePtr[3].uv = this->UV;
draw_list._VtxWritePtr[3].col = this->Col;
draw_list._VtxWritePtr[4].pos = P22;
draw_list._VtxWritePtr[4].uv = this->UV;
draw_list._VtxWritePtr[4].col = this->Col;
draw_list._VtxWritePtr += 5;
draw_list._IdxWritePtr[0] = (ImDrawIdx)(draw_list._VtxCurrentIdx);
draw_list._IdxWritePtr[1] = (ImDrawIdx)(draw_list._VtxCurrentIdx + 1 + intersect);
draw_list._IdxWritePtr[2] = (ImDrawIdx)(draw_list._VtxCurrentIdx + 0 + 3 * (this->P11.y >= this->P12.y) );
draw_list._IdxWritePtr[3] = (ImDrawIdx)(draw_list._VtxCurrentIdx + 1);
draw_list._IdxWritePtr[4] = (ImDrawIdx)(draw_list._VtxCurrentIdx + 3 - intersect);
draw_list._IdxWritePtr[5] = (ImDrawIdx)(draw_list._VtxCurrentIdx + 1 + 3 * (P21.y >= P22.y) );
draw_list._IdxWritePtr += 6;
draw_list._VtxCurrentIdx += 5;
this->P11 = P21;
this->P12 = P22;
return true;
}
};

//-----------------------------------------------------------------------------
// [SECTION] RenderPrimitives
//-----------------------------------------------------------------------------
Expand Down Expand Up @@ -1798,6 +1845,67 @@ void PlotShadedG(const char* label_id, ImPlotGetter getter_func1, void* data1, I
PlotShadedEx(label_id, getter1, getter2, flags);
}

//-----------------------------------------------------------------------------
// [SECTION] PlotShadedClip
//-----------------------------------------------------------------------------

// NEW
template <typename Getter1, typename Getter2>
void PlotShadedClipEx(const char* label_id, const Getter1& getter1, const Getter2& getter2, ImPlotShadedFlags flags) {
if (BeginItemEx(label_id, Fitter2<Getter1,Getter2>(getter1,getter2), flags, ImPlotCol_Fill)) {
const ImPlotNextItemData& s = GetItemData();
if (s.RenderFill) {
const ImU32 col = ImGui::GetColorU32(s.Colors[ImPlotCol_Fill]);
RenderPrimitives2<RendererShadedClip>(getter1,getter2,col);
}
EndItem();
}
}

template <typename T>
void PlotShadedClip(const char* label_id, const T* values, int count, double y_ref, double xscale, double x0, ImPlotShadedFlags flags, int offset, int stride) {
if (!(y_ref > -DBL_MAX))
y_ref = GetPlotLimits(IMPLOT_AUTO,IMPLOT_AUTO).Y.Min;
if (!(y_ref < DBL_MAX))
y_ref = GetPlotLimits(IMPLOT_AUTO,IMPLOT_AUTO).Y.Max;
GetterXY<IndexerLin,IndexerIdx<T>> getter1(IndexerLin(xscale,x0),IndexerIdx<T>(values,count,offset,stride),count);
GetterXY<IndexerLin,IndexerConst> getter2(IndexerLin(xscale,x0),IndexerConst(y_ref),count);
PlotShadedClipEx(label_id, getter1, getter2, flags);
}

template <typename T>
void PlotShadedClip(const char* label_id, const T* xs, const T* ys, int count, double y_ref, ImPlotShadedFlags flags, int offset, int stride) {
if (y_ref == -HUGE_VAL)
y_ref = GetPlotLimits(IMPLOT_AUTO,IMPLOT_AUTO).Y.Min;
if (y_ref == HUGE_VAL)
y_ref = GetPlotLimits(IMPLOT_AUTO,IMPLOT_AUTO).Y.Max;
GetterXY<IndexerIdx<T>,IndexerIdx<T>> getter1(IndexerIdx<T>(xs,count,offset,stride),IndexerIdx<T>(ys,count,offset,stride),count);
GetterXY<IndexerIdx<T>,IndexerConst> getter2(IndexerIdx<T>(xs,count,offset,stride),IndexerConst(y_ref),count);
PlotShadedClipEx(label_id, getter1, getter2, flags);
}


template <typename T>
void PlotShadedClip(const char* label_id, const T* xs, const T* ys1, const T* ys2, int count, ImPlotShadedFlags flags, int offset, int stride) {
GetterXY<IndexerIdx<T>,IndexerIdx<T>> getter1(IndexerIdx<T>(xs,count,offset,stride),IndexerIdx<T>(ys1,count,offset,stride),count);
GetterXY<IndexerIdx<T>,IndexerIdx<T>> getter2(IndexerIdx<T>(xs,count,offset,stride),IndexerIdx<T>(ys2,count,offset,stride),count);
PlotShadedClipEx(label_id, getter1, getter2, flags);
}

#define INSTANTIATE_MACRO(T) \
template IMPLOT_API void PlotShadedClip<T>(const char* label_id, const T* values, int count, double y_ref, double xscale, double x0, ImPlotShadedFlags flags, int offset, int stride); \
template IMPLOT_API void PlotShadedClip<T>(const char* label_id, const T* xs, const T* ys, int count, double y_ref, ImPlotShadedFlags flags, int offset, int stride); \
template IMPLOT_API void PlotShadedClip<T>(const char* label_id, const T* xs, const T* ys1, const T* ys2, int count, ImPlotShadedFlags flags, int offset, int stride);
CALL_INSTANTIATE_FOR_NUMERIC_TYPES()
#undef INSTANTIATE_MACRO

// custom
void PlotShadedClipG(const char* label_id, ImPlotGetter getter_func1, void* data1, ImPlotGetter getter_func2, void* data2, int count, ImPlotShadedFlags flags) {
GetterFuncPtr getter1(getter_func1, data1, count);
GetterFuncPtr getter2(getter_func2, data2, count);
PlotShadedClipEx(label_id, getter1, getter2, flags);
}

//-----------------------------------------------------------------------------
// [SECTION] PlotBars
//-----------------------------------------------------------------------------
Expand Down