mirror of
https://github.com/gwm17/implot.git
synced 2024-11-26 20:28:50 -05:00
constrain values <= 0 to DBL_MIN for log axes, fix div by zero
This commit is contained in:
parent
0cafcd0011
commit
e9469cf347
40
implot.cpp
40
implot.cpp
|
@ -507,34 +507,36 @@ void PullLinkedAxis(ImPlotAxis& axis) {
|
||||||
|
|
||||||
void UpdateTransformCache() {
|
void UpdateTransformCache() {
|
||||||
ImPlotContext& gp = *GImPlot;
|
ImPlotContext& gp = *GImPlot;
|
||||||
|
ImPlotPlot& plot = *gp.CurrentPlot;
|
||||||
// get pixels for transforms
|
// get pixels for transforms
|
||||||
for (int i = 0; i < IMPLOT_Y_AXES; i++) {
|
for (int i = 0; i < IMPLOT_Y_AXES; i++) {
|
||||||
gp.PixelRange[i] = ImRect(ImHasFlag(gp.CurrentPlot->XAxis.Flags, ImPlotAxisFlags_Invert) ? gp.CurrentPlot->PlotRect.Max.x : gp.CurrentPlot->PlotRect.Min.x,
|
gp.PixelRange[i] = ImRect(plot.XAxis.IsInverted() ? plot.PlotRect.Max.x : plot.PlotRect.Min.x,
|
||||||
ImHasFlag(gp.CurrentPlot->YAxis[i].Flags, ImPlotAxisFlags_Invert) ? gp.CurrentPlot->PlotRect.Min.y : gp.CurrentPlot->PlotRect.Max.y,
|
plot.YAxis[i].IsInverted() ? plot.PlotRect.Min.y : plot.PlotRect.Max.y,
|
||||||
ImHasFlag(gp.CurrentPlot->XAxis.Flags, ImPlotAxisFlags_Invert) ? gp.CurrentPlot->PlotRect.Min.x : gp.CurrentPlot->PlotRect.Max.x,
|
plot.XAxis.IsInverted() ? plot.PlotRect.Min.x : plot.PlotRect.Max.x,
|
||||||
ImHasFlag(gp.CurrentPlot->YAxis[i].Flags, ImPlotAxisFlags_Invert) ? gp.CurrentPlot->PlotRect.Max.y : gp.CurrentPlot->PlotRect.Min.y);
|
plot.YAxis[i].IsInverted() ? plot.PlotRect.Max.y : plot.PlotRect.Min.y);
|
||||||
gp.My[i] = (gp.PixelRange[i].Max.y - gp.PixelRange[i].Min.y) / gp.CurrentPlot->YAxis[i].Range.Size();
|
gp.My[i] = (gp.PixelRange[i].Max.y - gp.PixelRange[i].Min.y) / plot.YAxis[i].Range.Size();
|
||||||
}
|
}
|
||||||
gp.LogDenX = ImLog10(gp.CurrentPlot->XAxis.Range.Max / gp.CurrentPlot->XAxis.Range.Min);
|
gp.LogDenX = plot.XAxis.IsLog() ? ImLog10(plot.XAxis.Range.Max / plot.XAxis.Range.Min) : 0;
|
||||||
for (int i = 0; i < IMPLOT_Y_AXES; i++)
|
for (int i = 0; i < IMPLOT_Y_AXES; i++)
|
||||||
gp.LogDenY[i] = ImLog10(gp.CurrentPlot->YAxis[i].Range.Max / gp.CurrentPlot->YAxis[i].Range.Min);
|
gp.LogDenY[i] = plot.YAxis[i].IsLog() ? ImLog10(plot.YAxis[i].Range.Max / plot.YAxis[i].Range.Min) : 0;
|
||||||
gp.Mx = (gp.PixelRange[0].Max.x - gp.PixelRange[0].Min.x) / gp.CurrentPlot->XAxis.Range.Size();
|
gp.Mx = (gp.PixelRange[0].Max.x - gp.PixelRange[0].Min.x) / plot.XAxis.Range.Size();
|
||||||
}
|
}
|
||||||
|
|
||||||
ImPlotPoint PixelsToPlot(float x, float y, ImPlotYAxis y_axis_in) {
|
ImPlotPoint PixelsToPlot(float x, float y, ImPlotYAxis y_axis_in) {
|
||||||
ImPlotContext& gp = *GImPlot;
|
ImPlotContext& gp = *GImPlot;
|
||||||
|
ImPlotPlot& plot = *gp.CurrentPlot;
|
||||||
IM_ASSERT_USER_ERROR(gp.CurrentPlot != NULL, "PixelsToPlot() needs to be called between BeginPlot() and EndPlot()!");
|
IM_ASSERT_USER_ERROR(gp.CurrentPlot != NULL, "PixelsToPlot() needs to be called between BeginPlot() and EndPlot()!");
|
||||||
const ImPlotYAxis y_axis = y_axis_in >= 0 ? y_axis_in : gp.CurrentPlot->CurrentYAxis;
|
const ImPlotYAxis y_axis = y_axis_in >= 0 ? y_axis_in : plot.CurrentYAxis;
|
||||||
ImPlotPoint plt;
|
ImPlotPoint plt;
|
||||||
plt.x = (x - gp.PixelRange[y_axis].Min.x) / gp.Mx + gp.CurrentPlot->XAxis.Range.Min;
|
plt.x = (x - gp.PixelRange[y_axis].Min.x) / gp.Mx + plot.XAxis.Range.Min;
|
||||||
plt.y = (y - gp.PixelRange[y_axis].Min.y) / gp.My[y_axis] + gp.CurrentPlot->YAxis[y_axis].Range.Min;
|
plt.y = (y - gp.PixelRange[y_axis].Min.y) / gp.My[y_axis] + plot.YAxis[y_axis].Range.Min;
|
||||||
if (ImHasFlag(gp.CurrentPlot->XAxis.Flags, ImPlotAxisFlags_LogScale)) {
|
if (ImHasFlag(plot.XAxis.Flags, ImPlotAxisFlags_LogScale)) {
|
||||||
double t = (plt.x - gp.CurrentPlot->XAxis.Range.Min) / gp.CurrentPlot->XAxis.Range.Size();
|
double t = (plt.x - plot.XAxis.Range.Min) / plot.XAxis.Range.Size();
|
||||||
plt.x = ImPow(10, t * gp.LogDenX) * gp.CurrentPlot->XAxis.Range.Min;
|
plt.x = ImPow(10, t * gp.LogDenX) * plot.XAxis.Range.Min;
|
||||||
}
|
}
|
||||||
if (ImHasFlag(gp.CurrentPlot->YAxis[y_axis].Flags, ImPlotAxisFlags_LogScale)) {
|
if (ImHasFlag(plot.YAxis[y_axis].Flags, ImPlotAxisFlags_LogScale)) {
|
||||||
double t = (plt.y - gp.CurrentPlot->YAxis[y_axis].Range.Min) / gp.CurrentPlot->YAxis[y_axis].Range.Size();
|
double t = (plt.y - plot.YAxis[y_axis].Range.Min) / plot.YAxis[y_axis].Range.Size();
|
||||||
plt.y = ImPow(10, t * gp.LogDenY[y_axis]) * gp.CurrentPlot->YAxis[y_axis].Range.Min;
|
plt.y = ImPow(10, t * gp.LogDenY[y_axis]) * plot.YAxis[y_axis].Range.Min;
|
||||||
}
|
}
|
||||||
return plt;
|
return plt;
|
||||||
}
|
}
|
||||||
|
@ -543,17 +545,18 @@ ImPlotPoint PixelsToPlot(const ImVec2& pix, ImPlotYAxis y_axis) {
|
||||||
return PixelsToPlot(pix.x, pix.y, y_axis);
|
return PixelsToPlot(pix.x, pix.y, y_axis);
|
||||||
}
|
}
|
||||||
|
|
||||||
// This function is convenient but should not be used to process a high volume of points. Use the Transformer structs below instead.
|
|
||||||
ImVec2 PlotToPixels(double x, double y, ImPlotYAxis y_axis_in) {
|
ImVec2 PlotToPixels(double x, double y, ImPlotYAxis y_axis_in) {
|
||||||
ImPlotContext& gp = *GImPlot;
|
ImPlotContext& gp = *GImPlot;
|
||||||
IM_ASSERT_USER_ERROR(gp.CurrentPlot != NULL, "PlotToPixels() needs to be called between BeginPlot() and EndPlot()!");
|
IM_ASSERT_USER_ERROR(gp.CurrentPlot != NULL, "PlotToPixels() needs to be called between BeginPlot() and EndPlot()!");
|
||||||
const ImPlotYAxis y_axis = y_axis_in >= 0 ? y_axis_in : gp.CurrentPlot->CurrentYAxis;
|
const ImPlotYAxis y_axis = y_axis_in >= 0 ? y_axis_in : gp.CurrentPlot->CurrentYAxis;
|
||||||
ImVec2 pix;
|
ImVec2 pix;
|
||||||
if (ImHasFlag(gp.CurrentPlot->XAxis.Flags, ImPlotAxisFlags_LogScale)) {
|
if (ImHasFlag(gp.CurrentPlot->XAxis.Flags, ImPlotAxisFlags_LogScale)) {
|
||||||
|
x = x <= 0.0 ? IMPLOT_LOG_ZERO : x;
|
||||||
double t = ImLog10(x / gp.CurrentPlot->XAxis.Range.Min) / gp.LogDenX;
|
double t = ImLog10(x / gp.CurrentPlot->XAxis.Range.Min) / gp.LogDenX;
|
||||||
x = ImLerp(gp.CurrentPlot->XAxis.Range.Min, gp.CurrentPlot->XAxis.Range.Max, (float)t);
|
x = ImLerp(gp.CurrentPlot->XAxis.Range.Min, gp.CurrentPlot->XAxis.Range.Max, (float)t);
|
||||||
}
|
}
|
||||||
if (ImHasFlag(gp.CurrentPlot->YAxis[y_axis].Flags, ImPlotAxisFlags_LogScale)) {
|
if (ImHasFlag(gp.CurrentPlot->YAxis[y_axis].Flags, ImPlotAxisFlags_LogScale)) {
|
||||||
|
y = y <= 0.0 ? IMPLOT_LOG_ZERO : y;
|
||||||
double t = ImLog10(y / gp.CurrentPlot->YAxis[y_axis].Range.Min) / gp.LogDenY[y_axis];
|
double t = ImLog10(y / gp.CurrentPlot->YAxis[y_axis].Range.Min) / gp.LogDenY[y_axis];
|
||||||
y = ImLerp(gp.CurrentPlot->YAxis[y_axis].Range.Min, gp.CurrentPlot->YAxis[y_axis].Range.Max, (float)t);
|
y = ImLerp(gp.CurrentPlot->YAxis[y_axis].Range.Min, gp.CurrentPlot->YAxis[y_axis].Range.Max, (float)t);
|
||||||
}
|
}
|
||||||
|
@ -562,7 +565,6 @@ ImVec2 PlotToPixels(double x, double y, ImPlotYAxis y_axis_in) {
|
||||||
return pix;
|
return pix;
|
||||||
}
|
}
|
||||||
|
|
||||||
// This function is convenient but should not be used to process a high volume of points. Use the Transformer structs below instead.
|
|
||||||
ImVec2 PlotToPixels(const ImPlotPoint& plt, ImPlotYAxis y_axis) {
|
ImVec2 PlotToPixels(const ImPlotPoint& plt, ImPlotYAxis y_axis) {
|
||||||
return PlotToPixels(plt.x, plt.y, y_axis);
|
return PlotToPixels(plt.x, plt.y, y_axis);
|
||||||
}
|
}
|
||||||
|
|
|
@ -59,6 +59,8 @@
|
||||||
#define IMPLOT_MAX_TIME 32503680000
|
#define IMPLOT_MAX_TIME 32503680000
|
||||||
// Default label format for axis labels
|
// Default label format for axis labels
|
||||||
#define IMPLOT_LABEL_FMT "%g"
|
#define IMPLOT_LABEL_FMT "%g"
|
||||||
|
// Plot values less than or equal to 0 will be replaced with this on log scale axes
|
||||||
|
#define IMPLOT_LOG_ZERO DBL_MIN
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
// [SECTION] Macros
|
// [SECTION] Macros
|
||||||
|
@ -666,11 +668,11 @@ struct ImPlotAxis
|
||||||
void Constrain() {
|
void Constrain() {
|
||||||
Range.Min = ImConstrainNan(ImConstrainInf(Range.Min));
|
Range.Min = ImConstrainNan(ImConstrainInf(Range.Min));
|
||||||
Range.Max = ImConstrainNan(ImConstrainInf(Range.Max));
|
Range.Max = ImConstrainNan(ImConstrainInf(Range.Max));
|
||||||
if (ImHasFlag(Flags, ImPlotAxisFlags_LogScale)) {
|
if (IsLog()) {
|
||||||
Range.Min = ImConstrainLog(Range.Min);
|
Range.Min = ImConstrainLog(Range.Min);
|
||||||
Range.Max = ImConstrainLog(Range.Max);
|
Range.Max = ImConstrainLog(Range.Max);
|
||||||
}
|
}
|
||||||
if (ImHasFlag(Flags, ImPlotAxisFlags_Time)) {
|
if (IsTime()) {
|
||||||
Range.Min = ImConstrainTime(Range.Min);
|
Range.Min = ImConstrainTime(Range.Min);
|
||||||
Range.Max = ImConstrainTime(Range.Max);
|
Range.Max = ImConstrainTime(Range.Max);
|
||||||
}
|
}
|
||||||
|
|
|
@ -435,8 +435,9 @@ struct TransformerLogLin {
|
||||||
TransformerLogLin() : YAxis(GetCurrentYAxis()) {}
|
TransformerLogLin() : YAxis(GetCurrentYAxis()) {}
|
||||||
inline ImVec2 operator()(const ImPlotPoint& plt) const {
|
inline ImVec2 operator()(const ImPlotPoint& plt) const {
|
||||||
ImPlotContext& gp = *GImPlot;
|
ImPlotContext& gp = *GImPlot;
|
||||||
double t = ImLog10(plt.x / gp.CurrentPlot->XAxis.Range.Min) / gp.LogDenX;
|
double x = plt.x <= 0.0 ? IMPLOT_LOG_ZERO : plt.x;
|
||||||
double x = ImLerp(gp.CurrentPlot->XAxis.Range.Min, gp.CurrentPlot->XAxis.Range.Max, (float)t);
|
double t = ImLog10(x / gp.CurrentPlot->XAxis.Range.Min) / gp.LogDenX;
|
||||||
|
x = ImLerp(gp.CurrentPlot->XAxis.Range.Min, gp.CurrentPlot->XAxis.Range.Max, (float)t);
|
||||||
return ImVec2( (float)(gp.PixelRange[YAxis].Min.x + gp.Mx * (x - gp.CurrentPlot->XAxis.Range.Min)),
|
return ImVec2( (float)(gp.PixelRange[YAxis].Min.x + gp.Mx * (x - gp.CurrentPlot->XAxis.Range.Min)),
|
||||||
(float)(gp.PixelRange[YAxis].Min.y + gp.My[YAxis] * (plt.y - gp.CurrentPlot->YAxis[YAxis].Range.Min)) );
|
(float)(gp.PixelRange[YAxis].Min.y + gp.My[YAxis] * (plt.y - gp.CurrentPlot->YAxis[YAxis].Range.Min)) );
|
||||||
}
|
}
|
||||||
|
@ -448,8 +449,9 @@ struct TransformerLinLog {
|
||||||
TransformerLinLog() : YAxis(GetCurrentYAxis()) {}
|
TransformerLinLog() : YAxis(GetCurrentYAxis()) {}
|
||||||
inline ImVec2 operator()(const ImPlotPoint& plt) const {
|
inline ImVec2 operator()(const ImPlotPoint& plt) const {
|
||||||
ImPlotContext& gp = *GImPlot;
|
ImPlotContext& gp = *GImPlot;
|
||||||
double t = ImLog10(plt.y / gp.CurrentPlot->YAxis[YAxis].Range.Min) / gp.LogDenY[YAxis];
|
double y = plt.y <= 0.0 ? IMPLOT_LOG_ZERO : plt.y;
|
||||||
double y = ImLerp(gp.CurrentPlot->YAxis[YAxis].Range.Min, gp.CurrentPlot->YAxis[YAxis].Range.Max, (float)t);
|
double t = ImLog10(y / gp.CurrentPlot->YAxis[YAxis].Range.Min) / gp.LogDenY[YAxis];
|
||||||
|
y = ImLerp(gp.CurrentPlot->YAxis[YAxis].Range.Min, gp.CurrentPlot->YAxis[YAxis].Range.Max, (float)t);
|
||||||
return ImVec2( (float)(gp.PixelRange[YAxis].Min.x + gp.Mx * (plt.x - gp.CurrentPlot->XAxis.Range.Min)),
|
return ImVec2( (float)(gp.PixelRange[YAxis].Min.x + gp.Mx * (plt.x - gp.CurrentPlot->XAxis.Range.Min)),
|
||||||
(float)(gp.PixelRange[YAxis].Min.y + gp.My[YAxis] * (y - gp.CurrentPlot->YAxis[YAxis].Range.Min)) );
|
(float)(gp.PixelRange[YAxis].Min.y + gp.My[YAxis] * (y - gp.CurrentPlot->YAxis[YAxis].Range.Min)) );
|
||||||
}
|
}
|
||||||
|
@ -461,10 +463,12 @@ struct TransformerLogLog {
|
||||||
TransformerLogLog() : YAxis(GetCurrentYAxis()) {}
|
TransformerLogLog() : YAxis(GetCurrentYAxis()) {}
|
||||||
inline ImVec2 operator()(const ImPlotPoint& plt) const {
|
inline ImVec2 operator()(const ImPlotPoint& plt) const {
|
||||||
ImPlotContext& gp = *GImPlot;
|
ImPlotContext& gp = *GImPlot;
|
||||||
double t = ImLog10(plt.x / gp.CurrentPlot->XAxis.Range.Min) / gp.LogDenX;
|
double x = plt.x <= 0.0 ? IMPLOT_LOG_ZERO : plt.x;
|
||||||
double x = ImLerp(gp.CurrentPlot->XAxis.Range.Min, gp.CurrentPlot->XAxis.Range.Max, (float)t);
|
double y = plt.y <= 0.0 ? IMPLOT_LOG_ZERO : plt.y;
|
||||||
t = ImLog10(plt.y / gp.CurrentPlot->YAxis[YAxis].Range.Min) / gp.LogDenY[YAxis];
|
double t = ImLog10(x / gp.CurrentPlot->XAxis.Range.Min) / gp.LogDenX;
|
||||||
double y = ImLerp(gp.CurrentPlot->YAxis[YAxis].Range.Min, gp.CurrentPlot->YAxis[YAxis].Range.Max, (float)t);
|
x = ImLerp(gp.CurrentPlot->XAxis.Range.Min, gp.CurrentPlot->XAxis.Range.Max, (float)t);
|
||||||
|
t = ImLog10(y / gp.CurrentPlot->YAxis[YAxis].Range.Min) / gp.LogDenY[YAxis];
|
||||||
|
y = ImLerp(gp.CurrentPlot->YAxis[YAxis].Range.Min, gp.CurrentPlot->YAxis[YAxis].Range.Max, (float)t);
|
||||||
return ImVec2( (float)(gp.PixelRange[YAxis].Min.x + gp.Mx * (x - gp.CurrentPlot->XAxis.Range.Min)),
|
return ImVec2( (float)(gp.PixelRange[YAxis].Min.x + gp.Mx * (x - gp.CurrentPlot->XAxis.Range.Min)),
|
||||||
(float)(gp.PixelRange[YAxis].Min.y + gp.My[YAxis] * (y - gp.CurrentPlot->YAxis[YAxis].Range.Min)) );
|
(float)(gp.PixelRange[YAxis].Min.y + gp.My[YAxis] * (y - gp.CurrentPlot->YAxis[YAxis].Range.Min)) );
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue
Block a user