SciChart® the market leader in Fast WPF Charts, WPF 3D Charts, and now iOS Charting & Android Chart Components

Welcome to the SciChart Community Forums!

Please use the forums below to ask questions about SciChart. Take a moment to read our Question asking guidelines on how to ask a good question and our support policy

We also have a tag=SciChart on Stackoverflow.com where you can earn rep for your questions!

Answered
0
0

Hi,

I’ve implemented a Custom Rollover Modifier (by basically robbing the example given here – http://support.scichart.com/index.php?/Knowledgebase/Article/View/17235/32/custom-chartmodifiers—part-1—creating-a-custom-rollover-modifier) and it works fine with sorted data.

Unfortunately, a particular chart DataSeries we use has an additional terminating point added to the end but that points X coordinate is out of sequence with the rest and causes the DataSeries to be identified as being unsorted. When I try to use it with search mode “Nearest” it throws an exception saying the search mode must be “Exact” for it to work.

Here
https://www.scichart.com/questions/question/fix-data-values-that-arrive-in-a-non-sorted-date-time-order
You seem to suggest that SciChart should now handle unsorted data – Does this mean it handles it for display purposes only or should it work for a FindIndex?

An interesting observation is that if I use a standard rollover modifier with the same DataSeries it works – I assume it’s doing something with the data or it’s using a different method of finding the nearest point – could you tell me what this is?

Another thing I tried was to remove the last point from the series but the IsSorted flag remains as false and the FindIndex then still fails. I’m not sure what else to try short of copying the points over individually to a new DataSeries but this is seriously innefficient given the circumstances.

Some advice would be greatly appreciated.

Cheer
/Stuart

  • You must to post comments
Best Answer
0
0

Hi Stuart,

Thanks for your question. Actually, all modifiers call methods from RenderableSeries for hit-test. There are several of these containing “HitTest” in their names which should handle all possible cases. Concerning RolloverModifier, it calls the VerticalSliceHitTest method.

As to the internal implementation of these methods, they don’t call FindIndex directly either. There are two methods exposed by IDataSeries named FindClosestPoint and FindClosestLine (used when UseInterpolation is “True” on a modifier). That’s where FindIndex is called, and an alternative algorithm is used if data isn’t sorted.

So you should use those method, which suits your purposes better.

Concerning the unsorted DataSeries in your application, is data really unsorted or it is recognized as unsorted? If the latter is true, may I ask you to create a simple project which reproduces this issue and send it to us for investigation?

Hope this helps,

Best regards,
Yuriy

  • Stuart McCullough
    Hi Yuriy, Yes the data really is unsorted – I’ll upload a solution to demonstrate the issue.In the mean time I’ve worked around the problem by extracting the series values and finding the index manually (I need this index for other purposes)./StuUploading the solution – It’s “forbidding” me from uploading just about anything from Chrome. I’m down to zipped up source files on their own and it still doesn’t like it. I’ll post an answer and get the info to you that way. oh! i’m using v3.42.0.6778 by the way
  • Yuriy
    Hi Stuart, thanks for the sample. FindIndex(..) isn’t intended to work with unsorted data, so it isn’t a bug. When we claimed that support of unsorted data had been added, we meant that it is possible to use unsorted data within any DataSeries type, and the visual output will be right (before that there was the special UnsortedDataSeries type).Please try using IDataSeries.FindClosestPoint(..) or RenderableSeries.HitTest(..) instead, these should cope well with unsorted data. Let us know if it helps!
  • Stuart McCullough
    Hi Yuriy, I thought that’s what you meant and I never really thought it was a bug, if anything I’d just assumed I was using it incorrectly (as indeed I was). Thanks for taking the time to look at it and the feedback :-)/Stu
  • Yuriy
    Hi Stuart, you are welcome! Please don’t hesitate to ask if there are any issues!
  • You must to post comments
0
0

My source files:-

The XAML

<Window
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:views="clr-namespace:Arc_Client.Views"
    xmlns:s="http://schemas.abtsoftware.co.uk/scichart" x:Class="UnsortedDataExample.MainWindow"
    Title="MainWindow" Height="350" Width="525">

<Grid>

    <s:SciChartSurface x:Name="ChartSurface" HorizontalAlignment="Stretch" VerticalAlignment="Stretch" s:ThemeManager.Theme="Chrome" Margin="0,32,0,0" Loaded="ChartSurface_Loaded">

        <s:SciChartSurface.XAxis>
            <s:NumericAxis AutoRange="Once" GrowBy="1,1"/>
        </s:SciChartSurface.XAxis>

        <s:SciChartSurface.YAxes>
            <s:NumericAxis x:Name="LinearAxis" Id="LinearAxis" AutoRange="Always" AxisAlignment="Left" AxisTitle="Linear" GrowBy="1,1"/>
        </s:SciChartSurface.YAxes>

        <s:SciChartSurface.ChartModifier>
            <s:ModifierGroup>
                <views:CustomChartRolloverModifier x:Name="CustomRollover" 
                                IsEnabled="True" >
                </views:CustomChartRolloverModifier>
            </s:ModifierGroup>
        </s:SciChartSurface.ChartModifier>

    </s:SciChartSurface>

</Grid>

The Code behind it

using Abt.Controls.SciChart.Model.DataSeries;

using Abt.Controls.SciChart.Visuals.PointMarkers;
using Abt.Controls.SciChart.Visuals.RenderableSeries;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;

namespace UnsortedDataExample
{
///

/// Interaction logic for MainWindow.xaml
///

public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
}

    private void ChartSurface_Loaded(object sender, RoutedEventArgs e)
    {
        XyDataSeries<long, double> dataSeries = new XyDataSeries<long, double>();
        dataSeries.AcceptsUnsortedData = true;

        dataSeries.Append(0, 20);
        dataSeries.Append(50, 25);
        dataSeries.Append(200, 30);
        dataSeries.Append(300, 35);
        dataSeries.Append(5, 40);

        XyScatterRenderableSeries testSeries = new XyScatterRenderableSeries();
        testSeries.DataSeries = dataSeries;
        testSeries.YAxisId = "LinearAxis";
        testSeries.PointMarker = new EllipsePointMarker()
        {
            Fill = Colors.Red,
            Stroke = Colors.White,
            StrokeThickness = 2,
            Width = 10,
            Height = 10,
        };
        this.ChartSurface.RenderableSeries.Add(testSeries);

    }



}

}

…..and finally the rollover class demonstrating the problem FindIndex()

using System;

using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Media;
using System.Windows.Shapes;
using Abt.Controls.SciChart.ChartModifiers;
using Abt.Controls.SciChart;
using Abt.Controls.SciChart.Common.Extensions;
using System.Globalization;
using System.Collections.Generic;

namespace Arc_Client.Views
{
///
public class CustomChartRolloverModifier : ChartModifierBase
{
public static readonly DependencyProperty LineBrushProperty = DependencyProperty.Register(“LineBrush”, typeof(Brush), typeof(CustomChartRolloverModifier), new PropertyMetadata(new SolidColorBrush(Colors.LimeGreen), OnLineBrushChanged));

    public static readonly DependencyProperty TextForegroundProperty = DependencyProperty.Register("TextForeground", typeof(Brush), typeof(CustomChartRolloverModifier), new PropertyMetadata(new SolidColorBrush(Colors.White)));

    public Brush TextForeground
    {
        get { return (Brush)GetValue(TextForegroundProperty); }
        set { SetValue(TextForegroundProperty, value); }
    }
    private Line _line;
    private Brush _LineColour = new SolidColorBrush(Colors.LightBlue);

    public CustomChartRolloverModifier()
    {
        CreateLine(this);
    }

    public Brush LineBrush
    {
        get { return (Brush)GetValue(LineBrushProperty); }
        set { SetValue(LineBrushProperty, value); }
    }

    public override void OnParentSurfaceRendered(SciChartRenderedMessage e)
    {
        base.OnParentSurfaceRendered(e);
    }

    public override void OnModifierMouseMove(ModifierMouseArgs e)
    {
        base.OnModifierMouseMove(e);

        // Get all renderable series - NOTE: Currently we are assuming there is only one so some code is hardwired to point to series[0]. This will bite us in the bottom at some point I'm sure
        var allSeries = this.ParentSurface.RenderableSeries;

        // Translates the mouse point to chart area, e.g. when you have left axis
        var pt = GetPointRelativeTo(e.MousePoint, this.ModifierSurface);

        // Declare variables for information we're going to need as we progress
        double foundPointsXposition = -1;

        // Convert this point to an Xposition and formatted text for the X Axis ToolTip - Need to do the conversion based on the Axis type
        if (allSeries[0].XAxis is Abt.Controls.SciChart.Visuals.Axes.NumericAxis)     // SCAN CHART
        {
            try
            {
                double xDataForCoordinate = (double)allSeries[0].XAxis.GetDataValue(pt.X);                                      // Get XAxis general position
                int indexOfNearestPoint = allSeries[0].DataSeries.FindIndex(xDataForCoordinate, SearchMode.Nearest);            // Find index of nearest point - DIES HERE !!!!!!!
            }
            catch
            {
                return;
            }
        }

        // Position the rollover vertical line and add it to the ModifierSurface, which is just a canvas over the main chart area, on top of series
        _line.Y1 = 0;
        _line.Y2 = ModifierSurface.ActualHeight;
        _line.X1 = foundPointsXposition;
        _line.X2 = foundPointsXposition;
        this.ModifierSurface.Clear();
        this.ModifierSurface.Children.Add(_line);

    }

    public override void OnMasterMouseLeave(ModifierMouseArgs e)
    {
        base.OnMasterMouseLeave(e);
        this.ModifierSurface.Clear();
    }

    private static void OnLineBrushChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
    {
        var modifier = d as CustomChartRolloverModifier;
        CreateLine(modifier);
    }

    private static void CreateLine(CustomChartRolloverModifier modifier)
    {
        modifier._line = new Line() {
            Stroke = modifier._LineColour, 
            StrokeThickness = 3, 
            IsHitTestVisible = false 
        };
    }

}

}

  • Stuart McCullough
    ….and something went wrong with the formatting there too – it’s just not my day really :-( Hopefully there’s enough in the above mess to let you reproduce the problem though.
  • You must to post comments
Showing 2 results
Your Answer

Please first to submit.