Esempio n. 1
0
        /// <inheritdoc/>
        public override void FillOneRange(
            GraphicsPath gp,
            Processed2DPlotData pdata,
            IPlotRange range,
            IPlotArea layer,
            CSPlaneID fillDirection,
            bool ignoreMissingDataPoints,
            bool connectCircular,
            PointF[] allLinePoints,
            double logicalShiftX,
            double logicalShiftY
            )
        {
            if (range.Length < 4)
            {
                return;
            }

            if (connectCircular)
            {
                var circularLinePointsLengthM1 = 2 + TrimToValidBezierLength(range.Length);
                var circularLinePoints         = new PointF[circularLinePointsLengthM1 + 1];
                Array.Copy(allLinePoints, range.LowerBound, circularLinePoints, 0, range.Length); // Extract
                circularLinePoints[circularLinePointsLengthM1] = circularLinePoints[0];

                // amend missing control points
                if (circularLinePointsLengthM1 - range.Length >= 1)
                {
                    circularLinePoints[circularLinePointsLengthM1 - 1] = GdiExtensionMethods.Interpolate(circularLinePoints[circularLinePointsLengthM1 - 3], circularLinePoints[circularLinePointsLengthM1], 0.5); // Last Control point should be halfway between
                }
                if (circularLinePointsLengthM1 - range.Length >= 2)
                {
                    circularLinePoints[circularLinePointsLengthM1 - 2] = GdiExtensionMethods.Interpolate(circularLinePoints[circularLinePointsLengthM1 - 3], circularLinePoints[circularLinePointsLengthM1], 0.5); // Middle Control point should be halfway between previous fixed point and last(=first) fixed point
                }
                FillOneRange_PreprocessedPoints(gp, pdata, range, layer, fillDirection, circularLinePoints, connectCircular, logicalShiftX, logicalShiftY);
            }
            else
            {
                var trimmedLinePointsLength = TrimToValidBezierLength(range.Length);
                var trimmedLinePoints       = new PointF[trimmedLinePointsLength];
                Array.Copy(allLinePoints, range.LowerBound, trimmedLinePoints, 0, trimmedLinePointsLength); // Extract
                FillOneRange_PreprocessedPoints(gp, pdata, range, layer, fillDirection, trimmedLinePoints, connectCircular, logicalShiftX, logicalShiftY);
            }
        }
Esempio n. 2
0
        /// <summary>
        /// Template to make a line draw.
        /// </summary>
        /// <param name="g">Graphics context.</param>
        /// <param name="allLinePoints">The plot data. Don't use the Range property of the pdata, since it is overriden by the next argument.</param>
        /// <param name="range">The plot range to use.</param>
        /// <param name="layer">Graphics layer.</param>
        /// <param name="linePen">The pen to draw the line.</param>
        /// <param name="symbolGap">The size of the symbol gap. Argument is the original index of the data. The return value is the absolute symbol gap at this index.
        /// This function is null if no symbol gap is required.</param>
        /// <param name="skipFrequency">Skip frequency. Normally 1, thus all gaps are taken into account. If 2, only every 2nd gap is taken into account, and so on.</param>
        /// <param name="connectCircular">If true, there is a line connecting the start and the end of the range.</param>
        /// <param name="linePlotStyle">The line plot style.</param>
        public override void PaintOneRange(
            Graphics g,
            PointF[] allLinePoints,
            IPlotRange range,
            IPlotArea layer,
            PenX linePen,
            Func <int, double> symbolGap,
            int skipFrequency,
            bool connectCircular,
            LinePlotStyle linePlotStyle)
        {
            // Bezier is only supported with point numbers n=4+3*k
            // so trim the range appropriately
            if (range.Length < 4)
            {
                return; // then too less points are in this range
            }
            PointF[] circularLinePoints;

            if (connectCircular)
            {
                var circularLinePointsLengthM1 = 2 + TrimToValidBezierLength(range.Length);
                circularLinePoints = new PointF[circularLinePointsLengthM1 + 1];
                Array.Copy(allLinePoints, range.LowerBound, circularLinePoints, 0, range.Length); // Extract
                circularLinePoints[circularLinePointsLengthM1] = circularLinePoints[0];

                // amend missing control points
                if (circularLinePointsLengthM1 - range.Length >= 1)
                {
                    circularLinePoints[circularLinePointsLengthM1 - 1] = GdiExtensionMethods.Interpolate(circularLinePoints[circularLinePointsLengthM1 - 3], circularLinePoints[circularLinePointsLengthM1], 0.5); // Last Control point should be halfway between
                }
                if (circularLinePointsLengthM1 - range.Length >= 2)
                {
                    circularLinePoints[circularLinePointsLengthM1 - 2] = GdiExtensionMethods.Interpolate(circularLinePoints[circularLinePointsLengthM1 - 3], circularLinePoints[circularLinePointsLengthM1], 0.5); // Middle Control point should be halfway between previous fixed point and last(=first) fixed point
                }
                range = range.WithUpperBoundExtendedBy(circularLinePointsLengthM1 - range.Length);
            }
            else // not circular
            {
                var trimmedLength = TrimToValidBezierLength(range.Length);
                if (range.Length != trimmedLength)
                {
                    range = range.WithUpperBoundShortenedBy(range.Length - trimmedLength);
                }

                if (range.LowerBound == 0 && trimmedLength == allLinePoints.Length)
                {
                    circularLinePoints = allLinePoints;
                }
                else
                {
                    circularLinePoints = new PointF[trimmedLength];
                    Array.Copy(allLinePoints, range.LowerBound, circularLinePoints, 0, trimmedLength); // Extract
                }
            }

            if (null != symbolGap)                                                                  // circular with symbol gap
            {
                var realSkipFrequency = skipFrequency % 3 == 0 ? skipFrequency : skipFrequency * 3; // least common multiple of skipFrequency and 3
                var skipLinePoints    = new PointF[0];
                foreach (var segmentRange in GetSegmentRanges(range, symbolGap, realSkipFrequency, connectCircular))
                {
                    if (segmentRange.IsFullRangeClosedCurve) // test if this is a closed polygon without any gaps -> draw a closed polygon and return
                    {
                        // use the whole circular arry to draw a closed polygon without any gaps
                        g.DrawBeziers(linePen, circularLinePoints);
                    }
                    else
                    {
                        var skipLinePointsLength = 1 + segmentRange.Length;
                        if (skipLinePoints.Length != skipLinePointsLength)
                        {
                            skipLinePoints = new PointF[skipLinePointsLength];
                        }
                        Array.Copy(circularLinePoints, segmentRange.IndexAtSubRangeStart, skipLinePoints, 0, skipLinePointsLength);

                        PointF[] shortenedLinePoints;
                        if (segmentRange.GapAtSubRangeStart != 0 || segmentRange.GapAtSubRangeEnd != 0)
                        {
                            shortenedLinePoints = GdiExtensionMethods.ShortenBezierCurve(skipLinePoints, segmentRange.GapAtSubRangeStart / 2, segmentRange.GapAtSubRangeEnd / 2);
                        }
                        else
                        {
                            shortenedLinePoints = skipLinePoints;
                        }

                        if (null != shortenedLinePoints)
                        {
                            g.DrawBeziers(linePen, shortenedLinePoints);
                        }
                    }
                }
            }
            else // no symbol gap
            {
                g.DrawBeziers(linePen, circularLinePoints);
            }
        }