Skip to content

SP5 Signal: fix horizontal line rendering issue#2935

Merged
swharden merged 12 commits intoScottPlot:mainfrom
StendProg:SignalDrawFix#2933
Oct 17, 2023
Merged

SP5 Signal: fix horizontal line rendering issue#2935
swharden merged 12 commits intoScottPlot:mainfrom
StendProg:SignalDrawFix#2933

Conversation

@StendProg
Copy link
Contributor

@StendProg StendProg commented Oct 10, 2023

Purpose:
Fix for #2933.

The problem was this line:

rp.Canvas.DrawLine(x, verticalBars[i].Bottom, x, verticalBars[i].Top, paint);

In the case of identical y's in the entire pixel column, we draw a line from (x,y) to the same (x, y). The graphics library probably tries to optimize this and draws absolutely nothing, thus we lose the line thickness.
In this PR the drawing of unconnected vertical lines is changed to drawing a connected path along all vertical columns, which eliminates the effect described in #2933.

In the process of working on PR it turned out that this bug is always present and was even useful for drawing areas outside the signal. In fact, the same single point lines are always drawn there that were not displayed. Switching to path drawing started to display those invisible lines as well.
As a result, it had to be significantly redesigned, in particular to filter out pixel columns that lie outside the signal.

@swharden
Copy link
Member

swharden commented Oct 16, 2023

Hi @StendProg, thanks for this fix!

I identified a rendering issue that caused downward sloping lines to appear too thick. I figured out it was because LineTo() was drawing extra pixels as it jumped from the top of one vertical bar to the bottom of the next. I think I fixed it in a reasonable way, but I always welcome your input!

I'll merge this in now and we can create a new PR to improve or refine this code if needed 👍

Before

image

After

image

@swharden swharden enabled auto-merge October 16, 2023 12:41
@swharden swharden disabled auto-merge October 16, 2023 12:45
@swharden swharden changed the title Signal draw fix#2933 SP5 Signal: fix horizontal line rendering issue Oct 16, 2023
@StendProg
Copy link
Contributor Author

Hi @swharden,

Yes, it does look better with your extra fix. But we can find a counterexample for it too. For example, when neighboring pixel columns do not overlap by Y, then they will be unconnected.

If we continue these improvements, we can do what SignalXY draws for a single column:

  1. Line (Column[i-1].Right, Column[i].Left)
  2. Line (Column[i].Top, Column[i].Bottom)
  3. Line (Column[i].Right, Column[i+1].Left)
    SignalConnectionExample

The blue color indicates the original signal.
Rectangles mark the pixel column.
Green color indicates the lines to be drawn.

@swharden
Copy link
Member

Thanks for the feedback @StendProg!

when neighboring pixel columns do not overlap by Y, then they will be unconnected

I'm having trouble demonstrating this with code... do you have a similar code example I can use to check that the issue is present and confirm when it has been fixed?

Here's my attempt so far:

[Test]
public void Test_Signal_VerticalGap()
{
    double[] data = Generate.Sin(10_000, oscillations: 100);
    for (int i = (int)(data.Length * .3); i < (int)(data.Length * .7); i++)
    {
        data[i] = data[i] + 10;
    }

    ScottPlot.Plot plt = new();
    var sig = plt.Add.Signal(data);
    sig.LineStyle.AntiAlias = false;
    plt.Grids.Clear();
    plt.SaveTestImage();
}

image

@swharden
Copy link
Member

In theory the artifact you describe with the green squares makes sense, but in practice it's pretty hard to demonstrate

using ScottPlot;
using ScottPlot.WinForms;

double[] data = Generate.Sin(10_000, oscillations: 100);
for (int i = (int)(data.Length * .3); i < (int)(data.Length * .7); i++)
    data[i] = data[i] + 10;

Plot plot = new();
plot.Add.Signal(data);

Form form = new()
{
    Width = 600,
    Height = 400,
    StartPosition = FormStartPosition.CenterScreen
};

FormsPlot formsPlot1 = new()
{
    Dock = DockStyle.Fill
};

formsPlot1.Reset(plot);
formsPlot1.Refresh();
form.Controls.Add(formsPlot1);
form.ShowDialog();

step

@swharden
Copy link
Member

swharden commented Oct 17, 2023

If we continue these improvements, we can do what SignalXY draws for a single column:

This is probably the best solution, and it would be nice to share code between Signal and SignalXY

I'll work on that in a new issue/PR #2949

@swharden swharden merged commit c61bb77 into ScottPlot:main Oct 17, 2023
@StendProg
Copy link
Contributor Author

I was able to get this on the latest version:
SignalExample

I think the code will need a lot of reworking, but you're right that it should be a separate task.

You failed to reproduce the effect I described earlier because the X ranges for the pixel columns overlap (which should not be the case) and the data points can be included in both columns.
The overlap is most likely due to rounding in these rows:

double xUnitsPerPixel = Axes.XAxis.Width / Axes.DataRect.Width;
return Enumerable.Range(0, (int)Axes.DataRect.Width)

When iterating, we rounded the width, but when calculating the density of points per pixel, we didn't:

@swharden swharden linked an issue Nov 22, 2023 that may be closed by this pull request
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

SP5: signal plots with repeating values

2 participants