private CombinedSeries GetCombinedSeries(ISupportCombineMode combinableSeries) { Type type = combinableSeries.GetType(); ChartSeriesCombineMode combineMode = combinableSeries.CombineMode; AxisModel stackValueAxis = this.valueAxesExtractor(combinableSeries as IPlotAreaElementModelWithAxes); foreach (CombinedSeries series in this.CombinedSeries) { if (series.SeriesType == type && series.CombineMode == combineMode && (combineMode == ChartSeriesCombineMode.Cluster || ((combineMode == ChartSeriesCombineMode.Stack || combineMode == ChartSeriesCombineMode.Stack100) && series.StackValueAxis == stackValueAxis))) { return(series); } } CombinedSeries newSeries = new CombinedSeries(); newSeries.SeriesType = type; newSeries.CombineMode = combineMode; newSeries.CombineIndex = this.CombinedSeries.Count; newSeries.StackAxis = this.StackAxis; newSeries.StackValueAxis = stackValueAxis; this.CombinedSeries.Add(newSeries); return(newSeries); }
private void BuildYStripes(AxisModel yAxis, RadRect rect) { double height; double thickness = yAxis.TickThickness; double thicknessOffset = (int)(thickness / 2); int plotOriginX = (int)(this.GetChartArea().view.PlotOriginX *rect.Width); int plotOriginY = (int)(this.GetChartArea().view.PlotOriginY *rect.Height); foreach (AxisTickModel tick in yAxis.MajorTicks) { AxisTickModel nextMajor = tick.NextMajorTick; if (nextMajor == null) { break; } height = Math.Abs(tick.layoutSlot.Y - nextMajor.layoutSlot.Y); var top = yAxis.IsInverse ? nextMajor.layoutSlot.Y : tick.layoutSlot.Y; GridStripe stripe = new GridStripe(); stripe.BorderRect = new RadRect(rect.X, top + plotOriginY - height + thicknessOffset, rect.Width, height); stripe.FillRect = new RadRect(rect.X, top + plotOriginY - height + thickness, rect.Width, height - thickness); stripe.AssociatedTick = tick; this.yStripes.Add(stripe); } }
internal override void SetValueFromAxis(AxisModel axis, object newValue) { if (axis is NumericalAxisModel) { this.numericalPlot = newValue as NumericalAxisPlotInfo; if (this.numericalPlot != null) { this.isInNumericalRange = true; this.isPositive = this.numericalPlot.NormalizedValue >= this.numericalPlot.NormalizedOrigin; //// inverse axis with negative point value is equivalent to regular axis with positive point value if (this.numericalPlot.Axis.IsInverse && !RadMath.AreClose(this.numericalPlot.NormalizedValue, this.numericalPlot.NormalizedOrigin)) { this.isPositive ^= true; } } else { this.isInNumericalRange = false; this.isPositive = false; } } else if (axis is CategoricalAxisModel || axis is DateTimeContinuousAxisModel) { this.categoricalPlot = newValue as CategoricalAxisPlotInfo; this.isInCategoricalRange = true; } }
internal Tuple <object, object> ConvertPointToData(RadPoint coordinates, AxisModel firstAxis, AxisModel secondAxis) { object firstValue = null; object secondValue = null; if (this.view != null) { RadRect plotArea = this.plotArea.layoutSlot; double panOffsetX = this.view.PlotOriginX * plotArea.Width; double panOffsetY = this.view.PlotOriginY * plotArea.Height; RadRect plotAreaVirtualSize = new RadRect(plotArea.X, plotArea.Y, plotArea.Width * this.view.ZoomWidth, plotArea.Height * this.view.ZoomHeight); if (firstAxis != null && this.FirstAxes.Contains(firstAxis) && firstAxis.isUpdated) { firstValue = firstAxis.ConvertPhysicalUnitsToData(coordinates.X - panOffsetX, plotAreaVirtualSize); } if (secondAxis != null && this.SecondAxes.Contains(secondAxis) && secondAxis.isUpdated) { secondValue = secondAxis.ConvertPhysicalUnitsToData(coordinates.Y - panOffsetY, plotAreaVirtualSize); } } return(new Tuple <object, object>(firstValue, secondValue)); }
internal RadPoint ConvertDataToPoint(Tuple <object, object> data, AxisModel firstAxis, AxisModel secondAxis) { RadPoint coordinates = new RadPoint(double.NaN, double.NaN); if (this.view != null) { RadRect plotArea = this.plotArea.layoutSlot; RadRect plotAreaVirtualSize = new RadRect(plotArea.X, plotArea.Y, plotArea.Width * this.view.ZoomWidth, plotArea.Height * this.view.ZoomHeight); if (firstAxis != null && this.FirstAxes.Contains(firstAxis) && firstAxis.isUpdated) { AxisPlotInfo plotInfo = firstAxis.CreatePlotInfo(data.Item1); if (plotInfo != null) { coordinates.X = plotInfo.CenterX(plotAreaVirtualSize); } } if (secondAxis != null && this.SecondAxes.Contains(secondAxis) && secondAxis.isUpdated) { AxisPlotInfo plotInfo = secondAxis.CreatePlotInfo(data.Item2); if (plotInfo != null) { coordinates.Y = plotInfo.CenterY(plotAreaVirtualSize); } } } return(coordinates); }
private void BuildXStripes(AxisModel xAxis, RadRect rect) { double width; double thickness = xAxis.TickThickness; double thicknessOffset = (int)(thickness / 2); int plotOriginX = (int)(this.GetChartArea().view.PlotOriginX *rect.Width); int plotOriginY = (int)(this.GetChartArea().view.PlotOriginY *rect.Height); foreach (AxisTickModel tick in xAxis.MajorTicks) { AxisTickModel nextMajor = tick.NextMajorTick; if (nextMajor == null) { break; } width = Math.Abs(nextMajor.layoutSlot.X - tick.layoutSlot.X); var right = xAxis.IsInverse ? nextMajor.layoutSlot.X : tick.layoutSlot.X; GridStripe stripe = new GridStripe(); stripe.BorderRect = new RadRect(right + plotOriginX + thicknessOffset, rect.Y, width, rect.Height); stripe.FillRect = new RadRect(right + plotOriginY + thicknessOffset + thickness, rect.Y, width - thickness, rect.Height); stripe.AssociatedTick = tick; this.xStripes.Add(stripe); } }
internal void SetAxis(AxisModel axis, AxisType type) { Debug.Assert(axis != null, "axis should not be null!"); if (type == AxisType.First) { if (this.FirstAxes.Contains(axis)) { return; } this.FirstAxes.Add(axis); if (axis.isPrimary) { this.primaryFirstAxis = axis; } } else { if (this.SecondAxes.Contains(axis)) { return; } this.SecondAxes.Add(axis); if (axis.isPrimary) { this.primarySecondAxis = axis; } } axis.Type = type; this.AttachAxis(axis); }
public static CategoricalAxisPlotInfo Create(AxisModel axis, double value) { CategoricalAxisPlotInfo info = new CategoricalAxisPlotInfo(); info.Axis = axis; info.RangePosition = value; return(info); }
internal override object GetValueForAxis(AxisModel axis) { if (axis is NumericalAxisModel) { return(this.value); } return(this.Category); }
internal override object GetValueForAxis(AxisModel axis) { if (axis is NumericalAxisModel) { return(new Range(this.low, this.high)); } return(this.Category); }
internal override object GetValueForAxis(AxisModel axis) { if (axis.type == AxisType.First) { return(this.xValue); } return(this.yValue); }
internal override object GetValueForAxis(AxisModel axis) { if (axis is IContinuousAxisModel) { return(this.value); } return(null); }
internal override object GetValueForAxis(AxisModel axis) { if (axis is NumericalAxisModel) { return(new Ohlc(this.high, this.low, this.open, this.close)); } return(this.Category); }
public void DetachAxis(AxisModel axis) { if (this.FirstAxis == axis) { this.FirstAxis = null; } else if (this.SecondAxis == axis) { this.SecondAxis = null; } }
public virtual void AttachAxis(AxisModel axis, AxisType type) { if (type == AxisType.First) { this.FirstAxis = axis; } else { this.SecondAxis = axis; } }
public static NumericalAxisPlotInfo Create(AxisModel axis, double plotOffset, double value, double origin) { NumericalAxisPlotInfo info = new NumericalAxisPlotInfo(); info.Axis = axis; info.PlotOriginOffset = plotOffset; info.NormalizedValue = value; info.NormalizedOrigin = origin; return(info); }
protected static bool TryCreatePlotInfo(AxisModel axis, object value, out AxisPlotInfo plotInfo) { if (axis == null || value == null || !axis.isUpdated) { plotInfo = null; return(false); } plotInfo = axis.CreatePlotInfo(value); return(plotInfo != null); }
private void UpdateCombineStrategy(AxisModel stackAxis, IList <ChartSeriesModel> series) { ChartSeriesCombineStrategy strategy; if (!this.SeriesCombineStrategies.TryGetValue(stackAxis, out strategy)) { strategy = new ChartSeriesCombineStrategy(); this.SeriesCombineStrategies.Set(stackAxis, strategy); } strategy.Update(series, stackAxis); }
internal override void OnPropertyChanged(RadPropertyEventArgs e) { // update local value first and then call base to raise the PropertyChanged event (if needed) if (e.Key == AxisPropertyKey) { this.axis = (AxisModel)e.NewValue; this.UpdateCore(); } base.OnPropertyChanged(e); }
internal override void SetValueFromAxis(AxisModel axis, object value) { NumericalAxisPlotInfo plot = value as NumericalAxisPlotInfo; if (axis.type == AxisType.First) { this.xPlot = plot; } else { this.yPlot = plot; } }
internal override void SetValueFromAxis(AxisModel axis, object newValue) { NumericalAxisPlotInfo plotInfo = newValue as NumericalAxisPlotInfo; if (axis.type == AxisType.First) { this.valuePlot = plotInfo; } else { this.anglePlot = plotInfo; } }
public void Update(IList <ChartSeriesModel> series, AxisModel stackAxis) { if (this.isUpdated) { return; } this.StackAxis = stackAxis; if (stackAxis.Type == AxisType.First) { this.valueAxesExtractor = sm => sm.SecondAxis; } else { this.valueAxesExtractor = sm => sm.FirstAxis; } foreach (ChartSeriesModel model in series) { if (!model.presenter.IsVisible) { continue; } AxisModel stackValueAxis = this.valueAxesExtractor(model as IPlotAreaElementModelWithAxes); if (!this.StackValueAxes.Contains(stackValueAxis)) { this.StackValueAxes.Add(stackValueAxis); } ISupportCombineMode combinableSeries = model as ISupportCombineMode; if (combinableSeries == null || combinableSeries.CombineMode == ChartSeriesCombineMode.None) { this.NonCombinedSeries.Add(model); continue; } CombinedSeries combinedSeries = this.GetCombinedSeries(combinableSeries); combinedSeries.Series.Add(model); this.HasCombination = true; } if (this.HasCombination) { this.BuildGroups(); } this.isUpdated = true; }
internal override object GetValueForAxis(AxisModel axis) { if (axis.type == AxisType.First) { return(this.value); } if (this.value >= 0) { return(this.angle); } // consider negative values return(this.angle + 180); }
internal override void SetValueFromAxis(AxisModel axis, object value) { // ChartSeries labels rely on isPositive to flip alignment, so isPositive is set to true by default this.isPositive = true; if (axis is NumericalAxisModel) { this.numericalPlot = value as NumericalAxisRangePlotInfo; this.isInNumericalRange = true; } else if (axis is CategoricalAxisModel || axis is DateTimeContinuousAxisModel) { this.categoricalPlot = value as CategoricalAxisPlotInfo; this.isInCategoricalRange = true; } }
public AxisUpdateContext(AxisModel axis, IList <ChartSeriesModel> series, IEnumerable <ChartSeriesCombineStrategy> seriesCombineStrategies) { this.Series = series; if (axis.SupportsCombinedPlot) { return; } this.CombinedSeries = new List <CombinedSeries>(); this.NonCombinedSeries = new List <ChartSeriesModel>(); this.MinimumStackSum = double.PositiveInfinity; this.MaximumStackSum = double.NegativeInfinity; foreach (ChartSeriesCombineStrategy combineStrategy in seriesCombineStrategies) { if (!combineStrategy.StackValueAxes.Contains(axis)) { continue; } // extract only relevant combined and non combined series. foreach (var seriesModel in series) { bool isCombined = false; foreach (var combinedSeries in combineStrategy.CombinedSeries) { if (combinedSeries.Series.Contains(seriesModel)) { this.CombinedSeries.Add(combinedSeries); this.IsStacked |= combinedSeries.CombineMode == ChartSeriesCombineMode.Stack; this.IsStacked100 |= combinedSeries.CombineMode == ChartSeriesCombineMode.Stack100; isCombined = true; } } if (!isCombined && !this.NonCombinedSeries.Contains(seriesModel)) { this.NonCombinedSeries.Add(seriesModel); } } if (combineStrategy.MinimumStackSums.ContainsKey(axis)) { this.MinimumStackSum = Math.Min(combineStrategy.MinimumStackSums[axis], this.MinimumStackSum); this.MaximumStackSum = Math.Max(combineStrategy.MaximumStackSums[axis], this.MaximumStackSum); } } }
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(); } }
public void Measure(RadSize availableSize) { this.desiredWidth = 0; this.desiredHeight = 0; for (int i = 0; i < this.axes.Count; i++) { AxisModel axis = this.axes[i]; axis.Measure(availableSize); this.desiredWidth = this.desiredWidth + axis.desiredSize.Width; this.desiredHeight = this.desiredHeight + axis.desiredSize.Height; RadThickness margin = axis.desiredMargin; this.desiredMargin.Left = Math.Max(this.desiredMargin.Left, margin.Left); this.desiredMargin.Top = Math.Max(this.desiredMargin.Top, margin.Top); this.desiredMargin.Right = Math.Max(this.desiredMargin.Right, margin.Right); this.desiredMargin.Bottom = Math.Max(this.desiredMargin.Bottom, margin.Bottom); } }
internal override void OnPropertyChanged(RadPropertyEventArgs e) { // update local value first and then call base to raise the PropertyChanged event (if needed) if (e.Key == FirstAxisPropertyKey) { this.firstAxis = (AxisModel)e.NewValue; this.OnFirstAxisChanged(); } else if (e.Key == SecondAxisPropertyKey) { this.secondAxis = (AxisModel)e.NewValue; this.OnSecondAxisChanged(); } base.OnPropertyChanged(e); }
internal void RemoveAxis(AxisModel axis) { if (axis.type == AxisType.First) { this.FirstAxes.Remove(axis); if (axis.isPrimary) { this.primaryFirstAxis = null; } } else { this.SecondAxes.Remove(axis); if (axis.isPrimary) { this.primarySecondAxis = null; } } this.SeriesCombineStrategies.Remove(axis); this.DetachAxis(axis); }
internal override RadRect ArrangeOverride(RadRect rect) { this.radialLines.Clear(); this.polarLines.Clear(); RadPoint center = RadPoint.Round(rect.Center); double radius = Math.Max(0, rect.Width / 2); PolarChartAreaModel polarArea = this.GetChartArea <PolarChartAreaModel>(); PolarAxisModel polarAxis = polarArea.PolarAxis; foreach (AxisTickModel tick in polarAxis.MajorTicks) { double tickRadius = (int)(((double)tick.normalizedValue * radius) + 0.5); this.radialLines.Add(new RadCircle() { Center = center, Radius = tickRadius }); } AxisModel angleAxis = polarArea.AngleAxis; foreach (AxisTickModel tick in angleAxis.MajorTicks) { // do not add a line for the last tick if (RadMath.IsOne(angleAxis.IsInverse ? 1 - tick.normalizedValue : tick.normalizedValue)) { continue; } double angle = polarArea.NormalizeAngle((double)tick.value); this.polarLines.Add(new RadPolarVector() { Center = center, Point = tick.layoutSlot.Location, Angle = angle }); } return(rect); }