diff --git a/src/DLD-FUNCTIONS/__init_fltk__.cc b/src/DLD-FUNCTIONS/__init_fltk__.cc --- a/src/DLD-FUNCTIONS/__init_fltk__.cc +++ b/src/DLD-FUNCTIONS/__init_fltk__.cc @@ -1301,7 +1301,7 @@ pixel2pos (ax_obj, Fl::event_x (), Fl::event_y (), x1, y1); if (gui_mode == pan_zoom) - ap.translate_view (x0 - x1, y0 - y1); + ap.translate_view (x0, x1, y0, y1); else if (gui_mode == rotate_zoom) { double daz, del; diff --git a/src/graphics.cc b/src/graphics.cc --- a/src/graphics.cc +++ b/src/graphics.cc @@ -5977,12 +5977,6 @@ } lims = tmp_lims; } - else - { - // adjust min and max tics if they are out of limits - i1 = static_cast (std::ceil (lo / tick_sep)); - i2 = static_cast (gnulib::floor (hi / tick_sep)); - } Matrix tmp_ticks (1, i2-i1+1); for (int i = 0; i <= i2-i1; i++) @@ -6564,6 +6558,58 @@ { return x; } } +static Matrix +do_zoom (double val, double factor, const Matrix& lims, bool is_logscale) +{ + Matrix new_lims = lims; + + double lo = lims(0); + double hi = lims(1); + + bool is_negative = lo < 0 && hi < 0; + + if (is_logscale) + { + if (is_negative) + { + double tmp = hi; + hi = std::log10 (-lo); + lo = std::log10 (-tmp); + val = std::log10 (-val); + } + else + { + hi = std::log10 (hi); + lo = std::log10 (lo); + val = std::log10 (val); + } + } + + // Perform the zooming + lo = val + factor * (lo - val); + hi = val + factor * (hi - val); + + if (is_logscale) + { + if (is_negative) + { + double tmp = -std::pow (10.0, hi); + hi = -std::pow (10.0, lo); + lo = tmp; + } + else + { + lo = std::pow (10.0, lo); + hi = std::pow (10.0, hi); + } + } + + new_lims(0) = lo; + new_lims(1) = hi; + + return new_lims; +} + void axes::properties::zoom_about_point (double x, double y, double factor, bool push_to_zoom_stack) @@ -6586,11 +6632,8 @@ double max_neg_y = -octave_Inf; get_children_limits (miny, maxy, min_pos_y, max_neg_y, kids, 'y'); - // Perform the zooming - xlims (0) = x + factor * (xlims (0) - x); - xlims (1) = x + factor * (xlims (1) - x); - ylims (0) = y + factor * (ylims (0) - y); - ylims (1) = y + factor * (ylims (1) - y); + xlims = do_zoom (x, factor, xlims, xscale_is ("log")); + ylims = do_zoom (y, factor, ylims, yscale_is ("log")); zoom (xlims, ylims, push_to_zoom_stack); } @@ -6616,8 +6659,68 @@ update_ylim (false); } -void -axes::properties::translate_view (double delta_x, double delta_y) +static Matrix +do_translate (double x0, double x1, const Matrix& lims, bool is_logscale) +{ + Matrix new_lims = lims; + + double lo = lims(0); + double hi = lims(1); + + bool is_negative = lo < 0 && hi < 0; + + double delta; + + if (is_logscale) + { + if (is_negative) + { + double tmp = hi; + hi = std::log10 (-lo); + lo = std::log10 (-tmp); + x0 = -x0; + x1 = -x1; + } + else + { + hi = std::log10 (hi); + lo = std::log10 (lo); + } + + delta = std::log10 (x0) - std::log10 (x1); + } + else + { + delta = x0 - x1; + } + + // Perform the translation + lo += delta; + hi += delta; + + if (is_logscale) + { + if (is_negative) + { + double tmp = -std::pow (10.0, hi); + hi = -std::pow (10.0, lo); + lo = tmp; + } + else + { + lo = std::pow (10.0, lo); + hi = std::pow (10.0, hi); + } + } + + new_lims(0) = lo; + new_lims(1) = hi; + + return new_lims; +} + +void +axes::properties::translate_view (double x0, double x1, double y0, double y1) { // FIXME: Do we need error checking here? Matrix xlims = get_xlim ().matrix_value (); @@ -6637,10 +6740,8 @@ double max_neg_y = -octave_Inf; get_children_limits (miny, maxy, min_pos_y, max_neg_y, kids, 'y'); - xlims (0) += delta_x; - xlims (1) += delta_x; - ylims (0) += delta_y; - ylims (1) += delta_y; + xlims = do_translate (x0, x1, xlims, xscale_is ("log")); + ylims = do_translate (y0, y1, ylims, yscale_is ("log")); zoom (xlims, ylims, false); } diff --git a/src/graphics.h.in b/src/graphics.h.in --- a/src/graphics.h.in +++ b/src/graphics.h.in @@ -3663,7 +3663,7 @@ void zoom_about_point (double x, double y, double factor, bool push_to_zoom_stack = true); void zoom (const Matrix& xl, const Matrix& yl, bool push_to_zoom_stack = true); - void translate_view (double delta_x, double delta_y); + void translate_view (double x0, double x1, double y0, double y1); void rotate_view (double delta_az, double delta_el); void unzoom (void); void clear_zoom_stack (void);