Example #1
0
        /// <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)
        {
            if (_type == SymbolType.None)
            {
                return;
            }
            Symbol source = this;

            if (isSelected)
            {
                source = Selection.Symbol;
            }

            int tmpX, tmpY;

            int minX = (int)pane.Chart.Rect.Left;
            int maxX = (int)pane.Chart.Rect.Right;
            int minY = (int)pane.Chart.Rect.Top;
            int maxY = (int)pane.Chart.Rect.Bottom;

            // (Dale-a-b) we'll set an element to true when it has been drawn
            if (isPixelDrawn == null)
            {
                isPixelDrawn = new MultiDimBitArray(maxX, maxY);
            }
            else
            {
                isPixelDrawn.TryResize(maxX, maxY);
            }

            double     curX, curY, lowVal;
            IPointList points = curve.Points;

            if (points != null && (_border.IsVisible || _fill.IsVisible))
            {
                SmoothingMode 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 (Pen pen = source._border.GetPen(pane, scaleFactor))
                    using (GraphicsPath path = MakePath(g, scaleFactor))
                    {
                        RectangleF rect = path.GetBounds();

                        using (Brush brush = source.Fill.MakeBrush(rect))
                        {
                            ValueHandler valueHandler = new ValueHandler(pane, false);
                            Scale        xScale       = curve.GetXAxis(pane).Scale;
                            Scale        yScale       = curve.GetYAxis(pane).Scale;

                            bool xIsLog     = xScale.IsLog;
                            bool yIsLog     = yScale.IsLog;
                            bool xIsOrdinal = xScale.IsAnyOrdinal;

                            double xMin = xScale.Min;
                            double xMax = xScale.Max;

                            // Loop over each defined point
                            for (int i = 0; i < points.Count; i++)
                            {
                                // Get the user scale values for the current point
                                // use the valueHandler only for stacked types
                                if (pane.LineType == LineType.Stack)
                                {
                                    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;
                                    if (curve is StickItem)
                                    {
                                        curY = points[i].Z;
                                    }
                                    else
                                    {
                                        curY = 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 &&
                                    !System.Double.IsNaN(curX) &&
                                    !System.Double.IsNaN(curY) &&
                                    !System.Double.IsInfinity(curX) &&
                                    !System.Double.IsInfinity(curY) &&
                                    (curX > 0 || !xIsLog) &&
                                    (!yIsLog || curY > 0.0) &&
                                    (xIsOrdinal || (curX >= xMin && curX <= xMax)))
                                {
                                    // Transform the user scale values to pixel locations
                                    tmpX = (int)xScale.Transform(curve.IsOverrideOrdinal, i, curX);
                                    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,
                                    // then make a brush corresponding to the appropriate current value
                                    if (_fill.IsGradientValueType || _border._gradientFill.IsGradientValueType)
                                    {
                                        using (Brush tBrush = _fill.MakeBrush(rect, points[i]))
                                            using (Pen tPen = _border.GetPen(pane, scaleFactor, points[i]))
                                                this.DrawSymbol(g, tmpX, tmpY, path, tPen, tBrush);
                                    }
                                    else
                                    {
                                        // Otherwise, the brush is already defined
                                        // Draw the symbol at the specified pixel location
                                        this.DrawSymbol(g, tmpX, tmpY, path, pen, brush);
                                    }
                                }
                            }
                        }
                    }

                g.SmoothingMode = sModeSave;
            }
        }
Example #2
0
        /// <summary>
        /// Render text to the specified <see cref="Graphics"/> device
        /// by calling the Draw method of each <see cref="GraphObj"/> object in
        /// the collection.
        /// </summary>
        /// <remarks>This method is normally only called by the Draw method
        /// of the parent <see cref="GraphPane"/> 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>
        /// <param name="zOrder">A <see cref="ZOrder"/> enumeration that controls
        /// the placement of this <see cref="GraphObj"/> relative to other
        /// graphic objects.  The order of <see cref="GraphObj"/>'s with the
        /// same <see cref="ZOrder"/> value is control by their order in
        /// this <see cref="GraphObjList"/>.</param>
        public void Draw(Graphics g, PaneBase pane, float scaleFactor,
                         ZOrder zOrder)
        {
            GraphPane graphPane = pane as GraphPane;
            int       minX      = int.MinValue;
            int       maxX      = int.MaxValue;
            int       minY      = int.MinValue;
            int       maxY      = int.MaxValue;
            bool      isOptDraw = false;

            if (graphPane != null)
            {
                isOptDraw = true;
                minX      = (int)graphPane.Chart.Rect.Left;
                maxX      = (int)graphPane.Chart.Rect.Right;
                minY      = (int)graphPane.Chart.Rect.Top;
                maxY      = (int)graphPane.Chart.Rect.Bottom;
                if (isOptDraw)
                {
                    if (isPixelDrawn == null)
                    {
                        isPixelDrawn = new MultiDimBitArray(maxX, maxY);
                    }
                    else
                    {
                        isPixelDrawn.TryResize(maxX, maxY);
                    }
                }
            }



            // Draw the items in reverse order, so the last items in the
            // list appear behind the first items (consistent with
            // CurveList)
            List <GraphObj> graphObjs = zOrderList[(int)zOrder];

            for (int i = graphObjs.Count - 1; i >= 0; i--)
            {
                GraphObj item = graphObjs[i];
                PointF   pix  = item.Location.Transform(pane);
                if (item.ZOrder == zOrder && item.IsVisible &&
                    pix.X >= minX && pix.X <= maxX &&
                    pix.Y >= minY && pix.Y <= maxY)
                {
                    // Don't try to draw where we already drew.
                    // This is a huge optimization when there are
                    // many more draw items than pixels in the rectangle.
                    if (isPixelDrawn[(int)pix.X, (int)pix.Y])
                    {
                        continue;
                    }
                    isPixelDrawn[(int)pix.X, (int)pix.Y] = true;

                    Region region = null;
                    if (item.IsClippedToChartRect && pane is GraphPane)
                    {
                        region = g.Clip.Clone();
                        g.SetClip(((GraphPane)pane).Chart._rect);
                    }

                    item.Draw(g, pane, scaleFactor);

                    if (item.IsClippedToChartRect && pane is GraphPane)
                    {
                        g.Clip = region;
                    }
                }
            }
        }