/// <summary> /// To calculate the segments if the pyramid mode is surface /// </summary> private void CalculateSurfaceSegments(double sumValues, int count, double gapHeight, List <double> xValues) { var toggledYValues = YValues.ToList(); if (ToggledLegendIndex.Count > 0) { toggledYValues = GetYValues(); } currY = 0; double[] y = new double[count]; double[] height = new double[count]; double preSum = GetSurfaceHeight(0, sumValues); for (int i = 0; i < count; i++) { y[i] = currY; height[i] = GetSurfaceHeight(currY, Math.Abs(double.IsNaN(toggledYValues[i]) ? 0 : toggledYValues[i])); currY += height[i] + gapHeight * preSum; } double coef = 1 / (currY - gapHeight * preSum); for (int i = 0; i < count; i++) { double currHeight = 0; if (!double.IsNaN(YValues[i])) { currHeight = coef * y[i]; PyramidSegment pyramidSegment = new PyramidSegment(currHeight, coef * height[i], this.ExplodeOffset, this, i == this.ExplodeIndex || this.ExplodeAll ? true : false); pyramidSegment.Item = ActualData[i]; pyramidSegment.XData = xValues[i]; pyramidSegment.YData = Math.Abs(YValues[i]); if (ToggledLegendIndex.Contains(i)) { pyramidSegment.IsSegmentVisible = false; } else { pyramidSegment.IsSegmentVisible = true; } this.Segments.Add(pyramidSegment); if (AdornmentsInfo != null) { Adornments.Add(this.CreateAdornment(this, xValues[i], toggledYValues[i], 0, double.IsNaN(currHeight) ? 1 - height[i] / 2 : currHeight + coef * height[i] / 2)); } } } }
internal List <double> GetToggleYValues(List <double> groupToYValues) { var yvalues = new List <double>(); for (int i = 0; i < groupToYValues.Count; i++) { double yvalue = groupToYValues[i]; if (!ToggledLegendIndex.Contains(i)) { yvalues.Add(yvalue); } else { yvalues.Add(double.NaN); } } return(yvalues); }
/// <summary> /// To calculate the segments if the pyramid mode is linear /// </summary> private void CalculateLinearSegments(double sumValues, double gapRatio, int count, List <double> xValues) { var toggledYValues = YValues.ToList(); if (ToggledLegendIndex.Count > 0) { toggledYValues = GetYValues(); } currY = 0; double coef = 1d / (sumValues * (1 + gapRatio / (1 - gapRatio))); for (int i = 0; i < count; i++) { double height = 0; if (!double.IsNaN(YValues[i])) { height = coef * Math.Abs(double.IsNaN(toggledYValues[i]) ? 0 : toggledYValues[i]); PyramidSegment pyramidSegment = new PyramidSegment(currY, height, this.ExplodeOffset, this, i == ExplodeIndex || this.ExplodeAll ? true : false); pyramidSegment.Item = ActualData[i]; pyramidSegment.XData = xValues[i]; pyramidSegment.YData = Math.Abs(YValues[i]); if (ToggledLegendIndex.Contains(i)) { pyramidSegment.IsSegmentVisible = false; } else { pyramidSegment.IsSegmentVisible = true; } this.Segments.Add(pyramidSegment); currY += (gapRatio / (count - 1)) + height; if (AdornmentsInfo != null) { Adornments.Add(this.CreateAdornment(this, xValues[i], toggledYValues[i], 0, double.IsNaN(currY) ? 1 - height / 2 : currY - height / 2)); Adornments[Segments.Count - 1].Item = ActualData[i]; } } } }
/// <summary> /// To calculate the segments if the pyramid mode is vlaueisHeight. /// </summary> private void CalculateValueIsHeightSegments(IList <double> yValues, List <double> xValues, double sumValues, double gapRatio, int dataCount, int explodedIndex) { currY = 0d; double coefHeight = 1 / sumValues; double spacing = gapRatio / (DataCount - 1); for (int i = DataCount - 1; i >= 0; i--) { double height = 0; if (!double.IsNaN(YValues[i])) { height = Math.Abs(double.IsNaN(yValues[i]) ? 0 : yValues[i]) * coefHeight; FunnelSegment funnelSegment = new FunnelSegment(currY, height, this, explodedIndex == i || this.ExplodeAll ? true : false); funnelSegment.Item = ActualData[i]; // WPF-14426 Funnel series legend and segment colour is changing while setting emptypoint funnelSegment.XData = xValues[i]; funnelSegment.YData = YValues[i]; if (ToggledLegendIndex.Contains(i)) { funnelSegment.IsSegmentVisible = false; } else { funnelSegment.IsSegmentVisible = true; } Segments.Add(funnelSegment); if (AdornmentsInfo != null) { ChartAdornment adornment = (this.CreateAdornment(this, xValues[i], yValues[i], 0, double.IsNaN(currY) ? 0 : currY + (height + spacing) / 2)); adornment.Item = ActualData[i]; Adornments.Add(adornment); } currY += height + spacing; } } }
/// <summary> /// Creates the doughnut segments. /// </summary> public override void CreateSegments() { IList <double> toggledYValues = null; List <double> xValues = null; var actualData = ActualData; if (double.IsNaN(GroupTo)) { if (ToggledLegendIndex.Count > 0) { toggledYValues = GetYValues(); } else { toggledYValues = YValues; } xValues = GetXValues(); } else { if (Adornments != null) { Adornments.Clear(); } if (Segments != null) { Segments.Clear(); } var sumOfYValues = (from val in YValues select(val) > 0 ? val : Math.Abs(double.IsNaN(val) ? 0 : val)).Sum(); double xIndexValues = 0d; xValues = (from val in YValues where GetGroupModeValue(val, sumOfYValues) > GroupTo select(xIndexValues++)).ToList(); if (YValues.Count > xValues.Count) { xValues.Add(xIndexValues); } var groupToValues = GetGroupToYValues(); actualData = groupToValues.Item2; if (ToggledLegendIndex.Count > 0) { toggledYValues = GetToggleYValues(groupToValues.Item1); } else { toggledYValues = groupToValues.Item1; } } double arcEndAngle = DegreeToRadianConverter(EndAngle), arcStartAngle = DegreeToRadianConverter(StartAngle); if (arcStartAngle == arcEndAngle) { Segments.Clear(); } ARCLENGTH = arcEndAngle - arcStartAngle; if (Math.Abs(Math.Round(ARCLENGTH, 2)) > TotalArcLength) { ARCLENGTH = ARCLENGTH % TotalArcLength; } ClearUnUsedAdornments(this.DataCount); ClearUnUsedSegments(this.DataCount); int explodedIndex = ExplodeIndex; bool explodedAll = ExplodeAll; if (xValues != null) { var grandTotal = (from val in toggledYValues select(val) > 0 ? val : Math.Abs(double.IsNaN(val) ? 0 : val)).Sum(); var isMultipleDoughnut = !double.IsNaN(MaximumValue) && IsStackedDoughnut && GetDoughnutSeriesCount() == 1; bool isEndValueExceed = false; var visibleSegmentCount = 0; for (int i = 0; i < xValues.Count; i++) { isEndValueExceed = false; if (isMultipleDoughnut) { isEndValueExceed = (toggledYValues[i] >= MaximumValue); arcEndAngle = grandTotal == 0 ? 0 : (Math.Abs(double.IsNaN(toggledYValues[i]) ? 0 : isEndValueExceed ? MaximumValue : toggledYValues[i]) * (ARCLENGTH / MaximumValue)); } else { arcEndAngle = grandTotal == 0 ? 0 : (Math.Abs(double.IsNaN(toggledYValues[i]) ? 0 : toggledYValues[i]) * (ARCLENGTH / grandTotal)); } if (i < Segments.Count) { var doughnutSegment = Segments[i] as DoughnutSegment; doughnutSegment.SetData(arcStartAngle, arcStartAngle + arcEndAngle, this); doughnutSegment.XData = xValues[i]; doughnutSegment.YData = !double.IsNaN(GroupTo) ? Math.Abs(toggledYValues[i]) : Math.Abs(YValues[i]); doughnutSegment.AngleOfSlice = (2 * arcStartAngle + arcEndAngle) / 2; doughnutSegment.IsExploded = explodedAll || (explodedIndex == i); doughnutSegment.Item = actualData[i]; doughnutSegment.IsEndValueExceed = isEndValueExceed; doughnutSegment.DoughnutSegmentIndex = visibleSegmentCount; if (SegmentColorPath != null && !Segments[i].IsEmptySegmentInterior && ColorValues.Count > 0 && !Segments[i].IsSelectedSegment) { Segments[i].Interior = (Interior != null) ? Interior : ColorValues[i]; } if (ToggledLegendIndex.Contains(i)) { Segments[i].IsSegmentVisible = false; } else { Segments[i].IsSegmentVisible = true; } doughnutSegment.UpdateTrackInterior(i); } else { DoughnutSegment segment = new DoughnutSegment(arcStartAngle, arcStartAngle + arcEndAngle, this) { XData = xValues[i], YData = !double.IsNaN(GroupTo) ? Math.Abs(toggledYValues[i]) : Math.Abs(YValues[i]), AngleOfSlice = (2 * arcStartAngle + arcEndAngle) / 2, IsExploded = explodedAll || (explodedIndex == i), Item = actualData[i], IsEndValueExceed = isEndValueExceed, DoughnutSegmentIndex = visibleSegmentCount }; segment.SetData(arcStartAngle, arcStartAngle + arcEndAngle, this); if (ToggledLegendIndex.Contains(i)) { segment.IsSegmentVisible = false; } else { segment.IsSegmentVisible = true; } Segments.Add(segment); segment.UpdateTrackInterior(i); } if (AdornmentsInfo != null) { AddDoughnutAdornments( xValues[i], toggledYValues[i], arcStartAngle, arcStartAngle + arcEndAngle, Segments.Count - 1, i); } if (!double.IsNaN(toggledYValues[i])) { visibleSegmentCount++; } if (!IsStackedDoughnut) { arcStartAngle += arcEndAngle; } } if (ShowEmptyPoints) { UpdateEmptyPointSegments(xValues, false); } UpdateSegmentGapAngle(); } }
/// <summary> /// Creates the segments of PieSeries. /// </summary> public override void CreateSegments() { IList <double> toggledYValues = null; List <double> xValues = null; var actualData = ActualData; if (double.IsNaN(GroupTo)) { if (ToggledLegendIndex.Count > 0) { toggledYValues = GetYValues(); } else { toggledYValues = YValues; } xValues = GetXValues(); } else { if (Adornments != null) { Adornments.Clear(); } if (Segments != null) { Segments.Clear(); } var sumOfYValues = (from val in YValues select(val) > 0 ? val : Math.Abs(double.IsNaN(val) ? 0 : val)).Sum(); double xIndexValues = 0d; xValues = (from val in YValues where GetGroupModeValue(val, sumOfYValues) > GroupTo select(xIndexValues++)).ToList(); if (YValues.Count > xValues.Count) { xValues.Add(xIndexValues); } var groupToValues = GetGroupToYValues(); actualData = groupToValues.Item2; if (ToggledLegendIndex.Count > 0) { toggledYValues = GetToggleYValues(groupToValues.Item1); } else { toggledYValues = groupToValues.Item1; } } ClearUnUsedAdornments(this.DataCount); ClearUnUsedSegments(this.DataCount); int explodedIndex = ExplodeIndex; bool explodedAll = ExplodeAll; arcStartAngle = DegreeToRadianConverter(StartAngle); arcEndAngle = DegreeToRadianConverter(EndAngle); if (arcStartAngle == arcEndAngle) { Segments.Clear(); } ARCLENGTH = arcEndAngle - arcStartAngle; if (Math.Abs(Math.Round(ARCLENGTH, 2)) > TotalArcLength) { ARCLENGTH = ARCLENGTH % TotalArcLength; } if (xValues != null) { grandTotal = (from val in toggledYValues select(val) > 0 ? val : Math.Abs(double.IsNaN(val) ? 0 : val)).Sum(); for (int i = 0; i < xValues.Count; i++) { arcEndAngle = grandTotal == 0 ? 0 : (Math.Abs(double.IsNaN(toggledYValues[i]) ? 0 : toggledYValues[i]) * (ARCLENGTH / grandTotal)); if (i < Segments.Count) { (Segments[i] as PieSegment).SetData( arcStartAngle, arcStartAngle + arcEndAngle, this, actualData[i]); (Segments[i] as PieSegment).XData = xValues[i]; (Segments[i] as PieSegment).YData = !double.IsNaN(GroupTo) ? Math.Abs(toggledYValues[i]) : Math.Abs(YValues[i]); (Segments[i] as PieSegment).AngleOfSlice = (2 * arcStartAngle + arcEndAngle) / 2; (Segments[i] as PieSegment).IsExploded = explodedAll || (explodedIndex == i); (Segments[i] as PieSegment).Item = actualData[i]; if (SegmentColorPath != null && !Segments[i].IsEmptySegmentInterior && ColorValues.Count > 0 && !Segments[i].IsSelectedSegment) { Segments[i].Interior = (Interior != null) ? Interior : ColorValues[i]; } if (ToggledLegendIndex.Contains(i)) { Segments[i].IsSegmentVisible = false; } else { Segments[i].IsSegmentVisible = true; } } else { var segment = new PieSegment(arcStartAngle, arcStartAngle + arcEndAngle, this, actualData[i]); segment.SetData(arcStartAngle, arcStartAngle + arcEndAngle, this, actualData[i]); segment.XData = xValues[i]; segment.YData = !double.IsNaN(GroupTo) ? Math.Abs(toggledYValues[i]) : Math.Abs(YValues[i]); segment.AngleOfSlice = (2 * arcStartAngle + arcEndAngle) / 2; segment.IsExploded = explodedAll || explodedIndex == i; segment.Item = actualData[i]; if (ToggledLegendIndex.Contains(i)) { segment.IsSegmentVisible = false; } else { segment.IsSegmentVisible = true; } Segments.Add(segment); } if (AdornmentsInfo != null) { AddPieAdornments(xValues[i], toggledYValues[i], arcStartAngle, arcStartAngle + arcEndAngle, Segments.Count - 1, i, Segments[i] as PieSegment); } arcStartAngle += arcEndAngle; } if (ShowEmptyPoints) { UpdateEmptyPointSegments(xValues, false); } } }
/// <summary> /// Creates the points. /// </summary> protected virtual void CreatePoints() { var seriesCount = GetCircularSeriesCount(); var pieIndex = GetPieSeriesIndex(); Segments.Clear(); // PieSeries3D is not rendered properly while removing data dynamically-WPF-17521 Adornments.Clear(); IList <double> toggledYValues = null; if (ToggledLegendIndex.Count > 0) { toggledYValues = this.GetYValues(); } else { toggledYValues = this.YValues; } if (Area.RootPanelDesiredSize != null) { this.actualWidth = Area.RootPanelDesiredSize.Value.Width; this.actualHeight = Area.RootPanelDesiredSize.Value.Height; } var all = toggledYValues.Select(item => Math.Abs(double.IsNaN(item) ? 0d : item)).Sum(); var count = toggledYValues.Count; if (this.InnerRadius == 0) { double actualRadius = Math.Min(this.actualWidth, this.actualHeight) / 2; double equalParts = actualRadius / seriesCount; this.Radius = (equalParts * (pieIndex + 1)) - (equalParts * (1 - this.InternalCircleCoefficient)); this.InnerRadius = equalParts * pieIndex; } var pieHeight = Area.Depth; if (this.ExplodeIndex >= 0 && this.ExplodeIndex < count || this.ExplodeAll) { this.Radius -= this.ExplodeRadius; } double arcStartAngle = StartAngle, arcEndAngle = EndAngle, diffAngle; diffAngle = arcEndAngle - arcStartAngle; if (Math.Abs(diffAngle) > 360) { diffAngle = diffAngle % 360; } int segindex = 0; for (var i = 0; i < count; i++) { if (!double.IsNaN(this.YValues[i])) { var val = Math.Abs(double.IsNaN(toggledYValues[i]) ? 0 : toggledYValues[i]); arcEndAngle = all == 0 ? 0 : (Math.Abs(val) * ((diffAngle) / all)); var rect = new Rect(0, 0, this.actualWidth, this.actualHeight); if (this.ExplodeIndex == i || this.ExplodeAll) { var offset = new Point( (float)(Math.Cos(Math.PI * (2 * arcStartAngle + arcEndAngle) / 360)), (float)(Math.Sin(Math.PI * (2 * arcStartAngle + arcEndAngle) / 360))); rect = rect.Offset( 0.01f * this.Radius * offset.X * this.ExplodeRadius, 0.01f * this.Radius * offset.Y * this.ExplodeRadius); } if (seriesCount == 1) { this.Center = this.GetActualCenter(new Point(rect.X + rect.Width / 2, rect.Y + rect.Height / 2), this.Radius); } else { this.Center = new Point(this.actualWidth / 2, this.actualHeight / 2); if (this.ExplodeAll || this.ExplodeIndex == i) { this.Center = new Point(rect.X + Center.X, rect.Y + Center.Y); } } var center = new Vector3D(Center.X, Center.Y, 0); if (segindex < Segments.Count) { Segments[segindex].SetData(arcStartAngle, arcStartAngle + arcEndAngle, pieHeight, this.Radius, val, center.X, center.Y, center.Z, this.InnerRadius); if (ToggledLegendIndex.Contains(i)) { Segments[segindex].IsSegmentVisible = false; } else { Segments[segindex].IsSegmentVisible = true; } } else { Segments.Add(new PieSegment3D(this, center, arcStartAngle, arcStartAngle + arcEndAngle, pieHeight, this.Radius, i, val, this.InnerRadius)); } if (this.AdornmentsInfo != null) { this.AddPieAdornments(segindex, toggledYValues[i], arcStartAngle, arcStartAngle + arcEndAngle, i, this.Radius, Area.IsChartRotated() ? Area.Depth + 5d : 0d); } segindex++; arcStartAngle += arcEndAngle; } } }
/// <summary> /// To calculate the segments if the pyramid mode is valueisWidth. /// </summary> private void CalculateValueIsWidthSegments(IList <double> yValues, List <double> xValues, double sumValues, double gapRatio, int count, int explodedIndex) { currY = 0d; if (ToggledLegendIndex.Count > 0) { count = YValues.Count - ToggledLegendIndex.Count; } double offset = 1d / (count - 1); double height = (1 - gapRatio) / (count - 1); for (int i = DataCount - 1; i > 0; i--) { if (!double.IsNaN(YValues[i])) { double w1 = Math.Abs(YValues[i]); double w2 = 0; if (ToggledLegendIndex.Contains(i - 1)) { for (int k = i - 2; k >= 0; k--) { if (!(ToggledLegendIndex.Contains(k))) { w2 = Math.Abs(YValues[k]); break; } } } else { w2 = Math.Abs(YValues[i - 1]); } if (ToggledLegendIndex.Contains(i)) { height = 0; w2 = w1; } else { height = (1 - gapRatio) / (count - 1); } FunnelSegment funnelSegment = new FunnelSegment(currY, height, w1 / sumValues, w2 / sumValues, this, explodedIndex == i || this.ExplodeAll ? true : false); funnelSegment.Item = ActualData[i]; funnelSegment.XData = xValues[i]; funnelSegment.YData = YValues[i]; if (ToggledLegendIndex.Contains(i)) { funnelSegment.IsSegmentVisible = false; } else { funnelSegment.IsSegmentVisible = true; } Segments.Add(funnelSegment); if (AdornmentsInfo != null) { Adornments.Add(this.CreateAdornment(this, xValues[i], yValues[i], height, currY)); Adornments[Adornments.Count - 1].Item = ActualData[i]; } if (!(ToggledLegendIndex.Contains(i))) { currY += offset; } } } if (AdornmentsInfo != null && DataCount > 0) { Adornments.Add(this.CreateAdornment(this, xValues[0], yValues[0], height, currY)); Adornments[Adornments.Count - 1].Item = ActualData[0]; } }