private static void OnPieCoefficientPropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) { var series = d as PieSeries; series.InternalPieCoefficient = ChartMath.MinMax((double)e.NewValue, 0, 1); series.UpdateArea(); }
/// <summary> /// Updates the series when doughnut coefficient changed. /// </summary> /// <param name="d">The Dependency Object</param> /// <param name="e">The Event Arguments</param> private static void OnDoughnutCoefficientChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) { var doughnutSeries3D = d as DoughnutSeries3D; doughnutSeries3D.InternlDoughnutCoefficient = ChartMath.MinMax((double)e.NewValue, 0, 1); doughnutSeries3D.UpdateArea(); }
protected internal DoubleRange GetYRange(double x1, double y1, double x2, double y2, double x3, double y3, double x4, double y4) { DoubleRange range = DoubleRange.Union(new double[] { y1, y2, y3, y4 }); double cy = 3 * (y2 - y1); double by = 3 * (y3 - y3) - cy; double ay = y4 - y1 - by - cy; double r1, r2; if (ChartMath.SolveQuadraticEquation(3 * ay, 2 * by, cy, out r1, out r2)) { if (r1 >= 0 && r1 <= 1) { double y = ay * r1 * r1 * r1 + by * r1 * r1 + cy * r1 + y1; range = DoubleRange.Union(range, y); } if (r2 >= 0 && r2 <= 1) { double y = ay * r2 * r2 * r2 + by * r2 * r2 + cy * r2 + y1; range = DoubleRange.Union(range, y); } } return(range); }
private static void OnDoughnutSizeChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) { var series = d as DoughnutSeries; series.InternalDoughnutSize = ChartMath.MinMax((double)e.NewValue, 0, 1); series.UpdateArea(); }
/// <summary> /// Gets the normal. /// </summary> /// <param name="transform">The transform.</param> /// <returns>Returns Vector3D instance.</returns> internal virtual Vector3D GetNormal(Matrix3D transform) { Vector3D norm; if (VectorPoints != null) { norm = ChartMath.GetNormal( transform * VectorPoints[0], transform * VectorPoints[1], transform * VectorPoints[2]); for (var i = 3; (i < VectorPoints.Length) && !norm.IsValid; i++) { var v1 = transform * VectorPoints[i]; var v2 = transform * VectorPoints[0]; var v3 = transform * VectorPoints[i / 2]; norm = ChartMath.GetNormal(v1, v2, v3); } } else { norm = transform & normal; norm.Normalize(); } return(norm); }
public override void SetData(Point hlpoint, Point hrpoint, Point vtpoint, Point vbpoint) { _horLeftpoint = new ChartPoint(hlpoint.X, hlpoint.Y); _horRightpoint = new ChartPoint(hrpoint.X, hrpoint.Y); _verToppoint = new ChartPoint(vtpoint.X, vtpoint.Y); _verBottompoint = new ChartPoint(vbpoint.X, vbpoint.Y); switch (_parentSeries.Mode) { case ErrorBarMode.Horizontal: XRange = new DoubleRange(ChartMath.Min(hlpoint.X, hrpoint.X), ChartMath.Max(hlpoint.X, hrpoint.X)); YRange = DoubleRange.Empty; break; case ErrorBarMode.Vertical: YRange = new DoubleRange(vbpoint.Y, vtpoint.Y); XRange = DoubleRange.Empty; break; default: XRange = new DoubleRange(ChartMath.Min(hlpoint.X, hrpoint.X), ChartMath.Max(hlpoint.X, hrpoint.X)); YRange = new DoubleRange(vbpoint.Y, vtpoint.Y); break; } }
/// <summary> /// Updates the series when the circle coefficient changes. /// </summary> /// <param name="sender">The Sender</param> /// <param name="e">The Dependency Object</param> private static void OnCircleCoefficientChanged(DependencyObject sender, DependencyPropertyChangedEventArgs e) { var circularSeriesBase3D = sender as CircularSeriesBase3D; if (circularSeriesBase3D != null) { circularSeriesBase3D.InternalCircleCoefficient = ChartMath.MinMax((double)e.NewValue, 0, 1); circularSeriesBase3D.UpdateArea(); } }
private static void OnDoughnutHoleSizeChanged(DependencyObject sender, DependencyPropertyChangedEventArgs e) { var chartArea = sender as SfChart; if (chartArea != null) { chartArea.InternalDoughnutHoleSize = ChartMath.MinMax((double)e.NewValue, 0, 1); chartArea.ScheduleUpdate(); } }
/// <summary> /// To get the SurfaceHeight for PyramidSeries. /// </summary> public static double GetSurfaceHeight(double y, double surface) { double r1, r2; if (ChartMath.SolveQuadraticEquation(1, 2 * y, -surface, out r1, out r2)) { return(Math.Max(r1, r2)); } return(double.NaN); }
private Point[] GetHitRectPoints(Point point1, Point point2) { var extendedPoints = new Point[4]; extendedPoints[0] = ChartMath.CalculatePerpendicularDistantPoint(point1, point2, -GrabExtent); extendedPoints[1] = ChartMath.CalculatePerpendicularDistantPoint(point2, point1, GrabExtent); extendedPoints[2] = ChartMath.CalculatePerpendicularDistantPoint(point2, point1, -GrabExtent); extendedPoints[3] = ChartMath.CalculatePerpendicularDistantPoint(point1, point2, GrabExtent); return(extendedPoints); }
internal virtual bool IsPointInsideRectangle(Point point) { if (hitRectPoints != null) { return(ChartMath.IsPointInsideRectangle(point, hitRectPoints)); } else { return(false); } }
private void DrawMultipleDoughnut(IChartTransformer transformer) { if (IsSegmentVisible) { var segmentStartAngle = ActualStartAngle; var segmentEndAngle = ActualEndAngle; var center = parentSeries.Center; double actualRadius = parentSeries.InternalDoughnutSize * Math.Min(transformer.Viewport.Width, transformer.Viewport.Height) / 2; double remainingWidth = actualRadius - (actualRadius * Series.ActualArea.InternalDoughnutHoleSize); double equalParts = (remainingWidth / doughnutSegmentsCount) * parentSeries.InternalDoughnutCoefficient; double radius = actualRadius - (equalParts * (doughnutSegmentsCount - (DoughnutSegmentIndex + 1))); parentSeries.Radius = actualRadius - equalParts; double innerRadius = radius - equalParts; double outerRadius = radius - equalParts * parentSeries.SegmentSpacing; innerRadius = ChartMath.MaxZero(innerRadius); if (parentSeries.Segments.IndexOf(this) == 0) { parentSeries.InnerRadius = innerRadius; } this.pathGeometry = GetDoughnutGeometry(center, outerRadius, innerRadius, segmentStartAngle, segmentEndAngle, false); this.segmentPath.Data = pathGeometry; //Rendering the back segments. var seriesStartAngle = parentSeries.DegreeToRadianConverter(parentSeries.StartAngle); var seriesEndAngle = parentSeries.DegreeToRadianConverter(parentSeries.EndAngle); var totalArcLength = Math.PI * 2; var arcLength = seriesEndAngle - seriesStartAngle; if (Math.Abs(Math.Round(arcLength, 2)) > totalArcLength) { arcLength = arcLength % totalArcLength; } seriesEndAngle = arcLength + seriesStartAngle; this.circularPathGeometry = GetDoughnutGeometry(center, outerRadius, innerRadius, seriesStartAngle, seriesEndAngle, true); this.CircularDoughnutPath.Data = circularPathGeometry; } else { this.pathGeometry = null; this.segmentPath.Data = null; this.circularPathGeometry = null; this.CircularDoughnutPath.Data = null; } }
public override void SetData(ChartPoint hipoint, ChartPoint lopoint, ChartPoint sopoint, ChartPoint eopoint, ChartPoint scpoint, ChartPoint ecpoint, bool isbull) { this.hipoint = hipoint; this.lowpoint = lopoint; this.sopoint = sopoint; this.eopoint = eopoint; this.scpoint = scpoint; this.ecpoint = ecpoint; this.IsBull = isbull; var alignedValues = AlignHiLoSegment(sopoint.Y, scpoint.Y, hipoint.Y, lopoint.Y); this.hipoint.Y = alignedValues[0]; this.lowpoint.Y = alignedValues[1]; XRange = new DoubleRange(ChartMath.Min(scpoint.X, ecpoint.X, sopoint.X, eopoint.X), ChartMath.Max(scpoint.X, ecpoint.X, sopoint.X, eopoint.X)); YRange = new DoubleRange(lopoint.Y, hipoint.Y); }
/// <summary> /// Updates the <see cref="ZoomOut"/> icon. /// </summary> /// <param name="e">The Event Arguments</param> protected override void OnPointerPressed(PointerRoutedEventArgs e) { if (this.Source.ChartArea.AreaType != ChartAreaType.CartesianAxes) { return; } bool canZoom = false; int updatedAxes = 0; foreach (ChartAxisBase2D axis in this.Source.ChartArea.Axes) { if (axis.RegisteredSeries.Count > 0 && (axis.RegisteredSeries[0] as CartesianSeries) != null && (axis.RegisteredSeries[0] as CartesianSeries).IsActualTransposed) { if ((axis.Orientation == Orientation.Horizontal && (Source.ZoomMode == ZoomMode.Y || Source.ZoomMode == ZoomMode.XY)) || (axis.Orientation == Orientation.Vertical && (Source.ZoomMode == ZoomMode.X || Source.ZoomMode == ZoomMode.XY))) { canZoom = true; } } else { if ((axis.Orientation == Orientation.Vertical && (Source.ZoomMode == ZoomMode.Y || Source.ZoomMode == ZoomMode.XY)) || (axis.Orientation == Orientation.Horizontal && (Source.ZoomMode == ZoomMode.X || Source.ZoomMode == ZoomMode.XY))) { canZoom = true; } } if (canZoom) { var origin = 0.5; double currentScale = Math.Max(1 / ChartMath.MinMax(axis.ZoomFactor, 0, 1), 1); double cumulativeScale = Math.Max(currentScale + (0.25 * -1), 1); Source.Zoom(cumulativeScale, origin > 1d ? 1d : origin < 0d ? 0d : origin, axis); } canZoom = false; if (axis.ZoomFactor == 1 || axis.ZoomPosition == 0) { updatedAxes++; } } e.Handled = true; }
/// <summary> /// Calculates actual range /// </summary> /// <param name="axis">The axis.</param> /// <param name="range">The range.</param> /// <param name="logarithmicBase">The logarithmic base.</param> /// <returns></returns> internal static DoubleRange CalculateActualRange(ChartAxis axis, DoubleRange range, double logarithmicBase) { if (range.IsEmpty) { return(range); } double logStart = Math.Log(range.Start, logarithmicBase); logStart = double.IsInfinity(logStart) || double.IsNaN(logStart) ? range.Start : logStart; double logEnd = Math.Log(range.End, logarithmicBase); logEnd = double.IsInfinity(logEnd) || double.IsNaN(logEnd) ? logarithmicBase : logEnd; double mulS = ChartMath.Round(logStart, 1, false); double mulE = ChartMath.Round(logEnd, 1, true); range = new DoubleRange(mulS, mulE); return(range); }
/// <summary> /// Creates the point. /// </summary> protected override void CreatePoints() { if (Area.RootPanelDesiredSize != null) { this.actualWidth = Area.RootPanelDesiredSize.Value.Width; this.actualHeight = Area.RootPanelDesiredSize.Value.Height; } var doughnutIndex = GetPieSeriesIndex(); var doughnutCount = GetCircularSeriesCount(); double actualRadius = InternalCircleCoefficient * Math.Min(actualWidth, actualHeight) / 2; double remainingWidth = actualRadius - (actualRadius * Area.InternalDoughnutHoleSize); double equalParts = remainingWidth / doughnutCount; this.Radius = actualRadius - (equalParts * (doughnutCount - (doughnutIndex + 1))); this.InnerRadius = this.Radius - (equalParts * this.InternlDoughnutCoefficient); this.InnerRadius = ChartMath.MaxZero(this.InnerRadius); base.CreatePoints(); }
private void DrawSingleDoughnut(IChartTransformer transformer) { var segmentStartAngle = ActualStartAngle; var segmentEndAngle = ActualEndAngle; Point center; if (doughnutSeriesCount > 1) { center = new Point(0.5 * transformer.Viewport.Width, 0.5 * transformer.Viewport.Height); } else { center = parentSeries.Center; } CalculateGapRatioAngle(ref segmentEndAngle, ref segmentStartAngle); double actualRadius = parentSeries.InternalDoughnutSize * Math.Min(transformer.Viewport.Width, transformer.Viewport.Height) / 2; double remainingWidth = actualRadius - (actualRadius * Series.ActualArea.InternalDoughnutHoleSize); double equalParts = remainingWidth / doughnutSeriesCount; double radius = parentSeries.Radius = actualRadius - (equalParts * (doughnutSeriesCount - (doughnutSeriesIndex + 1))); double innerRadius = radius - (equalParts * parentSeries.InternalDoughnutCoefficient); innerRadius = ChartMath.MaxZero(innerRadius); if (parentSeries.Segments.IndexOf(this) == 0) { parentSeries.InnerRadius = innerRadius; } this.pathGeometry = GetDoughnutGeometry(center, radius, innerRadius, segmentStartAngle, segmentEndAngle, false); this.segmentPath.Data = pathGeometry; this.circularPathGeometry = null; this.CircularDoughnutPath.Data = null; }
private void TransformToScreenCoVertical() { Points = new PointCollection(); double prevXValue = 0; double prevYValue = 0; int i = 0; double yCoefficient = 0; var numericalAxis = fastSeries.ActualYAxis as NumericalAxis; bool isScaleBreak = numericalAxis != null && numericalAxis.AxisRanges != null && numericalAxis.AxisRanges.Count > 0; xValues = (Series.ActualXValues is List <double> && !Series.IsIndexed) ? Series.ActualXValues as List <double> : Series.GetXValues(); var isGrouping = (fastSeries.ActualXAxis is CategoryAxis) ? (fastSeries.ActualXAxis as CategoryAxis).IsIndexed : true; int startIndex = 0; prevXValue = fastSeries.IsIndexed ? 1 : xChartVals[0]; prevYValue = yChartVals[0]; int cnt = xChartVals.Count - 1; if (fastSeries.isLinearData) { for (i = 1; i < cnt; i++) { double xVal = xChartVals[i]; double yVal = yChartVals[i]; if ((xVal <= xEnd) && (xVal >= xStart)) { if (Math.Abs(prevXValue - xVal) >= xTolerance || Math.Abs(prevYValue - yVal) >= yTolerance) { yCoefficient = (isScaleBreak ? numericalAxis.CalculateValueToCoefficient(yVal) : 1 - ((yEnd - yVal) / yDelta)); Points.Add(new Point((yOffset + ySize * yCoefficient), (xOffset + xSize * ((xEnd - xVal) / xDelta)))); prevXValue = xVal; prevYValue = yVal; } } else if (xVal < xStart) { if (x_isInversed) { yCoefficient = (isScaleBreak ? numericalAxis.CalculateValueToCoefficient(yVal) : 1 - ((yEnd - yVal) / yDelta)); Points.Add(new Point((yOffset + ySize * yCoefficient), (xOffset + xSize * ((xEnd - xVal) / xDelta)))); } else { startIndex = i; } } else if (xVal > xEnd) { double yValue = ChartMath.GetInterpolarationPoint(xChartVals[i - 1], xChartVals[i], yChartVals[i - 1], yChartVals[i], xEnd); yCoefficient = (isScaleBreak ? numericalAxis.CalculateValueToCoefficient(yValue) : 1 - ((yEnd - yValue) / yDelta)); Points.Add(new Point((yOffset + ySize * yCoefficient), (xOffset))); break; } } } else { for (i = 1; i < cnt; i++) { double xVal = xChartVals[i]; double yVal = yChartVals[i]; if (Math.Abs(prevXValue - xVal) >= xTolerance || Math.Abs(prevYValue - yVal) >= yTolerance) { yCoefficient = (isScaleBreak ? numericalAxis.CalculateValueToCoefficient(yVal) : 1 - ((yEnd - yVal) / yDelta)); Points.Add(new Point((yOffset + ySize * yCoefficient), (xOffset + xSize * ((xEnd - xVal) / xDelta)))); prevXValue = xVal; prevYValue = yVal; } } } if (startIndex > 0) { double yValue = ChartMath.GetInterpolarationPoint(xChartVals[startIndex], xChartVals[startIndex + 1], yChartVals[startIndex], yChartVals[startIndex + 1], xStart); yCoefficient = (isScaleBreak ? numericalAxis.CalculateValueToCoefficient(yValue) : 1 - ((yEnd - yValue) / yDelta)); Points.Insert(0, new Point((yOffset + ySize * yCoefficient), (xOffset + xSize * ((xEnd - xStart) / xDelta)))); } else { yCoefficient = (isScaleBreak ? numericalAxis.CalculateValueToCoefficient(yChartVals[startIndex]) : 1 - ((yEnd - yChartVals[startIndex]) / yDelta)); Points.Insert(0, new Point((yOffset + ySize * yCoefficient), (xOffset + xSize * ((xEnd - xChartVals[startIndex]) / xDelta)))); } if (i == cnt) { yCoefficient = (isScaleBreak ? numericalAxis.CalculateValueToCoefficient(yChartVals[cnt]) : 1 - ((yEnd - yChartVals[cnt]) / yDelta)); Points.Add(new Point((yOffset + ySize * yCoefficient), (xOffset + xSize * ((xEnd - xChartVals[cnt]) / xDelta)))); } }
/// <summary> /// Updates the segments based on its data point value. This method is not /// intended to be called explicitly outside the Chart but it can be overriden by /// any derived class. /// </summary> /// <param name="transformer">Represents the view port of chart control.(refer <see cref="IChartTransformer"/>)</param> public override void Update(IChartTransformer transformer) { double radius = Radius; double actualRadius = Math.Min(transformer.Viewport.Width, transformer.Viewport.Height) / 2; if (Series is DoughnutSeries3D) { var hostSeries = Series as DoughnutSeries3D; double doughnutSeriesCount = hostSeries.GetCircularSeriesCount(); actualRadius *= hostSeries.InternalCircleCoefficient; Point center = hostSeries.Center; if (doughnutSeriesCount > 1) { center = new Point(transformer.Viewport.Width / 2, transformer.Viewport.Height / 2); } double remainingWidth = actualRadius - (actualRadius * Series.ActualArea.InternalDoughnutHoleSize); double equalParts = remainingWidth / doughnutSeriesCount; double innerRadius = radius - (equalParts * hostSeries.InternlDoughnutCoefficient); innerRadius = ChartMath.MaxZero(innerRadius); if (hostSeries.ExplodeIndex == hostSeries.Segments.Count - 1 || hostSeries.ExplodeAll) { var rect = new Rect(0, 0, transformer.Viewport.Width, transformer.Viewport.Height); center = hostSeries.GetActualCenter(new Point(rect.X + rect.Width / 2, rect.Y + rect.Height / 2), Radius); } if (hostSeries != null && hostSeries.LabelPosition == CircularSeriesLabelPosition.Inside) { double difference = (radius - innerRadius) / 2; radius -= difference; } this.X = center.X + radius * Math.Cos(Angle); this.Y = center.Y + radius * Math.Sin(Angle); } else if (Series is PieSeries3D) { var hostSeries = Series as PieSeries3D; Point center = hostSeries.Center; double pieSeriesCount = hostSeries.GetCircularSeriesCount(); double equalParts = actualRadius / pieSeriesCount; double innerRadius = equalParts * pieIndex; if (hostSeries.ExplodeIndex == hostSeries.Segments.Count - 1 || hostSeries.ExplodeAll) { var rect = new Rect(0, 0, transformer.Viewport.Width, transformer.Viewport.Height); center = hostSeries.GetActualCenter(new Point(rect.X + rect.Width / 2, rect.Y + rect.Height / 2), Radius); } if (hostSeries != null && hostSeries.LabelPosition == CircularSeriesLabelPosition.Inside) { if (pieIndex == 0) { radius = radius / 2; } else { double difference = (radius - innerRadius) / 2; radius -= difference; } } this.X = center.X + radius * Math.Cos(Angle); this.Y = center.Y + radius * Math.Sin(Angle); } this.ActualStartDepth = this.StartDepth; }
void TransformToScreenCo(ChartTransform.ChartCartesianTransformer cartesianTransformer) { int i = 0; bool x_isInversed = cartesianTransformer.XAxis.IsInversed; bool y_isInversed = cartesianTransformer.YAxis.IsInversed; double xStart = cartesianTransformer.XAxis.VisibleRange.Start; double xEnd = cartesianTransformer.XAxis.VisibleRange.End; double yStart = cartesianTransformer.YAxis.VisibleRange.Start; double yEnd = cartesianTransformer.YAxis.VisibleRange.End; double xDelta = x_isInversed ? xStart - xEnd : xEnd - xStart; double yDelta = y_isInversed ? yStart - yEnd : yEnd - yStart; double width = cartesianTransformer.XAxis.RenderedRect.Width; double height = cartesianTransformer.YAxis.RenderedRect.Height; availableSize = new Size(width, height); double xTolerance = Math.Abs((xDelta * 1) / availableSize.Width); double yTolerance = Math.Abs((yDelta * 1) / availableSize.Height); double left = cartesianTransformer.XAxis.RenderedRect.Left - fastSeries.Area.SeriesClipRect.Left; double top = cartesianTransformer.YAxis.RenderedRect.Top - fastSeries.Area.SeriesClipRect.Top; int count = (int)(Math.Ceiling(xEnd)); int start = (int)(Math.Floor(xStart)); if (x_isInversed) { double temp = xStart; xStart = xEnd; xEnd = temp; } if (y_isInversed) { double temp = yStart; yStart = yEnd; yEnd = temp; } if (RenderingMode == RenderingMode.Default) { Points = new PointCollection(); double xValue = 0; double yValue = 0; double prevXValue = 0; double prevYValue = 0; if (fastSeries.IsIndexed) { int length = Length - 1; start = start > length ? start : length; start = start < 0 ? 0 : start; count = count > yChartVals.Count ? yChartVals.Count : count; for (i = start; i <= count; i++) { double xVal = 0; double yVal = 0; if (i >= 0 && i < yChartVals.Count) { xVal = xChartVals[i]; yVal = yChartVals[i]; } else { continue; } if (Math.Abs(prevXValue - i) >= xTolerance || Math.Abs(prevYValue - yVal) >= yTolerance) { if (xVal <= xEnd && xVal >= xStart) { xValue = left + (availableSize.Width * ((i - xStart) / xDelta)); yValue = top + (availableSize.Height * (1 - ((yVal - yStart) / yDelta))); Points.Add(new Point(xValue, yValue)); } else if (xVal < xStart && i + 1 < yChartVals.Count) { double y = ChartMath.GetInterpolarationPoint(xChartVals[i], xChartVals[i + 1], yVal, yChartVals[i + 1], xStart); xValue = left; yValue = top + (availableSize.Height * (1 - ((y - yStart) / yDelta))); Points.Add(new Point(xValue, yValue)); } else if (xVal > xEnd && i - 1 > 0) { double y = ChartMath.GetInterpolarationPoint(xChartVals[i - 1], xChartVals[i], yChartVals[i - 1], yVal, xEnd); xValue = left + availableSize.Width; yValue = top + (availableSize.Height * (1 - ((y - yStart) / yDelta))); Points.Add(new Point(xValue, yValue)); } prevXValue = i; prevYValue = yVal; } } } else { int startIndex = 0; for (i = Length - 1; i < xChartVals.Count; i++) { double xVal = xChartVals[i]; double yVal = yChartVals[i]; if (Math.Abs(prevXValue - xVal) >= xTolerance || Math.Abs(prevYValue - yVal) >= yTolerance) { if ((xVal <= xEnd) && (xVal >= xStart)) { xValue = left + (availableSize.Width * ((xVal - xStart) / xDelta)); yValue = top + (availableSize.Height * (1 - ((yVal - yStart) / yDelta))); Points.Add(new Point(xValue, yValue)); } else if (xVal < xStart) { startIndex = i; } else if (xVal > xEnd) { if (i - 1 > -1) { double y = ChartMath.GetInterpolarationPoint(xChartVals[i - 1], xChartVals[i], yChartVals[i - 1], yVal, xEnd); xValue = left + availableSize.Width; yValue = top + (availableSize.Height * (1 - ((y - yStart) / yDelta))); Points.Add(new Point(xValue, yValue)); break; } } } prevXValue = xVal; prevYValue = yVal; } if (startIndex > 0) { if (startIndex + 1 < xChartVals.Count) { double y = ChartMath.GetInterpolarationPoint(xChartVals[startIndex], xChartVals[startIndex + 1], yChartVals[startIndex], yChartVals[startIndex + 1], xStart); xValue = left; yValue = top + (availableSize.Height * (1 - ((y - yStart) / yDelta))); Points.Insert(0, new Point(xValue, yValue)); } } } } else { xValues.Clear(); yValues.Clear(); double prevXValue = 0; double prevYValue = 0; float xValue = 0; float yValue = 0; if (fastSeries.IsIndexed) { prevXValue = 1; for (i = start; i <= count; i++) { double yVal = yChartVals[i]; if (Math.Abs(prevXValue - i) >= xTolerance || Math.Abs(prevYValue - yVal) >= yTolerance) { xValue = (float)(left + availableSize.Width * ((i - xStart) / xDelta)); yValue = (float)(top + availableSize.Height * (1 - ((yVal - yStart) / yDelta))); xValues.Add(xValue); yValues.Add(yValue); prevXValue = i; prevYValue = yVal; } } if (start > 0) { i = start - 1; double yVal = yChartVals[i]; xValue = (float)(left + availableSize.Width * ((i - xStart) / xDelta)); yValue = (float)(top + availableSize.Height * (1 - ((yVal - yStart) / yDelta))); xValues.Insert(0, xValue); yValues.Insert(0, yValue); } if (count < yChartVals.Count - 1) { i = count + 1; double yVal = yChartVals[i]; xValue = (float)(left + availableSize.Width * ((i - xStart) / xDelta)); yValue = (float)(top + availableSize.Height * (1 - ((yVal - yStart) / yDelta))); xValues.Add(xValue); yValues.Add(yValue); } } else { int startIndex = 0; for (i = Length - 1; i < xChartVals.Count; i++) { double xVal = xChartVals[i]; double yVal = yChartVals[i]; if ((xVal <= count) && (xVal >= start)) { if (Math.Abs(prevXValue - xVal) >= xTolerance || Math.Abs(prevYValue - yVal) >= yTolerance) { xValue = (float)(left + availableSize.Width * ((xVal - xStart) / xDelta)); yValue = (float)(top + availableSize.Height * (1 - ((yVal - yStart) / yDelta))); xValues.Add(xValue); yValues.Add(yValue); prevXValue = xVal; prevYValue = yVal; } } else if (xVal < start) { startIndex = i; } else if (xVal > count) { xValue = (float)(left + availableSize.Width * ((xVal - xStart) / xDelta)); yValue = (float)(top + availableSize.Height * (1 - ((yVal - yStart) / yDelta))); xValues.Add(xValue); yValues.Add(yValue); break; } } if (startIndex > 0) { xValue = (float)(left + availableSize.Width * ((xChartVals[startIndex] - xStart) / xDelta)); yValue = (float)(top + availableSize.Height * (1 - ((yChartVals[startIndex] - yStart) / yDelta))); xValues.Insert(0, xValue); yValues.Insert(0, yValue); } } } }
/// <summary> /// Creates the segments of <see cref="FastRangeAreaBitmapSeries"/>. /// </summary> public override void CreateSegments() { ChartPoint point1; ChartPoint point2; ChartPoint point3; ChartPoint point4; ChartPoint? crossPoint = null; List <ChartPoint> segPoints = new List <ChartPoint>(); List <double> xValues = null; if (ActualXAxis is CategoryAxis && !(ActualXAxis as CategoryAxis).IsIndexed) { xValues = GroupedXValuesIndexes; } else { xValues = GetXValues(); } if (xValues != null) { bool isGrouping = this.ActualXAxis is CategoryAxis ? (this.ActualXAxis as CategoryAxis).IsIndexed : true; if (!isGrouping) { Segments.Clear(); Adornments.Clear(); if (double.IsNaN(GroupedSeriesYValues[1][0]) || !double.IsNaN(GroupedSeriesYValues[0][0])) { segPoints.Add(new ChartPoint(xValues[0], GroupedSeriesYValues[1][0])); segPoints.Add(new ChartPoint(xValues[0], GroupedSeriesYValues[0][0])); var segment = new FastRangeAreaSegment(segPoints, false, this) { High = GroupedSeriesYValues[0][0], Low = GroupedSeriesYValues[1][0], Item = ActualData[0] }; AddSegment(segment, segPoints); } segPoints = new List <ChartPoint>(); int i; for (i = 0; i < xValues.Count - 1; i++) { if (!double.IsNaN(GroupedSeriesYValues[1][i]) && !double.IsNaN(GroupedSeriesYValues[0][i])) { point1 = new ChartPoint(xValues[i], GroupedSeriesYValues[1][i]); point3 = new ChartPoint(xValues[i], GroupedSeriesYValues[0][i]); if (i == 0 || (i < xValues.Count - 1 && (double.IsNaN(GroupedSeriesYValues[1][i - 1]) || double.IsNaN(GroupedSeriesYValues[0][i - 1])))) { segPoints.Add(point1); segPoints.Add(point3); } if (!double.IsNaN(GroupedSeriesYValues[1][i + 1]) && !double.IsNaN(GroupedSeriesYValues[0][i + 1])) { point2 = new ChartPoint(xValues[i + 1], GroupedSeriesYValues[1][i + 1]); point4 = new ChartPoint(xValues[i + 1], GroupedSeriesYValues[0][i + 1]); // UWP-8718 Use ChartMath.GetCrossPoint since it returns the ChartDataPoint withou rounding the values. crossPoint = ChartMath.GetCrossPoint(point1, point2, point3, point4); if (crossPoint != null) { var crossPointValue = new ChartPoint(crossPoint.Value.X, crossPoint.Value.Y); segPoints.Add(crossPointValue); segPoints.Add(crossPointValue); var segment = new FastRangeAreaSegment(segPoints, (GroupedSeriesYValues[1][i] > GroupedSeriesYValues[0][i]), this) { High = GroupedSeriesYValues[0][i], Low = GroupedSeriesYValues[1][i], Item = ActualData[i] }; AddSegment(segment, segPoints); segPoints = new List <ChartPoint>(); segPoints.Add(crossPointValue); segPoints.Add(crossPointValue); } segPoints.Add(point2); segPoints.Add(point4); } else if (i != 0 && !double.IsNaN(GroupedSeriesYValues[1][i - 1]) && !double.IsNaN(GroupedSeriesYValues[0][i - 1])) { segPoints.Add(point1); segPoints.Add(point3); } } else { if (segPoints.Count > 0) { if (!double.IsNaN(GroupedSeriesYValues[1][i - 1]) && !double.IsNaN(GroupedSeriesYValues[0][i - 1])) { var segment = new FastRangeAreaSegment(segPoints, false, this) { High = GroupedSeriesYValues[0][i - 1], Low = GroupedSeriesYValues[1][i - 1], Item = ActualData[i - 1] }; AddSegment(segment, segPoints); } } segPoints = new List <ChartPoint>(); } } if (segPoints.Count > 0) { var segment = new FastRangeAreaSegment(segPoints, (GroupedSeriesYValues[1][i] > GroupedSeriesYValues[0][i]), this) { High = GroupedSeriesYValues[0][i], Low = GroupedSeriesYValues[1][i], Item = ActualData[i] }; AddSegment(segment, segPoints); } else if (i == xValues.Count - 1 && (double.IsNaN(GroupedSeriesYValues[1][i]) || double.IsNaN(GroupedSeriesYValues[0][i]))) { segPoints.Add(new ChartPoint(xValues[i], GroupedSeriesYValues[1][i])); segPoints.Add(new ChartPoint(xValues[i], GroupedSeriesYValues[0][i])); var segment = new FastRangeAreaSegment(segPoints, false, this) { High = GroupedSeriesYValues[0][i], Low = GroupedSeriesYValues[1][i], Item = ActualData[i] }; AddSegment(segment, segPoints); } for (int j = 0; j < xValues.Count; j++) { if (AdornmentsInfo != null) { AddAdornments(xValues[j], 0, GroupedSeriesYValues[0][j], GroupedSeriesYValues[1][j], j); } } } else { Segments.Clear(); if (AdornmentsInfo != null) { if (AdornmentsInfo.AdornmentsPosition == AdornmentsPosition.TopAndBottom) { ClearUnUsedAdornments(this.DataCount * 2); } else { ClearUnUsedAdornments(this.DataCount); } } if (xValues != null) { if (double.IsNaN(LowValues[0]) || double.IsNaN(HighValues[0])) { segPoints.Add(new ChartPoint(xValues[0], LowValues[0])); segPoints.Add(new ChartPoint(xValues[0], HighValues[0])); var segment = new FastRangeAreaSegment(segPoints, false, this) { High = HighValues[0], Low = LowValues[0], Item = ActualData[0] }; AddSegment(segment, segPoints); } segPoints = new List <ChartPoint>(); int i; for (i = 0; i < DataCount - 1; i++) { if (!double.IsNaN(LowValues[i]) && !double.IsNaN(HighValues[i])) { point1 = new ChartPoint(xValues[i], LowValues[i]); point3 = new ChartPoint(xValues[i], HighValues[i]); if (i == 0 || (i < DataCount - 1 && (double.IsNaN(LowValues[i - 1]) || double.IsNaN(HighValues[i - 1])))) { segPoints.Add(point1); segPoints.Add(point3); } if (!double.IsNaN(LowValues[i + 1]) && !double.IsNaN(HighValues[i + 1])) { point2 = new ChartPoint(xValues[i + 1], LowValues[i + 1]); point4 = new ChartPoint(xValues[i + 1], HighValues[i + 1]); // UWP-8718 Use ChartMath.GetCrossPoint since it returns the ChartDataPoint withou rounding the values. crossPoint = ChartMath.GetCrossPoint(point1, point2, point3, point4); if (crossPoint != null) { var crossPointValue = new ChartPoint(crossPoint.Value.X, crossPoint.Value.Y); segPoints.Add(crossPointValue); segPoints.Add(crossPointValue); var segment = new FastRangeAreaSegment(segPoints, (LowValues[i] > HighValues[i]), this) { High = HighValues[i], Low = LowValues[i], Item = ActualData[i] }; AddSegment(segment, segPoints); segPoints = new List <ChartPoint>(); segPoints.Add(crossPointValue); segPoints.Add(crossPointValue); } segPoints.Add(point2); segPoints.Add(point4); } } else { if (segPoints.Count > 0) { if (!double.IsNaN(LowValues[i - 1]) && !double.IsNaN(HighValues[i - 1])) { var segment = new FastRangeAreaSegment(segPoints, false, this) { High = HighValues[i - 1], Low = LowValues[i - 1], Item = ActualData[i - 1] }; AddSegment(segment, segPoints); } } segPoints = new List <ChartPoint>(); } } if (segPoints.Count > 0) { var segment = new FastRangeAreaSegment(segPoints, (LowValues[i] > HighValues[i]), this) { High = HighValues[i], Low = LowValues[i], Item = ActualData[i] }; AddSegment(segment, segPoints); } else if (i == DataCount - 1 && (double.IsNaN(LowValues[i]) || double.IsNaN(HighValues[i]))) { segPoints.Add(new ChartPoint(xValues[i], LowValues[i])); segPoints.Add(new ChartPoint(xValues[i], HighValues[i])); var segment = new FastRangeAreaSegment(segPoints, false, this) { High = HighValues[i], Low = LowValues[i], Item = ActualData[i] }; AddSegment(segment, segPoints); } } for (int i = 0; i < xValues.Count; i++) { if (AdornmentsInfo != null) { AddAdornments(xValues[i], 0, HighValues[i], LowValues[i], i); } } } } // Updates the stroke rendering for empty points. if (Segments.Count > 1) { UpdateEmptyPointSegments(); } }
/// <summary> /// Updates the segments based on its data point value. This method is not /// intended to be called explicitly outside the Chart but it can be overriden by /// any derived class. /// </summary> /// <param name="transformer">Reresents the view port of chart control.(refer <see cref="IChartTransformer"/>)</param> public override void Update(IChartTransformer transformer) { double radius = Radius; double actualRadius = Math.Min(transformer.Viewport.Width, transformer.Viewport.Height) / 2; if (Series is PieSeries) { var hostSeries = Series as PieSeries; double pieSeriesCount = hostSeries.GetPieSeriesCount(); double equalParts = actualRadius / pieSeriesCount; double innerRadius = equalParts * pieIndex; Point center; if (pieSeriesCount == 1) { center = hostSeries.Center; } else { center = ChartLayoutUtils.GetCenter(transformer.Viewport); } if (hostSeries != null && hostSeries.LabelPosition == CircularSeriesLabelPosition.Inside) { if (pieIndex > 0) { double difference = (radius - innerRadius) / 2; radius = radius - difference; } else { radius = radius / 2; } } this.X = center.X + radius * Math.Cos(Angle); this.Y = center.Y + radius * Math.Sin(Angle); } else if (Series is DoughnutSeries) { var hostSeries = Series as DoughnutSeries; actualRadius *= hostSeries.InternalDoughnutSize; Point center; double remainingWidth = 0d, equalParts = 0d, innerRadius = 0d; var adornmentAngle = Angle; if (hostSeries.IsStackedDoughnut) { var adornmentIndex = Series.Adornments.IndexOf(this); var doughnutSegment = hostSeries.Segments[adornmentIndex] as DoughnutSegment; int doughnutSegmentsCount = hostSeries.Segments.Count; center = hostSeries.Center; remainingWidth = actualRadius - (actualRadius * Series.ActualArea.InternalDoughnutHoleSize); equalParts = (remainingWidth / doughnutSegmentsCount) * hostSeries.InternalDoughnutCoefficient; radius = actualRadius - (equalParts * (doughnutSegmentsCount - (doughnutSegment.DoughnutSegmentIndex + 1))); InnerDoughnutRadius = innerRadius = radius - equalParts; radius = radius - equalParts * hostSeries.SegmentSpacing; Radius = radius; innerRadius = ChartMath.MaxZero(innerRadius); double difference = (radius - innerRadius) / 2; radius = radius - difference; adornmentAngle = hostSeries.LabelPosition == CircularSeriesLabelPosition.Outside ? doughnutSegment.StartAngle : hostSeries.LabelPosition == CircularSeriesLabelPosition.OutsideExtended ? doughnutSegment.EndAngle : Angle; } else { int doughnutSeriesCount = hostSeries.GetDoughnutSeriesCount(); center = doughnutSeriesCount == 1 ? hostSeries.Center : ChartLayoutUtils.GetCenter(transformer.Viewport); remainingWidth = actualRadius - (actualRadius * Series.ActualArea.InternalDoughnutHoleSize); equalParts = remainingWidth / doughnutSeriesCount; InnerDoughnutRadius = innerRadius = radius - (equalParts * hostSeries.InternalDoughnutCoefficient); innerRadius = ChartMath.MaxZero(innerRadius); if (hostSeries != null && hostSeries.LabelPosition == CircularSeriesLabelPosition.Inside) { double difference = (radius - innerRadius) / 2; radius = radius - difference; } } this.X = center.X + radius * Math.Cos(adornmentAngle); this.Y = center.Y + radius * Math.Sin(adornmentAngle); } }
/// <summary> /// Creates the segments of HistogramSeries. /// </summary> public override void CreateSegments() { List <double> xValues = GetXValues(); int index = 0; double x1, y1, y2; float median; double origin = ActualXAxis != null ? ActualXAxis.Origin : 0; if (ActualXAxis != null && ActualXAxis.Origin == 0 && ActualYAxis is LogarithmicAxis && (ActualYAxis as LogarithmicAxis).Minimum != null) { origin = (double)(ActualYAxis as LogarithmicAxis).Minimum; } if (xValues != null) { Segments.Clear(); ClearUnUsedAdornments(Segments.Count); ActualYValues.Clear(); List <Point> dataPoints = new List <Point>(); List <ChartSegment> segmentsCollection = new List <ChartSegment>(); for (int i = 0; i < DataCount; i++) { dataPoints.Add(new Point(xValues[i], yValues[i])); } Array.Sort(dataPoints.ToArray(), new PointsSortByXComparer()); double interval = HistogramInterval; double start = 0; if (dataPoints.Count > 0) { start = ChartMath.Round(dataPoints[0].X, interval, false); } int pointsCount; double position = start; int intervalsCount = 0; List <Point> points = new List <Point>(); List <object> data = new List <object>(); HistogramSegment histogramSegment; for (int i = 0, ci = dataPoints.Count; i < ci; i++) { Point cdpt = dataPoints[i]; while (cdpt.X > position + interval) { pointsCount = points.Count; if (pointsCount > 0) { histogramSegment = new HistogramSegment(position, pointsCount, position + interval, 0, this); histogramSegment.XData = index; histogramSegment.YData = pointsCount; histogramSegment.Data = data; data = new List <object>(); segmentsCollection.Add(histogramSegment); ActualYValues.Add(pointsCount); points.Clear(); index++; } position += interval; intervalsCount++; } points.Add(dataPoints[i]); data.Add(ActualData[i]); } pointsCount = points.Count; if (pointsCount > 0) { intervalsCount++; histogramSegment = new HistogramSegment(position, pointsCount, position + interval, 0, this); histogramSegment.XData = index; histogramSegment.YData = pointsCount; histogramSegment.Data = data; data = new List <object>(); segmentsCollection.Add(histogramSegment); ActualYValues.Add(pointsCount); points.Clear(); } median = (float)interval / 2; if (AdornmentsInfo != null) { for (int i = 0; i < segmentsCollection.Count; i++) { x1 = (segmentsCollection[i] as HistogramSegment).XRange.Start; y1 = (segmentsCollection[i] as HistogramSegment).YData; y2 = origin; if (this.AdornmentsInfo.AdornmentsPosition == AdornmentsPosition.Top) { AddColumnAdornments( (segmentsCollection[i] as HistogramSegment).XData, (segmentsCollection[i] as HistogramSegment).YData, x1, y1, i, median); } else if (this.AdornmentsInfo.AdornmentsPosition == AdornmentsPosition.Bottom) { AddColumnAdornments( (segmentsCollection[i] as HistogramSegment).XData, (segmentsCollection[i] as HistogramSegment).YData, x1, y2, i, median); } else { AddColumnAdornments( (segmentsCollection[i] as HistogramSegment).XData, (segmentsCollection[i] as HistogramSegment).YData, x1, y1 + (y2 - y1) / 2, i, median); } } } #region Normal Distribution if (ShowNormalDistributionCurve) { double m, dev; GetHistogramMeanAndDeviation(dataPoints, out m, out dev); PointCollection distributionPoints = new PointCollection(); double min = start; double max = start + intervalsCount * interval; double del = (max - min) / (C_distributionPointsCount - 1); for (int i = 0; i < C_distributionPointsCount; i++) { double tx = min + i * del; double ty = NormalDistribution(tx, m, dev) * dataPoints.Count * interval; distributionPoints.Add(new Point(tx, ty)); } segmentsCollection.Add(new HistogramDistributionSegment(distributionPoints, this)); } foreach (var item in segmentsCollection) { Segments.Add(item); } #endregion } }