/// <summary> /// Draws the line plot using the Drawing Context and x and y axes provided /// </summary> /// <param name="ctx">The Drawing Context with 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(Context ctx, PhysicalAxis xAxis, PhysicalAxis yAxis) { SequenceAdapter dataTop = new SequenceAdapter(DataSource, DataMember, OrdinateDataTop, AbscissaData); SequenceAdapter dataBottom = new SequenceAdapter(DataSource, DataMember, OrdinateDataBottom, AbscissaData); ITransform2D t = Transform2D.GetTransformer(xAxis, yAxis); ctx.Save(); for (int i = 0; i < dataTop.Count; ++i) { Point physicalBottom = t.Transform(dataBottom[i]); Point physicalTop = t.Transform(dataTop[i]); if (physicalBottom != physicalTop) { Rectangle r = new Rectangle(physicalBottom.X - BarWidth / 2, physicalTop.Y, BarWidth, (physicalBottom.Y - physicalTop.Y)); ctx.SetColor(fillColor); ctx.Rectangle(r); ctx.FillPreserve(); ctx.SetColor(borderColor); ctx.Stroke(); } } ctx.Restore(); }
/// <summary> /// Draw the filled region /// </summary> /// <param name="g">The Drawing Context with 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(Context ctx, PhysicalAxis xAxis, PhysicalAxis yAxis) { ITransform2D t = Transform2D.GetTransformer(xAxis, yAxis); ctx.Save(); if (hl1 != null && hl2 != null) { ctx.MoveTo(t.Transform(xAxis.Axis.WorldMin, hl1.OrdinateValue)); ctx.LineTo(t.Transform(xAxis.Axis.WorldMax, hl1.OrdinateValue)); ctx.LineTo(t.Transform(xAxis.Axis.WorldMax, hl2.OrdinateValue)); ctx.LineTo(t.Transform(xAxis.Axis.WorldMin, hl2.OrdinateValue)); ctx.ClosePath(); } else if (vl1 != null && vl2 != null) { ctx.MoveTo(t.Transform(vl1.AbscissaValue, yAxis.Axis.WorldMin)); ctx.LineTo(t.Transform(vl1.AbscissaValue, yAxis.Axis.WorldMax)); ctx.LineTo(t.Transform(vl2.AbscissaValue, yAxis.Axis.WorldMax)); ctx.LineTo(t.Transform(vl2.AbscissaValue, yAxis.Axis.WorldMin)); ctx.ClosePath(); } else if (lp1 != null && lp2 != null) { SequenceAdapter a1 = new SequenceAdapter(lp1.DataSource, lp1.DataMember, lp1.OrdinateData, lp1.AbscissaData); SequenceAdapter a2 = new SequenceAdapter(lp2.DataSource, lp2.DataMember, lp2.OrdinateData, lp2.AbscissaData); // Start at first point of LinePlot 1 within plot bounds int start = 0; while (t.Transform(a1 [start]).X < xAxis.PhysicalMin.X) { ++start; } Point first = t.Transform(a1 [start]); ctx.MoveTo(first); // Join LinePlot 1 points in ascending order Point next; for (int i = start + 1; i < a1.Count - 1; ++i) { next = t.Transform(a1 [i]); if (next.X > xAxis.PhysicalMax.X) { break; } ctx.LineTo(next); } // Then join LinePlot 2 points in descending order int end = a2.Count - 1; while (t.Transform(a2 [end]).X > xAxis.PhysicalMax.X) { --end; } for (int i = end; i > 0; --i) { next = t.Transform(a2 [i]); if (next.X < xAxis.PhysicalMin.X) { break; } ctx.LineTo(next); } ctx.LineTo(first); ctx.ClosePath(); } else { throw new XwPlotException("Filled Region bounds not defined"); } ctx.SetColor(FillColor); ctx.Fill(); ctx.Restore(); }
/// <summary> /// Draws the line plot using the Context and Physical Axes provided /// </summary> /// <param name="ctx">The Drawing Context with 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(Context ctx, PhysicalAxis xAxis, PhysicalAxis yAxis, bool drawShadow) { SequenceAdapter data = new SequenceAdapter(DataSource, DataMember, OrdinateData, AbscissaData); ITransform2D t = Transform2D.GetTransformer(xAxis, yAxis); int numberPoints = data.Count; if (data.Count == 0) { return; } ctx.Save(); ctx.SetLineWidth(lineWidth); if (lineDash != null) { ctx.SetLineDash(0, lineDash); } if (numberPoints == 1) { Point physical = t.Transform(data[0]); if (drawShadow) { ctx.SetColor(shadowColor); ctx.MoveTo(physical.X - 0.5 + ShadowOffset.X, physical.Y + ShadowOffset.Y); ctx.LineTo(physical.X + 0.5 + ShadowOffset.X, physical.Y + ShadowOffset.Y); ctx.Stroke(); } else { ctx.SetColor(lineColor); ctx.MoveTo(physical.X - 0.5, physical.Y); ctx.LineTo(physical.X + 0.5, physical.Y); ctx.Stroke(); } } 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 && dx2 < leftCutoff) || (rightCutoff < dx1 && rightCutoff < dx2)) { continue; } // else draw line. Point p1 = t.Transform(data[i - 1]); Point 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) { ctx.SetColor(shadowColor); ctx.MoveTo(p1.X + ShadowOffset.X, p1.Y + ShadowOffset.Y); ctx.LineTo(p2.X + ShadowOffset.X, p2.Y + ShadowOffset.Y); ctx.Stroke(); } else { ctx.SetColor(lineColor); ctx.MoveTo(p1.X, p1.Y); ctx.LineTo(p2.X, p2.Y); ctx.Stroke(); } } } ctx.Restore(); }