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}"); } }
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(); }
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); }
public PlottableScatter(double[] xs, double[] ys, Color color, double lineWidth, double markerSize, string label, double[] errorX, double[] errorY, double errorLineWidth, double errorCapSize, bool stepDisplay, MarkerShape markerShape, LineStyle lineStyle) { if ((xs == null) || (ys == null)) { throw new ArgumentException("X and Y data cannot be null"); } if ((xs.Length == 0) || (ys.Length == 0)) { throw new ArgumentException("xs and ys must have at least one element"); } if (xs.Length != ys.Length) { throw new ArgumentException("Xs and Ys must have same length"); } if (errorY != null) { for (int i = 0; i < errorY.Length; i++) { if (errorY[i] < 0) { errorY[i] = -errorY[i]; } } } if (errorX != null) { for (int i = 0; i < errorX.Length; i++) { if (errorX[i] < 0) { errorX[i] = -errorX[i]; } } } this.xs = xs; this.ys = ys; this.color = color; this.lineWidth = lineWidth; this.markerSize = (float)markerSize; this.label = label; this.errorX = errorX; this.errorY = errorY; this.errorLineWidth = (float)errorLineWidth; this.errorCapSize = (float)errorCapSize; this.stepDisplay = stepDisplay; this.markerShape = markerShape; this.lineStyle = lineStyle; if (xs.Length != ys.Length) { throw new ArgumentException("X and Y arrays must have the same length"); } if ((errorX != null) && (xs.Length != errorX.Length)) { throw new ArgumentException("errorX must be the same length as the original data"); } if ((errorY != null) && (xs.Length != errorY.Length)) { throw new ArgumentException("errorY must be the same length as the original data"); } penLine = GDI.Pen(color, lineWidth, lineStyle, true); penLineError = GDI.Pen(color, errorLineWidth, LineStyle.Solid, true); }
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); }