/// <summary> /// Draw the <see cref="Symbol"/> to the specified <see cref="Graphics"/> device /// at the specified location. This routine draws a single symbol. /// </summary> /// <param name="g"> /// A graphic device object to be drawn into. This is normally e.Graphics from the /// PaintEventArgs argument to the Paint() method. /// </param> /// <param name="pane"> /// A reference to the <see cref="ZedGraph.GraphPane"/> object that is the parent or /// owner of this object. /// </param> /// <param name="x">The x position of the center of the symbol in /// pixel units</param> /// <param name="y">The y position of the center of the symbol in /// pixel units</param> /// <param name="scaleFactor"> /// The scaling factor for the features of the graph based on the <see cref="PaneBase.BaseDimension"/>. This /// scaling factor is calculated by the <see cref="PaneBase.CalcScaleFactor"/> method. The scale factor /// represents a linear multiple to be applied to font sizes, symbol sizes, etc. /// </param> /// <param name="dataValue">The data value to be used for a value-based /// color gradient. This is only applicable for <see cref="FillType.GradientByX"/>, /// <see cref="FillType.GradientByY"/> or <see cref="FillType.GradientByZ"/>.</param> /// <param name="isSelected">Indicates that the <see cref="Symbol" /> should be drawn /// with attributes from the <see cref="Selection" /> class. /// </param> public void DrawSymbol(Graphics g, GraphPane pane, int x, int y, float scaleFactor, bool isSelected, PointPair dataValue) { Symbol source = this; if (isSelected) { source = Selection.Symbol; } // Only draw if the symbol is visible if (_isVisible && this.Type != SymbolType.None && x < 100000 && x > -100000 && y < 100000 && y > -100000) { SmoothingMode sModeSave = g.SmoothingMode; if (_isAntiAlias) { g.SmoothingMode = SmoothingMode.HighQuality; } using (Pen pen = _border.GetPen(pane, scaleFactor, dataValue)) using (GraphicsPath path = this.MakePath(g, scaleFactor)) using (Brush brush = this.Fill.MakeBrush(path.GetBounds(), dataValue)) { DrawSymbol(g, x, y, path, pen, brush); } g.SmoothingMode = sModeSave; } }
/// <summary> /// Used internally to draw symbol. /// </summary> internal static void DrawSymbol(Graphics g, GraphPane pane, SymbolType type, int x, int y, float size, bool isVisible, Fill fill, Border border, float scaleFactor, bool isAntiAlias, IPointPair dataValue) { // Only draw if the symbol is visible if (!isVisible || type == SymbolType.None || Math.Abs(x) >= 100000 || Math.Abs(y) >= 100000) { return; } var sModeSave = g.SmoothingMode; if (isAntiAlias) { g.SmoothingMode = SmoothingMode.HighQuality; } using (var pen = border.GetPen(pane, scaleFactor, dataValue)) using (var path = MakePath(g, type, scaleFactor, size)) using (var brush = fill.MakeBrush(path.GetBounds(), dataValue)) drawSymbol(g, x, y, path, pen, brush, type, fill, border); g.SmoothingMode = sModeSave; }
/// <summary> /// Do all rendering associated with this <see cref="GasGaugeRegion"/> item to the specified /// <see cref="Graphics"/> device. This method is normally only /// called by the Draw method of the parent <see cref="ZedGraph.CurveList"/> /// collection object. /// </summary> /// <param name="g"> /// A graphic device object to be drawn into. This is normally e.Graphics from the /// PaintEventArgs argument to the Paint() method. /// </param> /// <param name="pane"> /// A reference to the <see cref="ZedGraph.GraphPane"/> object that is the parent or /// owner of this object. /// </param> /// <param name="pos">Not used for rendering GasGaugeNeedle</param> /// <param name="scaleFactor"> /// The scaling factor to be used for rendering objects. This is calculated and /// passed down by the parent <see cref="ZedGraph.GraphPane"/> object using the /// <see cref="PaneBase.CalcScaleFactor"/> method, and is used to proportionally adjust /// font sizes, etc. according to the actual size of the graph. /// </param> public override void Draw(Graphics g, GraphPane pane, int pos, float scaleFactor) { if (pane.Chart._rect.Width <= 0 && pane.Chart._rect.Height <= 0) { SlicePath = null; } else { CalcRectangle(g, pane, scaleFactor, pane.Chart._rect); SlicePath = new GraphicsPath(); if (!_isVisible) { return; } var tRect = _boundingRectangle; if (tRect.Width >= 1 && tRect.Height >= 1) { var sMode = g.SmoothingMode; g.SmoothingMode = SmoothingMode.AntiAlias; SlicePath.AddPie( tRect.X, tRect.Y, tRect.Width, tRect.Height, -0.0f, -180.0f); g.FillPie( Fill.MakeBrush(_boundingRectangle), tRect.X, tRect.Y, tRect.Width, tRect.Height, -StartAngle, -SweepAngle); if (Border.IsVisible) { var borderPen = _border.GetPen(pane, scaleFactor); g.DrawPie( borderPen, tRect.X, tRect.Y, tRect.Width, tRect.Height, -0.0f, -180.0f); borderPen.Dispose(); } g.SmoothingMode = sMode; } } }
/// <summary> /// Render the label for this <see cref="PieItem"/>. /// </summary> /// <param name="g"> /// A graphic device object to be drawn into. This is normally e.Graphics from the /// PaintEventArgs argument to the Paint() method. /// </param> /// <param name="pane"> /// A graphic device object to be drawn into. This is normally e.Graphics from the /// PaintEventArgs argument to the Paint() method. /// </param> /// <param name="rect">Bounding rectangle for this <see cref="PieItem"/>.</param> /// <param name="scaleFactor"> /// The scaling factor to be used for rendering objects. This is calculated and /// passed down by the parent <see cref="ZedGraph.GraphPane"/> object using the /// <see cref="PaneBase.CalcScaleFactor"/> method, and is used to proportionally adjust /// font sizes, etc. according to the actual size of the graph. /// </param> public void DrawLabel(Graphics g, GraphPane pane, RectangleF rect, float scaleFactor) { if (!_labelDetail.IsVisible) { return; } using (var labelPen = Border.GetPen(pane, scaleFactor)) { //draw line from intersection point to pivot point - g.DrawLine(labelPen, _intersectionPoint, _pivotPoint); //draw horizontal line to move label away from pie... g.DrawLine(labelPen, _pivotPoint, _endPoint); } //draw the label (TextObj) _labelDetail.Draw(g, pane, scaleFactor); }
/// <summary> /// Do all rendering associated with this <see cref="PieItem"/> item to the specified /// <see cref="Graphics"/> device. This method is normally only /// called by the Draw method of the parent <see cref="ZedGraph.CurveList"/> /// collection object. /// </summary> /// <param name="g"> /// A graphic device object to be drawn into. This is normally e.Graphics from the /// PaintEventArgs argument to the Paint() method. /// </param> /// <param name="pane"> /// A reference to the <see cref="ZedGraph.GraphPane"/> object that is the parent or /// owner of this object. /// </param> /// <param name="pos">Not used for rendering Pies</param>param> /// <param name="scaleFactor"> /// The scaling factor to be used for rendering objects. This is calculated and /// passed down by the parent <see cref="ZedGraph.GraphPane"/> object using the /// <see cref="PaneBase.CalcScaleFactor"/> method, and is used to proportionally adjust /// font sizes, etc. according to the actual size of the graph. /// </param> override public void Draw(Graphics g, GraphPane pane, int pos, float scaleFactor) { if (pane.Chart._rect.Width <= 0 && pane.Chart._rect.Height <= 0) { //pane.PieRect = RectangleF.Empty; _slicePath = null; } else { //pane.PieRect = CalcPieRect( g, pane, scaleFactor, pane.ChartRect ); CalcPieRect(g, pane, scaleFactor, pane.Chart._rect); _slicePath = new GraphicsPath(); if (!_isVisible) { return; } RectangleF tRect = _boundingRectangle; if (tRect.Width >= 1 && tRect.Height >= 1) { SmoothingMode sMode = g.SmoothingMode; g.SmoothingMode = SmoothingMode.AntiAlias; Fill tFill = _fill; Border tBorder = _border; if (this.IsSelected) { tFill = Selection.Fill; tBorder = Selection.Border; } using (Brush brush = tFill.MakeBrush(_boundingRectangle)) { g.FillPie(brush, tRect.X, tRect.Y, tRect.Width, tRect.Height, this.StartAngle, this.SweepAngle); //add GraphicsPath for hit testing _slicePath.AddPie(tRect.X, tRect.Y, tRect.Width, tRect.Height, this.StartAngle, this.SweepAngle); if (this.Border.IsVisible) { using (Pen borderPen = tBorder.GetPen(pane, scaleFactor)) { g.DrawPie(borderPen, tRect.X, tRect.Y, tRect.Width, tRect.Height, this.StartAngle, this.SweepAngle); } } if (_labelType != PieLabelType.None) { DrawLabel(g, pane, tRect, scaleFactor); } //brush.Dispose(); } g.SmoothingMode = sMode; } } }
/// <summary> /// Draw this <see cref="CurveItem"/> to the specified <see cref="Graphics"/> /// device as a symbol at each defined point. The routine /// only draws the symbols; the lines are draw by the /// <see cref="Line.DrawCurve"/> method. This method /// is normally only called by the Draw method of the /// <see cref="CurveItem"/> object /// </summary> /// <param name="g"> /// A graphic device object to be drawn into. This is normally e.Graphics from the /// PaintEventArgs argument to the Paint() method. /// </param> /// <param name="pane"> /// A reference to the <see cref="GraphPane"/> object that is the parent or /// owner of this object. /// </param> /// <param name="curve">A <see cref="LineItem"/> representing this /// curve.</param> /// <param name="scaleFactor"> /// The scaling factor to be used for rendering objects. This is calculated and /// passed down by the parent <see cref="GraphPane"/> object using the /// <see cref="PaneBase.CalcScaleFactor"/> method, and is used to proportionally adjust /// font sizes, etc. according to the actual size of the graph. /// </param> /// <param name="isSelected">Indicates that the <see cref="Symbol" /> should be drawn /// with attributes from the <see cref="Selection" /> class. /// </param> public void Draw(Graphics g, GraphPane pane, LineItem curve, float scaleFactor, bool isSelected) { var source = isSelected ? Selection.Symbol : this; var minX = (int)pane.Chart.Rect.Left; var maxX = (int)pane.Chart.Rect.Right; var minY = (int)pane.Chart.Rect.Top; var maxY = (int)pane.Chart.Rect.Bottom; var points = curve.Points; if (points == null || !IsVisible || (!Border.IsVisible && !Fill.IsVisible)) { return; } var sModeSave = g.SmoothingMode; if (IsAntiAlias) { g.SmoothingMode = SmoothingMode.HighQuality; } // For the sake of speed, go ahead and create a solid brush and a pen // If it's a gradient fill, it will be created on the fly for each symbol //SolidBrush brush = new SolidBrush( this.fill.Color ); using (var pen = source.Border.GetPen(pane, scaleFactor)) using (var path = MakePath(g, scaleFactor)) { var rect = path.GetBounds(); using (var brush = source.Fill.MakeBrush(rect)) { var valueHandler = new ValueHandler(pane, false); var xScale = curve.GetXAxis(pane).Scale; var yScale = curve.GetYAxis(pane).Scale; var xIsLog = xScale.IsLog; var yIsLog = yScale.IsLog; var xIsOrdinal = xScale.IsAnyOrdinal; var xMin = xScale.Min; var xMax = xScale.Max; // (Dale-a-b) we'll set an element to true when it has been drawn var isPixelDrawn = new bool[maxX + 1, maxY + 1]; // Loop over each defined point for (var i = 0; i < points.Count; i++) { // Get the user scale values for the current point // use the valueHandler only for stacked types double curX; double curY; if (pane.LineType == LineType.Stack) { double lowVal; valueHandler.GetValues(curve, i, out curX, out lowVal, out curY); } // otherwise, just access the values directly. Avoiding the valueHandler for // non-stacked types is an optimization to minimize overhead in case there are // a large number of points. else { curX = points[i].X; curY = curve is StickItem ? points[i].Z : points[i].Y; } // Any value set to double max is invalid and should be skipped // This is used for calculated values that are out of range, divide // by zero, etc. // Also, any value <= zero on a log scale is invalid if (curX == PointPair.Missing || curY == PointPair.Missing || double.IsNaN(curX) || double.IsNaN(curY) || double.IsInfinity(curX) || double.IsInfinity(curY) || (!(curX > 0) && xIsLog) || (yIsLog && !(curY > 0.0)) || (!xIsOrdinal && (!(curX >= xMin) || !(curX <= xMax)))) { continue; } // Transform the user scale values to pixel locations var tmpX = (int)xScale.Transform(curve.IsOverrideOrdinal, i, curX); var tmpY = (int)yScale.Transform(curve.IsOverrideOrdinal, i, curY); // Maintain an array of "used" pixel locations to avoid duplicate drawing operations if (tmpX >= minX && tmpX <= maxX && tmpY >= minY && tmpY <= maxY) // guard against the zoom-in case { if (isPixelDrawn[tmpX, tmpY]) { continue; } isPixelDrawn[tmpX, tmpY] = true; } // If the fill type for this symbol is a Gradient by value type, // the make a brush corresponding to the appropriate current value if (Fill.IsGradientValueType || Border.GradientFill.IsGradientValueType) { using (var tBrush = Fill.MakeBrush(rect, points[i])) using (var tPen = Border.GetPen(pane, scaleFactor, points[i])) drawSymbol(g, tmpX, tmpY, path, tPen, tBrush, Type, Fill, Border); } else { // Otherwise, the brush is already defined // Draw the symbol at the specified pixel location drawSymbol(g, tmpX, tmpY, path, pen, brush, Type, Fill, Border); } } } } g.SmoothingMode = sModeSave; }
public override void Draw(Graphics g, GraphPane pane, int pos, float scaleFactor) { if (pane.Chart._rect.Width <= 0 && pane.Chart._rect.Height <= 0) { _slicePath = null; } else { CalcRectangle(g, pane, scaleFactor, pane.Chart._rect); _slicePath = new GraphicsPath(); if (!_isVisible) { return; } RectangleF tRect = _boundingRectangle; if (tRect.Width >= 1 && tRect.Height >= 1) { SmoothingMode sMode = g.SmoothingMode; g.SmoothingMode = SmoothingMode.AntiAlias; _slicePath.AddPie(tRect.X, tRect.Y, tRect.Width, tRect.Height, -StartAngle, -SweepAngle); float avgAngle = 90 - ((SweepAngle / 2) + StartAngle); RectangleF gradientrect = new RectangleF(tRect.X - 10, tRect.Y - 10, tRect.Width + 20, tRect.Height + 20); using (LinearGradientBrush linearBrush = new LinearGradientBrush(gradientrect, RegionColorStart, RegionColorEnd, avgAngle)) { using (Pen regionPen = new Pen(linearBrush, pane.GasGaugeRegionWidth)) { g.DrawArc(regionPen, tRect.X, tRect.Y, tRect.Width, tRect.Height, -StartAngle, -SweepAngle); } } if (this.Border.IsVisible) { using (Pen borderPen = _border.GetPen(pane, scaleFactor)) { g.DrawPie(borderPen, tRect.X, tRect.Y, tRect.Width, tRect.Height, -StartAngle, -SweepAngle); } } //draw labels for the region limits if (pane.HasLabel || HasLabel) { double absmax = 0; double absmin = MinValue; foreach (object gg in pane.CurveList) { if (gg is GasGaugeRegion) { GasGaugeRegion ggr = (GasGaugeRegion)gg; if (absmax < ggr.MaxValue) { absmax = ggr.MaxValue; } if (absmin > ggr.MinValue) { absmin = ggr.MinValue; } } } DrawLabelValue(pane, (StartAngle + SweepAngle), ref m_LabelMin, MinValue); DrawLabelValue(pane, StartAngle, ref m_LabelMax, MaxValue); } else { if (m_LabelMin != null) { m_LabelMin.IsVisible = false; } if (m_LabelMax != null) { m_LabelMax.IsVisible = false; } } g.SmoothingMode = sMode; } } }
/// <summary> /// Render this object to the specified <see cref="Graphics"/> device. /// </summary> /// <remarks> /// This method is normally only called by the Draw method /// of the parent <see cref="GraphObjList"/> collection object. /// </remarks> /// <param name="g"> /// A graphic device object to be drawn into. This is normally e.Graphics from the /// PaintEventArgs argument to the Paint() method. /// </param> /// <param name="pane"> /// A reference to the <see cref="PaneBase"/> object that is the parent or /// owner of this object. /// </param> /// <param name="scaleFactor"> /// The scaling factor to be used for rendering objects. This is calculated and /// passed down by the parent <see cref="GraphPane"/> object using the /// <see cref="PaneBase.CalcScaleFactor"/> method, and is used to proportionally adjust /// font sizes, etc. according to the actual size of the graph. /// </param> override public void Draw(Graphics g, PaneBase pane, float scaleFactor) { // Convert the arrow coordinates from the user coordinate system // to the screen coordinate system RectangleF pixRect = this.GetPointRect(pane, scaleFactor); // Clip the rect to just outside the PaneRect so we don't end up with wild coordinates. RectangleF tmpRect = pane.Rect; tmpRect.Inflate(20, 20); pixRect.Intersect(tmpRect); if (Math.Abs(pixRect.Left) < 100000 && Math.Abs(pixRect.Top) < 100000) { // If the box is to be filled, fill it using (GraphicsPath path = new GraphicsPath()) { switch (this.Type) { case SymbolType.Square: { path.AddLine(pixRect.Left, pixRect.Bottom, pixRect.Right, pixRect.Bottom); path.AddLine(pixRect.Right, pixRect.Bottom, pixRect.Right, pixRect.Top); path.AddLine(pixRect.Right, pixRect.Top, pixRect.Left, pixRect.Top); path.AddLine(pixRect.Left, pixRect.Top, pixRect.Left, pixRect.Bottom); break; } case SymbolType.Diamond: { float midx = (pixRect.Left + pixRect.Right) / 2.0f; float midy = (pixRect.Top + pixRect.Bottom) / 2.0f; path.AddLine(pixRect.Left, midy, midx, pixRect.Bottom); path.AddLine(midx, pixRect.Bottom, pixRect.Right, midy); path.AddLine(pixRect.Right, midy, midx, pixRect.Top); path.AddLine(midx, pixRect.Top, pixRect.Left, midy); break; } case SymbolType.Triangle: { float midx = (pixRect.Left + pixRect.Right) / 2.0f; path.AddLine(midx, pixRect.Top, pixRect.Right, pixRect.Bottom); path.AddLine(pixRect.Right, pixRect.Bottom, pixRect.Left, pixRect.Bottom); path.AddLine(pixRect.Left, pixRect.Bottom, midx, pixRect.Top); break; } case SymbolType.Circle: { path.AddEllipse(pixRect); break; } case SymbolType.Plus: { float midx = (pixRect.Left + pixRect.Right) / 2.0f; float midy = (pixRect.Top + pixRect.Bottom) / 2.0f; path.AddLine(midx, pixRect.Bottom, midx, pixRect.Top); path.StartFigure(); path.AddLine(pixRect.Left, midy, pixRect.Right, midy); break; } case SymbolType.Star: { float midx = (pixRect.Left + pixRect.Right) / 2.0f; float midy = (pixRect.Top + pixRect.Bottom) / 2.0f; path.AddLine(midx, pixRect.Bottom, midx, pixRect.Top); path.StartFigure(); path.AddLine(pixRect.Left, midy, pixRect.Right, midy); path.StartFigure(); path.AddLine(pixRect.Left, pixRect.Bottom, pixRect.Right, pixRect.Top); path.StartFigure(); path.AddLine(pixRect.Left, pixRect.Top, pixRect.Right, pixRect.Bottom); break; } case SymbolType.TriangleDown: { float midx = (pixRect.Left + pixRect.Right) / 2.0f; path.AddLine(midx, pixRect.Bottom, pixRect.Right, pixRect.Top); path.AddLine(pixRect.Right, pixRect.Top, pixRect.Left, pixRect.Top); path.AddLine(pixRect.Left, pixRect.Top, midx, pixRect.Bottom); break; } case SymbolType.HDash: { float midy = (pixRect.Top + pixRect.Bottom) / 2.0f; path.AddLine(pixRect.Left, midy, pixRect.Right, midy); break; } case SymbolType.VDash: { float midx = (pixRect.Left + pixRect.Right) / 2.0f; path.AddLine(midx, pixRect.Bottom, midx, pixRect.Top); break; } case SymbolType.XCross: default: { path.AddLine(pixRect.Left, pixRect.Bottom, pixRect.Right, pixRect.Top); path.StartFigure(); path.AddLine(pixRect.Left, pixRect.Top, pixRect.Right, pixRect.Bottom); break; } } if (_fill.IsVisible) { if (this.Type == SymbolType.Circle || this.Type == SymbolType.Diamond || this.Type == SymbolType.Square || this.Type == SymbolType.Triangle || this.Type == SymbolType.TriangleDown) { using (Brush brush = _fill.MakeBrush(pixRect)) g.FillPath(brush, path); } } if (_border.IsVisible) { using (Pen pen = _border.GetPen(pane, scaleFactor)) g.DrawPath(pen, path); } } } }
/// <summary> /// Render this object to the specified <see cref="Graphics"/> device. /// </summary> /// <remarks> /// This method is normally only called by the Draw method /// of the parent <see cref="GraphObjList"/> collection object. /// </remarks> /// <param name="g"> /// A graphic device object to be drawn into. This is normally e.Graphics from the /// PaintEventArgs argument to the Paint() method. /// </param> /// <param name="pane"> /// A reference to the <see cref="PaneBase"/> object that is the parent or /// owner of this object. /// </param> /// <param name="scaleFactor"> /// The scaling factor to be used for rendering objects. This is calculated and /// passed down by the parent <see cref="GraphPane"/> object using the /// <see cref="PaneBase.CalcScaleFactor"/> method, and is used to proportionally adjust /// font sizes, etc. according to the actual size of the graph. /// </param> override public void Draw(Graphics g, PaneBase pane, float scaleFactor) { // Convert the arrow coordinates from the user coordinate system // to the screen coordinate system PointF pix1 = this.Location.TransformTopLeft(pane); PointF pix2 = this.Location.TransformBottomRight(pane); //RectangleF pixRect = this.Location.TransformRect(pane); RectangleF pixRect = new RectangleF(Math.Min(pix1.X, pix2.X), Math.Min(pix1.Y, pix2.Y), Math.Abs(pix2.X - pix1.X), Math.Abs(pix2.Y - pix1.Y)); //System.Diagnostics.Debug.WriteLine(string.Format("box {0} {1}", pix1, pix2)); // Clip the rect to just outside the PaneRect so we don't end up with wild coordinates. RectangleF tmpRect = pane.Rect; tmpRect.Inflate(20, 20); pixRect.Intersect(tmpRect); if (Math.Abs(pixRect.Left) < 100000 && Math.Abs(pixRect.Top) < 100000 && Math.Abs(pixRect.Right) < 100000 && Math.Abs(pixRect.Bottom) < 100000) { // If the box is to be filled, fill it _fill.Draw(g, pixRect); // Draw the border around the box if required //_border.Draw( g, pane, scaleFactor, pixRect ); if (_border.IsVisible) { var smode = g.SmoothingMode; g.SmoothingMode = SmoothingMode.AntiAlias; RectangleF tRect = pixRect; float scaledInflate = (float)(_border.InflateFactor * scaleFactor); tRect.Inflate(scaledInflate, scaledInflate); using (Pen pen = _border.GetPen(pane, scaleFactor)) { if (IsMoving) { // Set the DashCap to round. pen.DashCap = DashCap.Round; // Create a custom dash pattern. pen.DashPattern = new float[] { 4.0F, 4.0F }; } g.DrawRectangle(pen, tRect.X, tRect.Y, tRect.Width, tRect.Height); if (IsSelected) { Brush brush = new SolidBrush(Color.White); g.FillRectangles(brush, EdgeRects(pane)); pen.DashStyle = DashStyle.Solid; g.DrawRectangles(pen, EdgeRects(pane)); } } g.SmoothingMode = smode; } } }