/// <summary> /// Creates the segments of Box and Whisker Series. /// </summary> public override void CreateSegments() { ClearUnUsedSegments(this.DataCount); ClearUnUsedAdornments(this.DataCount * 5); DoubleRange sbsInfo = this.GetSideBySideInfo(this); double start = sbsInfo.Start; double end = sbsInfo.End; List <double> xValues = GetXValues(); ////UpdatePercentile(); UpdateWhiskerWidth(); if (adornmentInfo != null) { UpdateAdornmentLabelPositiion(); } outlierSegments = new List <ChartSegment>(); if (YCollection == null || YCollection.Count == 0) { return; } for (int i = 0; i < DataCount; i++) { double median, lowerQuartile, upperQuartile, minimum, maximum, x1, x2, average = 0d; List <double> outliers = new List <double>(); var ylist = YCollection[i].Where(x => !double.IsNaN(x)).ToArray(); if (ylist.Count() > 0) { Array.Sort(ylist); average = ylist.Average(); } int yCount = ylist.Length; isEvenList = yCount % 2 == 0; // Getting the required values. x1 = xValues[i] + start; x2 = xValues[i] + end; if (yCount == 0) { ////To create an empty segment for the additional space requirement in range calculation. if (i < Segments.Count) { var segment = Segments[i] as BoxAndWhiskerSegment; segment.SetData(x1, x2, double.NaN, double.NaN, double.NaN, double.NaN, double.NaN, double.NaN, double.NaN, xValues[i] + sbsInfo.Median, double.NaN); segment.Item = ActualData[i]; } else { BoxAndWhiskerSegment boxEmptySegment = new BoxAndWhiskerSegment(this); boxEmptySegment.SetData(x1, x2, double.NaN, double.NaN, double.NaN, double.NaN, double.NaN, double.NaN, double.NaN, xValues[i] + sbsInfo.Median, double.NaN); boxEmptySegment.Item = ActualData[i]; Segments.Add(boxEmptySegment); } if (AdornmentsInfo != null) { if (i < Adornments.Count / 5) { SetBoxWhiskerAdornments(sbsInfo, xValues[i], double.NaN, double.NaN, x1, double.NaN, double.NaN, double.NaN, outliers, i); } else { AddBoxWhiskerAdornments(sbsInfo, xValues[i], double.NaN, double.NaN, x1, double.NaN, double.NaN, double.NaN, outliers, i); } } continue; } if (BoxPlotMode == BoxPlotMode.Exclusive) { lowerQuartile = GetExclusiveQuartileValue(ylist, yCount, 0.25d); upperQuartile = GetExclusiveQuartileValue(ylist, yCount, 0.75d); median = GetExclusiveQuartileValue(ylist, yCount, 0.5d); } else if (BoxPlotMode == BoxPlotMode.Inclusive) { lowerQuartile = GetInclusiveQuartileValue(ylist, yCount, 0.25d); upperQuartile = GetInclusiveQuartileValue(ylist, yCount, 0.75d); median = GetInclusiveQuartileValue(ylist, yCount, 0.5d); } else { // Take the first half of the list. median = GetMedianValue(ylist); GetQuartileValues(ylist, yCount, out lowerQuartile, out upperQuartile); } GetMinMaxandOutlier(lowerQuartile, upperQuartile, ylist, out minimum, out maximum, outliers); double actualMinimum = minimum; double actualMaximum = maximum; if (outliers.Count > 0) { actualMinimum = Math.Min(outliers.Min(), actualMinimum); actualMaximum = Math.Max(outliers.Max(), actualMaximum); } ChartSegment currentSegment = null; if (i < Segments.Count) { currentSegment = Segments[i]; var segment = Segments[i] as BoxAndWhiskerSegment; segment.SetData(x1, x2, actualMinimum, minimum, lowerQuartile, median, upperQuartile, maximum, actualMaximum, xValues[i] + sbsInfo.Median, average); WhiskerWidth = whiskerWidth; segment.Item = ActualData[i]; } else { BoxAndWhiskerSegment boxSegment = new BoxAndWhiskerSegment(this); boxSegment.SetData(x1, x2, actualMinimum, minimum, lowerQuartile, median, upperQuartile, maximum, actualMaximum, xValues[i] + sbsInfo.Median, average); boxSegment.Item = ActualData[i]; boxSegment.Outliers = outliers; boxSegment.WhiskerWidth = whiskerWidth; currentSegment = boxSegment; Segments.Add(boxSegment); } if (AdornmentsInfo != null) { if (i < Adornments.Count / 5) { SetBoxWhiskerAdornments(sbsInfo, xValues[i], minimum, maximum, x1, median, lowerQuartile, upperQuartile, outliers, i); } else { AddBoxWhiskerAdornments(sbsInfo, xValues[i], minimum, maximum, x1, median, lowerQuartile, upperQuartile, outliers, i); } } if (outliers.Count > 0) { foreach (var outlier in outliers) { ScatterSegment scatterSegment = new ScatterSegment(); var position = x1 + (x2 - x1) / 2; scatterSegment.SetData(position, outlier); scatterSegment.ScatterWidth = 10; scatterSegment.ScatterHeight = 10; scatterSegment.Item = ActualData[i]; scatterSegment.Series = this; scatterSegment.CustomTemplate = OutlierTemplate; // The bindings are done with the segment not with the series. BindProperties(scatterSegment, currentSegment); outlierSegments.Add(scatterSegment); } } isEvenList = false; } foreach (ScatterSegment outlierSegment in outlierSegments) { this.Segments.Add(outlierSegment); if (AdornmentsInfo != null) { var adornment = this.CreateAdornment(this, outlierSegment.XData, outlierSegment.YData, outlierSegment.XData, outlierSegment.YData); adornment.ActualLabelPosition = topLabelPosition; adornment.Item = outlierSegment.Item; this.Adornments.Add(adornment); } } }
/// <summary> /// creates the segments of StackingColumnSeries. /// </summary> public override void CreateSegments() { List <double> xValues = null; var isGrouped = ActualXAxis is CategoryAxis && !(ActualXAxis as CategoryAxis).IsIndexed; DoubleRange sbsInfo = this.GetSideBySideInfo(this); double x1, x2, y1, y2; double Origin = this.ActualXAxis != null ? this.ActualXAxis.Origin : 0; if (ActualXAxis != null && ActualXAxis.Origin == 0 && ActualYAxis is LogarithmicAxis && (ActualYAxis as LogarithmicAxis).Minimum != null) { Origin = (double)(ActualYAxis as LogarithmicAxis).Minimum; } double median = sbsInfo.Delta / 2; if (isGrouped) { xValues = GroupedXValuesIndexes; } else { xValues = GetXValues(); } var stackingValues = GetCumulativeStackValues(this); if (stackingValues != null) { YRangeStartValues = stackingValues.StartValues; YRangeEndValues = stackingValues.EndValues; #if NETFX_CORE // Designer crashes when rebuild the SfChart bool _isInDesignMode = Windows.ApplicationModel.DesignMode.DesignModeEnabled; if (_isInDesignMode) { if (YRangeStartValues.Count == 0 && YRangeEndValues.Count == 0) { return; } } #endif if (YRangeStartValues == null) { YRangeStartValues = (from val in xValues select Origin).ToList(); } if (xValues != null) { if (isGrouped) { Segments.Clear(); Adornments.Clear(); int segmentCount = 0; for (int i = 0; i < DistinctValuesIndexes.Count; i++) { for (int j = 0; j < DistinctValuesIndexes[i].Count; j++) { int index = DistinctValuesIndexes[i][j]; if (j < xValues.Count) { x1 = i + sbsInfo.Start; x2 = i + sbsInfo.End; y2 = double.IsNaN(YRangeStartValues[segmentCount]) ? Origin : YRangeStartValues[segmentCount]; y1 = double.IsNaN(YRangeEndValues[segmentCount]) ? Origin : YRangeEndValues[segmentCount]; StackingColumnSegment columnSegment = new StackingColumnSegment(x1, y1, x2, y2, this); columnSegment.XData = xValues[segmentCount]; columnSegment.YData = GroupedSeriesYValues[0][index]; columnSegment.Item = GroupedActualData[segmentCount]; Segments.Add(columnSegment); if (AdornmentsInfo != null) { if (this.AdornmentsInfo.AdornmentsPosition == AdornmentsPosition.Top) { AddColumnAdornments(i, GroupedSeriesYValues[0][index], x1, y1, segmentCount, median); } else if (this.AdornmentsInfo.AdornmentsPosition == AdornmentsPosition.Bottom) { AddColumnAdornments(i, GroupedSeriesYValues[0][index], x1, y2, segmentCount, median); } else { AddColumnAdornments(i, GroupedSeriesYValues[0][index], x1, y1 + (y2 - y1) / 2, segmentCount, median); } } segmentCount++; } } } } else { ClearUnUsedSegments(this.DataCount); ClearUnUsedAdornments(this.DataCount); for (int i = 0; i < DataCount; i++) { x1 = xValues[i] + sbsInfo.Start; x2 = xValues[i] + sbsInfo.End; y2 = double.IsNaN(YRangeStartValues[i]) ? Origin : YRangeStartValues[i]; y1 = double.IsNaN(YRangeEndValues[i]) ? Origin : YRangeEndValues[i]; if (i < Segments.Count) { (Segments[i]).Item = ActualData[i]; (Segments[i] as StackingColumnSegment).XData = xValues[i]; (Segments[i] as StackingColumnSegment).YData = YValues[i]; (Segments[i]).SetData(x1, y1, x2, y2); if (SegmentColorPath != null && !Segments[i].IsEmptySegmentInterior && ColorValues.Count > 0 && !Segments[i].IsSelectedSegment) { Segments[i].Interior = (Interior != null) ? Interior : ColorValues[i]; } } else { StackingColumnSegment columnSegment = new StackingColumnSegment(x1, y1, x2, y2, this); columnSegment.XData = xValues[i]; columnSegment.YData = ActualSeriesYValues[0][i]; columnSegment.Item = ActualData[i]; Segments.Add(columnSegment); } if (AdornmentsInfo != null) { if (this.AdornmentsInfo.AdornmentsPosition == AdornmentsPosition.Top) { AddColumnAdornments(xValues[i], YValues[i], x1, y1, i, median); } else if (this.AdornmentsInfo.AdornmentsPosition == AdornmentsPosition.Bottom) { AddColumnAdornments(xValues[i], YValues[i], x1, y2, i, median); } else { AddColumnAdornments(xValues[i], YValues[i], x1, y1 + (y2 - y1) / 2, i, median); } } } } if (ShowEmptyPoints) { if (this is StackingColumn100Series) { var index = EmptyPointIndexes[0]; if (EmptyPointStyle == Charts.EmptyPointStyle.Symbol || EmptyPointStyle == Charts.EmptyPointStyle.SymbolAndInterior) { foreach (var n in index) { this.ActualSeriesYValues[0][n] = double.IsNaN(YRangeEndValues[n]) ? 0 : this.YRangeEndValues[n]; } } UpdateEmptyPointSegments(xValues, true); ReValidateYValues(EmptyPointIndexes); ValidateYValues(); } else { UpdateEmptyPointSegments(xValues, true); } } } } }
internal static DoubleRange ApplyBusinessHoursRangePadding(DateTimeAxis axis, DoubleRange range, double interval, DateTimeRangePadding rangePadding, DateTimeIntervalType intervalType) { DateTime startDate = range.Start.FromOADate(); DateTime endDate = range.End.FromOADate(); var startTime = new TimeSpan((int)axis.OpenTime, 0, 0); var endTime = new TimeSpan((int)axis.CloseTime, 0, 0); if (rangePadding == DateTimeRangePadding.Round || rangePadding == DateTimeRangePadding.Additional) { switch (intervalType) { case DateTimeIntervalType.Years: int startYear = (int)((int)(startDate.Year / interval) * interval); int endYear = endDate.Year + (startDate.Year - startYear); if (startYear <= 0) { startYear = 1; } if (endYear <= 0) { endYear = 1; } if (rangePadding == DateTimeRangePadding.Round) { range = new DoubleRange(new DateTime(startYear, 1, 1, 0, 0, 0).ToOADate(), new DateTime(endYear, 12, 31, 23, 59, 59).ToOADate()); } else { range = new DoubleRange(new DateTime(startYear - (int)interval, 1, 1, 0, 0, 0).ToOADate(), new DateTime(endYear + (int)interval, 12, 31, 23, 59, 59).ToOADate()); } break; case DateTimeIntervalType.Months: int month = (int)((int)(startDate.Month / interval) * interval); if (month <= 0) { month = 1; } int endmonth = range.End.FromOADate().Month + (startDate.Month - month); if (endmonth <= 0) { endmonth = 1; } if (endmonth > 12) { endmonth = 12; } if (rangePadding == DateTimeRangePadding.Round) { range = new DoubleRange(new DateTime(startDate.Year, month, 1, 0, 0, 0).ToOADate(), new DateTime(endDate.Year, endmonth, endmonth == 2 ? 28 : 30, 0, 0, 0).ToOADate()); } else { range = new DoubleRange(new DateTime(startDate.Year, month, 1, 0, 0, 0).AddMonths((int)(-interval)).ToOADate(), new DateTime(endDate.Year, endmonth, endmonth == 2 ? 28 : 30, 0, 0, 0).AddMonths((int)interval).ToOADate()); } break; case DateTimeIntervalType.Days: int day = (int)((int)(startDate.Day / interval) * interval); if (day <= 0) { day = 1; } int endday = startDate.Day - day; if (endday < 0) { endday = 1; } if (rangePadding == DateTimeRangePadding.Round) { range = new DoubleRange( new DateTime(startDate.Year, startDate.Month, day, startTime.Hours, startTime.Minutes, startTime.Seconds).ToOADate(), new DateTime(endDate.Year, endDate.Month, endDate.Day, endTime.Hours, endTime.Minutes, endTime.Seconds).AddDays(endday).ToOADate()); } else { range = new DoubleRange(new DateTime(startDate.Year, startDate.Month, day, startTime.Hours, startTime.Minutes, startTime.Seconds).AddDays(-interval).ToOADate(), new DateTime(endDate.Year, endDate.Month, endDate.Day, endTime.Hours, endTime.Minutes, endTime.Seconds).AddDays(interval + endday).ToOADate()); } break; case DateTimeIntervalType.Hours: if (rangePadding == DateTimeRangePadding.Round) { range = new DoubleRange( new DateTime( startDate.Year, startDate.Month, startDate.Day, startTime.Hours, 0, 0).ToOADate(), new DateTime( endDate.Year, endDate.Month, endDate.Day, endTime.Hours, 0, 0).ToOADate()); } else { range = new DoubleRange(new DateTime( startDate.Year, startDate.Month, startDate.Day, startDate.Hour, 0, 0).AddHours(-interval).ToOADate(), new DateTime( endDate.Year, endDate.Month, endDate.Day, endDate.Hour, 0, 0).AddHours(interval).ToOADate()); } break; case DateTimeIntervalType.Minutes: int minute = (int)((int)(startDate.Minute / interval) * interval); int endminute = range.End.FromOADate().Minute + (startDate.Minute - minute); if (rangePadding == DateTimeRangePadding.Round) { range = new DoubleRange( new DateTime( startDate.Year, startDate.Month, startDate.Day, startDate.Hour, minute, 0).ToOADate(), new DateTime( endDate.Year, endDate.Month, endDate.Day, endDate.Hour, endminute, 0).ToOADate()); } else { range = new DoubleRange(new DateTime( startDate.Year, startDate.Month, startDate.Day, startDate.Hour, startDate.Minute, 0).AddMinutes(-interval).ToOADate(), new DateTime( endDate.Year, endDate.Month, endDate.Day, endDate.Hour, endDate.Minute, 0).AddMinutes(interval).ToOADate()); } break; case DateTimeIntervalType.Seconds: int second = (int)((int)(startDate.Second / interval) * interval); int endsecond = range.End.FromOADate().Second + (startDate.Second - second); if (rangePadding == DateTimeRangePadding.Round) { range = new DoubleRange( new DateTime( startDate.Year, startDate.Month, startDate.Day, startDate.Hour, startDate.Minute, second, 0).ToOADate(), new DateTime( endDate.Year, endDate.Month, endDate.Day, endDate.Hour, endDate.Minute, endsecond, 0).ToOADate()); } else { range = new DoubleRange(new DateTime( startDate.Year, startDate.Month, startDate.Day, startDate.Hour, startDate.Minute, startDate.Second, 0).AddSeconds(-interval).ToOADate(), new DateTime( endDate.Year, endDate.Month, endDate.Day, endDate.Hour, endDate.Minute, endDate.Second, 0).AddSeconds(interval).ToOADate()); } break; case DateTimeIntervalType.Milliseconds: int milliseconds = (int)((int)(startDate.Millisecond / interval) * interval); int endmilliseconds = range.End.FromOADate().Millisecond + (startDate.Millisecond - milliseconds); if (rangePadding == DateTimeRangePadding.Round) { range = new DoubleRange( new DateTime( startDate.Year, startDate.Month, startDate.Day, startDate.Hour, startDate.Minute, startDate.Second, milliseconds).ToOADate(), new DateTime( endDate.Year, endDate.Month, endDate.Day, endDate.Hour, endDate.Minute, endDate.Second, endmilliseconds).ToOADate()); } else { range = new DoubleRange( new DateTime( startDate.Year, startDate.Month, startDate.Day, startDate.Hour, startDate.Minute, startDate.Second, startDate.Millisecond).AddMilliseconds(-interval).ToOADate(), new DateTime( endDate.Year, endDate.Month, endDate.Day, endDate.Hour, endDate.Minute, endDate.Second, endDate.Millisecond).AddMilliseconds(interval).ToOADate()); } break; } var newStartDate = range.Start.FromOADate(); var newEndDate = range.End.FromOADate(); newStartDate = newStartDate.ValidateNonWorkingDate(axis.InternalWorkingDays, true, axis.NonWorkingDays.Count); newStartDate = newStartDate.ValidateNonWorkingHours(axis.OpenTime, axis.CloseTime, true); newStartDate = newStartDate.ValidateNonWorkingDate(axis.InternalWorkingDays, true, axis.NonWorkingDays.Count); newEndDate = newEndDate.ValidateNonWorkingDate(axis.InternalWorkingDays, false, axis.NonWorkingDays.Count); newEndDate = newEndDate.ValidateNonWorkingHours(axis.OpenTime, axis.CloseTime, false); newEndDate = newEndDate.ValidateNonWorkingDate(axis.InternalWorkingDays, false, axis.NonWorkingDays.Count); return(new DoubleRange(newStartDate.ToOADate(), newEndDate.ToOADate())); } return(range); }
/// <summary> /// Finds the nearest point in ChartSeries relative to the mouse point/touch position. /// </summary> /// <param name="point">The co-ordinate point representing the current mouse point /touch position.</param> /// <param name="x">x-value of the nearest point.</param> /// <param name="y">y-value of the nearest point</param> /// <param name="stackedYValue"></param> public override void FindNearestChartPoint(Point point, out double x, out double y, out double stackedYValue) { x = double.NaN; y = 0d; stackedYValue = double.NaN; Point nearPoint = new Point(); if (this.IsIndexed || !(this.ActualXValues is IList <double>)) { if (ActualArea != null) { double xStart = ActualXAxis.VisibleRange.Start; double xEnd = ActualXAxis.VisibleRange.End; point = new Point(ActualArea.PointToValue(ActualXAxis, point), ActualArea.PointToValue(ActualYAxis, point)); double range = Math.Round(point.X); { var count = this.YCollection.Count; if (range <= xEnd && range >= xStart && range < count && range >= 0) { x = range; } } } } else { IList <double> xValues = this.ActualXValues as IList <double>; nearPoint.X = ActualXAxis.VisibleRange.Start; if (IsSideBySide) { DoubleRange sbsInfo = this.GetSideBySideInfo(this); nearPoint.X = ActualXAxis.VisibleRange.Start + sbsInfo.Start; } point = new Point(ActualArea.PointToValue(ActualXAxis, point), ActualArea.PointToValue(ActualYAxis, point)); for (int i = 0; i < DataCount; i++) { double x1 = xValues[i]; double y1 = 0d; if (this.ActualXAxis is LogarithmicAxis) { var logAxis = ActualXAxis as LogarithmicAxis; if (Math.Abs(point.X - x1) <= Math.Abs(point.X - nearPoint.X) && (Math.Log(point.X, logAxis.LogarithmicBase) > ActualXAxis.VisibleRange.Start && Math.Log(point.X, logAxis.LogarithmicBase) < ActualXAxis.VisibleRange.End)) { nearPoint = new Point(x1, y1); x = xValues[i]; } } else if (Math.Abs((point.X - x1)) <= Math.Abs((point.X - nearPoint.X)) && (point.X > ActualXAxis.VisibleRange.Start) && (point.X < ActualXAxis.VisibleRange.End)) { nearPoint = new Point(x1, y1); x = xValues[i]; } } } }
private void OnCalculateSegmentValues( out double x1, out double x2, out double y1, out double y2, int i, double origin, double xVal) { DoubleRange sbsInfo = this.GetSideBySideInfo(this); #region Datapoint calculation x1 = xVal + sbsInfo.Start; x2 = xVal + sbsInfo.End; if (i == 0) { if (YValues[i] >= 0) { y1 = YValues[i]; y2 = origin; } else if (double.IsNaN(YValues[i])) { y2 = origin; y1 = origin; } else { y2 = YValues[i]; y1 = origin; } } else { WaterfallSegment prevSegment = Segments[i - 1] as WaterfallSegment; // Positive value calculation if (YValues[i] >= 0) { if (YValues[i - 1] >= 0 || prevSegment.SegmentType == WaterfallSegmentType.Sum) { y1 = YValues[i] + prevSegment.Top; y2 = prevSegment.Top; } else if (double.IsNaN(YValues[i - 1])) { y1 = YValues[i] == 0 ? prevSegment.Bottom : prevSegment.Bottom + YValues[i]; y2 = prevSegment.Bottom; } else { y1 = YValues[i] + prevSegment.Bottom; y2 = prevSegment.Bottom; } } else if (double.IsNaN(YValues[i])) { // Empty value calculation if (YValues[i - 1] >= 0 || prevSegment.SegmentType == WaterfallSegmentType.Sum) { y1 = y2 = prevSegment.Top; } else { y1 = y2 = prevSegment.Bottom; } } else { // Negative value calculation if (YValues[i - 1] >= 0 || prevSegment.SegmentType == WaterfallSegmentType.Sum) { y1 = prevSegment.Top; y2 = YValues[i] + prevSegment.Top; } else { y1 = prevSegment.Bottom; y2 = YValues[i] + prevSegment.Bottom; } } } #endregion }
/// <summary> /// This method is used to gets the selected data point segment pixel positions /// </summary> internal void GenerateStackingBarPixels() { WriteableBitmap bmp = Area.fastRenderSurface; ChartTransform.ChartCartesianTransformer cartesianTransformer = CreateTransformer( new Size( Area.SeriesClipRect.Width, Area.SeriesClipRect.Height), true) as ChartTransform.ChartCartesianTransformer; bool isLogarithmic = cartesianTransformer.XAxis.IsLogarithmic || cartesianTransformer.YAxis.IsLogarithmic; bool x_isInversed = cartesianTransformer.XAxis.IsInversed; bool y_isInversed = cartesianTransformer.YAxis.IsInversed; double x1ChartVal, x2ChartVal, y1ChartVal, y2ChartVal; double xStart, xEnd, yStart, yEnd, width, height, left, top; int i = dataPoint.Index; DoubleRange sbsInfo = this.GetSideBySideInfo(this); List <double> xValues = GetStackingSeriesXValues(this); if (!this.IsIndexed) { x1ChartVal = xValues[i] + sbsInfo.Start; x2ChartVal = xValues[i] + sbsInfo.End; y1ChartVal = YRangeEndValues[i]; y2ChartVal = YRangeStartValues[i]; } else { x1ChartVal = i + sbsInfo.Start; x2ChartVal = i + sbsInfo.End; y1ChartVal = YRangeEndValues[i]; y2ChartVal = YRangeStartValues[i]; } xStart = cartesianTransformer.XAxis.VisibleRange.Start; xEnd = cartesianTransformer.XAxis.VisibleRange.End; yStart = cartesianTransformer.YAxis.VisibleRange.Start; yEnd = cartesianTransformer.YAxis.VisibleRange.End; width = cartesianTransformer.XAxis.RenderedRect.Height; height = cartesianTransformer.YAxis.RenderedRect.Width; // WPF-14441 - Calculating Bar Position for the Series left = Area.SeriesClipRect.Right - cartesianTransformer.YAxis.RenderedRect.Right; top = Area.SeriesClipRect.Bottom - cartesianTransformer.XAxis.RenderedRect.Bottom; Size availableSize = new Size(width, height); if (x_isInversed) { double temp = xStart; xStart = xEnd; xEnd = temp; } if (y_isInversed) { double temp = yStart; yStart = yEnd; yEnd = temp; } float x1Value = 0, x2Value = 0, y1Value = 0, y2Value = 0; // Removed the screen point calculation methods and added the point to value method. if (!isLogarithmic) { double x1Val = x_isInversed ? x2ChartVal < xEnd ? xEnd : x2ChartVal : x1ChartVal < xStart ? xStart : x1ChartVal; double x2Val = x_isInversed ? x1ChartVal > xStart ? xStart : x1ChartVal : x2ChartVal > xEnd ? xEnd : x2ChartVal; double y1Val = y_isInversed ? y2ChartVal > yStart ? yStart : y2ChartVal <yEnd?yEnd : y2ChartVal : y1ChartVal> yEnd ? yEnd : y1ChartVal < yStart ? yStart : y1ChartVal; double y2Val = y_isInversed ? y1ChartVal <yEnd?yEnd : y1ChartVal> yStart ? yStart : y1ChartVal : y2ChartVal <yStart?yStart : y2ChartVal> yEnd ? yEnd : y2ChartVal; x1Value = (float)(top + (availableSize.Width) * cartesianTransformer.XAxis.ValueToCoefficientCalc(x1Val)); x2Value = (float)(top + (availableSize.Width) * cartesianTransformer.XAxis.ValueToCoefficientCalc(x2Val)); y1Value = (float)(left + (availableSize.Height) * (1 - cartesianTransformer.YAxis.ValueToCoefficientCalc(y1Val))); y2Value = (float)(left + (availableSize.Height) * (1 - cartesianTransformer.YAxis.ValueToCoefficientCalc(y2Val))); } else { double xBase = cartesianTransformer.XAxis.IsLogarithmic ? (cartesianTransformer.XAxis as LogarithmicAxis).LogarithmicBase : 1; double yBase = cartesianTransformer.YAxis.IsLogarithmic ? (cartesianTransformer.YAxis as LogarithmicAxis).LogarithmicBase : 1; double logx1 = xBase == 1 ? x1ChartVal : Math.Log(x1ChartVal, xBase); double logx2 = xBase == 1 ? x2ChartVal : Math.Log(x2ChartVal, xBase); double logy1 = yBase == 1 ? y1ChartVal : Math.Log(y1ChartVal, yBase); double logy2 = yBase == 1 ? y2ChartVal : Math.Log(y2ChartVal, yBase); double x1Val = x_isInversed ? logx2 < xEnd ? xEnd : logx2 : logx1 < xStart ? xStart : logx1; double x2Val = x_isInversed ? logx1 > xStart ? xStart : logx1 : logx2 > xEnd ? xEnd : logx2; double y1Val = y_isInversed ? logy2 > yStart ? yStart : logy2 <yEnd?yEnd : logy2 : logy1> yEnd ? yEnd : logy1 < yStart ? yStart : logy1; double y2Val = y_isInversed ? logy1 <yEnd?yEnd : logy1> yStart ? yStart : logy1 : logy2 <yStart?yStart : logy2> yEnd ? yEnd : logy2; x1Value = (float)(top + (availableSize.Width) * cartesianTransformer.XAxis.ValueToCoefficientCalc(x1Val)); x2Value = (float)(top + (availableSize.Width) * cartesianTransformer.XAxis.ValueToCoefficientCalc(x2Val)); y1Value = (float)(left + (availableSize.Height) * (1 - cartesianTransformer.YAxis.ValueToCoefficientCalc(y1Val))); y2Value = (float)(left + (availableSize.Height) * (1 - cartesianTransformer.YAxis.ValueToCoefficientCalc(y2Val))); } float x1 = 0, x2, y1, y2, diff = 0; width = (int)Area.SeriesClipRect.Width; height = (int)Area.SeriesClipRect.Height; x1 = x1Value; x2 = x2Value; y1 = y1ChartVal > 0 ? y1Value : y2Value; y2 = y1ChartVal > 0 ? y2Value : y1Value; var spacingSegment = this as ISegmentSpacing; if (spacingSegment != null) { double spacing = spacingSegment.SegmentSpacing; if (spacing > 0 && spacing <= 1) { double leftpos = spacingSegment.CalculateSegmentSpacing(spacing, x1, x2); double rightpos = spacingSegment.CalculateSegmentSpacing(spacing, x2, x1); x2 = (float)leftpos; x1 = (float)rightpos; } } diff = x2 - x1; selectedSegmentPixels.Clear(); if (y1 < y2) { selectedSegmentPixels = bmp.GetRectangle( (int)width, (int)height, (int)(width - y2), (int)(height - x1 - diff), (int)(width - y1), (int)(height - x1), selectedSegmentPixels); } else { selectedSegmentPixels = bmp.GetRectangle( (int)width, (int)height, (int)(width - y1), (int)(height - x1 - diff), (int)(width - y2), (int)(height - x1), selectedSegmentPixels); } }
/// <summary> /// Creates the segments of CandleSeries. /// </summary> public override void CreateSegments() { DoubleRange sbsInfo = this.GetSideBySideInfo(this); double center = sbsInfo.Median; List <double> xValues = null; if (ActualXAxis is CategoryAxis && !(ActualXAxis as CategoryAxis).IsIndexed) { xValues = GroupedXValuesIndexes; } else { xValues = GetXValues(); } IList <double> values = GetComparisionModeValues(); if (xValues != null) { ClearUnUsedSegments(this.DataCount); if (AdornmentsInfo != null) { if (AdornmentsInfo.AdornmentsPosition == AdornmentsPosition.TopAndBottom) { ClearUnUsedAdornments(this.DataCount * 4); } else { ClearUnUsedAdornments(this.DataCount * 2); } } if (this.ActualXAxis is CategoryAxis && (!(this.ActualXAxis as CategoryAxis).IsIndexed)) { Segments.Clear(); Adornments.Clear(); for (int i = 0; i < xValues.Count; i++) { if (i < xValues.Count && GroupedSeriesYValues[0].Count > i) { double x1 = xValues[i] + sbsInfo.Start; double x2 = xValues[i] + sbsInfo.End; double y1 = GroupedSeriesYValues[2][i]; double y2 = GroupedSeriesYValues[3][i]; bool isbull = false; if (i == 0 || this.ComparisonMode == FinancialPrice.None) { isbull = GroupedSeriesYValues[3][i] > GroupedSeriesYValues[2][i]; } else { isbull = values[i] >= values[i - 1]; } ChartPoint cdpBottomLeft = new ChartPoint(x1, y1); ChartPoint cdpRightTop = new ChartPoint(x2, y2); ChartPoint hipoint = new ChartPoint(xValues[i] + center, GroupedSeriesYValues[0][i]); ChartPoint lopoint = new ChartPoint(xValues[i] + center, GroupedSeriesYValues[1][i]); var segment = new CandleSegment(); segment.Series = this; segment.BullFillColor = BullFillColor; segment.BearFillColor = BearFillColor; segment.Item = ActualData[i]; segment.SetData(cdpBottomLeft, cdpRightTop, hipoint, lopoint, isbull); segment.High = GroupedSeriesYValues[0][i]; segment.Low = GroupedSeriesYValues[1][i]; segment.Open = GroupedSeriesYValues[2][i]; segment.Close = GroupedSeriesYValues[3][i]; Segments.Add(segment); if (AdornmentsInfo != null) { AddAdornments(xValues[i], hipoint, lopoint, cdpBottomLeft, cdpBottomLeft, cdpRightTop, cdpRightTop, i, 0); } } } } else { for (int i = 0; i < DataCount; i++) { double x1 = xValues[i] + sbsInfo.Start; double x2 = xValues[i] + sbsInfo.End; double y1 = OpenValues[i]; double y2 = CloseValues[i]; bool isbull = false; if (i == 0 || this.ComparisonMode == FinancialPrice.None) { isbull = CloseValues[i] > OpenValues[i]; } else { isbull = values[i] >= values[i - 1]; } ChartPoint cdpBottomLeft = new ChartPoint(x1, y1); ChartPoint cdpRightTop = new ChartPoint(x2, y2); ChartPoint hipoint = new ChartPoint(xValues[i] + center, HighValues[i]); ChartPoint lopoint = new ChartPoint(xValues[i] + center, LowValues[i]); if (i < Segments.Count) { (Segments[i]).SetData(cdpBottomLeft, cdpRightTop, hipoint, lopoint, isbull); (Segments[i] as CandleSegment).High = HighValues[i]; (Segments[i] as CandleSegment).Low = LowValues[i]; (Segments[i] as CandleSegment).Open = OpenValues[i]; (Segments[i] as CandleSegment).Close = CloseValues[i]; Segments[i].Item = ActualData[i]; } else { var segment = new CandleSegment(); segment.Series = this; segment.BullFillColor = BullFillColor; segment.BearFillColor = BearFillColor; segment.Item = ActualData[i]; segment.SetData(cdpBottomLeft, cdpRightTop, hipoint, lopoint, isbull); segment.High = HighValues[i]; segment.Low = LowValues[i]; segment.Open = OpenValues[i]; segment.Close = CloseValues[i]; Segments.Add(segment); } if (AdornmentsInfo != null) { AddAdornments(xValues[i], hipoint, lopoint, cdpBottomLeft, cdpBottomLeft, cdpRightTop, cdpRightTop, i, 0); } } } if (ShowEmptyPoints) { UpdateEmptyPointSegments(xValues, true); } } }
protected internal override double CalculateNiceInterval(DoubleRange actualRange, Size availableSize) { DateTime dateTimeMin = actualRange.Start.FromOADate(); DateTime dateTimeMax = actualRange.End.FromOADate(); TimeSpan timeSpan = dateTimeMax.Subtract(dateTimeMin); double interval = 0; switch (IntervalType) { case DateTimeIntervalType.Years: interval = base.CalculateNiceInterval(new DoubleRange(0, timeSpan.TotalDays / 365), availableSize); break; case DateTimeIntervalType.Months: interval = base.CalculateNiceInterval(new DoubleRange(0, timeSpan.TotalDays / 30), availableSize); break; case DateTimeIntervalType.Days: interval = base.CalculateNiceInterval(new DoubleRange(0, timeSpan.TotalDays), availableSize); break; case DateTimeIntervalType.Hours: interval = base.CalculateNiceInterval(new DoubleRange(0, timeSpan.TotalHours), availableSize); break; case DateTimeIntervalType.Minutes: interval = base.CalculateNiceInterval(new DoubleRange(0, timeSpan.TotalMinutes), availableSize); break; case DateTimeIntervalType.Seconds: interval = base.CalculateNiceInterval(new DoubleRange(0, timeSpan.TotalSeconds), availableSize); break; case DateTimeIntervalType.Milliseconds: interval = base.CalculateNiceInterval(new DoubleRange(0, timeSpan.TotalMilliseconds), availableSize); break; case DateTimeIntervalType.Auto: interval = actualRange.Delta / GetActualDesiredIntervalsCount(availableSize); if (interval <= base.CalculateNiceInterval(new DoubleRange(0, timeSpan.TotalDays / 365), availableSize)) { interval = base.CalculateNiceInterval(new DoubleRange(0, timeSpan.TotalDays / 365), availableSize); ActualIntervalType = DateTimeIntervalType.Years; } else if (interval <= base.CalculateNiceInterval(new DoubleRange(0, timeSpan.TotalDays / 30), availableSize)) { interval = base.CalculateNiceInterval(new DoubleRange(0, timeSpan.TotalDays / 30), availableSize); ActualIntervalType = DateTimeIntervalType.Months; } else if (interval <= base.CalculateNiceInterval(new DoubleRange(0, timeSpan.TotalDays), availableSize)) { interval = base.CalculateNiceInterval(new DoubleRange(0, timeSpan.TotalDays), availableSize); ActualIntervalType = DateTimeIntervalType.Days; } else if (interval <= base.CalculateNiceInterval(new DoubleRange(0, timeSpan.TotalHours), availableSize)) { interval = base.CalculateNiceInterval(new DoubleRange(0, timeSpan.TotalHours), availableSize); ActualIntervalType = DateTimeIntervalType.Hours; } else if (interval <= base.CalculateNiceInterval(new DoubleRange(0, timeSpan.TotalMinutes), availableSize)) { interval = base.CalculateNiceInterval(new DoubleRange(0, timeSpan.TotalMinutes), availableSize); ActualIntervalType = DateTimeIntervalType.Minutes; } else if (interval <= base.CalculateNiceInterval(new DoubleRange(0, timeSpan.TotalSeconds), availableSize)) { interval = base.CalculateNiceInterval(new DoubleRange(0, timeSpan.TotalSeconds), availableSize); ActualIntervalType = DateTimeIntervalType.Seconds; } else if (interval <= base.CalculateNiceInterval(new DoubleRange(0, timeSpan.TotalMilliseconds), availableSize)) { interval = base.CalculateNiceInterval(new DoubleRange(0, timeSpan.TotalMilliseconds), availableSize); ActualIntervalType = DateTimeIntervalType.Milliseconds; } break; } return(Math.Max(1d, interval)); }
/// <summary> /// This method used to get the chart data at an index. /// </summary> /// <param name="mousePos"></param> /// <returns></returns> internal override void GeneratePixels() { WriteableBitmap bmp = Area.fastRenderSurface; ChartTransform.ChartCartesianTransformer cartesianTransformer = CreateTransformer(new Size(Area.SeriesClipRect.Width, Area.SeriesClipRect.Height), true) as ChartTransform.ChartCartesianTransformer; bool x_isInversed = cartesianTransformer.XAxis.IsInversed; bool y_isInversed = cartesianTransformer.YAxis.IsInversed; DoubleRange sbsInfo = GetSideBySideInfo(this); double center = sbsInfo.Median; double Left = sbsInfo.Start; double Right = sbsInfo.End; double xChartValue = dataPoint.XData; double yOpenChartValue = dataPoint.Open; double yCloseChartValue = dataPoint.Close; double yHighChartValue = dataPoint.High; double yLowChartValue = dataPoint.Low; int i = dataPoint.Index; float xValue, yHiValue, yLoValue, yOpenStartValue, yOpenEndValue, yCloseValue, yCloseEndValue; double spacing = (this as ISegmentSpacing).SegmentSpacing; double leftpos = (this as ISegmentSpacing).CalculateSegmentSpacing(spacing, Right, Left); double rightpos = (this as ISegmentSpacing).CalculateSegmentSpacing(spacing, Left, Right); if (spacing > 0 && spacing <= 1) { Left = leftpos; Right = rightpos; } double highValue = yHighChartValue; double lowValue = yLowChartValue; var alignedValues = Segments[0].AlignHiLoSegment(yOpenChartValue, yCloseChartValue, highValue, lowValue); highValue = alignedValues[0]; lowValue = alignedValues[1]; if (IsIndexed) { Point hiPoint = cartesianTransformer.TransformToVisible(i + center, highValue); Point loPoint = cartesianTransformer.TransformToVisible(xChartValue + center, lowValue); Point startopenpoint = cartesianTransformer.TransformToVisible(xChartValue + center, yOpenChartValue); Point endopenpoint = cartesianTransformer.TransformToVisible(xChartValue + Left, yOpenChartValue); Point endclosepoint = cartesianTransformer.TransformToVisible(i + Right, yCloseChartValue); if (!IsActualTransposed) { xValue = (float)hiPoint.X; yHiValue = (float)hiPoint.Y; yLoValue = (float)loPoint.Y; yOpenStartValue = (float)startopenpoint.Y; yOpenEndValue = (float)endopenpoint.X; yCloseValue = (float)endclosepoint.Y; yCloseEndValue = (float)endclosepoint.X; } else { xValue = (float)hiPoint.Y; yHiValue = (float)hiPoint.X; yLoValue = (float)loPoint.X; yOpenStartValue = (float)startopenpoint.X; yOpenEndValue = (float)endopenpoint.Y; yCloseValue = (float)endclosepoint.X; yCloseEndValue = (float)endclosepoint.Y; } } else { Point hiPoint = cartesianTransformer.TransformToVisible(xChartValue + center, highValue); Point loPoint = cartesianTransformer.TransformToVisible(xChartValue + center, lowValue); Point startopenpoint = cartesianTransformer.TransformToVisible(xChartValue + center, yOpenChartValue); Point endopenpoint = cartesianTransformer.TransformToVisible(xChartValue + Left, yOpenChartValue); Point endclosepoint = cartesianTransformer.TransformToVisible(xChartValue + Right, yCloseChartValue); if (!IsActualTransposed) { xValue = (float)hiPoint.X; yHiValue = (float)hiPoint.Y; yLoValue = (float)loPoint.Y; yOpenStartValue = (float)startopenpoint.Y; yOpenEndValue = (float)endopenpoint.X; yCloseValue = (float)endclosepoint.Y; yCloseEndValue = (float)endclosepoint.X; } else { xValue = (float)hiPoint.Y; yHiValue = (float)hiPoint.X; yLoValue = (float)loPoint.X; yOpenStartValue = (float)startopenpoint.X; yOpenEndValue = (float)endopenpoint.Y; yCloseValue = (float)endclosepoint.X; yCloseEndValue = (float)endclosepoint.Y; } } int width = (int)Area.SeriesClipRect.Width; int height = (int)Area.SeriesClipRect.Height; int leftThickness = (int)StrokeThickness / 2; int rightThickness = (int)(StrokeThickness % 2 == 0 ? (StrokeThickness / 2) : StrokeThickness / 2 + 1); selectedSegmentPixels.Clear(); float xStart = 0; float yStart = 0; float yEnd = 0; float yOpen = 0; float yOpenEnd = 0; float yClose = 0; float yCloseEnd = 0; int leftOffset, rightOffset; xStart = xValue; yStart = y_isInversed ? yLoValue : yHiValue; yEnd = y_isInversed ? yHiValue : yLoValue; yOpen = x_isInversed ? yCloseValue : yOpenStartValue; yOpenEnd = x_isInversed ? yCloseEndValue : yOpenEndValue; yClose = x_isInversed ? yOpenStartValue : yCloseValue; yCloseEnd = x_isInversed ? yOpenEndValue : yCloseEndValue; if (!IsActualTransposed) { leftOffset = (int)xStart - leftThickness; rightOffset = (int)xStart + rightThickness; selectedSegmentPixels = bmp.GetRectangle(width, height, leftOffset, (int)yStart, rightOffset, (int)yEnd, selectedSegmentPixels); leftOffset = (int)yOpen - leftThickness; rightOffset = (int)yOpen + rightThickness; selectedSegmentPixels = bmp.GetRectangle(width, height, (int)yOpenEnd, leftOffset, (int)xStart - leftThickness, (int)rightOffset, selectedSegmentPixels); leftOffset = (int)yClose - leftThickness; rightOffset = (int)yClose + rightThickness; selectedSegmentPixels = bmp.GetRectangle(width, height, (int)xStart + leftThickness, leftOffset, (int)yCloseEnd, (int)rightOffset, selectedSegmentPixels); } else { leftOffset = (int)xStart - leftThickness; rightOffset = (int)xStart + rightThickness; selectedSegmentPixels = bmp.GetRectangle(width, height, (int)yEnd, (int)leftOffset, (int)yStart, (int)rightOffset, selectedSegmentPixels); leftOffset = (int)yOpen - leftThickness; rightOffset = (int)yOpen + rightThickness; selectedSegmentPixels = bmp.GetRectangle(width, height, leftOffset, (int)xStart + leftThickness, (int)rightOffset, (int)yOpenEnd, selectedSegmentPixels); leftOffset = (int)yClose - leftThickness; rightOffset = (int)yClose + rightThickness; selectedSegmentPixels = bmp.GetRectangle(width, height, leftOffset, (int)yCloseEnd, (int)rightOffset, (int)xStart - leftThickness, selectedSegmentPixels); } }
protected override DoubleRange CalculateActualRange() { if (ActualRange.IsEmpty) // Executes when Minimum and Maximum aren't set. { DoubleRange range = base.CalculateActualRange(); // Execute when include the annotion range for Auto Range if (IncludeAnnotationRange) { foreach (var annotation in (Area as SfChart).Annotations) { if (Orientation == Orientation.Vertical && annotation.CoordinateUnit == CoordinateUnit.Axis && annotation.YAxis == this) { range += new DoubleRange( Annotation.ConvertData(annotation.Y1, this), annotation is TextAnnotation ? Annotation.ConvertData(annotation.Y1, this) : annotation is ImageAnnotation ? Annotation.ConvertData((annotation as ImageAnnotation).Y2, this) : Annotation.ConvertData((annotation as ShapeAnnotation).Y2, this)); } else if (Orientation == Orientation.Horizontal && annotation.CoordinateUnit == CoordinateUnit.Axis && annotation.XAxis == this) { range += new DoubleRange( Annotation.ConvertData(annotation.X1, this), annotation is TextAnnotation ? Annotation.ConvertData(annotation.X1, this) : annotation is ImageAnnotation ? Annotation.ConvertData((annotation as ImageAnnotation).X2, this) : Annotation.ConvertData((annotation as ShapeAnnotation).X2, this)); } } } return(range); } else if (Minimum != null && Maximum != null) // Executes when Minimum and Maximum are set. { return(ActualRange); } else { // Executes when either Minimum or Maximum is set. DoubleRange range = base.CalculateActualRange(); if (StartRangeFromZero && range.Start > 0) { return(new DoubleRange(0, range.End)); } else if (Minimum != null) { return(new DoubleRange(ActualRange.Start, double.IsNaN(range.End) ? ActualRange.Start + 1 : range.End)); } else if (Maximum != null) { return(new DoubleRange(double.IsNaN(range.Start) ? ActualRange.End - 1 : range.Start, ActualRange.End)); } else { if (IncludeAnnotationRange) { foreach (var annotation in (Area as SfChart).Annotations) { if (Orientation == Orientation.Vertical && annotation.CoordinateUnit == CoordinateUnit.Axis && annotation.YAxis == this) { range += new DoubleRange( Annotation.ConvertData(annotation.Y1, this), annotation is TextAnnotation ? Annotation.ConvertData(annotation.Y1, this) : annotation is ImageAnnotation ? Annotation.ConvertData((annotation as ImageAnnotation).Y2, this) : Annotation.ConvertData((annotation as ShapeAnnotation).Y2, this)); } else if (Orientation == Orientation.Horizontal && annotation.CoordinateUnit == CoordinateUnit.Axis && annotation.XAxis == this) { range += new DoubleRange( Annotation.ConvertData(annotation.X1, this), annotation is TextAnnotation ? Annotation.ConvertData(annotation.X1, this) : annotation is ImageAnnotation ? Annotation.ConvertData((annotation as ImageAnnotation).X2, this) : Annotation.ConvertData((annotation as ShapeAnnotation).X2, this)); } } } return(range); } } }
/// <summary> /// Creates the segments of FastHiLoOpenCloseBitmapSeries /// </summary> public override void CreateSegments() { List <double> xValues = null; var isGrouped = ActualXAxis is CategoryAxis && !(ActualXAxis as CategoryAxis).IsIndexed; if (isGrouped) { xValues = GroupedXValuesIndexes; } else { xValues = GetXValues(); } if (xValues != null) { if (isGrouped) { Segments.Clear(); Adornments.Clear(); if (Segment == null || Segments.Count == 0) { FastHiLoOpenCloseSegment segment = new FastHiLoOpenCloseSegment(xValues, GroupedSeriesYValues[0], GroupedSeriesYValues[1], GroupedSeriesYValues[2], GroupedSeriesYValues[3], this); segment.Series = this; segment.Item = ActualData; segment.SetData(xValues, GroupedSeriesYValues[0], GroupedSeriesYValues[1], GroupedSeriesYValues[2], GroupedSeriesYValues[3]); Segment = segment; this.Segments.Add(Segment); } DoubleRange sbsInfo = this.GetSideBySideInfo(this); double median = sbsInfo.Delta / 2; double center = sbsInfo.Median; double Left = sbsInfo.Start; double Right = sbsInfo.End; double leftpos = (this as ISegmentSpacing).CalculateSegmentSpacing(SegmentSpacing, Right, Left); double rightpos = (this as ISegmentSpacing).CalculateSegmentSpacing(SegmentSpacing, Left, Right); if (SegmentSpacing > 0 && SegmentSpacing <= 1) { Left = leftpos; Right = rightpos; } for (int i = 0; i < xValues.Count; i++) { if (i < xValues.Count && GroupedSeriesYValues[0].Count > i) { ChartPoint highPt = new ChartPoint(xValues[i] + center, GroupedSeriesYValues[0][i]); ChartPoint lowPt = new ChartPoint(xValues[i] + center, GroupedSeriesYValues[1][i]); ChartPoint startOpenPt = new ChartPoint(xValues[i] + Left, GroupedSeriesYValues[2][i]); ChartPoint endOpenPt = new ChartPoint(xValues[i] + center, GroupedSeriesYValues[2][i]); ChartPoint startClosePt = new ChartPoint(xValues[i] + Right, GroupedSeriesYValues[3][i]); ChartPoint endClosePt = new ChartPoint(xValues[i] + center, GroupedSeriesYValues[3][i]); if (AdornmentsInfo != null) { AddAdornments(xValues[i], highPt, lowPt, startOpenPt, endOpenPt, startClosePt, endClosePt, i, median); } } } } else { if (AdornmentsInfo != null) { if (AdornmentsInfo.AdornmentsPosition == AdornmentsPosition.TopAndBottom) { ClearUnUsedAdornments(this.DataCount * 4); } else { ClearUnUsedAdornments(this.DataCount * 2); } } if (Segment == null || Segments.Count == 0) { FastHiLoOpenCloseSegment segment = new FastHiLoOpenCloseSegment(xValues, HighValues, LowValues, OpenValues, CloseValues, this); segment.Series = this; segment.Item = ActualData; segment.SetData(xValues, HighValues, LowValues, OpenValues, CloseValues); Segment = segment; this.Segments.Add(Segment); } else if (xValues != null) { (Segment as FastHiLoOpenCloseSegment).Item = ActualData; (Segment as FastHiLoOpenCloseSegment).SetData(xValues, HighValues, LowValues, OpenValues, CloseValues); } if (AdornmentsInfo != null) { if (AdornmentsInfo.AdornmentsPosition == AdornmentsPosition.TopAndBottom) { ClearUnUsedAdornments(this.DataCount * 4); } else { ClearUnUsedAdornments(this.DataCount * 2); } } DoubleRange sbsInfo = this.GetSideBySideInfo(this); double median = sbsInfo.Delta / 2; double center = sbsInfo.Median; double Left = sbsInfo.Start; double Right = sbsInfo.End; double leftpos = (this as ISegmentSpacing).CalculateSegmentSpacing(SegmentSpacing, Right, Left); double rightpos = (this as ISegmentSpacing).CalculateSegmentSpacing(SegmentSpacing, Left, Right); if (SegmentSpacing > 0 && SegmentSpacing <= 1) { Left = leftpos; Right = rightpos; } for (int i = 0; i < this.DataCount; i++) { ChartPoint highPt = new ChartPoint(xValues[i] + center, HighValues[i]); ChartPoint lowPt = new ChartPoint(xValues[i] + center, LowValues[i]); ChartPoint startOpenPt = new ChartPoint(xValues[i] + Left, OpenValues[i]); ChartPoint endOpenPt = new ChartPoint(xValues[i] + center, OpenValues[i]); ChartPoint startClosePt = new ChartPoint(xValues[i] + Right, CloseValues[i]); ChartPoint endClosePt = new ChartPoint(xValues[i] + center, CloseValues[i]); if (AdornmentsInfo != null) { AddAdornments(xValues[i], highPt, lowPt, startOpenPt, endOpenPt, startClosePt, endClosePt, i, median); } } } } }
/// <summary> /// Excludes the specified range. /// </summary> /// <param name="range">The range.</param> /// <param name="excluder">The excluder.</param> /// <param name="leftRange">The left range.</param> /// <param name="rightRange">The right range.</param> /// <returns>True if empty</returns> public static bool Exclude(DoubleRange range, DoubleRange excluder, out DoubleRange leftRange, out DoubleRange rightRange) { leftRange = DoubleRange.Empty; rightRange = DoubleRange.Empty; if (!(range.IsEmpty || excluder.IsEmpty)) { if (excluder.m_end < range.m_start) { if (excluder.m_end > range.m_start) { leftRange = new DoubleRange(excluder.m_start, range.m_start); } else { leftRange = excluder; } } if (excluder.m_end > range.m_end) { if (excluder.m_start < range.m_end) { rightRange = new DoubleRange(range.m_end, excluder.m_end); } else { rightRange = excluder; } } } return(!(leftRange.IsEmpty && rightRange.IsEmpty)); }
/// <summary> /// Creates the segments of HiLoOpenCloseSeries /// </summary> public override void CreateSegments() { List <double> xValues = null; bool isGrouping = this.ActualXAxis is CategoryAxis ? (this.ActualXAxis as CategoryAxis).IsIndexed : true; if (!isGrouping) { xValues = GroupedXValuesIndexes; } else { xValues = GetXValues(); } IList <double> values = GetComparisionModeValues(); bool isBull = false; if (xValues != null) { DoubleRange sbsInfo = this.GetSideBySideInfo(this); double median = sbsInfo.Delta / 2; double center = sbsInfo.Median; double Left = sbsInfo.Start; double Right = sbsInfo.End; double leftpos = (this as ISegmentSpacing).CalculateSegmentSpacing(SegmentSpacing, Right, Left); double rightpos = (this as ISegmentSpacing).CalculateSegmentSpacing(SegmentSpacing, Left, Right); if (SegmentSpacing > 0 && SegmentSpacing <= 1) { Left = leftpos; Right = rightpos; } if (!isGrouping) { Segments.Clear(); Adornments.Clear(); for (int i = 0; i < xValues.Count; i++) { ChartPoint highPt = new ChartPoint(xValues[i] + center, GroupedSeriesYValues[0][i]); ChartPoint lowPt = new ChartPoint(xValues[i] + center, GroupedSeriesYValues[1][i]); ChartPoint startOpenPt = new ChartPoint(xValues[i] + Left, GroupedSeriesYValues[2][i]); ChartPoint endOpenPt = new ChartPoint(xValues[i] + center, GroupedSeriesYValues[2][i]); ChartPoint startClosePt = new ChartPoint(xValues[i] + Right, GroupedSeriesYValues[3][i]); ChartPoint endClosePt = new ChartPoint(xValues[i] + center, GroupedSeriesYValues[3][i]); if (i == 0 || this.ComparisonMode == FinancialPrice.None) { isBull = GroupedSeriesYValues[2][i] < GroupedSeriesYValues[3][i]; } else { isBull = values[i] >= values[i - 1]; } HiLoOpenCloseSegment hiloOpenClose = new HiLoOpenCloseSegment(highPt, lowPt, startOpenPt, endOpenPt, startClosePt, endClosePt, isBull, this, ActualData[i]); hiloOpenClose.SetData(highPt, lowPt, startOpenPt, endOpenPt, startClosePt, endClosePt, isBull); hiloOpenClose.BullFillColor = BullFillColor; hiloOpenClose.BearFillColor = BearFillColor; hiloOpenClose.High = GroupedSeriesYValues[0][i]; hiloOpenClose.Low = GroupedSeriesYValues[1][i]; hiloOpenClose.Open = GroupedSeriesYValues[2][i]; hiloOpenClose.Close = GroupedSeriesYValues[3][i]; hiloOpenClose.Item = ActualData[i]; Segments.Add(hiloOpenClose); if (AdornmentsInfo != null) { AddAdornments(xValues[i], highPt, lowPt, startOpenPt, endOpenPt, startClosePt, endClosePt, i, median); } } } else { if (Segments.Count > this.DataCount) { ClearUnUsedSegments(this.DataCount); } if (AdornmentsInfo != null) { if (AdornmentsInfo.AdornmentsPosition == AdornmentsPosition.TopAndBottom) { ClearUnUsedAdornments(this.DataCount * 4); } else { ClearUnUsedAdornments(this.DataCount * 2); } } for (int i = 0; i < this.DataCount; i++) { ChartPoint highPt = new ChartPoint(xValues[i] + center, HighValues[i]); ChartPoint lowPt = new ChartPoint(xValues[i] + center, LowValues[i]); ChartPoint startOpenPt = new ChartPoint(xValues[i] + Left, OpenValues[i]); ChartPoint endOpenPt = new ChartPoint(xValues[i] + center, OpenValues[i]); ChartPoint startClosePt = new ChartPoint(xValues[i] + Right, CloseValues[i]); ChartPoint endClosePt = new ChartPoint(xValues[i] + center, CloseValues[i]); if (i == 0 || this.ComparisonMode == FinancialPrice.None) { isBull = OpenValues[i] < CloseValues[i]; } else { isBull = values[i] >= values[i - 1]; } if (i < Segments.Count) { Segments[i].Item = ActualData[i]; (Segments[i]).SetData(highPt, lowPt, startOpenPt, endOpenPt, startClosePt, endClosePt, isBull); (Segments[i] as HiLoOpenCloseSegment).High = HighValues[i]; (Segments[i] as HiLoOpenCloseSegment).Low = LowValues[i]; (Segments[i] as HiLoOpenCloseSegment).Open = OpenValues[i]; (Segments[i] as HiLoOpenCloseSegment).Close = CloseValues[i]; } else { HiLoOpenCloseSegment hiloOpenClose = new HiLoOpenCloseSegment(highPt, lowPt, startOpenPt, endOpenPt, startClosePt, endClosePt, isBull, this, ActualData[i]); hiloOpenClose.SetData(highPt, lowPt, startOpenPt, endOpenPt, startClosePt, endClosePt, isBull); hiloOpenClose.BullFillColor = BullFillColor; hiloOpenClose.BearFillColor = BearFillColor; hiloOpenClose.High = HighValues[i]; hiloOpenClose.Low = LowValues[i]; hiloOpenClose.Open = OpenValues[i]; hiloOpenClose.Close = CloseValues[i]; hiloOpenClose.Item = ActualData[i]; Segments.Add(hiloOpenClose); } if (AdornmentsInfo != null) { AddAdornments(xValues[i], highPt, lowPt, startOpenPt, endOpenPt, startClosePt, endClosePt, i, median); } } } if (ShowEmptyPoints) { UpdateEmptyPointSegments(xValues, true); } } }
/// <summary> /// Apply padding based on interval /// </summary> /// <param name="axis">The axis.</param> /// <param name="range">The range.</param> /// <param name="interval">The interval.</param> /// <param name="rangePadding">The range padding.</param> /// <returns></returns> internal static DoubleRange ApplyRangePadding(ChartAxis axis, DoubleRange range, double interval, NumericalPadding rangePadding) { if (rangePadding == NumericalPadding.Normal) { double minimum = 0, remaining, start = range.Start; if (range.Start < 0) { start = 0; minimum = range.Start + (range.Start / 20); remaining = interval + (minimum % interval); if ((0.365 * interval) >= remaining) { minimum -= interval; } if (minimum % interval < 0) { minimum = (minimum - interval) - (minimum % interval); } } else { minimum = range.Start < ((5.0 / 6.0) * range.End) ? 0 : (range.Start - (range.End - range.Start) / 2); if (minimum % interval > 0) { minimum -= (minimum % interval); } } double maximum = (range.End + (range.End - start) / 20); remaining = interval - (maximum % interval); if ((0.365 * interval) >= remaining) { maximum += interval; } if (maximum % interval > 0) { maximum = (maximum + interval) - (maximum % interval); } range = new DoubleRange(minimum, maximum); if (minimum == 0d) { axis.ActualInterval = axis.CalculateActualInterval(range, axis.AvailableSize); return(new DoubleRange(0, Math.Ceiling(maximum / axis.ActualInterval) * axis.ActualInterval)); } } else if (rangePadding == NumericalPadding.Round || rangePadding == NumericalPadding.Additional) { double minimum = Math.Floor(range.Start / interval) * interval; double maximum = Math.Ceiling(range.End / interval) * interval; if (rangePadding == NumericalPadding.Additional) { minimum -= interval; maximum += interval; } return(new DoubleRange(minimum, maximum)); } return(range); }
/// <summary> /// Calculates actual interval /// </summary> /// <param name="range">The Range</param> /// <param name="availableSize">The Available Size</param> /// <returns>Actual Interval</returns> protected internal override double CalculateActualInterval(DoubleRange range, Size availableSize) { return(CategoryAxisHelper.CalculateActualInterval(this, range, availableSize, this.Interval)); }
/// <summary> /// Calculates nice interval. /// </summary> /// <param name="actualRange">The Actual Range</param> /// <param name="availableSize">The Available Range</param> /// <returns>Returns the calculated nice interval.</returns> protected internal override double CalculateNiceInterval(DoubleRange actualRange, Size availableSize) { return(LogarithmicAxisHelper.CalculateNiceInterval(this, actualRange, availableSize)); }
/// <summary> /// Apply padding based on interval /// </summary> /// <param name="range">The Range</param> /// <param name="interval">The Interval</param> /// <returns>The Range Padding</returns> protected override DoubleRange ApplyRangePadding(DoubleRange range, double interval) { return(CategoryAxisHelper.ApplyRangePadding(this, range, interval, LabelPlacement)); }
/// <summary> /// Creates the segments of WaterfallSeries. /// </summary> public override void CreateSegments() { List <double> xValues = GetXValues(); double median = 0d; DoubleRange sbsInfo = this.GetSideBySideInfo(this); median = sbsInfo.Delta / 2; 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) { double x1, x2, y1, y2; ClearUnUsedSegments(this.DataCount); ClearUnUsedAdornments(this.DataCount); for (int i = 0; i < this.DataCount; i++) { if (i < this.DataCount) { // Calculate the waterfall segment rendering values. OnCalculateSegmentValues( out x1, out x2, out y1, out y2, i, origin, xValues[i]); WaterfallSegment segment = null; bool isSum = false; if (i < Segments.Count) { segment = Segments[i] as WaterfallSegment; segment.SetData(x1, y1, x2, y2); segment.XData = xValues[i]; segment.YData = YValues[i]; segment.Item = ActualData[i]; if (segment.SegmentType == WaterfallSegmentType.Sum) { isSum = true; } // Update sum segment values. OnUpdateSumSegmentValues(segment, i, isSum, origin); segment.BindProperties(); } else { segment = new WaterfallSegment(x1, y1, x2, y2, this) { XData = xValues[i], YData = YValues[i], Item = ActualData[i] }; // Raise segment created event. isSum = RaiseSegmentCreatedEvent(segment, i); // Update sum segment values. OnUpdateSumSegmentValues(segment, i, isSum, origin); Segments.Add(segment); } #region Adornment calculation if (AdornmentsInfo != null) { if (segment.SegmentType == WaterfallSegmentType.Sum) { if (Segments.IndexOf(segment) > 0 && AllowAutoSum) { if (this.AdornmentsInfo.AdornmentsPosition == AdornmentsPosition.TopAndBottom) { AddColumnAdornments(xValues[i], segment.WaterfallSum, x1, segment.WaterfallSum / 2, i, median); } else if (segment.WaterfallSum >= 0) { AddColumnAdornments(xValues[i], segment.WaterfallSum, x1, segment.Top, i, median); } else { AddColumnAdornments(xValues[i], segment.WaterfallSum, x1, segment.Bottom, i, median); } } else { if (this.AdornmentsInfo.AdornmentsPosition == AdornmentsPosition.TopAndBottom) { AddColumnAdornments(xValues[i], YValues[i], x1, y1 + (y2 - y1) / 2, i, median); } else if (YValues[i] >= 0) { AddColumnAdornments(xValues[i], YValues[i], x1, segment.Top, i, median); } else { AddColumnAdornments(xValues[i], YValues[i], x1, segment.Bottom, i, median); } } } else if (this.AdornmentsInfo.AdornmentsPosition == AdornmentsPosition.Top) { if (segment.SegmentType == WaterfallSegmentType.Positive) { AddColumnAdornments(xValues[i], YValues[i], x1, y1, i, median); } else { AddColumnAdornments(xValues[i], YValues[i], x1, y2, i, median); } } else if (this.AdornmentsInfo.AdornmentsPosition == AdornmentsPosition.Bottom) { if (segment.SegmentType == WaterfallSegmentType.Positive) { AddColumnAdornments(xValues[i], YValues[i], x1, y2, i, median); } else { AddColumnAdornments(xValues[i], YValues[i], x1, y1, i, median); } } else { AddColumnAdornments(xValues[i], YValues[i], x1, y1 + (y2 - y1) / 2, i, median); } } #endregion } } } this.ActualArea.IsUpdateLegend = true; }
/// <summary> /// Apply padding based on interval /// </summary> /// <param name="axis"></param> /// <param name="range"></param> /// <param name="interval"></param> /// <param name="rangePadding"></param> /// <param name="intervalType"></param> /// <returns></returns> internal static DoubleRange ApplyRangePadding(ChartAxis axis, DoubleRange range, double interval, DateTimeRangePadding rangePadding, DateTimeIntervalType intervalType) { DateTime startDate = range.Start.FromOADate(); DateTime endDate = range.End.FromOADate(); var dateTimeAxis = axis as DateTimeAxis; if (dateTimeAxis != null && dateTimeAxis.EnableBusinessHours) { return(ApplyBusinessHoursRangePadding(dateTimeAxis, range, interval, rangePadding, intervalType)); } if (rangePadding == DateTimeRangePadding.Round || rangePadding == DateTimeRangePadding.Additional) { switch (intervalType) { case DateTimeIntervalType.Years: int startYear = (int)((int)(startDate.Year / interval) * interval); int endYear = endDate.Year + (startDate.Year - startYear); if (startYear <= 0) { startYear = 1; } if (endYear <= 0) { endYear = 1; } if (rangePadding == DateTimeRangePadding.Round) { range = new DoubleRange(new DateTime(startYear, 1, 1, 0, 0, 0).ToOADate(), new DateTime(endYear, 12, 31, 23, 59, 59).ToOADate()); } else { range = new DoubleRange(new DateTime(startYear - (int)interval, 1, 1, 0, 0, 0).ToOADate(), new DateTime(endYear + (int)interval, 12, 31, 23, 59, 59).ToOADate()); } break; case DateTimeIntervalType.Months: int month = (int)((int)(startDate.Month / interval) * interval); if (month <= 0) { month = 1; } int endmonth = range.End.FromOADate().Month + (startDate.Month - month); if (endmonth <= 0) { endmonth = 1; } if (endmonth > 12) { endmonth = 12; } if (rangePadding == DateTimeRangePadding.Round) { range = new DoubleRange(new DateTime(startDate.Year, month, 1, 0, 0, 0).ToOADate(), new DateTime(endDate.Year, endmonth, endmonth == 2 ? 28 : 30, 0, 0, 0).ToOADate()); } else { range = new DoubleRange(new DateTime(startDate.Year, month, 1, 0, 0, 0).AddMonths((int)(-interval)).ToOADate(), new DateTime(endDate.Year, endmonth, endmonth == 2 ? 28 : 30, 0, 0, 0).AddMonths((int)interval).ToOADate()); } break; case DateTimeIntervalType.Days: int day = (int)((int)(startDate.Day / interval) * interval); if (day <= 0) { day = 1; } int endday = startDate.Day - day; if (endday <= 0) { endday = 1; } if (rangePadding == DateTimeRangePadding.Round) { range = new DoubleRange(new DateTime(startDate.Year, startDate.Month, day, 0, 0, 0).ToOADate(), new DateTime(endDate.Year, endDate.Month, endDate.Day, 23, 59, 59).AddDays(endday).ToOADate()); } else { range = new DoubleRange(new DateTime(startDate.Year, startDate.Month, day, 0, 0, 0).AddDays(-interval).ToOADate(), new DateTime(endDate.Year, endDate.Month, endDate.Day, 23, 59, 59).AddDays(interval + endday).ToOADate()); } break; case DateTimeIntervalType.Hours: int hour = (int)((int)(startDate.Hour / interval) * interval); int endhour = endDate.Hour + (startDate.Hour - hour); if (rangePadding == DateTimeRangePadding.Round) { range = new DoubleRange( new DateTime( startDate.Year, startDate.Month, startDate.Day, hour, 0, 0).ToOADate(), new DateTime( endDate.Year, endDate.Month, endDate.Day, endhour, 0, 0).ToOADate()); } else { range = new DoubleRange(new DateTime( startDate.Year, startDate.Month, startDate.Day, startDate.Hour, 0, 0).AddHours(-interval).ToOADate(), new DateTime( endDate.Year, endDate.Month, endDate.Day, endDate.Hour, 0, 0).AddHours(interval).ToOADate()); } break; case DateTimeIntervalType.Minutes: int minute = (int)((int)(startDate.Minute / interval) * interval); int endminute = range.End.FromOADate().Minute + (startDate.Minute - minute); if (rangePadding == DateTimeRangePadding.Round) { range = new DoubleRange( new DateTime( startDate.Year, startDate.Month, startDate.Day, startDate.Hour, minute, 0).ToOADate(), new DateTime( endDate.Year, endDate.Month, endDate.Day, endDate.Hour, endminute, 0).ToOADate()); } else { range = new DoubleRange(new DateTime( startDate.Year, startDate.Month, startDate.Day, startDate.Hour, startDate.Minute, 0).AddMinutes(-interval).ToOADate(), new DateTime( endDate.Year, endDate.Month, endDate.Day, endDate.Hour, endDate.Minute, 0).AddMinutes(interval).ToOADate()); } break; case DateTimeIntervalType.Seconds: int second = (int)((int)(startDate.Second / interval) * interval); int endsecond = range.End.FromOADate().Second + (startDate.Second - second); if (rangePadding == DateTimeRangePadding.Round) { range = new DoubleRange( new DateTime( startDate.Year, startDate.Month, startDate.Day, startDate.Hour, startDate.Minute, second, 0).ToOADate(), new DateTime( endDate.Year, endDate.Month, endDate.Day, endDate.Hour, endDate.Minute, endsecond, 0).ToOADate()); } else { range = new DoubleRange(new DateTime( startDate.Year, startDate.Month, startDate.Day, startDate.Hour, startDate.Minute, startDate.Second, 0).AddSeconds(-interval).ToOADate(), new DateTime( endDate.Year, endDate.Month, endDate.Day, endDate.Hour, endDate.Minute, endDate.Second, 0).AddSeconds(interval).ToOADate()); } break; case DateTimeIntervalType.Milliseconds: int milliseconds = (int)((int)(startDate.Millisecond / interval) * interval); int endmilliseconds = range.End.FromOADate().Millisecond + (startDate.Millisecond - milliseconds); if (rangePadding == DateTimeRangePadding.Round) { range = new DoubleRange( new DateTime( startDate.Year, startDate.Month, startDate.Day, startDate.Hour, startDate.Minute, startDate.Second, milliseconds).ToOADate(), new DateTime( endDate.Year, endDate.Month, endDate.Day, endDate.Hour, endDate.Minute, endDate.Second, endmilliseconds).ToOADate()); } else { range = new DoubleRange(new DateTime( startDate.Year, startDate.Month, startDate.Day, startDate.Hour, startDate.Minute, startDate.Second, startDate.Millisecond).AddMilliseconds(-interval).ToOADate(), new DateTime( endDate.Year, endDate.Month, endDate.Day, endDate.Hour, endDate.Minute, endDate.Second, endDate.Millisecond).AddMilliseconds(interval).ToOADate()); } break; } return(range); } return(range); }
/// <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 overridden 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) { if (isSegmentUpdated) { Series.SeriesRootPanel.Clip = null; } ChartTransform.ChartCartesianTransformer cartesianTransformer = transformer as ChartTransform.ChartCartesianTransformer; double xEnd = cartesianTransformer.XAxis.VisibleRange.End; DoubleRange range = cartesianTransformer.XAxis.VisibleRange; PathFigure figure = new PathFigure(); PathGeometry segmentGeometry = new PathGeometry(); double origin = containerSeries.ActualXAxis != null ? containerSeries.ActualXAxis.Origin : 0;//setting origin value for splinearea segment WindowsLineSegment lineSegment; figure.StartPoint = transformer.TransformToVisible(segmentPoints[0].X, segmentPoints[0].Y); lineSegment = new WindowsLineSegment(); lineSegment.Point = transformer.TransformToVisible(segmentPoints[1].X, segmentPoints[1].Y); figure.Segments.Add(lineSegment); strokeGeometry = new PathGeometry(); strokeFigure = new PathFigure(); strokePath = new Path(); if (containerSeries.IsClosed && isEmpty) { AddStroke(figure.StartPoint); lineSegment = new WindowsLineSegment(); lineSegment.Point = transformer.TransformToVisible(segmentPoints[1].X, segmentPoints[1].Y); strokeFigure.Segments.Add(lineSegment); } else if (!containerSeries.IsClosed) { AddStroke(transformer.TransformToVisible(segmentPoints[1].X, segmentPoints[1].Y)); } int i; for (i = 2; i < segmentPoints.Count; i += 3) { double xVal = segmentPoints[i].X; if (xVal >= range.Start && xVal <= range.End || xEnd >= range.Start && xEnd <= range.End) { if (Series.ShowEmptyPoints || ((!double.IsNaN(segmentPoints[i].Y) && !double.IsNaN(segmentPoints[i + 1].Y) && !double.IsNaN(segmentPoints[i + 2].Y)))) { BezierSegment segment = new BezierSegment(); segment.Point1 = transformer.TransformToVisible(segmentPoints[i].X, segmentPoints[i].Y); segment.Point2 = transformer.TransformToVisible(segmentPoints[i + 1].X, segmentPoints[i + 1].Y); segment.Point3 = transformer.TransformToVisible(segmentPoints[i + 2].X, segmentPoints[i + 2].Y); figure.Segments.Add(segment); if ((isEmpty && !Series.ShowEmptyPoints) || !containerSeries.IsClosed) { BezierSegment strokeSegment = new BezierSegment(); strokeSegment.Point1 = segment.Point1; strokeSegment.Point2 = segment.Point2; strokeSegment.Point3 = segment.Point3; strokeFigure.Segments.Add(strokeSegment); } } else { if ((double.IsNaN(segmentPoints[i].Y) && double.IsNaN(segmentPoints[i + 1].Y) && double.IsNaN(segmentPoints[i + 2].Y))) { lineSegment = new WindowsLineSegment(); lineSegment.Point = transformer.TransformToVisible(segmentPoints[i - 1].X, origin); figure.Segments.Add(lineSegment); lineSegment = new WindowsLineSegment(); lineSegment.Point = transformer.TransformToVisible(segmentPoints[i + 2].X, origin); figure.Segments.Add(lineSegment); } else if (i > 0 && (double.IsNaN(segmentPoints[i - 1].Y) || double.IsNaN(segmentPoints[i].Y))) { lineSegment = new WindowsLineSegment(); lineSegment.Point = transformer.TransformToVisible(segmentPoints[i + 2].X, origin); figure.Segments.Add(lineSegment); lineSegment = new WindowsLineSegment(); lineSegment.Point = transformer.TransformToVisible(segmentPoints[i + 2].X, double.IsNaN(segmentPoints[i + 2].Y) ? origin : segmentPoints[i + 2].Y); if ((!Series.ShowEmptyPoints && !double.IsNaN(segmentPoints[i + 2].Y)) || !containerSeries.IsClosed) { strokeFigure = new PathFigure(); strokeFigure.StartPoint = lineSegment.Point; strokeGeometry.Figures.Add(strokeFigure); } figure.Segments.Add(lineSegment); } } } } Point point = transformer.TransformToVisible(segmentPoints[i - 1].X, origin); lineSegment = new WindowsLineSegment(); lineSegment.Point = point; figure.Segments.Add(lineSegment); if (containerSeries.IsClosed && !double.IsNaN(segmentPoints[i - 1].Y)) { lineSegment = new WindowsLineSegment(); lineSegment.Point = point; strokeFigure.Segments.Add(lineSegment); } //figure.IsClosed = true; isSegmentUpdated = true; segmentGeometry.Figures.Add(figure); this.segPath.Data = segmentGeometry; }
/// <summary> /// This method is used to gets the selected data point segment pixel positions /// </summary> internal void GenerateStackingColumnPixels() { WriteableBitmap bmp = Area.fastRenderSurface; ChartTransform.ChartCartesianTransformer cartesianTransformer = CreateTransformer( new Size( Area.SeriesClipRect.Width, Area.SeriesClipRect.Height), true) as ChartTransform.ChartCartesianTransformer; bool x_isInversed = cartesianTransformer.XAxis.IsInversed; bool y_isInversed = cartesianTransformer.YAxis.IsInversed; double x1ChartVal, x2ChartVal, y1ChartVal, y2ChartVal; int i = dataPoint.Index; DoubleRange sbsInfo = this.GetSideBySideInfo(this); List <double> xValues = GetStackingSeriesXValues(this); if (!this.IsIndexed) { x1ChartVal = xValues[i] + sbsInfo.Start; x2ChartVal = xValues[i] + sbsInfo.End; y1ChartVal = YRangeEndValues[i]; y2ChartVal = YRangeStartValues[i]; } else { x1ChartVal = i + sbsInfo.Start; x2ChartVal = i + sbsInfo.End; y1ChartVal = YRangeEndValues[i]; y2ChartVal = YRangeStartValues[i]; } double x1Val = x_isInversed ? x2ChartVal : x1ChartVal; double x2Val = x_isInversed ? x1ChartVal : x2ChartVal; double y2Val = y_isInversed ? y1ChartVal : y2ChartVal; double y1Val = y_isInversed ? y2ChartVal : y1ChartVal; Point tlpoint = cartesianTransformer.TransformToVisible(x1Val, y1Val); Point rbpoint = cartesianTransformer.TransformToVisible(x2Val, y2Val); float x1Value = ((float)tlpoint.X); float x2Value = ((float)rbpoint.X); float y1Value = ((float)tlpoint.Y); float y2Value = ((float)rbpoint.Y); float x1 = 0; float x2 = 0; float y1 = 0; float y2 = 0; int width = (int)Area.SeriesClipRect.Width; int height = (int)Area.SeriesClipRect.Height; selectedSegmentPixels.Clear(); x1 = x1Value; x2 = x2Value; y1 = y1ChartVal > 0 ? y1Value : y2Value; y2 = y1ChartVal > 0 ? y2Value : y1Value; var spacingSegment = this as ISegmentSpacing; if (spacingSegment != null) { double spacing = spacingSegment.SegmentSpacing; if (spacing > 0 && spacing <= 1) { double leftpos = spacingSegment.CalculateSegmentSpacing(spacing, x2, x1); double rightpos = spacingSegment.CalculateSegmentSpacing(spacing, x1, x2); x1 = (float)(leftpos); x2 = (float)(rightpos); } } if (y1 < y2) { selectedSegmentPixels = bmp.GetRectangle(width, height, (int)(x1), (int)y1, (int)x2, (int)y2, selectedSegmentPixels); } else { selectedSegmentPixels = bmp.GetRectangle(width, height, (int)(x1), (int)y2, (int)x2, (int)y1, selectedSegmentPixels); } }