Skip to content

Commit

Permalink
merge: pull request #55 from HeresJ0nny/main
Browse files Browse the repository at this point in the history
Add SetupAxisTicks for configuring custom ticks
  • Loading branch information
brenocq authored Jan 16, 2025
2 parents c861f94 + cff3927 commit 69ee921
Show file tree
Hide file tree
Showing 4 changed files with 112 additions and 3 deletions.
63 changes: 60 additions & 3 deletions implot3d.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -592,6 +592,11 @@ void RenderGrid(ImDrawList* draw_list, const ImPlot3DPlot& plot, const ImPlot3DP

// Compute position along u
float t_u = (tick.PlotPos - axis_u.Range.Min) / (axis_u.Range.Max - axis_u.Range.Min);

// Skip ticks that are out of range
if (t_u < 0.0f || t_u > 1.0f)
continue;

ImPlot3DPoint p_start = p0 + u_vec * t_u;
ImPlot3DPoint p_end = p3 + u_vec * t_u;

Expand All @@ -613,6 +618,11 @@ void RenderGrid(ImDrawList* draw_list, const ImPlot3DPlot& plot, const ImPlot3DP

// Compute position along v
float t_v = (tick.PlotPos - axis_v.Range.Min) / (axis_v.Range.Max - axis_v.Range.Min);

// Skip ticks that are out of range
if (t_v < 0.0f || t_v > 1.0f)
continue;

ImPlot3DPoint p_start = p0 + v_vec * t_v;
ImPlot3DPoint p_end = p1 + v_vec * t_v;

Expand Down Expand Up @@ -715,6 +725,9 @@ void RenderTickMarks(ImDrawList* draw_list, const ImPlot3DPlot& plot, const ImPl
const ImPlot3DTick& tick = axis.Ticker.Ticks[t];
float v = (tick.PlotPos - axis.Range.Min) / (axis.Range.Max - axis.Range.Min);

// Skip ticks that are out of range
if (v < 0.0f || v > 1.0f)
continue;
ImPlot3DPoint tick_pos_ndc = PlotToNDC(axis_start + axis_dir * (v * axis_len));

// Half tick on each side of the axis line
Expand Down Expand Up @@ -805,6 +818,10 @@ void RenderTickLabels(ImDrawList* draw_list, const ImPlot3DPlot& plot, const ImP

// Compute position along the axis
float t_axis = (tick.PlotPos - axis.Range.Min) / (axis.Range.Max - axis.Range.Min);

// Skip ticks that are out of range
if (t_axis < 0.0f || t_axis > 1.0f)
continue;
ImPlot3DPoint tick_pos = axis_start + axis_dir * t_axis;

// Convert to pixel coordinates
Expand Down Expand Up @@ -1106,6 +1123,15 @@ void Locator_Default(ImPlot3DTicker& ticker, const ImPlot3DRange& range, float p
}
}

void AddTicksCustom(const double* values, const char* const labels[], int n, ImPlot3DTicker& ticker, ImPlot3DFormatter formatter, void* data) {
for (int i = 0; i < n; ++i) {
if (labels != nullptr)
ticker.AddTick(values[i], false, true, labels[i]);
else
ticker.AddTick(values[i], false, true, formatter, data);
}
}

//------------------------------------------------------------------------------
// [SECTION] Context Menus
//------------------------------------------------------------------------------
Expand Down Expand Up @@ -1329,6 +1355,11 @@ bool BeginPlot(const char* title_id, const ImVec2& size, ImPlot3DFlags flags) {
// Reset legend
plot.Items.Legend.Reset();

// Reset axes
for (int i = 0; i < ImAxis3D_COUNT; ++i) {
plot.Axes[i].Reset();
}

// Push frame rect clipping
ImGui::PushClipRect(plot.FrameRect.Min, plot.FrameRect.Max, true);
plot.DrawList._Flags = window->DrawList->Flags;
Expand Down Expand Up @@ -1461,6 +1492,31 @@ void SetupAxisFormat(ImAxis3D idx, ImPlot3DFormatter formatter, void* data) {
axis.FormatterData = data;
}

void SetupAxisTicks(ImAxis3D idx, const double* values, int n_ticks, const char* const labels[], bool keep_default) {
ImPlot3DContext& gp = *GImPlot3D;
IM_ASSERT_USER_ERROR(gp.CurrentPlot != nullptr && !gp.CurrentPlot->SetupLocked,
"Setup needs to be called after BeginPlot and before any setup locking functions (e.g. PlotX)!");
ImPlot3DPlot& plot = *gp.CurrentPlot;
ImPlot3DAxis& axis = plot.Axes[idx];
axis.ShowDefaultTicks = keep_default;
AddTicksCustom(values,
labels,
n_ticks,
axis.Ticker,
axis.Formatter ? axis.Formatter : Formatter_Default,
(axis.Formatter && axis.FormatterData) ? axis.FormatterData : (void*)IMPLOT3D_LABEL_FORMAT);
}

void SetupAxisTicks(ImAxis3D idx, double v_min, double v_max, int n_ticks, const char* const labels[], bool keep_default) {
ImPlot3DContext& gp = *GImPlot3D;
IM_ASSERT_USER_ERROR(gp.CurrentPlot != nullptr && !gp.CurrentPlot->SetupLocked,
"Setup needs to be called after BeginPlot and before any setup locking functions (e.g. PlotX)!");
n_ticks = n_ticks < 2 ? 2 : n_ticks;
ImVector<double> temp;
FillRange(temp, n_ticks, v_min, v_max);
SetupAxisTicks(idx, temp.Data, n_ticks, labels, keep_default);
}

void SetupAxes(const char* x_label, const char* y_label, const char* z_label, ImPlot3DAxisFlags x_flags, ImPlot3DAxisFlags y_flags, ImPlot3DAxisFlags z_flags) {
SetupAxis(ImAxis3D_X, x_label, x_flags);
SetupAxis(ImAxis3D_Y, y_label, y_flags);
Expand Down Expand Up @@ -2093,9 +2149,10 @@ void SetupLock() {
// Compute ticks
for (int i = 0; i < 3; i++) {
ImPlot3DAxis& axis = plot.Axes[i];
axis.Ticker.Reset();
float pixels = plot.GetBoxZoom() * plot.BoxScale[i];
axis.Locator(axis.Ticker, axis.Range, pixels, axis.Formatter, axis.FormatterData);
if (axis.ShowDefaultTicks) {
float pixels = plot.GetBoxZoom() * plot.BoxScale[i];
axis.Locator(axis.Ticker, axis.Range, pixels, axis.Formatter, axis.FormatterData);
}
}

// Render title
Expand Down
6 changes: 6 additions & 0 deletions implot3d.h
Original file line number Diff line number Diff line change
Expand Up @@ -364,6 +364,12 @@ IMPLOT3D_API void SetupAxisLimits(ImAxis3D axis, double v_min, double v_max, ImP

IMPLOT3D_API void SetupAxisFormat(ImAxis3D idx, ImPlot3DFormatter formatter, void* data = nullptr);

// Sets an axis' ticks and optionally the labels. To keep the default ticks, set #keep_default=true
IMPLOT3D_API void SetupAxisTicks(ImAxis3D axis, const double* values, int n_ticks, const char* const labels[] = nullptr, bool keep_default = false);

// Sets an axis' ticks and optionally the labels for the next plot. To keep the default ticks, set #keep_default=true
IMPLOT3D_API void SetupAxisTicks(ImAxis3D axis, double v_min, double v_max, int n_ticks, const char* const labels[] = nullptr, bool keep_default = false);

// Sets the label and/or flags for primary X/Y/Z axes (shorthand for three calls to SetupAxis)
IMPLOT3D_API void SetupAxes(const char* x_label, const char* y_label, const char* z_label, ImPlot3DAxisFlags x_flags = 0, ImPlot3DAxisFlags y_flags = 0, ImPlot3DAxisFlags z_flags = 0);

Expand Down
24 changes: 24 additions & 0 deletions implot3d_demo.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -565,6 +565,29 @@ void DemoBoxScale() {
}
}

void DemoTickLabels() {
static bool custom_ticks = false;
static bool custom_labels = true;
ImGui::Checkbox("Show Custom Ticks", &custom_ticks);
if (custom_ticks) {
ImGui::SameLine();
ImGui::Checkbox("Show Custom Labels", &custom_labels);
}
const double pi = 3.14;
const char* pi_str[] = {"PI"};
static double letters_ticks[] = {0.0, 0.2, 0.4, 0.6, 0.8, 1.0};
static const char* letters_labels[] = {"A", "B", "C", "D", "E", "F"};
if (ImPlot3D::BeginPlot("##Ticks")) {
ImPlot3D::SetupAxesLimits(2, 5, 0, 1, 0, 1);
if (custom_ticks) {
ImPlot3D::SetupAxisTicks(ImAxis3D_X, &pi, 1, custom_labels ? pi_str : nullptr, true);
ImPlot3D::SetupAxisTicks(ImAxis3D_Y, letters_ticks, 6, custom_labels ? letters_labels : nullptr, false);
ImPlot3D::SetupAxisTicks(ImAxis3D_Z, 0, 1, 6, custom_labels ? letters_labels : nullptr, false);
}
ImPlot3D::EndPlot();
}
}

//-----------------------------------------------------------------------------
// [SECTION] Custom
//-----------------------------------------------------------------------------
Expand Down Expand Up @@ -753,6 +776,7 @@ void ShowDemoWindow(bool* p_open) {
}
if (ImGui::BeginTabItem("Axes")) {
DemoHeader("Box Scale", DemoBoxScale);
DemoHeader("Tick Labels", DemoTickLabels);
ImGui::EndTabItem();
}
if (ImGui::BeginTabItem("Custom")) {
Expand Down
22 changes: 22 additions & 0 deletions implot3d_internal.h
Original file line number Diff line number Diff line change
Expand Up @@ -97,6 +97,16 @@ static inline ImU32 ImMixU32(ImU32 a, ImU32 b, ImU32 s) {
#endif
}

// Fills a buffer with n samples linear interpolated from vmin to vmax
template <typename T>
void FillRange(ImVector<T>& buffer, int n, T vmin, T vmax) {
buffer.resize(n);
T step = (vmax - vmin) / (n - 1);
for (int i = 0; i < n; ++i) {
buffer[i] = vmin + i * step;
}
}

} // namespace ImPlot3D

//-----------------------------------------------------------------------------
Expand Down Expand Up @@ -440,6 +450,7 @@ struct ImPlot3DAxis {
ImPlot3DFormatter Formatter;
void* FormatterData;
ImPlot3DLocator Locator;
bool ShowDefaultTicks;
// Fit data
bool FitThisFrame;
ImPlot3DRange FitExtents;
Expand All @@ -458,6 +469,7 @@ struct ImPlot3DAxis {
Formatter = nullptr;
FormatterData = nullptr;
Locator = nullptr;
ShowDefaultTicks = true;
// Fit data
FitThisFrame = true;
FitExtents.Min = HUGE_VAL;
Expand All @@ -467,6 +479,16 @@ struct ImPlot3DAxis {
Held = false;
}

inline void Reset() {
Formatter = nullptr;
FormatterData = nullptr;
Locator = nullptr;
ShowDefaultTicks = true;
FitExtents.Min = HUGE_VAL;
FitExtents.Max = -HUGE_VAL;
Ticker.Reset();
}

inline void SetRange(double v1, double v2) {
Range.Min = (float)ImMin(v1, v2);
Range.Max = (float)ImMax(v1, v2);
Expand Down

0 comments on commit 69ee921

Please sign in to comment.