Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions implot.h
Original file line number Diff line number Diff line change
Expand Up @@ -720,6 +720,9 @@ typedef int (*ImPlotFormatter)(double value, char* buff, int size, void* user_da
// Callback signature for data getter.
typedef ImPlotPoint (*ImPlotGetter)(int idx, void* user_data);

// Callback signature for line segments filters.
typedef bool (*ImPlotFilter)(int idx, ImPlotPoint p1, ImPlotPoint p2, void* user_data);

// Callback signature for axis transform.
typedef double (*ImPlotTransform)(double value, void* user_data);

Expand Down Expand Up @@ -989,6 +992,7 @@ IMPLOT_API void SetNextAxesToFit();
IMPLOT_TMP void PlotLine(const char* label_id, const T* values, int count, double xscale=1, double xstart=0, const ImPlotSpec& spec=ImPlotSpec());
IMPLOT_TMP void PlotLine(const char* label_id, const T* xs, const T* ys, int count, const ImPlotSpec& spec=ImPlotSpec());
IMPLOT_API void PlotLineG(const char* label_id, ImPlotGetter getter, void* data, int count, const ImPlotSpec& spec=ImPlotSpec());
IMPLOT_API void PlotLineFiltered(const char* label_id, ImPlotGetter getter, ImPlotFilter filter, void* data, int count, const ImPlotSpec& spec=ImPlotSpec());

// Plots a standard 2D scatter plot. Default marker is ImPlotMarker_Circle.
IMPLOT_TMP void PlotScatter(const char* label_id, const T* values, int count, double xscale=1, double xstart=0, const ImPlotSpec& spec=ImPlotSpec());
Expand Down
248 changes: 248 additions & 0 deletions implot_items.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -617,6 +617,21 @@ struct GetterFuncPtr {
typedef ImPlotPoint value_type;
};

/// Interprets a user's function pointer as a line segments filter
struct FilterFuncPtr {
FilterFuncPtr(ImPlotFilter filter, void* data) :
Filter(filter),
Data(data)
{ }
template <typename I> IMPLOT_INLINE bool operator()(I idx, ImPlotPoint p1, ImPlotPoint p2) const {
return Filter(idx, p1, p2, Data);
}
ImPlotFilter Filter;
void* const Data;
typedef bool value_type;
};


template <typename _Getter>
struct GetterOverrideX {
GetterOverrideX(_Getter getter, double x) : Getter(getter), X(x), Count(getter.Count) { }
Expand Down Expand Up @@ -1005,6 +1020,45 @@ struct RendererLineStrip : RendererBase {
mutable ImVec2 UV1;
};

template <class _Getter, class _GetterColor, class _Filter>
struct RendererLineStripFiltered : RendererBase {
RendererLineStripFiltered(const _Getter& getter, const _GetterColor& getter_color, const _Filter& filter, float weight) :
RendererBase(getter.Count - 1, 6, 4),
Getter(getter),
GetterColor(getter_color),
Filter(filter),
HalfWeight(ImMax(1.0f,weight)*0.5f)
{
rawP1 = Getter[0];
P1 = this->Transformer(rawP1);
}
void Init(ImDrawList& draw_list) const {
GetLineRenderProps(draw_list, HalfWeight, UV0, UV1);
}
IMPLOT_INLINE bool Render(ImDrawList& draw_list, const ImRect& cull_rect, int prim) const {
ImPlotPoint rawP2 = Getter[prim + 1];
ImVec2 P2 = this->Transformer(rawP2);
if (!cull_rect.Overlaps(ImRect(ImMin(P1, P2), ImMax(P1, P2))) || !Filter(prim + 1, rawP1, rawP2)) {
P1 = P2;
rawP1 = rawP2;
return false;
}
ImU32 col = GetterColor[prim];
PrimLine(draw_list,P1,P2,HalfWeight,col,UV0,UV1);
P1 = P2;
rawP1 = rawP2;
return true;
}
const _Getter& Getter;
const _GetterColor& GetterColor;
const _Filter& Filter;
mutable float HalfWeight;
mutable ImVec2 P1;
mutable ImPlotPoint rawP1;
mutable ImVec2 UV0;
mutable ImVec2 UV1;
};

template <class _Getter, class _GetterColor>
struct RendererLineStripSkip : RendererBase {
RendererLineStripSkip(const _Getter& getter, const _GetterColor& getter_color, float weight) :
Expand Down Expand Up @@ -1039,6 +1093,49 @@ struct RendererLineStripSkip : RendererBase {
mutable ImVec2 UV1;
};

template <class _Getter, class _GetterColor, class _Filter>
struct RendererLineStripSkipFiltered : RendererBase {
RendererLineStripSkipFiltered(const _Getter& getter, const _GetterColor& getter_color, const _Filter& filter, float weight) :
RendererBase(getter.Count - 1, 6, 4),
Getter(getter),
GetterColor(getter_color),
Filter(filter),
HalfWeight(ImMax(1.0f,weight)*0.5f)
{
rawP1 = Getter[0];
P1 = this->Transformer(rawP1);
}
void Init(ImDrawList& draw_list) const {
GetLineRenderProps(draw_list, HalfWeight, UV0, UV1);
}
IMPLOT_INLINE bool Render(ImDrawList& draw_list, const ImRect& cull_rect, int prim) const {
ImPlotPoint rawP2 = Getter[prim + 1];
ImVec2 P2 = this->Transformer(rawP2);
if (!cull_rect.Overlaps(ImRect(ImMin(P1, P2), ImMax(P1, P2))) || !Filter(prim + 1, rawP1, rawP2)) {
if (!ImNan(P2.x) && !ImNan(P2.y)){
P1 = P2;
rawP1 = rawP2;
}
return false;
}
ImU32 col = GetterColor[prim];
PrimLine(draw_list,P1,P2,HalfWeight,col,UV0,UV1);
if (!ImNan(P2.x) && !ImNan(P2.y)){
P1 = P2;
rawP1 = rawP2;
}
return true;
}
const _Getter& Getter;
const _GetterColor& GetterColor;
const _Filter& Filter;
mutable float HalfWeight;
mutable ImVec2 P1;
mutable ImPlotPoint rawP1;
mutable ImVec2 UV0;
mutable ImVec2 UV1;
};

template <class _Getter, class _GetterColor>
struct RendererLineSegments1 : RendererBase {
RendererLineSegments1(const _Getter& getter, const _GetterColor& getter_color, float weight) :
Expand Down Expand Up @@ -1066,6 +1163,37 @@ struct RendererLineSegments1 : RendererBase {
mutable ImVec2 UV1;
};

template <class _Getter, class _GetterColor, class _Filter>
struct RendererLineSegments1Filtered : RendererBase {
RendererLineSegments1Filtered(const _Getter& getter, const _GetterColor& getter_color, const _Filter& filter, float weight) :
RendererBase(getter.Count / 2, 6, 4),
Getter(getter),
GetterColor(getter_color),
Filter(filter),
HalfWeight(ImMax(1.0f,weight)*0.5f)
{ }
void Init(ImDrawList& draw_list) const {
GetLineRenderProps(draw_list, HalfWeight, UV0, UV1);
}
IMPLOT_INLINE bool Render(ImDrawList& draw_list, const ImRect& cull_rect, int prim) const {
ImPlotPoint rawP1 = Getter[prim*2+0];
ImPlotPoint rawP2 = Getter[prim*2+1];
ImVec2 P1 = this->Transformer(rawP1);
ImVec2 P2 = this->Transformer(rawP2);
if (!cull_rect.Overlaps(ImRect(ImMin(P1, P2), ImMax(P1, P2))) || !Filter(prim, rawP1, rawP2))
return false;
ImU32 col = GetterColor[prim*2];
PrimLine(draw_list,P1,P2,HalfWeight,col,UV0,UV1);
return true;
}
const _Getter& Getter;
const _GetterColor& GetterColor;
const _Filter& Filter;
mutable float HalfWeight;
mutable ImVec2 UV0;
mutable ImVec2 UV1;
};

template <class _Getter1, class _Getter2, class _GetterColor>
struct RendererLineSegments2 : RendererBase {
RendererLineSegments2(const _Getter1& getter1, const _Getter2& getter2, const _GetterColor& getter_color, float weight) :
Expand Down Expand Up @@ -1095,6 +1223,38 @@ struct RendererLineSegments2 : RendererBase {
mutable ImVec2 UV1;
};

template <class _Getter1, class _Getter2, class _GetterColor, class _Filter>
struct RendererLineSegments2Filtered : RendererBase {
RendererLineSegments2Filtered(const _Getter1& getter1, const _Getter2& getter2, const _GetterColor& getter_color, const _Filter& filter, float weight) :
RendererBase(ImMin(getter1.Count, getter2.Count), 6, 4),
Getter1(getter1),
Getter2(getter2),
GetterColor(getter_color),
HalfWeight(ImMax(1.0f,weight)*0.5f)
{}
void Init(ImDrawList& draw_list) const {
GetLineRenderProps(draw_list, HalfWeight, UV0, UV1);
}
IMPLOT_INLINE bool Render(ImDrawList& draw_list, const ImRect& cull_rect, int prim) const {
ImPlotPoint rawP1 = Getter1[prim];
ImPlotPoint rawP2 = Getter2[prim];
ImVec2 P1 = this->Transformer(rawP1);
ImVec2 P2 = this->Transformer(rawP2);
if (!cull_rect.Overlaps(ImRect(ImMin(P1, P2), ImMax(P1, P2))) || !Filter(prim, rawP1, rawP2))
return false;
ImU32 col = GetterColor[prim];
PrimLine(draw_list,P1,P2,HalfWeight,col,UV0,UV1);
return true;
}
const _Getter1& Getter1;
const _Getter2& Getter2;
const _GetterColor& GetterColor;
const _Filter& Filter;
mutable float HalfWeight;
mutable ImVec2 UV0;
mutable ImVec2 UV1;
};

template <class _Getter1, class _Getter2, class _GetterColor>
struct RendererBarsFillV : RendererBase {
RendererBarsFillV(const _Getter1& getter1, const _Getter2& getter2, const _GetterColor& getter_color, double width) :
Expand Down Expand Up @@ -1536,6 +1696,13 @@ void RenderPrimitives2(const _Getter1& getter1, const _Getter2& getter2, Args...
RenderPrimitivesEx(_Renderer<_Getter1,_Getter2>(getter1,getter2,args...), draw_list, cull_rect);
}

template<template<class, class, class> class _Renderer, class _Getter1, class _Getter2, class _Filter, typename ...Args>
void RenderPrimitives2Filtered(const _Getter1& getter1, const _Getter2& getter2, const _Filter& filter, Args... args){
ImDrawList& draw_list = *GetPlotDrawList();
const ImRect& cull_rect = GetCurrentPlot()->PlotRect;
RenderPrimitivesEx(_Renderer<_Getter1,_Getter2, _Filter>(getter1,getter2,filter,args...), draw_list, cull_rect);
}

template <template <class,class,class> class _Renderer, class _Getter1, class _Getter2, class _Getter3, typename ...Args>
void RenderPrimitives3(const _Getter1& getter1, const _Getter2& getter2, const _Getter3& getter3, Args... args) {
ImDrawList& draw_list = *GetPlotDrawList();
Expand Down Expand Up @@ -1976,6 +2143,81 @@ void PlotLineEx(const char* label_id, const _Getter& getter, const ImPlotSpec& s
}
}

template <typename _Getter, typename _Filter>
void PlotLineFiltered(const char* label_id, const _Getter& getter, const _Filter& filter, const ImPlotSpec& spec) {
if (BeginItemEx(label_id, Fitter1<_Getter>(getter), spec, spec.LineColor, spec.Marker)) {
if (getter.Count <= 0) {
EndItem();
return;
}
const ImPlotNextItemData& s = GetItemData();
if (getter.Count > 1) {
if (ImHasFlag(spec.Flags, ImPlotLineFlags_Shaded) && s.RenderFill) {
GetterOverrideY<_Getter> getter2(getter, 0);
if (s.Spec.FillColors != nullptr) {
GetterIdxColor color_getter(s.Spec.FillColors, getter.Count, s.Spec.FillAlpha);
RenderPrimitives3<RendererShaded>(getter,getter2,color_getter);
} else {
const ImU32 col_fill = ImGui::GetColorU32(s.Spec.FillColor);
GetterConstColor color_getter(col_fill, s.Spec.FillAlpha);
RenderPrimitives3<RendererShaded>(getter,getter2,color_getter);
}
}
if (s.RenderLine) {
const ImU32 col_line = ImGui::GetColorU32(s.Spec.LineColor);
if (ImHasFlag(spec.Flags,ImPlotLineFlags_Segments)) {
if (s.Spec.LineColors != nullptr) {
GetterIdxColor color_getter(s.Spec.LineColors, getter.Count);
RenderPrimitives2Filtered<RendererLineSegments1Filtered>(getter,color_getter,filter,s.Spec.LineWeight);
} else {
GetterConstColor color_getter(col_line);
RenderPrimitives2Filtered<RendererLineSegments1Filtered>(getter,color_getter,filter,s.Spec.LineWeight);
}
}
else if (ImHasFlag(spec.Flags, ImPlotLineFlags_Loop)) {
if (s.Spec.LineColors != nullptr) {
GetterIdxColor color_getter(s.Spec.LineColors, getter.Count);
if (ImHasFlag(spec.Flags, ImPlotLineFlags_SkipNaN))
RenderPrimitives2Filtered<RendererLineStripSkipFiltered>(GetterLoop<_Getter>(getter),color_getter,filter,s.Spec.LineWeight);
else
RenderPrimitives2Filtered<RendererLineStripFiltered>(GetterLoop<_Getter>(getter),color_getter,filter,s.Spec.LineWeight);
} else {
GetterConstColor color_getter(col_line);
if (ImHasFlag(spec.Flags, ImPlotLineFlags_SkipNaN))
RenderPrimitives2Filtered<RendererLineStripSkipFiltered>(GetterLoop<_Getter>(getter),color_getter,filter,s.Spec.LineWeight);
else
RenderPrimitives2Filtered<RendererLineStripFiltered>(GetterLoop<_Getter>(getter),color_getter,filter,s.Spec.LineWeight);
}
}
else {
if (s.Spec.LineColors != nullptr) {
GetterIdxColor color_getter(s.Spec.LineColors, getter.Count);
if (ImHasFlag(spec.Flags, ImPlotLineFlags_SkipNaN))
RenderPrimitives2Filtered<RendererLineStripSkipFiltered>(getter,color_getter,filter,s.Spec.LineWeight);
else
RenderPrimitives2Filtered<RendererLineStripFiltered>(getter,color_getter,filter,s.Spec.LineWeight);
} else {
GetterConstColor color_getter(col_line);
if (ImHasFlag(spec.Flags, ImPlotLineFlags_SkipNaN))
RenderPrimitives2Filtered<RendererLineStripSkipFiltered>(getter,color_getter,filter,s.Spec.LineWeight);
else
RenderPrimitives2Filtered<RendererLineStripFiltered>(getter,color_getter,filter,s.Spec.LineWeight);
}
}
}
}
// render markers
if (s.RenderMarkers) {
if (ImHasFlag(spec.Flags, ImPlotLineFlags_NoClip)) {
PopPlotClipRect();
PushPlotClipRect(s.Spec.MarkerSize);
}
RenderColoredMarkers(getter, s);
}
EndItem();
}
}

template <typename T>
void PlotLine(const char* label_id, const T* values, int count, double xscale, double x0, const ImPlotSpec& spec) {
GetterXY<IndexerLin,IndexerIdx<T>> getter(IndexerLin(xscale,x0),IndexerIdx<T>(values,count,spec.Offset,Stride<T>(spec)),count);
Expand All @@ -2000,6 +2242,12 @@ void PlotLineG(const char* label_id, ImPlotGetter getter_func, void* data, int c
PlotLineEx(label_id, getter, spec);
}

void PlotLineFiltered(const char* label_id, ImPlotGetter getter_func, ImPlotFilter filter_func, void* data, int count, const ImPlotSpec& spec){
GetterFuncPtr getter(getter_func,data, count);
FilterFuncPtr filter(filter_func,data);
PlotLineFiltered(label_id, getter, filter, spec);
}

//-----------------------------------------------------------------------------
// [SECTION] PlotScatter
//-----------------------------------------------------------------------------
Expand Down