Question

i am stuck finding the correct mathematical formula to set the correct y position in a canvas based on the lowest and highest price (int32) in a list of prices.

I hope you can help me form a formula which will solve my problem.

I have a canvas control in which i want to draw lines to display the price trend. What i have is the list of prices to draw,

example: 10 20 30 40 50

the lowest and the highest price in the list and of course the canvas control.

the formular so far is:

double currentPriceLineY = canvas.Height - (canvas.Height * (history.Price / highestPrice));

with this code i set the y position of the line based on the highest price,

but now i have no clue how to combine this with the lowest price to be at the bottom of the canvas while the highest price is at the top of the canvas and the other prices between this both points with relation to the highest and the lowest price.

I am stuck since yesterday and decided to ask you guys for help and hope you can understand my problem.

Thanks in advance Avoider

Was it helpful?

Solution

First, calculate the difference between the lowest and highest value (I called it range in the code). Then for each value, subtract the minimum value from it and divide by the range. This will give you the percentage into the range for that value. Then draw your lines - keep in mind that 0 is at the top and canvas.Height is at the bottom. In the code, I inverted the percentage to fix that. I also added a TextBlock sitting on the line so you can see what value went with what line.

screenshot

Here is the implementation of it:

XAML:

<Window x:Class="WpfApplication3.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="MainWindow" Height="300" Width="300">
    <Window.Resources>
    </Window.Resources>
    <Grid>
        <Canvas Background="Beige" Name="canvas" Height="200" Width="200" />
    </Grid>
</Window>

Code:

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

        int highestPrice = 65;
        List<int> vals = new List<int>() { 10, 20, 30, 40, 50 };
        int min = vals.Min();
        int max = vals.Max();
        max = highestPrice > max ? highestPrice : max;
        double range = max - min;

        // Draw max in red
        Color c = new Color() { ScA = 1, ScR = 1, ScG = 0, ScB = 0 };
        // y = 0 is at the top of the canvas
        var line = new Line() { X1 = 0, Y1 = 0, X2 = canvas.Width, Y2 = 0, Stroke = new SolidColorBrush(c), StrokeThickness = 2.0 };
        canvas.Children.Add(line);
        // Add txt so we can visualize better
        var txt = new TextBlock() { Text = max.ToString() };
        Canvas.SetLeft(txt, canvas.Width / 2);
        Canvas.SetTop(txt, 0 - 9);
        canvas.Children.Add(txt);

        foreach (int val in vals)
        {
            double percent = 1.0 - ((val - min)/range); // 0 is at the top, so invert it by doing 1.0 - xxx
            double y = percent*canvas.Height;
            // Draw line in a shade of blue/green
            c = new Color() { ScA = 1, ScR = 0, ScG = 0.5f, ScB = (float)percent };
            line = new Line() { X1 = 0, Y1 = y, X2 = canvas.Width, Y2 = y, Stroke = new SolidColorBrush(c), StrokeThickness = 2.0 };
            canvas.Children.Add(line);

            // Add txt so we can visualize better
            txt = new TextBlock() { Text = val.ToString() };
            Canvas.SetLeft(txt, canvas.Width / 2);
            Canvas.SetTop(txt, y - 9);
            canvas.Children.Add(txt);
        }
    }
}
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top