123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221 |
- using ScottPlot.Drawing;
- using ScottPlot.Ticks;
- using System;
- using System.Drawing;
- using System.Linq;
- namespace ScottPlot.Renderable
- {
- static class AxisTicksRender
- {
- private static bool EdgeIsVertical(Edge edge) => (edge == Edge.Left || edge == Edge.Right);
- private static bool EdgeIsHorizontal(Edge edge) => (edge == Edge.Top || edge == Edge.Bottom);
- public static void RenderGridLines(PlotDimensions dims, Graphics gfx, double[] majorPositions, double[] minorPositions, double[] tickPositionSmajor,
- LineStyle gridLineStyle, Color gridLineColor, float gridLineWidth, Edge edge)
- {
- if (majorPositions is null || majorPositions.Length == 0 || minorPositions is null || minorPositions.Length == 0 || gridLineStyle == LineStyle.None)
- return;
- // don't draw grid lines on the last pixel to prevent drawing over the data frame
- float xEdgeLeft = dims.DataOffsetX + 1;
- float xEdgeRight = dims.DataOffsetX + dims.DataWidth - 1;
- float yEdgeTop = dims.DataOffsetY + 1;
- float yEdgeBottom = dims.DataOffsetY + dims.DataHeight - 1;
- if (EdgeIsVertical(edge))
- {
- //float x = (edge == Edge.Left) ? dims.DataOffsetX : dims.DataOffsetX + dims.DataWidth;
- //float x2 = (edge == Edge.Left) ? dims.DataOffsetX + dims.DataWidth : dims.DataOffsetX;
- var ys = majorPositions.Select(i => dims.GetPixelY(i)).Where(y => yEdgeTop < y && y < yEdgeBottom);
- if (gridLineStyle != LineStyle.None)
- using (var pen = GDI.Pen(gridLineColor, gridLineWidth, gridLineStyle))
- {
- //foreach (float y in ys)
- // gfx.DrawLine(pen, x, y, x2, y);
- Brush brush = new SolidBrush(gridLineColor);
- foreach (var itemx in tickPositionSmajor)
- {
- foreach (var itemy in minorPositions)
- {
- gfx.FillRectangle(brush, dims.GetPixelX(itemx), dims.GetPixelY(itemy), 1, 1);
- }
- foreach (float y in ys)
- {
- gfx.FillRectangle(brush, dims.GetPixelX(itemx), y, 1, 1);
- }
- }
- }
- }
- if (EdgeIsHorizontal(edge))
- {
- //float y = (edge == Edge.Top) ? dims.DataOffsetY : dims.DataOffsetY + dims.DataHeight;
- //float y2 = (edge == Edge.Top) ? dims.DataOffsetY + dims.DataHeight : dims.DataOffsetY;
- var xs = majorPositions.Select(i => dims.GetPixelX(i)).Where(x => xEdgeLeft < x && x < xEdgeRight);
- if (gridLineStyle != LineStyle.None)
- using (var pen = GDI.Pen(gridLineColor, gridLineWidth, gridLineStyle))
- {
- Brush brush = new SolidBrush(gridLineColor);
- foreach (var itemy in tickPositionSmajor)
- {
- foreach (var itemx in minorPositions)
- {
- gfx.FillRectangle(brush, dims.GetPixelX(itemx), dims.GetPixelY(itemy), 1, 1);
- }
- foreach (float x in xs)
- {
- gfx.FillRectangle(brush, x, dims.GetPixelY(itemy), 1, 1);
- }
- }
- }
- }
- }
- public static void RenderTickMarks(PlotDimensions dims, Graphics gfx, double[] positions,double[] tickPositionsMajor, float tickLength, Color tickColor, Edge edge, float pixelOffset)
- {
- if (positions is null || positions.Length == 0)
- return;
- if (EdgeIsVertical(edge))
- {
- float x = (edge == Edge.Left) ? dims.DataOffsetX - pixelOffset : dims.DataOffsetX + dims.DataWidth + pixelOffset;
- float tickDelta = (edge == Edge.Left) ? -tickLength : tickLength;
- var ys = positions.Select(i => dims.GetPixelY(i));
- var tickmajorys = tickPositionsMajor.Select(i => dims.GetPixelY(i));
- using (var pen = GDI.Pen(tickColor))
- {
- foreach (float y in ys)
- {
- //if (y > dims.DataOffsetY + dims.DataHeight || y < dims.DataOffsetY)
- // continue;
- gfx.DrawLine(pen, x, y, x - tickDelta, y);
- }
- foreach (var ty in tickmajorys)
- {
- gfx.DrawLine(pen, x, ty, x - tickDelta, ty);
- }
- }
- }
- if (EdgeIsHorizontal(edge))
- {
- float y = (edge == Edge.Top) ? dims.DataOffsetY - pixelOffset : dims.DataOffsetY + dims.DataHeight + pixelOffset;
- float tickDelta = (edge == Edge.Top) ? -tickLength : tickLength;
- var xs = positions.Select(i => dims.GetPixelX(i));
- var tickmajorxs = tickPositionsMajor.Select(i => dims.GetPixelX(i));
- using (var pen = GDI.Pen(tickColor))
- {
- foreach (float x in xs)
- {
- //if (x > dims.DataOffsetX + dims.DataWidth || y < dims.DataOffsetX)
- // continue;
- gfx.DrawLine(pen, x, y, x, y - tickDelta);
- }
- foreach (var tx in tickmajorxs)
- {
- gfx.DrawLine(pen, tx, y, tx, y - tickDelta);
- }
- }
- }
- }
- /// <summary>
- /// 绘制刻度的label
- /// </summary>
- /// <param name="dims"></param>
- /// <param name="gfx"></param>
- /// <param name="axisColor"></param>
- /// <param name="tc"></param>
- /// <param name="tickFont"></param>
- /// <param name="edge"></param>
- /// <param name="rotation"></param>
- /// <param name="rulerMode"></param>
- /// <param name="PixelOffset"></param>
- /// <param name="MajorTickLength"></param>
- /// <param name="MinorTickLength"></param>
- /// <param name="rectangle"></param>
- public static void RenderTickLabels(PlotDimensions dims, Graphics gfx, Color axisColor, TickCollection tc, Drawing.Font tickFont, Edge edge, float rotation, bool rulerMode, float PixelOffset, float MajorTickLength, float MinorTickLength, bool rectangle)
- {
- if (tc.tickLabels is null || tc.tickLabels.Length == 0)
- return;
- using (var font = GDI.Font(tickFont))
- using (var brush = GDI.Brush(tickFont.Color))
- using (var sf = GDI.StringFormat())
- {
- // TODO: Refactor to improve rotated tick label rendering:
- // 1) rotation should always be assumed
- // 2) a separate function should translate/rotate/render/reset
- // 3) all edges should support rotation
- if (edge == Edge.Bottom)//画在底部
- {
- sf.Alignment = rulerMode ? StringAlignment.Near : StringAlignment.Center;
- sf.LineAlignment = StringAlignment.Near;
- for (int i = 0; i < tc.tickPositionsMajor.Length; i++)
- {
- if (rectangle)
- {
- gfx.FillRectangle(GDI.Brush(Color.Black),
- x: dims.GetPixelX(tc.tickPositionsMajor[i]) - tc.tickLabels[i].Length * font.Height / 4,
- y: dims.DataOffsetY + dims.DataHeight - PixelOffset - MajorTickLength - font.Height,
- width: tc.tickLabels[i].Length * font.Height / 2,
- height: font.Height + 2);
- }
- gfx.DrawString(tc.tickLabels[i], font, GDI.Brush(axisColor), format: sf,
- x: dims.GetPixelX(tc.tickPositionsMajor[i]),
- y: dims.DataOffsetY + dims.DataHeight - PixelOffset - MajorTickLength - font.Height);
- }
- }
- else if (edge == Edge.Top)//画在上部
- {
- sf.Alignment = rulerMode ? StringAlignment.Near : StringAlignment.Center;
- sf.LineAlignment = StringAlignment.Near;
- for (int i = 0; i < tc.tickPositionsMajor.Length; i++)
- gfx.DrawString(tc.tickLabels[i], font, GDI.Brush(axisColor), format: sf,
- x: dims.GetPixelX(tc.tickPositionsMajor[i]),
- y: dims.DataOffsetY + PixelOffset - MajorTickLength + 10 + font.Height);
- }
- else if (edge == Edge.Left)//画在左方
- {
- sf.LineAlignment = rulerMode ? StringAlignment.Far : StringAlignment.Center;
- sf.Alignment = StringAlignment.Near;
- for (int i = 0; i < tc.tickPositionsMajor.Length; i++)
- gfx.DrawString(tc.tickLabels[i], font, GDI.Brush(axisColor), format: sf,
- x: dims.DataOffsetX + PixelOffset + 40,
- y: dims.GetPixelY(tc.tickPositionsMajor[i]));
- }
- else if (edge == Edge.Right)//画在右方
- {
- sf.LineAlignment = rulerMode ? StringAlignment.Far : StringAlignment.Center;
- sf.Alignment = StringAlignment.Far;
- for (int i = 0; i < tc.tickPositionsMajor.Length; i++)
- {
- var maxLabelSize = GDI.MeasureString(tc.tickLabels[i].Trim(), tickFont);
- if (rectangle)
- {
- gfx.FillRectangle(GDI.Brush(Color.Black),
- x: dims.DataOffsetX + dims.DataWidth - PixelOffset - 34 - maxLabelSize.Width,
- y: dims.GetPixelY(tc.tickPositionsMajor[i]) - font.Height / 2 - 3,
- width: tc.tickLabels[i].Length * font.Height / 2,
- height: font.Height + 2);
- }
- gfx.DrawString(tc.tickLabels[i], font, GDI.Brush(axisColor), format: sf,
- x: dims.DataOffsetX - PixelOffset - 30 + dims.DataWidth,
- y: dims.GetPixelY(tc.tickPositionsMajor[i]));
- }
- }
- else
- {
- throw new NotImplementedException();
- }
- }
- }
- }
- }
|