Exemplo n.º 1
0
        private static void LayoutFillArea(ValueLayout _vl, int si, KeyValuePair <int, Color> towards, PsychogramSeries target)
        {
            var region = new List <PointF>();

            region.AddRange(_vl.Slope[si]);
            region.AddRange(_vl.Slope[target.SeriesID].Reverse <PointF>());
            region.Add(region[0]);
            _vl.Fillregion[si] = region.ToArray();
            _vl.Fillcolor[si]  = towards.Value;
        }
Exemplo n.º 2
0
        private ValueLayout ComputeValuelayout(Layout _l, int xip)
        {
            var _vl = new ValueLayout()
            {
                Clipregion = new RectangleF(_l.grid_X[xip].X + 1, _l.bb_Plot.Top, _l.grid_Xstep, _l.bb_Plot.Height),
                value      = _data.Value(xip),
                Slope      = new List <PointF[]>(),
                Fillregion = new List <PointF[]>(),
                Fillcolor  = new List <Color>()
            };

            for (int si = 0; si < _data.Series.Count; ++si)
            {
                var slope = new List <PointF>();
                if (xip > 0)
                {
                    /* draw left slope */
                    slope.Add(new PointF(_l.grid_X[xip].X - _l.em_2, ValueYCoord(_l, _vl.value.PredecessorData[si])));
                    slope.Add(new PointF(_l.grid_X[xip].X + _l.em_2, ValueYCoord(_l, _vl.value.SeriesData[si])));
                }
                else
                {
                    /* start left point on grid line */
                    slope.Add(new PointF(_l.grid_X[xip].X, ValueYCoord(_l, _vl.value.SeriesData[si])));
                }
                if (xip < _data.XBarData.Count - 1)
                {
                    /* draw right slope */
                    slope.Add(new PointF(_l.grid_X[xip].X + _l.grid_Xstep - 1 - _l.em_2, ValueYCoord(_l, _vl.value.SeriesData[si])));
                    slope.Add(new PointF(_l.grid_X[xip].X + _l.grid_Xstep - 1 + _l.em_2, ValueYCoord(_l, _vl.value.SuccessorData[si])));
                }
                else
                {
                    /* end right point on grid boundary */
                    slope.Add(new PointF(_l.grid_X[xip].X + _l.grid_Xstep - 1, ValueYCoord(_l, _vl.value.SeriesData[si])));
                }
                /* commit */
                _vl.Slope.Add(slope.ToArray());
                _vl.Fillregion.Add(new PointF[] { }); /* add an empty array by default */
                _vl.Fillcolor.Add(Color.Transparent); /* add a transparent region fill by default */
            }
            if (_vl.Slope.Count <= 0)
            {
                _vl.Slope = null; /* [dlatikay 20120410] how to treat gaps? */
            }
            /* intra-series fill area? (separate loop cause need all series coords readily calculated) */
            for (int si = 0; si < _data.Series.Count; ++si)
            {
                var myser = _data.Series[si];

                /* can we have this use PsychogramBar.Outcome instead -> its the same logic just from another perspective. I do not like the idea of duplicating this here [dlatikay 20120410]
                 * positive */
                if (myser.AreaColorTowardsP != null)
                {
                    foreach (var towards in myser.AreaColorTowardsP)
                    {
                        /* is the series value where towards points to, bigger than my own value? */
                        var target = _data.Series.Find((x) => (x.SeriesID == towards.Key));
                        if (target != null && _vl.value.SeriesData[si] > _vl.value.SeriesData[target.SeriesID])
                        {
                            LayoutFillArea(_vl, si, towards, target);
                        }
                    }
                }
                /* negative */
                if (myser.AreaColorTowardsN != null)
                {
                    foreach (var towards in myser.AreaColorTowardsN)
                    {
                        /* is the series value where towards points to, smaller than my own value? */
                        var target = _data.Series.Find((x) => (x.SeriesID == towards.Key));
                        if (target != null && _vl.value.SeriesData[si] < _vl.value.SeriesData[target.SeriesID])
                        {
                            LayoutFillArea(_vl, si, towards, target);
                        }
                    }
                }
            }
            return(_vl);
        }
Exemplo n.º 3
0
        public Image Render(int size_px_x, int size_px_y)
        {
            /* apply the sort order */
            ApplySorting();
            /* do the graphical work */
            var canvas = new Bitmap(size_px_x, size_px_y, PixelFormat.Format32bppArgb);
            var ix0    = 0;

            using (var g = InitGraphics(canvas))
            {
                /* 1. compute the rectangular framework */
                var _l = ComputeMasterLayout(g);
#if DEBUG
                DrawDebugMasterLayout(g, _l);
#endif
                /* draw the plot area framing */
                g.DrawLines(Pens.Black, new PointF[] {
                    new PointF(_l.bb_Plot.Left, _l.boundingbox.Top),
                    new PointF(_l.bb_Plot.Left, _l.bb_Plot.Bottom - 1),
                    new PointF(_l.bb_Plot.Right - 1, _l.bb_Plot.Bottom - 1),
                    new PointF(_l.bb_Plot.Right - 1, _l.boundingbox.Top)
                });
                /* draw the plot area horizontal value scale */
                int yi = 0;
                foreach (var y in _data.YScale)
                {
                    g.DrawLine(_l.penY_GridLines, new PointF(_l.bb_Plot.Left + _l.em_2, _l.grid_Y[yi].Y), new PointF(_l.bb_Plot.Right - _l.em_2, _l.grid_Y[yi].Y));
                    g.DrawLine(_l.penY_GridTicks, new PointF(_l.bb_Plot.Left - _l.em_2, _l.grid_Y[yi].Y), new PointF(_l.bb_Plot.Left + _l.em_2, _l.grid_Y[yi].Y));
                    g.DrawLine(_l.penY_GridTicks, new PointF(_l.bb_Plot.Right - _l.em_2, _l.grid_Y[yi].Y), new PointF(_l.bb_Plot.Right + _l.em_2, _l.grid_Y[yi].Y));
                    /* plus the tick vertical y-axis labels */
                    var layoutrect = new Rectangle((int)_l.bb_yscaleL.Left, (int)(_l.grid_Y[yi].Y - _l.em), (int)(_l.bb_yscaleL.Width - _l.em_2), (int)(2 * _l.em));
#if DEBUG
                    DrawRectInclusive(g, Pens.BurlyWood, layoutrect);
#endif
                    TextRenderer.DrawText(g, _data.YScale[y].ToString(), _l.font_Valuelabels, layoutrect, Color.Black, Layout.textformatflags_right);
                    layoutrect = new Rectangle((int)(_l.bb_yscaleR.Left + _l.em_2), (int)(_l.grid_Y[yi].Y - _l.em), (int)(_l.bb_yscaleR.Width - _l.em_2), (int)(2 * _l.em));
#if DEBUG
                    DrawRectInclusive(g, Pens.BurlyWood, layoutrect);
#endif
                    TextRenderer.DrawText(g, _data.YScale[y].ToString(), _l.font_Valuelabels, layoutrect, Color.Black, Layout.textformatflags_left);
                    ++yi;
                }
                /* draw the plot area vertical rubrics scale */
                for (var xi = 0; xi < _l.grid_X.Length; ++xi)
                {
                    g.DrawLine(_l.penY_GridLines, new PointF(_l.grid_X[xi].X, _l.bb_Plot.Top - _l.em), new PointF(_l.grid_X[xi].X, _l.boundingbox.Bottom));
                }
                /* draw the average lines as bottommost layer onto the plot */
                if (_data.ShowAverageGraphLines)
                {
                    int si_av = 0;
                    foreach (var seri_a in _data.Series)
                    {
                        var average = seri_a.Average(_data.XBarData);
                        if (average > 0.0F)
                        {
                            var height = ValueYCoord(_l, seri_a.Average(_data.XBarData));
                            using (var spen = new Pen(_data.Series[si_av].LineColor, 2))
                            {
                                spen.DashStyle = DashStyle.Dash;
                                g.DrawLine(spen, new PointF(_l.bb_Plot.Left, height), new PointF(_l.bb_Plot.Right, height));
                            }
                        }
                        ++si_av;
                    }
                }
                /* draw the plot */
                ValueLayout lastvaluelayout = null;
                for (var pass = 1; pass <= 2; ++pass)
                {
                    for (var xip = 0; xip < _data.XBarData.Count; ++xip)
                    {
                        var _pl = ComputeValuelayout(_l, xip);
                        int si  = 0;
                        foreach (var slope in _pl.Slope)
                        {
                            if (pass == 1)
                            {
                                /* a. draw areas for each from-to covered sections */
                                if (_pl.Fillregion[si].Length > 0)
                                {
                                    g.SetClip(_pl.Clipregion);
                                    using (var fillco = new SolidBrush(_pl.Fillcolor[si]))
                                    {
                                        g.FillPolygon(fillco, _pl.Fillregion[si]);
                                    }
                                    g.ResetClip();
                                }
                            }
                            else if (pass == 2)
                            {
                                /* b. draw solid plot lines for the value of each series */
                                using (var brush = new SolidBrush(_data.Series[si].LineColor))
                                {
                                    using (var spen = new Pen(brush, 2))
                                    {
                                        g.DrawLines(spen, slope);
                                    }
                                }
                                /* label the values */
                                if (_data.Series[si].SeriesID == _data.SeriesIDToLabelY)
                                {
                                    var layoutrect = new Rectangle((int)_pl.Clipregion.Left, (int)(_l.bb_yvaluesT.Bottom - 2.0F * _l.em - 0.5F * _l.em_2), (int)_pl.Clipregion.Width, (int)(_l.bb_yvaluesT.Height - _l.em));
#if DEBUG
                                    DrawRectInclusive(g, Pens.BurlyWood, layoutrect);
#endif
                                    TextRenderer.DrawText(g, _pl.value.SeriesData[_data.SeriesIDToLabelY].ToString("0.#"), _l.font_Valuelabels, layoutrect, Color.Black, Layout.textformatflags_center);
                                }
                                lastvaluelayout = _pl;
                            }
                            /* advance */
                            ++si;
                        }
                    }
                }
                /* draw the legend, nicely optically connected to the plot */
                var _ll = ComputeLegendLayout(_l);
                var li0 = 0;
#if DEBUG
                DrawRectInclusive(g, Pens.BurlyWood, _ll.Boundingbox);
#endif
                foreach (var seri in _data.Series)
                {
                    using (var brush = new SolidBrush(_data.Series[li0].LineColor))
                    {
                        using (var spen = new Pen(brush, 1.5F))
                        {
                            DrawRectInclusive(g, spen, _ll.Outline[li0]);
                            g.FillRectangle(brush, _ll.Connector[li0].X - _l.em_2 / 2, _ll.Connector[li0].Y - _l.em_2 / 2, _l.em_2, _l.em_2);
#if DEBUG
                            DrawRectInclusive(g, Pens.BurlyWood, _ll.Textcontainer[li0]);
#endif
                        }
                        TextRenderer.DrawText(g, _data.Series[li0].LegendLabel, li0 == _data.SeriesIDToLabelY ? _l.font_SerieslegendFeatured : _l.font_Serieslegend, _ll.Textcontainer[li0], Color.Black, Layout.textformatflags_left_break);
                    }
                    /* draw the connector line (last bar > connector point) */
                    if (lastvaluelayout != null)
                    {
                        using (var cpen = new Pen(seri.LineColor, 1.5F))
                        {
                            g.DrawCurve(cpen, new PointF[] {
                                /* first point: end of the series on the last bar */
                                new PointF(_l.bb_Plot.Right, lastvaluelayout.Slope[li0].Last <PointF>().Y),
                                /* second point: connector handle of the legend */
                                _ll.Connector[li0]
                            });
                        }
                    }
                    /* advance */
                    ++li0;
                }
                /* render the totals */
                var textline = new Rectangle((int)_l.bb_Totals.Left, (int)_l.bb_Totals.Top, (int)_l.bb_Totals.Width, (int)_l.em * 2);
                TextRenderer.DrawText(g, "Gesamteindruck:", new Font(_l.font_Valuelabels, FontStyle.Bold | FontStyle.Underline), textline, Color.Black, Layout.textformatflags_left);
                var total = String.Format("{0} von {1} Punkten ({2}%)", _data.PointsTotal, _data.PointsMax, _data.PointsPercent);
                textline.Offset(0, (int)(_l.em * 2));
                TextRenderer.DrawText(g, total, new Font(_l.font_Valuelabels, FontStyle.Bold), textline, Color.Black, Layout.textformatflags_left);
                textline.Offset(0, (int)(_l.em));
                /* totals: compared values */
                foreach (var tseri in _data.Series)
                {
                    if (tseri.SeriesID == _data.SeriesIDToLabelY)
                    {
                        if (tseri.CompareWith != null)
                        {
                            foreach (var cmp in tseri.CompareWith)
                            {
                                RenderTotalTendency(g, _l, ref textline, cmp, Color.Red, Color.Green);
                            }
                        }
                    }
                }
                /* LAST STEP: draw the rotated x-axis labels */
                var brush_xtitles = SystemBrushes.WindowText;
                foreach (var xb in _data.XBarData)
                {
                    var s = xb.XTitle;
                    using (var textpic = new Bitmap((int)_l.y2_height, (int)_l.grid_Xstep, PixelFormat.Format32bppArgb))
                    {
                        var layoutrect = new Rectangle(0, 0, (int)_l.y2_height, (int)_l.grid_Xstep);
                        using (var gt = InitGraphics(textpic))
                        {
#if DEBUG
                            DrawRectInclusive(gt, Pens.BurlyWood, layoutrect);
#endif
                            TextRenderer.DrawText(gt, s, _l.font_XLabels, layoutrect, Color.Black, Layout.textformatflags_xlbl);
                        }
                        /* this drew badly on W2008 servers... had previously been replaced by pixel-by-pixel rotation as below */
                        textpic.RotateFlip(RotateFlipType.Rotate270FlipNone);
                        g.DrawImageUnscaled(textpic, (int)(_l.grid_X[ix0].X), (int)_l.bb_XLabels.Top);

                        /* [dlatikay 20120611] had to rotate pixelwise...
                         * [dlatikay 20120622] before realizing that the graphics object text rendition properties
                         * had to be set, and that did the trick.
                         * This means, that the GDI+ default settings apparently are different on W2K/W2K8/64bit!?
                         */
                        //var rot_lft = (int)(_l.grid_X[ix0].X);
                        //var rot_btm = (int)(_l.bb_XLabels.Top + _l.y2_height) - 1;
                        //for (var x = 0; x < layoutrect.Width; ++x)
                        //    for (var y = 0; y < layoutrect.Height; ++y)
                        //        canvas.SetPixel(rot_lft + y, rot_btm - x, textpic.GetPixel(layoutrect.Left + x, layoutrect.Top + y));
                    }
                    /* draw the icon */
                    RenderIcon(g, _l, ix0, xb);
                    /* advance */
                    ++ix0;
                }
            }
            return(canvas);
        }