Hi Rob,
yes, for sure, is one of the first I’ve looked :)
The tutorial is great for moving objects along bezier curve or organic path.
To perform this job the drawn curve can be not so smoothed.
In my case I need to create a curve by finger and to have a rendered curve without aliasing or pixels gap.
Searching on the net I have found a lot of solutions about smoothing curves and using splines.
Many of this suggest to use Catmull-rom algorithm for drawing smooth lines
But for drawing I don’t believe that to be best solution.
This algorithm works nice if you have a final set of control points, in case of drawing app I don’t have that, points will be added after user moves his finger, and I need to draw new lines immediately.
For this reason I’m using this function to recalculate the smoothed points for a quadratic curve.
I found this on code exchage https://code.coronalabs.com/code/drawing-app-corona
local function calculateSmoothLinePoints() --print("calculateSmoothLinePoints --\> ") -- 1 We need at least 3 points to use quad curves. if(#points \> 2) then local smoothedPoints = {}; -- 2 Each time we need our current point and 2 previous ones. for i=3,#points do --print(i); local prev2 = points[i - 2]; local prev1 = points[i - 1]; local cur = points[i]; -- print(prev2,prev1,cur,#points) -- 3 Calculate our middle points between touch points. local midPoint1 = Vector2D:Mult(Vector2D:Add(prev1, prev2), 0.5); local midPoint2 = Vector2D:Mult(Vector2D:Add(cur, prev1), 0.5); -- 4 Calculate number of segments, for each 2 pixels there will be one extra segment, -- minimum of 32 segments and maximum of 128. If 2 mid points would be 100 pixels apart -- we would have 50 segments, we need to make sure we have at least 32 segments or the bending will look aliased… local segmentDistance = 2; local distance = Vector2D:Dist(midPoint1, midPoint2); local numberOfSegments = mMin(mMax(min, mFloor(distance/segmentDistance)), max); --print(distance,numberOfSegments) -- 5 Calculate our interpolation t increase based on the number of segments. local t = 0; local step = 1 / numberOfSegments; for j=1,numberOfSegments do -- 6 Calculate our new points by using quad curve equation. Also use same interpolation for line width. local newPoint = Vector2D:Add(Vector2D:Add(Vector2D:Mult(midPoint1, mPow(1 - t, 2)), Vector2D:Mult(prev1, 2 \* (1 - t) \* t)), Vector2D:Mult(midPoint2, t \* t)); newPoint.width = cur.width table.insert(smoothedPoints, newPoint); t = t + step; end -- 7 Add final point connecting to our end point local finalPoint = {}; finalPoint = midPoint2; finalPoint.width = (cur.width ); --finalPoint.width = 2; table.insert(smoothedPoints, finalPoint); end -- 8 Since we will be drawing right after this function, we don’t need old points except the last 2. That way each time user moves his finger we can draw next segment. local new\_points = {points[#points-1],points[#points]} points= nil; points ={}; points = new\_points; return smoothedPoints; else return nil; end end
I have modified the example cutting the part that are not in line with my project and this solution seem to improve the quality of drawing but is far to be compared with the native approach using CoreGraphic.
Also there are a lot of problems against performances using this solution.
I’m wondering if this is the best solution to use with corona to draw smooth curves and if someone has already solved the problem to draw smooth and antialiased curves with Corona.
Thanks,
Ale