Draknek
Level 6
"Alan Hazelden" for short
|
|
« on: June 20, 2010, 04:18:17 AM » |
|
As the title says, I want to render a line with a given thickness, without anti-aliasing. Some variant of Bresenham's seems like it should do the trick, but I have yet to find/think of one that seems particularly efficient (although efficiency isn't massively important for this application). The only reference I've found so far is this StackOverflow question. Has anyone done this/got any other references? This is for AS3, so the first attempt I went with was to use the vector graphics line-drawing API. Unfortunately that has anti-aliasing, so isn't what I want. I read that you can disable anti-aliasing by setting stage.quality to low, but that just seems to give generally poor results (and is application-wide). Is there any other simple solution for AS3?
|
|
|
Logged
|
|
|
|
BorisTheBrave
|
|
« Reply #1 on: June 20, 2010, 04:42:24 AM » |
|
You could recompute bitmaps for many angles, and paste them together. Or you could draw aliased lines, and then use threshold to convert back to pure black and white.
|
|
|
Logged
|
|
|
|
raigan
|
|
« Reply #2 on: June 20, 2010, 04:45:01 AM » |
|
that just seems to give generally poor results
Could you describe "poor"? With quality=LOW, the results should be correct: an aliased thick line. If it looks like crap, that's because of the aliasing!
|
|
|
Logged
|
|
|
|
|
increpare
Guest
|
|
« Reply #4 on: June 20, 2010, 05:31:15 AM » |
|
neat! (also, I wouldn't personally worry too much about these sorts of fidelity issues in a program like this).
|
|
|
Logged
|
|
|
|
BorisTheBrave
|
|
« Reply #5 on: June 20, 2010, 06:39:51 AM » |
|
Yeah, I cannot see a big difference both look ok. The flashing circle looks off center, but that is probably because you are a half-pixel out or something.
|
|
|
Logged
|
|
|
|
st33d
Guest
|
|
« Reply #6 on: June 20, 2010, 09:16:23 AM » |
|
I posted a class that basically does Bresenham in AS3 here: http://forums.tigsource.com/index.php?topic=10505.0But of course it doesn't do thick lines. The drawing API isn't accurate regardless of the stage quality (it wasn't accurate on diagonals when I tested it). You have to be comfortable with losing a pixel either way because it tries to draw the stroke inbetween pixel locations. Consider this when choosing your stroke width.
|
|
|
Logged
|
|
|
|
nikki
|
|
« Reply #7 on: June 20, 2010, 10:26:55 AM » |
|
when you implement a simple bresenham algorithm , how does that compute anti-alias by itself ? It ought to be aliased until you implement the anti yourself...
or am i missing something here?
|
|
|
Logged
|
|
|
|
kiwi
|
|
« Reply #8 on: June 20, 2010, 10:34:56 AM » |
|
when you implement a simple bresenham algorithm , how does that compute anti-alias by itself ? It ought to be aliased until you implement the anti yourself...
or am i missing something here?
Someone correct me if I'm wrong, but after reading the wikipedia article, I think that Bresenhams' algorithm is just a rasterization algorithm, it's not supposed to anti-alias
|
|
|
Logged
|
|
|
|
Draknek
Level 6
"Alan Hazelden" for short
|
|
« Reply #9 on: June 20, 2010, 12:02:23 PM » |
|
(also, I wouldn't personally worry too much about these sorts of fidelity issues in a program like this).
Yeah, I would just stick with anti-aliasing if I didn't want to add a flood fill tool next. The main thing wrong with the quality=low option is that some lines with small brush sizes go shaky and look ugly. But probably you're right that it's not amazingly important. when you implement a simple bresenham algorithm , how does that compute anti-alias by itself ? It ought to be aliased until you implement the anti yourself...
or am i missing something here?
The problem is that I can't just use Bresenham's algorithm because that gives one-pixel wide lines and I need my lines to have thickness.
|
|
|
Logged
|
|
|
|
agj
|
|
« Reply #10 on: June 20, 2010, 12:49:42 PM » |
|
Haha, I'm loving this idea.
|
|
|
Logged
|
|
|
|
nikki
|
|
« Reply #11 on: June 20, 2010, 01:18:46 PM » |
|
The problem is that I can't just use Bresenham's algorithm because that gives one-pixel wide lines and I need my lines to have thickness. ahh yes, the thickness. i had a similar thing a while ago, i just plotted bresenham lines, and made an extra line or two around it to thicken it, the problem then is that the thickness appears different when the line is at different angles because you sometimes plot the lines over each other, the trick then is to make the startingpoint of the second (or more) line rotate , depending on the angle the first line is in. am i clear ? btw, how thick are we talking about?, and how long? by average max and min ?? oh and btw, this thing i made wasn't in as3 so it might not even be possible, but then again i'm sure you can plot pixels ? right
|
|
|
Logged
|
|
|
|
Glaiel-Gamer
Guest
|
|
« Reply #12 on: June 20, 2010, 03:15:32 PM » |
|
first plot a line perpendicular to the line you want, at the desired thickness, store the result as an array of offsets
like perps:
[(-2, -1), (-1, -1), (0, 0), (1, 1), (2, 1)]
now when you plot the bresenham line, every time you set a pixel, set all the offsets too
i.e. if you're gonna plot (34, 121), with the same offsets as above, you'd plot
(34, 121) + (-2, -1) (34, 121) + (-1, -1) (34, 121) + (0, 0) (34, 121) + (1, 1) (34, 121) + (2, 1)
|
|
|
Logged
|
|
|
|
Glaiel-Gamer
Guest
|
|
« Reply #13 on: June 20, 2010, 03:17:22 PM » |
|
although, I might add, your problem has to do with joins and not the lines themselves, and rolling your own would give exactly the same problem, probably worse, than flash in low quality
|
|
|
Logged
|
|
|
|
LemonScented
|
|
« Reply #14 on: June 20, 2010, 05:04:26 PM » |
|
I'm probably missing the point completely, but for lines with thickness, isn't it more useful to just think of them as rectangles? So it'd go something like:
1 - Define the line you want with the two endpoints, X and Y. Work out the length, L from the distance between them, and the angle A from one to the other.
2 - Work out an angle that's perpendicular to A. Draw lines at that perpendicular angle (using whichever line drawing algorithm you happen to like) such that the centre points of those lines run through X and Y, respectively.
3 - Connect the endpoints of the lines you drew in step 2, so you have a rectangle.
4 - Flood fill the rectangle (you're about to implement that anyway, yes?)
Is that at all helpful, or have I completely misunderstood you?
|
|
|
Logged
|
|
|
|
|
Draknek
Level 6
"Alan Hazelden" for short
|
|
« Reply #16 on: June 21, 2010, 02:26:21 AM » |
|
although, I might add, your problem has to do with joins and not the lines themselves, and rolling your own would give exactly the same problem, probably worse, than flash in low quality
I thought that at first, but the start/endpoints of the lines I'm telling Flash to draw are the same so there really shouldn't be any visible joins. With the 1-pixel brush I've confirmed that Flash's drawing in low quality mode is worse than Bresenham's algorithm. I'm probably missing the point completely, but for lines with thickness, isn't it more useful to just think of them as rectangles?
You're right that I could use flood fill to do that but only if the line is wide enough so that the middle section is connected. Something like this would cause problems:
for flood fill, flash has that built in
Yeah, that's really the only reason I decided to add that feature, because I knew I could get it for free.
|
|
|
Logged
|
|
|
|
muku
|
|
« Reply #17 on: June 21, 2010, 03:08:26 AM » |
|
Is there anything in particular wrong with this algorithm which was already linked from Stack Overflow? It seems to do exactly what you want. I found that one too when I was searching for this kind of stuff a while back.
|
|
|
Logged
|
|
|
|
Pishtaco
|
|
« Reply #18 on: June 21, 2010, 04:24:04 AM » |
|
Could you draw the anti-aliased line on a temporary bitmap, and then use the "threshold" function to clean up the edges?
|
|
|
Logged
|
|
|
|
Draknek
Level 6
"Alan Hazelden" for short
|
|
« Reply #19 on: June 21, 2010, 08:46:26 AM » |
|
In the end I went with rendering a circle at every step of Bresenham's algorithm. Seemed like the fastest solution to implement, and I decided that I didn't really care about efficiency after all. Hoping to release this properly in a few hours. Is there anything in particular wrong with this algorithm which was already linked from Stack Overflow? It seems to do exactly what you want. I found that one too when I was searching for this kind of stuff a while back. It was partially because I didn't want to read through 9 pages of low-quality scans and partially because I wasn't convinced that you need two nested loops to do it. Glaiel Gamer's suggestion of pre-caching the perpendicular offsets seems a sensible modification to get rid of one of them though (although obviously you can't do that with changing thickness which the linked algorithm can handle). Could you draw the anti-aliased line on a temporary bitmap, and then use the "threshold" function to clean up the edges?
Probably. I'd be a bit wary of using that on a 1-pixel thick line, but anything much larger than that should be fine and 1-pixel thick lines could be special-cased to use Bresenham's algorithm.
|
|
|
Logged
|
|
|
|
|