Spline value interpolation

Hello! I use your WPF example "VisualDataEditing" (removed all unnecessary from it and changed LineSeries to SplineSeries) to build a characteristic by measured values in several points. For example I set valeus in 10,20,30,40,50,60,70,80. But I also need to know exact values of resulting spline in intermediate points too, for example in 5,15,25,35,45,55,65,75. How can I get these intermediate values, that were interpolated by your spline ? Is it possoble with Syncfusion?


Attachment: Data_Editing_800210f9.zip

12 Replies

MK Muneesh Kumar G Syncfusion Team June 28, 2018 11:28 AM UTC

Hi Ivan, 
 
Thanks for using Syncfusion products.  
 
We can achieve your requirement by getting segments Q1 and Q2 points (Intermediate points) in event and convert that pixel points to data points as per the below code snippet.  
 
Code snippet.  
private void XySegmentDraggingBase_OnDragStart(object sender, ChartDragStartEventArgs e) 
        { 
            //Only dots are moveable 
             
            e.Cancel = !(string.Equals(e.BaseXValue.ToString(), "0")  
                || string.Equals(e.BaseXValue.ToString(), "10")  
                || string.Equals(e.BaseXValue.ToString(), "20")  
                || string.Equals(e.BaseXValue.ToString(), "30") 
                || string.Equals(e.BaseXValue.ToString(), "40")  
                || string.Equals(e.BaseXValue.ToString(), "50")  
                || string.Equals(e.BaseXValue.ToString(), "60")  
                || string.Equals(e.BaseXValue.ToString(), "70") 
                || string.Equals(e.BaseXValue.ToString(), "80") 
                || string.Equals(e.BaseXValue.ToString(), "90") 
                || string.Equals(e.BaseXValue.ToString(), "100") 
                       ); 
 
            foreach (SplineSegment segment in splineSeries.SeriesSegments) 
            { 
                var intermediatePoint1 = chart.PointToValue(chart.PrimaryAxis, segment.Q1); 
                var intermediatePoint2 = chart.PointToValue(chart.PrimaryAxis, segment.Q2); 
            } 
 
        } 
 
Also, you have used CategoryAxis and string data in application. We would like to inform you that CategoryAxis is an indexed based axis that plots values based on the index of the data point collection. So, if we get intermediate points means it also an index decimal point. So, we have changed the application data and axis type to numerical as per the below code snippet.  
 
Codes nippet [XAML]: 
  <charts:SfChart.PrimaryAxis> 
                <charts:NumericalAxis RangePadding="Additional" 
                                     Header="Growth(In Years)"  
                                     AxisLineStyle="{StaticResource axisStyle1}" 
                                     MajorTickLineStyle="{StaticResource axisStyle}"/> 
            </charts:SfChart.PrimaryAxis> 
 
Code snippet [C#]: 
private ObservableCollection<SalesAnalysisModel> GetRandomData() 
        { 
            ObservableCollection<SalesAnalysisModel> datas = new ObservableCollection<SalesAnalysisModel>(); 
 
             
            datas.Add(new SalesAnalysisModel(0, 824)); 
            datas.Add(new SalesAnalysisModel(10, 1057)); 
            datas.Add(new SalesAnalysisModel(20, 1319)); 
            datas.Add(new SalesAnalysisModel(30, 1764)); 
            datas.Add(new SalesAnalysisModel(40, 2544)); 
            datas.Add(new SalesAnalysisModel(50, 3813)); 
            datas.Add(new SalesAnalysisModel(60, 5725)); 
            datas.Add(new SalesAnalysisModel(70, 8432)); 
            datas.Add(new SalesAnalysisModel(80, 12088)); 
             
            return datas; 
        } 
 
We have modified our sample based on this, please find the sample from the following location.  
 
 
Please let us know if you have any queries.  
 
Thanks, 
Muneesh Kumar G. 



?? ???? June 29, 2018 05:53 AM UTC

Hi Muneesh,
Thanks a lot for your answer, modifying sample and your explain!
But, nevertheless, how can I get values of spline in 5,15,25... from Q1,Q2 values on each segment?
For example on the first segment:
chart.PointToValue(chart.PrimaryAxis, segment.Q1).toString() is 3.33333333*
chart.PointToValue(chart.PrimaryAxis, segment.Q2).toString() is 6.66666666*
segment.Q1 is 99.707...*;486.119...
segment.Q2 is 124.634...*;482.988...

So... repeating my question, how to get Y-value of spline in X-value 5,15,25...?
Maybe there is some 
mathematical function of getting value from Q1,Q2 (and maybe P1,P2) values of segment?

*not changing when I moving points of segment

Thanks, 
Ivan



SR Samuel Rajadurai Edwin Rajamanickam Syncfusion Team July 2, 2018 11:15 AM UTC

Hi Ivan, 
  
We have analyzed your requirement of getting intermediate values and you can achieve this by using segment properties X1,X2,Y1 and Y2 values as per the below code snippet. 
  
Code Snippet 
  
    public partial class MainWindow 
         { 
          … 
        private void XySegmentDraggingBase_OnDragStart(object sender, ChartDragStartEventArgs e) 
        { 
            //Only dots are moveable 
            … 
            foreach (SplineSegment segment in splineSeries.SeriesSegments) 
            { 
                var intermediatePoint1 = chart.PointToValue(chart.PrimaryAxis, segment.Q1); 
                var intermediatePoint2 = chart.PointToValue(chart.PrimaryAxis, segment.Q2); 
 
                var middleXValue = segment.X1 + Math.Abs(segment.X2 - segment.X1) / 2; 
                var middleYValue = segment.Y1 + Math.Abs(segment.Y2 - segment.Y1) / 2;            } 
        } 
      } 

  
We have modified our sample based on this, please find the sample from the following location.   
  
  
Please let us know if you have any queries.  
  
Regards,
Samuel 



?? ???? July 3, 2018 10:38 AM UTC

Hi, Samuel!
Thanks a lot for your answer and modifying sample!
I have analyzed it. And its not working with nonlinear splines (only with lines.. whitch is certainly too easy task to bother you).
I have modified our sample to show it. Please tell me if its not possible for Syncfusion to get Y-value for any X-value of created spline.

Thanks, 
Ivan

Attachment: Sample_76ffb2d3.zip


SR Samuel Rajadurai Edwin Rajamanickam Syncfusion Team July 5, 2018 02:12 PM UTC

Hi Ivan, 

  
We have analyzed and achieved your requirement of getting the mid-points for spline curves. This can be achieved using the Bezier Curve points formula. 
  
Code Snippet 
  
 
    public partial class MainWindow 
       { 
        private void XySegmentDraggingBase_OnDragStart(object sender, ChartDragStartEventArgs e) 
        { 
             
             
            foreach (SplineSegment segment in splineSeries.SeriesSegments) 
            { 
 
                var q1X = chart.PointToValue(chart.PrimaryAxis, segment.Q1); 
                var q2X = chart.PointToValue(chart.PrimaryAxis, segment.Q2); 
 
                var q1Y = chart.PointToValue (chart.SecondaryAxis, segment.Q1); 
                var q2Y = chart.PointToValue(chart.SecondaryAxis, segment.Q2); 
 
                var point = GetMiddleBezierPoint(new Point(q1X,q1Y), new Point(q2X,q2Y), new ChartPoint(segment.X1, segment.Y1), 
                    new ChartPoint(segment.X2, segment.Y2)); 
 
                TextBox_1.AppendText("X-value: " + point.X.ToString() + ",  " + "Y-value: " + point.Y.ToString() + Environment.NewLine); 
            } 
        } 
 
        private ChartPoint GetMiddleBezierPoint(Point q1, Point q2, ChartPoint point1, ChartPoint point2) 
        { 
            const double One_half = 1 / 2.0d; 
 
            double x1 = point1.X + Math.Abs(point2.X - point1.X) / 2; 
            double y1 = (1 - One_half) * (1 - One_half) * (1 - One_half) * point1.Y + 3 * (1 - One_half) * (1 - One_half) * One_half * q1.Y + 3 * (1 - One_half) * One_half * One_half * q2.Y + (One_half * One_half * One_half) * point2.Y; 
 
            var controlPoint1 = new ChartPoint(x1, y1); 
            return controlPoint1; 
        } 
    } 
 
  
We have also modified the sample according to your requirement. 
  
  
Regards,
Samuel 



?? ???? July 9, 2018 05:22 AM UTC

Thank you, Samuel!
That is exactly what I was talking about. Nothing impossible for Syncfusion =)


MK Muneesh Kumar G Syncfusion Team July 10, 2018 04:09 AM UTC

Hi Ivan,

Thanks for the update.

We are glad to know that the given solution works. Please let us know if you need any further assistance.

Thanks,
Muneesh Kumar G.


?? ???? replied to Samuel Rajadurai Edwin Rajamanickam August 1, 2018 04:49 AM UTC

Hi Ivan, 
  
We have analyzed your requirement of getting intermediate values and you can achieve this by using segment properties X1,X2,Y1 and Y2 values as per the below code snippet. 
  
Code Snippet 
  
    public partial class MainWindow 
         { 
          … 
        private void XySegmentDraggingBase_OnDragStart(object sender, ChartDragStartEventArgs e) 
        { 
            //Only dots are moveable 
            … 
            foreach (SplineSegment segment in splineSeries.SeriesSegments) 
            { 
                var intermediatePoint1 = chart.PointToValue(chart.PrimaryAxis, segment.Q1); 
                var intermediatePoint2 = chart.PointToValue(chart.PrimaryAxis, segment.Q2); 
 
                var middleXValue = segment.X1 + Math.Abs(segment.X2 - segment.X1) / 2; 
                var middleYValue = segment.Y1 + Math.Abs(segment.Y2 - segment.Y1) / 2;            } 
        } 
      } 

  
We have modified our sample based on this, please find the sample from the following location.   
  
  
Please let us know if you have any queries.  
  
Regards,
Samuel 


Hello!
Can you please help me, why its not working when I am getting back to Line series?
I have attached the modified sample.

Thanks, 
Ivan


Attachment: Sample_Modified_99bf06a6.zip


MK Muneesh Kumar G Syncfusion Team August 1, 2018 09:02 AM UTC

Hi Ivan, 

We have analyzed your query and we would like to inform you that spline and line series rendering values are different. So, you can get midpoint of line segment by using X1Value, X2Value, Y1Value and Y2Value values instead of X1, X2, Y1 and Y2 as per the below code snippet.
 
 
Code Snippet [C#] 
 
                     
        private void XySegmentDraggingBase_OnDragStart(object sender, ChartDragStartEventArgs e) 
        { 
            … 
             
            foreach (Syncfusion.UI.Xaml.Charts.LineSegment segment in lineSeries.SeriesSegments) 
            { 
                var middleXValue = segment.X1Value + Math.Abs(segment.X2Value - segment.X1Value) / 2; 
                var middleYValue = segment.Y1Value + Math.Abs(segment.Y2Value - segment.Y1Value) / 2; 
            } 
        } 
 
 
Regards,
Muneesh Kumar G.
 
 



?? ???? August 1, 2018 09:26 AM UTC

Thanks a lot for this fast reply!


?? ???? August 3, 2018 11:21 AM UTC

 Sorry for off topic question, but is there any opportunity to work with data points from code (from MainWindow class) keeping visual drag&drop interaction of course. I need to change existing and add new data points. Adding new instance of SalesAnalysisViewModel class to MainWindow class and adding new points to it has no result.


MK Muneesh Kumar G Syncfusion Team August 6, 2018 11:31 AM UTC

Hi Ivan, 
 
We have analyzed your requirement and you can achieve this by manipulating the ItemsSource property in series and do the required action as per the below code snippet.  
 
Code Snippet 
 
Add:  
 
 
        private void AddDataButton_Click(object sender, RoutedEventArgs e) 
        { 
            var model = new Model() { XValue = counter * 10, YValue = random.Next(100, 150) }; 
            var dataSource = (this.LineSeries1.ItemsSource as ObservableCollection<Model>); 
 
            dataSource.Add(model); 
 
            counter++; 
        } 
                     
 
 
Replace:  
 
 
        private void ChangeDataButton_Click(object sender, RoutedEventArgs e) 
        { 
            var model = new Model() { XValue = 10, YValue = random.Next(100, 150) }; 
            var dataSource = (this.LineSeries1.ItemsSource as ObservableCollection<Model>); 
 
            dataSource[0] = model; 
        }                     
 
 
Update :  
 
To update a certain value in the model. Implement property change for the model and enable the ListenPropertyChange property of the series and then replace the value at the required index. 
 
XAML 
 
 
        <chart:SfChart Margin="20"> 
        … 
 
            <chart:LineSeries XBindingPath="XValue"  
                              YBindingPath="YValue"  
                              ItemsSource="{Binding Data}" 
                              x:Name="LineSeries1" 
                              ListenPropertyChange="True"/> 
 
 
        </chart:SfChart> 
 
 
C# 
 
 
    public class Model : INotifyPropertyChanged 
    { 
        public event PropertyChangedEventHandler PropertyChanged; 
 
        private double yValue { get; set; } 
 
        … 
 
        public double YValue 
        { 
            get 
            { 
                return yValue;  
            } 
 
            set 
            { 
                yValue = value; 
                OnPropertyChanged("YValue"); 
            } 
        } 
 
        private void OnPropertyChanged(string propertyName) 
        { 
            PropertyChangedEventHandler handler = PropertyChanged; 
            if(handler != null) 
            { 
                handler(this, new PropertyChangedEventArgs(propertyName)); 
            } 
        } 
    } 
 
 
 
        private void ChangeValueButton_Click(object sender, RoutedEventArgs e) 
        { 
            var dataSource = (this.LineSeries1.ItemsSource as ObservableCollection<Model>); 
            dataSource[2].YValue = random.Next(100,150); 
        } 
 
 
We have prepared a sample based on this. Please find it from the link below. 
 
 
Hope this helps.  
 
Regards,
Muneesh Kumar G. 
 


Loader.
Up arrow icon