diff --git a/implot.h b/implot.h index a7961c4f..5ed83852 100644 --- a/implot.h +++ b/implot.h @@ -857,28 +857,28 @@ IMPLOT_API void SetNextAxesToFit(); // Plots a standard 2D line plot. IMPLOT_TMP void PlotLine(const char* label_id, const T* values, int count, double xscale=1, double xstart=0, ImPlotLineFlags flags=0, int offset=0, int stride=sizeof(T)); IMPLOT_TMP void PlotLine(const char* label_id, const T* xs, const T* ys, int count, ImPlotLineFlags flags=0, int offset=0, int stride=sizeof(T)); -IMPLOT_API void PlotLineG(const char* label_id, ImPlotGetter getter, void* data, int count, ImPlotLineFlags flags=0); +IMPLOT_API void PlotLineG(const char* label_id, ImPlotGetter getter, void* data, int count, ImPlotLineFlags flags=0, int idx_offset=0, int idx_stride=1); // 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, ImPlotScatterFlags flags=0, int offset=0, int stride=sizeof(T)); IMPLOT_TMP void PlotScatter(const char* label_id, const T* xs, const T* ys, int count, ImPlotScatterFlags flags=0, int offset=0, int stride=sizeof(T)); -IMPLOT_API void PlotScatterG(const char* label_id, ImPlotGetter getter, void* data, int count, ImPlotScatterFlags flags=0); +IMPLOT_API void PlotScatterG(const char* label_id, ImPlotGetter getter, void* data, int count, ImPlotScatterFlags flags=0, int idx_offset=0, int idx_stride=1); // Plots a a stairstep graph. The y value is continued constantly to the right from every x position, i.e. the interval [x[i], x[i+1]) has the value y[i] IMPLOT_TMP void PlotStairs(const char* label_id, const T* values, int count, double xscale=1, double xstart=0, ImPlotStairsFlags flags=0, int offset=0, int stride=sizeof(T)); IMPLOT_TMP void PlotStairs(const char* label_id, const T* xs, const T* ys, int count, ImPlotStairsFlags flags=0, int offset=0, int stride=sizeof(T)); -IMPLOT_API void PlotStairsG(const char* label_id, ImPlotGetter getter, void* data, int count, ImPlotStairsFlags flags=0); +IMPLOT_API void PlotStairsG(const char* label_id, ImPlotGetter getter, void* data, int count, ImPlotStairsFlags flags=0, int idx_offset=0, int idx_stride=1); // Plots a shaded (filled) region between two lines, or a line and a horizontal reference. Set yref to +/-INFINITY for infinite fill extents. IMPLOT_TMP void PlotShaded(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 PlotShaded(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 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); +IMPLOT_API void PlotShadedG(const char* label_id, ImPlotGetter getter1, void* data1, ImPlotGetter getter2, void* data2, int count, ImPlotShadedFlags flags=0, int idx_offset=0, int idx_stride=1); // 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)); -IMPLOT_API void PlotBarsG(const char* label_id, ImPlotGetter getter, void* data, int count, double bar_size, ImPlotBarsFlags flags=0); +IMPLOT_API void PlotBarsG(const char* label_id, ImPlotGetter getter, void* data, int count, double bar_size, ImPlotBarsFlags flags=0, int idx_offset=0, int idx_stride=1); // Plots a group of bars. #values is a row-major matrix with #item_count rows and #group_count cols. #label_ids should have #item_count elements. IMPLOT_TMP void PlotBarGroups(const char* const label_ids[], const T* values, int item_count, int group_count, double group_size=0.67, double shift=0, ImPlotBarGroupsFlags flags=0); @@ -911,7 +911,7 @@ IMPLOT_TMP double PlotHistogram2D(const char* label_id, const T* xs, const T* ys // Plots digital data. Digital plots do not respond to y drag or zoom, and are always referenced to the bottom of the plot. IMPLOT_TMP void PlotDigital(const char* label_id, const T* xs, const T* ys, int count, ImPlotDigitalFlags flags=0, int offset=0, int stride=sizeof(T)); -IMPLOT_API void PlotDigitalG(const char* label_id, ImPlotGetter getter, void* data, int count, ImPlotDigitalFlags flags=0); +IMPLOT_API void PlotDigitalG(const char* label_id, ImPlotGetter getter, void* data, int count, ImPlotDigitalFlags flags=0, int idx_offset=0, int idx_stride=1); // Plots an axis-aligned image. #bounds_min/bounds_max are in plot coordinates (y-up) and #uv0/uv1 are in texture coordinates (y-down). IMPLOT_API void PlotImage(const char* label_id, ImTextureID user_texture_id, const ImPlotPoint& bounds_min, const ImPlotPoint& bounds_max, const ImVec2& uv0=ImVec2(0,0), const ImVec2& uv1=ImVec2(1,1), const ImVec4& tint_col=ImVec4(1,1,1,1), ImPlotImageFlags flags=0); diff --git a/implot_demo.cpp b/implot_demo.cpp index d4536a4a..c650888c 100644 --- a/implot_demo.cpp +++ b/implot_demo.cpp @@ -63,6 +63,7 @@ struct WaveData { ImPlotPoint SineWave(int idx, void* wave_data); ImPlotPoint SawWave(int idx, void* wave_data); ImPlotPoint Spiral(int idx, void* wave_data); +ImPlotPoint CustomData(int idx, void* data); // 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); @@ -1957,6 +1958,39 @@ void Demo_CustomDataAndGetters() { ImPlot::EndPlot(); } + int dataCount = 100000; + ImGui::BulletText("For simple dynamic downsampling of huge datasets you can use the idx_offset and idx_stride parameters of Plot(type)G plotters."); + + static bool downsample = true; + ImGui::Checkbox("Enable downsampling", &downsample); + // downsample and clamp limits for performance! + ImPlot::SetNextAxisLimits(ImAxis_X1, 0, dataCount); + if (ImPlot::BeginPlot("##Custom Data Downsampling")) { + if (downsample) + { + int start_idx = (int)ImPlot::GetPlotLimits().X.Min; + + // clamp start_idx + start_idx = start_idx < 0 ? 0 : start_idx; + start_idx = start_idx >= dataCount ? (dataCount - 1) : start_idx; + + // add + 2 to fully draw the last line of the plot + int end_idx = (int)ImPlot::GetPlotLimits().X.Max + 2; + // clamp end_idx + end_idx = end_idx < 0 ? 0 : end_idx; + end_idx = end_idx >= dataCount ? (dataCount - 1) : end_idx; + + int idx_stride = (int)(ImPlot::GetPlotLimits().X.Size() / ImPlot::GetPlotSize().x) + 1; + int count = (end_idx - start_idx) / idx_stride; + + ImPlot::PlotLineG("Custom Data Downsampling", MyImPlot::CustomData, &dataCount, count, 0, start_idx, idx_stride); + } + else + { + ImPlot::PlotLineG("Custom Data Downsampling", MyImPlot::CustomData, &dataCount, dataCount); + } + ImPlot::EndPlot(); + } } //----------------------------------------------------------------------------- @@ -2330,6 +2364,15 @@ ImPlotPoint Spiral(int idx, void*) { 0.5f + (a + b*Th / (2.0f * (float)3.14))*sin(Th)); } +ImPlotPoint CustomData(int idx, void* data) { + int dataCount = *(int*)data; + srand(idx); + float x = (float)idx / (float)dataCount; + float y = (0.25f + 0.25f * sinf(25 * x) * sinf(5 * x) + ImPlot::RandomRange(-0.01f, 0.01f)); + unsigned char* ys = (unsigned char*)data; + return ImPlotPoint((float)idx, y); +} + void Sparkline(const char* id, const float* values, int count, float min_v, float max_v, int offset, const ImVec4& col, const ImVec2& size) { ImPlot::PushStyleVar(ImPlotStyleVar_PlotPadding, ImVec2(0,0)); if (ImPlot::BeginPlot(id,size,ImPlotFlags_CanvasOnly)) { diff --git a/implot_items.cpp b/implot_items.cpp index 741eaaf2..5a893e67 100644 --- a/implot_items.cpp +++ b/implot_items.cpp @@ -571,17 +571,21 @@ struct GetterXY { /// Interprets a user's function pointer as ImPlotPoints struct GetterFuncPtr { - GetterFuncPtr(ImPlotGetter getter, void* data, int count) : + GetterFuncPtr(ImPlotGetter getter, void* data, int count, int idx_offset, int idx_stride) : Getter(getter), Data(data), - Count(count) + Count(count), + IndexOffset(idx_offset), + IndexStride(idx_stride) { } template IMPLOT_INLINE ImPlotPoint operator()(I idx) const { - return Getter(idx, Data); + return Getter(idx * IndexStride + IndexOffset, Data); } ImPlotGetter Getter; void* const Data; const int Count; + const int IndexOffset; + const int IndexStride; }; template @@ -1635,8 +1639,8 @@ CALL_INSTANTIATE_FOR_NUMERIC_TYPES() #undef INSTANTIATE_MACRO // custom -void PlotLineG(const char* label_id, ImPlotGetter getter_func, void* data, int count, ImPlotLineFlags flags) { - GetterFuncPtr getter(getter_func,data, count); +void PlotLineG(const char* label_id, ImPlotGetter getter_func, void* data, int count, ImPlotLineFlags flags, int idx_offset, int idx_stride) { + GetterFuncPtr getter(getter_func,data, count, idx_offset, idx_stride); PlotLineEx(label_id, getter, flags); } @@ -1685,8 +1689,8 @@ CALL_INSTANTIATE_FOR_NUMERIC_TYPES() #undef INSTANTIATE_MACRO // custom -void PlotScatterG(const char* label_id, ImPlotGetter getter_func, void* data, int count, ImPlotScatterFlags flags) { - GetterFuncPtr getter(getter_func,data, count); +void PlotScatterG(const char* label_id, ImPlotGetter getter_func, void* data, int count, ImPlotScatterFlags flags, int idx_offset, int idx_stride) { + GetterFuncPtr getter(getter_func,data, count, idx_offset, idx_stride); return PlotScatterEx(label_id, getter, flags); } @@ -1749,8 +1753,8 @@ CALL_INSTANTIATE_FOR_NUMERIC_TYPES() #undef INSTANTIATE_MACRO // custom -void PlotStairsG(const char* label_id, ImPlotGetter getter_func, void* data, int count, ImPlotStairsFlags flags) { - GetterFuncPtr getter(getter_func,data, count); +void PlotStairsG(const char* label_id, ImPlotGetter getter_func, void* data, int count, ImPlotStairsFlags flags, int idx_offset, int idx_stride) { + GetterFuncPtr getter(getter_func,data, count, idx_offset, idx_stride); return PlotStairsEx(label_id, getter, flags); } @@ -1812,9 +1816,9 @@ CALL_INSTANTIATE_FOR_NUMERIC_TYPES() #undef INSTANTIATE_MACRO // custom -void PlotShadedG(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); +void PlotShadedG(const char* label_id, ImPlotGetter getter_func1, void* data1, ImPlotGetter getter_func2, void* data2, int count, ImPlotShadedFlags flags, int idx_offset, int idx_stride) { + GetterFuncPtr getter1(getter_func1, data1, count, idx_offset, idx_stride); + GetterFuncPtr getter2(getter_func2, data2, count, idx_offset, idx_stride); PlotShadedEx(label_id, getter1, getter2, flags); } @@ -1904,14 +1908,14 @@ void PlotBars(const char* label_id, const T* xs, const T* ys, int count, double CALL_INSTANTIATE_FOR_NUMERIC_TYPES() #undef INSTANTIATE_MACRO -void PlotBarsG(const char* label_id, ImPlotGetter getter_func, void* data, int count, double bar_size, ImPlotBarsFlags flags) { +void PlotBarsG(const char* label_id, ImPlotGetter getter_func, void* data, int count, double bar_size, ImPlotBarsFlags flags, int idx_offset, int idx_stride) { if (ImHasFlag(flags, ImPlotBarsFlags_Horizontal)) { - GetterFuncPtr getter1(getter_func, data, count); + GetterFuncPtr getter1(getter_func, data, count, idx_offset, idx_stride); GetterOverrideX getter2(getter1,0); PlotBarsHEx(label_id, getter1, getter2, bar_size, flags); } else { - GetterFuncPtr getter1(getter_func, data, count); + GetterFuncPtr getter1(getter_func, data, count, idx_offset, idx_stride); GetterOverrideY getter2(getter1,0); PlotBarsVEx(label_id, getter1, getter2, bar_size, flags); } @@ -2779,8 +2783,8 @@ CALL_INSTANTIATE_FOR_NUMERIC_TYPES() #undef INSTANTIATE_MACRO // custom -void PlotDigitalG(const char* label_id, ImPlotGetter getter_func, void* data, int count, ImPlotDigitalFlags flags) { - GetterFuncPtr getter(getter_func,data,count); +void PlotDigitalG(const char* label_id, ImPlotGetter getter_func, void* data, int count, ImPlotDigitalFlags flags, int idx_offset, int idx_stride) { + GetterFuncPtr getter(getter_func,data,count, idx_offset, idx_stride); return PlotDigitalEx(label_id, getter, flags); }