mirror of
https://github.com/gwm17/implot.git
synced 2024-11-26 20:28: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) {
|
||||
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;
|
||||
const ImPlotYAxis y_axis = gp.CurrentPlot->CurrentYAxis;
|
||||
ImPlotRange& ex_x = gp.ExtentsX;
|
||||
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);
|
||||
if (!ImNanOrInf(p.x) && !(log_x && p.x <= 0)) {
|
||||
ex_x.Min = p.x < ex_x.Min ? p.x : ex_x.Min;
|
||||
ex_x.Max = p.x > ex_x.Max ? p.x : ex_x.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;
|
||||
if (!ImNanOrInf(y) && !(log_y && y <= 0)) {
|
||||
ex_y.Min = y < ex_y.Min ? y : ex_y.Min;
|
||||
ex_y.Max = y > ex_y.Max ? 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* 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.
|
||||
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);
|
||||
if (show_fills) {
|
||||
ImGui::SameLine();
|
||||
if (ImGui::RadioButton("To -INF",shade_mode == 0))
|
||||
if (ImGui::RadioButton("To -INF",shade_mode == 0))
|
||||
shade_mode = 0;
|
||||
ImGui::SameLine();
|
||||
if (ImGui::RadioButton("To +INF",shade_mode == 1))
|
||||
if (ImGui::RadioButton("To +INF",shade_mode == 1))
|
||||
shade_mode = 1;
|
||||
ImGui::SameLine();
|
||||
if (ImGui::RadioButton("To Ref",shade_mode == 2))
|
||||
if (ImGui::RadioButton("To Ref",shade_mode == 2))
|
||||
shade_mode = 2;
|
||||
if (shade_mode == 2) {
|
||||
ImGui::SameLine();
|
||||
|
@ -436,6 +436,7 @@ void ShowDemoWindow(bool* p_open) {
|
|||
ImPlot::EndPlot();
|
||||
}
|
||||
}
|
||||
//-------------------------------------------------------------------------
|
||||
if (ImGui::CollapsingHeader("Stem Plots##")) {
|
||||
static double xs[51], ys1[51], ys2[51];
|
||||
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")) {
|
||||
static const char* labels1[] = {"Frogs","Hogs","Dogs","Logs"};
|
||||
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.
|
||||
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);
|
||||
// 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
|
||||
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;
|
||||
};
|
||||
|
||||
// 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
|
||||
struct GetterFuncPtr {
|
||||
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) {
|
||||
if (BeginItem(label_id, ImPlotCol_Fill)) {
|
||||
if (FitThisFrame()) {
|
||||
for (int i = 0; i < getter1.Count; ++i)
|
||||
FitPoint(getter1(i));
|
||||
for (int i = 0; i < getter1.Count; ++i)
|
||||
FitPoint(getter1(i));
|
||||
if (fit2) {
|
||||
for (int i = 0; i < getter2.Count; ++i)
|
||||
FitPoint(getter2(i));
|
||||
for (int i = 0; i < getter2.Count; ++i)
|
||||
FitPoint(getter2(i));
|
||||
}
|
||||
}
|
||||
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) {
|
||||
bool fit2 = true;
|
||||
if (y_ref == -HUGE_VAL) {
|
||||
fit2 = false;
|
||||
fit2 = false;
|
||||
y_ref = GetPlotLimits().Y.Min;
|
||||
}
|
||||
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) {
|
||||
bool fit2 = true;
|
||||
if (y_ref == -HUGE_VAL) {
|
||||
fit2 = false;
|
||||
fit2 = false;
|
||||
y_ref = GetPlotLimits().Y.Min;
|
||||
}
|
||||
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<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
|
||||
//-----------------------------------------------------------------------------
|
||||
|
|
Loading…
Reference in New Issue
Block a user