private void AddStackingAreaAdornments(IList <double> yValues) { double adornX = 0d, adornY = 0d; int i = 0; List <double> xValues = null; IList <double> actualYValues = YValues; if (ActualXAxis is CategoryAxis && !(ActualXAxis as CategoryAxis).IsIndexed) { xValues = GroupedXValuesIndexes; actualYValues = GroupedSeriesYValues[0]; } else { xValues = GetXValues(); } for (i = 0; i < xValues.Count; i++) { adornX = xValues[i]; adornY = yValues[i]; if (i < Adornments.Count) { Adornments[i].SetData(adornX, actualYValues[i], adornX, adornY); } else { Adornments.Add(this.CreateAdornment(this, adornX, actualYValues[i], adornX, adornY)); } Adornments[i].Item = ActualData[i]; } }
private void AddBoxWhiskerAdornments(DoubleRange sbsInfo, double xValue, double minimum, double maximum, double x1, double median, double lowerQuartile, double upperQuartile, List <double> outliers, int index) { if (AdornmentsInfo != null) { ChartAdornment adornment = null; var sbsMedian = sbsInfo.Delta / 2; adornment = this.CreateAdornment(this, xValue, minimum, x1 + sbsMedian, minimum); adornment.ActualLabelPosition = bottomLabelPosition; adornment.Item = ActualData[index]; Adornments.Add(adornment); adornment = this.CreateAdornment(this, xValue, lowerQuartile, x1 + sbsMedian, lowerQuartile); adornment.ActualLabelPosition = bottomLabelPosition; adornment.Item = ActualData[index]; Adornments.Add(adornment); adornment = this.CreateAdornment(this, xValue, median, x1 + sbsMedian, median); adornment.ActualLabelPosition = topLabelPosition; adornment.Item = ActualData[index]; Adornments.Add(adornment); adornment = this.CreateAdornment(this, xValue, upperQuartile, x1 + sbsMedian, upperQuartile); adornment.ActualLabelPosition = topLabelPosition; adornment.Item = ActualData[index]; Adornments.Add(adornment); adornment = this.CreateAdornment(this, xValue, maximum, x1 + sbsMedian, maximum); adornment.ActualLabelPosition = topLabelPosition; adornment.Item = ActualData[index]; Adornments.Add(adornment); } }
private void AddPieAdornments(double x, double y, double startAngle, double endAngle, int i, int index, PieSegment pieSegment) { double angle = (startAngle + endAngle) / 2; if (Area == null || Area.RootPanelDesiredSize == null || Area.RootPanelDesiredSize.Value == null) { return; } var actualheight = Area.RootPanelDesiredSize.Value.Height; var actualwidth = Area.RootPanelDesiredSize.Value.Width; var pieSeries = (from series in Area.VisibleSeries where series is PieSeries select series).ToList(); var pieSeriesCount = pieSeries.Count(); double pieIndex = pieSeries.IndexOf(this); double actualRadius = (Math.Min(actualwidth, actualheight)) / 2; double equalParts = actualRadius / (pieSeriesCount); double radius = (equalParts * (pieIndex + 1)) - (equalParts * (1 - InternalPieCoefficient)); if (index < Adornments.Count) { (Adornments[index] as ChartPieAdornment).SetData(x, y, angle, radius); } else { Adornments.Add(this.CreateAdornment(this, x, y, angle, radius)); } Adornments[index].Item = !double.IsNaN(GroupTo) ? Segments[index].Item : ActualData[index]; }
/// <summary> /// Method implementation for Add ColumnAdornments in Chart. /// </summary> /// <param name="values">The Value</param> protected virtual void AddColumnAdornments(params double[] values) { // values[0] --> xData // values[1] --> yData // values[2] --> xPos // values[3] --> yPos // values[4] --> data point index // values[5] --> Median value. double adornposX = values[2] + values[5], adornposY = values[3]; var pointIndex = (int)values[4]; if (pointIndex < Adornments.Count) { Adornments[pointIndex].SetData(values[0], values[1], adornposX, adornposY, values[6]); } else { Adornments.Add(this.CreateAdornment(this, values[0], values[1], adornposX, adornposY, values[6])); } if (ActualXAxis is CategoryAxis3D && !(ActualXAxis as CategoryAxis3D).IsIndexed) { Adornments[pointIndex].Item = this.GroupedActualData[pointIndex]; } else { Adornments[pointIndex].Item = this.ActualData[pointIndex]; } }
/// <summary> /// Adds the pie adornments. /// </summary> /// <param name="x">The X Value</param> /// <param name="y">The Y Value</param> /// <param name="startAngle">The Start Angle</param> /// <param name="endAngle">The End Angle</param> /// <param name="index">The Index</param> /// <param name="radius">The Radius</param> /// <param name="startDepth">The Start Depth</param> private void AddPieAdornments(double x, double y, double startAngle, double endAngle, int index, double radius, double startDepth) { startAngle = CircularSeriesBase3D.DegreeToRadianConverter(startAngle); endAngle = DegreeToRadianConverter(endAngle); var angle = (startAngle + endAngle) / 2; Adornments.Add(PieSeries3D.CreateAdornment(this, x, y, angle, radius, startDepth)); Adornments[(int)x].Item = this.ActualData[index]; }
/// <summary> /// Called when VisibleRange property changed /// </summary> protected override void OnVisibleRangeChanged(VisibleRangeChangedEventArgs e) { if (AdornmentsInfo != null && isAdornmentPending) { if (xValues != null && ActualXAxis != null && !ActualXAxis.VisibleRange.IsEmpty) { double xBase = ActualXAxis.IsLogarithmic ? (ActualXAxis as LogarithmicAxis).LogarithmicBase : 1; bool xIsLogarithmic = ActualXAxis.IsLogarithmic; double start = ActualXAxis.VisibleRange.Start; double end = ActualXAxis.VisibleRange.End; for (int i = 0; i < DataCount; i++) { double x, y; if (this.ActualXAxis is CategoryAxis && !(this.ActualXAxis as CategoryAxis).IsIndexed) { if (i < xValues.Count) { y = GroupedSeriesYValues[0][i]; x = xValues[i]; } else { return; } } else { x = xValues[i]; y = YValues[i]; } double edgeValue = xIsLogarithmic ? Math.Log(x, xBase) : x; if (edgeValue >= start && edgeValue <= end && !double.IsNaN(y)) { if (i < Adornments.Count) { Adornments[i].SetData(x, y, x, y); Adornments[i].Item = ActualData[i]; } else { Adornments.Add(this.CreateAdornment(this, x, y, x, y)); Adornments[Adornments.Count - 1].Item = ActualData[i]; } } } } isAdornmentPending = false; } }
/// <summary> /// Method implementation for Add Adornments at XY /// </summary> /// <param name="x">The X Value</param> /// <param name="y">The Y Value</param> /// <param name="pointindex">The Point Index</param> /// <param name="startDepth">The Start Depth</param> protected virtual void AddAdornmentAtXY(double x, double y, int pointindex, double startDepth) { double adornposX = x, adornposY = y; if (pointindex < Adornments.Count) { Adornments[pointindex].SetData(x, y, adornposX, adornposY); } else { Adornments.Add(this.CreateAdornment(this, x, y, adornposX, adornposY, startDepth)); } }
/// <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)); } } } }
/// <summary> /// Method implementation for Add ColumnAdornments in Chart /// </summary> /// <param name="values"></param> protected virtual void AddColumnAdornments(params double[] values) { ////values[0] --> xData ////values[1] --> yData ////values[2] --> xPos ////values[3] --> yPos ////values[4] --> data point index ////values[5] --> Median value. double adornposX = values[2] + values[5], adornposY = values[3]; int pointIndex = (int)values[4]; if ((EmptyPointIndexes != null && EmptyPointIndexes.Any() && EmptyPointIndexes[0].Contains(pointIndex) && (EmptyPointStyle == Charts.EmptyPointStyle.Symbol || EmptyPointStyle == Charts.EmptyPointStyle.SymbolAndInterior))) { if (this is StackingSeriesBase) { adornposY = (EmptyPointValue == EmptyPointValue.Average) ? values[3] : values[1]; } else { adornposY = values[1]; // WPF-13874-EmptyPoint segment adornmentinfo positioning wrongly when EmptyPointValues is Average } } if (pointIndex < Adornments.Count) { Adornments[pointIndex].SetData(values[0], values[1], adornposX, adornposY); } else { Adornments.Add(CreateAdornment(this, values[0], values[1], adornposX, adornposY)); } if (!(this is HistogramSeries)) { if (ActualXAxis is CategoryAxis && !(ActualXAxis as CategoryAxis).IsIndexed && this.GroupedActualData.Count > 0) { Adornments[pointIndex].Item = this.GroupedActualData[pointIndex]; } else { Adornments[pointIndex].Item = ActualData[pointIndex]; } } }
private void AddAdornments(double x, double yValue, int i) { double adornX = 0d, adornY = 0d; adornX = x; adornY = yValue; if (i < Adornments.Count) { Adornments[i].SetData(adornX, adornY, adornX, adornY); } else { Adornments.Add(this.CreateAdornment(this, adornX, adornY, adornX, adornY)); } Adornments[i].Item = ActualData[i]; }
/// <summary> /// Adds the adornment to the adornments collection. /// </summary> /// <param name="xValue">The X Value</param> /// <param name="yValue">The Y Value</param> /// <param name="index">The Index</param> /// <param name="depth">The Depth</param> protected virtual void AddAdornments(double xValue, double yValue, int index, double depth) { double adornX = 0d, adornY = 0d; adornX = xValue; adornY = yValue; if (index < Adornments.Count) { Adornments[index].SetData(adornX, adornY, adornX, adornY, depth); } else { Adornments.Add(this.CreateAdornment(this, adornX, adornY, adornX, adornY, depth)); } Adornments[index].Item = this.ActualData[index]; }
/// <summary> /// Method implementation for Add Adornments at XY /// </summary> /// <param name="x"></param> /// <param name="y"></param> /// <param name="pointindex"></param> protected virtual void AddAdornmentAtXY(double x, double y, int pointindex) { double adornposX = x, adornposY = y; if (pointindex < Adornments.Count) { Adornments[pointindex].SetData(x, y, adornposX, adornposY); } else { Adornments.Add(CreateAdornment(this, x, y, adornposX, adornposY)); } if (pointindex < ActualData.Count) { Adornments[pointindex].Item = ActualData[pointindex]; } }
private void AddDoughnutAdornments(double x, double y, double startAngle, double endAngle, int i, int index) { double angle = (startAngle + endAngle) / 2; if (Area == null || Area.RootPanelDesiredSize == null || Area.RootPanelDesiredSize.Value == null) { return; } var actualheight = Area.RootPanelDesiredSize.Value.Height; var actualwidth = Area.RootPanelDesiredSize.Value.Width; double doughnutIndex = 0d, actualRadius = 0d, remainingWidth = 0, equalParts = 0d, radius = 0d; if (IsStackedDoughnut) { int doughnutSegmentsCount = DataCount; actualRadius = this.InternalDoughnutSize * (Math.Min(actualwidth, actualheight)) / 2; remainingWidth = actualRadius - (actualRadius * ActualArea.InternalDoughnutHoleSize); equalParts = (remainingWidth / doughnutSegmentsCount) * InternalDoughnutCoefficient; // Segments count is not updated so datacount is used. For more safer update in dynamic updates the radius is also updated in the ChartPieAdornment.Update. radius = actualRadius - (equalParts * (doughnutSegmentsCount - (index + 1))); } else { var doughnutSeries = (from series in Area.VisibleSeries where series is DoughnutSeries select series).ToList(); var doughnutSeriesCount = doughnutSeries.Count(); doughnutIndex = doughnutSeries.IndexOf(this); actualRadius = this.InternalDoughnutSize * (Math.Min(actualwidth, actualheight)) / 2; remainingWidth = actualRadius - (actualRadius * Area.InternalDoughnutHoleSize); equalParts = remainingWidth / doughnutSeriesCount; radius = actualRadius - (equalParts * (doughnutSeriesCount - (doughnutIndex + 1))); } if (index < Adornments.Count) { Adornments[index].SetData(x, y, angle, radius); } else { Adornments.Add(this.CreateAdornment(this, x, y, angle, radius)); } Adornments[index].Item = !double.IsNaN(GroupTo) ? Segments[index].Item : ActualData[index]; }
/// <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> /// Method implementation for Add AreaAdornments in ChartAdornments /// </summary> /// <param name="values"></param> protected virtual void AddAreaAdornments(params IList <double>[] values) { IList <double> yValues = values[0]; List <double> xValues = new List <double>(); if (ActualXAxis is CategoryAxis && !(ActualXAxis as CategoryAxis).IsIndexed) { xValues = GroupedXValuesIndexes; } else { xValues = GetXValues(); } if (values.Length == 1) { int i; for (i = 0; i < DataCount; i++) { if (i < xValues.Count && i < yValues.Count) { double adornX = xValues[i]; double adornY = yValues[i]; if (i < Adornments.Count) { Adornments[i].SetData(xValues[i], yValues[i], adornX, adornY); } else { Adornments.Add(CreateAdornment(this, xValues[i], yValues[i], adornX, adornY)); } Adornments[i].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> /// 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]; } }
/// <summary> /// Creates the Segments of RadarSeries. /// </summary> public override void CreateSegments() { Segments.Clear(); Segment = null; if (DrawType == ChartSeriesDrawType.Area) { double Origin = this.ActualXAxis != null ? this.ActualXAxis.Origin : 0; List <double> xValues = GetXValues().ToList(); List <double> tempYValues = new List <double>(); tempYValues = (from val in YValues select val).ToList(); if (xValues != null) { if (!IsClosed) { xValues.Insert((int)DataCount - 1, xValues[(int)DataCount - 1]); xValues.Insert(0, xValues[0]); tempYValues.Insert(0, Origin); tempYValues.Insert(tempYValues.Count, Origin); } else { xValues.Insert(0, xValues[0]); tempYValues.Insert(0, YValues[0]); xValues.Insert(0, xValues[(int)DataCount]); tempYValues.Insert(0, YValues[(int)DataCount - 1]); } if (Segment == null) { Segment = new AreaSegment(xValues, tempYValues, this, null); Segment.SetData(xValues, tempYValues); Segments.Add(Segment); } else { Segment.SetData(xValues, tempYValues); } if (AdornmentsInfo != null) { AddAreaAdornments(YValues); } } } else if (DrawType == ChartSeriesDrawType.Line) { int index = -1; int i = 0; double xIndexValues = 0d; List <double> xValues = ActualXValues as List <double>; if (IsIndexed || xValues == null) { xValues = xValues != null ? (from val in (xValues)select(xIndexValues++)).ToList() : (from val in (ActualXValues as List <string>)select(xIndexValues++)).ToList(); } if (xValues != null) { for (i = 0; i < this.DataCount; i++) { index = i + 1; if (index < this.DataCount) { if (i < Segments.Count) { (Segments[i]).SetData(xValues[i], YValues[i], xValues[index], YValues[index]); } else { LineSegment line = new LineSegment(xValues[i], YValues[i], xValues[index], YValues[index], this, this); Segments.Add(line); } } if (AdornmentsInfo != null) { if (i < Adornments.Count) { Adornments[i].SetData(xValues[i], YValues[i], xValues[i], YValues[i]); } else { Adornments.Add(this.CreateAdornment(this, xValues[i], YValues[i], xValues[i], YValues[i])); } Adornments[i].Item = ActualData[i]; } } if (IsClosed) { LineSegment line = new LineSegment(xValues[0], YValues[0], xValues[i - 1], YValues[i - 1], this, this); Segments.Add(line); } if (ShowEmptyPoints) { UpdateEmptyPointSegments(xValues, false); } } } }
internal void AddAdornments(double xVal, double xOffset, double high, double low, int index) { double adornX = 0d, adornTop = 0d, adornBottom = 0d; ActualLabelPosition topLabelPosition; ActualLabelPosition bottomLabelPosition; ChartAdornment chartAdornment; var isRangeColumnSingleValue = this is RangeColumnSeries && !IsMultipleYPathRequired; if (this.AdornmentsInfo.AdornmentsPosition == AdornmentsPosition.Top && !isRangeColumnSingleValue) { adornX = xVal + xOffset; if (high > low) { adornTop = high; } else { adornTop = low; } topLabelPosition = this.IsActualTransposed ? this.ActualYAxis.IsInversed ? ActualLabelPosition.Left : ActualLabelPosition.Right : this.ActualYAxis.IsInversed ? ActualLabelPosition.Bottom : ActualLabelPosition.Top; if (index < Adornments.Count) { Adornments[index].ActualLabelPosition = topLabelPosition; Adornments[index].SetData(xVal, adornTop, adornX, adornTop); } else { chartAdornment = this.CreateAdornment(this, xVal, adornTop, adornX, adornTop); chartAdornment.ActualLabelPosition = topLabelPosition; Adornments.Add(chartAdornment); } Adornments[index].Item = ActualData[index]; } else if (this.AdornmentsInfo.AdornmentsPosition == AdornmentsPosition.Bottom && !isRangeColumnSingleValue) { adornX = xVal + xOffset; if (high > low) { adornBottom = low; } else { adornBottom = high; } bottomLabelPosition = this.IsActualTransposed ? this.ActualYAxis.IsInversed ? ActualLabelPosition.Right : ActualLabelPosition.Left : this.ActualYAxis.IsInversed ? ActualLabelPosition.Top : ActualLabelPosition.Bottom; if (index < Adornments.Count) { Adornments[index].ActualLabelPosition = bottomLabelPosition; Adornments[index].SetData(xVal, adornBottom, adornX, adornBottom); } else { chartAdornment = this.CreateAdornment(this, xVal, adornBottom, adornX, adornBottom); chartAdornment.ActualLabelPosition = bottomLabelPosition; Adornments.Add(chartAdornment); } Adornments[index].Item = ActualData[index]; } else { adornX = xVal + xOffset; if (this.IsActualTransposed) { if (this.ActualYAxis.IsInversed) { topLabelPosition = ActualLabelPosition.Left; bottomLabelPosition = ActualLabelPosition.Right; } else { topLabelPosition = ActualLabelPosition.Right; bottomLabelPosition = ActualLabelPosition.Left; } } else { if (this.ActualYAxis.IsInversed) { topLabelPosition = ActualLabelPosition.Bottom; bottomLabelPosition = ActualLabelPosition.Top; } else { topLabelPosition = ActualLabelPosition.Top; bottomLabelPosition = ActualLabelPosition.Bottom; } } if (high > low) { adornTop = high; adornBottom = low; } else { adornTop = low; adornBottom = high; } var adornmentCount = isRangeColumnSingleValue ? Adornments.Count : Adornments.Count / 2; if (index < adornmentCount) { if (isRangeColumnSingleValue) { Adornments[index].ActualLabelPosition = topLabelPosition; Adornments[index].SetData(xVal, adornTop, adornX, adornTop); } else { int j = 2 * index; Adornments[j].ActualLabelPosition = topLabelPosition; Adornments[j++].SetData(xVal, adornTop, adornX, adornTop); Adornments[j].ActualLabelPosition = bottomLabelPosition; Adornments[j].SetData(xVal, adornBottom, adornX, adornBottom); } } else { chartAdornment = this.CreateAdornment(this, xVal, adornTop, adornX, adornTop); chartAdornment.ActualLabelPosition = topLabelPosition; Adornments.Add(chartAdornment); if (isRangeColumnSingleValue) { Adornments[index].Item = ActualData[index]; return; } chartAdornment = this.CreateAdornment(this, xVal, adornBottom, adornX, adornBottom); chartAdornment.ActualLabelPosition = bottomLabelPosition; Adornments.Add(chartAdornment); } if (!isRangeColumnSingleValue) { int k = 2 * index; Adornments[k++].Item = ActualData[index]; Adornments[k].Item = ActualData[index]; } else { Adornments[index].Item = ActualData[index]; } } }
internal void AddAdornments(double xVal, ChartPoint highPt, ChartPoint lowPt, ChartPoint startOpenPt, ChartPoint endOpenPt, ChartPoint startClosePt, ChartPoint endClosePt, int i, double median) { double adornX1, adornX2, adornX3, adornX4, adornMax, adornMin, adornOpen, adornClose; ActualLabelPosition topLabelPosition; ActualLabelPosition leftLabelPosition; ActualLabelPosition bottomLabelPosition; ActualLabelPosition rightLabelPosition; ChartAdornment chartAdornment; // To check whether the high or low value is empty bool isEmpty = double.IsNaN(highPt.Y) || double.IsNaN(lowPt.Y); // When high or low value is empty, the empty point must be considered instead of the greatest value for AdornmentPosition. if (isEmpty || highPt.Y > lowPt.Y) { adornMax = highPt.Y; adornMin = lowPt.Y; } else { adornMax = lowPt.Y; adornMin = highPt.Y; } // To check whether the open or close value is empty. isEmpty = double.IsNaN(startOpenPt.Y) || double.IsNaN(startClosePt.Y); if (this.AdornmentsInfo.AdornmentsPosition == AdornmentsPosition.Top) { adornX1 = highPt.X; // When open or close value is empty, the empty point must be considered instead of the greatest value for the top AdornmentPostion. if (isEmpty || startOpenPt.Y > startClosePt.Y) { adornOpen = startOpenPt.Y; if (this is HiLoOpenCloseSeries || this is FastHiLoOpenCloseBitmapSeries) { adornX2 = startOpenPt.X; } else { adornX2 = highPt.X - median; } if (this.IsActualTransposed) { topLabelPosition = this.ActualYAxis.IsInversed ? ActualLabelPosition.Left : ActualLabelPosition.Right; leftLabelPosition = this.ActualXAxis.IsInversed ? ActualLabelPosition.Top : ActualLabelPosition.Bottom; } else { topLabelPosition = this.ActualYAxis.IsInversed ? ActualLabelPosition.Bottom : ActualLabelPosition.Top; leftLabelPosition = this.ActualXAxis.IsInversed ? ActualLabelPosition.Right : ActualLabelPosition.Left; } } else { adornOpen = startClosePt.Y; if (this is HiLoOpenCloseSeries || this is FastHiLoOpenCloseBitmapSeries) { adornX2 = startClosePt.X; } else { adornX2 = highPt.X + median; } if (this.IsActualTransposed) { topLabelPosition = this.ActualYAxis.IsInversed ? ActualLabelPosition.Left : ActualLabelPosition.Right; leftLabelPosition = this.ActualXAxis.IsInversed ? ActualLabelPosition.Bottom : ActualLabelPosition.Top; } else { topLabelPosition = this.ActualYAxis.IsInversed ? ActualLabelPosition.Bottom : ActualLabelPosition.Top; leftLabelPosition = this.ActualXAxis.IsInversed ? ActualLabelPosition.Left : ActualLabelPosition.Right; } } if (this is CandleSeries || this is FastCandleBitmapSeries) { leftLabelPosition = topLabelPosition; } if (i < Adornments.Count / 2) { int j = 2 * i; Adornments[j].ActualLabelPosition = topLabelPosition; Adornments[j++].SetData(xVal, adornMax, adornX1, adornMax); Adornments[j].ActualLabelPosition = leftLabelPosition; Adornments[j].SetData(xVal, adornOpen, adornX2, adornOpen); } else { chartAdornment = this.CreateAdornment(this, xVal, adornMax, adornX1, adornMax); chartAdornment.ActualLabelPosition = topLabelPosition; Adornments.Add(chartAdornment); chartAdornment = this.CreateAdornment(this, xVal, adornOpen, adornX2, adornOpen); chartAdornment.ActualLabelPosition = leftLabelPosition; Adornments.Add(chartAdornment); } int k = 2 * i; Adornments[k++].Item = ActualData[i]; Adornments[k].Item = ActualData[i]; } else if (this.AdornmentsInfo.AdornmentsPosition == AdornmentsPosition.Bottom) { adornX1 = lowPt.X; // When open or close value is empty, the empty point must be considered instead of the smallest value for the bottom AdornmentPosition. if (isEmpty || startClosePt.Y < startOpenPt.Y) { adornClose = endClosePt.Y; if (this is HiLoOpenCloseSeries || this is FastHiLoOpenCloseBitmapSeries) { adornX2 = startClosePt.X; } else { adornX2 = lowPt.X + median; } if (this.IsActualTransposed) { bottomLabelPosition = this.ActualYAxis.IsInversed ? ActualLabelPosition.Right : ActualLabelPosition.Left; rightLabelPosition = this.ActualXAxis.IsInversed ? ActualLabelPosition.Bottom : ActualLabelPosition.Top; } else { bottomLabelPosition = this.ActualYAxis.IsInversed ? ActualLabelPosition.Top : ActualLabelPosition.Bottom; rightLabelPosition = this.ActualXAxis.IsInversed ? ActualLabelPosition.Left : ActualLabelPosition.Right; } } else { adornClose = startOpenPt.Y; if (this is HiLoOpenCloseSeries || this is FastHiLoOpenCloseBitmapSeries) { adornX2 = startOpenPt.X; } else { adornX2 = lowPt.X - median; } if (this.IsActualTransposed) { bottomLabelPosition = this.ActualYAxis.IsInversed ? ActualLabelPosition.Right : ActualLabelPosition.Left; rightLabelPosition = this.ActualXAxis.IsInversed ? ActualLabelPosition.Top : ActualLabelPosition.Bottom; } else { bottomLabelPosition = this.ActualYAxis.IsInversed ? ActualLabelPosition.Top : ActualLabelPosition.Bottom; rightLabelPosition = this.ActualXAxis.IsInversed ? ActualLabelPosition.Right : ActualLabelPosition.Left; } } if (this is CandleSeries || this is FastCandleBitmapSeries) { rightLabelPosition = bottomLabelPosition; } if (i < Adornments.Count / 2) { int j = 2 * i; Adornments[j].ActualLabelPosition = bottomLabelPosition; Adornments[j++].SetData(xVal, adornMin, adornX1, adornMin); Adornments[j].ActualLabelPosition = rightLabelPosition; Adornments[j].SetData(xVal, adornClose, adornX2, adornClose); } else { chartAdornment = this.CreateAdornment(this, xVal, adornMin, adornX1, adornMin); chartAdornment.ActualLabelPosition = bottomLabelPosition; Adornments.Add(chartAdornment); chartAdornment = this.CreateAdornment(this, xVal, adornClose, adornX2, adornClose); chartAdornment.ActualLabelPosition = rightLabelPosition; Adornments.Add(chartAdornment); } int k = 2 * i; Adornments[k++].Item = ActualData[i]; Adornments[k].Item = ActualData[i]; } else { adornX1 = highPt.X; if (this is HiLoOpenCloseSeries || this is FastHiLoOpenCloseBitmapSeries) { adornX2 = startClosePt.X; adornX4 = startOpenPt.X; } else { adornX2 = highPt.X + median; adornX4 = lowPt.X - median; } adornX3 = lowPt.X; adornOpen = startOpenPt.Y; adornClose = endClosePt.Y; if (this.IsActualTransposed) { topLabelPosition = this.ActualYAxis.IsInversed ? ActualLabelPosition.Left : ActualLabelPosition.Right; leftLabelPosition = this.ActualXAxis.IsInversed ? ActualLabelPosition.Top : ActualLabelPosition.Bottom; bottomLabelPosition = this.ActualYAxis.IsInversed ? ActualLabelPosition.Right : ActualLabelPosition.Left; rightLabelPosition = this.ActualXAxis.IsInversed ? ActualLabelPosition.Bottom : ActualLabelPosition.Top; } else { topLabelPosition = this.ActualYAxis.IsInversed ? ActualLabelPosition.Bottom : ActualLabelPosition.Top; leftLabelPosition = this.ActualXAxis.IsInversed ? ActualLabelPosition.Right : ActualLabelPosition.Left; bottomLabelPosition = this.ActualYAxis.IsInversed ? ActualLabelPosition.Top : ActualLabelPosition.Bottom; rightLabelPosition = this.ActualXAxis.IsInversed ? ActualLabelPosition.Left : ActualLabelPosition.Right; } if (this is CandleSeries || this is FastCandleBitmapSeries) { leftLabelPosition = topLabelPosition; rightLabelPosition = bottomLabelPosition; } if (i < Adornments.Count / 4) { int j = 4 * i; Adornments[j].ActualLabelPosition = topLabelPosition; Adornments[j++].SetData(xVal, adornMax, adornX1, adornMax); Adornments[j].ActualLabelPosition = leftLabelPosition; Adornments[j++].SetData(xVal, adornOpen, adornX4, adornOpen); Adornments[j].ActualLabelPosition = bottomLabelPosition; Adornments[j++].SetData(xVal, adornMin, adornX3, adornMin); Adornments[j].ActualLabelPosition = rightLabelPosition; Adornments[j].SetData(xVal, adornClose, adornX2, adornClose); } else { chartAdornment = this.CreateAdornment(this, xVal, adornMax, adornX1, adornMax); chartAdornment.ActualLabelPosition = topLabelPosition; Adornments.Add(chartAdornment); chartAdornment = this.CreateAdornment(this, xVal, adornOpen, adornX4, adornOpen); chartAdornment.ActualLabelPosition = leftLabelPosition; Adornments.Add(chartAdornment); chartAdornment = this.CreateAdornment(this, xVal, adornMin, adornX3, adornMin); chartAdornment.ActualLabelPosition = bottomLabelPosition; Adornments.Add(chartAdornment); chartAdornment = this.CreateAdornment(this, xVal, adornClose, adornX2, adornClose); chartAdornment.ActualLabelPosition = rightLabelPosition; Adornments.Add(chartAdornment); } int k = 4 * i; Adornments[k++].Item = ActualData[i]; Adornments[k++].Item = ActualData[i]; Adornments[k++].Item = ActualData[i]; Adornments[k].Item = ActualData[i]; } }
protected override void OnVisibleRangeChanged(VisibleRangeChangedEventArgs e) { if (AdornmentsInfo != null && isAdornmentPending) { List <double> xValues = null; var isGrouped = ActualXAxis is CategoryAxis && !(ActualXAxis as CategoryAxis).IsIndexed; if (isGrouped) { xValues = GroupedXValuesIndexes; } else { xValues = GetXValues(); } if (xValues != null && ActualXAxis != null && !ActualXAxis.VisibleRange.IsEmpty) { double xBase = ActualXAxis.IsLogarithmic ? (ActualXAxis as LogarithmicAxis).LogarithmicBase : 1; double start = ActualXAxis.VisibleRange.Start; double end = ActualXAxis.VisibleRange.End; if (isGrouped) { for (int i = 0; i < xValues.Count; i++) { if (i < xValues.Count) { double x = xValues[i]; double actualX = ActualXAxis.IsLogarithmic ? Math.Log(x, xBase) : x; if (actualX >= start && actualX <= end) { double y = GroupedSeriesYValues[0][i]; if (i < Adornments.Count) { Adornments[i].SetData(x, y, x, y); } else { Adornments.Add(this.CreateAdornment(this, x, y, x, y)); } Adornments[i].Item = ActualData[i]; } } } } else { for (int i = 0; i < DataCount; i++) { double x = xValues[i]; double actualX = ActualXAxis.IsLogarithmic ? Math.Log(x, xBase) : x; if (actualX >= start && actualX <= end) { double y = YValues[i]; if (i < Adornments.Count) { Adornments[i].SetData(x, y, x, y); } else { Adornments.Add(this.CreateAdornment(this, x, y, x, y)); } Adornments[i].Item = ActualData[i]; } } } } isAdornmentPending = false; } }
/// <summary> /// Creates the segments of StepLineSeries. /// </summary> public override void CreateSegments() { List <double> xValues = null; bool isGrouping = this.ActualXAxis is CategoryAxis && !(this.ActualXAxis as CategoryAxis).IsIndexed; if (isGrouping) { xValues = GroupedXValuesIndexes; } else { xValues = GetXValues(); } if (xValues == null) { return; } double xOffset = 0d; if (ActualXAxis is CategoryAxis && (ActualXAxis as CategoryAxis).LabelPlacement == LabelPlacement.BetweenTicks) { xOffset = 0.5d; } if (isGrouping) { Segments.Clear(); Adornments.Clear(); for (int i = 0; i < xValues.Count; i++) { int index = i + 1; ChartPoint point1, point2, stepPoint; if (AdornmentsInfo != null) { Adornments.Add(this.CreateAdornment(this, xValues[i], GroupedSeriesYValues[0][i], xValues[i], GroupedSeriesYValues[0][i])); Adornments[i].Item = ActualData[i]; } if (index < xValues.Count) { point1 = new ChartPoint(xValues[i] - xOffset, GroupedSeriesYValues[0][i]); point2 = new ChartPoint(xValues[index] - xOffset, GroupedSeriesYValues[0][i]); stepPoint = new ChartPoint(xValues[index] - xOffset, GroupedSeriesYValues[0][index]); } else { if (!(xOffset > 0)) { continue; } point1 = new ChartPoint(xValues[i] - xOffset, GroupedSeriesYValues[0][i]); point2 = new ChartPoint(xValues[i] + xOffset, GroupedSeriesYValues[0][i]); stepPoint = new ChartPoint(xValues[i] - xOffset, GroupedSeriesYValues[0][i]); } var segment = new StepLineSegment(point1, stepPoint, point2, this) { Item = ActualData[i] }; segment.Series = this; List <ChartPoint> listPoints = new List <ChartPoint>(); listPoints.Add(point1); listPoints.Add(stepPoint); listPoints.Add(point2); segment.SetData(listPoints); Segments.Add(segment); listPoints = null; } } else { ClearUnUsedStepLineSegment(DataCount); ClearUnUsedAdornments(DataCount); for (int i = 0; i < DataCount; i++) { int index = i + 1; ChartPoint point1, point2, stepPoint; if (AdornmentsInfo != null) { if (i < Adornments.Count) { Adornments[i].SetData(xValues[i], YValues[i], xValues[i], YValues[i]); Adornments[i].Item = ActualData[i]; } else { Adornments.Add(this.CreateAdornment(this, xValues[i], YValues[i], xValues[i], YValues[i])); Adornments[i].Item = ActualData[i]; } } if (index < DataCount) { point1 = new ChartPoint(xValues[i] - xOffset, YValues[i]); point2 = new ChartPoint(xValues[index] - xOffset, YValues[i]); stepPoint = new ChartPoint(xValues[index] - xOffset, YValues[index]); } else { if (!(xOffset > 0)) { continue; } point1 = new ChartPoint(xValues[i] - xOffset, YValues[i]); point2 = new ChartPoint(xValues[i] + xOffset, YValues[i]); stepPoint = new ChartPoint(xValues[i] - xOffset, YValues[i]); } if (i < Segments.Count) { Segments[i].SetData(new List <ChartPoint> { point1, stepPoint, point2 }); Segments[i].Item = ActualData[i]; (Segments[i] as StepLineSegment).YData = YValues[i]; if (SegmentColorPath != null && !Segments[i].IsEmptySegmentInterior && ColorValues.Count > 0 && !Segments[i].IsSelectedSegment) { Segments[i].Interior = (Interior != null) ? Interior : ColorValues[i]; } } else { var segment = new StepLineSegment(point1, stepPoint, point2, this) { Item = ActualData[i] }; segment.Series = this; List <ChartPoint> listPoints = new List <ChartPoint>(); listPoints.Add(point1); listPoints.Add(stepPoint); listPoints.Add(point2); segment.SetData(listPoints); Segments.Add(segment); listPoints = null; } } } if (ShowEmptyPoints) { UpdateEmptyPointSegments(xValues, false); } }