/// <summary> /// Draws the clipped line segments. /// </summary> /// <param name="rc">The render context.</param> /// <param name="points">The points.</param> /// <param name="clippingRectangle">The clipping rectangle.</param> /// <param name="stroke">The stroke.</param> /// <param name="strokeThickness">The stroke thickness.</param> /// <param name="lineStyle">The line style.</param> /// <param name="lineJoin">The line join.</param> /// <param name="aliased">if set to <c>true</c> [aliased].</param> public static void DrawClippedLineSegments( this IRenderContext rc, IList <ScreenPoint> points, OxyRect clippingRectangle, OxyColor stroke, double strokeThickness, LineStyle lineStyle, OxyPenLineJoin lineJoin, bool aliased) { if (rc.SetClip(clippingRectangle)) { rc.DrawLineSegments(points, stroke, strokeThickness, lineStyle.GetDashArray(), lineJoin, aliased); rc.ResetClip(); return; } var clipping = new CohenSutherlandClipping(clippingRectangle.Left, clippingRectangle.Right, clippingRectangle.Top, clippingRectangle.Bottom); var clippedPoints = new List <ScreenPoint>(points.Count); for (int i = 0; i + 1 < points.Count; i += 2) { var s0 = points[i]; var s1 = points[i + 1]; if (clipping.ClipLine(ref s0, ref s1)) { clippedPoints.Add(s0); clippedPoints.Add(s1); } } rc.DrawLineSegments(clippedPoints, stroke, strokeThickness, lineStyle.GetDashArray(), lineJoin, aliased); }
/// <summary> /// Draws the polygon within the specified clipping rectangle. /// </summary> /// <param name="rc">The render context.</param> /// <param name="clippingRectangle">The clipping rectangle.</param> /// <param name="points">The points.</param> /// <param name="minDistSquared">The squared minimum distance between points.</param> /// <param name="fill">The fill color.</param> /// <param name="stroke">The stroke color.</param> /// <param name="strokeThickness">The stroke thickness.</param> /// <param name="lineStyle">The line style.</param> /// <param name="lineJoin">The line join.</param> /// <param name="aliased">The aliased.</param> public static void DrawClippedPolygon( this IRenderContext rc, OxyRect clippingRectangle, IList <ScreenPoint> points, double minDistSquared, OxyColor fill, OxyColor stroke, double strokeThickness = 1.0, LineStyle lineStyle = LineStyle.Solid, LineJoin lineJoin = LineJoin.Miter, bool aliased = false) { if (lineStyle == LineStyle.None) { return; } var outputBuffer = new List <ScreenPoint>(); ReducePoints(points, minDistSquared, outputBuffer); if (rc.SetClip(clippingRectangle)) { rc.DrawPolygon(outputBuffer, fill, stroke, strokeThickness, lineStyle.GetDashArray(), lineJoin, aliased); rc.ResetClip(); return; } var clippedPoints = SutherlandHodgmanClipping.ClipPolygon(clippingRectangle, outputBuffer); rc.DrawPolygon(clippedPoints, fill, stroke, strokeThickness, lineStyle.GetDashArray(), lineJoin, aliased); }
/// <summary> /// Draws the polygon within the specified clipping rectangle. /// </summary> /// <param name="rc">The render context.</param> /// <param name="clippingRectangle">The clipping rectangle.</param> /// <param name="points">The points.</param> /// <param name="minDistSquared">The squared minimum distance between points.</param> /// <param name="fill">The fill color.</param> /// <param name="stroke">The stroke color.</param> /// <param name="strokeThickness">The stroke thickness.</param> /// <param name="lineStyle">The line style.</param> /// <param name="lineJoin">The line join.</param> /// <param name="aliased">The aliased.</param> public static void DrawClippedPolygon( this IRenderContext rc, OxyRect clippingRectangle, IList <ScreenPoint> points, double minDistSquared, OxyColor fill, OxyColor stroke, double strokeThickness = 1.0, LineStyle lineStyle = LineStyle.Solid, LineJoin lineJoin = LineJoin.Miter, bool aliased = false) { if (lineStyle == LineStyle.None) { return; } // TODO: minDistSquared should be implemented or removed if (rc.SetClip(clippingRectangle)) { rc.DrawPolygon(points, fill, stroke, strokeThickness, lineStyle.GetDashArray(), lineJoin, aliased); rc.ResetClip(); return; } var clippedPoints = SutherlandHodgmanClipping.ClipPolygon(clippingRectangle, points); rc.DrawPolygon(clippedPoints, fill, stroke, strokeThickness, lineStyle.GetDashArray(), lineJoin, aliased); }
public override void Render(IRenderContext rc) { if (rc == null) { throw new ArgumentNullException(nameof(rc)); } if (!Lines.Any() || Lines.All(a => !a.Any())) { return; } VerifyAxes(); OxyRect clippingRect = GetClippingRect(); rc.SetClip(clippingRect); // Transform all points to screen coordinates foreach (IEnumerable <DataPoint> line in Lines) { int n0 = line.Count(); var pts0 = new ScreenPoint[n0]; TransformToScreenCoordinates(n0, pts0, line); rc.DrawLine(pts0, Color, StrokeThickness, Dashes?.ToArray() ?? LineStyle.GetDashArray()); } rc.ResetClip(); }
public override void Render(IRenderContext rc) { base.Render(rc); var sY = StartPoint.Y * (AssociatedSeries.Inverted ? -1 : 1); var eY = EndPoint.Y * (AssociatedSeries.Inverted ? -1 : 1); var actualStart = new DataPoint(StartPoint.X, sY); var actualEnd = new DataPoint(EndPoint.X, eY); _screenEndPoint = Transform(actualEnd); _screenStartPoint = Transform(actualStart); var d = _screenEndPoint - _screenStartPoint; d.Normalize(); var n = new ScreenVector(d.Y, -d.X); const double minimumSegmentLength = 4; var dashArray = LineStyle.GetDashArray(); if (!(StrokeThickness > 0) || LineStyle == LineStyle.None) { return; } rc.DrawReducedLine( new[] { _screenStartPoint, _screenEndPoint }, minimumSegmentLength * minimumSegmentLength, GetSelectableColor(ActualColor), StrokeThickness, EdgeRenderingMode, dashArray, LineJoin); }
protected void RenderLine(IRenderContext rc, OxyRect clippingRect, IList <ScreenPoint> pointsToRender, OxyColor lineColor, double strokeness, LineStyle lineStyle) { //var screenPoints = pointsToRender; var resampledPoints = ScreenPointHelper.ResamplePoints(pointsToRender, 2); //screenPoints = CreateSpline(resampledPoints, 0.5, null, false, 0.25); var outputBuffer = new List <ScreenPoint>(pointsToRender.Count); if (this.LineStyle == LineStyle.None) { foreach (ScreenPoint sp in pointsToRender) { rc.DrawMarker(clippingRect, sp, MarkerType.Diamond, null, 3, lineColor, lineColor, 1); } } else { var dash_array = lineStyle.GetDashArray(); rc.DrawClippedLine( clippingRect, pointsToRender, 0, lineColor, strokeness, dash_array, LineJoin.Round, false, outputBuffer); } }
/// <summary> /// Initializes a new instance of the <see cref="OxyPen" /> class. /// </summary> /// <param name="color">The color.</param> /// <param name="thickness">The thickness.</param> /// <param name="lineStyle">The line style.</param> /// <param name="lineJoin">The line join.</param> public OxyPen( OxyColor color, double thickness = 1.0, LineStyle lineStyle = LineStyle.Solid, LineJoin lineJoin = LineJoin.Miter) { this.Color = color; this.Thickness = thickness; this.DashArray = lineStyle.GetDashArray(); this.LineStyle = lineStyle; this.LineJoin = lineJoin; }
protected void RenderUnClippedLine(IRenderContext rc, IList <ScreenPoint> pointsToRender, OxyColor lineColor, double strokeness, LineStyle lineStyle) { var screenPoints = pointsToRender; var resampledPoints = ScreenPointHelper.ResamplePoints(pointsToRender, 2); screenPoints = CreateSpline(resampledPoints, 0.5, null, false, 0.25); var outputBuffer = new List <ScreenPoint>(pointsToRender.Count); var dash_array = lineStyle.GetDashArray(); rc.DrawLine(pointsToRender, lineColor, strokeness, dash_array, LineJoin.Round, false); }
/// <summary> /// Draws the clipped line. /// </summary> /// <param name="rc">The render context.</param> /// <param name="points">The points.</param> /// <param name="clippingRectangle">The clipping rectangle.</param> /// <param name="minDistSquared">The squared minimum distance.</param> /// <param name="stroke">The stroke.</param> /// <param name="strokeThickness">The stroke thickness.</param> /// <param name="lineStyle">The line style.</param> /// <param name="lineJoin">The line join.</param> /// <param name="aliased">if set to <c>true</c> [aliased].</param> /// <param name="pointsRendered">The points rendered callback.</param> public static void DrawClippedLine( this IRenderContext rc, IList <ScreenPoint> points, OxyRect clippingRectangle, double minDistSquared, OxyColor stroke, double strokeThickness, LineStyle lineStyle, OxyPenLineJoin lineJoin, bool aliased, Action <IList <ScreenPoint> > pointsRendered = null) { var clipping = new CohenSutherlandClipping(clippingRectangle.Left, clippingRectangle.Right, clippingRectangle.Top, clippingRectangle.Bottom); var pts = new List <ScreenPoint>(); int n = points.Count; if (n > 0) { if (n == 1) { pts.Add(points[0]); } var last = points[0]; for (int i = 1; i < n; i++) { var s0 = points[i - 1]; var s1 = points[i]; // Clipped version of this and next point. var sc0 = s0; var sc1 = s1; bool isInside = clipping.ClipLine(ref sc0, ref sc1); if (!isInside) { // keep the previous coordinate continue; } // render from s0c-s1c double dx = sc1.x - last.x; double dy = sc1.y - last.y; if ((dx * dx) + (dy * dy) > minDistSquared || i == 1 || i == n - 1) { if (!sc0.Equals(last) || i == 1) { pts.Add(sc0); } pts.Add(sc1); last = sc1; } // render the line if we are leaving the clipping region);); if (!clipping.IsInside(s1)) { if (pts.Count > 0) { EnsureNonEmptyLineIsVisible(pts); rc.DrawLine(pts, stroke, strokeThickness, lineStyle.GetDashArray(), lineJoin, aliased); if (pointsRendered != null) { pointsRendered(pts); } pts = new List <ScreenPoint>(); } } } if (pts.Count > 0) { EnsureNonEmptyLineIsVisible(pts); rc.DrawLine(pts, stroke, strokeThickness, lineStyle.GetDashArray(), lineJoin, aliased); // Execute the 'callback'. if (pointsRendered != null) { pointsRendered(pts); } } } }
/// <summary> /// Draws the clipped line. /// </summary> /// <param name="rc">The render context.</param> /// <param name="points">The points.</param> /// <param name="clippingRectangle">The clipping rectangle.</param> /// <param name="minDistSquared">The squared minimum distance.</param> /// <param name="stroke">The stroke.</param> /// <param name="strokeThickness">The stroke thickness.</param> /// <param name="lineStyle">The line style.</param> /// <param name="lineJoin">The line join.</param> /// <param name="aliased">if set to <c>true</c> [aliased].</param> /// <param name="pointsRendered">The points rendered callback.</param> public static void DrawClippedLine( this IRenderContext rc, IList<ScreenPoint> points, OxyRect clippingRectangle, double minDistSquared, OxyColor stroke, double strokeThickness, LineStyle lineStyle, OxyPenLineJoin lineJoin, bool aliased, Action<IList<ScreenPoint>> pointsRendered = null) { var clipping = new CohenSutherlandClipping(clippingRectangle.Left, clippingRectangle.Right, clippingRectangle.Top, clippingRectangle.Bottom); var pts = new List<ScreenPoint>(); int n = points.Count; if (n > 0) { if (n == 1) { pts.Add(points[0]); } var last = points[0]; for (int i = 1; i < n; i++) { var s0 = points[i - 1]; var s1 = points[i]; // Clipped version of this and next point. var sc0 = s0; var sc1 = s1; bool isInside = clipping.ClipLine(ref sc0, ref sc1); if (!isInside) { // keep the previous coordinate continue; } // render from s0c-s1c double dx = sc1.x - last.x; double dy = sc1.y - last.y; if ((dx * dx) + (dy * dy) > minDistSquared || i == 1 || i == n - 1) { if (!sc0.Equals(last) || i == 1) { pts.Add(sc0); } pts.Add(sc1); last = sc1; } // render the line if we are leaving the clipping region);); if (!clipping.IsInside(s1)) { if (pts.Count > 0) { EnsureNonEmptyLineIsVisible(pts); rc.DrawLine(pts, stroke, strokeThickness, lineStyle.GetDashArray(), lineJoin, aliased); if (pointsRendered != null) { pointsRendered(pts); } pts = new List<ScreenPoint>(); } } } if (pts.Count > 0) { EnsureNonEmptyLineIsVisible(pts); rc.DrawLine(pts, stroke, strokeThickness, lineStyle.GetDashArray(), lineJoin, aliased); // Execute the 'callback'. if (pointsRendered != null) { pointsRendered(pts); } } } }
/// <summary> /// Draws the polygon within the specified clipping rectangle. /// </summary> /// <param name="rc"> /// The render context. /// </param> /// <param name="points"> /// The points. /// </param> /// <param name="clippingRectangle"> /// The clipping rectangle. /// </param> /// <param name="minDistSquared"> /// The squared minimum distance between points. /// </param> /// <param name="fill"> /// The fill. /// </param> /// <param name="stroke"> /// The stroke. /// </param> /// <param name="strokeThickness"> /// The stroke thickness. /// </param> /// <param name="lineStyle"> /// The line style. /// </param> /// <param name="lineJoin"> /// The line join. /// </param> /// <param name="aliased"> /// The aliased. /// </param> public static void DrawClippedPolygon( this IRenderContext rc, IList<ScreenPoint> points, OxyRect clippingRectangle, double minDistSquared, OxyColor fill, OxyColor stroke, double strokeThickness = 1.0, LineStyle lineStyle = LineStyle.Solid, OxyPenLineJoin lineJoin = OxyPenLineJoin.Miter, bool aliased = false) { if (rc.SetClip(clippingRectangle)) { rc.DrawPolygon(points, fill, stroke, strokeThickness, lineStyle.GetDashArray(), lineJoin, aliased); rc.ResetClip(); return; } var clippedPoints = SutherlandHodgmanClipping.ClipPolygon(clippingRectangle, points); rc.DrawPolygon( clippedPoints, fill, stroke, strokeThickness, lineStyle.GetDashArray(), lineJoin, aliased); }
/// <summary> /// Draws the clipped line segments. /// </summary> /// <param name="rc">The render context.</param> /// <param name="points">The points.</param> /// <param name="clippingRectangle">The clipping rectangle.</param> /// <param name="stroke">The stroke.</param> /// <param name="strokeThickness">The stroke thickness.</param> /// <param name="lineStyle">The line style.</param> /// <param name="lineJoin">The line join.</param> /// <param name="aliased">if set to <c>true</c> [aliased].</param> public static void DrawClippedLineSegments( this IRenderContext rc, IList<ScreenPoint> points, OxyRect clippingRectangle, OxyColor stroke, double strokeThickness, LineStyle lineStyle, OxyPenLineJoin lineJoin, bool aliased) { if (rc.SetClip(clippingRectangle)) { rc.DrawLineSegments(points, stroke, strokeThickness, lineStyle.GetDashArray(), lineJoin, aliased); rc.ResetClip(); return; } var clipping = new CohenSutherlandClipping(clippingRectangle.Left, clippingRectangle.Right, clippingRectangle.Top, clippingRectangle.Bottom); var clippedPoints = new List<ScreenPoint>(points.Count); for (int i = 0; i + 1 < points.Count; i += 2) { var s0 = points[i]; var s1 = points[i + 1]; if (clipping.ClipLine(ref s0, ref s1)) { clippedPoints.Add(s0); clippedPoints.Add(s1); } } rc.DrawLineSegments(clippedPoints, stroke, strokeThickness, lineStyle.GetDashArray(), lineJoin, aliased); }
/// <summary> /// Draws the clipped line. /// </summary> /// <param name="rc">The render context.</param> /// <param name="points">The points.</param> /// <param name="clippingRectangle">The clipping rectangle.</param> /// <param name="minDistSquared">The min dist squared.</param> /// <param name="stroke">The stroke.</param> /// <param name="strokeThickness">The stroke thickness.</param> /// <param name="lineStyle">The line style.</param> /// <param name="lineJoin">The line join.</param> /// <param name="aliased">if set to <c>true</c> [aliased].</param> /// <param name="pointsRendered">The points rendered callback.</param> public static void DrawClippedLine( this IRenderContext rc, IList <ScreenPoint> points, OxyRect clippingRectangle, double minDistSquared, OxyColor stroke, double strokeThickness, LineStyle lineStyle, OxyPenLineJoin lineJoin, bool aliased, Action <IList <ScreenPoint> > pointsRendered = null) { var clipping = new CohenSutherlandClipping(clippingRectangle.Left, clippingRectangle.Right, clippingRectangle.Top, clippingRectangle.Bottom); var pts = new List <ScreenPoint>(); int n = points.Count; if (n > 0) { if (n == 1) { pts.Add(points[0]); } var last = points[0]; for (int i = 1; i < n; i++) { var s0 = points[i - 1]; var s1 = points[i]; // Clipped version of this and next point. var s0c = s0; var s1c = s1; bool isInside = clipping.ClipLine(ref s0c, ref s1c); s0 = s1; if (!isInside) { // keep the previous coordinate continue; } // render from s0c-s1c double dx = s1c.x - last.x; double dy = s1c.y - last.y; if (dx * dx + dy * dy > minDistSquared || i == 1 || i == n - 1) { if (!s0c.Equals(last) || i == 1) { pts.Add(s0c); } pts.Add(s1c); last = s1c; } // render the line if we are leaving the clipping region);); if (!clipping.IsInside(s1)) { if (pts.Count > 0) { rc.DrawLine( pts, stroke, strokeThickness, lineStyle.GetDashArray(), lineJoin, aliased); if (pointsRendered != null) { pointsRendered(pts); } pts = new List <ScreenPoint>(); } } } // Check if the line contains two points and they are at the same point if (pts.Count == 2) { if (pts[0].DistanceTo(pts[1]) < 1) { // Modify to a small horizontal line to make sure it is being rendered pts[1] = new ScreenPoint(pts[0].X + 1, pts[0].Y); pts[0] = new ScreenPoint(pts[0].X - 1, pts[0].Y); } } // Check if the line contains a single point if (pts.Count == 1) { // Add a second point to make sure the line is being rendered as a small dot pts.Add(new ScreenPoint(pts[0].X + 1, pts[0].Y)); pts[0] = new ScreenPoint(pts[0].X - 1, pts[0].Y); } if (pts.Count > 0) { rc.DrawLine(pts, stroke, strokeThickness, lineStyle.GetDashArray(), lineJoin, aliased); // Execute the 'callback'. if (pointsRendered != null) { pointsRendered(pts); } } } }
/// <summary> /// Draws the clipped line. /// </summary> /// <param name="rc">The render context.</param> /// <param name="points">The points.</param> /// <param name="clippingRectangle">The clipping rectangle.</param> /// <param name="minDistSquared">The min dist squared.</param> /// <param name="stroke">The stroke.</param> /// <param name="strokeThickness">The stroke thickness.</param> /// <param name="lineStyle">The line style.</param> /// <param name="lineJoin">The line join.</param> /// <param name="aliased">if set to <c>true</c> [aliased].</param> /// <param name="pointsRendered">The points rendered callback.</param> public static void DrawClippedLine( this IRenderContext rc, IList<ScreenPoint> points, OxyRect clippingRectangle, double minDistSquared, OxyColor stroke, double strokeThickness, LineStyle lineStyle, OxyPenLineJoin lineJoin, bool aliased, Action<IList<ScreenPoint>> pointsRendered = null) { var clipping = new CohenSutherlandClipping(clippingRectangle.Left, clippingRectangle.Right, clippingRectangle.Top, clippingRectangle.Bottom); var pts = new List<ScreenPoint>(); int n = points.Count; if (n > 0) { if (n == 1) { pts.Add(points[0]); } var last = points[0]; for (int i = 1; i < n; i++) { var s0 = points[i - 1]; var s1 = points[i]; // Clipped version of this and next point. var s0c = s0; var s1c = s1; bool isInside = clipping.ClipLine(ref s0c, ref s1c); s0 = s1; if (!isInside) { // keep the previous coordinate continue; } // render from s0c-s1c double dx = s1c.x - last.x; double dy = s1c.y - last.y; if (dx * dx + dy * dy > minDistSquared || i == 1 || i == n - 1) { if (!s0c.Equals(last) || i == 1) { pts.Add(s0c); } pts.Add(s1c); last = s1c; } // render the line if we are leaving the clipping region);); if (!clipping.IsInside(s1)) { if (pts.Count > 0) { rc.DrawLine( pts, stroke, strokeThickness, lineStyle.GetDashArray(), lineJoin, aliased); if (pointsRendered != null) { pointsRendered(pts); } pts = new List<ScreenPoint>(); } } } // Check if the line contains two points and they are at the same point if (pts.Count == 2) { if (pts[0].DistanceTo(pts[1]) < 1) { // Modify to a small horizontal line to make sure it is being rendered pts[1] = new ScreenPoint(pts[0].X + 1, pts[0].Y); pts[0] = new ScreenPoint(pts[0].X - 1, pts[0].Y); } } // Check if the line contains a single point if (pts.Count == 1) { // Add a second point to make sure the line is being rendered as a small dot pts.Add(new ScreenPoint(pts[0].X + 1, pts[0].Y)); pts[0] = new ScreenPoint(pts[0].X - 1, pts[0].Y); } if (pts.Count > 0) { rc.DrawLine(pts, stroke, strokeThickness, lineStyle.GetDashArray(), lineJoin, aliased); // Execute the 'callback'. if (pointsRendered != null) { pointsRendered(pts); } } } }
public override void Render(IRenderContext rc, PlotModel model1, AxisLayer axisLayer, int pass) { #if DEBUG_MAP Console.WriteLine("render timecategoryaxis " + this.Name); #endif PlotModel model = this.PlotModel; OxyColor live_color = OxyColors.Red; OxyColor forecast_color = OxyColors.Red; OxyColor separator_color = OxyColors.Red; OxyColor grid_color = OxyColors.Red; //OxyColor line_color = OxyColors.Red; if (Theme != null) { AxisStyle style = Theme.GetStyle(ThemeMode) as AxisStyle; TitleColor = Helper.ConvertColorToOxyColor(style.TitleColor); TextColor = Helper.ConvertColorToOxyColor(style.LabelColor); TicklineColor = Helper.ConvertColorToOxyColor(style.LineColor); live_color = Helper.ConvertColorToOxyColor(style.LiveColor); forecast_color = Helper.ConvertColorToOxyColor(style.ForecastColor); separator_color = Helper.ConvertColorToOxyColor(style.SepatorColor); grid_color = Helper.ConvertColorToOxyColor(style.GridColor); } //找到所有的y轴 if (TimeLines != null) { //绘制线标值和线条 FeatureTextIntersector intersector = new FeatureTextIntersector(FeatureTextIntersector.SortStyle.Horizontal, 3); for (int i = 0; i < TimeLines.Count; i++) { string label = TimeLines[i].Time.ToString("dd-HH"); OxySize size = rc.MeasureText(label); double x = TransformX(TimeLines[i].Index); if (x < model.PlotArea.Left || x > model.PlotArea.Right) { continue; } double y = model.PlotArea.Bottom; double y2 = y + 5; //if (TimeLines[i].TimeStyle == TimeStyle.Seperator) // continue; intersector.Add(new FeatureText(label, new ScreenPoint(x, y + 7), size, new ScreenPoint(x, y))); } List <FeatureText> features = intersector.DiscaredIntersection(this.Angle); if (features != null) { foreach (FeatureText feature in features) { rc.DrawText(feature.Position, feature.Text, TextColor, this.ActualFont, this.ActualFontSize, 200, this.Angle, HorizontalAlignment.Left, VerticalAlignment.Middle); } } //绘制纵线 foreach (Axis axis in model.Axes) { if (axis.Position == AxisPosition.Left || axis.Position == AxisPosition.Right) { if (axis is IAxis) { IAxis y_axis = axis as IAxis; if (!y_axis.AxisVisible) { continue; } foreach (TimeLine line in TimeLines) { OxyColor color = OxyColors.Red; double thickness = 1; LineStyle style = LineStyle.Solid; switch (line.TimeStyle) { case TimeStyle.Forecast: color = forecast_color; style = LineStyle.Dash; break; case TimeStyle.Live: color = live_color; break; case TimeStyle.Seperator: color = separator_color; style = LineStyle.Dash; thickness = 2; break; } IList <ScreenPoint> sps = new List <ScreenPoint>(); double x = TransformX(line.Index); double top = y_axis.Bound.Top; sps.Add(new ScreenPoint(x, top)); sps.Add(new ScreenPoint(x, y_axis.Bound.Bottom)); rc.DrawClippedLine(y_axis.Bound, sps, 2, color, thickness, style.GetDashArray(), LineJoin.Round, false); } } } } } }