/// <summary>
		/// Template to get a fill path.
		/// </summary>
		/// <param name="gp">Graphics path to fill with data.</param>
		/// <param name="pdata">The plot data. Do not use the plot point positions from here, since they are not shifted when shifting group styles are present.</param>
		/// <param name="range">The plot range to use.</param>
		/// <param name="layer">Graphics layer.</param>
		/// <param name="fillDirection">Designates a bound to fill to.</param>
		/// <param name="ignoreMissingDataPoints">If true, missing data points are ignored.</param>
		/// <param name="connectCircular">If true, the line is connected circular, and the area is the polygon inside of that circular connection.</param>
		/// <param name="allLinePointsShiftedAlready">The plot positions, already shifted when a logical shift needed to be applied. Don't use the Range property of the pdata, since it is overriden by the next argument.</param>
		/// <param name="logicalShiftX">The logical shift in x-direction.</param>
		/// <param name="logicalShiftY">The logical shift in x-direction.</param>
		public abstract void FillOneRange(
			GraphicsPath gp,
			Processed2DPlotData pdata,
			IPlotRange range,
			IPlotArea layer,
			CSPlaneID fillDirection,
			bool ignoreMissingDataPoints,
			bool connectCircular,
			PointF[] allLinePointsShiftedAlready,
			double logicalShiftX,
			double logicalShiftY
			);
Exemple #2
0
        /// <summary>
        /// Shift the plot points provided in <paramref name="pdata"/> with a logical shift in x- and/or y- direction.
        /// </summary>
        /// <param name="pdata">The plot point position data.</param>
        /// <param name="layer">The plot layer for which the data are intended.</param>
        /// <param name="logicalShiftX">The logical shift in x-direction.</param>
        /// <param name="logicalShiftY">The logical shift in y-direction.</param>
        /// <returns>Array of plot point positions, but now shifted by logical values in x-direction (<paramref name="logicalShiftX"/>) and y-direction (<paramref name="logicalShiftY"/>).</returns>
        public static PointF[] GetPlotPointsInAbsoluteLayerCoordinatesWithShift(Processed2DPlotData pdata, IPlotArea layer, double logicalShiftX, double logicalShiftY)
        {
            var result = new PointF[pdata.PlotPointsInAbsoluteLayerCoordinates.Length];

            foreach (PlotRange r in pdata.RangeList)
            {
                int lower  = r.LowerBound;
                int upper  = r.UpperBound;
                int offset = r.OffsetToOriginal;
                for (int j = lower; j < upper; ++j)
                {
                    int       originalRow = j + offset;
                    Logical3D logicalMean = layer.GetLogical3D(pdata, originalRow);
                    logicalMean.RX += logicalShiftX;
                    logicalMean.RY += logicalShiftY;
                    layer.CoordinateSystem.LogicalToLayerCoordinates(logicalMean, out var x, out var y);
                    result[j] = new PointF((float)x, (float)y);
                }
            }
            return(result);
        }
Exemple #3
0
		/// <inheritdoc/>
		public override void FillOneRange(
		GraphicsPath gp,
			Processed2DPlotData pdata,
			IPlotRange range,
			IPlotArea layer,
			CSPlaneID fillDirection,
			bool ignoreMissingDataPoints,
			bool connectCircular,
			PointF[] allLinePointsShiftedAlready,
			double logicalShiftX,
			double logicalShiftY
		)
		{
			if (range.Length < 2)
				return;

			int lastIdx;
			PointF[] linePoints = Segment2Connection_GetSubPoints(allLinePointsShiftedAlready, range, layer, connectCircular, out lastIdx);


			if (connectCircular)
			{
				gp.AddLines(linePoints);
				gp.CloseFigure();
			}
			else
			{
				int offs = range.LowerBound;
				for (int i = 0; i < linePoints.Length - 1; i += 2)
				{
					Logical3D r0 = layer.GetLogical3D(pdata, range.GetOriginalRowIndexFromPlotPointIndex(range.LowerBound + i));
					r0.RX += logicalShiftX;
					r0.RY += logicalShiftY;

					layer.CoordinateSystem.GetIsolineFromPlaneToPoint(gp, fillDirection, r0);
					gp.AddLine(linePoints[i].X, linePoints[i].Y, linePoints[i + 1].X, linePoints[i + 1].Y);
					Logical3D r1 = layer.GetLogical3D(pdata, range.GetOriginalRowIndexFromPlotPointIndex(range.LowerBound + i + 1));
					r1.RX += logicalShiftX;
					r1.RY += logicalShiftY;

					layer.CoordinateSystem.GetIsolineFromPointToPlane(gp, r1, fillDirection);
					layer.CoordinateSystem.GetIsolineOnPlane(gp, fillDirection, r1, r0);
					gp.StartFigure();
				}

				gp.CloseFigure();
			}
		}
Exemple #4
0
		/// <summary>
		/// Template to get a fill path.
		/// </summary>
		/// <param name="gp">Graphics path to fill with data.</param>
		/// <param name="pdata">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="fillDirection">Designates a bound to fill to.</param>
		/// <param name="linePoints">The points that mark the line.</param>
		/// <param name="connectCircular">If true, a circular connection is drawn.</param>
		/// <param name="allLinePointsShiftedAlready">The plot positions, already shifted when a logical shift needed to be applied. Don't use the Range property of the pdata, since it is overriden by the next argument.</param>
		/// <param name="logicalShiftX">The logical shift in x-direction.</param>
		/// <param name="logicalShiftY">The logical shift in x-direction.</param>
		public virtual void FillOneRange(
		GraphicsPath gp,
			Processed2DPlotData pdata,
			IPlotRange range,
			IPlotArea layer,
			CSPlaneID fillDirection,
			PointF[] linePoints,
			bool connectCircular,
			PointF[] allLinePointsShiftedAlready,
			double logicalShiftX,
			double logicalShiftY
		)
		{
			if (connectCircular)
			{
				gp.AddLines(linePoints);
				gp.CloseFigure();
			}
			else
			{
				Logical3D r0 = layer.GetLogical3D(pdata, range.OriginalFirstPoint);
				r0.RX += logicalShiftX;
				r0.RY += logicalShiftY;

				layer.CoordinateSystem.GetIsolineFromPlaneToPoint(gp, fillDirection, r0);
				gp.AddLines(linePoints);

				Logical3D r1 = layer.GetLogical3D(pdata, range.OriginalLastPoint);
				r1.RX += logicalShiftX;
				r1.RY += logicalShiftY;

				layer.CoordinateSystem.GetIsolineFromPointToPlane(gp, r1, fillDirection);
				layer.CoordinateSystem.GetIsolineOnPlane(gp, fillDirection, r1, r0);
				gp.CloseFigure();
			}
		}
Exemple #5
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 < 2)
				return;

			int lastIdx;
			int numberOfPointsPerOriginalPoint;
			PointF[] linepts = GetStepPolylinePoints(allLinePoints, range, layer, connectCircular, out numberOfPointsPerOriginalPoint, out lastIdx);
			FillOneRange(gp, pdata, range, layer, fillDirection, linepts, connectCircular, allLinePoints, logicalShiftX, logicalShiftY);
		}
Exemple #6
0
		/// <summary>
		/// Shift the plot points provided in <paramref name="pdata"/> with a logical shift in x- and/or y- direction.
		/// </summary>
		/// <param name="pdata">The plot point position data.</param>
		/// <param name="layer">The plot layer for which the data are intended.</param>
		/// <param name="logicalShiftX">The logical shift in x-direction.</param>
		/// <param name="logicalShiftY">The logical shift in y-direction.</param>
		/// <returns>Array of plot point positions, but now shifted by logical values in x-direction (<paramref name="logicalShiftX"/>) and y-direction (<paramref name="logicalShiftY"/>).</returns>
		public static PointF[] GetPlotPointsInAbsoluteLayerCoordinatesWithShift(Processed2DPlotData pdata, IPlotArea layer, double logicalShiftX, double logicalShiftY)
		{
			var result = new PointF[pdata.PlotPointsInAbsoluteLayerCoordinates.Length];
			foreach (PlotRange r in pdata.RangeList)
			{
				int lower = r.LowerBound;
				int upper = r.UpperBound;
				int offset = r.OffsetToOriginal;
				for (int j = lower; j < upper; ++j)
				{
					int originalRow = j + offset;
					Logical3D logicalMean = layer.GetLogical3D(pdata, originalRow);
					logicalMean.RX += logicalShiftX;
					logicalMean.RY += logicalShiftY;

					double x, y;
					layer.CoordinateSystem.LogicalToLayerCoordinates(logicalMean, out x, out y);
					result[j] = new PointF((float)x, (float)y);
				}
			}
			return result;
		}
Exemple #7
0
		public void Paint(System.Drawing.Graphics g, IPlotArea layer, Altaxo.Graph.Gdi.Plot.Data.Processed2DPlotData pdata, Processed2DPlotData prevItemData, Processed2DPlotData nextItemData)
		{
			// adjust the skip frequency if it was not set appropriate
			if (_skipFrequency <= 0)
				_skipFrequency = 1;

			if (_independentOnShiftingGroupStyles)
			{
				_cachedLogicalShiftX = _cachedLogicalShiftY = 0;
			}


			PlotRangeList rangeList = pdata.RangeList;



			if (this._ignoreMissingDataPoints)
			{
				// in case we ignore the missing points, all ranges can be plotted
				// as one range, i.e. continuously
				// for this, we create the totalRange, which contains all ranges
				var totalRange = new PlotRangeCompound(rangeList);
				this.PaintOneRange(AxisNumber, g, layer, totalRange, pdata);
			}
			else // we not ignore missing points, so plot all ranges separately
			{
				for (int i = 0; i < rangeList.Count; i++)
				{
					this.PaintOneRange(AxisNumber, g, layer, rangeList[i], pdata);
				}
			}
		}
Exemple #8
0
		protected void PaintOneRange(int axisNumber, Graphics g, IPlotArea layer, IPlotRange range, Processed2DPlotData pdata)
		{
			const double logicalClampMinimum = -10;
			const double logicalClampMaximum = 11;

			_skipFrequency = Math.Max(1, _skipFrequency);

			// Plot error bars for the dependent variable (y)
			var ptArray = pdata.PlotPointsInAbsoluteLayerCoordinates;
			var posErrCol = PositiveErrorColumn;
			var negErrCol = NegativeErrorColumn;

			if (null != posErrCol && !typeof(double).IsAssignableFrom(posErrCol.ItemType))
				posErrCol = null; // TODO make this an runtime paint error to be reported

			if (null != negErrCol && !typeof(double).IsAssignableFrom(negErrCol.ItemType))
				negErrCol = null; // TODO make this an runtime paint error to be reported

			if (posErrCol == null && negErrCol == null)
				return; // nothing to do if both error columns are null

			var strokePen = _pen.Clone();

			System.Drawing.Drawing2D.GraphicsPath errorBarPath = new System.Drawing.Drawing2D.GraphicsPath();

			Region oldClippingRegion = g.Clip;
			Region newClip = (Region)oldClippingRegion.Clone();


			int lower = range.LowerBound;
			int upper = range.UpperBound;

			for (int j = lower; j < upper; j += _skipFrequency)
			{
				int originalRowIndex = range.GetOriginalRowIndexFromPlotPointIndex(j);
				double symbolSize = null == _cachedSymbolSizeForIndexFunction ? _symbolSize : _cachedSymbolSizeForIndexFunction(originalRowIndex);
				strokePen.Width = (_lineWidth1Offset + _lineWidth1Factor * symbolSize);

				if (null != _cachedColorForIndexFunction)
					strokePen.Color = GdiColorHelper.ToNamedColor(_cachedColorForIndexFunction(originalRowIndex), "VariableColor");
				if (null != strokePen.EndCap)
					strokePen.EndCap = strokePen.EndCap.WithMinimumAbsoluteAndRelativeSize(symbolSize * _endCapSizeFactor + _endCapSizeOffset, 1 + 1E-6);

				AltaxoVariant vMeanPhysical = pdata.GetPhysical(axisNumber, originalRowIndex);
				Logical3D logicalMean = layer.GetLogical3D(pdata, originalRowIndex);
				logicalMean.RX += _cachedLogicalShiftX;
				logicalMean.RY += _cachedLogicalShiftY;

				if (!Calc.RMath.IsInIntervalCC(logicalMean.RX, logicalClampMinimum, logicalClampMaximum))
					continue;
				if (!Calc.RMath.IsInIntervalCC(logicalMean.RY, logicalClampMinimum, logicalClampMaximum))
					continue;

				var vMeanLogical = logicalMean.GetR(axisNumber);

				Logical3D logicalPos = logicalMean;
				Logical3D logicalNeg = logicalMean;
				bool logicalPosValid = false;
				bool logicalNegValid = false;

				switch (_meaningOfValues)
				{
					case ValueInterpretation.AbsoluteError:
						{
							if (posErrCol != null)
							{
								var vPosLogical = layer.Scales[axisNumber].PhysicalVariantToNormal(vMeanPhysical + Math.Abs(posErrCol[originalRowIndex]));
								vPosLogical = Calc.RMath.ClampToInterval(vPosLogical, logicalClampMinimum, logicalClampMaximum);
								logicalPos.SetR(axisNumber, vPosLogical);
								logicalPosValid = !logicalPos.IsNaN && vPosLogical != vMeanLogical;
							}

							if (negErrCol != null)
							{
								var vNegLogical = layer.Scales[axisNumber].PhysicalVariantToNormal(vMeanPhysical - Math.Abs(negErrCol[originalRowIndex]));
								vNegLogical = Calc.RMath.ClampToInterval(vNegLogical, logicalClampMinimum, logicalClampMaximum);
								logicalNeg.SetR(axisNumber, vNegLogical);
								logicalNegValid = !logicalNeg.IsNaN && vNegLogical != vMeanLogical;
							}
						}
						break;

					case ValueInterpretation.RelativeError:
						{
							if (posErrCol != null)
							{
								var vPosLogical = layer.Scales[axisNumber].PhysicalVariantToNormal(vMeanPhysical * (1 + Math.Abs(posErrCol[originalRowIndex])));
								vPosLogical = Calc.RMath.ClampToInterval(vPosLogical, logicalClampMinimum, logicalClampMaximum);
								logicalPos.SetR(axisNumber, vPosLogical);
								logicalPosValid = !logicalPos.IsNaN && vPosLogical != vMeanLogical;
							}

							if (negErrCol != null)
							{
								var vNegLogical = layer.Scales[axisNumber].PhysicalVariantToNormal(vMeanPhysical * (1 - Math.Abs(negErrCol[originalRowIndex])));
								vNegLogical = Calc.RMath.ClampToInterval(vNegLogical, logicalClampMinimum, logicalClampMaximum);
								logicalNeg.SetR(axisNumber, vNegLogical);
								logicalNegValid = !logicalNeg.IsNaN && vNegLogical != vMeanLogical;
							}
						}
						break;

					case ValueInterpretation.AbsoluteValue:
						{
							if (posErrCol != null)
							{
								var vPosLogical = layer.Scales[axisNumber].PhysicalVariantToNormal(posErrCol[originalRowIndex]);
								vPosLogical = Calc.RMath.ClampToInterval(vPosLogical, logicalClampMinimum, logicalClampMaximum);
								logicalPos.SetR(axisNumber, vPosLogical);
								logicalPosValid = !logicalPos.IsNaN && vPosLogical != vMeanLogical;
							}

							if (negErrCol != null)
							{
								var vNegLogical = layer.Scales[axisNumber].PhysicalVariantToNormal(negErrCol[originalRowIndex]);
								vNegLogical = Calc.RMath.ClampToInterval(vNegLogical, logicalClampMinimum, logicalClampMaximum);
								logicalNeg.SetR(axisNumber, vNegLogical);
								logicalNegValid = !logicalNeg.IsNaN && vNegLogical != vMeanLogical;
							}

							if (object.ReferenceEquals(negErrCol, posErrCol))
							{
								logicalNegValid = false; // then we need only to plot the positive column, since both colums are identical
							}
						}
						break;
				} // end switch

				if (!(logicalPosValid || logicalNegValid))
					continue; // nothing to do for this point if both pos and neg logical point are invalid.

				if (logicalNegValid)
				{
					errorBarPath.Reset();
					layer.CoordinateSystem.GetIsoline(errorBarPath, logicalMean, logicalNeg);
					PointF[] shortenedPathPoints = null;
					bool shortenedPathPointsCalculated = false;
					if (_useSymbolGap)
					{
						double gap = _symbolGapOffset + _symbolGapFactor * symbolSize;
						if (gap > 0)
						{
							errorBarPath.Flatten();
							var pathPoints = errorBarPath.PathPoints;
							shortenedPathPoints = GdiExtensionMethods.ShortenedBy(pathPoints, RADouble.NewAbs(gap / 2), RADouble.NewAbs(0));
							shortenedPathPointsCalculated = true;
							if (null == shortenedPathPoints && _forceVisibilityOfEndCap && !(strokePen.EndCap is Altaxo.Graph.Gdi.LineCaps.FlatCap))
							{
								var totalLineLength = GdiExtensionMethods.TotalLineLength(pathPoints);
								var shortTheLineBy = Math.Max(0, totalLineLength - 0.125 * strokePen.Width);
								shortenedPathPoints = GdiExtensionMethods.ShortenedBy(pathPoints, RADouble.NewAbs(shortTheLineBy), RADouble.NewAbs(0));
							}
						}
					}

					if (shortenedPathPointsCalculated)
					{
						if (null != shortenedPathPoints)
						{
							g.DrawLines(strokePen, shortenedPathPoints);
						}
					}
					else
					{
						g.DrawPath(strokePen, errorBarPath);
					}
				}

				if (logicalPosValid)
				{
					errorBarPath.Reset();
					layer.CoordinateSystem.GetIsoline(errorBarPath, logicalMean, logicalPos);
					PointF[] shortenedPathPoints = null;
					bool shortenedPathPointsCalculated = false;


					if (_useSymbolGap)
					{
						double gap = _symbolGapOffset + _symbolGapFactor * symbolSize;
						if (gap > 0)
						{
							errorBarPath.Flatten();
							var pathPoints = errorBarPath.PathPoints;
							shortenedPathPoints = GdiExtensionMethods.ShortenedBy(pathPoints, RADouble.NewAbs(gap / 2), RADouble.NewAbs(0));
							shortenedPathPointsCalculated = true;
							if (null == shortenedPathPoints && _forceVisibilityOfEndCap && !(strokePen.EndCap is Altaxo.Graph.Gdi.LineCaps.FlatCap))
							{
								var totalLineLength = GdiExtensionMethods.TotalLineLength(pathPoints);
								var shortTheLineBy = Math.Max(0, totalLineLength - 0.125 * strokePen.Width);
								shortenedPathPoints = GdiExtensionMethods.ShortenedBy(pathPoints, RADouble.NewAbs(shortTheLineBy), RADouble.NewAbs(0));
							}

						}
					}

					if (shortenedPathPointsCalculated)
					{
						if (null != shortenedPathPoints)
						{
							g.DrawLines(strokePen, shortenedPathPoints);
						}
					}
					else
					{
						g.DrawPath(strokePen, errorBarPath);
					}
				}
			}

			g.Clip = oldClippingRegion;

		}
Exemple #9
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
		)
		{
			PointF[] circularLinePoints = new PointF[range.Length + (connectCircular ? 1 : 0)];
			Array.Copy(allLinePoints, range.LowerBound, circularLinePoints, 0, range.Length); // Extract
			if (connectCircular)
				circularLinePoints[circularLinePoints.Length - 1] = circularLinePoints[0];

			if (connectCircular)
			{
				gp.AddLines(circularLinePoints);
				gp.CloseFigure();
			}
			else // not circular
			{
				Logical3D r0 = layer.GetLogical3D(pdata, range.OriginalFirstPoint);
				r0.RX += logicalShiftX;
				r0.RY += logicalShiftY;

				layer.CoordinateSystem.GetIsolineFromPlaneToPoint(gp, fillDirection, r0);
				gp.AddLines(circularLinePoints);
				Logical3D r1 = layer.GetLogical3D(pdata, connectCircular ? range.OriginalFirstPoint : range.OriginalLastPoint);
				r1.RX += logicalShiftX;
				r1.RY += logicalShiftY;

				layer.CoordinateSystem.GetIsolineFromPointToPlane(gp, r1, fillDirection);
				layer.CoordinateSystem.GetIsolineOnPlane(gp, fillDirection, r1, r0);
				gp.CloseFigure();
			}
		}
Exemple #10
0
		/// <summary>
		/// Template to get a fill path.
		/// </summary>
		/// <param name="gp">Graphics path to fill with data.</param>
		/// <param name="pdata">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="fillDirection">Designates a bound to fill to.</param>
		/// <param name="linePoints">The points that mark the line.</param>
		/// <param name="connectCircular">If true, a circular connection is drawn.</param>
		private void FillOneRange_PreprocessedPoints(
		GraphicsPath gp,
			Processed2DPlotData pdata,
			IPlotRange range,
			IPlotArea layer,
			CSPlaneID fillDirection,
			PointF[] linePoints,
			bool connectCircular,
			double logicalShiftX,
			double logicalShiftY
		)
		{
			if (connectCircular)
			{
				gp.AddBeziers(linePoints);
				gp.CloseFigure();

			}
			else
			{
				Logical3D r0 = layer.GetLogical3D(pdata, range.OriginalFirstPoint);
				r0.RX += logicalShiftX;
				r0.RY += logicalShiftY;
				layer.CoordinateSystem.GetIsolineFromPlaneToPoint(gp, fillDirection, r0);
				gp.AddBeziers(linePoints);

				Logical3D r1 = layer.GetLogical3D(pdata, range.GetOriginalRowIndexFromPlotPointIndex(range.LowerBound + linePoints.Length - 1));
				r1.RX += logicalShiftX;
				r1.RY += logicalShiftY;

				layer.CoordinateSystem.GetIsolineFromPointToPlane(gp, r1, fillDirection);
				layer.CoordinateSystem.GetIsolineOnPlane(gp, fillDirection, r1, r0);

				gp.CloseFigure();
			}

		}
Exemple #11
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);
			}
		}