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:
parent
5fd1ecdfd7
commit
6f7bf5f38b
27
implot.cpp
27
implot.cpp
|
@ -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;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
4
implot.h
4
implot.h
|
@ -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);
|
||||||
|
|
||||||
|
|
|
@ -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};
|
||||||
|
|
|
@ -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)
|
||||||
|
|
111
implot_items.cpp
111
implot_items.cpp
|
@ -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
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
|
|
Loading…
Reference in New Issue
Block a user