Ejemplo n.º 1
0
		private void PaintElement (ChartGraphics g, object element, ElementPosition position)
		{
			ChartPaintEventArgs e = new ChartPaintEventArgs (this, element, g, position);

			OnPrePaint (e);
			OnPostPaint (e);
		}
Ejemplo n.º 2
0
		internal ChartPaintEventArgs (Chart chart, object chartElement, ChartGraphics chartGraphics, ElementPosition position)
		{
			Chart = chart;
			ChartElement = chartElement;
			ChartGraphics = chartGraphics;
			Position = position;
		}
Ejemplo n.º 3
0
 /// <summary>
 /// Get the absolute location of dp 
 /// </summary>
 /// <param name="cg">for finding the absolute location</param>
 /// <param name="dp"></param>
 /// <returns></returns>
 public static PointF GetAbsolutePoint(ChartGraphics cg, DataPoint dp)
 {
     PointF p1 = new PointF(
     (float)cg.GetPositionFromAxis("Default", AxisName.X, dp.XValue),
     (float)cg.GetPositionFromAxis("Default", AxisName.Y, dp.YValues[0]));
     p1 = cg.GetAbsolutePoint(p1);
     return p1;
 }
Ejemplo n.º 4
0
		protected override void OnPaint (PaintEventArgs e)
		{
			base.OnPaint (e);

			ChartGraphics g = new ChartGraphics (e.Graphics);

			PaintElement (g, this, new ElementPosition (0, 0, 100, 100));

			foreach (var area in ChartAreas)
				PaintElement (g, area, new ElementPosition (9.299009f, 6.15f, 86.12599f, 81.1875f));

			foreach (var series in Series)
				PaintElement (g, series, new ElementPosition (9.299009f, 6.15f, 86.12599f, 81.1875f));
		}
        /// <summary>
        /// Gets position of the axis break line. Break line may be shown as a single
        /// line or two lines separated with a spacing.
        /// </summary>
        /// <param name="graph">Chart graphics.</param>
        /// <param name="nextSegment">Next segment reference.</param>
        /// <returns>Position of the axis break line in pixel coordinates.</returns>
        internal RectangleF GetBreakLinePosition(ChartGraphics graph, AxisScaleSegment nextSegment)
        {
            // Start with the plotting rectangle position
            RectangleF breakPosition = this.axis.PlotAreaPosition.ToRectangleF();

            // Find maximum scale value of the current segment and minimuj of the next
            double from = this.axis.GetLinearPosition(nextSegment.ScaleMinimum);
            double to   = this.axis.GetLinearPosition(this.ScaleMaximum);

            if (this.axis.AxisPosition == AxisPosition.Right || this.axis.AxisPosition == AxisPosition.Left)
            {
                breakPosition.Y      = (float)Math.Min(from, to);
                breakPosition.Height = (float)Math.Max(from, to);
            }
            else
            {
                breakPosition.X     = (float)Math.Min(from, to);
                breakPosition.Width = (float)Math.Max(from, to);;
            }

            // Convert to pixels
            breakPosition = Rectangle.Round(graph.GetAbsoluteRectangle(breakPosition));

            // Add border width
            if (this.axis.AxisPosition == AxisPosition.Right || this.axis.AxisPosition == AxisPosition.Left)
            {
                breakPosition.Height = (float)Math.Abs(breakPosition.Y - breakPosition.Height);
                breakPosition.X     -= this.axis.ChartArea.BorderWidth;
                breakPosition.Width += 2 * this.axis.ChartArea.BorderWidth;
            }
            else
            {
                breakPosition.Width   = (float)Math.Abs(breakPosition.X - breakPosition.Width);
                breakPosition.Y      -= this.axis.ChartArea.BorderWidth;
                breakPosition.Height += 2 * this.axis.ChartArea.BorderWidth;
            }

            return(breakPosition);
        }
        /// <summary>
        /// Gets text annotation content size based on the text and font.
        /// </summary>
        /// <returns>Annotation content position.</returns>
        override internal RectangleF GetContentPosition()
        {
            // Check image size
            if (this.Image.Length > 0)
            {
                // Try loading image and getting its size
                try
                {
                    if (this.Chart != null)
                    {
                        ImageLoader imageLoader = this.Common.ImageLoader;

                        if (imageLoader != null)
                        {
                            ChartGraphics chartGraphics = this.GetGraphics();

                            if (chartGraphics != null)
                            {
                                SizeF absSize = new SizeF();

                                if (imageLoader.GetAdjustedImageSize(this.Image, chartGraphics.Graphics, ref absSize))
                                {
                                    SizeF imageSize = chartGraphics.GetRelativeSize(absSize);
                                    return(new RectangleF(float.NaN, float.NaN, imageSize.Width, imageSize.Height));
                                }
                            }
                        }
                    }
                }
                catch (ArgumentException)
                {
                    // ArgumentException is thrown by LoadImage in certain situations when it can't load the image
                }
            }

            return(new RectangleF(float.NaN, float.NaN, float.NaN, float.NaN));
        }
        /// <summary>
        /// Gets text annotation content size based on the text and font.
        /// </summary>
        /// <returns>Annotation content position.</returns>
        override internal RectangleF GetContentPosition()
        {
            // Return pre calculated value
            if (!contentSize.IsEmpty)
            {
                return(new RectangleF(float.NaN, float.NaN, contentSize.Width, contentSize.Height));
            }

            // Create temporary bitmap based chart graphics if chart was not
            // rendered yet and the graphics was not created.
            // NOTE: Fix for issue #3978.
            Graphics graphics = null;

            System.Drawing.Image graphicsImage  = null;
            ChartGraphics        tempChartGraph = null;

            if (GetGraphics() == null && this.Common != null)
            {
                graphicsImage           = new System.Drawing.Bitmap(Common.ChartPicture.Width, Common.ChartPicture.Height);
                graphics                = Graphics.FromImage(graphicsImage);
                tempChartGraph          = new ChartGraphics(Common);
                tempChartGraph.Graphics = graphics;
                tempChartGraph.SetPictureSize(Common.ChartPicture.Width, Common.ChartPicture.Height);
                this.Common.graph = tempChartGraph;
            }

            // Calculate content size
            RectangleF result = RectangleF.Empty;

            if (GetGraphics() != null && this.Text.Trim().Length > 0)
            {
                // Measure text using current font and slightly increase it
                contentSize = GetGraphics().MeasureString(
                    "W" + this.ReplaceKeywords(this.Text.Replace("\\n", "\n")),
                    this.Font,
                    new SizeF(2000, 2000),
                    StringFormat.GenericTypographic);

                contentSize.Height *= 1.04f;

                // Convert to relative coordinates
                contentSize = GetGraphics().GetRelativeSize(contentSize);

                // Add spacing
                bool       annotationRelative = false;
                RectangleF textSpacing        = GetTextSpacing(out annotationRelative);
                float      spacingScaleX      = 1f;
                float      spacingScaleY      = 1f;
                if (annotationRelative)
                {
                    if (contentSize.Width > 25f)
                    {
                        spacingScaleX = contentSize.Width / 25f;
                        spacingScaleX = Math.Max(1f, spacingScaleX);
                    }
                    if (contentSize.Height > 25f)
                    {
                        spacingScaleY = contentSize.Height / 25f;
                        spacingScaleY = Math.Max(1f, spacingScaleY);
                    }
                }

                contentSize.Width  += (textSpacing.X + textSpacing.Width) * spacingScaleX;
                contentSize.Height += (textSpacing.Y + textSpacing.Height) * spacingScaleY;

                result = new RectangleF(float.NaN, float.NaN, contentSize.Width, contentSize.Height);
            }

            // Dispose temporary chart graphics
            if (tempChartGraph != null)
            {
                tempChartGraph.Dispose();
                graphics.Dispose();
                graphicsImage.Dispose();
                this.Common.graph = null;
            }

            return(result);
        }
Ejemplo n.º 8
0
        /// <summary>
        /// Draws a cardinal spline through a specified array of PointF structures
        /// using a specified tension. The drawing begins offset from
        /// the beginning of the array.
        /// </summary>
        /// <param name="pen">Pen object that determines the color, width, and height of the curve.</param>
        /// <param name="points">Array of PointF structures that define the spline.</param>
        /// <param name="offset">Offset from the first element in the array of the points parameter to the starting point in the curve.</param>
        /// <param name="numberOfSegments">Number of segments after the starting point to include in the curve.</param>
        /// <param name="tension">Value greater than or equal to 0.0F that specifies the tension of the curve.</param>
        internal void DrawCurve(
            Pen pen,
            PointF[] points,
            int offset,
            int numberOfSegments,
            float tension
            )
        {
            ChartGraphics chartGraphics = this as ChartGraphics;

            if (chartGraphics == null || !chartGraphics.IsMetafile)
            {
                RenderingObject.DrawCurve(pen, points, offset, numberOfSegments, tension);
            }
            else
            {
                // Special handling required for the metafiles. We cannot pass large array of
                // points because they will be persisted inside EMF file and cause exponential
                // increase in emf file size. Draw curve method uses additional 2, 3 or 4 points
                // depending on which segement is drawn.
                PointF[] pointsExact = null;
                if (offset == 0 && numberOfSegments == points.Length - 1)
                {
                    // In case the array contains the minimum required number of points
                    // to draw segments - just call the curve drawing method
                    RenderingObject.DrawCurve(pen, points, offset, numberOfSegments, tension);
                }
                else
                {
                    if (offset == 0 && numberOfSegments < points.Length - 1)
                    {
                        // Segment is at the beginning of the array with more points following
                        pointsExact = new PointF[numberOfSegments + 2];
                        for (int index = 0; index < numberOfSegments + 2; index++)
                        {
                            pointsExact[index] = points[index];
                        }
                    }
                    else if (offset > 0 && (offset + numberOfSegments) == points.Length - 1)
                    {
                        // Segment is at the end of the array with more points prior to it
                        pointsExact = new PointF[numberOfSegments + 2];
                        for (int index = 0; index < numberOfSegments + 2; index++)
                        {
                            pointsExact[index] = points[offset + index - 1];
                        }
                        offset = 1;
                    }
                    else if (offset > 0 && (offset + numberOfSegments) < points.Length - 1)
                    {
                        // Segment in the middle of the array with points prior and following it
                        pointsExact = new PointF[numberOfSegments + 3];
                        for (int index = 0; index < numberOfSegments + 3; index++)
                        {
                            pointsExact[index] = points[offset + index - 1];
                        }
                        offset = 1;
                    }

                    // Render the curve using minimum number of required points in the array
                    RenderingObject.DrawCurve(pen, pointsExact, offset, numberOfSegments, tension);
                }
            }
        }
        /// <summary>
        /// Draws text in specified rectangle.
        /// </summary>
        /// <param name="graphics">Chart graphics.</param>
        /// <param name="textPosition">Text position.</param>
        /// <param name="noSpacingForCenteredText">True if text allowed to be outside of position when centered.</param>
        /// <param name="getTextPosition">True if position text must be returned by the method.</param>
        /// <returns>Text actual position if required.</returns>
        internal RectangleF DrawText(ChartGraphics graphics, RectangleF textPosition, bool noSpacingForCenteredText, bool getTextPosition)
        {
            RectangleF textActualPosition = RectangleF.Empty;

            //***************************************************************
            //** Adjust text position uing text spacing
            //***************************************************************
            bool       annotationRelative = false;
            RectangleF textSpacing        = GetTextSpacing(out annotationRelative);
            float      spacingScaleX      = 1f;
            float      spacingScaleY      = 1f;

            if (annotationRelative)
            {
                if (textPosition.Width > 25f)
                {
                    spacingScaleX = textPosition.Width / 50f;
                    spacingScaleX = Math.Max(1f, spacingScaleX);
                }
                if (textPosition.Height > 25f)
                {
                    spacingScaleY = textPosition.Height / 50f;
                    spacingScaleY = Math.Max(1f, spacingScaleY);
                }
            }

            RectangleF textPositionWithSpacing = new RectangleF(textPosition.Location, textPosition.Size);

            textPositionWithSpacing.Width  -= (textSpacing.Width + textSpacing.X) * spacingScaleX;
            textPositionWithSpacing.X      += textSpacing.X * spacingScaleX;
            textPositionWithSpacing.Height -= (textSpacing.Height + textSpacing.Y) * spacingScaleY;
            textPositionWithSpacing.Y      += textSpacing.Y * spacingScaleY;

            //***************************************************************
            //** Replace new line characters
            //***************************************************************
            string titleText = this.ReplaceKeywords(this.Text.Replace("\\n", "\n"));

            //***************************************************************
            //** Check if centered text require spacing.
            //** Use only half of the spacing required.
            //** Apply only for 1 line of text.
            //***************************************************************
            if (noSpacingForCenteredText &&
                titleText.IndexOf('\n') == -1)
            {
                if (this.Alignment == ContentAlignment.MiddleCenter ||
                    this.Alignment == ContentAlignment.MiddleLeft ||
                    this.Alignment == ContentAlignment.MiddleRight)
                {
                    textPositionWithSpacing.Y       = textPosition.Y;
                    textPositionWithSpacing.Height  = textPosition.Height;
                    textPositionWithSpacing.Height -= textSpacing.Height / 2f + textSpacing.Y / 2f;
                    textPositionWithSpacing.Y      += textSpacing.Y / 2f;
                }
                if (this.Alignment == ContentAlignment.BottomCenter ||
                    this.Alignment == ContentAlignment.MiddleCenter ||
                    this.Alignment == ContentAlignment.TopCenter)
                {
                    textPositionWithSpacing.X      = textPosition.X;
                    textPositionWithSpacing.Width  = textPosition.Width;
                    textPositionWithSpacing.Width -= textSpacing.Width / 2f + textSpacing.X / 2f;
                    textPositionWithSpacing.X     += textSpacing.X / 2f;
                }
            }

            // Draw text
            using (Brush textBrush = new SolidBrush(this.ForeColor))
            {
                using (StringFormat format = new StringFormat(StringFormat.GenericTypographic))
                {
                    //***************************************************************
                    //** Set text format
                    //***************************************************************
                    format.FormatFlags = format.FormatFlags ^ StringFormatFlags.LineLimit;
                    format.Trimming    = StringTrimming.EllipsisCharacter;
                    if (this.Alignment == ContentAlignment.BottomRight ||
                        this.Alignment == ContentAlignment.MiddleRight ||
                        this.Alignment == ContentAlignment.TopRight)
                    {
                        format.Alignment = StringAlignment.Far;
                    }
                    if (this.Alignment == ContentAlignment.BottomCenter ||
                        this.Alignment == ContentAlignment.MiddleCenter ||
                        this.Alignment == ContentAlignment.TopCenter)
                    {
                        format.Alignment = StringAlignment.Center;
                    }
                    if (this.Alignment == ContentAlignment.BottomCenter ||
                        this.Alignment == ContentAlignment.BottomLeft ||
                        this.Alignment == ContentAlignment.BottomRight)
                    {
                        format.LineAlignment = StringAlignment.Far;
                    }
                    if (this.Alignment == ContentAlignment.MiddleCenter ||
                        this.Alignment == ContentAlignment.MiddleLeft ||
                        this.Alignment == ContentAlignment.MiddleRight)
                    {
                        format.LineAlignment = StringAlignment.Center;
                    }

                    //***************************************************************
                    //** Set shadow color and offset
                    //***************************************************************
                    Color     textShadowColor  = ChartGraphics.GetGradientColor(this.ForeColor, Color.Black, 0.8);
                    int       textShadowOffset = 1;
                    TextStyle textStyle        = this.TextStyle;
                    if (textStyle == TextStyle.Shadow &&
                        ShadowOffset != 0)
                    {
                        // Draw shadowed text
                        textShadowColor  = ShadowColor;
                        textShadowOffset = ShadowOffset;
                    }

                    if (textStyle == TextStyle.Shadow)
                    {
                        textShadowColor = (textShadowColor.A != 255) ? textShadowColor : Color.FromArgb(textShadowColor.A / 2, textShadowColor);
                    }

                    //***************************************************************
                    //** Get text actual position
                    //***************************************************************
                    if (getTextPosition)
                    {
                        // Measure text size
                        SizeF textSize = graphics.MeasureStringRel(
                            this.ReplaceKeywords(_text.Replace("\\n", "\n")),
                            this.Font,
                            textPositionWithSpacing.Size,
                            format);

                        // Get text position
                        textActualPosition = new RectangleF(textPositionWithSpacing.Location, textSize);
                        if (this.Alignment == ContentAlignment.BottomRight ||
                            this.Alignment == ContentAlignment.MiddleRight ||
                            this.Alignment == ContentAlignment.TopRight)
                        {
                            textActualPosition.X += textPositionWithSpacing.Width - textSize.Width;
                        }
                        if (this.Alignment == ContentAlignment.BottomCenter ||
                            this.Alignment == ContentAlignment.MiddleCenter ||
                            this.Alignment == ContentAlignment.TopCenter)
                        {
                            textActualPosition.X += (textPositionWithSpacing.Width - textSize.Width) / 2f;
                        }
                        if (this.Alignment == ContentAlignment.BottomCenter ||
                            this.Alignment == ContentAlignment.BottomLeft ||
                            this.Alignment == ContentAlignment.BottomRight)
                        {
                            textActualPosition.Y += textPositionWithSpacing.Height - textSize.Height;
                        }
                        if (this.Alignment == ContentAlignment.MiddleCenter ||
                            this.Alignment == ContentAlignment.MiddleLeft ||
                            this.Alignment == ContentAlignment.MiddleRight)
                        {
                            textActualPosition.Y += (textPositionWithSpacing.Height - textSize.Height) / 2f;
                        }

                        // Do not allow text to go outside annotation position
                        textActualPosition.Intersect(textPositionWithSpacing);
                    }

                    RectangleF absPosition = graphics.GetAbsoluteRectangle(textPositionWithSpacing);
                    Title.DrawStringWithStyle(
                        graphics,
                        titleText,
                        this.TextStyle,
                        this.Font,
                        absPosition,
                        this.ForeColor,
                        textShadowColor,
                        textShadowOffset,
                        format,
                        TextOrientation.Auto
                        );
                }
            }

            return(textActualPosition);
        }
        /// <summary>
        /// Paints the axis break line.
        /// </summary>
        /// <param name="graph">Chart graphics to use.</param>
        /// <param name="nextSegment">Axis scale segment next to current.</param>
        internal void PaintBreakLine(ChartGraphics graph, AxisScaleSegment nextSegment)
        {
            // Get break line position
            RectangleF breakPosition = this.GetBreakLinePosition(graph, nextSegment);

            // Get top line graphics path
            GraphicsPath breakLinePathTop    = this.GetBreakLinePath(breakPosition, true);
            GraphicsPath breakLinePathBottom = null;

            // Clear break line space using chart color behind the area
            if (breakPosition.Width > 0f && breakPosition.Height > 0f)
            {
                // Get bottom line graphics path
                breakLinePathBottom = this.GetBreakLinePath(breakPosition, false);

                // Clear plotting area background
                using (GraphicsPath fillPath = new GraphicsPath())
                {
                    // Create fill path out of top and bottom break lines
                    fillPath.AddPath(breakLinePathTop, true);
                    fillPath.Reverse();
                    fillPath.AddPath(breakLinePathBottom, true);
                    fillPath.CloseAllFigures();

                    // Use chart back color to fill the area
                    using (Brush fillBrush = this.GetChartFillBrush(graph))
                    {
                        graph.FillPath(fillBrush, fillPath);

                        // Check if shadow exsits in chart area
                        if (this.axis.ChartArea.ShadowOffset != 0 && !this.axis.ChartArea.ShadowColor.IsEmpty)
                        {
                            // Clear shadow
                            RectangleF shadowPartRect = breakPosition;
                            if (this.axis.AxisPosition == AxisPosition.Right || this.axis.AxisPosition == AxisPosition.Left)
                            {
                                shadowPartRect.Y      += this.axis.ChartArea.ShadowOffset;
                                shadowPartRect.Height -= this.axis.ChartArea.ShadowOffset;
                                shadowPartRect.X       = shadowPartRect.Right - 1;
                                shadowPartRect.Width   = this.axis.ChartArea.ShadowOffset + 2;
                            }
                            else
                            {
                                shadowPartRect.X     += this.axis.ChartArea.ShadowOffset;
                                shadowPartRect.Width -= this.axis.ChartArea.ShadowOffset;
                                shadowPartRect.Y      = shadowPartRect.Bottom - 1;
                                shadowPartRect.Height = this.axis.ChartArea.ShadowOffset + 2;
                            }
                            graph.FillRectangle(fillBrush, shadowPartRect);

                            // Draw new shadow
                            using (GraphicsPath shadowPath = new GraphicsPath())
                            {
                                shadowPath.AddPath(breakLinePathTop, false);

                                // Define maximum size
                                float size = this.axis.ChartArea.ShadowOffset;
                                if (this.axis.AxisPosition == AxisPosition.Right || this.axis.AxisPosition == AxisPosition.Left)
                                {
                                    size = Math.Min(size, breakPosition.Height);
                                }
                                else
                                {
                                    size = Math.Min(size, breakPosition.Width);
                                }

                                // Define step to increase transperancy
                                int transparencyStep = (int)(this.axis.ChartArea.ShadowColor.A / size);

                                // Set clip region to achieve spacing of the shadow
                                // Start with the plotting rectangle position
                                RectangleF clipRegion = graph.GetAbsoluteRectangle(this.axis.PlotAreaPosition.ToRectangleF());
                                if (this.axis.AxisPosition == AxisPosition.Right || this.axis.AxisPosition == AxisPosition.Left)
                                {
                                    clipRegion.X     += this.axis.ChartArea.ShadowOffset;
                                    clipRegion.Width += this.axis.ChartArea.ShadowOffset;
                                }
                                else
                                {
                                    clipRegion.Y      += this.axis.ChartArea.ShadowOffset;
                                    clipRegion.Height += this.axis.ChartArea.ShadowOffset;
                                }
                                graph.SetClip(graph.GetRelativeRectangle(clipRegion));

                                // Draw several lines to form shadow
                                for (int index = 0; index < size; index++)
                                {
                                    using (Matrix newMatrix = new Matrix())
                                    {
                                        // Shift top break line by 1 pixel
                                        if (this.axis.AxisPosition == AxisPosition.Right || this.axis.AxisPosition == AxisPosition.Left)
                                        {
                                            newMatrix.Translate(0f, 1f);
                                        }
                                        else
                                        {
                                            newMatrix.Translate(1f, 0f);
                                        }
                                        shadowPath.Transform(newMatrix);
                                    }

                                    // Get line color
                                    Color color = Color.FromArgb(
                                        this.axis.ChartArea.ShadowColor.A - transparencyStep * index,
                                        this.axis.ChartArea.ShadowColor);

                                    using (Pen shadowPen = new Pen(color, 1))
                                    {
                                        // Draw shadow
                                        graph.DrawPath(shadowPen, shadowPath);
                                    }
                                }

                                graph.ResetClip();
                            }
                        }
                    }
                }
            }

            // Draw Separator Line(s)
            if (this.axis.ScaleBreakStyle.BreakLineStyle != BreakLineStyle.None)
            {
                using (Pen pen = new Pen(this.axis.ScaleBreakStyle.LineColor, this.axis.ScaleBreakStyle.LineWidth))
                {
                    // Set line style
                    pen.DashStyle = graph.GetPenStyle(this.axis.ScaleBreakStyle.LineDashStyle);

                    // Draw break lines
                    graph.DrawPath(pen, breakLinePathTop);
                    if (breakPosition.Width > 0f && breakPosition.Height > 0f)
                    {
                        graph.DrawPath(pen, breakLinePathBottom);
                    }
                }
            }

            // Dispose break line paths
            breakLinePathTop.Dispose();
            breakLinePathTop = null;
            if (breakLinePathBottom != null)
            {
                breakLinePathBottom.Dispose();
                breakLinePathBottom = null;
            }
        }
        /// <summary>
        /// Gets all the RangePolygons between line1 and line2.
        /// </summary>
        /// <param name="cg">used for getting absolute values</param>
        /// <param name="line1">the line that has the 'good' values</param>
        /// <param name="line2">the line that has the 'bad' values </param>
        private void FillRangePolygons(ChartGraphics cg, Series line1, Series line2)
        {
            this.ClearRangePolygons();
            //System.Console.WriteLine("GetRangePolygons Start: " + DateTime.Now.Millisecond);
            DataPoint[] dpIntersections = LineUtils.GetAllIntersections(line1, line2);
            //ArrayList rPolygons = new ArrayList();

            if (dpIntersections != null)
            {
                switch (dpIntersections.Length)
                {
                    case 0:
                        //this is where tehre is no intersection
                        break;
                    case 1:
                        //this is the special case that there is only one intersection
                        RangePolygon sPolygon = GetStartPolygon(cg, line1, line2, dpIntersections[0], this.rPolygons.Count);

                        if (sPolygon != null)
                            rPolygons.Add(sPolygon);
                        RangePolygon ePolygon = GetEndPolygon(cg, line1, line2, dpIntersections[dpIntersections.Length - 1], this.rPolygons.Count);

                        if (ePolygon != null)
                            rPolygons.Add(ePolygon);

                        break;
                    default:

                        if (dpIntersections.Length >= 0)
                        {
                            RangePolygon startPolygon = GetStartPolygon(cg, line1, line2, dpIntersections[0], this.rPolygons.Count);

                            if (startPolygon != null)
                                rPolygons.Add(startPolygon);

                            for (int dpInterIndex = 0; dpInterIndex < dpIntersections.Length - 1; dpInterIndex++)
                            {
                                RangePolygon rp = GetPolygonOfIntersection(cg, line1,
                                    line2, dpIntersections[dpInterIndex], dpIntersections[dpInterIndex + 1], this.rPolygons.Count);
                                if (rp != null)
                                    rPolygons.Add(rp);
                            }

                            RangePolygon endPolygon = GetEndPolygon(cg, line1, line2, dpIntersections[dpIntersections.Length - 1], this.rPolygons.Count);

                            if (endPolygon != null)
                                rPolygons.Add(endPolygon);
                        }
                        else
                        {
                            break;
                        }
                        //System.Console.WriteLine("GetRangePolygons END: " + DateTime.Now.Millisecond);
                        break;
                }
            }
        }
        /// <summary>
        /// Gets a RangePolygon between two intersecting points
        /// </summary>
        /// <param name="cg">for finding the absolute coordinates</param>
        /// <param name="line1">line 1</param>
        /// <param name="line2">line 2</param>
        /// <param name="startPoint">the first intersection point</param>
        /// <param name="endPoint">the second intersection point</param>
        /// <param name="polygonID">id for the new polygon</param>
        /// <returns>a RangePolygon, null otherwise</returns>
        private RangePolygon GetPolygonOfIntersection(ChartGraphics cg, Series line1, Series line2, DataPoint startPoint, DataPoint endPoint, int polygonID)
        {
            //System.Console.WriteLine("GetPolygonIntersection Start: " + DateTime.Now.Millisecond);
            Series tempLine1 = LineUtils.PointsInRange(startPoint,
                     endPoint, line1);

            Series tempLine2 = LineUtils.PointsInRange(startPoint,
                                endPoint, line2);

            if (tempLine1 == null || tempLine2 == null)
                return null;

            RangePolygon.RANGETYPE rType;
            Series topLine;
            Series bottomLine;

            if (tempLine1.Points.Count == 0)
            {
                tempLine1.Points.Add(startPoint);
                tempLine1.Points.Add(endPoint);
            }
            if (tempLine2.Points.Count == 0)
            {
                tempLine2.Points.Add(startPoint);
                tempLine2.Points.Add(endPoint);
            }
            if (LineUtils.IsAbove(tempLine1, tempLine2))
            {
                topLine = tempLine1;
                bottomLine = tempLine2;
                rType = RangePolygon.RANGETYPE.TOP;
            }
            else
            {
                rType = RangePolygon.RANGETYPE.BOTTOM;
                topLine = tempLine2;
                bottomLine = tempLine1;
            }

            List<PointF> points = new List<PointF>();

            points.Add(LineUtils.GetAbsolutePoint(cg, startPoint));

            foreach (DataPoint dp in topLine.Points)
            {
                points.Add(LineUtils.GetAbsolutePoint(cg, dp));
            }

            points.Add(LineUtils.GetAbsolutePoint(cg, endPoint));

            bottomLine.Sort(PointSortOrder.Descending, "X");
            foreach (DataPoint dp in bottomLine.Points)
            {
                points.Add(LineUtils.GetAbsolutePoint(cg, dp));
            }

            points.Add(LineUtils.GetAbsolutePoint(cg, startPoint));

            //System.Console.WriteLine("GetPolygonIntersection END: " + DateTime.Now.Millisecond);
            return new RangePolygon(points.ToArray(), rType, polygonID);
        }
        /// <summary>
        /// Paints the annotation object on the specified graphics.
        /// </summary>
        /// <param name="graphics">
        /// A <see cref="ChartGraphics"/> object, used to paint the annotation object.
        /// </param>
        /// <param name="chart">
        /// Reference to the <see cref="Chart"/> owner control.
        /// </param>
        override internal void Paint(Chart chart, ChartGraphics graphics)
        {
            // Get annotation position in relative coordinates
            PointF firstPoint  = PointF.Empty;
            PointF anchorPoint = PointF.Empty;
            SizeF  size        = SizeF.Empty;

            GetRelativePosition(out firstPoint, out size, out anchorPoint);
            PointF secondPoint = new PointF(firstPoint.X + size.Width, firstPoint.Y + size.Height);

            // Create selection rectangle
            RectangleF selectionRect = new RectangleF(firstPoint, new SizeF(secondPoint.X - firstPoint.X, secondPoint.Y - firstPoint.Y));

            // Get position
            RectangleF rectanglePosition = new RectangleF(selectionRect.Location, selectionRect.Size);

            if (rectanglePosition.Width < 0)
            {
                rectanglePosition.X     = rectanglePosition.Right;
                rectanglePosition.Width = -rectanglePosition.Width;
            }
            if (rectanglePosition.Height < 0)
            {
                rectanglePosition.Y      = rectanglePosition.Bottom;
                rectanglePosition.Height = -rectanglePosition.Height;
            }

            // Check if position is valid
            if (float.IsNaN(rectanglePosition.X) ||
                float.IsNaN(rectanglePosition.Y) ||
                float.IsNaN(rectanglePosition.Right) ||
                float.IsNaN(rectanglePosition.Bottom))
            {
                return;
            }

            if (this.Common.ProcessModePaint)
            {
                // Draw "empty" image at design time
                if (this._imageName.Length == 0 && this.Chart.IsDesignMode())
                {
                    graphics.FillRectangleRel(
                        rectanglePosition,
                        this.BackColor,
                        this.BackHatchStyle,
                        this._imageName,
                        this._imageWrapMode,
                        this._imageTransparentColor,
                        GetImageAlignment(this.Alignment),
                        this.BackGradientStyle,
                        this.BackSecondaryColor,
                        this.LineColor,
                        this.LineWidth,
                        this.LineDashStyle,
                        this.ShadowColor,
                        this.ShadowOffset,
                        PenAlignment.Center);

                    // Draw text
                    using (Brush textBrush = new SolidBrush(this.ForeColor))
                    {
                        using (StringFormat format = new StringFormat(StringFormat.GenericTypographic))
                        {
                            format.Alignment     = StringAlignment.Center;
                            format.LineAlignment = StringAlignment.Center;
                            format.FormatFlags   = StringFormatFlags.LineLimit;
                            format.Trimming      = StringTrimming.EllipsisCharacter;
                            graphics.DrawStringRel(
                                "(no image)",
                                this.Font,
                                textBrush,
                                rectanglePosition,
                                format);
                        }
                    }
                }
                else
                {
                    // Draw image
                    graphics.FillRectangleRel(
                        rectanglePosition,
                        Color.Transparent,
                        this.BackHatchStyle,
                        this._imageName,
                        this._imageWrapMode,
                        this._imageTransparentColor,
                        GetImageAlignment(this.Alignment),
                        this.BackGradientStyle,
                        Color.Transparent,
                        Color.Transparent,
                        0,
                        this.LineDashStyle,
                        this.ShadowColor,
                        this.ShadowOffset,
                        PenAlignment.Center);
                }
            }

            if (this.Common.ProcessModeRegions)
            {
                // Add hot region
                this.Common.HotRegionsList.AddHotRegion(
                    rectanglePosition,
                    ReplaceKeywords(this.ToolTip),
                    String.Empty,
                    String.Empty,
                    String.Empty,
                    this,
                    ChartElementType.Annotation,
                    String.Empty);
            }

            // Paint selection handles
            PaintSelectionHandles(graphics, selectionRect, null);
        }
        internal void Paint(ChartGraphics chartGraph, bool drawAnnotationOnly)
        {
            ChartPicture chartPicture = this.Chart.chartPicture;

            // Restore previous background using double buffered bitmap
            if (!chartPicture.isSelectionMode &&
                this.Count > 0 /*&&
                                * !this.Chart.chartPicture.isPrinting*/)
            {
                chartPicture.backgroundRestored = true;
                Rectangle chartPosition = new Rectangle(0, 0, chartPicture.Width, chartPicture.Height);
                if (chartPicture.nonTopLevelChartBuffer == null || !drawAnnotationOnly)
                {
                    // Dispose previous bitmap
                    if (chartPicture.nonTopLevelChartBuffer != null)
                    {
                        chartPicture.nonTopLevelChartBuffer.Dispose();
                        chartPicture.nonTopLevelChartBuffer = null;
                    }

                    // Copy chart area plotting rectangle from the chart's dubble buffer image into area dubble buffer image
                    if (this.Chart.paintBufferBitmap != null &&
                        this.Chart.paintBufferBitmap.Size.Width >= chartPosition.Size.Width &&
                        this.Chart.paintBufferBitmap.Size.Height >= chartPosition.Size.Height)
                    {
                        chartPicture.nonTopLevelChartBuffer = this.Chart.paintBufferBitmap.Clone(
                            chartPosition, this.Chart.paintBufferBitmap.PixelFormat);
                    }
                }
                else if (drawAnnotationOnly && chartPicture.nonTopLevelChartBuffer != null)
                {
                    // Restore previous background
                    this.Chart.paintBufferBitmapGraphics.DrawImageUnscaled(
                        chartPicture.nonTopLevelChartBuffer,
                        chartPosition);
                }
            }

            // Draw all annotation objects
            foreach (Annotation annotation in this)
            {
                // Reset calculated relative position
                annotation.ResetCurrentRelativePosition();

                if (annotation.IsVisible())
                {
                    bool resetClip = false;

                    // Check if anchor point assosiated with plot area is inside the scaleView
                    if (annotation.IsAnchorVisible())
                    {
                        // Set annotation object clipping
                        if (annotation.ClipToChartArea.Length > 0 &&
                            annotation.ClipToChartArea != Constants.NotSetValue &&
                            Chart != null)
                        {
                            int areaIndex = Chart.ChartAreas.IndexOf(annotation.ClipToChartArea);
                            if (areaIndex >= 0)
                            {
                                // Get chart area object
                                ChartArea chartArea = Chart.ChartAreas[areaIndex];
                                chartGraph.SetClip(chartArea.PlotAreaPosition.ToRectangleF());
                                resetClip = true;
                            }
                        }

                        // Start Svg Selection mode
                        string url = String.Empty;
                        chartGraph.StartHotRegion(
                            annotation.ReplaceKeywords(url),
                            annotation.ReplaceKeywords(annotation.ToolTip));

                        // Draw annotation object
                        annotation.Paint(Chart, chartGraph);


                        // End Svg Selection mode
                        chartGraph.EndHotRegion( );

                        // Reset clipping region
                        if (resetClip)
                        {
                            chartGraph.ResetClip();
                        }
                    }
                }
            }
        }
        /// <summary>
        /// Paints an annotation object on the specified graphics.
        /// </summary>
        /// <param name="graphics">
        /// A <see cref="ChartGraphics"/> object, used to paint an annotation object.
        /// </param>
        /// <param name="chart">
        /// Reference to the <see cref="Chart"/> control.
        /// </param>
        override internal void Paint(Chart chart, ChartGraphics graphics)
        {
            // Get annotation position in relative coordinates
            PointF firstPoint  = PointF.Empty;
            PointF anchorPoint = PointF.Empty;
            SizeF  size        = SizeF.Empty;

            GetRelativePosition(out firstPoint, out size, out anchorPoint);
            PointF secondPoint = new PointF(firstPoint.X + size.Width, firstPoint.Y + size.Height);

            // Create selection rectangle
            RectangleF selectionRect = new RectangleF(firstPoint, new SizeF(secondPoint.X - firstPoint.X, secondPoint.Y - firstPoint.Y));

            // Get text position
            RectangleF rectanglePosition = new RectangleF(selectionRect.Location, selectionRect.Size);

            if (rectanglePosition.Width < 0)
            {
                rectanglePosition.X     = rectanglePosition.Right;
                rectanglePosition.Width = -rectanglePosition.Width;
            }
            if (rectanglePosition.Height < 0)
            {
                rectanglePosition.Y      = rectanglePosition.Bottom;
                rectanglePosition.Height = -rectanglePosition.Height;
            }

            // Check if position is valid
            if (float.IsNaN(rectanglePosition.X) ||
                float.IsNaN(rectanglePosition.Y) ||
                float.IsNaN(rectanglePosition.Right) ||
                float.IsNaN(rectanglePosition.Bottom))
            {
                return;
            }

            if (this.isRectVisible &&
                this.Common.ProcessModePaint)
            {
                // Draw rectangle
                graphics.FillRectangleRel(
                    rectanglePosition,
                    this.BackColor,
                    this.BackHatchStyle,
                    String.Empty,
                    ChartImageWrapMode.Scaled,
                    Color.Empty,
                    ChartImageAlignmentStyle.Center,
                    this.BackGradientStyle,
                    this.BackSecondaryColor,
                    this.LineColor,
                    this.LineWidth,
                    this.LineDashStyle,
                    this.ShadowColor,
                    this.ShadowOffset,
                    PenAlignment.Center,
                    this.isEllipse,
                    1,
                    false);
            }

            // Call base class to paint text, selection handles and process hot regions
            base.Paint(chart, graphics);
        }
        /// <summary>
        /// Paints the annotation object on the specified graphics.
        /// </summary>
        /// <param name="graphics">
        /// A <see cref="ChartGraphics"/>
        /// </param>
        /// <param name="chart">
        /// Reference to the <see cref="Chart"/> control that owns the annotation.
        /// </param>
        override internal void Paint(Chart chart, ChartGraphics graphics)
        {
            // Get annotation position in relative coordinates
            PointF firstPoint  = PointF.Empty;
            PointF anchorPoint = PointF.Empty;
            SizeF  size        = SizeF.Empty;

            GetRelativePosition(out firstPoint, out size, out anchorPoint);
            PointF secondPoint = new PointF(firstPoint.X + size.Width, firstPoint.Y + size.Height);

            // Create selection rectangle
            RectangleF selectionRect = new RectangleF(firstPoint, new SizeF(secondPoint.X - firstPoint.X, secondPoint.Y - firstPoint.Y));

            // Get text position
            RectangleF rectanglePosition = new RectangleF(selectionRect.Location, selectionRect.Size);

            if (rectanglePosition.Width < 0)
            {
                rectanglePosition.X     = rectanglePosition.Right;
                rectanglePosition.Width = -rectanglePosition.Width;
            }
            if (rectanglePosition.Height < 0)
            {
                rectanglePosition.Y      = rectanglePosition.Bottom;
                rectanglePosition.Height = -rectanglePosition.Height;
            }

            // Check if position is valid
            if (float.IsNaN(rectanglePosition.X) ||
                float.IsNaN(rectanglePosition.Y) ||
                float.IsNaN(rectanglePosition.Right) ||
                float.IsNaN(rectanglePosition.Bottom))
            {
                return;
            }

            if (this.Common.ProcessModePaint)
            {
                // Do not draw border if size is less that 10 pixels
                RectangleF absRectanglePosition = graphics.GetAbsoluteRectangle(rectanglePosition);
                if (absRectanglePosition.Width > 30f &&
                    absRectanglePosition.Height > 30f)
                {
                    // Draw rectangle
                    graphics.Draw3DBorderRel(
                        _borderSkin,
                        rectanglePosition,
                        this.BackColor,
                        this.BackHatchStyle,
                        String.Empty,
                        ChartImageWrapMode.Scaled,
                        Color.Empty,
                        ChartImageAlignmentStyle.Center,
                        this.BackGradientStyle,
                        this.BackSecondaryColor,
                        this.LineColor,
                        this.LineWidth,
                        this.LineDashStyle);
                }
            }

            // Call base class to paint text, selection handles and process hot regions
            base.Paint(chart, graphics);
        }
Ejemplo n.º 17
0
        /// <summary>
        /// Paints an annotation object on the specified graphics.
        /// </summary>
        /// <param name="graphics">
        /// A <see cref="ChartGraphics"/> object, used to paint an annotation object.
        /// </param>
        /// <param name="chart">
        /// Reference to the <see cref="Chart"/> owner control.
        /// </param>
        override internal void Paint(Chart chart, ChartGraphics graphics)
        {
            // Get annotation position in relative coordinates
            PointF firstPoint  = PointF.Empty;
            PointF anchorPoint = PointF.Empty;
            SizeF  size        = SizeF.Empty;

            GetRelativePosition(out firstPoint, out size, out anchorPoint);
            PointF secondPoint = new PointF(firstPoint.X + size.Width, firstPoint.Y + size.Height);

            // Create selection rectangle
            RectangleF selectionRect = new RectangleF(firstPoint, new SizeF(secondPoint.X - firstPoint.X, secondPoint.Y - firstPoint.Y));

            // Adjust coordinates
            AdjustLineCoordinates(ref firstPoint, ref secondPoint, ref selectionRect);

            // Check if text position is valid
            if (float.IsNaN(firstPoint.X) ||
                float.IsNaN(firstPoint.Y) ||
                float.IsNaN(secondPoint.X) ||
                float.IsNaN(secondPoint.Y))
            {
                return;
            }

            // Set line caps
            bool    capChanged  = false;
            LineCap oldStartCap = LineCap.Flat;
            LineCap oldEndCap   = LineCap.Flat;

            if (this._startCap != LineAnchorCapStyle.None ||
                this._endCap != LineAnchorCapStyle.None)
            {
                capChanged  = true;
                oldStartCap = graphics.Pen.StartCap;
                oldEndCap   = graphics.Pen.EndCap;

                // Apply anchor cap settings
                if (this._startCap == LineAnchorCapStyle.Arrow)
                {
                    // Adjust arrow size for small line width
                    if (this.LineWidth < 4)
                    {
                        int adjustment = 3 - this.LineWidth;
                        graphics.Pen.StartCap       = LineCap.Custom;
                        graphics.Pen.CustomStartCap = new AdjustableArrowCap(
                            this.LineWidth + adjustment,
                            this.LineWidth + adjustment,
                            true);
                    }
                    else
                    {
                        graphics.Pen.StartCap = LineCap.ArrowAnchor;
                    }
                }
                else if (this._startCap == LineAnchorCapStyle.Diamond)
                {
                    graphics.Pen.StartCap = LineCap.DiamondAnchor;
                }
                else if (this._startCap == LineAnchorCapStyle.Round)
                {
                    graphics.Pen.StartCap = LineCap.RoundAnchor;
                }
                else if (this._startCap == LineAnchorCapStyle.Square)
                {
                    graphics.Pen.StartCap = LineCap.SquareAnchor;
                }
                if (this._endCap == LineAnchorCapStyle.Arrow)
                {
                    // Adjust arrow size for small line width
                    if (this.LineWidth < 4)
                    {
                        int adjustment = 3 - this.LineWidth;
                        graphics.Pen.EndCap       = LineCap.Custom;
                        graphics.Pen.CustomEndCap = new AdjustableArrowCap(
                            this.LineWidth + adjustment,
                            this.LineWidth + adjustment,
                            true);
                    }
                    else
                    {
                        graphics.Pen.EndCap = LineCap.ArrowAnchor;
                    }
                }
                else if (this._endCap == LineAnchorCapStyle.Diamond)
                {
                    graphics.Pen.EndCap = LineCap.DiamondAnchor;
                }
                else if (this._endCap == LineAnchorCapStyle.Round)
                {
                    graphics.Pen.EndCap = LineCap.RoundAnchor;
                }
                else if (this._endCap == LineAnchorCapStyle.Square)
                {
                    graphics.Pen.EndCap = LineCap.SquareAnchor;
                }
            }

            if (this.Common.ProcessModePaint)
            {
                // Draw line
                graphics.DrawLineRel(
                    this.LineColor,
                    this.LineWidth,
                    this.LineDashStyle,
                    firstPoint,
                    secondPoint,
                    this.ShadowColor,
                    this.ShadowOffset);
            }

            if (this.Common.ProcessModeRegions)
            {
                // Create line graphics path
                using (GraphicsPath path = new GraphicsPath())
                {
                    path.AddLine(
                        graphics.GetAbsolutePoint(firstPoint),
                        graphics.GetAbsolutePoint(secondPoint));
                    using (Pen pen = (Pen)graphics.Pen.Clone())
                    {
                        // Increase pen size by 2 pixels
                        pen.DashStyle = DashStyle.Solid;
                        pen.Width    += 2;
                        try
                        {
                            path.Widen(pen);
                        }
                        catch (OutOfMemoryException)
                        {
                            // GraphicsPath.Widen incorrectly throws OutOfMemoryException
                            // catching here and reacting by not widening
                        }
                        catch (ArgumentException)
                        {
                        }
                    }

                    // Add hot region
                    this.Common.HotRegionsList.AddHotRegion(
                        graphics,
                        path,
                        false,
                        ReplaceKeywords(this.ToolTip),
                        String.Empty,
                        String.Empty,
                        String.Empty,
                        this,
                        ChartElementType.Annotation);
                }
            }


            // Restore line caps
            if (capChanged)
            {
                graphics.Pen.StartCap = oldStartCap;
                graphics.Pen.EndCap   = oldEndCap;
            }

            // Paint selection handles
            PaintSelectionHandles(graphics, selectionRect, null);
        }
        /// <summary>
        /// Paints annotation object on specified graphics.
        /// </summary>
        /// <param name="graphics">
        /// A <see cref="ChartGraphics"/> used to paint annotation object.
        /// </param>
        /// <param name="chart">
        /// Reference to the <see cref="Chart"/> control.
        /// </param>
        override internal void Paint(Chart chart, ChartGraphics graphics)
        {
            // Get annotation position in relative coordinates
            PointF firstPoint  = PointF.Empty;
            PointF anchorPoint = PointF.Empty;
            SizeF  size        = SizeF.Empty;

            GetRelativePosition(out firstPoint, out size, out anchorPoint);
            PointF secondPoint = new PointF(firstPoint.X + size.Width, firstPoint.Y + size.Height);

            // Create selection rectangle
            RectangleF selectionRect = new RectangleF(firstPoint, new SizeF(secondPoint.X - firstPoint.X, secondPoint.Y - firstPoint.Y));

            // Check if text position is valid
            if (float.IsNaN(firstPoint.X) ||
                float.IsNaN(firstPoint.Y) ||
                float.IsNaN(secondPoint.X) ||
                float.IsNaN(secondPoint.Y))
            {
                return;
            }

            // Get arrow shape path
            using (GraphicsPath arrowPathAbs = GetArrowPath(graphics, selectionRect))
            {
                // Draw arrow shape
                if (this.Common.ProcessModePaint)
                {
                    graphics.DrawPathAbs(
                        arrowPathAbs,
                        (this.BackColor.IsEmpty) ? Color.White : this.BackColor,
                        this.BackHatchStyle,
                        String.Empty,
                        ChartImageWrapMode.Scaled,
                        Color.Empty,
                        ChartImageAlignmentStyle.Center,
                        this.BackGradientStyle,
                        this.BackSecondaryColor,
                        this.LineColor,
                        this.LineWidth,
                        this.LineDashStyle,
                        PenAlignment.Center,
                        this.ShadowOffset,
                        this.ShadowColor);
                }

                // Process hot region
                if (this.Common.ProcessModeRegions)
                {
                    // Use callout defined hot region
                    this.Common.HotRegionsList.AddHotRegion(
                        graphics,
                        arrowPathAbs,
                        false,
                        ReplaceKeywords(this.ToolTip),
                        String.Empty,
                        String.Empty,
                        String.Empty,
                        this,
                        ChartElementType.Annotation);
                }

                // Paint selection handles
                PaintSelectionHandles(graphics, selectionRect, null);
            }
        }
        /// <summary>
        /// Get arrow path for the specified annotation position
        /// </summary>
        /// <param name="graphics"></param>
        /// <param name="position"></param>
        /// <returns></returns>
        private GraphicsPath GetArrowPath(
            ChartGraphics graphics,
            RectangleF position)
        {
            // Get absolute position
            RectangleF positionAbs = graphics.GetAbsoluteRectangle(position);
            PointF     firstPoint  = positionAbs.Location;
            PointF     secondPoint = new PointF(positionAbs.Right, positionAbs.Bottom);

            // Calculate arrow length
            float deltaX      = secondPoint.X - firstPoint.X;
            float deltaY      = secondPoint.Y - firstPoint.Y;
            float arrowLength = (float)Math.Sqrt(deltaX * deltaX + deltaY * deltaY);

            // Create unrotated graphics path for the arrow started at the annotation location
            // and going to the right for the length of the rotated arrow.
            GraphicsPath path = new GraphicsPath();

            PointF[] points       = null;
            float    pointerRatio = 2.1f;

            if (this.ArrowStyle == ArrowStyle.Simple)
            {
                points = new PointF[] {
                    firstPoint,
                    new PointF(firstPoint.X + this.ArrowSize * pointerRatio, firstPoint.Y - this.ArrowSize * pointerRatio),
                    new PointF(firstPoint.X + this.ArrowSize * pointerRatio, firstPoint.Y - this.ArrowSize),
                    new PointF(firstPoint.X + arrowLength, firstPoint.Y - this.ArrowSize),
                    new PointF(firstPoint.X + arrowLength, firstPoint.Y + this.ArrowSize),
                    new PointF(firstPoint.X + this.ArrowSize * pointerRatio, firstPoint.Y + this.ArrowSize),
                    new PointF(firstPoint.X + this.ArrowSize * pointerRatio, firstPoint.Y + this.ArrowSize * pointerRatio)
                };
            }
            else if (this.ArrowStyle == ArrowStyle.DoubleArrow)
            {
                points = new PointF[] {
                    firstPoint,
                    new PointF(firstPoint.X + this.ArrowSize * pointerRatio, firstPoint.Y - this.ArrowSize * pointerRatio),
                    new PointF(firstPoint.X + this.ArrowSize * pointerRatio, firstPoint.Y - this.ArrowSize),
                    new PointF(firstPoint.X + arrowLength - this.ArrowSize * pointerRatio, firstPoint.Y - this.ArrowSize),
                    new PointF(firstPoint.X + arrowLength - this.ArrowSize * pointerRatio, firstPoint.Y - this.ArrowSize * pointerRatio),
                    new PointF(firstPoint.X + arrowLength, firstPoint.Y),
                    new PointF(firstPoint.X + arrowLength - this.ArrowSize * pointerRatio, firstPoint.Y + this.ArrowSize * pointerRatio),
                    new PointF(firstPoint.X + arrowLength - this.ArrowSize * pointerRatio, firstPoint.Y + this.ArrowSize),
                    new PointF(firstPoint.X + this.ArrowSize * pointerRatio, firstPoint.Y + this.ArrowSize),
                    new PointF(firstPoint.X + this.ArrowSize * pointerRatio, firstPoint.Y + this.ArrowSize * pointerRatio)
                };
            }
            else if (this.ArrowStyle == ArrowStyle.Tailed)
            {
                float tailRatio = 2.1f;
                points = new PointF[] {
                    firstPoint,
                    new PointF(firstPoint.X + this.ArrowSize * pointerRatio, firstPoint.Y - this.ArrowSize * pointerRatio),
                    new PointF(firstPoint.X + this.ArrowSize * pointerRatio, firstPoint.Y - this.ArrowSize),
                    new PointF(firstPoint.X + arrowLength, firstPoint.Y - this.ArrowSize * tailRatio),
                    new PointF(firstPoint.X + arrowLength - this.ArrowSize * tailRatio, firstPoint.Y),
                    new PointF(firstPoint.X + arrowLength, firstPoint.Y + this.ArrowSize * tailRatio),
                    new PointF(firstPoint.X + this.ArrowSize * pointerRatio, firstPoint.Y + this.ArrowSize),
                    new PointF(firstPoint.X + this.ArrowSize * pointerRatio, firstPoint.Y + this.ArrowSize * pointerRatio)
                };
            }
            else
            {
                throw (new InvalidOperationException(SR.ExceptionAnnotationArrowStyleUnknown));
            }

            path.AddLines(points);
            path.CloseAllFigures();

            // Calculate arrow angle
            float angle = (float)(Math.Atan(deltaY / deltaX) * 180f / Math.PI);

            if (deltaX < 0)
            {
                angle += 180f;
            }

            // Rotate arrow path around the first point
            using (Matrix matrix = new Matrix())
            {
                matrix.RotateAt(angle, firstPoint);
                path.Transform(matrix);
            }

            return(path);
        }
Ejemplo n.º 20
0
        /// <summary>
        /// </summary>
        /// <param name="cg"></param>
        /// <param name="x"></param>
        /// <param name="y"></param>
        /// <returns></returns>
        private PointF ToPixelsPos(ChartGraphics cg, double x, double y)
        {
            var p = new PointF((float) cg.GetPositionFromAxis(kChartAreaName, AxisName.X, x),
                (float) cg.GetPositionFromAxis(kChartAreaName, AxisName.Y, y));


            return cg.GetAbsolutePoint(p);
        }
        /// <summary>
        /// Return intensity of lightStyle for 3D Cube. There are tree types of lights: None,
        /// Simplistic and Realistic. None Style have same lightStyle intensity on
        /// all polygons. Normal vector doesn’t have influence on this type
        /// of lighting. Simplistic style have lightStyle source, which is
        /// rotated together with scene. Realistic lighting have fixed lightStyle
        /// source and intensity of lightStyle is change when scene is rotated.
        /// </summary>
        /// <param name="surfaceColor">Color used for polygons without lighting</param>
        /// <param name="front">Color corrected with intensity of lightStyle for Front side of the 3D Rectangle</param>
        /// <param name="back">Color corrected with intensity of lightStyle for Back side of the 3D Rectangle</param>
        /// <param name="left">Color corrected with intensity of lightStyle for Left side of the 3D Rectangle</param>
        /// <param name="right">Color corrected with intensity of lightStyle for Right side of the 3D Rectangle</param>
        /// <param name="top">Color corrected with intensity of lightStyle for Top side of the 3D Rectangle</param>
        /// <param name="bottom">Color corrected with intensity of lightStyle for Bottom side of the 3D Rectangle</param>
        internal void GetLight(Color surfaceColor, out Color front, out Color back, out Color left, out Color right, out Color top, out Color bottom)
        {
            switch (_lightStyle)
            {
            // LightStyle style is None
            case  LightStyle.None:
            {
                front  = surfaceColor;
                left   = surfaceColor;
                top    = surfaceColor;
                back   = surfaceColor;
                right  = surfaceColor;
                bottom = surfaceColor;
                break;
            }

            // LightStyle style is Simplistic
            case  LightStyle.Simplistic:
            {
                front  = surfaceColor;
                left   = ChartGraphics.GetGradientColor(surfaceColor, Color.Black, 0.25);
                top    = ChartGraphics.GetGradientColor(surfaceColor, Color.Black, 0.15);
                back   = surfaceColor;
                right  = ChartGraphics.GetGradientColor(surfaceColor, Color.Black, 0.25);
                bottom = ChartGraphics.GetGradientColor(surfaceColor, Color.Black, 0.15);
                break;
            }

            // LightStyle style is Realistic
            default:
            {
                // For Right Axis angle Realistic lightStyle should be different
                if (_rightAngleAxis)
                {
                    // LightStyle source Vector
                    Point3D    lightSource   = new Point3D(0F, 0F, -1F);
                    Point3D [] rightPRpoints = new Point3D[1];
                    rightPRpoints[0] = lightSource;
                    RightAngleProjection(rightPRpoints);

                    // ******************************************************************
                    // Color correction. Angle between Normal vector of polygon and
                    // vector of lightStyle source is used.
                    // ******************************************************************
                    if (this._angleY >= 45 || this._angleY <= -45)
                    {
                        front = ChartGraphics.GetGradientColor(surfaceColor, Color.Black, GetAngle(lightSource, _lightVectors[1]) / Math.PI);

                        back = ChartGraphics.GetGradientColor(surfaceColor, Color.Black, GetAngle(lightSource, _lightVectors[2]) / Math.PI);

                        left = ChartGraphics.GetGradientColor(surfaceColor, Color.Black, 0);

                        right = ChartGraphics.GetGradientColor(surfaceColor, Color.Black, 0);
                    }
                    else
                    {
                        front = ChartGraphics.GetGradientColor(surfaceColor, Color.Black, 0);

                        back = ChartGraphics.GetGradientColor(surfaceColor, Color.Black, 1);

                        left = ChartGraphics.GetGradientColor(surfaceColor, Color.Black, GetAngle(lightSource, _lightVectors[3]) / Math.PI);

                        right = ChartGraphics.GetGradientColor(surfaceColor, Color.Black, GetAngle(lightSource, _lightVectors[4]) / Math.PI);
                    }

                    top = ChartGraphics.GetGradientColor(surfaceColor, Color.Black, GetAngle(lightSource, _lightVectors[5]) / Math.PI);

                    bottom = ChartGraphics.GetGradientColor(surfaceColor, Color.Black, GetAngle(lightSource, _lightVectors[6]) / Math.PI);
                }
                else
                {
                    // LightStyle source Vector
                    Point3D lightSource = new Point3D(0F, 0F, 1F);

                    // ******************************************************************
                    // Color correction. Angle between Normal vector of polygon and
                    // vector of lightStyle source is used.
                    // ******************************************************************
                    front = GetBrightGradientColor(surfaceColor, GetAngle(lightSource, _lightVectors[1]) / Math.PI);

                    back = GetBrightGradientColor(surfaceColor, GetAngle(lightSource, _lightVectors[2]) / Math.PI);

                    left = GetBrightGradientColor(surfaceColor, GetAngle(lightSource, _lightVectors[3]) / Math.PI);

                    right = GetBrightGradientColor(surfaceColor, GetAngle(lightSource, _lightVectors[4]) / Math.PI);

                    top = GetBrightGradientColor(surfaceColor, GetAngle(lightSource, _lightVectors[5]) / Math.PI);

                    bottom = GetBrightGradientColor(surfaceColor, GetAngle(lightSource, _lightVectors[6]) / Math.PI);
                }

                break;
            }
            }
        }
        /// <summary>
        /// Paints an annotation object using the specified graphics.
        /// </summary>
        /// <param name="graphics">
        /// A <see cref="ChartGraphics"/> object, used to paint the annotation object.
        /// </param>
        /// <param name="chart">
        /// Reference to the <see cref="Chart"/> control.
        /// </param>
        override internal void Paint(Chart chart, ChartGraphics graphics)
        {
            // Paint all annotations in the group
            foreach (Annotation annotation in this.annotations)
            {
                annotation.Paint(chart, graphics);
            }

            if ((this.Common.ProcessModePaint && this.IsSelected) ||
                this.Common.ProcessModeRegions)
            {
                // Get annotation position in relative coordinates
                PointF firstPoint  = PointF.Empty;
                PointF anchorPoint = PointF.Empty;
                SizeF  size        = SizeF.Empty;
                GetRelativePosition(out firstPoint, out size, out anchorPoint);
                PointF secondPoint = new PointF(firstPoint.X + size.Width, firstPoint.Y + size.Height);

                // Create selection rectangle
                RectangleF selectionRect = new RectangleF(firstPoint, new SizeF(secondPoint.X - firstPoint.X, secondPoint.Y - firstPoint.Y));

                // Check rectangle orientation
                if (selectionRect.Width < 0)
                {
                    selectionRect.X     = selectionRect.Right;
                    selectionRect.Width = -selectionRect.Width;
                }
                if (selectionRect.Height < 0)
                {
                    selectionRect.Y      = selectionRect.Bottom;
                    selectionRect.Height = -selectionRect.Height;
                }

                // Check if text position is valid
                if (selectionRect.IsEmpty ||
                    float.IsNaN(selectionRect.X) ||
                    float.IsNaN(selectionRect.Y) ||
                    float.IsNaN(selectionRect.Right) ||
                    float.IsNaN(selectionRect.Bottom))
                {
                    return;
                }

                if (this.Common.ProcessModeRegions)
                {
                    // Add hot region
                    this.Common.HotRegionsList.AddHotRegion(
                        selectionRect,
                        ReplaceKeywords(this.ToolTip),
                        String.Empty,
                        String.Empty,
                        String.Empty,
                        this,
                        ChartElementType.Annotation,
                        String.Empty);
                }

                // Paint selection handles
                PaintSelectionHandles(graphics, selectionRect, null);
            }
        }
        /// <summary>
        /// Return intensity of lightStyle for Polygons. There are tree types of lights: None,
        /// Simplistic and Realistic. None Style have same lightStyle intensity on
        /// all polygons. Normal vector doesn’t have influence on this type
        /// of lighting. Simplistic style have lightStyle source, which is
        /// rotated together with scene. Realistic lighting have fixed lightStyle
        /// source and intensity of lightStyle is change when scene is rotated.
        /// </summary>
        /// <param name="points">Points of the polygon</param>
        /// <param name="surfaceColor">Color used for polygons without lighting</param>
        /// <param name="visiblePolygon">This flag gets information if  polygon is visible or not.</param>
        /// <param name="rotation">Y angle ( from -90 to 90 ) Should be used width switchSeriesOrder to get from -180 to 180</param>
        /// <param name="surfaceName">Used for lighting of front - back and left - right sides</param>
        /// <param name="switchSeriesOrder">Used to calculate real y angle</param>
        /// <returns>Color corrected with intensity of lightStyle</returns>
        internal Color GetPolygonLight(Point3D[] points, Color surfaceColor, bool visiblePolygon, float rotation, SurfaceNames surfaceName, bool switchSeriesOrder)
        {
            // Corrected color
            Color color = surfaceColor;

            // Direction of lightStyle source
            Point3D lightSource;

            lightSource = new Point3D(0F, 0F, 1F);

            // There are tree different lightStyle styles: None, Simplistic and realistic.
            switch (_lightStyle)
            {
            // LightStyle style is None
            case  LightStyle.None:
            {
                // Use same color
                break;
            }

            // LightStyle style is Simplistic
            case  LightStyle.Simplistic:
            {
                // Find two vectors of polygon
                Point3D firstVector = new Point3D();
                firstVector.X = points[0].X - points[1].X;
                firstVector.Y = points[0].Y - points[1].Y;
                firstVector.Z = points[0].Z - points[1].Z;

                Point3D secondVector = new Point3D();
                secondVector.X = points[2].X - points[1].X;
                secondVector.Y = points[2].Y - points[1].Y;
                secondVector.Z = points[2].Z - points[1].Z;

                // Find Normal vector for Polygon
                Point3D normalVector = new Point3D();
                normalVector.X = firstVector.Y * secondVector.Z - firstVector.Z * secondVector.Y;
                normalVector.Y = firstVector.Z * secondVector.X - firstVector.X * secondVector.Z;
                normalVector.Z = firstVector.X * secondVector.Y - firstVector.Y * secondVector.X;

                // Polygon is left side ( like side of area chart )
                if (surfaceName == SurfaceNames.Left)
                {
                    color = ChartGraphics.GetGradientColor(surfaceColor, Color.Black, 0.15);
                }
                // Polygon is right side ( like side of area chart )
                else if (surfaceName == SurfaceNames.Right)
                {
                    color = ChartGraphics.GetGradientColor(surfaceColor, Color.Black, 0.15);
                }
                // Polygon is front side ( like side of area chart )
                else if (surfaceName == SurfaceNames.Front)
                {
                    color = surfaceColor;
                }
                // Polygon is back side ( like side of area chart )
                else if (surfaceName == SurfaceNames.Back)
                {
                    color = surfaceColor;
                }
                // Polygon has angle with bottom side ( Line chart or top of area chart )
                else
                {
                    float angleLeft;
                    float angleRight;

                    // Find angles between lightStyle and polygon for different y-axis angles.
                    if (switchSeriesOrder)
                    {
                        if (rotation > 0 && rotation <= 90)
                        {
                            angleLeft  = GetAngle(normalVector, _lightVectors[3]);
                            angleRight = GetAngle(normalVector, _lightVectors[4]);
                        }
                        else
                        {
                            angleLeft  = GetAngle(normalVector, _lightVectors[4]);
                            angleRight = GetAngle(normalVector, _lightVectors[3]);
                        }
                    }
                    else
                    {
                        if (rotation > 0 && rotation <= 90)
                        {
                            angleLeft  = GetAngle(normalVector, _lightVectors[4]);
                            angleRight = GetAngle(normalVector, _lightVectors[3]);
                        }
                        else
                        {
                            angleLeft  = GetAngle(normalVector, _lightVectors[3]);
                            angleRight = GetAngle(normalVector, _lightVectors[4]);
                        }
                    }

                    if (Math.Abs(angleLeft - angleRight) < 0.01)
                    {
                        color = ChartGraphics.GetGradientColor(surfaceColor, Color.Black, 0.25);
                    }
                    else if (angleLeft < angleRight)
                    {
                        color = ChartGraphics.GetGradientColor(surfaceColor, Color.Black, 0.25);
                    }
                    else
                    {
                        color = ChartGraphics.GetGradientColor(surfaceColor, Color.Black, 0.15);
                    }
                }

                break;
            }

            // LightStyle style is Realistic
            default:
            {
                // Find two vectors of polygon
                Point3D firstVector = new Point3D();
                firstVector.X = points[0].X - points[1].X;
                firstVector.Y = points[0].Y - points[1].Y;
                firstVector.Z = points[0].Z - points[1].Z;

                Point3D secondVector = new Point3D();
                secondVector.X = points[2].X - points[1].X;
                secondVector.Y = points[2].Y - points[1].Y;
                secondVector.Z = points[2].Z - points[1].Z;

                // Find Normal vector for Polygon
                Point3D normalVector = new Point3D();
                normalVector.X = firstVector.Y * secondVector.Z - firstVector.Z * secondVector.Y;
                normalVector.Y = firstVector.Z * secondVector.X - firstVector.X * secondVector.Z;
                normalVector.Z = firstVector.X * secondVector.Y - firstVector.Y * secondVector.X;

                // ******************************************************************
                // Color correction. Angle between Normal vector of polygon and
                // vector of lightStyle source is used.
                // ******************************************************************
                if (surfaceName == SurfaceNames.Front)
                {
                    lightSource.Z *= -1;
                    color          = GetBrightGradientColor(surfaceColor, GetAngle(lightSource, _lightVectors[2]) / Math.PI);
                }
                else if (surfaceName == SurfaceNames.Back)
                {
                    lightSource.Z *= -1;
                    color          = GetBrightGradientColor(surfaceColor, GetAngle(lightSource, _lightVectors[1]) / Math.PI);
                }
                else
                {
                    if (visiblePolygon)
                    {
                        lightSource.Z *= -1;
                    }

                    color = GetBrightGradientColor(surfaceColor, GetAngle(lightSource, normalVector) / Math.PI);
                }

                break;
            }
            }
            return(color);
        }
        /// <summary>
        /// Draw strip(s) or line(s).
        /// </summary>
        /// <param name="graph">Reference to the Chart Graphics object.</param>
        /// <param name="common">Common objects.</param>
        /// <param name="drawLinesOnly">Indicates if Lines or Stripes should be drawn.</param>
        internal void Paint(
            ChartGraphics graph,
            CommonElements common,
            bool drawLinesOnly)
        {
            // Strip lines are not supported in circular chart area
            if (this.Axis.ChartArea.chartAreaIsCurcular)
            {
                return;
            }

            // Get plot area position
            RectangleF plotAreaPosition = this.Axis.ChartArea.PlotAreaPosition.ToRectangleF();

            // Detect if strip/line is horizontal or vertical
            bool horizontal = true;

            if (this.Axis.AxisPosition == AxisPosition.Bottom || this.Axis.AxisPosition == AxisPosition.Top)
            {
                horizontal = false;
            }

            // Get first series attached to this axis
            Series axisSeries = null;

            if (Axis.axisType == AxisName.X || Axis.axisType == AxisName.X2)
            {
                List <string> seriesArray = Axis.ChartArea.GetXAxesSeries((Axis.axisType == AxisName.X) ? AxisType.Primary : AxisType.Secondary, Axis.SubAxisName);
                if (seriesArray.Count > 0)
                {
                    axisSeries = Axis.Common.DataManager.Series[seriesArray[0]];
                    if (axisSeries != null && !axisSeries.IsXValueIndexed)
                    {
                        axisSeries = null;
                    }
                }
            }

            // Get starting position from axis
            // NOTE: Starting position was changed from "this.Axis.minimum" to
            // fix the minimum scaleView location to fix issue #5962 -- AG
            double currentPosition = this.Axis.ViewMinimum;

            // Adjust start position depending on the interval type
            if (!Axis.ChartArea.chartAreaIsCurcular ||
                Axis.axisType == AxisName.Y ||
                Axis.axisType == AxisName.Y2)
            {
                double intervalToUse = this.Interval;

                // NOTE: fix for issue #5962
                // Always use original grid interval for isInterlaced strip lines.
                if (this.interlaced)
                {
                    // Automaticly generated isInterlaced strips have interval twice as big as major grids
                    intervalToUse /= 2.0;
                }
                currentPosition = ChartHelper.AlignIntervalStart(currentPosition, intervalToUse, this.IntervalType, axisSeries);
            }

            // Too many tick marks
            if (this.Interval != 0)
            {
                if ((Axis.ViewMaximum - Axis.ViewMinimum) / ChartHelper.GetIntervalSize(currentPosition, this._interval, this._intervalType, axisSeries, 0, DateTimeIntervalType.Number, false) > ChartHelper.MaxNumOfGridlines)
                {
                    return;
                }
            }

            DateTimeIntervalType offsetType = (IntervalOffsetType == DateTimeIntervalType.Auto) ? IntervalType : IntervalOffsetType;

            if (this.Interval == 0)
            {
                currentPosition = this.IntervalOffset;
            }

            /******************************************************************
             * Removed by AG. Causing issues with interalced strip lines.
             * /******************************************************************
             * else if(axisSeries != null && axisSeries.IsXValueIndexed)
             * {
             *      // Align first position for indexed series
             *      currentPosition += this.Axis.AlignIndexedIntervalStart(
             *              currentPosition,
             *              this.Interval,
             *              this.IntervalType,
             *              axisSeries,
             *              this.IntervalOffset,
             *              offsetType,
             *              false);
             * }
             */
            else
            {
                if (this.IntervalOffset > 0)
                {
                    currentPosition += ChartHelper.GetIntervalSize(currentPosition, this.IntervalOffset,
                                                                   offsetType, axisSeries, 0, DateTimeIntervalType.Number, false);
                }
                else if (this.IntervalOffset < 0)
                {
                    currentPosition -= ChartHelper.GetIntervalSize(currentPosition, -this.IntervalOffset,
                                                                   offsetType, axisSeries, 0, DateTimeIntervalType.Number, false);
                }
            }

            // Draw several lines or strips if Interval property is set
            int counter = 0;

            do
            {
                // Check if we do not exceed max number of elements
                if (counter++ > ChartHelper.MaxNumOfGridlines)
                {
                    break;
                }

                // Draw strip
                if (this.StripWidth > 0 && !drawLinesOnly)
                {
                    double stripRightPosition = currentPosition + ChartHelper.GetIntervalSize(currentPosition, this.StripWidth, this.StripWidthType, axisSeries, this.IntervalOffset, offsetType, false);
                    if (stripRightPosition > this.Axis.ViewMinimum && currentPosition < this.Axis.ViewMaximum)
                    {
                        // Calculate strip rectangle
                        RectangleF rect = RectangleF.Empty;
                        double     pos1 = (float)this.Axis.GetLinearPosition(currentPosition);
                        double     pos2 = (float)this.Axis.GetLinearPosition(stripRightPosition);
                        if (horizontal)
                        {
                            rect.X      = plotAreaPosition.X;
                            rect.Width  = plotAreaPosition.Width;
                            rect.Y      = (float)Math.Min(pos1, pos2);
                            rect.Height = (float)Math.Max(pos1, pos2) - rect.Y;

                            // Check rectangle boundaries
                            rect.Intersect(plotAreaPosition);
                        }
                        else
                        {
                            rect.Y      = plotAreaPosition.Y;
                            rect.Height = plotAreaPosition.Height;
                            rect.X      = (float)Math.Min(pos1, pos2);
                            rect.Width  = (float)Math.Max(pos1, pos2) - rect.X;

                            // Check rectangle boundaries
                            rect.Intersect(plotAreaPosition);
                        }

                        if (rect.Width > 0 && rect.Height > 0)
                        {
                            // Start Svg Selection mode
                            graph.StartHotRegion("", this._toolTip);
                            if (!this.Axis.ChartArea.Area3DStyle.Enable3D)
                            {
                                // Draw strip
                                graph.FillRectangleRel(rect,
                                                       this.BackColor, this.BackHatchStyle, this.BackImage,
                                                       this.BackImageWrapMode, this.BackImageTransparentColor, this.BackImageAlignment,
                                                       this.BackGradientStyle, this.BackSecondaryColor, this.BorderColor,
                                                       this.BorderWidth, this.BorderDashStyle, Color.Empty,
                                                       0, PenAlignment.Inset);
                            }
                            else
                            {
                                Draw3DStrip(graph, rect, horizontal);
                            }

                            // End Svg Selection mode
                            graph.EndHotRegion();

                            // Draw strip line title
                            PaintTitle(graph, rect);

                            if (common.ProcessModeRegions)
                            {
                                if (!this.Axis.ChartArea.Area3DStyle.Enable3D)
                                {
                                    common.HotRegionsList.AddHotRegion(rect, this.ToolTip, string.Empty, string.Empty, string.Empty, this, ChartElementType.StripLines, null);
                                }
                            }
                        }
                    }
                }
                // Draw line
                else if (this.StripWidth == 0 && drawLinesOnly)
                {
                    if (currentPosition > this.Axis.ViewMinimum && currentPosition < this.Axis.ViewMaximum)
                    {
                        // Calculate line position
                        PointF point1 = PointF.Empty;
                        PointF point2 = PointF.Empty;
                        if (horizontal)
                        {
                            point1.X = plotAreaPosition.X;
                            point1.Y = (float)this.Axis.GetLinearPosition(currentPosition);
                            point2.X = plotAreaPosition.Right;
                            point2.Y = point1.Y;
                        }
                        else
                        {
                            point1.X = (float)this.Axis.GetLinearPosition(currentPosition);
                            point1.Y = plotAreaPosition.Y;
                            point2.X = point1.X;
                            point2.Y = plotAreaPosition.Bottom;
                        }

                        // Start Svg Selection mode
                        graph.StartHotRegion("", this._toolTip);

                        // Draw Line
                        if (!this.Axis.ChartArea.Area3DStyle.Enable3D)
                        {
                            graph.DrawLineRel(this.BorderColor, this.BorderWidth, this.BorderDashStyle, point1, point2);
                        }
                        else
                        {
                            graph.Draw3DGridLine(this.Axis.ChartArea, _borderColor, _borderWidth, _borderDashStyle, point1, point2, horizontal, Axis.Common, this);
                        }

                        // End Svg Selection mode
                        graph.EndHotRegion();

                        // Draw strip line title
                        PaintTitle(graph, point1, point2);

                        if (common.ProcessModeRegions)
                        {
                            SizeF relBorderWidth = new SizeF(this.BorderWidth + 1, this.BorderWidth + 1);
                            relBorderWidth = graph.GetRelativeSize(relBorderWidth);
                            RectangleF lineRect = RectangleF.Empty;
                            if (horizontal)
                            {
                                lineRect.X      = point1.X;
                                lineRect.Y      = point1.Y - relBorderWidth.Height / 2f;
                                lineRect.Width  = point2.X - point1.X;
                                lineRect.Height = relBorderWidth.Height;
                            }
                            else
                            {
                                lineRect.X      = point1.X - relBorderWidth.Width / 2f;
                                lineRect.Y      = point1.Y;
                                lineRect.Width  = relBorderWidth.Width;
                                lineRect.Height = point2.Y - point1.Y;
                            }

                            common.HotRegionsList.AddHotRegion(lineRect, this.ToolTip, null, null, null, this, ChartElementType.StripLines, null);
                        }
                    }
                }

                // Go to the next line/strip
                if (this.Interval > 0)
                {
                    currentPosition += ChartHelper.GetIntervalSize(currentPosition, this.Interval, this.IntervalType, axisSeries, this.IntervalOffset, offsetType, false);
                }
            } while(this.Interval > 0 && currentPosition <= this.Axis.ViewMaximum);
        }
        /// <summary>
        /// Draws strip line in 3d.
        /// </summary>
        /// <param name="graph">Chart graphics.</param>
        /// <param name="rect">Strip rectangle.</param>
        /// <param name="horizontal">Indicates that strip is horizontal</param>
        private void Draw3DStrip(ChartGraphics graph, RectangleF rect, bool horizontal)
        {
            ChartArea             area          = this.Axis.ChartArea;
            GraphicsPath          path          = null;
            DrawingOperationTypes operationType = DrawingOperationTypes.DrawElement;

            if (this.Axis.Common.ProcessModeRegions)
            {
                operationType |= DrawingOperationTypes.CalcElementPath;
            }

            // Draw strip on the back/front wall
            path = graph.Fill3DRectangle(
                rect,
                area.IsMainSceneWallOnFront() ? area.areaSceneDepth : 0f,
                0,
                area.matrix3D,
                area.Area3DStyle.LightStyle,
                this.BackColor,
                this.BorderColor,
                this.BorderWidth,
                this.BorderDashStyle,
                operationType);

            if (this.Axis.Common.ProcessModeRegions)
            {
                this.Axis.Common.HotRegionsList.AddHotRegion(graph, path, false, this.ToolTip, null, null, null, this, ChartElementType.StripLines);
            }

            if (horizontal)
            {
                // Draw strip on the side wall (left or right)
                if (!area.IsSideSceneWallOnLeft())
                {
                    rect.X = rect.Right;
                }
                rect.Width = 0f;

                path = graph.Fill3DRectangle(
                    rect,
                    0f,
                    area.areaSceneDepth,
                    area.matrix3D,
                    area.Area3DStyle.LightStyle,
                    this.BackColor,
                    this.BorderColor,
                    this.BorderWidth,
                    this.BorderDashStyle,
                    operationType);
            }
            else if (area.IsBottomSceneWallVisible())
            {
                // Draw strip on the bottom wall (if visible)
                rect.Y      = rect.Bottom;
                rect.Height = 0f;

                path = graph.Fill3DRectangle(
                    rect,
                    0f,
                    area.areaSceneDepth,
                    area.matrix3D,
                    area.Area3DStyle.LightStyle,
                    this.BackColor,
                    this.BorderColor,
                    this.BorderWidth,
                    this.BorderDashStyle,
                    operationType);
            }

            if (this.Axis.Common.ProcessModeRegions)
            {
                this.Axis.Common.HotRegionsList.AddHotRegion(graph, path, false, this.ToolTip, null, null, null, this, ChartElementType.StripLines);
            }

            if (path != null)
            {
                path.Dispose();
            }
        }
        public void DrawPolygons(ChartGraphics cg, Series line1,
            Series line2)
        {
            FillRangePolygons(cg, line1, line2);

            //iterate through all the polygons and draw them
            for (int i = 0; i < RangePolygons.Length; i++)
            {
                //if the polygon is a BOTTOM range polygon than fill the color with transYellow
                //else fill with transBlue;
                if (RangePolygons[i].RangeType == System.Windows.Forms.DataVisualization.Charting.Utilities.RangePolygon.RANGETYPE.BOTTOM)

                    RangePolygons[i].FillColor = this.bottomColor;
                else
                    RangePolygons[i].FillColor = this.topColor;

                SolidBrush fillBrush = new SolidBrush(RangePolygons[i].FillColor);

                //do the actual drawing
                cg.Graphics.FillPolygon(fillBrush, RangePolygons[i].PolygonPoints);
            }
        }
        /// <summary>
        /// Draw strip/line title text
        /// </summary>
        /// <param name="graph">Chart graphics object.</param>
        /// <param name="rect">Rectangle to draw in.</param>
        private void PaintTitle(ChartGraphics graph, RectangleF rect)
        {
            if (this.Text.Length > 0)
            {
                // Get title text
                string titleText = this.Text;

                // Prepare string format
                using (StringFormat format = new StringFormat())
                {
                    format.Alignment = this.TextAlignment;

                    if (graph.IsRightToLeft)
                    {
                        if (format.Alignment == StringAlignment.Far)
                        {
                            format.Alignment = StringAlignment.Near;
                        }
                        else if (format.Alignment == StringAlignment.Near)
                        {
                            format.Alignment = StringAlignment.Far;
                        }
                    }

                    format.LineAlignment = this.TextLineAlignment;

                    // Adjust default title angle for horizontal lines
                    int angle = 0;
                    switch (this.TextOrientation)
                    {
                    case (TextOrientation.Rotated90):
                        angle = 90;
                        break;

                    case (TextOrientation.Rotated270):
                        angle = 270;
                        break;

                    case (TextOrientation.Auto):
                        if (this.Axis.AxisPosition == AxisPosition.Bottom || this.Axis.AxisPosition == AxisPosition.Top)
                        {
                            angle = 270;
                        }
                        break;
                    }

                    // Set vertical text for horizontal lines
                    if (angle == 90)
                    {
                        format.FormatFlags = StringFormatFlags.DirectionVertical;
                        angle = 0;
                    }
                    else if (angle == 270)
                    {
                        format.FormatFlags = StringFormatFlags.DirectionVertical;
                        angle = 180;
                    }

                    // Measure string size
                    SizeF size = graph.MeasureStringRel(titleText.Replace("\\n", "\n"), this.Font, new SizeF(100, 100), format, this.GetTextOrientation());

                    // Adjust text size
                    float zPositon = 0f;
                    if (this.Axis.ChartArea.Area3DStyle.Enable3D)
                    {
                        // Get projection coordinates
                        Point3D[] textSizeProjection = new Point3D[3];
                        zPositon = this.Axis.ChartArea.IsMainSceneWallOnFront() ? this.Axis.ChartArea.areaSceneDepth : 0f;
                        textSizeProjection[0] = new Point3D(0f, 0f, zPositon);
                        textSizeProjection[1] = new Point3D(size.Width, 0f, zPositon);
                        textSizeProjection[2] = new Point3D(0f, size.Height, zPositon);

                        // Transform coordinates of text size
                        this.Axis.ChartArea.matrix3D.TransformPoints(textSizeProjection);

                        // Adjust text size
                        int index = this.Axis.ChartArea.IsMainSceneWallOnFront() ? 0 : 1;
                        size.Width  *= size.Width / (textSizeProjection[index].X - textSizeProjection[(index == 0) ? 1 : 0].X);
                        size.Height *= size.Height / (textSizeProjection[2].Y - textSizeProjection[0].Y);
                    }


                    // Get relative size of the border width
                    SizeF sizeBorder = graph.GetRelativeSize(new SizeF(this.BorderWidth, this.BorderWidth));

                    // Find the center of rotation
                    PointF rotationCenter = PointF.Empty;
                    if (format.Alignment == StringAlignment.Near)
                    { // Near
                        rotationCenter.X = rect.X + size.Width / 2 + sizeBorder.Width;
                    }
                    else if (format.Alignment == StringAlignment.Far)
                    { // Far
                        rotationCenter.X = rect.Right - size.Width / 2 - sizeBorder.Width;
                    }
                    else
                    { // Center
                        rotationCenter.X = (rect.Left + rect.Right) / 2;
                    }

                    if (format.LineAlignment == StringAlignment.Near)
                    { // Near
                        rotationCenter.Y = rect.Top + size.Height / 2 + sizeBorder.Height;
                    }
                    else if (format.LineAlignment == StringAlignment.Far)
                    { // Far
                        rotationCenter.Y = rect.Bottom - size.Height / 2 - sizeBorder.Height;
                    }
                    else
                    { // Center
                        rotationCenter.Y = (rect.Bottom + rect.Top) / 2;
                    }

                    // Reset string alignment to center point
                    format.Alignment     = StringAlignment.Center;
                    format.LineAlignment = StringAlignment.Center;

                    if (this.Axis.ChartArea.Area3DStyle.Enable3D)
                    {
                        // Get projection coordinates
                        Point3D[] rotationCenterProjection = new Point3D[2];
                        rotationCenterProjection[0] = new Point3D(rotationCenter.X, rotationCenter.Y, zPositon);
                        if (format.FormatFlags == StringFormatFlags.DirectionVertical)
                        {
                            rotationCenterProjection[1] = new Point3D(rotationCenter.X, rotationCenter.Y - 20f, zPositon);
                        }
                        else
                        {
                            rotationCenterProjection[1] = new Point3D(rotationCenter.X - 20f, rotationCenter.Y, zPositon);
                        }

                        // Transform coordinates of text rotation point
                        this.Axis.ChartArea.matrix3D.TransformPoints(rotationCenterProjection);

                        // Adjust rotation point
                        rotationCenter = rotationCenterProjection[0].PointF;

                        // Adjust angle of the text
                        if (angle == 0 || angle == 180 || angle == 90 || angle == 270)
                        {
                            if (format.FormatFlags == StringFormatFlags.DirectionVertical)
                            {
                                angle += 90;
                            }

                            // Convert coordinates to absolute
                            rotationCenterProjection[0].PointF = graph.GetAbsolutePoint(rotationCenterProjection[0].PointF);
                            rotationCenterProjection[1].PointF = graph.GetAbsolutePoint(rotationCenterProjection[1].PointF);

                            // Calcuate axis angle
                            float angleXAxis = (float)Math.Atan(
                                (rotationCenterProjection[1].Y - rotationCenterProjection[0].Y) /
                                (rotationCenterProjection[1].X - rotationCenterProjection[0].X));
                            angleXAxis = (float)Math.Round(angleXAxis * 180f / (float)Math.PI);
                            angle     += (int)angleXAxis;
                        }
                    }

                    // Draw string
                    using (Brush brush = new SolidBrush(this.ForeColor))
                    {
                        graph.DrawStringRel(
                            titleText.Replace("\\n", "\n"),
                            this.Font,
                            brush,
                            rotationCenter,
                            format,
                            angle,
                            this.GetTextOrientation());
                    }
                }
            }
        }
 /// <summary>
 /// Gets the polygon that is the right most polygon.  
 /// A RangePolygon will only be created if line1 and line2 have the same final XValues
 /// </summary>
 /// <param name="cg">for finding the absolute coordinates</param>
 /// <param name="line1">line 1</param>
 /// <param name="line2">line 2</param>
 /// <param name="lastIntersection">last point of intersection</param>
 /// <param name="pID">id to give the new polygon</param>
 /// <returns>a RangePolygon, null otherwise</returns>
 private RangePolygon GetEndPolygon(ChartGraphics cg, Series line1,
     Series line2, DataPoint lastIntersection,int pID)
 {
     DataPoint line1X = line1.Points[line1.Points.Count - 1];
     DataPoint line2X = line2.Points[line2.Points.Count - 1];
     if (line1X.XValue == line2X.XValue)
     {
         return GetPolygonOfIntersection(cg, line1, line2, lastIntersection, line1X, pID);
     }
     return null;
 }
 /// <summary>
 /// Helper method which calculates chart area plotting position in pixels.
 /// </summary>
 /// <param name="area">Chart area to get the plotting area position.</param>
 /// <param name="chartGraphics">Chart graphics object.</param>
 /// <returns>Chart area ploting area position in pixels.</returns>
 private RectangleF GetChartAreaPlottingPosition(ChartArea area, ChartGraphics chartGraphics)
 {
     RectangleF plottingRect = area.Position.ToRectangleF();
     plottingRect.X += (area.Position.Width / 100F) * area.InnerPlotPosition.X;
     plottingRect.Y += (area.Position.Height / 100F) * area.InnerPlotPosition.Y;
     plottingRect.Width = (area.Position.Width / 100F) * area.InnerPlotPosition.Width;
     plottingRect.Height = (area.Position.Height / 100F) * area.InnerPlotPosition.Height;
     plottingRect = chartGraphics.GetAbsoluteRectangle(plottingRect);
     return plottingRect;
 }
 /// <summary>
 /// if line1 and line2 have the same initial X index, then create a polygon for it, else
 /// ignore it.
 /// </summary>
 /// <param name="cg">Chart Graphics finding the absolute coordinates</param>
 /// <param name="line1">line 1</param>
 /// <param name="line2">line 2</param>
 /// <returns>a RangePolygon if line1 and line2 have the same initial x index, else null</returns>
 private RangePolygon GetStartPolygon(ChartGraphics cg, Series line1,
     Series line2, DataPoint firstIntersection,int pID)
 {
     DataPoint line1X = line1.Points[0];
     DataPoint line2X = line2.Points[0];
     if (line1X.XValue == line2X.XValue)
     {
         return GetPolygonOfIntersection(cg, line1, line2, line1X, firstIntersection,pID);
     }
     return null;
 }
        /// <summary>
        /// Paints an annotation object on the specified graphics.
        /// </summary>
        /// <param name="graphics">
        /// A <see cref="ChartGraphics"/> object, used to paint an annotation object.
        /// </param>
        /// <param name="chart">
        /// Reference to the <see cref="Chart"/> owner control.
        /// </param>
        override internal void Paint(Chart chart, ChartGraphics graphics)
        {
            // Get annotation position in relative coordinates
            PointF firstPoint  = PointF.Empty;
            PointF anchorPoint = PointF.Empty;
            SizeF  size        = SizeF.Empty;

            GetRelativePosition(out firstPoint, out size, out anchorPoint);
            PointF secondPoint = new PointF(firstPoint.X + size.Width, firstPoint.Y + size.Height);

            // Create selection rectangle
            RectangleF selectionRect = new RectangleF(firstPoint, new SizeF(secondPoint.X - firstPoint.X, secondPoint.Y - firstPoint.Y));

            // Get text position
            RectangleF textPosition = new RectangleF(selectionRect.Location, selectionRect.Size);

            if (textPosition.Width < 0)
            {
                textPosition.X     = textPosition.Right;
                textPosition.Width = -textPosition.Width;
            }
            if (textPosition.Height < 0)
            {
                textPosition.Y      = textPosition.Bottom;
                textPosition.Height = -textPosition.Height;
            }

            // Check if text position is valid
            if (textPosition.IsEmpty ||
                float.IsNaN(textPosition.X) ||
                float.IsNaN(textPosition.Y) ||
                float.IsNaN(textPosition.Right) ||
                float.IsNaN(textPosition.Bottom))
            {
                return;
            }

            if (this.Common.ProcessModePaint)
            {
                DrawText(graphics, textPosition, false, false);
            }

            if (this.Common.ProcessModeRegions)
            {
                // Add hot region
                if (isEllipse)
                {
                    using (GraphicsPath ellipsePath = new GraphicsPath())
                    {
                        ellipsePath.AddEllipse(textPosition);
                        this.Common.HotRegionsList.AddHotRegion(
                            graphics,
                            ellipsePath,
                            true,
                            ReplaceKeywords(this.ToolTip),
                            String.Empty,
                            String.Empty,
                            String.Empty,
                            this,
                            ChartElementType.Annotation);
                    }
                }
                else
                {
                    this.Common.HotRegionsList.AddHotRegion(
                        textPosition,
                        ReplaceKeywords(this.ToolTip),
                        String.Empty,
                        String.Empty,
                        String.Empty,
                        this,
                        ChartElementType.Annotation,
                        String.Empty);
                }
            }

            // Paint selection handles
            PaintSelectionHandles(graphics, selectionRect, null);
        }