public override void Render(Settings settings)
        {
            if (label is null)
            {
                return;
            }

            SizeF size = GDI.MeasureString(settings.gfxData, label, font);

            double x = (xPixel >= 0) ? xPixel : settings.bmpData.Width + xPixel - size.Width;
            double y = (yPixel >= 0) ? yPixel : settings.bmpData.Height + yPixel - size.Height;

            PointF location = new PointF((float)x, (float)y);

            if (fill && shadow)
            {
                settings.gfxData.FillRectangle(shadowBrush, location.X + 5, location.Y + 5, size.Width, size.Height);
            }

            if (fill)
            {
                settings.gfxData.FillRectangle(fillBrush, location.X, location.Y, size.Width, size.Height);
            }

            if (pen.Width > 0)
            {
                settings.gfxData.DrawRectangle(pen, location.X, location.Y, size.Width, size.Height);
            }

            settings.gfxData.DrawString(label, font, fontBrush, location);
        }
Пример #2
0
        public override void Render(Settings settings)
        {
            float widthPx  = (float)(sizeX * settings.xAxisScale);
            float heightPx = (float)(sizeY * settings.yAxisScale);

            using (var font = new Font(fontName, (float)fontSize, fontStyle))
                using (var brush = new SolidBrush(color))
                    using (var pen = new Pen(color, (float)thickness))
                    {
                        PointF cornerPoint = settings.GetPixel(settings.axes.x.Max, settings.axes.y.Min);
                        cornerPoint.X -= (float)padPx;
                        cornerPoint.Y -= (float)padPx;

                        var xLabelSize = GDI.MeasureString(settings.gfxData, labelX, font);
                        var yLabelSize = GDI.MeasureString(settings.gfxData, labelY, font);
                        cornerPoint.X -= yLabelSize.Width * 1.2f;
                        cornerPoint.Y -= yLabelSize.Height;

                        PointF horizPoint    = new PointF(cornerPoint.X - widthPx, cornerPoint.Y);
                        PointF vertPoint     = new PointF(cornerPoint.X, cornerPoint.Y - heightPx);
                        PointF horizMidPoint = new PointF((cornerPoint.X + horizPoint.X) / 2, cornerPoint.Y);
                        PointF vertMidPoint  = new PointF(cornerPoint.X, (cornerPoint.Y + vertPoint.Y) / 2);

                        settings.gfxData.DrawLines(pen, new PointF[] { horizPoint, cornerPoint, vertPoint });
                        settings.gfxData.DrawString(labelX, font, brush, horizMidPoint.X, cornerPoint.Y, settings.misc.sfNorth);
                        settings.gfxData.DrawString(labelY, font, brush, cornerPoint.X, vertMidPoint.Y, settings.misc.sfWest);
                    }
        }
Пример #3
0
        private void RecalculatePositionsAutomaticDatetime(Settings settings)
        {
            // the goal of this function is to set tickPositionsMajor, tickLabels, tickPositionsMinor, cornerLabel, and maxLabelSize
            double low, high;
            int    tickCount;

            // predict maxLabelSize up front using predetermined label sizes
            maxLabelSize = GDI.MeasureString(settings.gfxData, "2019-08-20\n8:42:17 PM", settings.ticks.font);

            if (verticalAxis)
            {
                low       = settings.axes.y.Min - settings.yAxisUnitsPerPixel; // add an extra pixel to capture the edge tick
                high      = settings.axes.y.Max + settings.yAxisUnitsPerPixel; // add an extra pixel to capture the edge tick
                tickCount = (int)(settings.dataSize.Height / maxLabelSize.Height);
            }
            else
            {
                low       = settings.axes.x.Min - settings.xAxisUnitsPerPixel; // add an extra pixel to capture the edge tick
                high      = settings.axes.x.Max + settings.xAxisUnitsPerPixel; // add an extra pixel to capture the edge tick
                tickCount = (int)(settings.dataSize.Width / maxLabelSize.Width);
            }

            if (low < high)
            {
                low  = Math.Max(low, DateTime.MinValue.ToOADate());
                high = Math.Min(high, DateTime.MaxValue.ToOADate());

                var dtManualUnits   = (verticalAxis) ? settings.ticks.manualDateTimeSpacingUnitY : settings.ticks.manualDateTimeSpacingUnitX;
                var dtManualSpacing = (verticalAxis) ? settings.ticks.manualSpacingY : settings.ticks.manualSpacingX;

                var dateTicks = DateTimeTicks.GetTicks(DateTime.FromOADate(low), DateTime.FromOADate(high), tickCount, settings.culture, dtManualUnits, (int)dtManualSpacing);

                tickPositionsMajor = Tools.DateTimesToDoubles(dateTicks.Item1);
                tickLabels         = dateTicks.Item2;
                for (int i = 0; i < tickLabels.Length; i++)
                {
                    if (tickLabels[i].Contains(", "))
                    {
                        tickLabels[i] = tickLabels[i].Replace(", ", "\n");
                    }
                    else
                    {
                        tickLabels[i] += "\n "; // auto-layout works better if dates are always two lines
                    }
                }
            }
            else
            {
                tickPositionsMajor = new double[] { };
            }

            // dont forget to set all the things
            tickPositionsMinor = null;
            cornerLabel        = null;
            maxLabelSize       = LargestLabel(settings, tickLabels);
        }
Пример #4
0
        public SizeF LargestLabel(Settings settings, string[] labels)
        {
            SizeF max = new SizeF(0, 0);

            foreach (string label in labels)
            {
                SizeF tickLabelSize = GDI.MeasureString(settings.gfxData, label, settings.ticks.font);
                max.Width  = Math.Max(max.Width, tickLabelSize.Width);
                max.Height = Math.Max(max.Height, tickLabelSize.Height);
            }
            return(max);
        }
Пример #5
0
        private static void RenderTickMultipliers(Settings settings)
        {
            Brush brush = new SolidBrush(settings.ticks.colour);

            if ((settings.ticks.x.cornerLabel != "") && settings.ticks.displayXmajor)
            {
                SizeF multiplierLabelXsize = GDI.MeasureString(settings.gfxFigure, settings.ticks.x.cornerLabel, settings.ticks.font);
                settings.gfxFigure.DrawString(settings.ticks.x.cornerLabel, settings.ticks.font, brush,
                                              settings.dataOrigin.X + settings.dataSize.Width,
                                              settings.dataOrigin.Y + settings.dataSize.Height + multiplierLabelXsize.Height,
                                              settings.misc.sfNorthEast);
            }

            if ((settings.ticks.y.cornerLabel != "") && settings.ticks.displayYmajor)
            {
                settings.gfxFigure.DrawString(settings.ticks.y.cornerLabel, settings.ticks.font, brush,
                                              settings.dataOrigin.X,
                                              settings.dataOrigin.Y,
                                              settings.misc.sfSouthWest);
            }
        }
Пример #6
0
        public void Resize(int width, int height, bool useMeasuredStrings = false)
        {
            if (useMeasuredStrings && gfxData != null)
            {
                // this section was added before display scaling issues (pixel-referenced font sizes) were figured out.
                // it is probably not needed...

                string sampleString = "IPjg8.8";
                layout.yLabelWidth  = (int)GDI.MeasureString(gfxData, sampleString, yLabel.font).Height;
                layout.y2LabelWidth = (int)GDI.MeasureString(gfxData, sampleString, yLabel.font).Height; // currently y2 isn't supported
                layout.titleHeight  = (int)GDI.MeasureString(gfxData, sampleString, title.font).Height;
                layout.xLabelHeight = (int)GDI.MeasureString(gfxData, sampleString, xLabel.font).Height;

                var tickSize = GDI.MeasureString(gfxData, "0.001", ticks.font);
                layout.yScaleWidth  = (int)tickSize.Width;
                layout.y2ScaleWidth = (int)tickSize.Height; // currently y2 isn't supported
                layout.xScaleHeight = (int)tickSize.Height;
            }

            layout.Update(width, height);

            if (axes.equalAxes)
            {
                var limits = new AxisLimits2D(axes.ToArray());

                double xUnitsPerPixel = limits.xSpan / dataSize.Width;
                double yUnitsPerPixel = limits.ySpan / dataSize.Height;

                if (yUnitsPerPixel > xUnitsPerPixel)
                {
                    axes.Zoom(xUnitsPerPixel / yUnitsPerPixel, 1);
                }
                else
                {
                    axes.Zoom(1, yUnitsPerPixel / xUnitsPerPixel);
                }
            }
        }
Пример #7
0
        public static void DrawMarker(Graphics gfx, PointF pixelLocation, MarkerShape shape, float size, Color color)
        {
            Pen   pen   = new Pen(color);
            Brush brush = new SolidBrush(color);

            PointF     corner1 = new PointF(pixelLocation.X - size / 2, pixelLocation.Y - size / 2);
            PointF     corner2 = new PointF(pixelLocation.X + size / 2, pixelLocation.Y + size / 2);
            SizeF      bounds  = new SizeF(size, size);
            RectangleF rect    = new RectangleF(corner1, bounds);

            switch (shape)
            {
            case MarkerShape.filledCircle:
                gfx.FillEllipse(brush, rect);
                break;

            case MarkerShape.openCircle:
                gfx.DrawEllipse(pen, rect);
                break;

            case MarkerShape.filledSquare:
                gfx.FillRectangle(brush, rect);
                break;

            case MarkerShape.openSquare:
                gfx.DrawRectangle(pen, corner1.X, corner1.Y, size, size);
                break;

            case MarkerShape.filledDiamond:

                // Create points that define polygon.
                PointF point1 = new PointF(pixelLocation.X, pixelLocation.Y + size / 2);
                PointF point2 = new PointF(pixelLocation.X - size / 2, pixelLocation.Y);
                PointF point3 = new PointF(pixelLocation.X, pixelLocation.Y - size / 2);
                PointF point4 = new PointF(pixelLocation.X + size / 2, pixelLocation.Y);

                PointF[] curvePoints = { point1, point2, point3, point4 };

                //Draw polygon to screen
                gfx.FillPolygon(brush, curvePoints);
                break;

            case MarkerShape.openDiamond:

                // Create points that define polygon.
                PointF point5 = new PointF(pixelLocation.X, pixelLocation.Y + size / 2);
                PointF point6 = new PointF(pixelLocation.X - size / 2, pixelLocation.Y);
                PointF point7 = new PointF(pixelLocation.X, pixelLocation.Y - size / 2);
                PointF point8 = new PointF(pixelLocation.X + size / 2, pixelLocation.Y);

                PointF[] curvePoints2 = { point5, point6, point7, point8 };

                //Draw polygon to screen
                gfx.DrawPolygon(pen, curvePoints2);

                break;

            case MarkerShape.asterisk:
                Font   drawFont      = new Font("CourierNew", size * 3);
                SizeF  textSize      = GDI.MeasureString(gfx, "*", drawFont);
                PointF asteriskPoint = new PointF(pixelLocation.X - textSize.Width / 2, pixelLocation.Y - textSize.Height / 4);
                gfx.DrawString("*", drawFont, brush, asteriskPoint);

                break;

            case MarkerShape.hashTag:
                Font   drawFont2      = new Font("CourierNew", size * 2);
                SizeF  textSize2      = GDI.MeasureString(gfx, "#", drawFont2);
                PointF asteriskPoint2 = new PointF(pixelLocation.X - textSize2.Width / 2, pixelLocation.Y - textSize2.Height / 3);
                gfx.DrawString("#", drawFont2, brush, asteriskPoint2);

                break;

            case MarkerShape.cross:
                Font   drawFont3      = new Font("CourierNew", size * 2);
                SizeF  textSize3      = GDI.MeasureString(gfx, "+", drawFont3);
                PointF asteriskPoint3 = new PointF(pixelLocation.X - textSize3.Width / (5 / 2), pixelLocation.Y - textSize3.Height / 2);
                gfx.DrawString("+", drawFont3, brush, asteriskPoint3);

                break;

            case MarkerShape.eks:
                Font   drawFont4      = new Font("CourierNew", size * 2);
                SizeF  textSize4      = GDI.MeasureString(gfx, "x", drawFont4);
                PointF asteriskPoint4 = new PointF(pixelLocation.X - textSize4.Width / (5 / 2), pixelLocation.Y - textSize4.Height / 2);
                gfx.DrawString("x", drawFont4, brush, asteriskPoint4);

                break;

            case MarkerShape.verticalBar:
                Font   drawFont5      = new Font("CourierNew", size * 2);
                SizeF  textSize5      = GDI.MeasureString(gfx, "|", drawFont5);
                PointF asteriskPoint5 = new PointF(pixelLocation.X - textSize5.Width / (5 / 2), pixelLocation.Y - textSize5.Height / 2);
                gfx.DrawString("|", drawFont5, brush, asteriskPoint5);

                break;

            case MarkerShape.triUp:
                // Create points that define polygon.
                PointF point9  = new PointF(pixelLocation.X, pixelLocation.Y - size);
                PointF point10 = new PointF(pixelLocation.X, pixelLocation.Y);
                PointF point11 = new PointF(pixelLocation.X - size * (float)0.866, pixelLocation.Y + size * (float)0.5);
                PointF point12 = new PointF(pixelLocation.X, pixelLocation.Y);
                PointF point13 = new PointF(pixelLocation.X + size * (float)0.866, (pixelLocation.Y + size * (float)0.5));


                PointF[] curvePoints3 = { point12, point9, point10, point11, point12, point13 };

                //Draw polygon to screen
                gfx.DrawPolygon(pen, curvePoints3);

                break;

            case MarkerShape.triDown:
                // Create points that define polygon.
                PointF point14 = new PointF(pixelLocation.X, pixelLocation.Y + size);
                PointF point15 = new PointF(pixelLocation.X, pixelLocation.Y);
                PointF point16 = new PointF(pixelLocation.X - size * (float)0.866, pixelLocation.Y - size * (float)0.5);
                PointF point17 = new PointF(pixelLocation.X, pixelLocation.Y);
                PointF point18 = new PointF(pixelLocation.X + size * (float)0.866, (pixelLocation.Y - size * (float)0.5));


                PointF[] curvePoints4 = { point17, point14, point15, point16, point17, point18 };

                //Draw polygon to screen
                gfx.DrawPolygon(pen, curvePoints4);

                break;

            case MarkerShape.none:
                break;

            default:
                throw new NotImplementedException($"unsupported marker type: {shape}");
            }
        }
Пример #8
0
        public override void Render(Settings settings)
        {
            PointF defaultPoint      = settings.GetPixel(x, y);
            PointF textLocationPoint = new PointF();
            SizeF  stringSize        = GDI.MeasureString(settings.gfxData, text, font);

            if (rotation == 0)
            {
                switch (alignment)
                {
                case TextAlignment.lowerCenter:
                    textLocationPoint.Y = defaultPoint.Y - stringSize.Height;
                    textLocationPoint.X = defaultPoint.X - stringSize.Width / 2;
                    break;

                case TextAlignment.lowerLeft:
                    textLocationPoint.Y = defaultPoint.Y - stringSize.Height;
                    textLocationPoint.X = defaultPoint.X;
                    break;

                case TextAlignment.lowerRight:
                    textLocationPoint.Y = defaultPoint.Y - stringSize.Height;
                    textLocationPoint.X = defaultPoint.X - stringSize.Width;
                    break;

                case TextAlignment.middleLeft:
                    textLocationPoint.Y = defaultPoint.Y - stringSize.Height / 2;
                    textLocationPoint.X = defaultPoint.X;
                    break;

                case TextAlignment.middleRight:
                    textLocationPoint.Y = defaultPoint.Y - stringSize.Height / 2;
                    textLocationPoint.X = defaultPoint.X - stringSize.Width;
                    break;

                case TextAlignment.upperCenter:
                    textLocationPoint.Y = defaultPoint.Y;
                    textLocationPoint.X = defaultPoint.X - stringSize.Width / 2;
                    break;

                case TextAlignment.upperLeft:
                    textLocationPoint = defaultPoint;
                    break;

                case TextAlignment.upperRight:
                    textLocationPoint.Y = defaultPoint.Y;
                    textLocationPoint.X = defaultPoint.X - stringSize.Width;
                    break;

                case TextAlignment.middleCenter:
                    textLocationPoint.Y = defaultPoint.Y - stringSize.Height / 2;
                    textLocationPoint.X = defaultPoint.X - stringSize.Width / 2;
                    break;
                }
            }
            else
            {
                // ignore alignment if rotation is used
                textLocationPoint = new PointF(defaultPoint.X, defaultPoint.Y);
            }

            settings.gfxData.TranslateTransform((int)textLocationPoint.X, (int)textLocationPoint.Y);
            settings.gfxData.RotateTransform((float)rotation);
            if (frame)
            {
                Rectangle stringRect = new Rectangle(0, 0, (int)stringSize.Width, (int)stringSize.Height);
                settings.gfxData.FillRectangle(frameBrush, stringRect);
            }
            settings.gfxData.DrawString(text, font, brush, new PointF(0, 0));
            settings.gfxData.ResetTransform();
        }
Пример #9
0
        public static Bitmap DesignerModeBitmap(Size size, bool drawArrows = false)
        {
            Bitmap bmp = new Bitmap(size.Width, size.Height);

            Graphics gfx = Graphics.FromImage(bmp);

            gfx.Clear(ColorTranslator.FromHtml("#003366"));
            Brush brushLogo         = new SolidBrush(ColorTranslator.FromHtml("#FFFFFF"));
            Brush brushMeasurements = new SolidBrush(ColorTranslator.FromHtml("#006699"));
            Pen   pen = new Pen(ColorTranslator.FromHtml("#006699"), 3);

            pen.StartCap = System.Drawing.Drawing2D.LineCap.Round;
            pen.EndCap   = System.Drawing.Drawing2D.LineCap.Round;
            float arrowSize = 7;
            float padding   = 3;

            // logo
            FontFamily ff = new FontFamily(Fonts.GetDefaultFontName());

            gfx.DrawString("ScottPlot", new Font(ff, 24, FontStyle.Bold), brushLogo, 10, 10);
            var titleSize = GDI.MeasureString(gfx, "ScottPlot", new Font(ff, 24, FontStyle.Bold));

            gfx.DrawString($"version {GetVersionString()}", new Font(ff, 12, FontStyle.Italic), brushLogo, 12, (int)(10 + titleSize.Height * .7));

            if (drawArrows)
            {
                // horizontal arrow
                PointF left   = new PointF(padding, size.Height / 2);
                PointF leftA  = new PointF(left.X + arrowSize, left.Y + arrowSize);
                PointF leftB  = new PointF(left.X + arrowSize, left.Y - arrowSize);
                PointF right  = new PointF(size.Width - padding, size.Height / 2);
                PointF rightA = new PointF(right.X - arrowSize, right.Y + arrowSize);
                PointF rightB = new PointF(right.X - arrowSize, right.Y - arrowSize);
                gfx.DrawLine(pen, left, right);
                gfx.DrawLine(pen, left, leftA);
                gfx.DrawLine(pen, left, leftB);
                gfx.DrawLine(pen, right, rightA);
                gfx.DrawLine(pen, right, rightB);
                gfx.DrawString($"{size.Width}px",
                               new Font(ff, 12, FontStyle.Bold), brushMeasurements,
                               (float)(size.Width * .2), (float)(size.Height * .5));

                // vertical arrow
                PointF top  = new PointF(size.Width / 2, padding);
                PointF topA = new PointF(top.X - arrowSize, top.Y + arrowSize);
                PointF topB = new PointF(top.X + arrowSize, top.Y + arrowSize);
                PointF bot  = new PointF(size.Width / 2, size.Height - padding);
                PointF botA = new PointF(bot.X - arrowSize, bot.Y - arrowSize);
                PointF botB = new PointF(bot.X + arrowSize, bot.Y - arrowSize);
                gfx.DrawLine(pen, top, bot);
                gfx.DrawLine(pen, bot, botA);
                gfx.DrawLine(pen, bot, botB);
                gfx.DrawLine(pen, top, topA);
                gfx.DrawLine(pen, top, topB);
                gfx.RotateTransform(-90);
                gfx.DrawString($"{size.Height}px",
                               new Font(ff, 12, FontStyle.Bold), brushMeasurements,
                               (float)(-size.Height * .4), (float)(size.Width * .5));
            }

            return(bmp);
        }
Пример #10
0
        private void RecalculatePositionsAutomaticNumeric(Settings settings)
        {
            // predict maxLabelSize up front using predetermined label sizes
            string longestLabel = (dateFormat) ? "2019-08-20\n20:42:17" : "-8888";

            maxLabelSize = GDI.MeasureString(settings.gfxData, longestLabel, settings.ticks.font);

            double low, high, tickSpacing;
            int    maxTickCount;

            if (verticalAxis)
            {
                low          = settings.axes.y.Min - settings.yAxisUnitsPerPixel; // add an extra pixel to capture the edge tick
                high         = settings.axes.y.Max + settings.yAxisUnitsPerPixel; // add an extra pixel to capture the edge tick
                maxTickCount = (int)(settings.dataSize.Height / maxLabelSize.Height);
                tickSpacing  = (settings.ticks.manualSpacingY != 0) ? settings.ticks.manualSpacingY : GetIdealTickSpacing(low, high, maxTickCount);
            }
            else
            {
                low          = settings.axes.x.Min - settings.xAxisUnitsPerPixel; // add an extra pixel to capture the edge tick
                high         = settings.axes.x.Max + settings.xAxisUnitsPerPixel; // add an extra pixel to capture the edge tick
                maxTickCount = (int)(settings.dataSize.Width / maxLabelSize.Width * 1.2);
                tickSpacing  = (settings.ticks.manualSpacingX != 0) ? settings.ticks.manualSpacingX : GetIdealTickSpacing(low, high, maxTickCount);
            }

            // now that tick spacing is known, populate the list of ticks and labels
            double        firstTickOffset = low % (double)tickSpacing;
            List <double> positions       = new List <double>();

            for (double position = low - firstTickOffset; position < high; position += (double)tickSpacing)
            {
                if ((low < position) && (high > position))
                {
                    positions.Add(position);
                }
                if (positions.Count > 999)
                {
                    break;
                }
            }
            tickPositionsMajor = positions.ToArray();

            if (dateFormat)
            {
                tickLabels         = GetDateLabels(tickPositionsMajor, settings.culture);
                tickPositionsMinor = null;
            }
            else
            {
                (tickLabels, cornerLabel) = GetPrettyTickLabels(
                    tickPositionsMajor,
                    settings.ticks.useMultiplierNotation,
                    settings.ticks.useOffsetNotation,
                    settings.ticks.useExponentialNotation,
                    invertSign: invertSign,
                    culture: settings.culture
                    );

                if (logScale)
                {
                    tickPositionsMinor = MinorFromMajorLog(tickPositionsMajor, low, high);
                }
                else
                {
                    tickPositionsMinor = MinorFromMajor(tickPositionsMajor, 5, low, high);
                }
            }

            // now set the maximum label size based on the actual labels created
            maxLabelSize = LargestLabel(settings, tickLabels);
        }