Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Drawing varying line widths with NSBezierPath?

I would like to create a vector object that can be drawn with a pen tablet and will honor the pressure information from the pen (by increasing/decreasing line width appropriately). Now I know how to get the pressure info out of the NSEvent, but of course NSBezierPath doesn't support varying line widths.

So I'm trying to generate a Bezier path that is the outline of my line, by calculating the perpendicular lines at the ends of the curve and connecting those with the very same curve. It nearly works in my little test project for a single curve segment:

https://github.com/uliwitness/WideningBezierPathTest

but this has one big issue: The line thins to barely 2 pixels in the middle (it should only go from 32 to 8). Does anyone know how I'd adjust the control points so the two edges of the line in the curved part are at roughly the same distance ?

enter image description here

Anyone have ideas? Suggestions? Useful articles?

like image 483
uliwitness Avatar asked Mar 08 '14 14:03

uliwitness


1 Answers

Thanks to suggestions from others I've managed to cobble something together that works. I've committed the changes to the repository, but you can go back a few revisions if you want to see the older code. Here's what I do now:

  1. I flatten the path using bezierPathByFlatteningPath. This gives me straight line segments.
  2. I then calculate the start and end points of the perpendicular lines at the start and end of each line segment (these lines are as long as the line size should be at this point).
  3. I create a bezier path containing a parallelogram consisting of the two perpendicular lines plus lines connecting them. This gives a smooth transition in line widths for each segment.
  4. Once I have the segments, I draw the ending perpendicular lines of the path, plus the sides of each segment (but not the perpendicular lines between segments) into a new bezier path, which I can then fill to draw the stroke with the desired line width variations.

If you want to use this for printing or under HiDPI, you might have to muck with the "flatness" of the bezier path, but for 1x screen display it looks fine.

like image 193
uliwitness Avatar answered Oct 23 '22 08:10

uliwitness