epezent / implot

Immediate Mode Plotting
MIT License
4.78k stars 531 forks source link

Support for custom axis scaling functions? #346

Closed clo-yunhee closed 2 years ago

clo-yunhee commented 2 years ago

So I'm making an audio analysis app using ImGui, and I wanted to be able to plot frequency in other scales than linear or log (mel, erb, bark, etc.) Maybe it would be nice to be able to provide a custom scaling function for the values? The way I'm doing it atm is plotting as linear and doing the conversion beforehand, and then using a custom label formatter, but it's super janky

epezent commented 2 years ago

Custom scales are now possible with SetupAxisScale (see https://github.com/epezent/implot/discussions/370#discussioncomment-2978803). Note that this is somewhat experimental in the sense that scaling will work correctly, but tick placement may not be optimal for the desired scale. Sometime in the future, we may expose custom tick Locators for this purpose. Let me know how this works for your application and we'll go from there. Thanks!

// Callback signature for axis transform.
typedef double (*ImPlotTransform)(double value, void* user_data);

// Sets an axis' scale using user supplied forward and inverse transfroms.
void SetupAxisScale(ImAxis axis, ImPlotTransform forward, ImPlotTransform inverse, void* data=NULL);

Example:

static inline double TransformForward_Sqrt(double v, void*) {
    return sqrt(v);
}

static inline double TransformInverse_Sqrt(double v, void*) {
    return v*v;
}

...

if (ImPlot::BeginPlot("Sqrt")) {
    ImPlot::SetupAxis(ImAxis_X1, "Linear");
    ImPlot::SetupAxis(ImAxis_Y1, "Sqrt");
    ImPlot::SetupAxisScale(ImAxis_Y1, TransformForward_Sqrt, TransformInverse_Sqrt);
    ImPlot::PlotLine(...);
    ImPlot::EndPlot();
}

image