I am trying to create a Composite Chart that has a Polynomial Fit using a Scatter layer and using Scatter layer for the points.The problem is,the curve becomes really jagged. I have tried using separate X and Y axis and used SplineChart for one layer and ScatterChart for another layer but when I did the chart wouldn't display the points of the Scatter layer at the correct X,Y coordinates. Is there a better way to plot the Polynomial and display the Points in a Scatter layer? Also the user can also set the degree and interval that is used to calculate the Polynomial curve after the Chart has been displayed. This has caused issues with the chart not displaying the points correctly. All the series are bound to datatables or a binding list.
int topMargin = 5; int leftMargin = 5; int chartWidth = 90; int chartHeight = 100; var labelHash = new Hashtable(); labelHash.Add("TOOLTIPS", new CostToolTipRenderer(graphTable)); labelHash.Add("X_AXIS", new XAxisLabelRenderer(trendTable)); base.LabelHash = labelHash; base.Tooltips.FormatString = "<TOOLTIPS>"; base.DataSource = graphTable; base.DataBind(); this.ChartType = ChartType.Composite; this.CompositeChart.ChartAreas.Clear(); this.Series.Clear(); this.CompositeChart.Legends.Clear(); this.CompositeChart.ChartLayers.Clear(); ChartArea chartArea = new ChartArea(); chartArea.Border.Thickness = 0; chartArea.BoundsMeasureType = MeasureType.Percentage; chartArea.Bounds = new Rectangle(leftMargin, topMargin, chartWidth, chartHeight); this.CompositeChart.ChartAreas.Add(chartArea); // Create X axis AxisItem axisX = new AxisItem(); axisX.DataType = AxisDataType.Numeric; axisX.Labels.ItemFormatString = "<DATA_VALUE:###,###,###>"; //axisX.Labels.ItemFormatString = "<X_AXIS> "; axisX.SetLabelAxisType = SetLabelAxisType.ContinuousData; axisX.OrientationType = AxisNumber.X_Axis; axisX.Labels.Layout.Behavior = AxisLabelLayoutBehaviors.Auto; axisX.Labels.Orientation = TextOrientation.Custom; axisX.Labels.VerticalAlign = StringAlignment.Far; axisX.Labels.HorizontalAlign = StringAlignment.Near; axisX.Labels.OrientationAngle = 45; // Set the interval for the X axis axisX.RangeType = AxisRangeType.Custom; var trendMax = trendTable.AsEnumerable().Max(x => x.Field<double>("X")); var chartMax = PlanInfoList.Max(x => x.ExcessCapacity); var max= chartMax > trendMax ? chartMax : trendMax; axisX.RangeMin = 0; axisX.RangeMax = max + max * .05; axisX.TickmarkInterval = Interval; axisX.TickmarkStyle = AxisTickStyle.DataInterval; axisX.Extent = 150; chartArea.Axes.Add(axisX); // Create Y axis AxisItem axisY = new AxisItem(); axisY.DataType = AxisDataType.Numeric; axisY.Labels.ItemFormatString = "<DATA_VALUE: $###,###,###>"; axisY.Labels.HorizontalAlign = StringAlignment.Far; axisY.SetLabelAxisType = SetLabelAxisType.ContinuousData; axisY.OrientationType = AxisNumber.Y_Axis; // Set the custom interval for the Y axis axisY.RangeType = AxisRangeType.Custom; trendMax = trendTable.AsEnumerable().Max(x => x.Field<double>("Y")); var trendMin = trendTable.AsEnumerable().Min(x => x.Field<double>("Y")); chartMax= PlanInfoList.Max(x => x.TotalCost); var chartMin= PlanInfoList.Min(x => x.TotalCost); axisY.RangeMin = chartMin < trendMin ? chartMin : trendMin; axisY.RangeMax = chartMax>trendMax?chartMax:trendMax; axisY.Labels.Font = new Font("Ariel", 10f); axisY.Extent = 50; chartArea.Axes.Add(axisY); // Create a Trend Line(Polynomial) series XYSeries trendSeries = new XYSeries(); trendSeries.Label = "Trend Analysis"; trendSeries.PEs.Add(new PaintElement(Color.LimeGreen)); // Create a Cost series XYSeries costSeries = new XYSeries(); costSeries.Label = "Total Cost"; costSeries.PEs.Add(new PaintElement(Color.Red)); // Add DataSource and x,y columns to trend XYSeries trendSeries.Data.DataSource = trendTable; trendSeries.Data.ValueXColumn = "X"; trendSeries.Data.ValueYColumn = "Y"; costSeries.Data.DataSource = graphTable; costSeries.Data.ValueXColumn = "ExcessCapacity"; costSeries.Data.ValueYColumn = "TotalCost"; // Add a Trend ChartLayerAppearance var trendLayer = new ChartLayerAppearance(); trendLayer.ChartType = ChartType.ScatterChart; trendLayer.ChartArea = chartArea; trendLayer.AxisX = axisX; trendLayer.AxisY = axisY; trendLayer.Series.Add(trendSeries); // Add a LineAppearance to draw the polynomial fit var sceTrend = new ScatterChartAppearance(); sceTrend.ConnectWithLines = true; sceTrend.Icon = SymbolIcon.None; sceTrend.LineAppearance.Thickness = 5; sceTrend.LineAppearance.DrawStyle = LineDrawStyle.Dash; trendLayer.ChartTypeAppearance = sceTrend; // Add a Cost ChartLayerAppearance var costLayer = new ChartLayerAppearance(); costLayer.ChartType = ChartType.ScatterChart; costLayer.ChartArea = chartArea; costLayer.AxisX = axisX; costLayer.AxisY = axisY; costLayer.Series.Add(costSeries); // Add a Cost ScartChartAppearance var scaCost = new ScatterChartAppearance(); scaCost.ConnectWithLines = false; scaCost.Icon = SymbolIcon.Circle; scaCost.LineAppearance.Thickness = 5; scaCost.LineAppearance.DrawStyle = LineDrawStyle.Dash; costLayer.ChartTypeAppearance = scaCost; // Add trend XYSereies this.Series.Add(trendSeries); // Add cost XYSeries this.Series.Add(costSeries); // Add trend Chart layer to chart this.CompositeChart.ChartLayers.Add(trendLayer); // Add cost Chart layer to chart this.CompositeChart.ChartLayers.Add(costLayer); this.TitleLeft.Text = "Total Cost"; this.TitleLeft.Visible = true; this.TitleLeft.Extent = 50; this.TitleLeft.HorizontalAlign = StringAlignment.Center; this.TitleLeft.Font = new Font("Ariel", 12F); this.TitleLeft.FontColor = Color.DarkBlue; this.TitleBottom.Text = "Excess Capacity"; this.TitleBottom.Visible = true; this.TitleBottom.HorizontalAlign = StringAlignment.Center; this.TitleBottom.Extent = 50; this.TitleBottom.Font = new Font("Ariel", 12F); this.TitleBottom.FontColor = Color.DarkBlue; this.TitleTop.Text = "Trend Analysis Report"; this.TitleTop.Visible = true; this.TitleTop.HorizontalAlign = StringAlignment.Center; this.TitleTop.Font = new Font("Ariel", 14F,FontStyle.Bold); this.TitleTop.FontColor = Color.DarkBlue; // Create Composite legend located at bottom left hand corner of the chart var legend = new CompositeLegend(); legend.ChartLayers.Add(trendLayer); legend.ChartLayers.Add(costLayer); legend.Bounds = new Rectangle(2, 90, 5, 7); legend.BoundsMeasureType = MeasureType.Percentage; legend.PE.ElementType = PaintElementType.Gradient; legend.PE.FillGradientStyle = GradientStyle.ForwardDiagonal; legend.PE.Fill = Color.CornflowerBlue; legend.PE.FillStopColor = Color.Transparent; legend.Border.CornerRadius = 10; legend.Border.Thickness = 1; this.CompositeChart.Legends.Add(legend);
Hello,
Thank you for posting in our forums!
The SplineChart requires different axis types than the Scatter types, so you would need to create additional axes for each series to render correctly.
I would also recommend looking into using the UltraDataChart which may work better for your scenario.
If you have any further questions or concerns with this, please let me know.
I have tried using a separate axis but the problem I ran in to was that the points in the Scatter layer would not line up on the X axis with the ones on the Spline layer. Since the XYSeries for the Scatter layer uses a data value for the x and the Spline uses string value for x, this caused the points in the Scatter layer to not line up with the string values displayed in the x axis labels that the Spline layer created using the Numeric Series even though the data value for the points should have fallen between the x axis values. I hide the Y axis labels for the Spline chart and hide the x axis labels for the Scatter layer, this caused the points on the Scatter layer to shift to the far left.
Could you post a screenshot of what that looks like for me?
I would recommend using the UltraDataChart instead of the UltraChart for this.
The UltraDataChart has a ScatterSpline series that uses numeric X and Y axes along with a ScatterPoint series using the same axis types.
You can find more information on this in our documentation here.
Please let me know if you have any further questions or concerns with this.