# HG changeset patch # User jwe # Date 1201560286 0 # Node ID 65f0a8ced9d2d0b411893cc47081603ee6935b3f # Parent b9df9abdffbbc7f4b1d7b5c7787c1c7a03d0a83b [project @ 2008-01-28 22:42:18 by jwe] diff --git a/src/ChangeLog b/src/ChangeLog --- a/src/ChangeLog +++ b/src/ChangeLog @@ -1,3 +1,49 @@ +2008-01-28 Michael Goffioul + + * genprops.awk: Add update ('u') modifier and document the + readonly ('r') modifier. + * graphics.h.in (class base_scaler, class lin_scaler, class + log_scaler, class scaler): New classes to make abstraction of the + axis scale. + (base_graphics_backend::get_screen_resolution, + graphics_backend::get_screen_resolution): New methods. + (axes::properties::sx, axes::properties::sy, + axes::properties::sz): New scaler fields. + (axes::properties::get_x_scaler, axes::properties::get_y_scaler, + axes::properties::get_z_scaler): New accessors. + (axes::properties::x_render, axes::properties::x_render_inv, + axes::properties::x_gl_mat1, axes::properties::x_gl_mat2, + axes::properties::x_zlim): New utility Matrix fields. + (axes::properties::get_boundingbox, + axes::properties::update_camera, + axes::properites::update_aspectratios, + axes::properties::update_transform, + axes::properties::update_xscale, axes::properties::update_yscale, + axes::properties::update_zscale, axes::properties::update_view, + axes::properties::update_xdir, axes::properties::update_ydir, + axes::properties::update_zdir): New updater methods. + (axes::properties::init): Initialize sx, sy, sz and x_zlim correctly. + (axes::properties::position): Use valid default position value. + (axes::properties::xscale, axes::properties::yscale, + axes::properties::zscale, axes::properties::xdir, + axes::properties::ydir, axes::properties::zdir, + axes::properties::view): Add updater ('u') property modifier. + * graphics.cc (default_axes_position, default_axes_outerposition): + New initializers. + (convert_position): New utility function to convert position + according to specified units. + (gnuplot_backend::get_screen_resolution): New method. + (axes::properties::set_defaults): Initilize recently added properties. + (xform_matrix, xform_vector, transform, xform_scale, + xform_translate, scale, translate, xform, normalize, dot, cross, + unit_cube, cam2xform, xform2cam): New inline transformation + utility functions. + (axes::properties::update_camera, + axes::properties::update_aspectratios, + axes::properties::get_boundingbox): New updater methods for + computing transformation matrices. + (axes::update_axis_limits): Update transformation data. + 2008-01-28 John W. Eaton * oct-stream.cc (BEGIN_CHAR_CLASS_CONVERSION): Handle width properly. diff --git a/src/genprops.awk b/src/genprops.awk --- a/src/genprops.awk +++ b/src/genprops.awk @@ -108,6 +108,19 @@ ## ## h: Make the property hidden ## +## r: Make the property read-only. A read-only property is not +## settable from the global set (caseless_str, octave_value) +## method, but still has set_X accessor. +## +## u: The property has an updater method. This effectively add +## the line +## +## update_NAME (); +## +## to the type-specific set function. This line is added before +## any other update call (like those added by the 'l' or 'm' +## modifiers. +## ## The 'o' and 'O' qualifiers are only useful when the the property type ## is something other than octave_value. @@ -275,6 +288,8 @@ { printf ("\n {\n if (! error_state)\n {\n %s = val;\n", name[i]); + if (updater[i]) + printf (" %s ();\n", updater[i]); if (limits[i]) printf (" update_axis_limits (\"%s\");\n", name[i]); if (mode[i]) @@ -465,6 +480,7 @@ emit_get[idx] = "definition"; emit_set[idx] = "definition"; defval[idx] = ""; + updater[idx] = ""; ## if (type[idx] == "octave_value") ## emit_ov_set[idx] = ""; ## else @@ -510,6 +526,11 @@ if (index (quals, "r")) readonly[idx] = 1; + ## There is an updater method that should be called + ## from the set method + if (index (quals, "u")) + updater[idx] = ("update_" name[idx]); + ## ## emmit an asignment set function ## if (index (quals, "a")) ## emit_ov_set[idx] = "assignment"; diff --git a/src/graphics.cc b/src/graphics.cc --- a/src/graphics.cc +++ b/src/graphics.cc @@ -142,6 +142,25 @@ return retval; } +static Matrix +default_axes_position (void) +{ + Matrix m (1, 4, 0.0); + m(0) = 0.13; + m(1) = 0.11; + m(2) = 0.775; + m(3) = 0.815; + return m; +} + +static Matrix +default_axes_outerposition (void) +{ + Matrix m (1, 4, 0.0); + m(2) = m(3) = 1.0; + return m; +} + // NOTE: "cb" is passed by value, because "function_value" method // is non-const; passing "cb" by const-reference is not // possible @@ -200,6 +219,90 @@ END_INTERRUPT_WITH_EXCEPTIONS; } +static Matrix +convert_position (const Matrix& pos, const caseless_str& from_units, + const caseless_str& to_units, + const Matrix& parent_dim = Matrix (1, 2, 0.0), + const graphics_backend& backend = graphics_backend ()) +{ + Matrix retval (1, 4); + double res = 0; + + if (from_units.compare ("pixels")) + retval = pos; + else if (from_units.compare ("normalized")) + { + retval(0) = pos(0) * parent_dim(0) + 1; + retval(1) = pos(1) * parent_dim(1) + 1; + retval(2) = pos(2) * parent_dim(0); + retval(3) = pos(3) * parent_dim(1); + } + else if (from_units.compare ("characters")) + { + // FIXME: implement this + } + else + { + res = backend.get_screen_resolution (); + + double f = 0.0; + + if (from_units.compare ("points")) + f = res / 72.0; + else if (from_units.compare ("inches")) + f = res; + else if (from_units.compare ("centimeters")) + f = res / 2.54; + + if (f > 0) + { + retval(0) = pos(0) * f + 1; + retval(1) = pos(1) * f + 1; + retval(2) = pos(2) * f; + retval(3) = pos(3) * f; + } + } + + if (! to_units.compare ("pixels")) + { + if (to_units.compare ("normalized")) + { + retval(0) = (retval(0) - 1) / parent_dim(0); + retval(1) = (retval(1) - 1) / parent_dim(1); + retval(2) /= parent_dim(0); + retval(3) /= parent_dim(1); + } + else if (to_units.compare ("characters")) + { + // FIXME: implement this + } + else + { + if (res <= 0) + res = backend.get_screen_resolution (); + + double f = 0.0; + + if (to_units.compare ("points")) + f = res / 72.0; + else if (to_units.compare ("inches")) + f = res; + else if (to_units.compare ("centimeters")) + f = res / 2.54; + + if (f > 0) + { + retval(0) = (retval(0) - 1) / f; + retval(1) = (retval(1) - 1) / f; + retval(2) /= f; + retval(3) /= f; + } + } + } + + return retval; +} + // --------------------------------------------------------------------- radio_values::radio_values (const std::string& opt_string) @@ -1208,7 +1311,13 @@ } Matrix get_canvas_size (const graphics_handle&) const - { return Matrix (1, 2, 0.0); } + { + Matrix sz (1, 2, 0.0); + return sz; + } + + double get_screen_resolution (void) const + { return 72.0; } }; graphics_backend @@ -1365,7 +1474,7 @@ axes::properties::set_defaults (base_graphics_object& obj, const std::string& mode) { - position = Matrix (); + position = default_axes_position (); title = graphics_handle (); box = "on"; key = "off"; @@ -1424,6 +1533,34 @@ yaxislocation = "left"; xaxislocation = "bottom"; + // Note: camera properties will be set through update_transform + camerapositionmode = "auto"; + cameratargetmode = "auto"; + cameraupvectormode = "auto"; + cameraviewanglemode = "auto"; + plotboxaspectratio = Matrix (1, 3, 1.0); + drawmode = "normal"; + fontangle = "normal"; + fontname = "Helvetica"; + fontsize = 12; + fontunits = "points"; + fontweight = "normal"; + gridlinestyle = "-"; + linestyleorder = "-"; + linewidth = 0.5; + minorgridlinestyle = "-"; + // Note: plotboxaspectratio will be set through update_aspectratiors + plotboxaspectratiomode = "auto"; + projection = "orthographic"; + tickdir = "in"; + tickdirmode = "auto"; + ticklength = Matrix (1, 2, 0.1); + tightinset = Matrix (1, 4, 0.0); + + sx = "linear"; + sy = "linear"; + sz = "linear"; + Matrix tview (1, 2, 0.0); tview(1) = 90; view = tview; @@ -1449,6 +1586,8 @@ children = Matrix (); + update_transform (); + override_defaults (obj); } @@ -1514,6 +1653,421 @@ gh_manager::free (zlabel.handle_value ()); } +inline Matrix +xform_matrix (void) +{ + Matrix m (4, 4, 0.0); + for (int i = 0; i < 4; i++) + m(i,i) = 1; + return m; +} + +inline ColumnVector +xform_vector (void) +{ + ColumnVector v (4, 0.0); + v(3) = 1; + return v; +} + +inline ColumnVector +xform_vector (double x, double y, double z) +{ + ColumnVector v (4, 1.0); + v(0) = x; v(1) = y; v(2) = z; + return v; +} + +inline ColumnVector +transform (const Matrix& m, double x, double y, double z) +{ + return (m * xform_vector (x, y, z)); +} + +inline Matrix +xform_scale (double x, double y, double z) +{ + Matrix m (4, 4, 0.0); + m(0,0) = x; m(1,1) = y; m(2,2) = z; m(3,3) = 1; + return m; +} + +inline Matrix +xform_translate (double x, double y, double z) +{ + Matrix m = xform_matrix (); + m(0,3) = x; m(1,3) = y; m(2,3) = z; m(3,3) = 1; + return m; +} + +inline void +scale (Matrix& m, double x, double y, double z) +{ + m = m * xform_scale (x, y, z); +} + +inline void +translate (Matrix& m, double x, double y, double z) +{ + m = m * xform_translate (x, y, z); +} + +inline void +xform (ColumnVector& v, const Matrix& m) +{ + v = m*v; +} + +inline void +scale (ColumnVector& v, double x, double y, double z) +{ + v(0) *= x; + v(1) *= y; + v(2) *= z; +} + +inline void +translate (ColumnVector& v, double x, double y, double z) +{ + v(0) += x; + v(1) += y; + v(2) += z; +} + +inline void +normalize (ColumnVector& v) +{ + double fact = 1.0/sqrt(v(0)*v(0)+v(1)*v(1)+v(2)*v(2)); + scale (v, fact, fact, fact); +} + +inline double +dot (const ColumnVector& v1, const ColumnVector& v2) +{ + return (v1(0)*v2(0)+v1(1)*v2(1)+v1(2)*v2(2)); +} + +inline double +norm (const ColumnVector& v) +{ + return sqrt (dot (v, v)); +} + +inline ColumnVector +cross (const ColumnVector& v1, const ColumnVector& v2) +{ + ColumnVector r = xform_vector (); + r(0) = v1(1)*v2(2)-v1(2)*v2(1); + r(1) = v1(2)*v2(0)-v1(0)*v2(2); + r(2) = v1(0)*v2(1)-v1(1)*v2(0); + return r; +} + +inline Matrix +unit_cube (void) +{ + static double data[32] = { + 0,0,0,1, + 1,0,0,1, + 0,1,0,1, + 0,0,1,1, + 1,1,0,1, + 1,0,1,1, + 0,1,1,1, + 1,1,1,1}; + Matrix m (4, 8); + memcpy (m.fortran_vec (), data, sizeof(double)*32); + return m; +} + +inline ColumnVector +cam2xform (const Array& m) +{ + ColumnVector retval (4, 1.0); + memcpy (retval.fortran_vec (), m.fortran_vec (), sizeof(double)*3); + return retval; +} + +inline RowVector +xform2cam (const ColumnVector& v) +{ + return v.extract_n (0, 3).transpose (); +} + +void +axes::properties::update_camera (void) +{ + double xd = (xdir_is ("normal") ? 1 : -1); + double yd = (ydir_is ("normal") ? 1 : -1); + double zd = (zdir_is ("normal") ? 1 : -1); + + Matrix xlim = sx.scale (get_xlim ().matrix_value ()); + Matrix ylim = sy.scale (get_ylim ().matrix_value ()); + Matrix zlim = sz.scale (get_zlim ().matrix_value ()); + + double xo = xlim(xd > 0 ? 0 : 1); + double yo = ylim(yd > 0 ? 0 : 1); + double zo = zlim(zd > 0 ? 0 : 1); + + Matrix pb = get_plotboxaspectratio ().matrix_value (); + + bool autocam = (camerapositionmode_is ("auto") + && cameratargetmode_is ("auto") + && cameraupvectormode_is ("auto") + && cameraviewanglemode_is ("auto")); + bool dowarp = (autocam && dataaspectratiomode_is("auto") + && plotboxaspectratiomode_is ("auto")); + + ColumnVector c_eye (xform_vector ()); + ColumnVector c_center (xform_vector ()); + ColumnVector c_upv (xform_vector ()); + + if (cameratargetmode_is ("auto")) + { + c_center(0) = (xlim(0)+xlim(1))/2; + c_center(1) = (ylim(0)+ylim(1))/2; + c_center(2) = (zlim(0)+zlim(1))/2; + + cameratarget = xform2cam (c_center); + } + else + c_center = cam2xform (get_cameratarget ().matrix_value ()); + + if (camerapositionmode_is ("auto")) + { + Matrix view = get_view ().matrix_value (); + double az = view(0), el = view(1); + double d = 5*sqrt(pb(0)*pb(0)+pb(1)*pb(1)+pb(2)*pb(2)); + + if (el == 90 || el == -90) + c_eye(2) = d*signum(el); + else + { + az *= M_PI/180.0; + el *= M_PI/180.0; + c_eye(0) = d*cos(el)*sin(az); + c_eye(1) = -d*cos(el)*cos(az); + c_eye(2) = d*sin(el); + } + c_eye(0) = c_eye(0)*(xlim(1)-xlim(0))/(xd*pb(0))+c_center(0); + c_eye(1) = c_eye(1)*(ylim(1)-ylim(0))/(yd*pb(1))+c_center(1); + c_eye(2) = c_eye(2)*(zlim(1)-zlim(0))/(zd*pb(2))+c_center(2); + + cameraposition = xform2cam (c_eye); + } + else + c_eye = cam2xform (get_cameraposition ().matrix_value ()); + + if (cameraupvectormode_is ("auto")) + { + Matrix view = get_view ().matrix_value (); + double az = view(0), el = view(1); + + if (el == 90 || el == -90) + { + c_upv(0) = -sin(az*M_PI/180.0)*(xlim(1)-xlim(0))/pb(0); + c_upv(1) = cos(az*M_PI/180.0)*(ylim(1)-ylim(0))/pb(1); + } + else + c_upv(2) = 1; + + cameraupvector = xform2cam (c_upv); + } + else + c_upv = cam2xform (get_cameraupvector ().matrix_value ()); + + Matrix x_view = xform_matrix (); + Matrix x_projection = xform_matrix (); + Matrix x_viewport = xform_matrix (); + Matrix x_normrender = xform_matrix (); + Matrix x_pre = xform_matrix (); + + x_render = xform_matrix (); + x_render_inv = xform_matrix (); + + scale (x_pre, pb(0), pb(1), pb(2)); + translate (x_pre, -0.5, -0.5, -0.5); + scale (x_pre, xd/(xlim(1)-xlim(0)), yd/(ylim(1)-ylim(0)), + zd/(zlim(1)-zlim(0))); + translate (x_pre, -xo, -yo, -zo); + + xform (c_eye, x_pre); + xform (c_center, x_pre); + scale (c_upv, pb(0)/(xlim(1)-xlim(0)), pb(1)/(ylim(1)-ylim(0)), + pb(2)/(zlim(1)-zlim(0))); + translate (c_center, -c_eye(0), -c_eye(1), -c_eye(2)); + + ColumnVector F (c_center), f (F), UP (c_upv); + normalize (f); + normalize (UP); + + if (abs (dot (f, UP)) > 1e-15) + { + double fa = 1/sqrt(1-f(2)*f(2)); + scale (UP, fa, fa, fa); + } + + ColumnVector s = cross (f, UP); + ColumnVector u = cross (s, f); + + scale (x_view, 1, 1, -1); + Matrix l = xform_matrix (); + l(0,0) = s(0); l(0,1) = s(1); l(0,2) = s(2); + l(1,0) = u(0); l(1,1) = u(1); l(1,2) = u(2); + l(2,0) = -f(0); l(2,1) = -f(1); l(2,2) = -f(2); + x_view = x_view * l; + translate (x_view, -c_eye(0), -c_eye(1), -c_eye(2)); + scale (x_view, pb(0), pb(1), pb(2)); + translate (x_view, -0.5, -0.5, -0.5); + + Matrix x_cube = x_view * unit_cube (); + ColumnVector cmin = x_cube.row_min (), cmax = x_cube.row_max (); + double xM = cmax(0)-cmin(0); + double yM = cmax(1)-cmin(1); + + Matrix bb = get_boundingbox (); + Matrix cs = get_backend ().get_canvas_size (__myhandle__); + double fh = cs(1); + + double v_angle; + + if (cameraviewanglemode_is ("auto")) + { + double af; + + // FIXME: Was this really needed? When compared to Matlab, it + // does not seem to be required. Need investigation with concrete + // backend to see results visually. + if (false && dowarp) + af = 1.0 / (xM > yM ? xM : yM); + else + { + if ((bb(2)/bb(3)) > (xM/yM)) + af = 1.0 / yM; + else + af = 1.0 / xM; + } + v_angle = 2 * (180.0 / M_PI) * atan (1 / (2 * af * norm (F))); + + cameraviewangle = v_angle; + } + else + v_angle = get_cameraviewangle (); + + double pf = 1 / (2 * tan ((v_angle / 2) * M_PI / 180.0) * norm (F)); + scale (x_projection, pf, pf, 1); + + if (dowarp) + { + xM *= pf; + yM *= pf; + translate (x_viewport, bb(0)+bb(2)/2, fh-(bb(1)+bb(3)/2)+1, 0); + scale (x_viewport, bb(2)/xM, -bb(3)/yM, 1); + } + else + { + double pix = 1; + if (autocam) + { + if ((bb(2)/bb(3)) > (xM/yM)) + pix = bb(3); + else + pix = bb(2); + } + else + pix = (bb(2) < bb(3) ? bb(2) : bb(3)); + translate (x_viewport, bb(0)+bb(2)/2, fh-(bb(1)+bb(3)/2)+1, 0); + scale (x_viewport, pix, -pix, 1); + } + + x_normrender = x_viewport * x_projection * x_view; + + x_cube = x_normrender * unit_cube (); + cmin = x_cube.row_min (); + cmax = x_cube.row_max (); + x_zlim.resize (1, 2); + x_zlim(0) = cmin(2); + x_zlim(1) = cmax(2); + + x_render = x_normrender; + scale (x_render, xd/(xlim(1)-xlim(0)), yd/(ylim(1)-ylim(0)), + zd/(zlim(1)-zlim(0))); + translate (x_render, -xo, -yo, -zo); + + x_viewtransform = x_view; + x_projectiontransform = x_projection; + x_viewporttransform = x_viewport; + x_normrendertransform = x_normrender; + x_rendertransform = x_render; + + x_render_inv = x_render.inverse (); + + // Note: these matrices are a slight modified version of the regular + // matrices, more suited for OpenGL rendering (x_gl_mat1 => light + // => x_gl_mat2) + x_gl_mat1 = x_view; + scale (x_gl_mat1, xd/(xlim(1)-xlim(0)), yd/(ylim(1)-ylim(0)), + zd/(zlim(1)-zlim(0))); + translate (x_gl_mat1, -xo, -yo, -zo); + x_gl_mat2 = x_viewport * x_projection; +} + +void +axes::properties::update_aspectratios (void) +{ + Matrix xlim = get_xlim ().matrix_value (); + Matrix ylim = get_ylim ().matrix_value (); + Matrix zlim = get_zlim ().matrix_value (); + + double dx = (xlim(1)-xlim(0)); + double dy = (ylim(1)-ylim(0)); + double dz = (zlim(1)-zlim(0)); + + 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); + 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); + } + } + + // FIXME: if plotboxaspectratiomode is "manual", limits + // and/or dataaspectratio might be adapted +} + +Matrix +axes::properties::get_boundingbox (void) const +{ + graphics_backend b = get_backend (); + Matrix pos; + + pos = convert_position (get_position ().matrix_value (), get_units (), + "pixels", b.get_canvas_size (__myhandle__), b); + pos(0)--; + pos(1)--; + + return pos; +} + octave_value axes::get_default (const caseless_str& name) const { @@ -1778,6 +2332,8 @@ break; } + xproperties.update_transform (); + unwind_protect::run (); } diff --git a/src/graphics.h.in b/src/graphics.h.in --- a/src/graphics.h.in +++ b/src/graphics.h.in @@ -182,6 +182,129 @@ // --------------------------------------------------------------------- +class base_scaler +{ +public: + base_scaler (void) { } + + virtual Matrix scale (const Matrix& m) const + { + error ("invalid axis scale"); + return m; + } + + virtual double scale (double d) const + { + error ("invalid axis scale"); + return d; + } + + virtual double unscale (double d) const + { + error ("invalid axis scale"); + return d; + } + + virtual base_scaler* clone () const + { return new base_scaler (); } +}; + +class lin_scaler : public base_scaler +{ +public: + lin_scaler (void) { } + + Matrix scale (const Matrix& m) const { return m; } + + double scale (double d) const { return d; } + + double unscale (double d) const { return d; } + + base_scaler* clone (void) const { return new lin_scaler (); } +}; + +class log_scaler : public base_scaler +{ +public: + log_scaler (void) { } + + Matrix scale (const Matrix& m) const + { + Matrix retval (m.rows (), m.cols ()); + const double *d1 = m.fortran_vec (); + double *d2 = retval.fortran_vec (); + + for (int i = 0; i < m.numel (); i++) + d2[i] = log10 (d1[i]); + + return retval; + } + + double scale (double d) const + { return log10 (d); } + + double unscale (double d) const + { return pow (10.0, d); } + + base_scaler* clone (void) const + { return new log_scaler (); } +}; + +class scaler +{ +public: + scaler (void) : rep (new base_scaler ()) { } + + scaler (const scaler& s) : rep (s.rep->clone()) { } + + ~scaler (void) { delete rep; } + + Matrix scale (const Matrix& m) const + { return rep->scale (m); } + + double scale (double d) const + { return rep->scale (d); } + + double unscale (double d) const + { return rep->unscale (d); } + + scaler& operator = (const scaler& s) + { + if (rep) + { + delete rep; + rep = 0; + } + + rep = s.rep->clone (); + + return *this; + } + + scaler& operator = (const std::string& s) + { + if (rep) + { + delete rep; + rep = 0; + } + + if (s == "log") + rep = new log_scaler (); + else if (s == "linear") + rep = new lin_scaler (); + else + rep = new base_scaler (); + + return *this; + } + +private: + base_scaler *rep; +}; + +// --------------------------------------------------------------------- + class property; class base_property @@ -989,6 +1112,12 @@ return Matrix (1, 2, 0.0); } + virtual double get_screen_resolution (void) const + { + error ("get_screen_resolution: invalid graphics backend"); + return -1; + } + private: std::string name; int count; @@ -1053,6 +1182,9 @@ Matrix get_canvas_size (const graphics_handle& fh) const { return rep->get_canvas_size (fh); } + double get_screen_resolution (void) const + { return rep->get_screen_resolution (); } + OCTINTERP_API static graphics_backend default_backend (void); static void register_backend (const graphics_backend& b) @@ -2046,11 +2178,31 @@ void delete_children (void); + const scaler& get_x_scaler (void) const { return sx; } + const scaler& get_y_scaler (void) const { return sy; } + const scaler& get_z_scaler (void) const { return sz; } + + Matrix get_boundingbox (void) const; + + void update_camera (void); + void update_aspectratios (void); + void update_transform (void) + { + update_aspectratios (); + update_camera (); + } + + private: + scaler sx, sy, sz; + Matrix x_render, x_render_inv; + Matrix x_gl_mat1, x_gl_mat2; + Matrix x_zlim; + // See the genprops.awk script for an explanation of the // properties declarations. BEGIN_PROPERTIES(axes) - array_property position , Matrix () + array_property position , default_axes_position () mutable handle_property title GSO , graphics_handle () bool_property box , "on" bool_property key , "off" @@ -2099,17 +2251,17 @@ color_property xcolor , color_values (0, 0, 0) color_property ycolor , color_values (0, 0, 0) color_property zcolor , color_values (0, 0, 0) - radio_property xscale al , "{linear}|log" - radio_property yscale al , "{linear}|log" - radio_property zscale al , "{linear}|log" - radio_property xdir , "{normal}|reverse" - radio_property ydir , "{normal}|reverse" - radio_property zdir , "{normal}|reverse" + radio_property xscale alu , "{linear}|log" + radio_property yscale alu , "{linear}|log" + radio_property zscale alu , "{linear}|log" + radio_property xdir u , "{normal}|reverse" + radio_property ydir u , "{normal}|reverse" + radio_property zdir u , "{normal}|reverse" radio_property yaxislocation , "{left}|right|zero" radio_property xaxislocation , "{bottom}|top|zero" - array_property view , Matrix () + array_property view u , Matrix () radio_property nextplot , "add|replace_children|{replace}" - array_property outerposition , Matrix () + array_property outerposition , default_axes_outerposition () radio_property activepositionproperty , "{outerposition}|position" radio_property __colorbar__ h , "{none}|north|south|east|west|northoutside|southoutside|eastoutside|westoutside" color_property ambientlightcolor , color_values (1, 1, 1) @@ -2179,7 +2331,23 @@ currentpoint.add_constraint (dim_vector (2, 3)); ticklength.add_constraint (dim_vector (1, 2)); tightinset.add_constraint (dim_vector (1, 4)); + + x_zlim.resize (1, 2); + sx = "linear"; + sy = "linear"; + sz = "linear"; } + + private: + void update_xscale (void) { sx = get_xscale (); } + void update_yscale (void) { sy = get_yscale (); } + void update_zscale (void) { sz = get_zscale (); } + + void update_view (void) { update_camera (); } + + void update_xdir (void) { update_camera (); } + void update_ydir (void) { update_camera (); } + void update_zdir (void) { update_camera (); } }; private: diff --git a/src/oct-stream.cc b/src/oct-stream.cc --- a/src/oct-stream.cc +++ b/src/oct-stream.cc @@ -1541,8 +1541,8 @@ do \ { \ if (! width) \ - width = INT_MAX; - + width = INT_MAX; \ + \ std::ostringstream buf; \ \ std::string char_class = elt->char_class; \