/// <summary> /// Draws the line plot on a GDI+ surface against the provided x and y axes. /// </summary> /// <param name="g">The GDI+ surface on which to draw.</param> /// <param name="xAxis">The X-Axis to draw against.</param> /// <param name="yAxis">The Y-Axis to draw against.</param> /// <param name="drawShadow">If true draw the shadow for the line. If false, draw line.</param> public void DrawLineOrShadow(Graphics g, PhysicalAxis xAxis, PhysicalAxis yAxis, bool drawShadow) { Pen shadowPen = null; if (drawShadow) { shadowPen = (Pen)this.Pen.Clone(); shadowPen.Color = this.ShadowColor; } SequenceAdapter data = new SequenceAdapter(this.DataSource, this.DataMember, this.OrdinateData, this.AbscissaData); int numberPoints = data.Count; if (data.Count == 0) { return; } // clipping is now handled assigning a clip region in the // graphic object before this call if (numberPoints == 1) { PointF physical = Transform2D.GetTransformer(xAxis, yAxis).Transform(data[0]); if (drawShadow) { g.DrawLine(shadowPen, physical.X - 0.5f + this.ShadowOffset.X, physical.Y + this.ShadowOffset.Y, physical.X + 0.5f + this.ShadowOffset.X, physical.Y + this.ShadowOffset.Y); } else { g.DrawLine(Pen, physical.X - 0.5f, physical.Y, physical.X + 0.5f, physical.Y); } } else { // prepare for clipping double leftCutoff = xAxis.PhysicalToWorld(xAxis.PhysicalMin, false); double rightCutoff = xAxis.PhysicalToWorld(xAxis.PhysicalMax, false); if (leftCutoff > rightCutoff) { double temp = leftCutoff; leftCutoff = rightCutoff; rightCutoff = temp; } if (drawShadow) { // correct cut-offs double shadowCorrection = xAxis.PhysicalToWorld(ShadowOffset, false) - xAxis.PhysicalToWorld(new Point(0, 0), false); leftCutoff -= shadowCorrection; rightCutoff -= shadowCorrection; } // determine which points to plot double tradingTimeOffset = 0; List <PointD> plotPoints = new List <PointD>(numberPoints); PointD d1 = data[0]; PointD d2 = d1; if ((d1.X >= leftCutoff) && (d1.X <= rightCutoff)) { plotPoints.Add(d1); } DateTime prevTime = (DateTime)((System.Data.DataTable) this.DataSource).Rows[0][(string)this.AbscissaData]; for (int i = 1; i < numberPoints; ++i) { // check to see if any values null. If so, then continue. d1 = d2; d2 = data[i]; if (Double.IsNaN(d1.X) || Double.IsNaN(d1.Y) || Double.IsNaN(d2.X) || Double.IsNaN(d2.Y)) { continue; } // Get the X axis offset to strip out the non-trading time d1.X -= tradingTimeOffset; DateTime nextTime = (DateTime)((System.Data.DataTable) this.DataSource).Rows[i][(string)this.AbscissaData]; if (nextTime.TimeOfDay < prevTime.TimeOfDay) { tradingTimeOffset += (double)(nextTime - prevTime).Ticks; } prevTime = nextTime; d2.X -= tradingTimeOffset; // do horizontal clipping here, to speed up if ((d1.X < leftCutoff && d2.X < leftCutoff) || (rightCutoff < d1.X && rightCutoff < d2.X)) { continue; } // Add a point to plot plotPoints.Add(d2); } // create a transform, which takes into account the skipped time PhysicalAxis shunkAxis = new PhysicalAxis(new DateTimeAxis(xAxis.Axis.WorldMin, xAxis.Axis.WorldMax - tradingTimeOffset), xAxis.PhysicalMin, xAxis.PhysicalMax); ITransform2D t = Transform2D.GetTransformer(shunkAxis, yAxis); // plot those points for (int i = 1; i < plotPoints.Count; i++) { // else draw line. PointF p1 = t.Transform(plotPoints[i - 1]); PointF p2 = t.Transform(plotPoints[i]); // when very far zoomed in, points can fall ontop of each other, // and g.DrawLine throws an overflow exception if (p1.Equals(p2)) { continue; } if (drawShadow) { g.DrawLine(shadowPen, p1.X + ShadowOffset.X, p1.Y + ShadowOffset.Y, p2.X + ShadowOffset.X, p2.Y + ShadowOffset.Y); } else { g.DrawLine(Pen, p1.X, p1.Y, p2.X, p2.Y); } } } }
/// <summary> /// Draws the line plot on a GDI+ surface against the provided x and y axes. /// </summary> /// <param name="g">The GDI+ surface on which to draw.</param> /// <param name="xAxis">The X-Axis to draw against.</param> /// <param name="yAxis">The Y-Axis to draw against.</param> /// <param name="drawShadow">If true draw the shadow for the line. If false, draw line.</param> public void DrawLineOrShadow(Graphics g, PhysicalAxis xAxis, PhysicalAxis yAxis, bool drawShadow) { Pen shadowPen = null; if (drawShadow) { shadowPen = (Pen)Pen.Clone(); shadowPen.Color = ShadowColor; } SequenceAdapter data = new SequenceAdapter(DataSource, DataMember, OrdinateData, AbscissaData); ITransform2D t = Transform2D.GetTransformer(xAxis, yAxis); int numberPoints = data.Count; if (data.Count == 0) { return; } // clipping is now handled assigning a clip region in the // graphic object before this call if (numberPoints == 1) { PointF physical = t.Transform(data[0]); if (drawShadow) { g.DrawLine(shadowPen, physical.X - 0.5f + ShadowOffset.X, physical.Y + ShadowOffset.Y, physical.X + 0.5f + ShadowOffset.X, physical.Y + ShadowOffset.Y); } else { g.DrawLine(Pen, physical.X - 0.5f, physical.Y, physical.X + 0.5f, physical.Y); } } else { // prepare for clipping double leftCutoff = xAxis.PhysicalToWorld(xAxis.PhysicalMin, false); double rightCutoff = xAxis.PhysicalToWorld(xAxis.PhysicalMax, false); if (leftCutoff > rightCutoff) { Utils.Swap(ref leftCutoff, ref rightCutoff); } if (drawShadow) { // correct cut-offs double shadowCorrection = xAxis.PhysicalToWorld(ShadowOffset, false) - xAxis.PhysicalToWorld(new Point(0, 0), false); leftCutoff -= shadowCorrection; rightCutoff -= shadowCorrection; } for (int i = 1; i < numberPoints; ++i) { // check to see if any values null. If so, then continue. double dx1 = data[i - 1].X; double dx2 = data[i].X; double dy1 = data[i - 1].Y; double dy2 = data[i].Y; if (Double.IsNaN(dx1) || Double.IsNaN(dy1) || Double.IsNaN(dx2) || Double.IsNaN(dy2)) { continue; } // do horizontal clipping here, to speed up if ((dx1 < leftCutoff || rightCutoff < dx1) && (dx2 < leftCutoff || rightCutoff < dx2)) { continue; } // else draw line. PointF p1 = t.Transform(data[i - 1]); PointF p2 = t.Transform(data[i]); // when very far zoomed in, points can fall ontop of each other, // and g.DrawLine throws an overflow exception if (p1.Equals(p2)) { continue; } if (drawShadow) { g.DrawLine(shadowPen, p1.X + ShadowOffset.X, p1.Y + ShadowOffset.Y, p2.X + ShadowOffset.X, p2.Y + ShadowOffset.Y); } else { g.DrawLine(Pen, p1.X, p1.Y, p2.X, p2.Y); } } } }
/// <summary> /// Draws the line plot on a GDI+ surface against the provided x and y axes. /// </summary> /// <param name="g">The GDI+ surface on which to draw.</param> /// <param name="xAxis">The X-Axis to draw against.</param> /// <param name="yAxis">The Y-Axis to draw against.</param> public void Draw(Graphics g, PhysicalAxis xAxis, PhysicalAxis yAxis) { try { double xVal, yVal; int pointCount = m_lineData.Count; if (pointCount == 0) return; Stopwatch sw = StepTimer.Start("Transform"); Transform2D t = new Transform2D(xAxis, yAxis); // clipping is now handled assigning a clip region in the // graphic object before this call if (pointCount == 1) { m_lineData.Get(0, out xVal, out yVal); PointF physical = t.Transform(xVal, yVal); g.DrawLine(Pen, physical.X - 0.5f, physical.Y, physical.X + 0.5f, physical.Y); } else { int index = 0; PointF[] points = new PointF[pointCount]; PointF lastPoint = new PointF(Single.NaN, Single.NaN); for (int i = 0; i < pointCount; ++i) { // check to see if any values null. If so, then continue. m_lineData.Get(i, out xVal, out yVal); if (!Double.IsNaN(xVal + yVal)) //Adding a NaN with anything yeilds NaN { const float GDIMax = 1000000000f; const float GDIMin = -1000000000f; PointF p1 = t.Transform(xVal, yVal); if (p1.X > GDIMax) p1.X = GDIMax; if (p1.X < GDIMin) p1.X = GDIMin; if (p1.Y > GDIMax) p1.Y = GDIMax; if (p1.Y < GDIMin) p1.Y = GDIMin; if (!float.IsNaN(p1.X) && !float.IsNaN(p1.Y)) { if (p1 != lastPoint) { lastPoint = p1; points[index] = p1; index++; } } } } //System.Drawing.Drawing2D.GraphicsPath graphicsPath = new System.Drawing.Drawing2D.GraphicsPath(); //graphicsPath.AddLines(points.ToArray()); //g.DrawPath(Pen, graphicsPath); //g.CompositingQuality = CompositingQuality.HighQuality; //g.SmoothingMode = SmoothingMode.HighQuality; StepTimer.Stop(sw); sw = StepTimer.Start("GDI+"); if (index == 0) return; else if (index == 1) { PointF physical = points[0]; g.DrawLine(Pen, physical.X - 0.5f, physical.Y, physical.X + 0.5f, physical.Y); return; } if (index == points.Length) { g.DrawLines(Pen, points); } else { PointF[] newArray = new PointF[index]; Array.Copy(points, 0, newArray, 0, index); g.DrawLines(Pen, newArray); } StepTimer.Stop(sw); } } catch (Exception ex) { MessageBox.Show(ex.ToString()); throw; } }
/// <summary> /// Draws the line plot on a GDI+ surface against the provided x and y axes. /// </summary> /// <param name="g">The GDI+ surface on which to draw.</param> /// <param name="xAxis">The X-Axis to draw against.</param> /// <param name="yAxis">The Y-Axis to draw against.</param> public void Draw(Graphics g, PhysicalAxis xAxis, PhysicalAxis yAxis) { try { double xVal, yVal; int pointCount = m_lineData.Count; if (pointCount == 0) { return; } Stopwatch sw = StepTimer.Start("Transform"); Transform2D t = new Transform2D(xAxis, yAxis); // clipping is now handled assigning a clip region in the // graphic object before this call if (pointCount == 1) { m_lineData.Get(0, out xVal, out yVal); PointF physical = t.Transform(xVal, yVal); g.DrawLine(Pen, physical.X - 0.5f, physical.Y, physical.X + 0.5f, physical.Y); } else { int index = 0; PointF[] points = new PointF[pointCount]; PointF lastPoint = new PointF(Single.NaN, Single.NaN); for (int i = 0; i < pointCount; ++i) { // check to see if any values null. If so, then continue. m_lineData.Get(i, out xVal, out yVal); if (!Double.IsNaN(xVal + yVal)) //Adding a NaN with anything yeilds NaN { const float GDIMax = 1000000000f; const float GDIMin = -1000000000f; PointF p1 = t.Transform(xVal, yVal); if (p1.X > GDIMax) { p1.X = GDIMax; } if (p1.X < GDIMin) { p1.X = GDIMin; } if (p1.Y > GDIMax) { p1.Y = GDIMax; } if (p1.Y < GDIMin) { p1.Y = GDIMin; } if (!float.IsNaN(p1.X) && !float.IsNaN(p1.Y)) { if (p1 != lastPoint) { lastPoint = p1; points[index] = p1; index++; } } } } //System.Drawing.Drawing2D.GraphicsPath graphicsPath = new System.Drawing.Drawing2D.GraphicsPath(); //graphicsPath.AddLines(points.ToArray()); //g.DrawPath(Pen, graphicsPath); //g.CompositingQuality = CompositingQuality.HighQuality; //g.SmoothingMode = SmoothingMode.HighQuality; StepTimer.Stop(sw); sw = StepTimer.Start("GDI+"); if (index == 0) { return; } else if (index == 1) { PointF physical = points[0]; g.DrawLine(Pen, physical.X - 0.5f, physical.Y, physical.X + 0.5f, physical.Y); return; } if (index == points.Length) { g.DrawLines(Pen, points); } else { PointF[] newArray = new PointF[index]; Array.Copy(points, 0, newArray, 0, index); g.DrawLines(Pen, newArray); } StepTimer.Stop(sw); } } catch (Exception ex) { MessageBox.Show(ex.ToString()); throw; } }