# HG changeset patch # User Konstantinos Poulios # Date 1295644823 -3600 # Branch minorticks-restructure-draw_axes-bug-31800 # Node ID 2b1a942b84d387a962cc14caa4427d0b075e05eb # Parent 62b7ea59a6ff354d2841a83ba170773f1b70357a Restructuring draw_axes, enabling minorticks/grid in fltk, closing bug 31800 diff -r 62b7ea59a6ff -r 2b1a942b84d3 src/ChangeLog --- a/src/ChangeLog Fri Jan 21 20:22:42 2011 +0100 +++ b/src/ChangeLog Fri Jan 21 22:20:23 2011 +0100 @@ -1,3 +1,19 @@ +2011-01-22 Konstantinos Poulios + + * graphics.h.in, graphics.cc (xmtick, ymtick, zmtick): + New properties holding minor ticks positions. + (axes::properties::calc_ticks_and_lims): Calculation of minor ticks + positions. + * gl-render.h, gl-render.cc + (opengl_renderer::render_grid, opengl_renderer::render_tickmarks, + opengl_renderer::render_ticktexts): New functions. + (opengl_renderer::draw_axes): Make use of new rendering functions + and minor ticks positions. + Correct axis label positioning for x axis at top and y axis at right + position. Bug #31800. + Change axis positioning policy for 3D plots, keeping x and y axis + always at bottom. + 2011-01-21 Konstantinos Poulios * src/graphics.cc (axes::properties::set_xlabel, diff -r 62b7ea59a6ff -r 2b1a942b84d3 src/gl-render.cc --- a/src/gl-render.cc Fri Jan 21 20:22:42 2011 +0100 +++ b/src/gl-render.cc Fri Jan 21 22:20:23 2011 +0100 @@ -606,6 +606,137 @@ } void +opengl_renderer::render_grid (std::string& gridstyle, Matrix& ticks, + double lim1, double lim2, + double p1, double p1N, double p2, double p2N, + int xyz, bool is_3D) +{ + set_linestyle (gridstyle, true); + glBegin (GL_LINES); + for (int i = 0; i < ticks.numel (); i++) + { + double val = ticks(i); + if (lim1 <= val && val <= lim2) + { + if (xyz == 0) // X + { + glVertex3d (val, p1N, p2); + glVertex3d (val, p1, p2); + if (is_3D) + { + glVertex3d (val, p1, p2N); + glVertex3d (val, p1, p2); + } + } + else if (xyz == 1) // Y + { + glVertex3d (p1N, val, p2); + glVertex3d (p1, val, p2); + if (is_3D) + { + glVertex3d (p1, val, p2N); + glVertex3d (p1, val, p2); + } + } + else if (xyz == 2) // Z + { + glVertex3d (p1N, p2, val); + glVertex3d (p1, p2, val); + glVertex3d (p1, p2N, val); + glVertex3d (p1, p2, val); + } + } + } + glEnd (); + set_linestyle ("-", true); +} + +void +opengl_renderer::render_tickmarks(Matrix& ticks, double lim1, double lim2, + double p1, double p1N, double p2, double p2N, + double dx, double dy, double dz, + int xyz, bool doubleside) +{ + glBegin (GL_LINES); + for (int i = 0; i < ticks.numel (); i++) + { + double val = ticks(i); + + if (lim1 <= val && val <= lim2) + { + if (xyz == 0) // X + { + glVertex3d (val, p1, p2); + glVertex3d (val, p1+dy, p2+dz); + if (doubleside) + { + glVertex3d (val, p1N, p2N); + glVertex3d (val, p1N-dy, p2N-dz); + } + } + else if (xyz == 1) // Y + { + glVertex3d (p1, val, p2); + glVertex3d (p1+dx, val, p2+dz); + if (doubleside) + { + glVertex3d (p1N, val, p2N); + glVertex3d (p1N-dx, val, p2N-dz); + } + } + else if (xyz == 2) // Z + { + glVertex3d (p1, p2, val); + glVertex3d (p1+dx, p2+dy, val); + if (doubleside) + { + glVertex3d (p1N, p2N, val); + glVertex3d (p1N-dx, p2N-dy, val); + } + } + } + } + glEnd (); +} + +void +opengl_renderer::render_ticktexts(Matrix& ticks, string_vector& ticklabels, + double lim1, double lim2, + double p1, double p2, + int xyz, int ha, int va, + int& wmax, int& hmax) +{ + int n = std::min (ticklabels.numel (), ticks.numel ()); + + for (int i = 0; i < n; i++) + { + double val = ticks(i); + + if (lim1 <= val && val <= lim2) + { + Matrix b; + // FIXME: as tick text is transparent, shouldn't be + // drawn after axes object, for correct rendering? + if (xyz == 0) // X + { + b = render_text (ticklabels(i), val, p1, p2, ha, va); + } + else if (xyz == 1) // Y + { + b = render_text (ticklabels(i), p1, val, p2, ha, va); + } + else if (xyz == 2) // Z + { + b = render_text (ticklabels(i), p1, p2, val, ha, va); + } + + wmax = std::max (wmax, static_cast (b(2))); + hmax = std::max (hmax, static_cast (b(3))); + } + } +} + +void opengl_renderer::draw_axes (const axes::properties& props) { // setup OpenGL transformation @@ -783,7 +914,15 @@ bool xySym = (xd*yd*(xPlane-xPlaneN)*(yPlane-yPlaneN) > 0); bool x2Dtop = false; bool y2Dright = false; - double zpTick = zPlane; + bool layer2Dtop = false; + bool zSign = (zd*(zPlane-zPlaneN) <= 0); + bool xyzSym = zSign ? xySym : !xySym; + double xpTick = (zSign ? xPlaneN : xPlane); + double ypTick = (zSign ? yPlaneN : yPlane); + double zpTick = (zSign ? zPlane : zPlaneN); + double xpTickN = (zSign ? xPlane : xPlaneN); + double ypTickN = (zSign ? yPlane : yPlaneN); + double zpTickN = (zSign ? zPlaneN : zPlane); /* 2D mode */ if (xstate == AXE_HORZ_DIR && ystate == AXE_VERT_DIR) @@ -795,6 +934,8 @@ yPlaneN = tmp; x2Dtop = true; } + ypTick = yPlaneN; + ypTickN = yPlane; if (props.yaxislocation_is ("right")) { double tmp = xPlane; @@ -802,10 +943,20 @@ xPlaneN = tmp; y2Dright = true; } + xpTick = xPlaneN; + xpTickN = xPlane; if (props.layer_is ("top")) - zpTick = zPlaneN; + { + zpTick = zPlaneN; + layer2Dtop = true; + } + else + zpTick = zPlane; } + Matrix view = props.get_view ().matrix_value (); + bool nearhoriz = std::abs(view(1)) <= 5; + Matrix axe_color = props.get_color_rgb (); bool visible = props.is_visible (); bool box = props.is_box (); @@ -853,30 +1004,30 @@ // X box set_color (props.get_xcolor_rgb ()); - glVertex3d (xPlaneN, yPlaneN, zPlane); - glVertex3d (xPlane, yPlaneN, zPlane); + glVertex3d (xPlaneN, ypTick, zpTick); + glVertex3d (xPlane, ypTick, zpTick); if (box) { - glVertex3d (xPlaneN, yPlane, zPlane); - glVertex3d (xPlane, yPlane, zPlane); - glVertex3d (xPlaneN, yPlane, zPlaneN); - glVertex3d (xPlane, yPlane, zPlaneN); - glVertex3d (xPlaneN, yPlaneN, zPlaneN); - glVertex3d (xPlane, yPlaneN, zPlaneN); + glVertex3d (xPlaneN, ypTickN, zpTick); + glVertex3d (xPlane, ypTickN, zpTick); + glVertex3d (xPlaneN, ypTickN, zpTickN); + glVertex3d (xPlane, ypTickN, zpTickN); + glVertex3d (xPlaneN, ypTick, zpTickN); + glVertex3d (xPlane, ypTick, zpTickN); } // Y box set_color (props.get_ycolor_rgb ()); - glVertex3d (xPlaneN, yPlaneN, zPlane); - glVertex3d (xPlaneN, yPlane, zPlane); + glVertex3d (xpTick, yPlaneN, zpTick); + glVertex3d (xpTick, yPlane, zpTick); if (box) { - glVertex3d (xPlane, yPlaneN, zPlane); - glVertex3d (xPlane, yPlane, zPlane); - glVertex3d (xPlane, yPlaneN, zPlaneN); - glVertex3d (xPlane, yPlane, zPlaneN); - glVertex3d (xPlaneN, yPlaneN, zPlaneN); - glVertex3d (xPlaneN, yPlane, zPlaneN); + glVertex3d (xpTickN, yPlaneN, zpTick); + glVertex3d (xpTickN, yPlane, zpTick); + glVertex3d (xpTickN, yPlaneN, zpTickN); + glVertex3d (xpTickN, yPlane, zpTickN); + glVertex3d (xpTick, yPlaneN, zpTickN); + glVertex3d (xpTick, yPlane, zpTickN); } // Z box @@ -925,186 +1076,73 @@ bool do_xminorgrid = (props.is_xminorgrid () && (minorgridstyle != "none")); bool do_xminortick = props.is_xminortick (); Matrix xticks = xform.xscale (props.get_xtick ().matrix_value ()); - // FIXME: use pre-computed minor ticks - Matrix xmticks; + Matrix xmticks = xform.xscale (props.get_xmtick ().matrix_value ()); string_vector xticklabels = props.get_xticklabel ().all_strings (); int wmax = 0, hmax = 0; - bool tick_along_z = xisinf (fy); - Matrix tickpos (xticks.numel (), 3); + bool tick_along_z = nearhoriz || xisinf (fy); set_color (props.get_xcolor_rgb ()); // grid lines if (do_xgrid) - { - set_linestyle (gridstyle, true); - glBegin (GL_LINES); - for (int i = 0; i < xticks.numel (); i++) - { - double xval = xticks(i); - - if (xlim(0) <= xval && xlim(1) >= xval) - { - glVertex3d (xval, yPlaneN, zpTick); - glVertex3d (xval, yPlane, zpTick); - if (zstate != AXE_DEPTH_DIR) - { - glVertex3d (xval, yPlane, zPlaneN); - glVertex3d (xval, yPlane, zPlane); - } - } - } - glEnd (); - set_linestyle ("-", true); - } + render_grid (gridstyle, xticks, x_min, x_max, + yPlane, yPlaneN, layer2Dtop ? zPlaneN : zPlane, zPlaneN, + 0, (zstate != AXE_DEPTH_DIR)); // tick marks if (tick_along_z) { - glBegin (GL_LINES); - for (int i = 0; i < xticks.numel (); i++) - { - double xval = xticks(i); - - if (xlim(0) <= xval && xlim(1) >= xval) - { - glVertex3d (xval, yPlaneN, zPlane); - glVertex3d (xval, yPlaneN, zPlane+signum(zPlane-zPlaneN)*fz*xticklen*tickdir); - if (box && xstate != AXE_ANY_DIR) - { - glVertex3d (xval, yPlaneN, zPlaneN); - glVertex3d (xval, yPlaneN, - zPlaneN+signum(zPlaneN-zPlane)*fz*xticklen*tickdir); - } - tickpos(i,0) = xval; - tickpos(i,1) = yPlaneN; - tickpos(i,2) = zPlane+signum(zPlane-zPlaneN)*fz*xtickoffset; - } - } - glEnd (); + render_tickmarks (xticks, x_min, x_max, ypTick, ypTick, zpTick, zpTickN, + 0., 0., signum(zpTick-zpTickN)*fz*xticklen*tickdir, + 0, (box && xstate != AXE_ANY_DIR)); } else { - glBegin (GL_LINES); - for (int i = 0; i < xticks.numel (); i++) - { - double xval = xticks(i); - - if (xlim(0) <= xval && xlim(1) >= xval) - { - glVertex3d (xval, yPlaneN, zpTick); - glVertex3d (xval, yPlaneN+signum(yPlaneN-yPlane)*fy*xticklen*tickdir, zpTick); - if (box && xstate != AXE_ANY_DIR) - { - glVertex3d (xval, yPlane, zpTick); - glVertex3d (xval, - yPlane+signum(yPlane-yPlaneN)*fy*xticklen*tickdir, zpTick); - } - tickpos(i,0) = xval; - tickpos(i,1) = yPlaneN+signum(yPlaneN-yPlane)*fy*xtickoffset; - tickpos(i,2) = zPlane; - } - } - glEnd (); + render_tickmarks (xticks, x_min, x_max, ypTick, ypTickN, zpTick, zpTick, + 0., signum(ypTick-ypTickN)*fy*xticklen*tickdir, 0., + 0, (box && xstate != AXE_ANY_DIR)); } // tick texts if (xticklabels.numel () > 0) { - int n = std::min (xticklabels.numel (), xticks.numel ()); - int halign = (xstate == AXE_HORZ_DIR ? 1 : (xySym ? 0 : 2)); - int valign = (xstate == AXE_VERT_DIR - ? 1 - : (zd*zv(2) <= 0 && !x2Dtop ? 2 : 0)); - - for (int i = 0; i < n; i++) + int halign = (xstate == AXE_HORZ_DIR ? 1 : (xyzSym ? 0 : 2)); + int valign = (xstate == AXE_VERT_DIR ? 1 : (x2Dtop ? 0 : 2)); + + if (tick_along_z) { - double xval = xticks(i); - - if (xlim(0) <= xval && xlim(1) >= xval) - { - // FIXME: as tick text is transparent, shouldn't be - // drawn after axes object, for correct rendering? - Matrix b = render_text (xticklabels(i), - tickpos(i,0), tickpos(i,1), tickpos(i,2), - halign, valign); - - wmax = std::max (wmax, static_cast (b(2))); - hmax = std::max (hmax, static_cast (b(3))); - } + render_ticktexts (xticks, xticklabels, x_min, x_max, + ypTick, zpTick+signum(zpTick-zpTickN)*fz*xtickoffset, + 0, halign, valign, wmax, hmax); + } + else + { + render_ticktexts (xticks, xticklabels, x_min, x_max, + ypTick+signum(ypTick-ypTickN)*fy*xtickoffset, zpTick, + 0, halign, valign, wmax, hmax); } } // minor grid lines if (do_xminorgrid) - { - set_linestyle (minorgridstyle, true); - glBegin (GL_LINES); - for (int i = 0; i < xmticks.numel (); i++) - { - double xval = xmticks(i); - - if (xlim(0) <= xval && xlim(1) >= xval) - { - glVertex3d (xval, yPlaneN, zpTick); - glVertex3d (xval, yPlane, zpTick); - if (zstate != AXE_DEPTH_DIR) - { - glVertex3d (xval, yPlane, zPlaneN); - glVertex3d (xval, yPlane, zPlane); - } - } - } - glEnd (); - set_linestyle ("-", true); - } - + render_grid (minorgridstyle, xmticks, x_min, x_max, + yPlane, yPlaneN, layer2Dtop ? zPlaneN : zPlane, zPlaneN, + 0, (zstate != AXE_DEPTH_DIR)); + // minor tick marks if (do_xminortick) { if (tick_along_z) { - glBegin (GL_LINES); - for (int i = 0; i < xmticks.numel (); i++) - { - double xval = xmticks(i); - - if (xlim(0) <= xval && xlim(1) >= xval) - { - glVertex3d (xval, yPlaneN, zPlane); - glVertex3d (xval, yPlaneN, - zPlane+signum(zPlane-zPlaneN)*fz*xticklen/2*tickdir); - if (box && xstate != AXE_ANY_DIR) - { - glVertex3d (xval, yPlaneN, zPlaneN); - glVertex3d (xval, yPlaneN, - zPlaneN+signum(zPlaneN-zPlane)*fz*xticklen/2*tickdir); - } - } - } - glEnd (); + render_tickmarks (xmticks, x_min, x_max, ypTick, ypTick, zpTick, zpTickN, + 0., 0., signum(zpTick-zpTickN)*fz*xticklen/2*tickdir, + 0, (box && xstate != AXE_ANY_DIR)); } else { - glBegin (GL_LINES); - for (int i = 0; i < xmticks.numel (); i++) - { - double xval = xmticks(i); - - if (xlim(0) <= xval && xlim(1) >= xval) - { - glVertex3d (xval, yPlaneN, zpTick); - glVertex3d (xval, - yPlaneN+signum(yPlaneN-yPlane)*fy*xticklen/2*tickdir, zpTick); - if (box && xstate != AXE_ANY_DIR) - { - glVertex3d (xval, yPlane, zpTick); - glVertex3d (xval, - yPlane+signum(yPlane-yPlaneN)*fy*xticklen/2*tickdir, zpTick); - } - } - } - glEnd (); + render_tickmarks (xmticks, x_min, x_max, ypTick, ypTickN, zpTick, zpTick, + 0., signum(ypTick-ypTickN)*fy*xticklen/2*tickdir, 0., + 0, (box && xstate != AXE_ANY_DIR)); } } @@ -1117,37 +1155,37 @@ { if (xlabel_props.horizontalalignmentmode_is("auto")) { - xlabel_props.set_horizontalalignment (xstate > AXE_DEPTH_DIR ? "center" : (xySym ? "left" : "right")); + xlabel_props.set_horizontalalignment (xstate > AXE_DEPTH_DIR ? "center" : (xyzSym ? "left" : "right")); xlabel_props.set_horizontalalignmentmode("auto"); } if (xlabel_props.verticalalignmentmode_is("auto")) { - xlabel_props.set_verticalalignment (xstate == AXE_VERT_DIR ? "bottom" : (zd*zv(2) <= 0 ? "top" : "bottom")); + xlabel_props.set_verticalalignment (xstate == AXE_VERT_DIR || x2Dtop ? "bottom" : "top"); xlabel_props.set_verticalalignmentmode("auto"); } if (xlabel_props.positionmode_is("auto") || xlabel_props.rotationmode_is("auto")) { double angle = 0; - ColumnVector p = graphics_xform::xform_vector ((x_min+x_max)/2, yPlaneN, zPlane); + ColumnVector p = graphics_xform::xform_vector ((x_min+x_max)/2, ypTick, zpTick); if (tick_along_z) - p(2) += (signum(zPlane-zPlaneN)*fz*xtickoffset); + p(2) += (signum(zpTick-zpTickN)*fz*xtickoffset); else - p(1) += (signum(yPlaneN-yPlane)*fy*xtickoffset); + p(1) += (signum(ypTick-ypTickN)*fy*xtickoffset); p = xform.transform (p(0), p(1), p(2), false); switch (xstate) { case AXE_ANY_DIR: - p(0) += (xySym ? wmax : -wmax); - p(1) += (zd*zv(2) <= 0 ? hmax : -hmax); + p(0) += (xyzSym ? wmax : -wmax); + p(1) += hmax; break; case AXE_VERT_DIR: p(0) -= wmax; angle = 90; break; case AXE_HORZ_DIR: - p(1) += hmax; + p(1) += (x2Dtop ? -hmax : hmax); break; } if (xlabel_props.positionmode_is("auto")) @@ -1177,184 +1215,73 @@ bool do_yminorgrid = (props.is_yminorgrid () && (minorgridstyle != "none")); bool do_yminortick = props.is_yminortick (); Matrix yticks = xform.yscale (props.get_ytick ().matrix_value ()); - // FIXME: use pre-computed minor ticks - Matrix ymticks; + Matrix ymticks = xform.yscale (props.get_ymtick ().matrix_value ()); string_vector yticklabels = props.get_yticklabel ().all_strings (); int wmax = 0, hmax = 0; - bool tick_along_z = xisinf (fx); - Matrix tickpos (yticks.numel (), 3); + bool tick_along_z = nearhoriz || xisinf (fx); set_color (props.get_ycolor_rgb ()); // grid lines if (do_ygrid) - { - set_linestyle (gridstyle, true); - glBegin (GL_LINES); - for (int i = 0; i < yticks.numel (); i++) - { - double yval = yticks(i); - - if (ylim(0) <= yval && ylim(1) >= yval) - { - glVertex3d (xPlaneN, yval, zpTick); - glVertex3d (xPlane, yval, zpTick); - if (zstate != AXE_DEPTH_DIR) - { - glVertex3d (xPlane, yval, zPlaneN); - glVertex3d (xPlane, yval, zPlane); - } - } - } - glEnd (); - set_linestyle ("-", true); - } + render_grid (gridstyle, yticks, y_min, y_max, + xPlane, xPlaneN, layer2Dtop ? zPlaneN : zPlane, zPlaneN, + 1, (zstate != AXE_DEPTH_DIR)); // tick marks if (tick_along_z) { - glBegin (GL_LINES); - for (int i = 0; i < yticks.numel (); i++) - { - double yval = yticks(i); - - if (ylim(0) <= yval && ylim(1) >= yval) - { - glVertex3d (xPlaneN, yval, zPlane); - glVertex3d (xPlaneN, yval, zPlane+signum(zPlane-zPlaneN)*fz*yticklen*tickdir); - if (box && ystate != AXE_ANY_DIR) - { - glVertex3d (xPlaneN, yval, zPlaneN); - glVertex3d (xPlaneN, yval, - zPlaneN+signum(zPlaneN-zPlane)*fz*yticklen*tickdir); - } - tickpos(i,0) = xPlaneN; - tickpos(i,1) = yval; - tickpos(i,2) = zPlane+signum(zPlane-zPlaneN)*fz*ytickoffset; - } - } - glEnd (); + render_tickmarks (yticks, y_min, y_max, xpTick, xpTick, zpTick, zpTickN, + 0., 0., signum(zpTick-zpTickN)*fz*yticklen*tickdir, + 1, (box && ystate != AXE_ANY_DIR)); } else { - glBegin (GL_LINES); - for (int i = 0; i < yticks.numel (); i++) - { - double yval = yticks(i); - - if (ylim(0) <= yval && ylim(1) >= yval) - { - glVertex3d (xPlaneN, yval, zpTick); - glVertex3d (xPlaneN+signum(xPlaneN-xPlane)*fx*yticklen*tickdir, yval, zpTick); - if (box && ystate != AXE_ANY_DIR) - { - glVertex3d (xPlane, yval, zpTick); - glVertex3d (xPlane+signum(xPlane-xPlaneN)*fx*yticklen*tickdir, - yval, zpTick); - } - tickpos(i,0) = xPlaneN+signum(xPlaneN-xPlane)*fx*ytickoffset; - tickpos(i,1) = yval; - tickpos(i,2) = zPlane; - } - } - glEnd (); + render_tickmarks (yticks, y_min, y_max, xpTick, xpTickN, zpTick, zpTick, + signum(xPlaneN-xPlane)*fx*yticklen*tickdir, 0., 0., + 1, (box && ystate != AXE_ANY_DIR)); } // tick texts if (yticklabels.numel () > 0) { - int n = std::min (yticklabels.numel (), yticks.numel ()); - int halign = (ystate == AXE_HORZ_DIR ? 1 : (!xySym || y2Dright ? 0 : 2)); - int valign = (ystate == AXE_VERT_DIR ? 1 : (zd*zv(2) <= 0 ? 2 : 0)); - - for (int i = 0; i < n; i++) + int halign = (ystate == AXE_HORZ_DIR ? 1 : (!xyzSym || y2Dright ? 0 : 2)); + int valign = (ystate == AXE_VERT_DIR ? 1 : 2); + + if (tick_along_z) { - double yval = yticks(i); - - if (ylim(0) <= yval && ylim(1) >= yval) - { - // FIXME: as tick text is transparent, shouldn't be - // drawn after axes object, for correct rendering? - Matrix b = render_text (yticklabels(i), - tickpos(i,0), tickpos(i,1), tickpos(i,2), - halign, valign); - - wmax = std::max (wmax, static_cast (b(2))); - hmax = std::max (hmax, static_cast (b(3))); - } + render_ticktexts (yticks, yticklabels, y_min, y_max, + xpTick, zpTick+signum(zpTick-zpTickN)*fz*ytickoffset, + 1, halign, valign, wmax, hmax); + } + else + { + render_ticktexts (yticks, yticklabels, y_min, y_max, + xpTick+signum(xpTick-xpTickN)*fx*ytickoffset, zpTick, + 1, halign, valign, wmax, hmax); } } // minor grid lines if (do_yminorgrid) - { - set_linestyle (minorgridstyle, true); - glBegin (GL_LINES); - for (int i = 0; i < ymticks.numel (); i++) - { - double yval = ymticks(i); - - if (ylim(0) <= yval && ylim(1) >= yval) - { - glVertex3d (xPlaneN, yval, zpTick); - glVertex3d (xPlane, yval, zpTick); - if (zstate != AXE_DEPTH_DIR) - { - glVertex3d (xPlane, yval, zPlaneN); - glVertex3d (xPlane, yval, zPlane); - } - } - } - glEnd (); - set_linestyle ("-", true); - } + render_grid (minorgridstyle, ymticks, y_min, y_max, + xPlane, xPlaneN, layer2Dtop ? zPlaneN : zPlane, zPlaneN, + 1, (zstate != AXE_DEPTH_DIR)); // minor tick marks if (do_yminortick) { if (tick_along_z) { - glBegin (GL_LINES); - for (int i = 0; i < ymticks.numel (); i++) - { - double yval = ymticks(i); - - if (ylim(0) <= yval && ylim(1) >= yval) - { - glVertex3d (xPlaneN, yval, zPlane); - glVertex3d (xPlaneN, yval, - zPlane+signum(zPlane-zPlaneN)*fz*yticklen/2*tickdir); - if (box && ystate != AXE_ANY_DIR) - { - glVertex3d (xPlaneN, yval, zPlaneN); - glVertex3d (xPlaneN, yval, - zPlaneN+signum(zPlaneN-zPlane)*fz*yticklen/2*tickdir); - } - } - } - glEnd (); + render_tickmarks (ymticks, y_min, y_max, xpTick, xpTick, zpTick, zpTickN, + 0., 0., signum(zpTick-zpTickN)*fz*yticklen/2*tickdir, + 1, (box && ystate != AXE_ANY_DIR)); } else { - glBegin (GL_LINES); - for (int i = 0; i < ymticks.numel (); i++) - { - double yval = ymticks(i); - - if (ylim(0) <= yval && ylim(1) >= yval) - { - glVertex3d (xPlaneN, yval, zpTick); - glVertex3d (xPlaneN+signum(xPlaneN-xPlane)*fx*yticklen/2*tickdir, - yval, zpTick); - if (box && ystate != AXE_ANY_DIR) - { - glVertex3d (xPlane, yval, zpTick); - glVertex3d (xPlane+signum(xPlane-xPlaneN)*fx*yticklen/2*tickdir, - yval, zpTick); - } - } - } - glEnd (); + render_tickmarks (ymticks, y_min, y_max, xpTick, xpTickN, zpTick, zpTick, + signum(xpTick-xpTickN)*fx*yticklen/2*tickdir, 0., 0., + 1, (box && ystate != AXE_ANY_DIR)); } } @@ -1367,33 +1294,33 @@ { if (ylabel_props.horizontalalignmentmode_is("auto")) { - ylabel_props.set_horizontalalignment (ystate > AXE_DEPTH_DIR ? "center" : (!xySym ? "left" : "right")); + ylabel_props.set_horizontalalignment (ystate > AXE_DEPTH_DIR ? "center" : (!xyzSym ? "left" : "right")); ylabel_props.set_horizontalalignmentmode("auto"); } if (ylabel_props.verticalalignmentmode_is("auto")) { - ylabel_props.set_verticalalignment (ystate == AXE_VERT_DIR ? "bottom" : (zd*zv(2) <= 0 ? "top" : "bottom")); + ylabel_props.set_verticalalignment (ystate == AXE_VERT_DIR && !y2Dright ? "bottom" : "top"); ylabel_props.set_verticalalignmentmode("auto"); } if (ylabel_props.positionmode_is("auto") || ylabel_props.rotationmode_is("auto")) { double angle = 0; - ColumnVector p = graphics_xform::xform_vector (xPlaneN, (y_min+y_max)/2, zPlane); + ColumnVector p = graphics_xform::xform_vector (xpTick, (y_min+y_max)/2, zpTick); if (tick_along_z) - p(2) += (signum(zPlane-zPlaneN)*fz*ytickoffset); + p(2) += (signum(zpTick-zpTickN)*fz*ytickoffset); else - p(0) += (signum(xPlaneN-xPlane)*fx*ytickoffset); + p(0) += (signum(xpTick-xpTickN)*fx*ytickoffset); p = xform.transform (p(0), p(1), p(2), false); switch (ystate) { case AXE_ANY_DIR: - p(0) += (!xySym ? wmax : -wmax); - p(1) += (zd*zv(2) <= 0 ? hmax : -hmax); + p(0) += (!xyzSym ? wmax : -wmax); + p(1) += hmax; break; case AXE_VERT_DIR: - p(0) -= wmax; + p(0) += (y2Dright ? wmax : -wmax); angle = 90; break; case AXE_HORZ_DIR: @@ -1427,172 +1354,91 @@ bool do_zminorgrid = (props.is_zminorgrid () && (minorgridstyle != "none")); bool do_zminortick = props.is_zminortick (); Matrix zticks = xform.zscale (props.get_ztick ().matrix_value ()); - // FIXME: use pre-computed minor ticks - Matrix zmticks; + Matrix zmticks = xform.zscale (props.get_zmtick ().matrix_value ()); string_vector zticklabels = props.get_zticklabel ().all_strings (); int wmax = 0, hmax = 0; - Matrix tickpos (zticks.numel (), 3); set_color (props.get_zcolor_rgb ()); // grid lines if (do_zgrid) - { - set_linestyle (gridstyle, true); - glBegin (GL_LINES); - for (int i = 0; i < zticks.numel (); i++) - { - double zval = zticks(i); - - if (zlim(0) <= zval && zlim(1) >= zval) - { - glVertex3d (xPlaneN, yPlane, zval); - glVertex3d (xPlane, yPlane, zval); - glVertex3d (xPlane, yPlaneN, zval); - glVertex3d (xPlane, yPlane, zval); - } - } - glEnd (); - set_linestyle ("-", true); - } + render_grid (gridstyle, zticks, z_min, z_max, + xPlane, xPlaneN, yPlane, yPlaneN, 2, true); // tick marks if (xySym) { if (xisinf (fy)) { - glBegin (GL_LINES); - for (int i = 0; i < zticks.numel (); i++) - { - double zval = zticks(i); - - if (zlim(0) <= zval && zlim(1) >= zval) - { - glVertex3d (xPlaneN, yPlane, zval); - glVertex3d (xPlaneN+signum(xPlaneN-xPlane)*fx*zticklen*tickdir, - yPlane, zval); - if (box && zstate != AXE_ANY_DIR) - { - glVertex3d (xPlane, yPlane, zval); - glVertex3d (xPlane+signum(xPlane-xPlaneN)*fx*zticklen*tickdir, - yPlane, zval); - } - tickpos(i,0) = xPlaneN+signum(xPlaneN-xPlane)*fx*ztickoffset; - tickpos(i,1) = yPlane; - tickpos(i,2) = zval; - } - } - glEnd (); + render_tickmarks( zticks, z_min, z_max, xPlaneN, xPlane, yPlane, yPlane, + signum(xPlaneN-xPlane)*fx*zticklen*tickdir, 0., 0., + 2, (box && zstate != AXE_ANY_DIR)); } else { - glBegin (GL_LINES); - for (int i = 0; i < zticks.numel (); i++) - { - double zval = zticks(i); - - if (zlim(0) <= zval && zlim(1) >= zval) - { - glVertex3d (xPlaneN, yPlane, zval); - glVertex3d (xPlaneN, yPlane+signum(yPlane-yPlaneN)*fy*zticklen*tickdir, zval); - tickpos(i,0) = xPlaneN; - tickpos(i,1) = yPlane+signum(yPlane-yPlaneN)*fy*ztickoffset; - tickpos(i,2) = zval; - } - } - glEnd (); + render_tickmarks (zticks, z_min, z_max, xPlaneN, xPlaneN, yPlane, yPlane, + 0., signum(yPlane-yPlaneN)*fy*zticklen*tickdir, 0., + 2, false); } } else { if (xisinf (fx)) { - glBegin (GL_LINES); - for (int i = 0; i < zticks.numel (); i++) - { - double zval = zticks(i); - - if (zlim(0) <= zval && zlim(1) >= zval) - { - glVertex3d (xPlane, yPlaneN, zval); - glVertex3d (xPlane, yPlaneN+signum(yPlaneN-yPlane)*fy*zticklen*tickdir, zval); - if (box && zstate != AXE_ANY_DIR) - { - glVertex3d (xPlane, yPlane, zval); - glVertex3d (xPlane, yPlane+signum(yPlane-yPlaneN)*fy*zticklen*tickdir, zval); - } - tickpos(i,0) = xPlane; - tickpos(i,1) = yPlaneN+signum(yPlaneN-yPlane)*fy*ztickoffset; - tickpos(i,2) = zval; - } - } - glEnd (); + render_tickmarks (zticks, z_min, z_max, xPlaneN, xPlane, yPlaneN, yPlane, + 0., signum(yPlaneN-yPlane)*fy*zticklen*tickdir, 0., + 2, (box && zstate != AXE_ANY_DIR)); } else - { - glBegin (GL_LINES); - for (int i = 0; i < zticks.numel (); i++) - { - double zval = zticks(i); - - if (zlim(0) <= zval && zlim(1) >= zval) - { - glVertex3d (xPlane, yPlaneN, zval); - glVertex3d (xPlane+signum(xPlane-xPlaneN)*fx*zticklen*tickdir, yPlaneN, zval); - tickpos(i,0) = xPlane+signum(xPlane-xPlaneN)*fx*ztickoffset; - tickpos(i,1) = yPlaneN; - tickpos(i,2) = zval; - } - } - glEnd (); - } + { + render_tickmarks (zticks, z_min, z_max, xPlane, xPlane, yPlaneN, yPlane, + signum(xPlane-xPlaneN)*fx*zticklen*tickdir, 0., 0., + 2, false); + } } // FIXME: tick texts if (zticklabels.numel () > 0) { - int n = std::min (zticklabels.numel (), zticks.numel ()); int halign = 2; - int valign = (zstate == AXE_VERT_DIR ? 1 : (zd*zv(2) < 0 ? 3 : 2)); - - for (int i = 0; i < n; i++) + int valign = (zstate == AXE_VERT_DIR ? 1 : (zSign ? 3 : 2)); + + if (xySym) { - double zval = zticks(i); - - if (zlim(0) <= zval && zlim(1) >= zval) + if (xisinf (fy)) { - // FIXME: as tick text is transparent, shouldn't be - // drawn after axes object, for correct rendering? - Matrix b = render_text (zticklabels(i), - tickpos(i,0), tickpos(i,1), tickpos(i,2), - halign, valign); - - wmax = std::max (wmax, static_cast (b(2))); - hmax = std::max (hmax, static_cast (b(3))); + render_ticktexts (zticks, zticklabels, z_min, z_max, + xPlaneN+signum(xPlaneN-xPlane)*fx*ztickoffset, yPlane, + 2, halign, valign, wmax, hmax); + } + else + { + render_ticktexts (zticks, zticklabels, z_min, z_max, + xPlaneN, yPlane+signum(yPlane-yPlaneN)*fy*ztickoffset, + 2, halign, valign, wmax, hmax); + } + } + else + { + if (xisinf (fx)) + { + render_ticktexts (zticks, zticklabels, z_min, z_max, + xPlane, yPlaneN+signum(yPlaneN-yPlane)*fy*ztickoffset, + 2, halign, valign, wmax, hmax); + } + else + { + render_ticktexts (zticks, zticklabels, z_min, z_max, + xPlane+signum(xPlane-xPlaneN)*fx*ztickoffset, yPlaneN, + 2, halign, valign, wmax, hmax); } } } // minor grid lines if (do_zminorgrid) - { - set_linestyle (minorgridstyle, true); - glBegin (GL_LINES); - for (int i = 0; i < zmticks.numel (); i++) - { - double zval = zmticks(i); - - if (zlim(0) <= zval && zlim(1) >= zval) - { - glVertex3d (xPlaneN, yPlane, zval); - glVertex3d (xPlane, yPlane, zval); - glVertex3d (xPlane, yPlaneN, zval); - glVertex3d (xPlane, yPlane, zval); - } - } - glEnd (); - set_linestyle ("-", true); - } + render_grid (minorgridstyle, zmticks, z_min, z_max, + xPlane, xPlaneN, yPlane, yPlaneN, 2, true); // minor tick marks if (do_zminortick) @@ -1601,78 +1447,30 @@ { if (xisinf (fy)) { - glBegin (GL_LINES); - for (int i = 0; i < zmticks.numel (); i++) - { - double zval = zmticks(i); - - if (zlim(0) <= zval && zlim(1) >= zval) - { - glVertex3d (xPlaneN, yPlane, zval); - glVertex3d (xPlaneN+signum(xPlaneN-xPlane)*fx*zticklen/2*tickdir, - yPlane, zval); - if (box && zstate != AXE_ANY_DIR) - { - glVertex3d (xPlane, yPlane, zval); - glVertex3d (xPlane+signum(xPlane-xPlaneN)*fx*zticklen/2*tickdir, - yPlane, zval); - } - } - } - glEnd (); + render_tickmarks( zmticks, z_min, z_max, xPlaneN, xPlane, yPlane, yPlane, + signum(xPlaneN-xPlane)*fx*zticklen/2*tickdir, 0., 0., + 2, (box && zstate != AXE_ANY_DIR)); } else { - glBegin (GL_LINES); - for (int i = 0; i < zmticks.numel (); i++) - { - double zval = zmticks(i); - - if (zlim(0) <= zval && zlim(1) >= zval) - { - glVertex3d (xPlaneN, yPlane, zval); - glVertex3d (xPlaneN, yPlane+signum(yPlane-yPlaneN)*fy*zticklen/2*tickdir, zval); - } - } - glEnd (); + render_tickmarks (zmticks, z_min, z_max, xPlaneN, xPlaneN, yPlane, yPlane, + 0., signum(yPlane-yPlaneN)*fy*zticklen/2*tickdir, 0., + 2, false); } } else { if (xisinf (fx)) { - glBegin (GL_LINES); - for (int i = 0; i < zmticks.numel (); i++) - { - double zval = zmticks(i); - - if (zlim(0) <= zval && zlim(1) >= zval) - { - glVertex3d (xPlane, yPlaneN, zval); - glVertex3d (xPlane, yPlaneN+signum(yPlaneN-yPlane)*fy*zticklen/2*tickdir, zval); - if (box && zstate != AXE_ANY_DIR) - { - glVertex3d (xPlane, yPlane, zval); - glVertex3d (xPlane, yPlane+signum(yPlane-yPlaneN)*fy*zticklen/2*tickdir, zval); - } - } - } - glEnd (); + render_tickmarks (zmticks, z_min, z_max, xPlane, xPlane, yPlaneN, yPlane, + 0., signum(yPlaneN-yPlane)*fy*zticklen/2*tickdir, 0., + 2, (box && zstate != AXE_ANY_DIR)); } else { - glBegin (GL_LINES); - for (int i = 0; i < zmticks.numel (); i++) - { - double zval = zmticks(i); - - if (zlim(0) <= zval && zlim(1) >= zval) - { - glVertex3d (xPlane, yPlaneN, zval); - glVertex3d (xPlane+signum(xPlane-xPlaneN)*fx*zticklen/2*tickdir, yPlaneN, zval); - } - } - glEnd (); + render_tickmarks (zmticks, z_min, z_max, xPlane, xPlane, yPlaneN, yPlaneN, + signum(xPlane-xPlaneN)*fx*zticklen/2*tickdir, 0., 0., + 2, false); } } } @@ -1693,7 +1491,7 @@ } if (zlabel_props.verticalalignmentmode_is("auto")) { - zlabel_props.set_verticalalignment(zstate == AXE_VERT_DIR ? "bottom" : ((zd*zv(2) < 0 || camAuto) ? "bottom" : "top")); + zlabel_props.set_verticalalignment(zstate == AXE_VERT_DIR ? "bottom" : ((zSign || camAuto) ? "bottom" : "top")); zlabel_props.set_verticalalignmentmode("auto"); } @@ -1729,7 +1527,7 @@ } /* FIXME: what's the correct offset? p[0] += (!xySym ? wmax : -wmax); - p[1] += (zd*zv[2] <= 0 ? hmax : -hmax); + p[1] += (zSign ? hmax : -hmax); */ break; case AXE_VERT_DIR: diff -r 62b7ea59a6ff -r 2b1a942b84d3 src/gl-render.h --- a/src/gl-render.h Fri Jan 21 20:22:42 2011 +0100 +++ b/src/gl-render.h Fri Jan 21 22:20:23 2011 +0100 @@ -117,6 +117,22 @@ virtual void draw_pixels (GLsizei w, GLsizei h, GLenum format, GLenum type, const GLvoid *data); + virtual void render_grid (std::string& gridstyle, Matrix& ticks, + double lim1, double lim2, + double p1, double p1N, double p2, double p2N, + int xyz, bool is_3D); + + virtual void render_tickmarks(Matrix& ticks, double lim1, double lim2, + double p1, double p1N, double p2, double p2N, + double dx, double dy, double dz, + int xyz, bool doubleside); + + virtual void render_ticktexts(Matrix& ticks, string_vector& ticklabels, + double lim1, double lim2, + double p1, double p2, + int xyz, int ha, int va, + int& wmax, int& hmax); + private: opengl_renderer (const opengl_renderer&) : toolkit (), xform (), xmin (), xmax (), ymin (), ymax (), diff -r 62b7ea59a6ff -r 2b1a942b84d3 src/graphics.cc --- a/src/graphics.cc Fri Jan 21 20:22:42 2011 +0100 +++ b/src/graphics.cc Fri Jan 21 22:20:23 2011 +0100 @@ -4371,6 +4371,7 @@ void axes::properties::calc_ticks_and_lims (array_property& lims, array_property& ticks, + array_property& mticks, bool limmode_is_auto, bool is_logscale) { // FIXME -- add log ticks and lims @@ -4432,6 +4433,19 @@ } ticks = tmp_ticks; + + int n = is_logscale ? 9 : 4; + Matrix tmp_mticks (1, n * tmp_ticks.numel ()); + + for (int i = 0; i < tmp_ticks.numel ()-1; i++) + { + double d = (tmp_ticks (i+1) - tmp_ticks (i)) / (n+1); + for (int j = 0; j < n; j++) + { + tmp_mticks (n*i+j) = tmp_ticks (i) + d * (j+1); + } + } + mticks = tmp_mticks; } void diff -r 62b7ea59a6ff -r 2b1a942b84d3 src/graphics.h.in --- a/src/graphics.h.in Fri Jan 21 20:22:42 2011 +0100 +++ b/src/graphics.h.in Fri Jan 21 22:20:23 2011 +0100 @@ -3207,6 +3207,10 @@ array_property x_viewporttransform h , Matrix (4, 4, 0.0) array_property x_normrendertransform h , Matrix (4, 4, 0.0) array_property x_rendertransform h , Matrix (4, 4, 0.0) + // hidden properties for minor ticks + row_vector_property xmtick h , Matrix () + row_vector_property ymtick h , Matrix () + row_vector_property zmtick h , Matrix () END_PROPERTIES protected: @@ -3247,7 +3251,7 @@ { if (xtickmode.is ("auto")) { - calc_ticks_and_lims (xlim, xtick, xlimmode.is ("auto"), xscale.is ("log")); + calc_ticks_and_lims (xlim, xtick, xmtick, xlimmode.is ("auto"), xscale.is ("log")); update_xtick (); } } @@ -3255,7 +3259,7 @@ { if (ytickmode.is ("auto")) { - calc_ticks_and_lims (ylim, ytick, ylimmode.is ("auto"), yscale.is ("log")); + calc_ticks_and_lims (ylim, ytick, ymtick, ylimmode.is ("auto"), yscale.is ("log")); update_ytick (); } } @@ -3263,7 +3267,7 @@ { if (ztickmode.is ("auto")) { - calc_ticks_and_lims (zlim, ztick, zlimmode.is ("auto"), zscale.is ("log")); + calc_ticks_and_lims (zlim, ztick, zmtick, zlimmode.is ("auto"), zscale.is ("log")); update_ztick (); } } @@ -3289,7 +3293,8 @@ void update_position (void) { sync_positions (); } double calc_tick_sep (double minval, double maxval); - void calc_ticks_and_lims (array_property& lims, array_property& ticks, bool limmode_is_auto, bool is_logscale); + void calc_ticks_and_lims (array_property& lims, array_property& ticks, array_property& mticks, + bool limmode_is_auto, bool is_logscale); void calc_ticklabels (const array_property& ticks, any_property& labels, bool is_logscale); void fix_limits (array_property& lims) { @@ -3317,7 +3322,7 @@ void update_xlim (bool do_clr_zoom = true) { if (xtickmode.is ("auto")) - calc_ticks_and_lims (xlim, xtick, xlimmode.is ("auto"), xscale.is ("log")); + calc_ticks_and_lims (xlim, xtick, xmtick, xlimmode.is ("auto"), xscale.is ("log")); if (xticklabelmode.is ("auto")) calc_ticklabels (xtick, xticklabel, xscale.is ("log")); @@ -3330,7 +3335,7 @@ void update_ylim (bool do_clr_zoom = true) { if (ytickmode.is ("auto")) - calc_ticks_and_lims (ylim, ytick, ylimmode.is ("auto"), yscale.is ("log")); + calc_ticks_and_lims (ylim, ytick, ymtick, ylimmode.is ("auto"), yscale.is ("log")); if (yticklabelmode.is ("auto")) calc_ticklabels (ytick, yticklabel, yscale.is ("log")); @@ -3343,7 +3348,7 @@ void update_zlim (void) { if (ztickmode.is ("auto")) - calc_ticks_and_lims (zlim, ztick, zlimmode.is ("auto"), zscale.is ("log")); + calc_ticks_and_lims (zlim, ztick, zmtick, zlimmode.is ("auto"), zscale.is ("log")); if (zticklabelmode.is ("auto")) calc_ticklabels (ztick, zticklabel, zscale.is ("log"));