void draw_plot(RendererViewport r, Plot plot) { switch (plot.get_dimensions()) { case 1: { set_2d_plot_window(r, plot); draw_axes_2d(r, plot.get_axes()); // plot title Vector2Pair _window2d = r.get_window2d(); Vector2Pair _window2d_fit = r.get_window2d_fit(); r.draw_text( new Vector2((_window2d.v0.x() + _window2d.v1.x()) / 2.0, (_window2d_fit.v1.y() + _window2d.v1.y()) / 2.0), Vector2.vector2_10, plot.get_title(), (int)Renderer.TextAlignMask.TextAlignCenter | (int)Renderer.TextAlignMask.TextAlignMiddle, 18, r.get_style_color(Renderer.Style.StyleForeground)); // plot data for (int i = 0; i < plot.get_plot_count(); i++) { PlotData d = plot.get_plot_data(i); draw_plot_data_2d(r, (Set1d)d.get_set(), d); } break; } default: throw new InvalidOperationException("Unsupported dimensions " + plot.get_dimensions()); } }
void draw_plot_data_2d(RendererViewport r, Set1d data, PlotData style) { // spline interpolated curve between points Vector2Pair _window2d_fit = r.get_window2d_fit(); Vector2Pair _window2d = r.get_window2d(); Vector2 _2d_output_res = r.get_2d_output_res(); if ((style.get_style() & (int)PlotStyleMask.InterpolatePlot) != 0) { double x_step = (_window2d.v1.x() - _window2d.v0.x()) / _2d_output_res.x(); Range xr = data.get_x_range(0); double x_low = Math.Max(_window2d_fit.v0.x(), xr.first); double x_high = Math.Min(_window2d_fit.v1.x(), xr.second); double y1 = data.interpolate(x_low); for (double x = x_low + x_step; x < x_high + x_step / 2; x += x_step) { double y2 = data.interpolate(x); r.draw_segment(new Vector3Pair(new Vector3(x - x_step, y1, 0), new Vector3(x, y2, 0)), style.get_color()); y1 = y2; } } // line plot if ((style.get_style() & (int)PlotStyleMask.LinePlot) != 0) { Range p1 = new Range(data.get_x_value(0), data.get_y_value(0)); for (int j = 1; j < data.get_count(); j++) { Range p2 = new Range(data.get_x_value(j), data.get_y_value(j)); r.draw_segment( new Vector3Pair(new Vector3(p1.first, p1.second, 0), new Vector3(p2.first, p2.second, 0)), style.get_color()); p1 = p2; } } // draw cross tic for each point if ((style.get_style() & (int)PlotStyleMask.PointPlot) != 0) { for (int j = 0; j < data.get_count(); j++) { Vector2 p = new Vector2(data.get_x_value(j), data.get_y_value(j)); r.draw_point(p, style.get_color(), Renderer.PointStyle.PointStyleCross); } } // print value for each point if ((style.get_style() & (int)PlotStyleMask.ValuePlot) != 0) { for (int j = 0; j < data.get_count(); j++) { int a; // FIXME remove use of data pair Range p = new Range(data.get_x_value(j), data.get_y_value(j)); double prev = j > 0 ? data.get_y_value(j - 1) : p.second; double next = j + 1 < data.get_count() ? data.get_y_value(j + 1) : p.second; if (p.second > prev) // FIXME use derivative to find best text position { if (p.second > next) { a = (int)Renderer.TextAlignMask.TextAlignBottom | (int)Renderer.TextAlignMask.TextAlignCenter; } else { a = (int)Renderer.TextAlignMask.TextAlignBottom | (int)Renderer.TextAlignMask.TextAlignRight; } } else { if (p.second > next) { a = (int)Renderer.TextAlignMask.TextAlignTop | (int)Renderer.TextAlignMask.TextAlignRight; } else { a = (int)Renderer.TextAlignMask.TextAlignBottom | (int)Renderer.TextAlignMask.TextAlignLeft; } } string s = string.Format("{0:F2}", p.second); r.draw_text(new Vector2(p.first, p.second), Vector2.vector2_10, s, a, 12, style.get_color()); } } }