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!

Please note: SciChart team will only answer questions from customers with active support subscriptions. Expired support questions will be ignored. If your support status shows incorrectly, contact us and we will be glad to help.

1
0

If I have two points on my chart (x1, y1) and (x2, y2), what is the recommended way to create a line that goes through these two points? I maintain the value of the slope and the previously mentioned coordinates.

Thanks!

  • You must to post comments
0
0

Thanks for your comments!

Line Segment can be achieved with the LineAnnotation type. Please see our WPF Chart Annotations Example for what annotation types are available within SciChart WPF. The LineAnnotation documentation is here.

For a line that extends into infinity, it is possible with a small customization. Try this:

/// <summary>
/// Defines a read-only or editable Line annotation, which draws a Ray to the edges of the chart viewport, depending on two X,Y coordinates
/// 
/// e.g. if X Y coordinates are placed inside the chart, then the line extends until it hits the edge or the chart viewport
/// </summary>
public class RayAnnotation : LineAnnotation
{
    private Line _line;
    private Line _ghostLine;

    /// <summary>
    /// Initializes a new instance of the <see cref="RayAnnotation" /> class.
    /// </summary>
    public RayAnnotation()
    {
        // Reuse LineAnnotation control template from SciChart
        DefaultStyleKey = typeof(Abt.Controls.SciChart.Visuals.Annotations.LineAnnotation);
    }

    /// <summary>
    /// When overridden in a derived class, is invoked whenever application code or internal processes call <see cref="M:System.Windows.FrameworkElement.ApplyTemplate" />.
    /// </summary>
    public override void OnApplyTemplate()
    {
        base.OnApplyTemplate();

        AnnotationRoot = GetAndAssertTemplateChild<Grid>("PART_LineAnnotationRoot");
        _line = GetAndAssertTemplateChild<Line>("PART_Line");
        _ghostLine = GetAndAssertTemplateChild<Line>("PART_GhostLine");
    }

    /// <summary>
    /// Override in derived classes to handle specific placement of the annotation at the given <see cref="AnnotationCoordinates" />
    /// </summary>
    /// <param name="coordinates">The normalised <see cref="AnnotationCoordinates" /></param>
    protected override void PlaceAnnotation(AnnotationCoordinates coordinates)
    {
        // Ray defined as having two handle points but extending to right hand side of edge of viewport
        _line.X1 = coordinates.X1Coord;
        _line.Y1 = coordinates.Y1Coord;
        _ghostLine.X1 = coordinates.X1Coord;
        _ghostLine.Y1 = coordinates.Y1Coord;

        // Calculate gradient of line
        double m = (coordinates.Y1Coord - coordinates.Y2Coord)/(coordinates.X1Coord - coordinates.X2Coord);

        if (double.IsNaN(m) || double.IsInfinity(m))
        {
            // Possible divide by zero above, just draw a single point for now
            _ghostLine.X2 = coordinates.X1Coord;
            _ghostLine.Y2 = coordinates.Y1Coord;
            _line.X2 = coordinates.X1Coord;
            _line.Y2 = coordinates.Y1Coord;
            return;
        }

        bool isRight = coordinates.X2Coord > coordinates.X1Coord;

        // Calulate projected X,Y point that touches the right/top edge, or left/bottom edge of the viewport
        double projectedX = isRight ? base.ParentSurface.ModifierSurface.ActualWidth : 0;
        double projectedY = coordinates.Y1Coord + m * (projectedX - coordinates.X1Coord);

        if (projectedY < 0)
        {
            bool isUp = coordinates.Y1Coord > coordinates.Y2Coord;

            // If the projected Y coord was above the top-edge, transpose the projection 
            // so that X is calulated and Y is set to zero (top edge)
            projectedY = isUp ? 0 : base.ParentSurface.ModifierSurface.ActualHeight;
            projectedX = coordinates.X1Coord - coordinates.Y1Coord/m;
        }

        Console.WriteLine("Projected X,Y = {0:0.00},{1:0.00}", projectedX, projectedY);

        // Set right-most edge of the line based on the calculated projection point
        _ghostLine.X2 = projectedX;
        _ghostLine.Y2 = projectedY;
        _line.X2 = projectedX;
        _line.Y2 = projectedY;
    }
}
  • Ryan Woods
    I figured it out. Thanks for your patience.
  • Ryan Woods
    I have a question regarding the projection:bool isRight = coordinates.X2Coord > coordinates.X1Coord;// Calulate projected X,Y point that touches the right/top edge, or left/bottom edge of the viewport double projectedX = isRight ? base.ParentSurface.ModifierSurface.ActualWidth : 0; double projectedY = coordinates.Y1Coord + m * (projectedX – coordinates.X1Coord);if (projectedY <0> coordinates.Y2Coord;// If the projected Y coord was above the top-edge, transpose the projection // so that X is calulated and Y is set to zero (top edge) projectedY = isUp ? 0 : base.ParentSurface.ModifierSurface.ActualHeight; projectedX = coordinates.X1Coord – coordinates.Y1Coord / m; }I am trying to figure out how to turn this into a full line, not a line segment like the lineannotation and not a ray.My first thought is to change projectedx and projectedy to projectedx2 and projected y2. Then created a projectedx1 and projectedy1.I feel like I want to do the reverse,double projectedx1 = !isRight ? base.ParentSurface.ModifierSurface.ActualWidth : 0; double projectedy1 = coordinates.Y1Coord – m * (projectedX1 – coordinates.X1Coord);The same for isUp. Then apply those values to GhostLine.X1/Y1 and Line.X1/Y1Is this the correct approach? I am having a few problems here or there when I try to implement this.
  • Andrew
    Hi Ryan, Probably best writing a new answer with properly formatted code, as the above comment reads as a block and is kind of hard to understand.
  • Ryan Woods
    I wish that would have formatted like how I typed it…
  • Ryan Woods
    I added an answer but I am not sure if you get that alert.
0
0
       bool isRight = coordinates.X2Coord > coordinates.X1Coord;

        double projectedX1 = !isRight ? base.ParentSurface.ModifierSurface.ActualWidth : 0;
        double projectedY1 = coordinates.Y1Coord - m * (projectedX1 - coordinates.X1Coord);

        // Calulate projected X,Y point that touches the right/top edge, or left/bottom edge of the viewport
        double projectedX2 = isRight ? base.ParentSurface.ModifierSurface.ActualWidth : 0;
        double projectedY2 = coordinates.Y1Coord + m * (projectedX2 - coordinates.X1Coord);

        bool isUp = coordinates.Y1Coord > coordinates.Y2Coord;

        if (projectedY2 < 0)
        {


            // If the projected Y coord was above the top-edge, transpose the projection 
            // so that X is calulated and Y is set to zero (top edge)
            projectedY2 = isUp ? 0 : base.ParentSurface.ModifierSurface.ActualHeight;
            projectedX2 = coordinates.X1Coord - coordinates.Y1Coord / m;
        }

        if (projectedY1 > 0 && m != 0)
        {
            projectedY1 = !isUp ? 0 : base.ParentSurface.ModifierSurface.ActualHeight;
            projectedX1 = coordinates.X1Coord - coordinates.Y1Coord / m;
        }

        //Console.WriteLine("Projected X,Y = {0:0.00},{1:0.00}", projectedX2, projectedY2);


        GhostLine.X1 = projectedX1;
        GhostLine.Y1 = projectedY1;
        Line.X1 = projectedX1;
        Line.Y1 = projectedY1;

        // Set right-most edge of the line based on the calculated projection point
        GhostLine.X2 = projectedX2;
        GhostLine.Y2 = projectedY2;
        Line.X2 = projectedX2;
        Line.Y2 = projectedY2;

I have changed a few things but something seems off. I just reversed some of the logic. I would like to make it a full line, off to infinity in both directions. I feel that it is very close, just not quite there yet!

  • Andrew
    Hi Ryan, I’m not sure. We kind of provided that RayAnnotation code ‘as-is’ and don’t currently have time to investigate extending it. All I can say is the principle works, if you can calculate the X1Y1 X2Y2 values of the Line from the coordinates passed in, do please feel free to submit an edit as it will benefit other customers. Kind regards, Andrew
  • You must to post comments
Showing 2 results
Your Answer

Please first to submit.