1
0
Fork 0
mirror of https://github.com/gwm17/implot.git synced 2024-11-13 22:48:50 -05:00

adds PlotVLines and PlotHLines for plotting infinite reference lines (#166)

This commit is contained in:
Evan Pezent 2021-01-15 01:52:37 -06:00 committed by GitHub
parent 5fd1ecdfd7
commit 6f7bf5f38b
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 145 additions and 19 deletions

View File

@ -429,19 +429,28 @@ void BustPlotCache() {
} }
void FitPoint(const ImPlotPoint& p) { void FitPoint(const ImPlotPoint& p) {
FitPointX(p.x);
FitPointY(p.y);
}
void FitPointX(double x) {
ImPlotContext& gp = *GImPlot;
ImPlotRange& ex_x = gp.ExtentsX;
const bool log_x = ImHasFlag(gp.CurrentPlot->XAxis.Flags, ImPlotAxisFlags_LogScale);
if (!ImNanOrInf(x) && !(log_x && x <= 0)) {
ex_x.Min = x < ex_x.Min ? x : ex_x.Min;
ex_x.Max = x > ex_x.Max ? x : ex_x.Max;
}
}
void FitPointY(double y) {
ImPlotContext& gp = *GImPlot; ImPlotContext& gp = *GImPlot;
const ImPlotYAxis y_axis = gp.CurrentPlot->CurrentYAxis; const ImPlotYAxis y_axis = gp.CurrentPlot->CurrentYAxis;
ImPlotRange& ex_x = gp.ExtentsX;
ImPlotRange& ex_y = gp.ExtentsY[y_axis]; ImPlotRange& ex_y = gp.ExtentsY[y_axis];
const bool log_x = ImHasFlag(gp.CurrentPlot->XAxis.Flags, ImPlotAxisFlags_LogScale);
const bool log_y = ImHasFlag(gp.CurrentPlot->YAxis[y_axis].Flags, ImPlotAxisFlags_LogScale); const bool log_y = ImHasFlag(gp.CurrentPlot->YAxis[y_axis].Flags, ImPlotAxisFlags_LogScale);
if (!ImNanOrInf(p.x) && !(log_x && p.x <= 0)) { if (!ImNanOrInf(y) && !(log_y && y <= 0)) {
ex_x.Min = p.x < ex_x.Min ? p.x : ex_x.Min; ex_y.Min = y < ex_y.Min ? y : ex_y.Min;
ex_x.Max = p.x > ex_x.Max ? p.x : ex_x.Max; ex_y.Max = y > ex_y.Max ? y : ex_y.Max;
}
if (!ImNanOrInf(p.y) && !(log_y && p.y <= 0)) {
ex_y.Min = p.y < ex_y.Min ? p.y : ex_y.Min;
ex_y.Max = p.y > ex_y.Max ? p.y : ex_y.Max;
} }
} }

View File

@ -434,6 +434,10 @@ template <typename T> IMPLOT_API void PlotErrorBarsH(const char* label_id, const
template <typename T> IMPLOT_API void PlotStems(const char* label_id, const T* values, int count, double y_ref=0, double xscale=1, double x0=0, int offset=0, int stride=sizeof(T)); template <typename T> IMPLOT_API void PlotStems(const char* label_id, const T* values, int count, double y_ref=0, double xscale=1, double x0=0, int offset=0, int stride=sizeof(T));
template <typename T> IMPLOT_API void PlotStems(const char* label_id, const T* xs, const T* ys, int count, double y_ref=0, int offset=0, int stride=sizeof(T)); template <typename T> IMPLOT_API void PlotStems(const char* label_id, const T* xs, const T* ys, int count, double y_ref=0, int offset=0, int stride=sizeof(T));
/// Plots infinite vertical or horizontal lines (e.g. for references or asymptotes).
template <typename T> IMPLOT_API void PlotVLines(const char* label_id, const T* xs, int count, int offset=0, int stride=sizeof(T));
template <typename T> IMPLOT_API void PlotHLines(const char* label_id, const T* ys, int count, int offset=0, int stride=sizeof(T));
// Plots a pie chart. If the sum of values > 1 or normalize is true, each value will be normalized. Center and radius are in plot units. #label_fmt can be set to NULL for no labels. // Plots a pie chart. If the sum of values > 1 or normalize is true, each value will be normalized. Center and radius are in plot units. #label_fmt can be set to NULL for no labels.
template <typename T> IMPLOT_API void PlotPieChart(const char* const label_ids[], const T* values, int count, double x, double y, double radius, bool normalize=false, const char* label_fmt="%.1f", double angle0=90); template <typename T> IMPLOT_API void PlotPieChart(const char* const label_ids[], const T* values, int count, double x, double y, double radius, bool normalize=false, const char* label_fmt="%.1f", double angle0=90);

View File

@ -269,13 +269,13 @@ void ShowDemoWindow(bool* p_open) {
ImGui::Checkbox("Fills",&show_fills); ImGui::Checkbox("Fills",&show_fills);
if (show_fills) { if (show_fills) {
ImGui::SameLine(); ImGui::SameLine();
if (ImGui::RadioButton("To -INF",shade_mode == 0)) if (ImGui::RadioButton("To -INF",shade_mode == 0))
shade_mode = 0; shade_mode = 0;
ImGui::SameLine(); ImGui::SameLine();
if (ImGui::RadioButton("To +INF",shade_mode == 1)) if (ImGui::RadioButton("To +INF",shade_mode == 1))
shade_mode = 1; shade_mode = 1;
ImGui::SameLine(); ImGui::SameLine();
if (ImGui::RadioButton("To Ref",shade_mode == 2)) if (ImGui::RadioButton("To Ref",shade_mode == 2))
shade_mode = 2; shade_mode = 2;
if (shade_mode == 2) { if (shade_mode == 2) {
ImGui::SameLine(); ImGui::SameLine();
@ -436,6 +436,7 @@ void ShowDemoWindow(bool* p_open) {
ImPlot::EndPlot(); ImPlot::EndPlot();
} }
} }
//-------------------------------------------------------------------------
if (ImGui::CollapsingHeader("Stem Plots##")) { if (ImGui::CollapsingHeader("Stem Plots##")) {
static double xs[51], ys1[51], ys2[51]; static double xs[51], ys1[51], ys2[51];
for (int i = 0; i < 51; ++i) { for (int i = 0; i < 51; ++i) {
@ -456,6 +457,15 @@ void ShowDemoWindow(bool* p_open) {
} }
} }
//------------------------------------------------------------------------- //-------------------------------------------------------------------------
if (ImGui::CollapsingHeader("Infinite Lines")) {
static double vals[] = {0.25, 0.5, 0.75};
if (ImPlot::BeginPlot("##Infinite")) {
ImPlot::PlotVLines("VLines",vals,3);
ImPlot::PlotHLines("HLines",vals,3);
ImPlot::EndPlot();
}
}
//-------------------------------------------------------------------------
if (ImGui::CollapsingHeader("Pie Charts")) { if (ImGui::CollapsingHeader("Pie Charts")) {
static const char* labels1[] = {"Frogs","Hogs","Dogs","Logs"}; static const char* labels1[] = {"Frogs","Hogs","Dogs","Logs"};
static float data1[] = {0.15f, 0.30f, 0.2f, 0.05f}; static float data1[] = {0.15f, 0.30f, 0.2f, 0.05f};

View File

@ -762,8 +762,12 @@ inline ImPlotScale GetCurrentScale() { return GImPlot->Scales[GetCurrentYAxis()]
// Returns true if the user has requested data to be fit. // Returns true if the user has requested data to be fit.
inline bool FitThisFrame() { return GImPlot->FitThisFrame; } inline bool FitThisFrame() { return GImPlot->FitThisFrame; }
// Extends the current plots axes so that it encompasses point p // Extends the current plot's axes so that it encompasses point p
IMPLOT_API void FitPoint(const ImPlotPoint& p); IMPLOT_API void FitPoint(const ImPlotPoint& p);
// Extends the current plot's axes so that it encompasses a vertical line at x
IMPLOT_API void FitPointX(double x);
// Extends the current plot's axes so that it encompasses a horizontal line at y
IMPLOT_API void FitPointY(double y);
// Returns true if two ranges overlap // Returns true if two ranges overlap
inline bool RangesOverlap(const ImPlotRange& r1, const ImPlotRange& r2) inline bool RangesOverlap(const ImPlotRange& r1, const ImPlotRange& r2)

View File

@ -302,6 +302,26 @@ struct GetterXsYRef {
const int Stride; const int Stride;
}; };
// Interprets an array of Y points as ImPlotPoints where the X value is a constant reference value
template <typename T>
struct GetterXRefYs {
GetterXRefYs(double x_ref, const T* ys, int count, int offset, int stride) :
XRef(x_ref),
Ys(ys),
Count(count),
Offset(count ? ImPosMod(offset, count) : 0),
Stride(stride)
{ }
inline ImPlotPoint operator()(int idx) const {
return ImPlotPoint(XRef, (double)OffsetAndStride(Ys, idx, Count, Offset, Stride));
}
const double XRef;
const T* const Ys;
const int Count;
const int Offset;
const int Stride;
};
/// Interprets a user's function pointer as ImPlotPoints /// Interprets a user's function pointer as ImPlotPoints
struct GetterFuncPtr { struct GetterFuncPtr {
GetterFuncPtr(ImPlotPoint (*getter)(void* data, int idx), void* data, int count, int offset) : GetterFuncPtr(ImPlotPoint (*getter)(void* data, int idx), void* data, int count, int offset) :
@ -1123,11 +1143,11 @@ template <typename Getter1, typename Getter2>
inline void PlotShadedEx(const char* label_id, const Getter1& getter1, const Getter2& getter2, bool fit2) { inline void PlotShadedEx(const char* label_id, const Getter1& getter1, const Getter2& getter2, bool fit2) {
if (BeginItem(label_id, ImPlotCol_Fill)) { if (BeginItem(label_id, ImPlotCol_Fill)) {
if (FitThisFrame()) { if (FitThisFrame()) {
for (int i = 0; i < getter1.Count; ++i) for (int i = 0; i < getter1.Count; ++i)
FitPoint(getter1(i)); FitPoint(getter1(i));
if (fit2) { if (fit2) {
for (int i = 0; i < getter2.Count; ++i) for (int i = 0; i < getter2.Count; ++i)
FitPoint(getter2(i)); FitPoint(getter2(i));
} }
} }
const ImPlotNextItemData& s = GetItemData(); const ImPlotNextItemData& s = GetItemData();
@ -1149,7 +1169,7 @@ template <typename T>
void PlotShaded(const char* label_id, const T* values, int count, double y_ref, double xscale, double x0, int offset, int stride) { void PlotShaded(const char* label_id, const T* values, int count, double y_ref, double xscale, double x0, int offset, int stride) {
bool fit2 = true; bool fit2 = true;
if (y_ref == -HUGE_VAL) { if (y_ref == -HUGE_VAL) {
fit2 = false; fit2 = false;
y_ref = GetPlotLimits().Y.Min; y_ref = GetPlotLimits().Y.Min;
} }
if (y_ref == HUGE_VAL) { if (y_ref == HUGE_VAL) {
@ -1176,7 +1196,7 @@ template <typename T>
void PlotShaded(const char* label_id, const T* xs, const T* ys, int count, double y_ref, int offset, int stride) { void PlotShaded(const char* label_id, const T* xs, const T* ys, int count, double y_ref, int offset, int stride) {
bool fit2 = true; bool fit2 = true;
if (y_ref == -HUGE_VAL) { if (y_ref == -HUGE_VAL) {
fit2 = false; fit2 = false;
y_ref = GetPlotLimits().Y.Min; y_ref = GetPlotLimits().Y.Min;
} }
if (y_ref == HUGE_VAL) { if (y_ref == HUGE_VAL) {
@ -1592,6 +1612,85 @@ template IMPLOT_API void PlotStems<ImU64>(const char* label_id, const ImU64* xs,
template IMPLOT_API void PlotStems<float>(const char* label_id, const float* xs, const float* ys, int count, double y_ref, int offset, int stride); template IMPLOT_API void PlotStems<float>(const char* label_id, const float* xs, const float* ys, int count, double y_ref, int offset, int stride);
template IMPLOT_API void PlotStems<double>(const char* label_id, const double* xs, const double* ys, int count, double y_ref, int offset, int stride); template IMPLOT_API void PlotStems<double>(const char* label_id, const double* xs, const double* ys, int count, double y_ref, int offset, int stride);
//-----------------------------------------------------------------------------
// INFINITE LINES
//-----------------------------------------------------------------------------
template <typename T>
void PlotVLines(const char* label_id, const T* xs, int count, int offset, int stride) {
if (BeginItem(label_id, ImPlotCol_Line)) {
const ImPlotLimits lims = GetPlotLimits();
GetterXsYRef<T> get_min(xs,lims.Y.Min,count,offset,stride);
GetterXsYRef<T> get_max(xs,lims.Y.Max,count,offset,stride);
if (FitThisFrame()) {
for (int i = 0; i < get_min.Count; ++i)
FitPointX(get_min(i).x);
}
const ImPlotNextItemData& s = GetItemData();
ImDrawList& DrawList = *GetPlotDrawList();
// render stems
if (s.RenderLine) {
const ImU32 col_line = ImGui::GetColorU32(s.Colors[ImPlotCol_Line]);
switch (GetCurrentScale()) {
case ImPlotScale_LinLin: RenderLineSegments(get_min, get_max, TransformerLinLin(), DrawList, s.LineWeight, col_line); break;
case ImPlotScale_LogLin: RenderLineSegments(get_min, get_max, TransformerLogLin(), DrawList, s.LineWeight, col_line); break;
case ImPlotScale_LinLog: RenderLineSegments(get_min, get_max, TransformerLinLog(), DrawList, s.LineWeight, col_line); break;
case ImPlotScale_LogLog: RenderLineSegments(get_min, get_max, TransformerLogLog(), DrawList, s.LineWeight, col_line); break;
}
}
EndItem();
}
}
template IMPLOT_API void PlotVLines<ImS8>(const char* label_id, const ImS8* xs, int count, int offset, int stride);
template IMPLOT_API void PlotVLines<ImU8>(const char* label_id, const ImU8* xs, int count, int offset, int stride);
template IMPLOT_API void PlotVLines<ImS16>(const char* label_id, const ImS16* xs, int count, int offset, int stride);
template IMPLOT_API void PlotVLines<ImU16>(const char* label_id, const ImU16* xs, int count, int offset, int stride);
template IMPLOT_API void PlotVLines<ImS32>(const char* label_id, const ImS32* xs, int count, int offset, int stride);
template IMPLOT_API void PlotVLines<ImU32>(const char* label_id, const ImU32* xs, int count, int offset, int stride);
template IMPLOT_API void PlotVLines<ImS64>(const char* label_id, const ImS64* xs, int count, int offset, int stride);
template IMPLOT_API void PlotVLines<ImU64>(const char* label_id, const ImU64* xs, int count, int offset, int stride);
template IMPLOT_API void PlotVLines<float>(const char* label_id, const float* xs, int count, int offset, int stride);
template IMPLOT_API void PlotVLines<double>(const char* label_id, const double* xs, int count, int offset, int stride);
template <typename T>
void PlotHLines(const char* label_id, const T* ys, int count, int offset, int stride) {
if (BeginItem(label_id, ImPlotCol_Line)) {
const ImPlotLimits lims = GetPlotLimits();
GetterXRefYs<T> get_min(lims.X.Min,ys,count,offset,stride);
GetterXRefYs<T> get_max(lims.X.Max,ys,count,offset,stride);
if (FitThisFrame()) {
for (int i = 0; i < get_min.Count; ++i)
FitPointY(get_min(i).y);
}
const ImPlotNextItemData& s = GetItemData();
ImDrawList& DrawList = *GetPlotDrawList();
// render stems
if (s.RenderLine) {
const ImU32 col_line = ImGui::GetColorU32(s.Colors[ImPlotCol_Line]);
switch (GetCurrentScale()) {
case ImPlotScale_LinLin: RenderLineSegments(get_min, get_max, TransformerLinLin(), DrawList, s.LineWeight, col_line); break;
case ImPlotScale_LogLin: RenderLineSegments(get_min, get_max, TransformerLogLin(), DrawList, s.LineWeight, col_line); break;
case ImPlotScale_LinLog: RenderLineSegments(get_min, get_max, TransformerLinLog(), DrawList, s.LineWeight, col_line); break;
case ImPlotScale_LogLog: RenderLineSegments(get_min, get_max, TransformerLogLog(), DrawList, s.LineWeight, col_line); break;
}
}
EndItem();
}
}
template IMPLOT_API void PlotHLines<ImS8>(const char* label_id, const ImS8* ys, int count, int offset, int stride);
template IMPLOT_API void PlotHLines<ImU8>(const char* label_id, const ImU8* ys, int count, int offset, int stride);
template IMPLOT_API void PlotHLines<ImS16>(const char* label_id, const ImS16* ys, int count, int offset, int stride);
template IMPLOT_API void PlotHLines<ImU16>(const char* label_id, const ImU16* ys, int count, int offset, int stride);
template IMPLOT_API void PlotHLines<ImS32>(const char* label_id, const ImS32* ys, int count, int offset, int stride);
template IMPLOT_API void PlotHLines<ImU32>(const char* label_id, const ImU32* ys, int count, int offset, int stride);
template IMPLOT_API void PlotHLines<ImS64>(const char* label_id, const ImS64* ys, int count, int offset, int stride);
template IMPLOT_API void PlotHLines<ImU64>(const char* label_id, const ImU64* ys, int count, int offset, int stride);
template IMPLOT_API void PlotHLines<float>(const char* label_id, const float* ys, int count, int offset, int stride);
template IMPLOT_API void PlotHLines<double>(const char* label_id, const double* ys, int count, int offset, int stride);
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
// PLOT PIE CHART // PLOT PIE CHART
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------