private void UpdatePlotOrigin(AxisUpdateContext context) { if (DefaultOrigin >= this.actualRange.maximum) { this.normalizedOrigin = 1; } else if (DefaultOrigin > this.actualRange.minimum) { this.normalizedOrigin = (DefaultOrigin - this.actualRange.minimum) / (this.actualRange.maximum - this.actualRange.minimum); } else { this.normalizedOrigin = 0; } // apply the plot origin to the series if (context.Series != null) { double plotOrigin = this.IsInverse ? 1 - this.normalizedOrigin : this.normalizedOrigin; foreach (ChartSeriesModel model in context.Series) { model.SetValue(AxisModel.PlotOriginPropertyKey, plotOrigin); } } }
internal override void PlotCore(AxisUpdateContext context) { int count = this.categories.Count; if (count == 0) { return; } double step = this.CalculateRelativeStep(count); double value = 0; double gap = this.GapLength * step; double length = step - gap; double offset = this.actualPlotMode == AxisPlotMode.OnTicks ? 0 : step / 2; double position; for (int i = 0; i < count; i++) { AxisCategory category = this.categories[i]; position = this.IsInverse ? 1 - value - offset : value + offset; foreach (DataPoint point in category.Points) { CategoricalAxisPlotInfo info = CategoricalAxisPlotInfo.Create(this, value); info.CategoryKey = category.KeySource; info.Position = position; info.Length = length; point.SetValueFromAxis(this, info); } value += step; } }
internal override void UpdateActualRange(AxisUpdateContext context) { base.UpdateActualRange(context); // actual range always starts from zero this.actualRange.minimum = 0; }
internal override void UpdateCore(AxisUpdateContext context) { this.UpdateActualPlotMode(context.Series); this.categories.Clear(); this.BuildCategories(context); }
internal override void UpdateCore(AxisUpdateContext context) { base.UpdateCore(context); this.UpdateActualRange(context); this.UpdatePlotOrigin(context); this.isStacked100 = context.IsStacked100; }
internal void Plot(AxisUpdateContext context) { if (!this.isPlotValid) { // actual points plot this.PlotCore(context); this.isPlotValid = true; } }
internal void Update(AxisUpdateContext context) { if (this.isUpdated) { return; } this.UpdateCore(context); this.isUpdated = true; }
internal override void PlotCore(AxisUpdateContext context) { if (!this.CanPlot) { return; } decimal delta = this.plotInfo.Max - this.plotInfo.Min; if (delta == 0) { Debug.Assert(false, "Invalid plot pass."); return; } decimal pointPosition, timeSlotPosition, timeSlotLength; decimal pointSlotLength; decimal extend = this.plotInfo.Extend / 2; bool uniform = this.PlotStretch == DateTimePlotStretchMode.Uniform; foreach (DateTimePoint value in this.values) { if (value.Slot == null) { // We want to run the tests in both Debug and Release modes. this.ThrowNoTimeSlotException(); continue; } decimal pointTicks = value.Date.Ticks; pointPosition = (pointTicks - this.plotInfo.Min + extend) / delta; timeSlotLength = value.Slot.Ticks / delta; timeSlotPosition = pointPosition - (timeSlotLength / 2); if (uniform) { int pointCount = (value.Point.parent as ChartSeriesModel).DataPointsInternal.Count; pointSlotLength = (1m - this.gapLength) / pointCount; } else { pointSlotLength = (1m - this.gapLength) * timeSlotLength; } CategoricalAxisPlotInfo currentPlotInfo = CategoricalAxisPlotInfo.Create(this, (double)timeSlotPosition); currentPlotInfo.CategoryKey = value.Date; currentPlotInfo.Position = this.IsInverse ? 1 - (double)pointPosition : (double)pointPosition; currentPlotInfo.Length = (double)pointSlotLength; value.Point.SetValueFromAxis(this, currentPlotInfo); } }
private void PlotStacked100(AxisUpdateContext context) { // Note: Stacked100 series cannot be combined with stacked & normal series // so we should not plot any non-combined series here. foreach (CombinedSeries series in context.CombinedSeries) { foreach (CombineGroup group in series.Groups) { this.PlotCombineGroup(group, (stack, value) => value / (stack.PositiveSum - stack.NegativeSum)); } } }
private void PlotStacked(AxisUpdateContext context) { foreach (CombinedSeries series in context.CombinedSeries) { foreach (CombineGroup group in series.Groups) { this.PlotCombineGroup(group, (stack, value) => value); } } this.PlotNormal(context.NonCombinedSeries); }
internal override void UpdateCore(AxisUpdateContext context) { // reset the validation flag this.validCategories = true; base.UpdateCore(context); if (this.validCategories) { // sort the categories so that they are arranged in a chronological order this.categories.Sort(new DateTimeComparer()); } }
private void BuildCategories(AxisUpdateContext context) { if (context.Series == null) { return; } bool autoGroup = this.AutoGroup; Dictionary <object, AxisCategory> categoriesByKey = new Dictionary <object, AxisCategory>(8); AxisPlotDirection direction = this.type == AxisType.First ? AxisPlotDirection.Vertical : AxisPlotDirection.Horizontal; foreach (ChartSeriesModel series in context.Series) { // tell each series what is the plot direction series.SetValue(AxisModel.PlotDirectionPropertyKey, direction); if (!series.presenter.IsVisible) { continue; } foreach (DataPoint point in series.DataPointsInternal) { object value = this.GetCategoryValue(point); object categoryKey = this.GetCategoryKey(point, value); if (categoryKey == null) { continue; } AxisCategory category; if (autoGroup) { if (!categoriesByKey.TryGetValue(categoryKey, out category)) { category = this.CreateCategory(categoryKey, value); categoriesByKey[categoryKey] = category; } } else { category = this.CreateCategory(categoryKey, value); } category.Points.Add(point); } } }
internal override void PlotCore(AxisUpdateContext context) { if (context.IsStacked) { this.PlotStacked(context); } else if (context.IsStacked100) { this.PlotStacked100(context); } else if (context.Series != null) { this.PlotNormal(context.Series); } }
internal override void UpdateActualRange(AxisUpdateContext context) { this.actualRange = new ValueRange <double>(0, 360); object userStep = this.GetValue(MajorStepPropertyKey); if (userStep != null) { this.majorStep = (double)userStep; } else { this.majorStep = 30; } }
private void UpdateAxis(AxisModel axis, IList <ChartSeriesModel> series) { Debug.Assert(axis != null, "A series has not found any axes!"); AxisUpdateContext context = new AxisUpdateContext(axis, series, this.SeriesCombineStrategies.EnumerateValues()); axis.Update(context); bool plotInvalid = axis.isPlotValid; // plot points axis.Plot(context); if (axis.SupportsCombinedPlot && !plotInvalid && this.SeriesCombineStrategies.ContainsKey(axis)) { this.SeriesCombineStrategies[axis].Plot(); } }
internal virtual void UpdateActualRange(AxisUpdateContext context) { // TODO: Do not calculate auto-range if both min and max are user-defined this.pointMinMax = this.CalculateRange(context); this.actualRange = this.pointMinMax; object userMin = this.GetValue(MinimumPropertyKey); if (userMin != null) { this.actualRange.minimum = this.TransformValue((double)userMin); } object userMax = this.GetValue(MaximumPropertyKey); if (userMax != null) { this.actualRange.maximum = this.TransformValue((double)userMax); } this.actualRange.maximum = Math.Max(this.actualRange.minimum, this.actualRange.maximum); RangeCalculator calculator = new RangeCalculator(this, userMin != null, userMax != null); if (!context.IsStacked100) { this.actualRange = calculator.Extend(); } object userStep = this.GetValue(MajorStepPropertyKey); if (userStep != null) { // LogarithmicAxis.ExponentStep now specifies the actual exponent so we should not "transform" the step value here. this.majorStep = (double)userStep; } else { this.majorStep = this.CalculateAutoStep(this.actualRange); } this.actualRange = calculator.RoundToMajorStep(this.majorStep); if (this.userTickCount > 0 && userStep == null) { this.RoundToUserTicks(); } }
private ValueRange <double> CalculateRange(AxisUpdateContext context) { ValueRange <double> range; if (context.IsStacked) { range = this.CalculateStackedRange(context); } else if (context.IsStacked100) { range = CalculateStacked100Range(context); } else { range = this.CalculateNormalRange(context.Series); } return(range); }
private void BuildValues(AxisUpdateContext context) { this.values.Clear(); if (context.Series == null) { return; } AxisPlotDirection direction = this.type == AxisType.First ? AxisPlotDirection.Vertical : AxisPlotDirection.Horizontal; foreach (ChartSeriesModel series in context.Series) { // tell each series what is the plot direction series.SetValue(AxisModel.PlotDirectionPropertyKey, direction); if (!series.presenter.IsVisible) { continue; } foreach (DataPoint point in series.DataPointsInternal) { object value = point.GetValueForAxis(this); DateTime date; if (!DateTimeHelper.TryGetDateTime(value, out date)) { continue; } DateTimePoint datePoint = new DateTimePoint() { Point = point, Date = date }; this.values.Add(datePoint); } } // sort all the values chronologically this.values.Sort(); }
private ValueRange <double> CalculateStackedRange(AxisUpdateContext context) { ValueRange <double> stackedRange = new ValueRange <double>(); stackedRange.minimum = context.MinimumStackSum; stackedRange.maximum = context.MaximumStackSum; // loop through non-combined series to check min/max value in their points ValueRange <double> nonCombinedRange = this.CalculateNormalRange(context.NonCombinedSeries); if (stackedRange.minimum > nonCombinedRange.minimum) { stackedRange.minimum = nonCombinedRange.minimum; } if (stackedRange.maximum < nonCombinedRange.maximum) { stackedRange.maximum = nonCombinedRange.maximum; } return(stackedRange); }
internal override void UpdateCore(AxisUpdateContext context) { this.BuildValues(context); if (this.values.Count == 0) { return; } this.UpdateActualPlotMode(context.Series); this.UpdateActualRange(); this.FindMinDelta(); if (!this.CanPlot) { return; } this.UpdateUnits(); this.UpdatePlotInfo(); this.BuildTimeSlots(); }
internal virtual void UpdateCore(AxisUpdateContext context) { }
private static ValueRange <double> CalculateStacked100Range(AxisUpdateContext context) { // Note: Stacked100 series cannot be combined with stacked & normal series // so we should not loop through any potentially non-combined series here. ValueRange <double> stacked100Range = new ValueRange <double>(double.PositiveInfinity, double.NegativeInfinity); foreach (CombinedSeries series in context.CombinedSeries) { foreach (CombineGroup group in series.Groups) { foreach (CombineStack stack in group.Stacks) { if (stack.PositiveSum == 0 && stack.NegativeSum == 0) { continue; } if (stack.PositiveSum == 0) { if (stacked100Range.maximum < 0) { stacked100Range.maximum = 0; } if (stacked100Range.minimum > -1) { stacked100Range.minimum = -1; } } else if (stack.NegativeSum == 0) { if (stacked100Range.maximum < 1) { stacked100Range.maximum = 1; } if (stacked100Range.minimum > 0) { stacked100Range.minimum = 0; } } else { double calculatedValue = stack.PositiveSum / (stack.PositiveSum - stack.NegativeSum); if (calculatedValue > stacked100Range.maximum) { stacked100Range.maximum = calculatedValue; } calculatedValue = stack.NegativeSum / (stack.PositiveSum - stack.NegativeSum); if (calculatedValue < stacked100Range.minimum) { stacked100Range.minimum = calculatedValue; } } if (stacked100Range.minimum == -1 && stacked100Range.maximum == 1) { return(stacked100Range); } } } } // Stacked100 series may have had no data points added if (stacked100Range.minimum == double.PositiveInfinity) { stacked100Range.minimum = 0d; } if (stacked100Range.maximum == double.NegativeInfinity) { stacked100Range.maximum = 0d; } return(stacked100Range); }