Spencer Ruport
Spencer Ruport

Reputation: 35117

Bezier Curves in WPF

I'm drawing some Bezier curves in WPF and for the most part it's working but I'm getting some faint separations between each segment. As you can see they even appear in straight sections so I don't believe the issue is due to an insufficient number of segments. (This image is at 4x magnification.)

Faint separations

I'm using a collection of System.Windows.Shapes.Line objects to paint them. They are instantiated in code like so:

Shapes.Line Line = new Shapes.Line();
Line.Stroke = Brush;
Line.HorizontalAlignment = Windows.HorizontalAlignment.Left;
Line.VerticalAlignment = Windows.VerticalAlignment.Center;
Line.StrokeThickness = 10;

My theory is that this separation is due to the fact that the point where one line ends is the same point where the next begins but I unsure what's the best way to fix this. I'm fairly new at this so I don't want to go hacking away before I ask if anyone has any tried and true solutions to make these faint separations disappear.

EDIT:

Here is the code I'm using to generate the segments. The ILine interface is something I created but it's point values are simply translated to the System.Windows.Shapes.Line respective values later on in the program.

public static void FormBezier(List<ILine> Lines, Point[] pt)
{
    if (Lines.Count == 0) return;

    double t, dt, x0, y0, x1, y1;

    t = 0.0;
    dt = 1.0 / Lines.Count;
    x1 = X(t, new double[] { pt[0].X, pt[1].X, pt[2].X, pt[3].X });
    y1 = X(t, new double[] { pt[0].Y, pt[1].Y, pt[2].Y, pt[3].Y });
    t += dt;

    for(int index = 1; index < Lines.Count - 1; index++)
    {
        x0 = x1;
        y0 = y1;
        x1 = X(t, new double[] { pt[0].X, pt[1].X, pt[2].X, pt[3].X });
        y1 = X(t, new double[] { pt[0].Y, pt[1].Y, pt[2].Y, pt[3].Y });

        Lines[index].Start.X = x0;
        Lines[index].End.X = x1;
        Lines[index].Start.Y = y0;
        Lines[index].End.Y = y1;
        t += dt;
    }

    t = 1.0;
    x0 = x1;
    y0 = y1;
    x1 = X(t, new double[] { pt[0].X, pt[1].X, pt[2].X, pt[3].X });
    y1 = X(t, new double[] { pt[0].Y, pt[1].Y, pt[2].Y, pt[3].Y });
    Lines[Lines.Count - 1].Start.X = x0;
    Lines[Lines.Count - 1].End.X = x1;
    Lines[Lines.Count - 1].Start.Y = y0;
    Lines[Lines.Count - 1].End.Y = y1;
}
public static double X(double t, double[] x)
{
    return 
        x[0] * Math.Pow((1 - t), 3) + 
        x[1] * 3 * t * Math.Pow((1 - t), 2) + 
        x[2] * 3 * Math.Pow(t, 2) * (1 - t) + 
        x[3] * Math.Pow(t,  3);

}

Upvotes: 0

Views: 841

Answers (2)

Matt Burland
Matt Burland

Reputation: 45155

At a wild guess, it's probably a rounding error. The units used in WPF aren't pixels, they are resolution independent units. When WPF actually draws something it has to convert those units to real pixels on whatever screen it's drawing to. If the conversion ends up being half way between real pixels, it'll shade those pixels to try and approximate half a pixel in each real pixel. Hence you sometimes get gray pixels around a supposedly black line (anti-aliasing).

The property SnapsToDevicePixels might help you.

Upvotes: 2

Maciej
Maciej

Reputation: 7971

Clearly a fault in drawing algorithm. I am not best at WPF but you may want to have a look at this blog post.

Upvotes: 1

Related Questions