This is a migrated thread and some comments may be shown as answers.

Points plotted in wrong locations

4 Answers 124 Views
Chart (HTML5)
This is a migrated thread and some comments may be shown as answers.
Travis
Top achievements
Rank 1
Iron
Travis asked on 20 Apr 2016, 03:02 PM

So,I have an HtmlChart that I'm using for some graphs a client of mine needs. I've managed to get everything done up just so, but I noticed when I looked at the tooltip for the points,that the points appear to be plotted in the wrong location. (See image)

I've double-checked that the tooltip is showing the correct values for the points. But as you can see in the image, the points are off.

 

Any help with this is greatly appreciated.

4 Answers, 1 is accepted

Sort by
0
Travis
Top achievements
Rank 1
Iron
answered on 20 Apr 2016, 03:16 PM

Turns out, but subtracting an additional .5 from the MinValues of the X and Y Axis and adding an additional .5 to the MaxValues of the X and Y Axis, it plots correctly.

So, it appears, if you set the MinValues to the minimum point values and set the MaxValues to the maximum point values + 1, the chart will not plot correctly.It doesn't make much sense to me, but at least now I have a work-around.

0
Ianko
Telerik team
answered on 25 Apr 2016, 07:28 AM
Hi Travis,

I tried to replicate the same situation locally, but to no avail. 

Here is the code I used:
<telerik:RadHtmlChart runat="server" ID="ScatterLineChart1" Transitions="true">
    <PlotArea>
        <Series>
            <telerik:ScatterLineSeries Name="0.8C" MissingValues="Gap">
                <MarkersAppearance MarkersType="Circle" />
                <SeriesItems>
                    <telerik:ScatterSeriesItem X="28.6" Y="89.8" />
                    <telerik:ScatterSeriesItem X="30" Y="90" />
                </SeriesItems>
            </telerik:ScatterLineSeries>
        </Series>
        <XAxis MinValue="27" MaxValue="35">
            <MinorGridLines Visible="false" />
        </XAxis>
        <YAxis MinValue="84" MaxValue="91">
            <MinorGridLines Visible="false" />
        </YAxis>
         
    </PlotArea>
</telerik:RadHtmlChart>

And here is the result I get:


Regards,
Ianko
Telerik
Do you need help with upgrading your ASP.NET AJAX, WPF or WinForms projects? Check the Telerik API Analyzer and share your thoughts.
0
Travis
Top achievements
Rank 1
Iron
answered on 25 Apr 2016, 04:52 PM

I am postingg the ASP.NET code and the C# code I have in the code-behind in this post so you can create a single page ASP.NET WebForms app and duplicate the results:

<%@ Page Language="C#" AutoEventWireup="true" CodeBehind="Default.aspx.cs" Inherits="HtmlChartProblem.Default" %>
 
<%@ Register Assembly="Telerik.Web.UI" Namespace="Telerik.Web.UI" TagPrefix="telerik" %>
 
<!DOCTYPE html>
 
<head runat="server">
    <title></title>
</head>
<body>
    <form id="form1" runat="server">
    <div>
        <asp:ScriptManager ID="ScriptManager1" runat="server"></asp:ScriptManager>
        <telerik:RadHtmlChart ID="chartProctor" runat="server" Width="300" Height="275" BackColor="WhiteSmoke" BorderColor="Black" BorderWidth="1">
            <PlotArea>
                <XAxis AxisCrossingValue="0" Color="Black" MajorTickType="Outside" MinorTickType="Outside"
                    Reversed="false" Step="1" Type="Auto">
                    <LabelsAppearance DataFormatString="{0:D}" RotationAngle="0" />
                    <MajorGridLines Color="#000000" Width="1" />
                    <MinorGridLines Color="Black" Width="1" Visible="false" />
                    <TitleAppearance Position="Center" RotationAngle="0" Text="Moisture Content (%)" />
                </XAxis>
                <YAxis AxisCrossingValue="0" Color="Black" MajorTickSize="1" MajorTickType="Outside"
                    MinorTickSize="1" MinorTickType="None" MinValue="0" Reversed="false"
                    Step="2" Type="Numeric">
                    <LabelsAppearance DataFormatString="{0:D}" RotationAngle="0" />
                    <MajorGridLines Color="#000000" Width="1" />
                    <MinorGridLines Color="#F7F7F7" Width="1" Visible="false" />
                    <TitleAppearance Position="Center" RotationAngle="-90" Text="Dry Density (pcf)" />
                </YAxis>
            </PlotArea>
            <Legend>
                <Appearance Visible="false" Position="Bottom" />
            </Legend>
        </telerik:RadHtmlChart>
    </div>
    </form>
</body>
</html>

And here is the code I put in the code-behind:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
using Telerik.Web.UI;
 
namespace HtmlChartProblem
{
    public partial class Default : System.Web.UI.Page
    {
        protected void Page_Load(object sender, EventArgs e)
        {
            PlotProctorGraph();
        }
 
        private void solveTridiag(decimal[] sub, decimal[] diag, decimal[] sup, ref decimal[] b, int n)
        {
            /*                  solve linear system with tridiagonal n by n matrix a
                                using Gaussian elimination *without* pivoting
                                where   a(i,i-1) = sub[i]  for 2<=i<=n
                                        a(i,i)   = diag[i] for 1<=i<=n
                                        a(i,i+1) = sup[i]  for 1<=i<=n-1
                                (the values sub[1], sup[n] are ignored)
                                right hand side vector b[1:n] is overwritten with solution
                                NOTE: 1...n is used in all arrays, 0 is unused */
            int i;
            /*                  factorization and forward substitution */
            for (i = 2; i <= n; i++)
            {
                sub[i] = sub[i] / diag[i - 1];
                diag[i] = diag[i] - sub[i] * sup[i - 1];
                b[i] = b[i] - sub[i] * b[i - 1];
            }
            b[n] = b[n] / diag[n];
            for (i = n - 1; i >= 1; i--)
            {
                b[i] = (b[i] - sup[i] * b[i + 1]) / diag[i];
            }
        }
 
        private void PlotProctorGraph()
        {
            ScatterLineSeries series = new ScatterLineSeries();
            ScatterSeries scatterSeries = new ScatterSeries();
 
            scatterSeries.LabelsAppearance.DataFormatString = "{0}";
            scatterSeries.LabelsAppearance.Visible = false;
            scatterSeries.TooltipsAppearance.DataFormatString = "{0}, {1}";
            scatterSeries.TooltipsAppearance.BackgroundColor = System.Drawing.Color.White;
            scatterSeries.Appearance.FillStyle.BackgroundColor = System.Drawing.Color.Red;
 
            ScatterSeriesItem item;
 
            //Simulate reading data from the database and performing calculations to determine
            //point coordinates for plot. They are hard-coded here for simplicity so I don't have
            //to provide the database along with this sample
 
            // Plot 1
            item = new ScatterSeriesItem(16M, 100.9M, System.Drawing.Color.Red);
            scatterSeries.SeriesItems.Add(item);
 
            // Plot 2
            item = new ScatterSeriesItem(17.6M, 102.7M, System.Drawing.Color.Red);
            scatterSeries.SeriesItems.Add(item);
 
            // Plot 3
            item = new ScatterSeriesItem(19.8M, 100.6M, System.Drawing.Color.Red);
            scatterSeries.SeriesItems.Add(item);
 
            // Plot 4
            item = new ScatterSeriesItem(21.9M, 95M, System.Drawing.Color.Red);
            scatterSeries.SeriesItems.Add(item);
 
            chartProctor.PlotArea.Series.Add(scatterSeries);
 
            int numberOfPoints = scatterSeries.SeriesItems.Count;
 
            if (numberOfPoints > 1)
            {
                int precision = 10;
                decimal[] xcoords = new decimal[numberOfPoints], ycoords = new decimal[numberOfPoints];
 
                for (int i = 0; i < numberOfPoints; i++)
                {
                    xcoords[i] = (decimal) scatterSeries.SeriesItems[i].X;
                    ycoords[i] = (decimal) scatterSeries.SeriesItems[i].Y;
                }
 
                series = new ScatterLineSeries();
 
                series.LabelsAppearance.DataFormatString = "{0}";
                series.LabelsAppearance.Visible = false;
                series.TooltipsAppearance.DataFormatString = "{0:N1}, {1:N1}";
                series.TooltipsAppearance.BackgroundColor = System.Drawing.Color.White;
                series.Appearance.FillStyle.BackgroundColor = System.Drawing.Color.Gray;
                series.LineAppearance.LineStyle = Telerik.Web.UI.HtmlChart.Enums.LineStyle.Smooth;
                series.MarkersAppearance.Visible = false;
 
                decimal[] a = new decimal[numberOfPoints];
                decimal x1, x2, x, y;
                decimal[] h = new decimal[numberOfPoints];
                for (int i = 1; i <= numberOfPoints - 1; i++)
                {
                    h[i] = xcoords[i] - xcoords[i - 1];
                }
                if (numberOfPoints > 2)
                {
                    decimal[] sub = new decimal[numberOfPoints - 1];
                    decimal[] diag = new decimal[numberOfPoints - 1];
                    decimal[] sup = new decimal[numberOfPoints - 1];
 
                    for (int i = 1; i <= numberOfPoints - 2; i++)
                    {
                        diag[i] = (h[i] + h[i + 1]) / 3;
                        sup[i] = h[i + 1] / 6;
                        sub[i] = h[i] / 6;
                        a[i] = (ycoords[i + 1] - ycoords[i]) / h[i + 1] - (ycoords[i] - ycoords[i - 1]) / h[i];
                    }
                    solveTridiag(sub, diag, sup, ref a, numberOfPoints - 2);
                }
                // note that a[0]=a[np-1]=0
                // draw
 
                for (int i = 1; i <= numberOfPoints - 1; i++)
                {   // loop over intervals between nodes
                    for (int j = 1; j <= precision; j++)
                    {
                        x1 = (h[i] * j) / precision;
                        x2 = h[i] - x1;
                        y = ((-a[i - 1] / 6 * (x2 + h[i]) * x1 + ycoords[i - 1]) * x2 +
                            (-a[i] / 6 * (x1 + h[i]) * x2 + ycoords[i]) * x1) / h[i];
                        x = xcoords[i - 1] + x1;
 
                        item = new ScatterSeriesItem(x, y, System.Drawing.Color.Red);
                        series.SeriesItems.Add(item);
                    }
                }
 
                chartProctor.PlotArea.Series.Add(series);
            }
 
            series = new ScatterLineSeries();
 
            series.LabelsAppearance.DataFormatString = "{0}";
            series.LabelsAppearance.Visible = false;
            series.TooltipsAppearance.DataFormatString = "{0:N1}, {1:N1}";
            series.TooltipsAppearance.BackgroundColor = System.Drawing.Color.White;
            series.Appearance.FillStyle.BackgroundColor = System.Drawing.Color.Gray;
            series.LineAppearance.LineStyle = Telerik.Web.UI.HtmlChart.Enums.LineStyle.Smooth;
            series.MarkersAppearance.Visible = false;
 
            //Normally the arrays would contain data from the database, but as the values are hard-coded
            //for simplicity, I hard-code the array values here
 
            chartProctor.PlotArea.XAxis.MinValue = Convert.ToDecimal(GetMinNumber(new string[] { "16", "17.6", "19.8", "21.9" }) - .5);
            chartProctor.PlotArea.YAxis.MinValue = Convert.ToDecimal(GetMinNumber(new string[] { "100.9", "102.7", "100.6", "95" }) - .5);
 
            chartProctor.PlotArea.XAxis.MaxValue = Convert.ToDecimal(GetMaxNumber(new string[] { "16", "17.6", "19.8", "21.9" }) + 1.5);
            chartProctor.PlotArea.YAxis.MaxValue = Convert.ToDecimal(GetMaxNumber(new string[] { "100.9", "102.7", "100.6", "95" }) + 1.5);
        }
 
        protected double GetMaxNumber(string[] arrNumbers)
        {
            double MaxNumber = 0;
            foreach (string strNumber in arrNumbers)
            {
                if (strNumber.Length > 0)
                {
                    if (Convert.ToDouble(strNumber) > MaxNumber)
                    {
                        MaxNumber = Convert.ToDouble(strNumber);
                    }
                }
            }
            return MaxNumber;
        }
 
        protected double GetMinNumber(string[] arrNumbers)
        {
            double MinNumber = 1000000000;
            foreach (string strNumber in arrNumbers)
            {
                if (strNumber.Length > 0)
                {
                    if (Convert.ToDouble(strNumber) < MinNumber)
                    {
                        MinNumber = Convert.ToDouble(strNumber);
                    }
                }
            }
            return MinNumber;
        }
    }
}

This produces the graph in the image file attached.

0
Ianko
Telerik team
answered on 27 Apr 2016, 10:07 AM
Hi Travis,

The encountered result is due to the used formatting. The used one ({0:D}) rounds the value. Thus, 102.5 will become 103. This is applied only to the labels, thus, plot area is accurately rendered. It is the X and Y labels that mislead that points are not rendered at the proper position. 

I suggest you using proper formatting that does not round values. You can see this article on the matter—http://docs.telerik.com/kendo-ui/framework/globalization/numberformatting. On my end using this formatting works properly: DataFormatString="{0:n1}".

Regards,
Ianko
Telerik
Do you need help with upgrading your ASP.NET AJAX, WPF or WinForms projects? Check the Telerik API Analyzer and share your thoughts.
Tags
Chart (HTML5)
Asked by
Travis
Top achievements
Rank 1
Iron
Answers by
Travis
Top achievements
Rank 1
Iron
Ianko
Telerik team
Share this question
or