Drawing aliased, pixel-perfect 1px splines (Catmull-Rom, specifically)
Asked Answered
I

1

8

A brief background: I'm working on a web-based drawing application and need to draw 1px thick splines that pass through their control points.

The issue I'm struggling with is that I need to draw each of the pixels between p1 and p2 as if I were using a 1px pencil tool. So, no anti-aliasing and one pixel at a time. This needs to be done manually without the use of any line/curve library code as my brush system depends upon having a pixel coordinate to apply the brush tip to the canvas.

Essentially, I need to combine the one pixel stepping from something like the Bresenham algorithm with the coordinates returned by the Catmull-Rom equation. I'm having trouble because the Catmull-Rom points are not uniformly distributed (so I can't just say there should be 100 pixels in the curve and run the equation 100 times). I tried using an estimated starting value of the maximum of the X and Y deltas and filling in the gaps with Bresenham, but due to rounding I still end up with some "dirty" sections (ie. the line is clearly moving up and to the right but I still get two pixels with the same Y component, resulting in a "fat" section of the line).

I'm positive this has been solved because nearly every graphics program that draws splines has to support the clean pixel curves that I'm after. After quite a bit of math research, though, I'm a bit confused and still without a solution. Any advice?

EDIT: Here's an example of a curve that I might have to render:

alt text

Which might have an expected result looking like this (note that this is an estimate):

alt text

Using the Catmull-Rom spline equation, we need four points to create a segment. P0 and P3 are used as tangents for incoming and outgoing direction from the P1->P2 segment. With a Catmull-Rom spline, the blue section is all that gets interpolated as t moves from 0 to 1. P0 and P3 can be duplicated to ensure that the green portion gets rendered, so that is not an issue for me.

For simplicity's sake, I need to render the pixels on the curve between P1 and P2, given that I have tangents in the form of P0 and P3. I don't necessarily need to use Catmull-Rom splines, but they seem to be the right tool for this job being that control points must be passed through. The non-uniform distribution of interpolation points is what's throwing me for a loop.

EDIT2: Here's an example of what I mean when I say my resulting curve is dirty:

alt text

The red arrows point out a few locations where there should not be a pixel. This is occurring because the X and Y components of the coordinate that get calculated do not change at the same rate. So, when each of the components gets rounded (so I have an exact pixel location) it can be the case that either X or Y doesn't get bumped up because the calculated coordinate is, say, (42.4999, 50.98). Swapping the round for a floor or ceil doesn't solve the problem, as it just changes where it occurs.

Immingle answered 27/12, 2010 at 20:5 Comment(4)
It would be great if you can add another drawing showing your expected result from P1 to P2.Insulting
@belisarius I didn't work out the math for which pixels would be filled in based on the Catmull-Rom equation, but the second image should give you an idea of what I'm trying to achieve.Immingle
I asked for it due to your comment: but I still get two pixels with the same Y componentInsulting
@belisarius Understood. I can see how that comment could be confusing. It's sort of hard to explain without seeing the issue that my current implementation has, so I've attached another image. The third image is enlarged to 400% from my application. The red arrows indicate pixels that should not exist (the fraction in the Y component was low enough to not get rounded up).Immingle
I
2

Here you have a paper describing method for the re-parametrization of splines in order to get equally spaced points along the curve length. I think this can solve your problem if you can adapt it to Catmull-Rom curves (shouldn't be too difficult, I guess)

Insulting answered 27/12, 2010 at 22:36 Comment(2)
Thanks for the link to the paper. I hadn't included "arc length" in my Googling. I just did a bit more searching and came up with far better results (see actionscript.org/forums/showthread.php3?t=213252). It seems as though the accepted solution to this hinges quite a bit on approximation and pre-calculation. This may pose a performance issue for me since this is being done in JavaScript. I might re-post my issue differently after I've mulled this over, but for the time being thanks for the help. You've certainly pointed me in the right direction.Immingle
@Immingle Glad to help! Hope you can optimize it for your scenario.Insulting

© 2022 - 2024 — McMap. All rights reserved.