# HG changeset patch # User Konstantinos Poulios # Date 1288267966 -7200 # Branch aspectratios # Node ID 696408fe822199cc896cdc580967c3284e7c7d59 # Parent 2e32236eaa90d6b4b00bfd7648f34da8583b7dee aspectratios diff -r 2e32236eaa90 -r 696408fe8221 src/ChangeLog --- a/src/ChangeLog Thu Oct 28 13:22:49 2010 +0800 +++ b/src/ChangeLog Thu Oct 28 14:12:46 2010 +0200 @@ -1,3 +1,26 @@ +2010-10-28 Konstantinos Poulios + + * graphics.cc (normalized_aspectratios, max_axes_scale): + New file-scope static function + (updating_aspectratios): New file-scope variable. + (axes::properties::update_aspectratios, axes::update_axis_limits): + Return immediately if updating_aspecratios is true. + (axes::properties::update_aspectratios): + If dataaspectratiomode is set to manual this function will try to + respect it even after changes in xlim, ylim, zlim. + If both dataaspectratiomode and plotboxaspectratiomode is set to + manual this function will try to recalulate xlim, ylim, zlim + depending on the status of xlimmode, ylimmode, zlimmode. If + altering xlim, ylim, zlim is not possible, plotboxaspectratio will + be overriden. + * graphics.h.in (class axes::properties): Tag dataaspectratio, + dataaspectratiomode, plotboxaspectratio, and + plotboxaspectratiomode with "u" qualifier. + (axes::update_dataaspectratio, + axes::update_dataaspectratiomode, + axes::update_plotboxaspectratio, + axes::update_plotboxaspectratiomode): New functions. + 2010-10-25 John W. Eaton * octave.cc (octave_main): Use F77_CHAR_ARC_LEN macro to pass diff -r 2e32236eaa90 -r 696408fe8221 src/graphics.cc --- a/src/graphics.cc Thu Oct 28 13:22:49 2010 +0800 +++ b/src/graphics.cc Thu Oct 28 14:12:46 2010 +0200 @@ -3911,9 +3911,51 @@ x_gl_mat2 = x_viewport * x_projection; } +static void +normalized_aspectratios(Matrix& aspectratios, const Matrix& scalefactors, + double xlength, double ylength, double zlength) +{ + double xval = xlength/scalefactors(0); + double yval = ylength/scalefactors(1); + double zval = zlength/scalefactors(2); + + double minval = xmin (xmin (xval, yval), zval); + + aspectratios(0) = xval/minval; + aspectratios(1) = yval/minval; + aspectratios(2) = zval/minval; +} + +static void +max_axes_scale(double& s, Matrix& limits, const Matrix& kids, + double pbfactor, double dafactor, char limit_type, bool tight) +{ + if (tight) + { + double minval = octave_Inf; + double maxval = -octave_Inf; + double min_pos = octave_Inf; + get_children_limits (minval, maxval, min_pos, kids, limit_type); + if (!xisinf (minval) && !xisnan (minval) + && !xisinf (maxval) && !xisnan (maxval)) + { + limits(0) = minval; + limits(1) = maxval; + s = xmax(s, (maxval - minval) / (pbfactor * dafactor)); + } + } + else + s = xmax(s, (limits(1) - limits(0)) / (pbfactor * dafactor)); +} + +static bool updating_aspectratios = false; + void axes::properties::update_aspectratios (void) { + if (updating_aspectratios) + return; + Matrix xlimits = get_xlim ().matrix_value (); Matrix ylimits = get_ylim ().matrix_value (); Matrix zlimits = get_zlim ().matrix_value (); @@ -3922,35 +3964,102 @@ double dy = (ylimits(1)-ylimits(0)); double dz = (zlimits(1)-zlimits(0)); + Matrix da = get_dataaspectratio ().matrix_value (); + Matrix pba = get_plotboxaspectratio ().matrix_value (); + if (dataaspectratiomode_is ("auto")) { - double dmin = xmin (xmin (dx, dy), dz); - Matrix da (1, 3, 0.0); - - da(0) = dx/dmin; - da(1) = dy/dmin; - da(2) = dz/dmin; - - dataaspectratio = da; - } - - if (plotboxaspectratiomode_is ("auto")) - { - if (dataaspectratiomode_is ("auto")) - plotboxaspectratio = Matrix (1, 3, 1.0); + if (plotboxaspectratiomode_is ("auto")) + { + pba = Matrix (1, 3, 1.0); + plotboxaspectratio.set (pba, false); + } + + normalized_aspectratios(da, pba, dx, dy, dz); + dataaspectratio.set (da, false); + } + else if (plotboxaspectratiomode_is ("auto")) + { + normalized_aspectratios(pba, da, dx, dy, dz); + plotboxaspectratio.set (pba, false); + } + else + { + double s = -octave_Inf; + bool modified_limits = false; + Matrix kids; + + if (xlimmode_is ("auto") && ylimmode_is ("auto") && zlimmode_is ("auto")) + { + modified_limits = true; + kids = get_children (); + max_axes_scale(s, xlimits, kids, pba(0), da(0), 'x', true); + max_axes_scale(s, ylimits, kids, pba(1), da(1), 'y', true); + max_axes_scale(s, zlimits, kids, pba(2), da(2), 'z', true); + } + else if (xlimmode_is ("auto") && ylimmode_is ("auto")) + { + modified_limits = true; + max_axes_scale(s, zlimits, kids, pba(2), da(2), 'z', false); + } + else if (ylimmode_is ("auto") && zlimmode_is ("auto")) + { + modified_limits = true; + max_axes_scale(s, xlimits, kids, pba(0), da(0), 'x', false); + } + else if (zlimmode_is ("auto") && xlimmode_is ("auto")) + { + modified_limits = true; + max_axes_scale(s, ylimits, kids, pba(1), da(1), 'y', false); + } + + if (modified_limits) + { + + unwind_protect frame; + frame.protect_var (updating_aspectratios); + + updating_aspectratios = true; + + dx = pba(0) *da(0); + dy = pba(1) *da(1); + dz = pba(2) *da(2); + if (xisinf (s)) + s = 1 / xmin (xmin (dx, dy), dz); + + if (xlimmode_is ("auto")) + { + dx = s * dx; + xlimits(0) = 0.5 * (xlimits(0) + xlimits(1) - dx); + xlimits(1) = xlimits(0) + dx; + set_xlim(xlimits); + set_xlimmode("auto"); + } + + if (ylimmode_is ("auto")) + { + dy = s * dy; + ylimits(0) = 0.5 * (ylimits(0) + ylimits(1) - dy); + ylimits(1) = ylimits(0) + dy; + set_ylim(ylimits); + set_ylimmode("auto"); + } + + if (zlimmode_is ("auto")) + { + dz = s * dz; + zlimits(0) = 0.5 * (zlimits(0) + zlimits(1) - dz); + zlimits(1) = zlimits(0) + dz; + set_zlim(zlimits); + set_zlimmode("auto"); + } + } else { - Matrix da = get_dataaspectratio ().matrix_value (); - Matrix pba (1, 3, 0.0); - - pba(0) = dx/da(0); - pba(1) = dy/da(1); - pba(2) = dz/da(2); + normalized_aspectratios(pba, da, dx, dy, dz); + plotboxaspectratio.set (pba, false); } } - - // FIXME -- if plotboxaspectratiomode is "manual", limits - // and/or dataaspectratio might be adapted. } // The INTERNAL flag defines whether position or outerposition is used. @@ -4448,7 +4557,7 @@ void axes::update_axis_limits (const std::string& axis_type) { - if (updating_axis_limits) + if (updating_axis_limits || updating_aspectratios) return; Matrix kids = xproperties.get_children (); diff -r 2e32236eaa90 -r 696408fe8221 src/graphics.h.in --- a/src/graphics.h.in Thu Oct 28 13:22:49 2010 +0800 +++ b/src/graphics.h.in Thu Oct 28 14:12:46 2010 +0200 @@ -2911,8 +2911,8 @@ array_property position u , default_axes_position () bool_property box , "on" array_property colororder , default_colororder () - array_property dataaspectratio m , Matrix (1, 3, 1.0) - radio_property dataaspectratiomode , "{auto}|manual" + array_property dataaspectratio mu , Matrix (1, 3, 1.0) + radio_property dataaspectratiomode u , "{auto}|manual" radio_property layer , "{bottom}|top" row_vector_property xlim mu , default_lim () row_vector_property ylim mu , default_lim () @@ -2988,8 +2988,8 @@ string_array_property linestyleorder , "-" double_property linewidth , 0.5 radio_property minorgridlinestyle , "-|--|{:}|-.|none" - array_property plotboxaspectratio m , Matrix (1, 3, 1.0) - radio_property plotboxaspectratiomode , "{auto}|manual" + array_property plotboxaspectratio mu , Matrix (1, 3, 1.0) + radio_property plotboxaspectratiomode u , "{auto}|manual" radio_property projection , "{orthographic}|perpective" radio_property tickdir m , "{in}|out" radio_property tickdirmode , "{auto}|manual" @@ -3014,6 +3014,10 @@ void update_zscale (void) { sz = get_zscale (); } void update_view (void) { update_camera (); } + void update_dataaspectratio (void) { update_transform (); } + void update_dataaspectratiomode (void) { update_transform (); } + void update_plotboxaspectratio (void) { update_transform (); } + void update_plotboxaspectratiomode (void) { update_transform (); } void update_xdir (void) { update_camera (); } void update_ydir (void) { update_camera (); }